From ba0bd8116314836d5569c0d5748e06dd7ce2bce5 Mon Sep 17 00:00:00 2001 From: Chris Pezley Date: Mon, 10 Jul 2023 07:31:15 +0200 Subject: [PATCH 1/6] Add setting which determines whether or not to apply area transform when calculating gravity. --- doc/classes/Area3D.xml | 3 +++ doc/classes/PhysicsServer3D.xml | 25 ++++++++++++++----------- scene/3d/area_3d.cpp | 13 +++++++++++++ scene/3d/area_3d.h | 4 ++++ servers/physics_3d/godot_area_3d.cpp | 14 ++++++++++++-- servers/physics_3d/godot_area_3d.h | 4 ++++ servers/physics_server_3d.cpp | 1 + servers/physics_server_3d.h | 1 + 8 files changed, 52 insertions(+), 13 deletions(-) diff --git a/doc/classes/Area3D.xml b/doc/classes/Area3D.xml index 89b3f843af3f..8a2cc10e9de5 100644 --- a/doc/classes/Area3D.xml +++ b/doc/classes/Area3D.xml @@ -90,6 +90,9 @@ The distance at which the gravity strength is equal to [member gravity]. For example, on a planet 100 meters in radius with a surface gravity of 4.0 m/s², set the [member gravity] to 4.0 and the unit distance to 100.0. The gravity will have falloff according to the inverse square law, so in the example, at 200 meters from the center the gravity will be 1.0 m/s² (twice the distance, 1/4th the gravity), at 50 meters it will be 16.0 m/s² (half the distance, 4x the gravity), and so on. The above is true only when the unit distance is a positive number. When this is set to 0.0, the gravity will be constant regardless of distance. + + If [code]true[/code], gravity is transformed using the Area's transform. In other words, rotating the area with this setting active will also rotate the gravity vector. + Override mode for gravity calculations within this area. See [enum SpaceOverride] for possible values. diff --git a/doc/classes/PhysicsServer3D.xml b/doc/classes/PhysicsServer3D.xml index a21be3f66835..ef4c316972de 100644 --- a/doc/classes/PhysicsServer3D.xml +++ b/doc/classes/PhysicsServer3D.xml @@ -1327,38 +1327,41 @@ Constant to set/get gravity vector/center in an area. - + + Constant to set/get whether the area transform is applied to the gravity vector. + + Constant to set/get whether the gravity vector of an area is a direction, or a center point. - + Constant to set/get the distance at which the gravity strength is equal to the gravity controlled by [constant AREA_PARAM_GRAVITY]. For example, on a planet 100 meters in radius with a surface gravity of 4.0 m/s², set the gravity to 4.0 and the unit distance to 100.0. The gravity will have falloff according to the inverse square law, so in the example, at 200 meters from the center the gravity will be 1.0 m/s² (twice the distance, 1/4th the gravity), at 50 meters it will be 16.0 m/s² (half the distance, 4x the gravity), and so on. The above is true only when the unit distance is a positive number. When this is set to 0.0, the gravity will be constant regardless of distance. - + Constant to set/get linear damping override mode in an area. See [enum AreaSpaceOverrideMode] for possible values. - + Constant to set/get the linear damping factor of an area. - + Constant to set/get angular damping override mode in an area. See [enum AreaSpaceOverrideMode] for possible values. - + Constant to set/get the angular damping factor of an area. - + Constant to set/get the priority (order of processing) of an area. - + Constant to set/get the magnitude of area-specific wind force. - + Constant to set/get the 3D vector that specifies the origin from which an area-specific wind blows. - + Constant to set/get the 3D vector that specifies the direction in which an area-specific wind blows. - + Constant to set/get the exponential rate at which wind force decreases with distance from its origin. diff --git a/scene/3d/area_3d.cpp b/scene/3d/area_3d.cpp index 29d151b7263d..15993c01ed6b 100644 --- a/scene/3d/area_3d.cpp +++ b/scene/3d/area_3d.cpp @@ -51,6 +51,15 @@ bool Area3D::is_gravity_a_point() const { return gravity_is_point; } +void Area3D::set_gravity_apply_transform(bool p_enabled) { + gravity_apply_transform = p_enabled; + PhysicsServer3D::get_singleton()->area_set_param(get_rid(), PhysicsServer3D::AREA_PARAM_GRAVITY_APPLY_TRANSFORM, p_enabled); +} + +bool Area3D::is_gravity_apply_transform() const { + return gravity_apply_transform; +} + void Area3D::set_gravity_point_unit_distance(real_t p_scale) { gravity_point_unit_distance = p_scale; PhysicsServer3D::get_singleton()->area_set_param(get_rid(), PhysicsServer3D::AREA_PARAM_GRAVITY_POINT_UNIT_DISTANCE, p_scale); @@ -657,6 +666,9 @@ void Area3D::_bind_methods() { 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); + ClassDB::bind_method(D_METHOD("set_gravity_apply_transform", "enable"), &Area3D::set_gravity_apply_transform); + ClassDB::bind_method(D_METHOD("is_gravity_apply_transform"), &Area3D::is_gravity_apply_transform); + ClassDB::bind_method(D_METHOD("set_gravity_point_unit_distance", "distance_scale"), &Area3D::set_gravity_point_unit_distance); ClassDB::bind_method(D_METHOD("get_gravity_point_unit_distance"), &Area3D::get_gravity_point_unit_distance); @@ -743,6 +755,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::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::BOOL, "gravity_apply_transform", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_UPDATE_ALL_IF_MODIFIED), "set_gravity_apply_transform", "is_gravity_apply_transform"); 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"); diff --git a/scene/3d/area_3d.h b/scene/3d/area_3d.h index 454c8c296061..0992ff0f3cde 100644 --- a/scene/3d/area_3d.h +++ b/scene/3d/area_3d.h @@ -51,6 +51,7 @@ class Area3D : public CollisionObject3D { Vector3 gravity_vec; real_t gravity = 0.0; bool gravity_is_point = false; + bool gravity_apply_transform = true; real_t gravity_point_unit_distance = 0.0; SpaceOverride linear_damp_space_override = SPACE_OVERRIDE_DISABLED; @@ -155,6 +156,9 @@ class Area3D : public CollisionObject3D { void set_gravity_is_point(bool p_enabled); bool is_gravity_a_point() const; + void set_gravity_apply_transform(bool p_enabled); + bool is_gravity_apply_transform() const; + void set_gravity_point_unit_distance(real_t p_scale); real_t get_gravity_point_unit_distance() const; diff --git a/servers/physics_3d/godot_area_3d.cpp b/servers/physics_3d/godot_area_3d.cpp index 5bf16aa6884f..5e90263dba62 100644 --- a/servers/physics_3d/godot_area_3d.cpp +++ b/servers/physics_3d/godot_area_3d.cpp @@ -152,6 +152,9 @@ void GodotArea3D::set_param(PhysicsServer3D::AreaParameter p_param, const Varian case PhysicsServer3D::AREA_PARAM_GRAVITY_IS_POINT: gravity_is_point = p_value; break; + case PhysicsServer3D::AREA_PARAM_GRAVITY_APPLY_TRANSFORM: + gravity_apply_transform = p_value; + break; case PhysicsServer3D::AREA_PARAM_GRAVITY_POINT_UNIT_DISTANCE: gravity_point_unit_distance = p_value; break; @@ -197,6 +200,8 @@ Variant GodotArea3D::get_param(PhysicsServer3D::AreaParameter p_param) const { return gravity_vector; case PhysicsServer3D::AREA_PARAM_GRAVITY_IS_POINT: return gravity_is_point; + case PhysicsServer3D::AREA_PARAM_GRAVITY_APPLY_TRANSFORM: + return gravity_apply_transform; case PhysicsServer3D::AREA_PARAM_GRAVITY_POINT_UNIT_DISTANCE: return gravity_point_unit_distance; case PhysicsServer3D::AREA_PARAM_LINEAR_DAMP_OVERRIDE_MODE: @@ -327,9 +332,14 @@ void GodotArea3D::call_queries() { } void GodotArea3D::compute_gravity(const Vector3 &p_position, Vector3 &r_gravity) const { + Vector3 gravity_vector = get_gravity_vector(); + if (gravity_apply_transform) { + gravity_vector = get_transform().xform(gravity_vector); + } + 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; + Vector3 v = gravity_vector - p_position; if (gr_unit_dist > 0) { const real_t v_length_sq = v.length_squared(); if (v_length_sq > 0) { @@ -342,7 +352,7 @@ void GodotArea3D::compute_gravity(const Vector3 &p_position, Vector3 &r_gravity) r_gravity = v.normalized() * get_gravity(); } } else { - r_gravity = get_gravity_vector() * get_gravity(); + r_gravity = gravity_vector * get_gravity(); } } diff --git a/servers/physics_3d/godot_area_3d.h b/servers/physics_3d/godot_area_3d.h index f05d0f90197c..293f806bac4a 100644 --- a/servers/physics_3d/godot_area_3d.h +++ b/servers/physics_3d/godot_area_3d.h @@ -49,6 +49,7 @@ class GodotArea3D : public GodotCollisionObject3D { real_t gravity = 9.80665; Vector3 gravity_vector = Vector3(0, -1, 0); bool gravity_is_point = false; + bool gravity_apply_transform = true; real_t gravity_point_unit_distance = 0.0; real_t linear_damp = 0.1; real_t angular_damp = 0.1; @@ -133,6 +134,9 @@ class GodotArea3D : public GodotCollisionObject3D { _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_apply_transform(bool p_enable) { gravity_apply_transform = p_enable; } + _FORCE_INLINE_ bool is_gravity_apply_transform() const { return gravity_apply_transform; } + _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/servers/physics_server_3d.cpp b/servers/physics_server_3d.cpp index 6b8d3d1af684..cf57ade0d3cb 100644 --- a/servers/physics_server_3d.cpp +++ b/servers/physics_server_3d.cpp @@ -976,6 +976,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_APPLY_TRANSFORM); 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); diff --git a/servers/physics_server_3d.h b/servers/physics_server_3d.h index 33e9f8a7c9e7..48f382cf11c2 100644 --- a/servers/physics_server_3d.h +++ b/servers/physics_server_3d.h @@ -316,6 +316,7 @@ class PhysicsServer3D : public Object { AREA_PARAM_GRAVITY_OVERRIDE_MODE, AREA_PARAM_GRAVITY, AREA_PARAM_GRAVITY_VECTOR, + AREA_PARAM_GRAVITY_APPLY_TRANSFORM, AREA_PARAM_GRAVITY_IS_POINT, AREA_PARAM_GRAVITY_POINT_UNIT_DISTANCE, AREA_PARAM_LINEAR_DAMP_OVERRIDE_MODE, From 4fe566ca63a44cfbd243870745eaa1d16adad7bc Mon Sep 17 00:00:00 2001 From: Chris Pezley Date: Tue, 11 Jul 2023 07:21:43 +0200 Subject: [PATCH 2/6] Move declaration of new enum param to end of enum to avoid breaking compatibility. --- doc/classes/PhysicsServer3D.xml | 28 ++++++++++++++-------------- servers/physics_server_3d.h | 2 +- 2 files changed, 15 insertions(+), 15 deletions(-) diff --git a/doc/classes/PhysicsServer3D.xml b/doc/classes/PhysicsServer3D.xml index ef4c316972de..aac955a78b51 100644 --- a/doc/classes/PhysicsServer3D.xml +++ b/doc/classes/PhysicsServer3D.xml @@ -1327,43 +1327,43 @@ Constant to set/get gravity vector/center in an area. - - Constant to set/get whether the area transform is applied to the gravity vector. - - + Constant to set/get whether the gravity vector of an area is a direction, or a center point. - + Constant to set/get the distance at which the gravity strength is equal to the gravity controlled by [constant AREA_PARAM_GRAVITY]. For example, on a planet 100 meters in radius with a surface gravity of 4.0 m/s², set the gravity to 4.0 and the unit distance to 100.0. The gravity will have falloff according to the inverse square law, so in the example, at 200 meters from the center the gravity will be 1.0 m/s² (twice the distance, 1/4th the gravity), at 50 meters it will be 16.0 m/s² (half the distance, 4x the gravity), and so on. The above is true only when the unit distance is a positive number. When this is set to 0.0, the gravity will be constant regardless of distance. - + Constant to set/get linear damping override mode in an area. See [enum AreaSpaceOverrideMode] for possible values. - + Constant to set/get the linear damping factor of an area. - + Constant to set/get angular damping override mode in an area. See [enum AreaSpaceOverrideMode] for possible values. - + Constant to set/get the angular damping factor of an area. - + Constant to set/get the priority (order of processing) of an area. - + Constant to set/get the magnitude of area-specific wind force. - + Constant to set/get the 3D vector that specifies the origin from which an area-specific wind blows. - + Constant to set/get the 3D vector that specifies the direction in which an area-specific wind blows. - + Constant to set/get the exponential rate at which wind force decreases with distance from its origin. + + Constant to set/get whether the area transform is applied to the gravity vector. + This area does not affect gravity/damp. These are generally areas that exist only to detect collisions, and objects entering or exiting them. diff --git a/servers/physics_server_3d.h b/servers/physics_server_3d.h index 48f382cf11c2..4568f5bb619e 100644 --- a/servers/physics_server_3d.h +++ b/servers/physics_server_3d.h @@ -316,7 +316,6 @@ class PhysicsServer3D : public Object { AREA_PARAM_GRAVITY_OVERRIDE_MODE, AREA_PARAM_GRAVITY, AREA_PARAM_GRAVITY_VECTOR, - AREA_PARAM_GRAVITY_APPLY_TRANSFORM, AREA_PARAM_GRAVITY_IS_POINT, AREA_PARAM_GRAVITY_POINT_UNIT_DISTANCE, AREA_PARAM_LINEAR_DAMP_OVERRIDE_MODE, @@ -328,6 +327,7 @@ class PhysicsServer3D : public Object { AREA_PARAM_WIND_SOURCE, AREA_PARAM_WIND_DIRECTION, AREA_PARAM_WIND_ATTENUATION_FACTOR, + AREA_PARAM_GRAVITY_APPLY_TRANSFORM, }; virtual RID area_create() = 0; From 6475f5ab074111ef7d9a08dca8384732b91d426d Mon Sep 17 00:00:00 2001 From: Chris Pezley Date: Tue, 11 Jul 2023 07:46:51 +0200 Subject: [PATCH 3/6] Make gravity_apply_transform only available / used when gravity is *not* a point. Also change transform to only apply the basis, so that translation is not applied to the gravity vector. --- scene/3d/area_3d.cpp | 2 ++ servers/physics_3d/godot_area_3d.cpp | 11 ++++------- 2 files changed, 6 insertions(+), 7 deletions(-) diff --git a/scene/3d/area_3d.cpp b/scene/3d/area_3d.cpp index 15993c01ed6b..beae580aefb3 100644 --- a/scene/3d/area_3d.cpp +++ b/scene/3d/area_3d.cpp @@ -641,6 +641,8 @@ void Area3D::_validate_property(PropertyInfo &p_property) const { if (gravity_is_point) { if (p_property.name == "gravity_direction") { p_property.usage = PROPERTY_USAGE_NO_EDITOR; + } else if (p_property.name == "gravity_apply_transform") { + p_property.usage = PROPERTY_USAGE_NO_EDITOR; } } else { if (p_property.name.begins_with("gravity_point_")) { diff --git a/servers/physics_3d/godot_area_3d.cpp b/servers/physics_3d/godot_area_3d.cpp index 5e90263dba62..3f5942e6de4f 100644 --- a/servers/physics_3d/godot_area_3d.cpp +++ b/servers/physics_3d/godot_area_3d.cpp @@ -332,14 +332,9 @@ void GodotArea3D::call_queries() { } void GodotArea3D::compute_gravity(const Vector3 &p_position, Vector3 &r_gravity) const { - Vector3 gravity_vector = get_gravity_vector(); - if (gravity_apply_transform) { - gravity_vector = get_transform().xform(gravity_vector); - } - if (is_gravity_point()) { const real_t gr_unit_dist = get_gravity_point_unit_distance(); - Vector3 v = gravity_vector - p_position; + 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) { @@ -351,8 +346,10 @@ void GodotArea3D::compute_gravity(const Vector3 &p_position, Vector3 &r_gravity) } else { r_gravity = v.normalized() * get_gravity(); } + } else if (gravity_apply_transform) { + r_gravity = get_transform().get_basis().xform(get_gravity_vector()) * get_gravity(); } else { - r_gravity = gravity_vector * get_gravity(); + r_gravity = get_gravity_vector() * get_gravity(); } } From 5ead893079134ee55b19a3f79bf41631d09c512e Mon Sep 17 00:00:00 2001 From: Chris Pezley Date: Wed, 12 Jul 2023 07:05:46 +0200 Subject: [PATCH 4/6] Make gravity_apply_transform false by default. --- doc/classes/Area3D.xml | 2 +- scene/3d/area_3d.h | 2 +- servers/physics_3d/godot_area_3d.h | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/doc/classes/Area3D.xml b/doc/classes/Area3D.xml index 8a2cc10e9de5..59e7ccded917 100644 --- a/doc/classes/Area3D.xml +++ b/doc/classes/Area3D.xml @@ -90,7 +90,7 @@ The distance at which the gravity strength is equal to [member gravity]. For example, on a planet 100 meters in radius with a surface gravity of 4.0 m/s², set the [member gravity] to 4.0 and the unit distance to 100.0. The gravity will have falloff according to the inverse square law, so in the example, at 200 meters from the center the gravity will be 1.0 m/s² (twice the distance, 1/4th the gravity), at 50 meters it will be 16.0 m/s² (half the distance, 4x the gravity), and so on. The above is true only when the unit distance is a positive number. When this is set to 0.0, the gravity will be constant regardless of distance. - + If [code]true[/code], gravity is transformed using the Area's transform. In other words, rotating the area with this setting active will also rotate the gravity vector. diff --git a/scene/3d/area_3d.h b/scene/3d/area_3d.h index 0992ff0f3cde..776e7fb88ca5 100644 --- a/scene/3d/area_3d.h +++ b/scene/3d/area_3d.h @@ -51,7 +51,7 @@ class Area3D : public CollisionObject3D { Vector3 gravity_vec; real_t gravity = 0.0; bool gravity_is_point = false; - bool gravity_apply_transform = true; + bool gravity_apply_transform = false; real_t gravity_point_unit_distance = 0.0; SpaceOverride linear_damp_space_override = SPACE_OVERRIDE_DISABLED; diff --git a/servers/physics_3d/godot_area_3d.h b/servers/physics_3d/godot_area_3d.h index 293f806bac4a..63e1e3f707a5 100644 --- a/servers/physics_3d/godot_area_3d.h +++ b/servers/physics_3d/godot_area_3d.h @@ -49,7 +49,7 @@ class GodotArea3D : public GodotCollisionObject3D { real_t gravity = 9.80665; Vector3 gravity_vector = Vector3(0, -1, 0); bool gravity_is_point = false; - bool gravity_apply_transform = true; + bool gravity_apply_transform = false; real_t gravity_point_unit_distance = 0.0; real_t linear_damp = 0.1; real_t angular_damp = 0.1; From 04f7e9df279a51f53429057ed12a711bf2b96b13 Mon Sep 17 00:00:00 2001 From: Chris Pezley Date: Wed, 12 Jul 2023 07:12:13 +0200 Subject: [PATCH 5/6] Do not capitalize non-propper noun in the middle of a sentence. --- doc/classes/Area3D.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/classes/Area3D.xml b/doc/classes/Area3D.xml index 59e7ccded917..65286a21936d 100644 --- a/doc/classes/Area3D.xml +++ b/doc/classes/Area3D.xml @@ -91,7 +91,7 @@ The above is true only when the unit distance is a positive number. When this is set to 0.0, the gravity will be constant regardless of distance. - If [code]true[/code], gravity is transformed using the Area's transform. In other words, rotating the area with this setting active will also rotate the gravity vector. + If [code]true[/code], gravity is transformed using the area's transform. In other words, rotating the area with this setting active will also rotate the gravity vector. Override mode for gravity calculations within this area. See [enum SpaceOverride] for possible values. From ce49503c945ab2cd15fb1917b06cf1594a0343aa Mon Sep 17 00:00:00 2001 From: Chris Pezley Date: Wed, 12 Jul 2023 07:32:32 +0200 Subject: [PATCH 6/6] Implement the option for applying area transform to gravity for Area2D. --- doc/classes/Area2D.xml | 3 +++ doc/classes/PhysicsServer2D.xml | 3 +++ scene/2d/area_2d.cpp | 15 +++++++++++++++ scene/2d/area_2d.h | 4 ++++ servers/physics_2d/godot_area_2d.cpp | 7 +++++++ servers/physics_2d/godot_area_2d.h | 4 ++++ servers/physics_server_2d.cpp | 1 + servers/physics_server_2d.h | 3 ++- 8 files changed, 39 insertions(+), 1 deletion(-) diff --git a/doc/classes/Area2D.xml b/doc/classes/Area2D.xml index 6fa8e4ae9f43..a1a41d014192 100644 --- a/doc/classes/Area2D.xml +++ b/doc/classes/Area2D.xml @@ -90,6 +90,9 @@ The distance at which the gravity strength is equal to [member gravity]. For example, on a planet 100 pixels in radius with a surface gravity of 4.0 px/s², set the [member gravity] to 4.0 and the unit distance to 100.0. The gravity will have falloff according to the inverse square law, so in the example, at 200 pixels from the center the gravity will be 1.0 px/s² (twice the distance, 1/4th the gravity), at 50 pixels it will be 16.0 px/s² (half the distance, 4x the gravity), and so on. The above is true only when the unit distance is a positive number. When this is set to 0.0, the gravity will be constant regardless of distance. + + If [code]true[/code], gravity is transformed using the area's transform. In other words, rotating the area with this setting active will also rotate the gravity vector. + Override mode for gravity calculations within this area. See [enum SpaceOverride] for possible values. diff --git a/doc/classes/PhysicsServer2D.xml b/doc/classes/PhysicsServer2D.xml index 39d18a9e359a..39a8616b1a5f 100644 --- a/doc/classes/PhysicsServer2D.xml +++ b/doc/classes/PhysicsServer2D.xml @@ -1050,6 +1050,9 @@ Constant to set/get the priority (order of processing) of an area. The default value of this parameter is [code]0[/code]. + + Constant to set/get whether the area transform is applied to the gravity vector. + This area does not affect gravity/damp. These are generally areas that exist only to detect collisions, and objects entering or exiting them. diff --git a/scene/2d/area_2d.cpp b/scene/2d/area_2d.cpp index 2ea7a8d6aef5..55b3ac75d49d 100644 --- a/scene/2d/area_2d.cpp +++ b/scene/2d/area_2d.cpp @@ -51,6 +51,15 @@ bool Area2D::is_gravity_a_point() const { return gravity_is_point; } +void Area2D::set_gravity_apply_transform(bool p_enabled) { + gravity_apply_transform = p_enabled; + PhysicsServer2D::get_singleton()->area_set_param(get_rid(), PhysicsServer2D::AREA_PARAM_GRAVITY_APPLY_TRANSFORM, p_enabled); +} + +bool Area2D::is_gravity_apply_transform() const { + return gravity_apply_transform; +} + void Area2D::set_gravity_point_unit_distance(real_t p_scale) { gravity_point_unit_distance = p_scale; PhysicsServer2D::get_singleton()->area_set_param(get_rid(), PhysicsServer2D::AREA_PARAM_GRAVITY_POINT_UNIT_DISTANCE, p_scale); @@ -532,6 +541,8 @@ void Area2D::_validate_property(PropertyInfo &p_property) const { if (gravity_is_point) { if (p_property.name == "gravity_direction") { p_property.usage = PROPERTY_USAGE_NO_EDITOR; + } else if (p_property.name == "gravity_apply_transform") { + p_property.usage = PROPERTY_USAGE_NO_EDITOR; } } else { if (p_property.name.begins_with("gravity_point_")) { @@ -557,6 +568,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_apply_transform", "enable"), &Area2D::set_gravity_apply_transform); + ClassDB::bind_method(D_METHOD("is_gravity_apply_transform"), &Area2D::is_gravity_apply_transform); + 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); @@ -622,6 +636,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::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::BOOL, "gravity_apply_transform", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_UPDATE_ALL_IF_MODIFIED), "set_gravity_apply_transform", "is_gravity_apply_transform"); 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"); diff --git a/scene/2d/area_2d.h b/scene/2d/area_2d.h index 421c29f7589f..d9994820facf 100644 --- a/scene/2d/area_2d.h +++ b/scene/2d/area_2d.h @@ -51,6 +51,7 @@ class Area2D : public CollisionObject2D { Vector2 gravity_vec; real_t gravity = 0.0; bool gravity_is_point = false; + bool gravity_apply_transform = false; real_t gravity_point_unit_distance = 0.0; SpaceOverride linear_damp_space_override = SPACE_OVERRIDE_DISABLED; @@ -144,6 +145,9 @@ class Area2D : public CollisionObject2D { void set_gravity_is_point(bool p_enabled); bool is_gravity_a_point() const; + void set_gravity_apply_transform(bool p_enabled); + bool is_gravity_apply_transform() const; + void set_gravity_point_unit_distance(real_t p_scale); real_t get_gravity_point_unit_distance() const; diff --git a/servers/physics_2d/godot_area_2d.cpp b/servers/physics_2d/godot_area_2d.cpp index 4d2148aa07b4..c143140ca436 100644 --- a/servers/physics_2d/godot_area_2d.cpp +++ b/servers/physics_2d/godot_area_2d.cpp @@ -145,6 +145,9 @@ void GodotArea2D::set_param(PhysicsServer2D::AreaParameter p_param, const Varian case PhysicsServer2D::AREA_PARAM_GRAVITY_IS_POINT: gravity_is_point = p_value; break; + case PhysicsServer2D::AREA_PARAM_GRAVITY_APPLY_TRANSFORM: + gravity_apply_transform = p_value; + break; case PhysicsServer2D::AREA_PARAM_GRAVITY_POINT_UNIT_DISTANCE: gravity_point_unit_distance = p_value; break; @@ -176,6 +179,8 @@ Variant GodotArea2D::get_param(PhysicsServer2D::AreaParameter p_param) const { return gravity_vector; case PhysicsServer2D::AREA_PARAM_GRAVITY_IS_POINT: return gravity_is_point; + case PhysicsServer2D::AREA_PARAM_GRAVITY_APPLY_TRANSFORM: + return gravity_apply_transform; case PhysicsServer2D::AREA_PARAM_GRAVITY_POINT_UNIT_DISTANCE: return gravity_point_unit_distance; case PhysicsServer2D::AREA_PARAM_LINEAR_DAMP_OVERRIDE_MODE: @@ -312,6 +317,8 @@ void GodotArea2D::compute_gravity(const Vector2 &p_position, Vector2 &r_gravity) } else { r_gravity = v.normalized() * get_gravity(); } + } else if (gravity_apply_transform) { + r_gravity = get_transform().basis_xform(get_gravity_vector()) * get_gravity(); } else { r_gravity = get_gravity_vector() * get_gravity(); } diff --git a/servers/physics_2d/godot_area_2d.h b/servers/physics_2d/godot_area_2d.h index 234e4eb9a9d2..6732a565ee7f 100644 --- a/servers/physics_2d/godot_area_2d.h +++ b/servers/physics_2d/godot_area_2d.h @@ -48,6 +48,7 @@ class GodotArea2D : public GodotCollisionObject2D { real_t gravity = 9.80665; Vector2 gravity_vector = Vector2(0, -1); bool gravity_is_point = false; + bool gravity_apply_transform = false; real_t gravity_point_unit_distance = 0.0; real_t linear_damp = 0.1; real_t angular_damp = 1.0; @@ -124,6 +125,9 @@ class GodotArea2D : public GodotCollisionObject2D { _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_apply_transform(bool p_enable) { gravity_apply_transform = p_enable; } + _FORCE_INLINE_ bool is_gravity_apply_transform() const { return gravity_apply_transform; } + _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/servers/physics_server_2d.cpp b/servers/physics_server_2d.cpp index 79a8ebe3d1e1..ba254350214b 100644 --- a/servers/physics_server_2d.cpp +++ b/servers/physics_server_2d.cpp @@ -811,6 +811,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_APPLY_TRANSFORM); 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); diff --git a/servers/physics_server_2d.h b/servers/physics_server_2d.h index f1f6e843215d..630c6ff4165e 100644 --- a/servers/physics_server_2d.h +++ b/servers/physics_server_2d.h @@ -292,7 +292,8 @@ class PhysicsServer2D : public Object { AREA_PARAM_LINEAR_DAMP, AREA_PARAM_ANGULAR_DAMP_OVERRIDE_MODE, AREA_PARAM_ANGULAR_DAMP, - AREA_PARAM_PRIORITY + AREA_PARAM_PRIORITY, + AREA_PARAM_GRAVITY_APPLY_TRANSFORM }; virtual RID area_create() = 0;