Browse Source

Separate space override modes for gravity/damping in Area

Also make inspector clearer for gravity point properties.
PouleyKetchoupp 3 years ago
parent
commit
3d1c123d45

+ 18 - 9
doc/classes/Area2D.xml

@@ -50,6 +50,9 @@
 			The rate at which objects stop spinning in this area. Represents the angular velocity lost per second.
 			See [member ProjectSettings.physics/2d/default_angular_damp] for more details about damping.
 		</member>
+		<member name="angular_damp_space_override" type="int" setter="set_angular_damp_space_override_mode" getter="get_angular_damp_space_override_mode" enum="Area2D.SpaceOverride" default="0">
+			Override mode for angular damping calculations within this area. See [enum SpaceOverride] for possible values.
+		</member>
 		<member name="audio_bus_name" type="StringName" setter="set_audio_bus_name" getter="get_audio_bus_name" default="&amp;&quot;Master&quot;">
 			The name of the area's audio bus.
 		</member>
@@ -57,21 +60,30 @@
 			If [code]true[/code], the area's audio bus overrides the default audio bus.
 		</member>
 		<member name="gravity" type="float" setter="set_gravity" getter="get_gravity" default="980.0">
-			The area's gravity intensity (in pixels per second squared). This value multiplies the gravity vector. This is useful to alter the force of gravity without altering its direction.
+			The area's gravity intensity (in pixels per second squared). This value multiplies the gravity direction. This is useful to alter the force of gravity without altering its direction.
 		</member>
-		<member name="gravity_distance_scale" type="float" setter="set_gravity_distance_scale" getter="get_gravity_distance_scale" default="0.0">
-			The falloff factor for point gravity. The greater the value, the faster gravity decreases with distance.
+		<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">
-			If [code]true[/code], gravity is calculated from a point (set via [member gravity_vec]). See also [member space_override].
+			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_vec" type="Vector2" setter="set_gravity_vector" getter="get_gravity_vector" default="Vector2(0, 1)">
-			The area's gravity vector (not normalized). If gravity is a point (see [member gravity_point]), this will be the point of attraction.
+		<member name="gravity_point_center" type="Vector2" setter="set_gravity_point_center" getter="get_gravity_point_center" default="Vector2(0, 1)">
+			If gravity is a point (see [member gravity_point]), this will be the point of attraction.
+		</member>
+		<member name="gravity_point_distance_scale" type="float" setter="set_gravity_point_distance_scale" getter="get_gravity_point_distance_scale" default="0.0">
+			The falloff factor for point gravity. The greater the value, the faster gravity decreases with distance.
+		</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>
 		<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.
 		</member>
+		<member name="linear_damp_space_override" type="int" setter="set_linear_damp_space_override_mode" getter="get_linear_damp_space_override_mode" enum="Area2D.SpaceOverride" default="0">
+			Override mode for linear damping calculations within this area. See [enum SpaceOverride] for possible values.
+		</member>
 		<member name="monitorable" type="bool" setter="set_monitorable" getter="is_monitorable" default="true">
 			If [code]true[/code], other monitoring areas can detect this area.
 		</member>
@@ -81,9 +93,6 @@
 		<member name="priority" type="float" setter="set_priority" getter="get_priority" default="0.0">
 			The area's priority. Higher priority areas are processed first.
 		</member>
-		<member name="space_override" type="int" setter="set_space_override_mode" getter="get_space_override_mode" enum="Area2D.SpaceOverride" default="0">
-			Override mode for gravity and damping calculations within this area. See [enum SpaceOverride] for possible values.
-		</member>
 	</members>
 	<signals>
 		<signal name="area_entered">

+ 18 - 9
doc/classes/Area3D.xml

@@ -48,6 +48,9 @@
 			The rate at which objects stop spinning in this area. Represents the angular velocity lost per second.
 			See [member ProjectSettings.physics/3d/default_angular_damp] for more details about damping.
 		</member>
+		<member name="angular_damp_space_override" type="int" setter="set_angular_damp_space_override_mode" getter="get_angular_damp_space_override_mode" enum="Area3D.SpaceOverride" default="0">
+			Override mode for angular damping calculations within this area. See [enum SpaceOverride] for possible values.
+		</member>
 		<member name="audio_bus_name" type="StringName" setter="set_audio_bus_name" getter="get_audio_bus_name" default="&amp;&quot;Master&quot;">
 			The name of the area's audio bus.
 		</member>
@@ -55,21 +58,30 @@
 			If [code]true[/code], the area's audio bus overrides the default audio bus.
 		</member>
 		<member name="gravity" type="float" setter="set_gravity" getter="get_gravity" default="9.8">
-			The area's gravity intensity (in meters per second squared). This value multiplies the gravity vector. This is useful to alter the force of gravity without altering its direction.
+			The area's gravity intensity (in meters per second squared). This value multiplies the gravity direction. This is useful to alter the force of gravity without altering its direction.
 		</member>
-		<member name="gravity_distance_scale" type="float" setter="set_gravity_distance_scale" getter="get_gravity_distance_scale" default="0.0">
-			The falloff factor for point gravity. The greater the value, the faster gravity decreases with distance.
+		<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">
-			If [code]true[/code], gravity is calculated from a point (set via [member gravity_vec]). See also [member space_override].
+			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_vec" type="Vector3" setter="set_gravity_vector" getter="get_gravity_vector" default="Vector3(0, -1, 0)">
-			The area's gravity vector (not normalized). If gravity is a point (see [member gravity_point]), this will be the point of attraction.
+		<member name="gravity_point_center" type="Vector3" setter="set_gravity_point_center" getter="get_gravity_point_center" default="Vector3(0, -1, 0)">
+			If gravity is a point (see [member gravity_point]), this will be the point of attraction.
+		</member>
+		<member name="gravity_point_distance_scale" type="float" setter="set_gravity_point_distance_scale" getter="get_gravity_point_distance_scale" default="0.0">
+			The falloff factor for point gravity. The greater the value, the faster gravity decreases with distance.
+		</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>
 		<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.
 		</member>
+		<member name="linear_damp_space_override" type="int" setter="set_linear_damp_space_override_mode" getter="get_linear_damp_space_override_mode" enum="Area3D.SpaceOverride" default="0">
+			Override mode for linear damping calculations within this area. See [enum SpaceOverride] for possible values.
+		</member>
 		<member name="monitorable" type="bool" setter="set_monitorable" getter="is_monitorable" default="true">
 			If [code]true[/code], other monitoring areas can detect this area.
 		</member>
@@ -91,9 +103,6 @@
 		<member name="reverb_bus_uniformity" type="float" setter="set_reverb_uniformity" getter="get_reverb_uniformity" default="0.0">
 			The degree to which this area's reverb is a uniform effect. Ranges from [code]0[/code] to [code]1[/code] with [code]0.1[/code] precision.
 		</member>
-		<member name="space_override" type="int" setter="set_space_override_mode" getter="get_space_override_mode" enum="Area3D.SpaceOverride" default="0">
-			Override mode for gravity and damping calculations within this area. See [enum SpaceOverride] for possible values.
-		</member>
 		<member name="wind_attenuation_factor" type="float" setter="set_wind_attenuation_factor" getter="get_wind_attenuation_factor" default="0.0">
 			The exponential rate at which wind force decreases with distance from its origin.
 		</member>

+ 19 - 25
doc/classes/PhysicsServer2D.xml

@@ -98,13 +98,6 @@
 				Returns the space assigned to the area.
 			</description>
 		</method>
-		<method name="area_get_space_override_mode" qualifiers="const">
-			<return type="int" enum="PhysicsServer2D.AreaSpaceOverrideMode" />
-			<argument index="0" name="area" type="RID" />
-			<description>
-				Returns the space override mode for the area.
-			</description>
-		</method>
 		<method name="area_get_transform" qualifiers="const">
 			<return type="Transform2D" />
 			<argument index="0" name="area" type="RID" />
@@ -207,14 +200,6 @@
 				Assigns a space to the area.
 			</description>
 		</method>
-		<method name="area_set_space_override_mode">
-			<return type="void" />
-			<argument index="0" name="area" type="RID" />
-			<argument index="1" name="mode" type="int" enum="PhysicsServer2D.AreaSpaceOverrideMode" />
-			<description>
-				Sets the space override mode for the area. See [enum AreaSpaceOverrideMode] for a list of available modes.
-			</description>
-		</method>
 		<method name="area_set_transform">
 			<return type="void" />
 			<argument index="0" name="area" type="RID" />
@@ -855,28 +840,37 @@
 		<constant name="SHAPE_CUSTOM" value="8" enum="ShapeType">
 			This constant is used internally by the engine. Any attempt to create this kind of shape results in an error.
 		</constant>
-		<constant name="AREA_PARAM_GRAVITY" value="0" enum="AreaParameter">
+		<constant name="AREA_PARAM_GRAVITY_OVERRIDE_MODE" value="0" enum="AreaParameter">
+			Constant to set/get gravity override mode in an area. See [enum AreaSpaceOverrideMode] for possible values.
+		</constant>
+		<constant name="AREA_PARAM_GRAVITY" value="1" enum="AreaParameter">
 			Constant to set/get gravity strength in an area.
 		</constant>
-		<constant name="AREA_PARAM_GRAVITY_VECTOR" value="1" enum="AreaParameter">
+		<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="2" enum="AreaParameter">
+		<constant name="AREA_PARAM_GRAVITY_IS_POINT" value="3" enum="AreaParameter">
 			Constant to set/get whether the gravity vector of an area is a direction, or a center point.
 		</constant>
-		<constant name="AREA_PARAM_GRAVITY_DISTANCE_SCALE" value="3" enum="AreaParameter">
+		<constant name="AREA_PARAM_GRAVITY_DISTANCE_SCALE" value="4" enum="AreaParameter">
 			Constant to set/get the falloff factor for point gravity of an area. The greater this value is, the faster the strength of gravity decreases with the square of distance.
 		</constant>
-		<constant name="AREA_PARAM_GRAVITY_POINT_ATTENUATION" value="4" enum="AreaParameter">
+		<constant name="AREA_PARAM_GRAVITY_POINT_ATTENUATION" value="5" enum="AreaParameter">
 			This constant was used to set/get the falloff factor for point gravity. It has been superseded by [constant AREA_PARAM_GRAVITY_DISTANCE_SCALE].
 		</constant>
-		<constant name="AREA_PARAM_LINEAR_DAMP" value="5" enum="AreaParameter">
-			Constant to set/get the linear dampening factor of an area.
+		<constant name="AREA_PARAM_LINEAR_DAMP_OVERRIDE_MODE" value="6" enum="AreaParameter">
+			Constant to set/get linear damping override mode in an area. See [enum AreaSpaceOverrideMode] for possible values.
+		</constant>
+		<constant name="AREA_PARAM_LINEAR_DAMP" value="7" enum="AreaParameter">
+			Constant to set/get the linear damping factor of an area.
+		</constant>
+		<constant name="AREA_PARAM_ANGULAR_DAMP_OVERRIDE_MODE" value="8" enum="AreaParameter">
+			Constant to set/get angular damping override mode in an area. See [enum AreaSpaceOverrideMode] for possible values.
 		</constant>
-		<constant name="AREA_PARAM_ANGULAR_DAMP" value="6" enum="AreaParameter">
-			Constant to set/get the angular dampening factor of an area.
+		<constant name="AREA_PARAM_ANGULAR_DAMP" value="9" enum="AreaParameter">
+			Constant to set/get the angular damping factor of an area.
 		</constant>
-		<constant name="AREA_PARAM_PRIORITY" value="7" enum="AreaParameter">
+		<constant name="AREA_PARAM_PRIORITY" value="10" enum="AreaParameter">
 			Constant to set/get the priority (order of processing) of an area.
 		</constant>
 		<constant name="AREA_SPACE_OVERRIDE_DISABLED" value="0" enum="AreaSpaceOverrideMode">

+ 23 - 29
doc/classes/PhysicsServer3D.xml

@@ -85,13 +85,6 @@
 				Returns the space assigned to the area.
 			</description>
 		</method>
-		<method name="area_get_space_override_mode" qualifiers="const">
-			<return type="int" enum="PhysicsServer3D.AreaSpaceOverrideMode" />
-			<argument index="0" name="area" type="RID" />
-			<description>
-				Returns the space override mode for the area.
-			</description>
-		</method>
 		<method name="area_get_transform" qualifiers="const">
 			<return type="Transform3D" />
 			<argument index="0" name="area" type="RID" />
@@ -201,14 +194,6 @@
 				Assigns a space to the area.
 			</description>
 		</method>
-		<method name="area_set_space_override_mode">
-			<return type="void" />
-			<argument index="0" name="area" type="RID" />
-			<argument index="1" name="mode" type="int" enum="PhysicsServer3D.AreaSpaceOverrideMode" />
-			<description>
-				Sets the space override mode for the area. The modes are described in the [enum AreaSpaceOverrideMode] constants.
-			</description>
-		</method>
 		<method name="area_set_transform">
 			<return type="void" />
 			<argument index="0" name="area" type="RID" />
