summaryrefslogtreecommitdiff
path: root/editor/project_manager.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'editor/project_manager.cpp')
-rw-r--r--editor/project_manager.cpp227
1 files changed, 187 insertions, 40 deletions
diff --git a/editor/project_manager.cpp b/editor/project_manager.cpp
index b8fb9d4ab0..b0baf954d2 100644
--- a/editor/project_manager.cpp
+++ b/editor/project_manager.cpp
@@ -83,6 +83,8 @@ private:
Container *name_container;
Container *path_container;
Container *install_path_container;
+ Container *rasterizer_container;
+ Ref<ButtonGroup> rasterizer_button_group;
Label *msg;
LineEdit *project_path;
LineEdit *project_name;
@@ -432,22 +434,22 @@ private:
if (mode == MODE_RENAME) {
- String dir = _test_path();
- if (dir == "") {
+ String dir2 = _test_path();
+ if (dir2 == "") {
set_message(TTR("Invalid project path (changed anything?)."), MESSAGE_ERROR);
return;
}
ProjectSettings *current = memnew(ProjectSettings);
- int err = current->setup(dir, "");
+ int err = current->setup(dir2, "");
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);
} else {
ProjectSettings::CustomMap edited_settings;
edited_settings["application/config/name"] = project_name->get_text();
- if (current->save_custom(dir.plus_file("project.godot"), edited_settings, Vector<String>(), true) != OK) {
+ if (current->save_custom(dir2.plus_file("project.godot"), edited_settings, Vector<String>(), true) != OK) {
set_message(TTR("Couldn't edit project.godot in project path."), MESSAGE_ERROR);
}
}
@@ -471,6 +473,13 @@ private:
if (mode == MODE_NEW) {
ProjectSettings::CustomMap initial_settings;
+ if (rasterizer_button_group->get_pressed_button()->get_meta("driver_name") == "GLES3") {
+ initial_settings["rendering/quality/driver/driver_name"] = "GLES3";
+ } else {
+ initial_settings["rendering/quality/driver/driver_name"] = "GLES2";
+ initial_settings["rendering/vram_compression/import_etc2"] = false;
+ initial_settings["rendering/vram_compression/import_etc"] = true;
+ }
initial_settings["application/config/name"] = project_name->get_text();
initial_settings["application/config/icon"] = "res://icon.png";
initial_settings["rendering/environment/default_environment"] = "res://default_env.tres";
@@ -687,6 +696,7 @@ public:
msg->hide();
install_path_container->hide();
install_status_rect->hide();
+ rasterizer_container->hide();
get_ok()->set_disabled(false);
ProjectSettings *current = memnew(ProjectSettings);
@@ -738,6 +748,7 @@ public:
get_ok()->set_text(TTR("Import & Edit"));
name_container->hide();
install_path_container->hide();
+ rasterizer_container->hide();
project_path->grab_focus();
} else if (mode == MODE_NEW) {
@@ -746,6 +757,7 @@ public:
get_ok()->set_text(TTR("Create & Edit"));
name_container->show();
install_path_container->hide();
+ rasterizer_container->show();
project_name->call_deferred("grab_focus");
project_name->call_deferred("select_all");
@@ -753,15 +765,16 @@ public:
set_title(TTR("Install Project:") + " " + zip_title);
get_ok()->set_text(TTR("Install & Edit"));
- name_container->hide();
+ name_container->show();
install_path_container->hide();
+ rasterizer_container->hide();
project_path->grab_focus();
}
_test_path();
}
- popup_centered(Size2(500, 0) * EDSCALE);
+ popup_centered_minsize(Size2(500, 0) * EDSCALE);
}
ProjectDialog() {
@@ -785,7 +798,7 @@ public:
create_dir = memnew(Button);
pnhb->add_child(create_dir);
- create_dir->set_text(TTR("Create folder"));
+ create_dir->set_text(TTR("Create Folder"));
create_dir->connect("pressed", this, "_create_folder");
path_container = memnew(VBoxContainer);
@@ -840,6 +853,48 @@ public:
msg->set_align(Label::ALIGN_CENTER);
vb->add_child(msg);
+ // rasterizer selection
+ rasterizer_container = memnew(VBoxContainer);
+ vb->add_child(rasterizer_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.instance();
+
+ Container *rvb = memnew(VBoxContainer);
+ rvb->set_h_size_flags(SIZE_EXPAND_FILL);
+ rshb->add_child(rvb);
+ Button *rs_button = memnew(CheckBox);
+ rs_button->set_button_group(rasterizer_button_group);
+ rs_button->set_text(TTR("OpenGL ES 3.0"));
+ rs_button->set_meta("driver_name", "GLES3");
+ rs_button->set_pressed(true);
+ rvb->add_child(rs_button);
+ l = memnew(Label);
+ l->set_text(TTR("Higher visual quality\nAll features available\nIncompatible with older hardware\nNot recommended for web games"));
+ rvb->add_child(l);
+
+ rshb->add_child(memnew(VSeparator));
+
+ rvb = memnew(VBoxContainer);
+ rvb->set_h_size_flags(SIZE_EXPAND_FILL);
+ rshb->add_child(rvb);
+ rs_button = memnew(CheckBox);
+ rs_button->set_button_group(rasterizer_button_group);
+ rs_button->set_text(TTR("OpenGL ES 2.0"));
+ rs_button->set_meta("driver_name", "GLES2");
+ rvb->add_child(rs_button);
+ l = memnew(Label);
+ l->set_text(TTR("Lower visual quality\nSome features not available\nWorks on most hardware\nRecommended for web games"));
+ rvb->add_child(l);
+
+ l = memnew(Label);
+ l->set_text(TTR("Renderer can be changed later, but scenes may need to be adjusted."));
+ l->set_align(Label::ALIGN_CENTER);
+ rasterizer_container->add_child(l);
+
fdialog = memnew(FileDialog);
fdialog->set_access(FileDialog::ACCESS_FILESYSTEM);
fdialog_install = memnew(FileDialog);
@@ -932,6 +987,24 @@ void ProjectManager::_update_project_buttons() {
open_btn->set_disabled(empty_selection);
rename_btn->set_disabled(empty_selection);
run_btn->set_disabled(empty_selection);
+
+ bool missing_projects = false;
+ Map<String, String> list_all_projects;
+ for (int i = 0; i < scroll_children->get_child_count(); i++) {
+ HBoxContainer *hb = Object::cast_to<HBoxContainer>(scroll_children->get_child(i));
+ if (hb) {
+ list_all_projects.insert(hb->get_meta("name"), hb->get_meta("main_scene"));
+ }
+ }
+ for (Map<String, String>::Element *E = list_all_projects.front(); E; E = E->next()) {
+ String project_name = E->key().replace(":::", ":/").replace("::", "/") + "/project.godot";
+ if (!FileAccess::exists(project_name)) {
+ missing_projects = true;
+ break;
+ }
+ }
+
+ erase_missing_btn->set_visible(missing_projects);
}
void ProjectManager::_panel_input(const Ref<InputEvent> &p_ev, Node *p_hb) {
@@ -1081,7 +1154,7 @@ void ProjectManager::_unhandled_input(const Ref<InputEvent> &p_ev) {
break;
}
- // else fallthrough to key_down
+ FALLTHROUGH;
}
case KEY_DOWN: {
@@ -1367,6 +1440,7 @@ void ProjectManager::_on_projects_updated() {
}
void ProjectManager::_on_project_created(const String &dir) {
+ project_filter->clear();
bool has_already = false;
for (int i = 0; i < scroll_children->get_child_count(); i++) {
HBoxContainer *hb = Object::cast_to<HBoxContainer>(scroll_children->get_child(i));
@@ -1471,9 +1545,16 @@ void ProjectManager::_open_selected_projects_ask() {
}
int config_version = (int)cf->get_value("", "config_version", 0);
+
+ // 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_minsize();
+ return;
+ }
// 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 will not be able to open the project with previous versions of the engine anymore."), conf));
+ 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_minsize();
return;
}
@@ -1494,7 +1575,7 @@ void ProjectManager::_run_project_confirm() {
const String &selected_main = E->get();
if (selected_main == "") {
- run_error_diag->set_text(TTR("Can't run project: no main scene defined.\nPlease edit the project and set the main scene in \"Project Settings\" under the \"Application\" category."));
+ 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();
return;
}
@@ -1534,7 +1615,7 @@ void ProjectManager::_run_project() {
}
if (selected_list.size() > 1) {
- multi_run_ask->set_text(TTR("Are you sure to run more than one project?"));
+ multi_run_ask->set_text(vformat(TTR("Are you sure to run %d projects at once?"), selected_list.size()));
multi_run_ask->popup_centered_minsize();
} else {
_run_project_confirm();
@@ -1546,40 +1627,28 @@ void ProjectManager::_show_project(const String &p_path) {
OS::get_singleton()->shell_open(String("file://") + p_path);
}
-void ProjectManager::_scan_dir(DirAccess *da, float pos, float total, List<String> *r_projects) {
-
- List<String> subdirs;
+void ProjectManager::_scan_dir(const String &path, List<String> *r_projects) {
+ DirAccess *da = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
+ da->change_dir(path);
da->list_dir_begin();
String n = da->get_next();
while (n != String()) {
if (da->current_is_dir() && !n.begins_with(".")) {
- subdirs.push_front(n);
+ _scan_dir(da->get_current_dir().plus_file(n), r_projects);
} else if (n == "project.godot") {
r_projects->push_back(da->get_current_dir());
}
n = da->get_next();
}
da->list_dir_end();
- int m = 0;
- for (List<String>::Element *E = subdirs.front(); E; E = E->next()) {
-
- da->change_dir(E->get());
-
- float slice = total / subdirs.size();
- _scan_dir(da, pos + slice * m, slice, r_projects);
- da->change_dir("..");
- m++;
- }
+ memdelete(da);
}
void ProjectManager::_scan_begin(const String &p_base) {
print_line("Scanning projects at: " + p_base);
List<String> projects;
- DirAccess *da = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
- da->change_dir(p_base);
- _scan_dir(da, 0, 1, &projects);
- memdelete(da);
+ _scan_dir(p_base, &projects);
print_line("Found " + itos(projects.size()) + " projects.");
for (List<String>::Element *E = projects.front(); E; E = E->next()) {
@@ -1637,15 +1706,61 @@ void ProjectManager::_erase_project_confirm() {
_load_recent_projects();
}
+void ProjectManager::_erase_missing_projects_confirm() {
+
+ Map<String, String> list_all_projects;
+ for (int i = 0; i < scroll_children->get_child_count(); i++) {
+ HBoxContainer *hb = Object::cast_to<HBoxContainer>(scroll_children->get_child(i));
+ if (hb) {
+ list_all_projects.insert(hb->get_meta("name"), hb->get_meta("main_scene"));
+ }
+ }
+
+ if (list_all_projects.size() == 0) {
+ return;
+ }
+
+ int deleted_projects = 0;
+ int remaining_projects = 0;
+ for (Map<String, String>::Element *E = list_all_projects.front(); E; E = E->next()) {
+ String project_name = E->key().replace(":::", ":/").replace("::", "/") + "/project.godot";
+ if (!FileAccess::exists(project_name)) {
+ deleted_projects++;
+ EditorSettings::get_singleton()->erase("projects/" + E->key());
+ EditorSettings::get_singleton()->erase("favorite_projects/" + E->key());
+ } else {
+ remaining_projects++;
+ }
+ }
+ print_line("Deleted " + itos(deleted_projects) + " projects, remaining " + itos(remaining_projects) + " projects");
+ EditorSettings::get_singleton()->save();
+ selected_list.clear();
+ last_clicked = "";
+ _load_recent_projects();
+}
+
void ProjectManager::_erase_project() {
if (selected_list.size() == 0)
return;
- erase_ask->set_text(TTR("Remove project from the list? (Folder contents will not be modified)"));
+ String confirm_message;
+ if (selected_list.size() >= 2) {
+ confirm_message = vformat(TTR("Remove %d projects from the list?\nThe project folders' contents won't be modified."), selected_list.size());
+ } else {
+ confirm_message = TTR("Remove this project from the list?\nThe project folder's contents won't be modified.");
+ }
+
+ erase_ask->set_text(confirm_message);
erase_ask->popup_centered_minsize();
}
+void ProjectManager::_erase_missing_projects() {
+
+ erase_missing_ask->set_text(TTR("Remove all missing projects from the list? (Folders contents will not be modified)"));
+ erase_missing_ask->popup_centered_minsize();
+}
+
void ProjectManager::_language_selected(int p_id) {
String lang = language_btn->get_item_metadata(p_id);
@@ -1653,7 +1768,7 @@ void ProjectManager::_language_selected(int p_id) {
language_btn->set_text(lang);
language_btn->set_icon(get_icon("Environment", "EditorIcons"));
- language_restart_ask->set_text(TTR("Language changed.\nThe UI will update next time the editor or project manager starts."));
+ language_restart_ask->set_text(TTR("Language changed.\nThe interface will update after restarting the editor or project manager."));
language_restart_ask->popup_centered();
}
@@ -1714,7 +1829,8 @@ void ProjectManager::_files_dropped(PoolStringArray p_files, int p_screen) {
if (confirm) {
multi_scan_ask->get_ok()->disconnect("pressed", this, "_scan_multiple_folders");
multi_scan_ask->get_ok()->connect("pressed", this, "_scan_multiple_folders", varray(folders));
- multi_scan_ask->set_text(vformat(TTR("You are about the scan %s folders for existing Godot projects. Do you confirm?"), folders.size()));
+ multi_scan_ask->set_text(
+ vformat(TTR("Are you sure to scan %s folders for existing Godot projects?\nThis could take a while."), folders.size()));
multi_scan_ask->popup_centered_minsize();
} else {
_scan_multiple_folders(folders);
@@ -1741,7 +1857,9 @@ void ProjectManager::_bind_methods() {
ClassDB::bind_method("_new_project", &ProjectManager::_new_project);
ClassDB::bind_method("_rename_project", &ProjectManager::_rename_project);
ClassDB::bind_method("_erase_project", &ProjectManager::_erase_project);
+ ClassDB::bind_method("_erase_missing_projects", &ProjectManager::_erase_missing_projects);
ClassDB::bind_method("_erase_project_confirm", &ProjectManager::_erase_project_confirm);
+ ClassDB::bind_method("_erase_missing_projects_confirm", &ProjectManager::_erase_missing_projects_confirm);
ClassDB::bind_method("_language_selected", &ProjectManager::_language_selected);
ClassDB::bind_method("_restart_confirm", &ProjectManager::_restart_confirm);
ClassDB::bind_method("_exit_dialog", &ProjectManager::_exit_dialog);
@@ -1833,13 +1951,12 @@ ProjectManager::ProjectManager() {
Panel *panel = memnew(Panel);
gui_base->add_child(panel);
panel->set_anchors_and_margins_preset(Control::PRESET_WIDE);
+ panel->add_style_override("panel", gui_base->get_stylebox("Background", "EditorStyles"));
VBoxContainer *vb = memnew(VBoxContainer);
panel->add_child(vb);
- vb->set_anchors_and_margins_preset(Control::PRESET_WIDE, Control::PRESET_MODE_MINSIZE, 20 * EDSCALE);
- vb->set_margin(MARGIN_TOP, 4 * EDSCALE);
- vb->set_margin(MARGIN_BOTTOM, -4 * EDSCALE);
- vb->add_constant_override("separation", 15 * EDSCALE);
+ vb->set_anchors_and_margins_preset(Control::PRESET_WIDE, Control::PRESET_MODE_MINSIZE, 8 * EDSCALE);
+ vb->add_constant_override("separation", 8 * EDSCALE);
String cp;
cp += 0xA9;
@@ -1847,11 +1964,9 @@ ProjectManager::ProjectManager() {
HBoxContainer *top_hb = memnew(HBoxContainer);
vb->add_child(top_hb);
- CenterContainer *ccl = memnew(CenterContainer);
Label *l = memnew(Label);
l->set_text(VERSION_NAME + String(" - ") + TTR("Project Manager"));
- ccl->add_child(l);
- top_hb->add_child(ccl);
+ top_hb->add_child(l);
top_hb->add_spacer();
l = memnew(Label);
String hash = String(VERSION_HASH);
@@ -1982,6 +2097,12 @@ ProjectManager::ProjectManager() {
erase->connect("pressed", this, "_erase_project");
erase_btn = erase;
+ Button *erase_missing = memnew(Button);
+ erase_missing->set_text(TTR("Remove Missing"));
+ tree_vb->add_child(erase_missing);
+ erase_missing->connect("pressed", this, "_erase_missing_projects");
+ erase_missing_btn = erase_missing;
+
tree_vb->add_spacer();
if (StreamPeerSSL::is_available()) {
@@ -1998,6 +2119,8 @@ ProjectManager::ProjectManager() {
settings_hb->set_h_grow_direction(Control::GROW_DIRECTION_BEGIN);
language_btn = memnew(OptionButton);
+ language_btn->set_flat(true);
+ language_btn->set_focus_mode(Control::FOCUS_NONE);
Vector<String> editor_languages;
List<PropertyInfo> editor_settings_properties;
@@ -2031,6 +2154,19 @@ ProjectManager::ProjectManager() {
Button *cancel = memnew(Button);
cancel->set_text(TTR("Exit"));
cancel->set_custom_minimum_size(Size2(100, 1) * EDSCALE);
+
+#ifndef OSX_ENABLED
+ // Pressing Command + Q quits the Project Manager
+ // This is handled by the platform implementation on macOS,
+ // so only define the shortcut on other platforms
+ InputEventKey *quit_key = memnew(InputEventKey);
+ quit_key->set_command(true);
+ quit_key->set_scancode(KEY_Q);
+ ShortCut *quit_shortcut = memnew(ShortCut);
+ quit_shortcut->set_shortcut(quit_key);
+ cancel->set_shortcut(quit_shortcut);
+#endif
+
cc->add_child(cancel);
cancel->connect("pressed", this, "_exit_dialog");
vb->add_child(cc);
@@ -2043,6 +2179,11 @@ ProjectManager::ProjectManager() {
language_restart_ask->get_cancel()->set_text(TTR("Continue"));
gui_base->add_child(language_restart_ask);
+ erase_missing_ask = memnew(ConfirmationDialog);
+ erase_missing_ask->get_ok()->set_text(TTR("Remove All"));
+ erase_missing_ask->get_ok()->connect("pressed", this, "_erase_missing_projects_confirm");
+ gui_base->add_child(erase_missing_ask);
+
erase_ask = memnew(ConfirmationDialog);
erase_ask->get_ok()->set_text(TTR("Remove"));
erase_ask->get_ok()->connect("pressed", this, "_erase_project_confirm");
@@ -2091,7 +2232,7 @@ ProjectManager::ProjectManager() {
gui_base->add_child(dialog_error);
open_templates = memnew(ConfirmationDialog);
- open_templates->set_text(TTR("You don't currently have any projects.\nWould you like to explore the official example projects in the Asset Library?"));
+ 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->get_ok()->set_text(TTR("Open Asset Library"));
open_templates->connect("confirmed", this, "_open_asset_library");
add_child(open_templates);
@@ -2175,3 +2316,9 @@ ProjectListFilter::ProjectListFilter() {
has_search_box = false;
}
+
+void ProjectListFilter::clear() {
+ if (has_search_box) {
+ search_box->clear();
+ }
+}