using UnityEditor; using UnityEditorInternal; using UnityEngine; namespace Amanotes { internal class PresetTab { private Core.AmaDevSettings settings; private bool needsRefresh = true; private Vector2 scrollPos; private SerializedObject serializedSettings; private ReorderableList presetList; private SerializedProperty entriesProp; internal void Refresh() => needsRefresh = true; private void EnsureData() { if (!needsRefresh && settings != null) return; needsRefresh = false; settings = Core.AmaDevSettings.Instance; if (settings == null) return; serializedSettings = new SerializedObject(settings); entriesProp = serializedSettings.FindProperty("presetGenerator.entries"); presetList = new ReorderableList(serializedSettings, entriesProp, true, true, true, true) { drawHeaderCallback = rect => EditorGUI.LabelField(rect, "Preset Folder Entries"), elementHeightCallback = GetElementHeight, drawElementCallback = DrawElement, }; } internal void OnGUI() { EnsureData(); if (settings == null) { EditorGUILayout.HelpBox("No AmaDevSettings asset found.", MessageType.Info); if (GUILayout.Button("Create AmaDevSettings", GUILayout.Height(30))) { settings = Core.AmaDevSettings.GetOrCreate(); needsRefresh = true; } return; } if (EditorApplication.isCompiling) { EditorGUILayout.HelpBox("Compiling...", MessageType.Info); return; } serializedSettings.Update(); scrollPos = EditorGUILayout.BeginScrollView(scrollPos); presetList.DoLayoutList(); EditorGUILayout.EndScrollView(); serializedSettings.ApplyModifiedProperties(); GUILayout.FlexibleSpace(); DrawFooter(); } private void DrawFooter() { var sep = GUILayoutUtility.GetRect(0, 1, GUILayout.ExpandWidth(true)); EditorGUI.DrawRect(sep, new Color(0.3f, 0.3f, 0.3f, 1f)); bool anyValid = HasAnyValidEntry(); GUI.enabled = anyValid; var oldBg = GUI.backgroundColor; GUI.backgroundColor = new Color(0.3f, 0.7f, 1f, 1f); if (GUILayout.Button("Generate All", GUILayout.Height(26))) { serializedSettings.ApplyModifiedProperties(); settings.presetGenerator.GenerateAll(settings); } GUI.backgroundColor = oldBg; GUI.enabled = true; GUILayout.Space(2); } private float GetElementHeight(int index) { var entryProp = entriesProp.GetArrayElementAtIndex(index); bool showClassName = entryProp.FindPropertyRelative("generatedScript").objectReferenceValue == null; bool showTemplate = entryProp.FindPropertyRelative("templateAsset").objectReferenceValue != null; // Fields: sourceFolder, (template if assigned), namespace, generatedScript, (className if no script) int fieldCount = 3; // sourceFolder + namespace + generatedScript if (showTemplate) fieldCount++; if (showClassName) fieldCount++; float lineH = EditorGUIUtility.singleLineHeight + EditorGUIUtility.standardVerticalSpacing; return fieldCount * lineH + lineH + 30f + 12f; } private void DrawElement(Rect rect, int index, bool isActive, bool isFocused) { var entryProp = entriesProp.GetArrayElementAtIndex(index); float lineH = EditorGUIUtility.singleLineHeight + EditorGUIUtility.standardVerticalSpacing; float y = rect.y + 4f; // --- Source Folder (with change detection for auto-namespace) --- var sourceFolderProp = entryProp.FindPropertyRelative("sourceFolder"); var prevFolder = sourceFolderProp.objectReferenceValue; EditorGUI.PropertyField(new Rect(rect.x, y, rect.width, EditorGUIUtility.singleLineHeight), sourceFolderProp, new GUIContent("Source Folder")); y += lineH; // Auto-detect namespace when folder changes if (sourceFolderProp.objectReferenceValue != prevFolder && sourceFolderProp.objectReferenceValue != null) { var namespaceProp = entryProp.FindPropertyRelative("nameSpace"); if (string.IsNullOrEmpty(namespaceProp.stringValue)) { var folderPath = AssetDatabase.GetAssetPath(sourceFolderProp.objectReferenceValue); var detected = Core.AmaDevSettings.PresetGeneratorConfig.DetectNamespaceNearFolder(folderPath); if (detected != null) namespaceProp.stringValue = detected; } } // --- Template (only show if explicitly assigned; uses default otherwise) --- var templateProp = entryProp.FindPropertyRelative("templateAsset"); if (templateProp.objectReferenceValue != null) { EditorGUI.PropertyField(new Rect(rect.x, y, rect.width, EditorGUIUtility.singleLineHeight), templateProp, new GUIContent("Template (override)")); y += lineH; } // --- Namespace --- EditorGUI.PropertyField(new Rect(rect.x, y, rect.width, EditorGUIUtility.singleLineHeight), entryProp.FindPropertyRelative("nameSpace"), new GUIContent("Namespace")); y += lineH; // --- Generated Script OR Class Name --- var scriptProp = entryProp.FindPropertyRelative("generatedScript"); EditorGUI.PropertyField(new Rect(rect.x, y, rect.width, EditorGUIUtility.singleLineHeight), scriptProp, new GUIContent("Generated Script")); y += lineH; if (scriptProp.objectReferenceValue == null) { EditorGUI.PropertyField(new Rect(rect.x, y, rect.width, EditorGUIUtility.singleLineHeight), entryProp.FindPropertyRelative("generatedClassName"), new GUIContent("Class Name")); y += lineH; } serializedSettings.ApplyModifiedProperties(); var cfg = settings.presetGenerator; var entry = cfg.entries[index]; EditorGUI.LabelField(new Rect(rect.x, y, rect.width, EditorGUIUtility.singleLineHeight), GetEntryInfo(cfg, entry, index), EditorStyles.miniLabel); y += lineH; GUI.enabled = IsEntryValid(cfg, entry, index); if (GUI.Button(new Rect(rect.x, y, rect.width, 24f), $"Generate [{index}]")) { serializedSettings.ApplyModifiedProperties(); cfg.GenerateEntry(index, settings); } GUI.enabled = true; } private bool HasAnyValidEntry() { var cfg = settings.presetGenerator; for (int i = 0; i < cfg.entries.Count; i++) if (IsEntryValid(cfg, cfg.entries[i], i)) return true; return false; } private static bool IsEntryValid(Core.AmaDevSettings.PresetGeneratorConfig cfg, Core.AmaDevSettings.PresetFolderEntry entry, int index) { if (entry.sourceFolder == null) return false; var path = AssetDatabase.GetAssetPath(entry.sourceFolder); return AssetDatabase.IsValidFolder(path) && cfg.GetClassName(entry, index) != null; } private static string GetEntryInfo(Core.AmaDevSettings.PresetGeneratorConfig cfg, Core.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 templateLabel = entry.templateAsset != null ? "custom" : "default"; return $"Prefabs: {cfg.GetPrefabsInFolder(folderPath).Count} Class: {cfg.GetClassName(entry, index) ?? "?"} Template: {templateLabel}"; } } }