89 lines
3.9 KiB
Python
89 lines
3.9 KiB
Python
from mcp.server.fastmcp import FastMCP, Context
|
|
from typing import List, Optional
|
|
from unity_connection import get_unity_connection
|
|
|
|
def register_material_tools(mcp: FastMCP):
|
|
"""Register all material-related tools with the MCP server."""
|
|
|
|
@mcp.tool()
|
|
def set_material(
|
|
ctx: Context,
|
|
object_name: str,
|
|
material_name: Optional[str] = None,
|
|
color: Optional[List[float]] = None,
|
|
create_if_missing: bool = True
|
|
) -> str:
|
|
"""
|
|
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:
|
|
object_name: Target game object.
|
|
material_name: Optional material name. If provided, creates/uses a shared material asset.
|
|
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).
|
|
|
|
Returns:
|
|
str: Status message indicating success or failure.
|
|
"""
|
|
try:
|
|
unity = get_unity_connection()
|
|
|
|
# Check if the object exists
|
|
object_response = unity.send_command("FIND_OBJECTS_BY_NAME", {
|
|
"name": object_name
|
|
})
|
|
|
|
objects = object_response.get("objects", [])
|
|
if not objects:
|
|
return f"GameObject '{object_name}' not found in the scene."
|
|
|
|
# If a material name is specified, check if it exists
|
|
if material_name:
|
|
material_assets = unity.send_command("GET_ASSET_LIST", {
|
|
"type": "Material",
|
|
"search_pattern": material_name,
|
|
"folder": "Assets/Materials"
|
|
}).get("assets", [])
|
|
|
|
material_exists = any(asset.get("name") == material_name for asset in material_assets)
|
|
|
|
if not material_exists and not create_if_missing:
|
|
return f"Material '{material_name}' not found. Use create_if_missing=True to create it."
|
|
|
|
# Validate color values if provided
|
|
if color:
|
|
# Check if color has the right number of components (RGB or RGBA)
|
|
if not (len(color) == 3 or len(color) == 4):
|
|
return f"Error: Color must have 3 (RGB) or 4 (RGBA) components, but got {len(color)}."
|
|
|
|
# Check if all color values are in the 0-1 range
|
|
for i, value in enumerate(color):
|
|
if not isinstance(value, (int, float)):
|
|
return f"Error: Color component at index {i} is not a number."
|
|
|
|
if value < 0.0 or value > 1.0:
|
|
channel = "RGBA"[i] if i < 4 else f"component {i}"
|
|
return f"Error: Color {channel} value must be in the range 0.0-1.0, but got {value}."
|
|
|
|
# Set up parameters for the command
|
|
params = {
|
|
"object_name": object_name,
|
|
"create_if_missing": create_if_missing
|
|
}
|
|
if material_name:
|
|
params["material_name"] = material_name
|
|
if color:
|
|
params["color"] = color
|
|
|
|
result = unity.send_command("SET_MATERIAL", params)
|
|
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:
|
|
return f"Error setting material: {str(e)}" |