From 82a217570c5006fa6eac97d2b898526133ffc246 Mon Sep 17 00:00:00 2001 From: Silent Date: Thu, 18 Feb 2021 00:13:07 +0100 Subject: [PATCH 1/3] Save State UI: Add legend showing hotkeys --- .../save_state_selector_ui.cpp | 115 +++++++++++++----- 1 file changed, 84 insertions(+), 31 deletions(-) diff --git a/src/frontend-common/save_state_selector_ui.cpp b/src/frontend-common/save_state_selector_ui.cpp index da261831d..c0a274181 100644 --- a/src/frontend-common/save_state_selector_ui.cpp +++ b/src/frontend-common/save_state_selector_ui.cpp @@ -187,52 +187,105 @@ void SaveStateSelectorUI::Draw() ImGui::PushStyleVar(ImGuiStyleVar_WindowRounding, rounding); if (ImGui::Begin("##save_state_selector", nullptr, - ImGuiWindowFlags_NoFocusOnAppearing | ImGuiWindowFlags_NoInputs | ImGuiWindowFlags_NoTitleBar)) + ImGuiWindowFlags_NoFocusOnAppearing | ImGuiWindowFlags_NoInputs | ImGuiWindowFlags_NoTitleBar | + ImGuiWindowFlags_NoScrollbar)) { + // Leave 2 lines for the legend + const float legend_margin = ImGui::GetFontSize() * 2.0f + ImGui::GetStyle().ItemSpacing.y * 3.0f; const float padding = 10.0f * framebuffer_scale; - const ImVec2 image_size = ImVec2(128.0f * framebuffer_scale, (128.0f / (4.0f / 3.0f)) * framebuffer_scale); - const float item_height = image_size.y + padding * 2.0f; - const float text_indent = image_size.x + padding + padding; - for (size_t i = 0; i < m_slots.size(); i++) + ImGui::BeginChild("##item_list", ImVec2(0, -legend_margin), false, + ImGuiWindowFlags_NoFocusOnAppearing | ImGuiWindowFlags_NoInputs | ImGuiWindowFlags_NoTitleBar); { - const ListEntry& entry = m_slots[i]; - const float y_start = item_height * static_cast(i); + const ImVec2 image_size = ImVec2(128.0f * framebuffer_scale, (128.0f / (4.0f / 3.0f)) * framebuffer_scale); + const float item_height = image_size.y + padding * 2.0f; + const float text_indent = image_size.x + padding + padding; - if (i == m_current_selection) + for (size_t i = 0; i < m_slots.size(); i++) { - ImGui::SetCursorPosY(y_start); - ImGui::SetScrollHereY(); + const ListEntry& entry = m_slots[i]; + const float y_start = item_height * static_cast(i); - const ImVec2 p_start(ImGui::GetCursorScreenPos()); - const ImVec2 p_end(p_start.x + window_width, p_start.y + item_height); - ImGui::GetWindowDrawList()->AddRectFilled(p_start, p_end, ImColor(0.22f, 0.30f, 0.34f, 0.9f), rounding); - } + if (i == m_current_selection) + { + ImGui::SetCursorPosY(y_start); + ImGui::SetScrollHereY(); + + const ImVec2 p_start(ImGui::GetCursorScreenPos()); + const ImVec2 p_end(p_start.x + window_width, p_start.y + item_height); + ImGui::GetWindowDrawList()->AddRectFilled(p_start, p_end, ImColor(0.22f, 0.30f, 0.34f, 0.9f), rounding); + } + + if (entry.preview_texture) + { + ImGui::SetCursorPosY(y_start + padding); + ImGui::SetCursorPosX(padding); + ImGui::Image(reinterpret_cast(entry.preview_texture->GetHandle()), image_size); + } - if (entry.preview_texture) - { ImGui::SetCursorPosY(y_start + padding); - ImGui::SetCursorPosX(padding); - ImGui::Image(reinterpret_cast(entry.preview_texture->GetHandle()), image_size); + + ImGui::Indent(text_indent); + + ImGui::Text("%s Slot %d", + entry.global ? "Global" : (entry.game_code.empty() ? "Game" : entry.game_code.c_str()), entry.slot); + ImGui::TextUnformatted(entry.title.c_str()); + ImGui::TextUnformatted(entry.formatted_timestamp.c_str()); + ImGui::TextUnformatted(entry.path.c_str()); + + ImGui::Unindent(text_indent); } - - ImGui::SetCursorPosY(y_start + padding); - - ImGui::Indent(text_indent); - - ImGui::Text("%s Slot %d", entry.global ? "Global" : (entry.game_code.empty() ? "Game" : entry.game_code.c_str()), - entry.slot); - ImGui::TextUnformatted(entry.title.c_str()); - ImGui::TextUnformatted(entry.formatted_timestamp.c_str()); - ImGui::TextUnformatted(entry.path.c_str()); - - ImGui::Unindent(text_indent); } + ImGui::EndChild(); + + ImGui::BeginChild("##legend", ImVec2(0, 0), false, + ImGuiWindowFlags_NoFocusOnAppearing | ImGuiWindowFlags_NoInputs | ImGuiWindowFlags_NoTitleBar | + ImGuiWindowFlags_NoScrollbar); + { + ImGui::SetCursorPosX(padding); + ImGui::BeginTable("table", 2); + + auto strip_device_name = [](std::string str) { + std::string result; + + auto slash_pos = str.find_first_of('/'); + if (slash_pos != str.npos) + { + result = str.substr(slash_pos + 1); + } + else + { + result = std::move(str); + } + return result; + }; + + const std::string load_savestate_hotkey = + strip_device_name(m_host_interface->GetStringSettingValue("Hotkeys", "LoadSelectedSaveState")); + const std::string save_savestate_hotkey = + strip_device_name(m_host_interface->GetStringSettingValue("Hotkeys", "SaveSelectedSaveState")); + const std::string next_savestate_hotkey = + strip_device_name(m_host_interface->GetStringSettingValue("Hotkeys", "SelectNextSaveStateSlot")); + const std::string prev_savestate_hotkey = + strip_device_name(m_host_interface->GetStringSettingValue("Hotkeys", "SelectPreviousSaveStateSlot")); + + ImGui::TableNextColumn(); + ImGui::Text("%s - %s", load_savestate_hotkey.c_str(), "Load"); + ImGui::TableNextColumn(); + ImGui::Text("%s - %s", prev_savestate_hotkey.c_str(), "Select Previous"); + ImGui::TableNextColumn(); + ImGui::Text("%s - %s", save_savestate_hotkey.c_str(), "Save"); + ImGui::TableNextColumn(); + ImGui::Text("%s - %s", next_savestate_hotkey.c_str(), "Select Next"); + + ImGui::EndTable(); + } + ImGui::EndChild(); } + ImGui::End(); ImGui::PopStyleVar(2); ImGui::PopStyleColor(); - ImGui::End(); // auto-close if (m_open_timer.GetTimeSeconds() >= m_open_time) From e361b9f0126efe366ca16fc3a8c763e3740ddc61 Mon Sep 17 00:00:00 2001 From: Silent Date: Fri, 19 Feb 2021 20:14:33 +0100 Subject: [PATCH 2/3] Save State UI: Make the widget translatable --- .../save_state_selector_ui.cpp | 29 ++++++++++++++----- 1 file changed, 22 insertions(+), 7 deletions(-) diff --git a/src/frontend-common/save_state_selector_ui.cpp b/src/frontend-common/save_state_selector_ui.cpp index c0a274181..471e3c542 100644 --- a/src/frontend-common/save_state_selector_ui.cpp +++ b/src/frontend-common/save_state_selector_ui.cpp @@ -158,7 +158,7 @@ std::pair SaveStateSelectorUI::GetSlotTypeFromSelection(u32 selection void SaveStateSelectorUI::InitializePlaceholderListEntry(ListEntry* li, s32 slot, bool global) { - li->title = "No Save State"; + li->title = m_host_interface->TranslateStdString("SaveStateSelectorUI", "No Save State"); std::string().swap(li->game_code); std::string().swap(li->path); std::string().swap(li->formatted_timestamp); @@ -227,8 +227,19 @@ void SaveStateSelectorUI::Draw() ImGui::Indent(text_indent); - ImGui::Text("%s Slot %d", - entry.global ? "Global" : (entry.game_code.empty() ? "Game" : entry.game_code.c_str()), entry.slot); + if (entry.global) + { + ImGui::Text(m_host_interface->TranslateString("SaveStateSelectorUI", "Global Slot %d"), entry.slot); + } + else if (entry.game_code.empty()) + { + ImGui::Text(m_host_interface->TranslateString("SaveStateSelectorUI", "Gane Slot %d"), entry.slot); + } + else + { + ImGui::Text(m_host_interface->TranslateString("SaveStateSelectorUI", "%s Slot %d"), entry.game_code.c_str(), + entry.slot); + } ImGui::TextUnformatted(entry.title.c_str()); ImGui::TextUnformatted(entry.formatted_timestamp.c_str()); ImGui::TextUnformatted(entry.path.c_str()); @@ -270,13 +281,17 @@ void SaveStateSelectorUI::Draw() strip_device_name(m_host_interface->GetStringSettingValue("Hotkeys", "SelectPreviousSaveStateSlot")); ImGui::TableNextColumn(); - ImGui::Text("%s - %s", load_savestate_hotkey.c_str(), "Load"); + ImGui::Text("%s - %s", load_savestate_hotkey.c_str(), + m_host_interface->TranslateString("SaveStateSelectorUI", "Load").GetCharArray()); ImGui::TableNextColumn(); - ImGui::Text("%s - %s", prev_savestate_hotkey.c_str(), "Select Previous"); + ImGui::Text("%s - %s", prev_savestate_hotkey.c_str(), + m_host_interface->TranslateString("SaveStateSelectorUI", "Select Previous").GetCharArray()); ImGui::TableNextColumn(); - ImGui::Text("%s - %s", save_savestate_hotkey.c_str(), "Save"); + ImGui::Text("%s - %s", save_savestate_hotkey.c_str(), + m_host_interface->TranslateString("SaveStateSelectorUI", "Save").GetCharArray()); ImGui::TableNextColumn(); - ImGui::Text("%s - %s", next_savestate_hotkey.c_str(), "Select Next"); + ImGui::Text("%s - %s", next_savestate_hotkey.c_str(), + m_host_interface->TranslateString("SaveStateSelectorUI", "Select Next").GetCharArray()); ImGui::EndTable(); } From 78f9136fb8629f8af818c030181dd1bacf20246f Mon Sep 17 00:00:00 2001 From: Silent Date: Mon, 22 Feb 2021 19:34:51 +0100 Subject: [PATCH 3/3] Save State UI: Cache legend strings --- src/frontend-common/common_host_interface.cpp | 2 + .../save_state_selector_ui.cpp | 64 +++++++++---------- src/frontend-common/save_state_selector_ui.h | 9 ++- 3 files changed, 42 insertions(+), 33 deletions(-) diff --git a/src/frontend-common/common_host_interface.cpp b/src/frontend-common/common_host_interface.cpp index fab723463..cd36ec2bf 100644 --- a/src/frontend-common/common_host_interface.cpp +++ b/src/frontend-common/common_host_interface.cpp @@ -1292,6 +1292,8 @@ void CommonHostInterface::UpdateHotkeyInputMap(SettingsInterface& si) AddButtonToInputMap(binding, device, button, hi.handler); } } + + m_save_state_selector_ui->RefreshHotkeyLegend(); } bool CommonHostInterface::AddButtonToInputMap(const std::string& binding, const std::string_view& device, diff --git a/src/frontend-common/save_state_selector_ui.cpp b/src/frontend-common/save_state_selector_ui.cpp index 471e3c542..41bb085f9 100644 --- a/src/frontend-common/save_state_selector_ui.cpp +++ b/src/frontend-common/save_state_selector_ui.cpp @@ -1,5 +1,6 @@ #include "save_state_selector_ui.h" #include "common/log.h" +#include "common/string_util.h" #include "common/timestamp.h" #include "core/host_display.h" #include "core/system.h" @@ -23,6 +24,7 @@ void SaveStateSelectorUI::Open(float open_time /* = DEFAULT_OPEN_TIME */) m_open = true; RefreshList(); + RefreshHotkeyLegend(); } void SaveStateSelectorUI::Close() @@ -78,6 +80,32 @@ void SaveStateSelectorUI::RefreshList() m_current_selection = 0; } +void SaveStateSelectorUI::RefreshHotkeyLegend() +{ + if (!m_open) + return; + + auto format_legend_entry = [](std::string_view setting, std::string_view caption) { + auto slash_pos = setting.find_first_of('/'); + if (slash_pos != setting.npos) + { + setting = setting.substr(slash_pos + 1); + } + + return StringUtil::StdStringFromFormat("%.*s - %.*s", static_cast(setting.size()), setting.data(), + static_cast(caption.size()), caption.data()); + }; + + m_load_legend = format_legend_entry(m_host_interface->GetStringSettingValue("Hotkeys", "LoadSelectedSaveState"), + m_host_interface->TranslateStdString("SaveStateSelectorUI", "Load")); + m_save_legend = format_legend_entry(m_host_interface->GetStringSettingValue("Hotkeys", "SaveSelectedSaveState"), + m_host_interface->TranslateStdString("SaveStateSelectorUI", "Save")); + m_prev_legend = format_legend_entry(m_host_interface->GetStringSettingValue("Hotkeys", "SelectPreviousSaveStateSlot"), + m_host_interface->TranslateStdString("SaveStateSelectorUI", "Select Previous")); + m_next_legend = format_legend_entry(m_host_interface->GetStringSettingValue("Hotkeys", "SelectNextSaveStateSlot"), + m_host_interface->TranslateStdString("SaveStateSelectorUI", "Select Next")); +} + const char* SaveStateSelectorUI::GetSelectedStatePath() const { if (m_slots.empty() || m_slots[m_current_selection].path.empty()) @@ -256,42 +284,14 @@ void SaveStateSelectorUI::Draw() ImGui::SetCursorPosX(padding); ImGui::BeginTable("table", 2); - auto strip_device_name = [](std::string str) { - std::string result; - - auto slash_pos = str.find_first_of('/'); - if (slash_pos != str.npos) - { - result = str.substr(slash_pos + 1); - } - else - { - result = std::move(str); - } - return result; - }; - - const std::string load_savestate_hotkey = - strip_device_name(m_host_interface->GetStringSettingValue("Hotkeys", "LoadSelectedSaveState")); - const std::string save_savestate_hotkey = - strip_device_name(m_host_interface->GetStringSettingValue("Hotkeys", "SaveSelectedSaveState")); - const std::string next_savestate_hotkey = - strip_device_name(m_host_interface->GetStringSettingValue("Hotkeys", "SelectNextSaveStateSlot")); - const std::string prev_savestate_hotkey = - strip_device_name(m_host_interface->GetStringSettingValue("Hotkeys", "SelectPreviousSaveStateSlot")); - ImGui::TableNextColumn(); - ImGui::Text("%s - %s", load_savestate_hotkey.c_str(), - m_host_interface->TranslateString("SaveStateSelectorUI", "Load").GetCharArray()); + ImGui::TextUnformatted(m_load_legend.c_str()); ImGui::TableNextColumn(); - ImGui::Text("%s - %s", prev_savestate_hotkey.c_str(), - m_host_interface->TranslateString("SaveStateSelectorUI", "Select Previous").GetCharArray()); + ImGui::TextUnformatted(m_prev_legend.c_str()); ImGui::TableNextColumn(); - ImGui::Text("%s - %s", save_savestate_hotkey.c_str(), - m_host_interface->TranslateString("SaveStateSelectorUI", "Save").GetCharArray()); + ImGui::TextUnformatted(m_save_legend.c_str()); ImGui::TableNextColumn(); - ImGui::Text("%s - %s", next_savestate_hotkey.c_str(), - m_host_interface->TranslateString("SaveStateSelectorUI", "Select Next").GetCharArray()); + ImGui::TextUnformatted(m_next_legend.c_str()); ImGui::EndTable(); } diff --git a/src/frontend-common/save_state_selector_ui.h b/src/frontend-common/save_state_selector_ui.h index 5fc694795..dbb88ebaf 100644 --- a/src/frontend-common/save_state_selector_ui.h +++ b/src/frontend-common/save_state_selector_ui.h @@ -1,6 +1,6 @@ #pragma once -#include "common_host_interface.h" #include "common/timer.h" +#include "common_host_interface.h" #include class HostDisplayTexture; @@ -24,6 +24,8 @@ public: void ClearList(); void RefreshList(); + void RefreshHotkeyLegend(); + const char* GetSelectedStatePath() const; s32 GetSelectedStateSlot() const; @@ -51,6 +53,11 @@ private: void InitializeListEntry(ListEntry* li, CommonHostInterface::ExtendedSaveStateInfo* ssi); std::pair GetSlotTypeFromSelection(u32 selection) const; + std::string m_load_legend; + std::string m_save_legend; + std::string m_prev_legend; + std::string m_next_legend; + CommonHostInterface* m_host_interface; std::vector m_slots; u32 m_current_selection = 0;