@@ -1211,40 +1196,49 @@
 		<constant name="SHAPE_CUSTOM" value="10" enum="ShapeType">
 			This constant is used internally by the engine. Any attempt to create this kind of shape results in an error.
 		</constant>
-		<constant name="AREA_PARAM_GRAVITY" value="0" enum="AreaParameter">
+		<constant name="AREA_PARAM_GRAVITY_OVERRIDE_MODE" value="0" enum="AreaParameter">
+			Constant to set/get gravity override mode in an area. See [enum AreaSpaceOverrideMode] for possible values.
+		</constant>
+		<constant name="AREA_PARAM_GRAVITY" value="1" enum="AreaParameter">
 			Constant to set/get gravity strength in an area.
 		</constant>
-		<constant name="AREA_PARAM_GRAVITY_VECTOR" value="1" enum="AreaParameter">
+		<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="2" enum="AreaParameter">
+		<constant name="AREA_PARAM_GRAVITY_IS_POINT" value="3" enum="AreaParameter">
 			Constant to set/get whether the gravity vector of an area is a direction, or a center point.
 		</constant>
-		<constant name="AREA_PARAM_GRAVITY_DISTANCE_SCALE" value="3" enum="AreaParameter">
+		<constant name="AREA_PARAM_GRAVITY_DISTANCE_SCALE" value="4" enum="AreaParameter">
 			Constant to set/get the falloff factor for point gravity of an area. The greater this value is, the faster the strength of gravity decreases with the square of distance.
 		</constant>
-		<constant name="AREA_PARAM_GRAVITY_POINT_ATTENUATION" value="4" enum="AreaParameter">
+		<constant name="AREA_PARAM_GRAVITY_POINT_ATTENUATION" value="5" enum="AreaParameter">
 			This constant was used to set/get the falloff factor for point gravity. It has been superseded by [constant AREA_PARAM_GRAVITY_DISTANCE_SCALE].
 		</constant>
-		<constant name="AREA_PARAM_LINEAR_DAMP" value="5" enum="AreaParameter">
-			Constant to set/get the linear dampening factor of an area.
+		<constant name="AREA_PARAM_LINEAR_DAMP_OVERRIDE_MODE" value="6" enum="AreaParameter">
+			Constant to set/get linear damping override mode in an area. See [enum AreaSpaceOverrideMode] for possible values.
+		</constant>
+		<constant name="AREA_PARAM_LINEAR_DAMP" value="7" enum="AreaParameter">
+			Constant to set/get the linear damping factor of an area.
+		</constant>
+		<constant name="AREA_PARAM_ANGULAR_DAMP_OVERRIDE_MODE" value="8" enum="AreaParameter">
+			Constant to set/get angular damping override mode in an area. See [enum AreaSpaceOverrideMode] for possible values.
 		</constant>
-		<constant name="AREA_PARAM_ANGULAR_DAMP" value="6" enum="AreaParameter">
-			Constant to set/get the angular dampening factor of an area.
+		<constant name="AREA_PARAM_ANGULAR_DAMP" value="9" enum="AreaParameter">
+			Constant to set/get the angular damping factor of an area.
 		</constant>
-		<constant name="AREA_PARAM_PRIORITY" value="7" enum="AreaParameter">
+		<constant name="AREA_PARAM_PRIORITY" value="10" enum="AreaParameter">
 			Constant to set/get the priority (order of processing) of an area.
 		</constant>
-		<constant name="AREA_PARAM_WIND_FORCE_MAGNITUDE" value="8" enum="AreaParameter">
+		<constant name="AREA_PARAM_WIND_FORCE_MAGNITUDE" value="11" enum="AreaParameter">
 			Constant to set/get the magnitude of area-specific wind force.
 		</constant>
-		<constant name="AREA_PARAM_WIND_SOURCE" value="9" enum="AreaParameter">
+		<constant name="AREA_PARAM_WIND_SOURCE" value="12" enum="AreaParameter">
 			Constant to set/get the 3D vector that specifies the origin from which an area-specific wind blows.
 		</constant>
-		<constant name="AREA_PARAM_WIND_DIRECTION" value="10" enum="AreaParameter">
+		<constant name="AREA_PARAM_WIND_DIRECTION" value="13" enum="AreaParameter">
 			Constant to set/get the 3D vector that specifies the direction in which an area-specific wind blows.
 		</constant>
-		<constant name="AREA_PARAM_WIND_ATTENUATION_FACTOR" value="11" enum="AreaParameter">
+		<constant name="AREA_PARAM_WIND_ATTENUATION_FACTOR" value="14" enum="AreaParameter">
 			Constant to set/get the exponential rate at which wind force decreases with distance from its origin.
 		</constant>
 		<constant name="AREA_SPACE_OVERRIDE_DISABLED" value="0" enum="AreaSpaceOverrideMode">

+ 88 - 23
scene/2d/area_2d.cpp

@@ -33,13 +33,13 @@
 #include "scene/scene_string_names.h"
 #include "servers/audio_server.h"
 
-void Area2D::set_space_override_mode(SpaceOverride p_mode) {
-	space_override = p_mode;
-	PhysicsServer2D::get_singleton()->area_set_space_override_mode(get_rid(), PhysicsServer2D::AreaSpaceOverrideMode(p_mode));
+void Area2D::set_gravity_space_override_mode(SpaceOverride p_mode) {
+	gravity_space_override = p_mode;
+	PhysicsServer2D::get_singleton()->area_set_param(get_rid(), PhysicsServer2D::AREA_PARAM_GRAVITY_OVERRIDE_MODE, p_mode);
 }
 
-Area2D::SpaceOverride Area2D::get_space_override_mode() const {
-	return space_override;
+Area2D::SpaceOverride Area2D::get_gravity_space_override_mode() const {
+	return gravity_space_override;
 }
 
 void Area2D::set_gravity_is_point(bool p_enabled) {
@@ -51,21 +51,30 @@ bool Area2D::is_gravity_a_point() const {
 	return gravity_is_point;
 }
 
-void Area2D::set_gravity_distance_scale(real_t p_scale) {
+void Area2D::set_gravity_point_distance_scale(real_t p_scale) {
 	gravity_distance_scale = p_scale;
 	PhysicsServer2D::get_singleton()->area_set_param(get_rid(), PhysicsServer2D::AREA_PARAM_GRAVITY_DISTANCE_SCALE, p_scale);
 }
 
-real_t Area2D::get_gravity_distance_scale() const {
+real_t Area2D::get_gravity_point_distance_scale() const {
 	return gravity_distance_scale;
 }
 
-void Area2D::set_gravity_vector(const Vector2 &p_vec) {
-	gravity_vec = p_vec;
-	PhysicsServer2D::get_singleton()->area_set_param(get_rid(), PhysicsServer2D::AREA_PARAM_GRAVITY_VECTOR, p_vec);
+void Area2D::set_gravity_point_center(const Vector2 &p_center) {
+	gravity_vec = p_center;
+	PhysicsServer2D::get_singleton()->area_set_param(get_rid(), PhysicsServer2D::AREA_PARAM_GRAVITY_VECTOR, p_center);
 }
 
-Vector2 Area2D::get_gravity_vector() const {
+const Vector2 &Area2D::get_gravity_point_center() const {
+	return gravity_vec;
+}
+
+void Area2D::set_gravity_direction(const Vector2 &p_direction) {
+	gravity_vec = p_direction;
+	PhysicsServer2D::get_singleton()->area_set_param(get_rid(), PhysicsServer2D::AREA_PARAM_GRAVITY_VECTOR, p_direction);
+}
+
+const Vector2 &Area2D::get_gravity_direction() const {
 	return gravity_vec;
 }
 
@@ -78,6 +87,24 @@ real_t Area2D::get_gravity() const {
 	return gravity;
 }
 
+void Area2D::set_linear_damp_space_override_mode(SpaceOverride p_mode) {
+	linear_damp_space_override = p_mode;
+	PhysicsServer2D::get_singleton()->area_set_param(get_rid(), PhysicsServer2D::AREA_PARAM_LINEAR_DAMP_OVERRIDE_MODE, p_mode);
+}
+
+Area2D::SpaceOverride Area2D::get_linear_damp_space_override_mode() const {
+	return linear_damp_space_override;
+}
+
+void Area2D::set_angular_damp_space_override_mode(SpaceOverride p_mode) {
+	angular_damp_space_override = p_mode;
+	PhysicsServer2D::get_singleton()->area_set_param(get_rid(), PhysicsServer2D::AREA_PARAM_ANGULAR_DAMP_OVERRIDE_MODE, p_mode);
+}
+
+Area2D::SpaceOverride Area2D::get_angular_damp_space_override_mode() const {
+	return angular_damp_space_override;
+}
+
 void Area2D::set_linear_damp(real_t p_linear_damp) {
 	linear_damp = p_linear_damp;
 	PhysicsServer2D::get_singleton()->area_set_param(get_rid(), PhysicsServer2D::AREA_PARAM_LINEAR_DAMP, p_linear_damp);
@@ -483,25 +510,56 @@ void Area2D::_validate_property(PropertyInfo &property) const {
 		}
 
 		property.hint_string = options;
+	} else if (property.name.begins_with("gravity") && property.name != "gravity_space_override") {
+		if (gravity_space_override == SPACE_OVERRIDE_DISABLED) {
+			property.usage = PROPERTY_USAGE_NO_EDITOR | PROPERTY_USAGE_INTERNAL;
+		} else {
+			if (gravity_is_point) {
+				if (property.name == "gravity_direction") {
+					property.usage = PROPERTY_USAGE_NO_EDITOR | PROPERTY_USAGE_INTERNAL;
+				}
+			} else {
+				if (property.name.begins_with("gravity_point_")) {
+					property.usage = PROPERTY_USAGE_NO_EDITOR | PROPERTY_USAGE_INTERNAL;
+				}
+			}
+		}
+	} else if (property.name.begins_with("linear_damp") && property.name != "linear_damp_space_override") {
+		if (linear_damp_space_override == SPACE_OVERRIDE_DISABLED) {
+			property.usage = PROPERTY_USAGE_NO_EDITOR | PROPERTY_USAGE_INTERNAL;
+		}
+	} else if (property.name.begins_with("angular_damp") && property.name != "angular_damp_space_override") {
+		if (angular_damp_space_override == SPACE_OVERRIDE_DISABLED) {
+			property.usage = PROPERTY_USAGE_NO_EDITOR | PROPERTY_USAGE_INTERNAL;
+		}
 	}
 }
 
 void Area2D::_bind_methods() {
-	ClassDB::bind_method(D_METHOD("set_space_override_mode", "space_override_mode"), &Area2D::set_space_override_mode);
-	ClassDB::bind_method(D_METHOD("get_space_override_mode"), &Area2D::get_space_override_mode);
+	ClassDB::bind_method(D_METHOD("set_gravity_space_override_mode", "space_override_mode"), &Area2D::set_gravity_space_override_mode);
+	ClassDB::bind_method(D_METHOD("get_gravity_space_override_mode"), &Area2D::get_gravity_space_override_mode);
 
 	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_distance_scale", "distance_scale"), &Area2D::set_gravity_distance_scale);
-	ClassDB::bind_method(D_METHOD("get_gravity_distance_scale"), &Area2D::get_gravity_distance_scale);
+	ClassDB::bind_method(D_METHOD("set_gravity_point_distance_scale", "distance_scale"), &Area2D::set_gravity_point_distance_scale);
+	ClassDB::bind_method(D_METHOD("get_gravity_point_distance_scale"), &Area2D::get_gravity_point_distance_scale);
+
+	ClassDB::bind_method(D_METHOD("set_gravity_point_center", "center"), &Area2D::set_gravity_point_center);
+	ClassDB::bind_method(D_METHOD("get_gravity_point_center"), &Area2D::get_gravity_point_center);
 
-	ClassDB::bind_method(D_METHOD("set_gravity_vector", "vector"), &Area2D::set_gravity_vector);
-	ClassDB::bind_method(D_METHOD("get_gravity_vector"), &Area2D::get_gravity_vector);
+	ClassDB::bind_method(D_METHOD("set_gravity_direction", "direction"), &Area2D::set_gravity_direction);
+	ClassDB::bind_method(D_METHOD("get_gravity_direction"), &Area2D::get_gravity_direction);
 
 	ClassDB::bind_method(D_METHOD("set_gravity", "gravity"), &Area2D::set_gravity);
 	ClassDB::bind_method(D_METHOD("get_gravity"), &Area2D::get_gravity);
 
+	ClassDB::bind_method(D_METHOD("set_linear_damp_space_override_mode", "space_override_mode"), &Area2D::set_linear_damp_space_override_mode);
+	ClassDB::bind_method(D_METHOD("get_linear_damp_space_override_mode"), &Area2D::get_linear_damp_space_override_mode);
+
+	ClassDB::bind_method(D_METHOD("set_angular_damp_space_override_mode", "space_override_mode"), &Area2D::set_angular_damp_space_override_mode);
+	ClassDB::bind_method(D_METHOD("get_angular_damp_space_override_mode"), &Area2D::get_angular_damp_space_override_mode);
+
 	ClassDB::bind_method(D_METHOD("set_linear_damp", "linear_damp"), &Area2D::set_linear_damp);
 	ClassDB::bind_method(D_METHOD("get_linear_damp"), &Area2D::get_linear_damp);
 
@@ -543,13 +601,20 @@ void Area2D::_bind_methods() {
 	ADD_PROPERTY(PropertyInfo(Variant::BOOL, "monitorable"), "set_monitorable", "is_monitorable");
 	ADD_PROPERTY(PropertyInfo(Variant::INT, "priority", PROPERTY_HINT_RANGE, "0,128,1"), "set_priority", "get_priority");
 
-	ADD_GROUP("Physics Overrides", "");
-	ADD_PROPERTY(PropertyInfo(Variant::INT, "space_override", PROPERTY_HINT_ENUM, "Disabled,Combine,Combine-Replace,Replace,Replace-Combine"), "set_space_override_mode", "get_space_override_mode");
-	ADD_PROPERTY(PropertyInfo(Variant::BOOL, "gravity_point"), "set_gravity_is_point", "is_gravity_a_point");
-	ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "gravity_distance_scale", PROPERTY_HINT_RANGE, "0,1024,0.001,or_greater,exp"), "set_gravity_distance_scale", "get_gravity_distance_scale");
-	ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "gravity_vec"), "set_gravity_vector", "get_gravity_vector");
+	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::FLOAT, "gravity_point_distance_scale", PROPERTY_HINT_RANGE, "0,1024,0.001,or_greater,exp"), "set_gravity_point_distance_scale", "get_gravity_point_distance_scale");
+	ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "gravity_point_center"), "set_gravity_point_center", "get_gravity_point_center");
+	ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "gravity_direction"), "set_gravity_direction", "get_gravity_direction");
 	ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "gravity", PROPERTY_HINT_RANGE, "-4096,4096,0.001,or_lesser,or_greater"), "set_gravity", "get_gravity");
