diff options
author | Rémi Verschelde <rverschelde@gmail.com> | 2024-09-17 09:17:35 +0200 |
---|---|---|
committer | Rémi Verschelde <rverschelde@gmail.com> | 2024-09-17 09:17:35 +0200 |
commit | e72a70de8e7fc64fae7859fe30fffa9732da5602 (patch) | |
tree | 96dba1d697bca625d804b073e2d21dba582ecec0 /modules | |
parent | 13064c4ac848d7d8207a8a8b0d1eb02db91f9e62 (diff) | |
parent | 0468bea899fe4806d8358c1cab078f700ab84d22 (diff) | |
download | redot-engine-e72a70de8e7fc64fae7859fe30fffa9732da5602.tar.gz |
Merge pull request #87150 from demolke/bones
Add per-bone meta to Skeleton3D
Diffstat (limited to 'modules')
-rw-r--r-- | modules/gltf/gltf_document.cpp | 4 | ||||
-rw-r--r-- | modules/gltf/skin_tool.cpp | 5 | ||||
-rw-r--r-- | modules/gltf/tests/test_gltf_extras.h | 57 |
3 files changed, 66 insertions, 0 deletions
diff --git a/modules/gltf/gltf_document.cpp b/modules/gltf/gltf_document.cpp index 56dae65831..bd034cbdc5 100644 --- a/modules/gltf/gltf_document.cpp +++ b/modules/gltf/gltf_document.cpp @@ -5534,6 +5534,10 @@ void GLTFDocument::_convert_skeleton_to_gltf(Skeleton3D *p_skeleton3d, Ref<GLTFS joint_node->set_name(_gen_unique_name(p_state, skeleton->get_bone_name(bone_i))); joint_node->transform = skeleton->get_bone_pose(bone_i); joint_node->joint = true; + + if (p_skeleton3d->has_bone_meta(bone_i, "extras")) { + joint_node->set_meta("extras", p_skeleton3d->get_bone_meta(bone_i, "extras")); + } GLTFNodeIndex current_node_i = p_state->nodes.size(); p_state->scene_nodes.insert(current_node_i, skeleton); p_state->nodes.push_back(joint_node); diff --git a/modules/gltf/skin_tool.cpp b/modules/gltf/skin_tool.cpp index a344334d93..1522c0e324 100644 --- a/modules/gltf/skin_tool.cpp +++ b/modules/gltf/skin_tool.cpp @@ -602,6 +602,11 @@ Error SkinTool::_create_skeletons( skeleton->set_bone_pose_rotation(bone_index, node->transform.basis.get_rotation_quaternion()); skeleton->set_bone_pose_scale(bone_index, node->transform.basis.get_scale()); + // Store bone-level GLTF extras in skeleton per bone meta. + if (node->has_meta("extras")) { + skeleton->set_bone_meta(bone_index, "extras", node->get_meta("extras")); + } + if (node->parent >= 0 && nodes[node->parent]->skeleton == skel_i) { const int bone_parent = skeleton->find_bone(nodes[node->parent]->get_name()); ERR_FAIL_COND_V(bone_parent < 0, FAILED); diff --git a/modules/gltf/tests/test_gltf_extras.h b/modules/gltf/tests/test_gltf_extras.h index 96aadf3023..37c8f6925c 100644 --- a/modules/gltf/tests/test_gltf_extras.h +++ b/modules/gltf/tests/test_gltf_extras.h @@ -41,6 +41,7 @@ #include "modules/gltf/gltf_document.h" #include "modules/gltf/gltf_state.h" #include "scene/3d/mesh_instance_3d.h" +#include "scene/3d/skeleton_3d.h" #include "scene/main/window.h" #include "scene/resources/3d/primitive_meshes.h" #include "scene/resources/material.h" @@ -158,6 +159,62 @@ TEST_CASE("[SceneTree][Node] GLTF test mesh and material meta export and import" memdelete(original); memdelete(loaded); } + +TEST_CASE("[SceneTree][Node] GLTF test skeleton and bone export and import") { + // Setup scene. + Skeleton3D *skeleton = memnew(Skeleton3D); + skeleton->set_name("skeleton"); + Dictionary skeleton_extras; + skeleton_extras["node_type"] = "skeleton"; + skeleton->set_meta("extras", skeleton_extras); + + skeleton->add_bone("parent"); + skeleton->set_bone_rest(0, Transform3D()); + Dictionary parent_bone_extras; + parent_bone_extras["bone"] = "i_am_parent_bone"; + skeleton->set_bone_meta(0, "extras", parent_bone_extras); + + skeleton->add_bone("child"); + skeleton->set_bone_rest(1, Transform3D()); + skeleton->set_bone_parent(1, 0); + Dictionary child_bone_extras; + child_bone_extras["bone"] = "i_am_child_bone"; + skeleton->set_bone_meta(1, "extras", child_bone_extras); + + // We have to have a mesh to link with skeleton or it will not get imported. + Ref<PlaneMesh> meshdata = memnew(PlaneMesh); + meshdata->set_name("planemesh"); + + MeshInstance3D *mesh = memnew(MeshInstance3D); + mesh->set_mesh(meshdata); + mesh->set_name("mesh_instance_3d"); + + Node3D *scene = memnew(Node3D); + SceneTree::get_singleton()->get_root()->add_child(scene); + scene->add_child(skeleton); + scene->add_child(mesh); + scene->set_name("node3d"); + + // Now that both skeleton and mesh are part of scene, link them. + mesh->set_skeleton_path(mesh->get_path_to(skeleton)); + + // Convert to GLFT and back. + String tempfile = OS::get_singleton()->get_cache_path().path_join("gltf_bone_extras"); + Node *loaded = _gltf_export_then_import(scene, tempfile); + + // Compare the results. + CHECK(loaded->get_name() == "node3d"); + Skeleton3D *result = Object::cast_to<Skeleton3D>(loaded->find_child("Skeleton3D", false, true)); + CHECK(result->get_bone_name(0) == "parent"); + CHECK(Dictionary(result->get_bone_meta(0, "extras"))["bone"] == "i_am_parent_bone"); + CHECK(result->get_bone_name(1) == "child"); + CHECK(Dictionary(result->get_bone_meta(1, "extras"))["bone"] == "i_am_child_bone"); + + memdelete(skeleton); + memdelete(mesh); + memdelete(scene); + memdelete(loaded); +} } // namespace TestGltfExtras #endif // TOOLS_ENABLED |