diff options
-rw-r--r-- | scene/3d/physics_body.cpp | 9 | ||||
-rw-r--r-- | scene/3d/skeleton.cpp | 94 | ||||
-rw-r--r-- | scene/3d/skeleton.h | 7 |
3 files changed, 85 insertions, 25 deletions
diff --git a/scene/3d/physics_body.cpp b/scene/3d/physics_body.cpp index 5512fd4f10..0577a23ea6 100644 --- a/scene/3d/physics_body.cpp +++ b/scene/3d/physics_body.cpp @@ -1825,6 +1825,7 @@ void PhysicalBone::_notification(int p_what) { parent_skeleton = find_skeleton_parent(get_parent()); update_bone_id(); reset_to_rest_position(); + _reset_physics_simulation_state(); break; case NOTIFICATION_EXIT_TREE: if (parent_skeleton) { @@ -1886,10 +1887,8 @@ void PhysicalBone::_bind_methods() { ClassDB::bind_method(D_METHOD("set_body_offset", "offset"), &PhysicalBone::set_body_offset); ClassDB::bind_method(D_METHOD("get_body_offset"), &PhysicalBone::get_body_offset); - ClassDB::bind_method(D_METHOD("set_static_body", "simulate"), &PhysicalBone::set_static_body); ClassDB::bind_method(D_METHOD("is_static_body"), &PhysicalBone::is_static_body); - ClassDB::bind_method(D_METHOD("set_simulate_physics", "simulate"), &PhysicalBone::set_simulate_physics); ClassDB::bind_method(D_METHOD("get_simulate_physics"), &PhysicalBone::get_simulate_physics); ClassDB::bind_method(D_METHOD("is_simulating_physics"), &PhysicalBone::is_simulating_physics); @@ -1913,9 +1912,7 @@ void PhysicalBone::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::INT, "joint_type", PROPERTY_HINT_ENUM, "None,PinJoint,ConeJoint,HingeJoint,SliderJoint,6DOFJoint"), "set_joint_type", "get_joint_type"); ADD_PROPERTY(PropertyInfo(Variant::TRANSFORM, "joint_offset"), "set_joint_offset", "get_joint_offset"); - ADD_PROPERTY(PropertyInfo(Variant::BOOL, "simulate_physics"), "set_simulate_physics", "get_simulate_physics"); ADD_PROPERTY(PropertyInfo(Variant::TRANSFORM, "body_offset"), "set_body_offset", "get_body_offset"); - ADD_PROPERTY(PropertyInfo(Variant::BOOL, "static_body"), "set_static_body", "is_static_body"); ADD_PROPERTY(PropertyInfo(Variant::REAL, "mass", PROPERTY_HINT_EXP_RANGE, "0.01,65535,0.01"), "set_mass", "get_mass"); ADD_PROPERTY(PropertyInfo(Variant::REAL, "weight", PROPERTY_HINT_EXP_RANGE, "0.01,65535,0.01"), "set_weight", "get_weight"); @@ -2255,8 +2252,8 @@ PhysicalBone::PhysicalBone() : joint_data(NULL), static_body(false), simulate_physics(false), - _internal_static_body(!static_body), - _internal_simulate_physics(simulate_physics), + _internal_static_body(false), + _internal_simulate_physics(false), bone_id(-1), parent_skeleton(NULL), bone_name(""), diff --git a/scene/3d/skeleton.cpp b/scene/3d/skeleton.cpp index a7eb54c85d..76d90dc6ff 100644 --- a/scene/3d/skeleton.cpp +++ b/scene/3d/skeleton.cpp @@ -330,7 +330,7 @@ void Skeleton::add_bone(const String &p_name) { _make_dirty(); update_gizmo(); } -int Skeleton::find_bone(String p_name) const { +int Skeleton::find_bone(const String &p_name) const { for (int i = 0; i < bones.size(); i++) { @@ -347,6 +347,19 @@ String Skeleton::get_bone_name(int p_bone) const { return bones[p_bone].name; } +bool Skeleton::is_bone_parent_of(int p_bone, int p_parent_bone_id) const { + + int parent_of_bone = get_bone_parent(p_bone); + + if (-1 == parent_of_bone) + return false; + + if (parent_of_bone == p_parent_bone_id) + return true; + + return is_bone_parent_of(parent_of_bone, p_parent_bone_id); +} + int Skeleton::get_bone_count() const { return bones.size(); @@ -534,18 +547,6 @@ void Skeleton::localize_rests() { } } -void _notify_physical_bones_simulation(bool start, Node *p_node) { - - for (int i = p_node->get_child_count() - 1; 0 <= i; --i) { - _notify_physical_bones_simulation(start, p_node->get_child(i)); - } - - PhysicalBone *pb = Object::cast_to<PhysicalBone>(p_node); - if (pb) { - pb->set_simulate_physics(start); - } -} - void Skeleton::bind_physical_bone_to_bone(int p_bone, PhysicalBone *p_physical_bone) { ERR_FAIL_INDEX(p_bone, bones.size()); ERR_FAIL_COND(bones[p_bone].physical_bone); @@ -603,8 +604,67 @@ void Skeleton::_rebuild_physical_bones_cache() { } } -void Skeleton::physical_bones_simulation(bool start) { - _notify_physical_bones_simulation(start, this); +void _pb_stop_simulation(Node *p_node) { + + for (int i = p_node->get_child_count() - 1; 0 <= i; --i) { + _pb_stop_simulation(p_node->get_child(i)); + } + + PhysicalBone *pb = Object::cast_to<PhysicalBone>(p_node); + if (pb) { + pb->set_simulate_physics(false); + pb->set_static_body(false); + } +} + +void Skeleton::physical_bones_stop_simulation() { + _pb_stop_simulation(this); +} + +void _pb_start_simulation(const Skeleton *p_skeleton, Node *p_node, const Vector<int> &p_sim_bones) { + + for (int i = p_node->get_child_count() - 1; 0 <= i; --i) { + _pb_start_simulation(p_skeleton, p_node->get_child(i), p_sim_bones); + } + + PhysicalBone *pb = Object::cast_to<PhysicalBone>(p_node); + if (pb) { + bool sim = false; + for (int i = p_sim_bones.size() - 1; 0 <= i; --i) { + if (p_sim_bones[i] == pb->get_bone_id() || p_skeleton->is_bone_parent_of(pb->get_bone_id(), p_sim_bones[i])) { + sim = true; + break; + } + } + + pb->set_simulate_physics(true); + if (sim) { + pb->set_static_body(false); + } else { + pb->set_static_body(true); + } + } +} + +void Skeleton::physical_bones_start_simulation_on(const Array &p_bones) { + + Vector<int> sim_bones; + if (p_bones.size() <= 0) { + sim_bones.push_back(0); // if no bones is specified, activate ragdoll on full body + } else { + sim_bones.resize(p_bones.size()); + int c = 0; + for (int i = sim_bones.size() - 1; 0 <= i; --i) { + if (Variant::STRING == p_bones.get(i).get_type()) { + int bone_id = find_bone(p_bones.get(i)); + if (bone_id != -1) + sim_bones[c++] = bone_id; + } + } + sim_bones.resize(c); + } + + _pb_start_simulation(this, this, sim_bones); } void _physical_bones_add_remove_collision_exception(bool p_add, Node *p_node, RID p_exception) { @@ -667,7 +727,8 @@ void Skeleton::_bind_methods() { ClassDB::bind_method(D_METHOD("get_bone_transform", "bone_idx"), &Skeleton::get_bone_transform); - ClassDB::bind_method(D_METHOD("physical_bones_simulation", "start"), &Skeleton::physical_bones_simulation); + ClassDB::bind_method(D_METHOD("physical_bones_stop_simulation"), &Skeleton::physical_bones_stop_simulation); + ClassDB::bind_method(D_METHOD("physical_bones_start_simulation", "bones"), &Skeleton::physical_bones_start_simulation_on, DEFVAL(Array())); ClassDB::bind_method(D_METHOD("physical_bones_add_collision_exception", "exception"), &Skeleton::physical_bones_add_collision_exception); ClassDB::bind_method(D_METHOD("physical_bones_remove_collision_exception", "exception"), &Skeleton::physical_bones_remove_collision_exception); @@ -683,6 +744,5 @@ Skeleton::Skeleton() { } Skeleton::~Skeleton() { - VisualServer::get_singleton()->free(skeleton); } diff --git a/scene/3d/skeleton.h b/scene/3d/skeleton.h index f0e71c8b4f..dad11960a5 100644 --- a/scene/3d/skeleton.h +++ b/scene/3d/skeleton.h @@ -120,9 +120,11 @@ public: // skeleton creation api void add_bone(const String &p_name); - int find_bone(String p_name) const; + int find_bone(const String &p_name) const; String get_bone_name(int p_bone) const; + bool is_bone_parent_of(int p_bone_id, int p_parent_bone_id) const; + void set_bone_parent(int p_bone, int p_parent); int get_bone_parent(int p_bone) const; @@ -176,7 +178,8 @@ private: void _rebuild_physical_bones_cache(); public: - void physical_bones_simulation(bool start); + void physical_bones_stop_simulation(); + void physical_bones_start_simulation_on(const Array &p_bones); void physical_bones_add_collision_exception(RID p_exception); void physical_bones_remove_collision_exception(RID p_exception); |