Add an import setting use_legacy_names.

During the development of 3.3, internationalization features were added to allow arbitrary bone and node names.
However, doing so will break all references and existing animation clips for projects upgraded from 3.2
This adds an import setting, enabled by default, but disabled for newly generated .import files which restores the old behavior.
This commit is contained in:
Lyuma 2021-04-20 21:06:00 -07:00
parent 2335da5af2
commit d92a172879
5 changed files with 79 additions and 15 deletions

View file

@ -1754,6 +1754,7 @@ void EditorFileSystem::_reimport_file(const String &p_file) {
} else {
late_added_files.insert(p_file); //imported files do not call update_file(), but just in case..
params["nodes/use_legacy_names"] = false;
}
if (importer_name == "keep") {

View file

@ -35,6 +35,7 @@
#include "core/math/math_defs.h"
#include "core/os/file_access.h"
#include "core/os/os.h"
#include "modules/regex/regex.h"
#include "scene/3d/bone_attachment.h"
#include "scene/3d/camera.h"
#include "scene/3d/mesh_instance.h"
@ -155,9 +156,29 @@ static Transform _arr_to_xform(const Array &p_array) {
return xform;
}
String EditorSceneImporterGLTF::_sanitize_scene_name(GLTFState &state, const String &p_name) {
if (state.use_legacy_names) {
RegEx regex("([^a-zA-Z0-9_ -]+)");
String s_name = regex.sub(p_name, "", true);
return s_name;
} else {
return p_name.validate_node_name();
}
}
String EditorSceneImporterGLTF::_legacy_validate_node_name(const String &p_name) {
String invalid_character = ". : @ / \"";
String name = p_name;
Vector<String> chars = invalid_character.split(" ");
for (int i = 0; i < chars.size(); i++) {
name = name.replace(chars[i], "");
}
return name;
}
String EditorSceneImporterGLTF::_gen_unique_name(GLTFState &state, const String &p_name) {
const String s_name = p_name.validate_node_name();
const String s_name = _sanitize_scene_name(state, p_name);
String name;
int index = 1;
@ -165,7 +186,10 @@ String EditorSceneImporterGLTF::_gen_unique_name(GLTFState &state, const String
name = s_name;
if (index > 1) {
name += " " + itos(index);
if (state.use_legacy_names) {
name += " ";
}
name += itos(index);
}
if (!state.unique_names.has(name)) {
break;
@ -212,19 +236,37 @@ String EditorSceneImporterGLTF::_gen_unique_animation_name(GLTFState &state, con
return name;
}
String EditorSceneImporterGLTF::_sanitize_bone_name(const String &p_name) {
String name = p_name;
name = name.replace(":", "_");
name = name.replace("/", "_");
return name;
String EditorSceneImporterGLTF::_sanitize_bone_name(GLTFState &state, const String &p_name) {
if (state.use_legacy_names) {
String name = p_name.camelcase_to_underscore(true);
RegEx pattern_del("([^a-zA-Z0-9_ ])+");
name = pattern_del.sub(name, "", true);
RegEx pattern_nospace(" +");
name = pattern_nospace.sub(name, "_", true);
RegEx pattern_multiple("_+");
name = pattern_multiple.sub(name, "_", true);
RegEx pattern_padded("0+(\\d+)");
name = pattern_padded.sub(name, "$1", true);
return name;
} else {
String name = p_name;
name = name.replace(":", "_");
name = name.replace("/", "_");
if (name.empty()) {
name = "bone";
}
return name;
}
}
String EditorSceneImporterGLTF::_gen_unique_bone_name(GLTFState &state, const GLTFSkeletonIndex skel_i, const String &p_name) {
String s_name = _sanitize_bone_name(p_name);
if (s_name.empty()) {
s_name = "bone";
}
String s_name = _sanitize_bone_name(state, p_name);
String name;
int index = 1;
while (true) {
@ -2487,7 +2529,11 @@ Error EditorSceneImporterGLTF::_parse_animations(GLTFState &state) {
if (name.begins_with("loop") || name.ends_with("loop") || name.begins_with("cycle") || name.ends_with("cycle")) {
animation.loop = true;
}
animation.name = _gen_unique_animation_name(state, name);
if (state.use_legacy_names) {
animation.name = _sanitize_scene_name(state, name);
} else {
animation.name = _gen_unique_animation_name(state, name);
}
}
for (int j = 0; j < channels.size(); j++) {
@ -2795,7 +2841,11 @@ void EditorSceneImporterGLTF::_generate_scene_node(GLTFState &state, Node *scene
scene_parent->add_child(current_node);
current_node->set_owner(scene_root);
current_node->set_transform(gltf_node->xform);
current_node->set_name(gltf_node->name);
if (state.use_legacy_names) {
current_node->set_name(_legacy_validate_node_name(gltf_node->name));
} else {
current_node->set_name(gltf_node->name);
}
}
state.scene_nodes.insert(node_index, current_node);
@ -3147,7 +3197,11 @@ Spatial *EditorSceneImporterGLTF::_generate_scene(GLTFState &state, const int p_
Spatial *root = memnew(Spatial);
// scene_name is already unique
root->set_name(state.scene_name);
if (state.use_legacy_names) {
root->set_name(_legacy_validate_node_name(state.scene_name));
} else {
root->set_name(state.scene_name);
}
for (int i = 0; i < state.root_nodes.size(); ++i) {
_generate_scene_node(state, root, root, state.root_nodes[i]);
@ -3201,6 +3255,7 @@ Node *EditorSceneImporterGLTF::import_scene(const String &p_path, uint32_t p_fla
state.major_version = version.get_slice(".", 0).to_int();
state.minor_version = version.get_slice(".", 1).to_int();
state.use_named_skin_binds = p_flags & IMPORT_USE_NAMED_SKIN_BINDS;
state.use_legacy_names = p_flags & IMPORT_USE_LEGACY_NAMES;
/* STEP 0 PARSE SCENE */
Error err = _parse_scenes(state);

View file

@ -322,6 +322,7 @@ class EditorSceneImporterGLTF : public EditorSceneImporter {
Vector<uint8_t> glb_data;
bool use_named_skin_binds;
bool use_legacy_names;
Vector<GLTFNode *> nodes;
Vector<Vector<uint8_t> > buffers;
@ -359,12 +360,14 @@ class EditorSceneImporterGLTF : public EditorSceneImporter {
}
};
String _sanitize_scene_name(GLTFState &state, const String &p_name);
String _legacy_validate_node_name(const String &p_name);
String _gen_unique_name(GLTFState &state, const String &p_name);
String _sanitize_animation_name(const String &p_name);
String _gen_unique_animation_name(GLTFState &state, const String &p_name);
String _sanitize_bone_name(const String &p_name);
String _sanitize_bone_name(GLTFState &state, const String &p_name);
String _gen_unique_bone_name(GLTFState &state, const GLTFSkeletonIndex skel_i, const String &p_name);
Ref<Texture> _get_texture(GLTFState &state, const GLTFTextureIndex p_texture);

View file

@ -1158,6 +1158,7 @@ void ResourceImporterScene::get_import_options(List<ImportOption> *r_options, in
r_options->push_back(ImportOption(PropertyInfo(Variant::REAL, "nodes/root_scale", PROPERTY_HINT_RANGE, "0.001,1000,0.001"), 1.0));
r_options->push_back(ImportOption(PropertyInfo(Variant::STRING, "nodes/custom_script", PROPERTY_HINT_FILE, script_ext_hint), ""));
r_options->push_back(ImportOption(PropertyInfo(Variant::INT, "nodes/storage", PROPERTY_HINT_ENUM, "Single Scene,Instanced Sub-Scenes"), scenes_out ? 1 : 0));
r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL, "nodes/use_legacy_names"), true));
r_options->push_back(ImportOption(PropertyInfo(Variant::INT, "materials/location", PROPERTY_HINT_ENUM, "Node,Mesh"), (meshes_out || materials_out) ? 1 : 0));
r_options->push_back(ImportOption(PropertyInfo(Variant::INT, "materials/storage", PROPERTY_HINT_ENUM, "Built-In,Files (.material),Files (.tres)", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_UPDATE_ALL_IF_MODIFIED), materials_out ? 1 : 0));
r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL, "materials/keep_on_reimport"), materials_out));
@ -1312,6 +1313,9 @@ Error ResourceImporterScene::import(const String &p_source_file, const String &p
if (bool(p_options["skins/use_named_skins"]))
import_flags |= EditorSceneImporter::IMPORT_USE_NAMED_SKIN_BINDS;
if (bool(p_options["nodes/use_legacy_names"]))
import_flags |= EditorSceneImporter::IMPORT_USE_LEGACY_NAMES;
Error err = OK;
List<String> missing_deps; // for now, not much will be done with this
Node *scene = importer->import_scene(src_path, import_flags, fps, &missing_deps, &err);

View file

@ -60,6 +60,7 @@ public:
IMPORT_MATERIALS_IN_INSTANCES = 1024,
IMPORT_USE_COMPRESSION = 2048,
IMPORT_USE_NAMED_SKIN_BINDS = 4096,
IMPORT_USE_LEGACY_NAMES = 8192,
};