using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; using MCPForUnity.Editor.Constants; using MCPForUnity.Editor.Helpers; using MCPForUnity.Editor.Services; using MCPForUnity.Editor.Windows.Components.Advanced; using MCPForUnity.Editor.Windows.Components.AssetGen; using MCPForUnity.Editor.Windows.Components.Branding; using MCPForUnity.Editor.Windows.Components.ClientConfig; using MCPForUnity.Editor.Windows.Components.Connection; using MCPForUnity.Editor.Windows.Components.Resources; using MCPForUnity.Editor.Windows.Components.Tools; using MCPForUnity.Editor.Setup; using MCPForUnity.Editor.Windows.Components.Validation; using UnityEditor; using UnityEditor.UIElements; using UnityEngine; using UnityEngine.UIElements; namespace MCPForUnity.Editor.Windows { public class MCPForUnityEditorWindow : EditorWindow { // Section controllers private McpConnectionSection connectionSection; private McpClientConfigSection clientConfigSection; private McpAdvancedSection advancedSection; private McpToolsSection toolsSection; private McpResourcesSection resourcesSection; private McpAssetGenSection assetGenSection; // UI Elements private Label versionLabel; private VisualElement updateNotification; private Label updateNotificationText; private ToolbarToggle clientsTabToggle; private ToolbarToggle depsTabToggle; private ToolbarToggle advancedTabToggle; private ToolbarToggle toolsTabToggle; private ToolbarToggle resourcesTabToggle; private ToolbarToggle assetGenTabToggle; private VisualElement clientsPanel; private VisualElement depsPanel; private VisualElement advancedPanel; private VisualElement toolsPanel; private VisualElement resourcesPanel; private VisualElement assetGenPanel; private static readonly HashSet OpenWindows = new(); private bool guiCreated = false; private bool toolsLoaded = false; private bool resourcesLoaded = false; private double lastRefreshTime = 0; private const double RefreshDebounceSeconds = 0.5; private bool updateCheckQueued = false; private bool updateCheckInFlight = false; private enum ActivePanel { Clients, Deps, Advanced, Tools, Resources, AssetGen } internal static void CloseAllWindows() { var windows = OpenWindows.Where(window => window != null).ToArray(); foreach (var window in windows) { window.Close(); } } public static void ShowWindow() { var existingWindows = UnityEngine.Resources.FindObjectsOfTypeAll(); MCPForUnityEditorWindow window = null; if (existingWindows.Length > 0) { window = existingWindows[0]; // If multiple instances exist, keep one and close the extras to avoid stale hidden tabs. for (int i = 1; i < existingWindows.Length; i++) { try { existingWindows[i].Close(); } catch (Exception ex) { McpLog.Warn($"Error closing duplicate MCP window: {ex.Message}"); } } } else { window = GetWindow(ProductInfo.ProductName); } window.titleContent = new GUIContent(ProductInfo.ProductName); window.minSize = new Vector2(500, 340); if (window.position.width < 100 || window.position.height < 100) { window.position = new Rect(120, 120, 900, 700); } window.Show(); window.ShowTab(); window.Focus(); } // Helper to check and manage open windows from other classes public static bool HasAnyOpenWindow() { return OpenWindows.Count > 0; } public static void CloseAllOpenWindows() { if (OpenWindows.Count == 0) return; // Copy to array to avoid modifying the collection while iterating var arr = new MCPForUnityEditorWindow[OpenWindows.Count]; OpenWindows.CopyTo(arr); foreach (var window in arr) { try { window?.Close(); } catch (Exception ex) { McpLog.Warn($"Error closing MCP window: {ex.Message}"); } } } public void CreateGUI() { // Guard against repeated CreateGUI calls (e.g., domain reloads) if (guiCreated) return; string basePath = AssetPathUtility.GetMcpPackageRootPath(); // Load main window UXML var visualTree = AssetDatabase.LoadAssetAtPath( $"{basePath}/Editor/Windows/MCPForUnityEditorWindow.uxml" ); if (visualTree == null) { McpLog.Error( $"Failed to load UXML at: {basePath}/Editor/Windows/MCPForUnityEditorWindow.uxml" ); return; } rootVisualElement.Clear(); visualTree.CloneTree(rootVisualElement); // Load main window USS var mainStyleSheet = AssetDatabase.LoadAssetAtPath( $"{basePath}/Editor/Windows/MCPForUnityEditorWindow.uss" ); if (mainStyleSheet != null) { rootVisualElement.styleSheets.Add(mainStyleSheet); } // Load common USS var commonStyleSheet = AssetDatabase.LoadAssetAtPath( $"{basePath}/Editor/Windows/Components/Common.uss" ); if (commonStyleSheet != null) { rootVisualElement.styleSheets.Add(commonStyleSheet); } // Embed the Ocean brand mark at the left of the header bar var headerLeft = rootVisualElement.Q("header-left"); if (headerLeft != null && headerLeft.Q() == null) { var logo = new OceanMark { name = "header-logo" }; logo.AddToClassList("header-logo"); headerLeft.Insert(0, logo); } // Cache UI elements versionLabel = rootVisualElement.Q