Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add a setting to control applying area transform to gravity #79268

Open
wants to merge 6 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions doc/classes/Area2D.xml
Original file line number Diff line number Diff line change
Expand Up @@ -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.
</member>
<member name="gravity_apply_transform" type="bool" setter="set_gravity_apply_transform" getter="is_gravity_apply_transform" default="false">
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.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This implies that only rotation will apply, I think a more general wording is better

</member>
<member name="gravity_space_override" type="int" setter="set_gravity_space_override_mode" getter="get_gravity_space_override_mode" enum="Area2D.SpaceOverride" default="0">
Override mode for gravity calculations within this area. See [enum SpaceOverride] for possible values.
</member>
Expand Down
3 changes: 3 additions & 0 deletions doc/classes/Area3D.xml
Original file line number Diff line number Diff line change
Expand Up @@ -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.
</member>
<member name="gravity_apply_transform" type="bool" setter="set_gravity_apply_transform" getter="is_gravity_apply_transform" default="false">
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.
</member>
<member name="gravity_space_override" type="int" setter="set_gravity_space_override_mode" getter="get_gravity_space_override_mode" enum="Area3D.SpaceOverride" default="0">
Override mode for gravity calculations within this area. See [enum SpaceOverride] for possible values.
</member>
Expand Down
3 changes: 3 additions & 0 deletions doc/classes/PhysicsServer2D.xml
Original file line number Diff line number Diff line change
Expand Up @@ -1050,6 +1050,9 @@
<constant name="AREA_PARAM_PRIORITY" value="9" enum="AreaParameter">
Constant to set/get the priority (order of processing) of an area. The default value of this parameter is [code]0[/code].
</constant>
<constant name="AREA_PARAM_GRAVITY_APPLY_TRANSFORM" value="10" enum="AreaParameter">
Constant to set/get whether the area transform is applied to the gravity vector.
</constant>
<constant name="AREA_SPACE_OVERRIDE_DISABLED" value="0" enum="AreaSpaceOverrideMode">
This area does not affect gravity/damp. These are generally areas that exist only to detect collisions, and objects entering or exiting them.
</constant>
Expand Down
3 changes: 3 additions & 0 deletions doc/classes/PhysicsServer3D.xml
Original file line number Diff line number Diff line change
Expand Up @@ -1361,6 +1361,9 @@
<constant name="AREA_PARAM_WIND_ATTENUATION_FACTOR" value="13" enum="AreaParameter">
Constant to set/get the exponential rate at which wind force decreases with distance from its origin.
</constant>
<constant name="AREA_PARAM_GRAVITY_APPLY_TRANSFORM" value="14" enum="AreaParameter">
Constant to set/get whether the area transform is applied to the gravity vector.
</constant>
<constant name="AREA_SPACE_OVERRIDE_DISABLED" value="0" enum="AreaSpaceOverrideMode">
This area does not affect gravity/damp. These are generally areas that exist only to detect collisions, and objects entering or exiting them.
</constant>
Expand Down
15 changes: 15 additions & 0 deletions scene/2d/area_2d.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand Up @@ -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_")) {
Expand All @@ -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);

Expand Down Expand Up @@ -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");
Expand Down
4 changes: 4 additions & 0 deletions scene/2d/area_2d.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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;

Expand Down
15 changes: 15 additions & 0 deletions scene/3d/area_3d.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand Up @@ -632,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_")) {
Expand All @@ -657,6 +668,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);

Expand Down Expand Up @@ -743,6 +757,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");
Expand Down
4 changes: 4 additions & 0 deletions scene/3d/area_3d.h
Original file line number Diff line number Diff line change
Expand Up @@ -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 = false;
real_t gravity_point_unit_distance = 0.0;

SpaceOverride linear_damp_space_override = SPACE_OVERRIDE_DISABLED;
Expand Down Expand Up @@ -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;

Expand Down
7 changes: 7 additions & 0 deletions servers/physics_2d/godot_area_2d.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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:
Expand Down Expand Up @@ -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();
}
Expand Down
4 changes: 4 additions & 0 deletions servers/physics_2d/godot_area_2d.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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; }

Expand Down
7 changes: 7 additions & 0 deletions servers/physics_3d/godot_area_3d.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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:
Expand Down Expand Up @@ -341,6 +346,8 @@ 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();
Comment on lines +349 to +350
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

With this code, point gravity will always take the transform into account, but directional gravity will only take the transform into account when gravity_apply_transform is true. This seems like an odd inconsistency. However, making it consistent would require breaking behavior compatibility, which is what PR #90166 does.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd say there's a valid use case for not applying transform to the direction, much less so for the point, if we are to break compatibility I'd argue it would be to make both controllable, not make the directional one local

} else {
r_gravity = get_gravity_vector() * get_gravity();
}
Expand Down
4 changes: 4 additions & 0 deletions servers/physics_3d/godot_area_3d.h
Original file line number Diff line number Diff line change
Expand Up @@ -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 = false;
real_t gravity_point_unit_distance = 0.0;
real_t linear_damp = 0.1;
real_t angular_damp = 0.1;
Expand Down Expand Up @@ -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; }

Expand Down
1 change: 1 addition & 0 deletions servers/physics_server_2d.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
3 changes: 2 additions & 1 deletion servers/physics_server_2d.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
1 change: 1 addition & 0 deletions servers/physics_server_3d.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
1 change: 1 addition & 0 deletions servers/physics_server_3d.h
Original file line number Diff line number Diff line change
Expand Up @@ -327,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;
Expand Down