diff options
Diffstat (limited to 'editor/editor_node.cpp')
-rw-r--r-- | editor/editor_node.cpp | 385 |
1 files changed, 251 insertions, 134 deletions
diff --git a/editor/editor_node.cpp b/editor/editor_node.cpp index 5705629c56..2c3a84857a 100644 --- a/editor/editor_node.cpp +++ b/editor/editor_node.cpp @@ -60,6 +60,7 @@ #include "editor/import/editor_import_collada.h" #include "editor/import/editor_scene_importer_gltf.h" #include "editor/import/resource_importer_bitmask.h" +#include "editor/import/resource_importer_csv.h" #include "editor/import/resource_importer_csv_translation.h" #include "editor/import/resource_importer_image.h" #include "editor/import/resource_importer_layered_texture.h" @@ -122,6 +123,7 @@ #include "editor/plugins/theme_editor_plugin.h" #include "editor/plugins/tile_map_editor_plugin.h" #include "editor/plugins/tile_set_editor_plugin.h" +#include "editor/plugins/version_control_editor_plugin.h" #include "editor/plugins/visual_shader_editor_plugin.h" #include "editor/pvrtc_compress.h" #include "editor/register_exporters.h" @@ -135,6 +137,8 @@ void EditorNode::_update_scene_tabs() { bool show_rb = EditorSettings::get_singleton()->get("interface/scene_tabs/show_script_button"); + OS::get_singleton()->global_menu_clear("_dock"); + scene_tabs->clear_tabs(); Ref<Texture> script_icon = gui_base->get_icon("Script", "EditorIcons"); for (int i = 0; i < editor_data.get_edited_scene_count(); i++) { @@ -149,11 +153,16 @@ void EditorNode::_update_scene_tabs() { bool unsaved = (i == current) ? saved_version != editor_data.get_undo_redo().get_version() : editor_data.get_scene_version(i) != 0; scene_tabs->add_tab(editor_data.get_scene_title(i) + (unsaved ? "(*)" : ""), icon); + OS::get_singleton()->global_menu_add_item("_dock", editor_data.get_scene_title(i) + (unsaved ? "(*)" : ""), GLOBAL_SCENE, i); + if (show_rb && editor_data.get_scene_root_script(i).is_valid()) { scene_tabs->set_tab_right_button(i, script_icon); } } + OS::get_singleton()->global_menu_add_separator("_dock"); + OS::get_singleton()->global_menu_add_item("_dock", TTR("New Window"), GLOBAL_NEW_WINDOW, Variant()); + scene_tabs->set_current_tab(editor_data.get_edited_scene()); if (scene_tabs->get_offset_buttons_visible()) { @@ -177,6 +186,20 @@ void EditorNode::_update_scene_tabs() { } } +void EditorNode::_version_control_menu_option(int p_idx) { + + switch (vcs_actions_menu->get_item_id(p_idx)) { + case RUN_VCS_SETTINGS: { + + VersionControlEditorPlugin::get_singleton()->popup_vcs_set_up_dialog(gui_base); + } break; + case RUN_VCS_SHUT_DOWN: { + + VersionControlEditorPlugin::get_singleton()->shut_down(); + } break; + } +} + void EditorNode::_update_title() { String appname = ProjectSettings::get_singleton()->get("application/config/name"); @@ -290,6 +313,7 @@ void EditorNode::_notification(int p_what) { get_tree()->get_root()->set_as_audio_listener_2d(false); get_tree()->set_auto_accept_quit(false); get_tree()->connect("files_dropped", this, "_dropped_files"); + get_tree()->connect("global_menu_action", this, "_global_menu_action"); /* DO NOT LOAD SCENES HERE, WAIT FOR FILE SCANNING AND REIMPORT TO COMPLETE */ } break; @@ -334,6 +358,11 @@ void EditorNode::_notification(int p_what) { OS::get_singleton()->set_low_processor_usage_mode_sleep_usec(int(EDITOR_GET("interface/editor/unfocused_low_processor_mode_sleep_usec"))); } break; + case MainLoop::NOTIFICATION_WM_ABOUT: { + + show_about(); + } break; + case MainLoop::NOTIFICATION_WM_QUIT_REQUEST: { _menu_option_confirm(FILE_QUIT, false); @@ -397,6 +426,8 @@ void EditorNode::_notification(int p_what) { distraction_free->set_icon(gui_base->get_icon("DistractionFree", "EditorIcons")); scene_tab_add->set_icon(gui_base->get_icon("Add", "EditorIcons")); + bottom_panel_raise->set_icon(gui_base->get_icon("ExpandBottomDock", "EditorIcons")); + // clear_button->set_icon(gui_base->get_icon("Close", "EditorIcons")); don't have access to that node. needs to become a class property dock_tab_move_left->set_icon(theme->get_icon("Back", "EditorIcons")); dock_tab_move_right->set_icon(theme->get_icon("Forward", "EditorIcons")); @@ -872,7 +903,7 @@ void EditorNode::_set_scene_metadata(const String &p_file, int p_idx) { } Error err = cf->save(path); - ERR_FAIL_COND(err != OK); + ERR_FAIL_COND_MSG(err != OK, "Cannot save config file to '" + path + "'."); } bool EditorNode::_find_and_save_resource(RES p_res, Map<RES, bool> &processed, int32_t flags) { @@ -1574,6 +1605,7 @@ void EditorNode::push_item(Object *p_object, const String &p_property, bool p_in get_inspector()->edit(NULL); node_dock->set_node(NULL); scene_tree_dock->set_selected(NULL); + inspector_dock->update(NULL); return; } @@ -1662,9 +1694,10 @@ void EditorNode::_edit_current() { Resource *current_res = Object::cast_to<Resource>(current_obj); ERR_FAIL_COND(!current_res); - scene_tree_dock->set_selected(NULL); get_inspector()->edit(current_res); + scene_tree_dock->set_selected(NULL); node_dock->set_node(NULL); + inspector_dock->update(NULL); EditorNode::get_singleton()->get_import_dock()->set_edit_path(current_res->get_path()); int subr_idx = current_res->get_path().find("::"); @@ -1691,9 +1724,11 @@ void EditorNode::_edit_current() { if (current_node->is_inside_tree()) { node_dock->set_node(current_node); scene_tree_dock->set_selected(current_node); + inspector_dock->update(current_node); } else { node_dock->set_node(NULL); scene_tree_dock->set_selected(NULL); + inspector_dock->update(NULL); } if (get_edited_scene() && get_edited_scene()->get_filename() != String()) { @@ -1713,6 +1748,8 @@ void EditorNode::_edit_current() { get_inspector()->edit(current_obj); node_dock->set_node(NULL); + scene_tree_dock->set_selected(NULL); + inspector_dock->update(NULL); } inspector_dock->set_warning(editable_warning); @@ -1814,6 +1851,7 @@ void EditorNode::_run(bool p_current, const String &p_custom) { String main_scene; String run_filename; String args; + bool skip_breakpoints; if (p_current || (editor_data.get_edited_scene_root() && p_custom == editor_data.get_edited_scene_root()->get_filename())) { @@ -1879,8 +1917,9 @@ void EditorNode::_run(bool p_current, const String &p_custom) { editor_data.get_editor_breakpoints(&breakpoints); args = ProjectSettings::get_singleton()->get("editor/main_run_args"); + skip_breakpoints = ScriptEditor::get_singleton()->get_debugger()->is_skip_breakpoints(); - Error error = editor_run.run(run_filename, args, breakpoints); + Error error = editor_run.run(run_filename, args, breakpoints, skip_breakpoints); if (error != OK) { @@ -1913,10 +1952,7 @@ void EditorNode::_menu_option_confirm(int p_option, bool p_confirmed) { switch (p_option) { case FILE_NEW_SCENE: { - int idx = editor_data.add_edited_scene(-1); - _scene_tab_changed(idx); - editor_data.clear_editor_states(); - _update_scene_tabs(); + new_scene(); } break; case FILE_NEW_INHERITED_SCENE: @@ -1963,6 +1999,7 @@ void EditorNode::_menu_option_confirm(int p_option, bool p_confirmed) { break; opening_prev = true; open_request(previous_scenes.back()->get()); + previous_scenes.pop_back(); } break; case FILE_CLOSE_OTHERS: @@ -2175,27 +2212,27 @@ void EditorNode::_menu_option_confirm(int p_option, bool p_confirmed) { case EDIT_UNDO: { if (Input::get_singleton()->get_mouse_button_mask() & 0x7) { - log->add_message("Can't UNDO while mouse buttons are pressed."); + log->add_message("Can't undo while mouse buttons are pressed.", EditorLog::MSG_TYPE_EDITOR); } else { String action = editor_data.get_undo_redo().get_current_action_name(); if (!editor_data.get_undo_redo().undo()) { - log->add_message("There is nothing to UNDO."); + log->add_message("Nothing to undo.", EditorLog::MSG_TYPE_EDITOR); } else if (action != "") { - log->add_message("UNDO: " + action); + log->add_message("Undo: " + action, EditorLog::MSG_TYPE_EDITOR); } } } break; case EDIT_REDO: { if (Input::get_singleton()->get_mouse_button_mask() & 0x7) { - log->add_message("Can't REDO while mouse buttons are pressed."); + log->add_message("Can't redo while mouse buttons are pressed.", EditorLog::MSG_TYPE_EDITOR); } else { if (!editor_data.get_undo_redo().redo()) { - log->add_message("There is nothing to REDO."); + log->add_message("Nothing to redo.", EditorLog::MSG_TYPE_EDITOR); } else { String action = editor_data.get_undo_redo().get_current_action_name(); - log->add_message("REDO: " + action); + log->add_message("Redo: " + action, EditorLog::MSG_TYPE_EDITOR); } } } break; @@ -2328,6 +2365,9 @@ void EditorNode::_menu_option_confirm(int p_option, bool p_confirmed) { } } } break; + case RUN_PROJECT_DATA_FOLDER: { + OS::get_singleton()->shell_open(String("file://") + OS::get_singleton()->get_user_data_dir()); + } break; case FILE_EXPLORE_ANDROID_BUILD_TEMPLATES: { OS::get_singleton()->shell_open("file://" + ProjectSettings::get_singleton()->get_resource_path().plus_file("android")); } break; @@ -2482,7 +2522,7 @@ void EditorNode::_menu_option_confirm(int p_option, bool p_confirmed) { bool was_visible = OS::get_singleton()->is_console_visible(); OS::get_singleton()->set_console_visible(!was_visible); - EditorSettings::get_singleton()->set_setting("interface/editor/hide_console_window", !was_visible); + EditorSettings::get_singleton()->set_setting("interface/editor/hide_console_window", was_visible); } break; case EDITOR_SCREENSHOT: { @@ -2534,8 +2574,6 @@ void EditorNode::_menu_option_confirm(int p_option, bool p_confirmed) { save_all_scenes(); restart_editor(); } break; - default: { - } } } @@ -2560,7 +2598,7 @@ void EditorNode::_save_screenshot(NodePath p_path) { img->flip_y(); viewport->set_clear_mode(Viewport::CLEAR_MODE_ALWAYS); Error error = img->save_png(p_path); - ERR_FAIL_COND(error != OK); + ERR_FAIL_COND_MSG(error != OK, "Cannot save screenshot to file '" + p_path + "'."); } void EditorNode::_tool_menu_option(int p_idx) { @@ -2568,9 +2606,6 @@ void EditorNode::_tool_menu_option(int p_idx) { case TOOLS_ORPHAN_RESOURCES: { orphan_resources->show(); } break; - case RUN_PROJECT_DATA_FOLDER: { - OS::get_singleton()->shell_open(String("file://") + OS::get_singleton()->get_user_data_dir()); - } break; case TOOLS_CUSTOM: { if (tool_menu->get_item_submenu(p_idx) == "") { Array params = tool_menu->get_item_metadata(p_idx); @@ -2613,11 +2648,8 @@ void EditorNode::_exit_editor() { 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. - // No transition is applied, as the effect needs to be visible immediately - float c = 1.0f - float(EDITOR_GET("interface/editor/dim_amount")); - Color dim_color = Color(c, c, c); - gui_base->set_modulate(dim_color); + // Dim the editor window while it's quitting to make it clearer that it's busy + dim_editor(true, true); get_tree()->quit(); } @@ -2634,6 +2666,14 @@ void EditorNode::_discard_changes(const String &p_str) { case FILE_CLOSE_ALL: case SCENE_TAB_CLOSE: { + Node *scene = editor_data.get_edited_scene_root(tab_closing); + if (scene != NULL) { + String scene_filename = scene->get_filename(); + if (scene_filename != "") { + previous_scenes.push_back(scene_filename); + } + } + _remove_scene(tab_closing); _update_scene_tabs(); @@ -2699,6 +2739,21 @@ void EditorNode::_update_debug_options() { if (check_reload_scripts) _menu_option_confirm(RUN_RELOAD_SCRIPTS, true); } +void EditorNode::_update_file_menu_opened() { + + Ref<ShortCut> close_scene_sc = ED_GET_SHORTCUT("editor/close_scene"); + close_scene_sc->set_name(TTR("Close Scene")); + Ref<ShortCut> reopen_closed_scene_sc = ED_GET_SHORTCUT("editor/reopen_closed_scene"); + reopen_closed_scene_sc->set_name(TTR("Reopen Closed Scene")); + PopupMenu *pop = file_menu->get_popup(); + pop->set_item_disabled(pop->get_item_index(FILE_OPEN_PREV), previous_scenes.empty()); +} + +void EditorNode::_update_file_menu_closed() { + PopupMenu *pop = file_menu->get_popup(); + pop->set_item_disabled(pop->get_item_index(FILE_OPEN_PREV), false); +} + Control *EditorNode::get_viewport() { return viewport; @@ -2751,6 +2806,19 @@ void EditorNode::_editor_select(int p_which) { } } +void EditorNode::select_editor_by_name(const String &p_name) { + ERR_FAIL_COND(p_name == ""); + + for (int i = 0; i < main_editor_buttons.size(); i++) { + if (main_editor_buttons[i]->get_text() == p_name) { + _editor_select(i); + return; + } + } + + ERR_FAIL_MSG("The editor name '" + p_name + "' was not found."); +} + void EditorNode::add_editor_plugin(EditorPlugin *p_editor, bool p_config_changed) { if (p_editor->has_main_screen()) { @@ -2874,36 +2942,39 @@ void EditorNode::set_addon_plugin_enabled(const String &p_addon, bool p_enabled, return; } - String path = cf->get_value("plugin", "script"); - path = String("res://addons").plus_file(p_addon).plus_file(path); + String script_path = cf->get_value("plugin", "script"); + Ref<Script> script; // We need to save it for creating "ep" below. - Ref<Script> script = ResourceLoader::load(path); + // Only try to load the script if it has a name. Else, the plugin has no init script. + if (script_path.length() > 0) { + script_path = String("res://addons").plus_file(p_addon).plus_file(script_path); + script = ResourceLoader::load(script_path); - if (script.is_null()) { - show_warning(vformat(TTR("Unable to load addon script from path: '%s'."), path)); - return; - } + if (script.is_null()) { + show_warning(vformat(TTR("Unable to load addon script from path: '%s'."), script_path)); + return; + } - //errors in the script cause the base_type to be "" - if (String(script->get_instance_base_type()) == "") { - show_warning(vformat(TTR("Unable to load addon script from path: '%s' There seems to be an error in the code, please check the syntax."), path)); - return; - } + // Errors in the script cause the base_type to be an empty string. + if (String(script->get_instance_base_type()) == "") { + show_warning(vformat(TTR("Unable to load addon script from path: '%s' There seems to be an error in the code, please check the syntax."), script_path)); + return; + } - //could check inheritance.. - if (String(script->get_instance_base_type()) != "EditorPlugin") { - show_warning(vformat(TTR("Unable to load addon script from path: '%s' Base type is not EditorPlugin."), path)); - return; - } + // Plugin init scripts must inherit from EditorPlugin and be tools. + if (String(script->get_instance_base_type()) != "EditorPlugin") { + show_warning(vformat(TTR("Unable to load addon script from path: '%s' Base type is not EditorPlugin."), script_path)); + return; + } - if (!script->is_tool()) { - show_warning(vformat(TTR("Unable to load addon script from path: '%s' Script is not in tool mode."), path)); - return; + if (!script->is_tool()) { + show_warning(vformat(TTR("Unable to load addon script from path: '%s' Script is not in tool mode."), script_path)); + return; + } } EditorPlugin *ep = memnew(EditorPlugin); ep->set_script(script.get_ref_ptr()); - ep->set_dir_cache(p_addon); plugin_addons[p_addon] = ep; add_editor_plugin(ep, p_config_changed); @@ -3060,7 +3131,14 @@ void EditorNode::_clear_undo_history() { void EditorNode::set_current_scene(int p_idx) { + //Save the folding in case the scene gets reloaded. + if (editor_data.get_scene_path(p_idx) != "") + editor_folding.save_scene_folding(editor_data.get_edited_scene_root(p_idx), editor_data.get_scene_path(p_idx)); + if (editor_data.check_and_update_scene(p_idx)) { + if (editor_data.get_scene_path(p_idx) != "") + editor_folding.load_scene_folding(editor_data.get_edited_scene_root(p_idx), editor_data.get_scene_path(p_idx)); + call_deferred("_clear_undo_history"); } @@ -3111,6 +3189,14 @@ void EditorNode::fix_dependencies(const String &p_for_file) { dependency_fixer->edit(p_for_file); } +int EditorNode::new_scene() { + int idx = editor_data.add_edited_scene(-1); + _scene_tab_changed(idx); + editor_data.clear_editor_states(); + _update_scene_tabs(); + return idx; +} + Error EditorNode::load_scene(const String &p_scene, bool p_ignore_broken_deps, bool p_set_inherited, bool p_clear_errors, bool p_force_open_imported) { if (!is_inside_tree()) { @@ -3271,6 +3357,13 @@ Error EditorNode::load_scene(const String &p_scene, bool p_ignore_broken_deps, b void EditorNode::open_request(const String &p_path) { + if (!opening_prev) { + List<String>::Element *prev_scene = previous_scenes.find(p_path); + if (prev_scene != NULL) { + prev_scene->erase(); + } + } + load_scene(p_path); // as it will be opened in separate tab } @@ -3453,6 +3546,7 @@ void EditorNode::register_editor_types() { ClassDB::register_class<EditorResourcePreviewGenerator>(); ClassDB::register_virtual_class<EditorFileSystem>(); ClassDB::register_class<EditorFileSystemDirectory>(); + ClassDB::register_class<EditorVCSInterface>(); ClassDB::register_virtual_class<ScriptEditor>(); ClassDB::register_virtual_class<EditorInterface>(); ClassDB::register_class<EditorExportPlugin>(); @@ -3587,7 +3681,7 @@ Ref<Texture> EditorNode::get_object_icon(const Object *p_object, const String &p } Ref<Texture> EditorNode::get_class_icon(const String &p_class, const String &p_fallback) const { - ERR_FAIL_COND_V(p_class.empty(), NULL); + ERR_FAIL_COND_V_MSG(p_class.empty(), NULL, "Class name cannot be empty."); if (gui_base->has_icon(p_class, "EditorIcons")) { return gui_base->get_icon(p_class, "EditorIcons"); @@ -3762,9 +3856,13 @@ void EditorNode::show_accept(const String &p_text, const String &p_title) { void EditorNode::show_warning(const String &p_text, const String &p_title) { - warning->set_text(p_text); - warning->set_title(p_title); - warning->popup_centered_minsize(); + if (warning->is_inside_tree()) { + warning->set_text(p_text); + warning->set_title(p_title); + warning->popup_centered_minsize(); + } else { + WARN_PRINTS(p_title + " " + p_text); + } } void EditorNode::_copy_warning(const String &p_str) { @@ -4308,6 +4406,15 @@ bool EditorNode::ensure_main_scene(bool p_from_native) { return true; } +void EditorNode::run_play() { + _menu_option_confirm(RUN_STOP, true); + _run(false); +} + +void EditorNode::run_stop() { + _menu_option_confirm(RUN_STOP, false); +} + int EditorNode::get_current_tab() { return scene_tabs->get_current_tab(); } @@ -4471,8 +4578,17 @@ void EditorNode::_scene_tab_input(const Ref<InputEvent> &p_input) { scene_tabs_context_menu->add_separator(); scene_tabs_context_menu->add_item(TTR("Show in FileSystem"), FILE_SHOW_IN_FILESYSTEM); scene_tabs_context_menu->add_item(TTR("Play This Scene"), RUN_PLAY_SCENE); + scene_tabs_context_menu->add_separator(); - scene_tabs_context_menu->add_item(TTR("Close Tab"), FILE_CLOSE); + Ref<ShortCut> close_tab_sc = ED_GET_SHORTCUT("editor/close_scene"); + close_tab_sc->set_name(TTR("Close Tab")); + scene_tabs_context_menu->add_shortcut(close_tab_sc, FILE_CLOSE); + Ref<ShortCut> undo_close_tab_sc = ED_GET_SHORTCUT("editor/reopen_closed_scene"); + undo_close_tab_sc->set_name(TTR("Undo Close Tab")); + scene_tabs_context_menu->add_shortcut(undo_close_tab_sc, FILE_OPEN_PREV); + if (previous_scenes.empty()) { + scene_tabs_context_menu->set_item_disabled(scene_tabs_context_menu->get_item_index(FILE_OPEN_PREV), true); + } scene_tabs_context_menu->add_item(TTR("Close Other Tabs"), FILE_CLOSE_OTHERS); scene_tabs_context_menu->add_item(TTR("Close Tabs to the Right"), FILE_CLOSE_RIGHT); scene_tabs_context_menu->add_item(TTR("Close All Tabs"), FILE_CLOSE_ALL); @@ -4716,8 +4832,7 @@ void EditorNode::remove_control_from_dock(Control *p_control) { } } - ERR_EXPLAIN("Control was not in dock"); - ERR_FAIL_COND(!dock); + ERR_FAIL_COND_MSG(!dock, "Control was not in dock."); dock->remove_child(p_control); _update_dock_slots_visibility(); @@ -4776,7 +4891,7 @@ Variant EditorNode::drag_files_and_dirs(const Vector<String> &p_paths, Control * } int max_rows = 6; - int num_rows = p_paths.size() > max_rows ? max_rows - 1 : p_paths.size(); //Don't waste a row to say "1 more file" - list it instead. + int num_rows = p_paths.size() > max_rows ? max_rows - 1 : p_paths.size(); // Don't waste a row to say "1 more file" - list it instead. VBoxContainer *vbox = memnew(VBoxContainer); for (int i = 0; i < num_rows; i++) { HBoxContainer *hbox = memnew(HBoxContainer); @@ -4790,6 +4905,7 @@ Variant EditorNode::drag_files_and_dirs(const Vector<String> &p_paths, Control * label->set_text(p_paths[i].get_file()); icon->set_texture(gui_base->get_icon("File", "EditorIcons")); } + icon->set_stretch_mode(TextureRect::STRETCH_KEEP_CENTERED); icon->set_size(Size2(16, 16)); hbox->add_child(icon); hbox->add_child(label); @@ -4855,6 +4971,23 @@ void EditorNode::remove_tool_menu_item(const String &p_name) { } } +void EditorNode::_global_menu_action(const Variant &p_id, const Variant &p_meta) { + + int id = (int)p_id; + if (id == GLOBAL_NEW_WINDOW) { + if (OS::get_singleton()->get_main_loop()) { + List<String> args; + String exec = OS::get_singleton()->get_executable_path(); + + OS::ProcessID pid = 0; + OS::get_singleton()->execute(exec, args, false, &pid); + } + } else if (id == GLOBAL_SCENE) { + int idx = (int)p_meta; + scene_tabs->set_current_tab(idx); + } +} + void EditorNode::_dropped_files(const Vector<String> &p_files, int p_screen) { String to_path = ProjectSettings::get_singleton()->globalize_path(get_filesystem_dock()->get_selected_path()); @@ -5022,47 +5155,12 @@ void EditorNode::_open_imported() { load_scene(open_import_request, true, false, true, true); } -void EditorNode::dim_editor(bool p_dimming) { - static int dim_count = 0; - bool dim_ui = EditorSettings::get_singleton()->get("interface/editor/dim_editor_on_dialog_popup"); - if (p_dimming) { - if (dim_ui && dim_count == 0) { - _start_dimming(true); - } - dim_count++; - } else { - if (dim_count == 1) { - _start_dimming(false); - } - if (dim_count > 0) { - dim_count--; - } else { - ERR_PRINT("Undimmed before dimming!"); - } - } -} - -void EditorNode::_start_dimming(bool p_dimming) { - _dimming = p_dimming; - _dim_time = 0.0f; - _dim_timer->start(); -} - -void EditorNode::_dim_timeout() { - - _dim_time += _dim_timer->get_wait_time(); - float wait_time = EditorSettings::get_singleton()->get("interface/editor/dim_transition_time"); - - float c = 1.0f - (float)EditorSettings::get_singleton()->get("interface/editor/dim_amount"); - - Color base = _dimming ? Color(1, 1, 1) : Color(c, c, c); - Color final = _dimming ? Color(c, c, c) : Color(1, 1, 1); - - if (_dim_time + _dim_timer->get_wait_time() >= wait_time) { - gui_base->set_modulate(final); - _dim_timer->stop(); +void EditorNode::dim_editor(bool p_dimming, bool p_force_dim) { + // Dimming can be forced regardless of the editor setting, which is useful when quitting the editor + if ((p_force_dim || EditorSettings::get_singleton()->get("interface/editor/dim_editor_on_dialog_popup")) && p_dimming) { + gui_base->set_modulate(Color(0.5, 0.5, 0.5)); } else { - gui_base->set_modulate(base.linear_interpolate(final, _dim_time / wait_time)); + gui_base->set_modulate(Color(1, 1, 1)); } } @@ -5094,18 +5192,12 @@ Vector<Ref<EditorResourceConversionPlugin> > EditorNode::find_resource_conversio void EditorNode::_bottom_panel_raise_toggled(bool p_pressed) { - if (p_pressed) { - top_split->hide(); - bottom_panel_raise->set_icon(gui_base->get_icon("ShrinkBottomDock", "EditorIcons")); - } else { - top_split->show(); - bottom_panel_raise->set_icon(gui_base->get_icon("ExpandBottomDock", "EditorIcons")); - } + top_split->set_visible(!p_pressed); } void EditorNode::_update_video_driver_color() { - //todo probably should de-harcode this and add to editor settings + // TODO: Probably should de-hardcode this and add to editor settings. if (video_driver->get_text() == "GLES2") { video_driver->add_color_override("font_color", Color::hex(0x5586a4ff)); } else if (video_driver->get_text() == "GLES3") { @@ -5190,6 +5282,8 @@ void EditorNode::_bind_methods() { ClassDB::bind_method("_node_renamed", &EditorNode::_node_renamed); ClassDB::bind_method("edit_node", &EditorNode::edit_node); ClassDB::bind_method("_unhandled_input", &EditorNode::_unhandled_input); + ClassDB::bind_method("_update_file_menu_opened", &EditorNode::_update_file_menu_opened); + ClassDB::bind_method("_update_file_menu_closed", &EditorNode::_update_file_menu_closed); ClassDB::bind_method(D_METHOD("push_item", "object", "property", "inspector_only"), &EditorNode::push_item, DEFVAL(""), DEFVAL(false)); @@ -5241,7 +5335,9 @@ void EditorNode::_bind_methods() { ClassDB::bind_method("_clear_undo_history", &EditorNode::_clear_undo_history); ClassDB::bind_method("_dropped_files", &EditorNode::_dropped_files); + ClassDB::bind_method(D_METHOD("_global_menu_action"), &EditorNode::_global_menu_action, DEFVAL(Variant())); ClassDB::bind_method("_toggle_distraction_free_mode", &EditorNode::_toggle_distraction_free_mode); + ClassDB::bind_method("_version_control_menu_option", &EditorNode::_version_control_menu_option); ClassDB::bind_method("edit_item_resource", &EditorNode::edit_item_resource); ClassDB::bind_method(D_METHOD("get_gui_base"), &EditorNode::get_gui_base); @@ -5249,7 +5345,6 @@ void EditorNode::_bind_methods() { ClassDB::bind_method(D_METHOD("_open_imported"), &EditorNode::_open_imported); ClassDB::bind_method(D_METHOD("_inherit_imported"), &EditorNode::_inherit_imported); - ClassDB::bind_method(D_METHOD("_dim_timeout"), &EditorNode::_dim_timeout); ClassDB::bind_method("_copy_warning", &EditorNode::_copy_warning); @@ -5434,6 +5529,9 @@ EditorNode::EditorNode() { } } + // Define a minimum window size to prevent UI elements from overlapping or being cut off + OS::get_singleton()->set_min_window_size(Size2(1024, 600) * EDSCALE); + ResourceLoader::set_abort_on_missing_resources(false); FileDialog::set_default_show_hidden_files(EditorSettings::get_singleton()->get("filesystem/file_dialog/show_hidden_files")); EditorFileDialog::set_default_show_hidden_files(EditorSettings::get_singleton()->get("filesystem/file_dialog/show_hidden_files")); @@ -5468,6 +5566,10 @@ EditorNode::EditorNode() { import_csv_translation.instance(); ResourceFormatImporter::get_singleton()->add_importer(import_csv_translation); + Ref<ResourceImporterCSV> import_csv; + import_csv.instance(); + ResourceFormatImporter::get_singleton()->add_importer(import_csv); + Ref<ResourceImporterWAV> import_wav; import_wav.instance(); ResourceFormatImporter::get_singleton()->add_importer(import_wav); @@ -5565,6 +5667,8 @@ EditorNode::EditorNode() { EDITOR_DEF("interface/inspector/horizontal_vector_types_editing", true); EDITOR_DEF("interface/inspector/open_resources_in_current_inspector", true); EDITOR_DEF("interface/inspector/resources_to_open_in_new_inspector", "SpatialMaterial,Script,MeshLibrary,TileSet"); + EDITOR_DEF("interface/inspector/default_color_picker_mode", 0); + EditorSettings::get_singleton()->add_property_hint(PropertyInfo(Variant::INT, "interface/inspector/default_color_picker_mode", PROPERTY_HINT_ENUM, "RGB,HSV,RAW", PROPERTY_USAGE_DEFAULT)); EDITOR_DEF("run/auto_save/save_before_running", true); theme_base = memnew(Control); @@ -5708,6 +5812,7 @@ EditorNode::EditorNode() { dock_slot[i]->set_drag_to_rearrange_enabled(true); dock_slot[i]->set_tabs_rearrange_group(1); dock_slot[i]->connect("tab_changed", this, "_dock_tab_changed"); + dock_slot[i]->set_use_hidden_tabs_for_min_size(true); } dock_drag_timer = memnew(Timer); @@ -5866,23 +5971,25 @@ EditorNode::EditorNode() { PopupMenu *p; file_menu->set_tooltip(TTR("Operations with scene files.")); + p = file_menu->get_popup(); p->set_hide_on_window_lose_focus(true); p->add_shortcut(ED_SHORTCUT("editor/new_scene", TTR("New Scene")), FILE_NEW_SCENE); p->add_shortcut(ED_SHORTCUT("editor/new_inherited_scene", TTR("New Inherited Scene...")), FILE_NEW_INHERITED_SCENE); p->add_shortcut(ED_SHORTCUT("editor/open_scene", TTR("Open Scene..."), KEY_MASK_CMD + KEY_O), FILE_OPEN_SCENE); + p->add_shortcut(ED_SHORTCUT("editor/reopen_closed_scene", TTR("Reopen Closed Scene"), KEY_MASK_CMD + KEY_MASK_SHIFT + KEY_T), FILE_OPEN_PREV); + p->add_submenu_item(TTR("Open Recent"), "RecentScenes", FILE_OPEN_RECENT); + p->add_separator(); p->add_shortcut(ED_SHORTCUT("editor/save_scene", TTR("Save Scene"), KEY_MASK_CMD + KEY_S), FILE_SAVE_SCENE); p->add_shortcut(ED_SHORTCUT("editor/save_scene_as", TTR("Save Scene As..."), KEY_MASK_SHIFT + KEY_MASK_CMD + KEY_S), FILE_SAVE_AS_SCENE); p->add_shortcut(ED_SHORTCUT("editor/save_all_scenes", TTR("Save All Scenes"), KEY_MASK_ALT + KEY_MASK_SHIFT + KEY_MASK_CMD + KEY_S), FILE_SAVE_ALL_SCENES); - p->add_separator(); - p->add_shortcut(ED_SHORTCUT("editor/close_scene", TTR("Close Scene"), KEY_MASK_SHIFT + KEY_MASK_CMD + KEY_W), FILE_CLOSE); - p->add_separator(); - p->add_submenu_item(TTR("Open Recent"), "RecentScenes", FILE_OPEN_RECENT); + p->add_separator(); p->add_shortcut(ED_SHORTCUT("editor/quick_open", TTR("Quick Open..."), KEY_MASK_SHIFT + KEY_MASK_ALT + KEY_O), FILE_QUICK_OPEN); p->add_shortcut(ED_SHORTCUT("editor/quick_open_scene", TTR("Quick Open Scene..."), KEY_MASK_SHIFT + KEY_MASK_CMD + KEY_O), FILE_QUICK_OPEN_SCENE); p->add_shortcut(ED_SHORTCUT("editor/quick_open_script", TTR("Quick Open Script..."), KEY_MASK_ALT + KEY_MASK_CMD + KEY_O), FILE_QUICK_OPEN_SCRIPT); + p->add_separator(); PopupMenu *pm_export = memnew(PopupMenu); pm_export->set_name("Export"); @@ -5895,8 +6002,10 @@ EditorNode::EditorNode() { p->add_separator(); p->add_shortcut(ED_SHORTCUT("editor/undo", TTR("Undo"), KEY_MASK_CMD + KEY_Z), EDIT_UNDO, true); p->add_shortcut(ED_SHORTCUT("editor/redo", TTR("Redo"), KEY_MASK_SHIFT + KEY_MASK_CMD + KEY_Z), EDIT_REDO, true); + p->add_separator(); p->add_shortcut(ED_SHORTCUT("editor/revert_scene", TTR("Revert Scene")), EDIT_REVERT); + p->add_shortcut(ED_SHORTCUT("editor/close_scene", TTR("Close Scene"), KEY_MASK_SHIFT + KEY_MASK_CMD + KEY_W), FILE_CLOSE); recent_scenes = memnew(PopupMenu); recent_scenes->set_name("RecentScenes"); @@ -5904,7 +6013,7 @@ EditorNode::EditorNode() { recent_scenes->connect("id_pressed", this, "_open_recent_scene"); p->add_separator(); - p->add_item(TTR("Quit"), FILE_QUIT, KEY_MASK_CMD + KEY_Q); + p->add_shortcut(ED_SHORTCUT("editor/file_quit", TTR("Quit"), KEY_MASK_CMD + KEY_Q), FILE_QUIT, true); project_menu = memnew(MenuButton); project_menu->set_flat(false); @@ -5916,10 +6025,22 @@ EditorNode::EditorNode() { p = project_menu->get_popup(); p->set_hide_on_window_lose_focus(true); - p->add_shortcut(ED_SHORTCUT("editor/project_settings", TTR("Project Settings")), RUN_SETTINGS); - p->add_separator(); + p->add_shortcut(ED_SHORTCUT("editor/project_settings", TTR("Project Settings...")), RUN_SETTINGS); p->connect("id_pressed", this, "_menu_option"); - p->add_shortcut(ED_SHORTCUT("editor/export", TTR("Export")), FILE_EXPORT_PROJECT); + + vcs_actions_menu = VersionControlEditorPlugin::get_singleton()->get_version_control_actions_panel(); + vcs_actions_menu->set_name("Version Control"); + vcs_actions_menu->connect("index_pressed", this, "_version_control_menu_option"); + p->add_separator(); + p->add_child(vcs_actions_menu); + p->add_submenu_item(TTR("Version Control"), "Version Control"); + vcs_actions_menu->add_item(TTR("Set Up Version Control"), RUN_VCS_SETTINGS); + vcs_actions_menu->add_item(TTR("Shut Down Version Control"), RUN_VCS_SHUT_DOWN); + + p->add_separator(); + p->add_shortcut(ED_SHORTCUT("editor/export", TTR("Export...")), FILE_EXPORT_PROJECT); + p->add_item(TTR("Install Android Build Template..."), FILE_INSTALL_ANDROID_SOURCE); + p->add_item(TTR("Open Project Data Folder"), RUN_PROJECT_DATA_FOLDER); plugin_config_dialog = memnew(PluginConfigDialog); plugin_config_dialog->connect("plugin_ready", this, "_on_plugin_ready"); @@ -5928,19 +6049,15 @@ EditorNode::EditorNode() { tool_menu = memnew(PopupMenu); tool_menu->set_name("Tools"); tool_menu->connect("index_pressed", this, "_tool_menu_option"); - p->add_separator(); p->add_child(tool_menu); p->add_submenu_item(TTR("Tools"), "Tools"); - tool_menu->add_item(TTR("Orphan Resource Explorer"), TOOLS_ORPHAN_RESOURCES); - tool_menu->add_item(TTR("Open Project Data Folder"), RUN_PROJECT_DATA_FOLDER); - p->add_separator(); - p->add_item(TTR("Install Android Build Template"), FILE_INSTALL_ANDROID_SOURCE); - p->add_separator(); + tool_menu->add_item(TTR("Orphan Resource Explorer..."), TOOLS_ORPHAN_RESOURCES); + p->add_separator(); #ifdef OSX_ENABLED - p->add_item(TTR("Quit to Project List"), RUN_PROJECT_MANAGER, KEY_MASK_SHIFT + KEY_MASK_ALT + KEY_Q); + p->add_shortcut(ED_SHORTCUT("editor/quit_to_project_list", TTR("Quit to Project List"), KEY_MASK_SHIFT + KEY_MASK_ALT + KEY_Q), RUN_PROJECT_MANAGER, true); #else - p->add_item(TTR("Quit to Project List"), RUN_PROJECT_MANAGER, KEY_MASK_SHIFT + KEY_MASK_CMD + KEY_Q); + p->add_shortcut(ED_SHORTCUT("editor/quit_to_project_list", TTR("Quit to Project List"), KEY_MASK_SHIFT + KEY_MASK_CMD + KEY_Q), RUN_PROJECT_MANAGER, true); #endif menu_hb->add_spacer(); @@ -5988,7 +6105,7 @@ EditorNode::EditorNode() { p = settings_menu->get_popup(); p->set_hide_on_window_lose_focus(true); - p->add_shortcut(ED_SHORTCUT("editor/editor_settings", TTR("Editor Settings")), SETTINGS_PREFERENCES); + p->add_shortcut(ED_SHORTCUT("editor/editor_settings", TTR("Editor Settings...")), SETTINGS_PREFERENCES); p->add_separator(); editor_layouts = memnew(PopupMenu); @@ -6023,11 +6140,8 @@ EditorNode::EditorNode() { } p->add_separator(); - p->add_item(TTR("Manage Editor Features"), SETTINGS_MANAGE_FEATURE_PROFILES); - - p->add_separator(); - - p->add_item(TTR("Manage Export Templates"), SETTINGS_MANAGE_EXPORT_TEMPLATES); + p->add_item(TTR("Manage Editor Features..."), SETTINGS_MANAGE_FEATURE_PROFILES); + p->add_item(TTR("Manage Export Templates..."), SETTINGS_MANAGE_EXPORT_TEMPLATES); // Help Menu help_menu = memnew(MenuButton); @@ -6255,6 +6369,13 @@ EditorNode::EditorNode() { bottom_panel_hb_editors = memnew(HBoxContainer); bottom_panel_hb_editors->set_h_size_flags(Control::SIZE_EXPAND_FILL); bottom_panel_hb->add_child(bottom_panel_hb_editors); + + version_label = memnew(Label); + version_label->set_text(VERSION_FULL_CONFIG); + // Fade out the version label to be less prominent, but still readable + version_label->set_self_modulate(Color(1, 1, 1, 0.6)); + bottom_panel_hb->add_child(version_label); + bottom_panel_raise = memnew(ToolButton); bottom_panel_raise->set_icon(gui_base->get_icon("ExpandBottomDock", "EditorIcons")); @@ -6293,13 +6414,13 @@ EditorNode::EditorNode() { gui_base->add_child(custom_build_manage_templates); install_android_build_template = memnew(ConfirmationDialog); - install_android_build_template->set_text(TTR("This will install the Android project for custom builds.\nNote that, in order to use it, it needs to be enabled per export preset.")); + install_android_build_template->set_text(TTR("This will set up your project for custom Android builds by installing the source template to \"res://android/build\".\nYou can then apply modifications and build your own custom APK on export (adding modules, changing the AndroidManifest.xml, etc.).\nNote that in order to make custom builds instead of using pre-built APKs, the \"Use Custom Build\" option should be enabled in the Android export preset.")); install_android_build_template->get_ok()->set_text(TTR("Install")); install_android_build_template->connect("confirmed", this, "_menu_confirm_current"); gui_base->add_child(install_android_build_template); remove_android_build_template = memnew(ConfirmationDialog); - remove_android_build_template->set_text(TTR("Android build template is already installed and it won't be overwritten.\nRemove the \"build\" directory manually before attempting this operation again.")); + remove_android_build_template->set_text(TTR("The Android build template is already installed in this project and it won't be overwritten.\nRemove the \"res://android/build\" directory manually before attempting this operation again.")); remove_android_build_template->get_ok()->set_text(TTR("Show in File Manager")); remove_android_build_template->connect("confirmed", this, "_menu_option", varray(FILE_EXPLORE_ANDROID_BUILD_TEMPLATES)); gui_base->add_child(remove_android_build_template); @@ -6351,6 +6472,8 @@ EditorNode::EditorNode() { file_script->connect("file_selected", this, "_dialog_action"); file_menu->get_popup()->connect("id_pressed", this, "_menu_option"); + file_menu->connect("about_to_show", this, "_update_file_menu_opened"); + file_menu->get_popup()->connect("popup_hide", this, "_update_file_menu_closed"); settings_menu->get_popup()->connect("id_pressed", this, "_menu_option"); @@ -6387,6 +6510,7 @@ EditorNode::EditorNode() { //more visually meaningful to have this later raise_bottom_panel_item(AnimationPlayerEditor::singleton); + add_editor_plugin(VersionControlEditorPlugin::get_singleton()); add_editor_plugin(memnew(ShaderEditorPlugin(this))); add_editor_plugin(memnew(VisualShaderEditorPlugin(this))); @@ -6567,13 +6691,6 @@ EditorNode::EditorNode() { waiting_for_first_scan = true; - _dimming = false; - _dim_time = 0.0f; - _dim_timer = memnew(Timer); - _dim_timer->set_wait_time(0.01666f); - _dim_timer->connect("timeout", this, "_dim_timeout"); - add_child(_dim_timer); - print_handler.printfunc = _print_handler; print_handler.userdata = this; add_print_handler(&print_handler); |