diff --git a/doc/classes/EditorSceneFormatImporter.xml b/doc/classes/EditorSceneFormatImporter.xml index 6de9c2c5dc73..db93cab14c2e 100644 --- a/doc/classes/EditorSceneFormatImporter.xml +++ b/doc/classes/EditorSceneFormatImporter.xml @@ -39,7 +39,6 @@ - diff --git a/editor/import/editor_import_collada.cpp b/editor/import/editor_import_collada.cpp index 6890a4619305..c335655d4e59 100644 --- a/editor/import/editor_import_collada.cpp +++ b/editor/import/editor_import_collada.cpp @@ -65,7 +65,7 @@ struct ColladaImport { bool force_make_tangents = false; bool apply_mesh_xform_to_vertices = true; bool use_mesh_builtin_materials = false; - float bake_fps = 15; + float bake_fps = 30; HashMap node_map; //map from collada node to engine node HashMap node_name_map; //map from collada node to engine node @@ -1760,7 +1760,7 @@ void EditorSceneFormatImporterCollada::get_extensions(List *r_extensions r_extensions->push_back("dae"); } -Node *EditorSceneFormatImporterCollada::import_scene(const String &p_path, uint32_t p_flags, const HashMap &p_options, int p_bake_fps, List *r_missing_deps, Error *r_err) { +Node *EditorSceneFormatImporterCollada::import_scene(const String &p_path, uint32_t p_flags, const HashMap &p_options, List *r_missing_deps, Error *r_err) { if (r_err) { *r_err = OK; } @@ -1771,7 +1771,7 @@ Node *EditorSceneFormatImporterCollada::import_scene(const String &p_path, uint3 } state.use_mesh_builtin_materials = true; - state.bake_fps = p_bake_fps; + state.bake_fps = (float)p_options["animation/fps"]; Error err = state.load(p_path, flags, p_flags & EditorSceneFormatImporter::IMPORT_GENERATE_TANGENT_ARRAYS, false); diff --git a/editor/import/editor_import_collada.h b/editor/import/editor_import_collada.h index a75b0a903f46..ec30c91c1bb6 100644 --- a/editor/import/editor_import_collada.h +++ b/editor/import/editor_import_collada.h @@ -39,7 +39,7 @@ class EditorSceneFormatImporterCollada : public EditorSceneFormatImporter { public: virtual uint32_t get_import_flags() const override; virtual void get_extensions(List *r_extensions) const override; - virtual Node *import_scene(const String &p_path, uint32_t p_flags, const HashMap &p_options, int p_bake_fps, List *r_missing_deps = nullptr, Error *r_err = nullptr) override; + virtual Node *import_scene(const String &p_path, uint32_t p_flags, const HashMap &p_options, List *r_missing_deps = nullptr, Error *r_err = nullptr) override; EditorSceneFormatImporterCollada(); }; diff --git a/editor/import/resource_importer_obj.cpp b/editor/import/resource_importer_obj.cpp index fe70fd58b5dc..f19b4dbe56bb 100644 --- a/editor/import/resource_importer_obj.cpp +++ b/editor/import/resource_importer_obj.cpp @@ -422,7 +422,7 @@ static Error _parse_obj(const String &p_path, List> &r_meshes, bool p_ return OK; } -Node *EditorOBJImporter::import_scene(const String &p_path, uint32_t p_flags, const HashMap &p_options, int p_bake_fps, List *r_missing_deps, Error *r_err) { +Node *EditorOBJImporter::import_scene(const String &p_path, uint32_t p_flags, const HashMap &p_options, List *r_missing_deps, Error *r_err) { List> meshes; Error err = _parse_obj(p_path, meshes, false, p_flags & IMPORT_GENERATE_TANGENT_ARRAYS, false, Vector3(1, 1, 1), Vector3(0, 0, 0), r_missing_deps); diff --git a/editor/import/resource_importer_obj.h b/editor/import/resource_importer_obj.h index 4dfac90fa1fd..121d8e6d36e8 100644 --- a/editor/import/resource_importer_obj.h +++ b/editor/import/resource_importer_obj.h @@ -39,7 +39,7 @@ class EditorOBJImporter : public EditorSceneFormatImporter { public: virtual uint32_t get_import_flags() const override; virtual void get_extensions(List *r_extensions) const override; - virtual Node *import_scene(const String &p_path, uint32_t p_flags, const HashMap &p_options, int p_bake_fps, List *r_missing_deps, Error *r_err = nullptr) override; + virtual Node *import_scene(const String &p_path, uint32_t p_flags, const HashMap &p_options, List *r_missing_deps, Error *r_err = nullptr) override; EditorOBJImporter(); }; diff --git a/editor/import/resource_importer_scene.cpp b/editor/import/resource_importer_scene.cpp index ffe69544840c..a9ce6e9f88a4 100644 --- a/editor/import/resource_importer_scene.cpp +++ b/editor/import/resource_importer_scene.cpp @@ -74,13 +74,13 @@ void EditorSceneFormatImporter::get_extensions(List *r_extensions) const ERR_FAIL(); } -Node *EditorSceneFormatImporter::import_scene(const String &p_path, uint32_t p_flags, const HashMap &p_options, int p_bake_fps, List *r_missing_deps, Error *r_err) { +Node *EditorSceneFormatImporter::import_scene(const String &p_path, uint32_t p_flags, const HashMap &p_options, List *r_missing_deps, Error *r_err) { Dictionary options_dict; for (const KeyValue &elem : p_options) { options_dict[elem.key] = elem.value; } Object *ret = nullptr; - if (GDVIRTUAL_CALL(_import_scene, p_path, p_flags, options_dict, p_bake_fps, ret)) { + if (GDVIRTUAL_CALL(_import_scene, p_path, p_flags, options_dict, ret)) { return Object::cast_to(ret); } @@ -100,7 +100,7 @@ Variant EditorSceneFormatImporter::get_option_visibility(const String &p_path, b void EditorSceneFormatImporter::_bind_methods() { GDVIRTUAL_BIND(_get_import_flags); GDVIRTUAL_BIND(_get_extensions); - GDVIRTUAL_BIND(_import_scene, "path", "flags", "options", "bake_fps"); + GDVIRTUAL_BIND(_import_scene, "path", "flags", "options"); GDVIRTUAL_BIND(_get_import_options, "path"); GDVIRTUAL_BIND(_get_option_visibility, "path", "for_animation", "option"); @@ -1864,6 +1864,7 @@ void ResourceImporterScene::get_import_options(const String &p_path, Listpush_back(ImportOption(PropertyInfo(Variant::BOOL, "skins/use_named_skins"), true)); r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL, "animation/import"), true)); r_options->push_back(ImportOption(PropertyInfo(Variant::FLOAT, "animation/fps", PROPERTY_HINT_RANGE, "1,120,1"), 30)); + r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL, "animation/trimming"), false)); r_options->push_back(ImportOption(PropertyInfo(Variant::STRING, "import_script/path", PROPERTY_HINT_FILE, script_ext_hint), "")); r_options->push_back(ImportOption(PropertyInfo(Variant::DICTIONARY, "_subresources", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR), Dictionary())); @@ -2281,13 +2282,8 @@ Node *ResourceImporterScene::pre_import(const String &p_source_file, const HashM ERR_FAIL_COND_V(!importer.is_valid(), nullptr); - int bake_fps = 30; - if (p_options.has(SNAME("animation/fps"))) { - bake_fps = p_options[SNAME("animation/fps")]; - } - Error err = OK; - Node *scene = importer->import_scene(p_source_file, EditorSceneFormatImporter::IMPORT_ANIMATION | EditorSceneFormatImporter::IMPORT_GENERATE_TANGENT_ARRAYS, p_options, bake_fps, nullptr, &err); + Node *scene = importer->import_scene(p_source_file, EditorSceneFormatImporter::IMPORT_ANIMATION | EditorSceneFormatImporter::IMPORT_GENERATE_TANGENT_ARRAYS, p_options, nullptr, &err); if (!scene || err != OK) { return nullptr; } @@ -2326,8 +2322,6 @@ Error ResourceImporterScene::import(const String &p_source_file, const String &p ERR_FAIL_COND_V(!importer.is_valid(), ERR_FILE_UNRECOGNIZED); - float fps = p_options["animation/fps"]; - int import_flags = 0; if (animation_importer) { @@ -2350,7 +2344,7 @@ Error ResourceImporterScene::import(const String &p_source_file, const String &p Error err = OK; List missing_deps; // for now, not much will be done with this - Node *scene = importer->import_scene(src_path, import_flags, p_options, fps, &missing_deps, &err); + Node *scene = importer->import_scene(src_path, import_flags, p_options, &missing_deps, &err); if (!scene || err != OK) { return err; } @@ -2398,6 +2392,10 @@ Error ResourceImporterScene::import(const String &p_source_file, const String &p post_importer_plugins.write[i]->pre_process(scene, p_options); } + float fps = 30; + if (p_options.has(SNAME("animation/fps"))) { + fps = (float)p_options[SNAME("animation/fps")]; + } _pre_fix_animations(scene, scene, node_data, animation_data, fps); _post_fix_node(scene, scene, collision_map, occluder_arrays, scanned_meshes, node_data, material_data, animation_data, fps); _post_fix_animations(scene, scene, node_data, animation_data, fps); @@ -2612,7 +2610,7 @@ void EditorSceneFormatImporterESCN::get_extensions(List *r_extensions) c r_extensions->push_back("escn"); } -Node *EditorSceneFormatImporterESCN::import_scene(const String &p_path, uint32_t p_flags, const HashMap &p_options, int p_bake_fps, List *r_missing_deps, Error *r_err) { +Node *EditorSceneFormatImporterESCN::import_scene(const String &p_path, uint32_t p_flags, const HashMap &p_options, List *r_missing_deps, Error *r_err) { Error error; Ref ps = ResourceFormatLoaderText::singleton->load(p_path, p_path, &error); ERR_FAIL_COND_V_MSG(!ps.is_valid(), nullptr, "Cannot load scene as text resource from path '" + p_path + "'."); diff --git a/editor/import/resource_importer_scene.h b/editor/import/resource_importer_scene.h index 5f64330453b6..678251372b13 100644 --- a/editor/import/resource_importer_scene.h +++ b/editor/import/resource_importer_scene.h @@ -53,12 +53,12 @@ class EditorSceneFormatImporter : public RefCounted { protected: static void _bind_methods(); - Node *import_scene_wrapper(const String &p_path, uint32_t p_flags, Dictionary p_options, int p_bake_fps); - Ref import_animation_wrapper(const String &p_path, uint32_t p_flags, Dictionary p_options, int p_bake_fps); + Node *import_scene_wrapper(const String &p_path, uint32_t p_flags, Dictionary p_options); + Ref import_animation_wrapper(const String &p_path, uint32_t p_flags, Dictionary p_options); GDVIRTUAL0RC(int, _get_import_flags) GDVIRTUAL0RC(Vector, _get_extensions) - GDVIRTUAL4R(Object *, _import_scene, String, uint32_t, Dictionary, uint32_t) + GDVIRTUAL3R(Object *, _import_scene, String, uint32_t, Dictionary) GDVIRTUAL1(_get_import_options, String) GDVIRTUAL3RC(Variant, _get_option_visibility, String, bool, String) @@ -74,7 +74,7 @@ public: virtual uint32_t get_import_flags() const; virtual void get_extensions(List *r_extensions) const; - virtual Node *import_scene(const String &p_path, uint32_t p_flags, const HashMap &p_options, int p_bake_fps, List *r_missing_deps, Error *r_err = nullptr); + virtual Node *import_scene(const String &p_path, uint32_t p_flags, const HashMap &p_options, List *r_missing_deps, Error *r_err = nullptr); virtual void get_import_options(const String &p_path, List *r_options); virtual Variant get_option_visibility(const String &p_path, bool p_for_animation, const String &p_option, const HashMap &p_options); @@ -310,7 +310,7 @@ class EditorSceneFormatImporterESCN : public EditorSceneFormatImporter { public: virtual uint32_t get_import_flags() const override; virtual void get_extensions(List *r_extensions) const override; - virtual Node *import_scene(const String &p_path, uint32_t p_flags, const HashMap &p_options, int p_bake_fps, List *r_missing_deps, Error *r_err = nullptr) override; + virtual Node *import_scene(const String &p_path, uint32_t p_flags, const HashMap &p_options, List *r_missing_deps, Error *r_err = nullptr) override; }; template diff --git a/modules/gltf/doc_classes/GLTFDocument.xml b/modules/gltf/doc_classes/GLTFDocument.xml index 588015de620c..f313f4b28f73 100644 --- a/modules/gltf/doc_classes/GLTFDocument.xml +++ b/modules/gltf/doc_classes/GLTFDocument.xml @@ -14,7 +14,6 @@ - Takes a [PackedByteArray] defining a gLTF and returns a [GLTFState] object through the [param state] parameter. [b]Note:[/b] The [param base_path] tells [method append_from_buffer] where to find dependencies and can be empty. @@ -25,8 +24,7 @@ - - + Takes a path to a gLTF file and returns a [GLTFState] object through the [param state] parameter. [b]Note:[/b] The [param base_path] tells [method append_from_file] where to find dependencies and can be empty. @@ -37,7 +35,6 @@ - Takes a Godot Engine scene node and returns a [GLTFState] object through the [param state] parameter. @@ -52,7 +49,8 @@ - + + Takes a [GLTFState] object through the [param state] parameter and returns a Godot Engine scene node. diff --git a/modules/gltf/editor/editor_scene_exporter_gltf_plugin.cpp b/modules/gltf/editor/editor_scene_exporter_gltf_plugin.cpp index 95db1c096501..0c0b134bd147 100644 --- a/modules/gltf/editor/editor_scene_exporter_gltf_plugin.cpp +++ b/modules/gltf/editor/editor_scene_exporter_gltf_plugin.cpp @@ -85,7 +85,7 @@ void SceneExporterGLTFPlugin::_gltf2_dialog_action(String p_file) { state.instantiate(); int32_t flags = 0; flags |= EditorSceneFormatImporter::IMPORT_USE_NAMED_SKIN_BINDS; - Error err = doc->append_from_scene(root, state, flags, 30.0f); + Error err = doc->append_from_scene(root, state, flags); if (err != OK) { ERR_PRINT(vformat("glTF2 save scene error %s.", itos(err))); } diff --git a/modules/gltf/editor/editor_scene_importer_blend.cpp b/modules/gltf/editor/editor_scene_importer_blend.cpp index f0f642dd728f..7007ea5d13cf 100644 --- a/modules/gltf/editor/editor_scene_importer_blend.cpp +++ b/modules/gltf/editor/editor_scene_importer_blend.cpp @@ -59,7 +59,7 @@ void EditorSceneFormatImporterBlend::get_extensions(List *r_extensions) } Node *EditorSceneFormatImporterBlend::import_scene(const String &p_path, uint32_t p_flags, - const HashMap &p_options, int p_bake_fps, + const HashMap &p_options, List *r_missing_deps, Error *r_err) { // Get global paths for source and sink. @@ -228,14 +228,14 @@ 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(); } - Error err = gltf->append_from_file(sink.get_basename() + ".gltf", state, p_flags, p_bake_fps, base_dir); + Error err = gltf->append_from_file(sink.get_basename() + ".gltf", state, p_flags, base_dir); if (err != OK) { if (r_err) { *r_err = FAILED; } return nullptr; } - return gltf->generate_scene(state, p_bake_fps); + return gltf->generate_scene(state, (float)p_options["animation/fps"], (bool)p_options["animation/trimming"]); } Variant EditorSceneFormatImporterBlend::get_option_visibility(const String &p_path, bool p_for_animation, const String &p_option, diff --git a/modules/gltf/editor/editor_scene_importer_blend.h b/modules/gltf/editor/editor_scene_importer_blend.h index a1485ff82e42..fe687f19fc8d 100644 --- a/modules/gltf/editor/editor_scene_importer_blend.h +++ b/modules/gltf/editor/editor_scene_importer_blend.h @@ -66,7 +66,7 @@ public: virtual uint32_t get_import_flags() const override; virtual void get_extensions(List *r_extensions) const override; virtual Node *import_scene(const String &p_path, uint32_t p_flags, - const HashMap &p_options, int p_bake_fps, + const HashMap &p_options, List *r_missing_deps, Error *r_err = nullptr) override; virtual void get_import_options(const String &p_path, List *r_options) override; diff --git a/modules/gltf/editor/editor_scene_importer_fbx.cpp b/modules/gltf/editor/editor_scene_importer_fbx.cpp index 017a44cccf99..14f211741352 100644 --- a/modules/gltf/editor/editor_scene_importer_fbx.cpp +++ b/modules/gltf/editor/editor_scene_importer_fbx.cpp @@ -49,7 +49,7 @@ void EditorSceneFormatImporterFBX::get_extensions(List *r_extensions) co } Node *EditorSceneFormatImporterFBX::import_scene(const String &p_path, uint32_t p_flags, - const HashMap &p_options, int p_bake_fps, + const HashMap &p_options, List *r_missing_deps, Error *r_err) { // Get global paths for source and sink. @@ -95,14 +95,14 @@ Node *EditorSceneFormatImporterFBX::import_scene(const String &p_path, uint32_t Ref state; state.instantiate(); print_verbose(vformat("glTF path: %s", sink)); - Error err = gltf->append_from_file(sink, state, p_flags, p_bake_fps); + Error err = gltf->append_from_file(sink, state, p_flags); if (err != OK) { if (r_err) { *r_err = FAILED; } return nullptr; } - return gltf->generate_scene(state, p_bake_fps); + return gltf->generate_scene(state, (float)p_options["animation/fps"], (bool)p_options["animation/trimming"]); } Variant EditorSceneFormatImporterFBX::get_option_visibility(const String &p_path, bool p_for_animation, diff --git a/modules/gltf/editor/editor_scene_importer_fbx.h b/modules/gltf/editor/editor_scene_importer_fbx.h index b0039b1c8fbe..6bf9f3e03304 100644 --- a/modules/gltf/editor/editor_scene_importer_fbx.h +++ b/modules/gltf/editor/editor_scene_importer_fbx.h @@ -45,7 +45,7 @@ public: virtual uint32_t get_import_flags() const override; virtual void get_extensions(List *r_extensions) const override; virtual Node *import_scene(const String &p_path, uint32_t p_flags, - const HashMap &p_options, int p_bake_fps, + const HashMap &p_options, List *r_missing_deps, Error *r_err = nullptr) override; virtual void get_import_options(const String &p_path, List *r_options) override; diff --git a/modules/gltf/editor/editor_scene_importer_gltf.cpp b/modules/gltf/editor/editor_scene_importer_gltf.cpp index 161808aade43..3cf49a30467a 100644 --- a/modules/gltf/editor/editor_scene_importer_gltf.cpp +++ b/modules/gltf/editor/editor_scene_importer_gltf.cpp @@ -47,13 +47,13 @@ void EditorSceneFormatImporterGLTF::get_extensions(List *r_extensions) c } Node *EditorSceneFormatImporterGLTF::import_scene(const String &p_path, uint32_t p_flags, - const HashMap &p_options, int p_bake_fps, + const HashMap &p_options, List *r_missing_deps, Error *r_err) { Ref doc; doc.instantiate(); Ref state; state.instantiate(); - Error err = doc->append_from_file(p_path, state, p_flags, p_bake_fps); + Error err = doc->append_from_file(p_path, state, p_flags); if (err != OK) { if (r_err) { *r_err = err; @@ -63,7 +63,7 @@ Node *EditorSceneFormatImporterGLTF::import_scene(const String &p_path, uint32_t if (p_options.has("animation/import")) { state->set_create_animations(bool(p_options["animation/import"])); } - return doc->generate_scene(state, p_bake_fps); + return doc->generate_scene(state, (float)p_options["animation/fps"], (bool)p_options["animation/trimming"]); } #endif // TOOLS_ENABLED diff --git a/modules/gltf/editor/editor_scene_importer_gltf.h b/modules/gltf/editor/editor_scene_importer_gltf.h index edca038532ba..c0582b26c170 100644 --- a/modules/gltf/editor/editor_scene_importer_gltf.h +++ b/modules/gltf/editor/editor_scene_importer_gltf.h @@ -45,7 +45,7 @@ public: virtual uint32_t get_import_flags() const override; virtual void get_extensions(List *r_extensions) const override; virtual Node *import_scene(const String &p_path, uint32_t p_flags, - const HashMap &p_options, int p_bake_fps, + const HashMap &p_options, List *r_missing_deps, Error *r_err = nullptr) override; }; diff --git a/modules/gltf/gltf_document.cpp b/modules/gltf/gltf_document.cpp index eb8f7e5ebc7a..735e35ac1e50 100644 --- a/modules/gltf/gltf_document.cpp +++ b/modules/gltf/gltf_document.cpp @@ -5860,7 +5860,7 @@ T GLTFDocument::_interpolate_track(const Vector &p_times, const Vector state, AnimationPlayer *ap, const GLTFAnimationIndex index, const int bake_fps) { +void GLTFDocument::_import_animation(Ref state, AnimationPlayer *ap, const GLTFAnimationIndex index, const float bake_fps, const bool trimming) { Ref anim = state->animations[index]; String anim_name = anim->get_name(); @@ -5877,7 +5877,8 @@ void GLTFDocument::_import_animation(Ref state, AnimationPlayer *ap, animation->set_loop_mode(Animation::LOOP_LINEAR); } - float length = 0.0; + double anim_start = trimming ? INFINITY : 0.0; + double anim_end = 0.0; for (const KeyValue &track_i : anim->get_tracks()) { const GLTFAnimation::Track &track = track_i.value; @@ -5907,19 +5908,40 @@ void GLTFDocument::_import_animation(Ref state, AnimationPlayer *ap, transform_node_path = node_path; } - for (int i = 0; i < track.rotation_track.times.size(); i++) { - length = MAX(length, track.rotation_track.times[i]); - } - for (int i = 0; i < track.position_track.times.size(); i++) { - length = MAX(length, track.position_track.times[i]); - } - for (int i = 0; i < track.scale_track.times.size(); i++) { - length = MAX(length, track.scale_track.times[i]); - } - - for (int i = 0; i < track.weight_tracks.size(); i++) { - for (int j = 0; j < track.weight_tracks[i].times.size(); j++) { - length = MAX(length, track.weight_tracks[i].times[j]); + if (trimming) { + for (int i = 0; i < track.rotation_track.times.size(); i++) { + anim_start = MIN(anim_start, track.rotation_track.times[i]); + anim_end = MAX(anim_end, track.rotation_track.times[i]); + } + for (int i = 0; i < track.position_track.times.size(); i++) { + anim_start = MIN(anim_start, track.position_track.times[i]); + anim_end = MAX(anim_end, track.position_track.times[i]); + } + for (int i = 0; i < track.scale_track.times.size(); i++) { + anim_start = MIN(anim_start, track.scale_track.times[i]); + anim_end = MAX(anim_end, track.scale_track.times[i]); + } + for (int i = 0; i < track.weight_tracks.size(); i++) { + for (int j = 0; j < track.weight_tracks[i].times.size(); j++) { + anim_start = MIN(anim_start, track.weight_tracks[i].times[j]); + anim_end = MAX(anim_end, track.weight_tracks[i].times[j]); + } + } + } else { + // If you don't use trimming and the first key time is not at 0.0, fake keys will be inserted. + for (int i = 0; i < track.rotation_track.times.size(); i++) { + anim_end = MAX(anim_end, track.rotation_track.times[i]); + } + for (int i = 0; i < track.position_track.times.size(); i++) { + anim_end = MAX(anim_end, track.position_track.times[i]); + } + for (int i = 0; i < track.scale_track.times.size(); i++) { + anim_end = MAX(anim_end, track.scale_track.times[i]); + } + for (int i = 0; i < track.weight_tracks.size(); i++) { + for (int j = 0; j < track.weight_tracks[i].times.size(); j++) { + anim_end = MAX(anim_end, track.weight_tracks[i].times[j]); + } } } @@ -5988,10 +6010,8 @@ void GLTFDocument::_import_animation(Ref state, AnimationPlayer *ap, } } - //first determine animation length - const double increment = 1.0 / bake_fps; - double time = 0.0; + double time = anim_start; Vector3 base_pos; Quaternion base_rot; @@ -6017,26 +6037,26 @@ void GLTFDocument::_import_animation(Ref state, AnimationPlayer *ap, if (position_idx >= 0) { pos = _interpolate_track(track.position_track.times, track.position_track.values, time, track.position_track.interpolation); - animation->position_track_insert_key(position_idx, time, pos); + animation->position_track_insert_key(position_idx, time - anim_start, pos); } if (rotation_idx >= 0) { rot = _interpolate_track(track.rotation_track.times, track.rotation_track.values, time, track.rotation_track.interpolation); - animation->rotation_track_insert_key(rotation_idx, time, rot); + animation->rotation_track_insert_key(rotation_idx, time - anim_start, rot); } if (scale_idx >= 0) { scale = _interpolate_track(track.scale_track.times, track.scale_track.values, time, track.scale_track.interpolation); - animation->scale_track_insert_key(scale_idx, time, scale); + animation->scale_track_insert_key(scale_idx, time - anim_start, scale); } if (last) { break; } time += increment; - if (time >= length) { + if (time >= anim_end) { last = true; - time = length; + time = anim_end; } } } @@ -6071,21 +6091,21 @@ void GLTFDocument::_import_animation(Ref state, AnimationPlayer *ap, bool last = false; while (true) { real_t blend = _interpolate_track(track.weight_tracks[i].times, track.weight_tracks[i].values, time, gltf_interp); - animation->blend_shape_track_insert_key(track_idx, time, blend); + animation->blend_shape_track_insert_key(track_idx, time - anim_start, blend); if (last) { break; } time += increment; - if (time >= length) { + if (time >= anim_end) { last = true; - time = length; + time = anim_end; } } } } } - animation->set_length(length); + animation->set_length(anim_end - anim_start); Ref library; if (!ap->has_animation_library("")) { @@ -6585,7 +6605,7 @@ void GLTFDocument::_convert_animation(Ref state, AnimationPlayer *ap, } } -Error GLTFDocument::_parse(Ref state, String p_path, Ref f, int p_bake_fps) { +Error GLTFDocument::_parse(Ref state, String p_path, Ref f) { Error err; if (f.is_null()) { return FAILED; @@ -6636,7 +6656,7 @@ Error GLTFDocument::_parse(Ref state, String p_path, Ref } } - err = _parse_gltf_state(state, p_path, p_bake_fps); + err = _parse_gltf_state(state, p_path); ERR_FAIL_COND_V(err != OK, err); return OK; @@ -6754,14 +6774,14 @@ Error GLTFDocument::_serialize_file(Ref state, const String p_path) { } void GLTFDocument::_bind_methods() { - ClassDB::bind_method(D_METHOD("append_from_file", "path", "state", "flags", "bake_fps", "base_path"), - &GLTFDocument::append_from_file, DEFVAL(0), DEFVAL(30), DEFVAL(String())); - ClassDB::bind_method(D_METHOD("append_from_buffer", "bytes", "base_path", "state", "flags", "bake_fps"), - &GLTFDocument::append_from_buffer, DEFVAL(0), DEFVAL(30)); - ClassDB::bind_method(D_METHOD("append_from_scene", "node", "state", "flags", "bake_fps"), - &GLTFDocument::append_from_scene, DEFVAL(0), DEFVAL(30)); - ClassDB::bind_method(D_METHOD("generate_scene", "state", "bake_fps"), - &GLTFDocument::generate_scene, DEFVAL(30)); + ClassDB::bind_method(D_METHOD("append_from_file", "path", "state", "flags", "base_path"), + &GLTFDocument::append_from_file, DEFVAL(0), DEFVAL(String())); + ClassDB::bind_method(D_METHOD("append_from_buffer", "bytes", "base_path", "state", "flags"), + &GLTFDocument::append_from_buffer, DEFVAL(0)); + ClassDB::bind_method(D_METHOD("append_from_scene", "node", "state", "flags"), + &GLTFDocument::append_from_scene, DEFVAL(0)); + ClassDB::bind_method(D_METHOD("generate_scene", "state", "bake_fps", "trimming"), + &GLTFDocument::generate_scene, DEFVAL(30), DEFVAL(false)); ClassDB::bind_method(D_METHOD("generate_buffer", "state"), &GLTFDocument::generate_buffer); ClassDB::bind_method(D_METHOD("write_to_filesystem", "state", "path"), @@ -6870,7 +6890,7 @@ Error GLTFDocument::write_to_filesystem(Ref state, const String &p_pa return OK; } -Node *GLTFDocument::generate_scene(Ref state, int32_t p_bake_fps) { +Node *GLTFDocument::generate_scene(Ref state, float p_bake_fps, bool p_trimming) { ERR_FAIL_NULL_V(state, nullptr); ERR_FAIL_INDEX_V(0, state->root_nodes.size(), nullptr); Error err = OK; @@ -6884,7 +6904,7 @@ Node *GLTFDocument::generate_scene(Ref state, int32_t p_bake_fps) { root->add_child(ap, true); ap->set_owner(root); for (int i = 0; i < state->animations.size(); i++) { - _import_animation(state, ap, i, p_bake_fps); + _import_animation(state, ap, i, p_bake_fps, p_trimming); } } for (KeyValue E : state->scene_nodes) { @@ -6910,7 +6930,7 @@ Node *GLTFDocument::generate_scene(Ref state, int32_t p_bake_fps) { return root; } -Error GLTFDocument::append_from_scene(Node *p_node, Ref state, uint32_t p_flags, int32_t p_bake_fps) { +Error GLTFDocument::append_from_scene(Node *p_node, Ref state, uint32_t p_flags) { ERR_FAIL_COND_V(state.is_null(), FAILED); state->use_named_skin_binds = p_flags & GLTF_IMPORT_USE_NAMED_SKIN_BINDS; state->discard_meshes_and_materials = p_flags & GLTF_IMPORT_DISCARD_MESHES_AND_MATERIALS; @@ -6930,7 +6950,7 @@ Error GLTFDocument::append_from_scene(Node *p_node, Ref state, uint32 return OK; } -Error GLTFDocument::append_from_buffer(PackedByteArray p_bytes, String p_base_path, Ref state, uint32_t p_flags, int32_t p_bake_fps) { +Error GLTFDocument::append_from_buffer(PackedByteArray p_bytes, String p_base_path, Ref state, uint32_t p_flags) { ERR_FAIL_COND_V(state.is_null(), FAILED); // TODO Add missing texture and missing .bin file paths to r_missing_deps 2021-09-10 fire Error err = FAILED; @@ -6941,7 +6961,7 @@ Error GLTFDocument::append_from_buffer(PackedByteArray p_bytes, String p_base_pa file_access.instantiate(); file_access->open_custom(p_bytes.ptr(), p_bytes.size()); state->base_path = p_base_path.get_base_dir(); - err = _parse(state, state->base_path, file_access, p_bake_fps); + err = _parse(state, state->base_path, file_access); ERR_FAIL_COND_V(err != OK, err); for (Ref ext : document_extensions) { ERR_CONTINUE(ext.is_null()); @@ -6951,7 +6971,7 @@ Error GLTFDocument::append_from_buffer(PackedByteArray p_bytes, String p_base_pa return OK; } -Error GLTFDocument::_parse_gltf_state(Ref state, const String &p_search_path, float p_bake_fps) { +Error GLTFDocument::_parse_gltf_state(Ref state, const String &p_search_path) { Error err; /* PARSE EXTENSIONS */ @@ -7047,7 +7067,7 @@ Error GLTFDocument::_parse_gltf_state(Ref state, const String &p_sear return OK; } -Error GLTFDocument::append_from_file(String p_path, Ref r_state, uint32_t p_flags, int32_t p_bake_fps, String p_base_path) { +Error GLTFDocument::append_from_file(String p_path, Ref r_state, uint32_t p_flags, String p_base_path) { // TODO Add missing texture and missing .bin file paths to r_missing_deps 2021-09-10 fire if (r_state == Ref()) { r_state.instantiate(); @@ -7064,7 +7084,7 @@ Error GLTFDocument::append_from_file(String p_path, Ref r_state, uint base_path = p_path.get_base_dir(); } r_state->base_path = base_path; - err = _parse(r_state, base_path, f, p_bake_fps); + err = _parse(r_state, base_path, f); ERR_FAIL_COND_V(err != OK, err); for (Ref ext : document_extensions) { ERR_CONTINUE(ext.is_null()); diff --git a/modules/gltf/gltf_document.h b/modules/gltf/gltf_document.h index 5a0e4ff49811..6eb38354a2b7 100644 --- a/modules/gltf/gltf_document.h +++ b/modules/gltf/gltf_document.h @@ -292,17 +292,17 @@ private: static float get_max_component(const Color &p_color); public: - Error append_from_file(String p_path, Ref r_state, uint32_t p_flags = 0, int32_t p_bake_fps = 30, String p_base_path = String()); - Error append_from_buffer(PackedByteArray p_bytes, String p_base_path, Ref r_state, uint32_t p_flags = 0, int32_t p_bake_fps = 30); - Error append_from_scene(Node *p_node, Ref r_state, uint32_t p_flags = 0, int32_t p_bake_fps = 30); + Error append_from_file(String p_path, Ref r_state, uint32_t p_flags = 0, String p_base_path = String()); + Error append_from_buffer(PackedByteArray p_bytes, String p_base_path, Ref r_state, uint32_t p_flags = 0); + Error append_from_scene(Node *p_node, Ref r_state, uint32_t p_flags = 0); public: - Node *generate_scene(Ref state, int32_t p_bake_fps = 30.0f); + Node *generate_scene(Ref state, float p_bake_fps = 30.0f, bool p_trimming = false); PackedByteArray generate_buffer(Ref state); Error write_to_filesystem(Ref state, const String &p_path); public: - Error _parse_gltf_state(Ref state, const String &p_search_path, float p_bake_fps); + Error _parse_gltf_state(Ref state, const String &p_search_path); Error _parse_gltf_extensions(Ref state); void _process_mesh_instances(Ref state, Node *scene_root); void _generate_scene_node(Ref state, Node *scene_parent, @@ -310,7 +310,7 @@ public: const GLTFNodeIndex node_index); void _generate_skeleton_bone_node(Ref state, Node *scene_parent, Node3D *scene_root, const GLTFNodeIndex node_index); void _import_animation(Ref state, AnimationPlayer *ap, - const GLTFAnimationIndex index, const int bake_fps); + const GLTFAnimationIndex index, const float bake_fps, const bool trimming); void _convert_mesh_instances(Ref state); GLTFCameraIndex _convert_camera(Ref state, Camera3D *p_camera); void _convert_light_to_gltf(Light3D *light, Ref state, Ref gltf_node); @@ -368,7 +368,7 @@ public: void _convert_animation(Ref state, AnimationPlayer *ap, String p_animation_track_name); Error _serialize(Ref state, const String &p_path); - Error _parse(Ref state, String p_path, Ref f, int p_bake_fps); + Error _parse(Ref state, String p_path, Ref f); }; #endif // GLTF_DOCUMENT_H