Initial commit
This commit is contained in:
@@ -0,0 +1,107 @@
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
using UnityEngine.Events;
|
||||
|
||||
/// <summary>
|
||||
/// 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).
|
||||
/// </summary>
|
||||
public class SelectionManager : MonoBehaviour
|
||||
{
|
||||
private static SelectionManager instance;
|
||||
public static SelectionManager getInstance() => instance;
|
||||
|
||||
private RayInteractor rayInteractor;
|
||||
private BaseInputProvider inputProvider;
|
||||
|
||||
private readonly List<IInteractable> currentSelections = new List<IInteractable>();
|
||||
private bool multiSelectEnabled = false;
|
||||
|
||||
public UnityEvent<IInteractable> 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<IInteractable> 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);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user