diff options
Diffstat (limited to 'editor/import')
-rw-r--r-- | editor/import/post_import_plugin_skeleton_renamer.cpp | 144 | ||||
-rw-r--r-- | editor/import/post_import_plugin_skeleton_renamer.h | 46 | ||||
-rw-r--r-- | editor/import/resource_importer_scene.cpp | 77 | ||||
-rw-r--r-- | editor/import/resource_importer_scene.h | 2 | ||||
-rw-r--r-- | editor/import/scene_import_settings.cpp | 11 | ||||
-rw-r--r-- | editor/import/scene_import_settings.h | 1 |
6 files changed, 268 insertions, 13 deletions
diff --git a/editor/import/post_import_plugin_skeleton_renamer.cpp b/editor/import/post_import_plugin_skeleton_renamer.cpp new file mode 100644 index 0000000000..b0c4bc8c30 --- /dev/null +++ b/editor/import/post_import_plugin_skeleton_renamer.cpp @@ -0,0 +1,144 @@ +/*************************************************************************/ +/* post_import_plugin_skeleton_renamer.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#include "post_import_plugin_skeleton_renamer.h" + +#include "editor/import/scene_import_settings.h" +#include "scene/3d/importer_mesh_instance_3d.h" +#include "scene/3d/skeleton_3d.h" +#include "scene/animation/animation_player.h" +#include "scene/resources/bone_map.h" + +void PostImportPluginSkeletonRenamer::get_internal_import_options(InternalImportCategory p_category, List<ResourceImporter::ImportOption> *r_options) { + if (p_category == INTERNAL_IMPORT_CATEGORY_SKELETON_3D_NODE) { + r_options->push_back(ResourceImporter::ImportOption(PropertyInfo(Variant::BOOL, "retarget/bone_renamer/rename_bones"), true)); + } +} + +void PostImportPluginSkeletonRenamer::internal_process(InternalImportCategory p_category, Node *p_base_scene, Node *p_node, Ref<Resource> p_resource, const Dictionary &p_options) { + if (p_category == INTERNAL_IMPORT_CATEGORY_SKELETON_3D_NODE) { + // Prepare objects. + Object *map = p_options["retarget/bone_map"].get_validated_object(); + if (!map || !bool(p_options["retarget/bone_renamer/rename_bones"])) { + return; + } + BoneMap *bone_map = Object::cast_to<BoneMap>(map); + Skeleton3D *skeleton = Object::cast_to<Skeleton3D>(p_node); + + // Rename bones in Skeleton3D. + { + int len = skeleton->get_bone_count(); + for (int i = 0; i < len; i++) { + StringName bn = bone_map->find_profile_bone_name(skeleton->get_bone_name(i)); + if (bn) { + skeleton->set_bone_name(i, bn); + } + } + } + + // Rename bones in Skin. + { + TypedArray<Node> nodes = p_base_scene->find_children("*", "ImporterMeshInstance3D"); + while (nodes.size()) { + ImporterMeshInstance3D *mi = Object::cast_to<ImporterMeshInstance3D>(nodes.pop_back()); + Ref<Skin> skin = mi->get_skin(); + if (skin.is_valid()) { + Node *node = mi->get_node(mi->get_skeleton_path()); + if (node) { + Skeleton3D *mesh_skeleton = Object::cast_to<Skeleton3D>(node); + if (mesh_skeleton && node == skeleton) { + int len = skin->get_bind_count(); + for (int i = 0; i < len; i++) { + StringName bn = bone_map->find_profile_bone_name(skin->get_bind_name(i)); + if (bn) { + skin->set_bind_name(i, bn); + } + } + } + } + } + } + } + + // Rename bones in AnimationPlayer. + { + TypedArray<Node> nodes = p_base_scene->find_children("*", "AnimationPlayer"); + while (nodes.size()) { + AnimationPlayer *ap = Object::cast_to<AnimationPlayer>(nodes.pop_back()); + List<StringName> anims; + ap->get_animation_list(&anims); + for (const StringName &name : anims) { + Ref<Animation> anim = ap->get_animation(name); + int len = anim->get_track_count(); + for (int i = 0; i < len; i++) { + if (anim->track_get_path(i).get_subname_count() != 1 || !(anim->track_get_type(i) == Animation::TYPE_POSITION_3D || anim->track_get_type(i) == Animation::TYPE_ROTATION_3D || anim->track_get_type(i) == Animation::TYPE_SCALE_3D)) { + continue; + } + String track_path = String(anim->track_get_path(i).get_concatenated_names()); + Node *node = (ap->get_node(ap->get_root()))->get_node(NodePath(track_path)); + if (node) { + Skeleton3D *track_skeleton = Object::cast_to<Skeleton3D>(node); + if (track_skeleton && track_skeleton == skeleton) { + StringName bn = bone_map->find_profile_bone_name(anim->track_get_path(i).get_subname(0)); + if (bn) { + anim->track_set_path(i, track_path + ":" + bn); + } + } + } + } + } + } + } + + // Rename bones in all Nodes by calling method. + { + Vector<Variant> vargs; + vargs.push_back(p_base_scene); + vargs.push_back(skeleton); + vargs.push_back(bone_map); + const Variant **argptrs = (const Variant **)alloca(sizeof(const Variant **) * vargs.size()); + const Variant *args = vargs.ptr(); + uint32_t argcount = vargs.size(); + for (uint32_t i = 0; i < argcount; i++) { + argptrs[i] = &args[i]; + } + + TypedArray<Node> nodes = p_base_scene->find_children("*"); + while (nodes.size()) { + Node *nd = Object::cast_to<Node>(nodes.pop_back()); + Callable::CallError ce; + nd->callp("_notify_skeleton_bones_renamed", argptrs, argcount, ce); + } + } + } +} + +PostImportPluginSkeletonRenamer::PostImportPluginSkeletonRenamer() { +} diff --git a/editor/import/post_import_plugin_skeleton_renamer.h b/editor/import/post_import_plugin_skeleton_renamer.h new file mode 100644 index 0000000000..73cbabd1c5 --- /dev/null +++ b/editor/import/post_import_plugin_skeleton_renamer.h @@ -0,0 +1,46 @@ +/*************************************************************************/ +/* post_import_plugin_skeleton_renamer.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#ifndef POST_IMPORT_PLUGIN_SKELETON_RENAMER_H +#define POST_IMPORT_PLUGIN_SKELETON_RENAMER_H + +#include "resource_importer_scene.h" + +class PostImportPluginSkeletonRenamer : public EditorScenePostImportPlugin { + GDCLASS(PostImportPluginSkeletonRenamer, EditorScenePostImportPlugin); + +public: + virtual void get_internal_import_options(InternalImportCategory p_category, List<ResourceImporter::ImportOption> *r_options) override; + virtual void internal_process(InternalImportCategory p_category, Node *p_base_scene, Node *p_node, Ref<Resource> p_resource, const Dictionary &p_options) override; + + PostImportPluginSkeletonRenamer(); +}; + +#endif // POST_IMPORT_PLUGIN_SKELETON_RENAMER_H diff --git a/editor/import/resource_importer_scene.cpp b/editor/import/resource_importer_scene.cpp index 171ef5bf4c..a9c43e573f 100644 --- a/editor/import/resource_importer_scene.cpp +++ b/editor/import/resource_importer_scene.cpp @@ -232,6 +232,7 @@ void EditorScenePostImportPlugin::_bind_methods() { 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_SKELETON_3D_NODE); BIND_ENUM_CONSTANT(INTERNAL_IMPORT_CATEGORY_MAX); } @@ -766,6 +767,27 @@ Node *ResourceImporterScene::_post_fix_node(Node *p_node, Node *p_root, HashMap< } { + //make sure this is unique + node_settings = node_settings.duplicate(true); + //fill node settings for this node with default values + List<ImportOption> iopts; + if (Object::cast_to<ImporterMeshInstance3D>(p_node)) { + get_internal_import_options(INTERNAL_IMPORT_CATEGORY_MESH_3D_NODE, &iopts); + } else if (Object::cast_to<AnimationPlayer>(p_node)) { + get_internal_import_options(INTERNAL_IMPORT_CATEGORY_ANIMATION_NODE, &iopts); + } else if (Object::cast_to<Skeleton3D>(p_node)) { + get_internal_import_options(INTERNAL_IMPORT_CATEGORY_SKELETON_3D_NODE, &iopts); + } else { + get_internal_import_options(INTERNAL_IMPORT_CATEGORY_NODE, &iopts); + } + for (const ImportOption &E : iopts) { + if (!node_settings.has(E.option.name)) { + node_settings[E.option.name] = E.default_value; + } + } + } + + { 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, Ref<Resource>(), node_settings); @@ -785,6 +807,16 @@ Node *ResourceImporterScene::_post_fix_node(Node *p_node, Node *p_root, HashMap< } } + if (Object::cast_to<Skeleton3D>(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_SKELETON_3D_NODE, p_root, p_node, Ref<Resource>(), 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); @@ -799,6 +831,16 @@ Node *ResourceImporterScene::_post_fix_node(Node *p_node, Node *p_root, HashMap< if (!mat_id.is_empty() && p_material_data.has(mat_id)) { Dictionary matdata = p_material_data[mat_id]; + { + //fill node settings for this node with default values + List<ImportOption> iopts; + get_internal_import_options(INTERNAL_IMPORT_CATEGORY_MATERIAL, &iopts); + for (const ImportOption &E : iopts) { + if (!matdata.has(E.option.name)) { + matdata[E.option.name] = E.default_value; + } + } + } 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); @@ -966,19 +1008,6 @@ Node *ResourceImporterScene::_post_fix_node(Node *p_node, Node *p_root, HashMap< if (Object::cast_to<AnimationPlayer>(p_node)) { AnimationPlayer *ap = Object::cast_to<AnimationPlayer>(p_node); - { - //make sure this is unique - node_settings = node_settings.duplicate(true); - //fill node settings for this node with default values - List<ImportOption> iopts; - get_internal_import_options(INTERNAL_IMPORT_CATEGORY_ANIMATION_NODE, &iopts); - for (const ImportOption &E : iopts) { - if (!node_settings.has(E.option.name)) { - node_settings[E.option.name] = E.default_value; - } - } - } - 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, Ref<Resource>(), node_settings); } @@ -1385,6 +1414,10 @@ void ResourceImporterScene::get_internal_import_options(InternalImportCategory p r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL, "slice_" + itos(i + 1) + "/save_to_file/keep_custom_tracks"), false)); } } break; + case INTERNAL_IMPORT_CATEGORY_SKELETON_3D_NODE: { + r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL, "import/skip_import", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_UPDATE_ALL_IF_MODIFIED), false)); + r_options->push_back(ImportOption(PropertyInfo(Variant::OBJECT, "retarget/bone_map", PROPERTY_HINT_RESOURCE_TYPE, "BoneMap", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_UPDATE_ALL_IF_MODIFIED), Variant())); + } break; default: { } } @@ -1499,6 +1532,12 @@ bool ResourceImporterScene::get_internal_option_visibility(InternalImportCategor } } } break; + case INTERNAL_IMPORT_CATEGORY_SKELETON_3D_NODE: { + const bool use_retarget = p_options["retarget/bone_map"].get_validated_object() != nullptr; + if (p_option != "retarget/bone_map" && p_option.begins_with("retarget/")) { + return use_retarget; + } + } break; default: { } } @@ -1534,6 +1573,8 @@ bool ResourceImporterScene::get_internal_option_update_view_required(InternalImp } break; case INTERNAL_IMPORT_CATEGORY_ANIMATION_NODE: { } break; + case INTERNAL_IMPORT_CATEGORY_SKELETON_3D_NODE: { + } break; default: { } } @@ -1622,6 +1663,16 @@ void ResourceImporterScene::_generate_meshes(Node *p_node, const Dictionary &p_m if (!mesh_id.is_empty() && p_mesh_data.has(mesh_id)) { Dictionary mesh_settings = p_mesh_data[mesh_id]; + { + //fill node settings for this node with default values + List<ImportOption> iopts; + get_internal_import_options(INTERNAL_IMPORT_CATEGORY_MESH, &iopts); + for (const ImportOption &E : iopts) { + if (!mesh_settings.has(E.option.name)) { + mesh_settings[E.option.name] = E.default_value; + } + } + } if (mesh_settings.has("generate/shadow_meshes")) { int shadow_meshes = mesh_settings["generate/shadow_meshes"]; diff --git a/editor/import/resource_importer_scene.h b/editor/import/resource_importer_scene.h index 16cf3d651d..c143e86bd4 100644 --- a/editor/import/resource_importer_scene.h +++ b/editor/import/resource_importer_scene.h @@ -106,6 +106,7 @@ public: INTERNAL_IMPORT_CATEGORY_MATERIAL, INTERNAL_IMPORT_CATEGORY_ANIMATION, INTERNAL_IMPORT_CATEGORY_ANIMATION_NODE, + INTERNAL_IMPORT_CATEGORY_SKELETON_3D_NODE, INTERNAL_IMPORT_CATEGORY_MAX }; @@ -259,6 +260,7 @@ public: 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_SKELETON_3D_NODE = EditorScenePostImportPlugin::INTERNAL_IMPORT_CATEGORY_SKELETON_3D_NODE, INTERNAL_IMPORT_CATEGORY_MAX = EditorScenePostImportPlugin::INTERNAL_IMPORT_CATEGORY_MAX }; diff --git a/editor/import/scene_import_settings.cpp b/editor/import/scene_import_settings.cpp index 99d1658405..af145c22b4 100644 --- a/editor/import/scene_import_settings.cpp +++ b/editor/import/scene_import_settings.cpp @@ -339,6 +339,8 @@ void SceneImportSettings::_fill_scene(Node *p_node, TreeItem *p_parent_item) { category = ResourceImporterScene::INTERNAL_IMPORT_CATEGORY_MESH_3D_NODE; } else if (Object::cast_to<AnimationPlayer>(p_node)) { category = ResourceImporterScene::INTERNAL_IMPORT_CATEGORY_ANIMATION_NODE; + } else if (Object::cast_to<Skeleton3D>(p_node)) { + category = ResourceImporterScene::INTERNAL_IMPORT_CATEGORY_SKELETON_3D_NODE; } else { category = ResourceImporterScene::INTERNAL_IMPORT_CATEGORY_NODE; } @@ -617,6 +619,13 @@ SceneImportSettings *SceneImportSettings::get_singleton() { return singleton; } +Node *SceneImportSettings::get_selected_node() { + if (selected_id == "") { + return nullptr; + } + return node_map[selected_id].node; +} + void SceneImportSettings::_select(Tree *p_from, String p_type, String p_id) { selecting = true; scene_import_settings_data->hide_options = false; @@ -657,6 +666,8 @@ void SceneImportSettings::_select(Tree *p_from, String p_type, String p_id) { scene_import_settings_data->hide_options = editing_animation; } else if (Object::cast_to<AnimationPlayer>(nd.node)) { scene_import_settings_data->category = ResourceImporterScene::INTERNAL_IMPORT_CATEGORY_ANIMATION_NODE; + } else if (Object::cast_to<Skeleton3D>(nd.node)) { + scene_import_settings_data->category = ResourceImporterScene::INTERNAL_IMPORT_CATEGORY_SKELETON_3D_NODE; } else { scene_import_settings_data->category = ResourceImporterScene::INTERNAL_IMPORT_CATEGORY_NODE; scene_import_settings_data->hide_options = editing_animation; diff --git a/editor/import/scene_import_settings.h b/editor/import/scene_import_settings.h index 81d13166ab..b5cf82f64b 100644 --- a/editor/import/scene_import_settings.h +++ b/editor/import/scene_import_settings.h @@ -201,6 +201,7 @@ public: void update_view(); void open_settings(const String &p_path, bool p_for_animation = false); static SceneImportSettings *get_singleton(); + Node *get_selected_node(); SceneImportSettings(); ~SceneImportSettings(); }; |