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.cpp168
1 files changed, 96 insertions, 72 deletions
diff --git a/editor/project_manager.cpp b/editor/project_manager.cpp
index 6de4330493..4b3d468a61 100644
--- a/editor/project_manager.cpp
+++ b/editor/project_manager.cpp
@@ -294,13 +294,13 @@ private:
String sp = _test_path();
if (sp != "") {
- // set the project name to the select folder name
- if (project_name->get_text() == "") {
+ // If the project name is empty or default, infer the project name from the selected folder name
+ if (project_name->get_text() == "" || project_name->get_text() == TTR("New Game Project")) {
sp = sp.replace("\\", "/");
int lidx = sp.find_last("/");
if (lidx != -1) {
- sp = sp.substr(lidx + 1, sp.length());
+ sp = sp.substr(lidx + 1, sp.length()).capitalize();
}
if (sp == "" && mode == MODE_IMPORT)
sp = TTR("Imported Project");
@@ -919,28 +919,37 @@ public:
struct ProjectItem {
String project;
+ String project_name;
String path;
String conf;
- int config_version;
+ String icon;
+ String main_scene;
uint64_t last_modified;
bool favorite;
bool grayed;
- bool ordered_latest_modification;
+ ProjectListFilter::FilterOption filter_order_option;
ProjectItem() {}
- ProjectItem(const String &p_project, const String &p_path, const String &p_conf, int p_config_version, uint64_t p_last_modified, bool p_favorite = false, bool p_grayed = false, const bool p_ordered_latest_modification = true) {
+ ProjectItem(const String &p_project, const String &p_name, const String &p_path, const String &p_conf, const String &p_icon, const String &p_main_scene, uint64_t p_last_modified, bool p_favorite = false, bool p_grayed = false, const ProjectListFilter::FilterOption p_filter_order_option = ProjectListFilter::FILTER_NAME) {
project = p_project;
+ project_name = p_name;
path = p_path;
conf = p_conf;
- config_version = p_config_version;
+ icon = p_icon;
+ main_scene = p_main_scene;
last_modified = p_last_modified;
favorite = p_favorite;
grayed = p_grayed;
- ordered_latest_modification = p_ordered_latest_modification;
+ filter_order_option = p_filter_order_option;
}
_FORCE_INLINE_ bool operator<(const ProjectItem &l) const {
- if (ordered_latest_modification)
- return last_modified > l.last_modified;
- return project < l.project;
+ switch (filter_order_option) {
+ case ProjectListFilter::FILTER_PATH:
+ return project < l.project;
+ case ProjectListFilter::FILTER_MODIFIED:
+ return last_modified > l.last_modified;
+ default:
+ return project_name < l.project_name;
+ }
}
_FORCE_INLINE_ bool operator==(const ProjectItem &l) const { return project == l.project; }
};
@@ -961,9 +970,25 @@ void ProjectManager::_notification(int p_what) {
set_process_unhandled_input(is_visible_in_tree());
} break;
+ case NOTIFICATION_WM_QUIT_REQUEST: {
+
+ _dim_window();
+ } break;
}
}
+void ProjectManager::_dim_window() {
+
+ // This method must be called before calling `get_tree()->quit()`.
+ // Otherwise, its effect won't be visible
+
+ // Dim the project manager window while it's quitting to make it clearer that it's busy.
+ // No transition is applied, as the effect needs to be visible immediately
+ float c = 1.0f - float(EDITOR_GET("interface/editor/dim_amount"));
+ Color dim_color = Color(c, c, c);
+ gui_base->set_modulate(dim_color);
+}
+
void ProjectManager::_panel_draw(Node *p_hb) {
HBoxContainer *hb = Object::cast_to<HBoxContainer>(p_hb);
@@ -1240,13 +1265,7 @@ void ProjectManager::_load_recent_projects() {
Color font_color = gui_base->get_color("font_color", "Tree");
- bool set_ordered_latest_modification;
ProjectListFilter::FilterOption filter_order_option = project_order_filter->get_filter_option();
- if (filter_order_option == ProjectListFilter::FILTER_NAME) {
- set_ordered_latest_modification = false;
- } else {
- set_ordered_latest_modification = true;
- }
EditorSettings::get_singleton()->set("project_manager/sorting_order", (int)filter_order_option);
List<ProjectItem> projects;
@@ -1264,10 +1283,30 @@ void ProjectManager::_load_recent_projects() {
String project = _name.get_slice("/", 1);
String conf = path.plus_file("project.godot");
- int config_version = 0; // Assume 0 until we know better
bool favorite = (_name.begins_with("favorite_projects/")) ? true : false;
bool grayed = false;
+ Ref<ConfigFile> cf = memnew(ConfigFile);
+ Error cf_err = cf->load(conf);
+
+ int config_version = 0;
+ String project_name = TTR("Unnamed Project");
+ if (cf_err == OK) {
+
+ String cf_project_name = static_cast<String>(cf->get_value("application", "config/name", ""));
+ if (cf_project_name != "")
+ project_name = cf_project_name.xml_unescape();
+ config_version = (int)cf->get_value("", "config_version", 0);
+ }
+
+ if (config_version > ProjectSettings::CONFIG_VERSION) {
+ // Comes from an incompatible (more recent) Godot version, grey it out
+ grayed = true;
+ }
+
+ String icon = cf->get_value("application", "config/icon", "");
+ String main_scene = cf->get_value("application", "run/main_scene", "");
+
uint64_t last_modified = 0;
if (FileAccess::exists(conf)) {
last_modified = FileAccess::get_modified_time(conf);
@@ -1282,7 +1321,7 @@ void ProjectManager::_load_recent_projects() {
grayed = true;
}
- ProjectItem item(project, path, conf, config_version, last_modified, favorite, grayed, set_ordered_latest_modification);
+ ProjectItem item(project, project_name, path, conf, icon, main_scene, last_modified, favorite, grayed, filter_order_option);
if (favorite)
favorite_projects.push_back(item);
else
@@ -1310,43 +1349,23 @@ void ProjectManager::_load_recent_projects() {
String path = item.path;
String conf = item.conf;
- Ref<ConfigFile> cf = memnew(ConfigFile);
- Error cf_err = cf->load(conf);
-
- String project_name = TTR("Unnamed Project");
- if (cf_err == OK && cf->has_section_key("application", "config/name")) {
- project_name = static_cast<String>(cf->get_value("application", "config/name")).xml_unescape();
- }
-
- if (filter_option == ProjectListFilter::FILTER_NAME && search_term != "" && project_name.findn(search_term) == -1)
+ if (filter_option == ProjectListFilter::FILTER_NAME && search_term != "" && item.project_name.findn(search_term) == -1)
continue;
Ref<Texture> icon;
- String main_scene;
- if (cf_err == OK) {
- item.config_version = (int)cf->get_value("", "config_version", 0);
- if (item.config_version > ProjectSettings::CONFIG_VERSION) {
- // Comes from an incompatible (more recent) Godot version, grey it out
- item.grayed = true;
+ if (item.icon != "") {
+ Ref<Image> img;
+ img.instance();
+ Error err = img->load(item.icon.replace_first("res://", path + "/"));
+ if (err == OK) {
+
+ Ref<Texture> default_icon = get_icon("DefaultProjectIcon", "EditorIcons");
+ img->resize(default_icon->get_width(), default_icon->get_height());
+ Ref<ImageTexture> it = memnew(ImageTexture);
+ it->create_from_image(img);
+ icon = it;
}
-
- String appicon = cf->get_value("application", "config/icon", "");
- if (appicon != "") {
- Ref<Image> img;
- img.instance();
- Error err = img->load(appicon.replace_first("res://", path + "/"));
- if (err == OK) {
-
- Ref<Texture> default_icon = get_icon("DefaultProjectIcon", "EditorIcons");
- img->resize(default_icon->get_width(), default_icon->get_height());
- Ref<ImageTexture> it = memnew(ImageTexture);
- it->create_from_image(img);
- icon = it;
- }
- }
-
- main_scene = cf->get_value("application", "run/main_scene", "");
}
if (icon.is_null()) {
@@ -1360,7 +1379,7 @@ void ProjectManager::_load_recent_projects() {
HBoxContainer *hb = memnew(HBoxContainer);
hb->set_meta("name", project);
- hb->set_meta("main_scene", main_scene);
+ hb->set_meta("main_scene", item.main_scene);
hb->set_meta("favorite", is_favorite);
hb->connect("draw", this, "_panel_draw", varray(hb));
hb->connect("gui_input", this, "_panel_input", varray(hb));
@@ -1390,7 +1409,7 @@ void ProjectManager::_load_recent_projects() {
ec->set_custom_minimum_size(Size2(0, 1));
ec->set_mouse_filter(MOUSE_FILTER_PASS);
vb->add_child(ec);
- Label *title = memnew(Label(project_name));
+ Label *title = memnew(Label(item.project_name));
title->add_font_override("font", gui_base->get_font("title", "EditorFonts"));
title->add_color_override("font_color", font_color);
title->set_clip_text(true);
@@ -1514,6 +1533,7 @@ void ProjectManager::_open_selected_projects() {
ERR_FAIL_COND(err);
}
+ _dim_window();
get_tree()->quit();
}
@@ -1627,40 +1647,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()) {
@@ -1792,11 +1800,13 @@ void ProjectManager::_restart_confirm() {
Error err = OS::get_singleton()->execute(exec, args, false, &pid);
ERR_FAIL_COND(err);
+ _dim_window();
get_tree()->quit();
}
void ProjectManager::_exit_dialog() {
+ _dim_window();
get_tree()->quit();
}
@@ -1983,7 +1993,7 @@ ProjectManager::ProjectManager() {
l = memnew(Label);
String hash = String(VERSION_HASH);
if (hash.length() != 0)
- hash = "." + hash.left(7);
+ hash = "." + hash.left(9);
l->set_text("v" VERSION_FULL_BUILD "" + hash);
l->set_align(Label::ALIGN_CENTER);
top_hb->add_child(l);
@@ -2013,6 +2023,7 @@ ProjectManager::ProjectManager() {
sort_filters->add_child(sort_label);
Vector<String> sort_filter_titles;
sort_filter_titles.push_back("Name");
+ sort_filter_titles.push_back("Path");
sort_filter_titles.push_back("Last Modified");
project_order_filter = memnew(ProjectListFilter);
project_order_filter->_setup_filters(sort_filter_titles);
@@ -2166,6 +2177,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);