How to change the rest position of a PinJoint2d

:information_source: Attention Topic was automatically imported from the old Question2Answer platform.
:bust_in_silhouette: Asked By viiragon

How can I change PinJoint2d’s rest position of either node (A or B) dynamically in code, without creating a new joint?

By “Rest position” I mean relative position between nodes, that the joint tries to achieve by applying force to them.
It’s set up when you first join them all up, but I can’t seem to find a way to change it later (neither by code or the editor).

Is there a way to do it without reattaching everything?

What do you mean by “rest position”?

rolfpancake | 2018-02-14 07:24

Relative position between nodes that the pinJoint tries to achieve.
You know, position of nodes in which pinJoint doesn’t apply any force to them anymore.
It’s set up when you attach joint to both nodes, but I can’t find a way to change it after that…
(Sorry for confusion…)

viiragon | 2018-02-14 11:22

Oh okay now I understand. :slight_smile:

rolfpancake | 2018-02-14 11:55

:bust_in_silhouette: Reply From: rolfpancake

As far as I know there is no possibility in changing the distance between the two nodes which the PinJoint2d wants to reach. This would be an interesting feature so you could propose it in the github issues!

I’m not comfortable with Godots codebase, but if I’m not mistaken the resting distance is calculated with the help of the relative vectors rA and rB which are constructed by anchor_A and anchor_B:

rA = A->get_transform().basis_xform(anchor_A);
rB = B ? B->get_transform().basis_xform(anchor_B) : anchor_B;

(Can be found here)

The problem is that the initial positions of node A (p_body_a) and node B (p_body_b) are used to define these vectors when the PinJoint is created (in the constructor):

anchor_A = p_body_a->get_inv_transform().xform(p_pos);
anchor_B = p_body_b ? p_body_b->get_inv_transform().xform(p_pos) : p_pos;

(Found here)

So as long as anchor_A and anchor_B can’t be recalculated there is no way of changing this “resting distance”.

That’s too bad :frowning:
I’ll definietly propose it as I think it should be possible…

viiragon | 2018-02-14 18:21

You can link to the issue here so when people are curious if that changed somewhen in the future they can get more information on github.

rolfpancake | 2018-02-15 08:45

:bust_in_silhouette: Reply From: thomastc

I took a peek at the source code, assuming you are using Godot 3.

You want _configure_joint to be called, because it recreates the joint object in the physics server, which will use the current position of both bodies to determine the rest position.

_configure_point is called from _update_joint.

_update_joint gets called in several cases:

The latter is probably the most robust way of doing this. Note that the value must actually change for it to work. So you can use this workaround:

pin_joint.disable_collision = !pin_joint.disable_collision
pin_joint.disable_collision = !pin_joint.disable_collision

Removing the node from the tree (remove_child) and adding it again (add_child) should also work, but it can mess with the ordering of nodes so it’s not entirely free of side effects.