Merge pull request #88819 from lyuma/import_nodes_as_skeleton_bones

Add new scene import option to import as Skeleton
This commit is contained in:
Rémi Verschelde 2024-02-27 10:18:00 +01:00
commit 3780604d79
No known key found for this signature in database
GPG key ID: C3336907360768E1
14 changed files with 69 additions and 4 deletions

View file

@ -104,6 +104,9 @@ Node *EditorSceneFormatImporterFBX2GLTF::import_scene(const String &p_path, uint
gltf.instantiate();
Ref<GLTFState> state;
state.instantiate();
if (p_options.has(SNAME("nodes/import_as_skeleton_bones")) ? (bool)p_options[SNAME("nodes/import_as_skeleton_bones")] : false) {
state->set_import_as_skeleton_bones(true);
}
print_verbose(vformat("glTF path: %s", sink));
Error err = gltf->append_from_file(sink, state, p_flags, p_path.get_base_dir());
if (err != OK) {

View file

@ -73,6 +73,12 @@ Node *EditorSceneFormatImporterUFBX::import_scene(const String &p_path, uint32_t
int32_t enum_option = p_options["fbx/embedded_image_handling"];
state->set_handle_binary_image(enum_option);
}
if (p_options.has(SNAME("nodes/import_as_skeleton_bones")) ? (bool)p_options[SNAME("nodes/import_as_skeleton_bones")] : false) {
state->set_import_as_skeleton_bones(true);
}
if (p_options.has(SNAME("nodes/import_as_skeleton_bones")) ? (bool)p_options[SNAME("nodes/import_as_skeleton_bones")] : false) {
state->set_import_as_skeleton_bones(true);
}
p_flags |= EditorSceneFormatImporter::IMPORT_USE_NAMED_SKIN_BINDS;
Error err = fbx->append_from_file(path, state, p_flags, p_path.get_base_dir());
if (err != OK) {

View file

@ -2086,7 +2086,7 @@ Error FBXDocument::_parse_fbx_state(Ref<FBXState> p_state, const String &p_searc
ERR_FAIL_COND_V(err != OK, ERR_PARSE_ERROR);
/* DETERMINE SKELETONS */
err = SkinTool::_determine_skeletons(p_state->skins, p_state->nodes, p_state->skeletons);
err = SkinTool::_determine_skeletons(p_state->skins, p_state->nodes, p_state->skeletons, p_state->get_import_as_skeleton_bones() ? p_state->root_nodes : Vector<GLTFNodeIndex>());
ERR_FAIL_COND_V(err != OK, ERR_PARSE_ERROR);
/* CREATE SKELETONS */

View file

@ -289,8 +289,13 @@
The file name associated with this GLTF data. If it ends with [code].gltf[/code], this is text-based GLTF, otherwise this is binary GLB. This will be set during import when appending from a file, and will be set during export when writing to a file. If writing to a buffer, this will be an empty string.
</member>
<member name="glb_data" type="PackedByteArray" setter="set_glb_data" getter="get_glb_data" default="PackedByteArray()">
The binary buffer attached to a .glb file.
</member>
<member name="import_as_skeleton_bones" type="bool" setter="set_import_as_skeleton_bones" getter="get_import_as_skeleton_bones" default="false">
True to force all GLTFNodes in the document to be bones of a single Skeleton3D godot node.
</member>
<member name="json" type="Dictionary" setter="set_json" getter="get_json" default="{}">
The original raw JSON document corresponding to this GLTFState.
</member>
<member name="major_version" type="int" setter="set_major_version" getter="get_major_version" default="0">
</member>

View file

@ -287,6 +287,9 @@ Node *EditorSceneFormatImporterBlend::import_scene(const String &p_path, uint32_
if (p_options.has(SNAME("blender/materials/unpack_enabled")) && p_options[SNAME("blender/materials/unpack_enabled")]) {
base_dir = sink.get_base_dir();
}
if (p_options.has(SNAME("nodes/import_as_skeleton_bones")) ? (bool)p_options[SNAME("nodes/import_as_skeleton_bones")] : false) {
state->set_import_as_skeleton_bones(true);
}
state->set_scene_name(blend_basename);
err = gltf->append_from_file(sink.get_basename() + ".gltf", state, p_flags, base_dir);
if (err != OK) {

View file

@ -6937,7 +6937,7 @@ Error GLTFDocument::_parse_gltf_state(Ref<GLTFState> p_state, const String &p_se
ERR_FAIL_COND_V(err != OK, ERR_PARSE_ERROR);
/* DETERMINE SKELETONS */
err = SkinTool::_determine_skeletons(p_state->skins, p_state->nodes, p_state->skeletons);
err = SkinTool::_determine_skeletons(p_state->skins, p_state->nodes, p_state->skeletons, p_state->get_import_as_skeleton_bones() ? p_state->root_nodes : Vector<GLTFNodeIndex>());
ERR_FAIL_COND_V(err != OK, ERR_PARSE_ERROR);
/* PARSE MESHES (we have enough info now) */

View file

@ -90,6 +90,8 @@ void GLTFState::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_skeletons", "skeletons"), &GLTFState::set_skeletons);
ClassDB::bind_method(D_METHOD("get_create_animations"), &GLTFState::get_create_animations);
ClassDB::bind_method(D_METHOD("set_create_animations", "create_animations"), &GLTFState::set_create_animations);
ClassDB::bind_method(D_METHOD("get_import_as_skeleton_bones"), &GLTFState::get_import_as_skeleton_bones);
ClassDB::bind_method(D_METHOD("set_import_as_skeleton_bones", "import_as_skeleton_bones"), &GLTFState::set_import_as_skeleton_bones);
ClassDB::bind_method(D_METHOD("get_animations"), &GLTFState::get_animations);
ClassDB::bind_method(D_METHOD("set_animations", "animations"), &GLTFState::set_animations);
ClassDB::bind_method(D_METHOD("get_scene_node", "idx"), &GLTFState::get_scene_node);
@ -125,6 +127,7 @@ void GLTFState::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "unique_animation_names", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_STORAGE | PROPERTY_USAGE_INTERNAL | PROPERTY_USAGE_EDITOR), "set_unique_animation_names", "get_unique_animation_names"); // Set<String>
ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "skeletons", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_STORAGE | PROPERTY_USAGE_INTERNAL | PROPERTY_USAGE_EDITOR), "set_skeletons", "get_skeletons"); // Vector<Ref<GLTFSkeleton>>
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "create_animations"), "set_create_animations", "get_create_animations"); // bool
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "import_as_skeleton_bones"), "set_import_as_skeleton_bones", "get_import_as_skeleton_bones"); // bool
ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "animations", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_STORAGE | PROPERTY_USAGE_INTERNAL | PROPERTY_USAGE_EDITOR), "set_animations", "get_animations"); // Vector<Ref<GLTFAnimation>>
ADD_PROPERTY(PropertyInfo(Variant::INT, "handle_binary_image", PROPERTY_HINT_ENUM, "Discard All Textures,Extract Textures,Embed as Basis Universal,Embed as Uncompressed", PROPERTY_USAGE_STORAGE | PROPERTY_USAGE_INTERNAL | PROPERTY_USAGE_EDITOR), "set_handle_binary_image", "get_handle_binary_image"); // enum
@ -337,6 +340,14 @@ void GLTFState::set_create_animations(bool p_create_animations) {
create_animations = p_create_animations;
}
bool GLTFState::get_import_as_skeleton_bones() {
return import_as_skeleton_bones;
}
void GLTFState::set_import_as_skeleton_bones(bool p_import_as_skeleton_bones) {
import_as_skeleton_bones = p_import_as_skeleton_bones;
}
TypedArray<GLTFAnimation> GLTFState::get_animations() {
return GLTFTemplateConvert::to_array(animations);
}

