diff options
Diffstat (limited to 'editor/project_manager.cpp')
-rw-r--r-- | editor/project_manager.cpp | 185 |
1 files changed, 132 insertions, 53 deletions
diff --git a/editor/project_manager.cpp b/editor/project_manager.cpp index 270e04050e..5a1eedd8a2 100644 --- a/editor/project_manager.cpp +++ b/editor/project_manager.cpp @@ -59,6 +59,8 @@ #include "servers/navigation_server_3d.h" #include "servers/physics_server_2d.h" +constexpr int GODOT4_CONFIG_VERSION = 5; + class ProjectDialog : public ConfirmationDialog { GDCLASS(ProjectDialog, ConfirmationDialog); @@ -90,9 +92,9 @@ private: Container *name_container; Container *path_container; Container *install_path_container; - Container *rasterizer_container; + Container *renderer_container; HBoxContainer *default_files_container; - Ref<ButtonGroup> rasterizer_button_group; + Ref<ButtonGroup> renderer_button_group; Label *msg; LineEdit *project_path; LineEdit *project_name; @@ -141,7 +143,11 @@ private: install_status_rect->set_texture(new_icon); } - set_size(Size2(500, 0) * EDSCALE); + Size2i window_size = get_size(); + Size2 contents_min_size = get_contents_minimum_size(); + if (window_size.x < contents_min_size.x || window_size.y < contents_min_size.y) { + set_size(window_size.max(contents_min_size)); + } } String _test_path() { @@ -471,16 +477,19 @@ private: } PackedStringArray project_features = ProjectSettings::get_required_features(); ProjectSettings::CustomMap initial_settings; + // Be sure to change this code if/when renderers are changed. - int renderer_type = rasterizer_button_group->get_pressed_button()->get_meta(SNAME("driver_name")); - initial_settings["rendering/vulkan/rendering/back_end"] = renderer_type; - if (renderer_type == 0) { - project_features.push_back("Vulkan Clustered"); - } else if (renderer_type == 1) { - project_features.push_back("Vulkan Mobile"); + String renderer_type = renderer_button_group->get_pressed_button()->get_meta(SNAME("rendering_method")); + initial_settings["rendering/renderer/rendering_method"] = renderer_type; + + if (renderer_type == "forward_plus") { + project_features.push_back("Forward Plus"); + } else if (renderer_type == "mobile") { + project_features.push_back("Mobile"); } else { WARN_PRINT("Unknown renderer type. Please report this as a bug on GitHub."); } + project_features.sort(); initial_settings["application/config/features"] = project_features; initial_settings["application/config/name"] = project_name->get_text().strip_edges(); @@ -558,19 +567,19 @@ private: Ref<DirAccess> da = DirAccess::create(DirAccess::ACCESS_FILESYSTEM); da->make_dir(dir.path_join(rel_path)); } else { - Vector<uint8_t> data; - data.resize(info.uncompressed_size); + Vector<uint8_t> uncomp_data; + uncomp_data.resize(info.uncompressed_size); String rel_path = path.substr(zip_root.length()); //read unzOpenCurrentFile(pkg); - ret = unzReadCurrentFile(pkg, data.ptrw(), data.size()); + ret = unzReadCurrentFile(pkg, uncomp_data.ptrw(), uncomp_data.size()); ERR_BREAK_MSG(ret < 0, vformat("An error occurred while attempting to read from file: %s. This file will not be used.", rel_path)); unzCloseCurrentFile(pkg); Ref<FileAccess> f = FileAccess::open(dir.path_join(rel_path), FileAccess::WRITE); if (f.is_valid()) { - f->store_buffer(data.ptr(), data.size()); + f->store_buffer(uncomp_data.ptr(), uncomp_data.size()); } else { failed_files.push_back(rel_path); } @@ -682,7 +691,7 @@ public: msg->hide(); install_path_container->hide(); install_status_rect->hide(); - rasterizer_container->hide(); + renderer_container->hide(); default_files_container->hide(); get_ok_button()->set_disabled(false); @@ -733,7 +742,7 @@ public: set_ok_button_text(TTR("Import & Edit")); name_container->hide(); install_path_container->hide(); - rasterizer_container->hide(); + renderer_container->hide(); default_files_container->hide(); project_path->grab_focus(); @@ -742,7 +751,7 @@ public: set_ok_button_text(TTR("Create & Edit")); name_container->show(); install_path_container->hide(); - rasterizer_container->show(); + renderer_container->show(); default_files_container->show(); project_name->call_deferred(SNAME("grab_focus")); project_name->call_deferred(SNAME("select_all")); @@ -753,7 +762,7 @@ public: project_name->set_text(zip_title); name_container->show(); install_path_container->hide(); - rasterizer_container->hide(); + renderer_container->hide(); default_files_container->hide(); project_path->grab_focus(); } @@ -841,23 +850,23 @@ public: msg->set_horizontal_alignment(HORIZONTAL_ALIGNMENT_CENTER); vb->add_child(msg); - // rasterizer selection - rasterizer_container = memnew(VBoxContainer); - vb->add_child(rasterizer_container); + // Renderer selection. + renderer_container = memnew(VBoxContainer); + vb->add_child(renderer_container); l = memnew(Label); l->set_text(TTR("Renderer:")); - rasterizer_container->add_child(l); - Container *rshb = memnew(HBoxContainer); - rasterizer_container->add_child(rshb); - rasterizer_button_group.instantiate(); + renderer_container->add_child(l); + HBoxContainer *rshc = memnew(HBoxContainer); + renderer_container->add_child(rshc); + renderer_button_group.instantiate(); Container *rvb = memnew(VBoxContainer); rvb->set_h_size_flags(Control::SIZE_EXPAND_FILL); - rshb->add_child(rvb); + rshc->add_child(rvb); Button *rs_button = memnew(CheckBox); - rs_button->set_button_group(rasterizer_button_group); - rs_button->set_text(TTR("Vulkan Clustered")); - rs_button->set_meta(SNAME("driver_name"), 0); // Vulkan backend "Forward Clustered" + 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); rvb->add_child(rs_button); l = memnew(Label); @@ -869,15 +878,15 @@ public: l->set_modulate(Color(1, 1, 1, 0.7)); rvb->add_child(l); - rshb->add_child(memnew(VSeparator)); + rshc->add_child(memnew(VSeparator)); rvb = memnew(VBoxContainer); rvb->set_h_size_flags(Control::SIZE_EXPAND_FILL); - rshb->add_child(rvb); + rshc->add_child(rvb); rs_button = memnew(CheckBox); - rs_button->set_button_group(rasterizer_button_group); - rs_button->set_text(TTR("Vulkan Mobile")); - rs_button->set_meta(SNAME("driver_name"), 1); // Vulkan backend "Forward Mobile" + rs_button->set_button_group(renderer_button_group); + rs_button->set_text(TTR("Mobile")); + rs_button->set_meta(SNAME("rendering_method"), "mobile"); rvb->add_child(rs_button); l = memnew(Label); l->set_text( @@ -895,7 +904,7 @@ public: l->set_horizontal_alignment(HORIZONTAL_ALIGNMENT_CENTER); l->set_vertical_alignment(VERTICAL_ALIGNMENT_CENTER); l->set_modulate(Color(1, 1, 1, 0.7)); - rasterizer_container->add_child(l); + renderer_container->add_child(l); default_files_container = memnew(HBoxContainer); vb->add_child(default_files_container); @@ -1065,6 +1074,7 @@ public: int refresh_project(const String &dir_path); void add_project(const String &dir_path, bool favorite); void save_config(); + void set_project_version(const String &p_project_path, int version); private: static void _bind_methods(); @@ -1484,7 +1494,7 @@ void ProjectList::sort_projects() { for (int i = 0; i < _projects.size(); ++i) { Item &item = _projects.write[i]; - bool visible = true; + bool item_visible = true; if (!_search_term.is_empty()) { String search_path; if (_search_term.contains("/")) { @@ -1496,10 +1506,10 @@ void ProjectList::sort_projects() { } // When searching, display projects whose name or path contain the search term - visible = item.project_name.findn(_search_term) != -1 || search_path.findn(_search_term) != -1; + item_visible = item.project_name.findn(_search_term) != -1 || search_path.findn(_search_term) != -1; } - item.control->set_visible(visible); + item.control->set_visible(item_visible); } for (int i = 0; i < _projects.size(); ++i) { @@ -1673,6 +1683,15 @@ void ProjectList::save_config() { _config.save(_config_path); } +void ProjectList::set_project_version(const String &p_project_path, int p_version) { + for (ProjectList::Item &E : _projects) { + if (E.path == p_project_path) { + E.version = p_version; + break; + } + } +} + int ProjectList::get_project_count() const { return _projects.size(); } @@ -2152,9 +2171,11 @@ void ProjectManager::_open_selected_projects_ask() { return; } + const Size2i popup_min_width = Size2i(600.0 * EDSCALE, 0); + if (selected_list.size() > 1) { - multi_open_ask->set_text(TTR("Are you sure to open more than one project?")); - multi_open_ask->popup_centered(); + multi_open_ask->set_text(vformat(TTR("You requested to open %d projects in parallel. Do you confirm?\nNote that usual checks for engine version compatibility will be bypassed."), selected_list.size())); + multi_open_ask->popup_centered(popup_min_width); return; } @@ -2163,30 +2184,40 @@ void ProjectManager::_open_selected_projects_ask() { return; } - // Update the project settings or don't open - const String conf = project.path.path_join("project.godot"); + // Update the project settings or don't open. const int config_version = project.version; PackedStringArray unsupported_features = project.unsupported_features; Label *ask_update_label = ask_update_settings->get_label(); ask_update_label->set_horizontal_alignment(HORIZONTAL_ALIGNMENT_LEFT); // Reset in case of previous center align. + full_convert_button->hide(); - // Check if the config_version property was empty or 0 + ask_update_settings->get_ok_button()->set_text("OK"); + + // Check if the config_version property was empty or 0. if (config_version == 0) { - ask_update_settings->set_text(vformat(TTR("The following project settings file does not specify the version of Godot through which it was created.\n\n%s\n\nIf you proceed with opening it, it will be converted to Godot's current configuration file format.\nWarning: You won't be able to open the project with previous versions of the engine anymore."), conf)); - ask_update_settings->popup_centered(); + ask_update_settings->set_text(vformat(TTR("The selected project \"%s\" does not specify its supported Godot version in its configuration file (\"project.godot\").\n\nProject path: %s\n\nIf you proceed with opening it, it will be converted to Godot's current configuration file format.\n\nWarning: You won't be able to open the project with previous versions of the engine anymore."), project.project_name, project.path)); + ask_update_settings->popup_centered(popup_min_width); return; } - // Check if we need to convert project settings from an earlier engine version + // Check if we need to convert project settings from an earlier engine version. if (config_version < ProjectSettings::CONFIG_VERSION) { - ask_update_settings->set_text(vformat(TTR("The following project settings file was generated by an older engine version, and needs to be converted for this version:\n\n%s\n\nDo you want to convert it?\nWarning: You won't be able to open the project with previous versions of the engine anymore."), conf)); - ask_update_settings->popup_centered(); + if (config_version == GODOT4_CONFIG_VERSION - 1 && ProjectSettings::CONFIG_VERSION == GODOT4_CONFIG_VERSION) { // Conversion from Godot 3 to 4. + full_convert_button->show(); + ask_update_settings->set_text(vformat(TTR("The selected project \"%s\" was generated by Godot 3.x, and needs to be converted for Godot 4.x.\n\nProject path: %s\n\nYou have three options:\n- Convert only the configuration file (\"project.godot\"). Use this to open the project without attempting to convert its scenes, resources and scripts.\n- Convert the entire project including its scenes, resources and scripts (recommended if you are upgrading).\n- Do nothing and go back.\n\nWarning: If you select a conversion option, you won't be able to open the project with previous versions of the engine anymore."), project.project_name, project.path)); + ask_update_settings->get_ok_button()->set_text(TTR("Convert project.godot Only")); + } else { + ask_update_settings->set_text(vformat(TTR("The selected project \"%s\" was generated by an older engine version, and needs to be converted for this version.\n\nProject path: %s\n\nDo you want to convert it?\n\nWarning: You won't be able to open the project with previous versions of the engine anymore."), project.project_name, project.path)); + ask_update_settings->get_ok_button()->set_text(TTR("Convert project.godot")); + } + ask_update_settings->popup_centered(popup_min_width); + ask_update_settings->get_cancel_button()->grab_focus(); // To prevent accidents. return; } - // Check if the file was generated by a newer, incompatible engine version + // 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 at '%s'.") + "\n" + TTR("The project settings were created by a newer engine version, whose settings are not compatible with this version."), project.path)); - dialog_error->popup_centered(); + 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_width); return; } // Check if the project is using features not supported by this build of Godot. @@ -2215,14 +2246,46 @@ void ProjectManager::_open_selected_projects_ask() { warning_message += TTR("Open anyway? Project will be modified."); ask_update_label->set_horizontal_alignment(HORIZONTAL_ALIGNMENT_CENTER); ask_update_settings->set_text(warning_message); - ask_update_settings->popup_centered(); + ask_update_settings->popup_centered(popup_min_width); return; } - // Open if the project is up-to-date + // Open if the project is up-to-date. _open_selected_projects(); } +void ProjectManager::_full_convert_button_pressed() { + ask_update_settings->hide(); + ask_full_convert_dialog->popup_centered(Size2i(600.0 * EDSCALE, 0)); + ask_full_convert_dialog->get_cancel_button()->grab_focus(); +} + +void ProjectManager::_perform_full_project_conversion() { + Vector<ProjectList::Item> selected_list = _project_list->get_selected_projects(); + if (selected_list.is_empty()) { + return; + } + + const String &path = selected_list[0].path; + + print_line("Converting project: " + path); + + Ref<ConfigFile> cf; + cf.instantiate(); + cf->load(path.path_join("project.godot")); + cf->set_value("", "config_version", GODOT4_CONFIG_VERSION); + cf->save(path.path_join("project.godot")); + _project_list->set_project_version(path, GODOT4_CONFIG_VERSION); + + List<String> args; + args.push_back("--path"); + args.push_back(path); + args.push_back("--convert-3to4"); + + Error err = OS::get_singleton()->create_instance(args); + ERR_FAIL_COND(err); +} + void ProjectManager::_run_project_confirm() { Vector<ProjectList::Item> selected_list = _project_list->get_selected_projects(); @@ -2535,6 +2598,12 @@ ProjectManager::ProjectManager() { EditorFileDialog::set_default_show_hidden_files(EditorSettings::get_singleton()->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. + // Swap on means OK first. + AcceptDialog::set_swap_cancel_ok(swap_cancel_ok == 2); + } + set_anchors_and_offsets_preset(Control::PRESET_FULL_RECT); set_theme(create_custom_theme()); @@ -2724,9 +2793,10 @@ ProjectManager::ProjectManager() { settings_hb->add_child(h_spacer); language_btn = memnew(OptionButton); - language_btn->set_flat(true); language_btn->set_icon(get_theme_icon(SNAME("Environment"), SNAME("EditorIcons"))); 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. @@ -2823,9 +2893,18 @@ ProjectManager::ProjectManager() { add_child(multi_scan_ask); ask_update_settings = memnew(ConfirmationDialog); + ask_update_settings->set_autowrap(true); ask_update_settings->get_ok_button()->connect("pressed", callable_mp(this, &ProjectManager::_confirm_update_settings)); + full_convert_button = ask_update_settings->add_button("Convert Full Project", !GLOBAL_GET("gui/common/swap_cancel_ok")); + full_convert_button->connect("pressed", callable_mp(this, &ProjectManager::_full_convert_button_pressed)); add_child(ask_update_settings); + ask_full_convert_dialog = memnew(ConfirmationDialog); + ask_full_convert_dialog->set_autowrap(true); + ask_full_convert_dialog->set_text(TTR("This option will perform full project conversion, updating scenes, resources and scripts from Godot 3.x to work in Godot 4.0.\n\nNote that this is a best-effort conversion, i.e. it makes upgrading the project easier, but it will not open out-of-the-box and will still require manual adjustments.\n\nIMPORTANT: Make sure to backup your project before converting, as this operation makes it impossible to open it in older versions of Godot.")); + 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)); |