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();