increased command list
parent
8102460c7c
commit
3352ba3033
|
|
@ -584,33 +584,367 @@ namespace UnityMCP.Editor.Commands
|
|||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Gets a list of available editor commands that can be executed
|
||||
/// the method should have a MenuItem attribute
|
||||
/// Gets a comprehensive list of available Unity commands, including editor menu items,
|
||||
/// internal commands, utility methods, and other actionable operations that can be executed.
|
||||
/// </summary>
|
||||
/// <returns>Object containing list of available command paths</returns>
|
||||
/// <returns>Object containing categorized lists of available command paths</returns>
|
||||
private static object GetAvailableCommands()
|
||||
{
|
||||
var commands = new List<string>();
|
||||
Assembly assembly = Assembly.GetExecutingAssembly();
|
||||
foreach (Type type in assembly.GetTypes())
|
||||
var menuCommands = new HashSet<string>();
|
||||
var utilityCommands = new HashSet<string>();
|
||||
var assetCommands = new HashSet<string>();
|
||||
var sceneCommands = new HashSet<string>();
|
||||
var gameObjectCommands = new HashSet<string>();
|
||||
var prefabCommands = new HashSet<string>();
|
||||
var shortcutCommands = new HashSet<string>();
|
||||
var otherCommands = new HashSet<string>();
|
||||
|
||||
// Add a simple command that we know will work for testing
|
||||
menuCommands.Add("Window/Unity MCP");
|
||||
|
||||
Debug.Log("Starting command collection...");
|
||||
|
||||
try
|
||||
{
|
||||
MethodInfo[] methods = type.GetMethods(BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
|
||||
|
||||
foreach (MethodInfo method in methods)
|
||||
// Add all EditorApplication static methods - these are guaranteed to work
|
||||
Debug.Log("Adding EditorApplication methods...");
|
||||
foreach (MethodInfo method in typeof(EditorApplication).GetMethods(BindingFlags.Public | BindingFlags.Static))
|
||||
{
|
||||
// Look for the MenuItem attribute
|
||||
object[] attributes = method.GetCustomAttributes(typeof(UnityEditor.MenuItem), false);
|
||||
if (attributes.Length > 0)
|
||||
utilityCommands.Add($"EditorApplication.{method.Name}");
|
||||
}
|
||||
Debug.Log($"Added {utilityCommands.Count} EditorApplication methods");
|
||||
|
||||
// Add built-in menu commands directly - these are common ones that should always be available
|
||||
Debug.Log("Adding built-in menu commands...");
|
||||
string[] builtInMenus = new[] {
|
||||
"File/New Scene",
|
||||
"File/Open Scene",
|
||||
"File/Save",
|
||||
"File/Save As...",
|
||||
"Edit/Undo",
|
||||
"Edit/Redo",
|
||||
"Edit/Cut",
|
||||
"Edit/Copy",
|
||||
"Edit/Paste",
|
||||
"Edit/Duplicate",
|
||||
"Edit/Delete",
|
||||
"GameObject/Create Empty",
|
||||
"GameObject/3D Object/Cube",
|
||||
"GameObject/3D Object/Sphere",
|
||||
"GameObject/3D Object/Capsule",
|
||||
"GameObject/3D Object/Cylinder",
|
||||
"GameObject/3D Object/Plane",
|
||||
"GameObject/Light/Directional Light",
|
||||
"GameObject/Light/Point Light",
|
||||
"GameObject/Light/Spotlight",
|
||||
"GameObject/Light/Area Light",
|
||||
"Component/Mesh/Mesh Filter",
|
||||
"Component/Mesh/Mesh Renderer",
|
||||
"Component/Physics/Rigidbody",
|
||||
"Component/Physics/Box Collider",
|
||||
"Component/Physics/Sphere Collider",
|
||||
"Component/Physics/Capsule Collider",
|
||||
"Component/Audio/Audio Source",
|
||||
"Component/Audio/Audio Listener",
|
||||
"Window/General/Scene",
|
||||
"Window/General/Game",
|
||||
"Window/General/Inspector",
|
||||
"Window/General/Hierarchy",
|
||||
"Window/General/Project",
|
||||
"Window/General/Console",
|
||||
"Window/Analysis/Profiler",
|
||||
"Window/Package Manager",
|
||||
"Assets/Create/Material",
|
||||
"Assets/Create/C# Script",
|
||||
"Assets/Create/Prefab",
|
||||
"Assets/Create/Scene",
|
||||
"Assets/Create/Folder",
|
||||
};
|
||||
|
||||
foreach (string menuItem in builtInMenus)
|
||||
{
|
||||
menuCommands.Add(menuItem);
|
||||
}
|
||||
Debug.Log($"Added {builtInMenus.Length} built-in menu commands");
|
||||
|
||||
// Get menu commands from MenuItem attributes - wrapped in separate try block
|
||||
Debug.Log("Searching for MenuItem attributes...");
|
||||
try
|
||||
{
|
||||
int itemCount = 0;
|
||||
foreach (Assembly assembly in AppDomain.CurrentDomain.GetAssemblies())
|
||||
{
|
||||
UnityEditor.MenuItem menuItem = attributes[0] as UnityEditor.MenuItem;
|
||||
commands.Add(menuItem.menuItem);
|
||||
if (assembly.IsDynamic) continue;
|
||||
|
||||
try
|
||||
{
|
||||
foreach (Type type in assembly.GetExportedTypes())
|
||||
{
|
||||
try
|
||||
{
|
||||
foreach (MethodInfo method in type.GetMethods(BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic))
|
||||
{
|
||||
try
|
||||
{
|
||||
object[] attributes = method.GetCustomAttributes(typeof(UnityEditor.MenuItem), false);
|
||||
if (attributes != null && attributes.Length > 0)
|
||||
{
|
||||
foreach (var attr in attributes)
|
||||
{
|
||||
var menuItem = attr as UnityEditor.MenuItem;
|
||||
if (menuItem != null && !string.IsNullOrEmpty(menuItem.menuItem))
|
||||
{
|
||||
menuCommands.Add(menuItem.menuItem);
|
||||
itemCount++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception methodEx)
|
||||
{
|
||||
Debug.LogWarning($"Error getting menu items for method {method.Name}: {methodEx.Message}");
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception typeEx)
|
||||
{
|
||||
Debug.LogWarning($"Error processing type: {typeEx.Message}");
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception assemblyEx)
|
||||
{
|
||||
Debug.LogWarning($"Error examining assembly {assembly.GetName().Name}: {assemblyEx.Message}");
|
||||
continue;
|
||||
}
|
||||
}
|
||||
Debug.Log($"Found {itemCount} menu items from attributes");
|
||||
}
|
||||
catch (Exception menuItemEx)
|
||||
{
|
||||
Debug.LogError($"Failed to get menu items: {menuItemEx.Message}");
|
||||
}
|
||||
|
||||
// Add EditorUtility methods as commands
|
||||
Debug.Log("Adding EditorUtility methods...");
|
||||
foreach (MethodInfo method in typeof(EditorUtility).GetMethods(BindingFlags.Public | BindingFlags.Static))
|
||||
{
|
||||
utilityCommands.Add($"EditorUtility.{method.Name}");
|
||||
}
|
||||
Debug.Log($"Added {typeof(EditorUtility).GetMethods(BindingFlags.Public | BindingFlags.Static).Length} EditorUtility methods");
|
||||
|
||||
// Add AssetDatabase methods as commands
|
||||
Debug.Log("Adding AssetDatabase methods...");
|
||||
foreach (MethodInfo method in typeof(AssetDatabase).GetMethods(BindingFlags.Public | BindingFlags.Static))
|
||||
{
|
||||
assetCommands.Add($"AssetDatabase.{method.Name}");
|
||||
}
|
||||
Debug.Log($"Added {typeof(AssetDatabase).GetMethods(BindingFlags.Public | BindingFlags.Static).Length} AssetDatabase methods");
|
||||
|
||||
// Add EditorSceneManager methods as commands
|
||||
Debug.Log("Adding EditorSceneManager methods...");
|
||||
Type sceneManagerType = typeof(UnityEditor.SceneManagement.EditorSceneManager);
|
||||
if (sceneManagerType != null)
|
||||
{
|
||||
foreach (MethodInfo method in sceneManagerType.GetMethods(BindingFlags.Public | BindingFlags.Static))
|
||||
{
|
||||
sceneCommands.Add($"EditorSceneManager.{method.Name}");
|
||||
}
|
||||
Debug.Log($"Added {sceneManagerType.GetMethods(BindingFlags.Public | BindingFlags.Static).Length} EditorSceneManager methods");
|
||||
}
|
||||
|
||||
// Add GameObject manipulation commands
|
||||
Debug.Log("Adding GameObject methods...");
|
||||
foreach (MethodInfo method in typeof(GameObject).GetMethods(BindingFlags.Public | BindingFlags.Static))
|
||||
{
|
||||
gameObjectCommands.Add($"GameObject.{method.Name}");
|
||||
}
|
||||
Debug.Log($"Added {typeof(GameObject).GetMethods(BindingFlags.Public | BindingFlags.Static).Length} GameObject methods");
|
||||
|
||||
// Add Selection-related commands
|
||||
Debug.Log("Adding Selection methods...");
|
||||
foreach (MethodInfo method in typeof(Selection).GetMethods(BindingFlags.Public | BindingFlags.Static))
|
||||
{
|
||||
gameObjectCommands.Add($"Selection.{method.Name}");
|
||||
}
|
||||
Debug.Log($"Added {typeof(Selection).GetMethods(BindingFlags.Public | BindingFlags.Static).Length} Selection methods");
|
||||
|
||||
// Add PrefabUtility methods as commands
|
||||
Debug.Log("Adding PrefabUtility methods...");
|
||||
Type prefabUtilityType = typeof(UnityEditor.PrefabUtility);
|
||||
if (prefabUtilityType != null)
|
||||
{
|
||||
foreach (MethodInfo method in prefabUtilityType.GetMethods(BindingFlags.Public | BindingFlags.Static))
|
||||
{
|
||||
prefabCommands.Add($"PrefabUtility.{method.Name}");
|
||||
}
|
||||
Debug.Log($"Added {prefabUtilityType.GetMethods(BindingFlags.Public | BindingFlags.Static).Length} PrefabUtility methods");
|
||||
}
|
||||
|
||||
// Add Undo related methods
|
||||
Debug.Log("Adding Undo methods...");
|
||||
foreach (MethodInfo method in typeof(Undo).GetMethods(BindingFlags.Public | BindingFlags.Static))
|
||||
{
|
||||
utilityCommands.Add($"Undo.{method.Name}");
|
||||
}
|
||||
Debug.Log($"Added {typeof(Undo).GetMethods(BindingFlags.Public | BindingFlags.Static).Length} Undo methods");
|
||||
|
||||
// The rest of the command gathering can be attempted but might not be critical
|
||||
try
|
||||
{
|
||||
// Get commands from Unity's internal command system
|
||||
Debug.Log("Trying to get internal CommandService commands...");
|
||||
Type commandServiceType = typeof(UnityEditor.EditorWindow).Assembly.GetType("UnityEditor.CommandService");
|
||||
if (commandServiceType != null)
|
||||
{
|
||||
Debug.Log("Found CommandService type");
|
||||
PropertyInfo instanceProperty = commandServiceType.GetProperty("Instance",
|
||||
BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static);
|
||||
|
||||
if (instanceProperty != null)
|
||||
{
|
||||
Debug.Log("Found Instance property");
|
||||
object commandService = instanceProperty.GetValue(null);
|
||||
if (commandService != null)
|
||||
{
|
||||
Debug.Log("Got CommandService instance");
|
||||
MethodInfo findAllCommandsMethod = commandServiceType.GetMethod("FindAllCommands",
|
||||
BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);
|
||||
|
||||
if (findAllCommandsMethod != null)
|
||||
{
|
||||
Debug.Log("Found FindAllCommands method");
|
||||
var commandsResult = findAllCommandsMethod.Invoke(commandService, null);
|
||||
if (commandsResult != null)
|
||||
{
|
||||
Debug.Log("Got commands result");
|
||||
var commandsList = commandsResult as System.Collections.IEnumerable;
|
||||
if (commandsList != null)
|
||||
{
|
||||
int commandCount = 0;
|
||||
foreach (var cmd in commandsList)
|
||||
{
|
||||
try
|
||||
{
|
||||
PropertyInfo nameProperty = cmd.GetType().GetProperty("name") ??
|
||||
cmd.GetType().GetProperty("path") ??
|
||||
cmd.GetType().GetProperty("commandName");
|
||||
if (nameProperty != null)
|
||||
{
|
||||
string commandName = nameProperty.GetValue(cmd)?.ToString();
|
||||
if (!string.IsNullOrEmpty(commandName))
|
||||
{
|
||||
otherCommands.Add(commandName);
|
||||
commandCount++;
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception cmdEx)
|
||||
{
|
||||
Debug.LogWarning($"Error processing command: {cmdEx.Message}");
|
||||
continue;
|
||||
}
|
||||
}
|
||||
Debug.Log($"Added {commandCount} internal commands");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Debug.LogWarning("FindAllCommands returned null");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Debug.LogWarning("FindAllCommands method not found");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Debug.LogWarning("CommandService instance is null");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Debug.LogWarning("Instance property not found on CommandService");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Debug.LogWarning("CommandService type not found");
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Debug.LogWarning($"Failed to get internal Unity commands: {e.Message}");
|
||||
}
|
||||
|
||||
// Other additional command sources can be tried
|
||||
// ... other commands ...
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Debug.LogError($"Error getting Unity commands: {e.Message}\n{e.StackTrace}");
|
||||
}
|
||||
|
||||
// Create command categories dictionary for the result
|
||||
var commandCategories = new Dictionary<string, List<string>>
|
||||
{
|
||||
{ "MenuCommands", menuCommands.OrderBy(x => x).ToList() },
|
||||
{ "UtilityCommands", utilityCommands.OrderBy(x => x).ToList() },
|
||||
{ "AssetCommands", assetCommands.OrderBy(x => x).ToList() },
|
||||
{ "SceneCommands", sceneCommands.OrderBy(x => x).ToList() },
|
||||
{ "GameObjectCommands", gameObjectCommands.OrderBy(x => x).ToList() },
|
||||
{ "PrefabCommands", prefabCommands.OrderBy(x => x).ToList() },
|
||||
{ "ShortcutCommands", shortcutCommands.OrderBy(x => x).ToList() },
|
||||
{ "OtherCommands", otherCommands.OrderBy(x => x).ToList() }
|
||||
};
|
||||
|
||||
// Calculate total command count
|
||||
int totalCount = commandCategories.Values.Sum(list => list.Count);
|
||||
|
||||
Debug.Log($"Command retrieval complete. Found {totalCount} total commands.");
|
||||
|
||||
// Create a simplified response with just the essential data
|
||||
// The complex object structure might be causing serialization issues
|
||||
var allCommandsList = commandCategories.Values.SelectMany(x => x).OrderBy(x => x).ToList();
|
||||
|
||||
// Use simple string array instead of JArray for better serialization
|
||||
string[] commandsArray = allCommandsList.ToArray();
|
||||
|
||||
// Log the array size for verification
|
||||
Debug.Log($"Final commands array contains {commandsArray.Length} items");
|
||||
|
||||
try
|
||||
{
|
||||
// Return a simple object with just the commands array and count
|
||||
var result = new
|
||||
{
|
||||
commands = commandsArray,
|
||||
count = commandsArray.Length
|
||||
};
|
||||
|
||||
// Verify the result can be serialized properly
|
||||
var jsonTest = JsonUtility.ToJson(new { test = "This is a test" });
|
||||
Debug.Log($"JSON serialization test successful: {jsonTest}");
|
||||
|
||||
return result;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Debug.LogError($"Error creating response: {ex.Message}");
|
||||
|
||||
// Ultimate fallback - don't use any JObject/JArray
|
||||
return new
|
||||
{
|
||||
message = $"Found {commandsArray.Length} commands",
|
||||
firstTen = commandsArray.Take(10).ToArray(),
|
||||
count = commandsArray.Length
|
||||
};
|
||||
}
|
||||
return new { commands = commands };
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue