using System.Collections.Generic; using Cirno.Scripts.Interactables; using Godot; namespace Cirno.Scripts.Components.FSM._3DPlayer; public partial class SelectorController : Node { [Signal] public delegate void ShowSelectorEventHandler(); [Signal] public delegate void HideSelectorEventHandler(); [Signal] public delegate void ChangePositionEventHandler(Vector2 position); [Signal] public delegate void ChangeParent3DEventHandler(Node3D node); private bool _canSelect = true; public bool CanSelect => _canSelect; private bool _autoSelect = false; private double _cooldownTimer = 0f; private Interactable _lastInteractable; private List _interactables = []; private int _selectedInteractable; private int SelectedInteractableIndex { get => _selectedInteractable; set { if (value >= _interactables.Count) { _selectedInteractable = 0; } if (value < 0) { _selectedInteractable = _interactables.Count - 1; // if (_selectedInteractable < 0) // { // _selectedInteractable = 0; // } } } } public IInteractable SelectedInteractable { // The problem here is that if it's deselected the index is -1 get => SelectedInteractableIndex < 0 ? null : _interactables.Count > 0 ? SelectedInteractableIndex >= _interactables.Count ? _interactables[^1] : _interactables[SelectedInteractableIndex] : null; set { // Passing null deselects the interactable if (value == null) { _selectedInteractable = -1; NotifyChanged(null); return; } // If it's already in the list, set the current one to it, otherwise add it if (!_interactables.Contains(value)) { AddInteractable(value); } SelectedInteractableIndex = _interactables.IndexOf(value); NotifyChanged(value); } } public void SelectNext() { SelectedInteractableIndex += 1; // _selectedInteractable += 1; // if (_selectedInteractable >= _interactables.Count) // { // _selectedInteractable = 0; // } if (_interactables.Count <= 0) { SelectedInteractable = null; //SelectedInteractableIndex = -1; } // No need to set it because the selection is already handled when reading // else // { // SelectedInteractable = _interactables[_selectedInteractable]; // } UpdatePosition(); } public void SelectNextDelayed() { if (!_canSelect) { _autoSelect = true; } else { SelectNext(); } //CallDeferred(MethodName.SelectNext); } public void AddInteractable(IInteractable interactable) { if (!_interactables.Contains(interactable)) { _interactables.Add(interactable); // Always set the current one to the newest SelectedInteractable = interactable; // if (_interactables.Count == 1) // { // SelectedInteractable = interactable; // //_selectedInteractable = 0; // } } UpdatePosition(); } public void RemoveInteractable(IInteractable interactable) { _interactables.Remove(interactable); UpdatePosition(); } public void Deselect() { SelectedInteractable = null; //SelectedInteractableIndex = -1; EmitSignalHideSelector(); } public void DeselectWithCooldown() { Deselect(); _canSelect = false; _cooldownTimer = 0d; } public void UpdatePosition() { if (SelectedInteractable != null) { EmitSignalChangePosition(SelectedInteractable.GetScreenPosition()); //EmitSignalChangePosition3D(); EmitSignalChangeParent3D(SelectedInteractable as Node3D); EmitSignalShowSelector(); } else { EmitSignalHideSelector(); } } private void NotifyChanged(IInteractable interactable) { //EmitSignal(nameof(SelectedItemInteractableChanged), interactable); } public void Hide() { EmitSignalHideSelector(); } public void PhysicsProcess(double delta) { if (_canSelect is true) return; _cooldownTimer += delta; if (!(_cooldownTimer >= 0.2d)) return; _canSelect = true; _cooldownTimer = 0; if (!_autoSelect) return; _autoSelect = false; SelectNext(); //if (SelectedInteractable is null) return; //EmitSignalChangePosition(SelectedInteractable.GetScreenPosition()); } }