+
+	ADD_GROUP("Linear Damp", "linear_damp_");
+	ADD_PROPERTY(PropertyInfo(Variant::INT, "linear_damp_space_override", PROPERTY_HINT_ENUM, "Disabled,Combine,Combine-Replace,Replace,Replace-Combine", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_UPDATE_ALL_IF_MODIFIED), "set_linear_damp_space_override_mode", "get_linear_damp_space_override_mode");
 	ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "linear_damp", PROPERTY_HINT_RANGE, "0,100,0.001,or_greater"), "set_linear_damp", "get_linear_damp");
+
+	ADD_GROUP("Angular Damp", "angular_damp_");
+	ADD_PROPERTY(PropertyInfo(Variant::INT, "angular_damp_space_override", PROPERTY_HINT_ENUM, "Disabled,Combine,Combine-Replace,Replace,Replace-Combine", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_UPDATE_ALL_IF_MODIFIED), "set_angular_damp_space_override_mode", "get_angular_damp_space_override_mode");
 	ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "angular_damp", PROPERTY_HINT_RANGE, "0,100,0.001,or_greater"), "set_angular_damp", "get_angular_damp");
 
 	ADD_GROUP("Audio Bus", "audio_bus_");
@@ -566,7 +631,7 @@ void Area2D::_bind_methods() {
 Area2D::Area2D() :
 		CollisionObject2D(PhysicsServer2D::get_singleton()->area_create(), true) {
 	set_gravity(980);
-	set_gravity_vector(Vector2(0, 1));
+	set_gravity_direction(Vector2(0, 1));
 	set_monitoring(true);
 	set_monitorable(true);
 }

+ 21 - 7
scene/2d/area_2d.h

@@ -47,14 +47,19 @@ public:
 	};
 
 private:
-	SpaceOverride space_override = SPACE_OVERRIDE_DISABLED;
+	SpaceOverride gravity_space_override = SPACE_OVERRIDE_DISABLED;
 	Vector2 gravity_vec;
 	real_t gravity;
 	bool gravity_is_point = false;
 	real_t gravity_distance_scale = 0.0;
+
+	SpaceOverride linear_damp_space_override = SPACE_OVERRIDE_DISABLED;
+	SpaceOverride angular_damp_space_override = SPACE_OVERRIDE_DISABLED;
 	real_t linear_damp = 0.1;
 	real_t angular_damp = 1.0;
+
 	int priority = 0;
+
 	bool monitoring = false;
 	bool monitorable = false;
 	bool locked = false;
@@ -133,21 +138,30 @@ protected:
 	void _validate_property(PropertyInfo &property) const override;
 
 public:
-	void set_space_override_mode(SpaceOverride p_mode);
-	SpaceOverride get_space_override_mode() const;
+	void set_gravity_space_override_mode(SpaceOverride p_mode);
+	SpaceOverride get_gravity_space_override_mode() const;
 
 	void set_gravity_is_point(bool p_enabled);
 	bool is_gravity_a_point() const;
 
-	void set_gravity_distance_scale(real_t p_scale);
-	real_t get_gravity_distance_scale() const;
+	void set_gravity_point_distance_scale(real_t p_scale);
+	real_t get_gravity_point_distance_scale() const;
 
-	void set_gravity_vector(const Vector2 &p_vec);
-	Vector2 get_gravity_vector() const;
+	void set_gravity_point_center(const Vector2 &p_center);
+	const Vector2 &get_gravity_point_center() const;
+
+	void set_gravity_direction(const Vector2 &p_direction);
+	const Vector2 &get_gravity_direction() const;
 
 	void set_gravity(real_t p_gravity);
 	real_t get_gravity() const;
 
+	void set_linear_damp_space_override_mode(SpaceOverride p_mode);
+	SpaceOverride get_linear_damp_space_override_mode() const;
+
+	void set_angular_damp_space_override_mode(SpaceOverride p_mode);
+	SpaceOverride get_angular_damp_space_override_mode() const;
+
 	void set_linear_damp(real_t p_linear_damp);
 	real_t get_linear_damp() const;
 

+ 90 - 23
scene/3d/area_3d.cpp

@@ -33,13 +33,13 @@
 #include "scene/scene_string_names.h"
 #include "servers/audio_server.h"
 
-void Area3D::set_space_override_mode(SpaceOverride p_mode) {
-	space_override = p_mode;
-	PhysicsServer3D::get_singleton()->area_set_space_override_mode(get_rid(), PhysicsServer3D::AreaSpaceOverrideMode(p_mode));
+void Area3D::set_gravity_space_override_mode(SpaceOverride p_mode) {
+	gravity_space_override = p_mode;
+	PhysicsServer3D::get_singleton()->area_set_param(get_rid(), PhysicsServer3D::AREA_PARAM_GRAVITY_OVERRIDE_MODE, p_mode);
 }
 
-Area3D::SpaceOverride Area3D::get_space_override_mode() const {
-	return space_override;
+Area3D::SpaceOverride Area3D::get_gravity_space_override_mode() const {
+	return gravity_space_override;
 }
 
 void Area3D::set_gravity_is_point(bool p_enabled) {
@@ -51,21 +51,30 @@ bool Area3D::is_gravity_a_point() const {
 	return gravity_is_point;
 }
 
-void Area3D::set_gravity_distance_scale(real_t p_scale) {
+void Area3D::set_gravity_point_distance_scale(real_t p_scale) {
 	gravity_distance_scale = p_scale;
 	PhysicsServer3D::get_singleton()->area_set_param(get_rid(), PhysicsServer3D::AREA_PARAM_GRAVITY_DISTANCE_SCALE, p_scale);
 }
 
-real_t Area3D::get_gravity_distance_scale() const {
+real_t Area3D::get_gravity_point_distance_scale() const {
 	return gravity_distance_scale;
 }
 
-void Area3D::set_gravity_vector(const Vector3 &p_vec) {
-	gravity_vec = p_vec;
-	PhysicsServer3D::get_singleton()->area_set_param(get_rid(), PhysicsServer3D::AREA_PARAM_GRAVITY_VECTOR, p_vec);
+void Area3D::set_gravity_point_center(const Vector3 &p_center) {
+	gravity_vec = p_center;
+	PhysicsServer3D::get_singleton()->area_set_param(get_rid(), PhysicsServer3D::AREA_PARAM_GRAVITY_VECTOR, p_center);
 }
 
-Vector3 Area3D::get_gravity_vector() const {
+const Vector3 &Area3D::get_gravity_point_center() const {
+	return gravity_vec;
+}
+
+void Area3D::set_gravity_direction(const Vector3 &p_direction) {
+	gravity_vec = p_direction;
+	PhysicsServer3D::get_singleton()->area_set_param(get_rid(), PhysicsServer3D::AREA_PARAM_GRAVITY_VECTOR, p_direction);
+}
+
+const Vector3 &Area3D::get_gravity_direction() const {
 	return gravity_vec;
 }
 
@@ -78,6 +87,24 @@ real_t Area3D::get_gravity() const {
 	return gravity;
 }
 
+void Area3D::set_linear_damp_space_override_mode(SpaceOverride p_mode) {
+	linear_damp_space_override = p_mode;
+	PhysicsServer3D::get_singleton()->area_set_param(get_rid(), PhysicsServer3D::AREA_PARAM_LINEAR_DAMP_OVERRIDE_MODE, p_mode);
+}
+
+Area3D::SpaceOverride Area3D::get_linear_damp_space_override_mode() const {
+	return linear_damp_space_override;
+}
+
+void Area3D::set_angular_damp_space_override_mode(SpaceOverride p_mode) {
+	angular_damp_space_override = p_mode;
+	PhysicsServer3D::get_singleton()->area_set_param(get_rid(), PhysicsServer3D::AREA_PARAM_ANGULAR_DAMP_OVERRIDE_MODE, p_mode);
+}
+
+Area3D::SpaceOverride Area3D::get_angular_damp_space_override_mode() const {
+	return angular_damp_space_override;
+}
+
 void Area3D::set_linear_damp(real_t p_linear_damp) {
 	linear_damp = p_linear_damp;
 	PhysicsServer3D::get_singleton()->area_set_param(get_rid(), PhysicsServer3D::AREA_PARAM_LINEAR_DAMP, p_linear_damp);
@@ -579,27 +606,58 @@ void Area3D::_validate_property(PropertyInfo &property) const {
 		}
 
 		property.hint_string = options;
+	} else if (property.name.begins_with("gravity") && property.name != "gravity_space_override") {
+		if (gravity_space_override == SPACE_OVERRIDE_DISABLED) {
+			property.usage = PROPERTY_USAGE_NO_EDITOR | PROPERTY_USAGE_INTERNAL;
+		} else {
+			if (gravity_is_point) {
+				if (property.name == "gravity_direction") {
+					property.usage = PROPERTY_USAGE_NO_EDITOR | PROPERTY_USAGE_INTERNAL;
+				}
+			} else {
+				if (property.name.begins_with("gravity_point_")) {
+					property.usage = PROPERTY_USAGE_NO_EDITOR | PROPERTY_USAGE_INTERNAL;
+				}
+			}
+		}
+	} else if (property.name.begins_with("linear_damp") && property.name != "linear_damp_space_override") {
+		if (linear_damp_space_override == SPACE_OVERRIDE_DISABLED) {
+			property.usage = PROPERTY_USAGE_NO_EDITOR | PROPERTY_USAGE_INTERNAL;
+		}
+	} else if (property.name.begins_with("angular_damp") && property.name != "angular_damp_space_override") {
+		if (angular_damp_space_override == SPACE_OVERRIDE_DISABLED) {
+			property.usage = PROPERTY_USAGE_NO_EDITOR | PROPERTY_USAGE_INTERNAL;
+		}
 	}
 
 	CollisionObject3D::_validate_property(property);
 }
 
 void Area3D::_bind_methods() {
-	ClassDB::bind_method(D_METHOD("set_space_override_mode", "enable"), &Area3D::set_space_override_mode);
-	ClassDB::bind_method(D_METHOD("get_space_override_mode"), &Area3D::get_space_override_mode);
+	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_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_distance_scale", "distance_scale"), &Area3D::set_gravity_distance_scale);
-	ClassDB::bind_method(D_METHOD("get_gravity_distance_scale"), &Area3D::get_gravity_distance_scale);
+	ClassDB::bind_method(D_METHOD("set_gravity_point_distance_scale", "distance_scale"), &Area3D::set_gravity_point_distance_scale);
+	ClassDB::bind_method(D_METHOD("get_gravity_point_distance_scale"), &Area3D::get_gravity_point_distance_scale);
 
-	ClassDB::bind_method(D_METHOD("set_gravity_vector", "vector"), &Area3D::set_gravity_vector);
-	ClassDB::bind_method(D_METHOD("get_gravity_vector"), &Area3D::get_gravity_vector);
+	ClassDB::bind_method(D_METHOD("set_gravity_point_center", "center"), &Area3D::set_gravity_point_center);
+	ClassDB::bind_method(D_METHOD("get_gravity_point_center"), &Area3D::get_gravity_point_center);
+
+	ClassDB::bind_method(D_METHOD("set_gravity_direction", "direction"), &Area3D::set_gravity_direction);
+	ClassDB::bind_method(D_METHOD("get_gravity_direction"), &Area3D::get_gravity_direction);
 
 	ClassDB::bind_method(D_METHOD("set_gravity", "gravity"), &Area3D::set_gravity);
 	ClassDB::bind_method(D_METHOD("get_gravity"), &Area3D::get_gravity);
 
+	ClassDB::bind_method(D_METHOD("set_linear_damp_space_override_mode", "space_override_mode"), &Area3D::set_linear_damp_space_override_mode);
+	ClassDB::bind_method(D_METHOD("get_linear_damp_space_override_mode"), &Area3D::get_linear_damp_space_override_mode);
+
+	ClassDB::bind_method(D_METHOD("set_angular_damp_space_override_mode", "space_override_mode"), &Area3D::set_angular_damp_space_override_mode);
+	ClassDB::bind_method(D_METHOD("get_angular_damp_space_override_mode"), &Area3D::get_angular_damp_space_override_mode);
+
 	ClassDB::bind_method(D_METHOD("set_angular_damp", "angular_damp"), &Area3D::set_angular_damp);
 	ClassDB::bind_method(D_METHOD("get_angular_damp"), &Area3D::get_angular_damp);
 
@@ -662,14 +720,23 @@ void Area3D::_bind_methods() {
 	ADD_PROPERTY(PropertyInfo(Variant::BOOL, "monitorable"), "set_monitorable", "is_monitorable");
 	ADD_PROPERTY(PropertyInfo(Variant::INT, "priority", PROPERTY_HINT_RANGE, "0,128,1"), "set_priority", "get_priority");
 
-	ADD_GROUP("Physics Overrides", "");
-	ADD_PROPERTY(PropertyInfo(Variant::INT, "space_override", PROPERTY_HINT_ENUM, "Disabled,Combine,Combine-Replace,Replace,Replace-Combine"), "set_space_override_mode", "get_space_override_mode");
-	ADD_PROPERTY(PropertyInfo(Variant::BOOL, "gravity_point"), "set_gravity_is_point", "is_gravity_a_point");
-	ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "gravity_distance_scale", PROPERTY_HINT_RANGE, "0,1024,0.001,or_greater,exp"), "set_gravity_distance_scale", "get_gravity_distance_scale");
-	ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "gravity_vec"), "set_gravity_vector", "get_gravity_vector");
+	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::FLOAT, "gravity_point_distance_scale", PROPERTY_HINT_RANGE, "0,1024,0.001,or_greater,exp"), "set_gravity_point_distance_scale", "get_gravity_point_distance_scale");
+	ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "gravity_point_center"), "set_gravity_point_center", "get_gravity_point_center");
+	ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "gravity_direction"), "set_gravity_direction", "get_gravity_direction");
 	ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "gravity", PROPERTY_HINT_RANGE, "-32,32,0.001,or_lesser,or_greater"), "set_gravity", "get_gravity");
