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.
This commit is contained in:
reduz 2021-10-14 14:34:27 -03:00
parent e53e897b8c
commit b3bf90b3ce
21 changed files with 507 additions and 109 deletions

View file

@ -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() {
}

View file

@ -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

View file

@ -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;

View file

@ -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>());
}

View file

@ -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;