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.cpp277
1 files changed, 180 insertions, 97 deletions
diff --git a/editor/project_manager.cpp b/editor/project_manager.cpp
index e8fd3070c2..7ae03b3072 100644
--- a/editor/project_manager.cpp
+++ b/editor/project_manager.cpp
@@ -41,6 +41,7 @@
#include "core/string/translation.h"
#include "core/version.h"
#include "core/version_hash.gen.h"
+#include "editor/editor_vcs_interface.h"
#include "editor_scale.h"
#include "editor_settings.h"
#include "editor_themes.h"
@@ -52,6 +53,7 @@
#include "scene/gui/texture_rect.h"
#include "scene/main/window.h"
#include "servers/display_server.h"
+#include "servers/navigation_server_3d.h"
static inline String get_project_key_from_path(const String &dir) {
return dir.replace("/", "::");
@@ -66,19 +68,19 @@ public:
MODE_NEW,
MODE_IMPORT,
MODE_INSTALL,
- MODE_RENAME
+ MODE_RENAME,
};
private:
enum MessageType {
MESSAGE_ERROR,
MESSAGE_WARNING,
- MESSAGE_SUCCESS
+ MESSAGE_SUCCESS,
};
enum InputType {
PROJECT_PATH,
- INSTALL_PATH
+ INSTALL_PATH,
};
Mode mode;
@@ -89,6 +91,7 @@ private:
Container *path_container;
Container *install_path_container;
Container *rasterizer_container;
+ HBoxContainer *default_files_container;
Ref<ButtonGroup> rasterizer_button_group;
Label *msg;
LineEdit *project_path;
@@ -98,6 +101,7 @@ private:
TextureRect *install_status_rect;
FileDialog *fdialog;
FileDialog *fdialog_install;
+ OptionButton *vcs_metadata_selection;
String zip_path;
String zip_title;
AcceptDialog *dialog_error;
@@ -473,32 +477,29 @@ private:
cd->grab_focus();
return;
}
+ PackedStringArray project_features = ProjectSettings::get_required_features();
ProjectSettings::CustomMap initial_settings;
- initial_settings["rendering/vulkan/rendering/back_end"] = rasterizer_button_group->get_pressed_button()->get_meta(SNAME("driver_name"));
+ // 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");
+ } 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();
initial_settings["application/config/icon"] = "res://icon.png";
- initial_settings["rendering/environment/defaults/default_environment"] = "res://default_env.tres";
if (ProjectSettings::get_singleton()->save_custom(dir.plus_file("project.godot"), initial_settings, Vector<String>(), false) != OK) {
set_message(TTR("Couldn't create project.godot in project path."), MESSAGE_ERROR);
} else {
ResourceSaver::save(dir.plus_file("icon.png"), create_unscaled_default_project_icon());
-
- FileAccess *f = FileAccess::open(dir.plus_file("default_env.tres"), FileAccess::WRITE);
- if (!f) {
- set_message(TTR("Couldn't create project.godot in project path."), MESSAGE_ERROR);
- } else {
- f->store_line("[gd_resource type=\"Environment\" load_steps=2 format=3]");
- f->store_line("");
- f->store_line("[sub_resource type=\"Sky\" id=\"1\"]");
- f->store_line("");
- f->store_line("[resource]");
- f->store_line("background_mode = 2");
- f->store_line("sky = SubResource( \"1\" )");
- memdelete(f);
- }
+ EditorVCSInterface::create_vcs_metadata_files(EditorVCSInterface::VCSMetadata(vcs_metadata_selection->get_selected()), dir);
}
-
} else if (mode == MODE_INSTALL) {
if (project_path->get_text().ends_with(".zip")) {
dir = install_path->get_text();
@@ -693,6 +694,7 @@ public:
install_path_container->hide();
install_status_rect->hide();
rasterizer_container->hide();
+ default_files_container->hide();
get_ok_button()->set_disabled(false);
ProjectSettings *current = memnew(ProjectSettings);
@@ -744,6 +746,7 @@ public:
name_container->hide();
install_path_container->hide();
rasterizer_container->hide();
+ default_files_container->hide();
project_path->grab_focus();
} else if (mode == MODE_NEW) {
@@ -752,6 +755,7 @@ public:
name_container->show();
install_path_container->hide();
rasterizer_container->show();
+ default_files_container->show();
project_name->call_deferred(SNAME("grab_focus"));
project_name->call_deferred(SNAME("select_all"));
@@ -762,6 +766,7 @@ public:
name_container->show();
install_path_container->hide();
rasterizer_container->hide();
+ default_files_container->hide();
project_path->grab_focus();
}
@@ -904,6 +909,21 @@ public:
l->set_modulate(Color(1, 1, 1, 0.7));
rasterizer_container->add_child(l);
+ default_files_container = memnew(HBoxContainer);
+ vb->add_child(default_files_container);
+ l = memnew(Label);
+ l->set_text(TTR("Version Control Metadata:"));
+ default_files_container->add_child(l);
+ vcs_metadata_selection = memnew(OptionButton);
+ vcs_metadata_selection->set_custom_minimum_size(Size2(100, 20));
+ vcs_metadata_selection->add_item("None", (int)EditorVCSInterface::VCSMetadata::NONE);
+ vcs_metadata_selection->add_item("Git", (int)EditorVCSInterface::VCSMetadata::GIT);
+ vcs_metadata_selection->select((int)EditorVCSInterface::VCSMetadata::GIT);
+ default_files_container->add_child(vcs_metadata_selection);
+ Control *spacer = memnew(Control);
+ spacer->set_h_size_flags(Control::SIZE_EXPAND_FILL);
+ default_files_container->add_child(spacer);
+
fdialog = memnew(FileDialog);
fdialog->set_access(FileDialog::ACCESS_FILESYSTEM);
fdialog_install = memnew(FileDialog);
@@ -985,6 +1005,7 @@ public:
String path;
String icon;
String main_scene;
+ PackedStringArray unsupported_features;
uint64_t last_edited = 0;
bool favorite = false;
bool grayed = false;
@@ -1001,6 +1022,7 @@ public:
const String &p_path,
const String &p_icon,
const String &p_main_scene,
+ const PackedStringArray &p_unsupported_features,
uint64_t p_last_edited,
bool p_favorite,
bool p_grayed,
@@ -1012,6 +1034,7 @@ public:
path = p_path;
icon = p_icon;
main_scene = p_main_scene;
+ unsupported_features = p_unsupported_features;
last_edited = p_last_edited;
favorite = p_favorite;
grayed = p_grayed;
@@ -1063,8 +1086,7 @@ private:
void remove_project(int p_index, bool p_update_settings);
void update_icons_async();
void load_project_icon(int p_index);
-
- static void load_project_data(const String &p_property_key, Item &p_item, bool p_favorite);
+ static Item load_project_data(const String &p_property_key, bool p_favorite);
String _search_term;
FilterOption _order_option;
@@ -1155,7 +1177,8 @@ void ProjectList::load_project_icon(int p_index) {
item.control->icon_needs_reload = false;
}
-void ProjectList::load_project_data(const String &p_property_key, Item &p_item, bool p_favorite) {
+// Load project data from p_property_key and return it in a ProjectList::Item. p_favorite is passed directly into the Item.
+ProjectList::Item ProjectList::load_project_data(const String &p_property_key, bool p_favorite) {
String path = EditorSettings::get_singleton()->get(p_property_key);
String conf = path.plus_file("project.godot");
bool grayed = false;
@@ -1175,13 +1198,16 @@ void ProjectList::load_project_data(const String &p_property_key, Item &p_item,
}
if (config_version > ProjectSettings::CONFIG_VERSION) {
- // Comes from an incompatible (more recent) Godot version, grey it out
+ // Comes from an incompatible (more recent) Godot version, gray it out.
grayed = true;
}
- String description = cf->get_value("application", "config/description", "");
- String icon = cf->get_value("application", "config/icon", "");
- String main_scene = cf->get_value("application", "run/main_scene", "");
+ const String description = cf->get_value("application", "config/description", "");
+ const String icon = cf->get_value("application", "config/icon", "");
+ const String main_scene = cf->get_value("application", "run/main_scene", "");
+
+ PackedStringArray project_features = cf->get_value("application", "config/features", PackedStringArray());
+ PackedStringArray unsupported_features = ProjectSettings::get_unsupported_features(project_features);
uint64_t last_edited = 0;
if (FileAccess::exists(conf)) {
@@ -1203,9 +1229,9 @@ void ProjectList::load_project_data(const String &p_property_key, Item &p_item,
print_line("Project is missing: " + conf);
}
- String project_key = p_property_key.get_slice("/", 1);
+ const String project_key = p_property_key.get_slice("/", 1);
- p_item = Item(project_key, project_name, description, path, icon, main_scene, last_edited, p_favorite, grayed, missing, config_version);
+ return Item(project_key, project_name, description, path, icon, main_scene, unsupported_features, last_edited, p_favorite, grayed, missing, config_version);
}
void ProjectList::load_projects() {
@@ -1248,8 +1274,7 @@ void ProjectList::load_projects() {
String project_key = property_key.get_slice("/", 1);
bool favorite = favorites.has("favorite_projects/" + project_key);
- Item item;
- load_project_data(property_key, item, favorite);
+ Item item = load_project_data(property_key, favorite);
_projects.push_back(item);
}
@@ -1297,8 +1322,7 @@ void ProjectList::update_dock_menu() {
void ProjectList::_global_menu_new_window(const Variant &p_tag) {
List<String> args;
args.push_back("-p");
- String exec = OS::get_singleton()->get_executable_path();
- OS::get_singleton()->create_process(exec, args);
+ OS::get_singleton()->create_instance(args);
}
void ProjectList::_global_menu_open_project(const Variant &p_tag) {
@@ -1308,8 +1332,7 @@ void ProjectList::_global_menu_open_project(const Variant &p_tag) {
String conf = _projects[idx].path.plus_file("project.godot");
List<String> args;
args.push_back(conf);
- String exec = OS::get_singleton()->get_executable_path();
- OS::get_singleton()->create_process(exec, args);
+ OS::get_singleton()->create_instance(args);
}
}
@@ -1334,7 +1357,7 @@ void ProjectList::create_project_item_control(int p_index) {
TextureButton *favorite = memnew(TextureButton);
favorite->set_name("FavoriteButton");
favorite->set_normal_texture(favorite_icon);
- // This makes the project's "hover" style display correctly when hovering the 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), varray(hb));
favorite_box->add_child(favorite);
@@ -1364,40 +1387,65 @@ void ProjectList::create_project_item_control(int p_index) {
ec->set_custom_minimum_size(Size2(0, 1));
ec->set_mouse_filter(MOUSE_FILTER_PASS);
vb->add_child(ec);
- Label *title = memnew(Label(!item.missing ? item.project_name : TTR("Missing Project")));
- title->add_theme_font_override("font", get_theme_font(SNAME("title"), SNAME("EditorFonts")));
- title->add_theme_font_size_override("font_size", get_theme_font_size(SNAME("title_size"), SNAME("EditorFonts")));
- title->add_theme_color_override("font_color", font_color);
- title->set_clip_text(true);
- vb->add_child(title);
-
- HBoxContainer *path_hb = memnew(HBoxContainer);
- path_hb->set_h_size_flags(Control::SIZE_EXPAND_FILL);
- vb->add_child(path_hb);
-
- Button *show = memnew(Button);
- // Display a folder icon if the project directory can be opened, or a "broken file" icon if it can't.
- show->set_icon(get_theme_icon(!item.missing ? "Load" : "FileBroken", "EditorIcons"));
- if (!item.grayed) {
- // Don't make the icon less prominent if the parent is already grayed out.
- show->set_modulate(Color(1, 1, 1, 0.5));
- }
- path_hb->add_child(show);
-
- if (!item.missing) {
- show->connect("pressed", callable_mp(this, &ProjectList::_show_project), varray(item.path));
- show->set_tooltip(TTR("Show in File Manager"));
- } else {
- show->set_tooltip(TTR("Error: Project is missing on the filesystem."));
- }
- Label *fpath = memnew(Label(item.path));
- fpath->set_structured_text_bidi_override(Control::STRUCTURED_TEXT_FILE);
- path_hb->add_child(fpath);
- fpath->set_h_size_flags(Control::SIZE_EXPAND_FILL);
- fpath->set_modulate(Color(1, 1, 1, 0.5));
- fpath->add_theme_color_override("font_color", font_color);
- fpath->set_clip_text(true);
+ { // Top half, title and unsupported features labels.
+ HBoxContainer *title_hb = memnew(HBoxContainer);
+ vb->add_child(title_hb);
+
+ Label *title = memnew(Label(!item.missing ? item.project_name : TTR("Missing Project")));
+ title->set_h_size_flags(Control::SIZE_EXPAND_FILL);
+ title->add_theme_font_override("font", get_theme_font(SNAME("title"), SNAME("EditorFonts")));
+ title->add_theme_font_size_override("font_size", get_theme_font_size(SNAME("title_size"), SNAME("EditorFonts")));
+ title->add_theme_color_override("font_color", font_color);
+ title->set_clip_text(true);
+ title_hb->add_child(title);
+
+ String unsupported_features_str = Variant(item.unsupported_features).operator String().trim_prefix("[").trim_suffix("]");
+ int length = unsupported_features_str.length();
+ if (length > 0) {
+ Label *unsupported_label = memnew(Label(unsupported_features_str));
+ unsupported_label->set_custom_minimum_size(Size2(length * 15, 10) * EDSCALE);
+ unsupported_label->add_theme_font_override("font", get_theme_font(SNAME("title"), SNAME("EditorFonts")));
+ unsupported_label->add_theme_color_override("font_color", get_theme_color(SNAME("warning_color"), SNAME("Editor")));
+ unsupported_label->set_clip_text(true);
+ unsupported_label->set_align(Label::ALIGN_RIGHT);
+ title_hb->add_child(unsupported_label);
+ Control *spacer = memnew(Control());
+ spacer->set_custom_minimum_size(Size2(10, 10));
+ title_hb->add_child(spacer);
+ }
+ }
+
+ { // Bottom half, containing the path and view folder button.
+ HBoxContainer *path_hb = memnew(HBoxContainer);
+ path_hb->set_h_size_flags(Control::SIZE_EXPAND_FILL);
+ vb->add_child(path_hb);
+
+ Button *show = memnew(Button);
+ // Display a folder icon if the project directory can be opened, or a "broken file" icon if it can't.
+ show->set_icon(get_theme_icon(!item.missing ? "Load" : "FileBroken", "EditorIcons"));
+ show->set_flat(true);
+ if (!item.grayed) {
+ // Don't make the icon less prominent if the parent is already grayed out.
+ show->set_modulate(Color(1, 1, 1, 0.5));
+ }
+ path_hb->add_child(show);
+
+ if (!item.missing) {
+ show->connect("pressed", callable_mp(this, &ProjectList::_show_project), varray(item.path));
+ show->set_tooltip(TTR("Show in File Manager"));
+ } else {
+ show->set_tooltip(TTR("Error: Project is missing on the filesystem."));
+ }
+
+ Label *fpath = memnew(Label(item.path));
+ fpath->set_structured_text_bidi_override(Control::STRUCTURED_TEXT_FILE);
+ path_hb->add_child(fpath);
+ fpath->set_h_size_flags(Control::SIZE_EXPAND_FILL);
+ fpath->set_modulate(Color(1, 1, 1, 0.5));
+ fpath->add_theme_color_override("font_color", font_color);
+ fpath->set_clip_text(true);
+ }
_scroll_children->add_child(hb);
item.control = hb;
@@ -1511,7 +1559,7 @@ void ProjectList::remove_project(int p_index, bool p_update_settings) {
}
memdelete(item.control);
- _projects.remove(p_index);
+ _projects.remove_at(p_index);
if (p_update_settings) {
EditorSettings::get_singleton()->erase("projects/" + item.project_key);
@@ -1602,8 +1650,7 @@ int ProjectList::refresh_project(const String &dir_path) {
if (should_be_in_list) {
// Recreate it with updated info
- Item item;
- load_project_data(property_key, item, is_favourite);
+ Item item = load_project_data(property_key, is_favourite);
_projects.push_back(item);
create_project_item_control(_projects.size() - 1);
@@ -1701,7 +1748,7 @@ void ProjectList::erase_selected_projects(bool p_delete_project_contents) {
}
memdelete(item.control);
- _projects.remove(i);
+ _projects.remove_at(i);
--i;
}
}
@@ -1737,7 +1784,7 @@ void ProjectList::_panel_input(const Ref<InputEvent> &p_ev, Node *p_hb) {
int clicked_index = p_hb->get_index();
const Item &clicked_project = _projects[clicked_index];
- if (mb.is_valid() && mb->is_pressed() && mb->get_button_index() == MOUSE_BUTTON_LEFT) {
+ if (mb.is_valid() && mb->is_pressed() && mb->get_button_index() == MouseButton::LEFT) {
if (mb->is_shift_pressed() && _selected_project_keys.size() > 0 && _last_clicked != "" && clicked_project.project_key != _last_clicked) {
int anchor_index = -1;
for (int i = 0; i < _projects.size(); ++i) {
@@ -1901,7 +1948,7 @@ void ProjectManager::unhandled_key_input(const Ref<InputEvent> &p_ev) {
// This is handled by the platform implementation on macOS,
// so only define the shortcut on other platforms
#ifndef OSX_ENABLED
- if (k->get_keycode_with_modifiers() == (KEY_MASK_CMD | KEY_Q)) {
+ if (k->get_keycode_with_modifiers() == (KeyModifierMask::CMD | Key::Q)) {
_dim_window();
get_tree()->quit();
}
@@ -1914,24 +1961,24 @@ void ProjectManager::unhandled_key_input(const Ref<InputEvent> &p_ev) {
bool keycode_handled = true;
switch (k->get_keycode()) {
- case KEY_ENTER: {
+ case Key::ENTER: {
_open_selected_projects_ask();
} break;
- case KEY_HOME: {
+ case Key::HOME: {
if (_project_list->get_project_count() > 0) {
_project_list->select_project(0);
_update_project_buttons();
}
} break;
- case KEY_END: {
+ case Key::END: {
if (_project_list->get_project_count() > 0) {
_project_list->select_project(_project_list->get_project_count() - 1);
_update_project_buttons();
}
} break;
- case KEY_UP: {
+ case Key::UP: {
if (k->is_shift_pressed()) {
break;
}
@@ -1945,7 +1992,7 @@ void ProjectManager::unhandled_key_input(const Ref<InputEvent> &p_ev) {
break;
}
- case KEY_DOWN: {
+ case Key::DOWN: {
if (k->is_shift_pressed()) {
break;
}
@@ -1958,7 +2005,7 @@ void ProjectManager::unhandled_key_input(const Ref<InputEvent> &p_ev) {
}
} break;
- case KEY_F: {
+ case Key::F: {
if (k->is_command_pressed()) {
this->search_box->grab_focus();
} else {
@@ -2055,8 +2102,7 @@ void ProjectManager::_open_selected_projects() {
args.push_back("--single-window");
}
- String exec = OS::get_singleton()->get_executable_path();
- Error err = OS::get_singleton()->create_process(exec, args);
+ Error err = OS::get_singleton()->create_instance(args);
ERR_FAIL_COND(err);
}
@@ -2083,8 +2129,12 @@ void ProjectManager::_open_selected_projects_ask() {
}
// Update the project settings or don't open
- String conf = project.path.plus_file("project.godot");
- int config_version = project.version;
+ const String conf = project.path.plus_file("project.godot");
+ 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_align(Label::ALIGN_LEFT); // Reset in case of previous center align.
// Check if the config_version property was empty or 0
if (config_version == 0) {
@@ -2104,6 +2154,35 @@ void ProjectManager::_open_selected_projects_ask() {
dialog_error->popup_centered();
return;
}
+ // Check if the project is using features not supported by this build of Godot.
+ if (!unsupported_features.is_empty()) {
+ String warning_message = "";
+ for (int i = 0; i < unsupported_features.size(); i++) {
+ String feature = unsupported_features[i];
+ if (feature == "Double Precision") {
+ warning_message += TTR("Warning: This project uses double precision floats, but this version of\nGodot uses single precision floats. Opening this project may cause data loss.\n\n");
+ unsupported_features.remove_at(i);
+ i--;
+ } else if (feature == "C#") {
+ warning_message += TTR("Warning: This project uses C#, but this build of Godot does not have\nthe Mono module. If you proceed you will not be able to use any C# scripts.\n\n");
+ unsupported_features.remove_at(i);
+ i--;
+ } else if (feature.substr(0, 3).is_numeric()) {
+ warning_message += vformat(TTR("Warning: This project was built in Godot %s.\nOpening will upgrade or downgrade the project to Godot %s.\n\n"), Variant(feature), Variant(VERSION_BRANCH));
+ unsupported_features.remove_at(i);
+ i--;
+ }
+ }
+ if (!unsupported_features.is_empty()) {
+ String unsupported_features_str = Variant(unsupported_features).operator String().trim_prefix("[").trim_suffix("]");
+ warning_message += vformat(TTR("Warning: This project uses the following features not supported by this build of Godot:\n\n%s\n\n"), unsupported_features_str);
+ }
+ warning_message += TTR("Open anyway? Project will be modified.");
+ ask_update_label->set_align(Label::ALIGN_CENTER);
+ ask_update_settings->set_text(warning_message);
+ ask_update_settings->popup_centered();
+ return;
+ }
// Open if the project is up-to-date
_open_selected_projects();
@@ -2141,8 +2220,7 @@ void ProjectManager::_run_project_confirm() {
args.push_back("--disable-crash-handler");
}
- String exec = OS::get_singleton()->get_executable_path();
- Error err = OS::get_singleton()->create_process(exec, args);
+ Error err = OS::get_singleton()->create_instance(args);
ERR_FAIL_COND(err);
}
}
@@ -2271,8 +2349,7 @@ void ProjectManager::_language_selected(int p_id) {
void ProjectManager::_restart_confirm() {
List<String> args = OS::get_singleton()->get_cmdline_args();
- String exec = OS::get_singleton()->get_executable_path();
- Error err = OS::get_singleton()->create_process(exec, args);
+ Error err = OS::get_singleton()->create_instance(args);
ERR_FAIL_COND(err);
_dim_window();
@@ -2387,6 +2464,11 @@ ProjectManager::ProjectManager() {
EditorSettings::create();
}
+ // Turn off some servers we aren't going to be using in the Project Manager.
+ NavigationServer3D::get_singleton()->set_active(false);
+ PhysicsServer3D::get_singleton()->set_active(false);
+ PhysicsServer2D::get_singleton()->set_active(false);
+
EditorSettings::get_singleton()->set_optimize_save(false); //just write settings as they came
{
@@ -2525,19 +2607,19 @@ ProjectManager::ProjectManager() {
Button *create = memnew(Button);
create->set_text(TTR("New Project"));
- create->set_shortcut(ED_SHORTCUT("project_manager/new_project", TTR("New Project"), KEY_MASK_CMD | KEY_N));
+ create->set_shortcut(ED_SHORTCUT("project_manager/new_project", TTR("New Project"), KeyModifierMask::CMD | Key::N));
create->connect("pressed", callable_mp(this, &ProjectManager::_new_project));
tree_vb->add_child(create);
Button *import = memnew(Button);
import->set_text(TTR("Import"));
- import->set_shortcut(ED_SHORTCUT("project_manager/import_project", TTR("Import Project"), KEY_MASK_CMD | KEY_I));
+ import->set_shortcut(ED_SHORTCUT("project_manager/import_project", TTR("Import Project"), KeyModifierMask::CMD | Key::I));
import->connect("pressed", callable_mp(this, &ProjectManager::_import_project));
tree_vb->add_child(import);
Button *scan = memnew(Button);
scan->set_text(TTR("Scan"));
- scan->set_shortcut(ED_SHORTCUT("project_manager/scan_projects", TTR("Scan Projects"), KEY_MASK_CMD | KEY_S));
+ scan->set_shortcut(ED_SHORTCUT("project_manager/scan_projects", TTR("Scan Projects"), KeyModifierMask::CMD | Key::S));
scan->connect("pressed", callable_mp(this, &ProjectManager::_scan_projects));
tree_vb->add_child(scan);
@@ -2545,25 +2627,26 @@ ProjectManager::ProjectManager() {
open_btn = memnew(Button);
open_btn->set_text(TTR("Edit"));
- open_btn->set_shortcut(ED_SHORTCUT("project_manager/edit_project", TTR("Edit Project"), KEY_MASK_CMD | KEY_E));
+ open_btn->set_shortcut(ED_SHORTCUT("project_manager/edit_project", TTR("Edit Project"), KeyModifierMask::CMD | Key::E));
open_btn->connect("pressed", callable_mp(this, &ProjectManager::_open_selected_projects_ask));
tree_vb->add_child(open_btn);
run_btn = memnew(Button);
run_btn->set_text(TTR("Run"));
- run_btn->set_shortcut(ED_SHORTCUT("project_manager/run_project", TTR("Run Project"), KEY_MASK_CMD | KEY_R));
+ run_btn->set_shortcut(ED_SHORTCUT("project_manager/run_project", TTR("Run Project"), KeyModifierMask::CMD | Key::R));
run_btn->connect("pressed", callable_mp(this, &ProjectManager::_run_project));
tree_vb->add_child(run_btn);
rename_btn = memnew(Button);
rename_btn->set_text(TTR("Rename"));
- rename_btn->set_shortcut(ED_SHORTCUT("project_manager/rename_project", TTR("Rename Project"), KEY_F2));
+ // The F2 shortcut isn't overridden with Enter on macOS as Enter is already used to edit a project.
+ rename_btn->set_shortcut(ED_SHORTCUT("project_manager/rename_project", TTR("Rename Project"), Key::F2));
rename_btn->connect("pressed", callable_mp(this, &ProjectManager::_rename_project));
tree_vb->add_child(rename_btn);
erase_btn = memnew(Button);
erase_btn->set_text(TTR("Remove"));
- erase_btn->set_shortcut(ED_SHORTCUT("project_manager/remove_project", TTR("Remove Project"), KEY_DELETE));
+ erase_btn->set_shortcut(ED_SHORTCUT("project_manager/remove_project", TTR("Remove Project"), Key::KEY_DELETE));
erase_btn->connect("pressed", callable_mp(this, &ProjectManager::_erase_project));
tree_vb->add_child(erase_btn);
@@ -2634,7 +2717,7 @@ ProjectManager::ProjectManager() {
for (int i = 0; i < editor_languages.size(); i++) {
String lang = editor_languages[i];
String lang_name = TranslationServer::get_singleton()->get_locale_name(lang);
- language_btn->add_item(lang_name + " [" + lang + "]", i);
+ language_btn->add_item(vformat("[%s] %s", lang, lang_name), i);
language_btn->set_item_metadata(i, lang);
if (current_lang == lang) {
language_btn->select(i);