using System; using System.Collections.Generic; using UnityEditor; using UnityEngine; namespace Jovian.PopupSystem.Editor { [CustomPropertyDrawer(typeof(PopupCategory))] public sealed class PopupCategoryDrawer : PropertyDrawer { private static readonly string[] builtInIds = { "Character", "Item", "Skill", "General" }; private const string customLabel = "Custom..."; public override float GetPropertyHeight(SerializedProperty property, GUIContent label) { var idProp = FindIdProperty(property); if(idProp == null) { return EditorGUIUtility.singleLineHeight; } var currentValue = idProp.stringValue ?? ""; var isCustom = Array.IndexOf(builtInIds, currentValue) < 0; // Two lines when in custom mode: dropdown + text field return isCustom ? EditorGUIUtility.singleLineHeight * 2 + 2 : EditorGUIUtility.singleLineHeight; } public override void OnGUI(Rect position, SerializedProperty property, GUIContent label) { EditorGUI.BeginProperty(position, label, property); var idProp = FindIdProperty(property); if(idProp == null) { EditorGUI.LabelField(position, label.text, "Cannot resolve PopupCategory id field"); EditorGUI.EndProperty(); return; } var currentValue = idProp.stringValue ?? ""; var builtInIndex = Array.IndexOf(builtInIds, currentValue); var isCustom = builtInIndex < 0 && !string.IsNullOrEmpty(currentValue); // Build display options: built-in entries + "Custom..." var options = new List(builtInIds); options.Add(customLabel); // Determine selected index int selectedIndex; if(builtInIndex >= 0) { selectedIndex = builtInIndex; } else { selectedIndex = options.Count - 1; // "Custom..." } // First line: dropdown var dropdownRect = new Rect(position.x, position.y, position.width, EditorGUIUtility.singleLineHeight); var newIndex = EditorGUI.Popup(dropdownRect, label.text, selectedIndex, options.ToArray()); if(newIndex != selectedIndex) { if(newIndex < builtInIds.Length) { idProp.stringValue = builtInIds[newIndex]; } else { // Switched to custom — seed with a placeholder if currently built-in if(!isCustom) { idProp.stringValue = "NewCategory"; } } } // Second line: editable text field when custom var finalIsCustom = newIndex >= builtInIds.Length || (newIndex == selectedIndex && isCustom); if(finalIsCustom) { var textRect = new Rect( position.x + EditorGUIUtility.labelWidth + 2, position.y + EditorGUIUtility.singleLineHeight + 2, position.width - EditorGUIUtility.labelWidth - 2, EditorGUIUtility.singleLineHeight); var newValue = EditorGUI.TextField(textRect, idProp.stringValue); if(newValue != idProp.stringValue) { idProp.stringValue = newValue; } } EditorGUI.EndProperty(); } private static SerializedProperty FindIdProperty(SerializedProperty property) { // readonly struct with [SerializeField] readonly string id // Unity serializes this as "id" directly var prop = property.FindPropertyRelative("id"); if(prop != null) { return prop; } // Fallback: auto-property backing field pattern return property.FindPropertyRelative("k__BackingField"); } } }