1 /** 2 Helper to manage UndoRedo in the editor or custom tools. 3 4 Copyright: 5 Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. 6 Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) 7 Copyright (c) 2017-2018 Godot-D contributors 8 9 License: $(LINK2 https://opensource.org/licenses/MIT, MIT License) 10 11 12 */ 13 module godot.undoredo; 14 import std.meta : AliasSeq, staticIndexOf; 15 import std.traits : Unqual; 16 import godot.d.meta; 17 import godot.core; 18 import godot.c; 19 import godot.d.bind; 20 import godot.d.reference; 21 import godot.object; 22 import godot.classdb; 23 /** 24 Helper to manage UndoRedo in the editor or custom tools. 25 26 It works by registering methods and property changes inside 'actions'. 27 Common behavior is to create an action, then add do/undo calls to functions or property changes, then committing the action. 28 Here's an example on how to add an action to Godot editor's own 'undoredo': 29 30 31 var undoredo = get_undo_redo() # method of EditorPlugin 32 33 func do_something(): 34 pass # put your code here 35 36 func undo_something(): 37 pass # put here the code that reverts what's done by "do_something()" 38 39 func _on_MyButton_pressed(): 40 var node = get_node("MyNode2D") 41 undoredo.create_action("Move the node") 42 undoredo.add_do_method(self, "do_something") 43 undoredo.add_undo_method(self, "undo_something") 44 undoredo.add_do_property(node, "position", Vector2(100,100)) 45 undoredo.add_undo_property(node, "position", node.position) 46 undoredo.commit_action() 47 48 49 $(D createAction), $(D addDoMethod), $(D addUndoMethod), $(D addDoProperty), $(D addUndoProperty), and $(D commitAction) should be called one after the other, like in the example. Not doing so could lead to crashes. 50 If you don't need to register a method you can leave $(D addDoMethod) and $(D addUndoMethod) out, and so it goes for properties. You can register more than one method/property. 51 */ 52 @GodotBaseClass struct UndoRedo 53 { 54 enum string _GODOT_internal_name = "UndoRedo"; 55 public: 56 @nogc nothrow: 57 union { godot_object _godot_object; GodotObject _GODOT_base; } 58 alias _GODOT_base this; 59 alias BaseClasses = AliasSeq!(typeof(_GODOT_base), typeof(_GODOT_base).BaseClasses); 60 package(godot) __gshared bool _classBindingInitialized = false; 61 package(godot) static struct _classBinding 62 { 63 __gshared: 64 @GodotName("create_action") GodotMethod!(void, String, long) createAction; 65 @GodotName("commit_action") GodotMethod!(void) commitAction; 66 @GodotName("add_do_method") GodotMethod!(Variant, GodotObject, String, GodotVarArgs) addDoMethod; 67 @GodotName("add_undo_method") GodotMethod!(Variant, GodotObject, String, GodotVarArgs) addUndoMethod; 68 @GodotName("add_do_property") GodotMethod!(void, GodotObject, String, Variant) addDoProperty; 69 @GodotName("add_undo_property") GodotMethod!(void, GodotObject, String, Variant) addUndoProperty; 70 @GodotName("add_do_reference") GodotMethod!(void, GodotObject) addDoReference; 71 @GodotName("add_undo_reference") GodotMethod!(void, GodotObject) addUndoReference; 72 @GodotName("clear_history") GodotMethod!(void) clearHistory; 73 @GodotName("get_current_action_name") GodotMethod!(String) getCurrentActionName; 74 @GodotName("get_version") GodotMethod!(long) getVersion; 75 @GodotName("redo") GodotMethod!(bool) redo; 76 @GodotName("undo") GodotMethod!(bool) undo; 77 } 78 bool opEquals(in UndoRedo other) const { return _godot_object.ptr is other._godot_object.ptr; } 79 UndoRedo opAssign(T : typeof(null))(T n) { _godot_object.ptr = null; } 80 bool opEquals(typeof(null) n) const { return _godot_object.ptr is null; } 81 mixin baseCasts; 82 static UndoRedo _new() 83 { 84 static godot_class_constructor constructor; 85 if(constructor is null) constructor = _godot_api.godot_get_class_constructor("UndoRedo"); 86 if(constructor is null) return typeof(this).init; 87 return cast(UndoRedo)(constructor()); 88 } 89 @disable new(size_t s); 90 /// 91 enum MergeMode : int 92 { 93 /** 94 95 */ 96 mergeDisable = 0, 97 /** 98 99 */ 100 mergeEnds = 1, 101 /** 102 103 */ 104 mergeAll = 2, 105 } 106 /// 107 enum Constants : int 108 { 109 mergeDisable = 0, 110 mergeEnds = 1, 111 mergeAll = 2, 112 } 113 /** 114 Create a new action. After this is called, do all your calls to $(D addDoMethod), $(D addUndoMethod), $(D addDoProperty), and $(D addUndoProperty), then commit the action with $(D commitAction). 115 */ 116 void createAction(StringArg0)(in StringArg0 name, in long merge_mode = 0) 117 { 118 checkClassBinding!(typeof(this))(); 119 ptrcall!(void)(_classBinding.createAction, _godot_object, name, merge_mode); 120 } 121 /** 122 Commit the action. All 'do' methods/properties are called/set when this function is called. 123 */ 124 void commitAction() 125 { 126 checkClassBinding!(typeof(this))(); 127 ptrcall!(void)(_classBinding.commitAction, _godot_object); 128 } 129 /** 130 Register a method that will be called when the action is committed. 131 */ 132 Variant addDoMethod(StringArg1, VarArgs...)(GodotObject object, in StringArg1 method, VarArgs varArgs) 133 { 134 Array _GODOT_args = Array.empty_array; 135 _GODOT_args.append(object); 136 _GODOT_args.append(method); 137 foreach(vai, VA; VarArgs) 138 { 139 _GODOT_args.append(varArgs[vai]); 140 } 141 String _GODOT_method_name = String("add_do_method"); 142 return this.callv(_GODOT_method_name, _GODOT_args); 143 } 144 /** 145 Register a method that will be called when the action is undone. 146 */ 147 Variant addUndoMethod(StringArg1, VarArgs...)(GodotObject object, in StringArg1 method, VarArgs varArgs) 148 { 149 Array _GODOT_args = Array.empty_array; 150 _GODOT_args.append(object); 151 _GODOT_args.append(method); 152 foreach(vai, VA; VarArgs) 153 { 154 _GODOT_args.append(varArgs[vai]); 155 } 156 String _GODOT_method_name = String("add_undo_method"); 157 return this.callv(_GODOT_method_name, _GODOT_args); 158 } 159 /** 160 Register a property value change for 'do'. 161 */ 162 void addDoProperty(StringArg1, VariantArg2)(GodotObject object, in StringArg1 property, in VariantArg2 value) 163 { 164 checkClassBinding!(typeof(this))(); 165 ptrcall!(void)(_classBinding.addDoProperty, _godot_object, object, property, value); 166 } 167 /** 168 Register a property value change for 'undo'. 169 */ 170 void addUndoProperty(StringArg1, VariantArg2)(GodotObject object, in StringArg1 property, in VariantArg2 value) 171 { 172 checkClassBinding!(typeof(this))(); 173 ptrcall!(void)(_classBinding.addUndoProperty, _godot_object, object, property, value); 174 } 175 /** 176 Register a reference for 'do' that will be erased if the 'do' history is lost. This is useful mostly for new nodes created for the 'do' call. Do not use for resources. 177 */ 178 void addDoReference(GodotObject object) 179 { 180 checkClassBinding!(typeof(this))(); 181 ptrcall!(void)(_classBinding.addDoReference, _godot_object, object); 182 } 183 /** 184 Register a reference for 'undo' that will be erased if the 'undo' history is lost. This is useful mostly for nodes removed with the 'do' call (not the 'undo' call!). 185 */ 186 void addUndoReference(GodotObject object) 187 { 188 checkClassBinding!(typeof(this))(); 189 ptrcall!(void)(_classBinding.addUndoReference, _godot_object, object); 190 } 191 /** 192 Clear the undo/redo history and associated references. 193 */ 194 void clearHistory() 195 { 196 checkClassBinding!(typeof(this))(); 197 ptrcall!(void)(_classBinding.clearHistory, _godot_object); 198 } 199 /** 200 Get the name of the current action. 201 */ 202 String getCurrentActionName() const 203 { 204 checkClassBinding!(typeof(this))(); 205 return ptrcall!(String)(_classBinding.getCurrentActionName, _godot_object); 206 } 207 /** 208 Get the version, each time a new action is committed, the version number of the UndoRedo is increased automatically. 209 This is useful mostly to check if something changed from a saved version. 210 */ 211 long getVersion() const 212 { 213 checkClassBinding!(typeof(this))(); 214 return ptrcall!(long)(_classBinding.getVersion, _godot_object); 215 } 216 /** 217 Redo last action. 218 */ 219 bool redo() 220 { 221 checkClassBinding!(typeof(this))(); 222 return ptrcall!(bool)(_classBinding.redo, _godot_object); 223 } 224 /** 225 Undo last action. 226 */ 227 bool undo() 228 { 229 checkClassBinding!(typeof(this))(); 230 return ptrcall!(bool)(_classBinding.undo, _godot_object); 231 } 232 }