rj-action-library/Runtime/Interactions/Grabber.cs

125 lines
2.6 KiB
C#

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