Prechádzať zdrojové kódy

Merge pull request #56956 from rburing/fix_import_hints_breaking_animations_3.x

Rémi Verschelde 3 rokov pred
rodič
commit
45b8cc4854

+ 56 - 18
editor/import/resource_importer_scene.cpp

@@ -289,16 +289,17 @@ static void _gen_shape_list(const Ref<Mesh> &mesh, List<Ref<Shape>> &r_shape_lis
 	}
 }
 
-Node *ResourceImporterScene::_fix_node(Node *p_node, Node *p_root, Map<Ref<Mesh>, List<Ref<Shape>>> &collision_map, LightBakeMode p_light_bake_mode) {
-	// children first
+Node *ResourceImporterScene::_fix_node(Node *p_node, Node *p_root, Map<Ref<Mesh>, List<Ref<Shape>>> &collision_map, LightBakeMode p_light_bake_mode, List<Pair<NodePath, Node *>> &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<Ref<Mesh>
 	}
 
 	if (Object::cast_to<AnimationPlayer>(p_node)) {
-		//remove animations referencing non-importable nodes
 		AnimationPlayer *ap = Object::cast_to<AnimationPlayer>(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<StringName> anims;
 		ap->get_animation_list(&anims);
 		for (List<StringName>::Element *E = anims.front(); E; E = E->next()) {
 			Ref<Animation> 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<Ref<Mesh>
 					}
 				}
 			}
+
+			// 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<StringName> 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<Pair<NodePath, Node *>>::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<Ref<Mesh>
 		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<MeshInstance>(p_node);
 		if (mi) {
 			Ref<Mesh> mesh = mi->get_mesh();
 
 			if (mesh.is_valid()) {
 				List<Ref<Shape>> 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<Ref<Mesh>
 					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<Ref<Mesh>
 		} 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<Spatial>(sb)->set_transform(Object::cast_to<Spatial>(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<Ref<Mesh>
 		}
 	}
 
+	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<Ref<Mesh>, List<Ref<Shape>>> collision_map;
-
-	scene = _fix_node(scene, scene, collision_map, LightBakeMode(light_bake_mode));
+	List<Pair<NodePath, Node *>> 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);

+ 1 - 1
editor/import/resource_importer_scene.h

@@ -147,7 +147,7 @@ public:
 
 	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<Animation>, Ref<Animation>> &p_animations, Map<Ref<Material>, Ref<Material>> &p_materials, Map<Ref<ArrayMesh>, Ref<ArrayMesh>> &p_meshes);
 
-	Node *_fix_node(Node *p_node, Node *p_root, Map<Ref<Mesh>, List<Ref<Shape>>> &collision_map, LightBakeMode p_light_bake_mode);
+	Node *_fix_node(Node *p_node, Node *p_root, Map<Ref<Mesh>, List<Ref<Shape>>> &collision_map, LightBakeMode p_light_bake_mode, List<Pair<NodePath, Node *>> &r_node_renames);
 
 	void _create_clips(Node *scene, const Array &p_clips, bool p_bake_all);
 	void _filter_anim_tracks(Ref<Animation> anim, Set<String> &keep);