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

Area2D/3D Gravity: Replace point bool with a type enum, add Target gravity type #82878

Open
wants to merge 2 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
21 changes: 20 additions & 1 deletion doc/classes/Area2D.xml
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,13 @@
<link title="2D Platformer Demo">https://godotengine.org/asset-library/asset/2727</link>
</tutorials>
<methods>
<method name="_calculate_gravity_target" qualifiers="virtual">
<return type="Vector2" />
<param index="0" name="local_position" type="Vector2" />
<description>
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].
</description>
</method>
<method name="get_overlapping_areas" qualifiers="const">
<return type="Area2D[]" />
<description>
Expand Down Expand Up @@ -81,7 +88,7 @@
<member name="gravity_direction" type="Vector2" setter="set_gravity_direction" getter="get_gravity_direction" default="Vector2(0, 1)">
The area's gravity vector (not normalized).
</member>
<member name="gravity_point" type="bool" setter="set_gravity_is_point" getter="is_gravity_a_point" default="false">
<member name="gravity_point" type="bool" setter="set_gravity_is_point" getter="is_gravity_a_point" default="false" deprecated="Use [member gravity_type] instead.">
If [code]true[/code], gravity is calculated from a point (set via [member gravity_point_center]). See also [member gravity_space_override].
</member>
<member name="gravity_point_center" type="Vector2" setter="set_gravity_point_center" getter="get_gravity_point_center" default="Vector2(0, 1)">
Expand All @@ -94,6 +101,9 @@
<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>
<member name="gravity_type" type="int" setter="set_gravity_type" getter="get_gravity_type" enum="Area2D.GravityType" default="0">
Determines what type of gravity is applied, if [member gravity_space_override] is not disabled. See [enum GravityType] for possible values.
</member>
<member name="linear_damp" type="float" setter="set_linear_damp" getter="get_linear_damp" default="0.1">
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.
Expand Down Expand Up @@ -213,5 +223,14 @@
<constant name="SPACE_OVERRIDE_REPLACE_COMBINE" value="4" enum="SpaceOverride">
This area replaces any gravity/damping calculated so far (in [member priority] order), but keeps calculating the rest of the areas.
</constant>
<constant name="GRAVITY_TYPE_DIRECTIONAL" value="0" enum="GravityType">
Gravity that attracts in the direction specified by [member gravity_direction]. The strength of gravity is the same at all positions in the area.
</constant>
<constant name="GRAVITY_TYPE_POINT" value="1" enum="GravityType">
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.
</constant>
<constant name="GRAVITY_TYPE_TARGET" value="2" enum="GravityType">
Gravity that attracts towards a point defined by the output of the [method _calculate_gravity_target] callback method.
</constant>
</constants>
</class>
21 changes: 20 additions & 1 deletion doc/classes/Area3D.xml
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,13 @@
<link title="GUI in 3D Viewport Demo">https://godotengine.org/asset-library/asset/2807</link>
</tutorials>
<methods>
<method name="_calculate_gravity_target" qualifiers="virtual">
<return type="Vector3" />
<param index="0" name="local_position" type="Vector3" />
<description>
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].
</description>
</method>
<method name="get_overlapping_areas" qualifiers="const">
<return type="Area3D[]" />
<description>
Expand Down Expand Up @@ -81,7 +88,7 @@
<member name="gravity_direction" type="Vector3" setter="set_gravity_direction" getter="get_gravity_direction" default="Vector3(0, -1, 0)">
The area's gravity vector (not normalized).
</member>
<member name="gravity_point" type="bool" setter="set_gravity_is_point" getter="is_gravity_a_point" default="false">
<member name="gravity_point" type="bool" setter="set_gravity_is_point" getter="is_gravity_a_point" default="false" deprecated="Use [member gravity_type] instead.">
If [code]true[/code], gravity is calculated from a point (set via [member gravity_point_center]). See also [member gravity_space_override].
</member>
<member name="gravity_point_center" type="Vector3" setter="set_gravity_point_center" getter="get_gravity_point_center" default="Vector3(0, -1, 0)">
Expand All @@ -94,6 +101,9 @@
<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>
<member name="gravity_type" type="int" setter="set_gravity_type" getter="get_gravity_type" enum="Area3D.GravityType" default="0">
Determines what type of gravity is applied, if [member gravity_space_override] is not disabled. See [enum GravityType] for possible values.
</member>
<member name="linear_damp" type="float" setter="set_linear_damp" getter="get_linear_damp" default="0.1">
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.
Expand Down Expand Up @@ -237,5 +247,14 @@
<constant name="SPACE_OVERRIDE_REPLACE_COMBINE" value="4" enum="SpaceOverride">
This area replaces any gravity/damping calculated so far (in [member priority] order), but keeps calculating the rest of the areas.
</constant>
<constant name="GRAVITY_TYPE_DIRECTIONAL" value="0" enum="GravityType">
Gravity that attracts in the direction specified by [member gravity_direction]. The strength of gravity is the same at all positions in the area.
</constant>
<constant name="GRAVITY_TYPE_POINT" value="1" enum="GravityType">
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.
</constant>
<constant name="GRAVITY_TYPE_TARGET" value="2" enum="GravityType">
Gravity that attracts towards a point defined by the output of the [method _calculate_gravity_target] callback method.
</constant>
</constants>
</class>
14 changes: 13 additions & 1 deletion doc/classes/PhysicsServer2D.xml
Original file line number Diff line number Diff line change
Expand Up @@ -1060,7 +1060,10 @@
<constant name="AREA_PARAM_GRAVITY_VECTOR" value="2" enum="AreaParameter">
Constant to set/get gravity vector/center in an area. The default value of this parameter is [code]Vector2(0, -1)[/code].
</constant>
<constant name="AREA_PARAM_GRAVITY_IS_POINT" value="3" enum="AreaParameter">
<constant name="AREA_PARAM_GRAVITY_TYPE" value="3" enum="AreaParameter">
Constant to set/get the gravity type. See [enum AreaGravityType] for possible values.
</constant>
<constant name="AREA_PARAM_GRAVITY_IS_POINT" value="3" enum="AreaParameter" deprecated="Use [constant AREA_PARAM_GRAVITY_TYPE] instead.">
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].
</constant>
<constant name="AREA_PARAM_GRAVITY_POINT_UNIT_DISTANCE" value="4" enum="AreaParameter">
Expand Down Expand Up @@ -1097,6 +1100,15 @@
<constant name="AREA_SPACE_OVERRIDE_REPLACE_COMBINE" value="4" enum="AreaSpaceOverrideMode">
This area replaces any gravity/damp calculated so far, but keeps calculating the rest of the areas, down to the default one.
</constant>
<constant name="AREA_GRAVITY_TYPE_DIRECTIONAL" value="0" enum="AreaGravityType">
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.
</constant>
<constant name="AREA_GRAVITY_TYPE_POINT" value="1" enum="AreaGravityType">
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>
<constant name="AREA_GRAVITY_TYPE_TARGET" value="2" enum="AreaGravityType">
Gravity that attracts towards a target point defined by the output of the calculate gravity target callback method.
</constant>
<constant name="BODY_MODE_STATIC" value="0" enum="BodyMode">
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.
</constant>
Expand Down
14 changes: 13 additions & 1 deletion doc/classes/PhysicsServer3D.xml
Original file line number Diff line number Diff line change
Expand Up @@ -1636,7 +1636,10 @@
<constant name="AREA_PARAM_GRAVITY_VECTOR" value="2" enum="AreaParameter">
Constant to set/get gravity vector/center in an area.
</constant>
<constant name="AREA_PARAM_GRAVITY_IS_POINT" value="3" enum="AreaParameter">
<constant name="AREA_PARAM_GRAVITY_TYPE" value="3" enum="AreaParameter">
Constant to set/get the gravity type. See [enum AreaGravityType] for possible values.
</constant>
<constant name="AREA_PARAM_GRAVITY_IS_POINT" value="3" enum="AreaParameter" deprecated="Use [constant AREA_PARAM_GRAVITY_TYPE] instead.">
Constant to set/get whether the gravity vector of an area is a direction, or a center point.
</constant>
<constant name="AREA_PARAM_GRAVITY_POINT_UNIT_DISTANCE" value="4" enum="AreaParameter">
Expand Down Expand Up @@ -1685,6 +1688,15 @@
<constant name="AREA_SPACE_OVERRIDE_REPLACE_COMBINE" value="4" enum="AreaSpaceOverrideMode">
This area replaces any gravity/damp calculated so far, but keeps calculating the rest of the areas, down to the default one.
</constant>
<constant name="AREA_GRAVITY_TYPE_DIRECTIONAL" value="0" enum="AreaGravityType">
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.
</constant>
<constant name="AREA_GRAVITY_TYPE_POINT" value="1" enum="AreaGravityType">
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>
<constant name="AREA_GRAVITY_TYPE_TARGET" value="2" enum="AreaGravityType">
Gravity that attracts towards a target point defined by the output of the calculate gravity target callback method.
</constant>
<constant name="BODY_MODE_STATIC" value="0" enum="BodyMode">
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.
</constant>
Expand Down
57 changes: 38 additions & 19 deletions modules/godot_physics_2d/godot_area_2d.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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)) {
Expand All @@ -128,8 +132,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;
Expand Down Expand Up @@ -160,8 +164,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:
Expand Down Expand Up @@ -283,23 +287,38 @@ 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;
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:
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 {
r_gravity = Vector2();
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;
}
} else {
r_gravity = v.normalized() * get_gravity();
}
} else {
r_gravity = get_gravity_vector() * get_gravity();
const real_t gr_unit_dist = get_gravity_point_unit_distance();
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) {
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 = v.normalized() * get_gravity();
}
} break;
}
}

Expand Down
14 changes: 10 additions & 4 deletions modules/godot_physics_2d/godot_area_2d.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -57,6 +57,7 @@ class GodotArea2D : public GodotCollisionObject2D {
Callable monitor_callback;

Callable area_monitor_callback;
Callable gravity_target_callback;

SelfList<GodotArea2D> monitor_query_list;
SelfList<GodotArea2D> moved_list;
Expand Down Expand Up @@ -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);

Expand All @@ -121,8 +124,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; }
Expand Down Expand Up @@ -150,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();
Expand Down
7 changes: 7 additions & 0 deletions modules/godot_physics_2d/godot_physics_server_2d.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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() {
Expand Down
1 change: 1 addition & 0 deletions modules/godot_physics_2d/godot_physics_server_2d.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down
Loading
Loading