fix script adding issues
parent
f90188ed85
commit
afff1caa4f
|
|
@ -20,12 +20,40 @@ namespace MCPServer.Editor.Commands
|
||||||
public static object ViewScript(JObject @params)
|
public static object ViewScript(JObject @params)
|
||||||
{
|
{
|
||||||
string scriptPath = (string)@params["script_path"] ?? throw new System.Exception("Parameter 'script_path' is required.");
|
string scriptPath = (string)@params["script_path"] ?? throw new System.Exception("Parameter 'script_path' is required.");
|
||||||
string fullPath = Path.Combine(Application.dataPath, scriptPath);
|
bool requireExists = (bool?)@params["require_exists"] ?? true;
|
||||||
|
|
||||||
|
// Debug to help diagnose issues
|
||||||
|
Debug.Log($"ViewScript - Original script path: {scriptPath}");
|
||||||
|
|
||||||
|
// Handle path correctly to avoid double "Assets" folder issue
|
||||||
|
string relativePath;
|
||||||
|
if (scriptPath.StartsWith("Assets/", StringComparison.OrdinalIgnoreCase))
|
||||||
|
{
|
||||||
|
// If path already starts with Assets/, remove it for local path operations
|
||||||
|
relativePath = scriptPath.Substring(7);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
relativePath = scriptPath;
|
||||||
|
}
|
||||||
|
|
||||||
|
string fullPath = Path.Combine(Application.dataPath, relativePath);
|
||||||
|
Debug.Log($"ViewScript - Relative path: {relativePath}");
|
||||||
|
Debug.Log($"ViewScript - Full path: {fullPath}");
|
||||||
|
|
||||||
if (!File.Exists(fullPath))
|
if (!File.Exists(fullPath))
|
||||||
|
{
|
||||||
|
if (requireExists)
|
||||||
|
{
|
||||||
throw new System.Exception($"Script file not found: {scriptPath}");
|
throw new System.Exception($"Script file not found: {scriptPath}");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return new { exists = false, message = $"Script file not found: {scriptPath}" };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return new { content = File.ReadAllText(fullPath) };
|
return new { exists = true, content = File.ReadAllText(fullPath) };
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|
@ -33,6 +61,8 @@ namespace MCPServer.Editor.Commands
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private static void EnsureScriptsFolderExists()
|
private static void EnsureScriptsFolderExists()
|
||||||
{
|
{
|
||||||
|
// Never create an "Assets" folder as it's the project root
|
||||||
|
// Instead create "Scripts" within the existing Assets folder
|
||||||
string scriptsFolderPath = Path.Combine(Application.dataPath, "Scripts");
|
string scriptsFolderPath = Path.Combine(Application.dataPath, "Scripts");
|
||||||
if (!Directory.Exists(scriptsFolderPath))
|
if (!Directory.Exists(scriptsFolderPath))
|
||||||
{
|
{
|
||||||
|
|
@ -42,7 +72,7 @@ namespace MCPServer.Editor.Commands
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Creates a new Unity script file in the Scripts folder
|
/// Creates a new Unity script file in the specified folder
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public static object CreateScript(JObject @params)
|
public static object CreateScript(JObject @params)
|
||||||
{
|
{
|
||||||
|
|
@ -52,59 +82,75 @@ namespace MCPServer.Editor.Commands
|
||||||
string template = (string)@params["template"];
|
string template = (string)@params["template"];
|
||||||
string scriptFolder = (string)@params["script_folder"];
|
string scriptFolder = (string)@params["script_folder"];
|
||||||
string content = (string)@params["content"];
|
string content = (string)@params["content"];
|
||||||
|
bool overwrite = (bool?)@params["overwrite"] ?? false;
|
||||||
|
|
||||||
// Ensure script name ends with .cs
|
// Ensure script name ends with .cs
|
||||||
if (!scriptName.EndsWith(".cs"))
|
if (!scriptName.EndsWith(".cs", StringComparison.OrdinalIgnoreCase))
|
||||||
scriptName += ".cs";
|
scriptName += ".cs";
|
||||||
|
|
||||||
|
// Make sure scriptName doesn't contain path separators - extract base name
|
||||||
|
scriptName = Path.GetFileName(scriptName);
|
||||||
|
|
||||||
|
// Determine the script path
|
||||||
string scriptPath;
|
string scriptPath;
|
||||||
|
|
||||||
// If content is provided, use it directly
|
// Handle the script folder parameter
|
||||||
if (!string.IsNullOrEmpty(content))
|
if (string.IsNullOrEmpty(scriptFolder))
|
||||||
{
|
{
|
||||||
// Use specified folder or default to Scripts
|
// Default to Scripts folder within Assets
|
||||||
scriptPath = string.IsNullOrEmpty(scriptFolder) ? "Scripts" : scriptFolder;
|
scriptPath = "Scripts";
|
||||||
|
EnsureScriptsFolderExists();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Use provided folder path
|
||||||
|
scriptPath = scriptFolder;
|
||||||
|
|
||||||
// Ensure folder exists
|
// If scriptFolder starts with "Assets/", remove it for local path operations
|
||||||
|
if (scriptPath.StartsWith("Assets/", StringComparison.OrdinalIgnoreCase))
|
||||||
|
{
|
||||||
|
scriptPath = scriptPath.Substring(7);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create the full directory path, avoiding Assets/Assets issue
|
||||||
string folderPath = Path.Combine(Application.dataPath, scriptPath);
|
string folderPath = Path.Combine(Application.dataPath, scriptPath);
|
||||||
|
Debug.Log($"CreateScript - Script name: {scriptName}");
|
||||||
|
Debug.Log($"CreateScript - Script path: {scriptPath}");
|
||||||
|
Debug.Log($"CreateScript - Creating script in folder path: {folderPath}");
|
||||||
|
|
||||||
|
// Create directory if it doesn't exist
|
||||||
if (!Directory.Exists(folderPath))
|
if (!Directory.Exists(folderPath))
|
||||||
|
{
|
||||||
|
try
|
||||||
{
|
{
|
||||||
Directory.CreateDirectory(folderPath);
|
Directory.CreateDirectory(folderPath);
|
||||||
AssetDatabase.Refresh();
|
AssetDatabase.Refresh();
|
||||||
}
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
throw new System.Exception($"Failed to create directory '{scriptPath}': {ex.Message}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if script already exists
|
||||||
|
string fullFilePath = Path.Combine(folderPath, scriptName);
|
||||||
|
if (File.Exists(fullFilePath) && !overwrite)
|
||||||
|
{
|
||||||
|
throw new System.Exception($"Script file '{scriptName}' already exists in '{scriptPath}' and overwrite is not enabled.");
|
||||||
|
}
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
// If content is provided, use it directly
|
||||||
|
if (!string.IsNullOrEmpty(content))
|
||||||
|
{
|
||||||
// Create the script file with provided content
|
// Create the script file with provided content
|
||||||
string fullPath = Path.Combine(Application.dataPath, scriptPath, scriptName);
|
File.WriteAllText(fullFilePath, content);
|
||||||
File.WriteAllText(fullPath, content);
|
|
||||||
|
|
||||||
// Refresh the AssetDatabase
|
|
||||||
AssetDatabase.Refresh();
|
|
||||||
|
|
||||||
return new { message = $"Created script: {Path.Combine(scriptPath, scriptName)}" };
|
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
// Otherwise generate content based on template and parameters
|
// Otherwise generate content based on template and parameters
|
||||||
|
|
||||||
// Ensure Scripts folder exists
|
|
||||||
EnsureScriptsFolderExists();
|
|
||||||
|
|
||||||
// Create namespace-based folder structure if namespace is specified
|
|
||||||
scriptPath = string.IsNullOrEmpty(scriptFolder) ? "Scripts" : scriptFolder;
|
|
||||||
if (!string.IsNullOrEmpty(namespaceName))
|
|
||||||
{
|
|
||||||
if (scriptPath == "Scripts") // Only modify path if we're using the default
|
|
||||||
{
|
|
||||||
scriptPath = Path.Combine(scriptPath, namespaceName.Replace('.', '/'));
|
|
||||||
}
|
|
||||||
string namespaceFolderPath = Path.Combine(Application.dataPath, scriptPath);
|
|
||||||
if (!Directory.Exists(namespaceFolderPath))
|
|
||||||
{
|
|
||||||
Directory.CreateDirectory(namespaceFolderPath);
|
|
||||||
AssetDatabase.Refresh();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create the script content
|
|
||||||
StringBuilder contentBuilder = new StringBuilder();
|
StringBuilder contentBuilder = new StringBuilder();
|
||||||
|
|
||||||
// Add using directives
|
// Add using directives
|
||||||
|
|
@ -118,33 +164,34 @@ namespace MCPServer.Editor.Commands
|
||||||
contentBuilder.AppendLine("{");
|
contentBuilder.AppendLine("{");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add class definition
|
// Add class definition with indent based on namespace
|
||||||
contentBuilder.AppendLine($" public class {Path.GetFileNameWithoutExtension(scriptName)} : {scriptType}");
|
string indent = string.IsNullOrEmpty(namespaceName) ? "" : " ";
|
||||||
contentBuilder.AppendLine(" {");
|
contentBuilder.AppendLine($"{indent}public class {Path.GetFileNameWithoutExtension(scriptName)} : {scriptType}");
|
||||||
|
contentBuilder.AppendLine($"{indent}{{");
|
||||||
|
|
||||||
// Add default Unity methods based on script type
|
// Add default Unity methods based on script type
|
||||||
if (scriptType == "MonoBehaviour")
|
if (scriptType == "MonoBehaviour")
|
||||||
{
|
{
|
||||||
contentBuilder.AppendLine(" private void Start()");
|
contentBuilder.AppendLine($"{indent} private void Start()");
|
||||||
contentBuilder.AppendLine(" {");
|
contentBuilder.AppendLine($"{indent} {{");
|
||||||
contentBuilder.AppendLine(" // Initialize your component here");
|
contentBuilder.AppendLine($"{indent} // Initialize your component here");
|
||||||
contentBuilder.AppendLine(" }");
|
contentBuilder.AppendLine($"{indent} }}");
|
||||||
contentBuilder.AppendLine();
|
contentBuilder.AppendLine();
|
||||||
contentBuilder.AppendLine(" private void Update()");
|
contentBuilder.AppendLine($"{indent} private void Update()");
|
||||||
contentBuilder.AppendLine(" {");
|
contentBuilder.AppendLine($"{indent} {{");
|
||||||
contentBuilder.AppendLine(" // Update your component here");
|
contentBuilder.AppendLine($"{indent} // Update your component here");
|
||||||
contentBuilder.AppendLine(" }");
|
contentBuilder.AppendLine($"{indent} }}");
|
||||||
}
|
}
|
||||||
else if (scriptType == "ScriptableObject")
|
else if (scriptType == "ScriptableObject")
|
||||||
{
|
{
|
||||||
contentBuilder.AppendLine(" private void OnEnable()");
|
contentBuilder.AppendLine($"{indent} private void OnEnable()");
|
||||||
contentBuilder.AppendLine(" {");
|
contentBuilder.AppendLine($"{indent} {{");
|
||||||
contentBuilder.AppendLine(" // Initialize your ScriptableObject here");
|
contentBuilder.AppendLine($"{indent} // Initialize your ScriptableObject here");
|
||||||
contentBuilder.AppendLine(" }");
|
contentBuilder.AppendLine($"{indent} }}");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Close class
|
// Close class
|
||||||
contentBuilder.AppendLine(" }");
|
contentBuilder.AppendLine($"{indent}}}");
|
||||||
|
|
||||||
// Close namespace if specified
|
// Close namespace if specified
|
||||||
if (!string.IsNullOrEmpty(namespaceName))
|
if (!string.IsNullOrEmpty(namespaceName))
|
||||||
|
|
@ -152,14 +199,30 @@ namespace MCPServer.Editor.Commands
|
||||||
contentBuilder.AppendLine("}");
|
contentBuilder.AppendLine("}");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create the script file in the Scripts folder
|
// Write the generated content to file
|
||||||
string fullFilePath = Path.Combine(Application.dataPath, scriptPath, scriptName);
|
|
||||||
File.WriteAllText(fullFilePath, contentBuilder.ToString());
|
File.WriteAllText(fullFilePath, contentBuilder.ToString());
|
||||||
|
}
|
||||||
|
|
||||||
// Refresh the AssetDatabase
|
// Refresh the AssetDatabase to recognize the new script
|
||||||
AssetDatabase.Refresh();
|
AssetDatabase.Refresh();
|
||||||
|
|
||||||
return new { message = $"Created script: {Path.Combine(scriptPath, scriptName)}" };
|
// Return the relative path for easier reference
|
||||||
|
string relativePath = scriptPath.Replace('\\', '/');
|
||||||
|
if (!relativePath.StartsWith("Assets/"))
|
||||||
|
{
|
||||||
|
relativePath = $"Assets/{relativePath}";
|
||||||
|
}
|
||||||
|
|
||||||
|
return new {
|
||||||
|
message = $"Created script: {Path.Combine(relativePath, scriptName).Replace('\\', '/')}",
|
||||||
|
script_path = Path.Combine(relativePath, scriptName).Replace('\\', '/')
|
||||||
|
};
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Debug.LogError($"Failed to create script: {ex.Message}\n{ex.StackTrace}");
|
||||||
|
throw new System.Exception($"Failed to create script '{scriptName}': {ex.Message}");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|
@ -172,9 +235,26 @@ namespace MCPServer.Editor.Commands
|
||||||
bool createIfMissing = (bool?)@params["create_if_missing"] ?? false;
|
bool createIfMissing = (bool?)@params["create_if_missing"] ?? false;
|
||||||
bool createFolderIfMissing = (bool?)@params["create_folder_if_missing"] ?? false;
|
bool createFolderIfMissing = (bool?)@params["create_folder_if_missing"] ?? false;
|
||||||
|
|
||||||
string fullPath = Path.Combine(Application.dataPath, scriptPath);
|
// Handle path correctly to avoid double "Assets" folder
|
||||||
|
string relativePath;
|
||||||
|
if (scriptPath.StartsWith("Assets/", StringComparison.OrdinalIgnoreCase))
|
||||||
|
{
|
||||||
|
// If path already starts with Assets/, remove it for local path operations
|
||||||
|
relativePath = scriptPath.Substring(7);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
relativePath = scriptPath;
|
||||||
|
}
|
||||||
|
|
||||||
|
string fullPath = Path.Combine(Application.dataPath, relativePath);
|
||||||
string directory = Path.GetDirectoryName(fullPath);
|
string directory = Path.GetDirectoryName(fullPath);
|
||||||
|
|
||||||
|
// Debug the paths to help diagnose issues
|
||||||
|
Debug.Log($"UpdateScript - Original script path: {scriptPath}");
|
||||||
|
Debug.Log($"UpdateScript - Relative path: {relativePath}");
|
||||||
|
Debug.Log($"UpdateScript - Full path: {fullPath}");
|
||||||
|
|
||||||
// Check if file exists, create if requested
|
// Check if file exists, create if requested
|
||||||
if (!File.Exists(fullPath))
|
if (!File.Exists(fullPath))
|
||||||
{
|
{
|
||||||
|
|
@ -252,6 +332,7 @@ namespace MCPServer.Editor.Commands
|
||||||
{
|
{
|
||||||
string objectName = (string)@params["object_name"] ?? throw new System.Exception("Parameter 'object_name' is required.");
|
string objectName = (string)@params["object_name"] ?? throw new System.Exception("Parameter 'object_name' is required.");
|
||||||
string scriptName = (string)@params["script_name"] ?? throw new System.Exception("Parameter 'script_name' is required.");
|
string scriptName = (string)@params["script_name"] ?? throw new System.Exception("Parameter 'script_name' is required.");
|
||||||
|
string scriptPath = (string)@params["script_path"]; // Optional
|
||||||
|
|
||||||
// Find the target object
|
// Find the target object
|
||||||
GameObject targetObject = GameObject.Find(objectName);
|
GameObject targetObject = GameObject.Find(objectName);
|
||||||
|
|
@ -259,35 +340,119 @@ namespace MCPServer.Editor.Commands
|
||||||
throw new System.Exception($"Object '{objectName}' not found in scene.");
|
throw new System.Exception($"Object '{objectName}' not found in scene.");
|
||||||
|
|
||||||
// Ensure script name ends with .cs
|
// Ensure script name ends with .cs
|
||||||
if (!scriptName.EndsWith(".cs"))
|
if (!scriptName.EndsWith(".cs", StringComparison.OrdinalIgnoreCase))
|
||||||
scriptName += ".cs";
|
scriptName += ".cs";
|
||||||
|
|
||||||
|
// Remove the path from the scriptName if it contains path separators
|
||||||
|
string scriptFileName = Path.GetFileName(scriptName);
|
||||||
|
string scriptNameWithoutExtension = Path.GetFileNameWithoutExtension(scriptFileName);
|
||||||
|
|
||||||
// Find the script asset
|
// Find the script asset
|
||||||
string[] guids = AssetDatabase.FindAssets(Path.GetFileNameWithoutExtension(scriptName));
|
string[] guids;
|
||||||
if (guids.Length == 0)
|
|
||||||
throw new System.Exception($"Script '{scriptName}' not found in project.");
|
|
||||||
|
|
||||||
// Get the script asset
|
if (!string.IsNullOrEmpty(scriptPath))
|
||||||
string scriptPath = AssetDatabase.GUIDToAssetPath(guids[0]);
|
{
|
||||||
|
// If a specific path is provided, try that first
|
||||||
|
if (File.Exists(Path.Combine(Application.dataPath, scriptPath.Replace("Assets/", ""))))
|
||||||
|
{
|
||||||
|
// Use the direct path if it exists
|
||||||
MonoScript scriptAsset = AssetDatabase.LoadAssetAtPath<MonoScript>(scriptPath);
|
MonoScript scriptAsset = AssetDatabase.LoadAssetAtPath<MonoScript>(scriptPath);
|
||||||
if (scriptAsset == null)
|
if (scriptAsset != null)
|
||||||
throw new System.Exception($"Failed to load script asset: {scriptName}");
|
{
|
||||||
|
|
||||||
// Get the script type
|
|
||||||
System.Type scriptType = scriptAsset.GetClass();
|
System.Type scriptType = scriptAsset.GetClass();
|
||||||
if (scriptType == null)
|
if (scriptType != null)
|
||||||
throw new System.Exception($"Script '{scriptName}' does not contain a valid MonoBehaviour class.");
|
{
|
||||||
|
try
|
||||||
// Add the component
|
{
|
||||||
|
// Try to add the component
|
||||||
Component component = targetObject.AddComponent(scriptType);
|
Component component = targetObject.AddComponent(scriptType);
|
||||||
if (component == null)
|
if (component != null)
|
||||||
throw new System.Exception($"Failed to add component of type {scriptType.Name} to object '{objectName}'.");
|
{
|
||||||
|
|
||||||
return new
|
return new
|
||||||
{
|
{
|
||||||
message = $"Successfully attached script '{scriptName}' to object '{objectName}'",
|
message = $"Successfully attached script '{scriptFileName}' to object '{objectName}'",
|
||||||
component_type = scriptType.Name
|
component_type = scriptType.Name
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Debug.LogError($"Error attaching script component: {ex.Message}");
|
||||||
|
throw new System.Exception($"Failed to add component: {ex.Message}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Use the file name for searching if direct path didn't work
|
||||||
|
guids = AssetDatabase.FindAssets(scriptNameWithoutExtension + " t:script");
|
||||||
|
|
||||||
|
if (guids.Length == 0)
|
||||||
|
{
|
||||||
|
// Try a broader search if exact match fails
|
||||||
|
guids = AssetDatabase.FindAssets(scriptNameWithoutExtension);
|
||||||
|
|
||||||
|
if (guids.Length == 0)
|
||||||
|
throw new System.Exception($"Script '{scriptFileName}' not found in project.");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check each potential script until we find one that can be attached
|
||||||
|
foreach (string guid in guids)
|
||||||
|
{
|
||||||
|
string path = AssetDatabase.GUIDToAssetPath(guid);
|
||||||
|
|
||||||
|
// Filter to only consider .cs files
|
||||||
|
if (!path.EndsWith(".cs", StringComparison.OrdinalIgnoreCase))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
// Double check the file name to avoid false matches
|
||||||
|
string foundFileName = Path.GetFileName(path);
|
||||||
|
if (!string.Equals(foundFileName, scriptFileName, StringComparison.OrdinalIgnoreCase) &&
|
||||||
|
!string.Equals(Path.GetFileNameWithoutExtension(foundFileName), scriptNameWithoutExtension, StringComparison.OrdinalIgnoreCase))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
MonoScript scriptAsset = AssetDatabase.LoadAssetAtPath<MonoScript>(path);
|
||||||
|
if (scriptAsset == null)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
System.Type scriptType = scriptAsset.GetClass();
|
||||||
|
if (scriptType == null || !typeof(MonoBehaviour).IsAssignableFrom(scriptType))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
// Check if component is already attached
|
||||||
|
if (targetObject.GetComponent(scriptType) != null)
|
||||||
|
{
|
||||||
|
return new
|
||||||
|
{
|
||||||
|
message = $"Script '{scriptNameWithoutExtension}' is already attached to object '{objectName}'",
|
||||||
|
component_type = scriptType.Name
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add the component
|
||||||
|
Component component = targetObject.AddComponent(scriptType);
|
||||||
|
if (component != null)
|
||||||
|
{
|
||||||
|
return new
|
||||||
|
{
|
||||||
|
message = $"Successfully attached script '{scriptFileName}' to object '{objectName}'",
|
||||||
|
component_type = scriptType.Name,
|
||||||
|
script_path = path
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Debug.LogError($"Error attaching script '{path}': {ex.Message}");
|
||||||
|
// Continue trying other matches instead of failing immediately
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// If we've tried all possibilities and nothing worked
|
||||||
|
throw new System.Exception($"Could not attach script '{scriptFileName}' to object '{objectName}'. No valid script found or component creation failed.");
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -6,22 +6,35 @@ def register_script_tools(mcp: FastMCP):
|
||||||
"""Register all script-related tools with the MCP server."""
|
"""Register all script-related tools with the MCP server."""
|
||||||
|
|
||||||
@mcp.tool()
|
@mcp.tool()
|
||||||
def view_script(ctx: Context, script_path: str) -> str:
|
def view_script(ctx: Context, script_path: str, require_exists: bool = True) -> str:
|
||||||
"""View the contents of a Unity script file.
|
"""View the contents of a Unity script file.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
ctx: The MCP context
|
ctx: The MCP context
|
||||||
script_path: Path to the script file relative to the Assets folder
|
script_path: Path to the script file relative to the Assets folder
|
||||||
|
require_exists: Whether to raise an error if the file doesn't exist (default: True)
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
str: The contents of the script file or error message
|
str: The contents of the script file or error message
|
||||||
"""
|
"""
|
||||||
try:
|
try:
|
||||||
|
# Normalize script path to ensure it has the correct format
|
||||||
|
if not script_path.startswith("Assets/"):
|
||||||
|
script_path = f"Assets/{script_path}"
|
||||||
|
|
||||||
|
# Debug to help diagnose issues
|
||||||
|
print(f"ViewScript - Using normalized script path: {script_path}")
|
||||||
|
|
||||||
# Send command to Unity to read the script file
|
# Send command to Unity to read the script file
|
||||||
response = get_unity_connection().send_command("VIEW_SCRIPT", {
|
response = get_unity_connection().send_command("VIEW_SCRIPT", {
|
||||||
"script_path": script_path
|
"script_path": script_path,
|
||||||
|
"require_exists": require_exists
|
||||||
})
|
})
|
||||||
return response.get("content", "Script not found")
|
|
||||||
|
if response.get("exists", True):
|
||||||
|
return response.get("content", "Script contents not available")
|
||||||
|
else:
|
||||||
|
return response.get("message", "Script not found")
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
return f"Error viewing script: {str(e)}"
|
return f"Error viewing script: {str(e)}"
|
||||||
|
|
||||||
|
|
@ -32,7 +45,9 @@ def register_script_tools(mcp: FastMCP):
|
||||||
script_type: str = "MonoBehaviour",
|
script_type: str = "MonoBehaviour",
|
||||||
namespace: str = None,
|
namespace: str = None,
|
||||||
template: str = None,
|
template: str = None,
|
||||||
overwrite: bool = False
|
script_folder: str = None,
|
||||||
|
overwrite: bool = False,
|
||||||
|
content: str = None
|
||||||
) -> str:
|
) -> str:
|
||||||
"""Create a new Unity script file.
|
"""Create a new Unity script file.
|
||||||
|
|
||||||
|
|
@ -42,33 +57,59 @@ def register_script_tools(mcp: FastMCP):
|
||||||
script_type: Type of script (e.g., MonoBehaviour, ScriptableObject)
|
script_type: Type of script (e.g., MonoBehaviour, ScriptableObject)
|
||||||
namespace: Optional namespace for the script
|
namespace: Optional namespace for the script
|
||||||
template: Optional custom template to use
|
template: Optional custom template to use
|
||||||
|
script_folder: Optional folder path within Assets to create the script
|
||||||
overwrite: Whether to overwrite if script already exists (default: False)
|
overwrite: Whether to overwrite if script already exists (default: False)
|
||||||
|
content: Optional custom content for the script
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
str: Success message or error details
|
str: Success message or error details
|
||||||
"""
|
"""
|
||||||
try:
|
try:
|
||||||
# First check if a script with this name already exists
|
|
||||||
unity = get_unity_connection()
|
unity = get_unity_connection()
|
||||||
|
|
||||||
|
# Determine script path based on script_folder parameter
|
||||||
|
if script_folder:
|
||||||
|
# Use provided folder path
|
||||||
|
# Normalize the folder path first
|
||||||
|
if script_folder.startswith("Assets/"):
|
||||||
|
normalized_folder = script_folder
|
||||||
|
else:
|
||||||
|
normalized_folder = f"Assets/{script_folder}"
|
||||||
|
|
||||||
|
# Create the full path
|
||||||
|
if normalized_folder.endswith("/"):
|
||||||
|
script_path = f"{normalized_folder}{script_name}.cs"
|
||||||
|
else:
|
||||||
|
script_path = f"{normalized_folder}/{script_name}.cs"
|
||||||
|
|
||||||
|
# Debug to help diagnose issues
|
||||||
|
print(f"CreateScript - Folder: {script_folder}")
|
||||||
|
print(f"CreateScript - Normalized folder: {normalized_folder}")
|
||||||
|
print(f"CreateScript - Script path: {script_path}")
|
||||||
|
else:
|
||||||
|
# Default to Scripts folder when no folder is provided
|
||||||
script_path = f"Assets/Scripts/{script_name}.cs"
|
script_path = f"Assets/Scripts/{script_name}.cs"
|
||||||
|
print(f"CreateScript - Using default script path: {script_path}")
|
||||||
|
|
||||||
# Try to view the script to check if it exists
|
# Send command to Unity to create the script directly
|
||||||
existing_script_response = unity.send_command("VIEW_SCRIPT", {
|
# The C# handler will handle the file existence check
|
||||||
"script_path": script_path
|
params = {
|
||||||
})
|
|
||||||
|
|
||||||
# If the script exists and overwrite is False, return a message
|
|
||||||
if "content" in existing_script_response and not overwrite:
|
|
||||||
return f"Script '{script_name}.cs' already exists. Use overwrite=True to replace it."
|
|
||||||
|
|
||||||
# Send command to Unity to create the script
|
|
||||||
response = unity.send_command("CREATE_SCRIPT", {
|
|
||||||
"script_name": script_name,
|
"script_name": script_name,
|
||||||
"script_type": script_type,
|
"script_type": script_type,
|
||||||
"namespace": namespace,
|
"namespace": namespace,
|
||||||
"template": template,
|
"template": template,
|
||||||
"overwrite": overwrite
|
"overwrite": overwrite
|
||||||
})
|
}
|
||||||
|
|
||||||
|
# Add script_folder if provided
|
||||||
|
if script_folder:
|
||||||
|
params["script_folder"] = script_folder
|
||||||
|
|
||||||
|
# Add content if provided
|
||||||
|
if content:
|
||||||
|
params["content"] = content
|
||||||
|
|
||||||
|
response = unity.send_command("CREATE_SCRIPT", params)
|
||||||
return response.get("message", "Script created successfully")
|
return response.get("message", "Script created successfully")
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
return f"Error creating script: {str(e)}"
|
return f"Error creating script: {str(e)}"
|
||||||
|
|
@ -96,9 +137,19 @@ def register_script_tools(mcp: FastMCP):
|
||||||
try:
|
try:
|
||||||
unity = get_unity_connection()
|
unity = get_unity_connection()
|
||||||
|
|
||||||
|
# Normalize script path to ensure it has the correct format
|
||||||
|
# Make sure the path starts with Assets/ but not Assets/Assets/
|
||||||
|
if not script_path.startswith("Assets/"):
|
||||||
|
script_path = f"Assets/{script_path}"
|
||||||
|
|
||||||
|
# Debug to help diagnose issues
|
||||||
|
print(f"UpdateScript - Original path: {script_path}")
|
||||||
|
|
||||||
# Parse script path (for potential creation)
|
# Parse script path (for potential creation)
|
||||||
script_name = script_path.split("/")[-1].replace(".cs", "")
|
script_name = script_path.split("/")[-1]
|
||||||
script_folder = "/".join(script_path.split("/")[:-1])
|
if not script_name.endswith(".cs"):
|
||||||
|
script_name += ".cs"
|
||||||
|
script_path = f"{script_path}.cs"
|
||||||
|
|
||||||
if create_if_missing:
|
if create_if_missing:
|
||||||
# When create_if_missing is true, we'll just try to update directly,
|
# When create_if_missing is true, we'll just try to update directly,
|
||||||
|
|
@ -183,52 +234,29 @@ def register_script_tools(mcp: FastMCP):
|
||||||
if not script_name.lower().endswith(".cs"):
|
if not script_name.lower().endswith(".cs"):
|
||||||
script_name = f"{script_name}.cs"
|
script_name = f"{script_name}.cs"
|
||||||
|
|
||||||
# Determine the full script path
|
# Remove any path information from script_name if it contains slashes
|
||||||
if script_path is None:
|
script_basename = script_name.split('/')[-1]
|
||||||
# Use default Scripts folder if no path provided
|
|
||||||
script_path = f"Assets/Scripts/{script_name}"
|
# Determine the full script path if provided
|
||||||
elif not script_path.endswith(script_name):
|
if script_path is not None:
|
||||||
|
# Ensure script_path starts with Assets/
|
||||||
|
if not script_path.startswith("Assets/"):
|
||||||
|
script_path = f"Assets/{script_path}"
|
||||||
|
|
||||||
# If path is just a directory, append the script name
|
# If path is just a directory, append the script name
|
||||||
|
if not script_path.endswith(script_basename):
|
||||||
if script_path.endswith("/"):
|
if script_path.endswith("/"):
|
||||||
script_path = f"{script_path}{script_name}"
|
script_path = f"{script_path}{script_basename}"
|
||||||
else:
|
else:
|
||||||
script_path = f"{script_path}/{script_name}"
|
script_path = f"{script_path}/{script_basename}"
|
||||||
|
|
||||||
# Check if the script exists by trying to view it
|
|
||||||
existing_script_response = unity.send_command("VIEW_SCRIPT", {
|
|
||||||
"script_path": script_path
|
|
||||||
})
|
|
||||||
|
|
||||||
if "content" not in existing_script_response:
|
|
||||||
# If not found at the specific path, try to search for it in the project
|
|
||||||
script_found = False
|
|
||||||
try:
|
|
||||||
# Search in the entire Assets folder
|
|
||||||
script_assets = unity.send_command("LIST_SCRIPTS", {
|
|
||||||
"folder_path": "Assets"
|
|
||||||
}).get("scripts", [])
|
|
||||||
|
|
||||||
# Look for matching script name in any folder
|
|
||||||
matching_scripts = [path for path in script_assets if path.endswith(f"/{script_name}") or path == script_name]
|
|
||||||
|
|
||||||
if matching_scripts:
|
|
||||||
script_path = matching_scripts[0]
|
|
||||||
script_found = True
|
|
||||||
if len(matching_scripts) > 1:
|
|
||||||
return f"Multiple scripts named '{script_name}' found in the project. Please specify script_path parameter."
|
|
||||||
except:
|
|
||||||
pass
|
|
||||||
|
|
||||||
if not script_found:
|
|
||||||
return f"Script '{script_name}' not found in the project."
|
|
||||||
|
|
||||||
# Check if the script is already attached
|
# Check if the script is already attached
|
||||||
object_props = unity.send_command("GET_OBJECT_PROPERTIES", {
|
object_props = unity.send_command("GET_OBJECT_PROPERTIES", {
|
||||||
"name": object_name
|
"name": object_name
|
||||||
})
|
})
|
||||||
|
|
||||||
# Extract script name without .cs and without path
|
# Extract script name without .cs and without path for component type checking
|
||||||
script_class_name = script_name.replace(".cs", "")
|
script_class_name = script_basename.replace(".cs", "")
|
||||||
|
|
||||||
# Check if component is already attached
|
# Check if component is already attached
|
||||||
components = object_props.get("components", [])
|
components = object_props.get("components", [])
|
||||||
|
|
@ -237,11 +265,16 @@ def register_script_tools(mcp: FastMCP):
|
||||||
return f"Script '{script_class_name}' is already attached to '{object_name}'."
|
return f"Script '{script_class_name}' is already attached to '{object_name}'."
|
||||||
|
|
||||||
# Send command to Unity to attach the script
|
# Send command to Unity to attach the script
|
||||||
response = unity.send_command("ATTACH_SCRIPT", {
|
params = {
|
||||||
"object_name": object_name,
|
"object_name": object_name,
|
||||||
"script_name": script_name,
|
"script_name": script_basename
|
||||||
"script_path": script_path
|
}
|
||||||
})
|
|
||||||
|
# Add script_path if provided
|
||||||
|
if script_path:
|
||||||
|
params["script_path"] = script_path
|
||||||
|
|
||||||
|
response = unity.send_command("ATTACH_SCRIPT", params)
|
||||||
return response.get("message", "Script attached successfully")
|
return response.get("message", "Script attached successfully")
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
return f"Error attaching script: {str(e)}"
|
return f"Error attaching script: {str(e)}"
|
||||||
Loading…
Reference in New Issue