UndoRedo

继承: Object

为实现撤销和重做操作提供高阶接口。

描述

UndoRedo 的原理是在“动作”中注册方法和属性的变化。你可以创建一个动作,然后提供执行(do)和撤销(undo)这个动作需要进行的函数调用和属性更改,然后提交该动作。

动作提交后就会执行所有 do_* 方法。如果使用 undo 方法,那么就会执行 undo_* 方法。如果使用 redo 方法,那么就会再次执行所有 do_* 方法。

以下是添加动作的示例:

GDScriptC#

  1. var undo_redo = UndoRedo.new()
  2. func do_something():
  3. pass # 在此处编写你的代码。
  4. func undo_something():
  5. pass # 在此处编写恢复“do_something()”里所做事情的代码。
  6. func _on_my_button_pressed():
  7. var node = get_node("MyNode2D")
  8. undo_redo.create_action("移动节点")
  9. undo_redo.add_do_method(do_something)
  10. undo_redo.add_undo_method(undo_something)
  11. undo_redo.add_do_property(node, "position", Vector2(100,100))
  12. undo_redo.add_undo_property(node, "position", node.position)
  13. undo_redo.commit_action()
  1. private UndoRedo _undoRedo;
  2. public override void _Ready()
  3. {
  4. _undoRedo = new UndoRedo();
  5. }
  6. public void DoSomething()
  7. {
  8. // 在此处编写你的代码。
  9. }
  10. public void UndoSomething()
  11. {
  12. // 在此处编写恢复“DoSomething()”里所做事情的代码。
  13. }
  14. private void OnMyButtonPressed()
  15. {
  16. var node = GetNode<Node2D>("MyNode2D");
  17. _undoRedo.CreateAction("移动节点");
  18. _undoRedo.AddDoMethod(new Callable(this, MethodName.DoSomething));
  19. _undoRedo.AddUndoMethod(new Callable(this, MethodName.UndoSomething));
  20. _undoRedo.AddDoProperty(node, "position", new Vector2(100, 100));
  21. _undoRedo.AddUndoProperty(node, "position", node.Position);
  22. _undoRedo.CommitAction();
  23. }

调用 add_(un)do_* 方法之前,你需要先调用 create_action。调用之后则需要调用 commit_action

如果你不需要注册方法,则可以将 add_do_methodadd_undo_method 省去;属性同理。你也可以注册多个方法/属性。

如果你要制作 EditorPlugin,希望集成编辑器的撤销历史,请改用 EditorUndoRedoManager

如果你所注册的不同属性/方法之间有相互依赖,请注意默认情况下撤销操作的调用顺序和添加顺序是一致的。因此请不要将 do 操作和 undo 操作写在一起,最好还是和下面一样 do 和 do 一起写,undo 和 undo 一起写。

GDScriptC#

  1. undo_redo.create_action("添加对象")
  2. # DO
  3. undo_redo.add_do_method(_create_object)
  4. undo_redo.add_do_method(_add_object_to_singleton)
  5. # UNDO
  6. undo_redo.add_undo_method(_remove_object_from_singleton)
  7. undo_redo.add_undo_method(_destroy_that_object)
  8. undo_redo.commit_action()
  1. _undo_redo.CreateAction("添加对象");
  2. // DO
  3. _undo_redo.AddDoMethod(new Callable(this, MethodName.CreateObject));
  4. _undo_redo.AddDoMethod(new Callable(this, MethodName.AddObjectToSingleton));
  5. // UNDO
  6. _undo_redo.AddUndoMethod(new Callable(this, MethodName.RemoveObjectFromSingleton));
  7. _undo_redo.AddUndoMethod(new Callable(this, MethodName.DestroyThatObject));
  8. _undo_redo.CommitAction();

属性

int

max_steps

0

方法

void

add_do_method(callable: Callable)

void

add_do_property(object: Object, property: StringName, value: Variant)

void

add_do_reference(object: Object)

void

add_undo_method(callable: Callable)

void

add_undo_property(object: Object, property: StringName, value: Variant)

void

add_undo_reference(object: Object)

void

clear_history(increase_version: bool = true)

void

commit_action(execute: bool = true)

void

create_action(name: String, merge_mode: MergeMode = 0, backward_undo_ops: bool = false)

void

end_force_keep_in_merge_ends()

String

get_action_name(id: int)

int

get_current_action()

String

get_current_action_name() const

int

get_history_count()

int

get_version() const

bool

has_redo() const

bool

has_undo() const

bool

is_committing_action() const

bool

redo()

void

start_force_keep_in_merge_ends()

bool

undo()


信号

version_changed() 🔗

undoredo 被调用时调用。


