diff options
Diffstat (limited to 'scene/3d/skeleton.cpp')
-rw-r--r-- | scene/3d/skeleton.cpp | 131 |
1 files changed, 109 insertions, 22 deletions
diff --git a/scene/3d/skeleton.cpp b/scene/3d/skeleton.cpp index 17e67c47d1..b2252bcb04 100644 --- a/scene/3d/skeleton.cpp +++ b/scene/3d/skeleton.cpp @@ -30,8 +30,8 @@ #include "skeleton.h" +#include "core/engine.h" #include "core/message_queue.h" - #include "core/project_settings.h" #include "scene/3d/physics_body.h" #include "scene/resources/surface_tool.h" @@ -40,6 +40,7 @@ void SkinReference::_skin_changed() { if (skeleton_node) { skeleton_node->_make_dirty(); } + skeleton_version = 0; } void SkinReference::_bind_methods() { @@ -137,7 +138,7 @@ bool Skeleton::_get(const StringName &p_path, Variant &r_ret) const { else if (what == "bound_children") { Array children; - for (const List<uint32_t>::Element *E = bones[which].nodes_bound.front(); E; E = E->next()) { + for (const List<ObjectID>::Element *E = bones[which].nodes_bound.front(); E; E = E->next()) { Object *obj = ObjectDB::get_instance(E->get()); ERR_CONTINUE(!obj); @@ -301,7 +302,7 @@ void Skeleton::_notification(int p_what) { b.global_pose_override_amount = 0.0; } - for (List<uint32_t>::Element *E = b.nodes_bound.front(); E; E = E->next()) { + for (List<ObjectID>::Element *E = b.nodes_bound.front(); E; E = E->next()) { Object *obj = ObjectDB::get_instance(E->get()); ERR_CONTINUE(!obj); @@ -321,10 +322,49 @@ void Skeleton::_notification(int p_what) { if (E->get()->bind_count != bind_count) { VS::get_singleton()->skeleton_allocate(skeleton, bind_count); E->get()->bind_count = bind_count; + E->get()->skin_bone_indices.resize(bind_count); + E->get()->skin_bone_indices_ptrs = E->get()->skin_bone_indices.ptrw(); + } + + if (E->get()->skeleton_version != version) { + + for (uint32_t i = 0; i < bind_count; i++) { + StringName bind_name = skin->get_bind_name(i); + + if (bind_name != StringName()) { + //bind name used, use this + bool found = false; + for (int j = 0; j < len; j++) { + if (bonesptr[j].name == bind_name) { + E->get()->skin_bone_indices_ptrs[i] = j; + found = true; + break; + } + } + + if (!found) { + ERR_PRINT("Skin bind #" + itos(i) + " contains named bind '" + String(bind_name) + "' but Skeleton has no bone by that name."); + E->get()->skin_bone_indices_ptrs[i] = 0; + } + } else if (skin->get_bind_bone(i) >= 0) { + int bind_index = skin->get_bind_bone(i); + if (bind_index >= len) { + ERR_PRINT("Skin bind #" + itos(i) + " contains bone index bind: " + itos(bind_index) + " , which is greater than the skeleton bone count: " + itos(len) + "."); + E->get()->skin_bone_indices_ptrs[i] = 0; + } else { + E->get()->skin_bone_indices_ptrs[i] = bind_index; + } + } else { + ERR_PRINT("Skin bind #" + itos(i) + " does not contain a name nor a bone index."); + E->get()->skin_bone_indices_ptrs[i] = 0; + } + } + + E->get()->skeleton_version = version; } for (uint32_t i = 0; i < bind_count; i++) { - uint32_t bone_index = skin->get_bind_bone(i); + uint32_t bone_index = E->get()->skin_bone_indices_ptrs[i]; ERR_CONTINUE(bone_index >= (uint32_t)len); vs->skeleton_bone_set_transform(skeleton, i, bonesptr[bone_index].pose_global * skin->get_bind_pose(i)); } @@ -332,6 +372,27 @@ void Skeleton::_notification(int p_what) { dirty = false; } break; + +#ifndef _3D_DISABLED + case NOTIFICATION_INTERNAL_PHYSICS_PROCESS: { + // This is active only if the skeleton animates the physical bones + // and the state of the bone is not active. + if (animate_physical_bones) { + for (int i = 0; i < bones.size(); i += 1) { + if (bones[i].physical_bone) { + if (bones[i].physical_bone->is_simulating_physics() == false) { + bones[i].physical_bone->reset_to_rest_position(); + } + } + } + } + } break; + case NOTIFICATION_READY: { + if (Engine::get_singleton()->is_editor_hint()) { + set_physics_process_internal(true); + } + } break; +#endif } } @@ -366,6 +427,7 @@ void Skeleton::add_bone(const String &p_name) { b.name = p_name; bones.push_back(b); process_order_dirty = true; + version++; _make_dirty(); update_gizmo(); } @@ -483,9 +545,9 @@ void Skeleton::bind_child_node_to_bone(int p_bone, Node *p_node) { ERR_FAIL_NULL(p_node); ERR_FAIL_INDEX(p_bone, bones.size()); - uint32_t id = p_node->get_instance_id(); + ObjectID id = p_node->get_instance_id(); - for (const List<uint32_t>::Element *E = bones[p_bone].nodes_bound.front(); E; E = E->next()) { + for (const List<ObjectID>::Element *E = bones[p_bone].nodes_bound.front(); E; E = E->next()) { if (E->get() == id) return; // already here @@ -498,14 +560,14 @@ void Skeleton::unbind_child_node_from_bone(int p_bone, Node *p_node) { ERR_FAIL_NULL(p_node); ERR_FAIL_INDEX(p_bone, bones.size()); - uint32_t id = p_node->get_instance_id(); + ObjectID id = p_node->get_instance_id(); bones.write[p_bone].nodes_bound.erase(id); } void Skeleton::get_bound_child_nodes_to_bone(int p_bone, List<Node *> *p_bound) const { ERR_FAIL_INDEX(p_bone, bones.size()); - for (const List<uint32_t>::Element *E = bones[p_bone].nodes_bound.front(); E; E = E->next()) { + for (const List<ObjectID>::Element *E = bones[p_bone].nodes_bound.front(); E; E = E->next()) { Object *obj = ObjectDB::get_instance(E->get()); ERR_CONTINUE(!obj); @@ -517,7 +579,7 @@ void Skeleton::clear_bones() { bones.clear(); process_order_dirty = true; - + version++; _make_dirty(); } @@ -584,6 +646,27 @@ void Skeleton::localize_rests() { #ifndef _3D_DISABLED +void Skeleton::set_animate_physical_bones(bool p_animate) { + animate_physical_bones = p_animate; + + if (Engine::get_singleton()->is_editor_hint() == false) { + bool sim = false; + for (int i = 0; i < bones.size(); i += 1) { + if (bones[i].physical_bone) { + bones[i].physical_bone->reset_physics_simulation_state(); + if (bones[i].physical_bone->is_simulating_physics()) { + sim = true; + } + } + } + set_physics_process_internal(sim == false && p_animate); + } +} + +bool Skeleton::get_animate_physical_bones() const { + return animate_physical_bones; +} + 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); @@ -653,12 +736,14 @@ void _pb_stop_simulation(Node *p_node) { 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); + if (Engine::get_singleton()->is_editor_hint() == false && animate_physical_bones) { + set_physics_process_internal(true); + } } void _pb_start_simulation(const Skeleton *p_skeleton, Node *p_node, const Vector<int> &p_sim_bones) { @@ -669,24 +754,17 @@ void _pb_start_simulation(const Skeleton *p_skeleton, Node *p_node, const Vector 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; + pb->set_simulate_physics(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) { + set_physics_process_internal(false); Vector<int> sim_bones; if (p_bones.size() <= 0) { @@ -695,7 +773,8 @@ void Skeleton::physical_bones_start_simulation_on(const Array &p_bones) { 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()) { + Variant::Type type = p_bones.get(i).get_type(); + if (Variant::STRING == type || Variant::STRING_NAME == type) { int bone_id = find_bone(p_bones.get(i)); if (bone_id != -1) sim_bones.write[c++] = bone_id; @@ -791,8 +870,10 @@ Ref<SkinReference> Skeleton::register_skin(const Ref<Skin> &p_skin) { skin_bindings.insert(skin_ref.operator->()); - skin->connect("changed", skin_ref.operator->(), "_skin_changed"); - _make_dirty(); + skin->connect_compat("changed", skin_ref.operator->(), "_skin_changed"); + + _make_dirty(); //skin needs to be updated, so update skeleton + return skin_ref; } @@ -836,11 +917,15 @@ void Skeleton::_bind_methods() { #ifndef _3D_DISABLED + ClassDB::bind_method(D_METHOD("set_animate_physical_bones"), &Skeleton::set_animate_physical_bones); + ClassDB::bind_method(D_METHOD("get_animate_physical_bones"), &Skeleton::get_animate_physical_bones); + 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); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "animate_physical_bones"), "set_animate_physical_bones", "get_animate_physical_bones"); #endif // _3D_DISABLED BIND_CONSTANT(NOTIFICATION_UPDATE_SKELETON); @@ -848,7 +933,9 @@ void Skeleton::_bind_methods() { Skeleton::Skeleton() { + animate_physical_bones = true; dirty = false; + version = 1; process_order_dirty = true; } |