From 66009318e0827f01a584aca14c6e9ec0079354d3 Mon Sep 17 00:00:00 2001 From: reduz Date: Tue, 12 Apr 2022 16:07:09 +0200 Subject: [PATCH] Import scenes as AnimationLibrary Added the ability to import scenes as AnimationLibrary * Completes implementation of https://github.com/godotengine/godot-proposals/issues/4296 * Helps if you want to export animations to a separate file (say a GLTF) to avoid re-importing/exporting them every time the model changes. * Helps if you simply want to have animations using a dummy model, which can be shared across multiple models. Creates a secondary scene importer used only for animations. **NOTE**: A new flag for scene importer: EditorSceneFormatImporter.IMPORT_DISCARD_MESHES_AND_MATERIALS has been added, to hint importers that they should skip meshes and animations (and hence make importing faster). It is not implemented in any importer yet, this should be done in a separate PR. --- doc/classes/EditorSceneFormatImporter.xml | 14 +- doc/classes/EditorScenePostImportPlugin.xml | 6 +- editor/editor_node.cpp | 11 +- editor/editor_plugin.cpp | 8 +- editor/filesystem_dock.cpp | 24 +++- editor/import/editor_import_collada.cpp | 21 --- editor/import/editor_import_collada.h | 1 - editor/import/resource_importer_obj.cpp | 4 - editor/import/resource_importer_obj.h | 1 - editor/import/resource_importer_scene.cpp | 124 +++++++++++------ editor/import/resource_importer_scene.h | 39 +++--- editor/import/scene_import_settings.cpp | 128 +++++++++++++++--- editor/import/scene_import_settings.h | 7 +- .../editor/editor_scene_importer_blend.cpp | 14 +- .../gltf/editor/editor_scene_importer_blend.h | 4 +- .../gltf/editor/editor_scene_importer_fbx.cpp | 7 +- .../gltf/editor/editor_scene_importer_fbx.h | 4 +- .../editor/editor_scene_importer_gltf.cpp | 5 - .../gltf/editor/editor_scene_importer_gltf.h | 2 - modules/gltf/register_types.cpp | 6 +- 20 files changed, 269 insertions(+), 161 deletions(-) diff --git a/doc/classes/EditorSceneFormatImporter.xml b/doc/classes/EditorSceneFormatImporter.xml index 63c1498f200..0290d7207d0 100644 --- a/doc/classes/EditorSceneFormatImporter.xml +++ b/doc/classes/EditorSceneFormatImporter.xml @@ -29,16 +29,8 @@ - - - - - - - - - - + + @@ -63,5 +55,7 @@ + + diff --git a/doc/classes/EditorScenePostImportPlugin.xml b/doc/classes/EditorScenePostImportPlugin.xml index de9d5e067af..0fdbd5db1e2 100644 --- a/doc/classes/EditorScenePostImportPlugin.xml +++ b/doc/classes/EditorScenePostImportPlugin.xml @@ -34,7 +34,8 @@ - + + Return true or false whether a given option should be visible. Return null to ignore. @@ -42,7 +43,8 @@ - + + Return true or false whether a given option should be visible. Return null to ignore. diff --git a/editor/editor_node.cpp b/editor/editor_node.cpp index 99e30593a99..6fe6309eed1 100644 --- a/editor/editor_node.cpp +++ b/editor/editor_node.cpp @@ -5997,18 +5997,22 @@ EditorNode::EditorNode() { import_scene.instantiate(); ResourceFormatImporter::get_singleton()->add_importer(import_scene); + Ref import_animation; + import_animation = Ref(memnew(ResourceImporterScene(true))); + ResourceFormatImporter::get_singleton()->add_importer(import_animation); + { Ref import_collada; import_collada.instantiate(); - import_scene->add_importer(import_collada); + ResourceImporterScene::add_importer(import_collada); Ref import_obj2; import_obj2.instantiate(); - import_scene->add_importer(import_obj2); + ResourceImporterScene::add_importer(import_obj2); Ref import_escn; import_escn.instantiate(); - import_scene->add_importer(import_escn); + ResourceImporterScene::add_importer(import_escn); } Ref import_bitmap; @@ -7245,6 +7249,7 @@ EditorNode::EditorNode() { EditorNode::~EditorNode() { EditorInspector::cleanup_plugins(); EditorTranslationParser::get_singleton()->clean_parsers(); + ResourceImporterScene::clean_up_importer_plugins(); remove_print_handler(&print_handler); EditorHelp::cleanup_doc(); diff --git a/editor/editor_plugin.cpp b/editor/editor_plugin.cpp index 5166200ee3e..6596c245bcb 100644 --- a/editor/editor_plugin.cpp +++ b/editor/editor_plugin.cpp @@ -763,20 +763,20 @@ void EditorPlugin::remove_inspector_plugin(const Ref &p_p void EditorPlugin::add_scene_format_importer_plugin(const Ref &p_importer, bool p_first_priority) { ERR_FAIL_COND(!p_importer.is_valid()); - ResourceImporterScene::get_singleton()->add_importer(p_importer, p_first_priority); + ResourceImporterScene::add_importer(p_importer, p_first_priority); } void EditorPlugin::remove_scene_format_importer_plugin(const Ref &p_importer) { ERR_FAIL_COND(!p_importer.is_valid()); - ResourceImporterScene::get_singleton()->remove_importer(p_importer); + ResourceImporterScene::remove_importer(p_importer); } void EditorPlugin::add_scene_post_import_plugin(const Ref &p_plugin, bool p_first_priority) { - ResourceImporterScene::get_singleton()->add_post_importer_plugin(p_plugin, p_first_priority); + ResourceImporterScene::add_post_importer_plugin(p_plugin, p_first_priority); } void EditorPlugin::remove_scene_post_import_plugin(const Ref &p_plugin) { - ResourceImporterScene::get_singleton()->remove_post_importer_plugin(p_plugin); + ResourceImporterScene::remove_post_importer_plugin(p_plugin); } int find(const PackedStringArray &a, const String &v) { diff --git a/editor/filesystem_dock.cpp b/editor/filesystem_dock.cpp index a45568db48d..778c5c33ff7 100644 --- a/editor/filesystem_dock.cpp +++ b/editor/filesystem_dock.cpp @@ -989,7 +989,7 @@ void FileSystemDock::_select_file(const String &p_path, bool p_select_in_favorit { List importer_exts; - ResourceImporterScene::get_singleton()->get_recognized_extensions(&importer_exts); + ResourceImporterScene::get_scene_singleton()->get_recognized_extensions(&importer_exts); String extension = fpath.get_extension(); for (const String &E : importer_exts) { if (extension.nocasecmp_to(E) == 0) { @@ -1000,7 +1000,27 @@ void FileSystemDock::_select_file(const String &p_path, bool p_select_in_favorit } if (is_imported) { - ResourceImporterScene::get_singleton()->show_advanced_options(fpath); + ResourceImporterScene::get_scene_singleton()->show_advanced_options(fpath); + } else { + EditorNode::get_singleton()->open_request(fpath); + } + } else if (ResourceLoader::get_resource_type(fpath) == "AnimationLibrary") { + bool is_imported = false; + + { + List importer_exts; + ResourceImporterScene::get_animation_singleton()->get_recognized_extensions(&importer_exts); + String extension = fpath.get_extension(); + for (const String &E : importer_exts) { + if (extension.nocasecmp_to(E) == 0) { + is_imported = true; + break; + } + } + } + + if (is_imported) { + ResourceImporterScene::get_animation_singleton()->show_advanced_options(fpath); } else { EditorNode::get_singleton()->open_request(fpath); } diff --git a/editor/import/editor_import_collada.cpp b/editor/import/editor_import_collada.cpp index 97fc33ad25d..013dcb5deb7 100644 --- a/editor/import/editor_import_collada.cpp +++ b/editor/import/editor_import_collada.cpp @@ -1817,26 +1817,5 @@ Node *EditorSceneFormatImporterCollada::import_scene(const String &p_path, uint3 return state.scene; } -Ref EditorSceneFormatImporterCollada::import_animation(const String &p_path, uint32_t p_flags, const Map &p_options, int p_bake_fps) { - ColladaImport state; - - state.use_mesh_builtin_materials = false; - - Error err = state.load(p_path, Collada::IMPORT_FLAG_ANIMATION, p_flags & EditorSceneFormatImporter::IMPORT_GENERATE_TANGENT_ARRAYS); - ERR_FAIL_COND_V_MSG(err != OK, RES(), "Cannot load animation from file '" + p_path + "'."); - - state.create_animations(true); - if (state.scene) { - memdelete(state.scene); - } - - if (state.animations.size() == 0) { - return Ref(); - } - Ref anim = state.animations[0]; - - return anim; -} - EditorSceneFormatImporterCollada::EditorSceneFormatImporterCollada() { } diff --git a/editor/import/editor_import_collada.h b/editor/import/editor_import_collada.h index c32d785d1c2..be3f74d8213 100644 --- a/editor/import/editor_import_collada.h +++ b/editor/import/editor_import_collada.h @@ -40,7 +40,6 @@ 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 Map &p_options, int p_bake_fps, List *r_missing_deps = nullptr, Error *r_err = nullptr) override; - virtual Ref import_animation(const String &p_path, uint32_t p_flags, const Map &p_options, int p_bake_fps) override; EditorSceneFormatImporterCollada(); }; diff --git a/editor/import/resource_importer_obj.cpp b/editor/import/resource_importer_obj.cpp index 308eb9cefa1..88837d089ae 100644 --- a/editor/import/resource_importer_obj.cpp +++ b/editor/import/resource_importer_obj.cpp @@ -457,10 +457,6 @@ Node *EditorOBJImporter::import_scene(const String &p_path, uint32_t p_flags, co return scene; } -Ref EditorOBJImporter::import_animation(const String &p_path, uint32_t p_flags, const Map &p_options, int p_bake_fps) { - return Ref(); -} - void EditorOBJImporter::get_extensions(List *r_extensions) const { r_extensions->push_back("obj"); } diff --git a/editor/import/resource_importer_obj.h b/editor/import/resource_importer_obj.h index d7e3f0209da..1b5e8bbdc1b 100644 --- a/editor/import/resource_importer_obj.h +++ b/editor/import/resource_importer_obj.h @@ -40,7 +40,6 @@ 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 Map &p_options, int p_bake_fps, List *r_missing_deps, Error *r_err = nullptr) override; - virtual Ref import_animation(const String &p_path, uint32_t p_flags, const Map &p_options, int p_bake_fps) override; EditorOBJImporter(); }; diff --git a/editor/import/resource_importer_scene.cpp b/editor/import/resource_importer_scene.cpp index bfa71bfda42..bdb0c3c4935 100644 --- a/editor/import/resource_importer_scene.cpp +++ b/editor/import/resource_importer_scene.cpp @@ -87,26 +87,13 @@ Node *EditorSceneFormatImporter::import_scene(const String &p_path, uint32_t p_f ERR_FAIL_V(nullptr); } -Ref EditorSceneFormatImporter::import_animation(const String &p_path, uint32_t p_flags, const Map &p_options, int p_bake_fps) { - Dictionary options_dict; - for (const KeyValue &elem : p_options) { - options_dict[elem.key] = elem.value; - } - Ref ret; - if (GDVIRTUAL_CALL(_import_animation, p_path, p_flags, options_dict, p_bake_fps, ret)) { - return ret; - } - - ERR_FAIL_V(nullptr); -} - void EditorSceneFormatImporter::get_import_options(const String &p_path, List *r_options) { GDVIRTUAL_CALL(_get_import_options, p_path); } -Variant EditorSceneFormatImporter::get_option_visibility(const String &p_path, const String &p_option, const Map &p_options) { +Variant EditorSceneFormatImporter::get_option_visibility(const String &p_path, bool p_for_animation, const String &p_option, const Map &p_options) { Variant ret; - GDVIRTUAL_CALL(_get_option_visibility, p_path, p_option, ret); + GDVIRTUAL_CALL(_get_option_visibility, p_path, p_for_animation, p_option, ret); return ret; } @@ -114,15 +101,15 @@ 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_animation, "path", "flags", "options", "bake_fps"); GDVIRTUAL_BIND(_get_import_options, "path"); - GDVIRTUAL_BIND(_get_option_visibility, "path", "option"); + GDVIRTUAL_BIND(_get_option_visibility, "path", "for_animation", "option"); BIND_CONSTANT(IMPORT_SCENE); BIND_CONSTANT(IMPORT_ANIMATION); BIND_CONSTANT(IMPORT_FAIL_ON_MISSING_DEPENDENCIES); BIND_CONSTANT(IMPORT_GENERATE_TANGENT_ARRAYS); BIND_CONSTANT(IMPORT_USE_NAMED_SKIN_BINDS); + BIND_CONSTANT(IMPORT_DISCARD_MESHES_AND_MATERIALS); } ///////////////////////////////// @@ -179,10 +166,10 @@ void EditorScenePostImportPlugin::get_internal_import_options(InternalImportCate GDVIRTUAL_CALL(_get_internal_import_options, p_category); current_option_list = nullptr; } -Variant EditorScenePostImportPlugin::get_internal_option_visibility(InternalImportCategory p_category, const String &p_option, const Map &p_options) const { +Variant EditorScenePostImportPlugin::get_internal_option_visibility(InternalImportCategory p_category, bool p_for_animation, const String &p_option, const Map &p_options) const { current_options = &p_options; Variant ret; - GDVIRTUAL_CALL(_get_internal_option_visibility, p_category, p_option, ret); + GDVIRTUAL_CALL(_get_internal_option_visibility, p_category, p_for_animation, p_option, ret); current_options = nullptr; return ret; } @@ -205,10 +192,10 @@ void EditorScenePostImportPlugin::get_import_options(const String &p_path, List< GDVIRTUAL_CALL(_get_import_options, p_path); current_option_list = nullptr; } -Variant EditorScenePostImportPlugin::get_option_visibility(const String &p_path, const String &p_option, const Map &p_options) const { +Variant EditorScenePostImportPlugin::get_option_visibility(const String &p_path, bool p_for_animation, const String &p_option, const Map &p_options) const { current_options = &p_options; Variant ret; - GDVIRTUAL_CALL(_get_option_visibility, p_path, p_option, ret); + GDVIRTUAL_CALL(_get_option_visibility, p_path, p_for_animation, p_option, ret); current_options = nullptr; return ret; } @@ -231,11 +218,11 @@ void EditorScenePostImportPlugin::_bind_methods() { ClassDB::bind_method(D_METHOD("add_import_option_advanced", "type", "name", "default_value", "hint", "hint_string", "usage_flags"), &EditorScenePostImportPlugin::add_import_option_advanced, DEFVAL(PROPERTY_HINT_NONE), DEFVAL(""), DEFVAL(PROPERTY_USAGE_DEFAULT)); GDVIRTUAL_BIND(_get_internal_import_options, "category"); - GDVIRTUAL_BIND(_get_internal_option_visibility, "category", "option"); + GDVIRTUAL_BIND(_get_internal_option_visibility, "category", "for_animation", "option"); GDVIRTUAL_BIND(_get_internal_option_update_view_required, "category", "option"); GDVIRTUAL_BIND(_internal_process, "category", "base_node", "node", "resource"); GDVIRTUAL_BIND(_get_import_options, "path"); - GDVIRTUAL_BIND(_get_option_visibility, "path", "option"); + GDVIRTUAL_BIND(_get_option_visibility, "path", "for_animation", "option"); GDVIRTUAL_BIND(_pre_process, "scene"); GDVIRTUAL_BIND(_post_process, "scene"); @@ -251,11 +238,11 @@ void EditorScenePostImportPlugin::_bind_methods() { ///////////////////////////////////////////////////////// String ResourceImporterScene::get_importer_name() const { - return "scene"; + return animation_importer ? "animation_library" : "scene"; } String ResourceImporterScene::get_visible_name() const { - return "Scene"; + return animation_importer ? "Animation Library" : "Scene"; } void ResourceImporterScene::get_recognized_extensions(List *p_extensions) const { @@ -265,11 +252,11 @@ void ResourceImporterScene::get_recognized_extensions(List *p_extensions } String ResourceImporterScene::get_save_extension() const { - return "scn"; + return animation_importer ? "res" : "scn"; } String ResourceImporterScene::get_resource_type() const { - return "PackedScene"; + return animation_importer ? "AnimationLibrary" : "PackedScene"; } int ResourceImporterScene::get_format_version() const { @@ -277,26 +264,34 @@ int ResourceImporterScene::get_format_version() const { } bool ResourceImporterScene::get_option_visibility(const String &p_path, const String &p_option, const Map &p_options) const { - if (p_option.begins_with("animation/")) { + if (animation_importer) { + if (p_option == "animation/import") { // Option ignored, animation always imported. + return false; + } + } else if (p_option.begins_with("animation/")) { if (p_option != "animation/import" && !bool(p_options["animation/import"])) { return false; } } + if (animation_importer && (p_option.begins_with("nodes/") || p_option.begins_with("meshes/") || p_option.begins_with("skins/"))) { + return false; // Nothing to do here for animations. + } + if (p_option == "meshes/lightmap_texel_size" && int(p_options["meshes/light_baking"]) != 2) { // Only display the lightmap texel size import option when using the Static Lightmaps light baking mode. return false; } for (int i = 0; i < post_importer_plugins.size(); i++) { - Variant ret = post_importer_plugins.write[i]->get_option_visibility(p_path, p_option, p_options); + Variant ret = post_importer_plugins.write[i]->get_option_visibility(p_path, animation_importer, p_option, p_options); if (ret.get_type() == Variant::BOOL) { return ret; } } for (Ref importer : importers) { - Variant ret = importer->get_option_visibility(p_path, p_option, p_options); + Variant ret = importer->get_option_visibility(p_path, animation_importer, p_option, p_options); if (ret.get_type() == Variant::BOOL) { return ret; } @@ -1482,7 +1477,7 @@ bool ResourceImporterScene::get_internal_option_visibility(InternalImportCategor } for (int i = 0; i < post_importer_plugins.size(); i++) { - Variant ret = post_importer_plugins.write[i]->get_internal_option_visibility(EditorScenePostImportPlugin::InternalImportCategory(p_category), p_option, p_options); + Variant ret = post_importer_plugins.write[i]->get_internal_option_visibility(EditorScenePostImportPlugin::InternalImportCategory(p_category), animation_importer, p_option, p_options); if (ret.get_type() == Variant::BOOL) { return ret; } @@ -1974,8 +1969,13 @@ Error ResourceImporterScene::import(const String &p_source_file, const String &p int import_flags = 0; - if (bool(p_options["animation/import"])) { + if (animation_importer) { import_flags |= EditorSceneFormatImporter::IMPORT_ANIMATION; + import_flags |= EditorSceneFormatImporter::IMPORT_DISCARD_MESHES_AND_MATERIALS; + } else { + if (bool(p_options["animation/import"])) { + import_flags |= EditorSceneFormatImporter::IMPORT_ANIMATION; + } } if (bool(p_options["skins/use_named_skins"])) { @@ -2139,11 +2139,35 @@ Error ResourceImporterScene::import(const String &p_source_file, const String &p progress.step(TTR("Saving..."), 104); - Ref packer = memnew(PackedScene); - packer->pack(scene); - print_verbose("Saving scene to: " + p_save_path + ".scn"); - err = ResourceSaver::save(p_save_path + ".scn", packer); //do not take over, let the changed files reload themselves - ERR_FAIL_COND_V_MSG(err != OK, err, "Cannot save scene to file '" + p_save_path + ".scn'."); + if (animation_importer) { + Ref library; + for (int i = 0; i < scene->get_child_count(); i++) { + AnimationPlayer *ap = Object::cast_to(scene->get_child(i)); + if (ap) { + List libs; + ap->get_animation_library_list(&libs); + if (libs.size()) { + library = ap->get_animation_library(libs.front()->get()); + break; + } + } + } + + if (!library.is_valid()) { + library.instantiate(); // Will be empty + } + + print_verbose("Saving animation to: " + p_save_path + ".scn"); + err = ResourceSaver::save(p_save_path + ".res", library); //do not take over, let the changed files reload themselves + ERR_FAIL_COND_V_MSG(err != OK, err, "Cannot save animation to file '" + p_save_path + ".res'."); + + } else { + Ref packer = memnew(PackedScene); + packer->pack(scene); + print_verbose("Saving scene to: " + p_save_path + ".scn"); + err = ResourceSaver::save(p_save_path + ".scn", packer); //do not take over, let the changed files reload themselves + ERR_FAIL_COND_V_MSG(err != OK, err, "Cannot save scene to file '" + p_save_path + ".scn'."); + } memdelete(scene); @@ -2153,17 +2177,26 @@ Error ResourceImporterScene::import(const String &p_source_file, const String &p return OK; } -ResourceImporterScene *ResourceImporterScene::singleton = nullptr; +ResourceImporterScene *ResourceImporterScene::scene_singleton = nullptr; +ResourceImporterScene *ResourceImporterScene::animation_singleton = nullptr; + +Vector> ResourceImporterScene::importers; +Vector> ResourceImporterScene::post_importer_plugins; bool ResourceImporterScene::ResourceImporterScene::has_advanced_options() const { return true; } void ResourceImporterScene::ResourceImporterScene::show_advanced_options(const String &p_path) { - SceneImportSettings::get_singleton()->open_settings(p_path); + SceneImportSettings::get_singleton()->open_settings(p_path, animation_importer); } -ResourceImporterScene::ResourceImporterScene() { - singleton = this; +ResourceImporterScene::ResourceImporterScene(bool p_animation_import) { + if (p_animation_import) { + animation_singleton = this; + } else { + scene_singleton = this; + } + animation_importer = p_animation_import; } void ResourceImporterScene::add_importer(Ref p_importer, bool p_first_priority) { @@ -2192,6 +2225,11 @@ void ResourceImporterScene::remove_importer(Ref p_imp importers.erase(p_importer); } +void ResourceImporterScene::clean_up_importer_plugins() { + importers.clear(); + post_importer_plugins.clear(); +} + /////////////////////////////////////// uint32_t EditorSceneFormatImporterESCN::get_import_flags() const { @@ -2212,7 +2250,3 @@ Node *EditorSceneFormatImporterESCN::import_scene(const String &p_path, uint32_t return scene; } - -Ref EditorSceneFormatImporterESCN::import_animation(const String &p_path, uint32_t p_flags, const Map &p_options, int p_bake_fps) { - ERR_FAIL_V(Ref()); -} diff --git a/editor/import/resource_importer_scene.h b/editor/import/resource_importer_scene.h index a819be682df..368f68ae8fe 100644 --- a/editor/import/resource_importer_scene.h +++ b/editor/import/resource_importer_scene.h @@ -56,9 +56,8 @@ protected: GDVIRTUAL0RC(int, _get_import_flags) GDVIRTUAL0RC(Vector, _get_extensions) GDVIRTUAL4R(Object *, _import_scene, String, uint32_t, Dictionary, uint32_t) - GDVIRTUAL4R(Ref, _import_animation, String, uint32_t, Dictionary, uint32_t) GDVIRTUAL1(_get_import_options, String) - GDVIRTUAL2RC(Variant, _get_option_visibility, String, String) + GDVIRTUAL3RC(Variant, _get_option_visibility, String, bool, String) public: enum ImportFlags { @@ -67,14 +66,14 @@ public: IMPORT_FAIL_ON_MISSING_DEPENDENCIES = 4, IMPORT_GENERATE_TANGENT_ARRAYS = 8, IMPORT_USE_NAMED_SKIN_BINDS = 16, + IMPORT_DISCARD_MESHES_AND_MATERIALS = 32, //used for optimizing animation import }; 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 Map &p_options, int p_bake_fps, List *r_missing_deps, Error *r_err = nullptr); - virtual Ref import_animation(const String &p_path, uint32_t p_flags, const Map &p_options, int p_bake_fps); virtual void get_import_options(const String &p_path, List *r_options); - virtual Variant get_option_visibility(const String &p_path, const String &p_option, const Map &p_options); + virtual Variant get_option_visibility(const String &p_path, bool p_for_animation, const String &p_option, const Map &p_options); EditorSceneFormatImporter() {} }; @@ -118,11 +117,11 @@ private: protected: GDVIRTUAL1(_get_internal_import_options, int) - GDVIRTUAL2RC(Variant, _get_internal_option_visibility, int, String) + GDVIRTUAL3RC(Variant, _get_internal_option_visibility, int, bool, String) GDVIRTUAL2RC(Variant, _get_internal_option_update_view_required, int, String) GDVIRTUAL4(_internal_process, int, Node *, Node *, RES) GDVIRTUAL1(_get_import_options, String) - GDVIRTUAL2RC(Variant, _get_option_visibility, String, String) + GDVIRTUAL3RC(Variant, _get_option_visibility, String, bool, String) GDVIRTUAL1(_pre_process, Node *) GDVIRTUAL1(_post_process, Node *) @@ -134,13 +133,13 @@ public: void add_import_option_advanced(Variant::Type p_type, const String &p_name, Variant p_default_value, PropertyHint p_hint = PROPERTY_HINT_NONE, const String &p_hint_string = String(), int p_usage_flags = PROPERTY_USAGE_DEFAULT); virtual void get_internal_import_options(InternalImportCategory p_category, List *r_options); - virtual Variant get_internal_option_visibility(InternalImportCategory p_category, const String &p_option, const Map &p_options) const; + virtual Variant get_internal_option_visibility(InternalImportCategory p_category, bool p_for_animation, const String &p_option, const Map &p_options) const; virtual Variant get_internal_option_update_view_required(InternalImportCategory p_category, const String &p_option, const Map &p_options) const; virtual void internal_process(InternalImportCategory p_category, Node *p_base_scene, Node *p_node, RES p_resource, const Dictionary &p_options); virtual void get_import_options(const String &p_path, List *r_options); - virtual Variant get_option_visibility(const String &p_path, const String &p_option, const Map &p_options) const; + virtual Variant get_option_visibility(const String &p_path, bool p_for_animation, const String &p_option, const Map &p_options) const; virtual void pre_process(Node *p_scene, const Map &p_options); virtual void post_process(Node *p_scene, const Map &p_options); @@ -153,9 +152,11 @@ VARIANT_ENUM_CAST(EditorScenePostImportPlugin::InternalImportCategory) class ResourceImporterScene : public ResourceImporter { GDCLASS(ResourceImporterScene, ResourceImporter); - Vector> importers; + static Vector> importers; + static Vector> post_importer_plugins; - static ResourceImporterScene *singleton; + static ResourceImporterScene *scene_singleton; + static ResourceImporterScene *animation_singleton; enum LightBakeMode { LIGHT_BAKE_DISABLED, @@ -225,18 +226,21 @@ class ResourceImporterScene : public ResourceImporter { void _optimize_track_usage(AnimationPlayer *p_player, AnimationImportTracks *p_track_actions); - mutable Vector> post_importer_plugins; + bool animation_importer = false; public: - static ResourceImporterScene *get_singleton() { return singleton; } + static ResourceImporterScene *get_scene_singleton() { return scene_singleton; } + static ResourceImporterScene *get_animation_singleton() { return animation_singleton; } - void add_post_importer_plugin(const Ref &p_plugin, bool p_first_priority = false); - void remove_post_importer_plugin(const Ref &p_plugin); + static void add_post_importer_plugin(const Ref &p_plugin, bool p_first_priority = false); + static void remove_post_importer_plugin(const Ref &p_plugin); const Vector> &get_importers() const { return importers; } - void add_importer(Ref p_importer, bool p_first_priority = false); - void remove_importer(Ref p_importer); + static void add_importer(Ref p_importer, bool p_first_priority = false); + static void remove_importer(Ref p_importer); + + static void clean_up_importer_plugins(); virtual String get_importer_name() const override; virtual String get_visible_name() const override; @@ -283,7 +287,7 @@ public: virtual bool can_import_threaded() const override { return false; } - ResourceImporterScene(); + ResourceImporterScene(bool p_animation_import = false); template static Vector> get_collision_shapes(const Ref &p_mesh, const M &p_options); @@ -299,7 +303,6 @@ 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 Map &p_options, int p_bake_fps, List *r_missing_deps, Error *r_err = nullptr) override; - virtual Ref import_animation(const String &p_path, uint32_t p_flags, const Map &p_options, int p_bake_fps) override; }; #include "scene/resources/box_shape_3d.h" diff --git a/editor/import/scene_import_settings.cpp b/editor/import/scene_import_settings.cpp index 302bc984999..4e53a644ee2 100644 --- a/editor/import/scene_import_settings.cpp +++ b/editor/import/scene_import_settings.cpp @@ -47,6 +47,8 @@ class SceneImportSettingsData : public Object { Map current; Map defaults; List options; + bool hide_options = false; + String path; ResourceImporterScene::InternalImportCategory category = ResourceImporterScene::INTERNAL_IMPORT_CATEGORY_MAX; @@ -60,8 +62,26 @@ class SceneImportSettingsData : public Object { current[p_name] = p_value; - if (ResourceImporterScene::get_singleton()->get_internal_option_update_view_required(category, p_name, current)) { - SceneImportSettings::get_singleton()->update_view(); + if (SceneImportSettings::get_singleton()->is_editing_animation()) { + if (category == ResourceImporterScene::INTERNAL_IMPORT_CATEGORY_MAX) { + if (ResourceImporterScene::get_animation_singleton()->get_option_visibility(path, p_name, current)) { + SceneImportSettings::get_singleton()->update_view(); + } + } else { + if (ResourceImporterScene::get_animation_singleton()->get_internal_option_update_view_required(category, p_name, current)) { + SceneImportSettings::get_singleton()->update_view(); + } + } + } else { + if (category == ResourceImporterScene::INTERNAL_IMPORT_CATEGORY_MAX) { + if (ResourceImporterScene::get_scene_singleton()->get_option_visibility(path, p_name, current)) { + SceneImportSettings::get_singleton()->update_view(); + } + } else { + if (ResourceImporterScene::get_scene_singleton()->get_internal_option_update_view_required(category, p_name, current)) { + SceneImportSettings::get_singleton()->update_view(); + } + } } return true; @@ -82,9 +102,30 @@ class SceneImportSettingsData : public Object { return false; } void _get_property_list(List *p_list) const { + if (hide_options) { + return; + } for (const ResourceImporter::ImportOption &E : options) { - if (ResourceImporterScene::get_singleton()->get_internal_option_visibility(category, E.option.name, current)) { - p_list->push_back(E.option); + if (SceneImportSettings::get_singleton()->is_editing_animation()) { + if (category == ResourceImporterScene::INTERNAL_IMPORT_CATEGORY_MAX) { + if (ResourceImporterScene::get_animation_singleton()->get_option_visibility(path, E.option.name, current)) { + p_list->push_back(E.option); + } + } else { + if (ResourceImporterScene::get_animation_singleton()->get_internal_option_visibility(category, E.option.name, current)) { + p_list->push_back(E.option); + } + } + } else { + if (category == ResourceImporterScene::INTERNAL_IMPORT_CATEGORY_MAX) { + if (ResourceImporterScene::get_scene_singleton()->get_option_visibility(path, E.option.name, current)) { + p_list->push_back(E.option); + } + } else { + if (ResourceImporterScene::get_scene_singleton()->get_internal_option_visibility(category, E.option.name, current)) { + p_list->push_back(E.option); + } + } } } } @@ -326,7 +367,9 @@ void SceneImportSettings::_fill_scene(Node *p_node, TreeItem *p_parent_item) { } MeshInstance3D *mesh_node = Object::cast_to(p_node); if (mesh_node && mesh_node->get_mesh().is_valid()) { - _fill_mesh(scene_tree, mesh_node->get_mesh(), item); + if (!editing_animation) { + _fill_mesh(scene_tree, mesh_node->get_mesh(), item); + } // Add the collider view. MeshInstance3D *collider_view = memnew(MeshInstance3D); @@ -365,6 +408,9 @@ void SceneImportSettings::_update_scene() { } void SceneImportSettings::_update_view_gizmos() { + if (!is_visible()) { + return; + } for (const KeyValue &e : node_map) { bool generate_collider = false; if (e.value.settings.has(SNAME("generate/physics"))) { @@ -378,6 +424,7 @@ void SceneImportSettings::_update_view_gizmos() { } TypedArray descendants = mesh_node->find_nodes("collider_view", "MeshInstance3D"); + CRASH_COND_MSG(descendants.is_empty(), "This is unreachable, since the collider view is always created even when the collision is not used! If this is triggered there is a bug on the function `_fill_scene`."); MeshInstance3D *collider_view = static_cast(descendants[0].operator Object *()); @@ -460,7 +507,11 @@ void SceneImportSettings::_load_default_subresource_settings(Map options; - ResourceImporterScene::get_singleton()->get_internal_import_options(p_category, &options); + if (editing_animation) { + ResourceImporterScene::get_animation_singleton()->get_internal_import_options(p_category, &options); + } else { + ResourceImporterScene::get_scene_singleton()->get_internal_import_options(p_category, &options); + } for (const ResourceImporterScene::ImportOption &E : options) { String key = E.option.name; if (d.has(key)) { @@ -472,21 +523,32 @@ void SceneImportSettings::_load_default_subresource_settings(Mapstart(); } -void SceneImportSettings::open_settings(const String &p_path) { +void SceneImportSettings::open_settings(const String &p_path, bool p_for_animation) { if (scene) { memdelete(scene); scene = nullptr; } + + editing_animation = p_for_animation; scene_import_settings_data->settings = nullptr; - scene = ResourceImporterScene::get_singleton()->pre_import(p_path); + scene_import_settings_data->path = p_path; + + scene = ResourceImporterScene::get_scene_singleton()->pre_import(p_path); // Use the scene singleton here because we want to see the full thing. if (scene == nullptr) { EditorNode::get_singleton()->show_warning(TTR("Error opening scene")); return; } + // Visibility + data_mode->set_tab_hidden(1, p_for_animation); + data_mode->set_tab_hidden(2, p_for_animation); + + action_menu->get_popup()->set_item_disabled(action_menu->get_popup()->get_item_id(ACTION_EXTRACT_MATERIALS), p_for_animation); + action_menu->get_popup()->set_item_disabled(action_menu->get_popup()->get_item_id(ACTION_CHOOSE_MESH_SAVE_PATHS), p_for_animation); + base_path = p_path; material_set.clear(); @@ -540,7 +602,11 @@ void SceneImportSettings::open_settings(const String &p_path) { _update_view_gizmos(); _update_camera(); - set_title(vformat(TTR("Advanced Import Settings for '%s'"), base_path.get_file())); + if (p_for_animation) { + set_title(vformat(TTR("Advanced Import Settings for AnimationLibrary '%s'"), base_path.get_file())); + } else { + set_title(vformat(TTR("Advanced Import Settings for Scene '%s'"), base_path.get_file())); + } } SceneImportSettings *SceneImportSettings::singleton = nullptr; @@ -551,6 +617,7 @@ SceneImportSettings *SceneImportSettings::get_singleton() { void SceneImportSettings::_select(Tree *p_from, String p_type, String p_id) { selecting = true; + scene_import_settings_data->hide_options = false; if (p_type == "Node") { node_selected->hide(); //always hide just in case @@ -585,10 +652,12 @@ void SceneImportSettings::_select(Tree *p_from, String p_type, String p_id) { scene_import_settings_data->settings = &nd.settings; if (mi) { scene_import_settings_data->category = ResourceImporterScene::INTERNAL_IMPORT_CATEGORY_MESH_3D_NODE; + scene_import_settings_data->hide_options = editing_animation; } else if (Object::cast_to(nd.node)) { scene_import_settings_data->category = ResourceImporterScene::INTERNAL_IMPORT_CATEGORY_ANIMATION_NODE; } else { scene_import_settings_data->category = ResourceImporterScene::INTERNAL_IMPORT_CATEGORY_NODE; + scene_import_settings_data->hide_options = editing_animation; } } } else if (p_type == "Animation") { @@ -671,24 +740,36 @@ void SceneImportSettings::_select(Tree *p_from, String p_type, String p_id) { List options; - if (scene_import_settings_data->category == ResourceImporterScene::INTERNAL_IMPORT_CATEGORY_MAX) { - ResourceImporterScene::get_singleton()->get_import_options(base_path, &options); + if (editing_animation) { + if (scene_import_settings_data->category == ResourceImporterScene::INTERNAL_IMPORT_CATEGORY_MAX) { + ResourceImporterScene::get_animation_singleton()->get_import_options(base_path, &options); + } else { + ResourceImporterScene::get_animation_singleton()->get_internal_import_options(scene_import_settings_data->category, &options); + } + } else { - ResourceImporterScene::get_singleton()->get_internal_import_options(scene_import_settings_data->category, &options); + if (scene_import_settings_data->category == ResourceImporterScene::INTERNAL_IMPORT_CATEGORY_MAX) { + ResourceImporterScene::get_scene_singleton()->get_import_options(base_path, &options); + } else { + ResourceImporterScene::get_scene_singleton()->get_internal_import_options(scene_import_settings_data->category, &options); + } } scene_import_settings_data->defaults.clear(); scene_import_settings_data->current.clear(); - for (const ResourceImporter::ImportOption &E : options) { - scene_import_settings_data->defaults[E.option.name] = E.default_value; - //needed for visibility toggling (fails if something is missing) - if (scene_import_settings_data->settings->has(E.option.name)) { - scene_import_settings_data->current[E.option.name] = (*scene_import_settings_data->settings)[E.option.name]; - } else { - scene_import_settings_data->current[E.option.name] = E.default_value; + if (scene_import_settings_data->settings) { + for (const ResourceImporter::ImportOption &E : options) { + scene_import_settings_data->defaults[E.option.name] = E.default_value; + //needed for visibility toggling (fails if something is missing) + if (scene_import_settings_data->settings->has(E.option.name)) { + scene_import_settings_data->current[E.option.name] = (*scene_import_settings_data->settings)[E.option.name]; + } else { + scene_import_settings_data->current[E.option.name] = E.default_value; + } } } + scene_import_settings_data->options = options; inspector->edit(scene_import_settings_data); scene_import_settings_data->notify_property_list_changed(); @@ -836,7 +917,7 @@ void SceneImportSettings::_re_import() { main_settings["_subresources"] = subresources; } - EditorFileSystem::get_singleton()->reimport_file_with_custom_parameters(base_path, "scene", main_settings); + EditorFileSystem::get_singleton()->reimport_file_with_custom_parameters(base_path, editing_animation ? "animation_library" : "scene", main_settings); } void SceneImportSettings::_notification(int p_what) { @@ -1282,6 +1363,11 @@ SceneImportSettings::SceneImportSettings() { item_save_path->connect("file_selected", callable_mp(this, &SceneImportSettings::_save_path_changed)); save_path->connect("dir_selected", callable_mp(this, &SceneImportSettings::_save_dir_callback)); + + update_view_timer = memnew(Timer); + update_view_timer->set_wait_time(0.2); + update_view_timer->connect("timeout", callable_mp(this, &SceneImportSettings::_update_view_gizmos)); + add_child(update_view_timer); } SceneImportSettings::~SceneImportSettings() { diff --git a/editor/import/scene_import_settings.h b/editor/import/scene_import_settings.h index 3cf708740b8..55cfba3275e 100644 --- a/editor/import/scene_import_settings.h +++ b/editor/import/scene_import_settings.h @@ -189,12 +189,17 @@ class SceneImportSettings : public ConfirmationDialog { void _load_default_subresource_settings(Map &settings, const String &p_type, const String &p_import_id, ResourceImporterScene::InternalImportCategory p_category); + bool editing_animation = false; + + Timer *update_view_timer; + protected: void _notification(int p_what); public: + bool is_editing_animation() const { return editing_animation; } void update_view(); - void open_settings(const String &p_path); + void open_settings(const String &p_path, bool p_for_animation = false); static SceneImportSettings *get_singleton(); SceneImportSettings(); ~SceneImportSettings(); diff --git a/modules/gltf/editor/editor_scene_importer_blend.cpp b/modules/gltf/editor/editor_scene_importer_blend.cpp index ae05c1b68df..173d5131cf0 100644 --- a/modules/gltf/editor/editor_scene_importer_blend.cpp +++ b/modules/gltf/editor/editor_scene_importer_blend.cpp @@ -238,13 +238,12 @@ Node *EditorSceneFormatImporterBlend::import_scene(const String &p_path, uint32_ return gltf->generate_scene(state, p_bake_fps); } -Ref EditorSceneFormatImporterBlend::import_animation(const String &p_path, uint32_t p_flags, - const Map &p_options, int p_bake_fps) { - return Ref(); -} - -Variant EditorSceneFormatImporterBlend::get_option_visibility(const String &p_path, const String &p_option, +Variant EditorSceneFormatImporterBlend::get_option_visibility(const String &p_path, bool p_for_animation, const String &p_option, const Map &p_options) { + if (p_path.get_extension().to_lower() != "blend") { + return true; + } + if (p_option.begins_with("animation/")) { if (p_option != "animation/import" && !bool(p_options["animation/import"])) { return false; @@ -254,6 +253,9 @@ Variant EditorSceneFormatImporterBlend::get_option_visibility(const String &p_pa } void EditorSceneFormatImporterBlend::get_import_options(const String &p_path, List *r_options) { + if (p_path.get_extension().to_lower() != "blend") { + return; + } #define ADD_OPTION_BOOL(PATH, VALUE) \ r_options->push_back(ResourceImporter::ImportOption(PropertyInfo(Variant::BOOL, SNAME(PATH)), VALUE)); #define ADD_OPTION_ENUM(PATH, ENUM_HINT, VALUE) \ diff --git a/modules/gltf/editor/editor_scene_importer_blend.h b/modules/gltf/editor/editor_scene_importer_blend.h index 9a1b5f58034..0925333a283 100644 --- a/modules/gltf/editor/editor_scene_importer_blend.h +++ b/modules/gltf/editor/editor_scene_importer_blend.h @@ -68,11 +68,9 @@ public: virtual Node *import_scene(const String &p_path, uint32_t p_flags, const Map &p_options, int p_bake_fps, List *r_missing_deps, Error *r_err = nullptr) override; - virtual Ref import_animation(const String &p_path, uint32_t p_flags, - const Map &p_options, int p_bake_fps) override; virtual void get_import_options(const String &p_path, List *r_options) override; - virtual Variant get_option_visibility(const String &p_path, const String &p_option, + virtual Variant get_option_visibility(const String &p_path, bool p_for_animation, const String &p_option, const Map &p_options) override; }; diff --git a/modules/gltf/editor/editor_scene_importer_fbx.cpp b/modules/gltf/editor/editor_scene_importer_fbx.cpp index 24564f55be0..893d2efcec9 100644 --- a/modules/gltf/editor/editor_scene_importer_fbx.cpp +++ b/modules/gltf/editor/editor_scene_importer_fbx.cpp @@ -105,12 +105,7 @@ Node *EditorSceneFormatImporterFBX::import_scene(const String &p_path, uint32_t return gltf->generate_scene(state, p_bake_fps); } -Ref EditorSceneFormatImporterFBX::import_animation(const String &p_path, - uint32_t p_flags, const Map &p_options, int p_bake_fps) { - return Ref(); -} - -Variant EditorSceneFormatImporterFBX::get_option_visibility(const String &p_path, +Variant EditorSceneFormatImporterFBX::get_option_visibility(const String &p_path, bool p_for_animation, const String &p_option, const Map &p_options) { return true; } diff --git a/modules/gltf/editor/editor_scene_importer_fbx.h b/modules/gltf/editor/editor_scene_importer_fbx.h index bb69cfaa301..84de7fd1ccf 100644 --- a/modules/gltf/editor/editor_scene_importer_fbx.h +++ b/modules/gltf/editor/editor_scene_importer_fbx.h @@ -47,11 +47,9 @@ public: virtual Node *import_scene(const String &p_path, uint32_t p_flags, const Map &p_options, int p_bake_fps, List *r_missing_deps, Error *r_err = nullptr) override; - virtual Ref import_animation(const String &p_path, uint32_t p_flags, - const Map &p_options, int p_bake_fps) override; virtual void get_import_options(const String &p_path, List *r_options) override; - virtual Variant get_option_visibility(const String &p_path, const String &p_option, + virtual Variant get_option_visibility(const String &p_path, bool p_for_animation, const String &p_option, const Map &p_options) override; }; diff --git a/modules/gltf/editor/editor_scene_importer_gltf.cpp b/modules/gltf/editor/editor_scene_importer_gltf.cpp index 1d6a82e58ae..5e7811ad2b0 100644 --- a/modules/gltf/editor/editor_scene_importer_gltf.cpp +++ b/modules/gltf/editor/editor_scene_importer_gltf.cpp @@ -64,9 +64,4 @@ Node *EditorSceneFormatImporterGLTF::import_scene(const String &p_path, uint32_t return doc->generate_scene(state, p_bake_fps); } -Ref EditorSceneFormatImporterGLTF::import_animation(const String &p_path, - uint32_t p_flags, const Map &p_options, int p_bake_fps) { - return Ref(); -} - #endif // TOOLS_ENABLED diff --git a/modules/gltf/editor/editor_scene_importer_gltf.h b/modules/gltf/editor/editor_scene_importer_gltf.h index 1f62ca9537d..b714ada124f 100644 --- a/modules/gltf/editor/editor_scene_importer_gltf.h +++ b/modules/gltf/editor/editor_scene_importer_gltf.h @@ -47,8 +47,6 @@ public: virtual Node *import_scene(const String &p_path, uint32_t p_flags, const Map &p_options, int p_bake_fps, List *r_missing_deps, Error *r_err = nullptr) override; - virtual Ref import_animation(const String &p_path, uint32_t p_flags, - const Map &p_options, int p_bake_fps) override; }; #endif // TOOLS_ENABLED diff --git a/modules/gltf/register_types.cpp b/modules/gltf/register_types.cpp index e09c76f0528..b656788a10a 100644 --- a/modules/gltf/register_types.cpp +++ b/modules/gltf/register_types.cpp @@ -60,7 +60,7 @@ static void _editor_init() { Ref import_gltf; import_gltf.instantiate(); - ResourceImporterScene::get_singleton()->add_importer(import_gltf); + ResourceImporterScene::add_importer(import_gltf); // Blend to glTF importer. @@ -72,7 +72,7 @@ static void _editor_init() { if (blend_enabled) { Ref importer; importer.instantiate(); - ResourceImporterScene::get_singleton()->add_importer(importer); + ResourceImporterScene::add_importer(importer); Ref blend_import_query; blend_import_query.instantiate(); @@ -95,7 +95,7 @@ static void _editor_init() { } else { Ref importer; importer.instantiate(); - ResourceImporterScene::get_singleton()->add_importer(importer); + ResourceImporterScene::add_importer(importer); } } }