summaryrefslogtreecommitdiffstats
path: root/core/object/undo_redo.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'core/object/undo_redo.cpp')
-rw-r--r--core/object/undo_redo.cpp73
1 files changed, 46 insertions, 27 deletions
diff --git a/core/object/undo_redo.cpp b/core/object/undo_redo.cpp
index b0f9501985..3c1d4ef95e 100644
--- a/core/object/undo_redo.cpp
+++ b/core/object/undo_redo.cpp
@@ -71,9 +71,7 @@ bool UndoRedo::_redo(bool p_execute) {
}
current_action++;
- if (p_execute) {
- _process_operation_list(actions.write[current_action].do_ops.front());
- }
+ _process_operation_list(actions.write[current_action].do_ops.front(), p_execute);
version++;
emit_signal(SNAME("version_changed"));
@@ -136,17 +134,22 @@ void UndoRedo::add_do_method(const Callable &p_callable) {
ERR_FAIL_COND(action_level <= 0);
ERR_FAIL_COND((current_action + 1) >= actions.size());
- Object *object = p_callable.get_object();
- ERR_FAIL_NULL(object);
+ ObjectID object_id = p_callable.get_object_id();
+ Object *object = ObjectDB::get_instance(object_id);
+ ERR_FAIL_COND(object_id.is_valid() && object == nullptr);
Operation do_op;
do_op.callable = p_callable;
- do_op.object = p_callable.get_object_id();
+ do_op.object = object_id;
if (Object::cast_to<RefCounted>(object)) {
do_op.ref = Ref<RefCounted>(Object::cast_to<RefCounted>(object));
}
do_op.type = Operation::TYPE_METHOD;
do_op.name = p_callable.get_method();
+ if (do_op.name == StringName()) {
+ // There's no `get_method()` for custom callables, so use `operator String()` instead.
+ do_op.name = static_cast<String>(p_callable);
+ }
actions.write[current_action + 1].do_ops.push_back(do_op);
}
@@ -161,18 +164,23 @@ void UndoRedo::add_undo_method(const Callable &p_callable) {
return;
}
- Object *object = p_callable.get_object();
- ERR_FAIL_NULL(object);
+ ObjectID object_id = p_callable.get_object_id();
+ Object *object = ObjectDB::get_instance(object_id);
+ ERR_FAIL_COND(object_id.is_valid() && object == nullptr);
Operation undo_op;
undo_op.callable = p_callable;
- undo_op.object = p_callable.get_object_id();
+ undo_op.object = object_id;
if (Object::cast_to<RefCounted>(object)) {
undo_op.ref = Ref<RefCounted>(Object::cast_to<RefCounted>(object));
}
undo_op.type = Operation::TYPE_METHOD;
undo_op.force_keep_in_merge_ends = force_keep_in_merge_ends;
undo_op.name = p_callable.get_method();
+ if (undo_op.name == StringName()) {
+ // There's no `get_method()` for custom callables, so use `operator String()` instead.
+ undo_op.name = static_cast<String>(p_callable);
+ }
actions.write[current_action + 1].undo_ops.push_back(undo_op);
}
@@ -293,6 +301,8 @@ void UndoRedo::commit_action(bool p_execute) {
return; //still nested
}
+ bool add_message = !merging;
+
if (merging) {
version--;
merging = false;
@@ -306,12 +316,12 @@ void UndoRedo::commit_action(bool p_execute) {
_redo(p_execute); // perform action
committing--;
- if (callback && actions.size() > 0) {
+ if (add_message && callback && actions.size() > 0) {
callback(callback_ud, actions[actions.size() - 1].name);
}
}
-void UndoRedo::_process_operation_list(List<Operation>::Element *E) {
+void UndoRedo::_process_operation_list(List<Operation>::Element *E, bool p_execute) {
const int PREALLOCATE_ARGS_COUNT = 16;
LocalVector<const Variant *> args;
@@ -327,18 +337,20 @@ void UndoRedo::_process_operation_list(List<Operation>::Element *E) {
switch (op.type) {
case Operation::TYPE_METHOD: {
- Callable::CallError ce;
- Variant ret;
- op.callable.callp(nullptr, 0, ret, ce);
- if (ce.error != Callable::CallError::CALL_OK) {
- ERR_PRINT("Error calling UndoRedo method operation '" + String(op.name) + "': " + Variant::get_call_error_text(obj, op.name, nullptr, 0, ce));
- }
+ if (p_execute) {
+ Callable::CallError ce;
+ Variant ret;
+ op.callable.callp(nullptr, 0, ret, ce);
+ if (ce.error != Callable::CallError::CALL_OK) {
+ ERR_PRINT("Error calling UndoRedo method operation '" + String(op.name) + "': " + Variant::get_call_error_text(obj, op.name, nullptr, 0, ce));
+ }
#ifdef TOOLS_ENABLED
- Resource *res = Object::cast_to<Resource>(obj);
- if (res) {
- res->set_edited(true);
- }
+ Resource *res = Object::cast_to<Resource>(obj);
+ if (res) {
+ res->set_edited(true);
+ }
#endif
+ }
if (method_callback) {
Vector<Variant> binds;
@@ -363,13 +375,16 @@ void UndoRedo::_process_operation_list(List<Operation>::Element *E) {
}
} break;
case Operation::TYPE_PROPERTY: {
- obj->set(op.name, op.value);
+ if (p_execute) {
+ obj->set(op.name, op.value);
#ifdef TOOLS_ENABLED
- Resource *res = Object::cast_to<Resource>(obj);
- if (res) {
- res->set_edited(true);
- }
+ Resource *res = Object::cast_to<Resource>(obj);
+ if (res) {
+ res->set_edited(true);
+ }
#endif
+ }
+
if (property_callback) {
property_callback(prop_callback_ud, obj, op.name, op.value);
}
@@ -390,7 +405,7 @@ bool UndoRedo::undo() {
if (current_action < 0) {
return false; //nothing to redo
}
- _process_operation_list(actions.write[current_action].undo_ops.front());
+ _process_operation_list(actions.write[current_action].undo_ops.front(), true);
current_action--;
version--;
emit_signal(SNAME("version_changed"));
@@ -450,6 +465,10 @@ bool UndoRedo::has_redo() const {
return (current_action + 1) < actions.size();
}
+bool UndoRedo::is_merging() const {
+ return merging;
+}
+
uint64_t UndoRedo::get_version() const {
return version;
}