using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Events;
///
/// Manages selection state for placed interactable objects.
/// Listens to RayInteractor.OnSelectEvent (which only fires when no ghost is active).
/// Supports single and multi-select (Ctrl/Shift).
///
public class SelectionManager : MonoBehaviour
{
private static SelectionManager instance;
public static SelectionManager getInstance() => instance;
private RayInteractor rayInteractor;
private BaseInputProvider inputProvider;
private readonly List currentSelections = new List();
private bool multiSelectEnabled = false;
public UnityEvent SelectionEvent;
// -------------------------------------------------------------------------
// Unity lifecycle
// -------------------------------------------------------------------------
private void Awake()
{
if (instance == null) instance = this;
else Destroy(gameObject);
}
private void Start()
{
rayInteractor = RayInteractor.getInstance();
inputProvider = InputProviderManager.getInstance().getCurrentInputProvider();
inputProvider.OnEnableMultiSelect.AddListener(() => multiSelectEnabled = true);
inputProvider.OnDisableMultiSelect.AddListener(() => multiSelectEnabled = false);
// RayInteractor only fires this when no ghost is active, so we can safely handle selection here
rayInteractor.OnSelectEvent.AddListener(HandleSelect);
}
// -------------------------------------------------------------------------
// Selection logic
// -------------------------------------------------------------------------
private void HandleSelect(IInteractable interactable)
{
if (InputModeManager.Is(InputMode.UI)) return;
if (interactable == null)
{
SelectionEvent?.Invoke(interactable);
// Clicked empty space – clear selection unless multi-select is held
if (!multiSelectEnabled)
ClearSelection();
return;
}
if (multiSelectEnabled)
{
// Toggle the clicked interactable
if (currentSelections.Contains(interactable))
{
currentSelections.Remove(interactable);
interactable.highLightOff();
}
else
{
currentSelections.Add(interactable);
interactable.highLightOn();
}
}
else
{
// Replace selection with just this interactable
bool Exists = currentSelections.Contains(interactable);
ClearSelection();
if (!Exists) {
currentSelections.Add(interactable);
interactable.highLightOn();
}
}
SelectionEvent?.Invoke(interactable);
}
// -------------------------------------------------------------------------
// Public API
// -------------------------------------------------------------------------
public List GetCurrentSelections() => currentSelections;
public void ClearSelection()
{
foreach (IInteractable selection in currentSelections)
selection.highLightOff();
currentSelections.Clear();
SelectionEvent?.Invoke(null);
}
public bool HasOneSelection()
{
return !(currentSelections.Count > 1 || currentSelections.Count == 0);
}
}