|
@@ -52,6 +52,7 @@
|
|
#include "editor/themes/editor_scale.h"
|
|
#include "editor/themes/editor_scale.h"
|
|
#include "editor/themes/editor_theme_manager.h"
|
|
#include "editor/themes/editor_theme_manager.h"
|
|
#include "main/main.h"
|
|
#include "main/main.h"
|
|
|
|
+#include "scene/gui/check_box.h"
|
|
#include "scene/gui/flow_container.h"
|
|
#include "scene/gui/flow_container.h"
|
|
#include "scene/gui/line_edit.h"
|
|
#include "scene/gui/line_edit.h"
|
|
#include "scene/gui/margin_container.h"
|
|
#include "scene/gui/margin_container.h"
|
|
@@ -262,6 +263,7 @@ void ProjectManager::_update_theme(bool p_skip_creation) {
|
|
open_options_btn->set_button_icon(get_editor_theme_icon(SNAME("Collapse")));
|
|
open_options_btn->set_button_icon(get_editor_theme_icon(SNAME("Collapse")));
|
|
run_btn->set_button_icon(get_editor_theme_icon(SNAME("Play")));
|
|
run_btn->set_button_icon(get_editor_theme_icon(SNAME("Play")));
|
|
rename_btn->set_button_icon(get_editor_theme_icon(SNAME("Rename")));
|
|
rename_btn->set_button_icon(get_editor_theme_icon(SNAME("Rename")));
|
|
|
|
+ duplicate_btn->set_button_icon(get_editor_theme_icon(SNAME("Duplicate")));
|
|
manage_tags_btn->set_button_icon(get_editor_theme_icon("Script"));
|
|
manage_tags_btn->set_button_icon(get_editor_theme_icon("Script"));
|
|
erase_btn->set_button_icon(get_editor_theme_icon(SNAME("Remove")));
|
|
erase_btn->set_button_icon(get_editor_theme_icon(SNAME("Remove")));
|
|
erase_missing_btn->set_button_icon(get_editor_theme_icon(SNAME("Clear")));
|
|
erase_missing_btn->set_button_icon(get_editor_theme_icon(SNAME("Clear")));
|
|
@@ -276,6 +278,7 @@ void ProjectManager::_update_theme(bool p_skip_creation) {
|
|
open_btn->add_theme_constant_override("h_separation", get_theme_constant(SNAME("sidebar_button_icon_separation"), SNAME("ProjectManager")));
|
|
open_btn->add_theme_constant_override("h_separation", get_theme_constant(SNAME("sidebar_button_icon_separation"), SNAME("ProjectManager")));
|
|
run_btn->add_theme_constant_override("h_separation", get_theme_constant(SNAME("sidebar_button_icon_separation"), SNAME("ProjectManager")));
|
|
run_btn->add_theme_constant_override("h_separation", get_theme_constant(SNAME("sidebar_button_icon_separation"), SNAME("ProjectManager")));
|
|
rename_btn->add_theme_constant_override("h_separation", get_theme_constant(SNAME("sidebar_button_icon_separation"), SNAME("ProjectManager")));
|
|
rename_btn->add_theme_constant_override("h_separation", get_theme_constant(SNAME("sidebar_button_icon_separation"), SNAME("ProjectManager")));
|
|
|
|
+ duplicate_btn->add_theme_constant_override("h_separation", get_theme_constant(SNAME("sidebar_button_icon_separation"), SNAME("ProjectManager")));
|
|
manage_tags_btn->add_theme_constant_override("h_separation", get_theme_constant(SNAME("sidebar_button_icon_separation"), SNAME("ProjectManager")));
|
|
manage_tags_btn->add_theme_constant_override("h_separation", get_theme_constant(SNAME("sidebar_button_icon_separation"), SNAME("ProjectManager")));
|
|
erase_btn->add_theme_constant_override("h_separation", get_theme_constant(SNAME("sidebar_button_icon_separation"), SNAME("ProjectManager")));
|
|
erase_btn->add_theme_constant_override("h_separation", get_theme_constant(SNAME("sidebar_button_icon_separation"), SNAME("ProjectManager")));
|
|
erase_missing_btn->add_theme_constant_override("h_separation", get_theme_constant(SNAME("sidebar_button_icon_separation"), SNAME("ProjectManager")));
|
|
erase_missing_btn->add_theme_constant_override("h_separation", get_theme_constant(SNAME("sidebar_button_icon_separation"), SNAME("ProjectManager")));
|
|
@@ -561,15 +564,16 @@ void ProjectManager::_open_selected_projects_check_warnings() {
|
|
const int config_version = project.version;
|
|
const int config_version = project.version;
|
|
PackedStringArray unsupported_features = project.unsupported_features;
|
|
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.
|
|
ask_update_label->set_horizontal_alignment(HORIZONTAL_ALIGNMENT_LEFT); // Reset in case of previous center align.
|
|
|
|
+ ask_update_backup->set_pressed(false);
|
|
full_convert_button->hide();
|
|
full_convert_button->hide();
|
|
|
|
+ ask_update_backup->hide();
|
|
|
|
|
|
ask_update_settings->get_ok_button()->set_text("OK");
|
|
ask_update_settings->get_ok_button()->set_text("OK");
|
|
|
|
|
|
// Check if the config_version property was empty or 0.
|
|
// Check if the config_version property was empty or 0.
|
|
if (config_version == 0) {
|
|
if (config_version == 0) {
|
|
- 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_label->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_size);
|
|
ask_update_settings->popup_centered(popup_min_size);
|
|
return;
|
|
return;
|
|
}
|
|
}
|
|
@@ -577,10 +581,12 @@ void ProjectManager::_open_selected_projects_check_warnings() {
|
|
if (config_version < ProjectSettings::CONFIG_VERSION) {
|
|
if (config_version < ProjectSettings::CONFIG_VERSION) {
|
|
if (config_version == GODOT4_CONFIG_VERSION - 1 && ProjectSettings::CONFIG_VERSION == GODOT4_CONFIG_VERSION) { // Conversion from Godot 3 to 4.
|
|
if (config_version == GODOT4_CONFIG_VERSION - 1 && ProjectSettings::CONFIG_VERSION == GODOT4_CONFIG_VERSION) { // Conversion from Godot 3 to 4.
|
|
full_convert_button->show();
|
|
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_backup->show();
|
|
|
|
+ ask_update_label->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(TTRC("Convert project.godot Only"));
|
|
ask_update_settings->get_ok_button()->set_text(TTRC("Convert project.godot Only"));
|
|
} else {
|
|
} 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_backup->show();
|
|
|
|
+ ask_update_label->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(TTRC("Convert project.godot"));
|
|
ask_update_settings->get_ok_button()->set_text(TTRC("Convert project.godot"));
|
|
}
|
|
}
|
|
ask_update_settings->popup_centered(popup_min_size);
|
|
ask_update_settings->popup_centered(popup_min_size);
|
|
@@ -598,6 +604,7 @@ void ProjectManager::_open_selected_projects_check_warnings() {
|
|
for (int i = 0; i < unsupported_features.size(); i++) {
|
|
for (int i = 0; i < unsupported_features.size(); i++) {
|
|
const String &feature = unsupported_features[i];
|
|
const String &feature = unsupported_features[i];
|
|
if (feature == "Double Precision") {
|
|
if (feature == "Double Precision") {
|
|
|
|
+ ask_update_backup->show();
|
|
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");
|
|
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);
|
|
unsupported_features.remove_at(i);
|
|
i--;
|
|
i--;
|
|
@@ -606,6 +613,7 @@ void ProjectManager::_open_selected_projects_check_warnings() {
|
|
unsupported_features.remove_at(i);
|
|
unsupported_features.remove_at(i);
|
|
i--;
|
|
i--;
|
|
} else if (ProjectList::project_feature_looks_like_version(feature)) {
|
|
} else if (ProjectList::project_feature_looks_like_version(feature)) {
|
|
|
|
+ ask_update_backup->show();
|
|
version_convert_feature = feature;
|
|
version_convert_feature = feature;
|
|
warning_message += vformat(TTR("Warning: This project was last edited in Godot %s. Opening will change it to Godot %s.\n\n"), Variant(feature), Variant(GODOT_VERSION_BRANCH));
|
|
warning_message += vformat(TTR("Warning: This project was last edited in Godot %s. Opening will change it to Godot %s.\n\n"), Variant(feature), Variant(GODOT_VERSION_BRANCH));
|
|
unsupported_features.remove_at(i);
|
|
unsupported_features.remove_at(i);
|
|
@@ -618,7 +626,7 @@ void ProjectManager::_open_selected_projects_check_warnings() {
|
|
}
|
|
}
|
|
warning_message += TTR("Open anyway? Project will be modified.");
|
|
warning_message += TTR("Open anyway? Project will be modified.");
|
|
ask_update_label->set_horizontal_alignment(HORIZONTAL_ALIGNMENT_CENTER);
|
|
ask_update_label->set_horizontal_alignment(HORIZONTAL_ALIGNMENT_CENTER);
|
|
- ask_update_settings->set_text(warning_message);
|
|
|
|
|
|
+ ask_update_label->set_text(warning_message);
|
|
ask_update_settings->popup_centered(popup_min_size);
|
|
ask_update_settings->popup_centered(popup_min_size);
|
|
return;
|
|
return;
|
|
}
|
|
}
|
|
@@ -651,6 +659,14 @@ void ProjectManager::_open_selected_projects_check_recovery_mode() {
|
|
}
|
|
}
|
|
|
|
|
|
void ProjectManager::_open_selected_projects_with_migration() {
|
|
void ProjectManager::_open_selected_projects_with_migration() {
|
|
|
|
+ if (ask_update_backup->is_pressed() && project_list->get_selected_projects().size() == 1) {
|
|
|
|
+ ask_update_settings->hide();
|
|
|
|
+ ask_update_backup->set_pressed(false);
|
|
|
|
+
|
|
|
|
+ _duplicate_project_with_action(POST_DUPLICATE_ACTION_OPEN);
|
|
|
|
+ return;
|
|
|
|
+ }
|
|
|
|
+
|
|
#ifndef DISABLE_DEPRECATED
|
|
#ifndef DISABLE_DEPRECATED
|
|
if (project_list->get_selected_projects().size() == 1) {
|
|
if (project_list->get_selected_projects().size() == 1) {
|
|
// Only migrate if a single project is opened.
|
|
// Only migrate if a single project is opened.
|
|
@@ -692,6 +708,27 @@ void ProjectManager::_rename_project() {
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+void ProjectManager::_duplicate_project() {
|
|
|
|
+ _duplicate_project_with_action(POST_DUPLICATE_ACTION_NONE);
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+void ProjectManager::_duplicate_project_with_action(PostDuplicateAction p_post_action) {
|
|
|
|
+ Vector<ProjectList::Item> selected_projects = project_list->get_selected_projects();
|
|
|
|
+ if (selected_projects.is_empty()) {
|
|
|
|
+ return;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ post_duplicate_action = p_post_action;
|
|
|
|
+
|
|
|
|
+ const ProjectList::Item &project = selected_projects[0];
|
|
|
|
+
|
|
|
|
+ project_dialog->set_mode(ProjectDialog::MODE_DUPLICATE);
|
|
|
|
+ project_dialog->set_project_name(vformat("%s (%s)", project.project_name, p_post_action == POST_DUPLICATE_ACTION_NONE ? "Copy" : project.project_version));
|
|
|
|
+ project_dialog->set_original_project_path(project.path);
|
|
|
|
+ project_dialog->set_duplicate_can_edit(p_post_action == POST_DUPLICATE_ACTION_NONE);
|
|
|
|
+ project_dialog->show_dialog(false);
|
|
|
|
+}
|
|
|
|
+
|
|
void ProjectManager::_erase_project() {
|
|
void ProjectManager::_erase_project() {
|
|
const HashSet<String> &selected_list = project_list->get_selected_project_keys();
|
|
const HashSet<String> &selected_list = project_list->get_selected_project_keys();
|
|
|
|
|
|
@@ -744,6 +781,7 @@ void ProjectManager::_update_project_buttons() {
|
|
open_btn->set_disabled(empty_selection || is_missing_project_selected);
|
|
open_btn->set_disabled(empty_selection || is_missing_project_selected);
|
|
open_options_btn->set_disabled(empty_selection || is_missing_project_selected);
|
|
open_options_btn->set_disabled(empty_selection || is_missing_project_selected);
|
|
rename_btn->set_disabled(empty_selection || is_missing_project_selected);
|
|
rename_btn->set_disabled(empty_selection || is_missing_project_selected);
|
|
|
|
+ duplicate_btn->set_disabled(empty_selection || is_missing_project_selected);
|
|
manage_tags_btn->set_disabled(empty_selection || is_missing_project_selected || selected_projects.size() > 1);
|
|
manage_tags_btn->set_disabled(empty_selection || is_missing_project_selected || selected_projects.size() > 1);
|
|
run_btn->set_disabled(empty_selection || is_missing_project_selected);
|
|
run_btn->set_disabled(empty_selection || is_missing_project_selected);
|
|
|
|
|
|
@@ -836,6 +874,25 @@ void ProjectManager::_on_project_created(const String &dir, bool edit) {
|
|
project_list->update_dock_menu();
|
|
project_list->update_dock_menu();
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+void ProjectManager::_on_project_duplicated(const String &p_original_path, const String &p_duplicate_path, bool p_edit) {
|
|
|
|
+ if (post_duplicate_action == POST_DUPLICATE_ACTION_NONE) {
|
|
|
|
+ _on_project_created(p_duplicate_path, p_edit);
|
|
|
|
+ } else {
|
|
|
|
+ project_list->add_project(p_duplicate_path, false);
|
|
|
|
+ project_list->save_config();
|
|
|
|
+
|
|
|
|
+ if (post_duplicate_action == POST_DUPLICATE_ACTION_OPEN) {
|
|
|
|
+ _open_selected_projects_with_migration();
|
|
|
|
+ } else if (post_duplicate_action == POST_DUPLICATE_ACTION_FULL_CONVERSION) {
|
|
|
|
+ _full_convert_button_pressed();
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ project_list->update_dock_menu();
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ post_duplicate_action = POST_DUPLICATE_ACTION_NONE;
|
|
|
|
+}
|
|
|
|
+
|
|
void ProjectManager::_on_order_option_changed(int p_idx) {
|
|
void ProjectManager::_on_order_option_changed(int p_idx) {
|
|
if (is_inside_tree()) {
|
|
if (is_inside_tree()) {
|
|
project_list->set_order_option(p_idx);
|
|
project_list->set_order_option(p_idx);
|
|
@@ -1019,6 +1076,14 @@ void ProjectManager::_minor_project_migrate() {
|
|
|
|
|
|
void ProjectManager::_full_convert_button_pressed() {
|
|
void ProjectManager::_full_convert_button_pressed() {
|
|
ask_update_settings->hide();
|
|
ask_update_settings->hide();
|
|
|
|
+
|
|
|
|
+ if (ask_update_backup->is_pressed()) {
|
|
|
|
+ ask_update_backup->set_pressed(false);
|
|
|
|
+
|
|
|
|
+ _duplicate_project_with_action(POST_DUPLICATE_ACTION_FULL_CONVERSION);
|
|
|
|
+ return;
|
|
|
|
+ }
|
|
|
|
+
|
|
ask_full_convert_dialog->popup_centered(Size2i(600.0 * EDSCALE, 0));
|
|
ask_full_convert_dialog->popup_centered(Size2i(600.0 * EDSCALE, 0));
|
|
ask_full_convert_dialog->get_cancel_button()->grab_focus();
|
|
ask_full_convert_dialog->get_cancel_button()->grab_focus();
|
|
}
|
|
}
|
|
@@ -1525,6 +1590,11 @@ ProjectManager::ProjectManager() {
|
|
rename_btn->connect(SceneStringName(pressed), callable_mp(this, &ProjectManager::_rename_project));
|
|
rename_btn->connect(SceneStringName(pressed), callable_mp(this, &ProjectManager::_rename_project));
|
|
project_list_sidebar->add_child(rename_btn);
|
|
project_list_sidebar->add_child(rename_btn);
|
|
|
|
|
|
|
|
+ duplicate_btn = memnew(Button);
|
|
|
|
+ duplicate_btn->set_text(TTRC("Duplicate"));
|
|
|
|
+ duplicate_btn->connect(SceneStringName(pressed), callable_mp(this, &ProjectManager::_duplicate_project));
|
|
|
|
+ project_list_sidebar->add_child(duplicate_btn);
|
|
|
|
+
|
|
manage_tags_btn = memnew(Button);
|
|
manage_tags_btn = memnew(Button);
|
|
manage_tags_btn->set_text(TTRC("Manage Tags"));
|
|
manage_tags_btn->set_text(TTRC("Manage Tags"));
|
|
manage_tags_btn->set_shortcut(ED_SHORTCUT("project_manager/project_tags", TTRC("Manage Tags"), KeyModifierMask::CMD_OR_CTRL | Key::T));
|
|
manage_tags_btn->set_shortcut(ED_SHORTCUT("project_manager/project_tags", TTRC("Manage Tags"), KeyModifierMask::CMD_OR_CTRL | Key::T));
|
|
@@ -1636,7 +1706,18 @@ ProjectManager::ProjectManager() {
|
|
add_child(open_recovery_mode_ask);
|
|
add_child(open_recovery_mode_ask);
|
|
|
|
|
|
ask_update_settings = memnew(ConfirmationDialog);
|
|
ask_update_settings = memnew(ConfirmationDialog);
|
|
- ask_update_settings->set_autowrap(true);
|
|
|
|
|
|
+ add_child(ask_update_settings);
|
|
|
|
+ ask_update_vb = memnew(VBoxContainer);
|
|
|
|
+ ask_update_settings->add_child(ask_update_vb);
|
|
|
|
+ ask_update_label = memnew(Label);
|
|
|
|
+ ask_update_label->set_custom_minimum_size(Size2(300 * EDSCALE, 1));
|
|
|
|
+ ask_update_label->set_autowrap_mode(TextServer::AUTOWRAP_WORD);
|
|
|
|
+ ask_update_label->set_v_size_flags(SIZE_EXPAND_FILL);
|
|
|
|
+ ask_update_vb->add_child(ask_update_label);
|
|
|
|
+ ask_update_backup = memnew(CheckBox);
|
|
|
|
+ ask_update_backup->set_text(TTRC("Backup project first"));
|
|
|
|
+ ask_update_backup->set_h_size_flags(SIZE_SHRINK_CENTER);
|
|
|
|
+ ask_update_vb->add_child(ask_update_backup);
|
|
ask_update_settings->get_ok_button()->connect(SceneStringName(pressed), callable_mp(this, &ProjectManager::_open_selected_projects_with_migration));
|
|
ask_update_settings->get_ok_button()->connect(SceneStringName(pressed), callable_mp(this, &ProjectManager::_open_selected_projects_with_migration));
|
|
int ed_swap_cancel_ok = EDITOR_GET("interface/editor/accept_dialog_cancel_ok_buttons");
|
|
int ed_swap_cancel_ok = EDITOR_GET("interface/editor/accept_dialog_cancel_ok_buttons");
|
|
if (ed_swap_cancel_ok == 0) {
|
|
if (ed_swap_cancel_ok == 0) {
|
|
@@ -1644,7 +1725,6 @@ ProjectManager::ProjectManager() {
|
|
}
|
|
}
|
|
full_convert_button = ask_update_settings->add_button(TTRC("Convert Full Project"), ed_swap_cancel_ok != 2);
|
|
full_convert_button = ask_update_settings->add_button(TTRC("Convert Full Project"), ed_swap_cancel_ok != 2);
|
|
full_convert_button->connect(SceneStringName(pressed), callable_mp(this, &ProjectManager::_full_convert_button_pressed));
|
|
full_convert_button->connect(SceneStringName(pressed), callable_mp(this, &ProjectManager::_full_convert_button_pressed));
|
|
- add_child(ask_update_settings);
|
|
|
|
|
|
|
|
ask_full_convert_dialog = memnew(ConfirmationDialog);
|
|
ask_full_convert_dialog = memnew(ConfirmationDialog);
|
|
ask_full_convert_dialog->set_autowrap(true);
|
|
ask_full_convert_dialog->set_autowrap(true);
|
|
@@ -1655,6 +1735,7 @@ ProjectManager::ProjectManager() {
|
|
project_dialog = memnew(ProjectDialog);
|
|
project_dialog = memnew(ProjectDialog);
|
|
project_dialog->connect("projects_updated", callable_mp(this, &ProjectManager::_on_projects_updated));
|
|
project_dialog->connect("projects_updated", callable_mp(this, &ProjectManager::_on_projects_updated));
|
|
project_dialog->connect("project_created", callable_mp(this, &ProjectManager::_on_project_created));
|
|
project_dialog->connect("project_created", callable_mp(this, &ProjectManager::_on_project_created));
|
|
|
|
+ project_dialog->connect("project_duplicated", callable_mp(this, &ProjectManager::_on_project_duplicated));
|
|
add_child(project_dialog);
|
|
add_child(project_dialog);
|
|
|
|
|
|
error_dialog = memnew(AcceptDialog);
|
|
error_dialog = memnew(AcceptDialog);
|