Merge pull request #15 from justinpbarnett/bug/material-saving

material saving fix
main
Justin P Barnett 2025-03-19 18:12:00 -04:00 committed by GitHub
commit 03c12d0f3c
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 80 additions and 19 deletions

View File

@ -2,6 +2,8 @@ using UnityEngine;
using Newtonsoft.Json.Linq; using Newtonsoft.Json.Linq;
using UnityEngine.Rendering.Universal; using UnityEngine.Rendering.Universal;
using UnityEngine.Rendering; using UnityEngine.Rendering;
using UnityEditor;
using System.IO;
namespace MCPServer.Editor.Commands namespace MCPServer.Editor.Commands
{ {
@ -22,26 +24,72 @@ namespace MCPServer.Editor.Commands
// Check if URP is being used // Check if URP is being used
bool isURP = GraphicsSettings.currentRenderPipeline is UniversalRenderPipelineAsset; bool isURP = GraphicsSettings.currentRenderPipeline is UniversalRenderPipelineAsset;
// Create material with appropriate shader based on render pipeline Material material = null;
Material material; string materialName = (string)@params["material_name"];
if (isURP) bool createIfMissing = (bool)(@params["create_if_missing"] ?? true);
string materialPath = null;
// If material name is specified, try to find or create it
if (!string.IsNullOrEmpty(materialName))
{ {
material = new Material(Shader.Find("Universal Render Pipeline/Lit")); // Ensure Materials folder exists
const string materialsFolder = "Assets/Materials";
if (!Directory.Exists(materialsFolder))
{
Directory.CreateDirectory(materialsFolder);
}
materialPath = $"{materialsFolder}/{materialName}.mat";
material = AssetDatabase.LoadAssetAtPath<Material>(materialPath);
if (material == null && createIfMissing)
{
// Create new material with appropriate shader
material = new Material(isURP ? Shader.Find("Universal Render Pipeline/Lit") : Shader.Find("Standard"));
material.name = materialName;
// Save the material asset
AssetDatabase.CreateAsset(material, materialPath);
AssetDatabase.SaveAssets();
}
else if (material == null)
{
throw new System.Exception($"Material '{materialName}' not found and create_if_missing is false.");
}
} }
else else
{ {
material = new Material(Shader.Find("Standard")); // Create a temporary material if no name specified
material = new Material(isURP ? Shader.Find("Universal Render Pipeline/Lit") : Shader.Find("Standard"));
} }
if (@params.ContainsKey("material_name")) material.name = (string)@params["material_name"]; // Apply color if specified
if (@params.ContainsKey("color")) if (@params.ContainsKey("color"))
{ {
var colorArray = (JArray)@params["color"] ?? throw new System.Exception("Invalid color parameter."); var colorArray = (JArray)@params["color"];
if (colorArray.Count != 3) throw new System.Exception("Color must be an array of 3 floats [r, g, b]."); if (colorArray.Count < 3 || colorArray.Count > 4)
material.color = new Color((float)colorArray[0], (float)colorArray[1], (float)colorArray[2]); throw new System.Exception("Color must be an array of 3 (RGB) or 4 (RGBA) floats.");
Color color = new Color(
(float)colorArray[0],
(float)colorArray[1],
(float)colorArray[2],
colorArray.Count > 3 ? (float)colorArray[3] : 1.0f
);
material.color = color;
// If this is a saved material, make sure to save the color change
if (!string.IsNullOrEmpty(materialPath))
{
EditorUtility.SetDirty(material);
AssetDatabase.SaveAssets();
} }
}
// Apply the material to the renderer
renderer.material = material; renderer.material = material;
return new { material_name = material.name };
return new { material_name = material.name, path = materialPath };
} }
} }
} }

View File

@ -1,5 +1,5 @@
from mcp.server.fastmcp import FastMCP, Context from mcp.server.fastmcp import FastMCP, Context
from typing import List from typing import List, Optional
from unity_connection import get_unity_connection from unity_connection import get_unity_connection
def register_material_tools(mcp: FastMCP): def register_material_tools(mcp: FastMCP):
@ -9,18 +9,22 @@ def register_material_tools(mcp: FastMCP):
def set_material( def set_material(
ctx: Context, ctx: Context,
object_name: str, object_name: str,
material_name: str = None, material_name: Optional[str] = None,
color: List[float] = None, color: Optional[List[float]] = None,
create_if_missing: bool = True create_if_missing: bool = True
) -> str: ) -> str:
""" """
Apply or create a material for a game object. Apply or create a material for a game object. If material_name is provided,
the material will be saved as a shared asset in the Materials folder.
Args: Args:
object_name: Target game object. object_name: Target game object.
material_name: Optional material name. material_name: Optional material name. If provided, creates/uses a shared material asset.
color: Optional [R, G, B] values (0.0-1.0). color: Optional [R, G, B] or [R, G, B, A] values (0.0-1.0).
create_if_missing: Whether to create the material if it doesn't exist (default: True). create_if_missing: Whether to create the material if it doesn't exist (default: True).
Returns:
str: Status message indicating success or failure.
""" """
try: try:
unity = get_unity_connection() unity = get_unity_connection()
@ -63,14 +67,23 @@ def register_material_tools(mcp: FastMCP):
return f"Error: Color {channel} value must be in the range 0.0-1.0, but got {value}." return f"Error: Color {channel} value must be in the range 0.0-1.0, but got {value}."
# Set up parameters for the command # Set up parameters for the command
params = {"object_name": object_name} params = {
"object_name": object_name,
"create_if_missing": create_if_missing
}
if material_name: if material_name:
params["material_name"] = material_name params["material_name"] = material_name
params["create_if_missing"] = create_if_missing
if color: if color:
params["color"] = color params["color"] = color
result = unity.send_command("SET_MATERIAL", params) result = unity.send_command("SET_MATERIAL", params)
return f"Applied material to {object_name}: {result.get('material_name', 'unknown')}" material_name = result.get("material_name", "unknown")
material_path = result.get("path")
if material_path:
return f"Applied shared material '{material_name}' to {object_name} (saved at {material_path})"
else:
return f"Applied instance material '{material_name}' to {object_name}"
except Exception as e: except Exception as e:
return f"Error setting material: {str(e)}" return f"Error setting material: {str(e)}"