// Assets/_Project/Scripts/Gameplay/SelectionState.cs
using UnityEngine;
namespace TD.Gameplay
{
///
/// Scene-local selection state. Holds a single (the
/// builder, a tower, or any future selectable type) and fires
/// when it changes.
///
///
/// Local-only. Selection is a UI concept — other clients have no
/// business knowing whether you've selected something. The component is a plain
/// MonoBehaviour and lives in the scene alongside other client-side controllers.
///
/// Singleton. One per scene, accessed via .
/// Selection drivers (input controller, minimap) and selection consumers
/// (HUD, selection-ring visuals) all go through this single source of truth.
///
/// Builder convenience. returns the
/// current selection cast to Builder (or null if non-builder). Lets the input
/// controller and minimap keep the "is the local builder selected?" check
/// short without re-type-testing.
///
public class SelectionState : MonoBehaviour
{
// ----- Singleton --------------------------------------------------
public static SelectionState Instance { get; private set; }
private void Awake()
{
if (Instance != null && Instance != this)
{
Debug.LogWarning("[SelectionState] Multiple instances detected. " +
"Only one SelectionState should exist per scene.");
}
Instance = this;
}
private void OnDestroy()
{
if (Instance == this) Instance = null;
}
// ----- Selection state --------------------------------------------
private ISelectable selected;
/// The currently selected object, or null if nothing is selected.
public ISelectable SelectedObject => selected;
/// Convenience: the selected object if it's a Builder, else null.
public Builder SelectedBuilder => selected as Builder;
/// True if any object is currently selected.
public bool HasSelection => selected != null;
/// True if is the currently selected object.
public bool IsSelected(ISelectable s) => s != null && (object)selected == (object)s;
/// Builder overload — same semantics as .
public bool IsSelected(Builder b) => b != null && (object)selected == (object)b;
// ----- Events -----------------------------------------------------
///
/// Fired when the selection changes. Argument is the new selection (may be null).
/// Subscribe to drive selection-aware UI: highlights, context panels, hotkey hints.
///
public event System.Action OnSelectionChanged;
// ----- Mutators ---------------------------------------------------
///
/// Sets the selected object. Pass null to clear.
/// Fires only if the selection actually changes.
///
public void Select(ISelectable s)
{
if ((object)selected == (object)s) return;
selected = s;
OnSelectionChanged?.Invoke(selected);
}
/// Clears the selection. Equivalent to Select(null).
public void Clear() => Select((ISelectable)null);
}
}