ImGuiManager: Pack state in struct

This commit is contained in:
Stenzek 2025-01-02 21:33:53 +10:00
parent d3fe1dfc2c
commit ba15a76d7b
No known key found for this signature in database
1 changed files with 232 additions and 217 deletions

View File

@ -89,61 +89,71 @@ static void UpdateSoftwareCursorTexture(u32 index);
static void DestroySoftwareCursorTextures(); static void DestroySoftwareCursorTextures();
static void DrawSoftwareCursor(const SoftwareCursor& sc, const std::pair<float, float>& pos); static void DrawSoftwareCursor(const SoftwareCursor& sc, const std::pair<float, float>& pos);
static float s_global_prescale = 0.0f; // before window scale
static float s_global_scale = 0.0f;
static float s_screen_margin = 0.0f;
static constexpr std::array<ImWchar, 4> s_ascii_font_range = {{0x20, 0x7F, 0x00, 0x00}};
static std::string s_font_path;
static std::vector<WCharType> s_font_range;
static std::vector<WCharType> s_emoji_range;
static ImGuiContext* s_imgui_context;
static ImFont* s_debug_font;
static ImFont* s_osd_font;
static ImFont* s_fixed_font;
static ImFont* s_medium_font;
static ImFont* s_large_font;
static DynamicHeapArray<u8> s_standard_font_data;
static DynamicHeapArray<u8> s_fixed_font_data;
static DynamicHeapArray<u8> s_icon_fa_font_data;
static DynamicHeapArray<u8> s_icon_pf_font_data;
static DynamicHeapArray<u8> s_emoji_font_data;
static float s_window_width;
static float s_window_height;
static 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};
static std::atomic_bool s_imgui_wants_text{false};
// mapping of host key -> imgui key
static std::unordered_map<u32, ImGuiKey> s_imgui_key_map;
static constexpr float OSD_FADE_IN_TIME = 0.1f; static constexpr float OSD_FADE_IN_TIME = 0.1f;
static constexpr float OSD_FADE_OUT_TIME = 0.4f; static constexpr float OSD_FADE_OUT_TIME = 0.4f;
static std::deque<OSDMessage> s_osd_active_messages; static constexpr std::array<ImWchar, 4> s_ascii_font_range = {{0x20, 0x7F, 0x00, 0x00}};
static std::deque<OSDMessage> s_osd_posted_messages;
static std::mutex s_osd_messages_lock; namespace {
static bool s_show_osd_messages = true;
static bool s_scale_changed = false; struct ALIGN_TO_CACHE_LINE State
{
float global_prescale = 0.0f; // before window scale
float global_scale = 0.0f;
float screen_margin = 0.0f;
std::string font_path;
std::vector<WCharType> font_range;
std::vector<WCharType> emoji_range;
ImGuiContext* imgui_context;
ImFont* debug_font;
ImFont* osd_font;
ImFont* fixed_font;
ImFont* medium_font;
ImFont* large_font;
DynamicHeapArray<u8> standard_font_data;
DynamicHeapArray<u8> fixed_font_data;
DynamicHeapArray<u8> icon_fa_font_data;
DynamicHeapArray<u8> icon_pf_font_data;
DynamicHeapArray<u8> emoji_font_data;
float window_width;
float window_height;
Timer::Value last_render_time;
// cached copies of WantCaptureKeyboard/Mouse, used to know when to dispatch events
std::atomic_bool imgui_wants_keyboard{false};
std::atomic_bool imgui_wants_mouse{false};
std::atomic_bool imgui_wants_text{false};
// mapping of host key -> imgui key
std::unordered_map<u32, ImGuiKey> imgui_key_map;
std::deque<OSDMessage> osd_active_messages;
std::deque<OSDMessage> osd_posted_messages;
std::mutex osd_messages_lock;
bool show_osd_messages = true;
bool scale_changed = false;
std::array<ImGuiManager::SoftwareCursor, InputManager::MAX_SOFTWARE_CURSORS> software_cursors = {};
};
} // namespace
static State s_state;
static std::array<ImGuiManager::SoftwareCursor, InputManager::MAX_SOFTWARE_CURSORS> s_software_cursors = {};
} // namespace ImGuiManager } // namespace ImGuiManager
void ImGuiManager::SetFontPathAndRange(std::string path, std::vector<WCharType> range) void ImGuiManager::SetFontPathAndRange(std::string path, std::vector<WCharType> range)
{ {
if (s_font_path == path && s_font_range == range) if (s_state.font_path == path && s_state.font_range == range)
return; return;
s_font_path = std::move(path); s_state.font_path = std::move(path);
s_font_range = std::move(range); s_state.font_range = std::move(range);
s_standard_font_data = {}; s_state.standard_font_data = {};
ReloadFontDataIfActive(); ReloadFontDataIfActive();
} }
@ -154,23 +164,23 @@ void ImGuiManager::SetEmojiFontRange(std::vector<WCharType> range)
if (runtime_size == 0) if (runtime_size == 0)
{ {
if (s_emoji_range.empty()) if (s_state.emoji_range.empty())
return; return;
s_emoji_range = {}; s_state.emoji_range = {};
} }
else else
{ {
if (!s_emoji_range.empty() && (s_emoji_range.size() - builtin_size) == range.size() && if (!s_state.emoji_range.empty() && (s_state.emoji_range.size() - builtin_size) == range.size() &&
std::memcmp(s_emoji_range.data(), range.data(), range.size() * sizeof(ImWchar)) == 0) std::memcmp(s_state.emoji_range.data(), range.data(), range.size() * sizeof(ImWchar)) == 0)
{ {
// no change // no change
return; return;
} }
s_emoji_range = std::move(range); s_state.emoji_range = std::move(range);
s_emoji_range.resize(s_emoji_range.size() + builtin_size); s_state.emoji_range.resize(s_state.emoji_range.size() + builtin_size);
std::memcpy(&s_emoji_range[runtime_size], EMOJI_ICON_RANGE, sizeof(EMOJI_ICON_RANGE)); std::memcpy(&s_state.emoji_range[runtime_size], EMOJI_ICON_RANGE, sizeof(EMOJI_ICON_RANGE));
} }
ReloadFontDataIfActive(); ReloadFontDataIfActive();
@ -210,24 +220,24 @@ std::vector<ImGuiManager::WCharType> ImGuiManager::CompactFontRange(std::span<co
void ImGuiManager::SetGlobalScale(float global_scale) void ImGuiManager::SetGlobalScale(float global_scale)
{ {
if (s_global_prescale == global_scale) if (s_state.global_prescale == global_scale)
return; return;
s_global_prescale = global_scale; s_state.global_prescale = global_scale;
s_scale_changed = true; s_state.scale_changed = true;
} }
bool ImGuiManager::IsShowingOSDMessages() bool ImGuiManager::IsShowingOSDMessages()
{ {
return s_show_osd_messages; return s_state.show_osd_messages;
} }
void ImGuiManager::SetShowOSDMessages(bool enable) void ImGuiManager::SetShowOSDMessages(bool enable)
{ {
if (s_show_osd_messages == enable) if (s_state.show_osd_messages == enable)
return; return;
s_show_osd_messages = enable; s_state.show_osd_messages = enable;
if (!enable) if (!enable)
Host::ClearOSDMessages(false); Host::ClearOSDMessages(false);
} }
@ -240,15 +250,15 @@ bool ImGuiManager::Initialize(float global_scale, float screen_margin, Error* er
return false; return false;
} }
s_global_prescale = global_scale; s_state.global_prescale = global_scale;
s_global_scale = std::max( s_state.global_scale = std::max(
(g_gpu_device->HasMainSwapChain() ? g_gpu_device->GetMainSwapChain()->GetScale() : 1.0f) * global_scale, 1.0f); (g_gpu_device->HasMainSwapChain() ? g_gpu_device->GetMainSwapChain()->GetScale() : 1.0f) * global_scale, 1.0f);
s_screen_margin = std::max(screen_margin, 0.0f); s_state.screen_margin = std::max(screen_margin, 0.0f);
s_scale_changed = false; s_state.scale_changed = false;
s_imgui_context = ImGui::CreateContext(); s_state.imgui_context = ImGui::CreateContext();
ImGuiIO& io = s_imgui_context->IO; ImGuiIO& io = s_state.imgui_context->IO;
io.IniFilename = nullptr; io.IniFilename = nullptr;
io.BackendFlags |= ImGuiBackendFlags_HasGamepad | ImGuiBackendFlags_RendererHasVtxOffset; io.BackendFlags |= ImGuiBackendFlags_HasGamepad | ImGuiBackendFlags_RendererHasVtxOffset;
#ifndef __ANDROID__ #ifndef __ANDROID__
@ -260,15 +270,16 @@ bool ImGuiManager::Initialize(float global_scale, float screen_margin, Error* er
#endif #endif
SetCommonIOOptions(io); SetCommonIOOptions(io);
s_window_width = s_state.last_render_time = Timer::GetCurrentValue();
s_state.window_width =
g_gpu_device->HasMainSwapChain() ? static_cast<float>(g_gpu_device->GetMainSwapChain()->GetWidth()) : 0.0f; g_gpu_device->HasMainSwapChain() ? static_cast<float>(g_gpu_device->GetMainSwapChain()->GetWidth()) : 0.0f;
s_window_height = s_state.window_height =
g_gpu_device->HasMainSwapChain() ? static_cast<float>(g_gpu_device->GetMainSwapChain()->GetHeight()) : 0.0f; g_gpu_device->HasMainSwapChain() ? static_cast<float>(g_gpu_device->GetMainSwapChain()->GetHeight()) : 0.0f;
io.DisplayFramebufferScale = ImVec2(1, 1); // We already scale things ourselves, this would double-apply scaling io.DisplayFramebufferScale = ImVec2(1, 1); // We already scale things ourselves, this would double-apply scaling
io.DisplaySize = ImVec2(s_window_width, s_window_height); io.DisplaySize = ImVec2(s_state.window_width, s_state.window_height);
SetKeyMap(); SetKeyMap();
SetStyle(s_imgui_context->Style, s_global_scale); SetStyle(s_state.imgui_context->Style, s_state.global_scale);
if (!AddImGuiFonts(false, false) || !g_gpu_device->UpdateImGuiFontTexture()) if (!AddImGuiFonts(false, false) || !g_gpu_device->UpdateImGuiFontTexture())
{ {
@ -290,43 +301,43 @@ void ImGuiManager::Shutdown()
{ {
DestroySoftwareCursorTextures(); DestroySoftwareCursorTextures();
if (s_imgui_context) if (s_state.imgui_context)
{ {
ImGui::DestroyContext(s_imgui_context); ImGui::DestroyContext(s_state.imgui_context);
s_imgui_context = nullptr; s_state.imgui_context = nullptr;
} }
s_debug_font = nullptr; s_state.debug_font = nullptr;
s_fixed_font = nullptr; s_state.fixed_font = nullptr;
s_medium_font = nullptr; s_state.medium_font = nullptr;
s_large_font = nullptr; s_state.large_font = nullptr;
ImGuiFullscreen::SetFonts(nullptr, nullptr); ImGuiFullscreen::SetFonts(nullptr, nullptr);
} }
ImGuiContext* ImGuiManager::GetMainContext() ImGuiContext* ImGuiManager::GetMainContext()
{ {
return s_imgui_context; return s_state.imgui_context;
} }
void ImGuiManager::SetScreenMargin(float margin) void ImGuiManager::SetScreenMargin(float margin)
{ {
s_screen_margin = std::max(margin, 0.0f); s_state.screen_margin = std::max(margin, 0.0f);
} }
float ImGuiManager::GetWindowWidth() float ImGuiManager::GetWindowWidth()
{ {
return s_window_width; return s_state.window_width;
} }
float ImGuiManager::GetWindowHeight() float ImGuiManager::GetWindowHeight()
{ {
return s_window_height; return s_state.window_height;
} }
void ImGuiManager::WindowResized(float width, float height) void ImGuiManager::WindowResized(float width, float height)
{ {
s_window_width = width; s_state.window_width = width;
s_window_height = height; s_state.window_height = height;
ImGui::GetIO().DisplaySize = ImVec2(width, height); ImGui::GetIO().DisplaySize = ImVec2(width, height);
// Scale might have changed as a result of window resize. // Scale might have changed as a result of window resize.
@ -336,20 +347,20 @@ void ImGuiManager::WindowResized(float width, float height)
void ImGuiManager::RequestScaleUpdate() void ImGuiManager::RequestScaleUpdate()
{ {
// Might need to update the scale. // Might need to update the scale.
s_scale_changed = true; s_state.scale_changed = true;
} }
void ImGuiManager::UpdateScale() void ImGuiManager::UpdateScale()
{ {
const float window_scale = const float window_scale =
(g_gpu_device && g_gpu_device->HasMainSwapChain()) ? g_gpu_device->GetMainSwapChain()->GetScale() : 1.0f; (g_gpu_device && g_gpu_device->HasMainSwapChain()) ? g_gpu_device->GetMainSwapChain()->GetScale() : 1.0f;
const float scale = std::max(window_scale * s_global_prescale, 1.0f); const float scale = std::max(window_scale * s_state.global_prescale, 1.0f);
if ((!HasFullscreenFonts() || !ImGuiFullscreen::UpdateLayoutScale()) && scale == s_global_scale) if ((!HasFullscreenFonts() || !ImGuiFullscreen::UpdateLayoutScale()) && scale == s_state.global_scale)
return; return;
s_global_scale = scale; s_state.global_scale = scale;
SetStyle(s_imgui_context->Style, s_global_scale); SetStyle(s_state.imgui_context->Style, s_state.global_scale);
if (!AddImGuiFonts(HasDebugFont(), HasFullscreenFonts())) if (!AddImGuiFonts(HasDebugFont(), HasFullscreenFonts()))
Panic("Failed to create ImGui font text"); Panic("Failed to create ImGui font text");
@ -360,12 +371,15 @@ void ImGuiManager::UpdateScale()
void ImGuiManager::NewFrame() void ImGuiManager::NewFrame()
{ {
ImGuiIO& io = ImGui::GetIO(); const Timer::Value current_time = Timer::GetCurrentValue();
io.DeltaTime = static_cast<float>(s_last_render_time.GetTimeSecondsAndReset());
if (s_scale_changed) ImGuiIO& io = ImGui::GetIO();
io.DeltaTime = static_cast<float>(Timer::ConvertValueToSeconds(current_time - s_state.last_render_time));
s_state.last_render_time = current_time;
if (s_state.scale_changed)
{ {
s_scale_changed = false; s_state.scale_changed = false;
UpdateScale(); UpdateScale();
} }
@ -374,13 +388,13 @@ void ImGuiManager::NewFrame()
// Disable nav input on the implicit (Debug##Default) window. Otherwise we end up requesting keyboard // 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. // focus when there's nothing there. We use GetCurrentWindowRead() because otherwise it'll make it visible.
ImGui::GetCurrentWindowRead()->Flags |= ImGuiWindowFlags_NoNavInputs; ImGui::GetCurrentWindowRead()->Flags |= ImGuiWindowFlags_NoNavInputs;
s_imgui_wants_keyboard.store(io.WantCaptureKeyboard, std::memory_order_relaxed); s_state.imgui_wants_keyboard.store(io.WantCaptureKeyboard, std::memory_order_relaxed);
s_imgui_wants_mouse.store(io.WantCaptureMouse, std::memory_order_release); s_state.imgui_wants_mouse.store(io.WantCaptureMouse, std::memory_order_release);
const bool wants_text_input = io.WantTextInput; const bool wants_text_input = io.WantTextInput;
if (s_imgui_wants_text.load(std::memory_order_relaxed) != wants_text_input) if (s_state.imgui_wants_text.load(std::memory_order_relaxed) != wants_text_input)
{ {
s_imgui_wants_text.store(wants_text_input, std::memory_order_release); s_state.imgui_wants_text.store(wants_text_input, std::memory_order_release);
if (wants_text_input) if (wants_text_input)
Host::BeginTextInput(); Host::BeginTextInput();
else else
@ -560,65 +574,65 @@ void ImGuiManager::SetKeyMap()
{ImGuiKey_KeypadEnter, "KeypadReturn", nullptr}, {ImGuiKey_KeypadEnter, "KeypadReturn", nullptr},
{ImGuiKey_KeypadEqual, "KeypadEqual", nullptr}}; {ImGuiKey_KeypadEqual, "KeypadEqual", nullptr}};
s_imgui_key_map.clear(); s_state.imgui_key_map.clear();
for (const KeyMapping& km : mapping) for (const KeyMapping& km : mapping)
{ {
std::optional<u32> map(InputManager::ConvertHostKeyboardStringToCode(km.name)); std::optional<u32> map(InputManager::ConvertHostKeyboardStringToCode(km.name));
if (!map.has_value() && km.alt_name) if (!map.has_value() && km.alt_name)
map = InputManager::ConvertHostKeyboardStringToCode(km.alt_name); map = InputManager::ConvertHostKeyboardStringToCode(km.alt_name);
if (map.has_value()) if (map.has_value())
s_imgui_key_map[map.value()] = km.index; s_state.imgui_key_map[map.value()] = km.index;
} }
} }
bool ImGuiManager::LoadFontData(Error* error) bool ImGuiManager::LoadFontData(Error* error)
{ {
if (s_standard_font_data.empty()) if (s_state.standard_font_data.empty())
{ {
std::optional<DynamicHeapArray<u8>> font_data = s_font_path.empty() ? std::optional<DynamicHeapArray<u8>> font_data = s_state.font_path.empty() ?
Host::ReadResourceFile("fonts/Roboto-Regular.ttf", true, error) : Host::ReadResourceFile("fonts/Roboto-Regular.ttf", true, error) :
FileSystem::ReadBinaryFile(s_font_path.c_str(), error); FileSystem::ReadBinaryFile(s_state.font_path.c_str(), error);
if (!font_data.has_value()) if (!font_data.has_value())
return false; return false;
s_standard_font_data = std::move(font_data.value()); s_state.standard_font_data = std::move(font_data.value());
} }
if (s_fixed_font_data.empty()) if (s_state.fixed_font_data.empty())
{ {
std::optional<DynamicHeapArray<u8>> font_data = Host::ReadResourceFile("fonts/RobotoMono-Medium.ttf", true, error); std::optional<DynamicHeapArray<u8>> font_data = Host::ReadResourceFile("fonts/RobotoMono-Medium.ttf", true, error);
if (!font_data.has_value()) if (!font_data.has_value())
return false; return false;
s_fixed_font_data = std::move(font_data.value()); s_state.fixed_font_data = std::move(font_data.value());
} }
if (s_icon_fa_font_data.empty()) if (s_state.icon_fa_font_data.empty())
{ {
std::optional<DynamicHeapArray<u8>> font_data = Host::ReadResourceFile("fonts/fa-solid-900.ttf", true, error); std::optional<DynamicHeapArray<u8>> font_data = Host::ReadResourceFile("fonts/fa-solid-900.ttf", true, error);
if (!font_data.has_value()) if (!font_data.has_value())
return false; return false;
s_icon_fa_font_data = std::move(font_data.value()); s_state.icon_fa_font_data = std::move(font_data.value());
} }
if (s_icon_pf_font_data.empty()) if (s_state.icon_pf_font_data.empty())
{ {
std::optional<DynamicHeapArray<u8>> font_data = Host::ReadResourceFile("fonts/promptfont.otf", true, error); std::optional<DynamicHeapArray<u8>> font_data = Host::ReadResourceFile("fonts/promptfont.otf", true, error);
if (!font_data.has_value()) if (!font_data.has_value())
return false; return false;
s_icon_pf_font_data = std::move(font_data.value()); s_state.icon_pf_font_data = std::move(font_data.value());
} }
if (s_emoji_font_data.empty()) if (s_state.emoji_font_data.empty())
{ {
std::optional<DynamicHeapArray<u8>> font_data = std::optional<DynamicHeapArray<u8>> font_data =
Host::ReadCompressedResourceFile("fonts/TwitterColorEmoji-SVGinOT.ttf.zst", true, error); Host::ReadCompressedResourceFile("fonts/TwitterColorEmoji-SVGinOT.ttf.zst", true, error);
if (!font_data.has_value()) if (!font_data.has_value())
return false; return false;
s_emoji_font_data = std::move(font_data.value()); s_state.emoji_font_data = std::move(font_data.value());
} }
return true; return true;
@ -628,17 +642,18 @@ ImFont* ImGuiManager::AddTextFont(float size, bool full_glyph_range)
{ {
ImFontConfig cfg; ImFontConfig cfg;
cfg.FontDataOwnedByAtlas = false; cfg.FontDataOwnedByAtlas = false;
return ImGui::GetIO().Fonts->AddFontFromMemoryTTF(s_standard_font_data.data(), return ImGui::GetIO().Fonts->AddFontFromMemoryTTF(
static_cast<int>(s_standard_font_data.size()), size, &cfg, s_state.standard_font_data.data(), static_cast<int>(s_state.standard_font_data.size()), size, &cfg,
full_glyph_range ? s_font_range.data() : s_ascii_font_range.data()); full_glyph_range ? s_state.font_range.data() : s_ascii_font_range.data());
} }
ImFont* ImGuiManager::AddFixedFont(float size) ImFont* ImGuiManager::AddFixedFont(float size)
{ {
ImFontConfig cfg; ImFontConfig cfg;
cfg.FontDataOwnedByAtlas = false; cfg.FontDataOwnedByAtlas = false;
return ImGui::GetIO().Fonts->AddFontFromMemoryTTF( return ImGui::GetIO().Fonts->AddFontFromMemoryTTF(s_state.fixed_font_data.data(),
s_fixed_font_data.data(), static_cast<int>(s_fixed_font_data.size()), size, &cfg, s_ascii_font_range.data()); static_cast<int>(s_state.fixed_font_data.size()), size, &cfg,
s_ascii_font_range.data());
} }
bool ImGuiManager::AddIconFonts(float size) bool ImGuiManager::AddIconFonts(float size)
@ -651,9 +666,9 @@ bool ImGuiManager::AddIconFonts(float size)
cfg.GlyphMaxAdvanceX = size; cfg.GlyphMaxAdvanceX = size;
cfg.FontDataOwnedByAtlas = false; cfg.FontDataOwnedByAtlas = false;
if (!ImGui::GetIO().Fonts->AddFontFromMemoryTTF( if (!ImGui::GetIO().Fonts->AddFontFromMemoryTTF(s_state.icon_fa_font_data.data(),
s_icon_fa_font_data.data(), static_cast<int>(s_icon_fa_font_data.size()), size * 0.75f, &cfg, FA_ICON_RANGE)) static_cast<int>(s_state.icon_fa_font_data.size()), size * 0.75f,
[[unlikely]] &cfg, FA_ICON_RANGE)) [[unlikely]]
{ {
return false; return false;
} }
@ -667,9 +682,9 @@ bool ImGuiManager::AddIconFonts(float size)
cfg.GlyphMaxAdvanceX = size; cfg.GlyphMaxAdvanceX = size;
cfg.FontDataOwnedByAtlas = false; cfg.FontDataOwnedByAtlas = false;
if (!ImGui::GetIO().Fonts->AddFontFromMemoryTTF( if (!ImGui::GetIO().Fonts->AddFontFromMemoryTTF(s_state.icon_pf_font_data.data(),
s_icon_pf_font_data.data(), static_cast<int>(s_icon_pf_font_data.size()), size * 1.2f, &cfg, PF_ICON_RANGE)) static_cast<int>(s_state.icon_pf_font_data.size()), size * 1.2f,
[[unlikely]] &cfg, PF_ICON_RANGE)) [[unlikely]]
{ {
return false; return false;
} }
@ -685,8 +700,8 @@ bool ImGuiManager::AddIconFonts(float size)
cfg.FontBuilderFlags = ImGuiFreeTypeBuilderFlags_LoadColor | ImGuiFreeTypeBuilderFlags_Bitmap; cfg.FontBuilderFlags = ImGuiFreeTypeBuilderFlags_LoadColor | ImGuiFreeTypeBuilderFlags_Bitmap;
if (!ImGui::GetIO().Fonts->AddFontFromMemoryTTF( if (!ImGui::GetIO().Fonts->AddFontFromMemoryTTF(
s_emoji_font_data.data(), static_cast<int>(s_emoji_font_data.size()), size * 0.9f, &cfg, s_state.emoji_font_data.data(), static_cast<int>(s_state.emoji_font_data.size()), size * 0.9f, &cfg,
s_emoji_range.empty() ? EMOJI_ICON_RANGE : s_emoji_range.data())) [[unlikely]] s_state.emoji_range.empty() ? EMOJI_ICON_RANGE : s_state.emoji_range.data())) [[unlikely]]
{ {
return false; return false;
} }
@ -700,10 +715,10 @@ bool ImGuiManager::AddImGuiFonts(bool debug_font, bool fullscreen_fonts)
const float window_scale = const float window_scale =
(g_gpu_device && g_gpu_device->HasMainSwapChain()) ? g_gpu_device->GetMainSwapChain()->GetScale() : 1.0f; (g_gpu_device && g_gpu_device->HasMainSwapChain()) ? g_gpu_device->GetMainSwapChain()->GetScale() : 1.0f;
const float debug_font_size = std::ceil(15.0f * window_scale); const float debug_font_size = std::ceil(15.0f * window_scale);
const float standard_font_size = std::ceil(15.0f * s_global_scale); const float standard_font_size = std::ceil(15.0f * s_state.global_scale);
const float osd_font_size = std::ceil(17.0f * s_global_scale); const float osd_font_size = std::ceil(17.0f * s_state.global_scale);
INFO_LOG("Allocating fonts winscale={} globalscale={} debug={} fullscreen={}", window_scale, s_global_scale, INFO_LOG("Allocating fonts winscale={} globalscale={} debug={} fullscreen={}", window_scale, s_state.global_scale,
debug_font, fullscreen_fonts); debug_font, fullscreen_fonts);
ImGuiIO& io = ImGui::GetIO(); ImGuiIO& io = ImGui::GetIO();
@ -711,47 +726,47 @@ bool ImGuiManager::AddImGuiFonts(bool debug_font, bool fullscreen_fonts)
if (debug_font) if (debug_font)
{ {
s_debug_font = AddTextFont(debug_font_size, false); s_state.debug_font = AddTextFont(debug_font_size, false);
if (!s_debug_font) if (!s_state.debug_font)
return false; return false;
} }
s_fixed_font = AddFixedFont(standard_font_size); s_state.fixed_font = AddFixedFont(standard_font_size);
if (!s_fixed_font) if (!s_state.fixed_font)
return false; return false;
s_osd_font = AddTextFont(osd_font_size, true); s_state.osd_font = AddTextFont(osd_font_size, true);
if (!s_osd_font || !AddIconFonts(osd_font_size)) if (!s_state.osd_font || !AddIconFonts(osd_font_size))
return false; return false;
if (!debug_font) if (!debug_font)
s_debug_font = s_osd_font; s_state.debug_font = s_state.osd_font;
if (fullscreen_fonts) if (fullscreen_fonts)
{ {
const float medium_font_size = ImGuiFullscreen::LayoutScale(ImGuiFullscreen::LAYOUT_MEDIUM_FONT_SIZE); const float medium_font_size = ImGuiFullscreen::LayoutScale(ImGuiFullscreen::LAYOUT_MEDIUM_FONT_SIZE);
s_medium_font = AddTextFont(medium_font_size, true); s_state.medium_font = AddTextFont(medium_font_size, true);
if (!s_medium_font || !AddIconFonts(medium_font_size)) if (!s_state.medium_font || !AddIconFonts(medium_font_size))
return false; return false;
const float large_font_size = ImGuiFullscreen::LayoutScale(ImGuiFullscreen::LAYOUT_LARGE_FONT_SIZE); const float large_font_size = ImGuiFullscreen::LayoutScale(ImGuiFullscreen::LAYOUT_LARGE_FONT_SIZE);
s_large_font = AddTextFont(large_font_size, true); s_state.large_font = AddTextFont(large_font_size, true);
if (!s_large_font || !AddIconFonts(large_font_size)) if (!s_state.large_font || !AddIconFonts(large_font_size))
return false; return false;
} }
else else
{ {
s_medium_font = nullptr; s_state.medium_font = nullptr;
s_large_font = nullptr; s_state.large_font = nullptr;
} }
ImGuiFullscreen::SetFonts(s_medium_font, s_large_font); ImGuiFullscreen::SetFonts(s_state.medium_font, s_state.large_font);
return io.Fonts->Build(); return io.Fonts->Build();
} }
void ImGuiManager::ReloadFontDataIfActive() void ImGuiManager::ReloadFontDataIfActive()
{ {
if (!s_imgui_context) if (!s_state.imgui_context)
return; return;
ImGui::EndFrame(); ImGui::EndFrame();
@ -791,7 +806,7 @@ bool ImGuiManager::AddFullscreenFontsIfMissing()
bool ImGuiManager::HasDebugFont() bool ImGuiManager::HasDebugFont()
{ {
return (s_debug_font != s_osd_font); return (s_state.debug_font != s_state.osd_font);
} }
bool ImGuiManager::AddDebugFontIfMissing() bool ImGuiManager::AddDebugFontIfMissing()
@ -817,7 +832,7 @@ bool ImGuiManager::AddDebugFontIfMissing()
bool ImGuiManager::HasFullscreenFonts() bool ImGuiManager::HasFullscreenFonts()
{ {
return (s_medium_font && s_large_font); return (s_state.medium_font && s_state.large_font);
} }
void ImGuiManager::AddOSDMessage(std::string key, std::string message, float duration, bool is_warning) void ImGuiManager::AddOSDMessage(std::string key, std::string message, float duration, bool is_warning)
@ -827,7 +842,7 @@ void ImGuiManager::AddOSDMessage(std::string key, std::string message, float dur
else else
INFO_LOG("OSD: {}", message); INFO_LOG("OSD: {}", message);
if (!s_show_osd_messages && !is_warning) if (!s_state.show_osd_messages && !is_warning)
return; return;
const Timer::Value current_time = Timer::GetCurrentValue(); const Timer::Value current_time = Timer::GetCurrentValue();
@ -842,13 +857,13 @@ void ImGuiManager::AddOSDMessage(std::string key, std::string message, float dur
msg.last_y = -1.0f; msg.last_y = -1.0f;
msg.is_warning = is_warning; msg.is_warning = is_warning;
std::unique_lock<std::mutex> lock(s_osd_messages_lock); std::unique_lock<std::mutex> lock(s_state.osd_messages_lock);
s_osd_posted_messages.push_back(std::move(msg)); s_state.osd_posted_messages.push_back(std::move(msg));
} }
void ImGuiManager::RemoveKeyedOSDMessage(std::string key, bool is_warning) void ImGuiManager::RemoveKeyedOSDMessage(std::string key, bool is_warning)
{ {
if (!s_show_osd_messages && !is_warning) if (!s_state.show_osd_messages && !is_warning)
return; return;
ImGuiManager::OSDMessage msg = {}; ImGuiManager::OSDMessage msg = {};
@ -856,24 +871,24 @@ void ImGuiManager::RemoveKeyedOSDMessage(std::string key, bool is_warning)
msg.duration = 0.0f; msg.duration = 0.0f;
msg.is_warning = is_warning; msg.is_warning = is_warning;
std::unique_lock<std::mutex> lock(s_osd_messages_lock); std::unique_lock<std::mutex> lock(s_state.osd_messages_lock);
s_osd_posted_messages.push_back(std::move(msg)); s_state.osd_posted_messages.push_back(std::move(msg));
} }
void ImGuiManager::ClearOSDMessages(bool clear_warnings) void ImGuiManager::ClearOSDMessages(bool clear_warnings)
{ {
{ {
std::unique_lock<std::mutex> lock(s_osd_messages_lock); std::unique_lock<std::mutex> lock(s_state.osd_messages_lock);
if (clear_warnings) if (clear_warnings)
{ {
s_osd_posted_messages.clear(); s_state.osd_posted_messages.clear();
} }
else else
{ {
for (auto iter = s_osd_posted_messages.begin(); iter != s_osd_posted_messages.end();) for (auto iter = s_state.osd_posted_messages.begin(); iter != s_state.osd_posted_messages.end();)
{ {
if (!iter->is_warning) if (!iter->is_warning)
iter = s_osd_posted_messages.erase(iter); iter = s_state.osd_posted_messages.erase(iter);
else else
++iter; ++iter;
} }
@ -882,14 +897,14 @@ void ImGuiManager::ClearOSDMessages(bool clear_warnings)
if (clear_warnings) if (clear_warnings)
{ {
s_osd_active_messages.clear(); s_state.osd_active_messages.clear();
} }
else else
{ {
for (auto iter = s_osd_active_messages.begin(); iter != s_osd_active_messages.end();) for (auto iter = s_state.osd_active_messages.begin(); iter != s_state.osd_active_messages.end();)
{ {
if (!iter->is_warning) if (!iter->is_warning)
s_osd_active_messages.erase(iter); s_state.osd_active_messages.erase(iter);
else else
++iter; ++iter;
} }
@ -899,21 +914,21 @@ void ImGuiManager::ClearOSDMessages(bool clear_warnings)
void ImGuiManager::AcquirePendingOSDMessages(Timer::Value current_time) void ImGuiManager::AcquirePendingOSDMessages(Timer::Value current_time)
{ {
std::atomic_thread_fence(std::memory_order_consume); std::atomic_thread_fence(std::memory_order_consume);
if (s_osd_posted_messages.empty()) if (s_state.osd_posted_messages.empty())
return; return;
std::unique_lock lock(s_osd_messages_lock); std::unique_lock lock(s_state.osd_messages_lock);
for (;;) for (;;)
{ {
if (s_osd_posted_messages.empty()) if (s_state.osd_posted_messages.empty())
break; break;
OSDMessage& new_msg = s_osd_posted_messages.front(); OSDMessage& new_msg = s_state.osd_posted_messages.front();
std::deque<OSDMessage>::iterator iter; std::deque<OSDMessage>::iterator iter;
if (!new_msg.key.empty() && (iter = std::find_if(s_osd_active_messages.begin(), s_osd_active_messages.end(), if (!new_msg.key.empty() &&
[&new_msg](const OSDMessage& other) { (iter = std::find_if(s_state.osd_active_messages.begin(), s_state.osd_active_messages.end(),
return new_msg.key == other.key; [&new_msg](const OSDMessage& other) { return new_msg.key == other.key; })) !=
})) != s_osd_active_messages.end()) s_state.osd_active_messages.end())
{ {
iter->text = std::move(new_msg.text); iter->text = std::move(new_msg.text);
iter->duration = new_msg.duration; iter->duration = new_msg.duration;
@ -924,14 +939,14 @@ void ImGuiManager::AcquirePendingOSDMessages(Timer::Value current_time)
} }
else else
{ {
s_osd_active_messages.push_back(std::move(new_msg)); s_state.osd_active_messages.push_back(std::move(new_msg));
} }
s_osd_posted_messages.pop_front(); s_state.osd_posted_messages.pop_front();
static constexpr size_t MAX_ACTIVE_OSD_MESSAGES = 512; static constexpr size_t MAX_ACTIVE_OSD_MESSAGES = 512;
if (s_osd_active_messages.size() > MAX_ACTIVE_OSD_MESSAGES) if (s_state.osd_active_messages.size() > MAX_ACTIVE_OSD_MESSAGES)
s_osd_active_messages.pop_front(); s_state.osd_active_messages.pop_front();
} }
} }
@ -939,24 +954,24 @@ void ImGuiManager::DrawOSDMessages(Timer::Value current_time)
{ {
static constexpr float MOVE_DURATION = 0.5f; static constexpr float MOVE_DURATION = 0.5f;
ImFont* const font = s_osd_font; ImFont* const font = s_state.osd_font;
const float scale = s_global_scale; const float scale = s_state.global_scale;
const float spacing = std::ceil(6.0f * scale); const float spacing = std::ceil(6.0f * scale);
const float margin = std::ceil(s_screen_margin * scale); const float margin = std::ceil(s_state.screen_margin * scale);
const float padding = std::ceil(9.0f * scale); const float padding = std::ceil(9.0f * scale);
const float rounding = std::ceil(6.0f * scale); const float rounding = std::ceil(6.0f * scale);
const float max_width = s_window_width - (margin + padding) * 2.0f; const float max_width = s_state.window_width - (margin + padding) * 2.0f;
float position_x = margin; float position_x = margin;
float position_y = margin; float position_y = margin;
auto iter = s_osd_active_messages.begin(); auto iter = s_state.osd_active_messages.begin();
while (iter != s_osd_active_messages.end()) while (iter != s_state.osd_active_messages.end())
{ {
OSDMessage& msg = *iter; OSDMessage& msg = *iter;
const float time_passed = static_cast<float>(Timer::ConvertValueToSeconds(current_time - msg.start_time)); const float time_passed = static_cast<float>(Timer::ConvertValueToSeconds(current_time - msg.start_time));
if (time_passed >= msg.duration) if (time_passed >= msg.duration)
{ {
iter = s_osd_active_messages.erase(iter); iter = s_state.osd_active_messages.erase(iter);
continue; continue;
} }
@ -1074,68 +1089,68 @@ void Host::ClearOSDMessages(bool clear_warnings)
float ImGuiManager::GetGlobalScale() float ImGuiManager::GetGlobalScale()
{ {
return s_global_scale; return s_state.global_scale;
} }
float ImGuiManager::GetScreenMargin() float ImGuiManager::GetScreenMargin()
{ {
return s_screen_margin; return s_state.screen_margin;
} }
ImFont* ImGuiManager::GetDebugFont() ImFont* ImGuiManager::GetDebugFont()
{ {
return s_debug_font; return s_state.debug_font;
} }
ImFont* ImGuiManager::GetOSDFont() ImFont* ImGuiManager::GetOSDFont()
{ {
return s_osd_font; return s_state.osd_font;
} }
ImFont* ImGuiManager::GetFixedFont() ImFont* ImGuiManager::GetFixedFont()
{ {
return s_fixed_font; return s_state.fixed_font;
} }
ImFont* ImGuiManager::GetMediumFont() ImFont* ImGuiManager::GetMediumFont()
{ {
AddFullscreenFontsIfMissing(); AddFullscreenFontsIfMissing();
return s_medium_font; return s_state.medium_font;
} }
ImFont* ImGuiManager::GetLargeFont() ImFont* ImGuiManager::GetLargeFont()
{ {
AddFullscreenFontsIfMissing(); AddFullscreenFontsIfMissing();
return s_large_font; return s_state.large_font;
} }
bool ImGuiManager::WantsTextInput() bool ImGuiManager::WantsTextInput()
{ {
return s_imgui_wants_keyboard.load(std::memory_order_acquire); return s_state.imgui_wants_keyboard.load(std::memory_order_acquire);
} }
bool ImGuiManager::WantsMouseInput() bool ImGuiManager::WantsMouseInput()
{ {
return s_imgui_wants_mouse.load(std::memory_order_acquire); return s_state.imgui_wants_mouse.load(std::memory_order_acquire);
} }
void ImGuiManager::AddTextInput(std::string str) void ImGuiManager::AddTextInput(std::string str)
{ {
if (!s_imgui_context) if (!s_state.imgui_context)
return; return;
if (!s_imgui_wants_keyboard.load(std::memory_order_acquire)) if (!s_state.imgui_wants_keyboard.load(std::memory_order_acquire))
return; return;
s_imgui_context->IO.AddInputCharactersUTF8(str.c_str()); s_state.imgui_context->IO.AddInputCharactersUTF8(str.c_str());
} }
void ImGuiManager::UpdateMousePosition(float x, float y) void ImGuiManager::UpdateMousePosition(float x, float y)
{ {
if (!s_imgui_context) if (!s_state.imgui_context)
return; return;
s_imgui_context->IO.MousePos = ImVec2(x, y); s_state.imgui_context->IO.MousePos = ImVec2(x, y);
std::atomic_thread_fence(std::memory_order_release); std::atomic_thread_fence(std::memory_order_release);
} }
@ -1150,53 +1165,53 @@ void ImGuiManager::SetCommonIOOptions(ImGuiIO& io)
bool ImGuiManager::ProcessPointerButtonEvent(InputBindingKey key, float value) bool ImGuiManager::ProcessPointerButtonEvent(InputBindingKey key, float value)
{ {
if (!s_imgui_context || key.data >= std::size(ImGui::GetIO().MouseDown)) if (!s_state.imgui_context || key.data >= std::size(ImGui::GetIO().MouseDown))
return false; return false;
// still update state anyway // still update state anyway
s_imgui_context->IO.AddMouseButtonEvent(key.data, value != 0.0f); s_state.imgui_context->IO.AddMouseButtonEvent(key.data, value != 0.0f);
return s_imgui_wants_mouse.load(std::memory_order_acquire); return s_state.imgui_wants_mouse.load(std::memory_order_acquire);
} }
bool ImGuiManager::ProcessPointerAxisEvent(InputBindingKey key, float value) bool ImGuiManager::ProcessPointerAxisEvent(InputBindingKey key, float value)
{ {
if (!s_imgui_context || key.data < static_cast<u32>(InputPointerAxis::WheelX)) if (!s_state.imgui_context || key.data < static_cast<u32>(InputPointerAxis::WheelX))
return false; return false;
// still update state anyway // still update state anyway
const bool horizontal = (key.data == static_cast<u32>(InputPointerAxis::WheelX)); const bool horizontal = (key.data == static_cast<u32>(InputPointerAxis::WheelX));
s_imgui_context->IO.AddMouseWheelEvent(horizontal ? value : 0.0f, horizontal ? 0.0f : value); s_state.imgui_context->IO.AddMouseWheelEvent(horizontal ? value : 0.0f, horizontal ? 0.0f : value);
return s_imgui_wants_mouse.load(std::memory_order_acquire); return s_state.imgui_wants_mouse.load(std::memory_order_acquire);
} }
bool ImGuiManager::ProcessHostKeyEvent(InputBindingKey key, float value) bool ImGuiManager::ProcessHostKeyEvent(InputBindingKey key, float value)
{ {
if (!s_imgui_context) if (!s_state.imgui_context)
return false; return false;
// still update state anyway // still update state anyway
SetImKeyState(s_imgui_context->IO, key.data, (value != 0.0f)); SetImKeyState(s_state.imgui_context->IO, key.data, (value != 0.0f));
return s_imgui_wants_keyboard.load(std::memory_order_acquire); return s_state.imgui_wants_keyboard.load(std::memory_order_acquire);
} }
void ImGuiManager::SetImKeyState(ImGuiIO& io, u32 key, bool pressed) void ImGuiManager::SetImKeyState(ImGuiIO& io, u32 key, bool pressed)
{ {
const auto iter = s_imgui_key_map.find(key); const auto iter = s_state.imgui_key_map.find(key);
if (iter == s_imgui_key_map.end()) if (iter == s_state.imgui_key_map.end())
return; return;
const ImGuiKey imkey = iter->second; const ImGuiKey imkey = iter->second;
s_imgui_context->IO.AddKeyEvent(imkey, pressed); s_state.imgui_context->IO.AddKeyEvent(imkey, pressed);
// modifier keys need to be handled separately // modifier keys need to be handled separately
if ((imkey >= ImGuiKey_LeftCtrl && imkey <= ImGuiKey_LeftSuper) || if ((imkey >= ImGuiKey_LeftCtrl && imkey <= ImGuiKey_LeftSuper) ||
(imkey >= ImGuiKey_RightCtrl && imkey <= ImGuiKey_RightSuper)) (imkey >= ImGuiKey_RightCtrl && imkey <= ImGuiKey_RightSuper))
{ {
const u32 idx = imkey - ((imkey >= ImGuiKey_RightCtrl) ? ImGuiKey_RightCtrl : ImGuiKey_LeftCtrl); const u32 idx = imkey - ((imkey >= ImGuiKey_RightCtrl) ? ImGuiKey_RightCtrl : ImGuiKey_LeftCtrl);
s_imgui_context->IO.AddKeyEvent(static_cast<ImGuiKey>(static_cast<u32>(ImGuiMod_Ctrl) << idx), pressed); s_state.imgui_context->IO.AddKeyEvent(static_cast<ImGuiKey>(static_cast<u32>(ImGuiMod_Ctrl) << idx), pressed);
} }
} }
@ -1231,14 +1246,14 @@ bool ImGuiManager::ProcessGenericInputEvent(GenericInputBinding key, float value
ImGuiKey_GamepadL2, // R2 ImGuiKey_GamepadL2, // R2
}; };
if (!s_imgui_context) if (!s_state.imgui_context)
return false; return false;
if (static_cast<u32>(key) >= std::size(key_map) || key_map[static_cast<u32>(key)] == ImGuiKey_None) if (static_cast<u32>(key) >= std::size(key_map) || key_map[static_cast<u32>(key)] == ImGuiKey_None)
return false; return false;
s_imgui_context->IO.AddKeyAnalogEvent(key_map[static_cast<u32>(key)], (value > 0.0f), value); s_state.imgui_context->IO.AddKeyAnalogEvent(key_map[static_cast<u32>(key)], (value > 0.0f), value);
return s_imgui_wants_keyboard.load(std::memory_order_acquire); return s_state.imgui_wants_keyboard.load(std::memory_order_acquire);
} }
const char* ImGuiManager::GetClipboardTextImpl(void* userdata) const char* ImGuiManager::GetClipboardTextImpl(void* userdata)
@ -1265,22 +1280,22 @@ void ImGuiManager::SetClipboardTextImpl(void* userdata, const char* text)
void ImGuiManager::CreateSoftwareCursorTextures() void ImGuiManager::CreateSoftwareCursorTextures()
{ {
for (u32 i = 0; i < static_cast<u32>(s_software_cursors.size()); i++) for (u32 i = 0; i < static_cast<u32>(s_state.software_cursors.size()); i++)
{ {
if (!s_software_cursors[i].image_path.empty()) if (!s_state.software_cursors[i].image_path.empty())
UpdateSoftwareCursorTexture(i); UpdateSoftwareCursorTexture(i);
} }
} }
void ImGuiManager::DestroySoftwareCursorTextures() void ImGuiManager::DestroySoftwareCursorTextures()
{ {
for (SoftwareCursor& sc : s_software_cursors) for (SoftwareCursor& sc : s_state.software_cursors)
sc.texture.reset(); sc.texture.reset();
} }
void ImGuiManager::UpdateSoftwareCursorTexture(u32 index) void ImGuiManager::UpdateSoftwareCursorTexture(u32 index)
{ {
SoftwareCursor& sc = s_software_cursors[index]; SoftwareCursor& sc = s_state.software_cursors[index];
if (sc.image_path.empty()) if (sc.image_path.empty())
{ {
sc.texture.reset(); sc.texture.reset();
@ -1305,8 +1320,8 @@ void ImGuiManager::UpdateSoftwareCursorTexture(u32 index)
return; return;
} }
sc.extent_x = std::ceil(static_cast<float>(image.GetWidth()) * sc.scale * s_global_scale) / 2.0f; sc.extent_x = std::ceil(static_cast<float>(image.GetWidth()) * sc.scale * s_state.global_scale) / 2.0f;
sc.extent_y = std::ceil(static_cast<float>(image.GetHeight()) * sc.scale * s_global_scale) / 2.0f; sc.extent_y = std::ceil(static_cast<float>(image.GetHeight()) * sc.scale * s_state.global_scale) / 2.0f;
} }
void ImGuiManager::DrawSoftwareCursor(const SoftwareCursor& sc, const std::pair<float, float>& pos) void ImGuiManager::DrawSoftwareCursor(const SoftwareCursor& sc, const std::pair<float, float>& pos)
@ -1328,16 +1343,16 @@ void ImGuiManager::RenderSoftwareCursors()
// This one's okay to race, worst that happens is we render the wrong number of cursors for a frame. // This one's okay to race, worst that happens is we render the wrong number of cursors for a frame.
const u32 pointer_count = InputManager::GetPointerCount(); const u32 pointer_count = InputManager::GetPointerCount();
for (u32 i = 0; i < pointer_count; i++) for (u32 i = 0; i < pointer_count; i++)
DrawSoftwareCursor(s_software_cursors[i], InputManager::GetPointerAbsolutePosition(i)); DrawSoftwareCursor(s_state.software_cursors[i], InputManager::GetPointerAbsolutePosition(i));
for (u32 i = InputManager::MAX_POINTER_DEVICES; i < InputManager::MAX_SOFTWARE_CURSORS; i++) for (u32 i = InputManager::MAX_POINTER_DEVICES; i < InputManager::MAX_SOFTWARE_CURSORS; i++)
DrawSoftwareCursor(s_software_cursors[i], s_software_cursors[i].pos); DrawSoftwareCursor(s_state.software_cursors[i], s_state.software_cursors[i].pos);
} }
void ImGuiManager::SetSoftwareCursor(u32 index, std::string image_path, float image_scale, u32 multiply_color) void ImGuiManager::SetSoftwareCursor(u32 index, std::string image_path, float image_scale, u32 multiply_color)
{ {
DebugAssert(index < std::size(s_software_cursors)); DebugAssert(index < std::size(s_state.software_cursors));
SoftwareCursor& sc = s_software_cursors[index]; SoftwareCursor& sc = s_state.software_cursors[index];
sc.color = multiply_color | 0xFF000000; sc.color = multiply_color | 0xFF000000;
if (sc.image_path == image_path && sc.scale == image_scale) if (sc.image_path == image_path && sc.scale == image_scale)
return; return;
@ -1355,7 +1370,7 @@ void ImGuiManager::SetSoftwareCursor(u32 index, std::string image_path, float im
bool ImGuiManager::HasSoftwareCursor(u32 index) bool ImGuiManager::HasSoftwareCursor(u32 index)
{ {
return (index < s_software_cursors.size() && !s_software_cursors[index].image_path.empty()); return (index < s_state.software_cursors.size() && !s_state.software_cursors[index].image_path.empty());
} }
void ImGuiManager::ClearSoftwareCursor(u32 index) void ImGuiManager::ClearSoftwareCursor(u32 index)
@ -1366,7 +1381,7 @@ void ImGuiManager::ClearSoftwareCursor(u32 index)
void ImGuiManager::SetSoftwareCursorPosition(u32 index, float pos_x, float pos_y) void ImGuiManager::SetSoftwareCursorPosition(u32 index, float pos_x, float pos_y)
{ {
DebugAssert(index >= InputManager::MAX_POINTER_DEVICES); DebugAssert(index >= InputManager::MAX_POINTER_DEVICES);
SoftwareCursor& sc = s_software_cursors[index]; SoftwareCursor& sc = s_state.software_cursors[index];
sc.pos.first = pos_x; sc.pos.first = pos_x;
sc.pos.second = pos_y; sc.pos.second = pos_y;
} }
@ -1436,7 +1451,7 @@ bool ImGuiManager::CreateAuxiliaryRenderWindow(AuxiliaryRenderWindowState* state
AddDebugFontIfMissing(); AddDebugFontIfMissing();
state->imgui_context = ImGui::CreateContext(s_imgui_context->IO.Fonts); state->imgui_context = ImGui::CreateContext(s_state.imgui_context->IO.Fonts);
state->imgui_context->IO.DisplaySize = state->imgui_context->IO.DisplaySize =
ImVec2(static_cast<float>(state->swap_chain->GetWidth()), static_cast<float>(state->swap_chain->GetHeight())); ImVec2(static_cast<float>(state->swap_chain->GetWidth()), static_cast<float>(state->swap_chain->GetHeight()));
state->imgui_context->IO.IniFilename = nullptr; state->imgui_context->IO.IniFilename = nullptr;
@ -1505,7 +1520,7 @@ bool ImGuiManager::RenderAuxiliaryRenderWindow(AuxiliaryRenderWindowState* state
ImGui::SetCurrentContext(state->imgui_context); ImGui::SetCurrentContext(state->imgui_context);
ImGui::NewFrame(); ImGui::NewFrame();
ImGui::PushFont(s_debug_font); ImGui::PushFont(s_state.debug_font);
ImGui::SetNextWindowPos(ImVec2(0.0f, 0.0f), ImGuiCond_Always); ImGui::SetNextWindowPos(ImVec2(0.0f, 0.0f), ImGuiCond_Always);
ImGui::SetNextWindowSize(state->imgui_context->IO.DisplaySize, ImGuiCond_Always); ImGui::SetNextWindowSize(state->imgui_context->IO.DisplaySize, ImGuiCond_Always);
if (ImGui::Begin("AuxRenderWindowMain", nullptr, if (ImGui::Begin("AuxRenderWindowMain", nullptr,