2025-06-12 18:03:55 +02:00
|
|
|
|
using System.Collections.Generic;
|
|
|
|
|
|
using Cirno.Scripts.Interactables;
|
|
|
|
|
|
using Godot;
|
|
|
|
|
|
|
|
|
|
|
|
namespace Cirno.Scripts.Components.FSM._3DPlayer;
|
|
|
|
|
|
|
|
|
|
|
|
public partial class SelectorController : Node
|
|
|
|
|
|
{
|
2025-08-12 08:43:26 +02:00
|
|
|
|
[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;
|
2025-08-12 10:42:09 +02:00
|
|
|
|
|
2025-08-12 08:43:26 +02:00
|
|
|
|
private double _cooldownTimer = 0f;
|
2025-08-12 10:42:09 +02:00
|
|
|
|
|
2025-06-12 18:03:55 +02:00
|
|
|
|
private Interactable _lastInteractable;
|
|
|
|
|
|
|
|
|
|
|
|
private List<IInteractable> _interactables = [];
|
|
|
|
|
|
|
|
|
|
|
|
private int _selectedInteractable;
|
|
|
|
|
|
|
|
|
|
|
|
private int SelectedInteractableIndex
|
|
|
|
|
|
{
|
|
|
|
|
|
get => _selectedInteractable;
|
|
|
|
|
|
set
|
|
|
|
|
|
{
|
|
|
|
|
|
if (value >= _interactables.Count)
|
|
|
|
|
|
{
|
|
|
|
|
|
_selectedInteractable = 0;
|
2025-08-12 10:42:09 +02:00
|
|
|
|
return;
|
2025-06-12 18:03:55 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (value < 0)
|
|
|
|
|
|
{
|
|
|
|
|
|
_selectedInteractable = _interactables.Count - 1;
|
2025-08-12 08:43:26 +02:00
|
|
|
|
// if (_selectedInteractable < 0)
|
|
|
|
|
|
// {
|
|
|
|
|
|
// _selectedInteractable = 0;
|
|
|
|
|
|
// }
|
2025-08-12 10:42:09 +02:00
|
|
|
|
return;
|
2025-06-12 18:03:55 +02:00
|
|
|
|
}
|
2025-08-12 10:42:09 +02:00
|
|
|
|
|
|
|
|
|
|
_selectedInteractable = value;
|
2025-06-12 18:03:55 +02:00
|
|
|
|
}
|
|
|
|
|
|
}
|
2025-08-12 08:43:26 +02:00
|
|
|
|
|
2025-08-12 10:42:09 +02:00
|
|
|
|
public IInteractable GetSelectedInteractable()
|
|
|
|
|
|
{
|
|
|
|
|
|
return SelectedInteractableIndex < 0
|
|
|
|
|
|
? null
|
|
|
|
|
|
: _interactables.Count > 0
|
|
|
|
|
|
? SelectedInteractableIndex >= _interactables.Count
|
|
|
|
|
|
? _interactables[^1]
|
|
|
|
|
|
: _interactables[SelectedInteractableIndex]
|
|
|
|
|
|
: null;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-06-12 18:03:55 +02:00
|
|
|
|
public IInteractable SelectedInteractable
|
|
|
|
|
|
{
|
2025-08-12 08:43:26 +02:00
|
|
|
|
// The problem here is that if it's deselected the index is -1
|
2025-08-12 10:42:09 +02:00
|
|
|
|
// get =>
|
|
|
|
|
|
// SelectedInteractableIndex < 0
|
|
|
|
|
|
// ? null
|
|
|
|
|
|
// : _interactables.Count > 0
|
|
|
|
|
|
// ? SelectedInteractableIndex >= _interactables.Count
|
|
|
|
|
|
// ? _interactables[^1]
|
|
|
|
|
|
// : _interactables[SelectedInteractableIndex]
|
|
|
|
|
|
// : null;
|
2025-06-12 18:03:55 +02:00
|
|
|
|
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);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
2025-08-12 08:43:26 +02:00
|
|
|
|
|
2025-06-12 18:03:55 +02:00
|
|
|
|
public void SelectNext()
|
|
|
|
|
|
{
|
|
|
|
|
|
SelectedInteractableIndex += 1;
|
|
|
|
|
|
// _selectedInteractable += 1;
|
|
|
|
|
|
// if (_selectedInteractable >= _interactables.Count)
|
|
|
|
|
|
// {
|
|
|
|
|
|
// _selectedInteractable = 0;
|
|
|
|
|
|
// }
|
|
|
|
|
|
|
2025-08-12 08:43:26 +02:00
|
|
|
|
if (_interactables.Count <= 0)
|
2025-06-12 18:03:55 +02:00
|
|
|
|
{
|
2025-08-12 08:43:26 +02:00
|
|
|
|
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;
|
2025-06-12 18:03:55 +02:00
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
2025-08-12 08:43:26 +02:00
|
|
|
|
SelectNext();
|
2025-06-12 18:03:55 +02:00
|
|
|
|
}
|
2025-08-12 08:43:26 +02:00
|
|
|
|
//CallDeferred(MethodName.SelectNext);
|
2025-06-12 18:03:55 +02:00
|
|
|
|
}
|
2025-08-12 08:43:26 +02:00
|
|
|
|
|
2025-06-12 18:03:55 +02:00
|
|
|
|
public void AddInteractable(IInteractable interactable)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (!_interactables.Contains(interactable))
|
|
|
|
|
|
{
|
|
|
|
|
|
_interactables.Add(interactable);
|
|
|
|
|
|
|
2025-08-12 08:43:26 +02:00
|
|
|
|
|
|
|
|
|
|
// if (_interactables.Count == 1)
|
|
|
|
|
|
// {
|
|
|
|
|
|
// SelectedInteractable = interactable;
|
|
|
|
|
|
// //_selectedInteractable = 0;
|
|
|
|
|
|
// }
|
2025-06-12 18:03:55 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
2025-08-12 10:42:09 +02:00
|
|
|
|
// Always set the current one to the newest
|
|
|
|
|
|
SelectedInteractable = interactable;
|
|
|
|
|
|
|
2025-06-12 18:03:55 +02:00
|
|
|
|
UpdatePosition();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public void RemoveInteractable(IInteractable interactable)
|
|
|
|
|
|
{
|
2025-08-07 15:09:02 +02:00
|
|
|
|
_interactables.Remove(interactable);
|
2025-06-12 18:03:55 +02:00
|
|
|
|
|
|
|
|
|
|
UpdatePosition();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public void Deselect()
|
|
|
|
|
|
{
|
2025-08-12 08:43:26 +02:00
|
|
|
|
SelectedInteractable = null;
|
|
|
|
|
|
//SelectedInteractableIndex = -1;
|
2025-06-12 18:03:55 +02:00
|
|
|
|
EmitSignalHideSelector();
|
2025-08-12 08:43:26 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public void DeselectWithCooldown()
|
|
|
|
|
|
{
|
|
|
|
|
|
Deselect();
|
|
|
|
|
|
_canSelect = false;
|
|
|
|
|
|
_cooldownTimer = 0d;
|
2025-06-12 18:03:55 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public void UpdatePosition()
|
|
|
|
|
|
{
|
2025-08-12 10:42:09 +02:00
|
|
|
|
var selected = GetSelectedInteractable();
|
|
|
|
|
|
if (selected != null)
|
2025-06-12 18:03:55 +02:00
|
|
|
|
{
|
2025-08-12 10:42:09 +02:00
|
|
|
|
EmitSignalChangePosition(selected.GetScreenPosition());
|
2025-08-07 15:09:02 +02:00
|
|
|
|
//EmitSignalChangePosition3D();
|
2025-08-12 10:42:09 +02:00
|
|
|
|
EmitSignalChangeParent3D(selected as Node3D);
|
2025-06-12 18:03:55 +02:00
|
|
|
|
EmitSignalShowSelector();
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
EmitSignalHideSelector();
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
2025-08-12 08:43:26 +02:00
|
|
|
|
|
2025-06-12 18:03:55 +02:00
|
|
|
|
private void NotifyChanged(IInteractable interactable)
|
|
|
|
|
|
{
|
|
|
|
|
|
//EmitSignal(nameof(SelectedItemInteractableChanged), interactable);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public void Hide()
|
|
|
|
|
|
{
|
|
|
|
|
|
EmitSignalHideSelector();
|
|
|
|
|
|
}
|
2025-06-13 17:46:44 +02:00
|
|
|
|
|
2025-08-12 08:43:26 +02:00
|
|
|
|
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());
|
|
|
|
|
|
}
|
2025-06-12 18:03:55 +02:00
|
|
|
|
}
|