diff --git a/doc/base/classes.xml b/doc/base/classes.xml index 6aebbabea9f..24ea481f02e 100644 --- a/doc/base/classes.xml +++ b/doc/base/classes.xml @@ -24580,6 +24580,17 @@ This method controls whether the position between two cached points is interpola + + + + + + + + + Add a positioned force to the applied force and torque. As with [method body_apply_impulse], both the force and the offset from the body origin are in global coordinates. + + @@ -30041,7 +30052,14 @@ This method controls whether the position between two cached points is interpola - Return the body's moment of inertia. This is automatically computed from the mass and the shapes, so you can't set it. But at least you can find out what it's current value is... + Return the body's moment of inertia. This is usually automatically computed from the mass and the shapes. Note that this doesn't seem to work in a [code]_ready[/code] function: it apparently has not been auto-computed yet. + + + + + + + Set the body's moment of inertia. This is like mass, but for rotation: it determines how much torque it takes to rotate the body. The moment of inertia is usually computed automatically from the mass and the shapes, but this function allows you to set a custom value. Set 0 (or negative) inertia to return to automatically computing it. @@ -30221,12 +30239,12 @@ This method controls whether the position between two cached points is interpola - + - Apply a positioned impulse (which will be affected by the body mass and shape). This is the equivalent of hitting a billiard ball with a cue: a force that is applied once, and only once. + Apply a positioned impulse (which will be affected by the body mass and shape). This is the equivalent of hitting a billiard ball with a cue: a force that is applied once, and only once. Both the impulse and the offset from the body origin are in global coordinates. @@ -30257,6 +30275,15 @@ This method controls whether the position between two cached points is interpola Return the torque which is being applied to this body. + + + + + + + Add a positioned force to the applied force and torque. As with [method apply_impulse], both the force and the offset from the body origin are in global coordinates. + + diff --git a/scene/2d/physics_body_2d.cpp b/scene/2d/physics_body_2d.cpp index 517967bf6ce..8f0474b7658 100644 --- a/scene/2d/physics_body_2d.cpp +++ b/scene/2d/physics_body_2d.cpp @@ -602,6 +602,12 @@ real_t RigidBody2D::get_mass() const{ return mass; } +void RigidBody2D::set_inertia(real_t p_inertia) { + + ERR_FAIL_COND(p_inertia<=0); + Physics2DServer::get_singleton()->body_set_param(get_rid(),Physics2DServer::BODY_PARAM_INERTIA,p_inertia); +} + real_t RigidBody2D::get_inertia() const{ return Physics2DServer::get_singleton()->body_get_param(get_rid(),Physics2DServer::BODY_PARAM_INERTIA); @@ -797,6 +803,10 @@ float RigidBody2D::get_applied_torque() const { return Physics2DServer::get_singleton()->body_get_applied_torque(get_rid()); }; +void RigidBody2D::add_force(const Vector2& p_offset, const Vector2& p_force) { + + Physics2DServer::get_singleton()->body_add_force(get_rid(),p_offset,p_force); +} void RigidBody2D::set_continuous_collision_detection_mode(CCDMode p_mode) { @@ -874,6 +884,7 @@ void RigidBody2D::_bind_methods() { ObjectTypeDB::bind_method(_MD("get_mass"),&RigidBody2D::get_mass); ObjectTypeDB::bind_method(_MD("get_inertia"),&RigidBody2D::get_inertia); + ObjectTypeDB::bind_method(_MD("set_inertia","inertia"),&RigidBody2D::set_inertia); ObjectTypeDB::bind_method(_MD("set_weight","weight"),&RigidBody2D::set_weight); ObjectTypeDB::bind_method(_MD("get_weight"),&RigidBody2D::get_weight); @@ -912,7 +923,7 @@ void RigidBody2D::_bind_methods() { ObjectTypeDB::bind_method(_MD("get_continuous_collision_detection_mode"),&RigidBody2D::get_continuous_collision_detection_mode); ObjectTypeDB::bind_method(_MD("set_axis_velocity","axis_velocity"),&RigidBody2D::set_axis_velocity); - ObjectTypeDB::bind_method(_MD("apply_impulse","pos","impulse"),&RigidBody2D::apply_impulse); + ObjectTypeDB::bind_method(_MD("apply_impulse","offset","impulse"),&RigidBody2D::apply_impulse); ObjectTypeDB::bind_method(_MD("set_applied_force","force"),&RigidBody2D::set_applied_force); ObjectTypeDB::bind_method(_MD("get_applied_force"),&RigidBody2D::get_applied_force); @@ -920,6 +931,8 @@ void RigidBody2D::_bind_methods() { ObjectTypeDB::bind_method(_MD("set_applied_torque","torque"),&RigidBody2D::set_applied_torque); ObjectTypeDB::bind_method(_MD("get_applied_torque"),&RigidBody2D::get_applied_torque); + ObjectTypeDB::bind_method(_MD("add_force","offset","force"),&RigidBody2D::add_force); + ObjectTypeDB::bind_method(_MD("set_sleeping","sleeping"),&RigidBody2D::set_sleeping); ObjectTypeDB::bind_method(_MD("is_sleeping"),&RigidBody2D::is_sleeping); diff --git a/scene/2d/physics_body_2d.h b/scene/2d/physics_body_2d.h index 31dbfbcc6f6..5af65bff33c 100644 --- a/scene/2d/physics_body_2d.h +++ b/scene/2d/physics_body_2d.h @@ -217,7 +217,8 @@ public: void set_mass(real_t p_mass); real_t get_mass() const; - real_t get_inertia() const; // read-only: auto-computed from mass & shapes. + void set_inertia(real_t p_inertia); + real_t get_inertia() const; void set_weight(real_t p_weight); real_t get_weight() const; @@ -271,6 +272,8 @@ public: void set_applied_torque(const float p_torque); float get_applied_torque() const; + void add_force(const Vector2& p_offset, const Vector2& p_force); + Array get_colliding_bodies() const; //function for script diff --git a/servers/physics_2d/body_2d_sw.cpp b/servers/physics_2d/body_2d_sw.cpp index 97f08a6aa3e..12ac0bd1caa 100644 --- a/servers/physics_2d/body_2d_sw.cpp +++ b/servers/physics_2d/body_2d_sw.cpp @@ -33,7 +33,7 @@ void Body2DSW::_update_inertia() { - if (get_space() && !inertia_update_list.in_list()) + if (!user_inertia && get_space() && !inertia_update_list.in_list()) get_space()->body_add_to_inertia_update_list(&inertia_update_list); } @@ -48,6 +48,8 @@ void Body2DSW::update_inertias() { case Physics2DServer::BODY_MODE_RIGID: { + if(user_inertia) break; + //update tensor for allshapes, not the best way but should be somehow OK. (inspired from bullet) float total_area=0; @@ -157,6 +159,15 @@ void Body2DSW::set_param(Physics2DServer::BodyParameter p_param, float p_value) _update_inertia(); } break; + case Physics2DServer::BODY_PARAM_INERTIA: { + if(p_value<=0) { + user_inertia = false; + _update_inertia(); + } else { + user_inertia = true; + _inv_inertia = 1.0 / p_value; + } + } break; case Physics2DServer::BODY_PARAM_GRAVITY_SCALE: { gravity_scale=p_value; } break; @@ -187,8 +198,7 @@ float Body2DSW::get_param(Physics2DServer::BodyParameter p_param) const { return mass; } break; case Physics2DServer::BODY_PARAM_INERTIA: { - if(_inv_inertia == 0) return INFINITY; - else return 1.0 / _inv_inertia; + return _inv_inertia==0 ? 0 : 1.0 / _inv_inertia; } break; case Physics2DServer::BODY_PARAM_GRAVITY_SCALE: { return gravity_scale; @@ -669,6 +679,7 @@ Body2DSW::Body2DSW() : CollisionObject2DSW(TYPE_BODY), active_list(this), inerti angular_velocity=0; biased_angular_velocity=0; mass=1; + user_inertia=false; _inv_inertia=0; _inv_mass=1; bounce=0; diff --git a/servers/physics_2d/body_2d_sw.h b/servers/physics_2d/body_2d_sw.h index 6d9bf3cb03c..ed980176290 100644 --- a/servers/physics_2d/body_2d_sw.h +++ b/servers/physics_2d/body_2d_sw.h @@ -57,6 +57,7 @@ class Body2DSW : public CollisionObject2DSW { real_t _inv_mass; real_t _inv_inertia; + bool user_inertia; Vector2 gravity; real_t area_linear_damp; @@ -243,6 +244,11 @@ public: void set_applied_torque(real_t p_torque) { applied_torque=p_torque; } real_t get_applied_torque() const { return applied_torque; } + _FORCE_INLINE_ void add_force(const Vector2& p_force, const Vector2& p_offset) { + + applied_force += p_force; + applied_torque += p_offset.cross(p_force); + } _FORCE_INLINE_ void set_continuous_collision_detection_mode(Physics2DServer::CCDMode p_mode) { continuous_cd_mode=p_mode; } _FORCE_INLINE_ Physics2DServer::CCDMode get_continuous_collision_detection_mode() const { return continuous_cd_mode; } diff --git a/servers/physics_2d/physics_2d_server_sw.cpp b/servers/physics_2d/physics_2d_server_sw.cpp index c571331498d..3796ddd961e 100644 --- a/servers/physics_2d/physics_2d_server_sw.cpp +++ b/servers/physics_2d/physics_2d_server_sw.cpp @@ -860,6 +860,15 @@ void Physics2DServerSW::body_apply_impulse(RID p_body, const Vector2& p_pos, con body->wakeup(); }; +void Physics2DServerSW::body_add_force(RID p_body, const Vector2& p_offset, const Vector2& p_force) { + + Body2DSW *body = body_owner.get(p_body); + ERR_FAIL_COND(!body); + + body->add_force(p_force,p_offset); + body->wakeup(); +}; + void Physics2DServerSW::body_set_axis_velocity(RID p_body, const Vector2& p_axis_velocity) { Body2DSW *body = body_owner.get(p_body); diff --git a/servers/physics_2d/physics_2d_server_sw.h b/servers/physics_2d/physics_2d_server_sw.h index cd4dfc1a8b6..6415786803d 100644 --- a/servers/physics_2d/physics_2d_server_sw.h +++ b/servers/physics_2d/physics_2d_server_sw.h @@ -205,6 +205,8 @@ public: virtual void body_set_applied_torque(RID p_body, float p_torque); virtual float body_get_applied_torque(RID p_body) const; + virtual void body_add_force(RID p_body, const Vector2& p_offset, const Vector2& p_force); + virtual void body_apply_impulse(RID p_body, const Vector2& p_pos, const Vector2& p_impulse); virtual void body_set_axis_velocity(RID p_body, const Vector2& p_axis_velocity); diff --git a/servers/physics_2d/physics_2d_server_wrap_mt.h b/servers/physics_2d/physics_2d_server_wrap_mt.h index 60f8a4c879f..891c45addfb 100644 --- a/servers/physics_2d/physics_2d_server_wrap_mt.h +++ b/servers/physics_2d/physics_2d_server_wrap_mt.h @@ -205,6 +205,7 @@ public: FUNC2(body_set_applied_torque,RID,float); FUNC1RC(float,body_get_applied_torque,RID); + FUNC3(body_add_force,RID,const Vector2&,const Vector2&); FUNC3(body_apply_impulse,RID,const Vector2&,const Vector2&); FUNC2(body_set_axis_velocity,RID,const Vector2&); diff --git a/servers/physics_2d_server.cpp b/servers/physics_2d_server.cpp index 0ff5dba6ee7..a85fefe5ada 100644 --- a/servers/physics_2d_server.cpp +++ b/servers/physics_2d_server.cpp @@ -597,6 +597,7 @@ void Physics2DServer::_bind_methods() { ObjectTypeDB::bind_method(_MD("body_get_state","body","state"),&Physics2DServer::body_get_state); ObjectTypeDB::bind_method(_MD("body_apply_impulse","body","pos","impulse"),&Physics2DServer::body_apply_impulse); + ObjectTypeDB::bind_method(_MD("body_add_force","body","offset","force"),&Physics2DServer::body_add_force); ObjectTypeDB::bind_method(_MD("body_set_axis_velocity","body","axis_velocity"),&Physics2DServer::body_set_axis_velocity); ObjectTypeDB::bind_method(_MD("body_add_collision_exception","body","excepted_body"),&Physics2DServer::body_add_collision_exception); diff --git a/servers/physics_2d_server.h b/servers/physics_2d_server.h index 2d6c4fe3f8b..dd04f0f6b88 100644 --- a/servers/physics_2d_server.h +++ b/servers/physics_2d_server.h @@ -451,7 +451,9 @@ public: virtual void body_set_applied_torque(RID p_body, float p_torque)=0; virtual float body_get_applied_torque(RID p_body) const=0; - virtual void body_apply_impulse(RID p_body, const Vector2& p_pos, const Vector2& p_impulse)=0; + virtual void body_add_force(RID p_body, const Vector2& p_offset, const Vector2& p_force)=0; + + virtual void body_apply_impulse(RID p_body, const Vector2& p_offset, const Vector2& p_impulse)=0; virtual void body_set_axis_velocity(RID p_body, const Vector2& p_axis_velocity)=0; //fix