Updating HUD, Gold Config, and finishing off Play flow for 9player map.

This commit is contained in:
Matt F 2026-05-22 12:18:23 -07:00
parent a7be12fa9b
commit 3dcc0e7edd
28 changed files with 2272 additions and 9601 deletions

View file

@ -0,0 +1,112 @@
// 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;
}
}