diff options
Diffstat (limited to 'editor/project_manager.cpp')
-rw-r--r-- | editor/project_manager.cpp | 238 |
1 files changed, 145 insertions, 93 deletions
diff --git a/editor/project_manager.cpp b/editor/project_manager.cpp index 5a1eedd8a2..c4f5eb777e 100644 --- a/editor/project_manager.cpp +++ b/editor/project_manager.cpp @@ -1,32 +1,32 @@ -/*************************************************************************/ -/* project_manager.cpp */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ +/**************************************************************************/ +/* project_manager.cpp */ +/**************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/**************************************************************************/ +/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */ +/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/**************************************************************************/ #include "project_manager.h" @@ -49,6 +49,7 @@ #include "editor/editor_vcs_interface.h" #include "main/main.h" #include "scene/gui/center_container.h" +#include "scene/gui/check_box.h" #include "scene/gui/line_edit.h" #include "scene/gui/margin_container.h" #include "scene/gui/panel_container.h" @@ -93,6 +94,7 @@ private: Container *path_container; Container *install_path_container; Container *renderer_container; + Label *renderer_info; HBoxContainer *default_files_container; Ref<ButtonGroup> renderer_button_group; Label *msg; @@ -425,6 +427,35 @@ private: ok_pressed(); } + void _renderer_selected() { + String renderer_type = renderer_button_group->get_pressed_button()->get_meta(SNAME("rendering_method")); + + if (renderer_type == "forward_plus") { + renderer_info->set_text( + String::utf8("• ") + TTR("Supports desktop platforms only.") + + String::utf8("\n• ") + TTR("Advanced 3D graphics available.") + + String::utf8("\n• ") + TTR("Can scale to large complex scenes.") + + String::utf8("\n• ") + TTR("Uses RenderingDevice backend.") + + String::utf8("\n• ") + TTR("Slower rendering of simple scenes.")); + } else if (renderer_type == "mobile") { + renderer_info->set_text( + String::utf8("• ") + TTR("Supports desktop + mobile platforms.") + + String::utf8("\n• ") + TTR("Less advanced 3D graphics.") + + String::utf8("\n• ") + TTR("Less scalable for complex scenes.") + + String::utf8("\n• ") + TTR("Uses RenderingDevice backend.") + + String::utf8("\n• ") + TTR("Fast rendering of simple scenes.")); + } else if (renderer_type == "gl_compatibility") { + renderer_info->set_text( + String::utf8("• ") + TTR("Supports desktop, mobile + web platforms.") + + String::utf8("\n• ") + TTR("Least advanced 3D graphics (currently work-in-progress).") + + String::utf8("\n• ") + TTR("Intended for low-end/older devices.") + + String::utf8("\n• ") + TTR("Uses OpenGL 3 backend (OpenGL 3.3/ES 3.0/WebGL2).") + + String::utf8("\n• ") + TTR("Fastest rendering of simple scenes.")); + } else { + WARN_PRINT("Unknown renderer type. Please report this as a bug on GitHub."); + } + } + void ok_pressed() override { String dir = project_path->get_text(); @@ -435,17 +466,17 @@ private: return; } - ProjectSettings *current = memnew(ProjectSettings); - - int err = current->setup(dir2, ""); + // Load project.godot as ConfigFile to set the new name. + ConfigFile cfg; + String project_godot = dir2.path_join("project.godot"); + Error err = cfg.load(project_godot); if (err != OK) { - set_message(vformat(TTR("Couldn't load project.godot in project path (error %d). It may be missing or corrupted."), err), MESSAGE_ERROR); + set_message(vformat(TTR("Couldn't load project at '%s' (error %d). It may be missing or corrupted."), project_godot, err), MESSAGE_ERROR); } else { - ProjectSettings::CustomMap edited_settings; - edited_settings["application/config/name"] = project_name->get_text().strip_edges(); - - if (current->save_custom(dir2.path_join("project.godot"), edited_settings, Vector<String>(), true) != OK) { - set_message(TTR("Couldn't edit project.godot in project path."), MESSAGE_ERROR); + cfg.set_value("application", "config/name", project_name->get_text().strip_edges()); + err = cfg.save(project_godot); + if (err != OK) { + set_message(vformat(TTR("Couldn't save project at '%s' (error %d)."), project_godot, err), MESSAGE_ERROR); } } @@ -482,10 +513,15 @@ private: String renderer_type = renderer_button_group->get_pressed_button()->get_meta(SNAME("rendering_method")); initial_settings["rendering/renderer/rendering_method"] = renderer_type; + EditorSettings::get_singleton()->set("project_manager/default_renderer", renderer_type); + EditorSettings::get_singleton()->save(); + if (renderer_type == "forward_plus") { project_features.push_back("Forward Plus"); } else if (renderer_type == "mobile") { project_features.push_back("Mobile"); + } else if (renderer_type == "gl_compatibility") { + project_features.push_back("GL Compatibility"); } else { WARN_PRINT("Unknown renderer type. Please report this as a bug on GitHub."); } @@ -546,7 +582,6 @@ private: Vector<String> failed_files; - int idx = 0; while (ret == UNZ_OK) { //get filename unz_file_info info; @@ -585,7 +620,6 @@ private: } } - idx++; ret = unzGoToNextFile(pkg); } @@ -695,18 +729,19 @@ public: default_files_container->hide(); get_ok_button()->set_disabled(false); - ProjectSettings *current = memnew(ProjectSettings); - - int err = current->setup(project_path->get_text(), ""); + // Fetch current name from project.godot to prefill the text input. + ConfigFile cfg; + String project_godot = project_path->get_text().path_join("project.godot"); + Error err = cfg.load(project_godot); if (err != OK) { - set_message(vformat(TTR("Couldn't load project.godot in project path (error %d). It may be missing or corrupted."), err), MESSAGE_ERROR); + set_message(vformat(TTR("Couldn't load project at '%s' (error %d). It may be missing or corrupted."), project_godot, err), MESSAGE_ERROR); status_rect->show(); msg->show(); get_ok_button()->set_disabled(true); - } else if (current->has_setting("application/config/name")) { - String proj = current->get("application/config/name"); - project_name->set_text(proj); - _text_changed(proj); + } else { + String cur_name = cfg.get_value("application", "config/name", ""); + project_name->set_text(cur_name); + _text_changed(cur_name); } project_name->call_deferred(SNAME("grab_focus")); @@ -714,7 +749,7 @@ public: create_dir->hide(); } else { - fav_dir = EditorSettings::get_singleton()->get("filesystem/directories/default_project_path"); + fav_dir = EDITOR_GET("filesystem/directories/default_project_path"); if (!fav_dir.is_empty()) { project_path->set_text(fav_dir); fdialog->set_current_dir(fav_dir); @@ -860,42 +895,55 @@ public: renderer_container->add_child(rshc); renderer_button_group.instantiate(); + // Left hand side, used for checkboxes to select renderer. Container *rvb = memnew(VBoxContainer); - rvb->set_h_size_flags(Control::SIZE_EXPAND_FILL); rshc->add_child(rvb); + + String default_renderer_type = "forward_plus"; + if (EditorSettings::get_singleton()->has_setting("project_manager/default_renderer")) { + default_renderer_type = EditorSettings::get_singleton()->get_setting("project_manager/default_renderer"); + } + Button *rs_button = memnew(CheckBox); rs_button->set_button_group(renderer_button_group); rs_button->set_text(TTR("Forward+")); rs_button->set_meta(SNAME("rendering_method"), "forward_plus"); - rs_button->set_pressed(true); + rs_button->connect("pressed", callable_mp(this, &ProjectDialog::_renderer_selected)); rvb->add_child(rs_button); - l = memnew(Label); - l->set_text( - String::utf8("• ") + TTR("Supports desktop platforms only.") + - String::utf8("\n• ") + TTR("Advanced 3D graphics available.") + - String::utf8("\n• ") + TTR("Can scale to large complex scenes.") + - String::utf8("\n• ") + TTR("Slower rendering of simple scenes.")); - l->set_modulate(Color(1, 1, 1, 0.7)); - rvb->add_child(l); - - rshc->add_child(memnew(VSeparator)); + if (default_renderer_type == "forward_plus") { + rs_button->set_pressed(true); + } - rvb = memnew(VBoxContainer); - rvb->set_h_size_flags(Control::SIZE_EXPAND_FILL); - rshc->add_child(rvb); rs_button = memnew(CheckBox); rs_button->set_button_group(renderer_button_group); rs_button->set_text(TTR("Mobile")); rs_button->set_meta(SNAME("rendering_method"), "mobile"); + rs_button->connect("pressed", callable_mp(this, &ProjectDialog::_renderer_selected)); rvb->add_child(rs_button); - l = memnew(Label); - l->set_text( - String::utf8("• ") + TTR("Supports desktop + mobile platforms.") + - String::utf8("\n• ") + TTR("Less advanced 3D graphics.") + - String::utf8("\n• ") + TTR("Less scalable for complex scenes.") + - String::utf8("\n• ") + TTR("Faster rendering of simple scenes.")); - l->set_modulate(Color(1, 1, 1, 0.7)); - rvb->add_child(l); + if (default_renderer_type == "mobile") { + rs_button->set_pressed(true); + } + + rs_button = memnew(CheckBox); + rs_button->set_button_group(renderer_button_group); + rs_button->set_text(TTR("Compatibility")); + rs_button->set_meta(SNAME("rendering_method"), "gl_compatibility"); + rs_button->connect("pressed", callable_mp(this, &ProjectDialog::_renderer_selected)); + rvb->add_child(rs_button); + if (default_renderer_type == "gl_compatibility") { + rs_button->set_pressed(true); + } + + rshc->add_child(memnew(VSeparator)); + + // Right hand side, used for text explaining each choice. + rvb = memnew(VBoxContainer); + rvb->set_h_size_flags(Control::SIZE_EXPAND_FILL); + rshc->add_child(rvb); + renderer_info = memnew(Label); + renderer_info->set_modulate(Color(1, 1, 1, 0.7)); + rvb->add_child(renderer_info); + _renderer_selected(); l = memnew(Label); l->set_text(TTR("The renderer can be changed later, but scenes may need to be adjusted.")); @@ -1185,7 +1233,7 @@ void ProjectList::load_project_icon(int p_index) { // The default project icon is 128×128 to look crisp on hiDPI displays, // but we want the actual displayed size to be 64×64 on loDPI displays. - item.control->icon->set_ignore_texture_size(true); + item.control->icon->set_expand_mode(TextureRect::EXPAND_IGNORE_SIZE); item.control->icon->set_custom_minimum_size(Size2(64, 64) * EDSCALE); item.control->icon->set_stretch_mode(TextureRect::STRETCH_KEEP_ASPECT_CENTERED); @@ -1225,7 +1273,7 @@ ProjectList::Item ProjectList::load_project_data(const String &p_path, bool p_fa PackedStringArray unsupported_features = ProjectSettings::get_unsupported_features(project_features); uint64_t last_edited = 0; - if (FileAccess::exists(conf)) { + if (cf_err == OK) { // The modification date marks the date the project was last edited. // This is because the `project.godot` file will always be modified // when editing a project (but not when running it). @@ -1253,7 +1301,6 @@ void ProjectList::migrate_config() { if (FileAccess::exists(_config_path)) { return; } - print_line("Migrating legacy project list"); List<PropertyInfo> properties; EditorSettings::get_singleton()->get_property_list(&properties); @@ -1265,7 +1312,9 @@ void ProjectList::migrate_config() { continue; } - String path = EditorSettings::get_singleton()->get(property_key); + String path = EDITOR_GET(property_key); + print_line("Migrating legacy project '" + path + "'."); + String favoriteKey = "favorite_projects/" + property_key.get_slice("/", 1); bool favorite = EditorSettings::get_singleton()->has_setting(favoriteKey); add_project(path, favorite); @@ -1378,7 +1427,7 @@ void ProjectList::create_project_item_control(int p_index) { favorite_box->set_name("FavoriteBox"); TextureButton *favorite = memnew(TextureButton); favorite->set_name("FavoriteButton"); - favorite->set_normal_texture(favorite_icon); + favorite->set_texture_normal(favorite_icon); // This makes the project's "hover" style display correctly when hovering the favorite icon. favorite->set_mouse_filter(MOUSE_FILTER_PASS); favorite->connect("pressed", callable_mp(this, &ProjectList::_favorite_pressed).bind(hb)); @@ -1916,7 +1965,7 @@ void ProjectManager::_notification(int p_what) { } break; case NOTIFICATION_READY: { - int default_sorting = (int)EditorSettings::get_singleton()->get("project_manager/sorting_order"); + int default_sorting = (int)EDITOR_GET("project_manager/sorting_order"); filter_option->select(default_sorting); _project_list->set_order_option(default_sorting); @@ -2561,7 +2610,7 @@ ProjectManager::ProjectManager() { EditorSettings::get_singleton()->set_optimize_save(false); //just write settings as they came { - int display_scale = EditorSettings::get_singleton()->get("interface/editor/display_scale"); + int display_scale = EDITOR_GET("interface/editor/display_scale"); switch (display_scale) { case 0: @@ -2587,7 +2636,7 @@ ProjectManager::ProjectManager() { editor_set_scale(2.0); break; default: - editor_set_scale(EditorSettings::get_singleton()->get("interface/editor/custom_display_scale")); + editor_set_scale(EDITOR_GET("interface/editor/custom_display_scale")); break; } EditorFileDialog::get_icon_func = &ProjectManager::_file_dialog_get_icon; @@ -2596,7 +2645,7 @@ ProjectManager::ProjectManager() { // TRANSLATORS: This refers to the application where users manage their Godot projects. DisplayServer::get_singleton()->window_set_title(VERSION_NAME + String(" - ") + TTR("Project Manager", "Application")); - EditorFileDialog::set_default_show_hidden_files(EditorSettings::get_singleton()->get("filesystem/file_dialog/show_hidden_files")); + EditorFileDialog::set_default_show_hidden_files(EDITOR_GET("filesystem/file_dialog/show_hidden_files")); int swap_cancel_ok = EDITOR_GET("interface/editor/accept_dialog_cancel_ok_buttons"); if (swap_cancel_ok != 0) { // 0 is auto, set in register_scene based on DisplayServer. @@ -2604,8 +2653,9 @@ ProjectManager::ProjectManager() { AcceptDialog::set_swap_cancel_ok(swap_cancel_ok == 2); } - set_anchors_and_offsets_preset(Control::PRESET_FULL_RECT); - set_theme(create_custom_theme()); + Ref<Theme> theme = create_custom_theme(); + set_theme(theme); + DisplayServer::set_early_window_clear_color_override(true, theme->get_color(SNAME("background"), SNAME("Editor"))); set_anchors_and_offsets_preset(Control::PRESET_FULL_RECT); @@ -2815,7 +2865,7 @@ ProjectManager::ProjectManager() { } } - String current_lang = EditorSettings::get_singleton()->get("interface/editor/editor_language"); + String current_lang = EDITOR_GET("interface/editor/editor_language"); language_btn->set_text(current_lang); for (int i = 0; i < editor_languages.size(); i++) { @@ -2854,7 +2904,7 @@ ProjectManager::ProjectManager() { scan_dir->set_access(EditorFileDialog::ACCESS_FILESYSTEM); scan_dir->set_file_mode(EditorFileDialog::FILE_MODE_OPEN_DIR); scan_dir->set_title(TTR("Select a Folder to Scan")); // must be after mode or it's overridden - scan_dir->set_current_dir(EditorSettings::get_singleton()->get("filesystem/directories/default_project_path")); + scan_dir->set_current_dir(EDITOR_GET("filesystem/directories/default_project_path")); add_child(scan_dir); scan_dir->connect("dir_selected", callable_mp(this, &ProjectManager::_scan_begin)); @@ -2936,7 +2986,7 @@ ProjectManager::ProjectManager() { Ref<DirAccess> dir_access = DirAccess::create(DirAccess::AccessType::ACCESS_FILESYSTEM); - String default_project_path = EditorSettings::get_singleton()->get("filesystem/directories/default_project_path"); + String default_project_path = EDITOR_GET("filesystem/directories/default_project_path"); if (!dir_access->dir_exists(default_project_path)) { Error error = dir_access->make_dir_recursive(default_project_path); if (error != OK) { @@ -2944,7 +2994,7 @@ ProjectManager::ProjectManager() { } } - String autoscan_path = EditorSettings::get_singleton()->get("filesystem/directories/autoscan_project_path"); + String autoscan_path = EDITOR_GET("filesystem/directories/autoscan_project_path"); if (!autoscan_path.is_empty()) { if (dir_access->dir_exists(autoscan_path)) { _scan_begin(autoscan_path); @@ -2959,22 +3009,24 @@ ProjectManager::ProjectManager() { SceneTree::get_singleton()->get_root()->connect("files_dropped", callable_mp(this, &ProjectManager::_files_dropped)); // Define a minimum window size to prevent UI elements from overlapping or being cut off. - DisplayServer::get_singleton()->window_set_min_size(Size2(520, 350) * EDSCALE); + Window *w = Object::cast_to<Window>(SceneTree::get_singleton()->get_root()); + if (w) { + w->set_min_size(Size2(520, 350) * EDSCALE); + } // Resize the bootsplash window based on Editor display scale EDSCALE. float scale_factor = MAX(1, EDSCALE); if (scale_factor > 1.0) { Vector2i window_size = DisplayServer::get_singleton()->window_get_size(); - Vector2i screen_size = DisplayServer::get_singleton()->screen_get_size(); - Vector2i screen_position = DisplayServer::get_singleton()->screen_get_position(); + Rect2i screen_rect = DisplayServer::get_singleton()->screen_get_usable_rect(DisplayServer::get_singleton()->window_get_current_screen()); window_size *= scale_factor; DisplayServer::get_singleton()->window_set_size(window_size); - if (screen_size != Vector2i()) { + if (screen_rect.size != Vector2i()) { Vector2i window_position; - window_position.x = screen_position.x + (screen_size.x - window_size.x) / 2; - window_position.y = screen_position.y + (screen_size.y - window_size.y) / 2; + window_position.x = screen_rect.position.x + (screen_rect.size.x - window_size.x) / 2; + window_position.y = screen_rect.position.y + (screen_rect.size.y - window_size.y) / 2; DisplayServer::get_singleton()->window_set_position(window_position); } } |