diff --git a/doc/classes/EditorUndoRedoManager.xml b/doc/classes/EditorUndoRedoManager.xml index 6a66a35ce87..09293302817 100644 --- a/doc/classes/EditorUndoRedoManager.xml +++ b/doc/classes/EditorUndoRedoManager.xml @@ -96,11 +96,13 @@ + 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. + 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. diff --git a/editor/editor_inspector.cpp b/editor/editor_inspector.cpp index a55fe2098e8..0b2d0280899 100644 --- a/editor/editor_inspector.cpp +++ b/editor/editor_inspector.cpp @@ -4661,7 +4661,7 @@ void EditorInspector::_edit_set(const String &p_name, const Variant &p_value, bo _edit_request_change(object, p_name); emit_signal(_prop_edited, p_name); } 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); bool valid = false; Variant value = object->get(p_name, &valid); diff --git a/editor/editor_inspector.h b/editor/editor_inspector.h index 183c18c3afb..a0da16593a3 100644 --- a/editor/editor_inspector.h +++ b/editor/editor_inspector.h @@ -603,6 +603,7 @@ class EditorInspector : public ScrollContainer { bool keying = false; bool wide_editors = false; bool deletable_properties = false; + bool mark_unsaved = true; float refresh_countdown; bool update_tree_pending = false; @@ -703,6 +704,7 @@ public: void set_keying(bool p_active); 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; void set_property_name_style(EditorPropertyNameProcessor::Style p_style); diff --git a/editor/editor_settings_dialog.cpp b/editor/editor_settings_dialog.cpp index 016d2d5b314..01c0e2b5689 100644 --- a/editor/editor_settings_dialog.cpp +++ b/editor/editor_settings_dialog.cpp @@ -915,6 +915,7 @@ EditorSettingsDialog::EditorSettingsDialog() { inspector = memnew(SectionedInspector); inspector->get_inspector()->set_use_filter(true); + inspector->get_inspector()->set_mark_unsaved(false); inspector->register_search_box(search_box); inspector->register_advanced_toggle(advanced_switch); inspector->set_v_size_flags(Control::SIZE_EXPAND_FILL); diff --git a/editor/editor_undo_redo_manager.compat.inc b/editor/editor_undo_redo_manager.compat.inc new file mode 100644 index 00000000000..b44762e3111 --- /dev/null +++ b/editor/editor_undo_redo_manager.compat.inc @@ -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 diff --git a/editor/editor_undo_redo_manager.cpp b/editor/editor_undo_redo_manager.cpp index a278de0884b..2737d4d4b2e 100644 --- a/editor/editor_undo_redo_manager.cpp +++ b/editor/editor_undo_redo_manager.cpp @@ -29,6 +29,7 @@ /**************************************************************************/ #include "editor_undo_redo_manager.h" +#include "editor_undo_redo_manager.compat.inc" #include "core/io/resource.h" #include "core/os/os.h" @@ -125,7 +126,7 @@ void EditorUndoRedoManager::force_fixed_history() { 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) { // Nested action. 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.merge_mode = p_mode; pending_action.backward_undo_ops = p_backward_undo_ops; + pending_action.mark_unsaved = p_mark_unsaved; } 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) { - create_action_for_history(p_name, INVALID_HISTORY, p_mode, 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, p_mark_unsaved); if (p_custom_context) { // 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) { 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::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::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() { @@ -492,7 +513,7 @@ EditorUndoRedoManager::History *EditorUndoRedoManager::_get_newest_undo() { } 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("is_committing_action"), &EditorUndoRedoManager::is_committing_action); ClassDB::bind_method(D_METHOD("force_fixed_history"), &EditorUndoRedoManager::force_fixed_history); diff --git a/editor/editor_undo_redo_manager.h b/editor/editor_undo_redo_manager.h index 4b90a65e1b6..a67b900a041 100644 --- a/editor/editor_undo_redo_manager.h +++ b/editor/editor_undo_redo_manager.h @@ -51,6 +51,7 @@ public: String action_name; UndoRedo::MergeMode merge_mode = UndoRedo::MERGE_DISABLE; bool backward_undo_ops = false; + bool mark_unsaved = true; }; struct History { @@ -73,6 +74,11 @@ private: protected: 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: History &get_or_create_history(int p_idx); UndoRedo *get_history_undo_redo(int p_idx) const; @@ -80,8 +86,8 @@ public: History &get_history_for_object(Object *p_object); 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(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_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, 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_undo_methodp(Object *p_object, const StringName &p_method, const Variant **p_args, int p_argcount); diff --git a/editor/export/project_export.cpp b/editor/export/project_export.cpp index 5846fe7ee66..09c321aa9d9 100644 --- a/editor/export/project_export.cpp +++ b/editor/export/project_export.cpp @@ -1521,10 +1521,11 @@ ProjectExportDialog::ProjectExportDialog() { // Main preset parameters. parameters = memnew(EditorInspector); - sections->add_child(parameters); - parameters->set_name(TTR("Options")); + parameters->set_name(TTRC("Options")); + parameters->set_mark_unsaved(false); parameters->set_v_size_flags(Control::SIZE_EXPAND_FILL); parameters->set_use_doc_hints(true); + sections->add_child(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)); diff --git a/editor/plugins/tiles/tile_map_layer_editor.cpp b/editor/plugins/tiles/tile_map_layer_editor.cpp index 972bf5aaa18..4fd11c2966d 100644 --- a/editor/plugins/tiles/tile_map_layer_editor.cpp +++ b/editor/plugins/tiles/tile_map_layer_editor.cpp @@ -1313,7 +1313,7 @@ void TileMapLayerEditorTilesPlugin::_stop_dragging() { EditorUndoRedoManager *undo_redo = EditorUndoRedoManager::get_singleton(); switch (drag_type) { 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()); if (!Input::get_singleton()->is_key_pressed(Key::SHIFT) && !Input::get_singleton()->is_key_pressed(Key::CMD_OR_CTRL)) { diff --git a/editor/project_settings_editor.cpp b/editor/project_settings_editor.cpp index 0671684e0ec..6f0976e140f 100644 --- a/editor/project_settings_editor.cpp +++ b/editor/project_settings_editor.cpp @@ -718,6 +718,7 @@ ProjectSettingsEditor::ProjectSettingsEditor(EditorData *p_data) { general_settings_inspector->register_search_box(search_box); general_settings_inspector->register_advanced_toggle(advanced); 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_edited", callable_mp(this, &ProjectSettingsEditor::_setting_edited)); general_settings_inspector->get_inspector()->connect("restart_requested", callable_mp(this, &ProjectSettingsEditor::_editor_restart_request)); diff --git a/misc/extension_api_validation/4.4-stable.expected b/misc/extension_api_validation/4.4-stable.expected index 3265e1b8c73..33e335ff502 100644 --- a/misc/extension_api_validation/4.4-stable.expected +++ b/misc/extension_api_validation/4.4-stable.expected @@ -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. 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.