using System;
using System.Collections.Generic;
using System.Linq;
using Newtonsoft.Json.Linq;
using UnityEditor;
using UnityEditorInternal; // Required for tag management
using UnityEngine;
using UnityMcpBridge.Editor.Helpers; // For Response class
namespace UnityMcpBridge.Editor.Tools
{
///
/// Handles operations related to controlling and querying the Unity Editor state,
/// including managing Tags and Layers.
///
public static class ManageEditor
{
// Constant for starting user layer index
private const int FirstUserLayerIndex = 8;
// Constant for total layer count
private const int TotalLayerCount = 32;
///
/// Main handler for editor management actions.
///
public static object HandleCommand(JObject @params)
{
string action = @params["action"]?.ToString().ToLower();
// Parameters for specific actions
string tagName = @params["tagName"]?.ToString();
string layerName = @params["layerName"]?.ToString();
bool waitForCompletion = @params["waitForCompletion"]?.ToObject() ?? false; // Example - not used everywhere
if (string.IsNullOrEmpty(action))
{
return Response.Error("Action parameter is required.");
}
// Route action
switch (action)
{
// Play Mode Control
case "play":
try
{
if (!EditorApplication.isPlaying)
{
EditorApplication.isPlaying = true;
return Response.Success("Entered play mode.");
}
return Response.Success("Already in play mode.");
}
catch (Exception e)
{
return Response.Error($"Error entering play mode: {e.Message}");
}
case "pause":
try
{
if (EditorApplication.isPlaying)
{
EditorApplication.isPaused = !EditorApplication.isPaused;
return Response.Success(
EditorApplication.isPaused ? "Game paused." : "Game resumed."
);
}
return Response.Error("Cannot pause/resume: Not in play mode.");
}
catch (Exception e)
{
return Response.Error($"Error pausing/resuming game: {e.Message}");
}
case "stop":
try
{
if (EditorApplication.isPlaying)
{
EditorApplication.isPlaying = false;
return Response.Success("Exited play mode.");
}
return Response.Success("Already stopped (not in play mode).");
}
catch (Exception e)
{
return Response.Error($"Error stopping play mode: {e.Message}");
}
// Editor State/Info
case "get_state":
return GetEditorState();
case "get_windows":
return GetEditorWindows();
case "get_active_tool":
return GetActiveTool();
case "get_selection":
return GetSelection();
case "set_active_tool":
string toolName = @params["toolName"]?.ToString();
if (string.IsNullOrEmpty(toolName))
return Response.Error("'toolName' parameter required for set_active_tool.");
return SetActiveTool(toolName);
// Tag Management
case "add_tag":
if (string.IsNullOrEmpty(tagName))
return Response.Error("'tagName' parameter required for add_tag.");
return AddTag(tagName);
case "remove_tag":
if (string.IsNullOrEmpty(tagName))
return Response.Error("'tagName' parameter required for remove_tag.");
return RemoveTag(tagName);
case "get_tags":
return GetTags(); // Helper to list current tags
// Layer Management
case "add_layer":
if (string.IsNullOrEmpty(layerName))
return Response.Error("'layerName' parameter required for add_layer.");
return AddLayer(layerName);
case "remove_layer":
if (string.IsNullOrEmpty(layerName))
return Response.Error("'layerName' parameter required for remove_layer.");
return RemoveLayer(layerName);
case "get_layers":
return GetLayers(); // Helper to list current layers
// --- Settings (Example) ---
// case "set_resolution":
// int? width = @params["width"]?.ToObject();
// int? height = @params["height"]?.ToObject();
// if (!width.HasValue || !height.HasValue) return Response.Error("'width' and 'height' parameters required.");
// return SetGameViewResolution(width.Value, height.Value);
// case "set_quality":
// // Handle string name or int index
// return SetQualityLevel(@params["qualityLevel"]);
default:
return Response.Error(
$"Unknown action: '{action}'. Supported actions include play, pause, stop, get_state, get_windows, get_active_tool, get_selection, set_active_tool, add_tag, remove_tag, get_tags, add_layer, remove_layer, get_layers."
);
}
}
// --- Editor State/Info Methods ---
private static object GetEditorState()
{
try
{
var state = new
{
isPlaying = EditorApplication.isPlaying,
isPaused = EditorApplication.isPaused,
isCompiling = EditorApplication.isCompiling,
isUpdating = EditorApplication.isUpdating,
applicationPath = EditorApplication.applicationPath,
applicationContentsPath = EditorApplication.applicationContentsPath,
timeSinceStartup = EditorApplication.timeSinceStartup,
};
return Response.Success("Retrieved editor state.", state);
}
catch (Exception e)
{
return Response.Error($"Error getting editor state: {e.Message}");
}
}
private static object GetEditorWindows()
{
try
{
// Get all types deriving from EditorWindow
var windowTypes = AppDomain
.CurrentDomain.GetAssemblies()
.SelectMany(assembly => assembly.GetTypes())
.Where(type => type.IsSubclassOf(typeof(EditorWindow)))
.ToList();
var openWindows = new List