Files
encounter-system/Editor/EncounterDrawer.cs
2026-04-19 12:25:49 +02:00

82 lines
3.2 KiB
C#

using Jovian.EncounterSystem;
using UnityEditor;
using UnityEngine;
namespace Jovian.EncounterSystem.Editor {
/// <summary>
/// Draws each <see cref="Encounter"/> list element with its <see cref="EncounterDefinition.id"/>
/// as the foldout label (falling back to <c>name</c>, then the default element label).
/// Children are iterated manually to avoid recursing into this drawer.
/// </summary>
[CustomPropertyDrawer(typeof(Encounter))]
public class EncounterDrawer : PropertyDrawer {
private const string DefinitionBackingField = "<EncounterDefinition>k__BackingField";
public override void OnGUI(Rect position, SerializedProperty property, GUIContent label) {
var displayLabel = ResolveLabel(property, label);
var foldoutRect = new Rect(position.x, position.y, position.width, EditorGUIUtility.singleLineHeight);
property.isExpanded = EditorGUI.Foldout(foldoutRect, property.isExpanded, displayLabel, true);
if(!property.isExpanded) {
return;
}
EditorGUI.indentLevel++;
var y = position.y + EditorGUIUtility.singleLineHeight + EditorGUIUtility.standardVerticalSpacing;
var iterator = property.Copy();
var end = iterator.GetEndProperty();
if(iterator.NextVisible(true)) {
while(!SerializedProperty.EqualContents(iterator, end)) {
var h = EditorGUI.GetPropertyHeight(iterator, true);
var r = new Rect(position.x, y, position.width, h);
EditorGUI.PropertyField(r, iterator, true);
y += h + EditorGUIUtility.standardVerticalSpacing;
if(!iterator.NextVisible(false)) {
break;
}
}
}
EditorGUI.indentLevel--;
}
public override float GetPropertyHeight(SerializedProperty property, GUIContent label) {
var height = EditorGUIUtility.singleLineHeight;
if(!property.isExpanded) {
return height;
}
var iterator = property.Copy();
var end = iterator.GetEndProperty();
if(iterator.NextVisible(true)) {
while(!SerializedProperty.EqualContents(iterator, end)) {
height += EditorGUI.GetPropertyHeight(iterator, true) + EditorGUIUtility.standardVerticalSpacing;
if(!iterator.NextVisible(false)) {
break;
}
}
}
return height;
}
private static GUIContent ResolveLabel(SerializedProperty property, GUIContent fallback) {
var definition = property.FindPropertyRelative(DefinitionBackingField);
if(definition == null) {
return fallback;
}
var id = definition.FindPropertyRelative("id")?.stringValue;
if(!string.IsNullOrEmpty(id)) {
return new GUIContent(id);
}
var name = definition.FindPropertyRelative("name")?.stringValue;
if(!string.IsNullOrEmpty(name)) {
return new GUIContent(name);
}
return fallback;
}
}
}