analitics

Pages

Thursday, September 18, 2025

Blender 3D : ... addon add all materials from folder.

This is a simple addon for Blender 3D version 3.6.x version.
The addon search recursive all blend files from one folder and take all materials.
Let's see the script:
bl_info = {
    "name": "Append Materials from Folder",
    "author": "Grok",
    "version": (1, 2),
    "blender": (3, 0, 0),
    "location": "View3D > Sidebar > Append Materials",
    "description": "Select a folder and append all materials from .blend files recursively",
    "category": "Import-Export",
}

import bpy
import os
from bpy.types import Operator, Panel, PropertyGroup
from bpy.props import StringProperty, PointerProperty

class AppendMaterialsProperties(PropertyGroup):
    folder_path: StringProperty(
        name="Folder Path",
        description="Path to the folder containing .blend files",
        default="",
        maxlen=1024,
        subtype='DIR_PATH'
    )

class APPEND_OT_materials_from_folder(Operator):
    bl_idname = "append.materials_from_folder"
    bl_label = "Append Materials from Folder"
    bl_options = {'REGISTER', 'UNDO'}
    bl_description = "Append all materials from .blend files in the selected folder and subfolders"

    def execute(self, context):
        props = context.scene.append_materials_props
        folder_path = props.folder_path

        # Normalize path to avoid issues with slashes
        folder_path = os.path.normpath(bpy.path.abspath(folder_path))
        if not folder_path or not os.path.isdir(folder_path):
            self.report({'ERROR'}, f"Invalid or no folder selected: {folder_path}")
            return {'CANCELLED'}

        self.report({'INFO'}, f"Scanning folder: {folder_path}")
        blend_files_found = 0
        materials_appended = 0
        errors = []

        # Walk recursively through the folder
        for root, dirs, files in os.walk(folder_path):
            self.report({'INFO'}, f"Checking folder: {root}")
            for file in files:
                if file.lower().endswith('.blend'):
                    blend_files_found += 1
                    blend_path = os.path.join(root, file)
                    self.report({'INFO'}, f"Found .blend file: {blend_path}")
                    try:
                        # Open the .blend file to inspect materials
                        with bpy.data.libraries.load(blend_path, link=False) as (data_from, data_to):
                            if data_from.materials:
                                data_to.materials = data_from.materials
                                materials_appended += len(data_from.materials)
                                self.report({'INFO'}, f"Appended {len(data_from.materials)} materials from: {blend_path}")
                            else:
                                self.report({'WARNING'}, f"No materials found in: {blend_path}")
                    except Exception as e:
                        errors.append(f"Failed to process {blend_path}: {str(e)}")
                        self.report({'WARNING'}, f"Error in {blend_path}: {str(e)}")

        # Final report
        if blend_files_found == 0:
            self.report({'WARNING'}, f"No .blend files found in {folder_path} or its subfolders!")
        else:
            self.report({'INFO'}, f"Found {blend_files_found} .blend files, appended {materials_appended} materials.")
        if errors:
            self.report({'WARNING'}, f"Encountered {len(errors)} errors: {'; '.join(errors)}")

        return {'FINISHED'}

class VIEW3D_PT_append_materials(Panel):
    bl_space_type = 'VIEW_3D'
    bl_region_type = 'UI'
    bl_category = "Append Materials"
    bl_label = "Append Materials from Folder"

    def draw(self, context):
        layout = self.layout
        props = context.scene.append_materials_props
        layout.prop(props, "folder_path")
        layout.operator("append.materials_from_folder", text="Append Materials")

def register():
    bpy.utils.register_class(AppendMaterialsProperties)
    bpy.utils.register_class(APPEND_OT_materials_from_folder)
    bpy.utils.register_class(VIEW3D_PT_append_materials)
    bpy.types.Scene.append_materials_props = PointerProperty(type=AppendMaterialsProperties)

def unregister():
    bpy.utils.unregister_class(VIEW3D_PT_append_materials)
    bpy.utils.unregister_class(APPEND_OT_materials_from_folder)
    bpy.utils.unregister_class(AppendMaterialsProperties)
    del bpy.types.Scene.append_materials_props

if __name__ == "__main__":
    register()