Godot Version
4.4
Question
What is the canonical way to implement undo and redo for a newly created node in a scene?
Can I find an example of a proper implementation somewhere?
Details
I can’t figure out what to do with the UndoRedoManager in case of adding and removing nodes.
I’m convinced it requires this method somehow: add_undo_reference – but for the life of me, I cannot parse what the documentation is trying to tell me here.
I’ve tried using queue_free
/ free
on the node in the undo
-method, but redo fails this way.
See also
opened 11:35PM - 19 May 25 UTC
enhancement
help wanted
When you add a shape via the bottom panel, you cannot then undo that action (I'm… guessing the newly added shapes aren't registering with how Godot handles undo/redo operations.)
mrcdk
May 20, 2025, 1:03pm
2
1 Like
Thank you, I think this will work. I will verify it as soon as I’m able.
I think my mistake was to call free()
on the node, in stead of only removing it from the tree, like this subsnippet does:
undo_redo->add_do_method(p_parent, "add_child", child, true);
undo_redo->add_do_method(child, "set_owner", edited_scene);
undo_redo->add_do_reference(child);
undo_redo->add_undo_method(p_parent, "remove_child", child);
Guess I’ll also need to check if I need to replicate the _post_do_create
method as well:
undo_redo->add_do_reference(child);
undo_redo->add_undo_method(EditorNode::get_singleton(), "set_edited_scene", (Object *)nullptr);
}
undo_redo->add_do_method(this, "_post_do_create", child);
undo_redo->commit_action();
return child;
}
void SceneTreeDock::_post_do_create(Node *p_child) {
editor_selection->clear();
editor_selection->add_node(p_child);
_push_item(p_child);
// Make editor more comfortable, so some controls don't appear super shrunk.
Control *control = Object::cast_to<Control>(p_child);
if (control) {
Size2 ms = control->get_minimum_size();
if (ms.width < 4) {
ms.width = 40;
Just wondering, will the reference to this orphaned node then be cleaned up by the undo_redo_manager later?
mrcdk
May 20, 2025, 2:45pm
4
That’s what the add_do_reference()
does when erasing the history as far as I can tell from the code.
This add it to a list of references to delete:
And here deletes them when the action can’t be re-done:
1 Like
Youre right!
I’m sorry, I must be turning blind.. it’s right here in the snippet your shared:
new_name = adjust_name_casing(new_name);
}
child->set_name(new_name);
EditorUndoRedoManager *undo_redo = EditorUndoRedoManager::get_singleton();
undo_redo->create_action_for_history(TTR("Create Node"), editor_data->get_current_edited_scene_history_id());
if (edited_scene) {
undo_redo->add_do_method(p_parent, "add_child", child, true);
undo_redo->add_do_method(child, "set_owner", edited_scene);
undo_redo->add_do_reference(child);
undo_redo->add_undo_method(p_parent, "remove_child", child);
EditorDebuggerNode *ed = EditorDebuggerNode::get_singleton();
undo_redo->add_do_method(ed, "live_debug_create_node", edited_scene->get_path_to(p_parent), child->get_class(), new_name);
undo_redo->add_undo_method(ed, "live_debug_remove_node", NodePath(String(edited_scene->get_path_to(p_parent)).path_join(new_name)));
} else {
undo_redo->add_do_method(EditorNode::get_singleton(), "set_edited_scene", child);
undo_redo->add_do_method(scene_tree, "update_tree");
undo_redo->add_do_reference(child);
Thank you!
system
Closed
June 19, 2025, 3:11pm
6
This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.