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(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(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 OnNone; public event Action OnHover; public event Action OnActive; public event Action OnInactive; public event Action OnFocus; public event Action OnSelected; public event Action OnEnabled; public event Action OnChecked; public event Action OnRoot; } }