using System.Collections.Generic; using UnityEditor; using UnityEditorInternal; using UnityEngine; namespace Amanotes.Core { [CustomEditor(typeof(AmaDevSettings))] internal class AmaDevSettingsEditor : Editor { private AmaDevSettings settings; private int selectedTab; private ReorderableList presetList; private SerializedProperty presetEntriesProp; private static readonly string[] tabNames = { "Symbols", "Logger", "Presets" }; private void OnEnable() { settings = (AmaDevSettings)target; settings.ReadSymbols(); presetEntriesProp = serializedObject.FindProperty("presetGenerator.entries"); presetList = new ReorderableList(serializedObject, presetEntriesProp, true, true, true, true) { drawHeaderCallback = rect => EditorGUI.LabelField(rect, "Preset Folder Entries"), elementHeightCallback = GetPresetElementHeight, drawElementCallback = DrawPresetElement, }; } public override void OnInspectorGUI() { if (Application.isPlaying || EditorApplication.isPlayingOrWillChangePlaymode) { EditorGUILayout.HelpBox("Disabled in play mode.", MessageType.Info); Repaint(); return; } if (EditorApplication.isCompiling) { EditorGUILayout.HelpBox("Compiling...", MessageType.Info); Repaint(); return; } serializedObject.Update(); selectedTab = GUILayout.Toolbar(selectedTab, tabNames, GUILayout.Height(32f)); EditorGUILayout.Space(); switch (selectedTab) { case 0: DrawSymbolsTab(); break; case 1: DrawLoggerTab(); break; case 2: DrawPresetsTab(); break; } serializedObject.ApplyModifiedProperties(); } // ── Symbols Tab ────────────────────────────────────────────── private void DrawSymbolsTab() { var symbolsProp = serializedObject.FindProperty("symbolDefine.symbols"); EditorGUILayout.PropertyField(symbolsProp, new GUIContent("Define Symbols"), true); if (settings.logV2.enabled && settings.logV2.tags.Count > 0) { GUILayout.Space(4); GUILayout.BeginHorizontal(); if (GUILayout.Button("Select All Tags")) SetAllTags(true); if (GUILayout.Button("Deselect All Tags")) SetAllTags(false); GUILayout.EndHorizontal(); var tagsProp = serializedObject.FindProperty("logV2.tags"); EditorGUILayout.PropertyField(tagsProp, new GUIContent("Logger Tags"), true); } GUILayout.Space(16); if (GUILayout.Button("Apply", GUILayout.Height(30f))) { serializedObject.ApplyModifiedProperties(); settings.Apply(); Repaint(); } } private void SetAllTags(bool enabled) { for (int i = 0; i < settings.logV2.tags.Count; i++) settings.logV2.tags[i].enabled = enabled; settings.MarkDirty(); } // ── Logger Tab ─────────────────────────────────────────────── private static bool showTemplate; private void DrawLoggerTab() { var logProp = serializedObject.FindProperty("logV2"); var child = logProp.Copy(); var end = logProp.GetEndProperty(); child.NextVisible(true); while (!SerializedProperty.EqualContents(child, end)) { EditorGUILayout.PropertyField(child, true); child.NextVisible(false); } showTemplate = GUILayout.Toggle(showTemplate, "Logger class template", EditorStyles.foldout); if (showTemplate) { var templateProp = logProp.FindPropertyRelative("classTemplate"); EditorGUILayout.PropertyField(templateProp, GUIContent.none, false, GUILayout.Height(16 * 20)); } GUILayout.Space(16); if (GUILayout.Button("Apply", GUILayout.Height(30f))) { serializedObject.ApplyModifiedProperties(); settings.Apply(); Repaint(); } } // ── Presets Tab ────────────────────────────────────────────── private void DrawPresetsTab() { presetList.DoLayoutList(); EditorGUILayout.Space(); bool anyValid = HasAnyValidPresetEntry(); GUI.enabled = anyValid; if (GUILayout.Button("Generate All", GUILayout.Height(30))) { serializedObject.ApplyModifiedProperties(); settings.presetGenerator.GenerateAll(settings); } GUI.enabled = true; if (!anyValid) EditorGUILayout.HelpBox("Add at least one valid entry to generate.", MessageType.Info); } private float GetPresetElementHeight(int index) { var entryProp = presetEntriesProp.GetArrayElementAtIndex(index); var genScript = entryProp.FindPropertyRelative("generatedScript"); bool showClassName = genScript.objectReferenceValue == null; int fieldCount = showClassName ? 5 : 4; float lineH = EditorGUIUtility.singleLineHeight + EditorGUIUtility.standardVerticalSpacing; return fieldCount * lineH + lineH + 30f + 12f; } private void DrawPresetElement(Rect rect, int index, bool isActive, bool isFocused) { var entryProp = presetEntriesProp.GetArrayElementAtIndex(index); float lineH = EditorGUIUtility.singleLineHeight + EditorGUIUtility.standardVerticalSpacing; float y = rect.y + 4f; void Field(string propName, string label) { var prop = entryProp.FindPropertyRelative(propName); EditorGUI.PropertyField(new Rect(rect.x, y, rect.width, EditorGUIUtility.singleLineHeight), prop, new GUIContent(label)); y += lineH; } Field("sourceFolder", "Source Folder"); Field("templateAsset", "Template Asset"); Field("nameSpace", "Namespace"); Field("generatedScript", "Generated Script"); if (entryProp.FindPropertyRelative("generatedScript").objectReferenceValue == null) Field("generatedClassName", "Generated Class Name"); // Info row serializedObject.ApplyModifiedProperties(); var cfg = settings.presetGenerator; var entry = cfg.entries[index]; string info = GetPresetEntryInfo(cfg, entry, index); EditorGUI.LabelField(new Rect(rect.x, y, rect.width, EditorGUIUtility.singleLineHeight), info, EditorStyles.miniLabel); y += lineH; bool valid = IsPresetEntryValid(cfg, entry, index); GUI.enabled = valid; if (GUI.Button(new Rect(rect.x, y, rect.width, 24f), $"Generate Entry [{index}]")) { serializedObject.ApplyModifiedProperties(); cfg.GenerateEntry(index, settings); } GUI.enabled = true; } private bool HasAnyValidPresetEntry() { var cfg = settings.presetGenerator; for (int i = 0; i < cfg.entries.Count; i++) if (IsPresetEntryValid(cfg, cfg.entries[i], i)) return true; return false; } private static bool IsPresetEntryValid(AmaDevSettings.PresetGeneratorConfig cfg, AmaDevSettings.PresetFolderEntry entry, int index) { if (entry.templateAsset == null || entry.sourceFolder == null) return false; var path = AssetDatabase.GetAssetPath(entry.sourceFolder); if (!AssetDatabase.IsValidFolder(path)) return false; return cfg.GetClassName(entry, index) != null; } private static string GetPresetEntryInfo(AmaDevSettings.PresetGeneratorConfig cfg, AmaDevSettings.PresetFolderEntry entry, int index) { var folderPath = entry.sourceFolder != null ? AssetDatabase.GetAssetPath(entry.sourceFolder) : null; if (folderPath == null || !AssetDatabase.IsValidFolder(folderPath)) return "⚠ No valid source folder"; var prefabs = cfg.GetPrefabsInFolder(folderPath); var className = cfg.GetClassName(entry, index); return $"Prefabs: {prefabs.Count} Folder: {folderPath} Class: {className ?? "?"}"; } } // Keep the SymbolInfo property drawer working for the new type [CustomPropertyDrawer(typeof(AmaDevSettings.SymbolInfo))] internal class AmaDevSymbolInfoDrawer : PropertyDrawer { public override void OnGUI(Rect position, SerializedProperty property, GUIContent label) { EditorGUI.BeginProperty(position, label, property); var toggleRect = new Rect(position.x, position.y, 20, position.height); var labelRect = new Rect(position.x + 25, position.y, position.width - 25, position.height); var nameProp = property.FindPropertyRelative("name"); var enabledProp = property.FindPropertyRelative("enabled"); enabledProp.boolValue = EditorGUI.Toggle(toggleRect, enabledProp.boolValue); nameProp.stringValue = EditorGUI.TextField(labelRect, nameProp.stringValue, EditorStyles.label); EditorGUI.EndProperty(); } } }