diff options
Diffstat (limited to 'editor/editor_node.cpp')
-rw-r--r-- | editor/editor_node.cpp | 336 |
1 files changed, 195 insertions, 141 deletions
diff --git a/editor/editor_node.cpp b/editor/editor_node.cpp index e719797e03..891705da98 100644 --- a/editor/editor_node.cpp +++ b/editor/editor_node.cpp @@ -49,6 +49,7 @@ #include "core/version.h" #include "core/version_hash.gen.h" #include "main/main.h" +#include "scene/3d/importer_mesh_instance_3d.h" #include "scene/gui/center_container.h" #include "scene/gui/control.h" #include "scene/gui/dialogs.h" @@ -58,8 +59,8 @@ #include "scene/gui/panel.h" #include "scene/gui/panel_container.h" #include "scene/gui/split_container.h" +#include "scene/gui/tab_bar.h" #include "scene/gui/tab_container.h" -#include "scene/gui/tabs.h" #include "scene/gui/texture_progress_bar.h" #include "scene/main/window.h" #include "scene/resources/packed_scene.h" @@ -94,6 +95,7 @@ #include "editor/editor_settings.h" #include "editor/editor_spin_slider.h" #include "editor/editor_themes.h" +#include "editor/editor_toaster.h" #include "editor/editor_translation_parser.h" #include "editor/export_template_manager.h" #include "editor/filesystem_dock.h" @@ -113,7 +115,6 @@ #include "editor/import/resource_importer_texture_atlas.h" #include "editor/import/resource_importer_wav.h" #include "editor/import/scene_import_settings.h" -#include "editor/import/scene_importer_mesh_node_3d.h" #include "editor/import_dock.h" #include "editor/multi_node_edit.h" #include "editor/node_dock.h" @@ -394,7 +395,7 @@ void EditorNode::_version_control_menu_option(int p_idx) { void EditorNode::_update_title() { const String appname = ProjectSettings::get_singleton()->get("application/config/name"); String title = (appname.is_empty() ? "Unnamed Project" : appname) + String(" - ") + VERSION_NAME; - const String edited = editor_data.get_edited_scene_root() ? editor_data.get_edited_scene_root()->get_filename() : String(); + const String edited = editor_data.get_edited_scene_root() ? editor_data.get_edited_scene_root()->get_scene_file_path() : String(); if (!edited.is_empty()) { // Display the edited scene name before the program name so that it can be seen in the OS task bar. title = vformat("%s - %s", edited.get_file(), title); @@ -657,7 +658,7 @@ void EditorNode::_notification(int p_what) { } break; case EditorSettings::NOTIFICATION_EDITOR_SETTINGS_CHANGED: { - scene_tabs->set_tab_close_display_policy((bool(EDITOR_GET("interface/scene_tabs/always_show_close_button")) ? Tabs::CLOSE_BUTTON_SHOW_ALWAYS : Tabs::CLOSE_BUTTON_SHOW_ACTIVE_ONLY)); + scene_tabs->set_tab_close_display_policy((bool(EDITOR_GET("interface/scene_tabs/always_show_close_button")) ? TabBar::CLOSE_BUTTON_SHOW_ALWAYS : TabBar::CLOSE_BUTTON_SHOW_ACTIVE_ONLY)); theme = create_custom_theme(theme_base->get_theme()); theme_base->set_theme(theme); @@ -741,6 +742,21 @@ void EditorNode::_notification(int p_what) { main_editor_buttons.write[i]->add_theme_font_size_override("font_size", gui_base->get_theme_font_size(SNAME("main_button_font_size"), SNAME("EditorFonts"))); } + Set<String> updated_textfile_extensions; + bool extensions_match = true; + const Vector<String> textfile_ext = ((String)(EditorSettings::get_singleton()->get("docks/filesystem/textfile_extensions"))).split(",", false); + for (const String &E : textfile_ext) { + updated_textfile_extensions.insert(E); + if (extensions_match && !textfile_extensions.has(E)) { + extensions_match = false; + } + } + + if (!extensions_match || updated_textfile_extensions.size() < textfile_extensions.size()) { + textfile_extensions = updated_textfile_extensions; + EditorFileSystem::get_singleton()->scan(); + } + _update_update_spinner(); } break; @@ -822,7 +838,7 @@ void EditorNode::_resources_changed(const Vector<String> &p_resources) { } if (res->get_import_path() != String()) { - //this is an imported resource, will be reloaded if reimported via the _resources_reimported() callback + // this is an imported resource, will be reloaded if reimported via the _resources_reimported() callback continue; } @@ -926,21 +942,21 @@ void EditorNode::_fs_changed() { } void EditorNode::_resources_reimported(const Vector<String> &p_resources) { - List<String> scenes; //will load later + List<String> scenes; // will load later int current_tab = scene_tabs->get_current_tab(); for (int i = 0; i < p_resources.size(); i++) { String file_type = ResourceLoader::get_resource_type(p_resources[i]); if (file_type == "PackedScene") { scenes.push_back(p_resources[i]); - //reload later if needed, first go with normal resources + // reload later if needed, first go with normal resources continue; } if (!ResourceCache::has(p_resources[i])) { - continue; //not loaded, no need to reload + continue; // not loaded, no need to reload } - //reload normally + // reload normally Resource *resource = ResourceCache::get(p_resources[i]); if (resource) { resource->reload_from_file(); @@ -1114,11 +1130,17 @@ Error EditorNode::load_resource(const String &p_resource, bool p_ignore_broken_d dependency_errors.clear(); Error err; - RES res = ResourceLoader::load(p_resource, "", ResourceFormatLoader::CACHE_MODE_REUSE, &err); + + RES res; + if (ResourceLoader::exists(p_resource, "")) { + res = ResourceLoader::load(p_resource, "", ResourceFormatLoader::CACHE_MODE_REUSE, &err); + } else if (textfile_extensions.has(p_resource.get_extension())) { + res = ScriptEditor::get_singleton()->open_file(p_resource); + } ERR_FAIL_COND_V(!res.is_valid(), ERR_CANT_OPEN); if (!p_ignore_broken_deps && dependency_errors.has(p_resource)) { - //current_option = -1; + // current_option = -1; Vector<String> errors; for (Set<String>::Element *E = dependency_errors[p_resource].front(); E; E = E->next()) { errors.push_back(E->get()); @@ -1175,7 +1197,7 @@ void EditorNode::save_resource_as(const Ref<Resource> &p_resource, const String int srpos = path.find("::"); if (srpos != -1) { String base = path.substr(0, srpos); - if (!get_edited_scene() || get_edited_scene()->get_filename() != base) { + if (!get_edited_scene() || get_edited_scene()->get_scene_file_path() != base) { show_warning(TTR("This resource can't be saved because it does not belong to the edited scene. Make it unique first.")); return; } @@ -1194,7 +1216,7 @@ void EditorNode::save_resource_as(const Ref<Resource> &p_resource, const String List<String> preferred; for (const String &E : extensions) { if (p_resource->is_class("Script") && (E == "tres" || E == "res")) { - //this serves no purpose and confused people + // this serves no purpose and confused people continue; } file->add_filter("*." + E + " ; " + E.to_upper()); @@ -1303,7 +1325,7 @@ void EditorNode::_get_scene_metadata(const String &p_file) { Error err = cf->load(path); if (err != OK || !cf->has_section("editor_states")) { - return; //must not exist + return; // must not exist } List<String> esl; @@ -1327,7 +1349,7 @@ void EditorNode::_set_scene_metadata(const String &p_file, int p_idx) { return; } - scene->set_meta("__editor_run_settings__", Variant()); //clear it (no point in keeping it) + scene->set_meta("__editor_run_settings__", Variant()); // clear it (no point in keeping it) scene->set_meta("__editor_plugin_states__", Variant()); String path = EditorSettings::get_singleton()->get_project_settings_dir().plus_file(p_file.get_file() + "-editstate-" + p_file.md5_text() + ".cfg"); @@ -1370,10 +1392,10 @@ bool EditorNode::_find_and_save_resource(RES p_res, Map<RES, bool> &processed, i if (p_res->get_path().is_resource_file()) { if (changed || subchanged) { - //save + // save ResourceSaver::save(p_res->get_path(), p_res, flags); } - processed[p_res] = false; //because it's a file + processed[p_res] = false; // because it's a file return false; } else { processed[p_res] = changed; @@ -1471,7 +1493,7 @@ void EditorNode::_save_scene_with_preview(String p_file, int p_idx) { _find_node_types(editor_data.get_edited_scene_root(), c2d, c3d); save.step(TTR("Creating Thumbnail"), 1); - //current view? + // current view? Ref<Image> img; // If neither 3D or 2D nodes are present, make a 1x1 black texture. @@ -1524,12 +1546,12 @@ void EditorNode::_save_scene_with_preview(String p_file, int p_idx) { } img->convert(Image::FORMAT_RGB8); - //save thumbnail directly, as thumbnailer may not update due to actual scene not changing md5 + // save thumbnail directly, as thumbnailer may not update due to actual scene not changing md5 String temp_path = EditorPaths::get_singleton()->get_cache_dir(); String cache_base = ProjectSettings::get_singleton()->globalize_path(p_file).md5_text(); cache_base = temp_path.plus_file("resthumb-" + cache_base); - //does not have it, try to load a cached thumbnail + // does not have it, try to load a cached thumbnail String file = cache_base + ".png"; @@ -1549,7 +1571,7 @@ void EditorNode::_save_scene_with_preview(String p_file, int p_idx) { bool EditorNode::_validate_scene_recursive(const String &p_filename, Node *p_node) { for (int i = 0; i < p_node->get_child_count(); i++) { Node *child = p_node->get_child(i); - if (child->get_filename() == p_filename) { + if (child->get_scene_file_path() == p_filename) { return true; } @@ -1577,7 +1599,7 @@ static bool _find_edited_resources(const Ref<Resource> &p_resource, Set<Ref<Reso if (res.is_null()) { continue; } - if (res->get_path().is_resource_file()) { //not a subresource, continue + if (res->get_path().is_resource_file()) { // not a subresource, continue continue; } if (_find_edited_resources(res, edited_resources)) { @@ -1590,7 +1612,7 @@ static bool _find_edited_resources(const Ref<Resource> &p_resource, Set<Ref<Reso } int EditorNode::_save_external_resources() { - //save external resources and its subresources if any was modified + // save external resources and its subresources if any was modified int flg = 0; if (EditorSettings::get_singleton()->get("filesystem/on_save/compress_binary_resources")) { @@ -1606,7 +1628,7 @@ int EditorNode::_save_external_resources() { if (!res->get_path().is_resource_file()) { continue; } - //not only check if this resource is edited, check contained subresources too + // not only check if this resource is edited, check contained subresources too if (_find_edited_resources(res, edited_subresources)) { ResourceSaver::save(res->get_path(), res, flg); saved++; @@ -1645,7 +1667,7 @@ void EditorNode::_save_scene(String p_file, int idx) { return; } - if (scene->get_filename() != String() && _validate_scene_recursive(scene->get_filename(), scene)) { + if (scene->get_scene_file_path() != String() && _validate_scene_recursive(scene->get_scene_file_path(), scene)) { show_accept(TTR("This scene can't be saved because there is a cyclic instancing inclusion.\nPlease resolve it and then attempt to save again."), TTR("OK")); return; } @@ -1699,7 +1721,7 @@ void EditorNode::_save_scene(String p_file, int idx) { } if (err == OK) { - scene->set_filename(ProjectSettings::get_singleton()->localize_path(p_file)); + scene->set_scene_file_path(ProjectSettings::get_singleton()->localize_path(p_file)); if (idx < 0 || idx == editor_data.get_edited_scene()) { set_current_version(editor_data.get_undo_redo().get_version()); } else { @@ -1727,8 +1749,8 @@ void EditorNode::save_scene_list(Vector<String> p_scene_filenames) { for (int i = 0; i < editor_data.get_edited_scene_count(); i++) { Node *scene = editor_data.get_edited_scene_root(i); - if (scene && (p_scene_filenames.find(scene->get_filename()) >= 0)) { - _save_scene(scene->get_filename(), i); + if (scene && (p_scene_filenames.find(scene->get_scene_file_path()) >= 0)) { + _save_scene(scene->get_scene_file_path(), i); } } } @@ -1738,7 +1760,7 @@ void EditorNode::restart_editor() { String to_reopen; if (get_tree()->get_edited_scene_root()) { - to_reopen = get_tree()->get_edited_scene_root()->get_filename(); + to_reopen = get_tree()->get_edited_scene_root()->get_scene_file_path(); } _exit_editor(); @@ -1755,17 +1777,25 @@ void EditorNode::restart_editor() { } void EditorNode::_save_all_scenes() { + bool all_saved = true; for (int i = 0; i < editor_data.get_edited_scene_count(); i++) { Node *scene = editor_data.get_edited_scene_root(i); - if (scene && scene->get_filename() != "") { - if (i != editor_data.get_edited_scene()) { - _save_scene(scene->get_filename(), i); + if (scene) { + if (scene->get_scene_file_path() != "" && DirAccess::exists(scene->get_scene_file_path().get_base_dir())) { + if (i != editor_data.get_edited_scene()) { + _save_scene(scene->get_scene_file_path(), i); + } else { + _save_scene_with_preview(scene->get_scene_file_path()); + } } else { - _save_scene_with_preview(scene->get_filename()); + all_saved = false; } - } // else: ignore new scenes + } } + if (!all_saved) { + show_warning(TTR("Could not save one or more scenes!"), TTR("Save All Scenes")); + } _save_default_environment(); } @@ -1776,7 +1806,7 @@ void EditorNode::_mark_unsaved_scenes() { continue; } - String path = node->get_filename(); + String path = node->get_scene_file_path(); if (!(path == String() || FileAccess::exists(path))) { if (i == editor_data.get_edited_scene()) { set_current_version(-1); @@ -1807,7 +1837,7 @@ void EditorNode::_dialog_action(String p_file) { case SETTINGS_PICK_MAIN_SCENE: { ProjectSettings::get_singleton()->set("application/run/main_scene", p_file); ProjectSettings::get_singleton()->save(); - //would be nice to show the project manager opened with the highlighted field.. + // would be nice to show the project manager opened with the highlighted field.. if (pick_main_scene->has_meta("from_native") && (bool)pick_main_scene->get_meta("from_native")) { run_native->resume_run_native(); @@ -1950,7 +1980,7 @@ void EditorNode::_dialog_action(String p_file) { } } break; - default: { //save scene? + default: { // save scene? if (file->get_file_mode() == EditorFileDialog::FILE_MODE_SAVE_FILE) { _save_scene_with_preview(p_file); @@ -2111,7 +2141,7 @@ void EditorNode::_edit_current() { bool is_resource = current_obj->is_class("Resource"); bool is_node = current_obj->is_class("Node"); - String editable_warning; //none by default + String editable_warning; // none by default if (is_resource) { Resource *current_res = Object::cast_to<Resource>(current_obj); @@ -2128,7 +2158,7 @@ void EditorNode::_edit_current() { if (FileAccess::exists(base_path + ".import")) { editable_warning = TTR("This resource belongs to a scene that was imported, so it's not editable.\nPlease read the documentation relevant to importing scenes to better understand this workflow."); } else { - if ((!get_edited_scene() || get_edited_scene()->get_filename() != base_path) && ResourceLoader::get_resource_type(base_path) == "PackedScene") { + if ((!get_edited_scene() || get_edited_scene()->get_scene_file_path() != base_path) && ResourceLoader::get_resource_type(base_path) == "PackedScene") { editable_warning = TTR("This resource belongs to a scene that was instantiated or inherited.\nChanges to it won't be kept when saving the current scene."); } } @@ -2152,8 +2182,8 @@ void EditorNode::_edit_current() { inspector_dock->update(nullptr); } - if (get_edited_scene() && get_edited_scene()->get_filename() != String()) { - String source_scene = get_edited_scene()->get_filename(); + if (get_edited_scene() && get_edited_scene()->get_scene_file_path() != String()) { + String source_scene = get_edited_scene()->get_scene_file_path(); if (FileAccess::exists(source_scene + ".import")) { editable_warning = TTR("This scene was imported, so changes to it won't be kept.\nInstancing it or inheriting will allow making changes to it.\nPlease read the documentation relevant to importing scenes to better understand this workflow."); } @@ -2213,7 +2243,7 @@ void EditorNode::_edit_current() { for (; plugin_index < editor_table.size(); plugin_index++) { if (editor_table[plugin_index] == main_plugin) { if (!main_editor_buttons[plugin_index]->is_visible()) { - main_plugin = nullptr; //if button is not visible, then no plugin active + main_plugin = nullptr; // if button is not visible, then no plugin active } break; @@ -2276,7 +2306,7 @@ void EditorNode::_run(bool p_current, const String &p_custom) { String args; bool skip_breakpoints; - if (p_current || (editor_data.get_edited_scene_root() && p_custom != String() && p_custom == editor_data.get_edited_scene_root()->get_filename())) { + if (p_current || (editor_data.get_edited_scene_root() && p_custom != String() && p_custom == editor_data.get_edited_scene_root()->get_scene_file_path())) { Node *scene = editor_data.get_edited_scene_root(); if (!scene) { @@ -2284,7 +2314,7 @@ void EditorNode::_run(bool p_current, const String &p_custom) { return; } - if (scene->get_filename() == "") { + if (scene->get_scene_file_path() == "") { current_option = -1; _menu_option(FILE_SAVE_AS_SCENE); // Set the option to save and run so when the dialog is accepted, the scene runs. @@ -2293,13 +2323,13 @@ void EditorNode::_run(bool p_current, const String &p_custom) { return; } - run_filename = scene->get_filename(); + run_filename = scene->get_scene_file_path(); } else if (p_custom != "") { run_filename = p_custom; } if (run_filename == "") { - //evidently, run the scene + // evidently, run the scene if (!ensure_main_scene(false)) { return; } @@ -2309,8 +2339,8 @@ void EditorNode::_run(bool p_current, const String &p_custom) { if (unsaved_cache) { Node *scene = editor_data.get_edited_scene_root(); - if (scene && scene->get_filename() != "") { // Only autosave if there is a scene and if it has a path. - _save_scene_with_preview(scene->get_filename()); + if (scene && scene->get_scene_file_path() != "") { // Only autosave if there is a scene and if it has a path. + _save_scene_with_preview(scene->get_scene_file_path()); } } _menu_option(FILE_SAVE_ALL_SCENES); @@ -2382,7 +2412,7 @@ void EditorNode::_android_build_source_selected(const String &p_file) { export_template_manager->install_android_template_from_file(p_file); } void EditorNode::_menu_option_confirm(int p_option, bool p_confirmed) { - if (!p_confirmed) { //this may be a hack.. + if (!p_confirmed) { // this may be a hack.. current_option = (MenuOptions)p_option; } @@ -2403,7 +2433,7 @@ void EditorNode::_menu_option_confirm(int p_option, bool p_confirmed) { Node *scene = editor_data.get_edited_scene_root(); if (scene) { - file->set_current_path(scene->get_filename()); + file->set_current_path(scene->get_scene_file_path()); }; file->set_title(p_option == FILE_OPEN_SCENE ? TTR("Open Scene") : TTR("Open Base Scene")); file->popup_file_dialog(); @@ -2465,7 +2495,7 @@ void EditorNode::_menu_option_confirm(int p_option, bool p_confirmed) { if (unsaved_cache || p_option == FILE_CLOSE_ALL_AND_QUIT || p_option == FILE_CLOSE_ALL_AND_RUN_PROJECT_MANAGER) { Node *scene_root = editor_data.get_edited_scene_root(tab_closing); if (scene_root) { - String scene_filename = scene_root->get_filename(); + String scene_filename = scene_root->get_scene_file_path(); save_confirmation->get_ok_button()->set_text(TTR("Save & Close")); save_confirmation->set_text(vformat(TTR("Save changes to '%s' before closing?"), scene_filename != "" ? scene_filename : "unsaved scene")); save_confirmation->popup_centered(); @@ -2484,20 +2514,22 @@ void EditorNode::_menu_option_confirm(int p_option, bool p_confirmed) { case SCENE_TAB_CLOSE: case FILE_SAVE_SCENE: { int scene_idx = (p_option == FILE_SAVE_SCENE) ? -1 : tab_closing; - Node *scene = editor_data.get_edited_scene_root(scene_idx); - if (scene && scene->get_filename() != "") { - if (scene_idx != editor_data.get_edited_scene()) { - _save_scene_with_preview(scene->get_filename(), scene_idx); - } else { - _save_scene_with_preview(scene->get_filename()); - } + if (scene && scene->get_scene_file_path() != "") { + if (DirAccess::exists(scene->get_scene_file_path().get_base_dir())) { + if (scene_idx != editor_data.get_edited_scene()) { + _save_scene_with_preview(scene->get_scene_file_path(), scene_idx); + } else { + _save_scene_with_preview(scene->get_scene_file_path()); + } - if (scene_idx != -1) { - _discard_changes(); + if (scene_idx != -1) { + _discard_changes(); + } + save_layout(); + } else { + show_save_accept(vformat(TTR("%s no longer exists! Please specify a new save location."), scene->get_scene_file_path().get_base_dir()), TTR("OK")); } - save_layout(); - break; } [[fallthrough]]; @@ -2539,8 +2571,8 @@ void EditorNode::_menu_option_confirm(int p_option, bool p_confirmed) { file->add_filter("*." + extensions[i] + " ; " + extensions[i].to_upper()); } - if (scene->get_filename() != "") { - String path = scene->get_filename(); + if (scene->get_scene_file_path() != "") { + String path = scene->get_scene_file_path(); file->set_current_path(path); if (extensions.size()) { String ext = path.get_extension().to_lower(); @@ -2638,7 +2670,7 @@ void EditorNode::_menu_option_confirm(int p_option, bool p_confirmed) { break; } - String filename = scene->get_filename(); + String filename = scene->get_scene_file_path(); if (filename == String()) { show_warning(TTR("Can't reload a scene that was never saved.")); @@ -2760,7 +2792,7 @@ void EditorNode::_menu_option_confirm(int p_option, bool p_confirmed) { String unsaved_scenes; int i = _next_unsaved_scene(true, 0); while (i != -1) { - unsaved_scenes += "\n " + editor_data.get_edited_scene_root(i)->get_filename(); + unsaved_scenes += "\n " + editor_data.get_edited_scene_root(i)->get_scene_file_path(); i = _next_unsaved_scene(true, ++i); } @@ -2835,7 +2867,7 @@ void EditorNode::_menu_option_confirm(int p_option, bool p_confirmed) { Node *scene = editor_data.get_edited_scene_root(); if (scene) { - file->set_current_path(scene->get_filename()); + file->set_current_path(scene->get_scene_file_path()); }; file->set_title(TTR("Pick a Main Scene")); file->popup_file_dialog(); @@ -2937,7 +2969,7 @@ int EditorNode::_next_unsaved_scene(bool p_valid_filename, int p_start) { int current = editor_data.get_edited_scene(); bool unsaved = (i == current) ? saved_version != editor_data.get_undo_redo().get_version() : editor_data.get_scene_version(i) != 0; if (unsaved) { - String scene_filename = editor_data.get_edited_scene_root(i)->get_filename(); + String scene_filename = editor_data.get_edited_scene_root(i)->get_scene_file_path(); if (p_valid_filename && scene_filename.length() == 0) { continue; } @@ -2949,7 +2981,7 @@ int EditorNode::_next_unsaved_scene(bool p_valid_filename, int p_start) { void EditorNode::_exit_editor() { exiting = true; - resource_preview->stop(); //stop early to avoid crashes + resource_preview->stop(); // stop early to avoid crashes _save_docks(); // Dim the editor window while it's quitting to make it clearer that it's busy @@ -2969,7 +3001,7 @@ void EditorNode::_discard_changes(const String &p_str) { case SCENE_TAB_CLOSE: { Node *scene = editor_data.get_edited_scene_root(tab_closing); if (scene != nullptr) { - String scene_filename = scene->get_filename(); + String scene_filename = scene->get_scene_file_path(); if (scene_filename != "") { previous_scenes.push_back(scene_filename); } @@ -3055,7 +3087,7 @@ void EditorNode::_editor_select(int p_which) { ERR_FAIL_INDEX(p_which, editor_table.size()); - if (!main_editor_buttons[p_which]->is_visible()) { //button hidden, no editor + if (!main_editor_buttons[p_which]->is_visible()) { // button hidden, no editor return; } @@ -3177,8 +3209,8 @@ void EditorNode::_update_addon_config() { Vector<String> enabled_addons; - for (Map<String, EditorPlugin *>::Element *E = plugin_addons.front(); E; E = E->next()) { - enabled_addons.push_back(E->key()); + for (const KeyValue<String, EditorPlugin *> &E : plugin_addons) { + enabled_addons.push_back(E.key); } if (enabled_addons.size() == 0) { @@ -3197,7 +3229,7 @@ void EditorNode::set_addon_plugin_enabled(const String &p_addon, bool p_enabled, if (!p_enabled) { EditorPlugin *addon = plugin_addons[p_addon]; remove_editor_plugin(addon, p_config_changed); - memdelete(addon); //bye + memdelete(addon); // bye plugin_addons.erase(p_addon); _update_addon_config(); return; @@ -3289,10 +3321,10 @@ void EditorNode::_remove_edited_scene(bool p_change_tab) { void EditorNode::_remove_scene(int index, bool p_change_tab) { if (editor_data.get_edited_scene() == index) { - //Scene to remove is current scene + // Scene to remove is current scene _remove_edited_scene(p_change_tab); } else { - //Scene to remove is not active scene + // Scene to remove is not active scene editor_data.remove_scene(index); } } @@ -3306,7 +3338,7 @@ void EditorNode::set_edited_scene(Node *p_scene) { get_editor_data().set_edited_scene_root(p_scene); if (Object::cast_to<Popup>(p_scene)) { - Object::cast_to<Popup>(p_scene)->show(); //show popups + Object::cast_to<Popup>(p_scene)->show(); // show popups } scene_tree_dock->set_edited_scene(p_scene); if (get_tree()) { @@ -3342,7 +3374,7 @@ Dictionary EditorNode::_get_main_scene_state() { void EditorNode::_set_main_scene_state(Dictionary p_state, Node *p_for_scene) { if (get_edited_scene() != p_for_scene && p_for_scene != nullptr) { - return; //not for this scene + return; // not for this scene } changing_scene = false; @@ -3357,7 +3389,7 @@ void EditorNode::_set_main_scene_state(Dictionary p_state, Node *p_for_scene) { if (p_state.has("editor_index")) { int index = p_state["editor_index"]; - if (current < 2) { //if currently in spatial/2d, only switch to spatial/2d. if currently in script, stay there + if (current < 2) { // if currently in spatial/2d, only switch to spatial/2d. if currently in script, stay there if (index < 2 || !get_edited_scene()) { _editor_select(index); } @@ -3366,7 +3398,7 @@ void EditorNode::_set_main_scene_state(Dictionary p_state, Node *p_for_scene) { if (get_edited_scene()) { if (current < 2) { - //use heuristic instead + // use heuristic instead int n2d = 0, n3d = 0; _find_node_types(get_edited_scene(), n2d, n3d); if (n2d > n3d) { @@ -3388,7 +3420,7 @@ void EditorNode::_set_main_scene_state(Dictionary p_state, Node *p_for_scene) { scene_tree_dock->set_filter(p_state["node_filter"]); } - //this should only happen at the very end + // this should only happen at the very end EditorDebuggerNode::get_singleton()->update_live_edit_root(); ScriptEditor::get_singleton()->set_scene_root_script(editor_data.get_scene_root_script(editor_data.get_edited_scene())); @@ -3409,7 +3441,7 @@ void EditorNode::_clear_undo_history() { } void EditorNode::set_current_scene(int p_idx) { - //Save the folding in case the scene gets reloaded. + // Save the folding in case the scene gets reloaded. if (editor_data.get_scene_path(p_idx) != "" && editor_data.get_edited_scene_root(p_idx)) { editor_folding.save_scene_folding(editor_data.get_edited_scene_root(p_idx), editor_data.get_scene_path(p_idx)); } @@ -3437,7 +3469,7 @@ void EditorNode::set_current_scene(int p_idx) { Node *new_scene = editor_data.get_edited_scene_root(); if (Object::cast_to<Popup>(new_scene)) { - Object::cast_to<Popup>(new_scene)->show(); //show popups + Object::cast_to<Popup>(new_scene)->show(); // show popups } scene_tree_dock->set_edited_scene(new_scene); @@ -3456,7 +3488,7 @@ void EditorNode::set_current_scene(int p_idx) { _update_title(); - call_deferred(SNAME("_set_main_scene_state"), state, get_edited_scene()); //do after everything else is done setting up + call_deferred(SNAME("_set_main_scene_state"), state, get_edited_scene()); // do after everything else is done setting up } bool EditorNode::is_scene_open(const String &p_path) { @@ -3558,18 +3590,18 @@ Error EditorNode::load_scene(const String &p_scene, bool p_ignore_broken_deps, b return ERR_FILE_MISSING_DEPENDENCIES; } - dependency_errors.erase(lpath); //at least not self path + dependency_errors.erase(lpath); // at least not self path - for (Map<String, Set<String>>::Element *E = dependency_errors.front(); E; E = E->next()) { - String txt = vformat(TTR("Scene '%s' has broken dependencies:"), E->key()) + "\n"; - for (Set<String>::Element *F = E->get().front(); F; F = F->next()) { + for (KeyValue<String, Set<String>> &E : dependency_errors) { + String txt = vformat(TTR("Scene '%s' has broken dependencies:"), E.key) + "\n"; + for (Set<String>::Element *F = E.value.front(); F; F = F->next()) { txt += "\t" + F->get() + "\n"; } add_io_error(txt); } if (ResourceCache::has(lpath)) { - //used from somewhere else? no problem! update state and replace sdata + // used from somewhere else? no problem! update state and replace sdata Ref<PackedScene> ps = Ref<PackedScene>(Object::cast_to<PackedScene>(ResourceCache::get(lpath))); if (ps.is_valid()) { ps->replace_state(sdata->get_state()); @@ -3578,7 +3610,7 @@ Error EditorNode::load_scene(const String &p_scene, bool p_ignore_broken_deps, b } } else { - sdata->set_path(lpath, true); //take over path + sdata->set_path(lpath, true); // take over path } Node *new_scene = sdata->instantiate(PackedScene::GEN_EDIT_STATE_MAIN); @@ -3598,7 +3630,7 @@ Error EditorNode::load_scene(const String &p_scene, bool p_ignore_broken_deps, b Ref<SceneState> state = sdata->get_state(); state->set_path(lpath); new_scene->set_scene_inherited_state(state); - new_scene->set_filename(String()); + new_scene->set_scene_file_path(String()); } new_scene->set_scene_instance_state(Ref<SceneState>()); @@ -3771,7 +3803,7 @@ void EditorNode::_load_error_notify(void *p_ud, const String &p_text) { } bool EditorNode::_find_scene_in_use(Node *p_node, const String &p_path) const { - if (p_node->get_filename() == p_path) { + if (p_node->get_scene_file_path() == p_path) { return true; } @@ -3817,7 +3849,8 @@ void EditorNode::register_editor_types() { GDREGISTER_VIRTUAL_CLASS(EditorInterface); GDREGISTER_CLASS(EditorExportPlugin); GDREGISTER_CLASS(EditorResourceConversionPlugin); - GDREGISTER_CLASS(EditorSceneImporter); + GDREGISTER_CLASS(EditorSceneFormatImporter); + GDREGISTER_CLASS(EditorScenePostImportPlugin); GDREGISTER_CLASS(EditorInspector); GDREGISTER_CLASS(EditorInspectorPlugin); GDREGISTER_CLASS(EditorProperty); @@ -3827,8 +3860,6 @@ void EditorNode::register_editor_types() { GDREGISTER_CLASS(EditorSpinSlider); GDREGISTER_CLASS(EditorResourcePicker); GDREGISTER_CLASS(EditorScriptPicker); - GDREGISTER_CLASS(EditorSceneImporterMesh); - GDREGISTER_CLASS(EditorSceneImporterMeshNode3D); GDREGISTER_VIRTUAL_CLASS(FileSystemDock); @@ -3949,7 +3980,7 @@ void EditorNode::_pick_main_scene_custom_action(const String &p_custom_action_na pick_main_scene->hide(); current_option = SETTINGS_PICK_MAIN_SCENE; - _dialog_action(scene->get_filename()); + _dialog_action(scene->get_scene_file_path()); } } @@ -4025,8 +4056,8 @@ Ref<Texture2D> EditorNode::get_class_icon(const String &p_class, const String &p } const Map<String, Vector<EditorData::CustomType>> &p_map = EditorNode::get_editor_data().get_custom_types(); - for (const Map<String, Vector<EditorData::CustomType>>::Element *E = p_map.front(); E; E = E->next()) { - const Vector<EditorData::CustomType> &ct = E->value(); + for (const KeyValue<String, Vector<EditorData::CustomType>> &E : p_map) { + const Vector<EditorData::CustomType> &ct = E.value; for (int i = 0; i < ct.size(); ++i) { if (ct[i].name == p_class) { if (ct[i].icon.is_valid()) { @@ -4150,6 +4181,13 @@ void EditorNode::show_accept(const String &p_text, const String &p_title) { accept->popup_centered(); } +void EditorNode::show_save_accept(const String &p_text, const String &p_title) { + current_option = -1; + save_accept->get_ok_button()->set_text(p_title); + save_accept->set_text(p_text); + save_accept->popup_centered(); +} + void EditorNode::show_warning(const String &p_text, const String &p_title) { if (warning->is_inside_tree()) { warning->set_text(p_text); @@ -4186,7 +4224,7 @@ void EditorNode::_dock_make_float() { ERR_FAIL_COND(!dock); const Size2i borders = Size2i(4, 4) * EDSCALE; - Size2 dock_size = dock->get_size() + borders * 2; //remember size + Size2 dock_size = dock->get_size() + borders * 2; // remember size Point2 dock_screen_pos = dock->get_global_position() + get_tree()->get_root()->get_position() - borders; print_line("dock pos: " + dock->get_global_position() + " window pos: " + get_tree()->get_root()->get_position()); @@ -4426,7 +4464,7 @@ void EditorNode::_dock_select_draw() { void EditorNode::_save_docks() { if (waiting_for_first_scan) { - return; //scanning, do not touch docks + return; // scanning, do not touch docks } Ref<ConfigFile> config; config.instantiate(); @@ -4497,7 +4535,7 @@ void EditorNode::_load_docks() { config.instantiate(); Error err = config->load(EditorSettings::get_singleton()->get_project_settings_dir().plus_file("editor_layout.cfg")); if (err != OK) { - //no config + // no config if (overridden_default_layout >= 0) { _layout_menu_option(overridden_default_layout); } @@ -4610,7 +4648,7 @@ void EditorNode::_load_docks_from_config(Ref<ConfigFile> p_layout, const String for (int j = 0; j < names.size(); j++) { String name = names[j]; - //find it, in a horribly inefficient way + // find it, in a horribly inefficient way int atidx = -1; Control *node = nullptr; for (int k = 0; k < DOCK_SLOT_MAX; k++) { @@ -4624,7 +4662,7 @@ void EditorNode::_load_docks_from_config(Ref<ConfigFile> p_layout, const String atidx = k; break; } - if (atidx == -1) { //well, it's not anywhere + if (atidx == -1) { // well, it's not anywhere continue; } @@ -4740,7 +4778,7 @@ bool EditorNode::has_scenes_in_session() { } bool EditorNode::ensure_main_scene(bool p_from_native) { - pick_main_scene->set_meta("from_native", p_from_native); //whether from play button or native run + pick_main_scene->set_meta("from_native", p_from_native); // whether from play button or native run String main_scene = GLOBAL_DEF("application/run/main_scene", ""); if (main_scene == "") { @@ -4861,7 +4899,7 @@ void EditorNode::_update_layouts_menu() { config.instantiate(); Error err = config->load(EditorSettings::get_singleton()->get_editor_layouts_config()); if (err != OK) { - return; //no config + return; // no config } List<String> layouts; @@ -4902,7 +4940,7 @@ void EditorNode::_layout_menu_option(int p_id) { config.instantiate(); Error err = config->load(EditorSettings::get_singleton()->get_editor_layouts_config()); if (err != OK) { - return; //no config + return; // no config } _load_docks_from_config(config, editor_layouts->get_item_text(p_id)); @@ -4932,7 +4970,7 @@ void EditorNode::_scene_tab_closed(int p_tab, int option) { editor_data.get_scene_version(p_tab) != 0; if (unsaved) { save_confirmation->get_ok_button()->set_text(TTR("Save & Close")); - save_confirmation->set_text(vformat(TTR("Save changes to '%s' before closing?"), scene->get_filename() != "" ? scene->get_filename() : "unsaved scene")); + save_confirmation->set_text(vformat(TTR("Save changes to '%s' before closing?"), scene->get_scene_file_path() != "" ? scene->get_scene_file_path() : "unsaved scene")); save_confirmation->popup_centered(); } else { _discard_changes(); @@ -5043,7 +5081,7 @@ void EditorNode::_scene_tab_changed(int p_tab) { bool unsaved = (saved_version != editor_data.get_undo_redo().get_version()); if (p_tab == editor_data.get_edited_scene()) { - return; //pointless + return; // pointless } uint64_t next_scene_version = editor_data.get_scene_version(p_tab); @@ -5246,11 +5284,11 @@ Variant EditorNode::drag_resource(const Ref<Resource> &p_res, Control *p_from) { Ref<Texture2D> preview; { - //todo make proper previews + // todo make proper previews Ref<ImageTexture> texture = gui_base->get_theme_icon(SNAME("FileBigThumb"), SNAME("EditorIcons")); Ref<Image> img = texture->get_image(); img = img->duplicate(); - img->resize(48, 48); //meh + img->resize(48, 48); // meh Ref<ImageTexture> resized_pic = Ref<ImageTexture>(memnew(ImageTexture)); resized_pic->create_from_image(img); preview = resized_pic; @@ -5268,7 +5306,7 @@ Variant EditorNode::drag_resource(const Ref<Resource> &p_res, Control *p_from) { drag_control->add_child(label); - p_from->set_drag_preview(drag_control); //wait until it enters scene + p_from->set_drag_preview(drag_control); // wait until it enters scene label->set_position(Point2((preview->get_width() - label->get_minimum_size().width) / 2, preview->get_height())); @@ -5322,7 +5360,7 @@ Variant EditorNode::drag_files_and_dirs(const Vector<String> &p_paths, Control * } vbox->add_child(label); } - p_from->set_drag_preview(vbox); //wait until it enters scene + p_from->set_drag_preview(vbox); // wait until it enters scene Dictionary drag_data; drag_data["type"] = has_folder ? "files_and_dirs" : "files"; @@ -5439,7 +5477,7 @@ void EditorNode::reload_scene(const String &p_path) { if (scene_idx == -1) { if (get_edited_scene()) { - //scene is not open, so at it might be instantiated. We'll refresh the whole scene later. + // scene is not open, so at it might be instantiated. We'll refresh the whole scene later. editor_data.get_undo_redo().clear_history(); } return; @@ -5450,17 +5488,17 @@ void EditorNode::reload_scene(const String &p_path) { _set_scene_metadata(p_path); } - //remove scene + // remove scene _remove_scene(scene_idx, false); - //reload scene + // reload scene load_scene(p_path, true, false, true, true); - //adjust index so tab is back a the previous position + // adjust index so tab is back a the previous position editor_data.move_edited_scene_to_index(scene_idx); get_undo_redo()->clear_history(); - //recover the tab + // recover the tab scene_tabs->set_current_tab(current_tab); } @@ -5560,7 +5598,7 @@ void EditorNode::_update_video_driver_color() { void EditorNode::_video_driver_selected(int p_which) { String driver = video_driver->get_item_metadata(p_which); - String current = ""; //OS::get_singleton()->get_video_driver_name(OS::get_singleton()->get_current_video_driver()); + String current = ""; // OS::get_singleton()->get_video_driver_name(OS::get_singleton()->get_current_video_driver()); if (driver == current) { return; @@ -5749,9 +5787,9 @@ EditorNode::EditorNode() { PhysicsServer2D::get_singleton()->set_active(false); // no physics by default if editor ScriptServer::set_scripting_enabled(false); // no scripting by default if editor - EditorHelp::generate_doc(); //before any editor classes are created + EditorHelp::generate_doc(); // before any editor classes are created SceneState::set_disable_placeholders(true); - ResourceLoader::clear_translation_remaps(); //no remaps using during editor + ResourceLoader::clear_translation_remaps(); // no remaps using during editor ResourceLoader::clear_path_remaps(); Input *id = Input::get_singleton(); @@ -5765,8 +5803,8 @@ EditorNode::EditorNode() { } if (!found_touchscreen && Input::get_singleton()) { - //only if no touchscreen ui hint, set emulation - id->set_emulate_touch_from_mouse(false); //just disable just in case + // only if no touchscreen ui hint, set emulation + id->set_emulate_touch_from_mouse(false); // just disable just in case } DisplayServer::get_singleton()->cursor_set_custom_image(RES()); } @@ -5833,7 +5871,7 @@ EditorNode::EditorNode() { ResourceLoader::set_error_notify_func(this, _load_error_notify); ResourceLoader::set_dependency_error_notify_func(this, _dependency_error_report); - { //register importers at the beginning, so dialogs are created with the right extensions + { // register importers at the beginning, so dialogs are created with the right extensions Ref<ResourceImporterTexture> import_texture; import_texture.instantiate(); ResourceFormatImporter::get_singleton()->add_importer(import_texture); @@ -5899,7 +5937,7 @@ EditorNode::EditorNode() { ResourceFormatImporter::get_singleton()->add_importer(import_scene); { - Ref<EditorSceneImporterCollada> import_collada; + Ref<EditorSceneFormatImporterCollada> import_collada; import_collada.instantiate(); import_scene->add_importer(import_collada); @@ -5907,7 +5945,7 @@ EditorNode::EditorNode() { import_obj2.instantiate(); import_scene->add_importer(import_obj2); - Ref<EditorSceneImporterESCN> import_escn; + Ref<EditorSceneFormatImporterESCN> import_escn; import_escn.instantiate(); import_scene->add_importer(import_escn); } @@ -5936,7 +5974,7 @@ EditorNode::EditorNode() { EditorFileSystem *efs = memnew(EditorFileSystem); add_child(efs); - //used for previews + // used for previews FileDialog::get_icon_func = _file_dialog_get_icon; FileDialog::register_func = _file_dialog_register; FileDialog::unregister_func = _file_dialog_unregister; @@ -5955,7 +5993,7 @@ EditorNode::EditorNode() { ClassDB::set_class_enabled("RootMotionView", true); - //defs here, use EDITOR_GET in logic + // defs here, use EDITOR_GET in logic EDITOR_DEF_RST("interface/scene_tabs/always_show_close_button", false); EDITOR_DEF_RST("interface/scene_tabs/resize_if_many_tabs", true); EDITOR_DEF_RST("interface/scene_tabs/minimum_width", 50); @@ -5984,6 +6022,11 @@ EditorNode::EditorNode() { EditorSettings::get_singleton()->add_property_hint(PropertyInfo(Variant::INT, "interface/inspector/default_color_picker_shape", PROPERTY_HINT_ENUM, "HSV Rectangle,HSV Rectangle Wheel,VHS Circle", PROPERTY_USAGE_DEFAULT)); EDITOR_DEF("run/auto_save/save_before_running", true); + const Vector<String> textfile_ext = ((String)(EditorSettings::get_singleton()->get("docks/filesystem/textfile_extensions"))).split(",", false); + for (const String &E : textfile_ext) { + textfile_extensions.insert(E); + } + theme_base = memnew(Control); add_child(theme_base); theme_base->set_anchors_and_offsets_preset(Control::PRESET_WIDE); @@ -6174,22 +6217,22 @@ EditorNode::EditorNode() { tab_preview->set_position(Point2(2, 2) * EDSCALE); tab_preview_panel->add_child(tab_preview); - scene_tabs = memnew(Tabs); + scene_tabs = memnew(TabBar); scene_tabs->add_theme_style_override("tab_selected", gui_base->get_theme_stylebox(SNAME("SceneTabFG"), SNAME("EditorStyles"))); scene_tabs->add_theme_style_override("tab_unselected", gui_base->get_theme_stylebox(SNAME("SceneTabBG"), SNAME("EditorStyles"))); scene_tabs->set_select_with_rmb(true); scene_tabs->add_tab("unsaved"); - scene_tabs->set_tab_align(Tabs::ALIGN_LEFT); - scene_tabs->set_tab_close_display_policy((bool(EDITOR_DEF("interface/scene_tabs/always_show_close_button", false)) ? Tabs::CLOSE_BUTTON_SHOW_ALWAYS : Tabs::CLOSE_BUTTON_SHOW_ACTIVE_ONLY)); + scene_tabs->set_tab_align(TabBar::ALIGN_LEFT); + scene_tabs->set_tab_close_display_policy((bool(EDITOR_DEF("interface/scene_tabs/always_show_close_button", false)) ? TabBar::CLOSE_BUTTON_SHOW_ALWAYS : TabBar::CLOSE_BUTTON_SHOW_ACTIVE_ONLY)); scene_tabs->set_min_width(int(EDITOR_DEF("interface/scene_tabs/minimum_width", 50)) * EDSCALE); scene_tabs->set_drag_to_rearrange_enabled(true); scene_tabs->connect("tab_changed", callable_mp(this, &EditorNode::_scene_tab_changed)); - scene_tabs->connect("right_button_pressed", callable_mp(this, &EditorNode::_scene_tab_script_edited)); + scene_tabs->connect("tab_rmb_clicked", callable_mp(this, &EditorNode::_scene_tab_script_edited)); scene_tabs->connect("tab_closed", callable_mp(this, &EditorNode::_scene_tab_closed), varray(SCENE_TAB_CLOSE)); scene_tabs->connect("tab_hovered", callable_mp(this, &EditorNode::_scene_tab_hovered)); scene_tabs->connect("mouse_exited", callable_mp(this, &EditorNode::_scene_tab_exit)); scene_tabs->connect("gui_input", callable_mp(this, &EditorNode::_scene_tab_input)); - scene_tabs->connect("reposition_active_tab_request", callable_mp(this, &EditorNode::_reposition_active_tab)); + scene_tabs->connect("active_tab_rearranged", callable_mp(this, &EditorNode::_reposition_active_tab)); scene_tabs->connect("resized", callable_mp(this, &EditorNode::_update_scene_tabs)); tabbar_container = memnew(HBoxContainer); @@ -6263,6 +6306,10 @@ EditorNode::EditorNode() { gui_base->add_child(accept); accept->connect("confirmed", callable_mp(this, &EditorNode::_menu_confirm_current)); + save_accept = memnew(AcceptDialog); + gui_base->add_child(save_accept); + save_accept->connect("confirmed", callable_mp(this, &EditorNode::_menu_option), make_binds((int)MenuOptions::FILE_SAVE_AS_SCENE)); + project_export = memnew(ProjectExportDialog); gui_base->add_child(project_export); @@ -6702,6 +6749,9 @@ EditorNode::EditorNode() { bottom_panel_hb_editors->set_h_size_flags(Control::SIZE_EXPAND_FILL); bottom_panel_hb->add_child(bottom_panel_hb_editors); + editor_toaster = memnew(EditorToaster); + bottom_panel_hb->add_child(editor_toaster); + VBoxContainer *version_info_vbc = memnew(VBoxContainer); bottom_panel_hb->add_child(version_info_vbc); @@ -6874,7 +6924,7 @@ EditorNode::EditorNode() { EditorAudioBuses *audio_bus_editor = EditorAudioBuses::register_editor(); - ScriptTextEditor::register_editor(); //register one for text scripts + ScriptTextEditor::register_editor(); // register one for text scripts TextEditor::register_editor(); if (StreamPeerSSL::is_available()) { @@ -6883,13 +6933,13 @@ EditorNode::EditorNode() { WARN_PRINT("Asset Library not available, as it requires SSL to work."); } - //add interface before adding plugins + // add interface before adding plugins editor_interface = memnew(EditorInterface); add_child(editor_interface); - //more visually meaningful to have this later - raise_bottom_panel_item(AnimationPlayerEditor::singleton); + // more visually meaningful to have this later + raise_bottom_panel_item(AnimationPlayerEditor::get_singleton()); add_editor_plugin(VersionControlEditorPlugin::get_singleton()); add_editor_plugin(memnew(ShaderEditorPlugin(this))); @@ -7163,20 +7213,24 @@ bool EditorPluginList::forward_gui_input(const Ref<InputEvent> &p_event) { return discard; } -bool EditorPluginList::forward_spatial_gui_input(Camera3D *p_camera, const Ref<InputEvent> &p_event, bool serve_when_force_input_enabled) { - bool discard = false; +EditorPlugin::AfterGUIInput EditorPluginList::forward_spatial_gui_input(Camera3D *p_camera, const Ref<InputEvent> &p_event, bool serve_when_force_input_enabled) { + EditorPlugin::AfterGUIInput after = EditorPlugin::AFTER_GUI_INPUT_PASS; for (int i = 0; i < plugins_list.size(); i++) { if ((!serve_when_force_input_enabled) && plugins_list[i]->is_input_event_forwarding_always_enabled()) { continue; } - if (plugins_list[i]->forward_spatial_gui_input(p_camera, p_event)) { - discard = true; + EditorPlugin::AfterGUIInput current_after = plugins_list[i]->forward_spatial_gui_input(p_camera, p_event); + if (current_after == EditorPlugin::AFTER_GUI_INPUT_STOP) { + after = EditorPlugin::AFTER_GUI_INPUT_STOP; + } + if (after != EditorPlugin::AFTER_GUI_INPUT_STOP && current_after == EditorPlugin::AFTER_GUI_INPUT_DESELECT) { + after = EditorPlugin::AFTER_GUI_INPUT_DESELECT; } } - return discard; + return after; } void EditorPluginList::forward_canvas_draw_over_viewport(Control *p_overlay) { |