枚举

enum MergeMode: 🔗

MergeMode MERGE_DISABLE = 0

使“do”/“undo”操作保持在单独的动作中。

MergeMode MERGE_ENDS = 1

如果当前动作与上一个动作的名称相同,则将两者合并。仅保留第一个动作的“undo”操作和最后一个动作的“do”操作。适用于对单个值的连续更改。

MergeMode MERGE_ALL = 2

如果当前动作与上一个动作的名称相同,则将两者合并。


属性说明

int max_steps = 0 🔗

  • void set_max_steps(value: int)

  • int get_max_steps()

撤销/重做历史中能够存储的最大步数。如果存储的步数超出了这个限制,就会将最早的步骤从历史中移除,无法再通过调用 undo 到达。小于等于 0 表示没有限制。


方法说明

void add_do_method(callable: Callable) 🔗

注册 Callable,会在提交动作时调用。


void add_do_property(object: Object, property: StringName, value: Variant) 🔗

注册 property,会在提交动作时将其值更改为 value


void add_do_reference(object: Object) 🔗

注册对象的引用,删除“do”历史时会擦除该引用。适用于“do”动作添加的对象和“undo”动作移除的对象。

删除“do”历史时,如果该对象为 RefCounted,则会解除引用。否则会执行释放。请勿用于资源。

  1. var node = Node2D.new()
  2. undo_redo.create_action("添加节点")
  3. undo_redo.add_do_method(add_child.bind(node))
  4. undo_redo.add_do_reference(node)
  5. undo_redo.add_undo_method(remove_child.bind(node))
  6. undo_redo.commit_action()

void add_undo_method(callable: Callable) 🔗

注册 Callable,会在撤销动作时调用。


void add_undo_property(object: Object, property: StringName, value: Variant) 🔗

注册 property,会在撤销动作时将其值更改为 value


void add_undo_reference(object: Object) 🔗

注册对象的引用,删除“undo”历史时会擦除该引用。适用于“undo”动作添加的对象和“do”动作移除的对象。

删除“undo”历史时,如果该对象为 RefCounted,则会解除引用。否则会执行释放。请勿用于资源。

  1. var node = $Node2D
  2. undo_redo.create_action("移除节点")
  3. undo_redo.add_do_method(remove_child.bind(node))
  4. undo_redo.add_undo_method(add_child.bind(node))
  5. undo_redo.add_undo_reference(node)
  6. undo_redo.commit_action()

void clear_history(increase_version: bool = true) 🔗

清除撤销/重做历史和相关的引用。

false 传递给 increase_version 将防止在清除历史记录时增加版本号。


void commit_action(execute: bool = true) 🔗

提交动作。如果 executetrue(默认情况),则会在调用此函数时调用/设置所有“执行(do)”方法/属性。


void create_action(name: String, merge_mode: MergeMode = 0, backward_undo_ops: bool = false) 🔗

创建一个新的动作。调用后,请执行所有你需要的 add_do_methodadd_undo_methodadd_do_propertyadd_undo_property 调用,然后再用 commit_action 提交这个动作。

动作的合并方式由 merge_mode 决定。详见 MergeMode

动作中撤销操作的顺序由 backward_undo_ops 决定。backward_undo_opsfalse 时,撤销选项的顺序和添加顺序一致。也就是说,先添加的操作会先撤销。


void end_force_keep_in_merge_ends() 🔗

停止将操作标记为要处理,即使该动作在 MERGE_ENDS 模式下与另一个动作合并。请参阅 start_force_keep_in_merge_ends


String get_action_name(id: int) 🔗

根据索引获取动作名称。


int get_current_action() 🔗

获取当前动作的索引。


String get_current_action_name() const 🔗

获取当前动作的名称,等价于 get_action_name(get_current_action())


int get_history_count() 🔗

返回历史中有多少元素。


int get_version() const 🔗

获取版本。每次提交一个新的操作,UndoRedo 的版本号都会自动增加。

这主要用于检查保存的版本是否发生了更改。


bool has_redo() const 🔗

有“重做”动作可用时返回 true


bool has_undo() const 🔗

有“撤销”动作可用时返回 true


bool is_committing_action() const 🔗

如果 UndoRedo 当前正在提交动作,即运行其“do”的方法或属性变化,则返回 true(请参阅 commit_action)。


bool redo() 🔗

重做上一个动作。


void start_force_keep_in_merge_ends() 🔗

标记要处理的下一个“执行”和“撤消”操作,即使该动作在 MERGE_ENDS 模式下与另一个动作合并。使用 end_force_keep_in_merge_ends 返回到正常操作。


bool undo() 🔗

撤销上一个动作。