View file

@ -64,6 +64,7 @@ protected:
bool force_generate_tangents = false;
bool create_animations = true;
bool force_disable_compression = false;
bool import_as_skeleton_bones = false;
int handle_binary_image = HANDLE_BINARY_EXTRACT_TEXTURES;
@ -213,6 +214,9 @@ public:
bool get_create_animations();
void set_create_animations(bool p_create_animations);
bool get_import_as_skeleton_bones();
void set_import_as_skeleton_bones(bool p_import_as_skeleton_bones);
TypedArray<GLTFAnimation> get_animations();
void set_animations(TypedArray<GLTFAnimation> p_animations);

View file

@ -285,7 +285,18 @@ void SkinTool::_recurse_children(
Error SkinTool::_determine_skeletons(
Vector<Ref<GLTFSkin>> &skins,
Vector<Ref<GLTFNode>> &nodes,
Vector<Ref<GLTFSkeleton>> &skeletons) {
Vector<Ref<GLTFSkeleton>> &skeletons,
const Vector<GLTFNodeIndex> &p_single_skeleton_roots) {
if (!p_single_skeleton_roots.is_empty()) {
Ref<GLTFSkin> skin;
skin.instantiate();
skin->set_name("godot_single_skeleton_root");
for (GLTFNodeIndex i = 0; i < p_single_skeleton_roots.size(); i++) {
skin->joints.push_back(p_single_skeleton_roots[i]);
}
skins.push_back(skin);
}
// Using a disjoint set, we are going to potentially combine all skins that are actually branches
// of a main skeleton, or treat skins defining the same set of nodes as ONE skeleton.
// This is another unclear issue caused by the current glTF specification.

View file

@ -84,7 +84,8 @@ public:
static Error _determine_skeletons(
Vector<Ref<GLTFSkin>> &r_skins,
Vector<Ref<GLTFNode>> &r_nodes,
Vector<Ref<GLTFSkeleton>> &r_skeletons);
Vector<Ref<GLTFSkeleton>> &r_skeletons,
const Vector<GLTFNodeIndex> &p_single_skeleton_roots);
static Error _create_skeletons(
HashSet<String> &r_unique_names,
Vector<Ref<GLTFSkin>> &r_skins,