OSD: Add controller input display overlay

This commit is contained in:
Connor McLaughlin
2021-04-04 03:51:08 +10:00
parent a9a571cd6a
commit 251043f11a
25 changed files with 293 additions and 12 deletions

View File

@ -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

View File

@ -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)

View File

@ -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" />

View File

@ -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" />

View File

@ -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();
}

View 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

View 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