increased command list

main
Justin Barnett 2025-03-21 06:30:41 -04:00
parent 8102460c7c
commit 3352ba3033
1 changed files with 350 additions and 16 deletions

View File

@ -585,32 +585,366 @@ 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())
{
MethodInfo[] methods = type.GetMethods(BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
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>();
foreach (MethodInfo method in methods)
// Add a simple command that we know will work for testing
menuCommands.Add("Window/Unity MCP");
Debug.Log("Starting command collection...");
try
{
// 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))
{
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())
{
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
{
// Look for the MenuItem attribute
object[] attributes = method.GetCustomAttributes(typeof(UnityEditor.MenuItem), false);
if (attributes.Length > 0)
if (attributes != null && attributes.Length > 0)
{
UnityEditor.MenuItem menuItem = attributes[0] as UnityEditor.MenuItem;
commands.Add(menuItem.menuItem);
foreach (var attr in attributes)
{
var menuItem = attr as UnityEditor.MenuItem;
if (menuItem != null && !string.IsNullOrEmpty(menuItem.menuItem))
{
menuCommands.Add(menuItem.menuItem);
itemCount++;
}
}
}
return new { commands = commands };
}
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
};
}
}
}
}