Browse Source

Implement maximum undo steps in UndoRedo

Emmanouil Papadeas 1 year ago
parent
commit
c73bfd5d81
3 changed files with 29 additions and 0 deletions
  1. 20 0
      core/object/undo_redo.cpp
  2. 4 0
      core/object/undo_redo.h
  3. 5 0
      doc/classes/UndoRedo.xml

+ 20 - 0
core/object/undo_redo.cpp

@@ -316,6 +316,14 @@ void UndoRedo::commit_action(bool p_execute) {
 	_redo(p_execute); // perform action
 	_redo(p_execute); // perform action
 	committing--;
 	committing--;
 
 
+	if (max_steps > 0) {
+		// Clear early steps.
+
+		while (actions.size() > max_steps) {
+			_pop_history_tail();
+		}
+	}
+
 	if (add_message && callback && actions.size() > 0) {
 	if (add_message && callback && actions.size() > 0) {
 		callback(callback_ud, actions[actions.size() - 1].name);
 		callback(callback_ud, actions[actions.size() - 1].name);
 	}
 	}
@@ -473,6 +481,14 @@ uint64_t UndoRedo::get_version() const {
 	return version;
 	return version;
 }
 }
 
 
+void UndoRedo::set_max_steps(int p_max_steps) {
+	max_steps = p_max_steps;
+}
+
+int UndoRedo::get_max_steps() const {
+	return max_steps;
+}
+
 void UndoRedo::set_commit_notify_callback(CommitNotifyCallback p_callback, void *p_ud) {
 void UndoRedo::set_commit_notify_callback(CommitNotifyCallback p_callback, void *p_ud) {
 	callback = p_callback;
 	callback = p_callback;
 	callback_ud = p_ud;
 	callback_ud = p_ud;
@@ -517,9 +533,13 @@ void UndoRedo::_bind_methods() {
 	ClassDB::bind_method(D_METHOD("has_undo"), &UndoRedo::has_undo);
 	ClassDB::bind_method(D_METHOD("has_undo"), &UndoRedo::has_undo);
 	ClassDB::bind_method(D_METHOD("has_redo"), &UndoRedo::has_redo);
 	ClassDB::bind_method(D_METHOD("has_redo"), &UndoRedo::has_redo);
 	ClassDB::bind_method(D_METHOD("get_version"), &UndoRedo::get_version);
 	ClassDB::bind_method(D_METHOD("get_version"), &UndoRedo::get_version);
+	ClassDB::bind_method(D_METHOD("set_max_steps", "max_steps"), &UndoRedo::set_max_steps);
+	ClassDB::bind_method(D_METHOD("get_max_steps"), &UndoRedo::get_max_steps);
 	ClassDB::bind_method(D_METHOD("redo"), &UndoRedo::redo);
 	ClassDB::bind_method(D_METHOD("redo"), &UndoRedo::redo);
 	ClassDB::bind_method(D_METHOD("undo"), &UndoRedo::undo);
 	ClassDB::bind_method(D_METHOD("undo"), &UndoRedo::undo);
 
 
+	ADD_PROPERTY(PropertyInfo(Variant::INT, "max_steps", PROPERTY_HINT_RANGE, "0,50,1,or_greater"), "set_max_steps", "get_max_steps");
+
 	ADD_SIGNAL(MethodInfo("version_changed"));
 	ADD_SIGNAL(MethodInfo("version_changed"));
 
 
 	BIND_ENUM_CONSTANT(MERGE_DISABLE);
 	BIND_ENUM_CONSTANT(MERGE_DISABLE);

+ 4 - 0
core/object/undo_redo.h

@@ -80,6 +80,7 @@ private:
 	int current_action = -1;
 	int current_action = -1;
 	bool force_keep_in_merge_ends = false;
 	bool force_keep_in_merge_ends = false;
 	int action_level = 0;
 	int action_level = 0;
+	int max_steps = 0;
 	MergeMode merge_mode = MERGE_DISABLE;
 	MergeMode merge_mode = MERGE_DISABLE;
 	bool merging = false;
 	bool merging = false;
 	uint64_t version = 1;
 	uint64_t version = 1;
@@ -135,6 +136,9 @@ public:
 
 
 	uint64_t get_version() const;
 	uint64_t get_version() const;
 
 
+	void set_max_steps(int p_max_steps);
+	int get_max_steps() const;
+
 	void set_commit_notify_callback(CommitNotifyCallback p_callback, void *p_ud);
 	void set_commit_notify_callback(CommitNotifyCallback p_callback, void *p_ud);
 
 
 	void set_method_notify_callback(MethodNotifyCallback p_method_callback, void *p_ud);
 	void set_method_notify_callback(MethodNotifyCallback p_method_callback, void *p_ud);

+ 5 - 0
doc/classes/UndoRedo.xml

@@ -255,6 +255,11 @@
 			</description>
 			</description>
 		</method>
 		</method>
 	</methods>
 	</methods>
+	<members>
+		<member name="max_steps" type="int" setter="set_max_steps" getter="get_max_steps" default="0">
+			The maximum number of steps that can be stored in the undo/redo history. If the number of stored steps exceeds this limit, older steps are removed from history and can no longer be reached by calling [method undo]. A value of [code]0[/code] or lower means no limit.
+		</member>
+	</members>
 	<signals>
 	<signals>
 		<signal name="version_changed">
 		<signal name="version_changed">
 			<description>
 			<description>