Skip to content

Commit 35683de

Browse files
committed
Merge pull request #79796 from KoBeWi/hack_and_slash
Add a way to force history for undoredo
2 parents 95110dd + 57e0465 commit 35683de

5 files changed

Lines changed: 33 additions & 2 deletions

File tree

doc/classes/EditorUndoRedoManager.xml

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,13 @@
8888
The way undo operation are ordered in actions is dictated by [param backward_undo_ops]. When [param backward_undo_ops] is [code]false[/code] undo option are ordered in the same order they were added. Which means the first operation to be added will be the first to be undone.
8989
</description>
9090
</method>
91+
<method name="force_fixed_history">
92+
<return type="void" />
93+
<description>
94+
Forces the next operation (e.g. [method add_do_method]) to use the action's history rather than guessing it from the object. This is sometimes needed when a history can't be correctly determined, like for a nested resource that doesn't have a path yet.
95+
This method should only be used when absolutely necessary, otherwise it might cause invalid history state. For most of complex cases, the [code]custom_context[/code] parameter of [method create_action] is sufficient.
96+
</description>
97+
</method>
9198
<method name="get_history_undo_redo" qualifiers="const">
9299
<return type="UndoRedo" />
93100
<param index="0" name="id" type="int" />

editor/editor_undo_redo_manager.cpp

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -104,8 +104,13 @@ int EditorUndoRedoManager::get_history_id_for_object(Object *p_object) const {
104104
}
105105

