diff --git a/MCPForUnity/Editor/MenuItems/MCPForUnityMenu.cs b/MCPForUnity/Editor/MenuItems/MCPForUnityMenu.cs index 10f0524..38c8ea8 100644 --- a/MCPForUnity/Editor/MenuItems/MCPForUnityMenu.cs +++ b/MCPForUnity/Editor/MenuItems/MCPForUnityMenu.cs @@ -7,13 +7,7 @@ namespace MCPForUnity.Editor.MenuItems { public static class MCPForUnityMenu { - [MenuItem("Window/MCP For Unity/Setup Window", priority = 1)] - public static void ShowSetupWindow() - { - SetupWindowService.ShowSetupWindow(); - } - - [MenuItem("Window/MCP For Unity/Toggle MCP Window %#m", priority = 2)] + [MenuItem("Window/MCP For Unity/Toggle MCP Window %#m", priority = 1)] public static void ToggleMCPWindow() { if (MCPForUnityEditorWindow.HasAnyOpenWindow()) @@ -25,5 +19,18 @@ namespace MCPForUnity.Editor.MenuItems MCPForUnityEditorWindow.ShowWindow(); } } + + [MenuItem("Window/MCP For Unity/Setup Window", priority = 2)] + public static void ShowSetupWindow() + { + SetupWindowService.ShowSetupWindow(); + } + + + [MenuItem("Window/MCP For Unity/EditorPrefs", priority = 3)] + public static void ShowEditorPrefsWindow() + { + EditorPrefsWindow.ShowWindow(); + } } } diff --git a/MCPForUnity/Editor/Services/EditorPrefsWindowService.cs b/MCPForUnity/Editor/Services/EditorPrefsWindowService.cs new file mode 100644 index 0000000..2511b03 --- /dev/null +++ b/MCPForUnity/Editor/Services/EditorPrefsWindowService.cs @@ -0,0 +1,54 @@ +using System; +using MCPForUnity.Editor.Windows; +using UnityEditor; + +namespace MCPForUnity.Editor.Services +{ + /// + /// Service for managing the EditorPrefs window + /// Follows the Class-level Singleton pattern + /// + public class EditorPrefsWindowService + { + private static EditorPrefsWindowService _instance; + + /// + /// Get the singleton instance + /// + public static EditorPrefsWindowService Instance + { + get + { + if (_instance == null) + { + throw new Exception("EditorPrefsWindowService not initialized"); + } + return _instance; + } + } + + /// + /// Initialize the service + /// + public static void Initialize() + { + if (_instance == null) + { + _instance = new EditorPrefsWindowService(); + } + } + + private EditorPrefsWindowService() + { + // Private constructor for singleton + } + + /// + /// Show the EditorPrefs window + /// + public void ShowWindow() + { + EditorPrefsWindow.ShowWindow(); + } + } +} diff --git a/MCPForUnity/Editor/Services/EditorPrefsWindowService.cs.meta b/MCPForUnity/Editor/Services/EditorPrefsWindowService.cs.meta new file mode 100644 index 0000000..2dc46b1 --- /dev/null +++ b/MCPForUnity/Editor/Services/EditorPrefsWindowService.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 2a1c6e4725a484c0abf10f6eaa1d8d5d +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/MCPForUnity/Editor/Windows/EditorPrefs.meta b/MCPForUnity/Editor/Windows/EditorPrefs.meta new file mode 100644 index 0000000..ac0789d --- /dev/null +++ b/MCPForUnity/Editor/Windows/EditorPrefs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: acc0b0b106a5e4826ab3fdbda7916eaf +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/MCPForUnity/Editor/Windows/EditorPrefs/EditorPrefItem.uxml b/MCPForUnity/Editor/Windows/EditorPrefs/EditorPrefItem.uxml new file mode 100644 index 0000000..4d949a1 --- /dev/null +++ b/MCPForUnity/Editor/Windows/EditorPrefs/EditorPrefItem.uxml @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/MCPForUnity/Editor/Windows/EditorPrefs/EditorPrefItem.uxml.meta b/MCPForUnity/Editor/Windows/EditorPrefs/EditorPrefItem.uxml.meta new file mode 100644 index 0000000..b6dfa79 --- /dev/null +++ b/MCPForUnity/Editor/Windows/EditorPrefs/EditorPrefItem.uxml.meta @@ -0,0 +1,10 @@ +fileFormatVersion: 2 +guid: 06c99d6b0c7fa4fd3842e4d3b2a7407f +ScriptedImporter: + internalIDToNameTable: [] + externalObjects: {} + serializedVersion: 2 + userData: + assetBundleName: + assetBundleVariant: + script: {fileID: 13804, guid: 0000000000000000e000000000000000, type: 0} diff --git a/MCPForUnity/Editor/Windows/EditorPrefs/EditorPrefsWindow.cs b/MCPForUnity/Editor/Windows/EditorPrefs/EditorPrefsWindow.cs new file mode 100644 index 0000000..ef49cf8 --- /dev/null +++ b/MCPForUnity/Editor/Windows/EditorPrefs/EditorPrefsWindow.cs @@ -0,0 +1,347 @@ +using System; +using System.Collections.Generic; +using System.Globalization; +using System.Linq; +using System.Reflection; +using MCPForUnity.Editor.Constants; +using MCPForUnity.Editor.Helpers; +using UnityEditor; +using UnityEngine; +using UnityEngine.UIElements; + +namespace MCPForUnity.Editor.Windows +{ + /// + /// Editor window for managing Unity EditorPrefs, specifically for MCP For Unity development + /// + public class EditorPrefsWindow : EditorWindow + { + // UI Elements + private ScrollView scrollView; + private VisualElement prefsContainer; + + // Data + private List currentPrefs = new List(); + private HashSet knownMcpKeys = new HashSet(); + + // Type mapping for known EditorPrefs + private readonly Dictionary knownPrefTypes = new Dictionary + { + // Boolean prefs + { EditorPrefKeys.DebugLogs, EditorPrefType.Bool }, + { EditorPrefKeys.UseHttpTransport, EditorPrefType.Bool }, + { EditorPrefKeys.ResumeHttpAfterReload, EditorPrefType.Bool }, + { EditorPrefKeys.ResumeStdioAfterReload, EditorPrefType.Bool }, + { EditorPrefKeys.UseEmbeddedServer, EditorPrefType.Bool }, + { EditorPrefKeys.LockCursorConfig, EditorPrefType.Bool }, + { EditorPrefKeys.AutoRegisterEnabled, EditorPrefType.Bool }, + { EditorPrefKeys.SetupCompleted, EditorPrefType.Bool }, + { EditorPrefKeys.SetupDismissed, EditorPrefType.Bool }, + { EditorPrefKeys.CustomToolRegistrationEnabled, EditorPrefType.Bool }, + { EditorPrefKeys.TelemetryDisabled, EditorPrefType.Bool }, + + // Integer prefs + { EditorPrefKeys.UnitySocketPort, EditorPrefType.Int }, + { EditorPrefKeys.ValidationLevel, EditorPrefType.Int }, + { EditorPrefKeys.LastUpdateCheck, EditorPrefType.Int }, + { EditorPrefKeys.LastStdIoUpgradeVersion, EditorPrefType.Int }, + + // String prefs + { EditorPrefKeys.EditorWindowActivePanel, EditorPrefType.String }, + { EditorPrefKeys.ClaudeCliPathOverride, EditorPrefType.String }, + { EditorPrefKeys.UvxPathOverride, EditorPrefType.String }, + { EditorPrefKeys.HttpBaseUrl, EditorPrefType.String }, + { EditorPrefKeys.SessionId, EditorPrefType.String }, + { EditorPrefKeys.WebSocketUrlOverride, EditorPrefType.String }, + { EditorPrefKeys.GitUrlOverride, EditorPrefType.String }, + { EditorPrefKeys.PackageDeploySourcePath, EditorPrefType.String }, + { EditorPrefKeys.PackageDeployLastBackupPath, EditorPrefType.String }, + { EditorPrefKeys.PackageDeployLastTargetPath, EditorPrefType.String }, + { EditorPrefKeys.PackageDeployLastSourcePath, EditorPrefType.String }, + { EditorPrefKeys.ServerSrc, EditorPrefType.String }, + { EditorPrefKeys.LatestKnownVersion, EditorPrefType.String }, + }; + + // Templates + private VisualTreeAsset itemTemplate; + + /// + /// Show the EditorPrefs window + /// + public static void ShowWindow() + { + var window = GetWindow("EditorPrefs"); + window.minSize = new Vector2(600, 400); + window.Show(); + } + + public void CreateGUI() + { + string basePath = AssetPathUtility.GetMcpPackageRootPath(); + + // Load UXML + var visualTree = AssetDatabase.LoadAssetAtPath( + $"{basePath}/Editor/Windows/EditorPrefs/EditorPrefsWindow.uxml" + ); + + if (visualTree == null) + { + Debug.LogError("Failed to load EditorPrefsWindow.uxml template"); + return; + } + + // Load item template + itemTemplate = AssetDatabase.LoadAssetAtPath( + $"{basePath}/Editor/Windows/EditorPrefs/EditorPrefItem.uxml" + ); + + if (itemTemplate == null) + { + Debug.LogError("Failed to load EditorPrefItem.uxml template"); + return; + } + + visualTree.CloneTree(rootVisualElement); + + // Get references + scrollView = rootVisualElement.Q("scroll-view"); + prefsContainer = rootVisualElement.Q("prefs-container"); + + // Load known MCP keys + LoadKnownMcpKeys(); + + // Load initial data + RefreshPrefs(); + } + + private void LoadKnownMcpKeys() + { + knownMcpKeys.Clear(); + var fields = typeof(EditorPrefKeys).GetFields(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static); + + foreach (var field in fields) + { + if (field.IsLiteral && !field.IsInitOnly) + { + knownMcpKeys.Add(field.GetValue(null).ToString()); + } + } + } + + private void RefreshPrefs() + { + currentPrefs.Clear(); + prefsContainer.Clear(); + + // Get all EditorPrefs keys + var allKeys = new List(); + + // Always show all MCP keys + allKeys.AddRange(knownMcpKeys); + + // Try to find additional MCP keys + var mcpKeys = GetAllMcpKeys(); + foreach (var key in mcpKeys) + { + if (!allKeys.Contains(key)) + { + allKeys.Add(key); + } + } + + // Sort keys + allKeys.Sort(); + + // Create items for existing prefs + foreach (var key in allKeys) + { + // Skip Customer UUID but show everything else that's defined + if (key != EditorPrefKeys.CustomerUuid) + { + var item = CreateEditorPrefItem(key); + if (item != null) + { + currentPrefs.Add(item); + prefsContainer.Add(CreateItemUI(item)); + } + } + } + } + + private List GetAllMcpKeys() + { + // This is a simplified approach - in reality, getting all EditorPrefs is platform-specific + // For now, we'll return known MCP keys that might exist + var keys = new List(); + + // Add some common MCP keys that might not be in EditorPrefKeys + keys.Add("MCPForUnity.TestKey"); + + // Filter to only those that actually exist + return keys.Where(EditorPrefs.HasKey).ToList(); + } + + private EditorPrefItem CreateEditorPrefItem(string key) + { + var item = new EditorPrefItem { Key = key, IsKnown = knownMcpKeys.Contains(key) }; + + // Check if we know the type of this pref + if (knownPrefTypes.TryGetValue(key, out var knownType)) + { + // Use the known type + switch (knownType) + { + case EditorPrefType.Bool: + item.Type = EditorPrefType.Bool; + item.Value = EditorPrefs.GetBool(key, false).ToString(); + break; + case EditorPrefType.Int: + item.Type = EditorPrefType.Int; + item.Value = EditorPrefs.GetInt(key, 0).ToString(); + break; + case EditorPrefType.Float: + item.Type = EditorPrefType.Float; + item.Value = EditorPrefs.GetFloat(key, 0f).ToString(); + break; + case EditorPrefType.String: + item.Type = EditorPrefType.String; + item.Value = EditorPrefs.GetString(key, ""); + break; + } + } + else + { + // Only try to detect type for unknown keys that actually exist + if (!EditorPrefs.HasKey(key)) + { + // Key doesn't exist and we don't know its type, skip it + return null; + } + + // Unknown pref - try to detect type + var stringValue = EditorPrefs.GetString(key, ""); + + if (int.TryParse(stringValue, out var intValue)) + { + item.Type = EditorPrefType.Int; + item.Value = intValue.ToString(); + } + else if (float.TryParse(stringValue, out var floatValue)) + { + item.Type = EditorPrefType.Float; + item.Value = floatValue.ToString(); + } + else if (bool.TryParse(stringValue, out var boolValue)) + { + item.Type = EditorPrefType.Bool; + item.Value = boolValue.ToString(); + } + else + { + item.Type = EditorPrefType.String; + item.Value = stringValue; + } + } + + return item; + } + + private VisualElement CreateItemUI(EditorPrefItem item) + { + if (itemTemplate == null) + { + Debug.LogError("Item template not loaded"); + return new VisualElement(); + } + + var itemElement = itemTemplate.CloneTree(); + + // Set values + itemElement.Q