mirror of
https://github.com/godotengine/godot
synced 2024-09-05 14:08:33 +00:00
add backward_undo_ops as property for action
This commit is contained in:
parent
ae896bbd85
commit
81aa5ad999
|
@ -80,14 +80,14 @@ bool UndoRedo::_redo(bool p_execute) {
|
|||
return true;
|
||||
}
|
||||
|
||||
void UndoRedo::create_action(const String &p_name, MergeMode p_mode) {
|
||||
void UndoRedo::create_action(const String &p_name, MergeMode p_mode, bool p_backward_undo_ops) {
|
||||
uint64_t ticks = OS::get_singleton()->get_ticks_msec();
|
||||
|
||||
if (action_level == 0) {
|
||||
_discard_redo();
|
||||
|
||||
// Check if the merge operation is valid
|
||||
if (p_mode != MERGE_DISABLE && actions.size() && actions[actions.size() - 1].name == p_name && actions[actions.size() - 1].last_tick + 800 > ticks) {
|
||||
if (p_mode != MERGE_DISABLE && actions.size() && actions[actions.size() - 1].name == p_name && actions[actions.size() - 1].backward_undo_ops == p_backward_undo_ops && actions[actions.size() - 1].last_tick + 800 > ticks) {
|
||||
current_action = actions.size() - 2;
|
||||
|
||||
if (p_mode == MERGE_ENDS) {
|
||||
|
@ -108,12 +108,18 @@ void UndoRedo::create_action(const String &p_name, MergeMode p_mode) {
|
|||
|
||||
actions.write[actions.size() - 1].last_tick = ticks;
|
||||
|
||||
// Revert reverse from previous commit.
|
||||
if (actions[actions.size() - 1].backward_undo_ops) {
|
||||
actions.write[actions.size() - 1].undo_ops.reverse();
|
||||
}
|
||||
|
||||
merge_mode = p_mode;
|
||||
merging = true;
|
||||
} else {
|
||||
Action new_action;
|
||||
new_action.name = p_name;
|
||||
new_action.last_tick = ticks;
|
||||
new_action.backward_undo_ops = p_backward_undo_ops;
|
||||
actions.push_back(new_action);
|
||||
|
||||
merge_mode = MERGE_DISABLE;
|
||||
|
@ -292,6 +298,10 @@ void UndoRedo::commit_action(bool p_execute) {
|
|||
merging = false;
|
||||
}
|
||||
|
||||
if (actions[actions.size() - 1].backward_undo_ops) {
|
||||
actions.write[actions.size() - 1].undo_ops.reverse();
|
||||
}
|
||||
|
||||
committing++;
|
||||
_redo(p_execute); // perform action
|
||||
committing--;
|
||||
|
@ -458,7 +468,7 @@ UndoRedo::~UndoRedo() {
|
|||
}
|
||||
|
||||
void UndoRedo::_bind_methods() {
|
||||
ClassDB::bind_method(D_METHOD("create_action", "name", "merge_mode"), &UndoRedo::create_action, DEFVAL(MERGE_DISABLE));
|
||||
ClassDB::bind_method(D_METHOD("create_action", "name", "merge_mode", "backward_undo_ops"), &UndoRedo::create_action, DEFVAL(MERGE_DISABLE), DEFVAL(false));
|
||||
ClassDB::bind_method(D_METHOD("commit_action", "execute"), &UndoRedo::commit_action, DEFVAL(true));
|
||||
ClassDB::bind_method(D_METHOD("is_committing_action"), &UndoRedo::is_committing_action);
|
||||
|
||||
|
|
|
@ -72,7 +72,8 @@ private:
|
|||
String name;
|
||||
List<Operation> do_ops;
|
||||
List<Operation> undo_ops;
|
||||
uint64_t last_tick;
|
||||
uint64_t last_tick = 0;
|
||||
bool backward_undo_ops = false;
|
||||
};
|
||||
|
||||
Vector<Action> actions;
|
||||
|
@ -102,7 +103,7 @@ protected:
|
|||
static void _bind_methods();
|
||||
|
||||
public:
|
||||
void create_action(const String &p_name = "", MergeMode p_mode = MERGE_DISABLE);
|
||||
void create_action(const String &p_name = "", MergeMode p_mode = MERGE_DISABLE, bool p_backward_undo_ops = false);
|
||||
|
||||
void add_do_method(const Callable &p_callable);
|
||||
void add_undo_method(const Callable &p_callable);
|
||||
|
|
|
@ -80,10 +80,12 @@
|
|||
<param index="0" name="name" type="String" />
|
||||
<param index="1" name="merge_mode" type="int" enum="UndoRedo.MergeMode" default="0" />
|
||||
<param index="2" name="custom_context" type="Object" default="null" />
|
||||
<param index="3" name="backward_undo_ops" type="bool" default="false" />
|
||||
<description>
|
||||
Create a new action. After this is called, do all your calls to [method add_do_method], [method add_undo_method], [method add_do_property], and [method add_undo_property], then commit the action with [method commit_action].
|
||||
The way actions are merged is dictated by the [param merge_mode] argument. See [enum UndoRedo.MergeMode] for details.
|
||||
If [param custom_context] object is provided, it will be used for deducing target history (instead of using the first operation).
|
||||
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.
|
||||
</description>
|
||||
</method>
|
||||
<method name="get_history_undo_redo" qualifiers="const">
|
||||
|
|
|
@ -56,9 +56,38 @@
|
|||
}
|
||||
[/csharp]
|
||||
[/codeblocks]
|
||||
[method create_action], [method add_do_method], [method add_undo_method], [method add_do_property], [method add_undo_property], and [method commit_action] should be called one after the other, like in the example. Not doing so could lead to crashes.
|
||||
If you don't need to register a method, you can leave [method add_do_method] and [method add_undo_method] out; the same goes for properties. You can also register more than one method/property in the order they should run.
|
||||
Before calling any of the [code]add_(un)do_*[/code] methods, you need to first call [method create_action]. Afterwards you need to call [method commit_action].
|
||||
If you don't need to register a method, you can leave [method add_do_method] and [method add_undo_method] out; the same goes for properties. You can also register more than one method/property.
|
||||
If you are making an [EditorPlugin] and want to integrate into the editor's undo history, use [EditorUndoRedoManager] instead.
|
||||
If you are registering multiple properties/method which depend on one another, be aware that by default undo operation are called in the same order they have been added. Therefore instead of grouping do operation with their undo operations it is better to group do on one side and undo on the other as shown below.
|
||||
[codeblocks]
|
||||
[gdscript]
|
||||
undo_redo.create_action("Add object")
|
||||
|
||||
# DO
|
||||
undo_redo.add_do_method(_create_object)
|
||||
undo_redo.add_do_method(_add_object_to_singleton)
|
||||
|
||||
# UNDO
|
||||
undo_redo.add_undo_method(_remove_object_from_singleton)
|
||||
undo_redo.add_undo_method(_destroy_that_object)
|
||||
|
||||
undo_redo.commit_action()
|
||||
[/gdscript]
|
||||
[csharp]
|
||||
_undo_redo.CreateAction("Add object");
|
||||
|
||||
// DO
|
||||
_undo_redo.AddDoMethod(new Callable(this, MethodName.CreateObject));
|
||||
_undo_redo.AddDoMethod(new Callable(this, MethodName.AddObjectToSingleton));
|
||||
|
||||
// UNDO
|
||||
_undo_redo.AddUndoMethod(new Callable(this, MethodName.RemoveObjectFromSingleton));
|
||||
_undo_redo.AddUndoMethod(new Callable(this, MethodName.DestroyThatObject));
|
||||
|
||||
_undo_redo.CommitAction();
|
||||
[/csharp]
|
||||
[/codeblocks]
|
||||
</description>
|
||||
<tutorials>
|
||||
</tutorials>
|
||||
|
@ -144,9 +173,11 @@
|
|||
<return type="void" />
|
||||
<param index="0" name="name" type="String" />
|
||||
<param index="1" name="merge_mode" type="int" enum="UndoRedo.MergeMode" default="0" />
|
||||
<param index="2" name="backward_undo_ops" type="bool" default="false" />
|
||||
<description>
|
||||
Create a new action. After this is called, do all your calls to [method add_do_method], [method add_undo_method], [method add_do_property], and [method add_undo_property], then commit the action with [method commit_action].
|
||||
The way actions are merged is dictated by [param merge_mode]. See [enum MergeMode] for details.
|
||||
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.
|
||||
</description>
|
||||
</method>
|
||||
<method name="end_force_keep_in_merge_ends">
|
||||
|
|
|
@ -110,13 +110,13 @@ EditorUndoRedoManager::History &EditorUndoRedoManager::get_history_for_object(Ob
|
|||
History &history = get_or_create_history(history_id);
|
||||
if (pending_action.history_id == INVALID_HISTORY) {
|
||||
pending_action.history_id = history_id;
|
||||
history.undo_redo->create_action(pending_action.action_name, pending_action.merge_mode);
|
||||
history.undo_redo->create_action(pending_action.action_name, pending_action.merge_mode, pending_action.backward_undo_ops);
|
||||
}
|
||||
|
||||
return history;
|
||||
}
|
||||
|
||||
void EditorUndoRedoManager::create_action_for_history(const String &p_name, int p_history_id, UndoRedo::MergeMode p_mode) {
|
||||
void EditorUndoRedoManager::create_action_for_history(const String &p_name, int p_history_id, UndoRedo::MergeMode p_mode, bool p_backward_undo_ops) {
|
||||
if (pending_action.history_id != INVALID_HISTORY) {
|
||||
// Nested action.
|
||||
p_history_id = pending_action.history_id;
|
||||
|
@ -124,17 +124,18 @@ void EditorUndoRedoManager::create_action_for_history(const String &p_name, int
|
|||
pending_action.action_name = p_name;
|
||||
pending_action.timestamp = OS::get_singleton()->get_unix_time();
|
||||
pending_action.merge_mode = p_mode;
|
||||
pending_action.backward_undo_ops = p_backward_undo_ops;
|
||||
}
|
||||
|
||||
if (p_history_id != INVALID_HISTORY) {
|
||||
pending_action.history_id = p_history_id;
|
||||
History &history = get_or_create_history(p_history_id);
|
||||
history.undo_redo->create_action(pending_action.action_name, pending_action.merge_mode);
|
||||
history.undo_redo->create_action(pending_action.action_name, pending_action.merge_mode, pending_action.backward_undo_ops);
|
||||
}
|
||||
}
|
||||
|
||||
void EditorUndoRedoManager::create_action(const String &p_name, UndoRedo::MergeMode p_mode, Object *p_custom_context) {
|
||||
create_action_for_history(p_name, INVALID_HISTORY, p_mode);
|
||||
void EditorUndoRedoManager::create_action(const String &p_name, UndoRedo::MergeMode p_mode, Object *p_custom_context, bool p_backward_undo_ops) {
|
||||
create_action_for_history(p_name, INVALID_HISTORY, p_mode, p_backward_undo_ops);
|
||||
|
||||
if (p_custom_context) {
|
||||
// This assigns history to pending action.
|
||||
|
@ -487,7 +488,7 @@ EditorUndoRedoManager::History *EditorUndoRedoManager::_get_newest_undo() {
|
|||
}
|
||||
|
||||
void EditorUndoRedoManager::_bind_methods() {
|
||||
ClassDB::bind_method(D_METHOD("create_action", "name", "merge_mode", "custom_context"), &EditorUndoRedoManager::create_action, DEFVAL(UndoRedo::MERGE_DISABLE), DEFVAL((Object *)nullptr));
|
||||
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));
|
||||
ClassDB::bind_method(D_METHOD("commit_action", "execute"), &EditorUndoRedoManager::commit_action, DEFVAL(true));
|
||||
ClassDB::bind_method(D_METHOD("is_committing_action"), &EditorUndoRedoManager::is_committing_action);
|
||||
|
||||
|
|
|
@ -52,6 +52,7 @@ public:
|
|||
double timestamp = 0;
|
||||
String action_name;
|
||||
UndoRedo::MergeMode merge_mode = UndoRedo::MERGE_DISABLE;
|
||||
bool backward_undo_ops = false;
|
||||
};
|
||||
|
||||
struct History {
|
||||
|
@ -79,8 +80,8 @@ public:
|
|||
int get_history_id_for_object(Object *p_object) const;
|
||||
History &get_history_for_object(Object *p_object);
|
||||
|
||||
void create_action_for_history(const String &p_name, int p_history_id, UndoRedo::MergeMode p_mode = UndoRedo::MERGE_DISABLE);
|
||||
void create_action(const String &p_name = "", UndoRedo::MergeMode p_mode = UndoRedo::MERGE_DISABLE, Object *p_custom_context = nullptr);
|
||||
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);
|
||||
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);
|
||||
|
||||
void add_do_methodp(Object *p_object, const StringName &p_method, const Variant **p_args, int p_argcount);
|
||||
void add_undo_methodp(Object *p_object, const StringName &p_method, const Variant **p_args, int p_argcount);
|
||||
|
|
Loading…
Reference in a new issue