iFactory.Godot/BITKit/Scripts/Selector/CameraSelector.cs

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;
}
}