unity-mcp/MCPForUnity/Editor/Windows/MCPForUnityEditorWindow.cs

178 lines
6.3 KiB
C#

using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using UnityEditor;
using UnityEngine;
using UnityEngine.UIElements;
using MCPForUnity.Editor.Data;
using MCPForUnity.Editor.Helpers;
using MCPForUnity.Editor.Services;
using MCPForUnity.Editor.Windows.Components.Settings;
using MCPForUnity.Editor.Windows.Components.Connection;
using MCPForUnity.Editor.Windows.Components.ClientConfig;
namespace MCPForUnity.Editor.Windows
{
public class MCPForUnityEditorWindow : EditorWindow
{
// Section controllers
private McpSettingsSection settingsSection;
private McpConnectionSection connectionSection;
private McpClientConfigSection clientConfigSection;
// Data
private readonly McpClients mcpClients = new();
private static readonly HashSet<MCPForUnityEditorWindow> OpenWindows = new();
public static void ShowWindow()
{
var window = GetWindow<MCPForUnityEditorWindow>("MCP For Unity");
window.minSize = new Vector2(500, 600);
}
public void CreateGUI()
{
string basePath = AssetPathUtility.GetMcpPackageRootPath();
// Load main window UXML
var visualTree = AssetDatabase.LoadAssetAtPath<VisualTreeAsset>(
$"{basePath}/Editor/Windows/MCPForUnityEditorWindow.uxml"
);
if (visualTree == null)
{
McpLog.Error($"Failed to load UXML at: {basePath}/Editor/Windows/MCPForUnityEditorWindow.uxml");
return;
}
visualTree.CloneTree(rootVisualElement);
// Load main window USS
var mainStyleSheet = AssetDatabase.LoadAssetAtPath<StyleSheet>(
$"{basePath}/Editor/Windows/MCPForUnityEditorWindow.uss"
);
if (mainStyleSheet != null)
{
rootVisualElement.styleSheets.Add(mainStyleSheet);
}
// Load common USS
var commonStyleSheet = AssetDatabase.LoadAssetAtPath<StyleSheet>(
$"{basePath}/Editor/Windows/Components/Common.uss"
);
if (commonStyleSheet != null)
{
rootVisualElement.styleSheets.Add(commonStyleSheet);
}
// Get sections container
var sectionsContainer = rootVisualElement.Q<VisualElement>("sections-container");
if (sectionsContainer == null)
{
McpLog.Error("Failed to find sections-container in UXML");
return;
}
// Load and initialize Settings section
var settingsTree = AssetDatabase.LoadAssetAtPath<VisualTreeAsset>(
$"{basePath}/Editor/Windows/Components/Settings/McpSettingsSection.uxml"
);
if (settingsTree != null)
{
var settingsRoot = settingsTree.Instantiate();
sectionsContainer.Add(settingsRoot);
settingsSection = new McpSettingsSection(settingsRoot);
settingsSection.OnGitUrlChanged += () => clientConfigSection?.UpdateManualConfiguration();
settingsSection.OnHttpServerCommandUpdateRequested += () => connectionSection?.UpdateHttpServerCommandDisplay();
}
// Load and initialize Connection section
var connectionTree = AssetDatabase.LoadAssetAtPath<VisualTreeAsset>(
$"{basePath}/Editor/Windows/Components/Connection/McpConnectionSection.uxml"
);
if (connectionTree != null)
{
var connectionRoot = connectionTree.Instantiate();
sectionsContainer.Add(connectionRoot);
connectionSection = new McpConnectionSection(connectionRoot);
connectionSection.OnManualConfigUpdateRequested += () => clientConfigSection?.UpdateManualConfiguration();
}
// Load and initialize Client Configuration section
var clientConfigTree = AssetDatabase.LoadAssetAtPath<VisualTreeAsset>(
$"{basePath}/Editor/Windows/Components/ClientConfig/McpClientConfigSection.uxml"
);
if (clientConfigTree != null)
{
var clientConfigRoot = clientConfigTree.Instantiate();
sectionsContainer.Add(clientConfigRoot);
clientConfigSection = new McpClientConfigSection(clientConfigRoot, mcpClients);
}
// Initial updates
RefreshAllData();
}
private void OnEnable()
{
EditorApplication.update += OnEditorUpdate;
OpenWindows.Add(this);
}
private void OnDisable()
{
EditorApplication.update -= OnEditorUpdate;
OpenWindows.Remove(this);
}
private void OnFocus()
{
// Only refresh data if UI is built
if (rootVisualElement == null || rootVisualElement.childCount == 0)
return;
RefreshAllData();
}
private void OnEditorUpdate()
{
if (rootVisualElement == null || rootVisualElement.childCount == 0)
return;
connectionSection?.UpdateConnectionStatus();
}
private void RefreshAllData()
{
connectionSection?.UpdateConnectionStatus();
if (MCPServiceLocator.Bridge.IsRunning)
{
_ = connectionSection?.VerifyBridgeConnectionAsync();
}
settingsSection?.UpdatePathOverrides();
clientConfigSection?.RefreshSelectedClient();
}
internal static void RequestHealthVerification()
{
foreach (var window in OpenWindows)
{
window?.ScheduleHealthCheck();
}
}
private void ScheduleHealthCheck()
{
EditorApplication.delayCall += async () =>
{
if (this == null)
{
return;
}
await connectionSection?.VerifyBridgeConnectionAsync();
};
}
}
}