Repository: godotengine/godot
File: editor/scene_tree_dock.cpp (C++)

Code before:

void SceneTreeDock::_delete_confirm(bool p_cut) {
	List<Node *> remove_list = editor_selection->get_selected_node_list();

	if (remove_list.is_empty()) {
		return;
	}

	bool entire_scene = false;

	for (const Node *E : remove_list) {
		if (E == edited_scene) {
			entire_scene = true;
			break;
		}
	}

	EditorNode::get_singleton()->hide_unused_editors(this);

	EditorUndoRedoManager *undo_redo = EditorUndoRedoManager::get_singleton();
	undo_redo->create_action(p_cut ? TTR("Cut Node(s)") : TTR("Remove Node(s)"), UndoRedo::MERGE_DISABLE, remove_list.front()->get());

	if (entire_scene) {
		undo_redo->add_do_method(EditorNode::get_singleton(), "set_edited_scene", (Object *)nullptr);
		undo_redo->add_undo_method(EditorNode::get_singleton(), "set_edited_scene", edited_scene);
		undo_redo->add_undo_method(edited_scene, "set_owner", edited_scene->get_owner());
		undo_redo->add_undo_method(scene_tree, "update_tree");
		undo_redo->add_undo_reference(edited_scene);
	} else {
		for (const Node *E : remove_list) {
			// `move_child` + `get_index` doesn't really work for internal nodes.
			ERR_FAIL_COND_MSG(E->get_internal_mode() != INTERNAL_MODE_DISABLED, "Trying to remove internal node, this is not supported.");
		}
		if (delete_tracks_checkbox->is_pressed() || p_cut) {
			remove_list.sort_custom<Node::Comparator>(); // Sort nodes to keep positions.
			HashMap<Node *, NodePath> path_renames;

			//delete from animation
			for (Node *n : remove_list) {
				if (!n->is_inside_tree() || !n->get_parent()) {
					continue;
				}

				fill_path_renames(n, nullptr, &path_renames);
			}

			perform_node_renames(nullptr, &path_renames);
		}

		//delete for read
		for (Node *n : remove_list) {

Review comment (suggestion):
```suggestion
		// Get the original paths, transforms, and names for undo.
```

Code after:
		node->reparent(p_root);
		node->set_name(original_name);

		for (Node *F : owned) {
			F->set_owner(p_owner);
		}
	}
}

void SceneTreeDock::_reparent_nodes_to_paths_with_transform_and_name(Node *p_root, const Array &p_nodes, const Array &p_paths, const Array &p_transforms, const Array &p_names, Node *p_owner) {
	ERR_FAIL_COND(p_nodes.size() != p_paths.size());
	ERR_FAIL_COND(p_nodes.size() != p_transforms.size());
	ERR_FAIL_COND(p_nodes.size() != p_names.size());

	for (int i = 0; i < p_nodes.size(); i++) {
		Node *node = Object::cast_to<Node>(p_nodes[i]);
		ERR_FAIL_NULL(node);
		const NodePath &np = p_paths[i];
		Node *parent_node = p_root->get_node_or_null(np);
		ERR_FAIL_NULL(parent_node);

		List<Node *> owned;
		node->get_owned_by(p_owner, &owned);
		node->reparent(parent_node);
		node->set_name(p_names[i]);
		Node3D *node_3d = Object::cast_to<Node3D>(node);
		if (node_3d) {
			node_3d->set_transform(p_transforms[i]);
		} else {
			Node2D *node_2d = Object::cast_to<Node2D>(node);
			if (node_2d) {
				node_2d->set_transform(p_transforms[i]);
			}
		}

		for (Node *F : owned) {
			F->set_owner(p_owner);
		}
	}
}

void SceneTreeDock::_toggle_editable_children(Node *p_node) {
	if (!p_node) {
		return;
	}

	EditorUndoRedoManager *undo_redo = EditorUndoRedoManager::get_singleton();

	undo_redo->create_action(TTR("Toggle Editable Children"));

	bool editable = !EditorNode::get_singleton()->get_edited_scene()->is_editable_instance(p_node);