Move ImGui setup to common, and enable fullscreen UI in Qt

This commit is contained in:
Connor McLaughlin
2021-02-22 02:38:16 +10:00
parent d0f6ff03a5
commit 8318cdb3c1
16 changed files with 319 additions and 216 deletions

View File

@ -33,6 +33,8 @@ GeneralSettingsWidget::GeneralSettingsWidget(QtHostInterface* host_interface, QW
SettingWidgetBinder::BindWidgetToBoolSetting(m_host_interface, m_ui.applyGameSettings, "Main", "ApplyGameSettings",
true);
SettingWidgetBinder::BindWidgetToBoolSetting(m_host_interface, m_ui.autoLoadCheats, "Main", "AutoLoadCheats", false);
SettingWidgetBinder::BindWidgetToBoolSetting(m_host_interface, m_ui.enableFullscreenUI, "Main", "EnableFullscreenUI",
false);
SettingWidgetBinder::BindWidgetToEnumSetting(
m_host_interface, m_ui.controllerBackend, "Main", "ControllerBackend", &ControllerInterface::ParseBackendName,
@ -74,9 +76,12 @@ GeneralSettingsWidget::GeneralSettingsWidget(QtHostInterface* host_interface, QW
ControllerInterface::GetDefaultBackend())),
tr("Determines the backend which is used for controller input. Windows users may prefer "
"to use XInput over SDL2 for compatibility."));
dialog->registerWidgetHelp(
m_ui.enableFullscreenUI, tr("Enable Fullscreen UI"), tr("Unchecked"),
tr("Enables the fullscreen UI mode, suitable for controller operation which is used in the NoGUI frontend."));
// Since this one is compile-time selected, we don't put it in the .ui file.
int current_col = 0;
int current_col = 1;
int current_row = m_ui.formLayout_4->rowCount() - current_col;
#ifdef WITH_DISCORD_PRESENCE
{

View File

@ -102,6 +102,13 @@
</property>
</widget>
</item>
<item row="5" column="0">
<widget class="QCheckBox" name="enableFullscreenUI">
<property name="text">
<string>Enable Fullscreen UI</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>

View File

@ -10,6 +10,7 @@
#include "core/gpu.h"
#include "core/system.h"
#include "frontend-common/game_list.h"
#include "frontend-common/imgui_fullscreen.h"
#include "frontend-common/imgui_styles.h"
#include "frontend-common/ini_settings_interface.h"
#include "frontend-common/opengl_host_display.h"
@ -97,6 +98,10 @@ bool QtHostInterface::initializeOnThread()
if (!CommonHostInterface::Initialize())
return false;
// imgui setup
setImGuiFont();
setImGuiKeyMap();
// make sure the controllers have been detected
if (m_controller_interface)
m_controller_interface->PollEvents();
@ -294,7 +299,7 @@ void QtHostInterface::ApplySettings(bool display_osd_messages)
m_is_rendering_to_main = render_to_main;
updateDisplayState();
}
else
else if (!m_fullscreen_ui_enabled)
{
renderDisplay();
}
@ -367,6 +372,11 @@ void QtHostInterface::resumeSystemFromMostRecentState()
void QtHostInterface::onDisplayWindowKeyEvent(int key, bool pressed)
{
DebugAssert(isOnWorkerThread());
const u32 masked_key = static_cast<u32>(key) & IMGUI_KEY_MASK;
if (masked_key < countof(ImGuiIO::KeysDown))
ImGui::GetIO().KeysDown[masked_key] = pressed;
HandleHostKeyEvent(key, pressed);
}
@ -377,14 +387,11 @@ void QtHostInterface::onDisplayWindowMouseMoveEvent(int x, int y)
if (!m_display)
return;
m_display->SetMousePosition(x, y);
ImGuiIO& io = ImGui::GetIO();
io.MousePos[0] = static_cast<float>(x);
io.MousePos[1] = static_cast<float>(y);
if (ImGui::GetCurrentContext())
{
ImGuiIO& io = ImGui::GetIO();
io.MousePos[0] = static_cast<float>(x);
io.MousePos[1] = static_cast<float>(y);
}
m_display->SetMousePosition(x, y);
}
void QtHostInterface::onDisplayWindowMouseButtonEvent(int button, bool pressed)
@ -413,6 +420,7 @@ void QtHostInterface::onHostDisplayWindowResized(int width, int height)
return;
m_display->ResizeRenderWindow(width, height);
OnHostDisplayResized(width, height, m_display->GetWindowScale());
// re-render the display, since otherwise it will be out of date and stretched if paused
if (!System::IsShutdown())
@ -426,8 +434,9 @@ void QtHostInterface::onHostDisplayWindowResized(int width, int height)
updateDisplayState();
}
g_gpu->UpdateResolutionScale();
renderDisplay();
// force redraw if we're paused
if (!m_fullscreen_ui_enabled)
renderDisplay();
}
}
@ -470,16 +479,12 @@ bool QtHostInterface::AcquireHostDisplay()
return false;
}
createImGuiContext(display_widget->devicePixelRatioFromScreen());
if (!m_display->MakeRenderContextCurrent() ||
!m_display->InitializeRenderDevice(GetShaderCacheBasePath(), g_settings.gpu_use_debug_device,
g_settings.gpu_threaded_presentation) ||
!m_display->CreateImGuiContext() || !m_display->UpdateImGuiFontTexture() || !CreateHostDisplayResources())
!CreateHostDisplayResources())
{
ReleaseHostDisplayResources();
m_display->DestroyImGuiContext();
destroyImGuiContext();
m_display->DestroyRenderDevice();
emit destroyDisplayRequested();
m_display.reset();
@ -545,12 +550,16 @@ void QtHostInterface::updateDisplayState()
connectDisplaySignals(display_widget);
m_is_exclusive_fullscreen = m_display->IsFullscreen();
OnHostDisplayResized(m_display->GetWindowWidth(), m_display->GetWindowHeight(), m_display->GetWindowScale());
if (!System::IsShutdown())
{
g_gpu->UpdateResolutionScale();
UpdateSoftwareCursor();
redrawDisplayWindow();
if (!m_fullscreen_ui_enabled)
redrawDisplayWindow();
}
UpdateSpeedLimiterState();
}
@ -559,9 +568,7 @@ void QtHostInterface::ReleaseHostDisplay()
Assert(m_display);
ReleaseHostDisplayResources();
m_display->DestroyImGuiContext();
m_display->DestroyRenderDevice();
destroyImGuiContext();
emit destroyDisplayRequested();
m_display.reset();
m_is_fullscreen = false;
@ -1370,32 +1377,40 @@ void QtHostInterface::threadEntryPoint()
// TODO: Event which flags the thread as ready
while (!m_shutdown_flag.load())
{
if (!System::IsRunning())
if (System::IsRunning())
{
// wait until we have a system before running
m_worker_thread_event_loop->exec();
continue;
}
if (m_display_all_frames)
System::RunFrame();
else
System::RunFrames();
if (m_display_all_frames)
System::RunFrame();
UpdateControllerRumble();
if (m_frame_step_request)
{
m_frame_step_request = false;
PauseSystem(true);
}
renderDisplay();
System::UpdatePerformanceCounters();
if (m_throttler_enabled)
System::Throttle();
}
else
System::RunFrames();
UpdateControllerRumble();
if (m_frame_step_request)
{
m_frame_step_request = false;
PauseSystem(true);
// we want to keep rendering the UI when paused and fullscreen UI is enabled
if (!m_fullscreen_ui_enabled || !System::IsValid())
{
// wait until we have a system before running
m_worker_thread_event_loop->exec();
continue;
}
renderDisplay();
}
renderDisplay();
System::UpdatePerformanceCounters();
if (m_throttler_enabled)
System::Throttle();
m_worker_thread_event_loop->processEvents(QEventLoop::AllEvents);
PollAndUpdate();
}
@ -1447,8 +1462,10 @@ static std::string GetFontPath(const char* name)
#endif
}
static bool AddImGuiFont(const std::string& language, float size, float framebuffer_scale)
void QtHostInterface::setImGuiFont()
{
std::string language(GetStringSettingValue("Main", "Language", ""));
std::string path;
const ImWchar* range = nullptr;
#ifdef WIN32
@ -1465,34 +1482,35 @@ static bool AddImGuiFont(const std::string& language, float size, float framebuf
#endif
if (!path.empty())
{
return (ImGui::GetIO().Fonts->AddFontFromFileTTF(path.c_str(), size * framebuffer_scale, nullptr, range) !=
nullptr);
}
return false;
ImGuiFullscreen::SetFontFilename(std::move(path));
if (range)
ImGuiFullscreen::SetFontGlyphRanges(range);
}
void QtHostInterface::createImGuiContext(float framebuffer_scale)
void QtHostInterface::setImGuiKeyMap()
{
ImGui::CreateContext();
auto& io = ImGui::GetIO();
io.IniFilename = nullptr;
io.DisplayFramebufferScale.x = framebuffer_scale;
io.DisplayFramebufferScale.y = framebuffer_scale;
ImGui::GetStyle().ScaleAllSizes(framebuffer_scale);
ImGui::StyleColorsDarker();
std::string language = GetStringSettingValue("Main", "Language", "");
if (!AddImGuiFont(language, 15.0f, framebuffer_scale))
ImGui::AddRobotoRegularFont(15.0f * framebuffer_scale);
}
void QtHostInterface::destroyImGuiContext()
{
ImGui::DestroyContext();
ImGuiIO& io = ImGui::GetIO();
io.KeyMap[ImGuiKey_Tab] = Qt::Key_Tab & IMGUI_KEY_MASK;
io.KeyMap[ImGuiKey_LeftArrow] = Qt::Key_Left & IMGUI_KEY_MASK;
io.KeyMap[ImGuiKey_RightArrow] = Qt::Key_Right & IMGUI_KEY_MASK;
io.KeyMap[ImGuiKey_UpArrow] = Qt::Key_Up & IMGUI_KEY_MASK;
io.KeyMap[ImGuiKey_DownArrow] = Qt::Key_Down & IMGUI_KEY_MASK;
io.KeyMap[ImGuiKey_PageUp] = Qt::Key_PageUp & IMGUI_KEY_MASK;
io.KeyMap[ImGuiKey_PageDown] = Qt::Key_PageDown & IMGUI_KEY_MASK;
io.KeyMap[ImGuiKey_Home] = Qt::Key_Home & IMGUI_KEY_MASK;
io.KeyMap[ImGuiKey_End] = Qt::Key_End & IMGUI_KEY_MASK;
io.KeyMap[ImGuiKey_Insert] = Qt::Key_Insert & IMGUI_KEY_MASK;
io.KeyMap[ImGuiKey_Delete] = Qt::Key_Delete & IMGUI_KEY_MASK;
io.KeyMap[ImGuiKey_Backspace] = Qt::Key_Backspace & IMGUI_KEY_MASK;
io.KeyMap[ImGuiKey_Space] = Qt::Key_Space & IMGUI_KEY_MASK;
io.KeyMap[ImGuiKey_Enter] = Qt::Key_Enter & IMGUI_KEY_MASK;
io.KeyMap[ImGuiKey_Escape] = Qt::Key_Escape & IMGUI_KEY_MASK;
io.KeyMap[ImGuiKey_A] = Qt::Key_A & IMGUI_KEY_MASK;
io.KeyMap[ImGuiKey_C] = Qt::Key_C & IMGUI_KEY_MASK;
io.KeyMap[ImGuiKey_V] = Qt::Key_V & IMGUI_KEY_MASK;
io.KeyMap[ImGuiKey_X] = Qt::Key_X & IMGUI_KEY_MASK;
io.KeyMap[ImGuiKey_Y] = Qt::Key_Y & IMGUI_KEY_MASK;
io.KeyMap[ImGuiKey_Z] = Qt::Key_Z & IMGUI_KEY_MASK;
}
TinyString QtHostInterface::TranslateString(const char* context, const char* str) const

View File

@ -213,7 +213,10 @@ private:
BACKGROUND_CONTROLLER_POLLING_INTERVAL =
100, /// Interval at which the controllers are polled when the system is not active.
SETTINGS_SAVE_DELAY = 1000
SETTINGS_SAVE_DELAY = 1000,
/// Crappy solution to the Qt indices being massive.
IMGUI_KEY_MASK = 511,
};
using InputButtonHandler = std::function<void(bool)>;
@ -242,8 +245,8 @@ private:
void startBackgroundControllerPollTimer();
void stopBackgroundControllerPollTimer();
void createImGuiContext(float framebuffer_scale);
void destroyImGuiContext();
void setImGuiFont();
void setImGuiKeyMap();
void createThread();
void stopThread();