Major Comment and codebase cleanup

This commit is contained in:
2025-05-06 22:47:26 +02:00
parent ddb5a43a21
commit 932b39fd01
109 changed files with 622 additions and 10137 deletions

View File

@@ -12,18 +12,15 @@ bl_info = {
import bpy
# Import other modules (will be created later)
from . import operator
from . import panel
def register():
# Register classes from imported modules
operator.register()
panel.register()
print("Material Merger Addon Registered")
def unregister():
# Unregister classes from imported modules
panel.unregister()
operator.unregister()
print("Material Merger Addon Unregistered")

View File

@@ -10,7 +10,6 @@ MATERIAL_MERGE_NODEGROUP_NAME = "MaterialMerge"
HANDLER_NODEGROUP_NAME = "PBR_Handler" # Assumption from plan
BSDF_NODEGROUP_NAME = "PBR_BSDF" # Assumption from plan
# Helper function to copy nodes and identify outputs
def copy_material_nodes(source_mat, target_tree, location_offset=(0, 0)):
"""
Copies nodes from source_mat's node tree to target_tree, applying an offset.
@@ -25,7 +24,7 @@ def copy_material_nodes(source_mat, target_tree, location_offset=(0, 0)):
return None, None, None
source_tree = source_mat.node_tree
copied_node_map = {} # Map original node to copied node
copied_node_map = {}
copied_final_bsdf_node = None
copied_final_disp_node = None
@@ -50,7 +49,6 @@ def copy_material_nodes(source_mat, target_tree, location_offset=(0, 0)):
print(f" Identified top-level '{MATERIAL_MERGE_NODEGROUP_NAME}' in '{source_mat.name}'. Using its outputs.")
source_final_bsdf_node = top_merge_node
source_final_disp_node = top_merge_node # Both outputs come from the merge node
# Ensure the sockets exist before proceeding
if 'BSDF' not in source_final_bsdf_node.outputs or 'Displacement' not in source_final_disp_node.outputs:
print(f" Error: Identified merge node in '{source_mat.name}' lacks required BSDF/Displacement outputs.")
return None, None, None
@@ -65,7 +63,6 @@ def copy_material_nodes(source_mat, target_tree, location_offset=(0, 0)):
if not source_final_disp_node:
print(f" Error: Could not find base Handler node '{HANDLER_NODEGROUP_NAME}' in '{source_mat.name}'.")
return None, None, None
# Ensure sockets exist
if 'BSDF' not in source_final_bsdf_node.outputs:
print(f" Error: Identified BSDF node '{BSDF_NODEGROUP_NAME}' lacks BSDF output.")
return None, None, None
@@ -152,7 +149,6 @@ class MATERIAL_OT_merge_materials(Operator):
bl_label = "Merge Selected Materials"
bl_options = {'REGISTER', 'UNDO'}
# Properties to hold the names of the selected materials
# These will be set by the UI panel
material_a_name: StringProperty(
name="Material A",
@@ -195,14 +191,14 @@ class MATERIAL_OT_merge_materials(Operator):
# Add Material Output node
output_node = new_node_tree.nodes.new(type='ShaderNodeOutputMaterial')
output_node.location = (400, 0) # Basic positioning
output_node.location = (400, 0)
# 2. Copy nodes from source materials
print("Copying nodes for Material A...")
copied_map_a, copied_bsdf_a, copied_disp_a = copy_material_nodes(mat_a, new_node_tree, location_offset=(0, 0))
if not copied_bsdf_a or not copied_disp_a:
self.report({'ERROR'}, f"Failed to copy nodes or identify outputs for material '{mat_a.name}'. Check console for details.")
bpy.data.materials.remove(new_mat) # Clean up
bpy.data.materials.remove(new_mat)
return {'CANCELLED'}
print("Copying nodes for Material B...")
@@ -216,7 +212,7 @@ class MATERIAL_OT_merge_materials(Operator):
copied_map_b, copied_bsdf_b, copied_disp_b = copy_material_nodes(mat_b, new_node_tree, location_offset=(offset_x, 0))
if not copied_bsdf_b or not copied_disp_b:
self.report({'ERROR'}, f"Failed to copy nodes or identify outputs for material '{mat_b.name}'. Check console for details.")
bpy.data.materials.remove(new_mat) # Clean up
bpy.data.materials.remove(new_mat)
return {'CANCELLED'}
@@ -255,17 +251,14 @@ class MATERIAL_OT_merge_materials(Operator):
# Add the linked/appended group to the new material's node tree
merge_node = new_node_tree.nodes.new(type='ShaderNodeGroup')
merge_node.node_tree = merge_group
merge_node.label = MATERIAL_MERGE_NODEGROUP_NAME # Set label for clarity
merge_node.location = (200, 0) # Basic positioning
merge_node.label = MATERIAL_MERGE_NODEGROUP_NAME
merge_node.location = (200, 0)
# 4. Make Connections
links = new_node_tree.links
# Connect BSDFs to Merge node
# NOTE: Using original nodes here as placeholder. Needs to use *copied* nodes.
# NOTE: Using *copied* nodes now.
# Ensure the sockets exist before linking
bsdf_output_socket_a = copied_bsdf_a.outputs.get('BSDF')
shader_input_socket_a = merge_node.inputs.get('Shader A')
bsdf_output_socket_b = copied_bsdf_b.outputs.get('BSDF')
@@ -273,16 +266,13 @@ class MATERIAL_OT_merge_materials(Operator):
if not all([bsdf_output_socket_a, shader_input_socket_a, bsdf_output_socket_b, shader_input_socket_b]):
self.report({'ERROR'}, "Could not find required BSDF/Shader sockets for linking.")
bpy.data.materials.remove(new_mat) # Clean up
bpy.data.materials.remove(new_mat)
return {'CANCELLED'}
link_bsdf_a = links.new(bsdf_output_socket_a, shader_input_socket_a)
link_bsdf_b = links.new(bsdf_output_socket_b, shader_input_socket_b)
# Connect Displacements to Merge node
# NOTE: Using original nodes here as placeholder. Needs to use *copied* nodes.
# NOTE: Using *copied* nodes now.
# Ensure the sockets exist before linking
disp_output_socket_a = copied_disp_a.outputs.get('Displacement')
disp_input_socket_a = merge_node.inputs.get('Displacement A')
disp_output_socket_b = copied_disp_b.outputs.get('Displacement')
@@ -290,14 +280,13 @@ class MATERIAL_OT_merge_materials(Operator):
if not all([disp_output_socket_a, disp_input_socket_a, disp_output_socket_b, disp_input_socket_b]):
self.report({'ERROR'}, "Could not find required Displacement sockets for linking.")
bpy.data.materials.remove(new_mat) # Clean up
bpy.data.materials.remove(new_mat)
return {'CANCELLED'}
link_disp_a = links.new(disp_output_socket_a, disp_input_socket_a)
link_disp_b = links.new(disp_output_socket_b, disp_input_socket_b)
# Connect Merge node outputs to Material Output
# Ensure the sockets exist before linking
merge_bsdf_output = merge_node.outputs.get('BSDF')
output_surface_input = output_node.inputs.get('Surface')
merge_disp_output = merge_node.outputs.get('Displacement')
@@ -305,7 +294,7 @@ class MATERIAL_OT_merge_materials(Operator):
if not all([merge_bsdf_output, output_surface_input, merge_disp_output, output_disp_input]):
self.report({'ERROR'}, "Could not find required Merge/Output sockets for linking.")
bpy.data.materials.remove(new_mat) # Clean up
bpy.data.materials.remove(new_mat)
return {'CANCELLED'}
link_merge_bsdf = links.new(merge_bsdf_output, output_surface_input)
@@ -315,7 +304,6 @@ class MATERIAL_OT_merge_materials(Operator):
# 5. Layout (Optional)
# TODO: Implement better node layout
# Update node tree to apply changes
new_node_tree.nodes.update()
self.report({'INFO'}, f"Successfully merged '{mat_a.name}' and '{mat_b.name}' into '{new_mat.name}'")

View File

@@ -1,6 +1,6 @@
import bpy
from bpy.types import Panel
from .operator import MATERIAL_OT_merge_materials # Import the operator
from .operator import MATERIAL_OT_merge_materials
class MATERIAL_PT_material_merger_panel(Panel):
"""Creates a Panel in the Shader Editor sidebar"""
@@ -13,9 +13,6 @@ class MATERIAL_PT_material_merger_panel(Panel):
def draw(self, context):
layout = self.layout
# Get the active material in the Shader Editor
# This might be useful for defaulting one of the selectors
# mat = context.material
row = layout.row()
row.label(text="Select Materials to Merge:")
@@ -25,18 +22,14 @@ class MATERIAL_PT_material_merger_panel(Panel):
# We'll use StringProperty for simplicity in the UI for now.
# A more advanced UI might use PointerProperty to bpy.data.materials
# Material A selection
row = layout.row()
row.prop(context.scene, "material_merger_mat_a", text="Material A")
# Material B selection
row = layout.row()
row.prop(context.scene, "material_merger_mat_b", text="Material B")
# Merge button
row = layout.row()
# Pass the selected material names to the operator when button is clicked
row.operator(MATERIAL_OT_merge_materials.bl_idname, text=MATERIAL_OT_merge_materials.bl_label).material_a_name = context.scene.material_merger_mat_a
row.operator(MATERIAL_OT_merge_materials.bl_idname, text=MATERIAL_OT_merge_materials.bl_label).material_b_name = context.scene.material_merger_mat_b