diff --git a/editor/icons/ProjectDowngrade.svg b/editor/icons/ProjectDowngrade.svg
new file mode 100644
index 0000000000..34abaf97bc
--- /dev/null
+++ b/editor/icons/ProjectDowngrade.svg
@@ -0,0 +1 @@
+
diff --git a/editor/icons/ProjectDowngradeMajor.svg b/editor/icons/ProjectDowngradeMajor.svg
new file mode 100644
index 0000000000..dc59e033ae
--- /dev/null
+++ b/editor/icons/ProjectDowngradeMajor.svg
@@ -0,0 +1 @@
+
diff --git a/editor/icons/ProjectUpgrade.svg b/editor/icons/ProjectUpgrade.svg
new file mode 100644
index 0000000000..15e3dcca34
--- /dev/null
+++ b/editor/icons/ProjectUpgrade.svg
@@ -0,0 +1 @@
+
diff --git a/editor/icons/ProjectUpgradeMajor.svg b/editor/icons/ProjectUpgradeMajor.svg
new file mode 100644
index 0000000000..c37c629780
--- /dev/null
+++ b/editor/icons/ProjectUpgradeMajor.svg
@@ -0,0 +1 @@
+
diff --git a/editor/project_manager/project_list.cpp b/editor/project_manager/project_list.cpp
index bbbe0f537b..dd628ae511 100644
--- a/editor/project_manager/project_list.cpp
+++ b/editor/project_manager/project_list.cpp
@@ -72,6 +72,24 @@ void ProjectListItemControl::_notification(int p_what) {
project_title->end_bulk_theme_override();
project_path->add_theme_color_override(SceneStringName(font_color), get_theme_color(SceneStringName(font_color), SNAME("ProjectList")));
+
+ switch (version_match_type) {
+ case VersionMatchType::PROJECT_USES_OLDER_MAJOR:
+ project_different_version->set_texture(get_editor_theme_icon(SNAME("ProjectUpgradeMajor")));
+ break;
+ case VersionMatchType::PROJECT_USES_OLDER_MINOR:
+ project_different_version->set_texture(get_editor_theme_icon(SNAME("ProjectUpgrade")));
+ break;
+ case VersionMatchType::PROJECT_USES_NEWER_MAJOR:
+ project_different_version->set_texture(get_editor_theme_icon(SNAME("ProjectDowngradeMajor")));
+ break;
+ case VersionMatchType::PROJECT_USES_NEWER_MINOR:
+ project_different_version->set_texture(get_editor_theme_icon(SNAME("ProjectDowngrade")));
+ break;
+ default:
+ break;
+ }
+
project_unsupported_features->set_texture(get_editor_theme_icon(SNAME("NodeWarning")));
favorite_focus_color = get_theme_color(SNAME("accent_color"), EditorStringName(Editor));
@@ -268,6 +286,7 @@ void ProjectListItemControl::set_project_version(const String &p_info) {
void ProjectListItemControl::set_unsupported_features(PackedStringArray p_features) {
if (p_features.size() > 0) {
String tooltip_text = "";
+ bool unknown_version = false;
for (int i = 0; i < p_features.size(); i++) {
if (ProjectList::project_feature_looks_like_version(p_features[i])) {
PackedStringArray project_version_split = p_features[i].split(".");
@@ -276,18 +295,67 @@ void ProjectListItemControl::set_unsupported_features(PackedStringArray p_featur
project_version_major = project_version_split[0].to_int();
project_version_minor = project_version_split[1].to_int();
}
- if (GODOT_VERSION_MAJOR != project_version_major || GODOT_VERSION_MINOR <= project_version_minor) {
- // Don't show a warning if the project was last edited in a previous minor version.
- tooltip_text += TTR("This project was last edited in a different Godot version: ") + p_features[i] + "\n";
+
+ version_match_type = VersionMatchType::PROJECT_USES_SAME;
+ if (project_version_major > GODOT_VERSION_MAJOR) {
+ version_match_type = VersionMatchType::PROJECT_USES_NEWER_MAJOR;
+ } else if (project_version_major < GODOT_VERSION_MAJOR) {
+ version_match_type = VersionMatchType::PROJECT_USES_OLDER_MAJOR;
+ } else {
+ // Project is same major version.
+ // Is it the same minor version, or an upgrade or downgrade?
+ if (project_version_minor > GODOT_VERSION_MINOR) {
+ version_match_type = VersionMatchType::PROJECT_USES_NEWER_MINOR;
+ } else if (project_version_minor < GODOT_VERSION_MINOR) {
+ version_match_type = VersionMatchType::PROJECT_USES_OLDER_MINOR;
+ }
+ }
+
+ if (version_match_type != VersionMatchType::PROJECT_USES_SAME) {
+ String project_version_tooltip_text = TTR("This project was last edited in a different Godot version: ") + p_features[i] + "\n";
+ if (version_match_type == VersionMatchType::PROJECT_USES_OLDER_MAJOR || version_match_type == VersionMatchType::PROJECT_USES_OLDER_MINOR) {
+ project_version_tooltip_text += vformat(TTR("Opening it will upgrade it to Godot %s.%s."), GODOT_VERSION_MAJOR, GODOT_VERSION_MINOR) + "\n";
+ } else if (version_match_type == VersionMatchType::PROJECT_USES_NEWER_MAJOR || version_match_type == VersionMatchType::PROJECT_USES_NEWER_MINOR) {
+ project_version_tooltip_text += vformat(TTR("Opening it will downgrade it to Godot %s.%s."), GODOT_VERSION_MAJOR, GODOT_VERSION_MINOR) + "\n";
+ project_version_tooltip_text += TTR("Downgrading projects is not recommended.") + "\n";
+ }
+ project_different_version->set_focus_mode(FOCUS_ACCESSIBILITY);
+ project_different_version->set_tooltip_text(project_version_tooltip_text);
+ project_different_version->show();
+ } else {
+ project_different_version->hide();
+ }
+ } else {
+ if (p_features[i] == "3.x") {
+ version_match_type = VersionMatchType::PROJECT_USES_OLDER_MAJOR;
+ String project_version_tooltip_text = TTR("This project was last edited in a different Godot version: ") + p_features[i] + "\n";
+ project_version_tooltip_text += vformat(TTR("Opening it will upgrade it to Godot %s.%s."), GODOT_VERSION_MAJOR, GODOT_VERSION_MINOR) + "\n";
+ project_different_version->set_focus_mode(FOCUS_ACCESSIBILITY);
+ project_different_version->set_tooltip_text(project_version_tooltip_text);
+ project_different_version->show();
+ } else if (p_features[i] == TTR("Unknown version")) {
+ unknown_version = true;
+ project_different_version->hide();
}
- p_features.remove_at(i);
- i--;
}
+
+ p_features.remove_at(i);
+ i--;
+ }
+
+ // This is actually triggered when the project.godot file's config_version
+ // is less than 4, so perhaps it'd be more accurate to say the engine configuration
+ // file's version is not supported...? If the config/features array includes
+ // a proper version number, it will be displayed alongside the "unknown version"
+ // warning otherwise.
+ if (unknown_version) {
+ tooltip_text += TTR("This project uses an unknown version of Godot.") + "\n";
}
if (p_features.size() > 0) {
String unsupported_features_str = String(", ").join(p_features);
tooltip_text += TTR("This project uses features unsupported by the current build:") + "\n" + unsupported_features_str;
}
+
if (tooltip_text.is_empty()) {
return;
}
@@ -296,6 +364,7 @@ void ProjectListItemControl::set_unsupported_features(PackedStringArray p_featur
project_unsupported_features->set_tooltip_text(tooltip_text);
project_unsupported_features->show();
} else {
+ project_different_version->hide();
project_unsupported_features->hide();
}
}
@@ -440,6 +509,12 @@ ProjectListItemControl::ProjectListItemControl() {
path_hb->add_child(project_unsupported_features);
project_unsupported_features->hide();
+ project_different_version = memnew(TextureRect);
+ project_different_version->set_name("ProjectDifferentVersion");
+ project_different_version->set_stretch_mode(TextureRect::STRETCH_KEEP_CENTERED);
+ path_hb->add_child(project_different_version);
+ project_different_version->hide();
+
project_version = memnew(Label);
project_version->set_focus_mode(FOCUS_ACCESSIBILITY);
project_version->set_name("ProjectVersion");
diff --git a/editor/project_manager/project_list.h b/editor/project_manager/project_list.h
index f0c84d35ab..2c8ecac595 100644
--- a/editor/project_manager/project_list.h
+++ b/editor/project_manager/project_list.h
@@ -55,6 +55,7 @@ class ProjectListItemControl : public HBoxContainer {
Label *last_edited_info = nullptr;
Label *project_version = nullptr;
TextureRect *project_unsupported_features = nullptr;
+ TextureRect *project_different_version = nullptr;
HBoxContainer *tag_container = nullptr;
Button *touch_menu_button = nullptr;
@@ -67,6 +68,16 @@ class ProjectListItemControl : public HBoxContainer {
bool is_hovering = false;
bool is_favorite = false;
+ enum class VersionMatchType {
+ PROJECT_USES_SAME,
+ PROJECT_USES_OLDER_MAJOR,
+ PROJECT_USES_OLDER_MINOR,
+ PROJECT_USES_NEWER_MAJOR,
+ PROJECT_USES_NEWER_MINOR,
+ };
+
+ VersionMatchType version_match_type = VersionMatchType::PROJECT_USES_SAME;
+
void _update_favorite_button_focus_color();
void _favorite_button_pressed();
void _explore_button_pressed();