diff options
Diffstat (limited to 'editor/project_manager.cpp')
-rw-r--r-- | editor/project_manager.cpp | 334 |
1 files changed, 270 insertions, 64 deletions
diff --git a/editor/project_manager.cpp b/editor/project_manager.cpp index bd700342f6..3a6a73d3cc 100644 --- a/editor/project_manager.cpp +++ b/editor/project_manager.cpp @@ -72,16 +72,26 @@ private: MESSAGE_SUCCESS }; + enum InputType { + PROJECT_PATH, + INSTALL_PATH + }; + Mode mode; Button *browse; + Button *install_browse; Button *create_dir; Container *name_container; Container *path_container; + Container *install_path_container; Label *msg; LineEdit *project_path; LineEdit *project_name; + LineEdit *install_path; TextureRect *status_rect; + TextureRect *install_status_rect; FileDialog *fdialog; + FileDialog *fdialog_install; String zip_path; String zip_title; AcceptDialog *dialog_error; @@ -89,10 +99,11 @@ private: String created_folder_path; - void set_message(const String &p_msg, MessageType p_type = MESSAGE_SUCCESS) { + void set_message(const String &p_msg, MessageType p_type = MESSAGE_SUCCESS, InputType input_type = PROJECT_PATH) { msg->set_text(p_msg); - Ref<Texture> current_icon = status_rect->get_texture(); + Ref<Texture> current_path_icon = status_rect->get_texture(); + Ref<Texture> current_install_icon = install_status_rect->get_texture(); Ref<Texture> new_icon; switch (p_type) { @@ -119,8 +130,11 @@ private: } break; } - if (current_icon != new_icon) + if (current_path_icon != new_icon && input_type == PROJECT_PATH) { status_rect->set_texture(new_icon); + } else if (current_install_icon != new_icon && input_type == INSTALL_PATH) { + install_status_rect->set_texture(new_icon); + } set_size(Size2(500, 0) * EDSCALE); } @@ -128,11 +142,19 @@ private: String _test_path() { DirAccess *d = DirAccess::create(DirAccess::ACCESS_FILESYSTEM); - String valid_path; + String valid_path, valid_install_path; if (d->change_dir(project_path->get_text()) == OK) { valid_path = project_path->get_text(); } else if (d->change_dir(project_path->get_text().strip_edges()) == OK) { valid_path = project_path->get_text().strip_edges(); + } else if (project_path->get_text().ends_with(".zip")) { + if (d->file_exists(project_path->get_text())) { + valid_path = project_path->get_text(); + } + } else if (project_path->get_text().strip_edges().ends_with(".zip")) { + if (d->file_exists(project_path->get_text().strip_edges())) { + valid_path = project_path->get_text().strip_edges(); + } } if (valid_path == "") { @@ -142,11 +164,94 @@ private: return ""; } + if (mode == MODE_IMPORT && valid_path.ends_with(".zip")) { + if (d->change_dir(install_path->get_text()) == OK) { + valid_install_path = install_path->get_text(); + } else if (d->change_dir(install_path->get_text().strip_edges()) == OK) { + valid_install_path = install_path->get_text().strip_edges(); + } + + if (valid_install_path == "") { + set_message(TTR("The path does not exist."), MESSAGE_ERROR, INSTALL_PATH); + memdelete(d); + get_ok()->set_disabled(true); + return ""; + } + } + if (mode == MODE_IMPORT || mode == MODE_RENAME) { if (valid_path != "" && !d->file_exists("project.godot")) { - set_message(TTR("Please choose a 'project.godot' file."), MESSAGE_ERROR); + if (valid_path.ends_with(".zip")) { + FileAccess *src_f = NULL; + zlib_filefunc_def io = zipio_create_io_from_file(&src_f); + + unzFile pkg = unzOpen2(valid_path.utf8().get_data(), &io); + if (!pkg) { + + set_message(TTR("Error opening package file, not in zip format."), MESSAGE_ERROR); + memdelete(d); + get_ok()->set_disabled(true); + unzClose(pkg); + return ""; + } + + int ret = unzGoToFirstFile(pkg); + while (ret == UNZ_OK) { + unz_file_info info; + char fname[16384]; + ret = unzGetCurrentFileInfo(pkg, &info, fname, 16384, NULL, 0, NULL, 0); + + if (String(fname).ends_with("project.godot")) { + break; + } + + ret = unzGoToNextFile(pkg); + } + + if (ret == UNZ_END_OF_LIST_OF_FILE) { + set_message(TTR("Invalid '.zip' project file, does not contain a 'project.godot' file."), MESSAGE_ERROR); + memdelete(d); + get_ok()->set_disabled(true); + unzClose(pkg); + return ""; + } + + unzClose(pkg); + + // check if the specified install folder is empty, even though this is not an error, it is good to check here + d->list_dir_begin(); + bool is_empty = true; + String n = d->get_next(); + while (n != String()) { + if (n != "." && n != "..") { + is_empty = false; + break; + } + n = d->get_next(); + } + d->list_dir_end(); + + if (!is_empty) { + + set_message(TTR("Please choose an empty folder."), MESSAGE_WARNING, INSTALL_PATH); + memdelete(d); + get_ok()->set_disabled(true); + return ""; + } + + } else { + set_message(TTR("Please choose a 'project.godot' or '.zip' file."), MESSAGE_ERROR); + memdelete(d); + install_path_container->hide(); + get_ok()->set_disabled(true); + return ""; + } + + } else if (valid_path.ends_with("zip")) { + + set_message(TTR("Directory already contains a Godot project."), MESSAGE_ERROR, INSTALL_PATH); memdelete(d); get_ok()->set_disabled(true); return ""; @@ -159,7 +264,7 @@ private: bool is_empty = true; String n = d->get_next(); while (n != String()) { - if (!n.begins_with(".")) { // i don't know if this is enough to guarantee an empty dir + if (n != "." && n != "..") { // i don't know if this is enough to guarantee an empty dir is_empty = false; break; } @@ -177,6 +282,7 @@ private: } set_message(""); + set_message("", MESSAGE_SUCCESS, INSTALL_PATH); memdelete(d); get_ok()->set_disabled(false); return valid_path; @@ -199,6 +305,7 @@ private: sp = TTR("Imported Project"); project_name->set_text(sp); + _text_changed(sp); } } @@ -213,16 +320,26 @@ private: if (mode == MODE_IMPORT) { if (p.ends_with("project.godot")) { p = p.get_base_dir(); + install_path_container->hide(); + get_ok()->set_disabled(false); + } else if (p.ends_with(".zip")) { + install_path->set_text(p.get_base_dir()); + install_path_container->show(); get_ok()->set_disabled(false); } else { - set_message(TTR("Please choose a 'project.godot' file."), MESSAGE_ERROR); + set_message(TTR("Please choose a 'project.godot' or '.zip' file."), MESSAGE_ERROR); get_ok()->set_disabled(true); return; } } String sp = p.simplify_path(); project_path->set_text(sp); - get_ok()->call_deferred("grab_focus"); + _path_text_changed(sp); + if (p.ends_with(".zip")) { + install_path->call_deferred("grab_focus"); + } else { + get_ok()->call_deferred("grab_focus"); + } } void _path_selected(const String &p_path) { @@ -230,6 +347,15 @@ private: String p = p_path; String sp = p.simplify_path(); project_path->set_text(sp); + _path_text_changed(sp); + get_ok()->call_deferred("grab_focus"); + } + + void _install_path_selected(const String &p_path) { + String p = p_path; + String sp = p.simplify_path(); + install_path->set_text(sp); + _path_text_changed(sp); get_ok()->call_deferred("grab_focus"); } @@ -242,16 +368,25 @@ private: fdialog->set_mode(FileDialog::MODE_OPEN_FILE); fdialog->clear_filters(); fdialog->add_filter("project.godot ; " VERSION_NAME " Project"); + fdialog->add_filter("*.zip ; Zip File"); } else { fdialog->set_mode(FileDialog::MODE_OPEN_DIR); } fdialog->popup_centered_ratio(); } + void _browse_install_path() { + fdialog_install->set_current_dir(install_path->get_text()); + fdialog_install->set_mode(FileDialog::MODE_OPEN_DIR); + fdialog_install->popup_centered_ratio(); + } + void _create_folder() { - if (project_name->get_text() == "" || created_folder_path != "") + if (project_name->get_text() == "" || created_folder_path != "" || project_name->get_text().ends_with(".") || project_name->get_text().ends_with(" ")) { + set_message(TTR("Invalid Project Name."), MESSAGE_WARNING); return; + } DirAccess *d = DirAccess::create(DirAccess::ACCESS_FILESYSTEM); if (d->change_dir(project_path->get_text()) == OK) { @@ -261,7 +396,9 @@ private: if (d->make_dir(project_name->get_text()) == OK) { d->change_dir(project_name->get_text()); - project_path->set_text(d->get_current_dir()); + String dir_str = d->get_current_dir(); + project_path->set_text(dir_str); + _path_text_changed(dir_str); created_folder_path = d->get_current_dir(); create_dir->set_disabled(true); } else { @@ -321,7 +458,15 @@ private: } else { if (mode == MODE_IMPORT) { - // nothing to do + + if (project_path->get_text().ends_with(".zip")) { + + mode = MODE_INSTALL; + ok_pressed(); + + return; + } + } else { if (mode == MODE_NEW) { @@ -350,6 +495,11 @@ private: } else if (mode == MODE_INSTALL) { + if (project_path->get_text().ends_with(".zip")) { + dir = install_path->get_text(); + zip_path = project_path->get_text(); + } + FileAccess *src_f = NULL; zlib_filefunc_def io = zipio_create_io_from_file(&src_f); @@ -437,7 +587,7 @@ private: dialog_error->set_text(msg); dialog_error->popup_centered_minsize(); - } else { + } else if (!project_path->get_text().ends_with(".zip")) { dialog_error->set_text(TTR("Package Installed Successfully!")); dialog_error->popup_centered_minsize(); } @@ -473,10 +623,15 @@ private: _remove_created_folder(); project_path->clear(); + _path_text_changed(""); project_name->clear(); + _text_changed(""); if (status_rect->get_texture() == get_icon("StatusError", "EditorIcons")) msg->show(); + + if (install_status_rect->get_texture() == get_icon("StatusError", "EditorIcons")) + msg->show(); } void _notification(int p_what) { @@ -494,6 +649,8 @@ protected: ClassDB::bind_method("_path_text_changed", &ProjectDialog::_path_text_changed); ClassDB::bind_method("_path_selected", &ProjectDialog::_path_selected); ClassDB::bind_method("_file_selected", &ProjectDialog::_file_selected); + ClassDB::bind_method("_install_path_selected", &ProjectDialog::_install_path_selected); + ClassDB::bind_method("_browse_install_path", &ProjectDialog::_browse_install_path); ADD_SIGNAL(MethodInfo("project_created")); ADD_SIGNAL(MethodInfo("project_renamed")); } @@ -521,12 +678,15 @@ public: project_path->set_editable(false); browse->hide(); + install_browse->hide(); set_title(TTR("Rename Project")); get_ok()->set_text(TTR("Rename")); name_container->show(); status_rect->hide(); msg->hide(); + install_path_container->hide(); + install_status_rect->hide(); get_ok()->set_disabled(false); ProjectSettings *current = memnew(ProjectSettings); @@ -538,7 +698,9 @@ public: msg->show(); get_ok()->set_disabled(true); } else if (current->has_setting("application/config/name")) { - project_name->set_text(current->get("application/config/name")); + String proj = current->get("application/config/name"); + project_name->set_text(proj); + _text_changed(proj); } project_name->call_deferred("grab_focus"); @@ -557,19 +719,25 @@ public: fdialog->set_current_dir(d->get_current_dir()); memdelete(d); } - project_name->set_text(TTR("New Game Project")); + String proj = TTR("New Game Project"); + project_name->set_text(proj); + _text_changed(proj); project_path->set_editable(true); browse->set_disabled(false); browse->show(); + install_browse->set_disabled(false); + install_browse->show(); create_dir->show(); status_rect->show(); + install_status_rect->show(); msg->show(); if (mode == MODE_IMPORT) { set_title(TTR("Import Existing Project")); get_ok()->set_text(TTR("Import & Edit")); name_container->hide(); + install_path_container->hide(); project_path->grab_focus(); } else if (mode == MODE_NEW) { @@ -577,6 +745,7 @@ public: set_title(TTR("Create New Project")); get_ok()->set_text(TTR("Create & Edit")); name_container->show(); + install_path_container->hide(); project_name->grab_focus(); } else if (mode == MODE_INSTALL) { @@ -584,6 +753,7 @@ public: set_title(TTR("Install Project:") + " " + zip_title); get_ok()->set_text(TTR("Install & Edit")); name_container->hide(); + install_path_container->hide(); project_path->grab_focus(); } @@ -631,6 +801,20 @@ public: project_path->set_h_size_flags(SIZE_EXPAND_FILL); pphb->add_child(project_path); + install_path_container = memnew(VBoxContainer); + vb->add_child(install_path_container); + + l = memnew(Label); + l->set_text(TTR("Project Installation Path:")); + install_path_container->add_child(l); + + HBoxContainer *iphb = memnew(HBoxContainer); + install_path_container->add_child(iphb); + + install_path = memnew(LineEdit); + install_path->set_h_size_flags(SIZE_EXPAND_FILL); + iphb->add_child(install_path); + // status icon status_rect = memnew(TextureRect); status_rect->set_stretch_mode(TextureRect::STRETCH_KEEP_CENTERED); @@ -641,17 +825,33 @@ public: browse->connect("pressed", this, "_browse_path"); pphb->add_child(browse); + // install status icon + install_status_rect = memnew(TextureRect); + install_status_rect->set_stretch_mode(TextureRect::STRETCH_KEEP_CENTERED); + iphb->add_child(install_status_rect); + + install_browse = memnew(Button); + install_browse->set_text(TTR("Browse")); + install_browse->connect("pressed", this, "_browse_install_path"); + iphb->add_child(install_browse); + msg = memnew(Label); msg->set_align(Label::ALIGN_CENTER); vb->add_child(msg); fdialog = memnew(FileDialog); fdialog->set_access(FileDialog::ACCESS_FILESYSTEM); + fdialog_install = memnew(FileDialog); + fdialog_install->set_access(FileDialog::ACCESS_FILESYSTEM); add_child(fdialog); + add_child(fdialog_install); project_name->connect("text_changed", this, "_text_changed"); project_path->connect("text_changed", this, "_path_text_changed"); + install_path->connect("text_changed", this, "_path_text_changed"); fdialog->connect("dir_selected", this, "_path_selected"); fdialog->connect("file_selected", this, "_file_selected"); + fdialog_install->connect("dir_selected", this, "_install_path_selected"); + fdialog_install->connect("file_selected", this, "_install_path_selected"); set_hide_on_ok(false); mode = MODE_NEW; @@ -689,7 +889,7 @@ void ProjectManager::_notification(int p_what) { } break; case NOTIFICATION_READY: { - if (scroll_children->get_child_count() == 0) + if (scroll_children->get_child_count() == 0 && StreamPeerSSL::is_available()) open_templates->popup_centered_minsize(); } break; case NOTIFICATION_VISIBILITY_CHANGED: { @@ -715,17 +915,13 @@ void ProjectManager::_update_project_buttons() { CanvasItem *item = Object::cast_to<CanvasItem>(scroll_children->get_child(i)); item->update(); - - Button *show = Object::cast_to<Button>(item->get_node(NodePath("project/path_box/show"))); - if (show) { - String current = item->get_meta("name"); - show->set_visible(selected_list.has(current)); - } } - erase_btn->set_disabled(selected_list.size() < 1); - open_btn->set_disabled(selected_list.size() < 1); - rename_btn->set_disabled(selected_list.size() < 1); + bool empty_selection = selected_list.empty(); + erase_btn->set_disabled(empty_selection); + open_btn->set_disabled(empty_selection); + rename_btn->set_disabled(empty_selection); + run_btn->set_disabled(empty_selection); } void ProjectManager::_panel_input(const Ref<InputEvent> &p_ev, Node *p_hb) { @@ -1114,7 +1310,6 @@ void ProjectManager::_load_recent_projects() { path_hb->add_child(show); show->connect("pressed", this, "_show_project", varray(path)); show->set_tooltip(TTR("Show In File Manager")); - show->set_visible(false); Label *fpath = memnew(Label(path)); fpath->set_name("path"); @@ -1195,7 +1390,7 @@ void ProjectManager::_open_project_confirm() { return; } - print_line("OPENING: " + path + " (" + selected + ")"); + print_line("Editing project: " + path + " (" + selected + ")"); List<String> args; @@ -1252,7 +1447,7 @@ void ProjectManager::_run_project_confirm() { return; } - print_line("OPENING: " + path + " (" + selected + ")"); + print_line("Running project: " + path + " (" + selected + ")"); List<String> args; @@ -1318,13 +1513,13 @@ void ProjectManager::_scan_dir(DirAccess *da, float pos, float total, List<Strin void ProjectManager::_scan_begin(const String &p_base) { - print_line("SCAN PROJECTS AT: " + 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); - print_line("found: " + itos(projects.size()) + " projects."); + print_line("Found " + itos(projects.size()) + " projects."); for (List<String>::Element *E = projects.front(); E; E = E->next()) { String proj = E->get().replace("/", "::"); @@ -1517,19 +1712,46 @@ ProjectManager::ProjectManager() { EditorSettings::get_singleton()->set_optimize_save(false); //just write settings as they came { - int dpi_mode = EditorSettings::get_singleton()->get("interface/editor/hidpi_mode"); - if (dpi_mode == 0) { - const int screen = OS::get_singleton()->get_current_screen(); - editor_set_scale(OS::get_singleton()->get_screen_dpi(screen) >= 192 && OS::get_singleton()->get_screen_size(screen).x > 2000 ? 2.0 : 1.0); - } else if (dpi_mode == 1) { - editor_set_scale(0.75); - } else if (dpi_mode == 2) { - editor_set_scale(1.0); - } else if (dpi_mode == 3) { - editor_set_scale(1.5); - } else if (dpi_mode == 4) { - editor_set_scale(2.0); + int display_scale = EditorSettings::get_singleton()->get("interface/editor/display_scale"); + float custom_display_scale = EditorSettings::get_singleton()->get("interface/editor/custom_display_scale"); + + switch (display_scale) { + case 0: { + // Try applying a suitable display scale automatically + const int screen = OS::get_singleton()->get_current_screen(); + editor_set_scale(OS::get_singleton()->get_screen_dpi(screen) >= 192 && OS::get_singleton()->get_screen_size(screen).x > 2000 ? 2.0 : 1.0); + } break; + + case 1: { + editor_set_scale(0.75); + } break; + + case 2: { + editor_set_scale(1.0); + } break; + + case 3: { + editor_set_scale(1.25); + } break; + + case 4: { + editor_set_scale(1.5); + } break; + + case 5: { + editor_set_scale(1.75); + } break; + + case 6: { + editor_set_scale(2.0); + } break; + + default: { + editor_set_scale(custom_display_scale); + } break; } + + OS::get_singleton()->set_window_size(OS::get_singleton()->get_window_size() * MAX(1, EDSCALE)); } FileDialog::set_default_show_hidden_files(EditorSettings::get_singleton()->get("filesystem/file_dialog/show_hidden_files")); @@ -1554,8 +1776,7 @@ ProjectManager::ProjectManager() { vb->add_constant_override("separation", 15 * EDSCALE); String cp; - cp.push_back(0xA9); - cp.push_back(0); + cp += 0xA9; OS::get_singleton()->set_window_title(VERSION_NAME + String(" - ") + TTR("Project Manager") + " - " + cp + " 2007-2018 Juan Linietsky, Ariel Manzur & Godot Contributors"); HBoxContainer *top_hb = memnew(HBoxContainer); @@ -1570,7 +1791,7 @@ ProjectManager::ProjectManager() { String hash = String(VERSION_HASH); if (hash.length() != 0) hash = "." + hash.left(7); - l->set_text("v" VERSION_MKSTRING "" + hash); + l->set_text("v" VERSION_FULL_BUILD "" + hash); l->set_align(Label::ALIGN_CENTER); top_hb->add_child(l); @@ -1598,7 +1819,7 @@ ProjectManager::ProjectManager() { project_filter = memnew(ProjectListFilter); search_box->add_child(project_filter); project_filter->connect("filter_changed", this, "_load_recent_projects"); - project_filter->set_custom_minimum_size(Size2(250, 10)); + project_filter->set_custom_minimum_size(Size2(280, 10) * EDSCALE); search_tree_vb->add_child(search_box); PanelContainer *pc = memnew(PanelContainer); @@ -1796,18 +2017,6 @@ void ProjectListFilter::_setup_filters() { filter_option->add_item(TTR("Path")); } -void ProjectListFilter::_command(int p_command) { - switch (p_command) { - - case CMD_CLEAR_FILTER: { - if (search_box->get_text() != "") { - search_box->clear(); - emit_signal("filter_changed"); - } - } break; - } -} - void ProjectListFilter::_search_text_changed(const String &p_newtext) { emit_signal("filter_changed"); } @@ -1830,13 +2039,14 @@ void ProjectListFilter::_filter_option_selected(int p_idx) { void ProjectListFilter::_notification(int p_what) { - if (p_what == NOTIFICATION_ENTER_TREE) - clear_search_button->set_icon(get_icon("Close", "EditorIcons")); + if (p_what == NOTIFICATION_ENTER_TREE) { + search_box->set_right_icon(get_icon("Search", "EditorIcons")); + search_box->set_clear_button_enabled(true); + } } void ProjectListFilter::_bind_methods() { - ClassDB::bind_method(D_METHOD("_command"), &ProjectListFilter::_command); ClassDB::bind_method(D_METHOD("_search_text_changed"), &ProjectListFilter::_search_text_changed); ClassDB::bind_method(D_METHOD("_filter_option_selected"), &ProjectListFilter::_filter_option_selected); @@ -1861,8 +2071,4 @@ ProjectListFilter::ProjectListFilter() { search_box->connect("text_changed", this, "_search_text_changed"); search_box->set_h_size_flags(SIZE_EXPAND_FILL); add_child(search_box); - - clear_search_button = memnew(ToolButton); - clear_search_button->connect("pressed", this, "_command", make_binds(CMD_CLEAR_FILTER)); - add_child(clear_search_button); } |