2022-12-04 11:03:45 +00:00
|
|
|
// SPDX-FileCopyrightText: 2019-2022 Connor McLaughlin <stenzek@gmail.com>
|
|
|
|
// SPDX-License-Identifier: (GPL-3.0 OR CC-BY-NC-ND-4.0)
|
|
|
|
|
2022-07-11 13:03:29 +00:00
|
|
|
#include "imgui_manager.h"
|
|
|
|
#include "IconsFontAwesome5.h"
|
|
|
|
#include "common/assert.h"
|
|
|
|
#include "common/file_system.h"
|
|
|
|
#include "common/log.h"
|
|
|
|
#include "common/string_util.h"
|
|
|
|
#include "common/timer.h"
|
|
|
|
#include "common_host.h"
|
|
|
|
#include "core/gpu.h"
|
|
|
|
#include "core/host.h"
|
|
|
|
#include "core/host_display.h"
|
|
|
|
#include "core/system.h"
|
|
|
|
#include "fmt/format.h"
|
|
|
|
#include "fullscreen_ui.h"
|
|
|
|
#include "imgui.h"
|
|
|
|
#include "imgui_fullscreen.h"
|
|
|
|
#include "imgui_internal.h"
|
|
|
|
#include "input_manager.h"
|
|
|
|
#include <atomic>
|
|
|
|
#include <chrono>
|
|
|
|
#include <cmath>
|
|
|
|
#include <deque>
|
|
|
|
#include <mutex>
|
|
|
|
#include <unordered_map>
|
|
|
|
|
|
|
|
Log_SetChannel(ImGuiManager);
|
|
|
|
|
|
|
|
namespace ImGuiManager {
|
|
|
|
static void SetStyle();
|
|
|
|
static void SetKeyMap();
|
|
|
|
static bool LoadFontData();
|
|
|
|
static bool AddImGuiFonts(bool fullscreen_fonts);
|
2022-08-13 03:46:58 +00:00
|
|
|
static ImFont* AddTextFont(float size);
|
2022-07-11 13:03:29 +00:00
|
|
|
static ImFont* AddFixedFont(float size);
|
|
|
|
static bool AddIconFonts(float size);
|
|
|
|
static void AcquirePendingOSDMessages();
|
|
|
|
static void DrawOSDMessages();
|
|
|
|
} // namespace ImGuiManager
|
|
|
|
|
|
|
|
static float s_global_scale = 1.0f;
|
|
|
|
|
|
|
|
static std::string s_font_path;
|
|
|
|
static const ImWchar* s_font_range = nullptr;
|
|
|
|
|
|
|
|
static ImFont* s_standard_font;
|
|
|
|
static ImFont* s_fixed_font;
|
|
|
|
static ImFont* s_medium_font;
|
|
|
|
static ImFont* s_large_font;
|
|
|
|
|
|
|
|
static std::vector<u8> s_standard_font_data;
|
|
|
|
static std::vector<u8> s_fixed_font_data;
|
|
|
|
static std::vector<u8> s_icon_font_data;
|
|
|
|
|
|
|
|
static Common::Timer s_last_render_time;
|
|
|
|
|
|
|
|
// cached copies of WantCaptureKeyboard/Mouse, used to know when to dispatch events
|
|
|
|
static std::atomic_bool s_imgui_wants_keyboard{false};
|
|
|
|
static std::atomic_bool s_imgui_wants_mouse{false};
|
|
|
|
|
|
|
|
// mapping of host key -> imgui key
|
|
|
|
static std::unordered_map<u32, ImGuiKey> s_imgui_key_map;
|
|
|
|
|
|
|
|
void ImGuiManager::SetFontPath(std::string path)
|
|
|
|
{
|
|
|
|
s_font_path = std::move(path);
|
|
|
|
s_standard_font_data = {};
|
|
|
|
}
|
|
|
|
|
|
|
|
void ImGuiManager::SetFontRange(const u16* range)
|
|
|
|
{
|
|
|
|
s_font_range = range;
|
|
|
|
s_standard_font_data = {};
|
|
|
|
}
|
|
|
|
|
|
|
|
bool ImGuiManager::Initialize()
|
|
|
|
{
|
|
|
|
if (!LoadFontData())
|
|
|
|
{
|
|
|
|
Panic("Failed to load font data");
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
s_global_scale =
|
2022-07-28 10:08:54 +00:00
|
|
|
std::max(g_host_display->GetWindowScale() * static_cast<float>(g_settings.display_osd_scale / 100.0f), 1.0f);
|
2022-07-11 13:03:29 +00:00
|
|
|
|
|
|
|
ImGui::CreateContext();
|
|
|
|
|
|
|
|
ImGuiIO& io = ImGui::GetIO();
|
|
|
|
io.IniFilename = nullptr;
|
|
|
|
io.BackendFlags |= ImGuiBackendFlags_HasGamepad;
|
|
|
|
io.BackendUsingLegacyKeyArrays = 0;
|
|
|
|
io.BackendUsingLegacyNavInputArray = 0;
|
|
|
|
#ifndef __ANDROID__
|
|
|
|
// Android has no keyboard, nor are we using ImGui for any actual user-interactable windows.
|
|
|
|
io.ConfigFlags |=
|
|
|
|
ImGuiConfigFlags_NavEnableKeyboard | ImGuiConfigFlags_NavEnableGamepad | ImGuiConfigFlags_NoMouseCursorChange;
|
|
|
|
#else
|
|
|
|
io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard | ImGuiConfigFlags_NavEnableGamepad;
|
|
|
|
#endif
|
|
|
|
|
|
|
|
io.DisplayFramebufferScale = ImVec2(1, 1); // We already scale things ourselves, this would double-apply scaling
|
|
|
|
io.DisplaySize.x = static_cast<float>(g_host_display->GetWindowWidth());
|
|
|
|
io.DisplaySize.y = static_cast<float>(g_host_display->GetWindowHeight());
|
|
|
|
|
|
|
|
SetKeyMap();
|
|
|
|
SetStyle();
|
|
|
|
|
|
|
|
AssertMsg(!FullscreenUI::IsInitialized(), "Fullscreen UI is not initialized on ImGui init");
|
|
|
|
|
|
|
|
if (!g_host_display->CreateImGuiContext())
|
|
|
|
{
|
|
|
|
Panic("Failed to create ImGui device context");
|
|
|
|
g_host_display->DestroyImGuiContext();
|
|
|
|
ImGui::DestroyContext();
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!AddImGuiFonts(false) || !g_host_display->UpdateImGuiFontTexture())
|
|
|
|
{
|
|
|
|
Panic("Failed to create ImGui font text");
|
|
|
|
g_host_display->DestroyImGuiContext();
|
|
|
|
ImGui::DestroyContext();
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
// don't need the font data anymore, save some memory
|
|
|
|
ImGui::GetIO().Fonts->ClearTexData();
|
|
|
|
|
|
|
|
NewFrame();
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
void ImGuiManager::Shutdown()
|
|
|
|
{
|
|
|
|
FullscreenUI::Shutdown();
|
|
|
|
|
|
|
|
if (g_host_display)
|
|
|
|
g_host_display->DestroyImGuiContext();
|
|
|
|
if (ImGui::GetCurrentContext())
|
|
|
|
ImGui::DestroyContext();
|
|
|
|
|
|
|
|
s_standard_font = nullptr;
|
|
|
|
s_fixed_font = nullptr;
|
|
|
|
s_medium_font = nullptr;
|
|
|
|
s_large_font = nullptr;
|
|
|
|
ImGuiFullscreen::SetFonts(nullptr, nullptr, nullptr);
|
|
|
|
}
|
|
|
|
|
|
|
|
void ImGuiManager::WindowResized()
|
|
|
|
{
|
|
|
|
const u32 new_width = g_host_display ? g_host_display->GetWindowWidth() : 0;
|
|
|
|
const u32 new_height = g_host_display ? g_host_display->GetWindowHeight() : 0;
|
|
|
|
|
|
|
|
ImGui::GetIO().DisplaySize = ImVec2(static_cast<float>(new_width), static_cast<float>(new_height));
|
|
|
|
|
|
|
|
UpdateScale();
|
|
|
|
|
|
|
|
// restart imgui frame on the new window size to pick it up, otherwise we draw to the old size
|
|
|
|
ImGui::EndFrame();
|
|
|
|
NewFrame();
|
|
|
|
}
|
|
|
|
|
|
|
|
void ImGuiManager::UpdateScale()
|
|
|
|
{
|
|
|
|
const float window_scale = g_host_display ? g_host_display->GetWindowScale() : 1.0f;
|
2022-07-28 10:08:54 +00:00
|
|
|
const float scale = std::max(window_scale * static_cast<float>(g_settings.display_osd_scale / 100.0f), 1.0f);
|
2022-07-11 13:03:29 +00:00
|
|
|
|
|
|
|
if (scale == s_global_scale && (!HasFullscreenFonts() || !ImGuiFullscreen::UpdateLayoutScale()))
|
|
|
|
return;
|
|
|
|
|
|
|
|
// This is assumed to be called mid-frame.
|
|
|
|
ImGui::EndFrame();
|
|
|
|
|
|
|
|
s_global_scale = scale;
|
|
|
|
|
|
|
|
ImGui::GetStyle() = ImGuiStyle();
|
|
|
|
ImGui::GetStyle().WindowMinSize = ImVec2(1.0f, 1.0f);
|
|
|
|
SetStyle();
|
|
|
|
ImGui::GetStyle().ScaleAllSizes(scale);
|
|
|
|
|
|
|
|
if (!AddImGuiFonts(HasFullscreenFonts()))
|
|
|
|
Panic("Failed to create ImGui font text");
|
|
|
|
|
|
|
|
if (!g_host_display->UpdateImGuiFontTexture())
|
|
|
|
Panic("Failed to recreate font texture after scale+resize");
|
|
|
|
|
|
|
|
NewFrame();
|
|
|
|
}
|
|
|
|
|
|
|
|
void ImGuiManager::NewFrame()
|
|
|
|
{
|
|
|
|
ImGuiIO& io = ImGui::GetIO();
|
|
|
|
io.DeltaTime = static_cast<float>(s_last_render_time.GetTimeSecondsAndReset());
|
|
|
|
|
|
|
|
ImGui::NewFrame();
|
|
|
|
|
|
|
|
// Disable nav input on the implicit (Debug##Default) window. Otherwise we end up requesting keyboard
|
|
|
|
// focus when there's nothing there. We use GetCurrentWindowRead() because otherwise it'll make it visible.
|
|
|
|
ImGui::GetCurrentWindowRead()->Flags |= ImGuiWindowFlags_NoNavInputs;
|
|
|
|
s_imgui_wants_keyboard.store(io.WantCaptureKeyboard, std::memory_order_relaxed);
|
|
|
|
s_imgui_wants_mouse.store(io.WantCaptureMouse, std::memory_order_release);
|
|
|
|
}
|
|
|
|
|
|
|
|
void ImGuiManager::SetStyle()
|
|
|
|
{
|
|
|
|
ImGuiStyle& style = ImGui::GetStyle();
|
|
|
|
style = ImGuiStyle();
|
|
|
|
style.WindowMinSize = ImVec2(1.0f, 1.0f);
|
|
|
|
|
|
|
|
ImVec4* colors = style.Colors;
|
|
|
|
colors[ImGuiCol_Text] = ImVec4(0.95f, 0.96f, 0.98f, 1.00f);
|
|
|
|
colors[ImGuiCol_TextDisabled] = ImVec4(0.36f, 0.42f, 0.47f, 1.00f);
|
|
|
|
colors[ImGuiCol_WindowBg] = ImVec4(0.11f, 0.15f, 0.17f, 1.00f);
|
|
|
|
colors[ImGuiCol_ChildBg] = ImVec4(0.15f, 0.18f, 0.22f, 1.00f);
|
|
|
|
colors[ImGuiCol_PopupBg] = ImVec4(0.08f, 0.08f, 0.08f, 0.94f);
|
|
|
|
colors[ImGuiCol_Border] = ImVec4(0.08f, 0.10f, 0.12f, 1.00f);
|
|
|
|
colors[ImGuiCol_BorderShadow] = ImVec4(0.00f, 0.00f, 0.00f, 0.00f);
|
|
|
|
colors[ImGuiCol_FrameBg] = ImVec4(0.20f, 0.25f, 0.29f, 1.00f);
|
|
|
|
colors[ImGuiCol_FrameBgHovered] = ImVec4(0.12f, 0.20f, 0.28f, 1.00f);
|
|
|
|
colors[ImGuiCol_FrameBgActive] = ImVec4(0.09f, 0.12f, 0.14f, 1.00f);
|
|
|
|
colors[ImGuiCol_TitleBg] = ImVec4(0.09f, 0.12f, 0.14f, 0.65f);
|
|
|
|
colors[ImGuiCol_TitleBgActive] = ImVec4(0.08f, 0.10f, 0.12f, 1.00f);
|
|
|
|
colors[ImGuiCol_TitleBgCollapsed] = ImVec4(0.00f, 0.00f, 0.00f, 0.51f);
|
|
|
|
colors[ImGuiCol_MenuBarBg] = ImVec4(0.15f, 0.18f, 0.22f, 1.00f);
|
|
|
|
colors[ImGuiCol_ScrollbarBg] = ImVec4(0.02f, 0.02f, 0.02f, 0.39f);
|
|
|
|
colors[ImGuiCol_ScrollbarGrab] = ImVec4(0.20f, 0.25f, 0.29f, 1.00f);
|
|
|
|
colors[ImGuiCol_ScrollbarGrabHovered] = ImVec4(0.18f, 0.22f, 0.25f, 1.00f);
|
|
|
|
colors[ImGuiCol_ScrollbarGrabActive] = ImVec4(0.09f, 0.21f, 0.31f, 1.00f);
|
|
|
|
colors[ImGuiCol_CheckMark] = ImVec4(0.28f, 0.56f, 1.00f, 1.00f);
|
|
|
|
colors[ImGuiCol_SliderGrab] = ImVec4(0.28f, 0.56f, 1.00f, 1.00f);
|
|
|
|
colors[ImGuiCol_SliderGrabActive] = ImVec4(0.37f, 0.61f, 1.00f, 1.00f);
|
|
|
|
colors[ImGuiCol_Button] = ImVec4(0.20f, 0.25f, 0.29f, 1.00f);
|
|
|
|
colors[ImGuiCol_ButtonHovered] = ImVec4(0.33f, 0.38f, 0.46f, 1.00f);
|
|
|
|
colors[ImGuiCol_ButtonActive] = ImVec4(0.27f, 0.32f, 0.38f, 1.00f);
|
|
|
|
colors[ImGuiCol_Header] = ImVec4(0.20f, 0.25f, 0.29f, 0.55f);
|
|
|
|
colors[ImGuiCol_HeaderHovered] = ImVec4(0.33f, 0.38f, 0.46f, 1.00f);
|
|
|
|
colors[ImGuiCol_HeaderActive] = ImVec4(0.27f, 0.32f, 0.38f, 1.00f);
|
|
|
|
colors[ImGuiCol_Separator] = ImVec4(0.20f, 0.25f, 0.29f, 1.00f);
|
|
|
|
colors[ImGuiCol_SeparatorHovered] = ImVec4(0.33f, 0.38f, 0.46f, 1.00f);
|
|
|
|
colors[ImGuiCol_SeparatorActive] = ImVec4(0.27f, 0.32f, 0.38f, 1.00f);
|
|
|
|
colors[ImGuiCol_ResizeGrip] = ImVec4(0.26f, 0.59f, 0.98f, 0.25f);
|
|
|
|
colors[ImGuiCol_ResizeGripHovered] = ImVec4(0.33f, 0.38f, 0.46f, 1.00f);
|
|
|
|
colors[ImGuiCol_ResizeGripActive] = ImVec4(0.27f, 0.32f, 0.38f, 1.00f);
|
|
|
|
colors[ImGuiCol_Tab] = ImVec4(0.11f, 0.15f, 0.17f, 1.00f);
|
|
|
|
colors[ImGuiCol_TabHovered] = ImVec4(0.33f, 0.38f, 0.46f, 1.00f);
|
|
|
|
colors[ImGuiCol_TabActive] = ImVec4(0.27f, 0.32f, 0.38f, 1.00f);
|
|
|
|
colors[ImGuiCol_TabUnfocused] = ImVec4(0.11f, 0.15f, 0.17f, 1.00f);
|
|
|
|
colors[ImGuiCol_TabUnfocusedActive] = ImVec4(0.11f, 0.15f, 0.17f, 1.00f);
|
|
|
|
colors[ImGuiCol_PlotLines] = ImVec4(0.61f, 0.61f, 0.61f, 1.00f);
|
|
|
|
colors[ImGuiCol_PlotLinesHovered] = ImVec4(1.00f, 0.43f, 0.35f, 1.00f);
|
|
|
|
colors[ImGuiCol_PlotHistogram] = ImVec4(0.90f, 0.70f, 0.00f, 1.00f);
|
|
|
|
colors[ImGuiCol_PlotHistogramHovered] = ImVec4(1.00f, 0.60f, 0.00f, 1.00f);
|
|
|
|
colors[ImGuiCol_TextSelectedBg] = ImVec4(0.26f, 0.59f, 0.98f, 0.35f);
|
|
|
|
colors[ImGuiCol_DragDropTarget] = ImVec4(1.00f, 1.00f, 0.00f, 0.90f);
|
|
|
|
colors[ImGuiCol_NavHighlight] = ImVec4(0.26f, 0.59f, 0.98f, 1.00f);
|
|
|
|
colors[ImGuiCol_NavWindowingHighlight] = ImVec4(1.00f, 1.00f, 1.00f, 0.70f);
|
|
|
|
colors[ImGuiCol_NavWindowingDimBg] = ImVec4(0.80f, 0.80f, 0.80f, 0.20f);
|
|
|
|
colors[ImGuiCol_ModalWindowDimBg] = ImVec4(0.80f, 0.80f, 0.80f, 0.35f);
|
|
|
|
|
|
|
|
style.ScaleAllSizes(s_global_scale);
|
|
|
|
}
|
|
|
|
|
|
|
|
void ImGuiManager::SetKeyMap()
|
|
|
|
{
|
|
|
|
struct KeyMapping
|
|
|
|
{
|
|
|
|
int index;
|
|
|
|
const char* name;
|
|
|
|
const char* alt_name;
|
|
|
|
};
|
|
|
|
|
|
|
|
static constexpr KeyMapping mapping[] = {{ImGuiKey_LeftArrow, "Left"},
|
|
|
|
{ImGuiKey_RightArrow, "Right"},
|
|
|
|
{ImGuiKey_UpArrow, "Up"},
|
|
|
|
{ImGuiKey_DownArrow, "Down"},
|
|
|
|
{ImGuiKey_PageUp, "PageUp"},
|
|
|
|
{ImGuiKey_PageDown, "PageDown"},
|
|
|
|
{ImGuiKey_Home, "Home"},
|
|
|
|
{ImGuiKey_End, "End"},
|
|
|
|
{ImGuiKey_Insert, "Insert"},
|
|
|
|
{ImGuiKey_Delete, "Delete"},
|
|
|
|
{ImGuiKey_Backspace, "Backspace"},
|
|
|
|
{ImGuiKey_Space, "Space"},
|
|
|
|
{ImGuiKey_Enter, "Return"},
|
|
|
|
{ImGuiKey_Escape, "Escape"},
|
|
|
|
{ImGuiKey_LeftCtrl, "LeftCtrl", "Ctrl"},
|
|
|
|
{ImGuiKey_LeftShift, "LeftShift", "Shift"},
|
|
|
|
{ImGuiKey_LeftAlt, "LeftAlt", "Alt"},
|
|
|
|
{ImGuiKey_LeftSuper, "LeftSuper", "Super"},
|
|
|
|
{ImGuiKey_RightCtrl, "RightCtrl"},
|
|
|
|
{ImGuiKey_RightShift, "RightShift"},
|
|
|
|
{ImGuiKey_RightAlt, "RightAlt"},
|
|
|
|
{ImGuiKey_RightSuper, "RightSuper"},
|
|
|
|
{ImGuiKey_Menu, "Menu"},
|
|
|
|
{ImGuiKey_0, "0"},
|
|
|
|
{ImGuiKey_1, "1"},
|
|
|
|
{ImGuiKey_2, "2"},
|
|
|
|
{ImGuiKey_3, "3"},
|
|
|
|
{ImGuiKey_4, "4"},
|
|
|
|
{ImGuiKey_5, "5"},
|
|
|
|
{ImGuiKey_6, "6"},
|
|
|
|
{ImGuiKey_7, "7"},
|
|
|
|
{ImGuiKey_8, "8"},
|
|
|
|
{ImGuiKey_9, "9"},
|
|
|
|
{ImGuiKey_A, "A"},
|
|
|
|
{ImGuiKey_B, "B"},
|
|
|
|
{ImGuiKey_C, "C"},
|
|
|
|
{ImGuiKey_D, "D"},
|
|
|
|
{ImGuiKey_E, "E"},
|
|
|
|
{ImGuiKey_F, "F"},
|
|
|
|
{ImGuiKey_G, "G"},
|
|
|
|
{ImGuiKey_H, "H"},
|
|
|
|
{ImGuiKey_I, "I"},
|
|
|
|
{ImGuiKey_J, "J"},
|
|
|
|
{ImGuiKey_K, "K"},
|
|
|
|
{ImGuiKey_L, "L"},
|
|
|
|
{ImGuiKey_M, "M"},
|
|
|
|
{ImGuiKey_N, "N"},
|
|
|
|
{ImGuiKey_O, "O"},
|
|
|
|
{ImGuiKey_P, "P"},
|
|
|
|
{ImGuiKey_Q, "Q"},
|
|
|
|
{ImGuiKey_R, "R"},
|
|
|
|
{ImGuiKey_S, "S"},
|
|
|
|
{ImGuiKey_T, "T"},
|
|
|
|
{ImGuiKey_U, "U"},
|
|
|
|
{ImGuiKey_V, "V"},
|
|
|
|
{ImGuiKey_W, "W"},
|
|
|
|
{ImGuiKey_X, "X"},
|
|
|
|
{ImGuiKey_Y, "Y"},
|
|
|
|
{ImGuiKey_Z, "Z"},
|
|
|
|
{ImGuiKey_F1, "F1"},
|
|
|
|
{ImGuiKey_F2, "F2"},
|
|
|
|
{ImGuiKey_F3, "F3"},
|
|
|
|
{ImGuiKey_F4, "F4"},
|
|
|
|
{ImGuiKey_F5, "F5"},
|
|
|
|
{ImGuiKey_F6, "F6"},
|
|
|
|
{ImGuiKey_F7, "F7"},
|
|
|
|
{ImGuiKey_F8, "F8"},
|
|
|
|
{ImGuiKey_F9, "F9"},
|
|
|
|
{ImGuiKey_F10, "F10"},
|
|
|
|
{ImGuiKey_F11, "F11"},
|
|
|
|
{ImGuiKey_F12, "F12"},
|
|
|
|
{ImGuiKey_Apostrophe, "Apostrophe"},
|
|
|
|
{ImGuiKey_Comma, "Comma"},
|
|
|
|
{ImGuiKey_Minus, "Minus"},
|
|
|
|
{ImGuiKey_Period, "Period"},
|
|
|
|
{ImGuiKey_Slash, "Slash"},
|
|
|
|
{ImGuiKey_Semicolon, "Semicolon"},
|
|
|
|
{ImGuiKey_Equal, "Equal"},
|
|
|
|
{ImGuiKey_LeftBracket, "BracketLeft"},
|
|
|
|
{ImGuiKey_Backslash, "Backslash"},
|
|
|
|
{ImGuiKey_RightBracket, "BracketRight"},
|
|
|
|
{ImGuiKey_GraveAccent, "QuoteLeft"},
|
|
|
|
{ImGuiKey_CapsLock, "CapsLock"},
|
|
|
|
{ImGuiKey_ScrollLock, "ScrollLock"},
|
|
|
|
{ImGuiKey_NumLock, "NumLock"},
|
|
|
|
{ImGuiKey_PrintScreen, "PrintScreen"},
|
|
|
|
{ImGuiKey_Pause, "Pause"},
|
|
|
|
{ImGuiKey_Keypad0, "Keypad0"},
|
|
|
|
{ImGuiKey_Keypad1, "Keypad1"},
|
|
|
|
{ImGuiKey_Keypad2, "Keypad2"},
|
|
|
|
{ImGuiKey_Keypad3, "Keypad3"},
|
|
|
|
{ImGuiKey_Keypad4, "Keypad4"},
|
|
|
|
{ImGuiKey_Keypad5, "Keypad5"},
|
|
|
|
{ImGuiKey_Keypad6, "Keypad6"},
|
|
|
|
{ImGuiKey_Keypad7, "Keypad7"},
|
|
|
|
{ImGuiKey_Keypad8, "Keypad8"},
|
|
|
|
{ImGuiKey_Keypad9, "Keypad9"},
|
|
|
|
{ImGuiKey_KeypadDecimal, "KeypadPeriod"},
|
|
|
|
{ImGuiKey_KeypadDivide, "KeypadDivide"},
|
|
|
|
{ImGuiKey_KeypadMultiply, "KeypadMultiply"},
|
|
|
|
{ImGuiKey_KeypadSubtract, "KeypadMinus"},
|
|
|
|
{ImGuiKey_KeypadAdd, "KeypadPlus"},
|
|
|
|
{ImGuiKey_KeypadEnter, "KeypadReturn"},
|
|
|
|
{ImGuiKey_KeypadEqual, "KeypadEqual"}};
|
|
|
|
|
|
|
|
s_imgui_key_map.clear();
|
|
|
|
for (const KeyMapping& km : mapping)
|
|
|
|
{
|
|
|
|
std::optional<u32> map(InputManager::ConvertHostKeyboardStringToCode(km.name));
|
|
|
|
if (!map.has_value() && km.alt_name)
|
|
|
|
map = InputManager::ConvertHostKeyboardStringToCode(km.alt_name);
|
|
|
|
if (map.has_value())
|
|
|
|
s_imgui_key_map[map.value()] = km.index;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
bool ImGuiManager::LoadFontData()
|
|
|
|
{
|
|
|
|
if (s_standard_font_data.empty())
|
|
|
|
{
|
|
|
|
std::optional<std::vector<u8>> font_data = s_font_path.empty() ?
|
|
|
|
Host::ReadResourceFile("fonts/Roboto-Regular.ttf") :
|
|
|
|
FileSystem::ReadBinaryFile(s_font_path.c_str());
|
|
|
|
if (!font_data.has_value())
|
|
|
|
return false;
|
|
|
|
|
|
|
|
s_standard_font_data = std::move(font_data.value());
|
|
|
|
}
|
|
|
|
|
|
|
|
if (s_fixed_font_data.empty())
|
|
|
|
{
|
|
|
|
std::optional<std::vector<u8>> font_data = Host::ReadResourceFile("fonts/RobotoMono-Medium.ttf");
|
|
|
|
if (!font_data.has_value())
|
|
|
|
return false;
|
|
|
|
|
|
|
|
s_fixed_font_data = std::move(font_data.value());
|
|
|
|
}
|
|
|
|
|
|
|
|
if (s_icon_font_data.empty())
|
|
|
|
{
|
|
|
|
std::optional<std::vector<u8>> font_data = Host::ReadResourceFile("fonts/fa-solid-900.ttf");
|
|
|
|
if (!font_data.has_value())
|
|
|
|
return false;
|
|
|
|
|
|
|
|
s_icon_font_data = std::move(font_data.value());
|
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2022-08-13 03:46:58 +00:00
|
|
|
ImFont* ImGuiManager::AddTextFont(float size)
|
2022-07-11 13:03:29 +00:00
|
|
|
{
|
|
|
|
static const ImWchar default_ranges[] = {
|
|
|
|
// Basic Latin + Latin Supplement + Central European diacritics
|
|
|
|
0x0020,
|
|
|
|
0x017F,
|
|
|
|
|
|
|
|
// Cyrillic + Cyrillic Supplement
|
|
|
|
0x0400,
|
|
|
|
0x052F,
|
|
|
|
|
|
|
|
// Cyrillic Extended-A
|
|
|
|
0x2DE0,
|
|
|
|
0x2DFF,
|
|
|
|
|
|
|
|
// Cyrillic Extended-B
|
|
|
|
0xA640,
|
|
|
|
0xA69F,
|
|
|
|
|
|
|
|
0,
|
|
|
|
};
|
|
|
|
|
|
|
|
ImFontConfig cfg;
|
|
|
|
cfg.FontDataOwnedByAtlas = false;
|
|
|
|
return ImGui::GetIO().Fonts->AddFontFromMemoryTTF(s_standard_font_data.data(),
|
|
|
|
static_cast<int>(s_standard_font_data.size()), size, &cfg,
|
2022-08-13 03:46:58 +00:00
|
|
|
s_font_range ? s_font_range : default_ranges);
|
2022-07-11 13:03:29 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
ImFont* ImGuiManager::AddFixedFont(float size)
|
|
|
|
{
|
|
|
|
ImFontConfig cfg;
|
|
|
|
cfg.FontDataOwnedByAtlas = false;
|
|
|
|
return ImGui::GetIO().Fonts->AddFontFromMemoryTTF(s_fixed_font_data.data(),
|
|
|
|
static_cast<int>(s_fixed_font_data.size()), size, &cfg, nullptr);
|
|
|
|
}
|
|
|
|
|
|
|
|
bool ImGuiManager::AddIconFonts(float size)
|
|
|
|
{
|
2022-10-13 14:14:21 +00:00
|
|
|
static constexpr ImWchar range_fa[] = {
|
|
|
|
0xf002, 0xf002, 0xf005, 0xf005, 0xf007, 0xf007, 0xf00c, 0xf00e, 0xf011, 0xf011, 0xf013, 0xf013, 0xf017, 0xf017,
|
2022-11-05 05:01:48 +00:00
|
|
|
0xf019, 0xf019, 0xf01c, 0xf01c, 0xf021, 0xf021, 0xf023, 0xf023, 0xf025, 0xf025, 0xf027, 0xf028, 0xf02d, 0xf02e,
|
|
|
|
0xf030, 0xf030, 0xf03a, 0xf03a, 0xf03d, 0xf03d, 0xf049, 0xf04c, 0xf050, 0xf050, 0xf059, 0xf059, 0xf05e, 0xf05e,
|
|
|
|
0xf062, 0xf063, 0xf065, 0xf065, 0xf067, 0xf067, 0xf071, 0xf071, 0xf075, 0xf075, 0xf077, 0xf078, 0xf07b, 0xf07c,
|
|
|
|
0xf084, 0xf085, 0xf091, 0xf091, 0xf0a0, 0xf0a0, 0xf0ac, 0xf0ad, 0xf0c5, 0xf0c5, 0xf0c7, 0xf0c8, 0xf0cb, 0xf0cb,
|
|
|
|
0xf0d0, 0xf0d0, 0xf0dc, 0xf0dc, 0xf0e2, 0xf0e2, 0xf0eb, 0xf0eb, 0xf0f1, 0xf0f1, 0xf0f3, 0xf0f3, 0xf0fe, 0xf0fe,
|
|
|
|
0xf110, 0xf110, 0xf119, 0xf119, 0xf11b, 0xf11c, 0xf140, 0xf140, 0xf144, 0xf144, 0xf14a, 0xf14a, 0xf15b, 0xf15b,
|
|
|
|
0xf15d, 0xf15d, 0xf188, 0xf188, 0xf191, 0xf192, 0xf1dd, 0xf1de, 0xf1e6, 0xf1e6, 0xf1eb, 0xf1eb, 0xf1f8, 0xf1f8,
|
|
|
|
0xf1fc, 0xf1fc, 0xf242, 0xf242, 0xf245, 0xf245, 0xf26c, 0xf26c, 0xf279, 0xf279, 0xf2d0, 0xf2d0, 0xf2db, 0xf2db,
|
|
|
|
0xf2f2, 0xf2f2, 0xf2f5, 0xf2f5, 0xf3c1, 0xf3c1, 0xf410, 0xf410, 0xf466, 0xf466, 0xf500, 0xf500, 0xf51f, 0xf51f,
|
|
|
|
0xf545, 0xf545, 0xf548, 0xf548, 0xf552, 0xf552, 0xf57a, 0xf57a, 0xf5a2, 0xf5a2, 0xf5aa, 0xf5aa, 0xf5e7, 0xf5e7,
|
|
|
|
0xf65d, 0xf65e, 0xf6a9, 0xf6a9, 0xf7c2, 0xf7c2, 0xf807, 0xf807, 0xf815, 0xf815, 0xf818, 0xf818, 0xf84c, 0xf84c,
|
|
|
|
0xf8cc, 0xf8cc, 0x0, 0x0};
|
2022-07-11 13:03:29 +00:00
|
|
|
|
|
|
|
ImFontConfig cfg;
|
|
|
|
cfg.MergeMode = true;
|
|
|
|
cfg.PixelSnapH = true;
|
2022-09-03 03:39:59 +00:00
|
|
|
cfg.GlyphMinAdvanceX = size;
|
|
|
|
cfg.GlyphMaxAdvanceX = size;
|
2022-07-11 13:03:29 +00:00
|
|
|
cfg.FontDataOwnedByAtlas = false;
|
|
|
|
|
|
|
|
return (ImGui::GetIO().Fonts->AddFontFromMemoryTTF(s_icon_font_data.data(), static_cast<int>(s_icon_font_data.size()),
|
|
|
|
size * 0.75f, &cfg, range_fa) != nullptr);
|
|
|
|
}
|
|
|
|
|
|
|
|
bool ImGuiManager::AddImGuiFonts(bool fullscreen_fonts)
|
|
|
|
{
|
|
|
|
const float standard_font_size = std::ceil(15.0f * s_global_scale);
|
|
|
|
|
|
|
|
ImGuiIO& io = ImGui::GetIO();
|
|
|
|
io.Fonts->Clear();
|
|
|
|
|
2022-08-13 03:46:58 +00:00
|
|
|
s_standard_font = AddTextFont(standard_font_size);
|
2022-07-11 13:03:29 +00:00
|
|
|
if (!s_standard_font || !AddIconFonts(standard_font_size))
|
|
|
|
return false;
|
|
|
|
|
|
|
|
s_fixed_font = AddFixedFont(standard_font_size);
|
|
|
|
if (!s_fixed_font)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
if (fullscreen_fonts)
|
|
|
|
{
|
|
|
|
const float medium_font_size = std::ceil(ImGuiFullscreen::LayoutScale(ImGuiFullscreen::LAYOUT_MEDIUM_FONT_SIZE));
|
2022-08-13 03:46:58 +00:00
|
|
|
s_medium_font = AddTextFont(medium_font_size);
|
2022-07-11 13:03:29 +00:00
|
|
|
if (!s_medium_font || !AddIconFonts(medium_font_size))
|
|
|
|
return false;
|
|
|
|
|
|
|
|
const float large_font_size = std::ceil(ImGuiFullscreen::LayoutScale(ImGuiFullscreen::LAYOUT_LARGE_FONT_SIZE));
|
2022-08-13 03:46:58 +00:00
|
|
|
s_large_font = AddTextFont(large_font_size);
|
2022-07-11 13:03:29 +00:00
|
|
|
if (!s_large_font || !AddIconFonts(large_font_size))
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
s_medium_font = nullptr;
|
|
|
|
s_large_font = nullptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
ImGuiFullscreen::SetFonts(s_standard_font, s_medium_font, s_large_font);
|
|
|
|
|
|
|
|
return io.Fonts->Build();
|
|
|
|
}
|
|
|
|
|
|
|
|
bool ImGuiManager::AddFullscreenFontsIfMissing()
|
|
|
|
{
|
|
|
|
if (HasFullscreenFonts())
|
|
|
|
return true;
|
|
|
|
|
|
|
|
// can't do this in the middle of a frame
|
|
|
|
ImGui::EndFrame();
|
|
|
|
|
|
|
|
if (!AddImGuiFonts(true))
|
|
|
|
{
|
|
|
|
Log_ErrorPrint("Failed to lazily allocate fullscreen fonts.");
|
|
|
|
AddImGuiFonts(false);
|
|
|
|
}
|
|
|
|
|
|
|
|
g_host_display->UpdateImGuiFontTexture();
|
|
|
|
NewFrame();
|
|
|
|
|
|
|
|
return HasFullscreenFonts();
|
|
|
|
}
|
|
|
|
|
|
|
|
bool ImGuiManager::HasFullscreenFonts()
|
|
|
|
{
|
|
|
|
return (s_medium_font && s_large_font);
|
|
|
|
}
|
|
|
|
|
|
|
|
struct OSDMessage
|
|
|
|
{
|
|
|
|
std::string key;
|
|
|
|
std::string text;
|
|
|
|
std::chrono::steady_clock::time_point time;
|
|
|
|
float duration;
|
|
|
|
};
|
|
|
|
|
|
|
|
static std::deque<OSDMessage> s_osd_active_messages;
|
|
|
|
static std::deque<OSDMessage> s_osd_posted_messages;
|
|
|
|
static std::mutex s_osd_messages_lock;
|
|
|
|
|
|
|
|
void Host::AddOSDMessage(std::string message, float duration /*= 2.0f*/)
|
|
|
|
{
|
|
|
|
AddKeyedOSDMessage(std::string(), std::move(message), duration);
|
|
|
|
}
|
|
|
|
|
|
|
|
void Host::AddKeyedOSDMessage(std::string key, std::string message, float duration /* = 2.0f */)
|
|
|
|
{
|
|
|
|
OSDMessage msg;
|
|
|
|
msg.key = std::move(key);
|
|
|
|
msg.text = std::move(message);
|
|
|
|
msg.duration = duration;
|
|
|
|
msg.time = std::chrono::steady_clock::now();
|
|
|
|
|
|
|
|
std::unique_lock<std::mutex> lock(s_osd_messages_lock);
|
|
|
|
s_osd_posted_messages.push_back(std::move(msg));
|
|
|
|
}
|
|
|
|
|
|
|
|
void Host::AddFormattedOSDMessage(float duration, const char* format, ...)
|
|
|
|
{
|
|
|
|
std::va_list ap;
|
|
|
|
va_start(ap, format);
|
|
|
|
std::string ret = StringUtil::StdStringFromFormatV(format, ap);
|
|
|
|
va_end(ap);
|
|
|
|
return AddKeyedOSDMessage(std::string(), std::move(ret), duration);
|
|
|
|
}
|
|
|
|
|
2022-08-04 11:20:26 +00:00
|
|
|
void Host::AddIconOSDMessage(std::string key, const char* icon, std::string message, float duration /* = 2.0f */)
|
|
|
|
{
|
|
|
|
return AddKeyedOSDMessage(std::move(key), fmt::format("{} {}", icon, message), duration);
|
|
|
|
}
|
|
|
|
|
2022-07-11 13:03:29 +00:00
|
|
|
void Host::AddKeyedFormattedOSDMessage(std::string key, float duration, const char* format, ...)
|
|
|
|
{
|
|
|
|
std::va_list ap;
|
|
|
|
va_start(ap, format);
|
|
|
|
std::string ret = StringUtil::StdStringFromFormatV(format, ap);
|
|
|
|
va_end(ap);
|
|
|
|
return AddKeyedOSDMessage(std::move(key), std::move(ret), duration);
|
|
|
|
}
|
|
|
|
|
|
|
|
void Host::RemoveKeyedOSDMessage(std::string key)
|
|
|
|
{
|
|
|
|
OSDMessage msg;
|
|
|
|
msg.key = std::move(key);
|
|
|
|
msg.duration = 0.0f;
|
|
|
|
msg.time = std::chrono::steady_clock::now();
|
|
|
|
|
|
|
|
std::unique_lock<std::mutex> lock(s_osd_messages_lock);
|
|
|
|
s_osd_posted_messages.push_back(std::move(msg));
|
|
|
|
}
|
|
|
|
|
|
|
|
void Host::ClearOSDMessages()
|
|
|
|
{
|
|
|
|
{
|
|
|
|
std::unique_lock<std::mutex> lock(s_osd_messages_lock);
|
|
|
|
s_osd_posted_messages.clear();
|
|
|
|
}
|
|
|
|
|
|
|
|
s_osd_active_messages.clear();
|
|
|
|
}
|
|
|
|
|
|
|
|
void ImGuiManager::AcquirePendingOSDMessages()
|
|
|
|
{
|
|
|
|
std::atomic_thread_fence(std::memory_order_consume);
|
|
|
|
if (s_osd_posted_messages.empty())
|
|
|
|
return;
|
|
|
|
|
|
|
|
std::unique_lock lock(s_osd_messages_lock);
|
|
|
|
for (;;)
|
|
|
|
{
|
|
|
|
if (s_osd_posted_messages.empty())
|
|
|
|
break;
|
|
|
|
|
|
|
|
if (g_settings.display_show_osd_messages)
|
|
|
|
{
|
|
|
|
OSDMessage& new_msg = s_osd_posted_messages.front();
|
|
|
|
std::deque<OSDMessage>::iterator iter;
|
|
|
|
if (!new_msg.key.empty() && (iter = std::find_if(s_osd_active_messages.begin(), s_osd_active_messages.end(),
|
|
|
|
[&new_msg](const OSDMessage& other) {
|
|
|
|
return new_msg.key == other.key;
|
|
|
|
})) != s_osd_active_messages.end())
|
|
|
|
{
|
|
|
|
iter->text = std::move(new_msg.text);
|
|
|
|
iter->duration = new_msg.duration;
|
|
|
|
iter->time = new_msg.time;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
s_osd_active_messages.push_back(std::move(new_msg));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
s_osd_posted_messages.pop_front();
|
|
|
|
|
|
|
|
static constexpr size_t MAX_ACTIVE_OSD_MESSAGES = 512;
|
|
|
|
if (s_osd_active_messages.size() > MAX_ACTIVE_OSD_MESSAGES)
|
|
|
|
s_osd_active_messages.pop_front();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void ImGuiManager::DrawOSDMessages()
|
|
|
|
{
|
|
|
|
ImFont* const font = ImGui::GetFont();
|
|
|
|
const float scale = s_global_scale;
|
|
|
|
const float spacing = std::ceil(5.0f * scale);
|
|
|
|
const float margin = std::ceil(10.0f * scale);
|
|
|
|
const float padding = std::ceil(8.0f * scale);
|
|
|
|
const float rounding = std::ceil(5.0f * scale);
|
|
|
|
const float max_width = ImGui::GetIO().DisplaySize.x - (margin + padding) * 2.0f;
|
|
|
|
float position_x = margin;
|
|
|
|
float position_y = margin;
|
|
|
|
|
|
|
|
const auto now = std::chrono::steady_clock::now();
|
|
|
|
|
|
|
|
auto iter = s_osd_active_messages.begin();
|
|
|
|
while (iter != s_osd_active_messages.end())
|
|
|
|
{
|
|
|
|
const OSDMessage& msg = *iter;
|
|
|
|
const double time = std::chrono::duration<double>(now - msg.time).count();
|
|
|
|
const float time_remaining = static_cast<float>(msg.duration - time);
|
|
|
|
if (time_remaining <= 0.0f)
|
|
|
|
{
|
|
|
|
iter = s_osd_active_messages.erase(iter);
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
++iter;
|
|
|
|
|
|
|
|
const float opacity = std::min(time_remaining, 1.0f);
|
|
|
|
const u32 alpha = static_cast<u32>(opacity * 255.0f);
|
|
|
|
|
|
|
|
if (position_y >= ImGui::GetIO().DisplaySize.y)
|
|
|
|
break;
|
|
|
|
|
|
|
|
const ImVec2 pos(position_x, position_y);
|
|
|
|
const ImVec2 text_size(font->CalcTextSizeA(font->FontSize, max_width, max_width, msg.text.c_str(),
|
|
|
|
msg.text.c_str() + msg.text.length()));
|
|
|
|
const ImVec2 size(text_size.x + padding * 2.0f, text_size.y + padding * 2.0f);
|
|
|
|
const ImVec4 text_rect(pos.x + padding, pos.y + padding, pos.x + size.x - padding, pos.y + size.y - padding);
|
|
|
|
|
2022-07-23 03:00:09 +00:00
|
|
|
ImDrawList* dl = ImGui::GetForegroundDrawList();
|
2022-07-11 13:03:29 +00:00
|
|
|
dl->AddRectFilled(pos, ImVec2(pos.x + size.x, pos.y + size.y), IM_COL32(0x21, 0x21, 0x21, alpha), rounding);
|
|
|
|
dl->AddRect(pos, ImVec2(pos.x + size.x, pos.y + size.y), IM_COL32(0x48, 0x48, 0x48, alpha), rounding);
|
|
|
|
dl->AddText(font, font->FontSize, ImVec2(text_rect.x, text_rect.y), IM_COL32(0xff, 0xff, 0xff, alpha),
|
|
|
|
msg.text.c_str(), msg.text.c_str() + msg.text.length(), max_width, &text_rect);
|
|
|
|
position_y += size.y + spacing;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void ImGuiManager::RenderOSD()
|
|
|
|
{
|
|
|
|
AcquirePendingOSDMessages();
|
|
|
|
DrawOSDMessages();
|
|
|
|
}
|
|
|
|
|
|
|
|
float ImGuiManager::GetGlobalScale()
|
|
|
|
{
|
|
|
|
return s_global_scale;
|
|
|
|
}
|
|
|
|
|
|
|
|
float Host::GetOSDScale()
|
|
|
|
{
|
|
|
|
return s_global_scale;
|
|
|
|
}
|
|
|
|
|
|
|
|
ImFont* ImGuiManager::GetStandardFont()
|
|
|
|
{
|
|
|
|
return s_standard_font;
|
|
|
|
}
|
|
|
|
|
|
|
|
ImFont* ImGuiManager::GetFixedFont()
|
|
|
|
{
|
|
|
|
return s_fixed_font;
|
|
|
|
}
|
|
|
|
|
|
|
|
ImFont* ImGuiManager::GetMediumFont()
|
|
|
|
{
|
|
|
|
AddFullscreenFontsIfMissing();
|
|
|
|
return s_medium_font;
|
|
|
|
}
|
|
|
|
|
|
|
|
ImFont* ImGuiManager::GetLargeFont()
|
|
|
|
{
|
|
|
|
AddFullscreenFontsIfMissing();
|
|
|
|
return s_large_font;
|
|
|
|
}
|
|
|
|
|
2022-08-25 15:26:55 +00:00
|
|
|
bool ImGuiManager::WantsTextInput()
|
|
|
|
{
|
|
|
|
return s_imgui_wants_keyboard.load(std::memory_order_acquire);
|
|
|
|
}
|
|
|
|
|
|
|
|
void ImGuiManager::AddTextInput(std::string str)
|
|
|
|
{
|
|
|
|
if (!ImGui::GetCurrentContext())
|
|
|
|
return;
|
|
|
|
|
|
|
|
if (!s_imgui_wants_keyboard.load(std::memory_order_acquire))
|
|
|
|
return;
|
|
|
|
|
|
|
|
ImGui::GetIO().AddInputCharactersUTF8(str.c_str());
|
|
|
|
}
|
|
|
|
|
2022-07-11 13:03:29 +00:00
|
|
|
void ImGuiManager::UpdateMousePosition(float x, float y)
|
|
|
|
{
|
|
|
|
if (!ImGui::GetCurrentContext())
|
|
|
|
return;
|
|
|
|
|
|
|
|
ImGui::GetIO().MousePos = ImVec2(x, y);
|
|
|
|
std::atomic_thread_fence(std::memory_order_release);
|
|
|
|
}
|
|
|
|
|
|
|
|
bool ImGuiManager::ProcessPointerButtonEvent(InputBindingKey key, float value)
|
|
|
|
{
|
2022-08-10 05:54:53 +00:00
|
|
|
if (!ImGui::GetCurrentContext() || key.data >= std::size(ImGui::GetIO().MouseDown))
|
2022-07-11 13:03:29 +00:00
|
|
|
return false;
|
|
|
|
|
|
|
|
// still update state anyway
|
2022-08-10 05:54:53 +00:00
|
|
|
ImGui::GetIO().AddMouseButtonEvent(key.data, value != 0.0f);
|
2022-07-11 13:03:29 +00:00
|
|
|
|
|
|
|
return s_imgui_wants_mouse.load(std::memory_order_acquire);
|
|
|
|
}
|
|
|
|
|
|
|
|
bool ImGuiManager::ProcessPointerAxisEvent(InputBindingKey key, float value)
|
|
|
|
{
|
|
|
|
if (!ImGui::GetCurrentContext() || value == 0.0f || key.data < static_cast<u32>(InputPointerAxis::WheelX))
|
|
|
|
return false;
|
|
|
|
|
|
|
|
// still update state anyway
|
|
|
|
const bool horizontal = (key.data == static_cast<u32>(InputPointerAxis::WheelX));
|
|
|
|
ImGui::GetIO().AddMouseWheelEvent(horizontal ? value : 0.0f, horizontal ? 0.0f : value);
|
|
|
|
|
|
|
|
return s_imgui_wants_mouse.load(std::memory_order_acquire);
|
|
|
|
}
|
|
|
|
|
|
|
|
bool ImGuiManager::ProcessHostKeyEvent(InputBindingKey key, float value)
|
|
|
|
{
|
|
|
|
decltype(s_imgui_key_map)::iterator iter;
|
|
|
|
if (!ImGui::GetCurrentContext() || (iter = s_imgui_key_map.find(key.data)) == s_imgui_key_map.end())
|
|
|
|
return false;
|
|
|
|
|
|
|
|
// still update state anyway
|
|
|
|
ImGui::GetIO().AddKeyEvent(iter->second, value != 0.0);
|
|
|
|
|
|
|
|
return s_imgui_wants_keyboard.load(std::memory_order_acquire);
|
|
|
|
}
|
|
|
|
|
|
|
|
bool ImGuiManager::ProcessGenericInputEvent(GenericInputBinding key, float value)
|
|
|
|
{
|
|
|
|
static constexpr ImGuiKey key_map[] = {
|
|
|
|
ImGuiKey_None, // Unknown,
|
|
|
|
ImGuiKey_GamepadDpadUp, // DPadUp
|
|
|
|
ImGuiKey_GamepadDpadRight, // DPadRight
|
|
|
|
ImGuiKey_GamepadDpadLeft, // DPadLeft
|
|
|
|
ImGuiKey_GamepadDpadDown, // DPadDown
|
|
|
|
ImGuiKey_None, // LeftStickUp
|
|
|
|
ImGuiKey_None, // LeftStickRight
|
|
|
|
ImGuiKey_None, // LeftStickDown
|
|
|
|
ImGuiKey_None, // LeftStickLeft
|
|
|
|
ImGuiKey_GamepadL3, // L3
|
|
|
|
ImGuiKey_None, // RightStickUp
|
|
|
|
ImGuiKey_None, // RightStickRight
|
|
|
|
ImGuiKey_None, // RightStickDown
|
|
|
|
ImGuiKey_None, // RightStickLeft
|
|
|
|
ImGuiKey_GamepadR3, // R3
|
|
|
|
ImGuiKey_GamepadFaceUp, // Triangle
|
|
|
|
ImGuiKey_GamepadFaceRight, // Circle
|
|
|
|
ImGuiKey_GamepadFaceDown, // Cross
|
|
|
|
ImGuiKey_GamepadFaceLeft, // Square
|
|
|
|
ImGuiKey_GamepadBack, // Select
|
|
|
|
ImGuiKey_GamepadStart, // Start
|
|
|
|
ImGuiKey_None, // System
|
|
|
|
ImGuiKey_GamepadL1, // L1
|
|
|
|
ImGuiKey_GamepadL2, // L2
|
|
|
|
ImGuiKey_GamepadR1, // R1
|
|
|
|
ImGuiKey_GamepadL2, // R2
|
|
|
|
};
|
|
|
|
|
|
|
|
if (!ImGui::GetCurrentContext() || !s_imgui_wants_keyboard.load(std::memory_order_acquire))
|
|
|
|
return false;
|
|
|
|
|
|
|
|
if (static_cast<u32>(key) >= std::size(key_map) || key_map[static_cast<u32>(key)] == ImGuiKey_None)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
ImGui::GetIO().AddKeyAnalogEvent(key_map[static_cast<u32>(key)], (value > 0.0f), value);
|
|
|
|
return true;
|
|
|
|
}
|