diff options
Diffstat (limited to 'core/object/undo_redo.cpp')
-rw-r--r-- | core/object/undo_redo.cpp | 73 |
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; } |