From 3edb4f22564342bf6d50dca3f2daabba7d0a2262 Mon Sep 17 00:00:00 2001 From: TwistedTwigleg Date: Fri, 31 Jul 2020 11:37:06 -0400 Subject: [PATCH] Changes: * PhysicalBone2D - Fixed issue where physics would simulate regardless of whether it was supposed to or not. Now physics only simulate when simulate_physics is true. * PhysicalBone2D - Fixed issue where PhysicalBone2D nodes would be actively able to collide with other objects in the scene when simulate_physics is false. * PhysicalBone2D - Removed bloat code that was not doing anything. * PhysicalBones Modification2D - Fixed issue where the modification was not properly starting or stopping PhysicalBone2D nodes when calling start_simulation and stop_simulation. * PhysicalBones Modification2D - Make start_simulation and stop_simulation calls stored and executed in _execute, so they still work when called in _ready. --- scene/2d/physical_bone_2d.cpp | 48 +++++++-------- scene/2d/physical_bone_2d.h | 1 - scene/resources/skeleton_modification_2d.cpp | 62 +++++++++++--------- scene/resources/skeleton_modification_2d.h | 5 ++ 4 files changed, 58 insertions(+), 58 deletions(-) diff --git a/scene/2d/physical_bone_2d.cpp b/scene/2d/physical_bone_2d.cpp index a852939f9fde..3551d2203078 100644 --- a/scene/2d/physical_bone_2d.cpp +++ b/scene/2d/physical_bone_2d.cpp @@ -73,6 +73,14 @@ void PhysicalBone2D::_notification(int p_what) { child_joint->set_global_position(node_a->get_global_transform().get_origin()); } } + + // Remove any collision layers and masks if we're disabled. + // We do this so the RigidBody can still have it's layers and masks set like normal, but they will not be applied + // unless physics are told to simulate, only making them effective when we want them to be. + if (!_internal_simulate_physics) { + PhysicsServer2D::get_singleton()->body_set_collision_layer(get_rid(), 0); + PhysicsServer2D::get_singleton()->body_set_collision_mask(get_rid(), 0); + } } // Only in the editor: keep the PhysicalBone2D at the Bone2D position (if there is one) at all times. @@ -125,27 +133,6 @@ void PhysicalBone2D::_find_joint_child() { } } -void PhysicalBone2D::_direct_state_changed(Object *p_state) { - if (!simulate_physics || !_internal_simulate_physics) { - return; - } - PhysicsDirectBodyState2D *state; - state = Object::cast_to(p_state); - - if (!state) { - // This is not the physics we are looking for, so ignore it! - return; - } - - Transform2D global_transform(state->get_transform()); - - // Add rotation constraints here? Might be something to add in the future... - - set_notify_transform(false); - set_global_transform(global_transform); - set_notify_transform(true); -} - String PhysicalBone2D::get_configuration_warning() const { String warning = Node2D::get_configuration_warning(); @@ -200,24 +187,27 @@ void PhysicalBone2D::_auto_configure_joint() { } void PhysicalBone2D::_start_physics_simulation() { - if (_internal_simulate_physics || !parent_skeleton) { + if (_internal_simulate_physics) { return; } // Reset to Bone2D position _position_at_bone2d(); + // Let the RigidBody executing its force integration. PhysicsServer2D::get_singleton()->body_set_force_integration_callback(get_rid(), this, "_direct_state_changed"); + + // Apply the layers and masks + PhysicsServer2D::get_singleton()->body_set_collision_layer(get_rid(), get_collision_layer()); + PhysicsServer2D::get_singleton()->body_set_collision_mask(get_rid(), get_collision_mask()); + _internal_simulate_physics = true; } void PhysicalBone2D::_stop_physics_simulation() { - if (!parent_skeleton) { - return; - } - if (_internal_simulate_physics) { - PhysicsServer3D::get_singleton()->body_set_force_integration_callback(get_rid(), nullptr, ""); + // Stop the RigidBody from executing its force integration. + PhysicsServer2D::get_singleton()->body_set_force_integration_callback(get_rid(), nullptr, ""); _internal_simulate_physics = false; // Reset to Bone2D position @@ -242,8 +232,8 @@ void PhysicalBone2D::set_simulate_physics(bool p_simulate) { if (p_simulate == simulate_physics) { return; } - simulate_physics = p_simulate; + if (simulate_physics) { _start_physics_simulation(); } else { @@ -340,6 +330,8 @@ void PhysicalBone2D::_bind_methods() { } PhysicalBone2D::PhysicalBone2D() { + // Stop the RigidBody from executing its force integration. + PhysicsServer2D::get_singleton()->body_set_force_integration_callback(get_rid(), nullptr, ""); } PhysicalBone2D::~PhysicalBone2D() { diff --git a/scene/2d/physical_bone_2d.h b/scene/2d/physical_bone_2d.h index 58eb5901e7b4..38829a874c84 100644 --- a/scene/2d/physical_bone_2d.h +++ b/scene/2d/physical_bone_2d.h @@ -44,7 +44,6 @@ class PhysicalBone2D : public RigidBody2D { bool _get(const StringName &p_name, Variant &r_ret) const; void _get_property_list(List *p_list) const; void _notification(int p_what); - void _direct_state_changed(Object *p_state); static void _bind_methods(); private: diff --git a/scene/resources/skeleton_modification_2d.cpp b/scene/resources/skeleton_modification_2d.cpp index 71a216355b49..dac5a14a6147 100644 --- a/scene/resources/skeleton_modification_2d.cpp +++ b/scene/resources/skeleton_modification_2d.cpp @@ -2631,6 +2631,10 @@ void SkeletonModification2DPhysicalBones::execute(float delta) { return; } + if (_simulation_state_dirty) { + _update_simulation_state(); + } + for (int i = 0; i < physical_bone_chain.size(); i++) { PhysicalBone_Data2D bone_data = physical_bone_chain[i]; if (bone_data.physical_bone_node_cache.is_null()) { @@ -2644,10 +2648,10 @@ void SkeletonModification2DPhysicalBones::execute(float delta) { ERR_FAIL_INDEX_MSG(physical_bone->get_bone2d_index(), stack->skeleton->get_bone_count(), "PhysicalBone2D at index " + itos(i) + " has invalid Bone2D!"); Bone2D *bone_2d = stack->skeleton->get_bone(physical_bone->get_bone2d_index()); - // TODO: make sure the PhysicalBone2D is simulating before applying. - - bone_2d->set_global_transform(physical_bone->get_global_transform()); - stack->skeleton->set_bone_local_pose_override(physical_bone->get_bone2d_index(), bone_2d->get_transform(), stack->strength, true); + if (physical_bone->get_simulate_physics()) { + bone_2d->set_global_transform(physical_bone->get_global_transform()); + stack->skeleton->set_bone_local_pose_override(physical_bone->get_bone2d_index(), bone_2d->get_transform(), stack->strength, true); + } } } @@ -2721,39 +2725,39 @@ void SkeletonModification2DPhysicalBones::fetch_physical_bones() { } void SkeletonModification2DPhysicalBones::start_simulation(const TypedArray &p_bones) { - if (p_bones.size() <= 0) { - // Simulate all the bones! - for (int i = 0; i < physical_bone_chain.size(); i++) { - PhysicalBone2D *physical_bone = Object::cast_to(ObjectDB::get_instance(physical_bone_chain[i].physical_bone_node_cache)); - if (!physical_bone) { - continue; - } + _simulation_state_dirty = true; + _simulation_state_dirty_names = p_bones; + _simulation_state_dirty_process = true; - physical_bone->set_simulate_physics(true); - } - } else { - for (int i = 0; i < physical_bone_chain.size(); i++) { - PhysicalBone2D *physical_bone = Object::cast_to(ObjectDB::get_instance(physical_bone_chain[i].physical_bone_node_cache)); - if (!physical_bone) { - continue; - } - if (p_bones.has(physical_bone->get_name())) { - physical_bone->set_simulate_physics(true); - } - } + if (is_setup) { + _update_simulation_state(); } } void SkeletonModification2DPhysicalBones::stop_simulation(const TypedArray &p_bones) { - if (p_bones.size() <= 0) { - // Stop all the bones! + _simulation_state_dirty = true; + _simulation_state_dirty_names = p_bones; + _simulation_state_dirty_process = false; + + if (is_setup) { + _update_simulation_state(); + } +} + +void SkeletonModification2DPhysicalBones::_update_simulation_state() { + if (!_simulation_state_dirty) { + return; + } + _simulation_state_dirty = false; + + if (_simulation_state_dirty_names.size() <= 0) { for (int i = 0; i < physical_bone_chain.size(); i++) { - PhysicalBone2D *physical_bone = Object::cast_to(ObjectDB::get_instance(physical_bone_chain[i].physical_bone_node_cache)); + PhysicalBone2D *physical_bone = Object::cast_to(stack->skeleton->get_node(physical_bone_chain[i].physical_bone_node)); if (!physical_bone) { continue; } - physical_bone->set_simulate_physics(false); + physical_bone->set_simulate_physics(_simulation_state_dirty_process); } } else { for (int i = 0; i < physical_bone_chain.size(); i++) { @@ -2761,8 +2765,8 @@ void SkeletonModification2DPhysicalBones::stop_simulation(const TypedArrayget_name())) { - physical_bone->set_simulate_physics(false); + if (_simulation_state_dirty_names.has(physical_bone->get_name())) { + physical_bone->set_simulate_physics(_simulation_state_dirty_process); } } } diff --git a/scene/resources/skeleton_modification_2d.h b/scene/resources/skeleton_modification_2d.h index 56bf0013a21b..86aa41118a33 100644 --- a/scene/resources/skeleton_modification_2d.h +++ b/scene/resources/skeleton_modification_2d.h @@ -548,6 +548,11 @@ class SkeletonModification2DPhysicalBones : public SkeletonModification2D { void _physical_bone_update_cache(int p_joint_idx); + bool _simulation_state_dirty = false; + TypedArray _simulation_state_dirty_names; + bool _simulation_state_dirty_process; + void _update_simulation_state(); + protected: static void _bind_methods(); bool _get(const StringName &p_path, Variant &r_ret) const;