From 8f605c7379a2a6104a03cd37283afa7b662af087 Mon Sep 17 00:00:00 2001 From: Aaron Franke Date: Sun, 24 Sep 2023 21:30:24 -0500 Subject: [PATCH 1/2] Replace Area gravity point bool with a gravity type enum --- doc/classes/Area2D.xml | 11 +++++- doc/classes/Area3D.xml | 11 +++++- doc/classes/PhysicsServer2D.xml | 11 +++++- doc/classes/PhysicsServer3D.xml | 11 +++++- modules/godot_physics_2d/godot_area_2d.cpp | 40 ++++++++++++---------- modules/godot_physics_2d/godot_area_2d.h | 9 +++-- modules/godot_physics_3d/godot_area_3d.cpp | 40 ++++++++++++---------- modules/godot_physics_3d/godot_area_3d.h | 9 +++-- scene/2d/physics/area_2d.cpp | 34 ++++++++++++++---- scene/2d/physics/area_2d.h | 11 +++++- scene/3d/physics/area_3d.cpp | 34 ++++++++++++++---- scene/3d/physics/area_3d.h | 11 +++++- servers/physics_server_2d.cpp | 4 +++ servers/physics_server_2d.h | 9 ++++- servers/physics_server_3d.cpp | 4 +++ servers/physics_server_3d.h | 9 ++++- 16 files changed, 194 insertions(+), 64 deletions(-) diff --git a/doc/classes/Area2D.xml b/doc/classes/Area2D.xml index 4ad5db2b6731..a5abd6fb2f7c 100644 --- a/doc/classes/Area2D.xml +++ b/doc/classes/Area2D.xml @@ -81,7 +81,7 @@ The area's gravity vector (not normalized). - + If [code]true[/code], gravity is calculated from a point (set via [member gravity_point_center]). See also [member gravity_space_override]. @@ -94,6 +94,9 @@ Override mode for gravity calculations within this area. See [enum SpaceOverride] for possible values. + + Determines what type of gravity is applied, if [member gravity_space_override] is not disabled. See [enum GravityType] for possible values. + The rate at which objects stop moving in this area. Represents the linear velocity lost per second. See [member ProjectSettings.physics/2d/default_linear_damp] for more details about damping. @@ -213,5 +216,11 @@ This area replaces any gravity/damping calculated so far (in [member priority] order), but keeps calculating the rest of the areas. + + Gravity that attracts in the direction specified by [member gravity_direction]. The strength of gravity is the same at all positions in the area. + + + Gravity that attracts towards a point specified by [member gravity_point_center]. The strength of gravity is based on the distance to the point and the [member gravity_point_unit_distance] property. + diff --git a/doc/classes/Area3D.xml b/doc/classes/Area3D.xml index 8eedd3cdf2a6..62dddbc29bc0 100644 --- a/doc/classes/Area3D.xml +++ b/doc/classes/Area3D.xml @@ -81,7 +81,7 @@ The area's gravity vector (not normalized). - + If [code]true[/code], gravity is calculated from a point (set via [member gravity_point_center]). See also [member gravity_space_override]. @@ -94,6 +94,9 @@ Override mode for gravity calculations within this area. See [enum SpaceOverride] for possible values. + + Determines what type of gravity is applied, if [member gravity_space_override] is not disabled. See [enum GravityType] for possible values. + The rate at which objects stop moving in this area. Represents the linear velocity lost per second. See [member ProjectSettings.physics/3d/default_linear_damp] for more details about damping. @@ -237,5 +240,11 @@ This area replaces any gravity/damping calculated so far (in [member priority] order), but keeps calculating the rest of the areas. + + Gravity that attracts in the direction specified by [member gravity_direction]. The strength of gravity is the same at all positions in the area. + + + Gravity that attracts towards a point specified by [member gravity_point_center]. The strength of gravity is based on the distance to the point and the [member gravity_point_unit_distance] property. + diff --git a/doc/classes/PhysicsServer2D.xml b/doc/classes/PhysicsServer2D.xml index bd960e3da517..521ad52ba50e 100644 --- a/doc/classes/PhysicsServer2D.xml +++ b/doc/classes/PhysicsServer2D.xml @@ -1060,7 +1060,10 @@ Constant to set/get gravity vector/center in an area. The default value of this parameter is [code]Vector2(0, -1)[/code]. - + + Constant to set/get the gravity type. See [enum AreaGravityType] for possible values. + + Constant to set/get whether the gravity vector of an area is a direction, or a center point. The default value of this parameter is [code]false[/code]. @@ -1097,6 +1100,12 @@ This area replaces any gravity/damp calculated so far, but keeps calculating the rest of the areas, down to the default one. + + Gravity that attracts in the direction specified by [constant AREA_PARAM_GRAVITY_VECTOR]. The strength of gravity is the same at all positions in the area. + + + Gravity that attracts towards a point specified by [constant AREA_PARAM_GRAVITY_VECTOR]. The strength of gravity is based on the distance to the point and the [constant AREA_PARAM_GRAVITY_POINT_UNIT_DISTANCE] parameter. + Constant for static bodies. In this mode, a body can be only moved by user code and doesn't collide with other bodies along its path when moved. diff --git a/doc/classes/PhysicsServer3D.xml b/doc/classes/PhysicsServer3D.xml index f87d6342c79d..512d86a336ca 100644 --- a/doc/classes/PhysicsServer3D.xml +++ b/doc/classes/PhysicsServer3D.xml @@ -1636,7 +1636,10 @@ Constant to set/get gravity vector/center in an area. - + + Constant to set/get the gravity type. See [enum AreaGravityType] for possible values. + + Constant to set/get whether the gravity vector of an area is a direction, or a center point. @@ -1685,6 +1688,12 @@ This area replaces any gravity/damp calculated so far, but keeps calculating the rest of the areas, down to the default one. + + Gravity that attracts in the direction specified by [constant AREA_PARAM_GRAVITY_VECTOR]. The strength of gravity is the same at all positions in the area. + + + Gravity that attracts towards a point specified by [constant AREA_PARAM_GRAVITY_VECTOR]. The strength of gravity is based on the distance to the point and the [constant AREA_PARAM_GRAVITY_POINT_UNIT_DISTANCE] parameter. + Constant for static bodies. In this mode, a body can be only moved by user code and doesn't collide with other bodies along its path when moved. diff --git a/modules/godot_physics_2d/godot_area_2d.cpp b/modules/godot_physics_2d/godot_area_2d.cpp index d6c786706c25..6f4daabb5d3e 100644 --- a/modules/godot_physics_2d/godot_area_2d.cpp +++ b/modules/godot_physics_2d/godot_area_2d.cpp @@ -128,8 +128,8 @@ void GodotArea2D::set_param(PhysicsServer2D::AreaParameter p_param, const Varian case PhysicsServer2D::AREA_PARAM_GRAVITY_VECTOR: gravity_vector = p_value; break; - case PhysicsServer2D::AREA_PARAM_GRAVITY_IS_POINT: - gravity_is_point = p_value; + case PhysicsServer2D::AREA_PARAM_GRAVITY_TYPE: + gravity_type = (PhysicsServer2D::AreaGravityType)(int)p_value; break; case PhysicsServer2D::AREA_PARAM_GRAVITY_POINT_UNIT_DISTANCE: gravity_point_unit_distance = p_value; @@ -160,8 +160,8 @@ Variant GodotArea2D::get_param(PhysicsServer2D::AreaParameter p_param) const { return gravity; case PhysicsServer2D::AREA_PARAM_GRAVITY_VECTOR: return gravity_vector; - case PhysicsServer2D::AREA_PARAM_GRAVITY_IS_POINT: - return gravity_is_point; + case PhysicsServer2D::AREA_PARAM_GRAVITY_TYPE: + return gravity_type; case PhysicsServer2D::AREA_PARAM_GRAVITY_POINT_UNIT_DISTANCE: return gravity_point_unit_distance; case PhysicsServer2D::AREA_PARAM_LINEAR_DAMP_OVERRIDE_MODE: @@ -284,22 +284,26 @@ void GodotArea2D::call_queries() { } void GodotArea2D::compute_gravity(const Vector2 &p_position, Vector2 &r_gravity) const { - if (is_gravity_point()) { - const real_t gr_unit_dist = get_gravity_point_unit_distance(); - Vector2 v = get_transform().xform(get_gravity_vector()) - p_position; - if (gr_unit_dist > 0) { - const real_t v_length_sq = v.length_squared(); - if (v_length_sq > 0) { - const real_t gravity_strength = get_gravity() * gr_unit_dist * gr_unit_dist / v_length_sq; - r_gravity = v.normalized() * gravity_strength; + switch (gravity_type) { + case PhysicsServer2D::AREA_GRAVITY_TYPE_DIRECTIONAL: { + r_gravity = get_gravity_vector() * get_gravity(); + } break; + case PhysicsServer2D::AREA_GRAVITY_TYPE_POINT: { + Vector2 target_position = get_gravity_vector(); + const real_t gr_unit_dist = get_gravity_point_unit_distance(); + Vector2 v = get_transform().xform(target_position) - p_position; + if (gr_unit_dist > 0) { + const real_t v_length_sq = v.length_squared(); + if (v_length_sq > 0) { + const real_t gravity_strength = get_gravity() * gr_unit_dist * gr_unit_dist / v_length_sq; + r_gravity = v.normalized() * gravity_strength; + } else { + r_gravity = Vector2(); + } } else { - r_gravity = Vector2(); + r_gravity = v.normalized() * get_gravity(); } - } else { - r_gravity = v.normalized() * get_gravity(); - } - } else { - r_gravity = get_gravity_vector() * get_gravity(); + } break; } } diff --git a/modules/godot_physics_2d/godot_area_2d.h b/modules/godot_physics_2d/godot_area_2d.h index e6c3b45d6c35..96a2d9115549 100644 --- a/modules/godot_physics_2d/godot_area_2d.h +++ b/modules/godot_physics_2d/godot_area_2d.h @@ -47,7 +47,7 @@ class GodotArea2D : public GodotCollisionObject2D { real_t gravity = 9.80665; Vector2 gravity_vector = Vector2(0, -1); - bool gravity_is_point = false; + PhysicsServer2D::AreaGravityType gravity_type = PhysicsServer2D::AREA_GRAVITY_TYPE_DIRECTIONAL; real_t gravity_point_unit_distance = 0.0; real_t linear_damp = 0.1; real_t angular_damp = 1.0; @@ -121,8 +121,11 @@ class GodotArea2D : public GodotCollisionObject2D { _FORCE_INLINE_ void set_gravity_vector(const Vector2 &p_gravity) { gravity_vector = p_gravity; } _FORCE_INLINE_ Vector2 get_gravity_vector() const { return gravity_vector; } - _FORCE_INLINE_ void set_gravity_as_point(bool p_enable) { gravity_is_point = p_enable; } - _FORCE_INLINE_ bool is_gravity_point() const { return gravity_is_point; } + _FORCE_INLINE_ void set_gravity_type(PhysicsServer2D::AreaGravityType p_gravity_type) { gravity_type = p_gravity_type; } + _FORCE_INLINE_ PhysicsServer2D::AreaGravityType get_gravity_type() const { return gravity_type; } + + _FORCE_INLINE_ void set_gravity_as_point(bool p_enable) { gravity_type = p_enable ? PhysicsServer2D::AREA_GRAVITY_TYPE_POINT : PhysicsServer2D::AREA_GRAVITY_TYPE_DIRECTIONAL; } + _FORCE_INLINE_ bool is_gravity_point() const { return gravity_type == PhysicsServer2D::AREA_GRAVITY_TYPE_POINT; } _FORCE_INLINE_ void set_gravity_point_unit_distance(real_t scale) { gravity_point_unit_distance = scale; } _FORCE_INLINE_ real_t get_gravity_point_unit_distance() const { return gravity_point_unit_distance; } diff --git a/modules/godot_physics_3d/godot_area_3d.cpp b/modules/godot_physics_3d/godot_area_3d.cpp index d0b287b05861..428bc836251a 100644 --- a/modules/godot_physics_3d/godot_area_3d.cpp +++ b/modules/godot_physics_3d/godot_area_3d.cpp @@ -137,8 +137,8 @@ void GodotArea3D::set_param(PhysicsServer3D::AreaParameter p_param, const Varian case PhysicsServer3D::AREA_PARAM_GRAVITY_VECTOR: gravity_vector = p_value; break; - case PhysicsServer3D::AREA_PARAM_GRAVITY_IS_POINT: - gravity_is_point = p_value; + case PhysicsServer3D::AREA_PARAM_GRAVITY_TYPE: + gravity_type = (PhysicsServer3D::AreaGravityType)(int)p_value; break; case PhysicsServer3D::AREA_PARAM_GRAVITY_POINT_UNIT_DISTANCE: gravity_point_unit_distance = p_value; @@ -183,8 +183,8 @@ Variant GodotArea3D::get_param(PhysicsServer3D::AreaParameter p_param) const { return gravity; case PhysicsServer3D::AREA_PARAM_GRAVITY_VECTOR: return gravity_vector; - case PhysicsServer3D::AREA_PARAM_GRAVITY_IS_POINT: - return gravity_is_point; + case PhysicsServer3D::AREA_PARAM_GRAVITY_TYPE: + return gravity_type; case PhysicsServer3D::AREA_PARAM_GRAVITY_POINT_UNIT_DISTANCE: return gravity_point_unit_distance; case PhysicsServer3D::AREA_PARAM_LINEAR_DAMP_OVERRIDE_MODE: @@ -315,22 +315,26 @@ void GodotArea3D::call_queries() { } void GodotArea3D::compute_gravity(const Vector3 &p_position, Vector3 &r_gravity) const { - if (is_gravity_point()) { - const real_t gr_unit_dist = get_gravity_point_unit_distance(); - Vector3 v = get_transform().xform(get_gravity_vector()) - p_position; - if (gr_unit_dist > 0) { - const real_t v_length_sq = v.length_squared(); - if (v_length_sq > 0) { - const real_t gravity_strength = get_gravity() * gr_unit_dist * gr_unit_dist / v_length_sq; - r_gravity = v.normalized() * gravity_strength; + switch (gravity_type) { + case PhysicsServer3D::AREA_GRAVITY_TYPE_DIRECTIONAL: { + r_gravity = get_gravity_vector() * get_gravity(); + } break; + case PhysicsServer3D::AREA_GRAVITY_TYPE_POINT: { + Vector3 target_position = get_gravity_vector(); + const real_t gr_unit_dist = get_gravity_point_unit_distance(); + Vector3 v = get_transform().xform(target_position) - p_position; + if (gr_unit_dist > 0) { + const real_t v_length_sq = v.length_squared(); + if (v_length_sq > 0) { + const real_t gravity_strength = get_gravity() * gr_unit_dist * gr_unit_dist / v_length_sq; + r_gravity = v.normalized() * gravity_strength; + } else { + r_gravity = Vector3(); + } } else { - r_gravity = Vector3(); + r_gravity = v.normalized() * get_gravity(); } - } else { - r_gravity = v.normalized() * get_gravity(); - } - } else { - r_gravity = get_gravity_vector() * get_gravity(); + } break; } } diff --git a/modules/godot_physics_3d/godot_area_3d.h b/modules/godot_physics_3d/godot_area_3d.h index 2c1a782630ed..0dd2e6d99662 100644 --- a/modules/godot_physics_3d/godot_area_3d.h +++ b/modules/godot_physics_3d/godot_area_3d.h @@ -48,7 +48,7 @@ class GodotArea3D : public GodotCollisionObject3D { real_t gravity = 9.80665; Vector3 gravity_vector = Vector3(0, -1, 0); - bool gravity_is_point = false; + PhysicsServer3D::AreaGravityType gravity_type = PhysicsServer3D::AREA_GRAVITY_TYPE_DIRECTIONAL; real_t gravity_point_unit_distance = 0.0; real_t linear_damp = 0.1; real_t angular_damp = 0.1; @@ -130,8 +130,11 @@ class GodotArea3D : public GodotCollisionObject3D { _FORCE_INLINE_ void set_gravity_vector(const Vector3 &p_gravity) { gravity_vector = p_gravity; } _FORCE_INLINE_ Vector3 get_gravity_vector() const { return gravity_vector; } - _FORCE_INLINE_ void set_gravity_as_point(bool p_enable) { gravity_is_point = p_enable; } - _FORCE_INLINE_ bool is_gravity_point() const { return gravity_is_point; } + _FORCE_INLINE_ void set_gravity_type(PhysicsServer3D::AreaGravityType p_gravity_type) { gravity_type = p_gravity_type; } + _FORCE_INLINE_ PhysicsServer3D::AreaGravityType get_gravity_type() const { return gravity_type; } + + _FORCE_INLINE_ void set_gravity_as_point(bool p_enable) { gravity_type = p_enable ? PhysicsServer3D::AREA_GRAVITY_TYPE_POINT : PhysicsServer3D::AREA_GRAVITY_TYPE_DIRECTIONAL; } + _FORCE_INLINE_ bool is_gravity_point() const { return gravity_type == PhysicsServer3D::AREA_GRAVITY_TYPE_POINT; } _FORCE_INLINE_ void set_gravity_point_unit_distance(real_t scale) { gravity_point_unit_distance = scale; } _FORCE_INLINE_ real_t get_gravity_point_unit_distance() const { return gravity_point_unit_distance; } diff --git a/scene/2d/physics/area_2d.cpp b/scene/2d/physics/area_2d.cpp index 305ac8248e1b..7ed62d826be2 100644 --- a/scene/2d/physics/area_2d.cpp +++ b/scene/2d/physics/area_2d.cpp @@ -41,13 +41,21 @@ Area2D::SpaceOverride Area2D::get_gravity_space_override_mode() const { return gravity_space_override; } +void Area2D::set_gravity_type(GravityType p_type) { + gravity_type = p_type; + PhysicsServer2D::get_singleton()->area_set_param(get_rid(), PhysicsServer2D::AREA_PARAM_GRAVITY_TYPE, p_type); +} + +Area2D::GravityType Area2D::get_gravity_type() const { + return gravity_type; +} + void Area2D::set_gravity_is_point(bool p_enabled) { - gravity_is_point = p_enabled; - PhysicsServer2D::get_singleton()->area_set_param(get_rid(), PhysicsServer2D::AREA_PARAM_GRAVITY_IS_POINT, p_enabled); + set_gravity_type(p_enabled ? GravityType::GRAVITY_TYPE_POINT : GravityType::GRAVITY_TYPE_DIRECTIONAL); } bool Area2D::is_gravity_a_point() const { - return gravity_is_point; + return gravity_type != GravityType::GRAVITY_TYPE_DIRECTIONAL; } void Area2D::set_gravity_point_unit_distance(real_t p_scale) { @@ -556,12 +564,17 @@ void Area2D::_validate_property(PropertyInfo &p_property) const { if (gravity_space_override == SPACE_OVERRIDE_DISABLED) { p_property.usage = PROPERTY_USAGE_NO_EDITOR; } else { - if (gravity_is_point) { - if (p_property.name == "gravity_direction") { + if (gravity_type == GRAVITY_TYPE_DIRECTIONAL) { + if (p_property.name == "gravity_point_unit_distance") { p_property.usage = PROPERTY_USAGE_NO_EDITOR; } } else { - if (p_property.name.begins_with("gravity_point_")) { + if (p_property.name == "gravity_direction") { + p_property.usage = PROPERTY_USAGE_NO_EDITOR; + } + } + if (gravity_type != GRAVITY_TYPE_POINT) { + if (p_property.name == "gravity_point_center") { p_property.usage = PROPERTY_USAGE_NO_EDITOR; } } @@ -584,6 +597,9 @@ void Area2D::_bind_methods() { ClassDB::bind_method(D_METHOD("set_gravity_is_point", "enable"), &Area2D::set_gravity_is_point); ClassDB::bind_method(D_METHOD("is_gravity_a_point"), &Area2D::is_gravity_a_point); + ClassDB::bind_method(D_METHOD("set_gravity_type", "enable"), &Area2D::set_gravity_type); + ClassDB::bind_method(D_METHOD("get_gravity_type"), &Area2D::get_gravity_type); + ClassDB::bind_method(D_METHOD("set_gravity_point_unit_distance", "distance_scale"), &Area2D::set_gravity_point_unit_distance); ClassDB::bind_method(D_METHOD("get_gravity_point_unit_distance"), &Area2D::get_gravity_point_unit_distance); @@ -648,7 +664,8 @@ void Area2D::_bind_methods() { ADD_GROUP("Gravity", "gravity_"); ADD_PROPERTY(PropertyInfo(Variant::INT, "gravity_space_override", PROPERTY_HINT_ENUM, "Disabled,Combine,Combine-Replace,Replace,Replace-Combine", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_UPDATE_ALL_IF_MODIFIED), "set_gravity_space_override_mode", "get_gravity_space_override_mode"); - ADD_PROPERTY(PropertyInfo(Variant::BOOL, "gravity_point", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_UPDATE_ALL_IF_MODIFIED), "set_gravity_is_point", "is_gravity_a_point"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "gravity_type", PROPERTY_HINT_ENUM, "Directional,Point", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_UPDATE_ALL_IF_MODIFIED), "set_gravity_type", "get_gravity_type"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "gravity_point", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NONE), "set_gravity_is_point", "is_gravity_a_point"); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "gravity_point_unit_distance", PROPERTY_HINT_RANGE, "0,1024,0.001,or_greater,exp,suffix:px"), "set_gravity_point_unit_distance", "get_gravity_point_unit_distance"); ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "gravity_point_center", PROPERTY_HINT_NONE, "suffix:px"), "set_gravity_point_center", "get_gravity_point_center"); ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "gravity_direction"), "set_gravity_direction", "get_gravity_direction"); @@ -671,6 +688,9 @@ void Area2D::_bind_methods() { BIND_ENUM_CONSTANT(SPACE_OVERRIDE_COMBINE_REPLACE); BIND_ENUM_CONSTANT(SPACE_OVERRIDE_REPLACE); BIND_ENUM_CONSTANT(SPACE_OVERRIDE_REPLACE_COMBINE); + + BIND_ENUM_CONSTANT(GRAVITY_TYPE_DIRECTIONAL); + BIND_ENUM_CONSTANT(GRAVITY_TYPE_POINT); } Area2D::Area2D() : diff --git a/scene/2d/physics/area_2d.h b/scene/2d/physics/area_2d.h index 7c59d76e00bb..8c3fb401715e 100644 --- a/scene/2d/physics/area_2d.h +++ b/scene/2d/physics/area_2d.h @@ -46,11 +46,16 @@ class Area2D : public CollisionObject2D { SPACE_OVERRIDE_REPLACE_COMBINE }; + enum GravityType { + GRAVITY_TYPE_DIRECTIONAL, + GRAVITY_TYPE_POINT, + }; + private: SpaceOverride gravity_space_override = SPACE_OVERRIDE_DISABLED; Vector2 gravity_vec; real_t gravity = 0.0; - bool gravity_is_point = false; + GravityType gravity_type = GRAVITY_TYPE_DIRECTIONAL; real_t gravity_point_unit_distance = 0.0; SpaceOverride linear_damp_space_override = SPACE_OVERRIDE_DISABLED; @@ -145,6 +150,9 @@ class Area2D : public CollisionObject2D { void set_gravity_is_point(bool p_enabled); bool is_gravity_a_point() const; + void set_gravity_type(GravityType p_type); + GravityType get_gravity_type() const; + void set_gravity_point_unit_distance(real_t p_scale); real_t get_gravity_point_unit_distance() const; @@ -198,5 +206,6 @@ class Area2D : public CollisionObject2D { }; VARIANT_ENUM_CAST(Area2D::SpaceOverride); +VARIANT_ENUM_CAST(Area2D::GravityType); #endif // AREA_2D_H diff --git a/scene/3d/physics/area_3d.cpp b/scene/3d/physics/area_3d.cpp index be95512beae7..cf4a3dfa47b9 100644 --- a/scene/3d/physics/area_3d.cpp +++ b/scene/3d/physics/area_3d.cpp @@ -41,13 +41,21 @@ Area3D::SpaceOverride Area3D::get_gravity_space_override_mode() const { return gravity_space_override; } +void Area3D::set_gravity_type(GravityType p_type) { + gravity_type = p_type; + PhysicsServer3D::get_singleton()->area_set_param(get_rid(), PhysicsServer3D::AREA_PARAM_GRAVITY_TYPE, p_type); +} + +Area3D::GravityType Area3D::get_gravity_type() const { + return gravity_type; +} + void Area3D::set_gravity_is_point(bool p_enabled) { - gravity_is_point = p_enabled; - PhysicsServer3D::get_singleton()->area_set_param(get_rid(), PhysicsServer3D::AREA_PARAM_GRAVITY_IS_POINT, p_enabled); + set_gravity_type(p_enabled ? GravityType::GRAVITY_TYPE_POINT : GravityType::GRAVITY_TYPE_DIRECTIONAL); } bool Area3D::is_gravity_a_point() const { - return gravity_is_point; + return gravity_type != GravityType::GRAVITY_TYPE_DIRECTIONAL; } void Area3D::set_gravity_point_unit_distance(real_t p_scale) { @@ -660,12 +668,17 @@ void Area3D::_validate_property(PropertyInfo &p_property) const { if (gravity_space_override == SPACE_OVERRIDE_DISABLED) { p_property.usage = PROPERTY_USAGE_NO_EDITOR; } else { - if (gravity_is_point) { - if (p_property.name == "gravity_direction") { + if (gravity_type == GRAVITY_TYPE_DIRECTIONAL) { + if (p_property.name == "gravity_point_unit_distance") { p_property.usage = PROPERTY_USAGE_NO_EDITOR; } } else { - if (p_property.name.begins_with("gravity_point_")) { + if (p_property.name == "gravity_direction") { + p_property.usage = PROPERTY_USAGE_NO_EDITOR; + } + } + if (gravity_type != GRAVITY_TYPE_POINT) { + if (p_property.name == "gravity_point_center") { p_property.usage = PROPERTY_USAGE_NO_EDITOR; } } @@ -685,6 +698,9 @@ void Area3D::_bind_methods() { ClassDB::bind_method(D_METHOD("set_gravity_space_override_mode", "space_override_mode"), &Area3D::set_gravity_space_override_mode); ClassDB::bind_method(D_METHOD("get_gravity_space_override_mode"), &Area3D::get_gravity_space_override_mode); + ClassDB::bind_method(D_METHOD("set_gravity_type", "enable"), &Area3D::set_gravity_type); + ClassDB::bind_method(D_METHOD("get_gravity_type"), &Area3D::get_gravity_type); + ClassDB::bind_method(D_METHOD("set_gravity_is_point", "enable"), &Area3D::set_gravity_is_point); ClassDB::bind_method(D_METHOD("is_gravity_a_point"), &Area3D::is_gravity_a_point); @@ -773,7 +789,8 @@ void Area3D::_bind_methods() { ADD_GROUP("Gravity", "gravity_"); ADD_PROPERTY(PropertyInfo(Variant::INT, "gravity_space_override", PROPERTY_HINT_ENUM, "Disabled,Combine,Combine-Replace,Replace,Replace-Combine", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_UPDATE_ALL_IF_MODIFIED), "set_gravity_space_override_mode", "get_gravity_space_override_mode"); - ADD_PROPERTY(PropertyInfo(Variant::BOOL, "gravity_point", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_UPDATE_ALL_IF_MODIFIED), "set_gravity_is_point", "is_gravity_a_point"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "gravity_type", PROPERTY_HINT_ENUM, "Directional,Point", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_UPDATE_ALL_IF_MODIFIED), "set_gravity_type", "get_gravity_type"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "gravity_point", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NONE), "set_gravity_is_point", "is_gravity_a_point"); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "gravity_point_unit_distance", PROPERTY_HINT_RANGE, "0,1024,0.001,or_greater,exp,suffix:m"), "set_gravity_point_unit_distance", "get_gravity_point_unit_distance"); ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "gravity_point_center", PROPERTY_HINT_NONE, "suffix:m"), "set_gravity_point_center", "get_gravity_point_center"); ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "gravity_direction"), "set_gravity_direction", "get_gravity_direction"); @@ -807,6 +824,9 @@ void Area3D::_bind_methods() { BIND_ENUM_CONSTANT(SPACE_OVERRIDE_COMBINE_REPLACE); BIND_ENUM_CONSTANT(SPACE_OVERRIDE_REPLACE); BIND_ENUM_CONSTANT(SPACE_OVERRIDE_REPLACE_COMBINE); + + BIND_ENUM_CONSTANT(GRAVITY_TYPE_DIRECTIONAL); + BIND_ENUM_CONSTANT(GRAVITY_TYPE_POINT); } Area3D::Area3D() : diff --git a/scene/3d/physics/area_3d.h b/scene/3d/physics/area_3d.h index 8848f9c23a0b..2c66d57d0487 100644 --- a/scene/3d/physics/area_3d.h +++ b/scene/3d/physics/area_3d.h @@ -46,11 +46,16 @@ class Area3D : public CollisionObject3D { SPACE_OVERRIDE_REPLACE_COMBINE }; + enum GravityType { + GRAVITY_TYPE_DIRECTIONAL, + GRAVITY_TYPE_POINT, + }; + private: SpaceOverride gravity_space_override = SPACE_OVERRIDE_DISABLED; Vector3 gravity_vec; real_t gravity = 0.0; - bool gravity_is_point = false; + GravityType gravity_type = GRAVITY_TYPE_DIRECTIONAL; real_t gravity_point_unit_distance = 0.0; SpaceOverride linear_damp_space_override = SPACE_OVERRIDE_DISABLED; @@ -154,6 +159,9 @@ class Area3D : public CollisionObject3D { void set_gravity_space_override_mode(SpaceOverride p_mode); SpaceOverride get_gravity_space_override_mode() const; + void set_gravity_type(GravityType p_type); + GravityType get_gravity_type() const; + void set_gravity_is_point(bool p_enabled); bool is_gravity_a_point() const; @@ -231,5 +239,6 @@ class Area3D : public CollisionObject3D { }; VARIANT_ENUM_CAST(Area3D::SpaceOverride); +VARIANT_ENUM_CAST(Area3D::GravityType); #endif // AREA_3D_H diff --git a/servers/physics_server_2d.cpp b/servers/physics_server_2d.cpp index f4f9a2e8b759..b111a10265c3 100644 --- a/servers/physics_server_2d.cpp +++ b/servers/physics_server_2d.cpp @@ -818,6 +818,7 @@ void PhysicsServer2D::_bind_methods() { BIND_ENUM_CONSTANT(AREA_PARAM_GRAVITY_OVERRIDE_MODE); BIND_ENUM_CONSTANT(AREA_PARAM_GRAVITY); BIND_ENUM_CONSTANT(AREA_PARAM_GRAVITY_VECTOR); + BIND_ENUM_CONSTANT(AREA_PARAM_GRAVITY_TYPE); BIND_ENUM_CONSTANT(AREA_PARAM_GRAVITY_IS_POINT); BIND_ENUM_CONSTANT(AREA_PARAM_GRAVITY_POINT_UNIT_DISTANCE); BIND_ENUM_CONSTANT(AREA_PARAM_LINEAR_DAMP_OVERRIDE_MODE); @@ -832,6 +833,9 @@ void PhysicsServer2D::_bind_methods() { BIND_ENUM_CONSTANT(AREA_SPACE_OVERRIDE_REPLACE); BIND_ENUM_CONSTANT(AREA_SPACE_OVERRIDE_REPLACE_COMBINE); + BIND_ENUM_CONSTANT(AREA_GRAVITY_TYPE_DIRECTIONAL); + BIND_ENUM_CONSTANT(AREA_GRAVITY_TYPE_POINT); + BIND_ENUM_CONSTANT(BODY_MODE_STATIC); BIND_ENUM_CONSTANT(BODY_MODE_KINEMATIC); BIND_ENUM_CONSTANT(BODY_MODE_RIGID); diff --git a/servers/physics_server_2d.h b/servers/physics_server_2d.h index 67fc0ed899d5..0367b91b4576 100644 --- a/servers/physics_server_2d.h +++ b/servers/physics_server_2d.h @@ -286,7 +286,8 @@ class PhysicsServer2D : public Object { AREA_PARAM_GRAVITY_OVERRIDE_MODE, AREA_PARAM_GRAVITY, AREA_PARAM_GRAVITY_VECTOR, - AREA_PARAM_GRAVITY_IS_POINT, + AREA_PARAM_GRAVITY_TYPE, + AREA_PARAM_GRAVITY_IS_POINT = AREA_PARAM_GRAVITY_TYPE, AREA_PARAM_GRAVITY_POINT_UNIT_DISTANCE, AREA_PARAM_LINEAR_DAMP_OVERRIDE_MODE, AREA_PARAM_LINEAR_DAMP, @@ -308,6 +309,11 @@ class PhysicsServer2D : public Object { AREA_SPACE_OVERRIDE_REPLACE_COMBINE // Discards all previous calculations, then keeps combining }; + enum AreaGravityType { + AREA_GRAVITY_TYPE_DIRECTIONAL, + AREA_GRAVITY_TYPE_POINT, + }; + virtual void area_add_shape(RID p_area, RID p_shape, const Transform2D &p_transform = Transform2D(), bool p_disabled = false) = 0; virtual void area_set_shape(RID p_area, int p_shape_idx, RID p_shape) = 0; virtual void area_set_shape_transform(RID p_area, int p_shape_idx, const Transform2D &p_transform) = 0; @@ -833,6 +839,7 @@ VARIANT_ENUM_CAST(PhysicsServer2D::ShapeType); VARIANT_ENUM_CAST(PhysicsServer2D::SpaceParameter); VARIANT_ENUM_CAST(PhysicsServer2D::AreaParameter); VARIANT_ENUM_CAST(PhysicsServer2D::AreaSpaceOverrideMode); +VARIANT_ENUM_CAST(PhysicsServer2D::AreaGravityType); VARIANT_ENUM_CAST(PhysicsServer2D::BodyMode); VARIANT_ENUM_CAST(PhysicsServer2D::BodyParameter); VARIANT_ENUM_CAST(PhysicsServer2D::BodyDampMode); diff --git a/servers/physics_server_3d.cpp b/servers/physics_server_3d.cpp index 312b67ada955..d44f39e44dcd 100644 --- a/servers/physics_server_3d.cpp +++ b/servers/physics_server_3d.cpp @@ -1051,6 +1051,7 @@ void PhysicsServer3D::_bind_methods() { BIND_ENUM_CONSTANT(AREA_PARAM_GRAVITY_OVERRIDE_MODE); BIND_ENUM_CONSTANT(AREA_PARAM_GRAVITY); BIND_ENUM_CONSTANT(AREA_PARAM_GRAVITY_VECTOR); + BIND_ENUM_CONSTANT(AREA_PARAM_GRAVITY_TYPE); BIND_ENUM_CONSTANT(AREA_PARAM_GRAVITY_IS_POINT); BIND_ENUM_CONSTANT(AREA_PARAM_GRAVITY_POINT_UNIT_DISTANCE); BIND_ENUM_CONSTANT(AREA_PARAM_LINEAR_DAMP_OVERRIDE_MODE); @@ -1069,6 +1070,9 @@ void PhysicsServer3D::_bind_methods() { BIND_ENUM_CONSTANT(AREA_SPACE_OVERRIDE_REPLACE); BIND_ENUM_CONSTANT(AREA_SPACE_OVERRIDE_REPLACE_COMBINE); + BIND_ENUM_CONSTANT(AREA_GRAVITY_TYPE_DIRECTIONAL); + BIND_ENUM_CONSTANT(AREA_GRAVITY_TYPE_POINT); + BIND_ENUM_CONSTANT(BODY_MODE_STATIC); BIND_ENUM_CONSTANT(BODY_MODE_KINEMATIC); BIND_ENUM_CONSTANT(BODY_MODE_RIGID); diff --git a/servers/physics_server_3d.h b/servers/physics_server_3d.h index 33def7cf8d44..d530280bda79 100644 --- a/servers/physics_server_3d.h +++ b/servers/physics_server_3d.h @@ -318,7 +318,8 @@ class PhysicsServer3D : public Object { AREA_PARAM_GRAVITY_OVERRIDE_MODE, AREA_PARAM_GRAVITY, AREA_PARAM_GRAVITY_VECTOR, - AREA_PARAM_GRAVITY_IS_POINT, + AREA_PARAM_GRAVITY_TYPE, + AREA_PARAM_GRAVITY_IS_POINT = AREA_PARAM_GRAVITY_TYPE, AREA_PARAM_GRAVITY_POINT_UNIT_DISTANCE, AREA_PARAM_LINEAR_DAMP_OVERRIDE_MODE, AREA_PARAM_LINEAR_DAMP, @@ -344,6 +345,11 @@ class PhysicsServer3D : public Object { AREA_SPACE_OVERRIDE_REPLACE_COMBINE }; + enum AreaGravityType { + AREA_GRAVITY_TYPE_DIRECTIONAL, + AREA_GRAVITY_TYPE_POINT, + }; + virtual void area_add_shape(RID p_area, RID p_shape, const Transform3D &p_transform = Transform3D(), bool p_disabled = false) = 0; virtual void area_set_shape(RID p_area, int p_shape_idx, RID p_shape) = 0; virtual void area_set_shape_transform(RID p_area, int p_shape_idx, const Transform3D &p_transform) = 0; @@ -1041,6 +1047,7 @@ VARIANT_ENUM_CAST(PhysicsServer3D::ShapeType); VARIANT_ENUM_CAST(PhysicsServer3D::SpaceParameter); VARIANT_ENUM_CAST(PhysicsServer3D::AreaParameter); VARIANT_ENUM_CAST(PhysicsServer3D::AreaSpaceOverrideMode); +VARIANT_ENUM_CAST(PhysicsServer3D::AreaGravityType); VARIANT_ENUM_CAST(PhysicsServer3D::BodyMode); VARIANT_ENUM_CAST(PhysicsServer3D::BodyParameter); VARIANT_ENUM_CAST(PhysicsServer3D::BodyDampMode); From 478e52203469009e61e982cdbd9195c0334cc379 Mon Sep 17 00:00:00 2001 From: Aaron Franke Date: Fri, 29 Dec 2023 00:23:06 -0600 Subject: [PATCH 2/2] Add a Target gravity type to Area for a custom target point --- doc/classes/Area2D.xml | 10 ++++++++ doc/classes/Area3D.xml | 10 ++++++++ doc/classes/PhysicsServer2D.xml | 3 +++ doc/classes/PhysicsServer3D.xml | 3 +++ modules/godot_physics_2d/godot_area_2d.cpp | 23 +++++++++++++++---- modules/godot_physics_2d/godot_area_2d.h | 5 +++- .../godot_physics_server_2d.cpp | 7 ++++++ .../godot_physics_server_2d.h | 1 + modules/godot_physics_3d/godot_area_3d.cpp | 23 +++++++++++++++---- modules/godot_physics_3d/godot_area_3d.h | 5 +++- .../godot_physics_server_3d.cpp | 7 ++++++ .../godot_physics_server_3d.h | 1 + scene/2d/physics/area_2d.cpp | 16 ++++++++++++- scene/2d/physics/area_2d.h | 4 ++++ scene/3d/physics/area_3d.cpp | 16 ++++++++++++- scene/3d/physics/area_3d.h | 4 ++++ .../extensions/physics_server_2d_extension.h | 1 + .../extensions/physics_server_3d_extension.h | 1 + servers/physics_server_2d.cpp | 1 + servers/physics_server_2d.h | 2 ++ servers/physics_server_2d_wrap_mt.h | 1 + servers/physics_server_3d.cpp | 1 + servers/physics_server_3d.h | 2 ++ servers/physics_server_3d_wrap_mt.h | 1 + 24 files changed, 136 insertions(+), 12 deletions(-) diff --git a/doc/classes/Area2D.xml b/doc/classes/Area2D.xml index a5abd6fb2f7c..4b407136a0c4 100644 --- a/doc/classes/Area2D.xml +++ b/doc/classes/Area2D.xml @@ -15,6 +15,13 @@ https://godotengine.org/asset-library/asset/2727 + + + + + Callback method for calculating a custom target point for gravity. This is only used when the [member gravity_type] property is set to [constant GRAVITY_TYPE_TARGET]. + + @@ -222,5 +229,8 @@ Gravity that attracts towards a point specified by [member gravity_point_center]. The strength of gravity is based on the distance to the point and the [member gravity_point_unit_distance] property. + + Gravity that attracts towards a point defined by the output of the [method _calculate_gravity_target] callback method. + diff --git a/doc/classes/Area3D.xml b/doc/classes/Area3D.xml index 62dddbc29bc0..b0f943359044 100644 --- a/doc/classes/Area3D.xml +++ b/doc/classes/Area3D.xml @@ -15,6 +15,13 @@ https://godotengine.org/asset-library/asset/2807 + + + + + Callback method for calculating a custom target point for gravity. This is only used when the [member gravity_type] property is set to [constant GRAVITY_TYPE_TARGET]. + + @@ -246,5 +253,8 @@ Gravity that attracts towards a point specified by [member gravity_point_center]. The strength of gravity is based on the distance to the point and the [member gravity_point_unit_distance] property. + + Gravity that attracts towards a point defined by the output of the [method _calculate_gravity_target] callback method. + diff --git a/doc/classes/PhysicsServer2D.xml b/doc/classes/PhysicsServer2D.xml index 521ad52ba50e..96741cc5a2d1 100644 --- a/doc/classes/PhysicsServer2D.xml +++ b/doc/classes/PhysicsServer2D.xml @@ -1106,6 +1106,9 @@ Gravity that attracts towards a point specified by [constant AREA_PARAM_GRAVITY_VECTOR]. The strength of gravity is based on the distance to the point and the [constant AREA_PARAM_GRAVITY_POINT_UNIT_DISTANCE] parameter. + + Gravity that attracts towards a target point defined by the output of the calculate gravity target callback method. + Constant for static bodies. In this mode, a body can be only moved by user code and doesn't collide with other bodies along its path when moved. diff --git a/doc/classes/PhysicsServer3D.xml b/doc/classes/PhysicsServer3D.xml index 512d86a336ca..89a384b64bf8 100644 --- a/doc/classes/PhysicsServer3D.xml +++ b/doc/classes/PhysicsServer3D.xml @@ -1694,6 +1694,9 @@ Gravity that attracts towards a point specified by [constant AREA_PARAM_GRAVITY_VECTOR]. The strength of gravity is based on the distance to the point and the [constant AREA_PARAM_GRAVITY_POINT_UNIT_DISTANCE] parameter. + + Gravity that attracts towards a target point defined by the output of the calculate gravity target callback method. + Constant for static bodies. In this mode, a body can be only moved by user code and doesn't collide with other bodies along its path when moved. diff --git a/modules/godot_physics_2d/godot_area_2d.cpp b/modules/godot_physics_2d/godot_area_2d.cpp index 6f4daabb5d3e..cbc93620b7c1 100644 --- a/modules/godot_physics_2d/godot_area_2d.cpp +++ b/modules/godot_physics_2d/godot_area_2d.cpp @@ -107,6 +107,10 @@ void GodotArea2D::set_area_monitor_callback(const Callable &p_callback) { } } +void GodotArea2D::set_gravity_target_callback(const Callable &p_callback) { + gravity_target_callback = p_callback; +} + void GodotArea2D::_set_space_override_mode(PhysicsServer2D::AreaSpaceOverrideMode &r_mode, PhysicsServer2D::AreaSpaceOverrideMode p_new_mode) { bool do_override = p_new_mode != PhysicsServer2D::AREA_SPACE_OVERRIDE_DISABLED; if (do_override == (r_mode != PhysicsServer2D::AREA_SPACE_OVERRIDE_DISABLED)) { @@ -283,15 +287,26 @@ void GodotArea2D::call_queries() { } } -void GodotArea2D::compute_gravity(const Vector2 &p_position, Vector2 &r_gravity) const { +void GodotArea2D::compute_gravity(const Vector2 &p_global_position, Vector2 &r_gravity) const { switch (gravity_type) { case PhysicsServer2D::AREA_GRAVITY_TYPE_DIRECTIONAL: { r_gravity = get_gravity_vector() * get_gravity(); } break; - case PhysicsServer2D::AREA_GRAVITY_TYPE_POINT: { - Vector2 target_position = get_gravity_vector(); + case PhysicsServer2D::AREA_GRAVITY_TYPE_POINT: + case PhysicsServer2D::AREA_GRAVITY_TYPE_TARGET: { + Vector2 target_local_position; + if (gravity_type == PhysicsServer2D::AREA_GRAVITY_TYPE_POINT) { + target_local_position = get_gravity_vector(); + } else { + const Variant local_position_variant = get_inv_transform().xform(p_global_position); + const Variant *args[1] = { &local_position_variant }; + Variant ret; + Callable::CallError ce; + gravity_target_callback.callp(args, 1, ret, ce); + target_local_position = ret; + } const real_t gr_unit_dist = get_gravity_point_unit_distance(); - Vector2 v = get_transform().xform(target_position) - p_position; + Vector2 v = get_transform().xform(target_local_position) - p_global_position; if (gr_unit_dist > 0) { const real_t v_length_sq = v.length_squared(); if (v_length_sq > 0) { diff --git a/modules/godot_physics_2d/godot_area_2d.h b/modules/godot_physics_2d/godot_area_2d.h index 96a2d9115549..a52d6263c891 100644 --- a/modules/godot_physics_2d/godot_area_2d.h +++ b/modules/godot_physics_2d/godot_area_2d.h @@ -57,6 +57,7 @@ class GodotArea2D : public GodotCollisionObject2D { Callable monitor_callback; Callable area_monitor_callback; + Callable gravity_target_callback; SelfList monitor_query_list; SelfList moved_list; @@ -106,6 +107,8 @@ class GodotArea2D : public GodotCollisionObject2D { void set_area_monitor_callback(const Callable &p_callback); _FORCE_INLINE_ bool has_area_monitor_callback() const { return area_monitor_callback.is_valid(); } + void set_gravity_target_callback(const Callable &p_callback); + _FORCE_INLINE_ void add_body_to_query(GodotBody2D *p_body, uint32_t p_body_shape, uint32_t p_area_shape); _FORCE_INLINE_ void remove_body_from_query(GodotBody2D *p_body, uint32_t p_body_shape, uint32_t p_area_shape); @@ -153,7 +156,7 @@ class GodotArea2D : public GodotCollisionObject2D { void call_queries(); - void compute_gravity(const Vector2 &p_position, Vector2 &r_gravity) const; + void compute_gravity(const Vector2 &p_global_position, Vector2 &r_gravity) const; GodotArea2D(); ~GodotArea2D(); diff --git a/modules/godot_physics_2d/godot_physics_server_2d.cpp b/modules/godot_physics_2d/godot_physics_server_2d.cpp index 8df17992ea4e..22929cc1fded 100644 --- a/modules/godot_physics_2d/godot_physics_server_2d.cpp +++ b/modules/godot_physics_2d/godot_physics_server_2d.cpp @@ -527,6 +527,13 @@ void GodotPhysicsServer2D::area_set_area_monitor_callback(RID p_area, const Call area->set_area_monitor_callback(p_callback.is_valid() ? p_callback : Callable()); } +void GodotPhysicsServer2D::area_set_gravity_target_callback(RID p_area, const Callable &p_callback) { + GodotArea2D *area = area_owner.get_or_null(p_area); + ERR_FAIL_NULL(area); + + area->set_gravity_target_callback(p_callback.is_valid() ? p_callback : Callable()); +} + /* BODY API */ RID GodotPhysicsServer2D::body_create() { diff --git a/modules/godot_physics_2d/godot_physics_server_2d.h b/modules/godot_physics_2d/godot_physics_server_2d.h index 991cf67c951f..d7ed98a761fd 100644 --- a/modules/godot_physics_2d/godot_physics_server_2d.h +++ b/modules/godot_physics_2d/godot_physics_server_2d.h @@ -160,6 +160,7 @@ class GodotPhysicsServer2D : public PhysicsServer2D { virtual void area_set_monitor_callback(RID p_area, const Callable &p_callback) override; virtual void area_set_area_monitor_callback(RID p_area, const Callable &p_callback) override; + virtual void area_set_gravity_target_callback(RID p_area, const Callable &p_callback) override; virtual void area_set_pickable(RID p_area, bool p_pickable) override; diff --git a/modules/godot_physics_3d/godot_area_3d.cpp b/modules/godot_physics_3d/godot_area_3d.cpp index 428bc836251a..a8b71c0bd581 100644 --- a/modules/godot_physics_3d/godot_area_3d.cpp +++ b/modules/godot_physics_3d/godot_area_3d.cpp @@ -116,6 +116,10 @@ void GodotArea3D::set_area_monitor_callback(const Callable &p_callback) { } } +void GodotArea3D::set_gravity_target_callback(const Callable &p_callback) { + gravity_target_callback = p_callback; +} + void GodotArea3D::_set_space_override_mode(PhysicsServer3D::AreaSpaceOverrideMode &r_mode, PhysicsServer3D::AreaSpaceOverrideMode p_new_mode) { bool do_override = p_new_mode != PhysicsServer3D::AREA_SPACE_OVERRIDE_DISABLED; if (do_override == (r_mode != PhysicsServer3D::AREA_SPACE_OVERRIDE_DISABLED)) { @@ -314,15 +318,26 @@ void GodotArea3D::call_queries() { } } -void GodotArea3D::compute_gravity(const Vector3 &p_position, Vector3 &r_gravity) const { +void GodotArea3D::compute_gravity(const Vector3 &p_global_position, Vector3 &r_gravity) const { switch (gravity_type) { case PhysicsServer3D::AREA_GRAVITY_TYPE_DIRECTIONAL: { r_gravity = get_gravity_vector() * get_gravity(); } break; - case PhysicsServer3D::AREA_GRAVITY_TYPE_POINT: { - Vector3 target_position = get_gravity_vector(); + case PhysicsServer3D::AREA_GRAVITY_TYPE_POINT: + case PhysicsServer3D::AREA_GRAVITY_TYPE_TARGET: { + Vector3 target_local_position; + if (gravity_type == PhysicsServer3D::AREA_GRAVITY_TYPE_POINT) { + target_local_position = get_gravity_vector(); + } else { + const Variant local_position_variant = get_inv_transform().xform(p_global_position); + const Variant *args[1] = { &local_position_variant }; + Variant ret; + Callable::CallError ce; + gravity_target_callback.callp(args, 1, ret, ce); + target_local_position = ret; + } const real_t gr_unit_dist = get_gravity_point_unit_distance(); - Vector3 v = get_transform().xform(target_position) - p_position; + Vector3 v = get_transform().xform(target_local_position) - p_global_position; if (gr_unit_dist > 0) { const real_t v_length_sq = v.length_squared(); if (v_length_sq > 0) { diff --git a/modules/godot_physics_3d/godot_area_3d.h b/modules/godot_physics_3d/godot_area_3d.h index 0dd2e6d99662..a0f2819ff66a 100644 --- a/modules/godot_physics_3d/godot_area_3d.h +++ b/modules/godot_physics_3d/godot_area_3d.h @@ -61,6 +61,7 @@ class GodotArea3D : public GodotCollisionObject3D { Callable monitor_callback; Callable area_monitor_callback; + Callable gravity_target_callback; SelfList monitor_query_list; SelfList moved_list; @@ -112,6 +113,8 @@ class GodotArea3D : public GodotCollisionObject3D { void set_area_monitor_callback(const Callable &p_callback); _FORCE_INLINE_ bool has_area_monitor_callback() const { return area_monitor_callback.is_valid(); } + void set_gravity_target_callback(const Callable &p_callback); + _FORCE_INLINE_ void add_body_to_query(GodotBody3D *p_body, uint32_t p_body_shape, uint32_t p_area_shape); _FORCE_INLINE_ void remove_body_from_query(GodotBody3D *p_body, uint32_t p_body_shape, uint32_t p_area_shape); @@ -174,7 +177,7 @@ class GodotArea3D : public GodotCollisionObject3D { void call_queries(); - void compute_gravity(const Vector3 &p_position, Vector3 &r_gravity) const; + void compute_gravity(const Vector3 &p_global_position, Vector3 &r_gravity) const; GodotArea3D(); ~GodotArea3D(); diff --git a/modules/godot_physics_3d/godot_physics_server_3d.cpp b/modules/godot_physics_3d/godot_physics_server_3d.cpp index 6d0949acbeb8..dd7c24a1912a 100644 --- a/modules/godot_physics_3d/godot_physics_server_3d.cpp +++ b/modules/godot_physics_3d/godot_physics_server_3d.cpp @@ -437,6 +437,13 @@ void GodotPhysicsServer3D::area_set_area_monitor_callback(RID p_area, const Call area->set_area_monitor_callback(p_callback.is_valid() ? p_callback : Callable()); } +void GodotPhysicsServer3D::area_set_gravity_target_callback(RID p_area, const Callable &p_callback) { + GodotArea3D *area = area_owner.get_or_null(p_area); + ERR_FAIL_NULL(area); + + area->set_gravity_target_callback(p_callback.is_valid() ? p_callback : Callable()); +} + /* BODY API */ RID GodotPhysicsServer3D::body_create() { diff --git a/modules/godot_physics_3d/godot_physics_server_3d.h b/modules/godot_physics_3d/godot_physics_server_3d.h index 040e673dcd82..b805b26f5420 100644 --- a/modules/godot_physics_3d/godot_physics_server_3d.h +++ b/modules/godot_physics_3d/godot_physics_server_3d.h @@ -158,6 +158,7 @@ class GodotPhysicsServer3D : public PhysicsServer3D { virtual void area_set_monitor_callback(RID p_area, const Callable &p_callback) override; virtual void area_set_area_monitor_callback(RID p_area, const Callable &p_callback) override; + virtual void area_set_gravity_target_callback(RID p_area, const Callable &p_callback) override; /* BODY API */ diff --git a/scene/2d/physics/area_2d.cpp b/scene/2d/physics/area_2d.cpp index 7ed62d826be2..ebfbf3c27d32 100644 --- a/scene/2d/physics/area_2d.cpp +++ b/scene/2d/physics/area_2d.cpp @@ -44,6 +44,11 @@ Area2D::SpaceOverride Area2D::get_gravity_space_override_mode() const { void Area2D::set_gravity_type(GravityType p_type) { gravity_type = p_type; PhysicsServer2D::get_singleton()->area_set_param(get_rid(), PhysicsServer2D::AREA_PARAM_GRAVITY_TYPE, p_type); + if (gravity_type == GRAVITY_TYPE_TARGET) { + PhysicsServer2D::get_singleton()->area_set_gravity_target_callback(get_rid(), callable_mp(this, &Area2D::calculate_gravity_target)); + } else { + PhysicsServer2D::get_singleton()->area_set_gravity_target_callback(get_rid(), Callable()); + } } Area2D::GravityType Area2D::get_gravity_type() const { @@ -548,6 +553,12 @@ StringName Area2D::get_audio_bus_name() const { return SceneStringName(Master); } +Vector2 Area2D::calculate_gravity_target(const Vector2 &p_local_position) { + Vector2 ret; + GDVIRTUAL_CALL(_calculate_gravity_target, p_local_position, ret); + return ret; +} + void Area2D::_validate_property(PropertyInfo &p_property) const { if (p_property.name == "audio_bus_name") { String options; @@ -648,6 +659,8 @@ void Area2D::_bind_methods() { ClassDB::bind_method(D_METHOD("set_audio_bus_override", "enable"), &Area2D::set_audio_bus_override); ClassDB::bind_method(D_METHOD("is_overriding_audio_bus"), &Area2D::is_overriding_audio_bus); + GDVIRTUAL_BIND(_calculate_gravity_target, "local_position"); + ADD_SIGNAL(MethodInfo("body_shape_entered", PropertyInfo(Variant::RID, "body_rid"), PropertyInfo(Variant::OBJECT, "body", PROPERTY_HINT_RESOURCE_TYPE, "Node2D"), PropertyInfo(Variant::INT, "body_shape_index"), PropertyInfo(Variant::INT, "local_shape_index"))); ADD_SIGNAL(MethodInfo("body_shape_exited", PropertyInfo(Variant::RID, "body_rid"), PropertyInfo(Variant::OBJECT, "body", PROPERTY_HINT_RESOURCE_TYPE, "Node2D"), PropertyInfo(Variant::INT, "body_shape_index"), PropertyInfo(Variant::INT, "local_shape_index"))); ADD_SIGNAL(MethodInfo("body_entered", PropertyInfo(Variant::OBJECT, "body", PROPERTY_HINT_RESOURCE_TYPE, "Node2D"))); @@ -664,7 +677,7 @@ void Area2D::_bind_methods() { ADD_GROUP("Gravity", "gravity_"); ADD_PROPERTY(PropertyInfo(Variant::INT, "gravity_space_override", PROPERTY_HINT_ENUM, "Disabled,Combine,Combine-Replace,Replace,Replace-Combine", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_UPDATE_ALL_IF_MODIFIED), "set_gravity_space_override_mode", "get_gravity_space_override_mode"); - ADD_PROPERTY(PropertyInfo(Variant::INT, "gravity_type", PROPERTY_HINT_ENUM, "Directional,Point", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_UPDATE_ALL_IF_MODIFIED), "set_gravity_type", "get_gravity_type"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "gravity_type", PROPERTY_HINT_ENUM, "Directional,Point,Target", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_UPDATE_ALL_IF_MODIFIED), "set_gravity_type", "get_gravity_type"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "gravity_point", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NONE), "set_gravity_is_point", "is_gravity_a_point"); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "gravity_point_unit_distance", PROPERTY_HINT_RANGE, "0,1024,0.001,or_greater,exp,suffix:px"), "set_gravity_point_unit_distance", "get_gravity_point_unit_distance"); ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "gravity_point_center", PROPERTY_HINT_NONE, "suffix:px"), "set_gravity_point_center", "get_gravity_point_center"); @@ -691,6 +704,7 @@ void Area2D::_bind_methods() { BIND_ENUM_CONSTANT(GRAVITY_TYPE_DIRECTIONAL); BIND_ENUM_CONSTANT(GRAVITY_TYPE_POINT); + BIND_ENUM_CONSTANT(GRAVITY_TYPE_TARGET); } Area2D::Area2D() : diff --git a/scene/2d/physics/area_2d.h b/scene/2d/physics/area_2d.h index 8c3fb401715e..70b28bcd32bf 100644 --- a/scene/2d/physics/area_2d.h +++ b/scene/2d/physics/area_2d.h @@ -49,6 +49,7 @@ class Area2D : public CollisionObject2D { enum GravityType { GRAVITY_TYPE_DIRECTIONAL, GRAVITY_TYPE_POINT, + GRAVITY_TYPE_TARGET, }; private: @@ -201,6 +202,9 @@ class Area2D : public CollisionObject2D { void set_audio_bus_name(const StringName &p_audio_bus); StringName get_audio_bus_name() const; + virtual Vector2 calculate_gravity_target(const Vector2 &p_local_position); + GDVIRTUAL1R(Vector2, _calculate_gravity_target, Vector2); + Area2D(); ~Area2D(); }; diff --git a/scene/3d/physics/area_3d.cpp b/scene/3d/physics/area_3d.cpp index cf4a3dfa47b9..367fd47e501e 100644 --- a/scene/3d/physics/area_3d.cpp +++ b/scene/3d/physics/area_3d.cpp @@ -44,6 +44,11 @@ Area3D::SpaceOverride Area3D::get_gravity_space_override_mode() const { void Area3D::set_gravity_type(GravityType p_type) { gravity_type = p_type; PhysicsServer3D::get_singleton()->area_set_param(get_rid(), PhysicsServer3D::AREA_PARAM_GRAVITY_TYPE, p_type); + if (gravity_type == GRAVITY_TYPE_TARGET) { + PhysicsServer3D::get_singleton()->area_set_gravity_target_callback(get_rid(), callable_mp(this, &Area3D::calculate_gravity_target)); + } else { + PhysicsServer3D::get_singleton()->area_set_gravity_target_callback(get_rid(), Callable()); + } } Area3D::GravityType Area3D::get_gravity_type() const { @@ -652,6 +657,12 @@ float Area3D::get_reverb_uniformity() const { return reverb_uniformity; } +Vector3 Area3D::calculate_gravity_target(const Vector3 &p_local_position) { + Vector3 ret; + GDVIRTUAL_CALL(_calculate_gravity_target, p_local_position, ret); + return ret; +} + void Area3D::_validate_property(PropertyInfo &p_property) const { if (p_property.name == "audio_bus_name" || p_property.name == "reverb_bus_name") { String options; @@ -773,6 +784,8 @@ void Area3D::_bind_methods() { ClassDB::bind_method(D_METHOD("set_reverb_uniformity", "amount"), &Area3D::set_reverb_uniformity); ClassDB::bind_method(D_METHOD("get_reverb_uniformity"), &Area3D::get_reverb_uniformity); + GDVIRTUAL_BIND(_calculate_gravity_target, "local_position"); + ADD_SIGNAL(MethodInfo("body_shape_entered", PropertyInfo(Variant::RID, "body_rid"), PropertyInfo(Variant::OBJECT, "body", PROPERTY_HINT_RESOURCE_TYPE, "Node3D"), PropertyInfo(Variant::INT, "body_shape_index"), PropertyInfo(Variant::INT, "local_shape_index"))); ADD_SIGNAL(MethodInfo("body_shape_exited", PropertyInfo(Variant::RID, "body_rid"), PropertyInfo(Variant::OBJECT, "body", PROPERTY_HINT_RESOURCE_TYPE, "Node3D"), PropertyInfo(Variant::INT, "body_shape_index"), PropertyInfo(Variant::INT, "local_shape_index"))); ADD_SIGNAL(MethodInfo("body_entered", PropertyInfo(Variant::OBJECT, "body", PROPERTY_HINT_RESOURCE_TYPE, "Node3D"))); @@ -789,7 +802,7 @@ void Area3D::_bind_methods() { ADD_GROUP("Gravity", "gravity_"); ADD_PROPERTY(PropertyInfo(Variant::INT, "gravity_space_override", PROPERTY_HINT_ENUM, "Disabled,Combine,Combine-Replace,Replace,Replace-Combine", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_UPDATE_ALL_IF_MODIFIED), "set_gravity_space_override_mode", "get_gravity_space_override_mode"); - ADD_PROPERTY(PropertyInfo(Variant::INT, "gravity_type", PROPERTY_HINT_ENUM, "Directional,Point", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_UPDATE_ALL_IF_MODIFIED), "set_gravity_type", "get_gravity_type"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "gravity_type", PROPERTY_HINT_ENUM, "Directional,Point,Target", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_UPDATE_ALL_IF_MODIFIED), "set_gravity_type", "get_gravity_type"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "gravity_point", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NONE), "set_gravity_is_point", "is_gravity_a_point"); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "gravity_point_unit_distance", PROPERTY_HINT_RANGE, "0,1024,0.001,or_greater,exp,suffix:m"), "set_gravity_point_unit_distance", "get_gravity_point_unit_distance"); ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "gravity_point_center", PROPERTY_HINT_NONE, "suffix:m"), "set_gravity_point_center", "get_gravity_point_center"); @@ -827,6 +840,7 @@ void Area3D::_bind_methods() { BIND_ENUM_CONSTANT(GRAVITY_TYPE_DIRECTIONAL); BIND_ENUM_CONSTANT(GRAVITY_TYPE_POINT); + BIND_ENUM_CONSTANT(GRAVITY_TYPE_TARGET); } Area3D::Area3D() : diff --git a/scene/3d/physics/area_3d.h b/scene/3d/physics/area_3d.h index 2c66d57d0487..254a0bfeaef1 100644 --- a/scene/3d/physics/area_3d.h +++ b/scene/3d/physics/area_3d.h @@ -49,6 +49,7 @@ class Area3D : public CollisionObject3D { enum GravityType { GRAVITY_TYPE_DIRECTIONAL, GRAVITY_TYPE_POINT, + GRAVITY_TYPE_TARGET, }; private: @@ -234,6 +235,9 @@ class Area3D : public CollisionObject3D { void set_reverb_uniformity(float p_uniformity); float get_reverb_uniformity() const; + virtual Vector3 calculate_gravity_target(const Vector3 &p_local_position); + GDVIRTUAL1R(Vector3, _calculate_gravity_target, Vector3); + Area3D(); ~Area3D(); }; diff --git a/servers/extensions/physics_server_2d_extension.h b/servers/extensions/physics_server_2d_extension.h index 7bbd84ddf4ff..f994786c983a 100644 --- a/servers/extensions/physics_server_2d_extension.h +++ b/servers/extensions/physics_server_2d_extension.h @@ -280,6 +280,7 @@ class PhysicsServer2DExtension : public PhysicsServer2D { EXBIND2(area_set_monitor_callback, RID, const Callable &) EXBIND2(area_set_area_monitor_callback, RID, const Callable &) + EXBIND2(area_set_gravity_target_callback, RID, const Callable &) /* BODY API */ diff --git a/servers/extensions/physics_server_3d_extension.h b/servers/extensions/physics_server_3d_extension.h index b808b80b938b..9d933be7052d 100644 --- a/servers/extensions/physics_server_3d_extension.h +++ b/servers/extensions/physics_server_3d_extension.h @@ -283,6 +283,7 @@ class PhysicsServer3DExtension : public PhysicsServer3D { EXBIND2(area_set_monitor_callback, RID, const Callable &) EXBIND2(area_set_area_monitor_callback, RID, const Callable &) + EXBIND2(area_set_gravity_target_callback, RID, const Callable &) /* BODY API */ diff --git a/servers/physics_server_2d.cpp b/servers/physics_server_2d.cpp index b111a10265c3..7d2bc650281b 100644 --- a/servers/physics_server_2d.cpp +++ b/servers/physics_server_2d.cpp @@ -835,6 +835,7 @@ void PhysicsServer2D::_bind_methods() { BIND_ENUM_CONSTANT(AREA_GRAVITY_TYPE_DIRECTIONAL); BIND_ENUM_CONSTANT(AREA_GRAVITY_TYPE_POINT); + BIND_ENUM_CONSTANT(AREA_GRAVITY_TYPE_TARGET); BIND_ENUM_CONSTANT(BODY_MODE_STATIC); BIND_ENUM_CONSTANT(BODY_MODE_KINEMATIC); diff --git a/servers/physics_server_2d.h b/servers/physics_server_2d.h index 0367b91b4576..2b04c857d5bd 100644 --- a/servers/physics_server_2d.h +++ b/servers/physics_server_2d.h @@ -312,6 +312,7 @@ class PhysicsServer2D : public Object { enum AreaGravityType { AREA_GRAVITY_TYPE_DIRECTIONAL, AREA_GRAVITY_TYPE_POINT, + AREA_GRAVITY_TYPE_TARGET, }; virtual void area_add_shape(RID p_area, RID p_shape, const Transform2D &p_transform = Transform2D(), bool p_disabled = false) = 0; @@ -350,6 +351,7 @@ class PhysicsServer2D : public Object { virtual void area_set_monitor_callback(RID p_area, const Callable &p_callback) = 0; virtual void area_set_area_monitor_callback(RID p_area, const Callable &p_callback) = 0; + virtual void area_set_gravity_target_callback(RID p_area, const Callable &p_callback) = 0; /* BODY API */ diff --git a/servers/physics_server_2d_wrap_mt.h b/servers/physics_server_2d_wrap_mt.h index 5c757264b3b7..58819423fc0c 100644 --- a/servers/physics_server_2d_wrap_mt.h +++ b/servers/physics_server_2d_wrap_mt.h @@ -165,6 +165,7 @@ class PhysicsServer2DWrapMT : public PhysicsServer2D { FUNC2(area_set_monitor_callback, RID, const Callable &); FUNC2(area_set_area_monitor_callback, RID, const Callable &); + FUNC2(area_set_gravity_target_callback, RID, const Callable &); /* BODY API */ diff --git a/servers/physics_server_3d.cpp b/servers/physics_server_3d.cpp index d44f39e44dcd..a33eeed78b5b 100644 --- a/servers/physics_server_3d.cpp +++ b/servers/physics_server_3d.cpp @@ -1072,6 +1072,7 @@ void PhysicsServer3D::_bind_methods() { BIND_ENUM_CONSTANT(AREA_GRAVITY_TYPE_DIRECTIONAL); BIND_ENUM_CONSTANT(AREA_GRAVITY_TYPE_POINT); + BIND_ENUM_CONSTANT(AREA_GRAVITY_TYPE_TARGET); BIND_ENUM_CONSTANT(BODY_MODE_STATIC); BIND_ENUM_CONSTANT(BODY_MODE_KINEMATIC); diff --git a/servers/physics_server_3d.h b/servers/physics_server_3d.h index d530280bda79..b03678c3b08e 100644 --- a/servers/physics_server_3d.h +++ b/servers/physics_server_3d.h @@ -348,6 +348,7 @@ class PhysicsServer3D : public Object { enum AreaGravityType { AREA_GRAVITY_TYPE_DIRECTIONAL, AREA_GRAVITY_TYPE_POINT, + AREA_GRAVITY_TYPE_TARGET, }; virtual void area_add_shape(RID p_area, RID p_shape, const Transform3D &p_transform = Transform3D(), bool p_disabled = false) = 0; @@ -382,6 +383,7 @@ class PhysicsServer3D : public Object { virtual void area_set_monitor_callback(RID p_area, const Callable &p_callback) = 0; virtual void area_set_area_monitor_callback(RID p_area, const Callable &p_callback) = 0; + virtual void area_set_gravity_target_callback(RID p_area, const Callable &p_callback) = 0; virtual void area_set_ray_pickable(RID p_area, bool p_enable) = 0; diff --git a/servers/physics_server_3d_wrap_mt.h b/servers/physics_server_3d_wrap_mt.h index 2fd39546a59e..3197abc01cf0 100644 --- a/servers/physics_server_3d_wrap_mt.h +++ b/servers/physics_server_3d_wrap_mt.h @@ -167,6 +167,7 @@ class PhysicsServer3DWrapMT : public PhysicsServer3D { FUNC2(area_set_monitor_callback, RID, const Callable &); FUNC2(area_set_area_monitor_callback, RID, const Callable &); + FUNC2(area_set_gravity_target_callback, RID, const Callable &); /* BODY API */