From 83baecdff01894df55171ace7aa9e50b3001cc73 Mon Sep 17 00:00:00 2001 From: PouleyKetchoupp Date: Mon, 30 Aug 2021 11:48:43 -0700 Subject: [PATCH] Add AnimatableBody inherited from StaticBody for moving platforms Instead of having a physics node named Static that can be either Static or Kinematic, AnimatableBody is added again as a separate node: -Inherited from StaticBody to make its usage clearer -Still separated from CharacterBody to make its usage more focused Properly implemented constant velocity for kinematic bodies in godot physics servers (induced velocity without actually moving). Also updated description for the different physics nodes to make their usage clearer. --- doc/classes/AnimatableBody2D.xml | 22 +++ doc/classes/AnimatableBody3D.xml | 25 +++ doc/classes/CharacterBody2D.xml | 8 +- doc/classes/CharacterBody3D.xml | 6 +- doc/classes/PhysicsServer2D.xml | 2 +- doc/classes/PhysicsServer3D.xml | 2 +- doc/classes/RigidBody2D.xml | 5 +- doc/classes/RigidBody3D.xml | 7 +- doc/classes/StaticBody2D.xml | 23 +-- doc/classes/StaticBody3D.xml | 23 +-- editor/icons/AnimatableBody2D.svg | 1 + editor/icons/AnimatableBody3D.svg | 1 + scene/2d/physics_body_2d.cpp | 221 ++++++++----------------- scene/2d/physics_body_2d.h | 37 +++-- scene/3d/physics_body_3d.cpp | 262 +++++++++--------------------- scene/3d/physics_body_3d.h | 49 +++--- scene/register_scene_types.cpp | 2 + servers/physics_2d/body_2d_sw.cpp | 8 +- servers/physics_2d/body_2d_sw.h | 7 +- servers/physics_3d/body_3d_sw.cpp | 6 +- servers/physics_3d/body_3d_sw.h | 3 + 21 files changed, 291 insertions(+), 429 deletions(-) create mode 100644 doc/classes/AnimatableBody2D.xml create mode 100644 doc/classes/AnimatableBody3D.xml create mode 100644 editor/icons/AnimatableBody2D.svg create mode 100644 editor/icons/AnimatableBody3D.svg diff --git a/doc/classes/AnimatableBody2D.xml b/doc/classes/AnimatableBody2D.xml new file mode 100644 index 00000000000..731c7025492 --- /dev/null +++ b/doc/classes/AnimatableBody2D.xml @@ -0,0 +1,22 @@ + + + + Physics body for 2D physics which moves only by script or animation. Useful for moving platforms and doors. + + + Animatable body for 2D physics. + An animatable body can't be moved by external forces or contacts, but can be moved by script or animation to affect other bodies in its path. It is ideal for implementing moving objects in the environment, such as moving platforms or doors. + When the body is moved manually, either from code or from an [AnimationPlayer] (with [member AnimationPlayer.playback_process_mode] set to [code]physics[/code]), the physics will automatically compute an estimate of their linear and angular velocity. This makes them very useful for moving platforms or other AnimationPlayer-controlled objects (like a door, a bridge that opens, etc). + + + + + + + + If [code]true[/code], the body's movement will be synchronized to the physics frame. This is useful when animating movement via [AnimationPlayer], for example on moving platforms. Do [b]not[/b] use together with [method PhysicsBody2D.move_and_collide]. + + + + + diff --git a/doc/classes/AnimatableBody3D.xml b/doc/classes/AnimatableBody3D.xml new file mode 100644 index 00000000000..8192f26057b --- /dev/null +++ b/doc/classes/AnimatableBody3D.xml @@ -0,0 +1,25 @@ + + + + Physics body for 3D physics which moves only by script or animation. Useful for moving platforms and doors. + + + Animatable body for 3D physics. + An animatable body can't be moved by external forces or contacts, but can be moved by script or animation to affect other bodies in its path. It is ideal for implementing moving objects in the environment, such as moving platforms or doors. + When the body is moved manually, either from code or from an [AnimationPlayer] (with [member AnimationPlayer.playback_process_mode] set to [code]physics[/code]), the physics will automatically compute an estimate of their linear and angular velocity. This makes them very useful for moving platforms or other AnimationPlayer-controlled objects (like a door, a bridge that opens, etc). + + + https://godotengine.org/asset-library/asset/675 + https://godotengine.org/asset-library/asset/678 + https://godotengine.org/asset-library/asset/676 + + + + + + If [code]true[/code], the body's movement will be synchronized to the physics frame. This is useful when animating movement via [AnimationPlayer], for example on moving platforms. Do [b]not[/b] use together with [method PhysicsBody3D.move_and_collide]. + + + + + diff --git a/doc/classes/CharacterBody2D.xml b/doc/classes/CharacterBody2D.xml index 71e6eeab5a5..f98c22a1e93 100644 --- a/doc/classes/CharacterBody2D.xml +++ b/doc/classes/CharacterBody2D.xml @@ -1,12 +1,12 @@ - Character body 2D node. + Specialized 2D physics body node for characters moved by script. - Character bodies are special types of bodies that are meant to be user-controlled. They are not affected by physics at all; to other types of bodies, such as a rigid body, these are the same as a static body. However, they have two main uses: - [b]Kinematic characters:[/b] Character bodies have an API for moving objects with walls and slopes detection ([method move_and_slide] method), in addition to collision detection (also done with [method PhysicsBody3D.move_and_collide]). This makes them really useful to implement characters that move in specific ways and collide with the world, but don't require advanced physics. - [b]Kinematic motion:[/b] Character bodies can also be used for kinematic motion (same functionality as [member StaticBody3D.kinematic_motion] when enabled), which allows them to be moved by code and push other bodies on their path. + Character bodies are special types of bodies that are meant to be user-controlled. They are not affected by physics at all; to other types of bodies, such as a rigid body, these are the same as a [AnimatableBody2D]. However, they have two main uses: + [b]Kinematic characters:[/b] Character bodies have an API for moving objects with walls and slopes detection ([method move_and_slide] method), in addition to collision detection (also done with [method PhysicsBody2D.move_and_collide]). This makes them really useful to implement characters that move in specific ways and collide with the world, but don't require advanced physics. + [b]Kinematic motion:[/b] Character bodies can also be used for kinematic motion (same functionality as [AnimatableBody2D]), which allows them to be moved by code and push other bodies on their path. https://docs.godotengine.org/en/latest/tutorials/physics/kinematic_character_2d.html diff --git a/doc/classes/CharacterBody3D.xml b/doc/classes/CharacterBody3D.xml index 85135d55095..81ffbe01c1d 100644 --- a/doc/classes/CharacterBody3D.xml +++ b/doc/classes/CharacterBody3D.xml @@ -1,12 +1,12 @@ - Character body 3D node. + Specialized 3D physics body node for characters moved by script. - Character bodies are special types of bodies that are meant to be user-controlled. They are not affected by physics at all; to other types of bodies, such as a rigid body, these are the same as a static body. However, they have two main uses: + Character bodies are special types of bodies that are meant to be user-controlled. They are not affected by physics at all; to other types of bodies, such as a rigid body, these are the same as a [AnimatableBody3D]. However, they have two main uses: [b]Kinematic characters:[/b] Character bodies have an API for moving objects with walls and slopes detection ([method move_and_slide] method), in addition to collision detection (also done with [method PhysicsBody3D.move_and_collide]). This makes them really useful to implement characters that move in specific ways and collide with the world, but don't require advanced physics. - [b]Kinematic motion:[/b] Character bodies can also be used for kinematic motion (same functionality as [member StaticBody3D.kinematic_motion] when enabled), which allows them to be moved by code and push other bodies on their path. + [b]Kinematic motion:[/b] Character bodies can also be used for kinematic motion (same functionality as [AnimatableBody3D]), which allows them to be moved by code and push other bodies on their path. https://docs.godotengine.org/en/latest/tutorials/physics/kinematic_character_2d.html diff --git a/doc/classes/PhysicsServer2D.xml b/doc/classes/PhysicsServer2D.xml index 9867b98ae68..c412c7ec598 100644 --- a/doc/classes/PhysicsServer2D.xml +++ b/doc/classes/PhysicsServer2D.xml @@ -913,7 +913,7 @@ This area replaces any gravity/damp calculated so far, but keeps calculating the rest of the areas, down to the default one. - Constant for static bodies. In this mode, a body can be only moved by user code. + Constant for static bodies. In this mode, a body can be only moved by user code and doesn't collide with other bodies along its path when moved. Constant for kinematic bodies. In this mode, a body can be only moved by user code and collides with other bodies along its path. diff --git a/doc/classes/PhysicsServer3D.xml b/doc/classes/PhysicsServer3D.xml index 46cbe48b28b..46cde02f2ca 100644 --- a/doc/classes/PhysicsServer3D.xml +++ b/doc/classes/PhysicsServer3D.xml @@ -1262,7 +1262,7 @@ This area replaces any gravity/damp calculated so far, but keeps calculating the rest of the areas, down to the default one. - Constant for static bodies. In this mode, a body can be only moved by user code. + Constant for static bodies. In this mode, a body can be only moved by user code and doesn't collide with other bodies along its path when moved. Constant for kinematic bodies. In this mode, a body can be only moved by user code and collides with other bodies along its path. diff --git a/doc/classes/RigidBody2D.xml b/doc/classes/RigidBody2D.xml index db16552db35..40b5a706c75 100644 --- a/doc/classes/RigidBody2D.xml +++ b/doc/classes/RigidBody2D.xml @@ -1,7 +1,7 @@ - A body that is controlled by the 2D physics engine. + Physics Body which is moved by 2D physics simulation. Useful for objects that have gravity and can be pushed by other objects. This node implements simulated 2D physics. You do not control a RigidBody2D directly. Instead, you apply forces to it (gravity, impulses, etc.) and the physics simulation calculates the resulting movement based on its mass, friction, and other physical properties. @@ -131,6 +131,7 @@ The body's mode. See [enum Mode] for possible values. + For a body that uses only Static or Kinematic mode, use [StaticBody2D] or [AnimatableBody2D] instead. The physics material override for the body. @@ -199,7 +200,7 @@ Locked dynamic body mode. Similar to [constant MODE_DYNAMIC], but the body can not rotate. - Kinematic body mode. The body behaves like a [StaticBody2D] with [member StaticBody2D.kinematic_motion] enabled, and must be moved by user code. + Kinematic body mode. The body behaves like a [AnimatableBody2D], and must be moved by code. Continuous collision detection disabled. This is the fastest way to detect body collisions, but can miss small, fast-moving objects. diff --git a/doc/classes/RigidBody3D.xml b/doc/classes/RigidBody3D.xml index f4299335bf3..25fb1edde93 100644 --- a/doc/classes/RigidBody3D.xml +++ b/doc/classes/RigidBody3D.xml @@ -1,7 +1,7 @@ - Physics Body whose position is determined through physics simulation in 3D space. + Physics Body which is moved by 3D physics simulation. Useful for objects that have gravity and can be pushed by other objects. This is the node that implements full 3D physics. This means that you do not control a RigidBody3D directly. Instead, you can apply forces to it (gravity, impulses, etc.), and the physics simulation will calculate the resulting movement, collision, bouncing, rotating, etc. @@ -130,7 +130,8 @@ The body's mass. - The body mode. See [enum Mode] for possible values. + The body's mode. See [enum Mode] for possible values. + For a body that uses only Static or Kinematic mode, use [StaticBody3D] or [AnimatableBody3D] instead. The physics material override for the body. @@ -201,7 +202,7 @@ Locked dynamic body mode. Similar to [constant MODE_DYNAMIC], but the body can not rotate. - Kinematic body mode. The body behaves like a [StaticBody3D] with [member StaticBody3D.kinematic_motion] enabled, and can only move by user code. + Kinematic body mode. The body behaves like a [AnimatableBody3D], and can only move by user code. diff --git a/doc/classes/StaticBody2D.xml b/doc/classes/StaticBody2D.xml index 326bf58e225..0344c3e0d13 100644 --- a/doc/classes/StaticBody2D.xml +++ b/doc/classes/StaticBody2D.xml @@ -1,14 +1,14 @@ - Static body for 2D physics. + Physics body for 2D physics which is static or moves only by script. Useful for floor and walls. - Static body for 2D physics. A static body is a simple body that can't be moved by external forces or contacts. It is ideal for implementing objects in the environment, such as walls or platforms. In contrast to [RigidBody2D], they don't consume any CPU resources as long as they don't move. - They however have extra functionalities to move and affect other bodies: - [b]Constant velocity:[/b] [member constant_linear_velocity] and [member constant_angular_velocity] can be set for the static body, so even if it doesn't move, it affects other bodies as if it was moving (this is useful for simulating conveyor belts or conveyor wheels). - [b]Transform change:[/b] Static bodies can be also moved by code. Unless [member kinematic_motion] is enabled, they are just teleported in this case and don't affect other bodies on their path. - [b]Kinematic motion:[/b] Static bodies can have [member kinematic_motion] enabled to make them kinematic bodies that can be moved by code and push other bodies on their path. + Static body for 2D physics. + A static body is a simple body that can't be moved by external forces or contacts. It is ideal for implementing objects in the environment, such as walls or platforms. In contrast to [RigidBody2D], it doesn't consume any CPU resources as long as they don't move. + They have extra functionalities to move and affect other bodies: + [b]Static transform change:[/b] Static bodies can be moved by animation or script. In this case, they are just teleported and don't affect other bodies on their path. + [b]Constant velocity:[/b] When [member constant_linear_velocity] or [member constant_angular_velocity] is set, static bodies don't move themselves but affect touching bodies as if they were moving. This is useful for simulating conveyor belts or conveyor wheels. @@ -16,22 +16,15 @@ - The body's constant angular velocity. This does not rotate the body (unless [member kinematic_motion] is enabled), but affects other bodies that touch it, as if it were rotating. + The body's constant angular velocity. This does not rotate the body, but affects touching bodies, as if it were rotating. - The body's constant linear velocity. This does not move the body (unless [member kinematic_motion] is enabled), but affects other bodies that touch it, as if it were moving. - - - If [code]true[/code], the body will act the same as a [RigidBody2D] in [constant RigidBody2D.MODE_KINEMATIC] mode. - When the body is moved manually, either from code or from an [AnimationPlayer] (with [member AnimationPlayer.playback_process_mode] set to [code]physics[/code]), the physics will automatically compute an estimate of their linear and angular velocity. This makes them very useful for moving platforms or other AnimationPlayer-controlled objects (like a door, a bridge that opens, etc). + The body's constant linear velocity. This does not move the body, but affects touching bodies, as if it were moving. The physics material override for the body. If a material is assigned to this property, it will be used instead of any other physics material, such as an inherited one. - - If [code]true[/code] and [member kinematic_motion] is enabled, the body's movement will be synchronized to the physics frame. This is useful when animating movement via [AnimationPlayer], for example on moving platforms. Do [b]not[/b] use together with [method PhysicsBody2D.move_and_collide]. - diff --git a/doc/classes/StaticBody3D.xml b/doc/classes/StaticBody3D.xml index 69c123002f9..4cb51b60eca 100644 --- a/doc/classes/StaticBody3D.xml +++ b/doc/classes/StaticBody3D.xml @@ -1,14 +1,14 @@ - Static body for 3D physics. + Physics body for 3D physics which is static or moves only by script. Useful for floor and walls. - Static body for 3D physics. A static body is a simple body that can't be moved by external forces or contacts. It is ideal for implementing objects in the environment, such as walls or platforms. In contrast to [RigidBody3D], they don't consume any CPU resources as long as they don't move. - They however have extra functionalities to move and affect other bodies: - [b]Constant velocity:[/b] [member constant_linear_velocity] and [member constant_angular_velocity] can be set for the static body, so even if it doesn't move, it affects other bodies as if it was moving (this is useful for simulating conveyor belts or conveyor wheels). - [b]Transform change:[/b] Static bodies can be also moved by code. Unless [member kinematic_motion] is enabled, they are just teleported in this case and don't affect other bodies on their path. - [b]Kinematic motion:[/b] Static bodies can have [member kinematic_motion] enabled to make them kinematic bodies that can be moved by code and push other bodies on their path. + Static body for 3D physics. + A static body is a simple body that can't be moved by external forces or contacts. It is ideal for implementing objects in the environment, such as walls or platforms. In contrast to [RigidBody3D], it doesn't consume any CPU resources as long as they don't move. + They have extra functionalities to move and affect other bodies: + [b]Static transform change:[/b] Static bodies can be moved by animation or script. In this case, they are just teleported and don't affect other bodies on their path. + [b]Constant velocity:[/b] When [member constant_linear_velocity] or [member constant_angular_velocity] is set, static bodies don't move themselves but affect touching bodies as if they were moving. This is useful for simulating conveyor belts or conveyor wheels. https://godotengine.org/asset-library/asset/675 @@ -19,22 +19,15 @@ - The body's constant angular velocity. This does not rotate the body (unless [member kinematic_motion] is enabled), but affects other bodies that touch it, as if it were rotating. + The body's constant angular velocity. This does not rotate the body, but affects touching bodies, as if it were rotating. - The body's constant linear velocity. This does not move the body (unless [member kinematic_motion] is enabled), but affects other bodies that touch it, as if it were moving. - - - If [code]true[/code], the body will act the same as a [RigidBody3D] in [constant RigidBody3D.MODE_KINEMATIC] mode. - When the body is moved manually, either from code or from an [AnimationPlayer] (with [member AnimationPlayer.playback_process_mode] set to [code]physics[/code]), the physics will automatically compute an estimate of their linear and angular velocity. This makes them very useful for moving platforms or other AnimationPlayer-controlled objects (like a door, a bridge that opens, etc). + The body's constant linear velocity. This does not move the body, but affects touching bodies, as if it were moving. The physics material override for the body. If a material is assigned to this property, it will be used instead of any other physics material, such as an inherited one. - - If [code]true[/code] and [member kinematic_motion] is enabled, the body's movement will be synchronized to the physics frame. This is useful when animating movement via [AnimationPlayer], for example on moving platforms. Do [b]not[/b] use together with [method PhysicsBody3D.move_and_collide]. - diff --git a/editor/icons/AnimatableBody2D.svg b/editor/icons/AnimatableBody2D.svg new file mode 100644 index 00000000000..f4fed813c9f --- /dev/null +++ b/editor/icons/AnimatableBody2D.svg @@ -0,0 +1 @@ + diff --git a/editor/icons/AnimatableBody3D.svg b/editor/icons/AnimatableBody3D.svg new file mode 100644 index 00000000000..2e472f06257 --- /dev/null +++ b/editor/icons/AnimatableBody3D.svg @@ -0,0 +1 @@ + diff --git a/scene/2d/physics_body_2d.cpp b/scene/2d/physics_body_2d.cpp index 3518d434c30..125a7e6a617 100644 --- a/scene/2d/physics_body_2d.cpp +++ b/scene/2d/physics_body_2d.cpp @@ -165,21 +165,13 @@ void PhysicsBody2D::remove_collision_exception_with(Node *p_node) { void StaticBody2D::set_constant_linear_velocity(const Vector2 &p_vel) { constant_linear_velocity = p_vel; - if (kinematic_motion) { - _update_kinematic_motion(); - } else { - PhysicsServer2D::get_singleton()->body_set_state(get_rid(), PhysicsServer2D::BODY_STATE_LINEAR_VELOCITY, constant_linear_velocity); - } + PhysicsServer2D::get_singleton()->body_set_state(get_rid(), PhysicsServer2D::BODY_STATE_LINEAR_VELOCITY, constant_linear_velocity); } void StaticBody2D::set_constant_angular_velocity(real_t p_vel) { constant_angular_velocity = p_vel; - if (kinematic_motion) { - _update_kinematic_motion(); - } else { - PhysicsServer2D::get_singleton()->body_set_state(get_rid(), PhysicsServer2D::BODY_STATE_ANGULAR_VELOCITY, constant_angular_velocity); - } + PhysicsServer2D::get_singleton()->body_set_state(get_rid(), PhysicsServer2D::BODY_STATE_ANGULAR_VELOCITY, constant_angular_velocity); } Vector2 StaticBody2D::get_constant_linear_velocity() const { @@ -209,158 +201,22 @@ Ref StaticBody2D::get_physics_material_override() const { return physics_material_override; } -void StaticBody2D::set_kinematic_motion_enabled(bool p_enabled) { - if (p_enabled == kinematic_motion) { - return; - } - - kinematic_motion = p_enabled; - - if (kinematic_motion) { - set_body_mode(PhysicsServer2D::BODY_MODE_KINEMATIC); - } else { - set_body_mode(PhysicsServer2D::BODY_MODE_STATIC); - } - -#ifdef TOOLS_ENABLED - if (Engine::get_singleton()->is_editor_hint()) { - update_configuration_warnings(); - return; - } -#endif - - _update_kinematic_motion(); -} - -bool StaticBody2D::is_kinematic_motion_enabled() const { - return kinematic_motion; -} - -void StaticBody2D::set_sync_to_physics(bool p_enable) { - if (sync_to_physics == p_enable) { - return; - } - - sync_to_physics = p_enable; - -#ifdef TOOLS_ENABLED - if (Engine::get_singleton()->is_editor_hint()) { - update_configuration_warnings(); - return; - } -#endif - - if (kinematic_motion) { - _update_kinematic_motion(); - } -} - -bool StaticBody2D::is_sync_to_physics_enabled() const { - return sync_to_physics; -} - -void StaticBody2D::_body_state_changed_callback(void *p_instance, PhysicsDirectBodyState2D *p_state) { - StaticBody2D *body = (StaticBody2D *)p_instance; - body->_body_state_changed(p_state); -} - -void StaticBody2D::_body_state_changed(PhysicsDirectBodyState2D *p_state) { - if (!sync_to_physics) { - return; - } - - last_valid_transform = p_state->get_transform(); - set_notify_local_transform(false); - set_global_transform(last_valid_transform); - set_notify_local_transform(true); -} - -TypedArray StaticBody2D::get_configuration_warnings() const { - TypedArray warnings = PhysicsBody2D::get_configuration_warnings(); - - if (sync_to_physics && !kinematic_motion) { - warnings.push_back(TTR("Sync to physics works only when kinematic motion is enabled.")); - } - - return warnings; -} - -void StaticBody2D::_notification(int p_what) { - switch (p_what) { - case NOTIFICATION_ENTER_TREE: { - last_valid_transform = get_global_transform(); - } break; - - case NOTIFICATION_LOCAL_TRANSFORM_CHANGED: { - // Used by sync to physics, send the new transform to the physics... - Transform2D new_transform = get_global_transform(); - - double delta_time = get_physics_process_delta_time(); - new_transform.translate(constant_linear_velocity * delta_time); - new_transform.set_rotation(new_transform.get_rotation() + constant_angular_velocity * delta_time); - - PhysicsServer2D::get_singleton()->body_set_state(get_rid(), PhysicsServer2D::BODY_STATE_TRANSFORM, new_transform); - - // ... but then revert changes. - set_notify_local_transform(false); - set_global_transform(last_valid_transform); - set_notify_local_transform(true); - } break; - - case NOTIFICATION_INTERNAL_PHYSICS_PROCESS: { -#ifdef TOOLS_ENABLED - if (Engine::get_singleton()->is_editor_hint()) { - return; - } -#endif - - ERR_FAIL_COND(!kinematic_motion); - - Transform2D new_transform = get_global_transform(); - - double delta_time = get_physics_process_delta_time(); - new_transform.translate(constant_linear_velocity * delta_time); - new_transform.set_rotation(new_transform.get_rotation() + constant_angular_velocity * delta_time); - - if (sync_to_physics) { - // Propagate transform change to node. - set_global_transform(new_transform); - } else { - PhysicsServer2D::get_singleton()->body_set_state(get_rid(), PhysicsServer2D::BODY_STATE_TRANSFORM, new_transform); - - // Propagate transform change to node. - set_block_transform_notify(true); - set_global_transform(new_transform); - set_block_transform_notify(false); - } - } break; - } -} - void StaticBody2D::_bind_methods() { ClassDB::bind_method(D_METHOD("set_constant_linear_velocity", "vel"), &StaticBody2D::set_constant_linear_velocity); ClassDB::bind_method(D_METHOD("set_constant_angular_velocity", "vel"), &StaticBody2D::set_constant_angular_velocity); ClassDB::bind_method(D_METHOD("get_constant_linear_velocity"), &StaticBody2D::get_constant_linear_velocity); ClassDB::bind_method(D_METHOD("get_constant_angular_velocity"), &StaticBody2D::get_constant_angular_velocity); - ClassDB::bind_method(D_METHOD("set_kinematic_motion_enabled", "enabled"), &StaticBody2D::set_kinematic_motion_enabled); - ClassDB::bind_method(D_METHOD("is_kinematic_motion_enabled"), &StaticBody2D::is_kinematic_motion_enabled); - ClassDB::bind_method(D_METHOD("set_physics_material_override", "physics_material_override"), &StaticBody2D::set_physics_material_override); ClassDB::bind_method(D_METHOD("get_physics_material_override"), &StaticBody2D::get_physics_material_override); - ClassDB::bind_method(D_METHOD("set_sync_to_physics", "enable"), &StaticBody2D::set_sync_to_physics); - ClassDB::bind_method(D_METHOD("is_sync_to_physics_enabled"), &StaticBody2D::is_sync_to_physics_enabled); - ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "physics_material_override", PROPERTY_HINT_RESOURCE_TYPE, "PhysicsMaterial"), "set_physics_material_override", "get_physics_material_override"); ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "constant_linear_velocity"), "set_constant_linear_velocity", "get_constant_linear_velocity"); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "constant_angular_velocity"), "set_constant_angular_velocity", "get_constant_angular_velocity"); - ADD_PROPERTY(PropertyInfo(Variant::BOOL, "kinematic_motion"), "set_kinematic_motion_enabled", "is_kinematic_motion_enabled"); - ADD_PROPERTY(PropertyInfo(Variant::BOOL, "sync_to_physics"), "set_sync_to_physics", "is_sync_to_physics_enabled"); } -StaticBody2D::StaticBody2D() : - PhysicsBody2D(PhysicsServer2D::BODY_MODE_STATIC) { +StaticBody2D::StaticBody2D(PhysicsServer2D::BodyMode p_mode) : + PhysicsBody2D(p_mode) { } void StaticBody2D::_reload_physics_characteristics() { @@ -373,14 +229,28 @@ void StaticBody2D::_reload_physics_characteristics() { } } -void StaticBody2D::_update_kinematic_motion() { +void AnimatableBody2D::set_sync_to_physics(bool p_enable) { + if (sync_to_physics == p_enable) { + return; + } + + sync_to_physics = p_enable; + + _update_kinematic_motion(); +} + +bool AnimatableBody2D::is_sync_to_physics_enabled() const { + return sync_to_physics; +} + +void AnimatableBody2D::_update_kinematic_motion() { #ifdef TOOLS_ENABLED if (Engine::get_singleton()->is_editor_hint()) { return; } #endif - if (kinematic_motion && sync_to_physics) { + if (sync_to_physics) { PhysicsServer2D::get_singleton()->body_set_state_sync_callback(get_rid(), this, _body_state_changed_callback); set_only_update_transform_changes(true); set_notify_local_transform(true); @@ -389,15 +259,54 @@ void StaticBody2D::_update_kinematic_motion() { set_only_update_transform_changes(false); set_notify_local_transform(false); } +} - bool needs_physics_process = false; - if (kinematic_motion) { - if (!Math::is_zero_approx(constant_angular_velocity) || !constant_linear_velocity.is_equal_approx(Vector2())) { - needs_physics_process = true; - } +void AnimatableBody2D::_body_state_changed_callback(void *p_instance, PhysicsDirectBodyState2D *p_state) { + AnimatableBody2D *body = (AnimatableBody2D *)p_instance; + body->_body_state_changed(p_state); +} + +void AnimatableBody2D::_body_state_changed(PhysicsDirectBodyState2D *p_state) { + if (!sync_to_physics) { + return; } - set_physics_process_internal(needs_physics_process); + last_valid_transform = p_state->get_transform(); + set_notify_local_transform(false); + set_global_transform(last_valid_transform); + set_notify_local_transform(true); +} + +void AnimatableBody2D::_notification(int p_what) { + switch (p_what) { + case NOTIFICATION_ENTER_TREE: { + last_valid_transform = get_global_transform(); + } break; + + case NOTIFICATION_LOCAL_TRANSFORM_CHANGED: { + // Used by sync to physics, send the new transform to the physics... + Transform2D new_transform = get_global_transform(); + + PhysicsServer2D::get_singleton()->body_set_state(get_rid(), PhysicsServer2D::BODY_STATE_TRANSFORM, new_transform); + + // ... but then revert changes. + set_notify_local_transform(false); + set_global_transform(last_valid_transform); + set_notify_local_transform(true); + } break; + } +} + +void AnimatableBody2D::_bind_methods() { + ClassDB::bind_method(D_METHOD("set_sync_to_physics", "enable"), &AnimatableBody2D::set_sync_to_physics); + ClassDB::bind_method(D_METHOD("is_sync_to_physics_enabled"), &AnimatableBody2D::is_sync_to_physics_enabled); + + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "sync_to_physics"), "set_sync_to_physics", "is_sync_to_physics_enabled"); +} + +AnimatableBody2D::AnimatableBody2D() : + StaticBody2D(PhysicsServer2D::BODY_MODE_KINEMATIC) { + _update_kinematic_motion(); } void RigidBody2D::_body_enter_tree(ObjectID p_id) { diff --git a/scene/2d/physics_body_2d.h b/scene/2d/physics_body_2d.h index 1bf53ea53c1..24152060ec7 100644 --- a/scene/2d/physics_body_2d.h +++ b/scene/2d/physics_body_2d.h @@ -63,21 +63,13 @@ public: class StaticBody2D : public PhysicsBody2D { GDCLASS(StaticBody2D, PhysicsBody2D); +private: Vector2 constant_linear_velocity; real_t constant_angular_velocity = 0.0; Ref physics_material_override; - bool kinematic_motion = false; - bool sync_to_physics = false; - - Transform2D last_valid_transform; - - static void _body_state_changed_callback(void *p_instance, PhysicsDirectBodyState2D *p_state); - void _body_state_changed(PhysicsDirectBodyState2D *p_state); - protected: - void _notification(int p_what); static void _bind_methods(); public: @@ -90,18 +82,33 @@ public: Vector2 get_constant_linear_velocity() const; real_t get_constant_angular_velocity() const; - virtual TypedArray get_configuration_warnings() const override; - - StaticBody2D(); + StaticBody2D(PhysicsServer2D::BodyMode p_mode = PhysicsServer2D::BODY_MODE_STATIC); private: void _reload_physics_characteristics(); +}; +class AnimatableBody2D : public StaticBody2D { + GDCLASS(AnimatableBody2D, StaticBody2D); + +private: + bool sync_to_physics = false; + + Transform2D last_valid_transform; + + static void _body_state_changed_callback(void *p_instance, PhysicsDirectBodyState2D *p_state); + void _body_state_changed(PhysicsDirectBodyState2D *p_state); + +protected: + void _notification(int p_what); + static void _bind_methods(); + +public: + AnimatableBody2D(); + +private: void _update_kinematic_motion(); - void set_kinematic_motion_enabled(bool p_enabled); - bool is_kinematic_motion_enabled() const; - void set_sync_to_physics(bool p_enable); bool is_sync_to_physics_enabled() const; }; diff --git a/scene/3d/physics_body_3d.cpp b/scene/3d/physics_body_3d.cpp index 0356994cdb1..b8780af1479 100644 --- a/scene/3d/physics_body_3d.cpp +++ b/scene/3d/physics_body_3d.cpp @@ -223,72 +223,98 @@ Ref StaticBody3D::get_physics_material_override() const { return physics_material_override; } -void StaticBody3D::set_kinematic_motion_enabled(bool p_enabled) { - if (p_enabled == kinematic_motion) { - return; - } - - kinematic_motion = p_enabled; - - if (kinematic_motion) { - set_body_mode(PhysicsServer3D::BODY_MODE_KINEMATIC); - } else { - set_body_mode(PhysicsServer3D::BODY_MODE_STATIC); - } - -#ifdef TOOLS_ENABLED - if (Engine::get_singleton()->is_editor_hint()) { - update_configuration_warnings(); - return; - } -#endif - - _update_kinematic_motion(); -} - -bool StaticBody3D::is_kinematic_motion_enabled() const { - return kinematic_motion; -} - void StaticBody3D::set_constant_linear_velocity(const Vector3 &p_vel) { constant_linear_velocity = p_vel; - if (kinematic_motion) { - _update_kinematic_motion(); + PhysicsServer3D::get_singleton()->body_set_state(get_rid(), PhysicsServer3D::BODY_STATE_LINEAR_VELOCITY, constant_linear_velocity); +} + +void StaticBody3D::set_constant_angular_velocity(const Vector3 &p_vel) { + constant_angular_velocity = p_vel; + + PhysicsServer3D::get_singleton()->body_set_state(get_rid(), PhysicsServer3D::BODY_STATE_ANGULAR_VELOCITY, constant_angular_velocity); +} + +Vector3 StaticBody3D::get_constant_linear_velocity() const { + return constant_linear_velocity; +} + +Vector3 StaticBody3D::get_constant_angular_velocity() const { + return constant_angular_velocity; +} + +void StaticBody3D::_bind_methods() { + ClassDB::bind_method(D_METHOD("set_constant_linear_velocity", "vel"), &StaticBody3D::set_constant_linear_velocity); + ClassDB::bind_method(D_METHOD("set_constant_angular_velocity", "vel"), &StaticBody3D::set_constant_angular_velocity); + ClassDB::bind_method(D_METHOD("get_constant_linear_velocity"), &StaticBody3D::get_constant_linear_velocity); + ClassDB::bind_method(D_METHOD("get_constant_angular_velocity"), &StaticBody3D::get_constant_angular_velocity); + + ClassDB::bind_method(D_METHOD("set_physics_material_override", "physics_material_override"), &StaticBody3D::set_physics_material_override); + ClassDB::bind_method(D_METHOD("get_physics_material_override"), &StaticBody3D::get_physics_material_override); + + ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "physics_material_override", PROPERTY_HINT_RESOURCE_TYPE, "PhysicsMaterial"), "set_physics_material_override", "get_physics_material_override"); + ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "constant_linear_velocity"), "set_constant_linear_velocity", "get_constant_linear_velocity"); + ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "constant_angular_velocity"), "set_constant_angular_velocity", "get_constant_angular_velocity"); +} + +StaticBody3D::StaticBody3D(PhysicsServer3D::BodyMode p_mode) : + PhysicsBody3D(p_mode) { +} + +void StaticBody3D::_reload_physics_characteristics() { + if (physics_material_override.is_null()) { + PhysicsServer3D::get_singleton()->body_set_param(get_rid(), PhysicsServer3D::BODY_PARAM_BOUNCE, 0); + PhysicsServer3D::get_singleton()->body_set_param(get_rid(), PhysicsServer3D::BODY_PARAM_FRICTION, 1); } else { - PhysicsServer3D::get_singleton()->body_set_state(get_rid(), PhysicsServer3D::BODY_STATE_LINEAR_VELOCITY, constant_linear_velocity); + PhysicsServer3D::get_singleton()->body_set_param(get_rid(), PhysicsServer3D::BODY_PARAM_BOUNCE, physics_material_override->computed_bounce()); + PhysicsServer3D::get_singleton()->body_set_param(get_rid(), PhysicsServer3D::BODY_PARAM_FRICTION, physics_material_override->computed_friction()); } } -void StaticBody3D::set_sync_to_physics(bool p_enable) { +Vector3 AnimatableBody3D::get_linear_velocity() const { + return linear_velocity; +} + +Vector3 AnimatableBody3D::get_angular_velocity() const { + return angular_velocity; +} + +void AnimatableBody3D::set_sync_to_physics(bool p_enable) { if (sync_to_physics == p_enable) { return; } sync_to_physics = p_enable; + _update_kinematic_motion(); +} + +bool AnimatableBody3D::is_sync_to_physics_enabled() const { + return sync_to_physics; +} + +void AnimatableBody3D::_update_kinematic_motion() { #ifdef TOOLS_ENABLED if (Engine::get_singleton()->is_editor_hint()) { - update_configuration_warnings(); return; } #endif - if (kinematic_motion) { - _update_kinematic_motion(); + if (sync_to_physics) { + set_only_update_transform_changes(true); + set_notify_local_transform(true); + } else { + set_only_update_transform_changes(false); + set_notify_local_transform(false); } } -bool StaticBody3D::is_sync_to_physics_enabled() const { - return sync_to_physics; -} - -void StaticBody3D::_body_state_changed_callback(void *p_instance, PhysicsDirectBodyState3D *p_state) { - StaticBody3D *body = (StaticBody3D *)p_instance; +void AnimatableBody3D::_body_state_changed_callback(void *p_instance, PhysicsDirectBodyState3D *p_state) { + AnimatableBody3D *body = (AnimatableBody3D *)p_instance; body->_body_state_changed(p_state); } -void StaticBody3D::_body_state_changed(PhysicsDirectBodyState3D *p_state) { +void AnimatableBody3D::_body_state_changed(PhysicsDirectBodyState3D *p_state) { linear_velocity = p_state->get_linear_velocity(); angular_velocity = p_state->get_angular_velocity(); @@ -303,43 +329,7 @@ void StaticBody3D::_body_state_changed(PhysicsDirectBodyState3D *p_state) { _on_transform_changed(); } -TypedArray StaticBody3D::get_configuration_warnings() const { - TypedArray warnings = PhysicsBody3D::get_configuration_warnings(); - - if (sync_to_physics && !kinematic_motion) { - warnings.push_back(TTR("Sync to physics works only when kinematic motion is enabled.")); - } - - return warnings; -} - -void StaticBody3D::set_constant_angular_velocity(const Vector3 &p_vel) { - constant_angular_velocity = p_vel; - - if (kinematic_motion) { - _update_kinematic_motion(); - } else { - PhysicsServer3D::get_singleton()->body_set_state(get_rid(), PhysicsServer3D::BODY_STATE_ANGULAR_VELOCITY, constant_angular_velocity); - } -} - -Vector3 StaticBody3D::get_constant_linear_velocity() const { - return constant_linear_velocity; -} - -Vector3 StaticBody3D::get_constant_angular_velocity() const { - return constant_angular_velocity; -} - -Vector3 StaticBody3D::get_linear_velocity() const { - return linear_velocity; -} - -Vector3 StaticBody3D::get_angular_velocity() const { - return angular_velocity; -} - -void StaticBody3D::_notification(int p_what) { +void AnimatableBody3D::_notification(int p_what) { switch (p_what) { case NOTIFICATION_ENTER_TREE: { last_valid_transform = get_global_transform(); @@ -349,17 +339,6 @@ void StaticBody3D::_notification(int p_what) { // Used by sync to physics, send the new transform to the physics... Transform3D new_transform = get_global_transform(); - double delta_time = get_physics_process_delta_time(); - new_transform.origin += constant_linear_velocity * delta_time; - - real_t ang_vel = constant_angular_velocity.length(); - if (!Math::is_zero_approx(ang_vel)) { - Vector3 ang_vel_axis = constant_angular_velocity / ang_vel; - Basis rot(ang_vel_axis, ang_vel * delta_time); - new_transform.basis = rot * new_transform.basis; - new_transform.orthonormalize(); - } - PhysicsServer3D::get_singleton()->body_set_state(get_rid(), PhysicsServer3D::BODY_STATE_TRANSFORM, new_transform); // ... but then revert changes. @@ -368,108 +347,21 @@ void StaticBody3D::_notification(int p_what) { set_notify_local_transform(true); _on_transform_changed(); } break; - - case NOTIFICATION_INTERNAL_PHYSICS_PROCESS: { -#ifdef TOOLS_ENABLED - if (Engine::get_singleton()->is_editor_hint()) { - return; - } -#endif - - ERR_FAIL_COND(!kinematic_motion); - - Transform3D new_transform = get_global_transform(); - - double delta_time = get_physics_process_delta_time(); - new_transform.origin += constant_linear_velocity * delta_time; - - real_t ang_vel = constant_angular_velocity.length(); - if (!Math::is_zero_approx(ang_vel)) { - Vector3 ang_vel_axis = constant_angular_velocity / ang_vel; - Basis rot(ang_vel_axis, ang_vel * delta_time); - new_transform.basis = rot * new_transform.basis; - new_transform.orthonormalize(); - } - - if (sync_to_physics) { - // Propagate transform change to node. - set_global_transform(new_transform); - } else { - PhysicsServer3D::get_singleton()->body_set_state(get_rid(), PhysicsServer3D::BODY_STATE_TRANSFORM, new_transform); - - // Propagate transform change to node. - set_ignore_transform_notification(true); - set_global_transform(new_transform); - set_ignore_transform_notification(false); - _on_transform_changed(); - } - } break; } } -void StaticBody3D::_bind_methods() { - ClassDB::bind_method(D_METHOD("set_constant_linear_velocity", "vel"), &StaticBody3D::set_constant_linear_velocity); - ClassDB::bind_method(D_METHOD("set_constant_angular_velocity", "vel"), &StaticBody3D::set_constant_angular_velocity); - ClassDB::bind_method(D_METHOD("get_constant_linear_velocity"), &StaticBody3D::get_constant_linear_velocity); - ClassDB::bind_method(D_METHOD("get_constant_angular_velocity"), &StaticBody3D::get_constant_angular_velocity); +void AnimatableBody3D::_bind_methods() { + ClassDB::bind_method(D_METHOD("set_sync_to_physics", "enable"), &AnimatableBody3D::set_sync_to_physics); + ClassDB::bind_method(D_METHOD("is_sync_to_physics_enabled"), &AnimatableBody3D::is_sync_to_physics_enabled); - ClassDB::bind_method(D_METHOD("set_kinematic_motion_enabled", "enabled"), &StaticBody3D::set_kinematic_motion_enabled); - ClassDB::bind_method(D_METHOD("is_kinematic_motion_enabled"), &StaticBody3D::is_kinematic_motion_enabled); - - ClassDB::bind_method(D_METHOD("set_physics_material_override", "physics_material_override"), &StaticBody3D::set_physics_material_override); - ClassDB::bind_method(D_METHOD("get_physics_material_override"), &StaticBody3D::get_physics_material_override); - - ClassDB::bind_method(D_METHOD("set_sync_to_physics", "enable"), &StaticBody3D::set_sync_to_physics); - ClassDB::bind_method(D_METHOD("is_sync_to_physics_enabled"), &StaticBody3D::is_sync_to_physics_enabled); - - ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "physics_material_override", PROPERTY_HINT_RESOURCE_TYPE, "PhysicsMaterial"), "set_physics_material_override", "get_physics_material_override"); - ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "constant_linear_velocity"), "set_constant_linear_velocity", "get_constant_linear_velocity"); - ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "constant_angular_velocity"), "set_constant_angular_velocity", "get_constant_angular_velocity"); - ADD_PROPERTY(PropertyInfo(Variant::BOOL, "kinematic_motion"), "set_kinematic_motion_enabled", "is_kinematic_motion_enabled"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "sync_to_physics"), "set_sync_to_physics", "is_sync_to_physics_enabled"); } -StaticBody3D::StaticBody3D() : - PhysicsBody3D(PhysicsServer3D::BODY_MODE_STATIC) { -} +AnimatableBody3D::AnimatableBody3D() : + StaticBody3D(PhysicsServer3D::BODY_MODE_KINEMATIC) { + PhysicsServer3D::get_singleton()->body_set_state_sync_callback(get_rid(), this, _body_state_changed_callback); -void StaticBody3D::_reload_physics_characteristics() { - if (physics_material_override.is_null()) { - PhysicsServer3D::get_singleton()->body_set_param(get_rid(), PhysicsServer3D::BODY_PARAM_BOUNCE, 0); - PhysicsServer3D::get_singleton()->body_set_param(get_rid(), PhysicsServer3D::BODY_PARAM_FRICTION, 1); - } else { - PhysicsServer3D::get_singleton()->body_set_param(get_rid(), PhysicsServer3D::BODY_PARAM_BOUNCE, physics_material_override->computed_bounce()); - PhysicsServer3D::get_singleton()->body_set_param(get_rid(), PhysicsServer3D::BODY_PARAM_FRICTION, physics_material_override->computed_friction()); - } -} - -void StaticBody3D::_update_kinematic_motion() { -#ifdef TOOLS_ENABLED - if (Engine::get_singleton()->is_editor_hint()) { - return; - } -#endif - - if (kinematic_motion && sync_to_physics) { - set_only_update_transform_changes(true); - set_notify_local_transform(true); - } else { - set_only_update_transform_changes(false); - set_notify_local_transform(false); - } - - bool needs_physics_process = false; - if (kinematic_motion) { - PhysicsServer3D::get_singleton()->body_set_state_sync_callback(get_rid(), this, &StaticBody3D::_body_state_changed_callback); - - if (!constant_angular_velocity.is_equal_approx(Vector3()) || !constant_linear_velocity.is_equal_approx(Vector3())) { - needs_physics_process = true; - } - } else { - PhysicsServer3D::get_singleton()->body_set_state_sync_callback(get_rid(), nullptr, nullptr); - } - - set_physics_process_internal(needs_physics_process); + _update_kinematic_motion(); } void RigidBody3D::_body_enter_tree(ObjectID p_id) { @@ -1042,7 +934,7 @@ void RigidBody3D::_bind_methods() { RigidBody3D::RigidBody3D() : PhysicsBody3D(PhysicsServer3D::BODY_MODE_DYNAMIC) { - PhysicsServer3D::get_singleton()->body_set_state_sync_callback(get_rid(), this, &RigidBody3D::_body_state_changed_callback); + PhysicsServer3D::get_singleton()->body_set_state_sync_callback(get_rid(), this, _body_state_changed_callback); } RigidBody3D::~RigidBody3D() { @@ -2713,7 +2605,7 @@ void PhysicalBone3D::_start_physics_simulation() { set_body_mode(PhysicsServer3D::BODY_MODE_DYNAMIC); PhysicsServer3D::get_singleton()->body_set_collision_layer(get_rid(), get_collision_layer()); PhysicsServer3D::get_singleton()->body_set_collision_mask(get_rid(), get_collision_mask()); - PhysicsServer3D::get_singleton()->body_set_state_sync_callback(get_rid(), this, &PhysicalBone3D::_body_state_changed_callback); + PhysicsServer3D::get_singleton()->body_set_state_sync_callback(get_rid(), this, _body_state_changed_callback); set_as_top_level(true); _internal_simulate_physics = true; } diff --git a/scene/3d/physics_body_3d.h b/scene/3d/physics_body_3d.h index 8c09f77846e..7570e306f38 100644 --- a/scene/3d/physics_body_3d.h +++ b/scene/3d/physics_body_3d.h @@ -73,24 +73,13 @@ public: class StaticBody3D : public PhysicsBody3D { GDCLASS(StaticBody3D, PhysicsBody3D); +private: Vector3 constant_linear_velocity; Vector3 constant_angular_velocity; - Vector3 linear_velocity; - Vector3 angular_velocity; - Ref physics_material_override; - bool kinematic_motion = false; - bool sync_to_physics = false; - - Transform3D last_valid_transform; - - static void _body_state_changed_callback(void *p_instance, PhysicsDirectBodyState3D *p_state); - void _body_state_changed(PhysicsDirectBodyState3D *p_state); - protected: - void _notification(int p_what); static void _bind_methods(); public: @@ -103,21 +92,39 @@ public: Vector3 get_constant_linear_velocity() const; Vector3 get_constant_angular_velocity() const; - virtual Vector3 get_linear_velocity() const override; - virtual Vector3 get_angular_velocity() const override; - - virtual TypedArray get_configuration_warnings() const override; - - StaticBody3D(); + StaticBody3D(PhysicsServer3D::BodyMode p_mode = PhysicsServer3D::BODY_MODE_STATIC); private: void _reload_physics_characteristics(); +}; +class AnimatableBody3D : public StaticBody3D { + GDCLASS(AnimatableBody3D, StaticBody3D); + +private: + Vector3 linear_velocity; + Vector3 angular_velocity; + + bool sync_to_physics = false; + + Transform3D last_valid_transform; + + static void _body_state_changed_callback(void *p_instance, PhysicsDirectBodyState3D *p_state); + void _body_state_changed(PhysicsDirectBodyState3D *p_state); + +protected: + void _notification(int p_what); + static void _bind_methods(); + +public: + virtual Vector3 get_linear_velocity() const override; + virtual Vector3 get_angular_velocity() const override; + + AnimatableBody3D(); + +private: void _update_kinematic_motion(); - void set_kinematic_motion_enabled(bool p_enabled); - bool is_kinematic_motion_enabled() const; - void set_sync_to_physics(bool p_enable); bool is_sync_to_physics_enabled() const; }; diff --git a/scene/register_scene_types.cpp b/scene/register_scene_types.cpp index 0c97fee711b..25c8e3e0b7e 100644 --- a/scene/register_scene_types.cpp +++ b/scene/register_scene_types.cpp @@ -488,6 +488,7 @@ void register_scene_types() { GDREGISTER_VIRTUAL_CLASS(CollisionObject3D); GDREGISTER_VIRTUAL_CLASS(PhysicsBody3D); GDREGISTER_CLASS(StaticBody3D); + GDREGISTER_CLASS(AnimatableBody3D); GDREGISTER_CLASS(RigidBody3D); GDREGISTER_CLASS(KinematicCollision3D); GDREGISTER_CLASS(CharacterBody3D); @@ -647,6 +648,7 @@ void register_scene_types() { GDREGISTER_VIRTUAL_CLASS(CollisionObject2D); GDREGISTER_VIRTUAL_CLASS(PhysicsBody2D); GDREGISTER_CLASS(StaticBody2D); + GDREGISTER_CLASS(AnimatableBody2D); GDREGISTER_CLASS(RigidBody2D); GDREGISTER_CLASS(CharacterBody2D); GDREGISTER_CLASS(KinematicCollision2D); diff --git a/servers/physics_2d/body_2d_sw.cpp b/servers/physics_2d/body_2d_sw.cpp index 64f71fd25c3..d86943e6589 100644 --- a/servers/physics_2d/body_2d_sw.cpp +++ b/servers/physics_2d/body_2d_sw.cpp @@ -269,11 +269,13 @@ void Body2DSW::set_state(PhysicsServer2D::BodyState p_state, const Variant &p_va } break; case PhysicsServer2D::BODY_STATE_LINEAR_VELOCITY: { linear_velocity = p_variant; + constant_linear_velocity = linear_velocity; wakeup(); } break; case PhysicsServer2D::BODY_STATE_ANGULAR_VELOCITY: { angular_velocity = p_variant; + constant_angular_velocity = angular_velocity; wakeup(); } break; @@ -429,10 +431,10 @@ void Body2DSW::integrate_forces(real_t p_step) { if (mode == PhysicsServer2D::BODY_MODE_KINEMATIC) { //compute motion, angular and etc. velocities from prev transform motion = new_transform.get_origin() - get_transform().get_origin(); - linear_velocity = motion / p_step; + linear_velocity = constant_linear_velocity + motion / p_step; real_t rot = new_transform.get_rotation() - get_transform().get_rotation(); - angular_velocity = remainder(rot, 2.0 * Math_PI) / p_step; + angular_velocity = constant_angular_velocity + remainder(rot, 2.0 * Math_PI) / p_step; do_motion = true; @@ -621,8 +623,6 @@ Body2DSW::Body2DSW() : direct_state_query_list(this) { mode = PhysicsServer2D::BODY_MODE_DYNAMIC; active = true; - angular_velocity = 0; - biased_angular_velocity = 0; mass = 1; inertia = 0; user_inertia = false; diff --git a/servers/physics_2d/body_2d_sw.h b/servers/physics_2d/body_2d_sw.h index 9cd53ceca13..b83afdbec6d 100644 --- a/servers/physics_2d/body_2d_sw.h +++ b/servers/physics_2d/body_2d_sw.h @@ -44,10 +44,13 @@ class Body2DSW : public CollisionObject2DSW { PhysicsServer2D::BodyMode mode; Vector2 biased_linear_velocity; - real_t biased_angular_velocity; + real_t biased_angular_velocity = 0.0; Vector2 linear_velocity; - real_t angular_velocity; + real_t angular_velocity = 0.0; + + Vector2 constant_linear_velocity; + real_t constant_angular_velocity = 0.0; real_t linear_damp; real_t angular_damp; diff --git a/servers/physics_3d/body_3d_sw.cpp b/servers/physics_3d/body_3d_sw.cpp index 7f62e4eb852..6640245d91a 100644 --- a/servers/physics_3d/body_3d_sw.cpp +++ b/servers/physics_3d/body_3d_sw.cpp @@ -302,10 +302,12 @@ void Body3DSW::set_state(PhysicsServer3D::BodyState p_state, const Variant &p_va } break; case PhysicsServer3D::BODY_STATE_LINEAR_VELOCITY: { linear_velocity = p_variant; + constant_linear_velocity = linear_velocity; wakeup(); } break; case PhysicsServer3D::BODY_STATE_ANGULAR_VELOCITY: { angular_velocity = p_variant; + constant_angular_velocity = angular_velocity; wakeup(); } break; @@ -473,7 +475,7 @@ void Body3DSW::integrate_forces(real_t p_step) { //compute motion, angular and etc. velocities from prev transform motion = new_transform.origin - get_transform().origin; do_motion = true; - linear_velocity = motion / p_step; + linear_velocity = constant_linear_velocity + motion / p_step; //compute a FAKE angular velocity, not so easy Basis rot = new_transform.basis.orthonormalized() * get_transform().basis.orthonormalized().transposed(); @@ -482,7 +484,7 @@ void Body3DSW::integrate_forces(real_t p_step) { rot.get_axis_angle(axis, angle); axis.normalize(); - angular_velocity = axis * (angle / p_step); + angular_velocity = constant_angular_velocity + axis * (angle / p_step); } else { if (!omit_force_integration && !first_integration) { //overridden by direct state query diff --git a/servers/physics_3d/body_3d_sw.h b/servers/physics_3d/body_3d_sw.h index f58f40652b2..38b7c4f94c7 100644 --- a/servers/physics_3d/body_3d_sw.h +++ b/servers/physics_3d/body_3d_sw.h @@ -44,6 +44,9 @@ class Body3DSW : public CollisionObject3DSW { Vector3 linear_velocity; Vector3 angular_velocity; + Vector3 constant_linear_velocity; + Vector3 constant_angular_velocity; + Vector3 biased_linear_velocity; Vector3 biased_angular_velocity; real_t mass;