Soft grab (Nimso): ease the object into the hand (or the hand to the hold) before the weld
Light props (<= 6 kg) fly to the palm, static world / heavy things pull the hand; position only, ~0.1 s, never a snap. Welds no longer freeze a hover gap. Spike: 1 kg cube from 6 cm -> 1.5 mm, bar from 5 cm -> 1.2 cm (contact slop on a curved hold). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
83186f9676
commit
22159aa902
3 files changed
+198
-12
No files matched your search
+31
-12
@@ -26,6 +26,7 @@ public partial class PropGrabber : Node
|
||||
private readonly uint[] _grabSeq = new uint[2];
|
||||
private readonly float[] _breakTimer = new float[2];
|
||||
private readonly bool[] _gripPrev = new bool[2];
|
||||
private readonly SoftGrab[] _easing = new SoftGrab[2]; // grabbed, being eased into the hand (no weld yet)
|
||||
private uint _grabCount;
|
||||
|
||||
public override void _Ready()
|
||||
@@ -50,32 +51,50 @@ public partial class PropGrabber : Node
|
||||
public override void _PhysicsProcess(double delta)
|
||||
{
|
||||
float dt = (float)delta;
|
||||
for (int hand = 0; hand < 2; hand++)
|
||||
{
|
||||
SoftGrab ease = _easing[hand];
|
||||
if (ease == null)
|
||||
continue;
|
||||
if (!IsInstanceValid(ease.Target) || !IsInstanceValid(ease.Hand))
|
||||
_easing[hand] = null;
|
||||
else if (ease.Step(dt))
|
||||
{
|
||||
_easing[hand] = null;
|
||||
Weld(hand == 0 ? _left : _right, hand, ease.Hand, ease.Target);
|
||||
}
|
||||
}
|
||||
HoldUpdate(_left, 0, dt);
|
||||
HoldUpdate(_right, 1, dt);
|
||||
}
|
||||
|
||||
private void Weld(XRController3D controller, int hand, RigidBody3D handBody, PhysicsBody3D prop)
|
||||
{
|
||||
_held[hand] = prop;
|
||||
_grabSeq[hand] = _grabCount++;
|
||||
Vector3 pivot = PalmPoint(handBody, hand);
|
||||
_joints[hand] = MakeWeld(handBody, prop, pivot, RigidWeldBias);
|
||||
_localAnchor[hand] = prop.GlobalTransform.AffineInverse() * pivot;
|
||||
_arms?.SetHeld(hand, prop as RigidBody3D);
|
||||
PlayerRig.SetHeld(controller, prop);
|
||||
string what = prop is RigidBody3D rb ? $"{rb.Mass:0.###} kg" : "static world";
|
||||
GD.Print($"PropGrabber: grabbed '{prop.Name}' ({what}, {(hand == 0 ? "left" : "right")}{(_held[1 - hand] == prop ? ", two-handed" : "")})");
|
||||
}
|
||||
|
||||
private void UpdateHand(XRController3D controller, int hand)
|
||||
{
|
||||
bool grip = controller.GetFloat("grip") > GripThreshold;
|
||||
int other = 1 - hand;
|
||||
|
||||
if (grip && !_gripPrev[hand] && _held[hand] == null)
|
||||
if (grip && !_gripPrev[hand] && _held[hand] == null && _easing[hand] == null)
|
||||
{
|
||||
PhysicsBody3D prop = FindProp(controller, hand);
|
||||
RigidBody3D handBody = PhysicsHands.GetBody(controller);
|
||||
if (prop != null && handBody != null)
|
||||
{
|
||||
_held[hand] = prop;
|
||||
_grabSeq[hand] = _grabCount++;
|
||||
Vector3 pivot = PalmPoint(handBody, hand);
|
||||
_joints[hand] = MakeWeld(handBody, prop, pivot, RigidWeldBias);
|
||||
_localAnchor[hand] = prop.GlobalTransform.AffineInverse() * pivot;
|
||||
_arms?.SetHeld(hand, prop as RigidBody3D);
|
||||
PlayerRig.SetHeld(controller, prop);
|
||||
string what = prop is RigidBody3D rb ? $"{rb.Mass:0.###} kg" : "static world";
|
||||
GD.Print($"PropGrabber: grabbed '{prop.Name}' ({what}, {(hand == 0 ? "left" : "right")}{(_held[other] == prop ? ", two-handed" : "")})");
|
||||
}
|
||||
_easing[hand] = SoftGrab.Begin(handBody, hand, prop); // welded once it's in the hand (_PhysicsProcess)
|
||||
}
|
||||
if (!grip)
|
||||
_easing[hand] = null;
|
||||
|
||||
if (!grip && _held[hand] != null)
|
||||
{
|
||||
|
||||
Reference in new issue
Block a user