using Godot; using System.Collections; using System.Collections.Generic; using Godot.Collections; namespace Rokojori { [GlobalClass,Icon("res://addons/rokojori_action_library/Icons/Grabber.svg")] public partial class Grabber:Node3D, SensorInputHandler { [Export] public Sensor button; [Export] public Pointer pointer; [Export] public Action onGrab; [Export] public Action onRelease; [Export] public TimeLine timeLine; [Export] public Node3D grabOffset; [Export] public Smoothing positionSmoothing; [Export] public Smoothing rotationSmoothing; [ExportGroup("Read Only")] [Export] public Grabbable grabbable; public override void _Ready() { SensorManager.Register( this, button ); } public override void _ExitTree() { SensorManager.Unregister( this, button ); } TimeLineCallback _callback = null; public void _OnSensor( SensorEvent se ) { if ( se.isDown && _callback == null ) { StartGrabbing(); } else if ( se.isUp && _callback != null ) { ReleaseGrabbing(); } } void StartGrabbing() { var pointable = pointer.pointable; if ( pointable == null ) { return; } grabbable = Nodes.Find( pointable.GetParent() ); if ( grabbable == null ) { return; } grabbable.SetGrabber( this ); _callback = TimeLineManager.ScheduleCallback( timeLine, ( cb )=> { if ( cb != _callback ) { return; } positionSmoothing.SetCurrent( grabbable.grabTarget.GlobalPosition ); rotationSmoothing.SetCurrent( grabbable.grabTarget.GetGlobalQuaternion() ); UpdateGrabbable(); } ); Action.Trigger( onGrab ); } void ReleaseGrabbing() { if ( grabbable != null ) { grabbable.SetGrabber( null ); grabbable = null; } _callback.done = true; _callback = null; Action.Trigger( onRelease ); } void UpdateGrabbable() { // this.LogInfo( "Grabbing", HierarchyName.Of( grabbable ) ); grabbable.grabTarget.GlobalPosition = Smoothing.Apply( positionSmoothing, grabOffset.GlobalPosition, timeLine.delta ); grabbable.grabTarget.SetGlobalQuaternion( Smoothing.Apply( rotationSmoothing, grabOffset.GetGlobalQuaternion(), timeLine.delta ) ); grabbable.rigidBody3D.LinearVelocity = Vector3.Zero; grabbable.rigidBody3D.AngularVelocity = Vector3.Zero; } } }