123 lines
3.4 KiB
C#
123 lines
3.4 KiB
C#
using Godot;
|
|
using System;
|
|
using BITKit.Selection;
|
|
|
|
namespace BITKit
|
|
{
|
|
public partial class CameraSelector : EntityBehaviour,ISelector
|
|
{
|
|
[Export] private Node3D node3D;
|
|
[Export] private Control control;
|
|
[Export] private float distance;
|
|
|
|
private ISelectable _currentSelectable;
|
|
|
|
private readonly ValidHandle _isEnabled = new();
|
|
public override void _EnterTree()
|
|
{
|
|
base._EnterTree();
|
|
DI.Register<ISelector>(this);
|
|
}
|
|
|
|
public override void _Ready()
|
|
{
|
|
base._Ready();
|
|
if (control is not null)
|
|
{
|
|
control.MouseEntered += () => _isEnabled.RemoveDisableElements(control);
|
|
control.MouseExited += () => _isEnabled.AddDisableElements(control);
|
|
}
|
|
_isEnabled.AddElement(this);
|
|
}
|
|
|
|
public override void _Input(InputEvent @event)
|
|
{
|
|
base._Input(@event);
|
|
switch (@event)
|
|
{
|
|
case InputEventMouseButton { Pressed: true}:
|
|
if (_currentSelectable is not null)
|
|
{
|
|
_currentSelectable.SetSelectionState(SelectionState.Selected);
|
|
OnSelected?.Invoke(_currentSelectable);
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
public override void _Process(double delta)
|
|
{
|
|
base._Process(delta);
|
|
if (!_isEnabled)
|
|
{
|
|
if (_currentSelectable is not null)
|
|
{
|
|
_currentSelectable.SetSelectionState(SelectionState.None);
|
|
OnNone?.Invoke(_currentSelectable);
|
|
_currentSelectable = null;
|
|
}
|
|
}
|
|
|
|
var mousePosition = GetViewport().GetMousePosition();
|
|
var origin = CameraService.Singleton.ProjectRayOrigin(mousePosition);
|
|
var normal = CameraService.Singleton.ProjectRayNormal(mousePosition);
|
|
var end = origin + normal * distance;
|
|
var query = PhysicsRayQueryParameters3D.Create(origin, end);
|
|
query.CollideWithAreas = true;
|
|
|
|
var spaceState =node3D.GetWorld3D().DirectSpaceState;
|
|
var result = spaceState.IntersectRay(query);
|
|
|
|
ISelectable currentSelected=null;
|
|
if (result.TryGetValue("collider", out var collider))
|
|
{
|
|
var node = (Node3D)collider;
|
|
//var pos = (Vector3)result["position"];
|
|
|
|
MathNode.TryGetNodeInParent<ISelectable>(node, out currentSelected);
|
|
}
|
|
|
|
//BIT4Log.Log($"currentSelected:{currentSelected}");
|
|
|
|
switch (currentSelected,_currentSelectable)
|
|
{
|
|
case (not null,not null) when currentSelected != _currentSelectable:
|
|
OnNone?.Invoke(_currentSelectable);
|
|
_currentSelectable.SetSelectionState(SelectionState.None);
|
|
_currentSelectable = currentSelected;
|
|
_currentSelectable.SetSelectionState(SelectionState.Hover);
|
|
OnHover?.Invoke(_currentSelectable);
|
|
break;
|
|
case (null,null): break;
|
|
case (null,not null):
|
|
_currentSelectable.SetSelectionState(SelectionState.None);
|
|
OnNone?.Invoke(_currentSelectable);
|
|
_currentSelectable = null;
|
|
break;
|
|
case (not null,null):
|
|
_currentSelectable = currentSelected;
|
|
_currentSelectable.SetSelectionState(SelectionState.Hover);
|
|
OnHover?.Invoke(_currentSelectable);
|
|
break;
|
|
}
|
|
}
|
|
|
|
public bool TryGetCurrentSelectable(out ISelectable selectable)
|
|
{
|
|
selectable = _currentSelectable;
|
|
return selectable is not null;
|
|
}
|
|
|
|
public event Action<ISelectable> OnNone;
|
|
public event Action<ISelectable> OnHover;
|
|
public event Action<ISelectable> OnActive;
|
|
public event Action<ISelectable> OnInactive;
|
|
public event Action<ISelectable> OnFocus;
|
|
public event Action<ISelectable> OnSelected;
|
|
public event Action<ISelectable> OnEnabled;
|
|
public event Action<ISelectable> OnChecked;
|
|
public event Action<ISelectable> OnRoot;
|
|
}
|
|
|
|
}
|