diff --git a/doc/classes/Area2D.xml b/doc/classes/Area2D.xml
index 4ad5db2b6731..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].
+
+
@@ -81,7 +88,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 +101,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 +223,14 @@
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.
+
+
+ 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 8eedd3cdf2a6..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].
+
+
@@ -81,7 +88,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 +101,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 +247,14 @@
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.
+
+
+ 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 bd960e3da517..96741cc5a2d1 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,15 @@
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.
+
+
+ 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 f87d6342c79d..89a384b64bf8 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,15 @@
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.
+
+
+ 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 d6c786706c25..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)) {
@@ -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;
@@ -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:
@@ -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;
}
}
diff --git a/modules/godot_physics_2d/godot_area_2d.h b/modules/godot_physics_2d/godot_area_2d.h
index e6c3b45d6c35..a52d6263c891 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;
@@ -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);
@@ -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; }
@@ -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();
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 d0b287b05861..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)) {
@@ -137,8 +141,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 +187,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:
@@ -314,23 +318,38 @@ 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;
+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:
+ 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 {
- r_gravity = Vector3();
+ 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();
+ 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) {
+ 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 = v.normalized() * 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..a0f2819ff66a 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;
@@ -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);
@@ -130,8 +133,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; }
@@ -171,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 305ac8248e1b..ebfbf3c27d32 100644
--- a/scene/2d/physics/area_2d.cpp
+++ b/scene/2d/physics/area_2d.cpp
@@ -41,13 +41,26 @@ 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);
+ 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 {
+ 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) {
@@ -540,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;
@@ -556,12 +575,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 +608,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);
@@ -632,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")));
@@ -648,7 +677,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,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");
ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "gravity_direction"), "set_gravity_direction", "get_gravity_direction");
@@ -671,6 +701,10 @@ 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);
+ 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 7c59d76e00bb..70b28bcd32bf 100644
--- a/scene/2d/physics/area_2d.h
+++ b/scene/2d/physics/area_2d.h
@@ -46,11 +46,17 @@ class Area2D : public CollisionObject2D {
SPACE_OVERRIDE_REPLACE_COMBINE
};
+ enum GravityType {
+ GRAVITY_TYPE_DIRECTIONAL,
+ GRAVITY_TYPE_POINT,
+ GRAVITY_TYPE_TARGET,
+ };
+
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 +151,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;
@@ -193,10 +202,14 @@ 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();
};
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..367fd47e501e 100644
--- a/scene/3d/physics/area_3d.cpp
+++ b/scene/3d/physics/area_3d.cpp
@@ -41,13 +41,26 @@ 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);
+ 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 {
+ 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) {
@@ -644,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;
@@ -660,12 +679,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 +709,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);
@@ -757,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")));
@@ -773,7 +802,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,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");
ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "gravity_direction"), "set_gravity_direction", "get_gravity_direction");
@@ -807,6 +837,10 @@ 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);
+ 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 8848f9c23a0b..254a0bfeaef1 100644
--- a/scene/3d/physics/area_3d.h
+++ b/scene/3d/physics/area_3d.h
@@ -46,11 +46,17 @@ class Area3D : public CollisionObject3D {
SPACE_OVERRIDE_REPLACE_COMBINE
};
+ enum GravityType {
+ GRAVITY_TYPE_DIRECTIONAL,
+ GRAVITY_TYPE_POINT,
+ GRAVITY_TYPE_TARGET,
+ };
+
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 +160,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;
@@ -226,10 +235,14 @@ 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();
};
VARIANT_ENUM_CAST(Area3D::SpaceOverride);
+VARIANT_ENUM_CAST(Area3D::GravityType);
#endif // AREA_3D_H
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 f4f9a2e8b759..7d2bc650281b 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,10 @@ 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(AREA_GRAVITY_TYPE_TARGET);
+
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..2b04c857d5bd 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,12 @@ 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,
+ 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;
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;
@@ -344,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 */
@@ -833,6 +841,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_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 312b67ada955..a33eeed78b5b 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,10 @@ 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(AREA_GRAVITY_TYPE_TARGET);
+
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..b03678c3b08e 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,12 @@ class PhysicsServer3D : public Object {
AREA_SPACE_OVERRIDE_REPLACE_COMBINE
};
+ 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;
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;
@@ -376,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;
@@ -1041,6 +1049,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);
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 */