106106
EditorUndoRedoManager::History &EditorUndoRedoManager::get_history_for_object(Object *p_object) {
107-
int history_id = get_history_id_for_object(p_object);
108-
ERR_FAIL_COND_V_MSG(pending_action.history_id != INVALID_HISTORY && history_id != pending_action.history_id, get_or_create_history(pending_action.history_id), vformat("UndoRedo history mismatch: expected %d, got %d.", pending_action.history_id, history_id));
107+
int history_id;
108+
if (!forced_history) {
109+
history_id = get_history_id_for_object(p_object);
110+
ERR_FAIL_COND_V_MSG(pending_action.history_id != INVALID_HISTORY && history_id != pending_action.history_id, get_or_create_history(pending_action.history_id), vformat("UndoRedo history mismatch: expected %d, got %d.", pending_action.history_id, history_id));
111+
} else {
112+
history_id = pending_action.history_id;
113+
}
109114

110115
History &history = get_or_create_history(history_id);
111116
if (pending_action.history_id == INVALID_HISTORY) {
@@ -116,6 +121,11 @@ EditorUndoRedoManager::History &EditorUndoRedoManager::get_history_for_object(Ob
116121
return history;
117122
}
118123

124+
void EditorUndoRedoManager::force_fixed_history() {
125+
ERR_FAIL_COND_MSG(pending_action.history_id == INVALID_HISTORY, "The current action has no valid history assigned.");
126+
forced_history = true;
127+
}
128+
119129
void EditorUndoRedoManager::create_action_for_history(const String &p_name, int p_history_id, UndoRedo::MergeMode p_mode, bool p_backward_undo_ops) {
120130
if (pending_action.history_id != INVALID_HISTORY) {
121131
// Nested action.
@@ -236,6 +246,7 @@ void EditorUndoRedoManager::commit_action(bool p_execute) {
236246
return; // Empty action, do nothing.
237247
}
238248

249+
forced_history = false;
239250
is_committing = true;
240251

241252
History &history = get_or_create_history(pending_action.history_id);
@@ -469,6 +480,7 @@ void EditorUndoRedoManager::_bind_methods() {
469480
ClassDB::bind_method(D_METHOD("create_action", "name", "merge_mode", "custom_context", "backward_undo_ops"), &EditorUndoRedoManager::create_action, DEFVAL(UndoRedo::MERGE_DISABLE), DEFVAL((Object *)nullptr), DEFVAL(false));
470481
ClassDB::bind_method(D_METHOD("commit_action", "execute"), &EditorUndoRedoManager::commit_action, DEFVAL(true));
471482
ClassDB::bind_method(D_METHOD("is_committing_action"), &EditorUndoRedoManager::is_committing_action);
483+
ClassDB::bind_method(D_METHOD("force_fixed_history"), &EditorUndoRedoManager::force_fixed_history);
472484

473485
{
474486
MethodInfo mi;

editor/editor_undo_redo_manager.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,7 @@ class EditorUndoRedoManager : public Object {
6767
HashMap<int, History> history_map;
6868
Action pending_action;
6969

70+
bool forced_history = false;
7071
bool is_committing = false;
7172

7273
History *_get_newest_undo();
@@ -79,6 +80,7 @@ class EditorUndoRedoManager : public Object {
7980
UndoRedo *get_history_undo_redo(int p_idx) const;
8081
int get_history_id_for_object(Object *p_object) const;
8182
History &get_history_for_object(Object *p_object);
83+
void force_fixed_history();
8284

8385
void create_action_for_history(const String &p_name, int p_history_id, UndoRedo::MergeMode p_mode = UndoRedo::MERGE_DISABLE, bool p_backward_undo_ops = false);
8486
void create_action(const String &p_name = "", UndoRedo::MergeMode p_mode = UndoRedo::MERGE_DISABLE, Object *p_custom_context = nullptr, bool p_backward_undo_ops = false);

editor/plugins/sprite_frames_editor_plugin.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1056,21 +1056,25 @@ void SpriteFramesEditor::_rename_node_animation(EditorUndoRedoManager *undo_redo
10561056
for (Node *E : nodes) {
10571057
String current_name = E->call("get_animation");
10581058
if (current_name == p_filter) {
1059+
undo_redo->force_fixed_history(); // Fixes corner-case when editing SpriteFrames stored as separate file.
10591060
undo_redo->add_undo_method(E, "set_animation", p_new_animation);
10601061
}
10611062
String autoplay_name = E->call("get_autoplay");
10621063
if (autoplay_name == p_filter) {
1064+
undo_redo->force_fixed_history();
10631065
undo_redo->add_undo_method(E, "set_autoplay", p_new_autoplay);
10641066
}
10651067
}
10661068
} else {
10671069
for (Node *E : nodes) {
10681070
String current_name = E->call("get_animation");
10691071
if (current_name == p_filter) {
1072+
undo_redo->force_fixed_history();
10701073
undo_redo->add_do_method(E, "set_animation", p_new_animation);
10711074
}
10721075
String autoplay_name = E->call("get_autoplay");
10731076
if (autoplay_name == p_filter) {
1077+
undo_redo->force_fixed_history();
10741078
undo_redo->add_do_method(E, "set_autoplay", p_new_autoplay);
10751079
}
10761080
}

editor/plugins/visual_shader_editor_plugin.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3649,12 +3649,15 @@ void VisualShaderEditor::_add_node(int p_idx, const Vector<Variant> &p_ops, cons
36493649

36503650
if (output_port_type == VisualShaderNode::PORT_TYPE_SAMPLER) {
36513651
if (is_texture2d) {
3652+
undo_redo->force_fixed_history(); // vsnode is freshly created and has no path, so history can't be correctly determined.
36523653
undo_redo->add_do_method(vsnode.ptr(), "set_source", VisualShaderNodeTexture::SOURCE_PORT);
36533654
}
36543655
if (is_texture3d || is_texture2d_array) {
3656+
undo_redo->force_fixed_history();
36553657
undo_redo->add_do_method(vsnode.ptr(), "set_source", VisualShaderNodeSample3D::SOURCE_PORT);
36563658
}
36573659
if (is_cubemap) {
3660+
undo_redo->force_fixed_history();
36583661
undo_redo->add_do_method(vsnode.ptr(), "set_source", VisualShaderNodeCubemap::SOURCE_PORT);
36593662
}
36603663
}
@@ -3754,16 +3757,19 @@ void VisualShaderEditor::_add_node(int p_idx, const Vector<Variant> &p_ops, cons
37543757
//post-initialization
37553758

37563759
if (is_texture2d || is_texture3d || is_curve || is_curve_xyz) {
3760+
undo_redo->force_fixed_history();
37573761
undo_redo->add_do_method(vsnode.ptr(), "set_texture", ResourceLoader::load(p_resource_path));
37583762
return;
37593763
}
37603764

37613765
if (is_cubemap) {
3766+
undo_redo->force_fixed_history();
37623767
undo_redo->add_do_method(vsnode.ptr(), "set_cube_map", ResourceLoader::load(p_resource_path));
37633768
return;
37643769
}
37653770

37663771
if (is_texture2d_array) {
3772+
undo_redo->force_fixed_history();
37673773
undo_redo->add_do_method(vsnode.ptr(), "set_texture_array", ResourceLoader::load(p_resource_path));
37683774
}
37693775
}

0 commit comments

Comments
 (0)