FullscreenUI: Add option to display PS buttons instead of Xbox
This commit is contained in:
parent
4d6124d41b
commit
5ee069fc63
|
@ -420,6 +420,34 @@ static GPUTexture* GetTextureForGameListEntryType(GameList::EntryType type);
|
||||||
static GPUTexture* GetGameListCover(const GameList::Entry* entry);
|
static GPUTexture* GetGameListCover(const GameList::Entry* entry);
|
||||||
static GPUTexture* GetCoverForCurrentGame();
|
static GPUTexture* GetCoverForCurrentGame();
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
// Constants
|
||||||
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
static constexpr const std::array s_ps_button_mapping{
|
||||||
|
std::make_pair(ICON_PF_XBOX_DPAD_LEFT, ICON_PF_DPAD_LEFT),
|
||||||
|
std::make_pair(ICON_PF_XBOX_DPAD_UP, ICON_PF_DPAD_UP),
|
||||||
|
std::make_pair(ICON_PF_XBOX_DPAD_RIGHT, ICON_PF_DPAD_RIGHT),
|
||||||
|
std::make_pair(ICON_PF_XBOX_DPAD_DOWN, ICON_PF_DPAD_DOWN),
|
||||||
|
std::make_pair(ICON_PF_XBOX_DPAD_LEFT_RIGHT, ICON_PF_DPAD_LEFT_RIGHT),
|
||||||
|
std::make_pair(ICON_PF_XBOX_DPAD_UP_DOWN, ICON_PF_DPAD_UP_DOWN),
|
||||||
|
std::make_pair(ICON_PF_BUTTON_A, ICON_PF_BUTTON_CROSS),
|
||||||
|
std::make_pair(ICON_PF_BUTTON_B, ICON_PF_BUTTON_CIRCLE),
|
||||||
|
std::make_pair(ICON_PF_BUTTON_X, ICON_PF_BUTTON_SQUARE),
|
||||||
|
std::make_pair(ICON_PF_BUTTON_Y, ICON_PF_BUTTON_TRIANGLE),
|
||||||
|
std::make_pair(ICON_PF_SHARE_CAPTURE, ICON_PF_DUALSHOCK_SHARE),
|
||||||
|
std::make_pair(ICON_PF_BURGER_MENU, ICON_PF_DUALSHOCK_OPTIONS),
|
||||||
|
std::make_pair(ICON_PF_XBOX, ICON_PF_PLAYSTATION),
|
||||||
|
std::make_pair(ICON_PF_LEFT_SHOULDER_LB, ICON_PF_LEFT_SHOULDER_L1),
|
||||||
|
std::make_pair(ICON_PF_LEFT_TRIGGER_LT, ICON_PF_LEFT_TRIGGER_L2),
|
||||||
|
std::make_pair(ICON_PF_RIGHT_SHOULDER_RB, ICON_PF_RIGHT_SHOULDER_R1),
|
||||||
|
std::make_pair(ICON_PF_RIGHT_TRIGGER_RT, ICON_PF_RIGHT_TRIGGER_R2),
|
||||||
|
};
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
// State
|
||||||
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
struct ALIGN_TO_CACHE_LINE UIState
|
struct ALIGN_TO_CACHE_LINE UIState
|
||||||
|
@ -590,6 +618,9 @@ bool FullscreenUI::Initialize()
|
||||||
ImGuiFullscreen::SetSmoothScrolling(Host::GetBaseBoolSettingValue("Main", "FullscreenUISmoothScrolling", true));
|
ImGuiFullscreen::SetSmoothScrolling(Host::GetBaseBoolSettingValue("Main", "FullscreenUISmoothScrolling", true));
|
||||||
ImGuiFullscreen::UpdateLayoutScale();
|
ImGuiFullscreen::UpdateLayoutScale();
|
||||||
|
|
||||||
|
if (Host::GetBaseBoolSettingValue("Main", "FullscreenUIDisplayPSIcons", false))
|
||||||
|
ImGuiFullscreen::SetFullscreenFooterTextIconMapping(s_ps_button_mapping);
|
||||||
|
|
||||||
if (!ImGuiManager::AddFullscreenFontsIfMissing() || !ImGuiFullscreen::Initialize("images/placeholder.png") ||
|
if (!ImGuiManager::AddFullscreenFontsIfMissing() || !ImGuiFullscreen::Initialize("images/placeholder.png") ||
|
||||||
!LoadResources())
|
!LoadResources())
|
||||||
{
|
{
|
||||||
|
@ -1717,7 +1748,7 @@ void FullscreenUI::DrawInputBindingButton(SettingsInterface* bsi, InputBindingIn
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (oneline && type != InputBindingInfo::Type::Pointer && type != InputBindingInfo::Type::Device)
|
if (oneline && type != InputBindingInfo::Type::Pointer && type != InputBindingInfo::Type::Device)
|
||||||
InputManager::PrettifyInputBinding(value);
|
InputManager::PrettifyInputBinding(value, &ImGuiFullscreen::GetControllerIconMapping);
|
||||||
|
|
||||||
if (show_type)
|
if (show_type)
|
||||||
{
|
{
|
||||||
|
@ -3245,6 +3276,18 @@ void FullscreenUI::DrawInterfaceSettingsPage()
|
||||||
ImGuiFullscreen::SetTheme(bsi->GetBoolValue("Main", "UseLightFullscreenUITheme", false));
|
ImGuiFullscreen::SetTheme(bsi->GetBoolValue("Main", "UseLightFullscreenUITheme", false));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (DrawToggleSetting(
|
||||||
|
bsi, FSUI_ICONSTR(ICON_PF_GAMEPAD, "Use DualShock/DualSense Button Icons"),
|
||||||
|
FSUI_CSTR(
|
||||||
|
"Displays DualShock/DualSense button icons in the footer and input binding, instead of Xbox buttons."),
|
||||||
|
"Main", "FullscreenUIDisplayPSIcons", false))
|
||||||
|
{
|
||||||
|
if (bsi->GetBoolValue("Main", "FullscreenUIDisplayPSIcons", false))
|
||||||
|
ImGuiFullscreen::SetFullscreenFooterTextIconMapping(s_ps_button_mapping);
|
||||||
|
else
|
||||||
|
ImGuiFullscreen::SetFullscreenFooterTextIconMapping({});
|
||||||
|
}
|
||||||
|
|
||||||
if (DrawToggleSetting(bsi, FSUI_ICONSTR(ICON_FA_LIST, "Smooth Scrolling"),
|
if (DrawToggleSetting(bsi, FSUI_ICONSTR(ICON_FA_LIST, "Smooth Scrolling"),
|
||||||
FSUI_CSTR("Enables smooth scrolling of menus in Big Picture UI."), "Main",
|
FSUI_CSTR("Enables smooth scrolling of menus in Big Picture UI."), "Main",
|
||||||
"FullscreenUISmoothScrolling", true))
|
"FullscreenUISmoothScrolling", true))
|
||||||
|
@ -7575,7 +7618,7 @@ void FullscreenUI::CopyTextToClipboard(std::string title, std::string_view text)
|
||||||
|
|
||||||
void FullscreenUI::DrawAboutWindow()
|
void FullscreenUI::DrawAboutWindow()
|
||||||
{
|
{
|
||||||
ImGui::SetNextWindowSize(LayoutScale(1000.0f, 540.0f));
|
ImGui::SetNextWindowSize(LayoutScale(1000.0f, 545.0f));
|
||||||
ImGui::SetNextWindowPos(ImGui::GetIO().DisplaySize * 0.5f, ImGuiCond_Always, ImVec2(0.5f, 0.5f));
|
ImGui::SetNextWindowPos(ImGui::GetIO().DisplaySize * 0.5f, ImGuiCond_Always, ImVec2(0.5f, 0.5f));
|
||||||
ImGui::OpenPopup(FSUI_CSTR("About DuckStation"));
|
ImGui::OpenPopup(FSUI_CSTR("About DuckStation"));
|
||||||
|
|
||||||
|
|
|
@ -931,7 +931,7 @@ void SaveStateSelectorUI::DestroyTextures()
|
||||||
void SaveStateSelectorUI::RefreshHotkeyLegend()
|
void SaveStateSelectorUI::RefreshHotkeyLegend()
|
||||||
{
|
{
|
||||||
auto format_legend_entry = [](SmallString binding, std::string_view caption) {
|
auto format_legend_entry = [](SmallString binding, std::string_view caption) {
|
||||||
InputManager::PrettifyInputBinding(binding);
|
InputManager::PrettifyInputBinding(binding, &ImGuiFullscreen::GetControllerIconMapping);
|
||||||
return fmt::format("{} - {}", binding, caption);
|
return fmt::format("{} - {}", binding, caption);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -445,7 +445,7 @@ TinyString DInputSource::ConvertKeyToString(InputBindingKey key)
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
TinyString DInputSource::ConvertKeyToIcon(InputBindingKey key)
|
TinyString DInputSource::ConvertKeyToIcon(InputBindingKey key, InputManager::BindingIconMappingFunction mapper)
|
||||||
{
|
{
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
|
@ -49,7 +49,7 @@ public:
|
||||||
bool ContainsDevice(std::string_view device) const override;
|
bool ContainsDevice(std::string_view device) const override;
|
||||||
std::optional<InputBindingKey> ParseKeyString(std::string_view device, std::string_view binding) override;
|
std::optional<InputBindingKey> ParseKeyString(std::string_view device, std::string_view binding) override;
|
||||||
TinyString ConvertKeyToString(InputBindingKey key) override;
|
TinyString ConvertKeyToString(InputBindingKey key) override;
|
||||||
TinyString ConvertKeyToIcon(InputBindingKey key) override;
|
TinyString ConvertKeyToIcon(InputBindingKey key, InputManager::BindingIconMappingFunction mapper) override;
|
||||||
|
|
||||||
std::unique_ptr<ForceFeedbackDevice> CreateForceFeedbackDevice(std::string_view device, Error* error) override;
|
std::unique_ptr<ForceFeedbackDevice> CreateForceFeedbackDevice(std::string_view device, Error* error) override;
|
||||||
|
|
||||||
|
|
|
@ -125,6 +125,7 @@ struct ALIGN_TO_CACHE_LINE UIState
|
||||||
|
|
||||||
SmallString fullscreen_footer_text;
|
SmallString fullscreen_footer_text;
|
||||||
SmallString last_fullscreen_footer_text;
|
SmallString last_fullscreen_footer_text;
|
||||||
|
std::vector<std::pair<std::string_view, std::string_view>> fullscreen_footer_icon_mapping;
|
||||||
float fullscreen_text_change_time;
|
float fullscreen_text_change_time;
|
||||||
|
|
||||||
bool choice_dialog_open = false;
|
bool choice_dialog_open = false;
|
||||||
|
@ -237,6 +238,7 @@ void ImGuiFullscreen::Shutdown(bool clear_state)
|
||||||
|
|
||||||
if (clear_state)
|
if (clear_state)
|
||||||
{
|
{
|
||||||
|
s_state.fullscreen_footer_icon_mapping = {};
|
||||||
s_state.notifications.clear();
|
s_state.notifications.clear();
|
||||||
s_state.background_progress_dialogs.clear();
|
s_state.background_progress_dialogs.clear();
|
||||||
s_state.fullscreen_footer_text.clear();
|
s_state.fullscreen_footer_text.clear();
|
||||||
|
@ -816,6 +818,16 @@ bool ImGuiFullscreen::IsGamepadInputSource()
|
||||||
return (ImGui::GetCurrentContext()->NavInputSource == ImGuiInputSource_Gamepad);
|
return (ImGui::GetCurrentContext()->NavInputSource == ImGuiInputSource_Gamepad);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::string_view ImGuiFullscreen::GetControllerIconMapping(std::string_view icon)
|
||||||
|
{
|
||||||
|
const auto iter =
|
||||||
|
std::lower_bound(s_state.fullscreen_footer_icon_mapping.begin(), s_state.fullscreen_footer_icon_mapping.end(), icon,
|
||||||
|
[](const auto& it, const auto& value) { return (it.first < value); });
|
||||||
|
if (iter != s_state.fullscreen_footer_icon_mapping.end() && iter->first == icon)
|
||||||
|
icon = iter->second;
|
||||||
|
return icon;
|
||||||
|
}
|
||||||
|
|
||||||
void ImGuiFullscreen::CreateFooterTextString(SmallStringBase& dest,
|
void ImGuiFullscreen::CreateFooterTextString(SmallStringBase& dest,
|
||||||
std::span<const std::pair<const char*, std::string_view>> items)
|
std::span<const std::pair<const char*, std::string_view>> items)
|
||||||
{
|
{
|
||||||
|
@ -825,7 +837,7 @@ void ImGuiFullscreen::CreateFooterTextString(SmallStringBase& dest,
|
||||||
if (!dest.empty())
|
if (!dest.empty())
|
||||||
dest.append(" ");
|
dest.append(" ");
|
||||||
|
|
||||||
dest.append(icon);
|
dest.append(GetControllerIconMapping(icon));
|
||||||
dest.append(' ');
|
dest.append(' ');
|
||||||
dest.append(text);
|
dest.append(text);
|
||||||
}
|
}
|
||||||
|
@ -841,6 +853,21 @@ void ImGuiFullscreen::SetFullscreenFooterText(std::span<const std::pair<const ch
|
||||||
CreateFooterTextString(s_state.fullscreen_footer_text, items);
|
CreateFooterTextString(s_state.fullscreen_footer_text, items);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ImGuiFullscreen::SetFullscreenFooterTextIconMapping(std::span<const std::pair<const char*, const char*>> mapping)
|
||||||
|
{
|
||||||
|
if (mapping.empty())
|
||||||
|
{
|
||||||
|
s_state.fullscreen_footer_icon_mapping = {};
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
s_state.fullscreen_footer_icon_mapping.reserve(mapping.size());
|
||||||
|
for (const auto& [icon, mapped_icon] : mapping)
|
||||||
|
s_state.fullscreen_footer_icon_mapping.emplace_back(icon, mapped_icon);
|
||||||
|
std::sort(s_state.fullscreen_footer_icon_mapping.begin(), s_state.fullscreen_footer_icon_mapping.end(),
|
||||||
|
[](const auto& lhs, const auto& rhs) { return (lhs.first < rhs.first); });
|
||||||
|
}
|
||||||
|
|
||||||
void ImGuiFullscreen::DrawFullscreenFooter()
|
void ImGuiFullscreen::DrawFullscreenFooter()
|
||||||
{
|
{
|
||||||
const ImGuiIO& io = ImGui::GetIO();
|
const ImGuiIO& io = ImGui::GetIO();
|
||||||
|
|
|
@ -187,9 +187,11 @@ bool BeginFullscreenWindow(const ImVec2& position, const ImVec2& size, const cha
|
||||||
void EndFullscreenWindow();
|
void EndFullscreenWindow();
|
||||||
|
|
||||||
bool IsGamepadInputSource();
|
bool IsGamepadInputSource();
|
||||||
|
std::string_view GetControllerIconMapping(std::string_view icon);
|
||||||
void CreateFooterTextString(SmallStringBase& dest, std::span<const std::pair<const char*, std::string_view>> items);
|
void CreateFooterTextString(SmallStringBase& dest, std::span<const std::pair<const char*, std::string_view>> items);
|
||||||
void SetFullscreenFooterText(std::string_view text);
|
void SetFullscreenFooterText(std::string_view text);
|
||||||
void SetFullscreenFooterText(std::span<const std::pair<const char*, std::string_view>> items);
|
void SetFullscreenFooterText(std::span<const std::pair<const char*, std::string_view>> items);
|
||||||
|
void SetFullscreenFooterTextIconMapping(std::span<const std::pair<const char*, const char*>> mapping);
|
||||||
void DrawFullscreenFooter();
|
void DrawFullscreenFooter();
|
||||||
|
|
||||||
void PrerenderMenuButtonBorder();
|
void PrerenderMenuButtonBorder();
|
||||||
|
|
|
@ -3,6 +3,6 @@
|
||||||
|
|
||||||
static constexpr ImWchar FA_ICON_RANGE[] = { 0xe06f,0xe070,0xe086,0xe086,0xf002,0xf002,0xf005,0xf005,0xf007,0xf007,0xf00c,0xf00e,0xf011,0xf013,0xf017,0xf017,0xf019,0xf019,0xf01c,0xf01c,0xf021,0xf021,0xf023,0xf023,0xf025,0xf026,0xf028,0xf028,0xf02e,0xf02e,0xf030,0xf030,0xf03a,0xf03a,0xf03d,0xf03d,0xf04a,0xf04c,0xf050,0xf050,0xf056,0xf056,0xf05e,0xf05e,0xf062,0xf063,0xf065,0xf067,0xf071,0xf071,0xf075,0xf075,0xf077,0xf078,0xf07b,0xf07c,0xf083,0xf085,0xf091,0xf091,0xf0ac,0xf0ae,0xf0b2,0xf0b2,0xf0c3,0xf0c3,0xf0c5,0xf0c5,0xf0c7,0xf0c9,0xf0cb,0xf0cb,0xf0d0,0xf0d0,0xf0dc,0xf0dc,0xf0e0,0xf0e0,0xf0e2,0xf0e2,0xf0e7,0xf0e8,0xf0eb,0xf0eb,0xf0f1,0xf0f1,0xf0f3,0xf0f3,0xf0fe,0xf0fe,0xf110,0xf110,0xf11b,0xf11c,0xf140,0xf140,0xf144,0xf144,0xf146,0xf146,0xf14a,0xf14a,0xf15b,0xf15d,0xf191,0xf192,0xf1ab,0xf1ab,0xf1c0,0xf1c0,0xf1c5,0xf1c5,0xf1de,0xf1de,0xf1e6,0xf1e6,0xf1eb,0xf1eb,0xf1f8,0xf1f8,0xf1fb,0xf1fc,0xf201,0xf201,0xf240,0xf240,0xf242,0xf242,0xf245,0xf245,0xf26c,0xf26c,0xf279,0xf279,0xf2c1,0xf2c1,0xf2d0,0xf2d0,0xf2db,0xf2db,0xf2f1,0xf2f2,0xf302,0xf302,0xf31e,0xf31e,0xf338,0xf338,0xf35d,0xf35d,0xf360,0xf360,0xf362,0xf362,0xf3fd,0xf3fd,0xf410,0xf410,0xf422,0xf422,0xf424,0xf424,0xf462,0xf462,0xf466,0xf466,0xf4ce,0xf4ce,0xf500,0xf500,0xf51f,0xf51f,0xf538,0xf538,0xf53f,0xf53f,0xf545,0xf545,0xf547,0xf548,0xf54c,0xf54c,0xf55b,0xf55b,0xf55d,0xf55d,0xf565,0xf565,0xf56e,0xf570,0xf575,0xf575,0xf5a2,0xf5a2,0xf5aa,0xf5aa,0xf5c7,0xf5c7,0xf5cb,0xf5cb,0xf5e7,0xf5e7,0xf5ee,0xf5ee,0xf61f,0xf61f,0xf65d,0xf65e,0xf6a9,0xf6a9,0xf6cf,0xf6cf,0xf70c,0xf70c,0xf70e,0xf70e,0xf78c,0xf78c,0xf794,0xf794,0xf7a0,0xf7a0,0xf7a4,0xf7a5,0xf7c2,0xf7c2,0xf807,0xf807,0xf815,0xf815,0xf818,0xf818,0xf84c,0xf84c,0xf87d,0xf87d,0xf8cc,0xf8cc,0x0,0x0 };
|
static constexpr ImWchar FA_ICON_RANGE[] = { 0xe06f,0xe070,0xe086,0xe086,0xf002,0xf002,0xf005,0xf005,0xf007,0xf007,0xf00c,0xf00e,0xf011,0xf013,0xf017,0xf017,0xf019,0xf019,0xf01c,0xf01c,0xf021,0xf021,0xf023,0xf023,0xf025,0xf026,0xf028,0xf028,0xf02e,0xf02e,0xf030,0xf030,0xf03a,0xf03a,0xf03d,0xf03d,0xf04a,0xf04c,0xf050,0xf050,0xf056,0xf056,0xf05e,0xf05e,0xf062,0xf063,0xf065,0xf067,0xf071,0xf071,0xf075,0xf075,0xf077,0xf078,0xf07b,0xf07c,0xf083,0xf085,0xf091,0xf091,0xf0ac,0xf0ae,0xf0b2,0xf0b2,0xf0c3,0xf0c3,0xf0c5,0xf0c5,0xf0c7,0xf0c9,0xf0cb,0xf0cb,0xf0d0,0xf0d0,0xf0dc,0xf0dc,0xf0e0,0xf0e0,0xf0e2,0xf0e2,0xf0e7,0xf0e8,0xf0eb,0xf0eb,0xf0f1,0xf0f1,0xf0f3,0xf0f3,0xf0fe,0xf0fe,0xf110,0xf110,0xf11b,0xf11c,0xf140,0xf140,0xf144,0xf144,0xf146,0xf146,0xf14a,0xf14a,0xf15b,0xf15d,0xf191,0xf192,0xf1ab,0xf1ab,0xf1c0,0xf1c0,0xf1c5,0xf1c5,0xf1de,0xf1de,0xf1e6,0xf1e6,0xf1eb,0xf1eb,0xf1f8,0xf1f8,0xf1fb,0xf1fc,0xf201,0xf201,0xf240,0xf240,0xf242,0xf242,0xf245,0xf245,0xf26c,0xf26c,0xf279,0xf279,0xf2c1,0xf2c1,0xf2d0,0xf2d0,0xf2db,0xf2db,0xf2f1,0xf2f2,0xf302,0xf302,0xf31e,0xf31e,0xf338,0xf338,0xf35d,0xf35d,0xf360,0xf360,0xf362,0xf362,0xf3fd,0xf3fd,0xf410,0xf410,0xf422,0xf422,0xf424,0xf424,0xf462,0xf462,0xf466,0xf466,0xf4ce,0xf4ce,0xf500,0xf500,0xf51f,0xf51f,0xf538,0xf538,0xf53f,0xf53f,0xf545,0xf545,0xf547,0xf548,0xf54c,0xf54c,0xf55b,0xf55b,0xf55d,0xf55d,0xf565,0xf565,0xf56e,0xf570,0xf575,0xf575,0xf5a2,0xf5a2,0xf5aa,0xf5aa,0xf5c7,0xf5c7,0xf5cb,0xf5cb,0xf5e7,0xf5e7,0xf5ee,0xf5ee,0xf61f,0xf61f,0xf65d,0xf65e,0xf6a9,0xf6a9,0xf6cf,0xf6cf,0xf70c,0xf70c,0xf70e,0xf70e,0xf78c,0xf78c,0xf794,0xf794,0xf7a0,0xf7a0,0xf7a4,0xf7a5,0xf7c2,0xf7c2,0xf807,0xf807,0xf815,0xf815,0xf818,0xf818,0xf84c,0xf84c,0xf87d,0xf87d,0xf8cc,0xf8cc,0x0,0x0 };
|
||||||
|
|
||||||
static constexpr ImWchar PF_ICON_RANGE[] = { 0x2196,0x2199,0x219e,0x21a1,0x21b0,0x21b3,0x21ba,0x21c3,0x21c7,0x21ca,0x21d0,0x21d4,0x21dc,0x21dd,0x21e0,0x21e3,0x21ed,0x21ee,0x21f7,0x21f8,0x21fa,0x21fb,0x227a,0x227f,0x2284,0x2284,0x2349,0x2349,0x235e,0x235e,0x2360,0x2361,0x2364,0x2366,0x23b2,0x23b4,0x23ce,0x23ce,0x23f4,0x23f7,0x2427,0x243a,0x243c,0x243e,0x2460,0x246b,0x248f,0x248f,0x24f5,0x24fd,0x24ff,0x24ff,0x2717,0x2717,0x278a,0x278e,0x27fc,0x27fc,0xe001,0xe001,0xff21,0xff3a,0x1f52b,0x1f52b,0x1f578,0x1f578,0x0,0x0 };
|
static constexpr ImWchar PF_ICON_RANGE[] = { 0x2196,0x2199,0x219e,0x21a3,0x21b0,0x21b3,0x21ba,0x21c3,0x21c7,0x21ca,0x21d0,0x21d4,0x21e0,0x21e3,0x21e6,0x21e8,0x21ed,0x21ee,0x21f7,0x21f8,0x21fa,0x21fb,0x227a,0x227f,0x2284,0x2284,0x2349,0x2349,0x235e,0x235e,0x2360,0x2361,0x2364,0x2366,0x23b2,0x23b4,0x23ce,0x23ce,0x23f4,0x23f7,0x2427,0x243a,0x243c,0x243e,0x2460,0x246b,0x248f,0x248f,0x24f5,0x24fd,0x24ff,0x24ff,0x2717,0x2717,0x278a,0x278e,0x27fc,0x27fc,0xe000,0xe001,0xff21,0xff3a,0x1f52b,0x1f52b,0x1f578,0x1f578,0x0,0x0 };
|
||||||
|
|
||||||
static constexpr ImWchar EMOJI_ICON_RANGE[] = { 0x2139,0x2139,0x23e9,0x23ea,0x23f8,0x23f8,0x26a0,0x26a0,0x1f4be,0x1f4be,0x1f4c2,0x1f4c2,0x1f4f7,0x1f4f8,0x1f504,0x1f504,0x1f507,0x1f507,0x1f509,0x1f50a,0x1f50d,0x1f50d,0x1f513,0x1f513,0x0,0x0 };
|
static constexpr ImWchar EMOJI_ICON_RANGE[] = { 0x2139,0x2139,0x23e9,0x23ea,0x23f8,0x23f8,0x26a0,0x26a0,0x1f4be,0x1f4be,0x1f4c2,0x1f4c2,0x1f4f7,0x1f4f8,0x1f504,0x1f504,0x1f507,0x1f507,0x1f509,0x1f50a,0x1f50d,0x1f50d,0x1f513,0x1f513,0x0,0x0 };
|
||||||
|
|
|
@ -110,7 +110,8 @@ static std::optional<InputBindingKey> ParseSensorKey(std::string_view source, st
|
||||||
|
|
||||||
static std::vector<std::string_view> SplitChord(std::string_view binding);
|
static std::vector<std::string_view> SplitChord(std::string_view binding);
|
||||||
static bool SplitBinding(std::string_view binding, std::string_view* source, std::string_view* sub_binding);
|
static bool SplitBinding(std::string_view binding, std::string_view* source, std::string_view* sub_binding);
|
||||||
static void PrettifyInputBindingPart(std::string_view binding, SmallString& ret, bool& changed);
|
static void PrettifyInputBindingPart(std::string_view binding, BindingIconMappingFunction mapper, SmallString& ret,
|
||||||
|
bool& changed);
|
||||||
static void AddBindings(const std::vector<std::string>& bindings, const InputEventHandler& handler);
|
static void AddBindings(const std::vector<std::string>& bindings, const InputEventHandler& handler);
|
||||||
static void UpdatePointerCount();
|
static void UpdatePointerCount();
|
||||||
|
|
||||||
|
@ -384,11 +385,13 @@ std::string InputManager::ConvertInputBindingKeysToString(InputBindingInfo::Type
|
||||||
return ss.str();
|
return ss.str();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool InputManager::PrettifyInputBinding(SmallStringBase& binding)
|
bool InputManager::PrettifyInputBinding(SmallStringBase& binding, BindingIconMappingFunction mapper /*= nullptr*/)
|
||||||
{
|
{
|
||||||
if (binding.empty())
|
if (binding.empty())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
mapper = mapper ? mapper : [](std::string_view v) { return v; };
|
||||||
|
|
||||||
const std::string_view binding_view = binding.view();
|
const std::string_view binding_view = binding.view();
|
||||||
|
|
||||||
SmallString ret;
|
SmallString ret;
|
||||||
|
@ -405,7 +408,7 @@ bool InputManager::PrettifyInputBinding(SmallStringBase& binding)
|
||||||
{
|
{
|
||||||
if (!ret.empty())
|
if (!ret.empty())
|
||||||
ret.append(" + ");
|
ret.append(" + ");
|
||||||
PrettifyInputBindingPart(part, ret, changed);
|
PrettifyInputBindingPart(part, mapper, ret, changed);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
last = next + 1;
|
last = next + 1;
|
||||||
|
@ -417,7 +420,7 @@ bool InputManager::PrettifyInputBinding(SmallStringBase& binding)
|
||||||
{
|
{
|
||||||
if (!ret.empty())
|
if (!ret.empty())
|
||||||
ret.append(" + ");
|
ret.append(" + ");
|
||||||
PrettifyInputBindingPart(part, ret, changed);
|
PrettifyInputBindingPart(part, mapper, ret, changed);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -427,7 +430,8 @@ bool InputManager::PrettifyInputBinding(SmallStringBase& binding)
|
||||||
return changed;
|
return changed;
|
||||||
}
|
}
|
||||||
|
|
||||||
void InputManager::PrettifyInputBindingPart(const std::string_view binding, SmallString& ret, bool& changed)
|
void InputManager::PrettifyInputBindingPart(const std::string_view binding, BindingIconMappingFunction mapper,
|
||||||
|
SmallString& ret, bool& changed)
|
||||||
{
|
{
|
||||||
std::string_view source, sub_binding;
|
std::string_view source, sub_binding;
|
||||||
if (!SplitBinding(binding, &source, &sub_binding))
|
if (!SplitBinding(binding, &source, &sub_binding))
|
||||||
|
@ -477,7 +481,7 @@ void InputManager::PrettifyInputBindingPart(const std::string_view binding, Smal
|
||||||
std::optional<InputBindingKey> key = s_input_sources[i]->ParseKeyString(source, sub_binding);
|
std::optional<InputBindingKey> key = s_input_sources[i]->ParseKeyString(source, sub_binding);
|
||||||
if (key.has_value())
|
if (key.has_value())
|
||||||
{
|
{
|
||||||
const TinyString icon = s_input_sources[i]->ConvertKeyToIcon(key.value());
|
const TinyString icon = s_input_sources[i]->ConvertKeyToIcon(key.value(), mapper);
|
||||||
if (!icon.empty())
|
if (!icon.empty())
|
||||||
{
|
{
|
||||||
ret.append(icon);
|
ret.append(icon);
|
||||||
|
|
|
@ -253,7 +253,9 @@ std::string ConvertInputBindingKeysToString(InputBindingInfo::Type binding_type,
|
||||||
size_t num_keys);
|
size_t num_keys);
|
||||||
|
|
||||||
/// Represents a binding with icon fonts, if available.
|
/// Represents a binding with icon fonts, if available.
|
||||||
bool PrettifyInputBinding(SmallStringBase& binding);
|
/// Optionally maps icon fonts to a different style, e.g. xbox icons -> PS buttons.
|
||||||
|
using BindingIconMappingFunction = std::string_view(*)(std::string_view);
|
||||||
|
bool PrettifyInputBinding(SmallStringBase& binding, BindingIconMappingFunction mapper = nullptr);
|
||||||
|
|
||||||
/// Returns a list of all hotkeys.
|
/// Returns a list of all hotkeys.
|
||||||
std::vector<const HotkeyInfo*> GetHotkeyList();
|
std::vector<const HotkeyInfo*> GetHotkeyList();
|
||||||
|
|
|
@ -35,7 +35,7 @@ public:
|
||||||
virtual bool ContainsDevice(std::string_view device) const = 0;
|
virtual bool ContainsDevice(std::string_view device) const = 0;
|
||||||
virtual std::optional<InputBindingKey> ParseKeyString(std::string_view device, std::string_view binding) = 0;
|
virtual std::optional<InputBindingKey> ParseKeyString(std::string_view device, std::string_view binding) = 0;
|
||||||
virtual TinyString ConvertKeyToString(InputBindingKey key) = 0;
|
virtual TinyString ConvertKeyToString(InputBindingKey key) = 0;
|
||||||
virtual TinyString ConvertKeyToIcon(InputBindingKey key) = 0;
|
virtual TinyString ConvertKeyToIcon(InputBindingKey key, InputManager::BindingIconMappingFunction mapper) = 0;
|
||||||
|
|
||||||
/// Enumerates available devices. Returns a pair of the prefix (e.g. SDL-0) and the device name.
|
/// Enumerates available devices. Returns a pair of the prefix (e.g. SDL-0) and the device name.
|
||||||
virtual std::vector<std::pair<std::string, std::string>> EnumerateDevices() = 0;
|
virtual std::vector<std::pair<std::string, std::string>> EnumerateDevices() = 0;
|
||||||
|
|
|
@ -41,8 +41,8 @@ static constexpr const char* s_sdl_axis_icons[][2] = {
|
||||||
{ICON_PF_LEFT_ANALOG_UP, ICON_PF_LEFT_ANALOG_DOWN}, // SDL_CONTROLLER_AXIS_LEFTY
|
{ICON_PF_LEFT_ANALOG_UP, ICON_PF_LEFT_ANALOG_DOWN}, // SDL_CONTROLLER_AXIS_LEFTY
|
||||||
{ICON_PF_RIGHT_ANALOG_LEFT, ICON_PF_RIGHT_ANALOG_RIGHT}, // SDL_CONTROLLER_AXIS_RIGHTX
|
{ICON_PF_RIGHT_ANALOG_LEFT, ICON_PF_RIGHT_ANALOG_RIGHT}, // SDL_CONTROLLER_AXIS_RIGHTX
|
||||||
{ICON_PF_RIGHT_ANALOG_UP, ICON_PF_RIGHT_ANALOG_DOWN}, // SDL_CONTROLLER_AXIS_RIGHTY
|
{ICON_PF_RIGHT_ANALOG_UP, ICON_PF_RIGHT_ANALOG_DOWN}, // SDL_CONTROLLER_AXIS_RIGHTY
|
||||||
{nullptr, ICON_PF_LEFT_TRIGGER_PULL}, // SDL_CONTROLLER_AXIS_TRIGGERLEFT
|
{nullptr, ICON_PF_LEFT_TRIGGER_LT}, // SDL_CONTROLLER_AXIS_TRIGGERLEFT
|
||||||
{nullptr, ICON_PF_RIGHT_TRIGGER_PULL}, // SDL_CONTROLLER_AXIS_TRIGGERRIGHT
|
{nullptr, ICON_PF_RIGHT_TRIGGER_RT}, // SDL_CONTROLLER_AXIS_TRIGGERRIGHT
|
||||||
};
|
};
|
||||||
static constexpr const GenericInputBinding s_sdl_generic_binding_axis_mapping[][2] = {
|
static constexpr const GenericInputBinding s_sdl_generic_binding_axis_mapping[][2] = {
|
||||||
{GenericInputBinding::LeftStickLeft, GenericInputBinding::LeftStickRight}, // SDL_CONTROLLER_AXIS_LEFTX
|
{GenericInputBinding::LeftStickLeft, GenericInputBinding::LeftStickRight}, // SDL_CONTROLLER_AXIS_LEFTX
|
||||||
|
@ -92,6 +92,12 @@ static constexpr const char* s_sdl_button_icons[] = {
|
||||||
ICON_PF_XBOX_DPAD_DOWN, // SDL_CONTROLLER_BUTTON_DPAD_DOWN
|
ICON_PF_XBOX_DPAD_DOWN, // SDL_CONTROLLER_BUTTON_DPAD_DOWN
|
||||||
ICON_PF_XBOX_DPAD_LEFT, // SDL_CONTROLLER_BUTTON_DPAD_LEFT
|
ICON_PF_XBOX_DPAD_LEFT, // SDL_CONTROLLER_BUTTON_DPAD_LEFT
|
||||||
ICON_PF_XBOX_DPAD_RIGHT, // SDL_CONTROLLER_BUTTON_DPAD_RIGHT
|
ICON_PF_XBOX_DPAD_RIGHT, // SDL_CONTROLLER_BUTTON_DPAD_RIGHT
|
||||||
|
nullptr, // SDL_CONTROLLER_BUTTON_MISC1
|
||||||
|
nullptr, // SDL_CONTROLLER_BUTTON_PADDLE1
|
||||||
|
nullptr, // SDL_CONTROLLER_BUTTON_PADDLE2
|
||||||
|
nullptr, // SDL_CONTROLLER_BUTTON_PADDLE3
|
||||||
|
nullptr, // SDL_CONTROLLER_BUTTON_PADDLE4
|
||||||
|
ICON_PF_DUALSHOCK_TOUCHPAD, // SDL_CONTROLLER_BUTTON_TOUCHPAD
|
||||||
};
|
};
|
||||||
static constexpr const GenericInputBinding s_sdl_generic_binding_button_mapping[] = {
|
static constexpr const GenericInputBinding s_sdl_generic_binding_button_mapping[] = {
|
||||||
GenericInputBinding::Cross, // SDL_CONTROLLER_BUTTON_A
|
GenericInputBinding::Cross, // SDL_CONTROLLER_BUTTON_A
|
||||||
|
@ -539,7 +545,7 @@ TinyString SDLInputSource::ConvertKeyToString(InputBindingKey key)
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
TinyString SDLInputSource::ConvertKeyToIcon(InputBindingKey key)
|
TinyString SDLInputSource::ConvertKeyToIcon(InputBindingKey key, InputManager::BindingIconMappingFunction mapper)
|
||||||
{
|
{
|
||||||
TinyString ret;
|
TinyString ret;
|
||||||
|
|
||||||
|
@ -550,13 +556,13 @@ TinyString SDLInputSource::ConvertKeyToIcon(InputBindingKey key)
|
||||||
if (key.data < std::size(s_sdl_axis_icons) && key.modifier != InputModifier::FullAxis)
|
if (key.data < std::size(s_sdl_axis_icons) && key.modifier != InputModifier::FullAxis)
|
||||||
{
|
{
|
||||||
ret.format("SDL-{} {}", static_cast<u32>(key.source_index),
|
ret.format("SDL-{} {}", static_cast<u32>(key.source_index),
|
||||||
s_sdl_axis_icons[key.data][key.modifier == InputModifier::None]);
|
mapper(s_sdl_axis_icons[key.data][key.modifier == InputModifier::None]));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (key.source_subtype == InputSubclass::ControllerButton)
|
else if (key.source_subtype == InputSubclass::ControllerButton)
|
||||||
{
|
{
|
||||||
if (key.data < std::size(s_sdl_button_icons))
|
if (key.data < std::size(s_sdl_button_icons) && s_sdl_button_icons[key.data])
|
||||||
ret.format("SDL-{} {}", static_cast<u32>(key.source_index), s_sdl_button_icons[key.data]);
|
ret.format("SDL-{} {}", static_cast<u32>(key.source_index), mapper(s_sdl_button_icons[key.data]));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -37,7 +37,7 @@ public:
|
||||||
bool ContainsDevice(std::string_view device) const override;
|
bool ContainsDevice(std::string_view device) const override;
|
||||||
std::optional<InputBindingKey> ParseKeyString(std::string_view device, std::string_view binding) override;
|
std::optional<InputBindingKey> ParseKeyString(std::string_view device, std::string_view binding) override;
|
||||||
TinyString ConvertKeyToString(InputBindingKey key) override;
|
TinyString ConvertKeyToString(InputBindingKey key) override;
|
||||||
TinyString ConvertKeyToIcon(InputBindingKey key) override;
|
TinyString ConvertKeyToIcon(InputBindingKey key, InputManager::BindingIconMappingFunction mapper) override;
|
||||||
|
|
||||||
std::unique_ptr<ForceFeedbackDevice> CreateForceFeedbackDevice(std::string_view device, Error* error) override;
|
std::unique_ptr<ForceFeedbackDevice> CreateForceFeedbackDevice(std::string_view device, Error* error) override;
|
||||||
|
|
||||||
|
|
|
@ -106,7 +106,7 @@ TinyString Win32RawInputSource::ConvertKeyToString(InputBindingKey key)
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
TinyString Win32RawInputSource::ConvertKeyToIcon(InputBindingKey key)
|
TinyString Win32RawInputSource::ConvertKeyToIcon(InputBindingKey key, InputManager::BindingIconMappingFunction mapper)
|
||||||
{
|
{
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
|
@ -33,7 +33,7 @@ public:
|
||||||
bool ContainsDevice(std::string_view device) const override;
|
bool ContainsDevice(std::string_view device) const override;
|
||||||
std::optional<InputBindingKey> ParseKeyString(std::string_view device, std::string_view binding) override;
|
std::optional<InputBindingKey> ParseKeyString(std::string_view device, std::string_view binding) override;
|
||||||
TinyString ConvertKeyToString(InputBindingKey key) override;
|
TinyString ConvertKeyToString(InputBindingKey key) override;
|
||||||
TinyString ConvertKeyToIcon(InputBindingKey key) override;
|
TinyString ConvertKeyToIcon(InputBindingKey key, InputManager::BindingIconMappingFunction mapper) override;
|
||||||
|
|
||||||
std::unique_ptr<ForceFeedbackDevice> CreateForceFeedbackDevice(std::string_view device, Error* error) override;
|
std::unique_ptr<ForceFeedbackDevice> CreateForceFeedbackDevice(std::string_view device, Error* error) override;
|
||||||
|
|
||||||
|
|
|
@ -29,8 +29,8 @@ static constexpr const char* s_axis_icons[][2] = {
|
||||||
{ICON_PF_LEFT_ANALOG_UP, ICON_PF_LEFT_ANALOG_DOWN}, // AXIS_LEFTY
|
{ICON_PF_LEFT_ANALOG_UP, ICON_PF_LEFT_ANALOG_DOWN}, // AXIS_LEFTY
|
||||||
{ICON_PF_RIGHT_ANALOG_LEFT, ICON_PF_RIGHT_ANALOG_RIGHT}, // AXIS_RIGHTX
|
{ICON_PF_RIGHT_ANALOG_LEFT, ICON_PF_RIGHT_ANALOG_RIGHT}, // AXIS_RIGHTX
|
||||||
{ICON_PF_RIGHT_ANALOG_UP, ICON_PF_RIGHT_ANALOG_DOWN}, // AXIS_RIGHTY
|
{ICON_PF_RIGHT_ANALOG_UP, ICON_PF_RIGHT_ANALOG_DOWN}, // AXIS_RIGHTY
|
||||||
{nullptr, ICON_PF_LEFT_TRIGGER_PULL}, // AXIS_TRIGGERLEFT
|
{nullptr, ICON_PF_LEFT_TRIGGER_LT}, // AXIS_TRIGGERLEFT
|
||||||
{nullptr, ICON_PF_RIGHT_TRIGGER_PULL}, // AXIS_TRIGGERRIGHT
|
{nullptr, ICON_PF_RIGHT_TRIGGER_RT}, // AXIS_TRIGGERRIGHT
|
||||||
};
|
};
|
||||||
static const GenericInputBinding s_xinput_generic_binding_axis_mapping[][2] = {
|
static const GenericInputBinding s_xinput_generic_binding_axis_mapping[][2] = {
|
||||||
{GenericInputBinding::LeftStickLeft, GenericInputBinding::LeftStickRight}, // AXIS_LEFTX
|
{GenericInputBinding::LeftStickLeft, GenericInputBinding::LeftStickRight}, // AXIS_LEFTX
|
||||||
|
@ -346,7 +346,7 @@ TinyString XInputSource::ConvertKeyToString(InputBindingKey key)
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
TinyString XInputSource::ConvertKeyToIcon(InputBindingKey key)
|
TinyString XInputSource::ConvertKeyToIcon(InputBindingKey key, InputManager::BindingIconMappingFunction mapper)
|
||||||
{
|
{
|
||||||
TinyString ret;
|
TinyString ret;
|
||||||
|
|
||||||
|
@ -357,13 +357,13 @@ TinyString XInputSource::ConvertKeyToIcon(InputBindingKey key)
|
||||||
if (key.data < std::size(s_axis_icons) && key.modifier != InputModifier::FullAxis)
|
if (key.data < std::size(s_axis_icons) && key.modifier != InputModifier::FullAxis)
|
||||||
{
|
{
|
||||||
ret.format("XInput-{} {}", static_cast<u32>(key.source_index),
|
ret.format("XInput-{} {}", static_cast<u32>(key.source_index),
|
||||||
s_axis_icons[key.data][key.modifier == InputModifier::None]);
|
mapper(s_axis_icons[key.data][key.modifier == InputModifier::None]));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (key.source_subtype == InputSubclass::ControllerButton)
|
else if (key.source_subtype == InputSubclass::ControllerButton)
|
||||||
{
|
{
|
||||||
if (key.data < std::size(s_button_icons))
|
if (key.data < std::size(s_button_icons))
|
||||||
ret.format("XInput-{} {}", static_cast<u32>(key.source_index), s_button_icons[key.data]);
|
ret.format("XInput-{} {}", static_cast<u32>(key.source_index), mapper(s_button_icons[key.data]));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -51,7 +51,7 @@ public:
|
||||||
bool ContainsDevice(std::string_view device) const override;
|
bool ContainsDevice(std::string_view device) const override;
|
||||||
std::optional<InputBindingKey> ParseKeyString(std::string_view device, std::string_view binding) override;
|
std::optional<InputBindingKey> ParseKeyString(std::string_view device, std::string_view binding) override;
|
||||||
TinyString ConvertKeyToString(InputBindingKey key) override;
|
TinyString ConvertKeyToString(InputBindingKey key) override;
|
||||||
TinyString ConvertKeyToIcon(InputBindingKey key) override;
|
TinyString ConvertKeyToIcon(InputBindingKey key, InputManager::BindingIconMappingFunction mapper) override;
|
||||||
|
|
||||||
std::unique_ptr<ForceFeedbackDevice> CreateForceFeedbackDevice(std::string_view device, Error* error) override;
|
std::unique_ptr<ForceFeedbackDevice> CreateForceFeedbackDevice(std::string_view device, Error* error) override;
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue