Add EditorPrefs management window for MCP configuration debugging (#491)
* Add EditorPrefs management window for MCP configuration debugging Meant to help with dev and testing, not so much the average user * Update MCPForUnity/Editor/Windows/EditorPrefs/EditorPrefsWindow.cs Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com> * Revert "Update MCPForUnity/Editor/Windows/EditorPrefs/EditorPrefsWindow.cs" This reverts commit 09bb4e1d2582678bc87d0ace45f9d8c3c88c3203. * Reapply "Update MCPForUnity/Editor/Windows/EditorPrefs/EditorPrefsWindow.cs" This reverts commit 6ccbc5e478f0bd2b61c992ae60db0ca367d651ae. * Fix EditorPrefs type detection using sentinel values and null handling * Simplify EditorPrefs type detection using known type mapping and basic parsing Replace complex sentinel-based type detection with a dictionary of known pref types and simple TryParse fallback for unknown keys. Remove null handling and HasKey checks for known keys since they're defined in EditorPrefKeys. --------- Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>main
parent
eea02d1a0d
commit
c770a8c713
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,54 @@
|
|||
using System;
|
||||
using MCPForUnity.Editor.Windows;
|
||||
using UnityEditor;
|
||||
|
||||
namespace MCPForUnity.Editor.Services
|
||||
{
|
||||
/// <summary>
|
||||
/// Service for managing the EditorPrefs window
|
||||
/// Follows the Class-level Singleton pattern
|
||||
/// </summary>
|
||||
public class EditorPrefsWindowService
|
||||
{
|
||||
private static EditorPrefsWindowService _instance;
|
||||
|
||||
/// <summary>
|
||||
/// Get the singleton instance
|
||||
/// </summary>
|
||||
public static EditorPrefsWindowService Instance
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_instance == null)
|
||||
{
|
||||
throw new Exception("EditorPrefsWindowService not initialized");
|
||||
}
|
||||
return _instance;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initialize the service
|
||||
/// </summary>
|
||||
public static void Initialize()
|
||||
{
|
||||
if (_instance == null)
|
||||
{
|
||||
_instance = new EditorPrefsWindowService();
|
||||
}
|
||||
}
|
||||
|
||||
private EditorPrefsWindowService()
|
||||
{
|
||||
// Private constructor for singleton
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Show the EditorPrefs window
|
||||
/// </summary>
|
||||
public void ShowWindow()
|
||||
{
|
||||
EditorPrefsWindow.ShowWindow();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 2a1c6e4725a484c0abf10f6eaa1d8d5d
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
fileFormatVersion: 2
|
||||
guid: acc0b0b106a5e4826ab3fdbda7916eaf
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
|
|
@ -0,0 +1,21 @@
|
|||
<ui:UXML xmlns:ui="UnityEngine.UIElements" xmlns:uie="UnityEditor.UIElements" editor-extension-mode="True">
|
||||
<ui:VisualElement class="pref-item">
|
||||
<ui:VisualElement class="pref-row">
|
||||
<!-- Key and Known indicator -->
|
||||
<ui:VisualElement class="key-section">
|
||||
<ui:Label name="key-label" class="key-label" />
|
||||
</ui:VisualElement>
|
||||
|
||||
<!-- Value field -->
|
||||
<ui:TextField name="value-field" class="value-field" />
|
||||
|
||||
<!-- Type dropdown -->
|
||||
<ui:DropdownField name="type-dropdown" class="type-dropdown" choices="String,Int,Float,Bool" index="0" />
|
||||
|
||||
<!-- Action buttons -->
|
||||
<ui:VisualElement class="action-buttons">
|
||||
<ui:Button name="save-button" text="✓" class="save-button" tooltip="Save changes" />
|
||||
</ui:VisualElement>
|
||||
</ui:VisualElement>
|
||||
</ui:VisualElement>
|
||||
</ui:UXML>
|
||||
|
|
@ -0,0 +1,10 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 06c99d6b0c7fa4fd3842e4d3b2a7407f
|
||||
ScriptedImporter:
|
||||
internalIDToNameTable: []
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
script: {fileID: 13804, guid: 0000000000000000e000000000000000, type: 0}
|
||||
|
|
@ -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
|
||||
{
|
||||
/// <summary>
|
||||
/// Editor window for managing Unity EditorPrefs, specifically for MCP For Unity development
|
||||
/// </summary>
|
||||
public class EditorPrefsWindow : EditorWindow
|
||||
{
|
||||
// UI Elements
|
||||
private ScrollView scrollView;
|
||||
private VisualElement prefsContainer;
|
||||
|
||||
// Data
|
||||
private List<EditorPrefItem> currentPrefs = new List<EditorPrefItem>();
|
||||
private HashSet<string> knownMcpKeys = new HashSet<string>();
|
||||
|
||||
// Type mapping for known EditorPrefs
|
||||
private readonly Dictionary<string, EditorPrefType> knownPrefTypes = new Dictionary<string, EditorPrefType>
|
||||
{
|
||||
// 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;
|
||||
|
||||
/// <summary>
|
||||
/// Show the EditorPrefs window
|
||||
/// </summary>
|
||||
public static void ShowWindow()
|
||||
{
|
||||
var window = GetWindow<EditorPrefsWindow>("EditorPrefs");
|
||||
window.minSize = new Vector2(600, 400);
|
||||
window.Show();
|
||||
}
|
||||
|
||||
public void CreateGUI()
|
||||
{
|
||||
string basePath = AssetPathUtility.GetMcpPackageRootPath();
|
||||
|
||||
// Load UXML
|
||||
var visualTree = AssetDatabase.LoadAssetAtPath<VisualTreeAsset>(
|
||||
$"{basePath}/Editor/Windows/EditorPrefs/EditorPrefsWindow.uxml"
|
||||
);
|
||||
|
||||
if (visualTree == null)
|
||||
{
|
||||
Debug.LogError("Failed to load EditorPrefsWindow.uxml template");
|
||||
return;
|
||||
}
|
||||
|
||||
// Load item template
|
||||
itemTemplate = AssetDatabase.LoadAssetAtPath<VisualTreeAsset>(
|
||||
$"{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<ScrollView>("scroll-view");
|
||||
prefsContainer = rootVisualElement.Q<VisualElement>("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<string>();
|
||||
|
||||
// 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<string> 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<string>();
|
||||
|
||||
// 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<Label>("key-label").text = item.Key;
|
||||
var valueField = itemElement.Q<TextField>("value-field");
|
||||
valueField.value = item.Value;
|
||||
|
||||
var typeDropdown = itemElement.Q<DropdownField>("type-dropdown");
|
||||
typeDropdown.index = (int)item.Type;
|
||||
|
||||
// Buttons
|
||||
var saveButton = itemElement.Q<Button>("save-button");
|
||||
|
||||
// Callbacks
|
||||
saveButton.clicked += () => SavePref(item, valueField.value, (EditorPrefType)typeDropdown.index);
|
||||
|
||||
return itemElement;
|
||||
}
|
||||
|
||||
private void SavePref(EditorPrefItem item, string newValue, EditorPrefType newType)
|
||||
{
|
||||
SaveValue(item.Key, newValue, newType);
|
||||
RefreshPrefs();
|
||||
}
|
||||
|
||||
private void SaveValue(string key, string value, EditorPrefType type)
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case EditorPrefType.String:
|
||||
EditorPrefs.SetString(key, value);
|
||||
break;
|
||||
case EditorPrefType.Int:
|
||||
if (int.TryParse(value, out var intValue))
|
||||
{
|
||||
EditorPrefs.SetInt(key, intValue);
|
||||
}
|
||||
else
|
||||
{
|
||||
EditorUtility.DisplayDialog("Error", $"Cannot convert '{value}' to int", "OK");
|
||||
return;
|
||||
}
|
||||
break;
|
||||
case EditorPrefType.Float:
|
||||
if (float.TryParse(value, out var floatValue))
|
||||
{
|
||||
EditorPrefs.SetFloat(key, floatValue);
|
||||
}
|
||||
else
|
||||
{
|
||||
EditorUtility.DisplayDialog("Error", $"Cannot convert '{value}' to float", "OK");
|
||||
return;
|
||||
}
|
||||
break;
|
||||
case EditorPrefType.Bool:
|
||||
if (bool.TryParse(value, out var boolValue))
|
||||
{
|
||||
EditorPrefs.SetBool(key, boolValue);
|
||||
}
|
||||
else
|
||||
{
|
||||
EditorUtility.DisplayDialog("Error", $"Cannot convert '{value}' to bool (use 'True' or 'False')", "OK");
|
||||
return;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Represents an EditorPrefs item
|
||||
/// </summary>
|
||||
public class EditorPrefItem
|
||||
{
|
||||
public string Key { get; set; }
|
||||
public string Value { get; set; }
|
||||
public EditorPrefType Type { get; set; }
|
||||
public bool IsKnown { get; set; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// EditorPrefs value types
|
||||
/// </summary>
|
||||
public enum EditorPrefType
|
||||
{
|
||||
String,
|
||||
Int,
|
||||
Float,
|
||||
Bool
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: ceb71bbae267c4765aff72e4cc845ecb
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
|
|
@ -0,0 +1,228 @@
|
|||
.header {
|
||||
padding-bottom: 16px;
|
||||
border-bottom-width: 1px;
|
||||
border-bottom-color: #333333;
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
|
||||
.title {
|
||||
-unity-font-style: bold;
|
||||
font-size: 18px;
|
||||
margin-bottom: 4px;
|
||||
}
|
||||
|
||||
.description {
|
||||
color: #999999;
|
||||
font-size: 12px;
|
||||
white-space: normal;
|
||||
margin-left: 4px;
|
||||
}
|
||||
|
||||
.controls {
|
||||
flex-direction: row;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
margin-bottom: 16px;
|
||||
padding: 8px;
|
||||
background-color: #393939;
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
.add-section {
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
|
||||
.primary-button {
|
||||
-unity-text-align: middle-left;
|
||||
background-color: #4a90e2;
|
||||
color: white;
|
||||
border-radius: 4px;
|
||||
padding: 8px 16px;
|
||||
}
|
||||
|
||||
.primary-button:hover {
|
||||
background-color: #357abd;
|
||||
}
|
||||
|
||||
.secondary-button {
|
||||
background-color: #393939;
|
||||
border-left-width: 1px;
|
||||
border-right-width: 1px;
|
||||
border-top-width: 1px;
|
||||
border-bottom-width: 1px;
|
||||
border-left-color: #555555;
|
||||
border-right-color: #555555;
|
||||
border-top-color: #555555;
|
||||
border-bottom-color: #555555;
|
||||
border-radius: 4px;
|
||||
padding: 6px 12px;
|
||||
width: 80px;
|
||||
}
|
||||
|
||||
.secondary-button:hover {
|
||||
background-color: #484848;
|
||||
}
|
||||
|
||||
/* Add New Row */
|
||||
.add-new-row {
|
||||
background-color: #393939;
|
||||
border-left-width: 1px;
|
||||
border-right-width: 1px;
|
||||
border-top-width: 1px;
|
||||
border-bottom-width: 1px;
|
||||
border-left-color: #555555;
|
||||
border-right-color: #555555;
|
||||
border-top-color: #555555;
|
||||
border-bottom-color: #555555;
|
||||
border-radius: 4px;
|
||||
padding: 16px;
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
|
||||
.add-row-content {
|
||||
flex-direction: row;
|
||||
align-items: flex-end;
|
||||
}
|
||||
|
||||
.add-row-content .key-field {
|
||||
flex: 1;
|
||||
min-width: 200px;
|
||||
margin-right: 12px;
|
||||
}
|
||||
|
||||
.add-row-content .value-field {
|
||||
flex: 1;
|
||||
min-width: 150px;
|
||||
margin-right: 12px;
|
||||
}
|
||||
|
||||
.add-row-content .type-dropdown {
|
||||
width: 100px;
|
||||
margin-right: 12px;
|
||||
}
|
||||
|
||||
.add-buttons {
|
||||
flex-direction: row;
|
||||
justify-content: flex-end;
|
||||
margin-top: 8px;
|
||||
}
|
||||
|
||||
.add-buttons .cancel-button {
|
||||
margin-left: 8px;
|
||||
}
|
||||
|
||||
.save-button {
|
||||
background-color: #4caf50;
|
||||
color: white;
|
||||
min-width: 60px;
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
.save-button:hover {
|
||||
background-color: #45a049;
|
||||
}
|
||||
|
||||
.cancel-button {
|
||||
background-color: #393939;
|
||||
border-left-width: 1px;
|
||||
border-right-width: 1px;
|
||||
border-top-width: 1px;
|
||||
border-bottom-width: 1px;
|
||||
border-left-color: #555555;
|
||||
border-right-color: #555555;
|
||||
border-top-color: #555555;
|
||||
border-bottom-color: #555555;
|
||||
min-width: 60px;
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
.cancel-button:hover {
|
||||
background-color: #484848;
|
||||
}
|
||||
|
||||
/* Pref Items */
|
||||
.prefs-container {
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.pref-item {
|
||||
margin-bottom: 8px;
|
||||
background-color: #393939;
|
||||
border-left-width: 1px;
|
||||
border-right-width: 1px;
|
||||
border-top-width: 1px;
|
||||
border-bottom-width: 1px;
|
||||
border-left-color: #555555;
|
||||
border-right-color: #555555;
|
||||
border-top-color: #555555;
|
||||
border-bottom-color: #555555;
|
||||
border-radius: 4px;
|
||||
padding: 8px;
|
||||
}
|
||||
|
||||
.pref-row {
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
flex-wrap: nowrap; /* Prevent wrapping */
|
||||
}
|
||||
|
||||
.pref-row .key-section {
|
||||
flex-shrink: 0;
|
||||
width: 200px; /* Fixed width for key section */
|
||||
margin-right: 12px;
|
||||
}
|
||||
|
||||
.pref-row .value-field {
|
||||
flex: 1;
|
||||
min-width: 150px;
|
||||
margin-right: 12px;
|
||||
}
|
||||
|
||||
.pref-row .type-dropdown {
|
||||
width: 100px;
|
||||
margin-right: 12px;
|
||||
}
|
||||
|
||||
.pref-row .action-buttons {
|
||||
flex-direction: row;
|
||||
width: 32px;
|
||||
justify-content: flex-start;
|
||||
}
|
||||
|
||||
.key-section {
|
||||
flex-direction: column;
|
||||
min-width: 200px;
|
||||
}
|
||||
|
||||
.key-label {
|
||||
-unity-font-style: bold;
|
||||
color: white;
|
||||
white-space: normal;
|
||||
}
|
||||
|
||||
.value-field {
|
||||
flex: 1;
|
||||
min-width: 150px;
|
||||
}
|
||||
|
||||
.type-dropdown {
|
||||
width: 100px;
|
||||
}
|
||||
|
||||
.action-buttons {
|
||||
flex-direction: row;
|
||||
}
|
||||
|
||||
.action-buttons .save-button {
|
||||
background-color: #4caf50;
|
||||
color: white;
|
||||
min-width: 32px;
|
||||
height: 28px;
|
||||
padding: 0;
|
||||
font-size: 16px;
|
||||
-unity-font-style: bold;
|
||||
}
|
||||
|
||||
.action-buttons .save-button:hover {
|
||||
background-color: #45a049;
|
||||
}
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 3980375ed546e47abafcafe11e953e87
|
||||
ScriptedImporter:
|
||||
internalIDToNameTable: []
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
script: {fileID: 12385, guid: 0000000000000000e000000000000000, type: 0}
|
||||
disableValidation: 0
|
||||
|
|
@ -0,0 +1,30 @@
|
|||
<ui:UXML xmlns:ui="UnityEngine.UIElements" xmlns:uie="UnityEditor.UIElements" editor-extension-mode="True">
|
||||
<Style src="../Components/Common.uss" />
|
||||
<Style src="EditorPrefsWindow.uss" />
|
||||
|
||||
<ui:ScrollView name="scroll-view" mode="Vertical">
|
||||
<!-- Header -->
|
||||
<ui:VisualElement class="header">
|
||||
<ui:Label text="EditorPrefs Manager" class="title" />
|
||||
<ui:Label text="Manage MCP for Unity EditorPrefs. Useful for development and testing." class="description" />
|
||||
</ui:VisualElement>
|
||||
|
||||
<!-- Add New Row (initially hidden) -->
|
||||
<ui:VisualElement name="add-new-row" class="add-new-row" style="display: none;">
|
||||
<ui:VisualElement class="add-row-content">
|
||||
<ui:TextField name="new-key-field" label="Key" class="key-field" />
|
||||
<ui:TextField name="new-value-field" label="Value" class="value-field" />
|
||||
<ui:DropdownField name="new-type-dropdown" label="Type" class="type-dropdown" choices="String,Int,Float,Bool" index="0" />
|
||||
<ui:VisualElement class="add-buttons">
|
||||
<ui:Button name="create-button" text="Create" class="save-button" />
|
||||
<ui:Button name="cancel-button" text="Cancel" class="cancel-button" />
|
||||
</ui:VisualElement>
|
||||
</ui:VisualElement>
|
||||
</ui:VisualElement>
|
||||
|
||||
<!-- Prefs List -->
|
||||
<ui:VisualElement name="prefs-container" class="prefs-container">
|
||||
<!-- Items will be added here programmatically -->
|
||||
</ui:VisualElement>
|
||||
</ui:ScrollView>
|
||||
</ui:UXML>
|
||||
|
|
@ -0,0 +1,10 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 0cfa716884c1445d8a5e9581bbe2e9ce
|
||||
ScriptedImporter:
|
||||
internalIDToNameTable: []
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
script: {fileID: 13804, guid: 0000000000000000e000000000000000, type: 0}
|
||||
Loading…
Reference in New Issue