using UnityEngine; using TD.Core; #if UNITY_EDITOR using UnityEditor; #endif namespace TD.Levels { /// /// Authoring volume that defines a player's owned territory. Tiles covered by a /// PlayerZoneVolume are in the baked grid (unless /// covered by an Invalid-validity volume — Invalid wins). /// /// /// A single player's zone may consist of multiple PlayerZoneVolume instances with the same /// ; the bake unions their tile coverage. This supports L-shapes and other /// non-rectangular zone footprints. /// public class PlayerZoneVolume : VolumeBase { [Tooltip("Which player owns this zone.")] public PlayerSlot owner = PlayerSlot.Player1; [Tooltip("Whether tiles in this volume are buildable. Defaults to Allowed.")] public PlacementValidity placementValidity = PlacementValidity.Allowed; // Per-volume gizmo Y level (see gizmo design summary). Player zones draw lowest so // overlapping spawners/leak exits/goals stack on top of them. private const float FillYLevel = 0.02f; protected override bool GetAlwaysShowToggle(LevelAuthoring authoring) { return authoring.alwaysShowPlayerZones; } // Selection-only by default. Always-on path runs from OnDrawGizmos when the toggle is set. private void OnDrawGizmosSelected() { DrawGizmosCore(); } private void OnDrawGizmos() { if (ShouldDrawAlwaysOn()) { DrawGizmosCore(); } } private void DrawGizmosCore() { Color baseColor = PlayerColors.Get(owner); DrawTileCoverageFill(baseColor, alpha: 0.35f, yLevel: FillYLevel); DrawRectangularOutline(baseColor, yLevel: FillYLevel); #if UNITY_EDITOR // Label centered on the volume's bounds, identifying which player owns this build area. var col = Collider; if (col != null) { Vector3 labelPos = new Vector3(col.bounds.center.x, FillYLevel + 0.1f, col.bounds.center.z); Handles.Label(labelPos, $"{FormatPlayerName(owner)} Build Area"); } #endif } } }