Merge pull request #111528 from Meorge/feat/project-manager-upgrade

Depict version discrepancies in Project Manager
This commit is contained in:
Thaddeus Crews 2026-03-06 12:40:02 -06:00
commit a209e26690
No known key found for this signature in database
GPG key ID: 8C6E5FEB5FC03CCC
6 changed files with 95 additions and 5 deletions

View file

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" xml:space="preserve" width="16" height="16" fill-rule="evenodd" stroke-linejoin="round" stroke-miterlimit="2" clip-rule="evenodd"><path fill="none" d="M0 0H16V16H0z"/><path fill="none" stroke="#FFDD65" stroke-linecap="round" stroke-width="2.8" d="M 2.4,5.4 8,11 13.6,5.4"/></svg>

After

Width:  |  Height:  |  Size: 320 B

View file

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" xml:space="preserve" width="16" height="16" fill-rule="evenodd" stroke-linejoin="round" stroke-miterlimit="2" clip-rule="evenodd"><path fill="none" d="M0 0H16V16H0z"/><path fill="none" stroke="#FFDD65" stroke-linecap="round" stroke-width="2.8" d="M2.4 8.4 8 14 13.6 8.4M2.4 1.8350515l5.6 5.6 5.6-5.6"/></svg>

After

Width:  |  Height:  |  Size: 349 B

View file

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" xml:space="preserve" width="16" height="16" fill-rule="evenodd" stroke-linejoin="round" stroke-miterlimit="2" clip-rule="evenodd"><path fill="none" d="M0 0H16V16H0z"/><path fill="none" stroke="#699CE8" stroke-linecap="round" stroke-width="2.8" d="M 2.4,9.6 8,4 13.6,9.6"/></svg>

After

Width:  |  Height:  |  Size: 319 B

View file

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" xml:space="preserve" width="16" height="16" fill-rule="evenodd" stroke-linejoin="round" stroke-miterlimit="2" clip-rule="evenodd"><path fill="none" d="M0 0H16V16H0z"/><path fill="none" stroke="#699CE8" stroke-linecap="round" stroke-width="2.8" d="M2.4 7.599999 8 2 13.6 7.599999M2.4 14.164948l5.6-5.6 5.6 5.6"/></svg>

After

Width:  |  Height:  |  Size: 358 B

View file

@ -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");

View file

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