From 742c54d0a708d3f2c505ffafde71449b5dc3d376 Mon Sep 17 00:00:00 2001 From: Ricardo Buring Date: Wed, 19 Jan 2022 16:25:51 +0100 Subject: [PATCH] Fix import hints breaking node paths in animations --- editor/import/resource_importer_scene.cpp | 74 +++++++++++++++++------ editor/import/resource_importer_scene.h | 2 +- 2 files changed, 57 insertions(+), 19 deletions(-) diff --git a/editor/import/resource_importer_scene.cpp b/editor/import/resource_importer_scene.cpp index da34244dd705..39f0f2fc42ef 100644 --- a/editor/import/resource_importer_scene.cpp +++ b/editor/import/resource_importer_scene.cpp @@ -289,16 +289,17 @@ static void _gen_shape_list(const Ref &mesh, List> &r_shape_lis } } -Node *ResourceImporterScene::_fix_node(Node *p_node, Node *p_root, Map, List>> &collision_map, LightBakeMode p_light_bake_mode) { - // children first +Node *ResourceImporterScene::_fix_node(Node *p_node, Node *p_root, Map, List>> &collision_map, LightBakeMode p_light_bake_mode, List> &r_node_renames) { + // Children first. for (int i = 0; i < p_node->get_child_count(); i++) { - Node *r = _fix_node(p_node->get_child(i), p_root, collision_map, p_light_bake_mode); + Node *r = _fix_node(p_node->get_child(i), p_root, collision_map, p_light_bake_mode, r_node_renames); if (!r) { - i--; //was erased + i--; // Was erased. } } String name = p_node->get_name(); + NodePath original_path = p_root->get_path_to(p_node); // Used to detect renames due to import hints. bool isroot = p_node == p_root; @@ -337,14 +338,21 @@ Node *ResourceImporterScene::_fix_node(Node *p_node, Node *p_root, Map } if (Object::cast_to(p_node)) { - //remove animations referencing non-importable nodes AnimationPlayer *ap = Object::cast_to(p_node); + // Node paths in animation tracks are relative to the following path (this is used to fix node paths below). + Node *ap_root = ap->get_node(ap->get_root()); + NodePath path_prefix = p_root->get_path_to(ap_root); + + bool nodes_were_renamed = r_node_renames.size() != 0; + List anims; ap->get_animation_list(&anims); for (List::Element *E = anims.front(); E; E = E->next()) { Ref anim = ap->get_animation(E->get()); ERR_CONTINUE(anim.is_null()); + + // Remove animation tracks referencing non-importable nodes for (int i = 0; i < anim->get_track_count(); i++) { NodePath path = anim->track_get_path(i); @@ -357,6 +365,27 @@ Node *ResourceImporterScene::_fix_node(Node *p_node, Node *p_root, Map } } } + + // Fix node paths in animations, in case nodes were renamed earlier due to import hints. + if (nodes_were_renamed) { + for (int i = 0; i < anim->get_track_count(); i++) { + NodePath path = anim->track_get_path(i); + // Convert track path to absolute node path without subnames (some manual work because we are not in the scene tree). + Vector absolute_path_names = path_prefix.get_names(); + absolute_path_names.append_array(path.get_names()); + NodePath absolute_path(absolute_path_names, false); + absolute_path.simplify(); + // Fix paths to renamed nodes. + for (const List>::Element *F = r_node_renames.front(); F; F = F->next()) { + if (F->get().first == absolute_path) { + NodePath new_path(ap_root->get_path_to(F->get().second).get_names(), path.get_subnames(), false); + print_verbose(vformat("Fix: Correcting node path in animation track: %s should be %s", path, new_path)); + anim->track_set_path(i, new_path); + break; // Only one match is possible. + } + } + } + } } } @@ -364,13 +393,22 @@ Node *ResourceImporterScene::_fix_node(Node *p_node, Node *p_root, Map if (isroot) { return p_node; } + + String fixed_name; + if (_teststr(name, "colonly")) { + fixed_name = _fixstr(name, "colonly"); + } else if (_teststr(name, "convcolonly")) { + fixed_name = _fixstr(name, "convcolonly"); + } + + ERR_FAIL_COND_V(fixed_name == String(), nullptr); + MeshInstance *mi = Object::cast_to(p_node); if (mi) { Ref mesh = mi->get_mesh(); if (mesh.is_valid()) { List> shapes; - String fixed_name; if (collision_map.has(mesh)) { shapes = collision_map[mesh]; } else if (_teststr(name, "colonly")) { @@ -381,14 +419,6 @@ Node *ResourceImporterScene::_fix_node(Node *p_node, Node *p_root, Map collision_map[mesh] = shapes; } - if (_teststr(name, "colonly")) { - fixed_name = _fixstr(name, "colonly"); - } else if (_teststr(name, "convcolonly")) { - fixed_name = _fixstr(name, "convcolonly"); - } - - ERR_FAIL_COND_V(fixed_name == String(), nullptr); - if (shapes.size()) { StaticBody *col = memnew(StaticBody); col->set_transform(mi->get_transform()); @@ -404,11 +434,11 @@ Node *ResourceImporterScene::_fix_node(Node *p_node, Node *p_root, Map } else if (p_node->has_meta("empty_draw_type")) { String empty_draw_type = String(p_node->get_meta("empty_draw_type")); StaticBody *sb = memnew(StaticBody); - sb->set_name(_fixstr(name, "colonly")); + sb->set_name(fixed_name); Object::cast_to(sb)->set_transform(Object::cast_to(p_node)->get_transform()); p_node->replace_by(sb); memdelete(p_node); - p_node = nullptr; + p_node = sb; CollisionShape *colshape = memnew(CollisionShape); if (empty_draw_type == "CUBE") { BoxShape *boxShape = memnew(BoxShape); @@ -594,6 +624,14 @@ Node *ResourceImporterScene::_fix_node(Node *p_node, Node *p_root, Map } } + if (p_node) { + NodePath new_path = p_root->get_path_to(p_node); + if (new_path != original_path) { + print_verbose(vformat("Fix: Renamed %s to %s", original_path, new_path)); + r_node_renames.push_back({ original_path, p_node }); + } + } + return p_node; } @@ -1297,8 +1335,8 @@ Error ResourceImporterScene::import(const String &p_source_file, const String &p int light_bake_mode = p_options["meshes/light_baking"]; Map, List>> collision_map; - - scene = _fix_node(scene, scene, collision_map, LightBakeMode(light_bake_mode)); + List> node_renames; + scene = _fix_node(scene, scene, collision_map, LightBakeMode(light_bake_mode), node_renames); if (use_optimizer) { _optimize_animations(scene, anim_optimizer_linerr, anim_optimizer_angerr, anim_optimizer_maxang); diff --git a/editor/import/resource_importer_scene.h b/editor/import/resource_importer_scene.h index 2ee60db1bdff..c354fca05458 100644 --- a/editor/import/resource_importer_scene.h +++ b/editor/import/resource_importer_scene.h @@ -147,7 +147,7 @@ class ResourceImporterScene : public ResourceImporter { void _make_external_resources(Node *p_node, const String &p_base_path, bool p_make_animations, bool p_animations_as_text, bool p_keep_animations, bool p_make_materials, bool p_materials_as_text, bool p_keep_materials, bool p_make_meshes, bool p_meshes_as_text, Map, Ref> &p_animations, Map, Ref> &p_materials, Map, Ref> &p_meshes); - Node *_fix_node(Node *p_node, Node *p_root, Map, List>> &collision_map, LightBakeMode p_light_bake_mode); + Node *_fix_node(Node *p_node, Node *p_root, Map, List>> &collision_map, LightBakeMode p_light_bake_mode, List> &r_node_renames); void _create_clips(Node *scene, const Array &p_clips, bool p_bake_all); void _filter_anim_tracks(Ref anim, Set &keep);