diff --git a/COPYRIGHT.txt b/COPYRIGHT.txt
index 500eb84d08b..81dc8c81b88 100644
--- a/COPYRIGHT.txt
+++ b/COPYRIGHT.txt
@@ -85,6 +85,11 @@ Copyright: 2001, Robert Penner
2007-2014, Juan Linietsky, Ariel Manzur
License: Expat
+Files: ./servers/physics_2d/godot_joints_2d.cpp
+Comment: Chipmunk2D Joint Constraints
+Copyright: 2007, Scott Lembcke
+License: Expat
+
Files: ./servers/physics_3d/collision_solver_3d_sat.cpp
Comment: Open Dynamics Engine
Copyright: 2001-2003, Russell L. Smith, Alen Ladavac, Nguyen Binh
diff --git a/doc/classes/PhysicsServer2D.xml b/doc/classes/PhysicsServer2D.xml
index 39d18a9e359..ae25af1dd93 100644
--- a/doc/classes/PhysicsServer2D.xml
+++ b/doc/classes/PhysicsServer2D.xml
@@ -839,6 +839,14 @@
Sets the value of the given joint parameter. See [enum JointParam] for the list of available parameters.
+
+
+
+
+
+ Gets a pin joint flag (see [enum PinJointFlag] constants).
+
+
@@ -847,6 +855,15 @@
Returns the value of a pin joint parameter. See [enum PinJointParam] for a list of available parameters.
+
+
+
+
+
+
+ Sets a pin joint flag (see [enum PinJointFlag] constants).
+
+
@@ -1160,6 +1177,21 @@
Constant to set/get a how much the bond of the pin joint can flex. The default value of this parameter is [code]0.0[/code].
+
+ The maximum rotation around the pin.
+
+
+ The minimum rotation around the pin.
+
+
+ Target speed for the motor. In radians per second.
+
+
+ If [code]true[/code], the pin has a maximum and a minimum rotation.
+
+
+ If [code]true[/code], a motor turns the pin.
+
Sets the resting length of the spring joint. The joint will always try to go to back this length when pulled apart. The default value of this parameter is the distance between the joint's anchor points.
diff --git a/doc/classes/PhysicsServer2DExtension.xml b/doc/classes/PhysicsServer2DExtension.xml
index e2f86cae5da..8d9a1713373 100644
--- a/doc/classes/PhysicsServer2DExtension.xml
+++ b/doc/classes/PhysicsServer2DExtension.xml
@@ -780,6 +780,13 @@
+
+
+
+
+
+
+
@@ -787,6 +794,14 @@
+
+
+
+
+
+
+
+
diff --git a/doc/classes/PinJoint2D.xml b/doc/classes/PinJoint2D.xml
index 6adfc818e7a..a252f603122 100644
--- a/doc/classes/PinJoint2D.xml
+++ b/doc/classes/PinJoint2D.xml
@@ -9,6 +9,21 @@
+
+ If [code]true[/code], the pin maximum and minimum rotation, defined by [member angular_limit_lower] and [member angular_limit_upper] are applied.
+
+
+ The minimum rotation. Only active if [member angular_limit_enabled] is [code]true[/code].
+
+
+ The maximum rotation. Only active if [member angular_limit_enabled] is [code]true[/code].
+
+
+ When activated, a motor turns the pin.
+
+
+ Target speed for the motor. In radians per second.
+
The higher this value, the more the bond to the pinned partner can flex.
diff --git a/scene/2d/joint_2d.cpp b/scene/2d/joint_2d.cpp
index 62b44655c1e..41b121a482a 100644
--- a/scene/2d/joint_2d.cpp
+++ b/scene/2d/joint_2d.cpp
@@ -277,9 +277,17 @@ void PinJoint2D::_notification(int p_what) {
void PinJoint2D::_configure_joint(RID p_joint, PhysicsBody2D *body_a, PhysicsBody2D *body_b) {
PhysicsServer2D::get_singleton()->joint_make_pin(p_joint, get_global_position(), body_a->get_rid(), body_b ? body_b->get_rid() : RID());
PhysicsServer2D::get_singleton()->pin_joint_set_param(p_joint, PhysicsServer2D::PIN_JOINT_SOFTNESS, softness);
+ PhysicsServer2D::get_singleton()->pin_joint_set_param(p_joint, PhysicsServer2D::PIN_JOINT_LIMIT_UPPER, angular_limit_upper);
+ PhysicsServer2D::get_singleton()->pin_joint_set_param(p_joint, PhysicsServer2D::PIN_JOINT_LIMIT_LOWER, angular_limit_lower);
+ PhysicsServer2D::get_singleton()->pin_joint_set_param(p_joint, PhysicsServer2D::PIN_JOINT_MOTOR_TARGET_VELOCITY, motor_target_velocity);
+ PhysicsServer2D::get_singleton()->pin_joint_set_flag(p_joint, PhysicsServer2D::PIN_JOINT_FLAG_MOTOR_ENABLED, motor_enabled);
+ PhysicsServer2D::get_singleton()->pin_joint_set_flag(p_joint, PhysicsServer2D::PIN_JOINT_FLAG_ANGULAR_LIMIT_ENABLED, angular_limit_enabled);
}
void PinJoint2D::set_softness(real_t p_softness) {
+ if (softness == p_softness) {
+ return;
+ }
softness = p_softness;
queue_redraw();
if (is_configured()) {
@@ -291,11 +299,103 @@ real_t PinJoint2D::get_softness() const {
return softness;
}
+void PinJoint2D::set_angular_limit_lower(real_t p_angular_limit_lower) {
+ if (angular_limit_lower == p_angular_limit_lower) {
+ return;
+ }
+ angular_limit_lower = p_angular_limit_lower;
+ queue_redraw();
+ if (is_configured()) {
+ PhysicsServer2D::get_singleton()->pin_joint_set_param(get_rid(), PhysicsServer2D::PIN_JOINT_LIMIT_LOWER, p_angular_limit_lower);
+ }
+}
+
+real_t PinJoint2D::get_angular_limit_lower() const {
+ return angular_limit_lower;
+}
+
+void PinJoint2D::set_angular_limit_upper(real_t p_angular_limit_upper) {
+ if (angular_limit_upper == p_angular_limit_upper) {
+ return;
+ }
+ angular_limit_upper = p_angular_limit_upper;
+ queue_redraw();
+ if (is_configured()) {
+ PhysicsServer2D::get_singleton()->pin_joint_set_param(get_rid(), PhysicsServer2D::PIN_JOINT_LIMIT_UPPER, p_angular_limit_upper);
+ }
+}
+
+real_t PinJoint2D::get_angular_limit_upper() const {
+ return angular_limit_upper;
+}
+
+void PinJoint2D::set_motor_target_velocity(real_t p_motor_target_velocity) {
+ if (motor_target_velocity == p_motor_target_velocity) {
+ return;
+ }
+ motor_target_velocity = p_motor_target_velocity;
+ queue_redraw();
+ if (is_configured()) {
+ PhysicsServer2D::get_singleton()->pin_joint_set_param(get_rid(), PhysicsServer2D::PIN_JOINT_MOTOR_TARGET_VELOCITY, motor_target_velocity);
+ }
+}
+
+real_t PinJoint2D::get_motor_target_velocity() const {
+ return motor_target_velocity;
+}
+
+void PinJoint2D::set_motor_enabled(bool p_motor_enabled) {
+ if (motor_enabled == p_motor_enabled) {
+ return;
+ }
+ motor_enabled = p_motor_enabled;
+ queue_redraw();
+ if (is_configured()) {
+ PhysicsServer2D::get_singleton()->pin_joint_set_flag(get_rid(), PhysicsServer2D::PIN_JOINT_FLAG_MOTOR_ENABLED, motor_enabled);
+ }
+}
+
+bool PinJoint2D::is_motor_enabled() const {
+ return motor_enabled;
+}
+
+void PinJoint2D::set_angular_limit_enabled(bool p_angular_limit_enabled) {
+ if (angular_limit_enabled == p_angular_limit_enabled) {
+ return;
+ }
+ angular_limit_enabled = p_angular_limit_enabled;
+ queue_redraw();
+ if (is_configured()) {
+ PhysicsServer2D::get_singleton()->pin_joint_set_flag(get_rid(), PhysicsServer2D::PIN_JOINT_FLAG_ANGULAR_LIMIT_ENABLED, angular_limit_enabled);
+ }
+}
+
+bool PinJoint2D::is_angular_limit_enabled() const {
+ return angular_limit_enabled;
+}
+
void PinJoint2D::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_softness", "softness"), &PinJoint2D::set_softness);
ClassDB::bind_method(D_METHOD("get_softness"), &PinJoint2D::get_softness);
+ ClassDB::bind_method(D_METHOD("set_angular_limit_lower", "angular_limit_lower"), &PinJoint2D::set_angular_limit_lower);
+ ClassDB::bind_method(D_METHOD("get_angular_limit_lower"), &PinJoint2D::get_angular_limit_lower);
+ ClassDB::bind_method(D_METHOD("set_angular_limit_upper", "angular_limit_upper"), &PinJoint2D::set_angular_limit_upper);
+ ClassDB::bind_method(D_METHOD("get_angular_limit_upper"), &PinJoint2D::get_angular_limit_upper);
+ ClassDB::bind_method(D_METHOD("set_motor_target_velocity", "motor_target_velocity"), &PinJoint2D::set_motor_target_velocity);
+ ClassDB::bind_method(D_METHOD("get_motor_target_velocity"), &PinJoint2D::get_motor_target_velocity);
+ ClassDB::bind_method(D_METHOD("set_motor_enabled", "enabled"), &PinJoint2D::set_motor_enabled);
+ ClassDB::bind_method(D_METHOD("is_motor_enabled"), &PinJoint2D::is_motor_enabled);
+ ClassDB::bind_method(D_METHOD("set_angular_limit_enabled", "enabled"), &PinJoint2D::set_angular_limit_enabled);
+ ClassDB::bind_method(D_METHOD("is_angular_limit_enabled"), &PinJoint2D::is_angular_limit_enabled);
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "softness", PROPERTY_HINT_RANGE, "0.00,16,0.01,exp"), "set_softness", "get_softness");
+ ADD_GROUP("Angular Limit", "angular_limit_");
+ ADD_PROPERTY(PropertyInfo(Variant::BOOL, "angular_limit_enabled"), "set_angular_limit_enabled", "is_angular_limit_enabled");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "angular_limit_lower", PROPERTY_HINT_RANGE, "-180,180,0.1,radians_as_degrees"), "set_angular_limit_lower", "get_angular_limit_lower");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "angular_limit_upper", PROPERTY_HINT_RANGE, "-180,180,0.1,radians_as_degrees"), "set_angular_limit_upper", "get_angular_limit_upper");
+ ADD_GROUP("Motor", "motor_");
+ ADD_PROPERTY(PropertyInfo(Variant::BOOL, "motor_enabled"), "set_motor_enabled", "is_motor_enabled");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "motor_target_velocity", PROPERTY_HINT_RANGE, U"-200,200,0.01,or_greater,or_less,radians_as_degrees,suffix:\u00B0/s"), "set_motor_target_velocity", "get_motor_target_velocity");
}
PinJoint2D::PinJoint2D() {
diff --git a/scene/2d/joint_2d.h b/scene/2d/joint_2d.h
index 581a3b6757b..5ff75a77a12 100644
--- a/scene/2d/joint_2d.h
+++ b/scene/2d/joint_2d.h
@@ -85,6 +85,11 @@ class PinJoint2D : public Joint2D {
GDCLASS(PinJoint2D, Joint2D);
real_t softness = 0.0;
+ real_t angular_limit_lower = 0.0;
+ real_t angular_limit_upper = 0.0;
+ real_t motor_target_velocity = 0.0;
+ bool motor_enabled = false;
+ bool angular_limit_enabled = false;
protected:
void _notification(int p_what);
@@ -94,6 +99,17 @@ protected:
public:
void set_softness(real_t p_softness);
real_t get_softness() const;
+ void set_angular_limit_lower(real_t p_angular_limit_lower);
+ real_t get_angular_limit_lower() const;
+ void set_angular_limit_upper(real_t p_angular_limit_upper);
+ real_t get_angular_limit_upper() const;
+ void set_motor_target_velocity(real_t p_motor_target_velocity);
+ real_t get_motor_target_velocity() const;
+
+ void set_motor_enabled(bool p_motor_enabled);
+ bool is_motor_enabled() const;
+ void set_angular_limit_enabled(bool p_angular_limit_enabled);
+ bool is_angular_limit_enabled() const;
PinJoint2D();
};
diff --git a/servers/extensions/physics_server_2d_extension.cpp b/servers/extensions/physics_server_2d_extension.cpp
index 96f09a8b1cc..f8e78d655f4 100644
--- a/servers/extensions/physics_server_2d_extension.cpp
+++ b/servers/extensions/physics_server_2d_extension.cpp
@@ -316,6 +316,9 @@ void PhysicsServer2DExtension::_bind_methods() {
GDVIRTUAL_BIND(_joint_make_groove, "joint", "a_groove1", "a_groove2", "b_anchor", "body_a", "body_b");
GDVIRTUAL_BIND(_joint_make_damped_spring, "joint", "anchor_a", "anchor_b", "body_a", "body_b");
+ GDVIRTUAL_BIND(_pin_joint_set_flag, "joint", "flag", "enabled");
+ GDVIRTUAL_BIND(_pin_joint_get_flag, "joint", "flag");
+
GDVIRTUAL_BIND(_pin_joint_set_param, "joint", "param", "value");
GDVIRTUAL_BIND(_pin_joint_get_param, "joint", "param");
diff --git a/servers/extensions/physics_server_2d_extension.h b/servers/extensions/physics_server_2d_extension.h
index 6ddbb98766d..6e0277a7c68 100644
--- a/servers/extensions/physics_server_2d_extension.h
+++ b/servers/extensions/physics_server_2d_extension.h
@@ -419,6 +419,9 @@ public:
EXBIND6(joint_make_groove, RID, const Vector2 &, const Vector2 &, const Vector2 &, RID, RID)
EXBIND5(joint_make_damped_spring, RID, const Vector2 &, const Vector2 &, RID, RID)
+ EXBIND3(pin_joint_set_flag, RID, PinJointFlag, bool)
+ EXBIND2RC(bool, pin_joint_get_flag, RID, PinJointFlag)
+
EXBIND3(pin_joint_set_param, RID, PinJointParam, real_t)
EXBIND2RC(real_t, pin_joint_get_param, RID, PinJointParam)
diff --git a/servers/physics_2d/godot_joints_2d.cpp b/servers/physics_2d/godot_joints_2d.cpp
index c7cdd271ca0..567ae01c491 100644
--- a/servers/physics_2d/godot_joints_2d.cpp
+++ b/servers/physics_2d/godot_joints_2d.cpp
@@ -155,6 +155,9 @@ bool GodotPinJoint2D::setup(real_t p_step) {
bias = delta * -(get_bias() == 0 ? space->get_constraint_bias() : get_bias()) * (1.0 / p_step);
+ // Compute max impulse.
+ jn_max = get_max_force() * p_step;
+
return true;
}
@@ -170,12 +173,41 @@ bool GodotPinJoint2D::pre_solve(real_t p_step) {
if (B && dynamic_B) {
B->apply_impulse(P, rB);
}
+ // Angle limits joint pre_solve step taken from https://github.com/slembcke/Chipmunk2D/blob/d0239ef4599b3688a5a336373f7d0a68426414ba/src/cpRotaryLimitJoint.c
+ real_t i_sum_local = A->get_inv_inertia();
+ if (B) {
+ i_sum_local += B->get_inv_inertia();
+ }
+ i_sum = 1.0 / (i_sum_local);
+ if (angular_limit_enabled && B) {
+ Vector2 diff_vector = B->get_transform().get_origin() - A->get_transform().get_origin();
+ diff_vector = diff_vector.rotated(-initial_angle);
+ real_t dist = diff_vector.angle();
+ real_t pdist = 0.0;
+ if (dist > angular_limit_upper) {
+ pdist = dist - angular_limit_upper;
+ } else if (dist < angular_limit_lower) {
+ pdist = dist - angular_limit_lower;
+ }
+ real_t error_bias = Math::pow(1.0 - 0.15, 60.0);
+ // Calculate bias velocity.
+ bias_velocity = -CLAMP((-1.0 - Math::pow(error_bias, p_step)) * pdist / p_step, -get_max_bias(), get_max_bias());
+ // If the bias velocity is 0, the joint is not at a limit.
+ if (bias_velocity >= -CMP_EPSILON && bias_velocity <= CMP_EPSILON) {
+ j_acc = 0;
+ is_joint_at_limit = false;
+ } else {
+ is_joint_at_limit = true;
+ }
+ } else {
+ bias_velocity = 0.0;
+ }
return true;
}
void GodotPinJoint2D::solve(real_t p_step) {
- // compute relative velocity
+ // Compute relative velocity.
Vector2 vA = A->get_linear_velocity() - custom_cross(rA - A->get_center_of_mass(), A->get_angular_velocity());
Vector2 rel_vel;
@@ -184,6 +216,33 @@ void GodotPinJoint2D::solve(real_t p_step) {
} else {
rel_vel = -vA;
}
+ // Angle limits joint solve step taken from https://github.com/slembcke/Chipmunk2D/blob/d0239ef4599b3688a5a336373f7d0a68426414ba/src/cpRotaryLimitJoint.c
+ if ((angular_limit_enabled || motor_enabled) && B) {
+ // Compute relative rotational velocity.
+ real_t wr = B->get_angular_velocity() - A->get_angular_velocity();
+ // Motor solve part taken from https://github.com/slembcke/Chipmunk2D/blob/d0239ef4599b3688a5a336373f7d0a68426414ba/src/cpSimpleMotor.c
+ if (motor_enabled) {
+ wr -= motor_target_velocity;
+ }
+ real_t j_max = jn_max;
+
+ // Compute normal impulse.
+ real_t j = -(bias_velocity + wr) * i_sum;
+ real_t j_old = j_acc;
+ // Only enable the limits if we have to.
+ if (angular_limit_enabled && is_joint_at_limit) {
+ if (bias_velocity < 0.0) {
+ j_acc = CLAMP(j_old + j, 0.0, j_max);
+ } else {
+ j_acc = CLAMP(j_old + j, -j_max, 0.0);
+ }
+ } else {
+ j_acc = CLAMP(j_old + j, -j_max, j_max);
+ }
+ j = j_acc - j_old;
+ A->apply_torque_impulse(-j * A->get_inv_inertia());
+ B->apply_torque_impulse(j * B->get_inv_inertia());
+ }
Vector2 impulse = M.basis_xform(bias - rel_vel - Vector2(softness, softness) * P);
@@ -198,14 +257,59 @@ void GodotPinJoint2D::solve(real_t p_step) {
}
void GodotPinJoint2D::set_param(PhysicsServer2D::PinJointParam p_param, real_t p_value) {
- if (p_param == PhysicsServer2D::PIN_JOINT_SOFTNESS) {
- softness = p_value;
+ switch (p_param) {
+ case PhysicsServer2D::PIN_JOINT_SOFTNESS: {
+ softness = p_value;
+ } break;
+ case PhysicsServer2D::PIN_JOINT_LIMIT_UPPER: {
+ angular_limit_upper = p_value;
+ } break;
+ case PhysicsServer2D::PIN_JOINT_LIMIT_LOWER: {
+ angular_limit_lower = p_value;
+ } break;
+ case PhysicsServer2D::PIN_JOINT_MOTOR_TARGET_VELOCITY: {
+ motor_target_velocity = p_value;
+ } break;
}
}
real_t GodotPinJoint2D::get_param(PhysicsServer2D::PinJointParam p_param) const {
- if (p_param == PhysicsServer2D::PIN_JOINT_SOFTNESS) {
- return softness;
+ switch (p_param) {
+ case PhysicsServer2D::PIN_JOINT_SOFTNESS: {
+ return softness;
+ }
+ case PhysicsServer2D::PIN_JOINT_LIMIT_UPPER: {
+ return angular_limit_upper;
+ }
+ case PhysicsServer2D::PIN_JOINT_LIMIT_LOWER: {
+ return angular_limit_lower;
+ }
+ case PhysicsServer2D::PIN_JOINT_MOTOR_TARGET_VELOCITY: {
+ return motor_target_velocity;
+ }
+ }
+ ERR_FAIL_V(0);
+}
+
+void GodotPinJoint2D::set_flag(PhysicsServer2D::PinJointFlag p_flag, bool p_enabled) {
+ switch (p_flag) {
+ case PhysicsServer2D::PIN_JOINT_FLAG_ANGULAR_LIMIT_ENABLED: {
+ angular_limit_enabled = p_enabled;
+ } break;
+ case PhysicsServer2D::PIN_JOINT_FLAG_MOTOR_ENABLED: {
+ motor_enabled = p_enabled;
+ } break;
+ }
+}
+
+bool GodotPinJoint2D::get_flag(PhysicsServer2D::PinJointFlag p_flag) const {
+ switch (p_flag) {
+ case PhysicsServer2D::PIN_JOINT_FLAG_ANGULAR_LIMIT_ENABLED: {
+ return angular_limit_enabled;
+ }
+ case PhysicsServer2D::PIN_JOINT_FLAG_MOTOR_ENABLED: {
+ return motor_enabled;
+ }
}
ERR_FAIL_V(0);
}
@@ -220,6 +324,7 @@ GodotPinJoint2D::GodotPinJoint2D(const Vector2 &p_pos, GodotBody2D *p_body_a, Go
p_body_a->add_constraint(this, 0);
if (p_body_b) {
p_body_b->add_constraint(this, 1);
+ initial_angle = A->get_transform().get_origin().angle_to_point(B->get_transform().get_origin());
}
}
diff --git a/servers/physics_2d/godot_joints_2d.h b/servers/physics_2d/godot_joints_2d.h
index 7a75781c879..c6a1fdb6921 100644
--- a/servers/physics_2d/godot_joints_2d.h
+++ b/servers/physics_2d/godot_joints_2d.h
@@ -88,8 +88,19 @@ class GodotPinJoint2D : public GodotJoint2D {
Vector2 anchor_A;
Vector2 anchor_B;
Vector2 bias;
+ real_t initial_angle = 0.0;
+ real_t bias_velocity = 0.0;
+ real_t jn_max = 0.0;
+ real_t j_acc = 0.0;
+ real_t i_sum = 0.0;
Vector2 P;
real_t softness = 0.0;
+ real_t angular_limit_lower = 0.0;
+ real_t angular_limit_upper = 0.0;
+ real_t motor_target_velocity = 0.0;
+ bool is_joint_at_limit = false;
+ bool motor_enabled = false;
+ bool angular_limit_enabled = false;
public:
virtual PhysicsServer2D::JointType get_type() const override { return PhysicsServer2D::JOINT_TYPE_PIN; }
@@ -101,6 +112,9 @@ public:
void set_param(PhysicsServer2D::PinJointParam p_param, real_t p_value);
real_t get_param(PhysicsServer2D::PinJointParam p_param) const;
+ void set_flag(PhysicsServer2D::PinJointFlag p_flag, bool p_enabled);
+ bool get_flag(PhysicsServer2D::PinJointFlag p_flag) const;
+
GodotPinJoint2D(const Vector2 &p_pos, GodotBody2D *p_body_a, GodotBody2D *p_body_b = nullptr);
};
diff --git a/servers/physics_2d/godot_physics_server_2d.cpp b/servers/physics_2d/godot_physics_server_2d.cpp
index 30600e0e573..5e01abd555c 100644
--- a/servers/physics_2d/godot_physics_server_2d.cpp
+++ b/servers/physics_2d/godot_physics_server_2d.cpp
@@ -1158,6 +1158,24 @@ void GodotPhysicsServer2D::joint_make_damped_spring(RID p_joint, const Vector2 &
memdelete(prev_joint);
}
+void GodotPhysicsServer2D::pin_joint_set_flag(RID p_joint, PinJointFlag p_flag, bool p_enabled) {
+ GodotJoint2D *joint = joint_owner.get_or_null(p_joint);
+ ERR_FAIL_NULL(joint);
+ ERR_FAIL_COND(joint->get_type() != JOINT_TYPE_PIN);
+
+ GodotPinJoint2D *pin_joint = static_cast(joint);
+ pin_joint->set_flag(p_flag, p_enabled);
+}
+
+bool GodotPhysicsServer2D::pin_joint_get_flag(RID p_joint, PinJointFlag p_flag) const {
+ GodotJoint2D *joint = joint_owner.get_or_null(p_joint);
+ ERR_FAIL_NULL_V(joint, 0);
+ ERR_FAIL_COND_V(joint->get_type() != JOINT_TYPE_PIN, 0);
+
+ GodotPinJoint2D *pin_joint = static_cast(joint);
+ return pin_joint->get_flag(p_flag);
+}
+
void GodotPhysicsServer2D::pin_joint_set_param(RID p_joint, PinJointParam p_param, real_t p_value) {
GodotJoint2D *joint = joint_owner.get_or_null(p_joint);
ERR_FAIL_NULL(joint);
diff --git a/servers/physics_2d/godot_physics_server_2d.h b/servers/physics_2d/godot_physics_server_2d.h
index e9b8d9a90a4..991cf67c951 100644
--- a/servers/physics_2d/godot_physics_server_2d.h
+++ b/servers/physics_2d/godot_physics_server_2d.h
@@ -275,6 +275,8 @@ public:
virtual void joint_make_groove(RID p_joint, const Vector2 &p_a_groove1, const Vector2 &p_a_groove2, const Vector2 &p_b_anchor, RID p_body_a, RID p_body_b) override;
virtual void joint_make_damped_spring(RID p_joint, const Vector2 &p_anchor_a, const Vector2 &p_anchor_b, RID p_body_a, RID p_body_b = RID()) override;
+ virtual void pin_joint_set_flag(RID p_joint, PinJointFlag p_flag, bool p_enabled) override;
+ virtual bool pin_joint_get_flag(RID p_joint, PinJointFlag p_flag) const override;
virtual void pin_joint_set_param(RID p_joint, PinJointParam p_param, real_t p_value) override;
virtual real_t pin_joint_get_param(RID p_joint, PinJointParam p_param) const override;
virtual void damped_spring_joint_set_param(RID p_joint, DampedSpringParam p_param, real_t p_value) override;
diff --git a/servers/physics_3d/godot_physics_server_3d.cpp b/servers/physics_3d/godot_physics_server_3d.cpp
index b6d8acfbf3b..1a71b9e07f9 100644
--- a/servers/physics_3d/godot_physics_server_3d.cpp
+++ b/servers/physics_3d/godot_physics_server_3d.cpp
@@ -1356,12 +1356,12 @@ real_t GodotPhysicsServer3D::hinge_joint_get_param(RID p_joint, HingeJointParam
return hinge_joint->get_param(p_param);
}
-void GodotPhysicsServer3D::hinge_joint_set_flag(RID p_joint, HingeJointFlag p_flag, bool p_value) {
+void GodotPhysicsServer3D::hinge_joint_set_flag(RID p_joint, HingeJointFlag p_flag, bool p_enabled) {
GodotJoint3D *joint = joint_owner.get_or_null(p_joint);
ERR_FAIL_COND(!joint);
ERR_FAIL_COND(joint->get_type() != JOINT_TYPE_HINGE);
GodotHingeJoint3D *hinge_joint = static_cast(joint);
- hinge_joint->set_flag(p_flag, p_value);
+ hinge_joint->set_flag(p_flag, p_enabled);
}
bool GodotPhysicsServer3D::hinge_joint_get_flag(RID p_joint, HingeJointFlag p_flag) const {
diff --git a/servers/physics_server_2d.cpp b/servers/physics_server_2d.cpp
index a5fa5291c04..aea0c52a630 100644
--- a/servers/physics_server_2d.cpp
+++ b/servers/physics_server_2d.cpp
@@ -776,6 +776,9 @@ void PhysicsServer2D::_bind_methods() {
ClassDB::bind_method(D_METHOD("joint_make_groove", "joint", "groove1_a", "groove2_a", "anchor_b", "body_a", "body_b"), &PhysicsServer2D::joint_make_groove, DEFVAL(RID()), DEFVAL(RID()));
ClassDB::bind_method(D_METHOD("joint_make_damped_spring", "joint", "anchor_a", "anchor_b", "body_a", "body_b"), &PhysicsServer2D::joint_make_damped_spring, DEFVAL(RID()));
+ ClassDB::bind_method(D_METHOD("pin_joint_set_flag", "joint", "flag", "enabled"), &PhysicsServer2D::pin_joint_set_flag);
+ ClassDB::bind_method(D_METHOD("pin_joint_get_flag", "joint", "flag"), &PhysicsServer2D::pin_joint_get_flag);
+
ClassDB::bind_method(D_METHOD("pin_joint_set_param", "joint", "param", "value"), &PhysicsServer2D::pin_joint_set_param);
ClassDB::bind_method(D_METHOD("pin_joint_get_param", "joint", "param"), &PhysicsServer2D::pin_joint_get_param);
@@ -863,6 +866,12 @@ void PhysicsServer2D::_bind_methods() {
BIND_ENUM_CONSTANT(JOINT_PARAM_MAX_FORCE);
BIND_ENUM_CONSTANT(PIN_JOINT_SOFTNESS);
+ BIND_ENUM_CONSTANT(PIN_JOINT_LIMIT_UPPER);
+ BIND_ENUM_CONSTANT(PIN_JOINT_LIMIT_LOWER);
+ BIND_ENUM_CONSTANT(PIN_JOINT_MOTOR_TARGET_VELOCITY);
+
+ BIND_ENUM_CONSTANT(PIN_JOINT_FLAG_ANGULAR_LIMIT_ENABLED);
+ BIND_ENUM_CONSTANT(PIN_JOINT_FLAG_MOTOR_ENABLED);
BIND_ENUM_CONSTANT(DAMPED_SPRING_REST_LENGTH);
BIND_ENUM_CONSTANT(DAMPED_SPRING_STIFFNESS);
diff --git a/servers/physics_server_2d.h b/servers/physics_server_2d.h
index f1f6e843215..67fc0ed899d 100644
--- a/servers/physics_server_2d.h
+++ b/servers/physics_server_2d.h
@@ -553,12 +553,23 @@ public:
virtual void joint_make_damped_spring(RID p_joint, const Vector2 &p_anchor_a, const Vector2 &p_anchor_b, RID p_body_a, RID p_body_b = RID()) = 0;
enum PinJointParam {
- PIN_JOINT_SOFTNESS
+ PIN_JOINT_SOFTNESS,
+ PIN_JOINT_LIMIT_UPPER,
+ PIN_JOINT_LIMIT_LOWER,
+ PIN_JOINT_MOTOR_TARGET_VELOCITY
};
virtual void pin_joint_set_param(RID p_joint, PinJointParam p_param, real_t p_value) = 0;
virtual real_t pin_joint_get_param(RID p_joint, PinJointParam p_param) const = 0;
+ enum PinJointFlag {
+ PIN_JOINT_FLAG_ANGULAR_LIMIT_ENABLED,
+ PIN_JOINT_FLAG_MOTOR_ENABLED
+ };
+
+ virtual void pin_joint_set_flag(RID p_joint, PinJointFlag p_flag, bool p_enabled) = 0;
+ virtual bool pin_joint_get_flag(RID p_joint, PinJointFlag p_flag) const = 0;
+
enum DampedSpringParam {
DAMPED_SPRING_REST_LENGTH,
DAMPED_SPRING_STIFFNESS,
@@ -830,6 +841,7 @@ VARIANT_ENUM_CAST(PhysicsServer2D::CCDMode);
VARIANT_ENUM_CAST(PhysicsServer2D::JointParam);
VARIANT_ENUM_CAST(PhysicsServer2D::JointType);
VARIANT_ENUM_CAST(PhysicsServer2D::PinJointParam);
+VARIANT_ENUM_CAST(PhysicsServer2D::PinJointFlag);
VARIANT_ENUM_CAST(PhysicsServer2D::DampedSpringParam);
VARIANT_ENUM_CAST(PhysicsServer2D::AreaBodyStatus);
VARIANT_ENUM_CAST(PhysicsServer2D::ProcessInfo);
diff --git a/servers/physics_server_2d_wrap_mt.h b/servers/physics_server_2d_wrap_mt.h
index cf7cc7f1361..0ae004da198 100644
--- a/servers/physics_server_2d_wrap_mt.h
+++ b/servers/physics_server_2d_wrap_mt.h
@@ -297,6 +297,9 @@ public:
FUNC3(pin_joint_set_param, RID, PinJointParam, real_t);
FUNC2RC(real_t, pin_joint_get_param, RID, PinJointParam);
+ FUNC3(pin_joint_set_flag, RID, PinJointFlag, bool);
+ FUNC2RC(bool, pin_joint_get_flag, RID, PinJointFlag);
+
FUNC3(damped_spring_joint_set_param, RID, DampedSpringParam, real_t);
FUNC2RC(real_t, damped_spring_joint_get_param, RID, DampedSpringParam);
diff --git a/servers/physics_server_3d.h b/servers/physics_server_3d.h
index 68dda8b84d5..d78a59e17f0 100644
--- a/servers/physics_server_3d.h
+++ b/servers/physics_server_3d.h
@@ -687,7 +687,7 @@ public:
virtual void hinge_joint_set_param(RID p_joint, HingeJointParam p_param, real_t p_value) = 0;
virtual real_t hinge_joint_get_param(RID p_joint, HingeJointParam p_param) const = 0;
- virtual void hinge_joint_set_flag(RID p_joint, HingeJointFlag p_flag, bool p_value) = 0;
+ virtual void hinge_joint_set_flag(RID p_joint, HingeJointFlag p_flag, bool p_enabled) = 0;
virtual bool hinge_joint_get_flag(RID p_joint, HingeJointFlag p_flag) const = 0;
enum SliderJointParam {