forked from Shardstone/trail-into-darkness
105 lines
4.0 KiB
C#
105 lines
4.0 KiB
C#
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<string>(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("<id>k__BackingField");
|
|
}
|
|
}
|
|
}
|