Allow undoredo actions to not make history unsaved
This commit is contained in:
@ -96,11 +96,13 @@
|
|||||||
<param index="1" name="merge_mode" type="int" enum="UndoRedo.MergeMode" default="0" />
|
<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="2" name="custom_context" type="Object" default="null" />
|
||||||
<param index="3" name="backward_undo_ops" type="bool" default="false" />
|
<param index="3" name="backward_undo_ops" type="bool" default="false" />
|
||||||
|
<param index="4" name="mark_unsaved" type="bool" default="true" />
|
||||||
<description>
|
<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].
|
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.
|
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).
|
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.
|
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.
|
||||||
|
If [param mark_unsaved] is [code]false[/code], the action will not mark the history as unsaved. This is useful for example for actions that change a selection, or a setting that will be saved automatically. Otherwise, this should be left to [code]true[/code] if the action requires saving by the user or if it can cause data loss when left unsaved.
|
||||||
</description>
|
</description>
|
||||||
</method>
|
</method>
|
||||||
<method name="force_fixed_history">
|
<method name="force_fixed_history">
|
||||||
|
|||||||
@ -4661,7 +4661,7 @@ void EditorInspector::_edit_set(const String &p_name, const Variant &p_value, bo
|
|||||||
_edit_request_change(object, p_name);
|
_edit_request_change(object, p_name);
|
||||||
emit_signal(_prop_edited, p_name);
|
emit_signal(_prop_edited, p_name);
|
||||||
} else {
|
} else {
|
||||||
undo_redo->create_action(vformat(TTR("Set %s"), p_name), UndoRedo::MERGE_ENDS);
|
undo_redo->create_action(vformat(TTR("Set %s"), p_name), UndoRedo::MERGE_ENDS, nullptr, false, mark_unsaved);
|
||||||
undo_redo->add_do_property(object, p_name, p_value);
|
undo_redo->add_do_property(object, p_name, p_value);
|
||||||
bool valid = false;
|
bool valid = false;
|
||||||
Variant value = object->get(p_name, &valid);
|
Variant value = object->get(p_name, &valid);
|
||||||
|
|||||||
@ -603,6 +603,7 @@ class EditorInspector : public ScrollContainer {
|
|||||||
bool keying = false;
|
bool keying = false;
|
||||||
bool wide_editors = false;
|
bool wide_editors = false;
|
||||||
bool deletable_properties = false;
|
bool deletable_properties = false;
|
||||||
|
bool mark_unsaved = true;
|
||||||
|
|
||||||
float refresh_countdown;
|
float refresh_countdown;
|
||||||
bool update_tree_pending = false;
|
bool update_tree_pending = false;
|
||||||
@ -703,6 +704,7 @@ public:
|
|||||||
|
|
||||||
void set_keying(bool p_active);
|
void set_keying(bool p_active);
|
||||||
void set_read_only(bool p_read_only);
|
void set_read_only(bool p_read_only);
|
||||||
|
void set_mark_unsaved(bool p_mark) { mark_unsaved = p_mark; }
|
||||||
|
|
||||||
EditorPropertyNameProcessor::Style get_property_name_style() const;
|
EditorPropertyNameProcessor::Style get_property_name_style() const;
|
||||||
void set_property_name_style(EditorPropertyNameProcessor::Style p_style);
|
void set_property_name_style(EditorPropertyNameProcessor::Style p_style);
|
||||||
|
|||||||
@ -915,6 +915,7 @@ EditorSettingsDialog::EditorSettingsDialog() {
|
|||||||
|
|
||||||
inspector = memnew(SectionedInspector);
|
inspector = memnew(SectionedInspector);
|
||||||
inspector->get_inspector()->set_use_filter(true);
|
inspector->get_inspector()->set_use_filter(true);
|
||||||
|
inspector->get_inspector()->set_mark_unsaved(false);
|
||||||
inspector->register_search_box(search_box);
|
inspector->register_search_box(search_box);
|
||||||
inspector->register_advanced_toggle(advanced_switch);
|
inspector->register_advanced_toggle(advanced_switch);
|
||||||
inspector->set_v_size_flags(Control::SIZE_EXPAND_FILL);
|
inspector->set_v_size_flags(Control::SIZE_EXPAND_FILL);
|
||||||
|
|||||||
41
editor/editor_undo_redo_manager.compat.inc
Normal file
41
editor/editor_undo_redo_manager.compat.inc
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
/**************************************************************************/
|
||||||
|
/* editor_undo_redo_manager.compat.inc */
|
||||||
|
/**************************************************************************/
|
||||||
|
/* This file is part of: */
|
||||||
|
/* GODOT ENGINE */
|
||||||
|
/* https://godotengine.org */
|
||||||
|
/**************************************************************************/
|
||||||
|
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
|
||||||
|
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
|
||||||
|
/* */
|
||||||
|
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||||
|
/* a copy of this software and associated documentation files (the */
|
||||||
|
/* "Software"), to deal in the Software without restriction, including */
|
||||||
|
/* without limitation the rights to use, copy, modify, merge, publish, */
|
||||||
|
/* distribute, sublicense, and/or sell copies of the Software, and to */
|
||||||
|
/* permit persons to whom the Software is furnished to do so, subject to */
|
||||||
|
/* the following conditions: */
|
||||||
|
/* */
|
||||||
|
/* The above copyright notice and this permission notice shall be */
|
||||||
|
/* included in all copies or substantial portions of the Software. */
|
||||||
|
/* */
|
||||||
|
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
|
||||||
|
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
|
||||||
|
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
|
||||||
|
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
|
||||||
|
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
|
||||||
|
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||||
|
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||||
|
/**************************************************************************/
|
||||||
|
|
||||||
|
#ifndef DISABLE_DEPRECATED
|
||||||
|
|
||||||
|
void EditorUndoRedoManager::_create_action_bind_compat_106121(const String &p_name, UndoRedo::MergeMode p_mode, Object *p_custom_context, bool p_backward_undo_ops) {
|
||||||
|
create_action(p_name, p_mode, p_custom_context, p_backward_undo_ops, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
void EditorUndoRedoManager::_bind_compatibility_methods() {
|
||||||
|
ClassDB::bind_compatibility_method(D_METHOD("create_action", "name", "merge_mode", "custom_context", "backward_undo_ops"), &EditorUndoRedoManager::_create_action_bind_compat_106121, DEFVAL(UndoRedo::MERGE_DISABLE), DEFVAL((Object *)nullptr), DEFVAL(false));
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
@ -29,6 +29,7 @@
|
|||||||
/**************************************************************************/
|
/**************************************************************************/
|
||||||
|
|
||||||
#include "editor_undo_redo_manager.h"
|
#include "editor_undo_redo_manager.h"
|
||||||
|
#include "editor_undo_redo_manager.compat.inc"
|
||||||
|
|
||||||
#include "core/io/resource.h"
|
#include "core/io/resource.h"
|
||||||
#include "core/os/os.h"
|
#include "core/os/os.h"
|
||||||
@ -125,7 +126,7 @@ void EditorUndoRedoManager::force_fixed_history() {
|
|||||||
forced_history = true;
|
forced_history = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void EditorUndoRedoManager::create_action_for_history(const String &p_name, int p_history_id, UndoRedo::MergeMode p_mode, bool p_backward_undo_ops) {
|
void EditorUndoRedoManager::create_action_for_history(const String &p_name, int p_history_id, UndoRedo::MergeMode p_mode, bool p_backward_undo_ops, bool p_mark_unsaved) {
|
||||||
if (pending_action.history_id != INVALID_HISTORY) {
|
if (pending_action.history_id != INVALID_HISTORY) {
|
||||||
// Nested action.
|
// Nested action.
|
||||||
p_history_id = pending_action.history_id;
|
p_history_id = pending_action.history_id;
|
||||||
@ -134,6 +135,7 @@ void EditorUndoRedoManager::create_action_for_history(const String &p_name, int
|
|||||||
pending_action.timestamp = OS::get_singleton()->get_unix_time();
|
pending_action.timestamp = OS::get_singleton()->get_unix_time();
|
||||||
pending_action.merge_mode = p_mode;
|
pending_action.merge_mode = p_mode;
|
||||||
pending_action.backward_undo_ops = p_backward_undo_ops;
|
pending_action.backward_undo_ops = p_backward_undo_ops;
|
||||||
|
pending_action.mark_unsaved = p_mark_unsaved;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (p_history_id != INVALID_HISTORY) {
|
if (p_history_id != INVALID_HISTORY) {
|
||||||
@ -143,8 +145,8 @@ void EditorUndoRedoManager::create_action_for_history(const String &p_name, int
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void EditorUndoRedoManager::create_action(const String &p_name, UndoRedo::MergeMode p_mode, Object *p_custom_context, bool p_backward_undo_ops) {
|
void EditorUndoRedoManager::create_action(const String &p_name, UndoRedo::MergeMode p_mode, Object *p_custom_context, bool p_backward_undo_ops, bool p_mark_unsaved) {
|
||||||
create_action_for_history(p_name, INVALID_HISTORY, p_mode, p_backward_undo_ops);
|
create_action_for_history(p_name, INVALID_HISTORY, p_mode, p_backward_undo_ops, p_mark_unsaved);
|
||||||
|
|
||||||
if (p_custom_context) {
|
if (p_custom_context) {
|
||||||
// This assigns history to pending action.
|
// This assigns history to pending action.
|
||||||
@ -380,7 +382,26 @@ void EditorUndoRedoManager::set_history_as_unsaved(int p_id) {
|
|||||||
|
|
||||||
bool EditorUndoRedoManager::is_history_unsaved(int p_id) {
|
bool EditorUndoRedoManager::is_history_unsaved(int p_id) {
|
||||||
History &history = get_or_create_history(p_id);
|
History &history = get_or_create_history(p_id);
|
||||||
return history.undo_redo->get_version() != history.saved_version;
|
|
||||||
|
int version_difference = history.undo_redo->get_version() - history.saved_version;
|
||||||
|
if (version_difference > 0) {
|
||||||
|
List<Action>::Element *E = history.undo_stack.back();
|
||||||
|
for (int i = 0; i < version_difference; i++) {
|
||||||
|
if (E->get().mark_unsaved) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
E = E->prev();
|
||||||
|
}
|
||||||
|
} else if (version_difference < 0) {
|
||||||
|
List<Action>::Element *E = history.redo_stack.back();
|
||||||
|
for (int i = 0; i > version_difference; i--) {
|
||||||
|
if (E->get().mark_unsaved) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
E = E->prev();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool EditorUndoRedoManager::has_undo() {
|
bool EditorUndoRedoManager::has_undo() {
|
||||||
@ -492,7 +513,7 @@ EditorUndoRedoManager::History *EditorUndoRedoManager::_get_newest_undo() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void EditorUndoRedoManager::_bind_methods() {
|
void EditorUndoRedoManager::_bind_methods() {
|
||||||
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("create_action", "name", "merge_mode", "custom_context", "backward_undo_ops", "mark_unsaved"), &EditorUndoRedoManager::create_action, DEFVAL(UndoRedo::MERGE_DISABLE), DEFVAL((Object *)nullptr), DEFVAL(false), DEFVAL(true));
|
||||||
ClassDB::bind_method(D_METHOD("commit_action", "execute"), &EditorUndoRedoManager::commit_action, DEFVAL(true));
|
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);
|
ClassDB::bind_method(D_METHOD("is_committing_action"), &EditorUndoRedoManager::is_committing_action);
|
||||||
ClassDB::bind_method(D_METHOD("force_fixed_history"), &EditorUndoRedoManager::force_fixed_history);
|
ClassDB::bind_method(D_METHOD("force_fixed_history"), &EditorUndoRedoManager::force_fixed_history);
|
||||||
|
|||||||
@ -51,6 +51,7 @@ public:
|
|||||||
String action_name;
|
String action_name;
|
||||||
UndoRedo::MergeMode merge_mode = UndoRedo::MERGE_DISABLE;
|
UndoRedo::MergeMode merge_mode = UndoRedo::MERGE_DISABLE;
|
||||||
bool backward_undo_ops = false;
|
bool backward_undo_ops = false;
|
||||||
|
bool mark_unsaved = true;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct History {
|
struct History {
|
||||||
@ -73,6 +74,11 @@ private:
|
|||||||
protected:
|
protected:
|
||||||
static void _bind_methods();
|
static void _bind_methods();
|
||||||
|
|
||||||
|
#ifndef DISABLE_DEPRECATED
|
||||||
|
void _create_action_bind_compat_106121(const String &p_name = "", UndoRedo::MergeMode p_mode = UndoRedo::MERGE_DISABLE, Object *p_custom_context = nullptr, bool p_backward_undo_ops = false);
|
||||||
|
static void _bind_compatibility_methods();
|
||||||
|
#endif
|
||||||
|
|
||||||
public:
|
public:
|
||||||
History &get_or_create_history(int p_idx);
|
History &get_or_create_history(int p_idx);
|
||||||
UndoRedo *get_history_undo_redo(int p_idx) const;
|
UndoRedo *get_history_undo_redo(int p_idx) const;
|
||||||
@ -80,8 +86,8 @@ public:
|
|||||||
History &get_history_for_object(Object *p_object);
|
History &get_history_for_object(Object *p_object);
|
||||||
void force_fixed_history();
|
void force_fixed_history();
|
||||||
|
|
||||||
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_for_history(const String &p_name, int p_history_id, UndoRedo::MergeMode p_mode = UndoRedo::MERGE_DISABLE, bool p_backward_undo_ops = false, bool p_mark_unsaved = true);
|
||||||
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 create_action(const String &p_name = "", UndoRedo::MergeMode p_mode = UndoRedo::MERGE_DISABLE, Object *p_custom_context = nullptr, bool p_backward_undo_ops = false, bool p_mark_unsaved = true);
|
||||||
|
|
||||||
void add_do_methodp(Object *p_object, const StringName &p_method, const Variant **p_args, int p_argcount);
|
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);
|
void add_undo_methodp(Object *p_object, const StringName &p_method, const Variant **p_args, int p_argcount);
|
||||||
|
|||||||
@ -1521,10 +1521,11 @@ ProjectExportDialog::ProjectExportDialog() {
|
|||||||
// Main preset parameters.
|
// Main preset parameters.
|
||||||
|
|
||||||
parameters = memnew(EditorInspector);
|
parameters = memnew(EditorInspector);
|
||||||
sections->add_child(parameters);
|
parameters->set_name(TTRC("Options"));
|
||||||
parameters->set_name(TTR("Options"));
|
parameters->set_mark_unsaved(false);
|
||||||
parameters->set_v_size_flags(Control::SIZE_EXPAND_FILL);
|
parameters->set_v_size_flags(Control::SIZE_EXPAND_FILL);
|
||||||
parameters->set_use_doc_hints(true);
|
parameters->set_use_doc_hints(true);
|
||||||
|
sections->add_child(parameters);
|
||||||
parameters->connect("property_edited", callable_mp(this, &ProjectExportDialog::_update_parameters));
|
parameters->connect("property_edited", callable_mp(this, &ProjectExportDialog::_update_parameters));
|
||||||
EditorExport::get_singleton()->connect("export_presets_updated", callable_mp(this, &ProjectExportDialog::_force_update_current_preset_parameters));
|
EditorExport::get_singleton()->connect("export_presets_updated", callable_mp(this, &ProjectExportDialog::_force_update_current_preset_parameters));
|
||||||
|
|
||||||
|
|||||||
@ -1313,7 +1313,7 @@ void TileMapLayerEditorTilesPlugin::_stop_dragging() {
|
|||||||
EditorUndoRedoManager *undo_redo = EditorUndoRedoManager::get_singleton();
|
EditorUndoRedoManager *undo_redo = EditorUndoRedoManager::get_singleton();
|
||||||
switch (drag_type) {
|
switch (drag_type) {
|
||||||
case DRAG_TYPE_SELECT: {
|
case DRAG_TYPE_SELECT: {
|
||||||
undo_redo->create_action_for_history(TTR("Change selection"), EditorNode::get_editor_data().get_current_edited_scene_history_id());
|
undo_redo->create_action_for_history(TTR("Change selection"), EditorNode::get_editor_data().get_current_edited_scene_history_id(), UndoRedo::MERGE_DISABLE, false, false);
|
||||||
undo_redo->add_undo_method(this, "_set_tile_map_selection", _get_tile_map_selection());
|
undo_redo->add_undo_method(this, "_set_tile_map_selection", _get_tile_map_selection());
|
||||||
|
|
||||||
if (!Input::get_singleton()->is_key_pressed(Key::SHIFT) && !Input::get_singleton()->is_key_pressed(Key::CMD_OR_CTRL)) {
|
if (!Input::get_singleton()->is_key_pressed(Key::SHIFT) && !Input::get_singleton()->is_key_pressed(Key::CMD_OR_CTRL)) {
|
||||||
|
|||||||
@ -718,6 +718,7 @@ ProjectSettingsEditor::ProjectSettingsEditor(EditorData *p_data) {
|
|||||||
general_settings_inspector->register_search_box(search_box);
|
general_settings_inspector->register_search_box(search_box);
|
||||||
general_settings_inspector->register_advanced_toggle(advanced);
|
general_settings_inspector->register_advanced_toggle(advanced);
|
||||||
general_settings_inspector->get_inspector()->set_use_filter(true);
|
general_settings_inspector->get_inspector()->set_use_filter(true);
|
||||||
|
general_settings_inspector->get_inspector()->set_mark_unsaved(false);
|
||||||
general_settings_inspector->get_inspector()->connect("property_selected", callable_mp(this, &ProjectSettingsEditor::_setting_selected));
|
general_settings_inspector->get_inspector()->connect("property_selected", callable_mp(this, &ProjectSettingsEditor::_setting_selected));
|
||||||
general_settings_inspector->get_inspector()->connect("property_edited", callable_mp(this, &ProjectSettingsEditor::_setting_edited));
|
general_settings_inspector->get_inspector()->connect("property_edited", callable_mp(this, &ProjectSettingsEditor::_setting_edited));
|
||||||
general_settings_inspector->get_inspector()->connect("restart_requested", callable_mp(this, &ProjectSettingsEditor::_editor_restart_request));
|
general_settings_inspector->get_inspector()->connect("restart_requested", callable_mp(this, &ProjectSettingsEditor::_editor_restart_request));
|
||||||
|
|||||||
@ -104,3 +104,10 @@ GH-105570
|
|||||||
Validate extension JSON: Error: Field 'classes/RenderingDevice/methods/texture_create_from_extension/arguments': size changed value in new API, from 9 to 10.
|
Validate extension JSON: Error: Field 'classes/RenderingDevice/methods/texture_create_from_extension/arguments': size changed value in new API, from 9 to 10.
|
||||||
|
|
||||||
Argument added; p_mipmaps. Compatibility method registered.
|
Argument added; p_mipmaps. Compatibility method registered.
|
||||||
|
|
||||||
|
GH-106121
|
||||||
|
--------
|
||||||
|
Validate extension JSON: Error: Field 'classes/EditorUndoRedoManager/methods/create_action/arguments': size changed value in new API, from 4 to 5.
|
||||||
|
Validate extension JSON: Error: Field 'classes/EditorUndoRedoManager/methods/create_action/arguments': size changed value in new API, from 3 to 5.
|
||||||
|
|
||||||
|
New argument added. Compatibility method registered.
|
||||||
|
|||||||
Reference in New Issue
Block a user