mirror of
https://github.com/RetroDECK/Duckstation.git
synced 2024-11-30 01:25:51 +00:00
OSD: Add controller input display overlay
This commit is contained in:
parent
a9a571cd6a
commit
251043f11a
|
@ -328,4 +328,6 @@
|
|||
<string name="main_activity_empty_game_list_start_file">Start File</string>
|
||||
<string name="update_notes_title">Update Notes</string>
|
||||
<string name="update_notes_message_version_controller_update">This DuckStation update includes support for multiple controllers with vibration, and binding devices such as keyboards/volume buttons.\n\nYou must re-bind your controllers, otherwise they will no longer function. Do you want to do this now?</string>
|
||||
<string name="settings_osd_show_show_inputs">Show Controller Input</string>
|
||||
<string name="settings_summary_osd_show_inputs">Shows the current controller state of the system in the bottom-left corner of the display.</string>
|
||||
</resources>
|
||||
|
|
|
@ -98,5 +98,11 @@
|
|||
app:defaultValue="false"
|
||||
app:summary="@string/settings_summary_osd_show_resolution"
|
||||
app:iconSpaceReserved="false" />
|
||||
<SwitchPreferenceCompat
|
||||
app:key="Display/ShowInputs"
|
||||
app:title="@string/settings_osd_show_show_inputs"
|
||||
app:defaultValue="false"
|
||||
app:summary="@string/settings_summary_osd_show_inputs"
|
||||
app:iconSpaceReserved="false" />
|
||||
|
||||
</PreferenceScreen>
|
||||
|
|
|
@ -104,6 +104,16 @@ std::optional<s32> AnalogController::GetButtonCodeByName(std::string_view button
|
|||
return StaticGetButtonCodeByName(button_name);
|
||||
}
|
||||
|
||||
float AnalogController::GetAxisState(s32 axis_code) const
|
||||
{
|
||||
if (axis_code < 0 || axis_code >= static_cast<s32>(Axis::Count))
|
||||
return 0.0f;
|
||||
|
||||
// 0..255 -> -1..1
|
||||
const float value = (((static_cast<float>(m_axis_state[static_cast<s32>(axis_code)]) / 255.0f) * 2.0f) - 1.0f);
|
||||
return std::clamp(value / m_axis_scale, -1.0f, 1.0f);
|
||||
}
|
||||
|
||||
void AnalogController::SetAxisState(s32 axis_code, float value)
|
||||
{
|
||||
if (axis_code < 0 || axis_code >= static_cast<s32>(Axis::Count))
|
||||
|
@ -124,6 +134,15 @@ void AnalogController::SetAxisState(Axis axis, u8 value)
|
|||
m_axis_state[static_cast<u8>(axis)] = value;
|
||||
}
|
||||
|
||||
bool AnalogController::GetButtonState(s32 button_code) const
|
||||
{
|
||||
if (button_code < 0 || button_code >= static_cast<s32>(Button::Analog))
|
||||
return false;
|
||||
|
||||
const u16 bit = u16(1) << static_cast<u8>(button_code);
|
||||
return ((m_button_state & bit) == 0);
|
||||
}
|
||||
|
||||
void AnalogController::SetButtonState(Button button, bool pressed)
|
||||
{
|
||||
if (button == Button::Analog)
|
||||
|
|
|
@ -59,7 +59,9 @@ public:
|
|||
void Reset() override;
|
||||
bool DoState(StateWrapper& sw, bool ignore_input_state) override;
|
||||
|
||||
float GetAxisState(s32 axis_code) const override;
|
||||
void SetAxisState(s32 axis_code, float value) override;
|
||||
bool GetButtonState(s32 button_code) const override;
|
||||
void SetButtonState(s32 button_code, bool pressed) override;
|
||||
u32 GetButtonStateBits() const override;
|
||||
std::optional<u32> GetAnalogInputBytes() const override;
|
||||
|
|
|
@ -69,6 +69,16 @@ std::optional<s32> AnalogJoystick::GetButtonCodeByName(std::string_view button_n
|
|||
return StaticGetButtonCodeByName(button_name);
|
||||
}
|
||||
|
||||
float AnalogJoystick::GetAxisState(s32 axis_code) const
|
||||
{
|
||||
if (axis_code < 0 || axis_code >= static_cast<s32>(Axis::Count))
|
||||
return 0.0f;
|
||||
|
||||
// 0..255 -> -1..1
|
||||
const float value = (((static_cast<float>(m_axis_state[static_cast<s32>(axis_code)]) / 255.0f) * 2.0f) - 1.0f);
|
||||
return std::clamp(value / m_axis_scale, -1.0f, 1.0f);
|
||||
}
|
||||
|
||||
void AnalogJoystick::SetAxisState(s32 axis_code, float value)
|
||||
{
|
||||
if (axis_code < 0 || axis_code >= static_cast<s32>(Axis::Count))
|
||||
|
@ -89,6 +99,15 @@ void AnalogJoystick::SetAxisState(Axis axis, u8 value)
|
|||
m_axis_state[static_cast<u8>(axis)] = value;
|
||||
}
|
||||
|
||||
bool AnalogJoystick::GetButtonState(s32 button_code) const
|
||||
{
|
||||
if (button_code < 0 || button_code >= static_cast<s32>(Button::Count))
|
||||
return false;
|
||||
|
||||
const u16 bit = u16(1) << static_cast<u8>(button_code);
|
||||
return ((m_button_state & bit) == 0);
|
||||
}
|
||||
|
||||
void AnalogJoystick::SetButtonState(Button button, bool pressed)
|
||||
{
|
||||
if (button == Button::Mode)
|
||||
|
|
|
@ -57,7 +57,9 @@ public:
|
|||
void Reset() override;
|
||||
bool DoState(StateWrapper& sw, bool apply_input_state) override;
|
||||
|
||||
float GetAxisState(s32 axis_code) const override;
|
||||
void SetAxisState(s32 axis_code, float value) override;
|
||||
bool GetButtonState(s32 button_code) const override;
|
||||
void SetButtonState(s32 button_code, bool pressed) override;
|
||||
u32 GetButtonStateBits() const override;
|
||||
std::optional<u32> GetAnalogInputBytes() const override;
|
||||
|
|
|
@ -26,8 +26,18 @@ bool Controller::Transfer(const u8 data_in, u8* data_out)
|
|||
return false;
|
||||
}
|
||||
|
||||
float Controller::GetAxisState(s32 axis_code) const
|
||||
{
|
||||
return 0.0f;
|
||||
}
|
||||
|
||||
void Controller::SetAxisState(s32 axis_code, float value) {}
|
||||
|
||||
bool Controller::GetButtonState(s32 button_code) const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
void Controller::SetButtonState(s32 button_code, bool pressed) {}
|
||||
|
||||
u32 Controller::GetButtonStateBits() const
|
||||
|
|
|
@ -45,9 +45,15 @@ public:
|
|||
// Returns the value of ACK, as well as filling out_data.
|
||||
virtual bool Transfer(const u8 data_in, u8* data_out);
|
||||
|
||||
/// Changes the specified axis state. Values are normalized from -1..1.
|
||||
virtual float GetAxisState(s32 axis_code) const;
|
||||
|
||||
/// Changes the specified axis state. Values are normalized from -1..1.
|
||||
virtual void SetAxisState(s32 axis_code, float value);
|
||||
|
||||
/// Returns the specified button state.
|
||||
virtual bool GetButtonState(s32 button_code) const;
|
||||
|
||||
/// Changes the specified button state.
|
||||
virtual void SetButtonState(s32 button_code, bool pressed);
|
||||
|
||||
|
|
|
@ -42,7 +42,14 @@ bool DigitalController::DoState(StateWrapper& sw, bool apply_input_state)
|
|||
return true;
|
||||
}
|
||||
|
||||
void DigitalController::SetAxisState(s32 axis_code, float value) {}
|
||||
bool DigitalController::GetButtonState(s32 button_code) const
|
||||
{
|
||||
if (button_code < 0 || button_code >= static_cast<s32>(Button::Count))
|
||||
return false;
|
||||
|
||||
const u16 bit = u16(1) << static_cast<u8>(button_code);
|
||||
return ((m_button_state & bit) == 0);
|
||||
}
|
||||
|
||||
void DigitalController::SetButtonState(Button button, bool pressed)
|
||||
{
|
||||
|
|
|
@ -46,7 +46,7 @@ public:
|
|||
void Reset() override;
|
||||
bool DoState(StateWrapper& sw, bool apply_input_state) override;
|
||||
|
||||
void SetAxisState(s32 axis_code, float value) override;
|
||||
bool GetButtonState(s32 button_code) const override;
|
||||
void SetButtonState(s32 button_code, bool pressed) override;
|
||||
u32 GetButtonStateBits() const override;
|
||||
|
||||
|
|
|
@ -56,7 +56,14 @@ bool NamcoGunCon::DoState(StateWrapper& sw, bool apply_input_state)
|
|||
return true;
|
||||
}
|
||||
|
||||
void NamcoGunCon::SetAxisState(s32 axis_code, float value) {}
|
||||
bool NamcoGunCon::GetButtonState(s32 button_code) const
|
||||
{
|
||||
if (button_code < 0 || button_code > static_cast<s32>(Button::B))
|
||||
return false;
|
||||
|
||||
const u16 bit = u16(1) << static_cast<u8>(button_code);
|
||||
return ((m_button_state & bit) == 0);
|
||||
}
|
||||
|
||||
void NamcoGunCon::SetButtonState(Button button, bool pressed)
|
||||
{
|
||||
|
|
|
@ -36,7 +36,7 @@ public:
|
|||
void LoadSettings(const char* section) override;
|
||||
bool GetSoftwareCursor(const Common::RGBA8Image** image, float* image_scale, bool* relative_mode) override;
|
||||
|
||||
void SetAxisState(s32 axis_code, float value) override;
|
||||
bool GetButtonState(s32 button_code) const override;
|
||||
void SetButtonState(s32 button_code, bool pressed) override;
|
||||
|
||||
void ResetTransferState() override;
|
||||
|
|
|
@ -48,6 +48,16 @@ bool NeGcon::DoState(StateWrapper& sw, bool apply_input_state)
|
|||
return true;
|
||||
}
|
||||
|
||||
float NeGcon::GetAxisState(s32 axis_code) const
|
||||
{
|
||||
if (axis_code < 0 || axis_code >= static_cast<s32>(Axis::Count))
|
||||
return 0.0f;
|
||||
|
||||
// 0..255 -> -1..1
|
||||
const float value = (((static_cast<float>(m_axis_state[static_cast<s32>(axis_code)]) / 255.0f) * 2.0f) - 1.0f);
|
||||
return std::clamp(value, -1.0f, 1.0f);
|
||||
}
|
||||
|
||||
void NeGcon::SetAxisState(s32 axis_code, float value)
|
||||
{
|
||||
if (axis_code < 0 || axis_code >= static_cast<s32>(Axis::Count))
|
||||
|
@ -78,6 +88,15 @@ void NeGcon::SetAxisState(Axis axis, u8 value)
|
|||
m_axis_state[static_cast<u8>(axis)] = value;
|
||||
}
|
||||
|
||||
bool NeGcon::GetButtonState(s32 button_code) const
|
||||
{
|
||||
if (button_code < 0 || button_code >= static_cast<s32>(Button::Count))
|
||||
return false;
|
||||
|
||||
const u16 bit = u16(1) << static_cast<u8>(button_code);
|
||||
return ((m_button_state & bit) == 0);
|
||||
}
|
||||
|
||||
void NeGcon::SetButtonState(s32 button_code, bool pressed)
|
||||
{
|
||||
if (button_code < 0 || button_code >= static_cast<s32>(Button::Count))
|
||||
|
|
|
@ -48,7 +48,10 @@ public:
|
|||
void Reset() override;
|
||||
bool DoState(StateWrapper& sw, bool apply_input_state) override;
|
||||
|
||||
float GetAxisState(s32 axis_code) const override;
|
||||
void SetAxisState(s32 axis_code, float value) override;
|
||||
|
||||
bool GetButtonState(s32 button_code) const override;
|
||||
void SetButtonState(s32 button_code, bool pressed) override;
|
||||
|
||||
void ResetTransferState() override;
|
||||
|
|
|
@ -59,7 +59,14 @@ bool PlayStationMouse::DoState(StateWrapper& sw, bool apply_input_state)
|
|||
return true;
|
||||
}
|
||||
|
||||
void PlayStationMouse::SetAxisState(s32 axis_code, float value) {}
|
||||
bool PlayStationMouse::GetButtonState(s32 button_code) const
|
||||
{
|
||||
if (button_code < 0 || button_code >= static_cast<s32>(Button::Count))
|
||||
return false;
|
||||
|
||||
const u16 bit = u16(1) << static_cast<u8>(button_code);
|
||||
return ((m_button_state & bit) == 0);
|
||||
}
|
||||
|
||||
void PlayStationMouse::SetButtonState(Button button, bool pressed)
|
||||
{
|
||||
|
|
|
@ -32,7 +32,7 @@ public:
|
|||
void Reset() override;
|
||||
bool DoState(StateWrapper& sw, bool apply_input_state) override;
|
||||
|
||||
void SetAxisState(s32 axis_code, float value) override;
|
||||
bool GetButtonState(s32 button_code) const override;
|
||||
void SetButtonState(s32 button_code, bool pressed) override;
|
||||
|
||||
void ResetTransferState() override;
|
||||
|
|
|
@ -51,6 +51,7 @@ DisplaySettingsWidget::DisplaySettingsWidget(QtHostInterface* host_interface, QW
|
|||
SettingWidgetBinder::BindWidgetToBoolSetting(m_host_interface, m_ui.showSpeed, "Display", "ShowSpeed", false);
|
||||
SettingWidgetBinder::BindWidgetToBoolSetting(m_host_interface, m_ui.showResolution, "Display", "ShowResolution",
|
||||
false);
|
||||
SettingWidgetBinder::BindWidgetToBoolSetting(m_host_interface, m_ui.showInput, "Display", "ShowInputs", false);
|
||||
|
||||
connect(m_ui.renderer, QOverload<int>::of(&QComboBox::currentIndexChanged), this,
|
||||
&DisplaySettingsWidget::populateGPUAdaptersAndResolutions);
|
||||
|
@ -135,6 +136,9 @@ DisplaySettingsWidget::DisplaySettingsWidget(QtHostInterface* host_interface, QW
|
|||
tr("Shows the current emulation speed of the system in the top-right corner of the display as a percentage."));
|
||||
dialog->registerWidgetHelp(m_ui.showResolution, tr("Show Resolution"), tr("Unchecked"),
|
||||
tr("Shows the resolution of the game in the top-right corner of the display."));
|
||||
dialog->registerWidgetHelp(
|
||||
m_ui.showInput, tr("Show Controller Input"), tr("Unchecked"),
|
||||
tr("Shows the current controller state of the system in the bottom-left corner of the display."));
|
||||
|
||||
#ifdef _WIN32
|
||||
{
|
||||
|
|
|
@ -209,6 +209,13 @@
|
|||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="1">
|
||||
<widget class="QCheckBox" name="showInput">
|
||||
<property name="text">
|
||||
<string>Show Controller Input</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
|
|
|
@ -17,8 +17,10 @@ add_library(frontend-common
|
|||
icon.h
|
||||
ini_settings_interface.cpp
|
||||
ini_settings_interface.h
|
||||
imgui_fullscreen.h
|
||||
input_overlay_ui.cpp
|
||||
input_overlay_ui.h
|
||||
imgui_fullscreen.cpp
|
||||
imgui_fullscreen.h
|
||||
imgui_impl_opengl3.cpp
|
||||
imgui_impl_opengl3.h
|
||||
imgui_impl_vulkan.cpp
|
||||
|
|
|
@ -28,6 +28,7 @@
|
|||
#include "imgui_fullscreen.h"
|
||||
#include "imgui_styles.h"
|
||||
#include "ini_settings_interface.h"
|
||||
#include "input_overlay_ui.h"
|
||||
#include "save_state_selector_ui.h"
|
||||
#include "scmversion/scmversion.h"
|
||||
#include <cmath>
|
||||
|
@ -57,6 +58,7 @@
|
|||
Log_SetChannel(CommonHostInterface);
|
||||
|
||||
static std::string s_settings_filename;
|
||||
static std::unique_ptr<FrontendCommon::InputOverlayUI> s_input_overlay_ui;
|
||||
|
||||
CommonHostInterface::CommonHostInterface() = default;
|
||||
|
||||
|
@ -104,6 +106,8 @@ bool CommonHostInterface::Initialize()
|
|||
|
||||
void CommonHostInterface::Shutdown()
|
||||
{
|
||||
s_input_overlay_ui.reset();
|
||||
|
||||
HostInterface::Shutdown();
|
||||
|
||||
ImGui::DestroyContext();
|
||||
|
@ -1038,6 +1042,9 @@ void CommonHostInterface::DrawImGuiWindows()
|
|||
if (m_save_state_selector_ui->IsOpen())
|
||||
m_save_state_selector_ui->Draw();
|
||||
|
||||
if (s_input_overlay_ui)
|
||||
s_input_overlay_ui->Draw();
|
||||
|
||||
if (m_fullscreen_ui_enabled)
|
||||
{
|
||||
FullscreenUI::Render();
|
||||
|
@ -1210,11 +1217,6 @@ void CommonHostInterface::DrawOSDMessages()
|
|||
{
|
||||
AcquirePendingOSDMessages();
|
||||
|
||||
constexpr ImGuiWindowFlags window_flags = ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoInputs |
|
||||
ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoSavedSettings |
|
||||
ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_NoNav |
|
||||
ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoFocusOnAppearing;
|
||||
|
||||
const float scale = ImGui::GetIO().DisplayFramebufferScale.x;
|
||||
const float spacing = 5.0f * scale;
|
||||
const float margin = 10.0f * scale;
|
||||
|
@ -2639,6 +2641,13 @@ void CommonHostInterface::LoadSettings(SettingsInterface& si)
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
const bool input_display_enabled = si.GetBoolValue("Display", "ShowInputs", false);
|
||||
const bool input_display_state = static_cast<bool>(s_input_overlay_ui);
|
||||
if (input_display_enabled && !s_input_overlay_ui)
|
||||
s_input_overlay_ui = std::make_unique<FrontendCommon::InputOverlayUI>();
|
||||
else if (!input_display_enabled && s_input_overlay_ui)
|
||||
s_input_overlay_ui.reset();
|
||||
}
|
||||
|
||||
void CommonHostInterface::SaveSettings(SettingsInterface& si)
|
||||
|
|
|
@ -104,6 +104,7 @@
|
|||
<ClCompile Include="imgui_impl_vulkan.cpp" />
|
||||
<ClCompile Include="imgui_styles.cpp" />
|
||||
<ClCompile Include="ini_settings_interface.cpp" />
|
||||
<ClCompile Include="input_overlay_ui.cpp" />
|
||||
<ClCompile Include="opengl_host_display.cpp" />
|
||||
<ClCompile Include="postprocessing_chain.cpp" />
|
||||
<ClCompile Include="postprocessing_shader.cpp" />
|
||||
|
@ -135,6 +136,7 @@
|
|||
<ClInclude Include="imgui_impl_vulkan.h" />
|
||||
<ClInclude Include="imgui_styles.h" />
|
||||
<ClInclude Include="ini_settings_interface.h" />
|
||||
<ClInclude Include="input_overlay_ui.h" />
|
||||
<ClInclude Include="opengl_host_display.h" />
|
||||
<ClInclude Include="postprocessing_chain.h" />
|
||||
<ClInclude Include="postprocessing_shader.h" />
|
||||
|
|
|
@ -30,6 +30,7 @@
|
|||
<ClCompile Include="cheevos.cpp" />
|
||||
<ClCompile Include="http_downloader.cpp" />
|
||||
<ClCompile Include="http_downloader_winhttp.cpp" />
|
||||
<ClCompile Include="input_overlay_ui.cpp" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="icon.h" />
|
||||
|
@ -61,6 +62,7 @@
|
|||
<ClInclude Include="cheevos.h" />
|
||||
<ClInclude Include="http_downloader.h" />
|
||||
<ClInclude Include="http_downloader_winhttp.h" />
|
||||
<ClInclude Include="input_overlay_ui.h" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="font_roboto_regular.inl" />
|
||||
|
|
|
@ -1980,6 +1980,10 @@ void DrawSettingsWindow()
|
|||
ToggleButton("Show Resolution",
|
||||
"Shows the current rendering resolution of the system in the top-right corner of the display.",
|
||||
&s_settings_copy.display_show_resolution);
|
||||
settings_changed |= ToggleButtonForNonSetting(
|
||||
"Show Controller Input",
|
||||
"Shows the current controller state of the system in the bottom-left corner of the display.", "Display",
|
||||
"ShowInputs", false);
|
||||
|
||||
EndMenuButtons();
|
||||
}
|
||||
|
|
118
src/frontend-common/input_overlay_ui.cpp
Normal file
118
src/frontend-common/input_overlay_ui.cpp
Normal file
|
@ -0,0 +1,118 @@
|
|||
#include "input_overlay_ui.h"
|
||||
#include "common_host_interface.h"
|
||||
#include "core/pad.h"
|
||||
#include "core/settings.h"
|
||||
#include "core/system.h"
|
||||
#include "fullscreen_ui.h"
|
||||
#include "imgui_fullscreen.h"
|
||||
|
||||
static CommonHostInterface* GetHostInterface()
|
||||
{
|
||||
return static_cast<CommonHostInterface*>(g_host_interface);
|
||||
}
|
||||
|
||||
namespace FrontendCommon {
|
||||
|
||||
InputOverlayUI::InputOverlayUI() = default;
|
||||
|
||||
InputOverlayUI::~InputOverlayUI() = default;
|
||||
|
||||
void InputOverlayUI::Draw()
|
||||
{
|
||||
UpdateNames();
|
||||
|
||||
if (m_active_ports == 0)
|
||||
return;
|
||||
|
||||
ImFont* font;
|
||||
float margin, spacing, shadow_offset;
|
||||
|
||||
if (GetHostInterface()->IsFullscreenUIEnabled())
|
||||
{
|
||||
font = ImGuiFullscreen::g_large_font;
|
||||
margin = ImGuiFullscreen::LayoutScale(10.0f);
|
||||
spacing = ImGuiFullscreen::LayoutScale(5.0f);
|
||||
shadow_offset = ImGuiFullscreen::LayoutScale(1.0f);
|
||||
}
|
||||
else
|
||||
{
|
||||
font = ImGui::GetFont();
|
||||
margin = ImGuiFullscreen::DPIScale(10.0f);
|
||||
spacing = ImGuiFullscreen::DPIScale(5.0f);
|
||||
shadow_offset = ImGuiFullscreen::DPIScale(1.0f);
|
||||
}
|
||||
|
||||
static constexpr u32 text_color = IM_COL32(0xff, 0xff, 0xff, 255);
|
||||
static constexpr u32 shadow_color = IM_COL32(0x00, 0x00, 0x00, 100);
|
||||
|
||||
const ImVec2& display_size = ImGui::GetIO().DisplaySize;
|
||||
ImDrawList* dl = ImGui::GetBackgroundDrawList();
|
||||
|
||||
float current_x = margin;
|
||||
float current_y =
|
||||
display_size.y - margin - ((static_cast<float>(m_active_ports) * (font->FontSize + spacing)) - spacing);
|
||||
|
||||
const ImVec4 clip_rect(current_x, current_y, display_size.x - margin, display_size.y - margin);
|
||||
|
||||
LargeString text;
|
||||
|
||||
for (u32 port = 0; port < NUM_CONTROLLER_AND_CARD_PORTS; port++)
|
||||
{
|
||||
if (m_types[port] == ControllerType::None)
|
||||
continue;
|
||||
|
||||
const Controller* controller = g_pad.GetController(port);
|
||||
DebugAssert(controller);
|
||||
|
||||
text.Format("P%u |", port + 1u);
|
||||
|
||||
if (!m_axis_names[port].empty())
|
||||
{
|
||||
for (const auto& [axis_name, axis_code, axis_type] : m_axis_names[port])
|
||||
{
|
||||
const float value = controller->GetAxisState(axis_code);
|
||||
text.AppendFormattedString(" %s: %.2f", axis_name.c_str(), value);
|
||||
}
|
||||
|
||||
text.AppendString(" |");
|
||||
}
|
||||
|
||||
for (const auto& [button_name, button_code] : m_button_names[port])
|
||||
{
|
||||
const bool pressed = controller->GetButtonState(button_code);
|
||||
if (pressed)
|
||||
text.AppendFormattedString(" %s", button_name.c_str());
|
||||
}
|
||||
|
||||
dl->AddText(font, font->FontSize, ImVec2(current_x + shadow_offset, current_y + shadow_offset), shadow_color,
|
||||
text.GetCharArray(), text.GetCharArray() + text.GetLength(), 0.0f, &clip_rect);
|
||||
dl->AddText(font, font->FontSize, ImVec2(current_x, current_y), text_color, text.GetCharArray(),
|
||||
text.GetCharArray() + text.GetLength(), 0.0f, &clip_rect);
|
||||
|
||||
current_y += font->FontSize + spacing;
|
||||
}
|
||||
}
|
||||
|
||||
void InputOverlayUI::UpdateNames()
|
||||
{
|
||||
m_active_ports = 0;
|
||||
if (!System::IsValid())
|
||||
return;
|
||||
|
||||
for (u32 port = 0; port < NUM_CONTROLLER_AND_CARD_PORTS; port++)
|
||||
{
|
||||
const Controller* controller = g_pad.GetController(port);
|
||||
const ControllerType type = (controller) ? controller->GetType() : ControllerType::None;
|
||||
if (type != ControllerType::None)
|
||||
m_active_ports++;
|
||||
|
||||
if (type == m_types[port])
|
||||
continue;
|
||||
|
||||
m_axis_names[port] = Controller::GetAxisNames(type);
|
||||
m_button_names[port] = Controller::GetButtonNames(type);
|
||||
m_types[port] = type;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace FrontendCommon
|
24
src/frontend-common/input_overlay_ui.h
Normal file
24
src/frontend-common/input_overlay_ui.h
Normal file
|
@ -0,0 +1,24 @@
|
|||
#pragma once
|
||||
#include "core/controller.h"
|
||||
#include <array>
|
||||
|
||||
namespace FrontendCommon {
|
||||
|
||||
class InputOverlayUI
|
||||
{
|
||||
public:
|
||||
InputOverlayUI();
|
||||
~InputOverlayUI();
|
||||
|
||||
void Draw();
|
||||
|
||||
private:
|
||||
void UpdateNames();
|
||||
|
||||
std::array<Controller::AxisList, NUM_CONTROLLER_AND_CARD_PORTS> m_axis_names;
|
||||
std::array<Controller::ButtonList, NUM_CONTROLLER_AND_CARD_PORTS> m_button_names;
|
||||
std::array<ControllerType, NUM_CONTROLLER_AND_CARD_PORTS> m_types{};
|
||||
u32 m_active_ports = 0;
|
||||
};
|
||||
|
||||
} // namespace FrontendCommon
|
Loading…
Reference in a new issue