From 6dc5dc3479f7758d6f52038659ebefbd9ae4d3a4 Mon Sep 17 00:00:00 2001 From: kobewi Date: Sun, 16 Oct 2022 18:09:17 +0200 Subject: [PATCH] Add `_get_unsaved_status()` method to EditorPlugin --- doc/classes/EditorPlugin.xml | 16 ++++++++++++++++ editor/editor_node.cpp | 26 ++++++++++++++++++++++++++ editor/editor_node.h | 1 + editor/editor_plugin.cpp | 8 +++++++- editor/editor_plugin.h | 2 ++ 5 files changed, 52 insertions(+), 1 deletion(-) diff --git a/doc/classes/EditorPlugin.xml b/doc/classes/EditorPlugin.xml index 957b6d8e88a..8d0a13279d1 100644 --- a/doc/classes/EditorPlugin.xml +++ b/doc/classes/EditorPlugin.xml @@ -280,6 +280,22 @@ [/codeblock] + + + + Override this method to provide a custom message that lists unsaved changes. The editor will call this method on exit and display it in a confirmation dialog. Return empty string if the plugin has no unsaved changes. + If the user confirms saving, [method _save_external_data] will be called, before closing the editor. + [codeblock] + func _get_unsaved_status(): + if unsaved: + return "Save changes in MyCustomPlugin before closing?" + return "" + + func _save_external_data(): + unsaved = false + [/codeblock] + + diff --git a/editor/editor_node.cpp b/editor/editor_node.cpp index bcf5da5e573..f304850b507 100644 --- a/editor/editor_node.cpp +++ b/editor/editor_node.cpp @@ -2777,6 +2777,11 @@ void EditorNode::_menu_option_confirm(int p_option, bool p_confirmed) { case FILE_QUIT: case RUN_PROJECT_MANAGER: case RELOAD_CURRENT_PROJECT: { + if (p_confirmed && plugin_to_save) { + plugin_to_save->save_external_data(); + p_confirmed = false; + } + if (!p_confirmed) { bool save_each = EDITOR_GET("interface/editor/save_each_scene_on_quit"); if (_next_unsaved_scene(!save_each) == -1) { @@ -2792,6 +2797,27 @@ void EditorNode::_menu_option_confirm(int p_option, bool p_confirmed) { save_confirmation->popup_centered(); break; } + + plugin_to_save = nullptr; + for (int i = 0; i < editor_data.get_editor_plugin_count(); i++) { + const String unsaved_status = editor_data.get_editor_plugin(i)->get_unsaved_status(); + if (!unsaved_status.is_empty()) { + if (p_option == RELOAD_CURRENT_PROJECT) { + save_confirmation->set_ok_button_text(TTR("Save & Reload")); + save_confirmation->set_text(RTR(unsaved_status)); + } else { + save_confirmation->set_ok_button_text(TTR("Save & Quit")); + save_confirmation->set_text(RTR(unsaved_status)); + } + save_confirmation->popup_centered(); + plugin_to_save = editor_data.get_editor_plugin(i); + break; + } + } + + if (plugin_to_save) { + break; + } _discard_changes(); break; diff --git a/editor/editor_node.h b/editor/editor_node.h index 65f85a76c98..6384c27c722 100644 --- a/editor/editor_node.h +++ b/editor/editor_node.h @@ -382,6 +382,7 @@ private: AcceptDialog *save_accept = nullptr; EditorAbout *about = nullptr; AcceptDialog *warning = nullptr; + EditorPlugin *plugin_to_save = nullptr; int overridden_default_layout = -1; Ref default_layout; diff --git a/editor/editor_plugin.cpp b/editor/editor_plugin.cpp index 5170c2fdfbe..f2a8324332c 100644 --- a/editor/editor_plugin.cpp +++ b/editor/editor_plugin.cpp @@ -341,7 +341,12 @@ void EditorPlugin::clear() { GDVIRTUAL_CALL(_clear); } -// if editor references external resources/scenes, save them +String EditorPlugin::get_unsaved_status() const { + String ret; + GDVIRTUAL_CALL(_get_unsaved_status, ret); + return ret; +} + void EditorPlugin::save_external_data() { GDVIRTUAL_CALL(_save_external_data); } @@ -594,6 +599,7 @@ void EditorPlugin::_bind_methods() { GDVIRTUAL_BIND(_get_state); GDVIRTUAL_BIND(_set_state, "state"); GDVIRTUAL_BIND(_clear); + GDVIRTUAL_BIND(_get_unsaved_status); GDVIRTUAL_BIND(_save_external_data); GDVIRTUAL_BIND(_apply_changes); GDVIRTUAL_BIND(_get_breakpoints); diff --git a/editor/editor_plugin.h b/editor/editor_plugin.h index 69789a4d4f6..d74064e89c7 100644 --- a/editor/editor_plugin.h +++ b/editor/editor_plugin.h @@ -88,6 +88,7 @@ protected: GDVIRTUAL0RC(Dictionary, _get_state) GDVIRTUAL1(_set_state, Dictionary) GDVIRTUAL0(_clear) + GDVIRTUAL0RC(String, _get_unsaved_status) GDVIRTUAL0(_save_external_data) GDVIRTUAL0(_apply_changes) GDVIRTUAL0RC(Vector, _get_breakpoints) @@ -175,6 +176,7 @@ public: virtual Dictionary get_state() const; //save editor state so it can't be reloaded when reloading scene virtual void set_state(const Dictionary &p_state); //restore editor state (likely was saved with the scene) virtual void clear(); // clear any temporary data in the editor, reset it (likely new scene or load another scene) + virtual String get_unsaved_status() const; virtual void save_external_data(); // if editor references external resources/scenes, save them virtual void apply_changes(); // if changes are pending in editor, apply them virtual void get_breakpoints(List *p_breakpoints);