diff options
Diffstat (limited to 'editor/project_manager.cpp')
-rw-r--r-- | editor/project_manager.cpp | 778 |
1 files changed, 461 insertions, 317 deletions
diff --git a/editor/project_manager.cpp b/editor/project_manager.cpp index d18e5a237f..ffb482d103 100644 --- a/editor/project_manager.cpp +++ b/editor/project_manager.cpp @@ -38,7 +38,6 @@ #include "core/io/stream_peer_tls.h" #include "core/os/keyboard.h" #include "core/os/os.h" -#include "core/string/translation.h" #include "core/version.h" #include "editor/editor_about.h" #include "editor/editor_settings.h" @@ -48,11 +47,11 @@ #include "editor/project_manager/project_dialog.h" #include "editor/project_manager/project_list.h" #include "editor/project_manager/project_tag.h" +#include "editor/project_manager/quick_settings_dialog.h" #include "editor/themes/editor_icons.h" #include "editor/themes/editor_scale.h" #include "editor/themes/editor_theme_manager.h" #include "main/main.h" -#include "scene/gui/center_container.h" #include "scene/gui/check_box.h" #include "scene/gui/color_rect.h" #include "scene/gui/flow_container.h" @@ -60,9 +59,11 @@ #include "scene/gui/margin_container.h" #include "scene/gui/option_button.h" #include "scene/gui/panel_container.h" +#include "scene/gui/rich_text_label.h" #include "scene/gui/separator.h" #include "scene/gui/texture_rect.h" #include "scene/main/window.h" +#include "scene/theme/theme_db.h" #include "servers/display_server.h" #include "servers/navigation_server_3d.h" #include "servers/physics_server_2d.h" @@ -75,91 +76,20 @@ ProjectManager *ProjectManager::singleton = nullptr; void ProjectManager::_notification(int p_what) { switch (p_what) { - case NOTIFICATION_TRANSLATION_CHANGED: - case NOTIFICATION_LAYOUT_DIRECTION_CHANGED: { - settings_hb->set_anchors_and_offsets_preset(Control::PRESET_TOP_RIGHT); - queue_redraw(); - } break; - case NOTIFICATION_ENTER_TREE: { Engine::get_singleton()->set_editor_hint(false); - } break; - - case NOTIFICATION_THEME_CHANGED: { - background_panel->add_theme_style_override("panel", get_theme_stylebox(SNAME("Background"), EditorStringName(EditorStyles))); - loading_label->add_theme_font_override("font", get_theme_font(SNAME("bold"), EditorStringName(EditorFonts))); - search_panel->add_theme_style_override("panel", get_theme_stylebox(SNAME("search_panel"), SNAME("ProjectManager"))); - - // Top bar. - search_box->set_right_icon(get_editor_theme_icon(SNAME("Search"))); - language_btn->set_icon(get_editor_theme_icon(SNAME("Environment"))); - - // Sidebar. - create_btn->set_icon(get_editor_theme_icon(SNAME("Add"))); - import_btn->set_icon(get_editor_theme_icon(SNAME("Load"))); - scan_btn->set_icon(get_editor_theme_icon(SNAME("Search"))); - open_btn->set_icon(get_editor_theme_icon(SNAME("Edit"))); - run_btn->set_icon(get_editor_theme_icon(SNAME("Play"))); - rename_btn->set_icon(get_editor_theme_icon(SNAME("Rename"))); - manage_tags_btn->set_icon(get_editor_theme_icon("Script")); - erase_btn->set_icon(get_editor_theme_icon(SNAME("Remove"))); - erase_missing_btn->set_icon(get_editor_theme_icon(SNAME("Clear"))); - create_tag_btn->set_icon(get_editor_theme_icon("Add")); - - tag_error->add_theme_color_override("font_color", get_theme_color("error_color", EditorStringName(Editor))); - tag_edit_error->add_theme_color_override("font_color", get_theme_color("error_color", EditorStringName(Editor))); - create_btn->add_theme_constant_override("h_separation", get_theme_constant(SNAME("sidebar_button_icon_separation"), SNAME("ProjectManager"))); - import_btn->add_theme_constant_override("h_separation", get_theme_constant(SNAME("sidebar_button_icon_separation"), SNAME("ProjectManager"))); - scan_btn->add_theme_constant_override("h_separation", get_theme_constant(SNAME("sidebar_button_icon_separation"), SNAME("ProjectManager"))); - open_btn->add_theme_constant_override("h_separation", get_theme_constant(SNAME("sidebar_button_icon_separation"), SNAME("ProjectManager"))); - run_btn->add_theme_constant_override("h_separation", get_theme_constant(SNAME("sidebar_button_icon_separation"), SNAME("ProjectManager"))); - rename_btn->add_theme_constant_override("h_separation", get_theme_constant(SNAME("sidebar_button_icon_separation"), SNAME("ProjectManager"))); - manage_tags_btn->add_theme_constant_override("h_separation", get_theme_constant(SNAME("sidebar_button_icon_separation"), SNAME("ProjectManager"))); - erase_btn->add_theme_constant_override("h_separation", get_theme_constant(SNAME("sidebar_button_icon_separation"), SNAME("ProjectManager"))); - erase_missing_btn->add_theme_constant_override("h_separation", get_theme_constant(SNAME("sidebar_button_icon_separation"), SNAME("ProjectManager"))); - - // Asset library popup. - if (asset_library) { - // Removes extra border margins. - asset_library->add_theme_style_override("panel", memnew(StyleBoxEmpty)); - } - } break; - - case NOTIFICATION_RESIZED: { - if (open_templates && open_templates->is_visible()) { - open_templates->popup_centered(); - } - if (asset_library) { - real_t size = get_size().x / EDSCALE; - // Adjust names of tabs to fit the new size. - if (size < 650) { - local_projects_vb->set_name(TTR("Local")); - asset_library->set_name(TTR("Asset Library")); - } else { - local_projects_vb->set_name(TTR("Local Projects")); - asset_library->set_name(TTR("Asset Library Projects")); - } - } + // Theme has already been created in the constructor, so we can skip that step. + _update_theme(true); } break; case NOTIFICATION_READY: { - int default_sorting = (int)EDITOR_GET("project_manager/sorting_order"); + const int default_sorting = (int)EDITOR_GET("project_manager/sorting_order"); filter_option->select(default_sorting); - _project_list->set_order_option(default_sorting); + project_list->set_order_option(default_sorting); -#ifndef ANDROID_ENABLED - if (_project_list->get_project_count() >= 1) { - // Focus on the search box immediately to allow the user - // to search without having to reach for their mouse - search_box->grab_focus(); - } -#endif - - // Suggest browsing asset library to get templates/demos. - if (asset_library && open_templates && _project_list->get_project_count() == 0) { - open_templates->popup_centered(); - } + _select_main_view(MAIN_VIEW_PROJECTS); + _update_list_placeholder(); } break; case NOTIFICATION_VISIBILITY_CHANGED: { @@ -173,6 +103,13 @@ void ProjectManager::_notification(int p_what) { case NOTIFICATION_WM_ABOUT: { _show_about(); } break; + + case EditorSettings::NOTIFICATION_EDITOR_SETTINGS_CHANGED: { + if (EditorThemeManager::is_generated_theme_outdated()) { + _update_theme(); + } + _update_list_placeholder(); + } break; } } @@ -233,21 +170,166 @@ void ProjectManager::_update_size_limits() { // We try to set it to half the screen resolution, but no smaller than the minimum window size. Size2 half_screen_rect = (screen_rect.size * EDSCALE) / 2; Size2 maximum_popup_size = MAX(half_screen_rect, minimum_size); - language_btn->get_popup()->set_max_size(maximum_popup_size); + quick_settings_dialog->update_size_limits(maximum_popup_size); } } -void ProjectManager::_show_about() { - about->popup_centered(Size2(780, 500) * EDSCALE); +void ProjectManager::_update_theme(bool p_skip_creation) { + if (!p_skip_creation) { + theme = EditorThemeManager::generate_theme(theme); + DisplayServer::set_early_window_clear_color_override(true, theme->get_color(SNAME("background"), EditorStringName(Editor))); + } + + List<Ref<Theme>> editor_themes; + editor_themes.push_back(theme); + editor_themes.push_back(ThemeDB::get_singleton()->get_default_theme()); + + ThemeContext *node_tc = ThemeDB::get_singleton()->get_theme_context(this); + if (node_tc) { + node_tc->set_themes(editor_themes); + } else { + ThemeDB::get_singleton()->create_theme_context(this, editor_themes); + } + + Window *owner_window = get_window(); + if (owner_window) { + ThemeContext *window_tc = ThemeDB::get_singleton()->get_theme_context(owner_window); + if (window_tc) { + window_tc->set_themes(editor_themes); + } else { + ThemeDB::get_singleton()->create_theme_context(owner_window, editor_themes); + } + } + + // Update styles. + { + const int top_bar_separation = get_theme_constant(SNAME("top_bar_separation"), EditorStringName(Editor)); + root_container->add_theme_constant_override("margin_left", top_bar_separation); + root_container->add_theme_constant_override("margin_top", top_bar_separation); + root_container->add_theme_constant_override("margin_bottom", top_bar_separation); + root_container->add_theme_constant_override("margin_right", top_bar_separation); + main_vbox->add_theme_constant_override("separation", top_bar_separation); + + background_panel->add_theme_style_override("panel", get_theme_stylebox(SNAME("Background"), EditorStringName(EditorStyles))); + main_view_container->add_theme_style_override("panel", get_theme_stylebox(SNAME("panel"), SNAME("TabContainer"))); + + title_bar_logo->set_icon(get_editor_theme_icon(SNAME("TitleBarLogo"))); + + _set_main_view_icon(MAIN_VIEW_PROJECTS, get_editor_theme_icon(SNAME("ProjectList"))); + _set_main_view_icon(MAIN_VIEW_ASSETLIB, get_editor_theme_icon(SNAME("AssetLib"))); + + // Project list. + { + loading_label->add_theme_font_override("font", get_theme_font(SNAME("bold"), EditorStringName(EditorFonts))); + project_list_panel->add_theme_style_override("panel", get_theme_stylebox(SNAME("project_list"), SNAME("ProjectManager"))); + + empty_list_create_project->set_icon(get_editor_theme_icon(SNAME("Add"))); + empty_list_import_project->set_icon(get_editor_theme_icon(SNAME("Load"))); + empty_list_open_assetlib->set_icon(get_editor_theme_icon(SNAME("AssetLib"))); + + empty_list_online_warning->add_theme_font_override("font", get_theme_font(SNAME("italic"), EditorStringName(EditorFonts))); + empty_list_online_warning->add_theme_color_override("font_color", get_theme_color(SNAME("font_placeholder_color"), EditorStringName(Editor))); + + // Top bar. + search_box->set_right_icon(get_editor_theme_icon(SNAME("Search"))); + quick_settings_button->set_icon(get_editor_theme_icon(SNAME("Tools"))); + + // Sidebar. + create_btn->set_icon(get_editor_theme_icon(SNAME("Add"))); + import_btn->set_icon(get_editor_theme_icon(SNAME("Load"))); + scan_btn->set_icon(get_editor_theme_icon(SNAME("Search"))); + open_btn->set_icon(get_editor_theme_icon(SNAME("Edit"))); + run_btn->set_icon(get_editor_theme_icon(SNAME("Play"))); + rename_btn->set_icon(get_editor_theme_icon(SNAME("Rename"))); + manage_tags_btn->set_icon(get_editor_theme_icon("Script")); + erase_btn->set_icon(get_editor_theme_icon(SNAME("Remove"))); + erase_missing_btn->set_icon(get_editor_theme_icon(SNAME("Clear"))); + create_tag_btn->set_icon(get_editor_theme_icon("Add")); + + tag_error->add_theme_color_override("font_color", get_theme_color("error_color", EditorStringName(Editor))); + tag_edit_error->add_theme_color_override("font_color", get_theme_color("error_color", EditorStringName(Editor))); + + create_btn->add_theme_constant_override("h_separation", get_theme_constant(SNAME("sidebar_button_icon_separation"), SNAME("ProjectManager"))); + import_btn->add_theme_constant_override("h_separation", get_theme_constant(SNAME("sidebar_button_icon_separation"), SNAME("ProjectManager"))); + scan_btn->add_theme_constant_override("h_separation", get_theme_constant(SNAME("sidebar_button_icon_separation"), SNAME("ProjectManager"))); + open_btn->add_theme_constant_override("h_separation", get_theme_constant(SNAME("sidebar_button_icon_separation"), SNAME("ProjectManager"))); + run_btn->add_theme_constant_override("h_separation", get_theme_constant(SNAME("sidebar_button_icon_separation"), SNAME("ProjectManager"))); + rename_btn->add_theme_constant_override("h_separation", get_theme_constant(SNAME("sidebar_button_icon_separation"), SNAME("ProjectManager"))); + manage_tags_btn->add_theme_constant_override("h_separation", get_theme_constant(SNAME("sidebar_button_icon_separation"), SNAME("ProjectManager"))); + erase_btn->add_theme_constant_override("h_separation", get_theme_constant(SNAME("sidebar_button_icon_separation"), SNAME("ProjectManager"))); + erase_missing_btn->add_theme_constant_override("h_separation", get_theme_constant(SNAME("sidebar_button_icon_separation"), SNAME("ProjectManager"))); + } + + // Asset library popup. + if (asset_library) { + // Removes extra border margins. + asset_library->add_theme_style_override("panel", memnew(StyleBoxEmpty)); + } + } } -void ProjectManager::_version_button_pressed() { - DisplayServer::get_singleton()->clipboard_set(version_btn->get_text()); +Button *ProjectManager::_add_main_view(MainViewTab p_id, const String &p_name, const Ref<Texture2D> &p_icon, Control *p_view_control) { + ERR_FAIL_INDEX_V(p_id, MAIN_VIEW_MAX, nullptr); + ERR_FAIL_COND_V(main_view_map.has(p_id), nullptr); + ERR_FAIL_COND_V(main_view_toggle_map.has(p_id), nullptr); + + Button *toggle_button = memnew(Button); + toggle_button->set_flat(true); + toggle_button->set_theme_type_variation("MainScreenButton"); + toggle_button->set_toggle_mode(true); + toggle_button->set_button_group(main_view_toggles_group); + toggle_button->set_text(p_name); + toggle_button->connect("pressed", callable_mp(this, &ProjectManager::_select_main_view).bind((int)p_id)); + + main_view_toggles->add_child(toggle_button); + main_view_toggle_map[p_id] = toggle_button; + + _set_main_view_icon(p_id, p_icon); + + p_view_control->set_visible(false); + main_view_container->add_child(p_view_control); + main_view_map[p_id] = p_view_control; + + return toggle_button; } -void ProjectManager::_on_tab_changed(int p_tab) { +void ProjectManager::_set_main_view_icon(MainViewTab p_id, const Ref<Texture2D> &p_icon) { + ERR_FAIL_INDEX(p_id, MAIN_VIEW_MAX); + ERR_FAIL_COND(!main_view_toggle_map.has(p_id)); + + Button *toggle_button = main_view_toggle_map[p_id]; + + Ref<Texture2D> old_icon = toggle_button->get_icon(); + if (old_icon.is_valid()) { + old_icon->disconnect_changed(callable_mp((Control *)toggle_button, &Control::update_minimum_size)); + } + + if (p_icon.is_valid()) { + toggle_button->set_icon(p_icon); + // Make sure the control is updated if the icon is reimported. + p_icon->connect_changed(callable_mp((Control *)toggle_button, &Control::update_minimum_size)); + } else { + toggle_button->set_icon(Ref<Texture2D>()); + } +} + +void ProjectManager::_select_main_view(int p_id) { + MainViewTab view_id = (MainViewTab)p_id; + + ERR_FAIL_INDEX(view_id, MAIN_VIEW_MAX); + ERR_FAIL_COND(!main_view_map.has(view_id)); + ERR_FAIL_COND(!main_view_toggle_map.has(view_id)); + + if (current_main_view != view_id) { + main_view_toggle_map[current_main_view]->set_pressed_no_signal(false); + main_view_map[current_main_view]->set_visible(false); + current_main_view = view_id; + } + main_view_toggle_map[current_main_view]->set_pressed_no_signal(true); + main_view_map[current_main_view]->set_visible(true); + #ifndef ANDROID_ENABLED - if (p_tab == 0) { // Projects + if (current_main_view == MAIN_VIEW_PROJECTS && search_box->is_inside_tree()) { // Automatically grab focus when the user moves from the Templates tab // back to the Projects tab. search_box->grab_focus(); @@ -258,27 +340,25 @@ void ProjectManager::_on_tab_changed(int p_tab) { #endif } -void ProjectManager::_open_asset_library() { - asset_library->disable_community_support(); - tabs->set_current_tab(1); +void ProjectManager::_show_about() { + about_dialog->popup_centered(Size2(780, 500) * EDSCALE); } -// Quick settings. - -void ProjectManager::_language_selected(int p_id) { - String lang = language_btn->get_item_metadata(p_id); - EditorSettings::get_singleton()->set("interface/editor/editor_language", lang); +void ProjectManager::_open_asset_library_confirmed() { + const int network_mode = EDITOR_GET("network/connection/network_mode"); + if (network_mode == EditorSettings::NETWORK_OFFLINE) { + EditorSettings::get_singleton()->set_setting("network/connection/network_mode", EditorSettings::NETWORK_ONLINE); + EditorSettings::get_singleton()->notify_changes(); + EditorSettings::get_singleton()->save(); + } - restart_required_dialog->popup_centered(); + asset_library->disable_community_support(); + _select_main_view(MAIN_VIEW_ASSETLIB); } -void ProjectManager::_restart_confirm() { - List<String> args = OS::get_singleton()->get_cmdline_args(); - Error err = OS::get_singleton()->create_instance(args); - ERR_FAIL_COND(err); - - _dim_window(); - get_tree()->quit(); +void ProjectManager::_show_error(const String &p_message, const Size2 &p_min_size) { + error_dialog->set_text(p_message); + error_dialog->popup_centered(p_min_size); } void ProjectManager::_dim_window() { @@ -292,14 +372,55 @@ void ProjectManager::_dim_window() { set_modulate(dim_color); } +// Quick settings. + +void ProjectManager::_show_quick_settings() { + quick_settings_dialog->popup_centered(Size2(600, 200) * EDSCALE); +} + +void ProjectManager::_restart_confirmed() { + List<String> args = OS::get_singleton()->get_cmdline_args(); + Error err = OS::get_singleton()->create_instance(args); + ERR_FAIL_COND(err); + + _dim_window(); + get_tree()->quit(); +} + +// Footer. + +void ProjectManager::_version_button_pressed() { + DisplayServer::get_singleton()->clipboard_set(version_btn->get_text()); +} + // Project list. +void ProjectManager::_update_list_placeholder() { + if (project_list->get_project_count() > 0) { + empty_list_placeholder->hide(); + return; + } + + empty_list_open_assetlib->set_visible(asset_library); + + const int network_mode = EDITOR_GET("network/connection/network_mode"); + if (network_mode == EditorSettings::NETWORK_OFFLINE) { + empty_list_open_assetlib->set_text(TTR("Go Online and Open Asset Library")); + empty_list_online_warning->set_visible(true); + } else { + empty_list_open_assetlib->set_text(TTR("Open Asset Library")); + empty_list_online_warning->set_visible(false); + } + + empty_list_placeholder->show(); +} + void ProjectManager::_scan_projects() { scan_dir->popup_file_dialog(); } void ProjectManager::_run_project() { - const HashSet<String> &selected_list = _project_list->get_selected_project_keys(); + const HashSet<String> &selected_list = project_list->get_selected_project_keys(); if (selected_list.size() < 1) { return; @@ -314,13 +435,12 @@ void ProjectManager::_run_project() { } void ProjectManager::_run_project_confirm() { - Vector<ProjectList::Item> selected_list = _project_list->get_selected_projects(); + Vector<ProjectList::Item> selected_list = project_list->get_selected_projects(); for (int i = 0; i < selected_list.size(); ++i) { const String &selected_main = selected_list[i].main_scene; if (selected_main.is_empty()) { - run_error_diag->set_text(TTR("Can't run project: no main scene defined.\nPlease edit the project and set the main scene in the Project Settings under the \"Application\" category.")); - run_error_diag->popup_centered(); + _show_error(TTR("Can't run project: Project has no main scene defined.\nPlease edit the project and set the main scene in the Project Settings under the \"Application\" category.")); continue; } @@ -328,8 +448,7 @@ void ProjectManager::_run_project_confirm() { // `.substr(6)` on `ProjectSettings::get_singleton()->get_imported_files_path()` strips away the leading "res://". if (!DirAccess::exists(path.path_join(ProjectSettings::get_singleton()->get_imported_files_path().substr(6)))) { - run_error_diag->set_text(TTR("Can't run project: Assets need to be imported.\nPlease edit the project to trigger the initial import.")); - run_error_diag->popup_centered(); + _show_error(TTR("Can't run project: Assets need to be imported first.\nPlease edit the project to trigger the initial import.")); continue; } @@ -354,14 +473,13 @@ void ProjectManager::_open_selected_projects() { // This is especially important for the Web project manager. loading_label->show(); - const HashSet<String> &selected_list = _project_list->get_selected_project_keys(); - + const HashSet<String> &selected_list = project_list->get_selected_project_keys(); for (const String &path : selected_list) { String conf = path.path_join("project.godot"); if (!FileAccess::exists(conf)) { - dialog_error->set_text(vformat(TTR("Can't open project at '%s'."), path)); - dialog_error->popup_centered(); + loading_label->hide(); + _show_error(vformat(TTR("Can't open project at '%s'.\nProject file doesn't exist or is inaccessible."), path)); return; } @@ -379,18 +497,22 @@ void ProjectManager::_open_selected_projects() { args.push_back("--editor"); Error err = OS::get_singleton()->create_instance(args); - ERR_FAIL_COND(err); + if (err != OK) { + loading_label->hide(); + _show_error(vformat(TTR("Can't open project at '%s'.\nFailed to start the editor."), path)); + ERR_PRINT(vformat("Failed to start an editor instance for the project at '%s', error code %d.", path, err)); + return; + } } - _project_list->project_opening_initiated = true; + project_list->project_opening_initiated = true; _dim_window(); get_tree()->quit(); } void ProjectManager::_open_selected_projects_ask() { - const HashSet<String> &selected_list = _project_list->get_selected_project_keys(); - + const HashSet<String> &selected_list = project_list->get_selected_project_keys(); if (selected_list.size() < 1) { return; } @@ -403,7 +525,7 @@ void ProjectManager::_open_selected_projects_ask() { return; } - ProjectList::Item project = _project_list->get_selected_projects()[0]; + ProjectList::Item project = project_list->get_selected_projects()[0]; if (project.missing) { return; } @@ -440,8 +562,7 @@ void ProjectManager::_open_selected_projects_ask() { } // Check if the file was generated by a newer, incompatible engine version. if (config_version > ProjectSettings::CONFIG_VERSION) { - dialog_error->set_text(vformat(TTR("Can't open project \"%s\" at the following path:\n\n%s\n\nThe project settings were created by a newer engine version, whose settings are not compatible with this version."), project.project_name, project.path)); - dialog_error->popup_centered(popup_min_size); + _show_error(vformat(TTR("Can't open project \"%s\" at the following path:\n\n%s\n\nThe project settings were created by a newer engine version, whose settings are not compatible with this version."), project.project_name, project.path), popup_min_size); return; } // Check if the project is using features not supported by this build of Godot. @@ -479,38 +600,38 @@ void ProjectManager::_open_selected_projects_ask() { } void ProjectManager::_install_project(const String &p_zip_path, const String &p_title) { - npdialog->set_mode(ProjectDialog::MODE_INSTALL); - npdialog->set_zip_path(p_zip_path); - npdialog->set_zip_title(p_title); - npdialog->show_dialog(); + project_dialog->set_mode(ProjectDialog::MODE_INSTALL); + project_dialog->set_zip_path(p_zip_path); + project_dialog->set_zip_title(p_title); + project_dialog->show_dialog(); } void ProjectManager::_import_project() { - npdialog->set_mode(ProjectDialog::MODE_IMPORT); - npdialog->ask_for_path_and_show(); + project_dialog->set_mode(ProjectDialog::MODE_IMPORT); + project_dialog->ask_for_path_and_show(); } void ProjectManager::_new_project() { - npdialog->set_mode(ProjectDialog::MODE_NEW); - npdialog->show_dialog(); + project_dialog->set_mode(ProjectDialog::MODE_NEW); + project_dialog->show_dialog(); } void ProjectManager::_rename_project() { - const HashSet<String> &selected_list = _project_list->get_selected_project_keys(); + const HashSet<String> &selected_list = project_list->get_selected_project_keys(); if (selected_list.size() == 0) { return; } for (const String &E : selected_list) { - npdialog->set_project_path(E); - npdialog->set_mode(ProjectDialog::MODE_RENAME); - npdialog->show_dialog(); + project_dialog->set_project_path(E); + project_dialog->set_mode(ProjectDialog::MODE_RENAME); + project_dialog->show_dialog(); } } void ProjectManager::_erase_project() { - const HashSet<String> &selected_list = _project_list->get_selected_project_keys(); + const HashSet<String> &selected_list = project_list->get_selected_project_keys(); if (selected_list.size() == 0) { return; @@ -534,17 +655,19 @@ void ProjectManager::_erase_missing_projects() { } void ProjectManager::_erase_project_confirm() { - _project_list->erase_selected_projects(false); + project_list->erase_selected_projects(false); _update_project_buttons(); + _update_list_placeholder(); } void ProjectManager::_erase_missing_projects_confirm() { - _project_list->erase_missing_projects(); + project_list->erase_missing_projects(); _update_project_buttons(); + _update_list_placeholder(); } void ProjectManager::_update_project_buttons() { - Vector<ProjectList::Item> selected_projects = _project_list->get_selected_projects(); + Vector<ProjectList::Item> selected_projects = project_list->get_selected_projects(); bool empty_selection = selected_projects.is_empty(); bool is_missing_project_selected = false; @@ -561,53 +684,53 @@ void ProjectManager::_update_project_buttons() { manage_tags_btn->set_disabled(empty_selection || is_missing_project_selected || selected_projects.size() > 1); run_btn->set_disabled(empty_selection || is_missing_project_selected); - erase_missing_btn->set_disabled(!_project_list->is_any_project_missing()); + erase_missing_btn->set_disabled(!project_list->is_any_project_missing()); } void ProjectManager::_on_projects_updated() { - Vector<ProjectList::Item> selected_projects = _project_list->get_selected_projects(); + Vector<ProjectList::Item> selected_projects = project_list->get_selected_projects(); int index = 0; for (int i = 0; i < selected_projects.size(); ++i) { - index = _project_list->refresh_project(selected_projects[i].path); + index = project_list->refresh_project(selected_projects[i].path); } if (index != -1) { - _project_list->ensure_project_visible(index); + project_list->ensure_project_visible(index); } - _project_list->update_dock_menu(); + project_list->update_dock_menu(); } void ProjectManager::_on_project_created(const String &dir) { - _project_list->add_project(dir, false); - _project_list->save_config(); + project_list->add_project(dir, false); + project_list->save_config(); search_box->clear(); - int i = _project_list->refresh_project(dir); - _project_list->select_project(i); - _project_list->ensure_project_visible(i); + int i = project_list->refresh_project(dir); + project_list->select_project(i); + project_list->ensure_project_visible(i); _open_selected_projects_ask(); - _project_list->update_dock_menu(); + project_list->update_dock_menu(); } void ProjectManager::_on_order_option_changed(int p_idx) { if (is_inside_tree()) { - _project_list->set_order_option(p_idx); + project_list->set_order_option(p_idx); } } void ProjectManager::_on_search_term_changed(const String &p_term) { - _project_list->set_search_term(p_term); - _project_list->sort_projects(); + project_list->set_search_term(p_term); + project_list->sort_projects(); // Select the first visible project in the list. // This makes it possible to open a project without ever touching the mouse, // as the search field is automatically focused on startup. - _project_list->select_first_visible_project(); + project_list->select_first_visible_project(); _update_project_buttons(); } void ProjectManager::_on_search_term_submitted(const String &p_text) { - if (tabs->get_current_tab() != 0) { + if (current_main_view != MAIN_VIEW_PROJECTS) { return; } @@ -625,7 +748,7 @@ void ProjectManager::_manage_project_tags() { project_tags->get_child(i)->queue_free(); } - const ProjectList::Item item = _project_list->get_selected_projects()[0]; + const ProjectList::Item item = project_list->get_selected_projects()[0]; current_project_tags = item.tags; for (const String &tag : current_project_tags) { ProjectTag *tag_control = memnew(ProjectTag(tag, true)); @@ -669,7 +792,7 @@ void ProjectManager::_apply_project_tags() { } ConfigFile cfg; - const String project_godot = _project_list->get_selected_projects()[0].path.path_join("project.godot"); + const String project_godot = project_list->get_selected_projects()[0].path.path_join("project.godot"); Error err = cfg.load(project_godot); if (err != OK) { tag_edit_error->set_text(vformat(TTR("Couldn't load project at '%s' (error %d). It may be missing or corrupted."), project_godot, err)); @@ -747,7 +870,7 @@ void ProjectManager::_full_convert_button_pressed() { } void ProjectManager::_perform_full_project_conversion() { - Vector<ProjectList::Item> selected_list = _project_list->get_selected_projects(); + Vector<ProjectList::Item> selected_list = project_list->get_selected_projects(); if (selected_list.is_empty()) { return; } @@ -765,7 +888,7 @@ void ProjectManager::_perform_full_project_conversion() { Error err = OS::get_singleton()->create_instance(args); ERR_FAIL_COND(err); - _project_list->set_project_version(path, GODOT4_CONFIG_VERSION); + project_list->set_project_version(path, GODOT4_CONFIG_VERSION); } // Input and I/O. @@ -790,7 +913,7 @@ void ProjectManager::shortcut_input(const Ref<InputEvent> &p_ev) { } #endif - if (tabs->get_current_tab() != 0) { + if (current_main_view != MAIN_VIEW_PROJECTS) { return; } @@ -801,15 +924,15 @@ void ProjectManager::shortcut_input(const Ref<InputEvent> &p_ev) { _open_selected_projects_ask(); } break; case Key::HOME: { - if (_project_list->get_project_count() > 0) { - _project_list->select_project(0); + if (project_list->get_project_count() > 0) { + project_list->select_project(0); _update_project_buttons(); } } break; case Key::END: { - if (_project_list->get_project_count() > 0) { - _project_list->select_project(_project_list->get_project_count() - 1); + if (project_list->get_project_count() > 0) { + project_list->select_project(project_list->get_project_count() - 1); _update_project_buttons(); } @@ -819,10 +942,10 @@ void ProjectManager::shortcut_input(const Ref<InputEvent> &p_ev) { break; } - int index = _project_list->get_single_selected_index(); + int index = project_list->get_single_selected_index(); if (index > 0) { - _project_list->select_project(index - 1); - _project_list->ensure_project_visible(index - 1); + project_list->select_project(index - 1); + project_list->ensure_project_visible(index - 1); _update_project_buttons(); } @@ -833,10 +956,10 @@ void ProjectManager::shortcut_input(const Ref<InputEvent> &p_ev) { break; } - int index = _project_list->get_single_selected_index(); - if (index + 1 < _project_list->get_project_count()) { - _project_list->select_project(index + 1); - _project_list->ensure_project_visible(index + 1); + int index = project_list->get_single_selected_index(); + if (index + 1 < project_list->get_project_count()) { + project_list->select_project(index + 1); + project_list->ensure_project_visible(index + 1); _update_project_buttons(); } @@ -879,7 +1002,7 @@ void ProjectManager::_files_dropped(PackedStringArray p_files) { for (const String &E : folders_set) { folders.push_back(E); } - _project_list->find_projects_multiple(folders); + project_list->find_projects_multiple(folders); } // Object methods. @@ -955,10 +1078,9 @@ ProjectManager::ProjectManager() { Window::set_root_layout_direction(pm_root_dir); EditorThemeManager::initialize(); - Ref<Theme> theme = EditorThemeManager::generate_theme(); + theme = EditorThemeManager::generate_theme(); DisplayServer::set_early_window_clear_color_override(true, theme->get_color(SNAME("background"), EditorStringName(Editor))); - set_theme(theme); set_anchors_and_offsets_preset(Control::PRESET_FULL_RECT); _build_icon_type_cache(theme); @@ -970,95 +1092,59 @@ ProjectManager::ProjectManager() { add_child(background_panel); background_panel->set_anchors_and_offsets_preset(Control::PRESET_FULL_RECT); - VBoxContainer *vb = memnew(VBoxContainer); - background_panel->add_child(vb); - vb->set_anchors_and_offsets_preset(Control::PRESET_FULL_RECT, Control::PRESET_MODE_MINSIZE, 8 * EDSCALE); - - Control *center_box = memnew(Control); - center_box->set_v_size_flags(Control::SIZE_EXPAND_FILL); - vb->add_child(center_box); + root_container = memnew(MarginContainer); + add_child(root_container); + root_container->set_anchors_and_offsets_preset(Control::PRESET_FULL_RECT); - tabs = memnew(TabContainer); - tabs->set_anchors_and_offsets_preset(Control::PRESET_FULL_RECT); - center_box->add_child(tabs); - tabs->connect("tab_changed", callable_mp(this, &ProjectManager::_on_tab_changed)); + main_vbox = memnew(VBoxContainer); + root_container->add_child(main_vbox); - // Quick settings. + // Title bar. { - settings_hb = memnew(HBoxContainer); - settings_hb->set_alignment(BoxContainer::ALIGNMENT_END); - settings_hb->set_h_grow_direction(Control::GROW_DIRECTION_BEGIN); - settings_hb->set_anchors_and_offsets_preset(Control::PRESET_TOP_RIGHT); - - // A VBoxContainer that contains a dummy Control node to adjust the LinkButton's vertical position. - VBoxContainer *spacer_vb = memnew(VBoxContainer); - settings_hb->add_child(spacer_vb); - - Control *v_spacer = memnew(Control); - spacer_vb->add_child(v_spacer); - - version_btn = memnew(LinkButton); - String hash = String(VERSION_HASH); - if (hash.length() != 0) { - hash = " " + vformat("[%s]", hash.left(9)); - } - version_btn->set_text("v" VERSION_FULL_BUILD + hash); - // Fade the version label to be less prominent, but still readable. - version_btn->set_self_modulate(Color(1, 1, 1, 0.6)); - version_btn->set_underline_mode(LinkButton::UNDERLINE_MODE_ON_HOVER); - version_btn->set_tooltip_text(TTR("Click to copy.")); - version_btn->connect("pressed", callable_mp(this, &ProjectManager::_version_button_pressed)); - spacer_vb->add_child(version_btn); - - // Add a small horizontal spacer between the version and language buttons - // to distinguish them. - Control *h_spacer = memnew(Control); - settings_hb->add_child(h_spacer); - - language_btn = memnew(OptionButton); - language_btn->set_focus_mode(Control::FOCUS_NONE); - language_btn->set_fit_to_longest_item(false); - language_btn->set_flat(true); - language_btn->connect("item_selected", callable_mp(this, &ProjectManager::_language_selected)); -#ifdef ANDROID_ENABLED - // The language selection dropdown doesn't work on Android (as the setting isn't saved), see GH-60353. - // Also, the dropdown it spawns is very tall and can't be scrolled without a hardware mouse. - // Hiding the language selection dropdown also leaves more space for the version label to display. - language_btn->hide(); -#endif - - Vector<String> editor_languages; - List<PropertyInfo> editor_settings_properties; - EditorSettings::get_singleton()->get_property_list(&editor_settings_properties); - for (const PropertyInfo &pi : editor_settings_properties) { - if (pi.name == "interface/editor/editor_language") { - editor_languages = pi.hint_string.split(","); - break; - } - } - - String current_lang = EDITOR_GET("interface/editor/editor_language"); - language_btn->set_text(current_lang); - - for (int i = 0; i < editor_languages.size(); i++) { - const String &lang = editor_languages[i]; - String lang_name = TranslationServer::get_singleton()->get_locale_name(lang); - language_btn->add_item(vformat("[%s] %s", lang, lang_name), i); - language_btn->set_item_metadata(i, lang); - if (current_lang == lang) { - language_btn->select(i); - } - } - - settings_hb->add_child(language_btn); - center_box->add_child(settings_hb); + title_bar = memnew(HBoxContainer); + main_vbox->add_child(title_bar); + + HBoxContainer *left_hbox = memnew(HBoxContainer); + left_hbox->set_alignment(BoxContainer::ALIGNMENT_BEGIN); + left_hbox->set_h_size_flags(Control::SIZE_EXPAND_FILL); + left_hbox->set_stretch_ratio(1.0); + title_bar->add_child(left_hbox); + + title_bar_logo = memnew(Button); + title_bar_logo->set_flat(true); + left_hbox->add_child(title_bar_logo); + title_bar_logo->connect("pressed", callable_mp(this, &ProjectManager::_show_about)); + + main_view_toggles = memnew(HBoxContainer); + main_view_toggles->set_alignment(BoxContainer::ALIGNMENT_CENTER); + main_view_toggles->set_h_size_flags(Control::SIZE_EXPAND_FILL); + main_view_toggles->set_stretch_ratio(2.0); + title_bar->add_child(main_view_toggles); + + main_view_toggles_group.instantiate(); + + HBoxContainer *right_hbox = memnew(HBoxContainer); + right_hbox->set_alignment(BoxContainer::ALIGNMENT_END); + right_hbox->set_h_size_flags(Control::SIZE_EXPAND_FILL); + right_hbox->set_stretch_ratio(1.0); + title_bar->add_child(right_hbox); + + quick_settings_button = memnew(Button); + quick_settings_button->set_flat(true); + quick_settings_button->set_text(TTR("Settings")); + right_hbox->add_child(quick_settings_button); + quick_settings_button->connect("pressed", callable_mp(this, &ProjectManager::_show_quick_settings)); } + main_view_container = memnew(PanelContainer); + main_view_container->set_v_size_flags(Control::SIZE_EXPAND_FILL); + main_vbox->add_child(main_view_container); + // Project list view. { local_projects_vb = memnew(VBoxContainer); - local_projects_vb->set_name(TTR("Local Projects")); - tabs->add_child(local_projects_vb); + local_projects_vb->set_name("LocalProjectsTab"); + _add_main_view(MAIN_VIEW_PROJECTS, TTR("Projects"), Ref<Texture2D>(), local_projects_vb); // Project list's top bar. { @@ -1067,7 +1153,7 @@ ProjectManager::ProjectManager() { local_projects_vb->add_child(hb); create_btn = memnew(Button); - create_btn->set_text(TTR("New")); + create_btn->set_text(TTR("Create")); create_btn->set_shortcut(ED_SHORTCUT("project_manager/new_project", TTR("New Project"), KeyModifierMask::CMD_OR_CTRL | Key::N)); create_btn->connect("pressed", callable_mp(this, &ProjectManager::_new_project)); hb->add_child(create_btn); @@ -1086,9 +1172,8 @@ ProjectManager::ProjectManager() { loading_label = memnew(Label(TTR("Loading, please wait..."))); loading_label->set_h_size_flags(Control::SIZE_EXPAND_FILL); - hb->add_child(loading_label); - // The loading label is shown later. loading_label->hide(); + hb->add_child(loading_label); search_box = memnew(LineEdit); search_box->set_placeholder(TTR("Filter Projects")); @@ -1123,88 +1208,158 @@ ProjectManager::ProjectManager() { // Project list and its sidebar. { - HBoxContainer *search_tree_hb = memnew(HBoxContainer); - local_projects_vb->add_child(search_tree_hb); - search_tree_hb->set_v_size_flags(Control::SIZE_EXPAND_FILL); - - search_panel = memnew(PanelContainer); - search_panel->set_h_size_flags(Control::SIZE_EXPAND_FILL); - search_tree_hb->add_child(search_panel); - - _project_list = memnew(ProjectList); - _project_list->set_horizontal_scroll_mode(ScrollContainer::SCROLL_MODE_DISABLED); - search_panel->add_child(_project_list); - _project_list->connect(ProjectList::SIGNAL_LIST_CHANGED, callable_mp(this, &ProjectManager::_update_project_buttons)); - _project_list->connect(ProjectList::SIGNAL_SELECTION_CHANGED, callable_mp(this, &ProjectManager::_update_project_buttons)); - _project_list->connect(ProjectList::SIGNAL_PROJECT_ASK_OPEN, callable_mp(this, &ProjectManager::_open_selected_projects_ask)); + HBoxContainer *project_list_hbox = memnew(HBoxContainer); + local_projects_vb->add_child(project_list_hbox); + project_list_hbox->set_v_size_flags(Control::SIZE_EXPAND_FILL); + + project_list_panel = memnew(PanelContainer); + project_list_panel->set_h_size_flags(Control::SIZE_EXPAND_FILL); + project_list_hbox->add_child(project_list_panel); + + project_list = memnew(ProjectList); + project_list->set_horizontal_scroll_mode(ScrollContainer::SCROLL_MODE_DISABLED); + project_list_panel->add_child(project_list); + project_list->connect(ProjectList::SIGNAL_LIST_CHANGED, callable_mp(this, &ProjectManager::_update_project_buttons)); + project_list->connect(ProjectList::SIGNAL_LIST_CHANGED, callable_mp(this, &ProjectManager::_update_list_placeholder)); + project_list->connect(ProjectList::SIGNAL_SELECTION_CHANGED, callable_mp(this, &ProjectManager::_update_project_buttons)); + project_list->connect(ProjectList::SIGNAL_PROJECT_ASK_OPEN, callable_mp(this, &ProjectManager::_open_selected_projects_ask)); + + // Empty project list placeholder. + { + empty_list_placeholder = memnew(VBoxContainer); + empty_list_placeholder->set_v_size_flags(Control::SIZE_SHRINK_CENTER); + empty_list_placeholder->add_theme_constant_override("separation", 16 * EDSCALE); + empty_list_placeholder->hide(); + project_list_panel->add_child(empty_list_placeholder); + + RichTextLabel *empty_list_message = memnew(RichTextLabel); + empty_list_message->set_use_bbcode(true); + empty_list_message->set_fit_content(true); + empty_list_message->set_h_size_flags(SIZE_EXPAND_FILL); + empty_list_message->add_theme_style_override("normal", memnew(StyleBoxEmpty)); + + const String line1 = TTR("You don't have any projects yet."); + const String line2 = TTR("Get started by creating a new one,\nimporting one that exists, or by downloading a project template from the Asset Library!"); + empty_list_message->set_text(vformat("[center][b]%s[/b] %s[/center]", line1, line2)); + empty_list_placeholder->add_child(empty_list_message); + + HBoxContainer *empty_list_actions = memnew(HBoxContainer); + empty_list_actions->set_alignment(BoxContainer::ALIGNMENT_CENTER); + empty_list_placeholder->add_child(empty_list_actions); + + empty_list_create_project = memnew(Button); + empty_list_create_project->set_text(TTR("Create New Project")); + empty_list_create_project->set_theme_type_variation("PanelBackgroundButton"); + empty_list_actions->add_child(empty_list_create_project); + empty_list_create_project->connect("pressed", callable_mp(this, &ProjectManager::_new_project)); + + empty_list_import_project = memnew(Button); + empty_list_import_project->set_text(TTR("Import Existing Project")); + empty_list_import_project->set_theme_type_variation("PanelBackgroundButton"); + empty_list_actions->add_child(empty_list_import_project); + empty_list_import_project->connect("pressed", callable_mp(this, &ProjectManager::_import_project)); + + empty_list_open_assetlib = memnew(Button); + empty_list_open_assetlib->set_text(TTR("Open Asset Library")); + empty_list_open_assetlib->set_theme_type_variation("PanelBackgroundButton"); + empty_list_actions->add_child(empty_list_open_assetlib); + empty_list_open_assetlib->connect("pressed", callable_mp(this, &ProjectManager::_open_asset_library_confirmed)); + + empty_list_online_warning = memnew(Label); + empty_list_online_warning->set_horizontal_alignment(HorizontalAlignment::HORIZONTAL_ALIGNMENT_CENTER); + empty_list_online_warning->set_custom_minimum_size(Size2(220, 0) * EDSCALE); + empty_list_online_warning->set_autowrap_mode(TextServer::AUTOWRAP_WORD); + empty_list_online_warning->set_h_size_flags(Control::SIZE_EXPAND_FILL); + empty_list_online_warning->set_text(TTR("Note: The Asset Library requires an online connection and involves sending data over the internet.")); + empty_list_placeholder->add_child(empty_list_online_warning); + } // The side bar with the edit, run, rename, etc. buttons. - VBoxContainer *tree_vb = memnew(VBoxContainer); - tree_vb->set_custom_minimum_size(Size2(120, 120)); - search_tree_hb->add_child(tree_vb); + VBoxContainer *project_list_sidebar = memnew(VBoxContainer); + project_list_sidebar->set_custom_minimum_size(Size2(120, 120)); + project_list_hbox->add_child(project_list_sidebar); - tree_vb->add_child(memnew(HSeparator)); + project_list_sidebar->add_child(memnew(HSeparator)); open_btn = memnew(Button); open_btn->set_text(TTR("Edit")); open_btn->set_shortcut(ED_SHORTCUT("project_manager/edit_project", TTR("Edit Project"), KeyModifierMask::CMD_OR_CTRL | Key::E)); open_btn->connect("pressed", callable_mp(this, &ProjectManager::_open_selected_projects_ask)); - tree_vb->add_child(open_btn); + project_list_sidebar->add_child(open_btn); run_btn = memnew(Button); run_btn->set_text(TTR("Run")); run_btn->set_shortcut(ED_SHORTCUT("project_manager/run_project", TTR("Run Project"), KeyModifierMask::CMD_OR_CTRL | Key::R)); run_btn->connect("pressed", callable_mp(this, &ProjectManager::_run_project)); - tree_vb->add_child(run_btn); + project_list_sidebar->add_child(run_btn); rename_btn = memnew(Button); rename_btn->set_text(TTR("Rename")); // The F2 shortcut isn't overridden with Enter on macOS as Enter is already used to edit a project. rename_btn->set_shortcut(ED_SHORTCUT("project_manager/rename_project", TTR("Rename Project"), Key::F2)); rename_btn->connect("pressed", callable_mp(this, &ProjectManager::_rename_project)); - tree_vb->add_child(rename_btn); + project_list_sidebar->add_child(rename_btn); manage_tags_btn = memnew(Button); manage_tags_btn->set_text(TTR("Manage Tags")); - tree_vb->add_child(manage_tags_btn); + project_list_sidebar->add_child(manage_tags_btn); erase_btn = memnew(Button); erase_btn->set_text(TTR("Remove")); erase_btn->set_shortcut(ED_SHORTCUT("project_manager/remove_project", TTR("Remove Project"), Key::KEY_DELETE)); erase_btn->connect("pressed", callable_mp(this, &ProjectManager::_erase_project)); - tree_vb->add_child(erase_btn); + project_list_sidebar->add_child(erase_btn); + + Control *filler = memnew(Control); + filler->set_v_size_flags(Control::SIZE_EXPAND_FILL); + project_list_sidebar->add_child(filler); erase_missing_btn = memnew(Button); erase_missing_btn->set_text(TTR("Remove Missing")); erase_missing_btn->connect("pressed", callable_mp(this, &ProjectManager::_erase_missing_projects)); - tree_vb->add_child(erase_missing_btn); - - tree_vb->add_spacer(); - - about_btn = memnew(Button); - about_btn->set_text(TTR("About")); - about_btn->connect("pressed", callable_mp(this, &ProjectManager::_show_about)); - tree_vb->add_child(about_btn); + project_list_sidebar->add_child(erase_missing_btn); } } + // Asset library view. if (AssetLibraryEditorPlugin::is_available()) { asset_library = memnew(EditorAssetLibrary(true)); - asset_library->set_name(TTR("Asset Library Projects")); - tabs->add_child(asset_library); + asset_library->set_name("AssetLibraryTab"); + _add_main_view(MAIN_VIEW_ASSETLIB, TTR("Asset Library"), Ref<Texture2D>(), asset_library); asset_library->connect("install_asset", callable_mp(this, &ProjectManager::_install_project)); } else { - print_verbose("Asset Library not available (due to using Web editor, or SSL support disabled)."); + VBoxContainer *asset_library_filler = memnew(VBoxContainer); + asset_library_filler->set_name("AssetLibraryTab"); + Button *asset_library_toggle = _add_main_view(MAIN_VIEW_ASSETLIB, TTR("Asset Library"), Ref<Texture2D>(), asset_library_filler); + asset_library_toggle->set_disabled(true); + asset_library_toggle->set_tooltip_text(TTR("Asset Library not available (due to using Web editor, or because SSL support disabled).")); + } + + // Footer bar. + { + HBoxContainer *footer_bar = memnew(HBoxContainer); + footer_bar->set_alignment(BoxContainer::ALIGNMENT_END); + main_vbox->add_child(footer_bar); + + version_btn = memnew(LinkButton); + String hash = String(VERSION_HASH); + if (hash.length() != 0) { + hash = " " + vformat("[%s]", hash.left(9)); + } + version_btn->set_text("v" VERSION_FULL_BUILD + hash); + // Fade the version label to be less prominent, but still readable. + version_btn->set_self_modulate(Color(1, 1, 1, 0.6)); + version_btn->set_underline_mode(LinkButton::UNDERLINE_MODE_ON_HOVER); + version_btn->set_tooltip_text(TTR("Click to copy the version information.")); + version_btn->connect("pressed", callable_mp(this, &ProjectManager::_version_button_pressed)); + footer_bar->add_child(version_btn); } // Dialogs. { - restart_required_dialog = memnew(ConfirmationDialog); - restart_required_dialog->set_ok_button_text(TTR("Restart Now")); - restart_required_dialog->get_ok_button()->connect("pressed", callable_mp(this, &ProjectManager::_restart_confirm)); - restart_required_dialog->set_cancel_button_text(TTR("Continue")); - restart_required_dialog->set_text(TTR("Settings changed!\nThe project manager must be restarted for changes to take effect.")); - add_child(restart_required_dialog); + quick_settings_dialog = memnew(QuickSettingsDialog); + add_child(quick_settings_dialog); + quick_settings_dialog->connect("restart_required", callable_mp(this, &ProjectManager::_restart_confirmed)); scan_dir = memnew(EditorFileDialog); scan_dir->set_previews_enabled(false); @@ -1213,7 +1368,7 @@ ProjectManager::ProjectManager() { scan_dir->set_title(TTR("Select a Folder to Scan")); // must be after mode or it's overridden scan_dir->set_current_dir(EDITOR_GET("filesystem/directories/default_project_path")); add_child(scan_dir); - scan_dir->connect("dir_selected", callable_mp(_project_list, &ProjectList::find_projects)); + scan_dir->connect("dir_selected", callable_mp(project_list, &ProjectList::find_projects)); erase_missing_ask = memnew(ConfirmationDialog); erase_missing_ask->set_ok_button_text(TTR("Remove All")); @@ -1260,28 +1415,17 @@ ProjectManager::ProjectManager() { ask_full_convert_dialog->connect("confirmed", callable_mp(this, &ProjectManager::_perform_full_project_conversion)); add_child(ask_full_convert_dialog); - npdialog = memnew(ProjectDialog); - npdialog->connect("projects_updated", callable_mp(this, &ProjectManager::_on_projects_updated)); - npdialog->connect("project_created", callable_mp(this, &ProjectManager::_on_project_created)); - add_child(npdialog); - - run_error_diag = memnew(AcceptDialog); - run_error_diag->set_title(TTR("Can't run project")); - add_child(run_error_diag); + project_dialog = memnew(ProjectDialog); + project_dialog->connect("projects_updated", callable_mp(this, &ProjectManager::_on_projects_updated)); + project_dialog->connect("project_created", callable_mp(this, &ProjectManager::_on_project_created)); + add_child(project_dialog); - dialog_error = memnew(AcceptDialog); - add_child(dialog_error); - - if (asset_library) { - open_templates = memnew(ConfirmationDialog); - open_templates->set_text(TTR("You currently don't have any projects.\nWould you like to explore official example projects in the Asset Library?")); - open_templates->set_ok_button_text(TTR("Open Asset Library")); - open_templates->connect("confirmed", callable_mp(this, &ProjectManager::_open_asset_library)); - add_child(open_templates); - } + error_dialog = memnew(AcceptDialog); + error_dialog->set_title(TTR("Error")); + add_child(error_dialog); - about = memnew(EditorAbout); - add_child(about); + about_dialog = memnew(EditorAbout); + add_child(about_dialog); } // Tag management. @@ -1370,7 +1514,7 @@ ProjectManager::ProjectManager() { String autoscan_path = EDITOR_GET("filesystem/directories/autoscan_project_path"); if (!autoscan_path.is_empty()) { if (dir_access->dir_exists(autoscan_path)) { - _project_list->find_projects(autoscan_path); + project_list->find_projects(autoscan_path); scanned_for_projects = true; } else { Error error = dir_access->make_dir_recursive(autoscan_path); @@ -1381,7 +1525,7 @@ ProjectManager::ProjectManager() { } if (!scanned_for_projects) { - _project_list->update_project_list(); + project_list->update_project_list(); } } |