diff --git a/COPYRIGHT.txt b/COPYRIGHT.txt index ce9be3dd5e2a..e79817a2e76f 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 39d18a9e359a..ae25af1dd93c 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 e2f86cae5daa..8d9a17133733 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 6adfc818e7a4..a252f603122a 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 62b44655c1ea..41b121a482a6 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 581a3b6757ba..5ff75a77a122 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 96f09a8b1cc0..f8e78d655f49 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 6ddbb98766dd..6e0277a7c681 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 c7cdd271ca06..567ae01c4918 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 7a75781c8792..c6a1fdb69218 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 30600e0e573f..5e01abd555ce 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 e9b8d9a90a40..991cf67c951f 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 b6d8acfbf3b0..1a71b9e07f94 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 a5fa5291c04e..aea0c52a630f 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 f1f6e843215d..67fc0ed899d5 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 cf7cc7f13619..0ae004da198e 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 68dda8b84d5d..d78a59e17f0a 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 {