UnityTowerDefense/Assets/_Project/Scripts/Editor/Gameplay/WaveGoldEntryDrawer.cs

112 lines
5.4 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// Assets/_Project/Scripts/Editor/Gameplay/WaveGoldEntryDrawer.cs
using UnityEditor;
using UnityEngine;
using TD.Gameplay;
namespace TD.Editor.Gameplay
{
/// <summary>
/// Custom property drawer for <see cref="WaveGoldEntry"/>. Renders the standard fields
/// followed by a read-only "Preview Total" line computed from the entry's values, so
/// designers can see at a glance how much a single player could earn from a wave.
/// </summary>
/// <remarks>
/// The preview includes the kill-reward portion only when the entry's <c>Wave</c>
/// reference is assigned (it's needed to count enemies in that wave). When unset, the
/// preview shows just <c>CompletionBonus + NoLeaksBonus</c> and labels itself so the
/// designer knows to drop a WaveDefinition in for a complete number.
/// </remarks>
[CustomPropertyDrawer(typeof(WaveGoldEntry))]
public class WaveGoldEntryDrawer : PropertyDrawer
{
private const float PreviewLineExtraHeight = 4f;
public override float GetPropertyHeight(SerializedProperty property, GUIContent label)
{
// Sum the children + one extra line for the preview label. We render children
// ourselves rather than using EditorGUI.PropertyField default since we want a
// foldout with our custom preview tacked onto the end.
if (!property.isExpanded) return EditorGUIUtility.singleLineHeight;
float h = EditorGUIUtility.singleLineHeight; // foldout
h += SpacedLineHeight() * 4; // Wave + GoldPerEnemy + Completion + NoLeaks
h += SpacedLineHeight() + PreviewLineExtraHeight; // preview label
return h;
}
public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
{
// Foldout header.
Rect headerRect = new Rect(position.x, position.y, position.width,
EditorGUIUtility.singleLineHeight);
property.isExpanded = EditorGUI.Foldout(headerRect, property.isExpanded, label,
toggleOnLabelClick: true);
if (!property.isExpanded) return;
float y = position.y + SpacedLineHeight();
float indent = 14f;
Rect Row()
{
Rect r = new Rect(position.x + indent, y, position.width - indent,
EditorGUIUtility.singleLineHeight);
y += SpacedLineHeight();
return r;
}
// Standard property fields.
var waveProp = property.FindPropertyRelative("Wave");
var perEnemyProp = property.FindPropertyRelative("GoldPerEnemy");
var completionProp = property.FindPropertyRelative("CompletionBonus");
var noLeaksProp = property.FindPropertyRelative("NoLeaksBonus");
EditorGUI.PropertyField(Row(), waveProp);
EditorGUI.PropertyField(Row(), perEnemyProp);
EditorGUI.PropertyField(Row(), completionProp);
EditorGUI.PropertyField(Row(), noLeaksProp);
// Compute the preview total. We instantiate the same logic as the runtime
// property — read the serialized values, count enemies in the optional Wave,
// sum it all up. Done inline (rather than calling WaveGoldEntry.PreviewTotalGold
// directly) because SerializedProperty edits aren't applied to the target object
// until ApplyModifiedProperties runs at the end of the frame, so reading the
// backing class instance here would show stale data while the user is typing.
int perEnemy = perEnemyProp.intValue;
int completion = completionProp.intValue;
int noLeaks = noLeaksProp.intValue;
var waveAsset = waveProp.objectReferenceValue as WaveDefinition;
int enemyCount = 0;
if (waveAsset != null && waveAsset.Entries != null)
{
foreach (var e in waveAsset.Entries)
{
if (e.EnemyType != null && e.Count > 0)
enemyCount += e.Count;
}
}
int total = perEnemy * enemyCount + completion + noLeaks;
// Preview line. Slightly dimmed style, italic, non-editable. Includes a
// breakdown so the designer can see where the number came from.
y += PreviewLineExtraHeight;
Rect previewRect = new Rect(position.x + indent, y, position.width - indent,
EditorGUIUtility.singleLineHeight);
string breakdown = waveAsset != null
? $"Preview Total: {total} g ({perEnemy} × {enemyCount} enemies " +
$"+ {completion} completion + {noLeaks} no-leak)"
: $"Preview Total: {completion + noLeaks} g (bonuses only — assign Wave " +
$"to include kill rewards)";
var prevStyle = new GUIStyle(EditorStyles.miniLabel) { fontStyle = FontStyle.Italic };
using (new EditorGUI.DisabledScope(true))
{
EditorGUI.LabelField(previewRect, breakdown, prevStyle);
}
}
private static float SpacedLineHeight()
=> EditorGUIUtility.singleLineHeight + EditorGUIUtility.standardVerticalSpacing;
}
}