mirror of
https://github.com/Vita3K/Vita3K.git
synced 2026-07-11 01:34:23 +02:00
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:
@@ -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>
|
||||
|
||||
@@ -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
@@ -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>
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
@@ -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")) {
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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::PushStyleColor(ImGuiCol_Text, GUI_COLOR_TEXT);
|
||||
if (ImGui::MenuItem(lang["all"].c_str(), nullptr, app_region == ALL))
|
||||
app_region = ALL;
|
||||
if (ImGui::BeginMenu(lang["by_region"].c_str())) {
|
||||
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_compat_state == ALL_COMPAT_STATE))
|
||||
app_region = AppRegion::ALL, app_compat_state = ALL_COMPAT_STATE;
|
||||
if (ImGui::BeginMenu(lang["by_region"].c_str())) {
|
||||
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,10 +632,16 @@ 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;
|
||||
|
||||
if (is_not_sys_app) {
|
||||
// Filter app by region and type
|
||||
if (is_not_sys_app && app_filter(app.title_id))
|
||||
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()))
|
||||
continue;
|
||||
@@ -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();
|
||||
|
||||
@@ -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" },
|
||||
|
||||
Reference in New Issue
Block a user