diff options
Diffstat (limited to 'scene/3d/skeleton_3d.cpp')
-rw-r--r-- | scene/3d/skeleton_3d.cpp | 172 |
1 files changed, 79 insertions, 93 deletions
diff --git a/scene/3d/skeleton_3d.cpp b/scene/3d/skeleton_3d.cpp index 9e403a6ecd..1bc138704e 100644 --- a/scene/3d/skeleton_3d.cpp +++ b/scene/3d/skeleton_3d.cpp @@ -153,14 +153,14 @@ bool Skeleton3D::_get(const StringName &p_path, Variant &r_ret) const { void Skeleton3D::_get_property_list(List<PropertyInfo> *p_list) const { for (int i = 0; i < bones.size(); i++) { - String prep = "bones/" + itos(i) + "/"; - p_list->push_back(PropertyInfo(Variant::STRING, prep + "name", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR)); - p_list->push_back(PropertyInfo(Variant::INT, prep + "parent", PROPERTY_HINT_RANGE, "-1," + itos(bones.size() - 1) + ",1", PROPERTY_USAGE_NO_EDITOR)); - p_list->push_back(PropertyInfo(Variant::TRANSFORM3D, prep + "rest", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR)); - p_list->push_back(PropertyInfo(Variant::BOOL, prep + "enabled", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR)); - p_list->push_back(PropertyInfo(Variant::VECTOR3, prep + "position", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR)); - p_list->push_back(PropertyInfo(Variant::QUATERNION, prep + "rotation", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR)); - p_list->push_back(PropertyInfo(Variant::VECTOR3, prep + "scale", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR)); + const String prep = vformat("%s/%d/", PNAME("bones"), i); + p_list->push_back(PropertyInfo(Variant::STRING, prep + PNAME("name"), PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR)); + p_list->push_back(PropertyInfo(Variant::INT, prep + PNAME("parent"), PROPERTY_HINT_RANGE, "-1," + itos(bones.size() - 1) + ",1", PROPERTY_USAGE_NO_EDITOR)); + p_list->push_back(PropertyInfo(Variant::TRANSFORM3D, prep + PNAME("rest"), PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR)); + p_list->push_back(PropertyInfo(Variant::BOOL, prep + PNAME("enabled"), PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR)); + p_list->push_back(PropertyInfo(Variant::VECTOR3, prep + PNAME("position"), PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR)); + p_list->push_back(PropertyInfo(Variant::QUATERNION, prep + PNAME("rotation"), PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR)); + p_list->push_back(PropertyInfo(Variant::VECTOR3, prep + PNAME("scale"), PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR)); } #ifndef _3D_DISABLED @@ -176,39 +176,37 @@ void Skeleton3D::_get_property_list(List<PropertyInfo> *p_list) const { } } -void Skeleton3D::_validate_property(PropertyInfo &property) const { - PackedStringArray split = property.name.split("/"); +void Skeleton3D::_validate_property(PropertyInfo &p_property) const { + PackedStringArray split = p_property.name.split("/"); if (split.size() == 3 && split[0] == "bones") { if (split[2] == "rest") { - property.usage |= PROPERTY_USAGE_READ_ONLY; + p_property.usage |= PROPERTY_USAGE_READ_ONLY; } if (is_show_rest_only()) { if (split[2] == "enabled") { - property.usage |= PROPERTY_USAGE_READ_ONLY; + p_property.usage |= PROPERTY_USAGE_READ_ONLY; } if (split[2] == "position") { - property.usage |= PROPERTY_USAGE_READ_ONLY; + p_property.usage |= PROPERTY_USAGE_READ_ONLY; } if (split[2] == "rotation") { - property.usage |= PROPERTY_USAGE_READ_ONLY; + p_property.usage |= PROPERTY_USAGE_READ_ONLY; } if (split[2] == "scale") { - property.usage |= PROPERTY_USAGE_READ_ONLY; + p_property.usage |= PROPERTY_USAGE_READ_ONLY; } } else if (!is_bone_enabled(split[1].to_int())) { if (split[2] == "position") { - property.usage |= PROPERTY_USAGE_READ_ONLY; + p_property.usage |= PROPERTY_USAGE_READ_ONLY; } if (split[2] == "rotation") { - property.usage |= PROPERTY_USAGE_READ_ONLY; + p_property.usage |= PROPERTY_USAGE_READ_ONLY; } if (split[2] == "scale") { - property.usage |= PROPERTY_USAGE_READ_ONLY; + p_property.usage |= PROPERTY_USAGE_READ_ONLY; } } } - - Node3D::_validate_property(property); } void Skeleton3D::_update_process_order() { @@ -263,19 +261,19 @@ void Skeleton3D::_notification(int p_what) { force_update_all_bone_transforms(); // Update skins. - for (Set<SkinReference *>::Element *E = skin_bindings.front(); E; E = E->next()) { - const Skin *skin = E->get()->skin.operator->(); - RID skeleton = E->get()->skeleton; + for (SkinReference *E : skin_bindings) { + const Skin *skin = E->skin.operator->(); + RID skeleton = E->skeleton; uint32_t bind_count = skin->get_bind_count(); - if (E->get()->bind_count != bind_count) { + if (E->bind_count != bind_count) { RS::get_singleton()->skeleton_allocate_data(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(); + E->bind_count = bind_count; + E->skin_bone_indices.resize(bind_count); + E->skin_bone_indices_ptrs = E->skin_bone_indices.ptrw(); } - if (E->get()->skeleton_version != version) { + if (E->skeleton_version != version) { for (uint32_t i = 0; i < bind_count; i++) { StringName bind_name = skin->get_bind_name(i); @@ -284,7 +282,7 @@ void Skeleton3D::_notification(int p_what) { bool found = false; for (int j = 0; j < len; j++) { if (bonesptr[j].name == bind_name) { - E->get()->skin_bone_indices_ptrs[i] = j; + E->skin_bone_indices_ptrs[i] = j; found = true; break; } @@ -292,27 +290,27 @@ void Skeleton3D::_notification(int p_what) { if (!found) { ERR_PRINT("Skin bind #" + itos(i) + " contains named bind '" + String(bind_name) + "' but Skeleton3D has no bone by that name."); - E->get()->skin_bone_indices_ptrs[i] = 0; + E->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; + E->skin_bone_indices_ptrs[i] = 0; } else { - E->get()->skin_bone_indices_ptrs[i] = bind_index; + E->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->skin_bone_indices_ptrs[i] = 0; } } - E->get()->skeleton_version = version; + E->skeleton_version = version; } for (uint32_t i = 0; i < bind_count; i++) { - uint32_t bone_index = E->get()->skin_bone_indices_ptrs[i]; + uint32_t bone_index = E->skin_bone_indices_ptrs[i]; ERR_CONTINUE(bone_index >= (uint32_t)len); rs->skeleton_bone_set_transform(skeleton, i, bonesptr[bone_index].pose_global * skin->get_bind_pose(i)); } @@ -326,13 +324,11 @@ void Skeleton3D::_notification(int p_what) { 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 (Engine::get_singleton()->is_editor_hint()) { - 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(); - } + 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(); } } } @@ -495,6 +491,19 @@ int Skeleton3D::get_bone_axis_forward_enum(int p_bone) { return bones[p_bone].rest_bone_forward_axis; } +void Skeleton3D::set_motion_scale(float p_motion_scale) { + if (p_motion_scale <= 0) { + motion_scale = 1; + ERR_FAIL_MSG("Motion scale must be larger than 0."); + } + motion_scale = p_motion_scale; +} + +float Skeleton3D::get_motion_scale() const { + ERR_FAIL_COND_V(motion_scale <= 0, 1); + return motion_scale; +} + // Skeleton creation api void Skeleton3D::add_bone(const String &p_name) { @@ -604,43 +613,8 @@ Vector<int> Skeleton3D::get_bone_children(int p_bone) { return bones[p_bone].child_bones; } -void Skeleton3D::set_bone_children(int p_bone, Vector<int> p_children) { - const int bone_size = bones.size(); - ERR_FAIL_INDEX(p_bone, bone_size); - bones.write[p_bone].child_bones = p_children; - - process_order_dirty = true; - rest_dirty = true; - _make_dirty(); -} - -void Skeleton3D::add_bone_child(int p_bone, int p_child) { - const int bone_size = bones.size(); - ERR_FAIL_INDEX(p_bone, bone_size); - bones.write[p_bone].child_bones.push_back(p_child); - - process_order_dirty = true; - rest_dirty = true; - _make_dirty(); -} - -void Skeleton3D::remove_bone_child(int p_bone, int p_child) { - const int bone_size = bones.size(); - ERR_FAIL_INDEX(p_bone, bone_size); - - int child_idx = bones[p_bone].child_bones.find(p_child); - if (child_idx >= 0) { - bones.write[p_bone].child_bones.remove_at(child_idx); - } else { - WARN_PRINT("Cannot remove child bone: Child bone not found."); - } - - process_order_dirty = true; - rest_dirty = true; - _make_dirty(); -} - Vector<int> Skeleton3D::get_parentless_bones() { + _update_process_order(); return parentless_bones; } @@ -750,6 +724,20 @@ Vector3 Skeleton3D::get_bone_pose_scale(int p_bone) const { return bones[p_bone].pose_scale; } +void Skeleton3D::reset_bone_pose(int p_bone) { + const int bone_size = bones.size(); + ERR_FAIL_INDEX(p_bone, bone_size); + set_bone_pose_position(p_bone, bones[p_bone].rest.origin); + set_bone_pose_rotation(p_bone, bones[p_bone].rest.basis.get_rotation_quaternion()); + set_bone_pose_scale(p_bone, bones[p_bone].rest.basis.get_scale()); +} + +void Skeleton3D::reset_bone_poses() { + for (int i = 0; i < bones.size(); i++) { + reset_bone_pose(i); + } +} + Transform3D Skeleton3D::get_bone_pose(int p_bone) const { const int bone_size = bones.size(); ERR_FAIL_INDEX_V(p_bone, bone_size, Transform3D()); @@ -767,8 +755,6 @@ void Skeleton3D::_make_dirty() { } void Skeleton3D::localize_rests() { - _update_process_order(); - Vector<int> bones_to_process = get_parentless_bones(); while (bones_to_process.size() > 0) { int current_bone_idx = bones_to_process[0]; @@ -960,7 +946,6 @@ Ref<Skin> Skeleton3D::create_skin_from_rest_transforms() { skin.instantiate(); skin->set_bind_count(bones.size()); - _update_process_order(); // Just in case. // Pose changed, rebuild cache of inverses. const Bone *bonesptr = bones.ptr(); @@ -1000,9 +985,9 @@ Ref<Skin> Skeleton3D::create_skin_from_rest_transforms() { Ref<SkinReference> Skeleton3D::register_skin(const Ref<Skin> &p_skin) { ERR_FAIL_COND_V(p_skin.is_null(), Ref<SkinReference>()); - for (Set<SkinReference *>::Element *E = skin_bindings.front(); E; E = E->next()) { - if (E->get()->skin == p_skin) { - return Ref<SkinReference>(E->get()); + for (const SkinReference *E : skin_bindings) { + if (E->skin == p_skin) { + return Ref<SkinReference>(E); } } @@ -1217,9 +1202,6 @@ void Skeleton3D::_bind_methods() { ClassDB::bind_method(D_METHOD("unparent_bone_and_rest", "bone_idx"), &Skeleton3D::unparent_bone_and_rest); ClassDB::bind_method(D_METHOD("get_bone_children", "bone_idx"), &Skeleton3D::get_bone_children); - ClassDB::bind_method(D_METHOD("set_bone_children", "bone_idx", "bone_children"), &Skeleton3D::set_bone_children); - ClassDB::bind_method(D_METHOD("add_bone_child", "bone_idx", "child_bone_idx"), &Skeleton3D::add_bone_child); - ClassDB::bind_method(D_METHOD("remove_bone_child", "bone_idx", "child_bone_idx"), &Skeleton3D::remove_bone_child); ClassDB::bind_method(D_METHOD("get_parentless_bones"), &Skeleton3D::get_parentless_bones); @@ -1243,6 +1225,9 @@ void Skeleton3D::_bind_methods() { ClassDB::bind_method(D_METHOD("get_bone_pose_rotation", "bone_idx"), &Skeleton3D::get_bone_pose_rotation); ClassDB::bind_method(D_METHOD("get_bone_pose_scale", "bone_idx"), &Skeleton3D::get_bone_pose_scale); + ClassDB::bind_method(D_METHOD("reset_bone_pose", "bone_idx"), &Skeleton3D::reset_bone_pose); + ClassDB::bind_method(D_METHOD("reset_bone_poses"), &Skeleton3D::reset_bone_poses); + ClassDB::bind_method(D_METHOD("is_bone_enabled", "bone_idx"), &Skeleton3D::is_bone_enabled); ClassDB::bind_method(D_METHOD("set_bone_enabled", "bone_idx", "enabled"), &Skeleton3D::set_bone_enabled, DEFVAL(true)); @@ -1259,6 +1244,9 @@ void Skeleton3D::_bind_methods() { ClassDB::bind_method(D_METHOD("force_update_all_bone_transforms"), &Skeleton3D::force_update_all_bone_transforms); ClassDB::bind_method(D_METHOD("force_update_bone_child_transform", "bone_idx"), &Skeleton3D::force_update_bone_children_transforms); + ClassDB::bind_method(D_METHOD("set_motion_scale", "motion_scale"), &Skeleton3D::set_motion_scale); + ClassDB::bind_method(D_METHOD("get_motion_scale"), &Skeleton3D::get_motion_scale); + // Helper functions ClassDB::bind_method(D_METHOD("global_pose_to_world_transform", "global_pose"), &Skeleton3D::global_pose_to_world_transform); ClassDB::bind_method(D_METHOD("world_transform_to_global_pose", "world_transform"), &Skeleton3D::world_transform_to_global_pose); @@ -1282,15 +1270,13 @@ void Skeleton3D::_bind_methods() { ClassDB::bind_method(D_METHOD("get_modification_stack"), &Skeleton3D::get_modification_stack); ClassDB::bind_method(D_METHOD("execute_modifications", "delta", "execution_mode"), &Skeleton3D::execute_modifications); -#ifndef _3D_DISABLED + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "motion_scale", PROPERTY_HINT_RANGE, "0.001,10,0.001,or_greater"), "set_motion_scale", "get_motion_scale"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "show_rest_only"), "set_show_rest_only", "is_show_rest_only"); +#ifndef _3D_DISABLED ADD_PROPERTY(PropertyInfo(Variant::BOOL, "animate_physical_bones"), "set_animate_physical_bones", "get_animate_physical_bones"); #endif // _3D_DISABLED -#ifdef TOOLS_ENABLED ADD_SIGNAL(MethodInfo("pose_updated")); -#endif // TOOLS_ENABLED - ADD_SIGNAL(MethodInfo("bone_pose_changed", PropertyInfo(Variant::INT, "bone_idx"))); ADD_SIGNAL(MethodInfo("bone_enabled_changed", PropertyInfo(Variant::INT, "bone_idx"))); ADD_SIGNAL(MethodInfo("show_rest_only_changed")); @@ -1303,7 +1289,7 @@ Skeleton3D::Skeleton3D() { Skeleton3D::~Skeleton3D() { // Some skins may remain bound. - for (Set<SkinReference *>::Element *E = skin_bindings.front(); E; E = E->next()) { - E->get()->skeleton_node = nullptr; + for (SkinReference *E : skin_bindings) { + E->skeleton_node = nullptr; } } |