gui/home screen: Add app filter by compat state.

compat: fix typo of CompatibilityState enum.
gui: fix day on format dd/mm/yyyy for start screen.
This commit is contained in:
Zangetsu38
2023-04-01 02:32:04 +02:00
committed by Zangetsu
parent a46fd1463f
commit e395624811
13 changed files with 120 additions and 63 deletions
+1
View File
@@ -341,6 +341,7 @@ Do not power off the system or close the application.</warning_saving>
<by_type>By Type</by_type>
<commercial>Commercial</commercial>
<homebrew>Homebrew</homebrew>
<by_compatibility_state>By Compatibility State</by_compatibility_state>
<ver>Ver</ver>
<cat>Cat</cat>
<comp>Comp</comp>
+1
View File
@@ -341,6 +341,7 @@ Do not power off the system or close the application.</warning_saving>
<by_type>By Type</by_type>
<commercial>Commercial</commercial>
<homebrew>Homebrew</homebrew>
<by_compatibility_state>By Compatibility State</by_compatibility_state>
<ver>Ver</ver>
<cat>Cat</cat>
<comp>Comp</comp>
+20
View File
@@ -282,6 +282,26 @@ Ne pas éteindre le système, ni fermer l'application.</warning_saving>
<data_delete>Données à supprimer :</data_delete>
</game_data>
<home_screen>
<filter>Filtre</filter>
<sort_app>Trier les applications par</sort_app>
<all>Toutes</all>
<by_region>Par région</by_region>
<usa>USA</usa>
<europe>Europe</europe>
<japan>Japon</japan>
<asia>Asie</asia>
<by_type>Par type</by_type>
<commercial>Commercial</commercial>
<homebrew>Homebrew</homebrew>
<by_compatibility_state>Par état de compatibilité</by_compatibility_state>
<ver>Ver</ver>
<cat>Cat</cat>
<comp>Comp</comp>
<last_time>Dernière fois</last_time>
<refresh>Rafraîchir</refresh>
</home_screen>
<indicator>
<app_added_home>L'application a été ajoutée à l'écran d'accueil.</app_added_home>
<delete_all>Supprimer tout</delete_all>
+1
View File
@@ -336,6 +336,7 @@ SDL2に対応したコントローラーを接続してください。</not_conn
<by_type>種類</by_type>
<commercial>商用ゲーム</commercial>
<homebrew>自作ゲーム</homebrew>
<by_compatibility_state>互換性状態別</by_compatibility_state>
<ver>Ver</ver>
<cat>カテゴリー</cat>
<comp>互換性</comp>
+17 -17
View File
@@ -24,19 +24,19 @@
namespace compat {
enum CompatibilityState {
Unknown = -1,
Nothing,
Bootable,
Intro,
Menu,
Ingame_Less,
Ingame_More,
Playable,
UNKNOWN = -1,
NOTHING,
BOOTABLE,
INTRO,
MENU,
INGAME_LESS,
INGAME_MORE,
PLAYABLE,
};
struct Compatibility {
uint32_t issue_id;
CompatibilityState state = Unknown;
CompatibilityState state = UNKNOWN;
time_t updated_at;
};
@@ -44,14 +44,14 @@ struct CompatState {
bool compat_db_loaded = false;
std::map<std::string, Compatibility> app_compat_db;
std::map<CompatibilityState, ImVec4> compat_color{
{ Unknown, ImVec4(0.54f, 0.54f, 0.54f, 1.f) },
{ Nothing, ImVec4(1.00f, 0.00f, 0.00f, 1.f) }, // #ff0000
{ Bootable, ImVec4(0.39f, 0.12f, 0.62f, 1.f) }, // #621fa5
{ Intro, ImVec4(0.77f, 0.08f, 0.52f, 1.f) }, // #c71585
{ Menu, ImVec4(0.11f, 0.46f, 0.85f, 1.f) }, // #1d76db
{ Ingame_Less, ImVec4(0.88f, 0.54f, 0.12f, 1.f) }, // #e08a1e
{ Ingame_More, ImVec4(1.00f, 0.84f, 0.00f, 1.f) }, // #ffd700
{ Playable, ImVec4(0.05f, 0.54f, 0.09f, 1.f) }, // #0e8a16
{ UNKNOWN, ImVec4(0.54f, 0.54f, 0.54f, 1.f) },
{ NOTHING, ImVec4(1.00f, 0.00f, 0.00f, 1.f) }, // #ff0000
{ BOOTABLE, ImVec4(0.39f, 0.12f, 0.62f, 1.f) }, // #621fa5
{ INTRO, ImVec4(0.77f, 0.08f, 0.52f, 1.f) }, // #c71585
{ MENU, ImVec4(0.11f, 0.46f, 0.85f, 1.f) }, // #1d76db
{ INGAME_LESS, ImVec4(0.88f, 0.54f, 0.12f, 1.f) }, // #e08a1e
{ INGAME_MORE, ImVec4(1.00f, 0.84f, 0.00f, 1.f) }, // #ffd700
{ PLAYABLE, ImVec4(0.05f, 0.54f, 0.09f, 1.f) }, // #0e8a16
};
};
+10 -10
View File
@@ -80,19 +80,19 @@ bool load_compat_app_db(GuiState &gui, EmuEnvState &emuenv) {
continue;
}
auto state = CompatibilityState::Unknown;
auto state = CompatibilityState::UNKNOWN;
const auto labels = app.child("labels");
if (!labels.empty()) {
for (const auto &label : labels) {
const auto label_id = static_cast<LabelIdState>(label.text().as_uint());
switch (label_id) {
case LabelIdState::Nothing: state = Nothing; break;
case LabelIdState::Bootable: state = Bootable; break;
case LabelIdState::Intro: state = Intro; break;
case LabelIdState::Menu: state = Menu; break;
case LabelIdState::Ingame_Less: state = Ingame_Less; break;
case LabelIdState::Ingame_More: state = Ingame_More; break;
case LabelIdState::Playable: state = Playable; break;
case LabelIdState::Nothing: state = NOTHING; break;
case LabelIdState::Bootable: state = BOOTABLE; break;
case LabelIdState::Intro: state = INTRO; break;
case LabelIdState::Menu: state = MENU; break;
case LabelIdState::Ingame_Less: state = INGAME_LESS; break;
case LabelIdState::Ingame_More: state = INGAME_MORE; break;
case LabelIdState::Playable: state = PLAYABLE; break;
default: break;
}
}
@@ -100,7 +100,7 @@ bool load_compat_app_db(GuiState &gui, EmuEnvState &emuenv) {
const auto updated_at = app.child("updated_at").text().as_llong();
// Check if app missing a status label
if (state == Unknown)
if (state == UNKNOWN)
LOG_WARN("App with title ID {} has an issue but no status label. Please check GitHub issue {} and request a status label to be added.", title_id, issue_id);
// Check if app already exists in compatibility database
@@ -112,7 +112,7 @@ bool load_compat_app_db(GuiState &gui, EmuEnvState &emuenv) {
// Update compatibility status of all user apps
for (auto &app : gui.app_selector.user_apps)
app.compat = gui.compat.app_compat_db.contains(app.title_id) ? gui.compat.app_compat_db[app.title_id].state : CompatibilityState::Unknown;
app.compat = gui.compat.app_compat_db.contains(app.title_id) ? gui.compat.app_compat_db[app.title_id].state : CompatibilityState::UNKNOWN;
return !gui.compat.app_compat_db.empty();
}
+2 -2
View File
@@ -297,9 +297,9 @@ void draw_app_context_menu(GuiState &gui, EmuEnvState &emuenv, const std::string
const auto is_commercial_app = title_id.find("PCS") != std::string::npos;
const auto has_state_report = gui.compat.compat_db_loaded ? gui.compat.app_compat_db.contains(title_id) : false;
const auto compat_state = has_state_report ? gui.compat.app_compat_db[title_id].state : compat::Unknown;
const auto compat_state = has_state_report ? gui.compat.app_compat_db[title_id].state : compat::UNKNOWN;
const auto compat_state_color = gui.compat.compat_color[compat_state];
const auto compat_state_str = has_state_report ? lang_compat.states[compat_state] : lang_compat.states[compat::Unknown];
const auto compat_state_str = has_state_report ? lang_compat.states[compat_state] : lang_compat.states[compat::UNKNOWN];
// App Context Menu
if (ImGui::BeginPopupContextItem("##app_context_menu")) {
+5 -6
View File
@@ -638,24 +638,23 @@ std::map<DateTime, std::string> get_date_time(GuiState &gui, EmuEnvState &emuenv
const auto days_str = gui.lang.common.mday[date_time.tm_mday];
const auto year = date_time.tm_year + 1900;
const auto month = date_time.tm_mon + 1;
const auto days = date_time.tm_mday;
const auto day = date_time.tm_mday;
switch (emuenv.cfg.sys_date_format) {
case SCE_SYSTEM_PARAM_DATE_FORMAT_YYYYMMDD:
date_time_str[DateTime::DATE_DETAIL] = fmt::format("{} {} ({})", month_str, days_str, day_str);
date_time_str[DateTime::DATE_MINI] = fmt::format("{}/{}/{}", year, month, days);
date_time_str[DateTime::DATE_MINI] = fmt::format("{}/{}/{}", year, month, day);
break;
case SCE_SYSTEM_PARAM_DATE_FORMAT_DDMMYYYY: {
const auto small_month_str = gui.lang.common.small_ymonth[date_time.tm_mon];
const auto small_days_str = gui.lang.common.small_mday[date_time.tm_mon];
const auto small_days_str = gui.lang.common.small_mday[day];
date_time_str[DateTime::DATE_DETAIL] = fmt::format("{} {} ({})", small_days_str, small_month_str, day_str);
date_time_str[DateTime::DATE_MINI] = fmt::format("{}/{}/{}", days, month, year);
date_time_str[DateTime::DATE_MINI] = fmt::format("{}/{}/{}", day, month, year);
break;
}
case SCE_SYSTEM_PARAM_DATE_FORMAT_MMDDYYYY:
date_time_str[DateTime::DATE_DETAIL] = fmt::format("{} {} ({})", month_str, days_str, day_str);
date_time_str[DateTime::DATE_MINI] = fmt::format("{}/{}/{}", month, days, year);
date_time_str[DateTime::DATE_MINI] = fmt::format("{}/{}/{}", month, day, year);
break;
default: break;
}
}
const auto is_afternoon = date_time.tm_hour > 12;
+50 -16
View File
@@ -242,43 +242,48 @@ enum AppRegion {
HOMEBREW,
};
constexpr compat::CompatibilityState ALL_COMPAT_STATE = static_cast<compat::CompatibilityState>(7);
static AppRegion app_region = ALL;
static compat::CompatibilityState app_compat_state = ALL_COMPAT_STATE;
static bool app_filter(const std::string &app) {
const auto filter_app_region = [&](const std::vector<std::string> &app_region) {
const auto app_region_index = std::find_if(app_region.begin(), app_region.end(), [&](const std::string &a) {
const auto filter_app = [&](const std::vector<std::string> &app_region) {
const auto app_index = std::find_if(app_region.begin(), app_region.end(), [&](const std::string &a) {
return app.find(a) != std::string::npos;
});
return app_region_index == app_region.end();
return app_index == app_region.end();
};
switch (app_region) {
case ALL:
break;
case USA:
if (filter_app_region({ "PCSA", "PCSE" }))
if (filter_app({ "PCSA", "PCSE" }))
return true;
break;
case EURO:
if (filter_app_region({ "PCSF", "PCSB" }))
if (filter_app({ "PCSF", "PCSB" }))
return true;
break;
case JAPAN:
if (filter_app_region({ "PCSC", "PCSG" }))
if (filter_app({ "PCSC", "PCSG" }))
return true;
break;
case ASIA:
if (filter_app_region({ "PCSD", "PCSH" }))
if (filter_app({ "PCSD", "PCSH" }))
return true;
break;
case COMMERCIAL:
if (filter_app_region({ "PCS" }))
if (filter_app({ "PCS" }))
return true;
break;
case HOMEBREW:
if (!filter_app_region({ "PCS" }))
if (!filter_app({ "PCS" }))
return true;
break;
}
return false;
}
@@ -528,11 +533,11 @@ void draw_home_screen(GuiState &gui, EmuEnvState &emuenv) {
}
}
if (ImGui::BeginPopup("app_filter")) {
ImGui::SetWindowFontScale(1.1f * VIEWPORT_RES_SCALE.x);
ImGui::PushStyleColor(ImGuiCol_Text, GUI_COLOR_TEXT);
if (ImGui::MenuItem(lang["all"].c_str(), nullptr, app_region == ALL))
app_region = ALL;
if (ImGui::MenuItem(lang["all"].c_str(), nullptr, app_region == ALL && app_compat_state == ALL_COMPAT_STATE))
app_region = AppRegion::ALL, app_compat_state = ALL_COMPAT_STATE;
if (ImGui::BeginMenu(lang["by_region"].c_str())) {
ImGui::SetWindowFontScale(1.1f * VIEWPORT_RES_SCALE.x);
if (ImGui::MenuItem(lang["usa"].c_str(), nullptr, app_region == USA))
app_region = USA;
if (ImGui::MenuItem(lang["europe"].c_str(), nullptr, app_region == EURO))
@@ -550,6 +555,29 @@ void draw_home_screen(GuiState &gui, EmuEnvState &emuenv) {
app_region = HOMEBREW;
ImGui::EndMenu();
}
if (ImGui::BeginMenu(lang["by_compatibility_state"].c_str())) {
if (ImGui::MenuItem(lang["all"].c_str(), nullptr, app_compat_state == ALL_COMPAT_STATE))
app_compat_state = ALL_COMPAT_STATE;
auto lang_compat = gui.lang.compatibility.states;
if (ImGui::MenuItem(lang_compat[compat::UNKNOWN].c_str(), nullptr, app_compat_state == compat::UNKNOWN))
app_compat_state = compat::UNKNOWN;
if (ImGui::MenuItem(lang_compat[compat::NOTHING].c_str(), nullptr, app_compat_state == compat::NOTHING))
app_compat_state = compat::NOTHING;
if (ImGui::MenuItem(lang_compat[compat::BOOTABLE].c_str(), nullptr, app_compat_state == compat::BOOTABLE))
app_compat_state = compat::BOOTABLE;
if (ImGui::MenuItem(lang_compat[compat::INTRO].c_str(), nullptr, app_compat_state == compat::INTRO))
app_compat_state = compat::INTRO;
if (ImGui::MenuItem(lang_compat[compat::MENU].c_str(), nullptr, app_compat_state == compat::MENU))
app_compat_state = compat::MENU;
if (ImGui::MenuItem(lang_compat[compat::INGAME_LESS].c_str(), nullptr, app_compat_state == compat::INGAME_LESS))
app_compat_state = compat::INGAME_LESS;
if (ImGui::MenuItem(lang_compat[compat::INGAME_MORE].c_str(), nullptr, app_compat_state == compat::INGAME_MORE))
app_compat_state = compat::INGAME_MORE;
if (ImGui::MenuItem(lang_compat[compat::PLAYABLE].c_str(), nullptr, app_compat_state == compat::PLAYABLE))
app_compat_state = compat::PLAYABLE;
ImGui::EndMenu();
}
ImGui::PopStyleColor();
ImGui::EndPopup();
}
@@ -604,9 +632,15 @@ void draw_home_screen(GuiState &gui, EmuEnvState &emuenv) {
bool selected = false;
const auto is_not_sys_app = app.title_id.find("NPXS") == std::string::npos;
// Filter app by region and type
if (is_not_sys_app && app_filter(app.title_id))
continue;
if (is_not_sys_app) {
// Filter app by region and type
if (app_filter(app.title_id))
continue;
// Filter commercial app by compatibility
if ((app_region != HOMEBREW) && (app_compat_state != ALL_COMPAT_STATE) && (app_compat_state != app.compat))
continue;
}
// Search app by title or title id
if (!gui.app_search_bar.PassFilter(app.title.c_str()) && !gui.app_search_bar.PassFilter(app.title_id.c_str()))
@@ -650,7 +684,7 @@ void draw_home_screen(GuiState &gui, EmuEnvState &emuenv) {
// Draw the compatibility badge for commercial apps when they are within the visible area.
if (element_is_within_visible_area && (app.title_id.find("PCS") != std::string::npos)) {
const auto compat_state = (gui.compat.compat_db_loaded ? gui.compat.app_compat_db.contains(app.title_id) : false) ? gui.compat.app_compat_db[app.title_id].state : compat::Unknown;
const auto compat_state = (gui.compat.compat_db_loaded ? gui.compat.app_compat_db.contains(app.title_id) : false) ? gui.compat.app_compat_db[app.title_id].state : compat::UNKNOWN;
const auto compat_state_vec4 = gui.compat.compat_color[compat_state];
const ImU32 compat_state_color = IM_COL32((int)(compat_state_vec4.x * 255.0f), (int)(compat_state_vec4.y * 255.0f), (int)(compat_state_vec4.z * 255.0f), (int)(compat_state_vec4.w * 255.0f));
const auto current_pos = ImGui::GetCursorPos();
+9 -8
View File
@@ -175,14 +175,14 @@ struct LangState {
struct Compatibility {
std::string name = "Compatibility";
std::map<compat::CompatibilityState, std::string> states = {
{ compat::Unknown, "Unknown" },
{ compat::Nothing, "Nothing" },
{ compat::Bootable, "Bootable" },
{ compat::Intro, "Intro" },
{ compat::Menu, "Menu" },
{ compat::Ingame_Less, "Ingame -" },
{ compat::Ingame_More, "Ingame +" },
{ compat::Playable, "Playable" }
{ compat::UNKNOWN, "Unknown" },
{ compat::NOTHING, "Nothing" },
{ compat::BOOTABLE, "Bootable" },
{ compat::INTRO, "Intro" },
{ compat::MENU, "Menu" },
{ compat::INGAME_LESS, "Ingame -" },
{ compat::INGAME_MORE, "Ingame +" },
{ compat::PLAYABLE, "Playable" }
};
};
Compatibility compatibility;
@@ -272,6 +272,7 @@ struct LangState {
{ "by_type", "By Type" },
{ "commercial", "Commercial" },
{ "homebrew", "Homebrew" },
{ "by_compatibility_state", "By Compatibility State" },
{ "ver", "Ver" },
{ "cat", "Cat" },
{ "comp", "Comp" },