+
+	ADD_GROUP("Linear Damp", "linear_damp_");
+	ADD_PROPERTY(PropertyInfo(Variant::INT, "linear_damp_space_override", PROPERTY_HINT_ENUM, "Disabled,Combine,Combine-Replace,Replace,Replace-Combine", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_UPDATE_ALL_IF_MODIFIED), "set_linear_damp_space_override_mode", "get_linear_damp_space_override_mode");
 	ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "linear_damp", PROPERTY_HINT_RANGE, "0,100,0.001,or_greater"), "set_linear_damp", "get_linear_damp");
+
+	ADD_GROUP("Angular Damp", "angular_damp_");
+	ADD_PROPERTY(PropertyInfo(Variant::INT, "angular_damp_space_override", PROPERTY_HINT_ENUM, "Disabled,Combine,Combine-Replace,Replace,Replace-Combine", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_UPDATE_ALL_IF_MODIFIED), "set_angular_damp_space_override_mode", "get_angular_damp_space_override_mode");
 	ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "angular_damp", PROPERTY_HINT_RANGE, "0,100,0.001,or_greater"), "set_angular_damp", "get_angular_damp");
+
+	ADD_GROUP("Wind", "wind_");
 	ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "wind_force_magnitude", PROPERTY_HINT_RANGE, "0,10,0.001,or_greater"), "set_wind_force_magnitude", "get_wind_force_magnitude");
 	ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "wind_attenuation_factor", PROPERTY_HINT_RANGE, "0.0,3.0,0.001,or_greater"), "set_wind_attenuation_factor", "get_wind_attenuation_factor");
 	ADD_PROPERTY(PropertyInfo(Variant::NODE_PATH, "wind_source_path", PROPERTY_HINT_NODE_PATH_VALID_TYPES, "Node3D"), "set_wind_source_path", "get_wind_source_path");
@@ -694,7 +761,7 @@ void Area3D::_bind_methods() {
 Area3D::Area3D() :
 		CollisionObject3D(PhysicsServer3D::get_singleton()->area_create(), true) {
 	set_gravity(9.8);
-	set_gravity_vector(Vector3(0, -1, 0));
+	set_gravity_direction(Vector3(0, -1, 0));
 	set_monitoring(true);
 	set_monitorable(true);
 }

+ 22 - 7
scene/3d/area_3d.h

@@ -47,17 +47,23 @@ public:
 	};
 
 private:
-	SpaceOverride space_override = SPACE_OVERRIDE_DISABLED;
+	SpaceOverride gravity_space_override = SPACE_OVERRIDE_DISABLED;
 	Vector3 gravity_vec;
 	real_t gravity;
 	bool gravity_is_point = false;
 	real_t gravity_distance_scale = 0.0;
+
+	SpaceOverride linear_damp_space_override = SPACE_OVERRIDE_DISABLED;
+	SpaceOverride angular_damp_space_override = SPACE_OVERRIDE_DISABLED;
 	real_t angular_damp = 0.1;
 	real_t linear_damp = 0.1;
+
 	int priority = 0;
+
 	real_t wind_force_magnitude = 0.0;
 	real_t wind_attenuation_factor = 0.0;
 	NodePath wind_source_path;
+
 	bool monitoring = false;
 	bool monitorable = false;
 	bool locked = false;
@@ -144,21 +150,30 @@ protected:
 	static void _bind_methods();
 
 public:
-	void set_space_override_mode(SpaceOverride p_mode);
-	SpaceOverride get_space_override_mode() const;
+	void set_gravity_space_override_mode(SpaceOverride p_mode);
+	SpaceOverride get_gravity_space_override_mode() const;
 
 	void set_gravity_is_point(bool p_enabled);
 	bool is_gravity_a_point() const;
 
-	void set_gravity_distance_scale(real_t p_scale);
-	real_t get_gravity_distance_scale() const;
+	void set_gravity_point_distance_scale(real_t p_scale);
+	real_t get_gravity_point_distance_scale() const;
 
-	void set_gravity_vector(const Vector3 &p_vec);
-	Vector3 get_gravity_vector() const;
+	void set_gravity_point_center(const Vector3 &p_center);
+	const Vector3 &get_gravity_point_center() const;
+
+	void set_gravity_direction(const Vector3 &p_direction);
+	const Vector3 &get_gravity_direction() const;
 
 	void set_gravity(real_t p_gravity);
 	real_t get_gravity() const;
 
+	void set_linear_damp_space_override_mode(SpaceOverride p_mode);
+	SpaceOverride get_linear_damp_space_override_mode() const;
+
+	void set_angular_damp_space_override_mode(SpaceOverride p_mode);
+	SpaceOverride get_angular_damp_space_override_mode() const;
+
 	void set_angular_damp(real_t p_angular_damp);
 	real_t get_angular_damp() const;
 

+ 19 - 4
servers/physics_2d/godot_area_2d.cpp

@@ -121,18 +121,21 @@ void GodotArea2D::set_area_monitor_callback(const Callable &p_callback) {
 	}
 }
 
-void GodotArea2D::set_space_override_mode(PhysicsServer2D::AreaSpaceOverrideMode p_mode) {
-	bool do_override = p_mode != PhysicsServer2D::AREA_SPACE_OVERRIDE_DISABLED;
-	if (do_override == (space_override_mode != PhysicsServer2D::AREA_SPACE_OVERRIDE_DISABLED)) {
+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)) {
 		return;
 	}
 	_unregister_shapes();
