diff options
author | reduz <reduzio@gmail.com> | 2021-10-14 14:34:27 -0300 |
---|---|---|
committer | reduz <reduzio@gmail.com> | 2021-10-15 09:12:04 -0300 |
commit | b3bf90b3ce740b2956509427656c908df51c929f (patch) | |
tree | ddbc9c3a4d4a058cae59dc755cd4c8fcb28673d3 /editor | |
parent | e53e897b8c70cef11a2a0b13edbad9f038f26e58 (diff) |
Add scene Post-Import Plugin support.
* New plugin system to control the whole import workflow
* Can add options and run code at every import step (general, per node, mesh, animation, material etc.)
This constitutes a first version of these plugins. The ability to interact with the import preview dialog will likely be added later on.
Diffstat (limited to 'editor')
-rw-r--r-- | editor/editor_node.cpp | 7 | ||||
-rw-r--r-- | editor/editor_plugin.cpp | 17 | ||||
-rw-r--r-- | editor/editor_plugin.h | 7 | ||||
-rw-r--r-- | editor/import/editor_import_collada.cpp | 14 | ||||
-rw-r--r-- | editor/import/editor_import_collada.h | 6 | ||||
-rw-r--r-- | editor/import/resource_importer_obj.h | 4 | ||||
-rw-r--r-- | editor/import/resource_importer_scene.cpp | 252 | ||||
-rw-r--r-- | editor/import/resource_importer_scene.h | 95 |
8 files changed, 335 insertions, 67 deletions
diff --git a/editor/editor_node.cpp b/editor/editor_node.cpp index 9b7dc966e6..2f92f60d5e 100644 --- a/editor/editor_node.cpp +++ b/editor/editor_node.cpp @@ -3848,7 +3848,8 @@ void EditorNode::register_editor_types() { GDREGISTER_VIRTUAL_CLASS(EditorInterface); GDREGISTER_CLASS(EditorExportPlugin); GDREGISTER_CLASS(EditorResourceConversionPlugin); - GDREGISTER_CLASS(EditorSceneImporter); + GDREGISTER_CLASS(EditorSceneFormatImporter); + GDREGISTER_CLASS(EditorScenePostImportPlugin); GDREGISTER_CLASS(EditorInspector); GDREGISTER_CLASS(EditorInspectorPlugin); GDREGISTER_CLASS(EditorProperty); @@ -5935,7 +5936,7 @@ EditorNode::EditorNode() { ResourceFormatImporter::get_singleton()->add_importer(import_scene); { - Ref<EditorSceneImporterCollada> import_collada; + Ref<EditorSceneFormatImporterCollada> import_collada; import_collada.instantiate(); import_scene->add_importer(import_collada); @@ -5943,7 +5944,7 @@ EditorNode::EditorNode() { import_obj2.instantiate(); import_scene->add_importer(import_obj2); - Ref<EditorSceneImporterESCN> import_escn; + Ref<EditorSceneFormatImporterESCN> import_escn; import_escn.instantiate(); import_scene->add_importer(import_escn); } diff --git a/editor/editor_plugin.cpp b/editor/editor_plugin.cpp index aee8322a97..61c01993ae 100644 --- a/editor/editor_plugin.cpp +++ b/editor/editor_plugin.cpp @@ -762,16 +762,23 @@ void EditorPlugin::remove_inspector_plugin(const Ref<EditorInspectorPlugin> &p_p EditorInspector::remove_inspector_plugin(p_plugin); } -void EditorPlugin::add_scene_import_plugin(const Ref<EditorSceneImporter> &p_importer) { +void EditorPlugin::add_scene_format_importer_plugin(const Ref<EditorSceneFormatImporter> &p_importer) { ERR_FAIL_COND(!p_importer.is_valid()); ResourceImporterScene::get_singleton()->add_importer(p_importer); } -void EditorPlugin::remove_scene_import_plugin(const Ref<EditorSceneImporter> &p_importer) { +void EditorPlugin::remove_scene_format_importer_plugin(const Ref<EditorSceneFormatImporter> &p_importer) { ERR_FAIL_COND(!p_importer.is_valid()); ResourceImporterScene::get_singleton()->remove_importer(p_importer); } +void EditorPlugin::add_scene_post_import_plugin(const Ref<EditorScenePostImportPlugin> &p_plugin) { + ResourceImporterScene::get_singleton()->add_post_importer_plugin(p_plugin); +} +void EditorPlugin::remove_scene_post_import_plugin(const Ref<EditorScenePostImportPlugin> &p_plugin) { + ResourceImporterScene::get_singleton()->remove_post_importer_plugin(p_plugin); +} + int find(const PackedStringArray &a, const String &v) { const String *r = a.ptr(); for (int j = 0; j < a.size(); ++j) { @@ -879,8 +886,10 @@ void EditorPlugin::_bind_methods() { ClassDB::bind_method(D_METHOD("remove_translation_parser_plugin", "parser"), &EditorPlugin::remove_translation_parser_plugin); ClassDB::bind_method(D_METHOD("add_import_plugin", "importer"), &EditorPlugin::add_import_plugin); ClassDB::bind_method(D_METHOD("remove_import_plugin", "importer"), &EditorPlugin::remove_import_plugin); - ClassDB::bind_method(D_METHOD("add_scene_import_plugin", "scene_importer"), &EditorPlugin::add_scene_import_plugin); - ClassDB::bind_method(D_METHOD("remove_scene_import_plugin", "scene_importer"), &EditorPlugin::remove_scene_import_plugin); + ClassDB::bind_method(D_METHOD("add_scene_format_importer_plugin", "scene_format_importer"), &EditorPlugin::add_scene_format_importer_plugin); + ClassDB::bind_method(D_METHOD("remove_scene_format_importer_plugin", "scene_format_importer"), &EditorPlugin::remove_scene_format_importer_plugin); + ClassDB::bind_method(D_METHOD("add_scene_post_import_plugin", "scene_import_plugin"), &EditorPlugin::add_scene_post_import_plugin); + ClassDB::bind_method(D_METHOD("remove_scene_post_import_plugin", "scene_import_plugin"), &EditorPlugin::remove_scene_post_import_plugin); ClassDB::bind_method(D_METHOD("add_export_plugin", "plugin"), &EditorPlugin::add_export_plugin); ClassDB::bind_method(D_METHOD("remove_export_plugin", "plugin"), &EditorPlugin::remove_export_plugin); ClassDB::bind_method(D_METHOD("add_spatial_gizmo_plugin", "plugin"), &EditorPlugin::add_spatial_gizmo_plugin); diff --git a/editor/editor_plugin.h b/editor/editor_plugin.h index 57830df327..278059f8c4 100644 --- a/editor/editor_plugin.h +++ b/editor/editor_plugin.h @@ -288,8 +288,11 @@ public: void add_inspector_plugin(const Ref<EditorInspectorPlugin> &p_plugin); void remove_inspector_plugin(const Ref<EditorInspectorPlugin> &p_plugin); - void add_scene_import_plugin(const Ref<EditorSceneImporter> &p_importer); - void remove_scene_import_plugin(const Ref<EditorSceneImporter> &p_importer); + void add_scene_format_importer_plugin(const Ref<EditorSceneFormatImporter> &p_importer); + void remove_scene_format_importer_plugin(const Ref<EditorSceneFormatImporter> &p_importer); + + void add_scene_post_import_plugin(const Ref<EditorScenePostImportPlugin> &p_importer); + void remove_scene_post_import_plugin(const Ref<EditorScenePostImportPlugin> &p_importer); void add_autoload_singleton(const String &p_name, const String &p_path); void remove_autoload_singleton(const String &p_name); diff --git a/editor/import/editor_import_collada.cpp b/editor/import/editor_import_collada.cpp index d1bacf54de..4e343ce3ce 100644 --- a/editor/import/editor_import_collada.cpp +++ b/editor/import/editor_import_collada.cpp @@ -1748,15 +1748,15 @@ void ColladaImport::create_animation(int p_clip, bool p_import_value_tracks) { /*************************************** SCENE ***********************************/ /*********************************************************************************/ -uint32_t EditorSceneImporterCollada::get_import_flags() const { +uint32_t EditorSceneFormatImporterCollada::get_import_flags() const { return IMPORT_SCENE | IMPORT_ANIMATION; } -void EditorSceneImporterCollada::get_extensions(List<String> *r_extensions) const { +void EditorSceneFormatImporterCollada::get_extensions(List<String> *r_extensions) const { r_extensions->push_back("dae"); } -Node *EditorSceneImporterCollada::import_scene(const String &p_path, uint32_t p_flags, int p_bake_fps, List<String> *r_missing_deps, Error *r_err) { +Node *EditorSceneFormatImporterCollada::import_scene(const String &p_path, uint32_t p_flags, int p_bake_fps, List<String> *r_missing_deps, Error *r_err) { if (r_err) { *r_err = OK; } @@ -1769,7 +1769,7 @@ Node *EditorSceneImporterCollada::import_scene(const String &p_path, uint32_t p_ state.use_mesh_builtin_materials = true; state.bake_fps = p_bake_fps; - Error err = state.load(p_path, flags, p_flags & EditorSceneImporter::IMPORT_GENERATE_TANGENT_ARRAYS, false); + Error err = state.load(p_path, flags, p_flags & EditorSceneFormatImporter::IMPORT_GENERATE_TANGENT_ARRAYS, false); if (r_err) { *r_err = err; @@ -1812,12 +1812,12 @@ Node *EditorSceneImporterCollada::import_scene(const String &p_path, uint32_t p_ return state.scene; } -Ref<Animation> EditorSceneImporterCollada::import_animation(const String &p_path, uint32_t p_flags, int p_bake_fps) { +Ref<Animation> EditorSceneFormatImporterCollada::import_animation(const String &p_path, uint32_t p_flags, int p_bake_fps) { ColladaImport state; state.use_mesh_builtin_materials = false; - Error err = state.load(p_path, Collada::IMPORT_FLAG_ANIMATION, p_flags & EditorSceneImporter::IMPORT_GENERATE_TANGENT_ARRAYS); + 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); @@ -1833,5 +1833,5 @@ Ref<Animation> EditorSceneImporterCollada::import_animation(const String &p_path return anim; } -EditorSceneImporterCollada::EditorSceneImporterCollada() { +EditorSceneFormatImporterCollada::EditorSceneFormatImporterCollada() { } diff --git a/editor/import/editor_import_collada.h b/editor/import/editor_import_collada.h index bf45322765..055a6fe178 100644 --- a/editor/import/editor_import_collada.h +++ b/editor/import/editor_import_collada.h @@ -33,8 +33,8 @@ #include "editor/import/resource_importer_scene.h" -class EditorSceneImporterCollada : public EditorSceneImporter { - GDCLASS(EditorSceneImporterCollada, EditorSceneImporter); +class EditorSceneFormatImporterCollada : public EditorSceneFormatImporter { + GDCLASS(EditorSceneFormatImporterCollada, EditorSceneFormatImporter); public: virtual uint32_t get_import_flags() const override; @@ -42,7 +42,7 @@ public: virtual Node *import_scene(const String &p_path, uint32_t p_flags, int p_bake_fps, List<String> *r_missing_deps = nullptr, Error *r_err = nullptr) override; virtual Ref<Animation> import_animation(const String &p_path, uint32_t p_flags, int p_bake_fps) override; - EditorSceneImporterCollada(); + EditorSceneFormatImporterCollada(); }; #endif diff --git a/editor/import/resource_importer_obj.h b/editor/import/resource_importer_obj.h index 1bb5ef33ce..d9f2f79903 100644 --- a/editor/import/resource_importer_obj.h +++ b/editor/import/resource_importer_obj.h @@ -33,8 +33,8 @@ #include "resource_importer_scene.h" -class EditorOBJImporter : public EditorSceneImporter { - GDCLASS(EditorOBJImporter, EditorSceneImporter); +class EditorOBJImporter : public EditorSceneFormatImporter { + GDCLASS(EditorOBJImporter, EditorSceneFormatImporter); public: virtual uint32_t get_import_flags() const override; diff --git a/editor/import/resource_importer_scene.cpp b/editor/import/resource_importer_scene.cpp index 1780aed4cb..c393d7f5fc 100644 --- a/editor/import/resource_importer_scene.cpp +++ b/editor/import/resource_importer_scene.cpp @@ -52,7 +52,7 @@ #include "scene/resources/surface_tool.h" #include "scene/resources/world_boundary_shape_3d.h" -uint32_t EditorSceneImporter::get_import_flags() const { +uint32_t EditorSceneFormatImporter::get_import_flags() const { int ret; if (GDVIRTUAL_CALL(_get_import_flags, ret)) { return ret; @@ -61,7 +61,7 @@ uint32_t EditorSceneImporter::get_import_flags() const { ERR_FAIL_V(0); } -void EditorSceneImporter::get_extensions(List<String> *r_extensions) const { +void EditorSceneFormatImporter::get_extensions(List<String> *r_extensions) const { Vector<String> arr; if (GDVIRTUAL_CALL(_get_extensions, arr)) { for (int i = 0; i < arr.size(); i++) { @@ -73,7 +73,7 @@ void EditorSceneImporter::get_extensions(List<String> *r_extensions) const { ERR_FAIL(); } -Node *EditorSceneImporter::import_scene(const String &p_path, uint32_t p_flags, int p_bake_fps, List<String> *r_missing_deps, Error *r_err) { +Node *EditorSceneFormatImporter::import_scene(const String &p_path, uint32_t p_flags, int p_bake_fps, List<String> *r_missing_deps, Error *r_err) { Object *ret; if (GDVIRTUAL_CALL(_import_scene, p_path, p_flags, p_bake_fps, ret)) { return Object::cast_to<Node>(ret); @@ -82,7 +82,7 @@ Node *EditorSceneImporter::import_scene(const String &p_path, uint32_t p_flags, ERR_FAIL_V(nullptr); } -Ref<Animation> EditorSceneImporter::import_animation(const String &p_path, uint32_t p_flags, int p_bake_fps) { +Ref<Animation> EditorSceneFormatImporter::import_animation(const String &p_path, uint32_t p_flags, int p_bake_fps) { Ref<Animation> ret; if (GDVIRTUAL_CALL(_import_animation, p_path, p_flags, p_bake_fps, ret)) { return ret; @@ -94,17 +94,17 @@ Ref<Animation> EditorSceneImporter::import_animation(const String &p_path, uint3 //for documenters, these functions are useful when an importer calls an external conversion helper (like, fbx2gltf), //and you want to load the resulting file -Node *EditorSceneImporter::import_scene_from_other_importer(const String &p_path, uint32_t p_flags, int p_bake_fps) { +Node *EditorSceneFormatImporter::import_scene_from_other_importer(const String &p_path, uint32_t p_flags, int p_bake_fps) { return ResourceImporterScene::get_singleton()->import_scene_from_other_importer(this, p_path, p_flags, p_bake_fps); } -Ref<Animation> EditorSceneImporter::import_animation_from_other_importer(const String &p_path, uint32_t p_flags, int p_bake_fps) { +Ref<Animation> EditorSceneFormatImporter::import_animation_from_other_importer(const String &p_path, uint32_t p_flags, int p_bake_fps) { return ResourceImporterScene::get_singleton()->import_animation_from_other_importer(this, p_path, p_flags, p_bake_fps); } -void EditorSceneImporter::_bind_methods() { - ClassDB::bind_method(D_METHOD("import_scene_from_other_importer", "path", "flags", "bake_fps"), &EditorSceneImporter::import_scene_from_other_importer); - ClassDB::bind_method(D_METHOD("import_animation_from_other_importer", "path", "flags", "bake_fps"), &EditorSceneImporter::import_animation_from_other_importer); +void EditorSceneFormatImporter::_bind_methods() { + ClassDB::bind_method(D_METHOD("import_scene_from_other_importer", "path", "flags", "bake_fps"), &EditorSceneFormatImporter::import_scene_from_other_importer); + ClassDB::bind_method(D_METHOD("import_animation_from_other_importer", "path", "flags", "bake_fps"), &EditorSceneFormatImporter::import_animation_from_other_importer); GDVIRTUAL_BIND(_get_import_flags); GDVIRTUAL_BIND(_get_extensions); @@ -144,6 +144,105 @@ void EditorScenePostImport::init(const String &p_source_file) { EditorScenePostImport::EditorScenePostImport() { } +/////////////////////////////////////////////////////// + +Variant EditorScenePostImportPlugin::get_option_value(const StringName &p_name) const { + ERR_FAIL_COND_V_MSG(current_options == nullptr && current_options_dict == nullptr, Variant(), "get_option_value called from a function where option values are not available."); + ERR_FAIL_COND_V_MSG(current_options && !current_options->has(p_name), Variant(), "get_option_value called with unexisting option argument: " + String(p_name)); + ERR_FAIL_COND_V_MSG(current_options_dict && !current_options_dict->has(p_name), Variant(), "get_option_value called with unexisting option argument: " + String(p_name)); + if (current_options) { + (*current_options)[p_name]; + } + if (current_options_dict) { + (*current_options_dict)[p_name]; + } + return Variant(); +} +void EditorScenePostImportPlugin::add_import_option(const String &p_name, Variant p_default_value) { + ERR_FAIL_COND_MSG(current_option_list == nullptr, "add_import_option() can only be called from get_import_options()"); + add_import_option_advanced(p_default_value.get_type(), p_name, p_default_value); +} +void EditorScenePostImportPlugin::add_import_option_advanced(Variant::Type p_type, const String &p_name, Variant p_default_value, PropertyHint p_hint, const String &p_hint_string, int p_usage_flags) { + ERR_FAIL_COND_MSG(current_option_list == nullptr, "add_import_option_advanced() can only be called from get_import_options()"); + current_option_list->push_back(ResourceImporter::ImportOption(PropertyInfo(p_type, p_name, p_hint, p_hint_string, p_usage_flags), p_default_value)); +} + +void EditorScenePostImportPlugin::get_internal_import_options(InternalImportCategory p_category, List<ResourceImporter::ImportOption> *r_options) { + current_option_list = r_options; + 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<StringName, Variant> &p_options) const { + current_options = &p_options; + Variant ret; + GDVIRTUAL_CALL(_get_internal_option_visibility, p_category, p_option, ret); + current_options = nullptr; + return ret; +} +Variant EditorScenePostImportPlugin::get_internal_option_update_view_required(InternalImportCategory p_category, const String &p_option, const Map<StringName, Variant> &p_options) const { + current_options = &p_options; + Variant ret; + GDVIRTUAL_CALL(_get_internal_option_update_view_required, p_category, p_option, ret); + current_options = nullptr; + return ret; +} + +void EditorScenePostImportPlugin::internal_process(InternalImportCategory p_category, Node *p_base_scene, Node *p_node, RES p_resource, const Dictionary &p_options) { + current_options_dict = &p_options; + GDVIRTUAL_CALL(_internal_process, p_category, p_base_scene, p_node, p_resource); + current_options_dict = nullptr; +} + +void EditorScenePostImportPlugin::get_import_options(List<ResourceImporter::ImportOption> *r_options) { + current_option_list = r_options; + GDVIRTUAL_CALL(_get_import_options); + current_option_list = nullptr; +} +Variant EditorScenePostImportPlugin::get_option_visibility(const String &p_option, const Map<StringName, Variant> &p_options) const { + current_options = &p_options; + Variant ret; + GDVIRTUAL_CALL(_get_option_visibility, p_option, ret); + current_options = nullptr; + return ret; +} + +void EditorScenePostImportPlugin::pre_process(Node *p_scene, const Map<StringName, Variant> &p_options) { + current_options = &p_options; + GDVIRTUAL_CALL(_pre_process, p_scene); + current_options = nullptr; +} +void EditorScenePostImportPlugin::post_process(Node *p_scene, const Map<StringName, Variant> &p_options) { + current_options = &p_options; + GDVIRTUAL_CALL(_post_process, p_scene); + current_options = nullptr; +} + +void EditorScenePostImportPlugin::_bind_methods() { + ClassDB::bind_method(D_METHOD("get_option_value", "name"), &EditorScenePostImportPlugin::get_option_value); + + ClassDB::bind_method(D_METHOD("add_import_option", "name", "value"), &EditorScenePostImportPlugin::add_import_option); + 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_update_view_required, "category", "option"); + GDVIRTUAL_BIND(_internal_process, "category", "base_node", "node", "resource"); + GDVIRTUAL_BIND(_get_import_options); + GDVIRTUAL_BIND(_get_option_visibility, "option"); + GDVIRTUAL_BIND(_pre_process, "scene"); + GDVIRTUAL_BIND(_post_process, "scene"); + + BIND_ENUM_CONSTANT(INTERNAL_IMPORT_CATEGORY_NODE); + BIND_ENUM_CONSTANT(INTERNAL_IMPORT_CATEGORY_MESH_3D_NODE); + BIND_ENUM_CONSTANT(INTERNAL_IMPORT_CATEGORY_MESH); + BIND_ENUM_CONSTANT(INTERNAL_IMPORT_CATEGORY_MATERIAL); + BIND_ENUM_CONSTANT(INTERNAL_IMPORT_CATEGORY_ANIMATION); + BIND_ENUM_CONSTANT(INTERNAL_IMPORT_CATEGORY_ANIMATION_NODE); + BIND_ENUM_CONSTANT(INTERNAL_IMPORT_CATEGORY_MAX); +} + +///////////////////////////////////////////////////////// + String ResourceImporterScene::get_importer_name() const { return "scene"; } @@ -153,7 +252,7 @@ String ResourceImporterScene::get_visible_name() const { } void ResourceImporterScene::get_recognized_extensions(List<String> *p_extensions) const { - for (Set<Ref<EditorSceneImporter>>::Element *E = importers.front(); E; E = E->next()) { + for (Set<Ref<EditorSceneFormatImporter>>::Element *E = importers.front(); E; E = E->next()) { E->get()->get_extensions(p_extensions); } } @@ -181,6 +280,13 @@ bool ResourceImporterScene::get_option_visibility(const String &p_option, const return false; } + for (int i = 0; i < post_importer_plugins.size(); i++) { + Variant ret = post_importer_plugins.write[i]->get_option_visibility(p_option, p_options); + if (ret.get_type() == Variant::BOOL) { + return ret; + } + } + return true; } @@ -547,6 +653,26 @@ Node *ResourceImporterScene::_post_fix_node(Node *p_node, Node *p_root, Map<Ref< return nullptr; } + { + ObjectID node_id = p_node->get_instance_id(); + for (int i = 0; i < post_importer_plugins.size(); i++) { + post_importer_plugins.write[i]->internal_process(EditorScenePostImportPlugin::INTERNAL_IMPORT_CATEGORY_NODE, p_root, p_node, RES(), node_settings); + if (ObjectDB::get_instance(node_id) == nullptr) { //may have been erased, so do not continue + break; + } + } + } + + if (Object::cast_to<ImporterMeshInstance3D>(p_node)) { + ObjectID node_id = p_node->get_instance_id(); + for (int i = 0; i < post_importer_plugins.size(); i++) { + post_importer_plugins.write[i]->internal_process(EditorScenePostImportPlugin::INTERNAL_IMPORT_CATEGORY_MESH_3D_NODE, p_root, p_node, RES(), node_settings); + if (ObjectDB::get_instance(node_id) == nullptr) { //may have been erased, so do not continue + break; + } + } + } + if (Object::cast_to<ImporterMeshInstance3D>(p_node)) { ImporterMeshInstance3D *mi = Object::cast_to<ImporterMeshInstance3D>(p_node); @@ -566,6 +692,11 @@ Node *ResourceImporterScene::_post_fix_node(Node *p_node, Node *p_root, Map<Ref< if (mat_id != String() && p_material_data.has(mat_id)) { Dictionary matdata = p_material_data[mat_id]; + + for (int j = 0; j < post_importer_plugins.size(); j++) { + post_importer_plugins.write[j]->internal_process(EditorScenePostImportPlugin::INTERNAL_IMPORT_CATEGORY_MATERIAL, p_root, p_node, mat, matdata); + } + if (matdata.has("use_external/enabled") && bool(matdata["use_external/enabled"]) && matdata.has("use_external/path")) { String path = matdata["use_external/path"]; Ref<Material> external_mat = ResourceLoader::load(path); @@ -715,6 +846,10 @@ Node *ResourceImporterScene::_post_fix_node(Node *p_node, Node *p_root, Map<Ref< } } + for (int i = 0; i < post_importer_plugins.size(); i++) { + post_importer_plugins.write[i]->internal_process(EditorScenePostImportPlugin::INTERNAL_IMPORT_CATEGORY_ANIMATION_NODE, p_root, p_node, RES(), node_settings); + } + bool use_optimizer = node_settings["optimizer/enabled"]; float anim_optimizer_linerr = node_settings["optimizer/max_linear_error"]; float anim_optimizer_angerr = node_settings["optimizer/max_angular_error"]; @@ -790,6 +925,31 @@ Node *ResourceImporterScene::_post_fix_node(Node *p_node, Node *p_root, Map<Ref< _optimize_track_usage(ap, import_tracks_mode); } } + + if (post_importer_plugins.size()) { + List<StringName> anims; + ap->get_animation_list(&anims); + for (const StringName &name : anims) { + if (p_animation_data.has(name)) { + Ref<Animation> anim = ap->get_animation(name); + Dictionary anim_settings = p_animation_data[name]; + { + //fill with default values + List<ImportOption> iopts; + get_internal_import_options(INTERNAL_IMPORT_CATEGORY_ANIMATION, &iopts); + for (const ImportOption &F : iopts) { + if (!anim_settings.has(F.option.name)) { + anim_settings[F.option.name] = F.default_value; + } + } + } + + for (int i = 0; i < post_importer_plugins.size(); i++) { + post_importer_plugins.write[i]->internal_process(EditorScenePostImportPlugin::INTERNAL_IMPORT_CATEGORY_ANIMATION, p_root, p_node, anim, node_settings); + } + } + } + } } return p_node; @@ -1052,6 +1212,10 @@ void ResourceImporterScene::get_internal_import_options(InternalImportCategory p default: { } } + + for (int i = 0; i < post_importer_plugins.size(); i++) { + post_importer_plugins.write[i]->get_internal_import_options(EditorScenePostImportPlugin::InternalImportCategory(p_category), r_options); + } } bool ResourceImporterScene::get_internal_option_visibility(InternalImportCategory p_category, const String &p_option, const Map<StringName, Variant> &p_options) const { @@ -1154,6 +1318,13 @@ 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); + if (ret.get_type() == Variant::BOOL) { + return ret; + } + } + return true; } @@ -1181,6 +1352,14 @@ bool ResourceImporterScene::get_internal_option_update_view_required(InternalImp default: { } } + + for (int i = 0; i < post_importer_plugins.size(); i++) { + Variant ret = post_importer_plugins.write[i]->get_internal_option_update_view_required(EditorScenePostImportPlugin::InternalImportCategory(p_category), p_option, p_options); + if (ret.get_type() == Variant::BOOL) { + return ret; + } + } + return false; } @@ -1212,6 +1391,10 @@ void ResourceImporterScene::get_import_options(List<ImportOption> *r_options, in 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_NOEDITOR), Dictionary())); + + for (int i = 0; i < post_importer_plugins.size(); i++) { + post_importer_plugins.write[i]->get_import_options(r_options); + } } void ResourceImporterScene::_replace_owner(Node *p_node, Node *p_scene, Node *p_new_owner) { @@ -1225,11 +1408,11 @@ void ResourceImporterScene::_replace_owner(Node *p_node, Node *p_scene, Node *p_ } } -Node *ResourceImporterScene::import_scene_from_other_importer(EditorSceneImporter *p_exception, const String &p_path, uint32_t p_flags, int p_bake_fps) { - Ref<EditorSceneImporter> importer; +Node *ResourceImporterScene::import_scene_from_other_importer(EditorSceneFormatImporter *p_exception, const String &p_path, uint32_t p_flags, int p_bake_fps) { + Ref<EditorSceneFormatImporter> importer; String ext = p_path.get_extension().to_lower(); - for (Set<Ref<EditorSceneImporter>>::Element *E = importers.front(); E; E = E->next()) { + for (Set<Ref<EditorSceneFormatImporter>>::Element *E = importers.front(); E; E = E->next()) { if (E->get().ptr() == p_exception) { continue; } @@ -1255,11 +1438,11 @@ Node *ResourceImporterScene::import_scene_from_other_importer(EditorSceneImporte return importer->import_scene(p_path, p_flags, p_bake_fps, &missing, &err); } -Ref<Animation> ResourceImporterScene::import_animation_from_other_importer(EditorSceneImporter *p_exception, const String &p_path, uint32_t p_flags, int p_bake_fps) { - Ref<EditorSceneImporter> importer; +Ref<Animation> ResourceImporterScene::import_animation_from_other_importer(EditorSceneFormatImporter *p_exception, const String &p_path, uint32_t p_flags, int p_bake_fps) { + Ref<EditorSceneFormatImporter> importer; String ext = p_path.get_extension().to_lower(); - for (Set<Ref<EditorSceneImporter>>::Element *E = importers.front(); E; E = E->next()) { + for (Set<Ref<EditorSceneFormatImporter>>::Element *E = importers.front(); E; E = E->next()) { if (E->get().ptr() == p_exception) { continue; } @@ -1356,6 +1539,10 @@ void ResourceImporterScene::_generate_meshes(Node *p_node, const Dictionary &p_m save_to_file = ""; } } + + for (int i = 0; i < post_importer_plugins.size(); i++) { + post_importer_plugins.write[i]->internal_process(EditorScenePostImportPlugin::INTERNAL_IMPORT_CATEGORY_MESH, nullptr, src_mesh_node, src_mesh_node->get_mesh(), mesh_settings); + } } if (generate_lods) { @@ -1592,13 +1779,13 @@ void ResourceImporterScene::_optimize_track_usage(AnimationPlayer *p_player, Ani } Node *ResourceImporterScene::pre_import(const String &p_source_file) { - Ref<EditorSceneImporter> importer; + Ref<EditorSceneFormatImporter> importer; String ext = p_source_file.get_extension().to_lower(); EditorProgress progress("pre-import", TTR("Pre-Import Scene"), 0); progress.step(TTR("Importing Scene..."), 0); - for (Set<Ref<EditorSceneImporter>>::Element *E = importers.front(); E; E = E->next()) { + for (Set<Ref<EditorSceneFormatImporter>>::Element *E = importers.front(); E; E = E->next()) { List<String> extensions; E->get()->get_extensions(&extensions); @@ -1617,7 +1804,7 @@ Node *ResourceImporterScene::pre_import(const String &p_source_file) { ERR_FAIL_COND_V(!importer.is_valid(), nullptr); Error err = OK; - Node *scene = importer->import_scene(p_source_file, EditorSceneImporter::IMPORT_ANIMATION | EditorSceneImporter::IMPORT_GENERATE_TANGENT_ARRAYS, 15, nullptr, &err); + Node *scene = importer->import_scene(p_source_file, EditorSceneFormatImporter::IMPORT_ANIMATION | EditorSceneFormatImporter::IMPORT_GENERATE_TANGENT_ARRAYS, 15, nullptr, &err); if (!scene || err != OK) { return nullptr; } @@ -1632,13 +1819,13 @@ Node *ResourceImporterScene::pre_import(const String &p_source_file) { Error ResourceImporterScene::import(const String &p_source_file, const String &p_save_path, const Map<StringName, Variant> &p_options, List<String> *r_platform_variants, List<String> *r_gen_files, Variant *r_metadata) { const String &src_path = p_source_file; - Ref<EditorSceneImporter> importer; + Ref<EditorSceneFormatImporter> importer; String ext = src_path.get_extension().to_lower(); EditorProgress progress("import", TTR("Import Scene"), 104); progress.step(TTR("Importing Scene..."), 0); - for (Set<Ref<EditorSceneImporter>>::Element *E = importers.front(); E; E = E->next()) { + for (Set<Ref<EditorSceneFormatImporter>>::Element *E = importers.front(); E; E = E->next()) { List<String> extensions; E->get()->get_extensions(&extensions); @@ -1661,16 +1848,16 @@ Error ResourceImporterScene::import(const String &p_source_file, const String &p int import_flags = 0; if (bool(p_options["animation/import"])) { - import_flags |= EditorSceneImporter::IMPORT_ANIMATION; + import_flags |= EditorSceneFormatImporter::IMPORT_ANIMATION; } if (bool(p_options["skins/use_named_skins"])) { - import_flags |= EditorSceneImporter::IMPORT_USE_NAMED_SKIN_BINDS; + import_flags |= EditorSceneFormatImporter::IMPORT_USE_NAMED_SKIN_BINDS; } bool ensure_tangents = p_options["meshes/ensure_tangents"]; if (ensure_tangents) { - import_flags |= EditorSceneImporter::IMPORT_GENERATE_TANGENT_ARRAYS; + import_flags |= EditorSceneFormatImporter::IMPORT_GENERATE_TANGENT_ARRAYS; } Error err = OK; @@ -1701,6 +1888,11 @@ Error ResourceImporterScene::import(const String &p_source_file, const String &p Map<Ref<ImporterMesh>, Vector<Ref<Shape3D>>> collision_map; _pre_fix_node(scene, scene, collision_map); + + for (int i = 0; i < post_importer_plugins.size(); i++) { + post_importer_plugins.write[i]->pre_process(scene, p_options); + } + _post_fix_node(scene, scene, collision_map, scanned_meshes, node_data, material_data, animation_data, fps); String root_type = p_options["nodes/root_type"]; @@ -1804,6 +1996,10 @@ Error ResourceImporterScene::import(const String &p_source_file, const String &p } } + for (int i = 0; i < post_importer_plugins.size(); i++) { + post_importer_plugins.write[i]->post_process(scene, p_options); + } + progress.step(TTR("Saving..."), 104); Ref<PackedScene> packer = memnew(PackedScene); @@ -1835,15 +2031,15 @@ ResourceImporterScene::ResourceImporterScene() { /////////////////////////////////////// -uint32_t EditorSceneImporterESCN::get_import_flags() const { +uint32_t EditorSceneFormatImporterESCN::get_import_flags() const { return IMPORT_SCENE; } -void EditorSceneImporterESCN::get_extensions(List<String> *r_extensions) const { +void EditorSceneFormatImporterESCN::get_extensions(List<String> *r_extensions) const { r_extensions->push_back("escn"); } -Node *EditorSceneImporterESCN::import_scene(const String &p_path, uint32_t p_flags, int p_bake_fps, List<String> *r_missing_deps, Error *r_err) { +Node *EditorSceneFormatImporterESCN::import_scene(const String &p_path, uint32_t p_flags, int p_bake_fps, List<String> *r_missing_deps, Error *r_err) { Error error; Ref<PackedScene> 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 + "'."); @@ -1854,6 +2050,6 @@ Node *EditorSceneImporterESCN::import_scene(const String &p_path, uint32_t p_fla return scene; } -Ref<Animation> EditorSceneImporterESCN::import_animation(const String &p_path, uint32_t p_flags, int p_bake_fps) { +Ref<Animation> EditorSceneFormatImporterESCN::import_animation(const String &p_path, uint32_t p_flags, int p_bake_fps) { ERR_FAIL_V(Ref<Animation>()); } diff --git a/editor/import/resource_importer_scene.h b/editor/import/resource_importer_scene.h index a612de940a..fab602b8ff 100644 --- a/editor/import/resource_importer_scene.h +++ b/editor/import/resource_importer_scene.h @@ -42,8 +42,8 @@ class Material; class AnimationPlayer; class ImporterMesh; -class EditorSceneImporter : public RefCounted { - GDCLASS(EditorSceneImporter, RefCounted); +class EditorSceneFormatImporter : public RefCounted { + GDCLASS(EditorSceneFormatImporter, RefCounted); protected: static void _bind_methods(); @@ -70,7 +70,7 @@ public: virtual Node *import_scene(const String &p_path, uint32_t p_flags, int p_bake_fps, List<String> *r_missing_deps, Error *r_err = nullptr); virtual Ref<Animation> import_animation(const String &p_path, uint32_t p_flags, int p_bake_fps); - EditorSceneImporter() {} + EditorSceneFormatImporter() {} }; class EditorScenePostImport : public RefCounted { @@ -90,10 +90,64 @@ public: EditorScenePostImport(); }; +class EditorScenePostImportPlugin : public RefCounted { + GDCLASS(EditorScenePostImportPlugin, RefCounted); + +public: + enum InternalImportCategory { + INTERNAL_IMPORT_CATEGORY_NODE, + INTERNAL_IMPORT_CATEGORY_MESH_3D_NODE, + INTERNAL_IMPORT_CATEGORY_MESH, + INTERNAL_IMPORT_CATEGORY_MATERIAL, + INTERNAL_IMPORT_CATEGORY_ANIMATION, + INTERNAL_IMPORT_CATEGORY_ANIMATION_NODE, + INTERNAL_IMPORT_CATEGORY_MAX + }; + +private: + mutable const Map<StringName, Variant> *current_options = nullptr; + mutable const Dictionary *current_options_dict = nullptr; + List<ResourceImporter::ImportOption> *current_option_list = nullptr; + InternalImportCategory current_category = INTERNAL_IMPORT_CATEGORY_MAX; + +protected: + GDVIRTUAL1(_get_internal_import_options, int) + GDVIRTUAL2RC(Variant, _get_internal_option_visibility, int, String) + GDVIRTUAL2RC(Variant, _get_internal_option_update_view_required, int, String) + GDVIRTUAL4(_internal_process, int, Node *, Node *, RES) + GDVIRTUAL0(_get_import_options) + GDVIRTUAL1RC(Variant, _get_option_visibility, String) + GDVIRTUAL1(_pre_process, Node *) + GDVIRTUAL1(_post_process, Node *) + + static void _bind_methods(); + +public: + Variant get_option_value(const StringName &p_name) const; + void add_import_option(const String &p_name, Variant p_default_value); + 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<ResourceImporter::ImportOption> *r_options); + virtual Variant get_internal_option_visibility(InternalImportCategory p_category, const String &p_option, const Map<StringName, Variant> &p_options) const; + virtual Variant get_internal_option_update_view_required(InternalImportCategory p_category, const String &p_option, const Map<StringName, Variant> &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(List<ResourceImporter::ImportOption> *r_options); + virtual Variant get_option_visibility(const String &p_option, const Map<StringName, Variant> &p_options) const; + + virtual void pre_process(Node *p_scene, const Map<StringName, Variant> &p_options); + virtual void post_process(Node *p_scene, const Map<StringName, Variant> &p_options); + + EditorScenePostImportPlugin() {} +}; + +VARIANT_ENUM_CAST(EditorScenePostImportPlugin::InternalImportCategory) + class ResourceImporterScene : public ResourceImporter { GDCLASS(ResourceImporterScene, ResourceImporter); - Set<Ref<EditorSceneImporter>> importers; + Set<Ref<EditorSceneFormatImporter>> importers; static ResourceImporterScene *singleton; @@ -158,13 +212,18 @@ class ResourceImporterScene : public ResourceImporter { void _optimize_track_usage(AnimationPlayer *p_player, AnimationImportTracks *p_track_actions); + mutable Vector<Ref<EditorScenePostImportPlugin>> post_importer_plugins; + public: static ResourceImporterScene *get_singleton() { return singleton; } - const Set<Ref<EditorSceneImporter>> &get_importers() const { return importers; } + void add_post_importer_plugin(const Ref<EditorScenePostImportPlugin> &p_plugin) { post_importer_plugins.push_back(p_plugin); } + void remove_post_importer_plugin(const Ref<EditorScenePostImportPlugin> &p_plugin) { post_importer_plugins.erase(p_plugin); } - void add_importer(Ref<EditorSceneImporter> p_importer) { importers.insert(p_importer); } - void remove_importer(Ref<EditorSceneImporter> p_importer) { importers.erase(p_importer); } + const Set<Ref<EditorSceneFormatImporter>> &get_importers() const { return importers; } + + void add_importer(Ref<EditorSceneFormatImporter> p_importer) { importers.insert(p_importer); } + void remove_importer(Ref<EditorSceneFormatImporter> p_importer) { importers.erase(p_importer); } virtual String get_importer_name() const override; virtual String get_visible_name() const override; @@ -177,13 +236,13 @@ public: virtual String get_preset_name(int p_idx) const override; enum InternalImportCategory { - INTERNAL_IMPORT_CATEGORY_NODE, - INTERNAL_IMPORT_CATEGORY_MESH_3D_NODE, - INTERNAL_IMPORT_CATEGORY_MESH, - INTERNAL_IMPORT_CATEGORY_MATERIAL, - INTERNAL_IMPORT_CATEGORY_ANIMATION, - INTERNAL_IMPORT_CATEGORY_ANIMATION_NODE, - INTERNAL_IMPORT_CATEGORY_MAX + INTERNAL_IMPORT_CATEGORY_NODE = EditorScenePostImportPlugin::INTERNAL_IMPORT_CATEGORY_NODE, + INTERNAL_IMPORT_CATEGORY_MESH_3D_NODE = EditorScenePostImportPlugin::INTERNAL_IMPORT_CATEGORY_MESH_3D_NODE, + INTERNAL_IMPORT_CATEGORY_MESH = EditorScenePostImportPlugin::INTERNAL_IMPORT_CATEGORY_MESH, + INTERNAL_IMPORT_CATEGORY_MATERIAL = EditorScenePostImportPlugin::INTERNAL_IMPORT_CATEGORY_MATERIAL, + INTERNAL_IMPORT_CATEGORY_ANIMATION = EditorScenePostImportPlugin::INTERNAL_IMPORT_CATEGORY_ANIMATION, + INTERNAL_IMPORT_CATEGORY_ANIMATION_NODE = EditorScenePostImportPlugin::INTERNAL_IMPORT_CATEGORY_ANIMATION_NODE, + INTERNAL_IMPORT_CATEGORY_MAX = EditorScenePostImportPlugin::INTERNAL_IMPORT_CATEGORY_MAX }; void get_internal_import_options(InternalImportCategory p_category, List<ImportOption> *r_options) const; @@ -205,8 +264,8 @@ public: Node *pre_import(const String &p_source_file); virtual Error import(const String &p_source_file, const String &p_save_path, const Map<StringName, Variant> &p_options, List<String> *r_platform_variants, List<String> *r_gen_files = nullptr, Variant *r_metadata = nullptr) override; - Node *import_scene_from_other_importer(EditorSceneImporter *p_exception, const String &p_path, uint32_t p_flags, int p_bake_fps); - Ref<Animation> import_animation_from_other_importer(EditorSceneImporter *p_exception, const String &p_path, uint32_t p_flags, int p_bake_fps); + Node *import_scene_from_other_importer(EditorSceneFormatImporter *p_exception, const String &p_path, uint32_t p_flags, int p_bake_fps); + Ref<Animation> import_animation_from_other_importer(EditorSceneFormatImporter *p_exception, const String &p_path, uint32_t p_flags, int p_bake_fps); virtual bool has_advanced_options() const override; virtual void show_advanced_options(const String &p_path) override; @@ -222,8 +281,8 @@ public: static Transform3D get_collision_shapes_transform(const M &p_options); }; -class EditorSceneImporterESCN : public EditorSceneImporter { - GDCLASS(EditorSceneImporterESCN, EditorSceneImporter); +class EditorSceneFormatImporterESCN : public EditorSceneFormatImporter { + GDCLASS(EditorSceneFormatImporterESCN, EditorSceneFormatImporter); public: virtual uint32_t get_import_flags() const override; |