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 }, { EditorPrefKeys.DevModeForceServerRefresh, 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.HttpTransportScope, 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) { McpLog.Error("Failed to load EditorPrefsWindow.uxml template"); return; } // Load item template itemTemplate = AssetDatabase.LoadAssetAtPath( $"{basePath}/Editor/Windows/EditorPrefs/EditorPrefItem.uxml" ); if (itemTemplate == null) { McpLog.Error("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) { McpLog.Error("Item template not loaded"); return new VisualElement(); } var itemElement = itemTemplate.CloneTree(); // Set values itemElement.Q