-	space_override_mode = p_mode;
+	r_mode = p_new_mode;
 	_shape_changed();
 }
 
 void GodotArea2D::set_param(PhysicsServer2D::AreaParameter p_param, const Variant &p_value) {
 	switch (p_param) {
+		case PhysicsServer2D::AREA_PARAM_GRAVITY_OVERRIDE_MODE:
+			_set_space_override_mode(gravity_override_mode, (PhysicsServer2D::AreaSpaceOverrideMode)(int)p_value);
+			break;
 		case PhysicsServer2D::AREA_PARAM_GRAVITY:
 			gravity = p_value;
 			break;
@@ -148,9 +151,15 @@ void GodotArea2D::set_param(PhysicsServer2D::AreaParameter p_param, const Varian
 		case PhysicsServer2D::AREA_PARAM_GRAVITY_POINT_ATTENUATION:
 			point_attenuation = p_value;
 			break;
+		case PhysicsServer2D::AREA_PARAM_LINEAR_DAMP_OVERRIDE_MODE:
+			_set_space_override_mode(linear_damping_override_mode, (PhysicsServer2D::AreaSpaceOverrideMode)(int)p_value);
+			break;
 		case PhysicsServer2D::AREA_PARAM_LINEAR_DAMP:
 			linear_damp = p_value;
 			break;
+		case PhysicsServer2D::AREA_PARAM_ANGULAR_DAMP_OVERRIDE_MODE:
+			_set_space_override_mode(angular_damping_override_mode, (PhysicsServer2D::AreaSpaceOverrideMode)(int)p_value);
+			break;
 		case PhysicsServer2D::AREA_PARAM_ANGULAR_DAMP:
 			angular_damp = p_value;
 			break;
@@ -162,6 +171,8 @@ void GodotArea2D::set_param(PhysicsServer2D::AreaParameter p_param, const Varian
 
 Variant GodotArea2D::get_param(PhysicsServer2D::AreaParameter p_param) const {
 	switch (p_param) {
+		case PhysicsServer2D::AREA_PARAM_GRAVITY_OVERRIDE_MODE:
+			return gravity_override_mode;
 		case PhysicsServer2D::AREA_PARAM_GRAVITY:
 			return gravity;
 		case PhysicsServer2D::AREA_PARAM_GRAVITY_VECTOR:
@@ -172,8 +183,12 @@ Variant GodotArea2D::get_param(PhysicsServer2D::AreaParameter p_param) const {
 			return gravity_distance_scale;
 		case PhysicsServer2D::AREA_PARAM_GRAVITY_POINT_ATTENUATION:
 			return point_attenuation;
+		case PhysicsServer2D::AREA_PARAM_LINEAR_DAMP_OVERRIDE_MODE:
+			return linear_damping_override_mode;
 		case PhysicsServer2D::AREA_PARAM_LINEAR_DAMP:
 			return linear_damp;
+		case PhysicsServer2D::AREA_PARAM_ANGULAR_DAMP_OVERRIDE_MODE:
+			return angular_damping_override_mode;
 		case PhysicsServer2D::AREA_PARAM_ANGULAR_DAMP:
 			return angular_damp;
 		case PhysicsServer2D::AREA_PARAM_PRIORITY:

+ 6 - 4
servers/physics_2d/godot_area_2d.h

@@ -41,7 +41,10 @@ class GodotBody2D;
 class GodotConstraint2D;
 
 class GodotArea2D : public GodotCollisionObject2D {
-	PhysicsServer2D::AreaSpaceOverrideMode space_override_mode = PhysicsServer2D::AREA_SPACE_OVERRIDE_DISABLED;
+	PhysicsServer2D::AreaSpaceOverrideMode gravity_override_mode = PhysicsServer2D::AREA_SPACE_OVERRIDE_DISABLED;
+	PhysicsServer2D::AreaSpaceOverrideMode linear_damping_override_mode = PhysicsServer2D::AREA_SPACE_OVERRIDE_DISABLED;
+	PhysicsServer2D::AreaSpaceOverrideMode angular_damping_override_mode = PhysicsServer2D::AREA_SPACE_OVERRIDE_DISABLED;
+
 	real_t gravity = 9.80665;
 	Vector2 gravity_vector = Vector2(0, -1);
 	bool gravity_is_point = false;
@@ -96,6 +99,8 @@ class GodotArea2D : public GodotCollisionObject2D {
 	virtual void _shapes_changed();
 	void _queue_monitor_update();
 
+	void _set_space_override_mode(PhysicsServer2D::AreaSpaceOverrideMode &r_mode, PhysicsServer2D::AreaSpaceOverrideMode p_new_mode);
+
 public:
 	void set_monitor_callback(const Callable &p_callback);
 	_FORCE_INLINE_ bool has_monitor_callback() const { return !monitor_callback.is_null(); }
@@ -112,9 +117,6 @@ public:
 	void set_param(PhysicsServer2D::AreaParameter p_param, const Variant &p_value);
 	Variant get_param(PhysicsServer2D::AreaParameter p_param) const;
 
-	void set_space_override_mode(PhysicsServer2D::AreaSpaceOverrideMode p_mode);
-	PhysicsServer2D::AreaSpaceOverrideMode get_space_override_mode() const { return space_override_mode; }
-
 	_FORCE_INLINE_ void set_gravity(real_t p_gravity) { gravity = p_gravity; }
 	_FORCE_INLINE_ real_t get_gravity() const { return gravity; }
 

+ 14 - 6
servers/physics_2d/godot_area_pair_2d.cpp

@@ -38,10 +38,18 @@ bool GodotAreaPair2D::setup(real_t p_step) {
 	}
 
 	process_collision = false;
+	has_space_override = false;
 	if (result != colliding) {
-		if (area->get_space_override_mode() != PhysicsServer2D::AREA_SPACE_OVERRIDE_DISABLED) {
-			process_collision = true;
-		} else if (area->has_monitor_callback()) {
+		if ((int)area->get_param(PhysicsServer2D::AREA_PARAM_GRAVITY_OVERRIDE_MODE) != PhysicsServer2D::AREA_SPACE_OVERRIDE_DISABLED) {
+			has_space_override = true;
+		} else if ((int)area->get_param(PhysicsServer2D::AREA_PARAM_LINEAR_DAMP_OVERRIDE_MODE) != PhysicsServer2D::AREA_SPACE_OVERRIDE_DISABLED) {
+			has_space_override = true;
+		} else if ((int)area->get_param(PhysicsServer2D::AREA_PARAM_ANGULAR_DAMP_OVERRIDE_MODE) != PhysicsServer2D::AREA_SPACE_OVERRIDE_DISABLED) {
+			has_space_override = true;
+		}
+		process_collision = has_space_override;
+
+		if (area->has_monitor_callback()) {
 			process_collision = true;
 		}
 
@@ -57,7 +65,7 @@ bool GodotAreaPair2D::pre_solve(real_t p_step) {
 	}
 
 	if (colliding) {
-		if (area->get_space_override_mode() != PhysicsServer2D::AREA_SPACE_OVERRIDE_DISABLED) {
+		if (has_space_override) {
 			body->add_area(area);
 		}
 
@@ -65,7 +73,7 @@ bool GodotAreaPair2D::pre_solve(real_t p_step) {
 			area->add_body_to_query(body, body_shape, area_shape);
 		}
 	} else {
-		if (area->get_space_override_mode() != PhysicsServer2D::AREA_SPACE_OVERRIDE_DISABLED) {
+		if (has_space_override) {
 			body->remove_area(area);
 		}
 
@@ -95,7 +103,7 @@ GodotAreaPair2D::GodotAreaPair2D(GodotBody2D *p_body, int p_body_shape, GodotAre
 
 GodotAreaPair2D::~GodotAreaPair2D() {
 	if (colliding) {
-		if (area->get_space_override_mode() != PhysicsServer2D::AREA_SPACE_OVERRIDE_DISABLED) {
+		if (has_space_override) {
 			body->remove_area(area);
 		}
 		if (area->has_monitor_callback()) {

+ 1 - 0
servers/physics_2d/godot_area_pair_2d.h

@@ -41,6 +41,7 @@ class GodotAreaPair2D : public GodotConstraint2D {
 	int body_shape = 0;
 	int area_shape = 0;
 	bool colliding = false;
+	bool has_space_override = false;
 	bool process_collision = false;
 
 public:

+ 84 - 29
servers/physics_2d/godot_body_2d.cpp

@@ -410,15 +410,6 @@ void GodotBody2D::set_space(GodotSpace2D *p_space) {
 	}
 }
 
-void GodotBody2D::_compute_area_gravity_and_damping(const GodotArea2D *p_area) {
-	Vector2 area_gravity;
-	p_area->compute_gravity(get_transform().get_origin(), area_gravity);
-	gravity += area_gravity;
-
-	total_linear_damp += p_area->get_linear_damp();
-	total_angular_damp += p_area->get_angular_damp();
-}
-
 void GodotBody2D::_update_transform_dependent() {
 	center_of_mass = get_transform().basis_xform(center_of_mass_local);
 }
@@ -428,8 +419,16 @@ void GodotBody2D::integrate_forces(real_t p_step) {
 		return;
 	}
 
+	ERR_FAIL_COND(!get_space());
+
 	int ac = areas.size();
+
+	bool gravity_done = false;
+	bool linear_damp_done = false;
+	bool angular_damp_done = false;
+
 	bool stopped = false;
+
 	gravity = Vector2(0, 0);
 
 	total_linear_damp = 0.0;
@@ -440,33 +439,89 @@ void GodotBody2D::integrate_forces(real_t p_step) {
 		areas.sort();
 		const AreaCMP *aa = &areas[0];
 		for (int i = ac - 1; i >= 0 && !stopped; i--) {
-			PhysicsServer2D::AreaSpaceOverrideMode mode = aa[i].area->get_space_override_mode();
-			switch (mode) {
-				case PhysicsServer2D::AREA_SPACE_OVERRIDE_COMBINE:
-				case PhysicsServer2D::AREA_SPACE_OVERRIDE_COMBINE_REPLACE: {
-					_compute_area_gravity_and_damping(aa[i].area);
-					stopped = mode == PhysicsServer2D::AREA_SPACE_OVERRIDE_COMBINE_REPLACE;
-				} break;
-				case PhysicsServer2D::AREA_SPACE_OVERRIDE_REPLACE:
-				case PhysicsServer2D::AREA_SPACE_OVERRIDE_REPLACE_COMBINE: {
-					gravity = Vector2(0, 0);
-					total_linear_damp = 0.0;
-					total_angular_damp = 0.0;
-					_compute_area_gravity_and_damping(aa[i].area);
-					stopped = mode == PhysicsServer2D::AREA_SPACE_OVERRIDE_REPLACE;
-				} break;
-				default: {
+			if (!gravity_done) {
+				PhysicsServer2D::AreaSpaceOverrideMode area_gravity_mode = (PhysicsServer2D::AreaSpaceOverrideMode)(int)aa[i].area->get_param(PhysicsServer2D::AREA_PARAM_GRAVITY_OVERRIDE_MODE);
+				if (area_gravity_mode != PhysicsServer2D::AREA_SPACE_OVERRIDE_DISABLED) {
+					Vector2 area_gravity;
+					aa[i].area->compute_gravity(get_transform().get_origin(), area_gravity);
+					switch (area_gravity_mode) {
+						case PhysicsServer2D::AREA_SPACE_OVERRIDE_COMBINE:
+						case PhysicsServer2D::AREA_SPACE_OVERRIDE_COMBINE_REPLACE: {
+							gravity += area_gravity;
+							gravity_done = area_gravity_mode == PhysicsServer2D::AREA_SPACE_OVERRIDE_COMBINE_REPLACE;
+						} break;
+						case PhysicsServer2D::AREA_SPACE_OVERRIDE_REPLACE:
+						case PhysicsServer2D::AREA_SPACE_OVERRIDE_REPLACE_COMBINE: {
+							gravity = area_gravity;
+							gravity_done = area_gravity_mode == PhysicsServer2D::AREA_SPACE_OVERRIDE_REPLACE;
+						} break;
+						default: {
+						}
+					}
 				}
 			}
+			if (!linear_damp_done) {
+				PhysicsServer2D::AreaSpaceOverrideMode area_linear_damp_mode = (PhysicsServer2D::AreaSpaceOverrideMode)(int)aa[i].area->get_param(PhysicsServer2D::AREA_PARAM_LINEAR_DAMP_OVERRIDE_MODE);
+				if (area_linear_damp_mode != PhysicsServer2D::AREA_SPACE_OVERRIDE_DISABLED) {
+					real_t area_linear_damp = aa[i].area->get_linear_damp();
+					switch (area_linear_damp_mode) {
+						case PhysicsServer2D::AREA_SPACE_OVERRIDE_COMBINE:
+						case PhysicsServer2D::AREA_SPACE_OVERRIDE_COMBINE_REPLACE: {
+							total_linear_damp += area_linear_damp;
+							linear_damp_done = area_linear_damp_mode == PhysicsServer2D::AREA_SPACE_OVERRIDE_COMBINE_REPLACE;
+						} break;
+						case PhysicsServer2D::AREA_SPACE_OVERRIDE_REPLACE:
+						case PhysicsServer2D::AREA_SPACE_OVERRIDE_REPLACE_COMBINE: {
+							total_linear_damp = area_linear_damp;
+							linear_damp_done = area_linear_damp_mode == PhysicsServer2D::AREA_SPACE_OVERRIDE_REPLACE;
+						} break;
+						default: {
+						}
+					}
+				}
+			}
+			if (!angular_damp_done) {
+				PhysicsServer2D::AreaSpaceOverrideMode area_angular_damp_mode = (PhysicsServer2D::AreaSpaceOverrideMode)(int)aa[i].area->get_param(PhysicsServer2D::AREA_PARAM_ANGULAR_DAMP_OVERRIDE_MODE);
+				if (area_angular_damp_mode != PhysicsServer2D::AREA_SPACE_OVERRIDE_DISABLED) {
+					real_t area_angular_damp = aa[i].area->get_angular_damp();
+					switch (area_angular_damp_mode) {
+						case PhysicsServer2D::AREA_SPACE_OVERRIDE_COMBINE:
+						case PhysicsServer2D::AREA_SPACE_OVERRIDE_COMBINE_REPLACE: {
+							total_angular_damp += area_angular_damp;
+							angular_damp_done = area_angular_damp_mode == PhysicsServer2D::AREA_SPACE_OVERRIDE_COMBINE_REPLACE;
+						} break;
+						case PhysicsServer2D::AREA_SPACE_OVERRIDE_REPLACE:
+						case PhysicsServer2D::AREA_SPACE_OVERRIDE_REPLACE_COMBINE: {
+							total_angular_damp = area_angular_damp;
+							angular_damp_done = area_angular_damp_mode == PhysicsServer2D::AREA_SPACE_OVERRIDE_REPLACE;
+						} break;
+						default: {
+						}
+					}
+				}
+			}
+			stopped = gravity_done && linear_damp_done && angular_damp_done;
 		}
 	}
 
-	// Override linear damping with body's value.
+	// Add default gravity and damping from space area.
 	if (!stopped) {
-		GodotArea2D *def_area = get_space()->get_default_area();
-		ERR_FAIL_COND(!def_area);
+		GodotArea2D *default_area = get_space()->get_default_area();
+		ERR_FAIL_COND(!default_area);
 
-		_compute_area_gravity_and_damping(def_area);
+		if (!gravity_done) {
+			Vector2 default_gravity;
+			default_area->compute_gravity(get_transform().get_origin(), default_gravity);
+			gravity += default_gravity;
+		}
+
+		if (!linear_damp_done) {
+			total_linear_damp += default_area->get_linear_damp();
+		}
+
+		if (!angular_damp_done) {
+			total_angular_damp += default_area->get_angular_damp();
+		}
 	}
 
 	// Override linear damping with body's value.

+ 0 - 2
servers/physics_2d/godot_body_2d.h

@@ -145,8 +145,6 @@ class GodotBody2D : public GodotCollisionObject2D {
 
 	uint64_t island_step = 0;
 
-	void _compute_area_gravity_and_damping(const GodotArea2D *p_area);
-
 	void _update_transform_dependent();
 
 	friend class GodotPhysicsDirectBodyState2D; // i give up, too many functions to expose

+ 2 - 16
servers/physics_2d/godot_physics_server_2d.cpp

@@ -289,7 +289,7 @@ RID GodotPhysicsServer2D::area_create() {
 	RID rid = area_owner.make_rid(area);
 	area->set_self(rid);
 	return rid;
-};
+}
 
 void GodotPhysicsServer2D::area_set_space(RID p_area, RID p_space) {
 	GodotArea2D *area = area_owner.get_or_null(p_area);
@@ -307,7 +307,7 @@ void GodotPhysicsServer2D::area_set_space(RID p_area, RID p_space) {
 
 	area->clear_constraints();
 	area->set_space(space);
-};
+}
 
 RID GodotPhysicsServer2D::area_get_space(RID p_area) const {
 	GodotArea2D *area = area_owner.get_or_null(p_area);
@@ -318,20 +318,6 @@ RID GodotPhysicsServer2D::area_get_space(RID p_area) const {
 		return RID();
 	}
 	return space->get_self();
-};
-
-void GodotPhysicsServer2D::area_set_space_override_mode(RID p_area, AreaSpaceOverrideMode p_mode) {
-	GodotArea2D *area = area_owner.get_or_null(p_area);
-	ERR_FAIL_COND(!area);
-
-	area->set_space_override_mode(p_mode);
-}
-
-PhysicsServer2D::AreaSpaceOverrideMode GodotPhysicsServer2D::area_get_space_override_mode(RID p_area) const {
-	const GodotArea2D *area = area_owner.get_or_null(p_area);
-	ERR_FAIL_COND_V(!area, AREA_SPACE_OVERRIDE_DISABLED);
-
-	return area->get_space_override_mode();
 }
 
 void GodotPhysicsServer2D::area_add_shape(RID p_area, RID p_shape, const Transform2D &p_transform, bool p_disabled) {

+ 0 - 3
servers/physics_2d/godot_physics_server_2d.h

@@ -124,9 +124,6 @@ public:
 
 	virtual RID area_create() override;
 
-	virtual void area_set_space_override_mode(RID p_area, AreaSpaceOverrideMode p_mode) override;
-	virtual AreaSpaceOverrideMode area_get_space_override_mode(RID p_area) const override;
-
 	virtual void area_set_space(RID p_area, RID p_space) override;
 	virtual RID area_get_space(RID p_area) const override;
 

+ 19 - 4
servers/physics_3d/godot_area_3d.cpp

@@ -128,18 +128,21 @@ void GodotArea3D::set_area_monitor_callback(const Callable &p_callback) {
 	}
 }
 
-void GodotArea3D::set_space_override_mode(PhysicsServer3D::AreaSpaceOverrideMode p_mode) {
-	bool do_override = p_mode != PhysicsServer3D::AREA_SPACE_OVERRIDE_DISABLED;
-	if (do_override == (space_override_mode != PhysicsServer3D::AREA_SPACE_OVERRIDE_DISABLED)) {
+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)) {
 		return;
 	}
 	_unregister_shapes();
-	space_override_mode = p_mode;
+	r_mode = p_new_mode;
 	_shape_changed();
 }
 
 void GodotArea3D::set_param(PhysicsServer3D::AreaParameter p_param, const Variant &p_value) {
 	switch (p_param) {
+		case PhysicsServer3D::AREA_PARAM_GRAVITY_OVERRIDE_MODE:
+			_set_space_override_mode(gravity_override_mode, (PhysicsServer3D::AreaSpaceOverrideMode)(int)p_value);
+			break;
 		case PhysicsServer3D::AREA_PARAM_GRAVITY:
 			gravity = p_value;
 			break;
@@ -155,9 +158,15 @@ void GodotArea3D::set_param(PhysicsServer3D::AreaParameter p_param, const Varian
 		case PhysicsServer3D::AREA_PARAM_GRAVITY_POINT_ATTENUATION:
 			point_attenuation = p_value;
 			break;
+		case PhysicsServer3D::AREA_PARAM_LINEAR_DAMP_OVERRIDE_MODE:
+			_set_space_override_mode(linear_damping_override_mode, (PhysicsServer3D::AreaSpaceOverrideMode)(int)p_value);
+			break;
 		case PhysicsServer3D::AREA_PARAM_LINEAR_DAMP:
 			linear_damp = p_value;
 			break;
+		case PhysicsServer3D::AREA_PARAM_ANGULAR_DAMP_OVERRIDE_MODE:
+			_set_space_override_mode(angular_damping_override_mode, (PhysicsServer3D::AreaSpaceOverrideMode)(int)p_value);
+			break;
 		case PhysicsServer3D::AREA_PARAM_ANGULAR_DAMP:
 			angular_damp = p_value;
 			break;
@@ -183,6 +192,8 @@ void GodotArea3D::set_param(PhysicsServer3D::AreaParameter p_param, const Varian
 
 Variant GodotArea3D::get_param(PhysicsServer3D::AreaParameter p_param) const {
 	switch (p_param) {
+		case PhysicsServer3D::AREA_PARAM_GRAVITY_OVERRIDE_MODE:
+			return gravity_override_mode;
 		case PhysicsServer3D::AREA_PARAM_GRAVITY:
 			return gravity;
 		case PhysicsServer3D::AREA_PARAM_GRAVITY_VECTOR:
@@ -193,8 +204,12 @@ Variant GodotArea3D::get_param(PhysicsServer3D::AreaParameter p_param) const {
 			return gravity_distance_scale;
 		case PhysicsServer3D::AREA_PARAM_GRAVITY_POINT_ATTENUATION:
 			return point_attenuation;
+		case PhysicsServer3D::AREA_PARAM_LINEAR_DAMP_OVERRIDE_MODE:
+			return linear_damping_override_mode;
 		case PhysicsServer3D::AREA_PARAM_LINEAR_DAMP:
 			return linear_damp;
+		case PhysicsServer3D::AREA_PARAM_ANGULAR_DAMP_OVERRIDE_MODE:
+			return angular_damping_override_mode;
 		case PhysicsServer3D::AREA_PARAM_ANGULAR_DAMP:
 			return angular_damp;
 		case PhysicsServer3D::AREA_PARAM_PRIORITY:

+ 6 - 4
servers/physics_3d/godot_area_3d.h

@@ -42,7 +42,10 @@ class GodotSoftBody3D;
 class GodotConstraint3D;
 
 class GodotArea3D : public GodotCollisionObject3D {
-	PhysicsServer3D::AreaSpaceOverrideMode space_override_mode = PhysicsServer3D::AREA_SPACE_OVERRIDE_DISABLED;
+	PhysicsServer3D::AreaSpaceOverrideMode gravity_override_mode = PhysicsServer3D::AREA_SPACE_OVERRIDE_DISABLED;
+	PhysicsServer3D::AreaSpaceOverrideMode linear_damping_override_mode = PhysicsServer3D::AREA_SPACE_OVERRIDE_DISABLED;
+	PhysicsServer3D::AreaSpaceOverrideMode angular_damping_override_mode = PhysicsServer3D::AREA_SPACE_OVERRIDE_DISABLED;
+
 	real_t gravity = 9.80665;
 	Vector3 gravity_vector = Vector3(0, -1, 0);
 	bool gravity_is_point = false;
@@ -102,6 +105,8 @@ class GodotArea3D : public GodotCollisionObject3D {
 	virtual void _shapes_changed();
 	void _queue_monitor_update();
 
+	void _set_space_override_mode(PhysicsServer3D::AreaSpaceOverrideMode &r_mode, PhysicsServer3D::AreaSpaceOverrideMode p_new_mode);
+
 public:
 	void set_monitor_callback(const Callable &p_callback);
 	_FORCE_INLINE_ bool has_monitor_callback() const { return !monitor_callback.is_null(); }
@@ -121,9 +126,6 @@ public:
 	void set_param(PhysicsServer3D::AreaParameter p_param, const Variant &p_value);
 	Variant get_param(PhysicsServer3D::AreaParameter p_param) const;
 
-	void set_space_override_mode(PhysicsServer3D::AreaSpaceOverrideMode p_mode);
-	PhysicsServer3D::AreaSpaceOverrideMode get_space_override_mode() const { return space_override_mode; }
-
 	_FORCE_INLINE_ void set_gravity(real_t p_gravity) { gravity = p_gravity; }
 	_FORCE_INLINE_ real_t get_gravity() const { return gravity; }
 

+ 25 - 12
servers/physics_3d/godot_area_pair_3d.cpp

@@ -39,10 +39,18 @@ bool GodotAreaPair3D::setup(real_t p_step) {
 	}
 
 	process_collision = false;
+	has_space_override = false;
 	if (result != colliding) {
-		if (area->get_space_override_mode() != PhysicsServer3D::AREA_SPACE_OVERRIDE_DISABLED) {
-			process_collision = true;
-		} else if (area->has_monitor_callback()) {
+		if ((int)area->get_param(PhysicsServer3D::AREA_PARAM_GRAVITY_OVERRIDE_MODE) != PhysicsServer3D::AREA_SPACE_OVERRIDE_DISABLED) {
+			has_space_override = true;
+		} else if ((int)area->get_param(PhysicsServer3D::AREA_PARAM_LINEAR_DAMP_OVERRIDE_MODE) != PhysicsServer3D::AREA_SPACE_OVERRIDE_DISABLED) {
+			has_space_override = true;
+		} else if ((int)area->get_param(PhysicsServer3D::AREA_PARAM_ANGULAR_DAMP_OVERRIDE_MODE) != PhysicsServer3D::AREA_SPACE_OVERRIDE_DISABLED) {
+			has_space_override = true;
+		}
+		process_collision = has_space_override;
+
+		if (area->has_monitor_callback()) {
 			process_collision = true;
 		}
 
@@ -58,7 +66,7 @@ bool GodotAreaPair3D::pre_solve(real_t p_step) {
 	}
 
 	if (colliding) {
-		if (area->get_space_override_mode() != PhysicsServer3D::AREA_SPACE_OVERRIDE_DISABLED) {
+		if (has_space_override) {
 			body->add_area(area);
 		}
 
@@ -66,7 +74,7 @@ bool GodotAreaPair3D::pre_solve(real_t p_step) {
 			area->add_body_to_query(body, body_shape, area_shape);
 		}
 	} else {
-		if (area->get_space_override_mode() != PhysicsServer3D::AREA_SPACE_OVERRIDE_DISABLED) {
+		if (has_space_override) {
 			body->remove_area(area);
 		}
 
@@ -96,7 +104,7 @@ GodotAreaPair3D::GodotAreaPair3D(GodotBody3D *p_body, int p_body_shape, GodotAre
 
 GodotAreaPair3D::~GodotAreaPair3D() {
 	if (colliding) {
-		if (area->get_space_override_mode() != PhysicsServer3D::AREA_SPACE_OVERRIDE_DISABLED) {
+		if (has_space_override) {
 			body->remove_area(area);
 		}
 		if (area->has_monitor_callback()) {
@@ -207,10 +215,15 @@ bool GodotAreaSoftBodyPair3D::setup(real_t p_step) {
 	}
 
 	process_collision = false;
+	has_space_override = false;
 	if (result != colliding) {
-		if (area->get_space_override_mode() != PhysicsServer3D::AREA_SPACE_OVERRIDE_DISABLED) {
-			process_collision = true;
-		} else if (area->has_monitor_callback()) {
+		if ((int)area->get_param(PhysicsServer3D::AREA_PARAM_GRAVITY_OVERRIDE_MODE) != PhysicsServer3D::AREA_SPACE_OVERRIDE_DISABLED) {
+			has_space_override = true;
+		} else if (area->get_wind_force_magnitude() > CMP_EPSILON) {
+			has_space_override = true;
+		}
+
+		if (area->has_monitor_callback()) {
 			process_collision = true;
 		}
 
@@ -226,7 +239,7 @@ bool GodotAreaSoftBodyPair3D::pre_solve(real_t p_step) {
 	}
 
 	if (colliding) {
-		if (area->get_space_override_mode() != PhysicsServer3D::AREA_SPACE_OVERRIDE_DISABLED) {
+		if (has_space_override) {
 			soft_body->add_area(area);
 		}
 
@@ -234,7 +247,7 @@ bool GodotAreaSoftBodyPair3D::pre_solve(real_t p_step) {
 			area->add_soft_body_to_query(soft_body, soft_body_shape, area_shape);
 		}
 	} else {
-		if (area->get_space_override_mode() != PhysicsServer3D::AREA_SPACE_OVERRIDE_DISABLED) {
+		if (has_space_override) {
 			soft_body->remove_area(area);
 		}
 
@@ -261,7 +274,7 @@ GodotAreaSoftBodyPair3D::GodotAreaSoftBodyPair3D(GodotSoftBody3D *p_soft_body, i
 
 GodotAreaSoftBodyPair3D::~GodotAreaSoftBodyPair3D() {
 	if (colliding) {
-		if (area->get_space_override_mode() != PhysicsServer3D::AREA_SPACE_OVERRIDE_DISABLED) {
+		if (has_space_override) {
 			soft_body->remove_area(area);
 		}
 		if (area->has_monitor_callback()) {

+ 2 - 0
servers/physics_3d/godot_area_pair_3d.h

@@ -43,6 +43,7 @@ class GodotAreaPair3D : public GodotConstraint3D {
 	int area_shape;
 	bool colliding = false;
 	bool process_collision = false;
+	bool has_space_override = false;
 
 public:
 	virtual bool setup(real_t p_step) override;
@@ -79,6 +80,7 @@ class GodotAreaSoftBodyPair3D : public GodotConstraint3D {
 	int area_shape;
 	bool colliding = false;
 	bool process_collision = false;
+	bool has_space_override = false;
 
 public:
 	virtual bool setup(real_t p_step) override;

+ 83 - 28
servers/physics_3d/godot_body_3d.cpp

@@ -457,15 +457,6 @@ void GodotBody3D::set_space(GodotSpace3D *p_space) {
 	}
 }
 
-void GodotBody3D::_compute_area_gravity_and_damping(const GodotArea3D *p_area) {
-	Vector3 area_gravity;
-	p_area->compute_gravity(get_transform().get_origin(), area_gravity);
-	gravity += area_gravity;
-
-	total_linear_damp += p_area->get_linear_damp();
-	total_angular_damp += p_area->get_angular_damp();
-}
-
 void GodotBody3D::set_axis_lock(PhysicsServer3D::BodyAxis p_axis, bool lock) {
 	if (lock) {
 		locked_axis |= p_axis;
@@ -483,8 +474,16 @@ void GodotBody3D::integrate_forces(real_t p_step) {
 		return;
 	}
 
+	ERR_FAIL_COND(!get_space());
+
 	int ac = areas.size();
+
+	bool gravity_done = false;
+	bool linear_damp_done = false;
+	bool angular_damp_done = false;
+
 	bool stopped = false;
+
 	gravity = Vector3(0, 0, 0);
 
 	total_linear_damp = 0.0;
@@ -495,33 +494,89 @@ void GodotBody3D::integrate_forces(real_t p_step) {
 		areas.sort();
 		const AreaCMP *aa = &areas[0];
 		for (int i = ac - 1; i >= 0 && !stopped; i--) {
-			PhysicsServer3D::AreaSpaceOverrideMode mode = aa[i].area->get_space_override_mode();
-			switch (mode) {
-				case PhysicsServer3D::AREA_SPACE_OVERRIDE_COMBINE:
-				case PhysicsServer3D::AREA_SPACE_OVERRIDE_COMBINE_REPLACE: {
-					_compute_area_gravity_and_damping(aa[i].area);
-					stopped = mode == PhysicsServer3D::AREA_SPACE_OVERRIDE_COMBINE_REPLACE;
-				} break;
-				case PhysicsServer3D::AREA_SPACE_OVERRIDE_REPLACE:
-				case PhysicsServer3D::AREA_SPACE_OVERRIDE_REPLACE_COMBINE: {
-					gravity = Vector3(0, 0, 0);
-					total_linear_damp = 0.0;
-					total_angular_damp = 0.0;
-					_compute_area_gravity_and_damping(aa[i].area);
-					stopped = mode == PhysicsServer3D::AREA_SPACE_OVERRIDE_REPLACE;
-				} break;
-				default: {
+			if (!gravity_done) {
+				PhysicsServer3D::AreaSpaceOverrideMode area_gravity_mode = (PhysicsServer3D::AreaSpaceOverrideMode)(int)aa[i].area->get_param(PhysicsServer3D::AREA_PARAM_GRAVITY_OVERRIDE_MODE);
+				if (area_gravity_mode != PhysicsServer3D::AREA_SPACE_OVERRIDE_DISABLED) {
+					Vector3 area_gravity;
+					aa[i].area->compute_gravity(get_transform().get_origin(), area_gravity);
+					switch (area_gravity_mode) {
+						case PhysicsServer3D::AREA_SPACE_OVERRIDE_COMBINE:
+						case PhysicsServer3D::AREA_SPACE_OVERRIDE_COMBINE_REPLACE: {
+							gravity += area_gravity;
+							gravity_done = area_gravity_mode == PhysicsServer3D::AREA_SPACE_OVERRIDE_COMBINE_REPLACE;
+						} break;
+						case PhysicsServer3D::AREA_SPACE_OVERRIDE_REPLACE:
+						case PhysicsServer3D::AREA_SPACE_OVERRIDE_REPLACE_COMBINE: {
+							gravity = area_gravity;
+							gravity_done = area_gravity_mode == PhysicsServer3D::AREA_SPACE_OVERRIDE_REPLACE;
+						} break;
+						default: {
+						}
+					}
+				}
+			}
+			if (!linear_damp_done) {
+				PhysicsServer3D::AreaSpaceOverrideMode area_linear_damp_mode = (PhysicsServer3D::AreaSpaceOverrideMode)(int)aa[i].area->get_param(PhysicsServer3D::AREA_PARAM_LINEAR_DAMP_OVERRIDE_MODE);
+				if (area_linear_damp_mode != PhysicsServer3D::AREA_SPACE_OVERRIDE_DISABLED) {
+					real_t area_linear_damp = aa[i].area->get_linear_damp();
+					switch (area_linear_damp_mode) {
+						case PhysicsServer3D::AREA_SPACE_OVERRIDE_COMBINE:
+						case PhysicsServer3D::AREA_SPACE_OVERRIDE_COMBINE_REPLACE: {
+							total_linear_damp += area_linear_damp;
+							linear_damp_done = area_linear_damp_mode == PhysicsServer3D::AREA_SPACE_OVERRIDE_COMBINE_REPLACE;
+						} break;
+						case PhysicsServer3D::AREA_SPACE_OVERRIDE_REPLACE:
+						case PhysicsServer3D::AREA_SPACE_OVERRIDE_REPLACE_COMBINE: {
+							total_linear_damp = area_linear_damp;
+							linear_damp_done = area_linear_damp_mode == PhysicsServer3D::AREA_SPACE_OVERRIDE_REPLACE;
+						} break;
+						default: {
+						}
+					}
+				}
+			}
+			if (!angular_damp_done) {
+				PhysicsServer3D::AreaSpaceOverrideMode area_angular_damp_mode = (PhysicsServer3D::AreaSpaceOverrideMode)(int)aa[i].area->get_param(PhysicsServer3D::AREA_PARAM_ANGULAR_DAMP_OVERRIDE_MODE);
+				if (area_angular_damp_mode != PhysicsServer3D::AREA_SPACE_OVERRIDE_DISABLED) {
+					real_t area_angular_damp = aa[i].area->get_angular_damp();
+					switch (area_angular_damp_mode) {
+						case PhysicsServer3D::AREA_SPACE_OVERRIDE_COMBINE:
+						case PhysicsServer3D::AREA_SPACE_OVERRIDE_COMBINE_REPLACE: {
+							total_angular_damp += area_angular_damp;
+							angular_damp_done = area_angular_damp_mode == PhysicsServer3D::AREA_SPACE_OVERRIDE_COMBINE_REPLACE;
+						} break;
+						case PhysicsServer3D::AREA_SPACE_OVERRIDE_REPLACE:
+						case PhysicsServer3D::AREA_SPACE_OVERRIDE_REPLACE_COMBINE: {
+							total_angular_damp = area_angular_damp;
+							angular_damp_done = area_angular_damp_mode == PhysicsServer3D::AREA_SPACE_OVERRIDE_REPLACE;
+						} break;
+						default: {
+						}
+					}
 				}
 			}
+			stopped = gravity_done && linear_damp_done && angular_damp_done;
 		}
 	}
 
 	// Add default gravity and damping from space area.
 	if (!stopped) {
-		GodotArea3D *def_area = get_space()->get_default_area();
-		ERR_FAIL_COND(!def_area);
+		GodotArea3D *default_area = get_space()->get_default_area();
+		ERR_FAIL_COND(!default_area);
 
-		_compute_area_gravity_and_damping(def_area);
+		if (!gravity_done) {
+			Vector3 default_gravity;
+			default_area->compute_gravity(get_transform().get_origin(), default_gravity);
+			gravity += default_gravity;
+		}
+
+		if (!linear_damp_done) {
+			total_linear_damp += default_area->get_linear_damp();
+		}
+
+		if (!angular_damp_done) {
+			total_angular_damp += default_area->get_angular_damp();
+		}
 	}
 
 	// Override linear damping with body's value.

+ 0 - 2
servers/physics_3d/godot_body_3d.h

@@ -139,8 +139,6 @@ class GodotBody3D : public GodotCollisionObject3D {
 
 	uint64_t island_step = 0;
 
-	void _compute_area_gravity_and_damping(const GodotArea3D *p_area);
-
 	void _update_transform_dependent();
 
 	friend class GodotPhysicsDirectBodyState3D; // i give up, too many functions to expose

+ 2 - 16
servers/physics_3d/godot_physics_server_3d.cpp

@@ -219,7 +219,7 @@ RID GodotPhysicsServer3D::area_create() {
 	RID rid = area_owner.make_rid(area);
 	area->set_self(rid);
 	return rid;
-};
+}
 
 void GodotPhysicsServer3D::area_set_space(RID p_area, RID p_space) {
 	GodotArea3D *area = area_owner.get_or_null(p_area);
@@ -237,7 +237,7 @@ void GodotPhysicsServer3D::area_set_space(RID p_area, RID p_space) {
 
 	area->clear_constraints();
 	area->set_space(space);
-};
+}
 
 RID GodotPhysicsServer3D::area_get_space(RID p_area) const {
 	GodotArea3D *area = area_owner.get_or_null(p_area);
@@ -248,20 +248,6 @@ RID GodotPhysicsServer3D::area_get_space(RID p_area) const {
 		return RID();
 	}
 	return space->get_self();
-};
-
-void GodotPhysicsServer3D::area_set_space_override_mode(RID p_area, AreaSpaceOverrideMode p_mode) {
-	GodotArea3D *area = area_owner.get_or_null(p_area);
-	ERR_FAIL_COND(!area);
-
-	area->set_space_override_mode(p_mode);
-}
-
-PhysicsServer3D::AreaSpaceOverrideMode GodotPhysicsServer3D::area_get_space_override_mode(RID p_area) const {
-	const GodotArea3D *area = area_owner.get_or_null(p_area);
-	ERR_FAIL_COND_V(!area, AREA_SPACE_OVERRIDE_DISABLED);
-
-	return area->get_space_override_mode();
 }
 
 void GodotPhysicsServer3D::area_add_shape(RID p_area, RID p_shape, const Transform3D &p_transform, bool p_disabled) {

+ 0 - 3
servers/physics_3d/godot_physics_server_3d.h

@@ -122,9 +122,6 @@ public:
 
 	virtual RID area_create() override;
 
-	virtual void area_set_space_override_mode(RID p_area, AreaSpaceOverrideMode p_mode) override;
-	virtual AreaSpaceOverrideMode area_get_space_override_mode(RID p_area) const override;
-
 	virtual void area_set_space(RID p_area, RID p_space) override;
 	virtual RID area_get_space(RID p_area) const override;
 

+ 46 - 48
servers/physics_3d/godot_soft_body_3d.cpp

@@ -917,9 +917,7 @@ void GodotSoftBody3D::add_velocity(const Vector3 &p_velocity) {
 	}
 }
 
-void GodotSoftBody3D::apply_forces(bool p_has_wind_forces) {
-	int ac = areas.size();
-
+void GodotSoftBody3D::apply_forces(const LocalVector<GodotArea3D *> &p_wind_areas) {
 	if (nodes.is_empty()) {
 		return;
 	}
@@ -932,7 +930,6 @@ void GodotSoftBody3D::apply_forces(bool p_has_wind_forces) {
 
 	// Iterate over faces (try not to iterate elsewhere if possible).
 	for (i = 0, ni = faces.size(); i < ni; ++i) {
-		bool stopped = false;
 		const Face &face = faces[i];
 
 		Vector3 wind_force(0, 0, 0);
@@ -941,24 +938,10 @@ void GodotSoftBody3D::apply_forces(bool p_has_wind_forces) {
 		volume += vec3_dot(face.n[0]->x - org, vec3_cross(face.n[1]->x - org, face.n[2]->x - org));
 
 		// Compute nodal forces from area winds.
-		if (ac && p_has_wind_forces) {
-			const AreaCMP *aa = &areas[0];
-			for (j = ac - 1; j >= 0 && !stopped; j--) {
-				PhysicsServer3D::AreaSpaceOverrideMode mode = aa[j].area->get_space_override_mode();
-				switch (mode) {
-					case PhysicsServer3D::AREA_SPACE_OVERRIDE_COMBINE:
-					case PhysicsServer3D::AREA_SPACE_OVERRIDE_COMBINE_REPLACE: {
-						wind_force += _compute_area_windforce(aa[j].area, &face);
-						stopped = mode == PhysicsServer3D::AREA_SPACE_OVERRIDE_COMBINE_REPLACE;
-					} break;
-					case PhysicsServer3D::AREA_SPACE_OVERRIDE_REPLACE:
-					case PhysicsServer3D::AREA_SPACE_OVERRIDE_REPLACE_COMBINE: {
-						wind_force = _compute_area_windforce(aa[j].area, &face);
-						stopped = mode == PhysicsServer3D::AREA_SPACE_OVERRIDE_REPLACE;
-					} break;
-					default: {
-					}
-				}
+		int wind_area_count = p_wind_areas.size();
+		if (wind_area_count > 0) {
+			for (j = 0; j < wind_area_count; j++) {
+				wind_force += _compute_area_windforce(p_wind_areas[j], &face);
 			}
 
 			for (j = 0; j < 3; j++) {
@@ -1004,44 +987,59 @@ void GodotSoftBody3D::predict_motion(real_t p_delta) {
 
 	ERR_FAIL_COND(!get_space());
 
-	GodotArea3D *def_area = get_space()->get_default_area();
-	ERR_FAIL_COND(!def_area);
-	gravity = def_area->get_gravity_vector() * def_area->get_gravity();
-
 	int ac = areas.size();
-	bool stopped = false;
-	bool has_wind_forces = false;
+
+	bool gravity_done = false;
+
+	LocalVector<GodotArea3D *> wind_areas;
 
 	if (ac) {
 		areas.sort();
 		const AreaCMP *aa = &areas[0];
-		for (int i = ac - 1; i >= 0 && !stopped; i--) {
-			// Avoids unnecessary loop in apply_forces().
-			has_wind_forces = has_wind_forces || aa[i].area->get_wind_force_magnitude() > CMP_EPSILON;
-
-			PhysicsServer3D::AreaSpaceOverrideMode mode = aa[i].area->get_space_override_mode();
-			switch (mode) {
-				case PhysicsServer3D::AREA_SPACE_OVERRIDE_COMBINE:
-				case PhysicsServer3D::AREA_SPACE_OVERRIDE_COMBINE_REPLACE: {
-					_compute_area_gravity(aa[i].area);
-					stopped = mode == PhysicsServer3D::AREA_SPACE_OVERRIDE_COMBINE_REPLACE;
-				} break;
-				case PhysicsServer3D::AREA_SPACE_OVERRIDE_REPLACE:
-				case PhysicsServer3D::AREA_SPACE_OVERRIDE_REPLACE_COMBINE: {
-					gravity = Vector3(0, 0, 0);
-					_compute_area_gravity(aa[i].area);
-					stopped = mode == PhysicsServer3D::AREA_SPACE_OVERRIDE_REPLACE;
-				} break;
-				default: {
+		for (int i = ac - 1; i >= 0; i--) {
+			if (!gravity_done) {
+				PhysicsServer3D::AreaSpaceOverrideMode area_gravity_mode = (PhysicsServer3D::AreaSpaceOverrideMode)(int)aa[i].area->get_param(PhysicsServer3D::AREA_PARAM_GRAVITY_OVERRIDE_MODE);
+				if (area_gravity_mode != PhysicsServer3D::AREA_SPACE_OVERRIDE_DISABLED) {
+					Vector3 area_gravity;
+					aa[i].area->compute_gravity(get_transform().get_origin(), area_gravity);
+					switch (area_gravity_mode) {
+						case PhysicsServer3D::AREA_SPACE_OVERRIDE_COMBINE:
+						case PhysicsServer3D::AREA_SPACE_OVERRIDE_COMBINE_REPLACE: {
+							gravity += area_gravity;
+							gravity_done = area_gravity_mode == PhysicsServer3D::AREA_SPACE_OVERRIDE_COMBINE_REPLACE;
+						} break;
+						case PhysicsServer3D::AREA_SPACE_OVERRIDE_REPLACE:
+						case PhysicsServer3D::AREA_SPACE_OVERRIDE_REPLACE_COMBINE: {
+							gravity = Vector3(0, 0, 0);
+							gravity = area_gravity;
+							gravity_done = area_gravity_mode == PhysicsServer3D::AREA_SPACE_OVERRIDE_REPLACE;
+						} break;
+						default: {
+						}
+					}
 				}
 			}
+
+			if (aa[i].area->get_wind_force_magnitude() > CMP_EPSILON) {
+				wind_areas.push_back(aa[i].area);
+			}
 		}
 	}
 
+	// Add default gravity and damping from space area.
+	if (!gravity_done) {
+		GodotArea3D *default_area = get_space()->get_default_area();
+		ERR_FAIL_COND(!default_area);
+
+		Vector3 default_gravity;
+		default_area->compute_gravity(get_transform().get_origin(), default_gravity);
+		gravity += default_gravity;
+	}
+
 	// Apply forces.
 	add_velocity(gravity * p_delta);
-	if (pressure_coefficient > CMP_EPSILON || has_wind_forces) {
-		apply_forces(has_wind_forces);
+	if (pressure_coefficient > CMP_EPSILON || !wind_areas.is_empty()) {
+		apply_forces(wind_areas);
 	}
 
 	// Avoid soft body from 'exploding' so use some upper threshold of maximum motion

+ 1 - 1
servers/physics_3d/godot_soft_body_3d.h

@@ -232,7 +232,7 @@ private:
 
 	void add_velocity(const Vector3 &p_velocity);
 
-	void apply_forces(bool p_has_wind_forces);
+	void apply_forces(const LocalVector<GodotArea3D *> &p_wind_areas);
 
 	bool create_from_trimesh(const Vector<int> &p_indices, const Vector<Vector3> &p_vertices);
 	void generate_bending_constraints(int p_distance);

+ 3 - 3
servers/physics_server_2d.cpp

@@ -605,9 +605,6 @@ void PhysicsServer2D::_bind_methods() {
 	ClassDB::bind_method(D_METHOD("area_set_space", "area", "space"), &PhysicsServer2D::area_set_space);
 	ClassDB::bind_method(D_METHOD("area_get_space", "area"), &PhysicsServer2D::area_get_space);
 
-	ClassDB::bind_method(D_METHOD("area_set_space_override_mode", "area", "mode"), &PhysicsServer2D::area_set_space_override_mode);
-	ClassDB::bind_method(D_METHOD("area_get_space_override_mode", "area"), &PhysicsServer2D::area_get_space_override_mode);
-
 	ClassDB::bind_method(D_METHOD("area_add_shape", "area", "shape", "transform", "disabled"), &PhysicsServer2D::area_add_shape, DEFVAL(Transform2D()), DEFVAL(false));
 	ClassDB::bind_method(D_METHOD("area_set_shape", "area", "shape_idx", "shape"), &PhysicsServer2D::area_set_shape);
 	ClassDB::bind_method(D_METHOD("area_set_shape_transform", "area", "shape_idx", "transform"), &PhysicsServer2D::area_set_shape_transform);
@@ -751,12 +748,15 @@ void PhysicsServer2D::_bind_methods() {
 	BIND_ENUM_CONSTANT(SHAPE_CONCAVE_POLYGON);
 	BIND_ENUM_CONSTANT(SHAPE_CUSTOM);
 
+	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_IS_POINT);
 	BIND_ENUM_CONSTANT(AREA_PARAM_GRAVITY_DISTANCE_SCALE);
 	BIND_ENUM_CONSTANT(AREA_PARAM_GRAVITY_POINT_ATTENUATION);
+	BIND_ENUM_CONSTANT(AREA_PARAM_LINEAR_DAMP_OVERRIDE_MODE);
 	BIND_ENUM_CONSTANT(AREA_PARAM_LINEAR_DAMP);
+	BIND_ENUM_CONSTANT(AREA_PARAM_ANGULAR_DAMP_OVERRIDE_MODE);
 	BIND_ENUM_CONSTANT(AREA_PARAM_ANGULAR_DAMP);
 	BIND_ENUM_CONSTANT(AREA_PARAM_PRIORITY);
 

+ 3 - 3
servers/physics_server_2d.h

@@ -264,12 +264,15 @@ public:
 	//missing attenuation? missing better override?
 
 	enum AreaParameter {
+		AREA_PARAM_GRAVITY_OVERRIDE_MODE,
 		AREA_PARAM_GRAVITY,
 		AREA_PARAM_GRAVITY_VECTOR,
 		AREA_PARAM_GRAVITY_IS_POINT,
 		AREA_PARAM_GRAVITY_DISTANCE_SCALE,
 		AREA_PARAM_GRAVITY_POINT_ATTENUATION,
+		AREA_PARAM_LINEAR_DAMP_OVERRIDE_MODE,
 		AREA_PARAM_LINEAR_DAMP,
+		AREA_PARAM_ANGULAR_DAMP_OVERRIDE_MODE,
 		AREA_PARAM_ANGULAR_DAMP,
 		AREA_PARAM_PRIORITY
 	};
@@ -287,9 +290,6 @@ public:
 		AREA_SPACE_OVERRIDE_REPLACE_COMBINE // Discards all previous calculations, then keeps combining
 	};
 
-	virtual void area_set_space_override_mode(RID p_area, AreaSpaceOverrideMode p_mode) = 0;
-	virtual AreaSpaceOverrideMode area_get_space_override_mode(RID p_area) const = 0;
-
 	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;

+ 0 - 3
servers/physics_server_2d_wrap_mt.h

@@ -133,9 +133,6 @@ public:
 	FUNC2(area_set_space, RID, RID);
 	FUNC1RC(RID, area_get_space, RID);
 
-	FUNC2(area_set_space_override_mode, RID, AreaSpaceOverrideMode);
-	FUNC1RC(AreaSpaceOverrideMode, area_get_space_override_mode, RID);
-
 	FUNC4(area_add_shape, RID, RID, const Transform2D &, bool);
 	FUNC3(area_set_shape, RID, int, RID);
 	FUNC3(area_set_shape_transform, RID, int, const Transform2D &);

+ 3 - 3
servers/physics_server_3d.cpp

@@ -653,9 +653,6 @@ void PhysicsServer3D::_bind_methods() {
 	ClassDB::bind_method(D_METHOD("area_set_space", "area", "space"), &PhysicsServer3D::area_set_space);
 	ClassDB::bind_method(D_METHOD("area_get_space", "area"), &PhysicsServer3D::area_get_space);
 
-	ClassDB::bind_method(D_METHOD("area_set_space_override_mode", "area", "mode"), &PhysicsServer3D::area_set_space_override_mode);
-	ClassDB::bind_method(D_METHOD("area_get_space_override_mode", "area"), &PhysicsServer3D::area_get_space_override_mode);
-
 	ClassDB::bind_method(D_METHOD("area_add_shape", "area", "shape", "transform", "disabled"), &PhysicsServer3D::area_add_shape, DEFVAL(Transform3D()), DEFVAL(false));
 	ClassDB::bind_method(D_METHOD("area_set_shape", "area", "shape_idx", "shape"), &PhysicsServer3D::area_set_shape);
 	ClassDB::bind_method(D_METHOD("area_set_shape_transform", "area", "shape_idx", "transform"), &PhysicsServer3D::area_set_shape_transform);
@@ -901,12 +898,15 @@ void PhysicsServer3D::_bind_methods() {
 	BIND_ENUM_CONSTANT(SHAPE_SOFT_BODY);
 	BIND_ENUM_CONSTANT(SHAPE_CUSTOM);
 
+	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_IS_POINT);
 	BIND_ENUM_CONSTANT(AREA_PARAM_GRAVITY_DISTANCE_SCALE);
 	BIND_ENUM_CONSTANT(AREA_PARAM_GRAVITY_POINT_ATTENUATION);
+	BIND_ENUM_CONSTANT(AREA_PARAM_LINEAR_DAMP_OVERRIDE_MODE);
 	BIND_ENUM_CONSTANT(AREA_PARAM_LINEAR_DAMP);
+	BIND_ENUM_CONSTANT(AREA_PARAM_ANGULAR_DAMP_OVERRIDE_MODE);
 	BIND_ENUM_CONSTANT(AREA_PARAM_ANGULAR_DAMP);
 	BIND_ENUM_CONSTANT(AREA_PARAM_PRIORITY);
 	BIND_ENUM_CONSTANT(AREA_PARAM_WIND_FORCE_MAGNITUDE);

+ 3 - 3
servers/physics_server_3d.h

@@ -285,12 +285,15 @@ public:
 	//missing attenuation? missing better override?
 
 	enum AreaParameter {
+		AREA_PARAM_GRAVITY_OVERRIDE_MODE,
 		AREA_PARAM_GRAVITY,
 		AREA_PARAM_GRAVITY_VECTOR,
 		AREA_PARAM_GRAVITY_IS_POINT,
 		AREA_PARAM_GRAVITY_DISTANCE_SCALE,
 		AREA_PARAM_GRAVITY_POINT_ATTENUATION,
+		AREA_PARAM_LINEAR_DAMP_OVERRIDE_MODE,
 		AREA_PARAM_LINEAR_DAMP,
+		AREA_PARAM_ANGULAR_DAMP_OVERRIDE_MODE,
 		AREA_PARAM_ANGULAR_DAMP,
 		AREA_PARAM_PRIORITY,
 		AREA_PARAM_WIND_FORCE_MAGNITUDE,
@@ -312,9 +315,6 @@ public:
 		AREA_SPACE_OVERRIDE_REPLACE_COMBINE
 	};
 
-	virtual void area_set_space_override_mode(RID p_area, AreaSpaceOverrideMode p_mode) = 0;
-	virtual AreaSpaceOverrideMode area_get_space_override_mode(RID p_area) const = 0;
-
 	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;

+ 0 - 3
servers/physics_server_3d_wrap_mt.h

@@ -137,9 +137,6 @@ public:
 	FUNC2(area_set_space, RID, RID);
 	FUNC1RC(RID, area_get_space, RID);
 
-	FUNC2(area_set_space_override_mode, RID, AreaSpaceOverrideMode);
-	FUNC1RC(AreaSpaceOverrideMode, area_get_space_override_mode, RID);
-
 	FUNC4(area_add_shape, RID, RID, const Transform3D &, bool);
 	FUNC3(area_set_shape, RID, int, RID);
 	FUNC3(area_set_shape_transform, RID, int, const Transform3D &);