From 962839ad5742eb9dc1890aa67e92bb9b0cc840bf Mon Sep 17 00:00:00 2001 From: ahujasid Date: Sat, 8 Mar 2025 01:07:37 +0530 Subject: [PATCH] change material seems to be working now --- blender_mcp_addon.py | 121 +++++++++++++++++++++++++++--------------- blender_mcp_server.py | 38 ------------- 2 files changed, 77 insertions(+), 82 deletions(-) diff --git a/blender_mcp_addon.py b/blender_mcp_addon.py index 8336384..4c74102 100644 --- a/blender_mcp_addon.py +++ b/blender_mcp_addon.py @@ -354,54 +354,87 @@ class BlenderMCPServer: def set_material(self, object_name, material_name=None, create_if_missing=True, color=None): """Set or create a material for an object""" - obj = bpy.data.objects.get(object_name) - if not obj: - raise ValueError(f"Object not found: {object_name}") - - # If material_name is provided, try to find or create the material - if material_name: - mat = bpy.data.materials.get(material_name) - if not mat and create_if_missing: - mat = bpy.data.materials.new(name=material_name) - - # Set material color if provided - if color and len(color) >= 3: - mat.use_nodes = True - bsdf = mat.node_tree.nodes.get('Principled BSDF') - if bsdf: - bsdf.inputs[0].default_value = (color[0], color[1], color[2], 1.0 if len(color) < 4 else color[3]) + try: + # Get the object + obj = bpy.data.objects.get(object_name) + if not obj: + raise ValueError(f"Object not found: {object_name}") - # Assign material to object - if mat: - if obj.data.materials: - obj.data.materials[0] = mat - else: - obj.data.materials.append(mat) + # Make sure object can accept materials + if not hasattr(obj, 'data') or not hasattr(obj.data, 'materials'): + raise ValueError(f"Object {object_name} cannot accept materials") - return {"object": object_name, "material": material_name} - - # If only color is provided, create a new material with the color - elif color: - # Create a new material with auto-generated name - mat_name = f"{object_name}_material" - mat = bpy.data.materials.new(name=mat_name) - - # Set material color - mat.use_nodes = True - bsdf = mat.node_tree.nodes.get('Principled BSDF') - if bsdf: - bsdf.inputs[0].default_value = (color[0], color[1], color[2], 1.0 if len(color) < 4 else color[3]) - - # Assign material to object - if obj.data.materials: - obj.data.materials[0] = mat + # Create or get material + if material_name: + mat = bpy.data.materials.get(material_name) + if not mat and create_if_missing: + mat = bpy.data.materials.new(name=material_name) + print(f"Created new material: {material_name}") else: - obj.data.materials.append(mat) + # Generate unique material name if none provided + mat_name = f"{object_name}_material" + mat = bpy.data.materials.get(mat_name) + if not mat: + mat = bpy.data.materials.new(name=mat_name) + material_name = mat_name + print(f"Using material: {mat_name}") - return {"object": object_name, "material": mat_name} - - else: - return {"error": "Either material_name or color must be provided"} + # Set up material nodes if needed + if mat: + if not mat.use_nodes: + mat.use_nodes = True + + # Get or create Principled BSDF + principled = mat.node_tree.nodes.get('Principled BSDF') + if not principled: + principled = mat.node_tree.nodes.new('ShaderNodeBsdfPrincipled') + # Get or create Material Output + output = mat.node_tree.nodes.get('Material Output') + if not output: + output = mat.node_tree.nodes.new('ShaderNodeOutputMaterial') + # Link if not already linked + if not principled.outputs[0].links: + mat.node_tree.links.new(principled.outputs[0], output.inputs[0]) + + # Set color if provided + if color and len(color) >= 3: + principled.inputs['Base Color'].default_value = ( + color[0], + color[1], + color[2], + 1.0 if len(color) < 4 else color[3] + ) + print(f"Set material color to {color}") + + # Assign material to object if not already assigned + if mat: + if not obj.data.materials: + obj.data.materials.append(mat) + else: + # Only modify first material slot + obj.data.materials[0] = mat + + print(f"Assigned material {mat.name} to object {object_name}") + + return { + "status": "success", + "object": object_name, + "material": mat.name, + "color": color if color else None + } + else: + raise ValueError(f"Failed to create or find material: {material_name}") + + except Exception as e: + print(f"Error in set_material: {str(e)}") + import traceback + traceback.print_exc() + return { + "status": "error", + "message": str(e), + "object": object_name, + "material": material_name if 'material_name' in locals() else None + } def render_scene(self, output_path=None, resolution_x=None, resolution_y=None): """Render the current scene""" diff --git a/blender_mcp_server.py b/blender_mcp_server.py index 730413f..b2d7d7b 100644 --- a/blender_mcp_server.py +++ b/blender_mcp_server.py @@ -473,44 +473,6 @@ def set_material( logger.error(f"Error setting material: {str(e)}") return f"Error setting material: {str(e)}" -@mcp.tool() -def render_scene( - ctx: Context, - output_path: str = None, - resolution_x: int = None, - resolution_y: int = None -) -> str: - """ - Render the current scene and return the image. - - Parameters: - - output_path: Optional path to save the rendered image - - resolution_x: Optional horizontal resolution - - resolution_y: Optional vertical resolution - """ - try: - # Get the global connection - blender = get_blender_connection() - - params = {} - if output_path: - params["output_path"] = output_path - if resolution_x: - params["resolution_x"] = resolution_x - if resolution_y: - params["resolution_y"] = resolution_y - - result = blender.send_command("render_scene", params) - - if "image_path" in result: - # If we have an image path, we could potentially load and return the image - return f"Scene rendered to {result['image_path']}" - else: - return "Scene rendered successfully" - except Exception as e: - logger.error(f"Error rendering scene: {str(e)}") - return f"Error rendering scene: {str(e)}" - @mcp.tool() def execute_blender_code(ctx: Context, code: str) -> str: """