From 2ff87e9e159d0ecb58f8ac8fa423ede1a60b7a8b Mon Sep 17 00:00:00 2001 From: uc-hoba Date: Wed, 3 Jun 2026 15:25:38 +0800 Subject: [PATCH] refactor(editor): add foldout UI for entries in debug editors --- Assets/Main.unity | 2 +- .../Editor/DebugMonitorHUDEditor.cs | 62 ++++++++++++++++--- .../Editor/DebugSettingsGUIEditor.cs | 57 ++++++++++++++--- 3 files changed, 101 insertions(+), 20 deletions(-) diff --git a/Assets/Main.unity b/Assets/Main.unity index 314b3e8..9d1aec8 100644 --- a/Assets/Main.unity +++ b/Assets/Main.unity @@ -1112,7 +1112,7 @@ MonoBehaviour: m_Name: m_EditorClassIdentifier: UltraCombos.GiantMuseum.Runtime::UltraCombos.DebugMonitorHUD displayText: {fileID: 587767519} - refreshRate: 30 + refreshRate: 20 entries: - target: {fileID: 476511607} groupLabel: Display diff --git a/Packages/com.ultracombos.giant-museum/Editor/DebugMonitorHUDEditor.cs b/Packages/com.ultracombos.giant-museum/Editor/DebugMonitorHUDEditor.cs index 6911c53..66a40f3 100644 --- a/Packages/com.ultracombos.giant-museum/Editor/DebugMonitorHUDEditor.cs +++ b/Packages/com.ultracombos.giant-museum/Editor/DebugMonitorHUDEditor.cs @@ -25,6 +25,20 @@ namespace UltraCombos private SerializedProperty displayTextProp; private SerializedProperty refreshRateProp; + // Per-entry foldout state (editor-only, not serialized). + private readonly List entryFoldouts = new(); + + // Lazily-built style: foldout triangle + bold text. + private static GUIStyle boldFoldout; + private static GUIStyle GetBoldFoldout() + { + if (boldFoldout == null) + { + boldFoldout = new GUIStyle(EditorStyles.foldout) { fontStyle = FontStyle.Bold }; + } + return boldFoldout; + } + private void OnEnable() { displayTextProp = serializedObject.FindProperty("displayText"); @@ -51,13 +65,22 @@ namespace UltraCombos EditorGUILayout.Space(10); EditorGUILayout.LabelField("Entries", EditorStyles.boldLabel); + // Sync foldout list length with entries. + while (entryFoldouts.Count < hud.entries.Count) + { + entryFoldouts.Add(true); + } + for (var i = 0; i < hud.entries.Count; i++) { - var removed = DrawEntry(hud, hud.entries[i], i); + var (removed, expanded) = DrawEntry(hud, hud.entries[i], i, entryFoldouts[i]); + entryFoldouts[i] = expanded; + if (removed) { Undo.RecordObject(hud, "Remove Entry"); hud.entries.RemoveAt(i); + entryFoldouts.RemoveAt(i); EditorUtility.SetDirty(hud); i--; } @@ -70,32 +93,51 @@ namespace UltraCombos { Undo.RecordObject(hud, "Add Entry"); hud.entries.Add(new DebugMonitorHUD.Entry()); + entryFoldouts.Add(true); EditorUtility.SetDirty(hud); } } - // ── Draw one Entry — returns true when the user clicked Remove ───────────── + // ── Draw one Entry ──────────────────────────────────────────────────────── + // Returns (removed, expanded). - private static bool DrawEntry(DebugMonitorHUD hud, DebugMonitorHUD.Entry entry, int index) + private static (bool removed, bool expanded) DrawEntry( + DebugMonitorHUD hud, DebugMonitorHUD.Entry entry, int index, bool expanded) { var removed = false; using (new EditorGUILayout.VerticalScope(EditorStyles.helpBox)) { - // Header row - using (new EditorGUILayout.HorizontalScope()) + // ── Header row ──────────────────────────────────────────────────── { - var title = string.IsNullOrEmpty(entry.groupLabel) + var fieldCount = entry.fields.Count; + var groupPart = string.IsNullOrEmpty(entry.groupLabel) ? $"Entry {index}" : $"Entry {index} — {entry.groupLabel}"; - EditorGUILayout.LabelField(title, EditorStyles.boldLabel); - GUILayout.FlexibleSpace(); - if (GUILayout.Button("✕", GUILayout.Width(22), GUILayout.Height(18))) + var summary = fieldCount > 0 ? $"{groupPart} ({fieldCount})" : groupPart; + + // Reserve one full-width line, then split off a fixed-width button on the right. + var lineRect = EditorGUILayout.GetControlRect(false, EditorGUIUtility.singleLineHeight); + var buttonRect = new Rect(lineRect.xMax - 24, lineRect.y, 22, 18); + var foldRect = new Rect(lineRect.x, lineRect.y, lineRect.width - 26, lineRect.height); + + // Use a style derived from EditorStyles.foldout so the triangle is preserved. + expanded = EditorGUI.Foldout(foldRect, expanded, summary, + toggleOnLabelClick: true, GetBoldFoldout()); + + if (GUI.Button(buttonRect, "✕")) { removed = true; } } + if (!expanded) + { + return (removed, expanded); + } + + // ── Body ────────────────────────────────────────────────────────── + // Group label EditorGUI.BeginChangeCheck(); var newLabel = EditorGUILayout.TextField("Group Label", entry.groupLabel); @@ -140,7 +182,7 @@ namespace UltraCombos } } - return removed; + return (removed, expanded); } // ── Member checkboxes ───────────────────────────────────────────────────── diff --git a/Packages/com.ultracombos.giant-museum/Editor/DebugSettingsGUIEditor.cs b/Packages/com.ultracombos.giant-museum/Editor/DebugSettingsGUIEditor.cs index c589baf..e7d00cd 100644 --- a/Packages/com.ultracombos.giant-museum/Editor/DebugSettingsGUIEditor.cs +++ b/Packages/com.ultracombos.giant-museum/Editor/DebugSettingsGUIEditor.cs @@ -25,6 +25,20 @@ namespace UltraCombos private SerializedProperty toggleKeyProp; private SerializedProperty initialRectProp; + // Per-entry foldout state (editor-only, not serialized). + private readonly List entryFoldouts = new(); + + // Lazily-built style: foldout triangle + bold text. + private static GUIStyle boldFoldout; + private static GUIStyle GetBoldFoldout() + { + if (boldFoldout == null) + { + boldFoldout = new GUIStyle(EditorStyles.foldout) { fontStyle = FontStyle.Bold }; + } + return boldFoldout; + } + private void OnEnable() { toggleKeyProp = serializedObject.FindProperty("toggleKey"); @@ -47,13 +61,22 @@ namespace UltraCombos EditorGUILayout.Space(10); EditorGUILayout.LabelField("Entries", EditorStyles.boldLabel); + // Sync foldout list length with entries. + while (entryFoldouts.Count < gui.entries.Count) + { + entryFoldouts.Add(true); + } + for (var i = 0; i < gui.entries.Count; i++) { - var removed = DrawEntry(gui, gui.entries[i], i); + var (removed, expanded) = DrawEntry(gui, gui.entries[i], i, entryFoldouts[i]); + entryFoldouts[i] = expanded; + if (removed) { Undo.RecordObject(gui, "Remove Entry"); gui.entries.RemoveAt(i); + entryFoldouts.RemoveAt(i); EditorUtility.SetDirty(gui); i--; } @@ -66,32 +89,48 @@ namespace UltraCombos { Undo.RecordObject(gui, "Add Entry"); gui.entries.Add(new DebugSettingsGUI.Entry()); + entryFoldouts.Add(true); EditorUtility.SetDirty(gui); } } - // ── Draw one Entry — returns true when the user clicked Remove ───────────── + // ── Draw one Entry — returns (removed, expanded) ────────────────────────── - private static bool DrawEntry(DebugSettingsGUI gui, DebugSettingsGUI.Entry entry, int index) + private static (bool removed, bool expanded) DrawEntry( + DebugSettingsGUI gui, DebugSettingsGUI.Entry entry, int index, bool expanded) { var removed = false; using (new EditorGUILayout.VerticalScope(EditorStyles.helpBox)) { // Header row - using (new EditorGUILayout.HorizontalScope()) { - var title = string.IsNullOrEmpty(entry.groupLabel) + var fieldCount = entry.fields.Count; + var groupPart = string.IsNullOrEmpty(entry.groupLabel) ? $"Entry {index}" : $"Entry {index} — {entry.groupLabel}"; - EditorGUILayout.LabelField(title, EditorStyles.boldLabel); - GUILayout.FlexibleSpace(); - if (GUILayout.Button("✕", GUILayout.Width(22), GUILayout.Height(18))) + var summary = fieldCount > 0 ? $"{groupPart} ({fieldCount})" : groupPart; + + // Reserve one full-width line, then split off a fixed-width button on the right. + var lineRect = EditorGUILayout.GetControlRect(false, EditorGUIUtility.singleLineHeight); + var buttonRect = new Rect(lineRect.xMax - 24, lineRect.y, 22, 18); + var foldRect = new Rect(lineRect.x, lineRect.y, lineRect.width - 26, lineRect.height); + + // Use a style derived from EditorStyles.foldout so the triangle is preserved. + expanded = EditorGUI.Foldout(foldRect, expanded, summary, + toggleOnLabelClick: true, GetBoldFoldout()); + + if (GUI.Button(buttonRect, "✕")) { removed = true; } } + if (!expanded) + { + return (removed, expanded); + } + // Group label EditorGUI.BeginChangeCheck(); var newLabel = EditorGUILayout.TextField("Group Label", entry.groupLabel); @@ -136,7 +175,7 @@ namespace UltraCombos } } - return removed; + return (removed, expanded); } // ── Member checkboxes ─────────────────────────────────────────────────────