gui: init once. reset ui driver when needed. android 120+ Hz support

ImGui is now initialized once at startup and shutdown before
terminating. graphics initialization is independent.
Move more imgui stuff into imgui drivers.
switch: set scaling on external screen to 1.4, same as xbox
UI scaling refactoring.
This commit is contained in:
Flyinghead 2022-04-13 18:06:19 +02:00
parent ddfc00ed9f
commit a710674cd4
46 changed files with 243 additions and 222 deletions

View File

@ -247,7 +247,7 @@ public:
void restart()
{
emu.unloadGame();
emu.loadGame(settings.content.path);
emu.loadGame(settings.content.path.c_str());
emu.start();
}

View File

@ -399,21 +399,19 @@ int main(int argc, char* argv[])
mainui_loop();
flycast_term();
os_UninstallFaultHandler();
#if defined(USE_EVDEV)
input_evdev_close();
#endif
#if defined(SUPPORT_X11)
x11_window_destroy();
#endif
#if defined(USE_SDL)
sdl_window_destroy();
#endif
flycast_term();
os_UninstallFaultHandler();
#if defined(__SWITCH__)
socketExit();
#endif

View File

@ -279,7 +279,7 @@ void x11_window_create()
int x11Screen = XDefaultScreen(x11_disp);
float xdpi = (float)DisplayWidth(x11_disp, x11Screen) / DisplayWidthMM(x11_disp, x11Screen) * 25.4;
float ydpi = (float)DisplayHeight(x11_disp, x11Screen) / DisplayHeightMM(x11_disp, x11Screen) * 25.4;
screen_dpi = std::max(xdpi, ydpi);
settings.display.dpi = std::max(xdpi, ydpi);
int depth = CopyFromParent;

View File

@ -366,7 +366,7 @@ static void beginWindow(const char *title, int x, int y, int w, int h)
ImGui::PushStyleVar(ImGuiStyleVar_WindowRounding, 0);
ImGui::PushStyleVar(ImGuiStyleVar_WindowBorderSize, 0);
ImGui::SetNextWindowPos(ImVec2(x, y));
ImGui::SetNextWindowSize(ImVec2(w * scaling, h * scaling));
ImGui::SetNextWindowSize(ImVec2(w * settings.display.uiScale, h * settings.display.uiScale));
ImGui::SetNextWindowBgAlpha(0.7f);
ImGui::Begin(title, NULL, ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoNavInputs | ImGuiWindowFlags_NoNavFocus);
ImGui::PushStyleColor(ImGuiCol_PlotHistogram, ImVec4(0.557f, 0.268f, 0.965f, 1.f));
@ -392,7 +392,7 @@ static void uiTextRightAligned(const std::string& text)
static void uiBargraph(float v)
{
ImGui::ProgressBar(v, ImVec2(-1, 10.f * scaling), "");
ImGui::ProgressBar(v, ImVec2(-1, 10.f * settings.display.uiScale), "");
}
static int uiButton(lua_State *L)

View File

@ -818,14 +818,14 @@ void displayStats()
ImGui::PushStyleVar(ImGuiStyleVar_WindowRounding, 0);
ImGui::PushStyleVar(ImGuiStyleVar_WindowBorderSize, 0);
ImGui::SetNextWindowPos(ImVec2(10, 10));
ImGui::SetNextWindowSize(ImVec2(95 * scaling, 0));
ImGui::SetNextWindowSize(ImVec2(95 * settings.display.uiScale, 0));
ImGui::SetNextWindowBgAlpha(0.7f);
ImGui::Begin("##ggpostats", NULL, ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoDecoration | ImGuiWindowFlags_NoInputs);
ImGui::PushStyleColor(ImGuiCol_PlotHistogram, ImVec4(0.557f, 0.268f, 0.965f, 1.f));
// Send Queue
ImGui::Text("Send Q");
ImGui::ProgressBar(stats.network.send_queue_len / 10.f, ImVec2(-1, 10.f * scaling), "");
ImGui::ProgressBar(stats.network.send_queue_len / 10.f, ImVec2(-1, 10.f * settings.display.uiScale), "");
// Frame Delay
ImGui::Text("Delay");
@ -847,7 +847,7 @@ void displayStats()
// yellow
ImGui::PushStyleColor(ImGuiCol_PlotHistogram, ImVec4(.9f, .9f, .1f, 1));
ImGui::Text("Predicted");
ImGui::ProgressBar(stats.sync.predicted_frames / 7.f, ImVec2(-1, 10.f * scaling), "");
ImGui::ProgressBar(stats.sync.predicted_frames / 7.f, ImVec2(-1, 10.f * settings.display.uiScale), "");
if (stats.sync.predicted_frames >= 5)
ImGui::PopStyleColor();
@ -856,7 +856,7 @@ void displayStats()
if (timesync > 0)
ImGui::PushStyleColor(ImGuiCol_Text, ImVec4(1, 0, 0, 1));
ImGui::Text("Behind");
ImGui::ProgressBar(0.5f + stats.timesync.local_frames_behind / 16.f, ImVec2(-1, 10.f * scaling), "");
ImGui::ProgressBar(0.5f + stats.timesync.local_frames_behind / 16.f, ImVec2(-1, 10.f * settings.display.uiScale), "");
if (timesync > 0)
{
ImGui::PopStyleColor();

View File

@ -44,7 +44,7 @@ int flycast_init(int argc, char* argv[])
LogManager::Init();
config::Settings::instance().load(false);
}
gui_init();
os_CreateWindow();
os_SetupInput();
@ -76,6 +76,7 @@ void flycast_term()
gui_cancel_load();
lua::term();
emu.term();
gui_term();
}
void dc_savestate(int index)

View File

@ -25,6 +25,14 @@
class DX11Driver final : public ImGuiDriver
{
public:
DX11Driver(ID3D11Device* device, ID3D11DeviceContext* deviceContext) {
ImGui_ImplDX11_Init(device, deviceContext);
}
~DX11Driver() {
ImGui_ImplDX11_Shutdown();
}
void newFrame() override {
ImGui_ImplDX11_NewFrame();
}

View File

@ -20,22 +20,16 @@
#include "rend/osd.h"
#ifdef LIBRETRO
#include "vmu_xhair.h"
#else
#include "rend/gui.h"
#endif
void DX11Overlay::draw(u32 width, u32 height, bool vmu, bool crosshair)
{
#ifdef LIBRETRO
const float scaling = 1;
#endif
RECT rect { 0, 0, (LONG)width, (LONG)height };
deviceContext->RSSetScissorRects(1, &rect);
if (vmu)
{
float vmu_padding = 8.f * scaling;
float vmu_height = 70.f * scaling;
float vmu_padding = 8.f * settings.display.uiScale;
float vmu_height = 70.f * settings.display.uiScale;
float vmu_width = 48.f / 32.f * vmu_height;
#ifndef LIBRETRO
@ -178,7 +172,7 @@ void DX11Overlay::draw(u32 width, u32 height, bool vmu, bool crosshair)
#ifdef LIBRETRO
float halfWidth = LIGHTGUN_CROSSHAIR_SIZE / 2.f;
#else
float halfWidth = XHAIR_WIDTH * gui_get_scaling() / 2.f;
float halfWidth = XHAIR_WIDTH * settings.display.uiScale / 2.f;
#endif
D3D11_VIEWPORT vp{};
vp.TopLeftX = x - halfWidth;

View File

@ -18,7 +18,6 @@
*/
#include "dx11context.h"
#ifndef LIBRETRO
#include "rend/gui.h"
#include "rend/osd.h"
#ifdef USE_SDL
#include "sdl/sdl.h"
@ -26,6 +25,7 @@
#include "hw/pvr/Renderer_if.h"
#include "emulator.h"
#include "dx11_driver.h"
#include "imgui_impl_dx11.h"
#ifdef TARGET_UWP
#include <windows.h>
#include <gamingdeviceinformation.h>
@ -53,12 +53,10 @@ bool DX11Context::init(bool keepCurrentWindow)
settings.display.height = displayMode->ResolutionHeightInRawPixels;
if (settings.display.width == 3840)
// 4K
scaling = 2.8f;
settings.display.uiScale = 2.8f;
else
scaling = 1.4f;
settings.display.uiScale = 1.4f;
}
else
scaling = 1.f;
#endif
D3D_FEATURE_LEVEL featureLevels[] =
@ -158,12 +156,12 @@ bool DX11Context::init(bool keepCurrentWindow)
NOTICE_LOG(RENDERER, "No system-provided shader cache");
}
imguiDriver = std::unique_ptr<ImGuiDriver>(new DX11Driver());
imguiDriver = std::unique_ptr<ImGuiDriver>(new DX11Driver(pDevice, pDeviceContext));
resize();
gui_init();
shaders.init(pDevice, &D3DCompile);
overlay.init(pDevice, pDeviceContext, &shaders, &samplers);
return ImGui_ImplDX11_Init(pDevice, pDeviceContext);
return true;
}
void DX11Context::term()
@ -174,8 +172,6 @@ void DX11Context::term()
samplers.term();
shaders.term();
imguiDriver.reset();
ImGui_ImplDX11_Shutdown();
gui_term();
renderTargetView.reset();
swapchain1.reset();
swapchain.reset();

View File

@ -25,7 +25,6 @@
#include <windows.h>
#include <d3d11.h>
#include <dxgi1_2.h>
#include "imgui_impl_dx11.h"
#include "windows/comptr.h"
#include "dx11_overlay.h"
#include "wsi/context.h"

View File

@ -18,7 +18,6 @@
*/
#include "d3d_overlay.h"
#include "rend/osd.h"
#include "rend/gui.h"
#include <glm/glm.hpp>
#include <glm/gtx/transform.hpp>
@ -39,8 +38,8 @@ void D3DOverlay::draw(u32 width, u32 height, bool vmu, bool crosshair)
setupRenderState(width, height);
if (vmu)
{
float vmu_padding = 8.f * scaling;
float vmu_height = 70.f * scaling;
float vmu_padding = 8.f * settings.display.uiScale;
float vmu_height = 70.f * settings.display.uiScale;
float vmu_width = 48.f / 32.f * vmu_height;
for (size_t i = 0; i < vmuTextures.size(); i++)
@ -118,7 +117,7 @@ void D3DOverlay::draw(u32 width, u32 height, bool vmu, bool crosshair)
float x, y;
std::tie(x, y) = getCrosshairPosition(i);
float halfWidth = XHAIR_WIDTH * gui_get_scaling() / 2.f;
float halfWidth = XHAIR_WIDTH * settings.display.uiScale / 2.f;
RECT rect { (long) (x - halfWidth), (long) (y - halfWidth), (long) (x + halfWidth), (long) (y + halfWidth) };
D3DCOLOR color = (config::CrosshairColor[i] & 0xFF00FF00)
| ((config::CrosshairColor[i] >> 16) & 0xFF)

View File

@ -24,7 +24,15 @@
class DX9Driver final : public ImGuiDriver
{
public:
void newFrame() override {
DX9Driver(IDirect3DDevice9* device) {
ImGui_ImplDX9_Init(device);
}
~DX9Driver() {
ImGui_ImplDX9_Shutdown();
}
void newFrame() override {
ImGui_ImplDX9_NewFrame();
}

View File

@ -18,7 +18,6 @@
*/
#include "dxcontext.h"
#include "d3d_renderer.h"
#include "rend/gui.h"
#include "rend/osd.h"
#ifdef USE_SDL
#include "sdl/sdl.h"
@ -26,6 +25,7 @@
#include "hw/pvr/Renderer_if.h"
#include "emulator.h"
#include "dx9_driver.h"
#include "imgui_impl_dx9.h"
DXContext theDXContext;
@ -74,10 +74,10 @@ bool DXContext::init(bool keepCurrentWindow)
if (FAILED(pD3D->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, (HWND)window,
D3DCREATE_HARDWARE_VERTEXPROCESSING, &d3dpp, &pDevice.get())))
return false;
imguiDriver = std::unique_ptr<ImGuiDriver>(new DX9Driver());
gui_init();
imguiDriver = std::unique_ptr<ImGuiDriver>(new DX9Driver(pDevice));
overlay.init(pDevice);
return ImGui_ImplDX9_Init(pDevice.get());
return true;
}
void DXContext::term()
@ -85,8 +85,6 @@ void DXContext::term()
GraphicsContext::instance = nullptr;
overlay.term();
imguiDriver.reset();
ImGui_ImplDX9_Shutdown();
gui_term();
pDevice.reset();
pD3D.reset();
}

View File

@ -22,7 +22,6 @@
#include "types.h"
#include <windows.h>
#include <d3d9.h>
#include "imgui_impl_dx9.h"
#include "windows/comptr.h"
#include "d3d_overlay.h"
#include "wsi/context.h"

View File

@ -76,9 +76,9 @@ void OpenGLDriver::displayVmus()
ImGui::Begin("vmu-window", nullptr, ImGuiWindowFlags_NoDecoration | ImGuiWindowFlags_NoNav | ImGuiWindowFlags_NoInputs
| ImGuiWindowFlags_NoBackground | ImGuiWindowFlags_NoFocusOnAppearing);
const float width = VMU_WIDTH * scaling;
const float height = VMU_HEIGHT * scaling;
const float padding = VMU_PADDING * scaling;
const float width = VMU_WIDTH * settings.display.uiScale;
const float height = VMU_HEIGHT * settings.display.uiScale;
const float padding = VMU_PADDING * settings.display.uiScale;
for (int i = 0; i < 8; i++)
{
if (!vmu_lcd_status[i])
@ -137,9 +137,9 @@ void OpenGLDriver::displayCrosshairs()
ImVec2 pos;
std::tie(pos.x, pos.y) = getCrosshairPosition(i);
pos.x -= (XHAIR_WIDTH * scaling) / 2.f;
pos.y += (XHAIR_WIDTH * scaling) / 2.f;
ImVec2 pos_b(pos.x + XHAIR_WIDTH * scaling, pos.y - XHAIR_HEIGHT * scaling);
pos.x -= (XHAIR_WIDTH * settings.display.uiScale) / 2.f;
pos.y += (XHAIR_WIDTH * settings.display.uiScale) / 2.f;
ImVec2 pos_b(pos.x + XHAIR_WIDTH * settings.display.uiScale, pos.y - XHAIR_HEIGHT * settings.display.uiScale);
ImGui::GetWindowDrawList()->AddImage(crosshairTexId, pos, pos_b, ImVec2(0, 1), ImVec2(1, 0), config::CrosshairColor[i]);
}

View File

@ -47,12 +47,10 @@
static bool game_started;
int screen_dpi = 96;
int insetLeft, insetRight, insetTop, insetBottom;
std::unique_ptr<ImGuiDriver> imguiDriver;
static bool inited = false;
float scaling = 1;
GuiState gui_state = GuiState::Main;
static bool commandLineStart;
static u32 mouseButtons;
@ -138,7 +136,19 @@ void gui_init()
#if defined(__ANDROID__) || defined(TARGET_IPHONE)
ImGui::GetStyle().TouchExtraPadding = ImVec2(1, 1); // from 0,0
#endif
EventManager::listen(Event::Resume, emuEventCallback);
EventManager::listen(Event::Start, emuEventCallback);
EventManager::listen(Event::Terminate, emuEventCallback);
ggpo::receiveChatMessages([](int playerNum, const std::string& msg) { chat.receive(playerNum, msg); });
}
void gui_initFonts()
{
static float uiScale;
verify(inited);
if (settings.display.uiScale == uiScale && ImGui::GetIO().Fonts->IsBuilt())
return;
// Load Fonts
// - If no fonts are loaded, dear imgui will use the default font. You can also load multiple fonts and use ImGui::PushFont()/PopFont() to select them.
// - AddFontFromFileTTF() will return the ImFont* so you can store it if you need to select the font among multiple.
@ -153,14 +163,15 @@ void gui_init()
//io.Fonts->AddFontFromFileTTF("../../misc/fonts/ProggyTiny.ttf", 10.0f);
//ImFont* font = io.Fonts->AddFontFromFileTTF("c:\\Windows\\Fonts\\ArialUni.ttf", 18.0f, NULL, io.Fonts->GetGlyphRangesJapanese());
//IM_ASSERT(font != NULL);
#if !defined(_WIN32) && !defined(__SWITCH__)
scaling = std::max(1.f, screen_dpi / 100.f * 0.75f);
#if !defined(TARGET_UWP) && !defined(__SWITCH__)
settings.display.uiScale = std::max(1.f, settings.display.dpi / 100.f * 0.75f);
// Limit scaling on small low-res screens
if (settings.display.width <= 640 || settings.display.height <= 480)
scaling = std::min(1.2f, scaling);
settings.display.uiScale = std::min(1.4f, settings.display.uiScale);
#endif
if (scaling > 1)
ImGui::GetStyle().ScaleAllSizes(scaling);
uiScale = settings.display.uiScale;
if (settings.display.uiScale > 1)
ImGui::GetStyle().ScaleAllSizes(settings.display.uiScale);
static const ImWchar ranges[] =
{
@ -168,7 +179,10 @@ void gui_init()
0,
};
io.Fonts->AddFontFromMemoryCompressedTTF(roboto_medium_compressed_data, roboto_medium_compressed_size, 17.f * scaling, nullptr, ranges);
ImGuiIO& io = ImGui::GetIO();
io.Fonts->Clear();
const float fontSize = 17.f * settings.display.uiScale;
io.Fonts->AddFontFromMemoryCompressedTTF(roboto_medium_compressed_data, roboto_medium_compressed_size, fontSize, nullptr, ranges);
ImFontConfig font_cfg;
font_cfg.MergeMode = true;
#ifdef _WIN32
@ -179,33 +193,33 @@ void gui_init()
case 932: // Japanese
{
font_cfg.FontNo = 2; // UIGothic
ImFont* font = io.Fonts->AddFontFromFileTTF((fontDir + "msgothic.ttc").c_str(), 17.f * scaling, &font_cfg, io.Fonts->GetGlyphRangesJapanese());
ImFont* font = io.Fonts->AddFontFromFileTTF((fontDir + "msgothic.ttc").c_str(), fontSize, &font_cfg, io.Fonts->GetGlyphRangesJapanese());
font_cfg.FontNo = 2; // Meiryo UI
if (font == nullptr)
io.Fonts->AddFontFromFileTTF((fontDir + "Meiryo.ttc").c_str(), 17.f * scaling, &font_cfg, io.Fonts->GetGlyphRangesJapanese());
io.Fonts->AddFontFromFileTTF((fontDir + "Meiryo.ttc").c_str(), fontSize, &font_cfg, io.Fonts->GetGlyphRangesJapanese());
}
break;
case 949: // Korean
{
ImFont* font = io.Fonts->AddFontFromFileTTF((fontDir + "Malgun.ttf").c_str(), 17.f * scaling, &font_cfg, io.Fonts->GetGlyphRangesKorean());
ImFont* font = io.Fonts->AddFontFromFileTTF((fontDir + "Malgun.ttf").c_str(), fontSize, &font_cfg, io.Fonts->GetGlyphRangesKorean());
if (font == nullptr)
{
font_cfg.FontNo = 2; // Dotum
io.Fonts->AddFontFromFileTTF((fontDir + "Gulim.ttc").c_str(), 17.f * scaling, &font_cfg, io.Fonts->GetGlyphRangesKorean());
io.Fonts->AddFontFromFileTTF((fontDir + "Gulim.ttc").c_str(), fontSize, &font_cfg, io.Fonts->GetGlyphRangesKorean());
}
}
break;
case 950: // Traditional Chinese
{
font_cfg.FontNo = 1; // Microsoft JhengHei UI Regular
ImFont* font = io.Fonts->AddFontFromFileTTF((fontDir + "Msjh.ttc").c_str(), 17.f * scaling, &font_cfg, GetGlyphRangesChineseTraditionalOfficial());
ImFont* font = io.Fonts->AddFontFromFileTTF((fontDir + "Msjh.ttc").c_str(), fontSize, &font_cfg, GetGlyphRangesChineseTraditionalOfficial());
font_cfg.FontNo = 0;
if (font == nullptr)
io.Fonts->AddFontFromFileTTF((fontDir + "MSJH.ttf").c_str(), 17.f * scaling, &font_cfg, GetGlyphRangesChineseTraditionalOfficial());
io.Fonts->AddFontFromFileTTF((fontDir + "MSJH.ttf").c_str(), fontSize, &font_cfg, GetGlyphRangesChineseTraditionalOfficial());
}
break;
case 936: // Simplified Chinese
io.Fonts->AddFontFromFileTTF((fontDir + "Simsun.ttc").c_str(), 17.f * scaling, &font_cfg, GetGlyphRangesChineseSimplifiedOfficial());
io.Fonts->AddFontFromFileTTF((fontDir + "Simsun.ttc").c_str(), fontSize, &font_cfg, GetGlyphRangesChineseSimplifiedOfficial());
break;
default:
break;
@ -218,19 +232,19 @@ void gui_init()
if (locale.find("ja") == 0) // Japanese
{
io.Fonts->AddFontFromFileTTF((fontDir + "ヒラギノ角ゴシック W4.ttc").c_str(), 17.f * scaling, &font_cfg, io.Fonts->GetGlyphRangesJapanese());
io.Fonts->AddFontFromFileTTF((fontDir + "ヒラギノ角ゴシック W4.ttc").c_str(), fontSize, &font_cfg, io.Fonts->GetGlyphRangesJapanese());
}
else if (locale.find("ko") == 0) // Korean
{
io.Fonts->AddFontFromFileTTF((fontDir + "AppleSDGothicNeo.ttc").c_str(), 17.f * scaling, &font_cfg, io.Fonts->GetGlyphRangesKorean());
io.Fonts->AddFontFromFileTTF((fontDir + "AppleSDGothicNeo.ttc").c_str(), fontSize, &font_cfg, io.Fonts->GetGlyphRangesKorean());
}
else if (locale.find("zh-Hant") == 0) // Traditional Chinese
{
io.Fonts->AddFontFromFileTTF((fontDir + "PingFang.ttc").c_str(), 17.f * scaling, &font_cfg, GetGlyphRangesChineseTraditionalOfficial());
io.Fonts->AddFontFromFileTTF((fontDir + "PingFang.ttc").c_str(), fontSize, &font_cfg, GetGlyphRangesChineseTraditionalOfficial());
}
else if (locale.find("zh-Hans") == 0) // Simplified Chinese
{
io.Fonts->AddFontFromFileTTF((fontDir + "PingFang.ttc").c_str(), 17.f * scaling, &font_cfg, GetGlyphRangesChineseSimplifiedOfficial());
io.Fonts->AddFontFromFileTTF((fontDir + "PingFang.ttc").c_str(), fontSize, &font_cfg, GetGlyphRangesChineseSimplifiedOfficial());
}
#elif defined(__ANDROID__)
if (getenv("FLYCAST_LOCALE") != nullptr)
@ -248,17 +262,12 @@ void gui_init()
glyphRanges = GetGlyphRangesChineseSimplifiedOfficial();
if (glyphRanges != nullptr)
io.Fonts->AddFontFromFileTTF("/system/fonts/NotoSansCJK-Regular.ttc", 17.f * scaling, &font_cfg, glyphRanges);
io.Fonts->AddFontFromFileTTF("/system/fonts/NotoSansCJK-Regular.ttc", fontSize, &font_cfg, glyphRanges);
}
// TODO Linux, iOS, ...
#endif
NOTICE_LOG(RENDERER, "Screen DPI is %d, size %d x %d. Scaling by %.2f", screen_dpi, settings.display.width, settings.display.height, scaling);
EventManager::listen(Event::Resume, emuEventCallback);
EventManager::listen(Event::Start, emuEventCallback);
EventManager::listen(Event::Terminate, emuEventCallback);
ggpo::receiveChatMessages([](int playerNum, const std::string& msg) { chat.receive(playerNum, msg); });
NOTICE_LOG(RENDERER, "Screen DPI is %.0f, size %d x %d. Scaling by %.2f", settings.display.dpi, settings.display.width, settings.display.height, settings.display.uiScale);
}
void gui_keyboard_input(u16 wc)
@ -490,7 +499,7 @@ static void gui_display_commands()
imguiDriver->displayVmus();
centerNextWindow();
ImGui::SetNextWindowSize(ImVec2(330 * scaling, 0));
ImGui::SetNextWindowSize(ScaledVec2(330, 0));
ImGui::Begin("##commands", NULL, ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoMove | ImGuiWindowFlags_AlwaysAutoResize);
@ -502,7 +511,7 @@ static void gui_display_commands()
}
// Load State
if (ImGui::Button("Load State", ImVec2(110 * scaling, 50 * scaling)) && !loadSaveStateDisabled)
if (ImGui::Button("Load State", ScaledVec2(110, 50)) && !loadSaveStateDisabled)
{
gui_state = GuiState::Closed;
dc_loadstate(config::SavestateSlot);
@ -511,7 +520,7 @@ static void gui_display_commands()
// Slot #
std::string slot = "Slot " + std::to_string((int)config::SavestateSlot + 1);
if (ImGui::Button(slot.c_str(), ImVec2(80 * scaling - ImGui::GetStyle().FramePadding.x, 50 * scaling)))
if (ImGui::Button(slot.c_str(), ImVec2(80 * settings.display.uiScale - ImGui::GetStyle().FramePadding.x, 50 * settings.display.uiScale)))
ImGui::OpenPopup("slot_select_popup");
if (ImGui::BeginPopup("slot_select_popup"))
{
@ -526,7 +535,7 @@ static void gui_display_commands()
ImGui::SameLine();
// Save State
if (ImGui::Button("Save State", ImVec2(110 * scaling, 50 * scaling)) && !loadSaveStateDisabled)
if (ImGui::Button("Save State", ScaledVec2(110, 50)) && !loadSaveStateDisabled)
{
gui_state = GuiState::Closed;
dc_savestate(config::SavestateSlot);
@ -540,12 +549,12 @@ static void gui_display_commands()
ImGui::Columns(2, "buttons", false);
// Settings
if (ImGui::Button("Settings", ImVec2(150 * scaling, 50 * scaling)))
if (ImGui::Button("Settings", ScaledVec2(150, 50)))
{
gui_state = GuiState::Settings;
}
ImGui::NextColumn();
if (ImGui::Button("Resume", ImVec2(150 * scaling, 50 * scaling)))
if (ImGui::Button("Resume", ScaledVec2(150, 50)))
{
GamepadDevice::load_system_mappings();
gui_state = GuiState::Closed;
@ -555,7 +564,7 @@ static void gui_display_commands()
// Insert/Eject Disk
const char *disk_label = libGDR_GetDiscType() == Open ? "Insert Disk" : "Eject Disk";
if (ImGui::Button(disk_label, ImVec2(150 * scaling, 50 * scaling)))
if (ImGui::Button(disk_label, ScaledVec2(150, 50)))
{
if (libGDR_GetDiscType() == Open)
{
@ -575,7 +584,7 @@ static void gui_display_commands()
ImGui::PushItemFlag(ImGuiItemFlags_Disabled, true);
ImGui::PushStyleVar(ImGuiStyleVar_Alpha, ImGui::GetStyle().Alpha * 0.5f);
}
if (ImGui::Button("Cheats", ImVec2(150 * scaling, 50 * scaling)) && !settings.network.online)
if (ImGui::Button("Cheats", ScaledVec2(150, 50)) && !settings.network.online)
{
gui_state = GuiState::Cheats;
}
@ -587,8 +596,8 @@ static void gui_display_commands()
ImGui::Columns(1, nullptr, false);
// Exit
if (ImGui::Button("Exit", ImVec2(300 * scaling + ImGui::GetStyle().ColumnsMinSpacing + ImGui::GetStyle().FramePadding.x * 2 - 1,
50 * scaling)))
if (ImGui::Button("Exit", ScaledVec2(300, 50)
+ ImVec2(ImGui::GetStyle().ColumnsMinSpacing + ImGui::GetStyle().FramePadding.x * 2 - 1, 0)))
{
gui_stop_game();
}
@ -835,7 +844,7 @@ static DreamcastKey getOppositeDirectionKey(DreamcastKey key)
}
static void detect_input_popup(const Mapping *mapping)
{
ImVec2 padding = ImVec2(20 * scaling, 20 * scaling);
ImVec2 padding = ScaledVec2(20, 20);
ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, padding);
ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, padding);
if (ImGui::BeginPopupModal("Map Control", NULL, ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoMove))
@ -914,12 +923,13 @@ static void controller_mapping_popup(const std::shared_ptr<GamepadDevice>& gamep
const float col_width = (winWidth - style.GrabMinSize - style.ItemSpacing.x
- (ImGui::CalcTextSize("Map").x + style.FramePadding.x * 2.0f + style.ItemSpacing.x)
- (ImGui::CalcTextSize("Unmap").x + style.FramePadding.x * 2.0f + style.ItemSpacing.x)) / 2;
const float scaling = settings.display.uiScale;
static int item_current_map_idx = 0;
static int last_item_current_map_idx = 2;
std::shared_ptr<InputMapping> input_mapping = gamepad->get_input_mapping();
if (input_mapping == NULL || ImGui::Button("Done", ImVec2(100 * scaling, 30 * scaling)))
if (input_mapping == NULL || ImGui::Button("Done", ScaledVec2(100, 30)))
{
ImGui::CloseCurrentPopup();
gamepad->save_mapping(map_system);
@ -964,7 +974,7 @@ static void controller_mapping_popup(const std::shared_ptr<GamepadDevice>& gamep
{
if (gamepad->isPerGameMapping())
{
if (ImGui::Button("Delete Game Config", ImVec2(0, 30 * scaling)))
if (ImGui::Button("Delete Game Config", ScaledVec2(0, 30)))
{
gamepad->setPerGameMapping(false);
if (!gamepad->find_mapping(map_system))
@ -973,15 +983,15 @@ static void controller_mapping_popup(const std::shared_ptr<GamepadDevice>& gamep
}
else
{
if (ImGui::Button("Make Game Config", ImVec2(0, 30 * scaling)))
if (ImGui::Button("Make Game Config", ScaledVec2(0, 30)))
gamepad->setPerGameMapping(true);
}
ImGui::SameLine();
}
if (ImGui::Button("Reset...", ImVec2(100 * scaling, 30 * scaling)))
if (ImGui::Button("Reset...", ScaledVec2(100, 30)))
ImGui::OpenPopup("Confirm Reset");
ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(20 * scaling, 20 * scaling));
ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ScaledVec2(20, 20));
if (ImGui::BeginPopupModal("Confirm Reset", NULL, ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoMove))
{
ImGui::Text("Are you sure you want to reset the mappings to default?");
@ -997,7 +1007,7 @@ static void controller_mapping_popup(const std::shared_ptr<GamepadDevice>& gamep
}
ImGui::NewLine();
ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(20 * scaling, ImGui::GetStyle().ItemSpacing.y));
ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(10 * scaling, 10 * scaling));
ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ScaledVec2(10, 10));
if (ImGui::Button("Yes"))
{
gamepad->resetMappingToDefault(arcade_button_mode, !hitbox);
@ -1124,18 +1134,18 @@ void error_popup()
{
if (!error_msg_shown && !error_msg.empty())
{
ImVec2 padding = ImVec2(20 * scaling, 20 * scaling);
ImVec2 padding = ScaledVec2(20, 20);
ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, padding);
ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, padding);
ImGui::OpenPopup("Error");
if (ImGui::BeginPopupModal("Error", NULL, ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoScrollbar))
{
ImGui::PushTextWrapPos(ImGui::GetCursorPos().x + 400.f * scaling);
ImGui::PushTextWrapPos(ImGui::GetCursorPos().x + 400.f * settings.display.uiScale);
ImGui::TextWrapped("%s", error_msg.c_str());
ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(16 * scaling, 3 * scaling));
ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ScaledVec2(16, 3));
float currentwidth = ImGui::GetContentRegionAvail().x;
ImGui::SetCursorPosX((currentwidth - 80.f * scaling) / 2.f + ImGui::GetStyle().WindowPadding.x);
if (ImGui::Button("OK", ImVec2(80.f * scaling, 0.f)))
ImGui::SetCursorPosX((currentwidth - 80.f * settings.display.uiScale) / 2.f + ImGui::GetStyle().WindowPadding.x);
if (ImGui::Button("OK", ScaledVec2(80.f, 0)))
{
error_msg.clear();
ImGui::CloseCurrentPopup();
@ -1160,12 +1170,12 @@ static void contentpath_warning_popup()
ImGui::OpenPopup("Incorrect Content Location?");
if (ImGui::BeginPopupModal("Incorrect Content Location?", NULL, ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoMove))
{
ImGui::PushTextWrapPos(ImGui::GetCursorPos().x + 400.f * scaling);
ImGui::PushTextWrapPos(ImGui::GetCursorPos().x + 400.f * settings.display.uiScale);
ImGui::TextWrapped(" Scanned %d folders but no game can be found! ", scanner.empty_folders_scanned);
ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(16 * scaling, 3 * scaling));
ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ScaledVec2(16, 3));
float currentwidth = ImGui::GetContentRegionAvail().x;
ImGui::SetCursorPosX((currentwidth - 100.f * scaling) / 2.f + ImGui::GetStyle().WindowPadding.x - 55.f * scaling);
if (ImGui::Button("Reselect", ImVec2(100.f * scaling, 0.f)))
ImGui::SetCursorPosX((currentwidth - 100.f * settings.display.uiScale) / 2.f + ImGui::GetStyle().WindowPadding.x - 55.f * settings.display.uiScale);
if (ImGui::Button("Reselect", ScaledVec2(100.f, 0)))
{
scanner.content_path_looks_incorrect = false;
ImGui::CloseCurrentPopup();
@ -1173,8 +1183,8 @@ static void contentpath_warning_popup()
}
ImGui::SameLine();
ImGui::SetCursorPosX((currentwidth - 100.f * scaling) / 2.f + ImGui::GetStyle().WindowPadding.x + 55.f * scaling);
if (ImGui::Button("Cancel", ImVec2(100.f * scaling, 0.f)))
ImGui::SetCursorPosX((currentwidth - 100.f * settings.display.uiScale) / 2.f + ImGui::GetStyle().WindowPadding.x + 55.f * settings.display.uiScale);
if (ImGui::Button("Cancel", ScaledVec2(100.f, 0)))
{
scanner.content_path_looks_incorrect = false;
ImGui::CloseCurrentPopup();
@ -1215,7 +1225,7 @@ static void gui_display_settings()
| ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoCollapse);
ImVec2 normal_padding = ImGui::GetStyle().FramePadding;
if (ImGui::Button("Done", ImVec2(100 * scaling, 30 * scaling)))
if (ImGui::Button("Done", ScaledVec2(100, 30)))
{
if (game_started)
gui_state = GuiState::Commands;
@ -1235,10 +1245,10 @@ static void gui_display_settings()
if (game_started)
{
ImGui::SameLine();
ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(16 * scaling, normal_padding.y));
ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(16 * settings.display.uiScale, normal_padding.y));
if (config::Settings::instance().hasPerGameConfig())
{
if (ImGui::Button("Delete Game Config", ImVec2(0, 30 * scaling)))
if (ImGui::Button("Delete Game Config", ScaledVec2(0, 30)))
{
config::Settings::instance().setPerGameConfig(false);
config::Settings::instance().load(false);
@ -1247,13 +1257,13 @@ static void gui_display_settings()
}
else
{
if (ImGui::Button("Make Game Config", ImVec2(0, 30 * scaling)))
if (ImGui::Button("Make Game Config", ScaledVec2(0, 30)))
config::Settings::instance().setPerGameConfig(true);
}
ImGui::PopStyleVar();
}
ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(16 * scaling, 6 * scaling)); // from 4, 3
ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ScaledVec2(16, 6));
if (ImGui::BeginTabBar("settings", ImGuiTabBarFlags_NoTooltip))
{
@ -1317,7 +1327,7 @@ static void gui_display_settings()
to_delete = i;
ImGui::PopID();
}
ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(24 * scaling, 3 * scaling));
ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ScaledVec2(24, 3));
if (ImGui::Button("Add"))
ImGui::OpenPopup("Select Directory");
select_file_popup("Select Directory", [](bool cancelled, std::string selection)
@ -1450,9 +1460,9 @@ static void gui_display_settings()
#endif
if (gamepad->is_rumble_enabled())
{
ImGui::SameLine(0, 16 * scaling);
ImGui::SameLine(0, 16 * settings.display.uiScale);
int power = gamepad->get_rumble_power();
ImGui::SetNextItemWidth(150 * scaling);
ImGui::SetNextItemWidth(150 * settings.display.uiScale);
if (ImGui::SliderInt("Rumble", &power, 0, 100))
gamepad->set_rumble_power(power);
}
@ -2217,15 +2227,15 @@ static void gui_display_content()
ImGui::Begin("##main", NULL, ImGuiWindowFlags_NoDecoration);
ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(20 * scaling, 8 * scaling)); // from 8, 4
ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ScaledVec2(20, 8));
ImGui::AlignTextToFramePadding();
ImGui::Indent(10 * scaling);
ImGui::Indent(10 * settings.display.uiScale);
ImGui::Text("GAMES");
ImGui::Unindent(10 * scaling);
ImGui::Unindent(10 * settings.display.uiScale);
static ImGuiTextFilter filter;
#if !defined(__ANDROID__) && !defined(TARGET_IPHONE) && !defined(TARGET_UWP)
ImGui::SameLine(0, 32 * scaling);
ImGui::SameLine(0, 32 * settings.display.uiScale);
filter.Draw("Filter");
#endif
if (gui_state != GuiState::SelectDisk)
@ -2249,7 +2259,7 @@ static void gui_display_content()
// Only if Filter and Settings aren't focused... ImGui::SetNextWindowFocus();
ImGui::BeginChild(ImGui::GetID("library"), ImVec2(0, 0), true, ImGuiWindowFlags_DragScrolling);
{
ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(8 * scaling, 20 * scaling)); // from 8, 4
ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ScaledVec2(8, 20));
ImGui::PushID("bios");
if (ImGui::Selectable("Dreamcast BIOS"))
@ -2373,13 +2383,13 @@ static std::future<bool> networkStatus;
static void gui_network_start()
{
centerNextWindow();
ImGui::SetNextWindowSize(ImVec2(330 * scaling, 180 * scaling));
ImGui::SetNextWindowSize(ScaledVec2(330, 180));
ImGui::Begin("##network", NULL, ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoResize);
ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(20 * scaling, 10 * scaling));
ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ScaledVec2(20, 10));
ImGui::AlignTextToFramePadding();
ImGui::SetCursorPosX(20.f * scaling);
ImGui::SetCursorPosX(20.f * settings.display.uiScale);
if (networkStatus.wait_for(std::chrono::milliseconds(0)) == std::future_status::ready)
{
@ -2410,9 +2420,9 @@ static void gui_network_start()
ImGui::Text("%s", get_notification().c_str());
float currentwidth = ImGui::GetContentRegionAvail().x;
ImGui::SetCursorPosX((currentwidth - 100.f * scaling) / 2.f + ImGui::GetStyle().WindowPadding.x);
ImGui::SetCursorPosY(126.f * scaling);
if (ImGui::Button("Cancel", ImVec2(100.f * scaling, 0.f)))
ImGui::SetCursorPosX((currentwidth - 100.f * settings.display.uiScale) / 2.f + ImGui::GetStyle().WindowPadding.x);
ImGui::SetCursorPosY(126.f * settings.display.uiScale);
if (ImGui::Button("Cancel", ScaledVec2(100.f, 0)))
{
NetworkHandshake::instance->stop();
try {
@ -2434,13 +2444,13 @@ static void gui_network_start()
static void gui_display_loadscreen()
{
centerNextWindow();
ImGui::SetNextWindowSize(ImVec2(330 * scaling, 180 * scaling));
ImGui::SetNextWindowSize(ScaledVec2(330, 180));
ImGui::Begin("##loading", NULL, ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoResize);
ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(20 * scaling, 10 * scaling));
ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ScaledVec2(20, 10));
ImGui::AlignTextToFramePadding();
ImGui::SetCursorPosX(20.f * scaling);
ImGui::SetCursorPosX(20.f * settings.display.uiScale);
try {
if (gameLoader.ready())
{
@ -2462,13 +2472,13 @@ static void gui_display_loadscreen()
label = "Loading...";
ImGui::Text("%s", label);
ImGui::PushStyleColor(ImGuiCol_PlotHistogram, ImVec4(0.557f, 0.268f, 0.965f, 1.f));
ImGui::ProgressBar(gameLoader.getProgress().progress, ImVec2(-1, 20.f * scaling), "");
ImGui::ProgressBar(gameLoader.getProgress().progress, ImVec2(-1, 20.f * settings.display.uiScale), "");
ImGui::PopStyleColor();
float currentwidth = ImGui::GetContentRegionAvail().x;
ImGui::SetCursorPosX((currentwidth - 100.f * scaling) / 2.f + ImGui::GetStyle().WindowPadding.x);
ImGui::SetCursorPosY(126.f * scaling);
if (ImGui::Button("Cancel", ImVec2(100.f * scaling, 0.f)))
ImGui::SetCursorPosX((currentwidth - 100.f * settings.display.uiScale) / 2.f + ImGui::GetStyle().WindowPadding.x);
ImGui::SetCursorPosY(126.f * settings.display.uiScale);
if (ImGui::Button("Cancel", ScaledVec2(100.f, 0)))
gameLoader.cancel();
}
} catch (const FlycastException& ex) {
@ -2526,7 +2536,7 @@ void gui_display_ui()
break;
case GuiState::VJoyEditCommands:
#ifdef __ANDROID__
gui_display_vjoy_commands(scaling);
gui_display_vjoy_commands();
#endif
break;
case GuiState::SelectDisk:

View File

@ -21,6 +21,7 @@
#include "cfg/option.h"
void gui_init();
void gui_initFonts();
void gui_open_settings();
void gui_display_ui();
void gui_display_notification(const char *msg, int duration);
@ -45,9 +46,6 @@ void gui_start_game(const std::string& path);
void gui_error(const std::string& what);
void gui_setOnScreenKeyboardCallback(void (*callback)(bool show));
extern int screen_dpi;
extern float scaling;
enum class GuiState {
Closed,
Commands,
@ -71,6 +69,3 @@ static inline bool gui_is_content_browser()
{
return gui_state == GuiState::Main;
}
static inline float gui_get_scaling() {
return scaling;
}

View File

@ -29,27 +29,27 @@
void vjoy_reset_editing();
void vjoy_stop_editing(bool canceled);
void gui_display_vjoy_commands(float scaling)
void gui_display_vjoy_commands()
{
centerNextWindow();
ImGui::Begin("Virtual Joystick", NULL, ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoCollapse
| ImGuiWindowFlags_NoMove | ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoScrollbar);
if (ImGui::Button("Save", ImVec2(150 * scaling, 50 * scaling)))
if (ImGui::Button("Save", ScaledVec2(150, 50)))
{
vjoy_stop_editing(false);
gui_state = GuiState::Settings;
}
ImGui::SameLine();
if (ImGui::Button("Reset", ImVec2(150 * scaling, 50 * scaling)))
if (ImGui::Button("Reset", ScaledVec2(150, 50)))
{
vjoy_reset_editing();
gui_state = GuiState::VJoyEdit;
}
ImGui::SameLine();
if (ImGui::Button("Cancel", ImVec2(150 * scaling, 50 * scaling)))
if (ImGui::Button("Cancel", ScaledVec2(150, 50)))
{
vjoy_stop_editing(true);
gui_state = GuiState::Settings;

View File

@ -18,5 +18,5 @@
*/
#pragma once
void gui_display_vjoy_commands(float scaling);
void gui_display_vjoy_commands();
void vjoy_start_editing();

View File

@ -56,8 +56,8 @@ public:
ImGui::PushStyleVar(ImGuiStyleVar_WindowRounding, 0);
ImGui::PushStyleVar(ImGuiStyleVar_WindowBorderSize, 0);
ImGui::SetNextWindowPos(ImVec2((settings.display.width - 400 * scaling) / 2, settings.display.height - 220 * scaling), ImGuiCond_FirstUseEver);
ImGui::SetNextWindowSize(ImVec2(400 * scaling, 220 * scaling), ImGuiCond_FirstUseEver);
ImGui::SetNextWindowPos(ImVec2(settings.display.width / 2, settings.display.height) - ScaledVec2(200.f, 220.f), ImGuiCond_FirstUseEver);
ImGui::SetNextWindowSize(ScaledVec2(400, 220), ImGuiCond_FirstUseEver);
ImGui::SetNextWindowBgAlpha(0.7f);
ImGui::SetNextWindowFocus();
if (ImGui::Begin("Chat", &visible, ImGuiWindowFlags_NoScrollbar))

View File

@ -28,14 +28,14 @@ static void addCheat()
static char cheatName[64];
static char cheatCode[128];
centerNextWindow();
ImGui::SetNextWindowSize(ImVec2(std::min(ImGui::GetIO().DisplaySize.x, 600 * scaling), std::min(ImGui::GetIO().DisplaySize.y, 400 * scaling)));
ImGui::SetNextWindowSize(min(ImGui::GetIO().DisplaySize, ScaledVec2(600.f, 400.f)));
ImGui::Begin("##main", nullptr, ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoTitleBar
| ImGuiWindowFlags_NoMove | ImGuiWindowFlags_AlwaysAutoResize);
ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(20 * scaling, 8 * scaling)); // from 8, 4
ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ScaledVec2(20, 8));
ImGui::AlignTextToFramePadding();
ImGui::Indent(10 * scaling);
ImGui::Indent(10 * settings.display.uiScale);
ImGui::Text("ADD CHEAT");
ImGui::SameLine(ImGui::GetWindowContentRegionMax().x - ImGui::CalcTextSize("Cancel").x - ImGui::GetStyle().FramePadding.x * 4.f
@ -55,7 +55,7 @@ static void addCheat()
}
}
ImGui::Unindent(10 * scaling);
ImGui::Unindent(10 * settings.display.uiScale);
ImGui::PopStyleVar();
ImGui::BeginChild(ImGui::GetID("input"), ImVec2(0, 0), true);
@ -75,14 +75,14 @@ void gui_cheats()
return;
}
centerNextWindow();
ImGui::SetNextWindowSize(ImVec2(std::min(ImGui::GetIO().DisplaySize.x, 600 * scaling), std::min(ImGui::GetIO().DisplaySize.y, 400 * scaling)));
ImGui::SetNextWindowSize(min(ImGui::GetIO().DisplaySize, ScaledVec2(600.f, 400.f)));
ImGui::Begin("##main", nullptr, ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoTitleBar
| ImGuiWindowFlags_NoMove | ImGuiWindowFlags_AlwaysAutoResize);
ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(20 * scaling, 8 * scaling)); // from 8, 4
ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ScaledVec2(20, 8));
ImGui::AlignTextToFramePadding();
ImGui::Indent(10 * scaling);
ImGui::Indent(10 * settings.display.uiScale);
ImGui::Text("CHEATS");
ImGui::SameLine(ImGui::GetWindowContentRegionMax().x - ImGui::CalcTextSize("Add").x - ImGui::CalcTextSize("Close").x - ImGui::GetStyle().FramePadding.x * 6.f
@ -103,7 +103,7 @@ void gui_cheats()
if (ImGui::Button("Close"))
gui_state = GuiState::Commands;
ImGui::Unindent(10 * scaling);
ImGui::Unindent(10 * settings.display.uiScale);
ImGui::PopStyleVar();
ImGui::BeginChild(ImGui::GetID("cheats"), ImVec2(0, 0), true, ImGuiWindowFlags_DragScrolling);

View File

@ -215,10 +215,10 @@ void select_file_popup(const char *prompt, StringCallback callback,
}
ImGui::Text("%s", error_message.empty() ? select_current_directory.c_str() : error_message.c_str());
ImGui::BeginChild(ImGui::GetID("dir_list"), ImVec2(0, - 30 * gui_get_scaling() - ImGui::GetStyle().ItemSpacing.y),
ImGui::BeginChild(ImGui::GetID("dir_list"), ImVec2(0, - 30 * settings.display.uiScale - ImGui::GetStyle().ItemSpacing.y),
true, ImGuiWindowFlags_DragScrolling);
ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(8 * gui_get_scaling(), 20 * gui_get_scaling())); // from 8, 4
ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ScaledVec2(8, 20));
for (const auto& name : subfolders)
@ -302,7 +302,7 @@ void select_file_popup(const char *prompt, StringCallback callback,
ImGui::EndChild();
if (!selectFile)
{
if (ImGui::Button("Select Current Directory", ImVec2(0, 30 * gui_get_scaling())))
if (ImGui::Button("Select Current Directory", ScaledVec2(0, 30)))
{
if (callback(false, select_current_directory))
{
@ -312,7 +312,7 @@ void select_file_popup(const char *prompt, StringCallback callback,
}
ImGui::SameLine();
}
if (ImGui::Button("Cancel", ImVec2(0, 30 * gui_get_scaling())))
if (ImGui::Button("Cancel", ScaledVec2(0, 30)))
{
subfolders_read = false;
callback(true, "");

View File

@ -112,3 +112,21 @@ private:
LoadProgress progress;
std::future<void> future;
};
struct ScaledVec2 : public ImVec2
{
ScaledVec2()
: ImVec2() {}
ScaledVec2(float x, float y)
: ImVec2(x * settings.display.uiScale, y * settings.display.uiScale) {}
};
inline static ImVec2 min(const ImVec2& l, const ImVec2& r) {
return ImVec2(std::min(l.x, r.x), std::min(l.y, r.y));
}
inline static ImVec2 operator+(const ImVec2& l, const ImVec2& r) {
return ImVec2(l.x + r.x, l.y + r.y);
}
inline static ImVec2 operator-(const ImVec2& l, const ImVec2& r) {
return ImVec2(l.x - r.x, l.y - r.y);
}

View File

@ -18,11 +18,15 @@
*/
#pragma once
#include "imgui/imgui.h"
#include "gui.h"
#include <memory>
class ImGuiDriver
{
public:
ImGuiDriver() {
gui_initFonts();
}
virtual ~ImGuiDriver() = default;
virtual void newFrame() = 0;

View File

@ -700,7 +700,7 @@ void ImGui_ImplVulkan_InvalidateDeviceObjects()
}
if (g_FontView) { vkDestroyImageView(g_Device, g_FontView, g_Allocator); g_FontView = VK_NULL_HANDLE; }
if (g_FontImage) { vkDestroyImage(g_Device, g_FontImage, g_Allocator); g_FontImage = VK_NULL_HANDLE; }
if (g_FontImage) { vkDestroyImage(g_Device, g_FontImage, g_Allocator); g_FontImage = VK_NULL_HANDLE; ImGui::GetIO().Fonts->SetTexID(NULL); }
if (g_FontMemory) { vkFreeMemory(g_Device, g_FontMemory, g_Allocator); g_FontMemory = VK_NULL_HANDLE; }
if (g_FontSampler) { vkDestroySampler(g_Device, g_FontSampler, g_Allocator); g_FontSampler = VK_NULL_HANDLE; }
if (g_DescriptorSetLayout) { vkDestroyDescriptorSetLayout(g_Device, g_DescriptorSetLayout, g_Allocator); g_DescriptorSetLayout = VK_NULL_HANDLE; }

View File

@ -279,7 +279,6 @@ bool VulkanContext::InitInstance(const char** extensions, uint32_t extensions_co
void VulkanContext::InitImgui()
{
imguiDriver = std::unique_ptr<ImGuiDriver>(new VulkanDriver());
gui_init();
ImGui_ImplVulkan_InitInfo initInfo = {};
initInfo.Instance = (VkInstance)*instance;
initInfo.PhysicalDevice = (VkPhysicalDevice)physicalDevice;
@ -719,7 +718,7 @@ bool VulkanContext::init()
settings.display.pointScale = (float)settings.display.width / w;
float hdpi, vdpi;
if (!SDL_GetDisplayDPI(SDL_GetWindowDisplayIndex(sdlWin), nullptr, &hdpi, &vdpi))
screen_dpi = (int)roundf(std::max(hdpi, vdpi));
settings.display.dpi = roundf(std::max(hdpi, vdpi));
#elif defined(_WIN32)
vk::Win32SurfaceCreateInfoKHR createInfo(vk::Win32SurfaceCreateFlagsKHR(), GetModuleHandle(NULL), (HWND)window);
surface = instance->createWin32SurfaceKHRUnique(createInfo);
@ -913,7 +912,7 @@ void VulkanContext::PresentFrame(vk::Image image, vk::ImageView imageView, const
if (lastFrameView) // Might have been nullified if swap chain recreated
DrawFrame(imageView, extent);
DrawOverlay(gui_get_scaling(), config::FloatVMUs, true);
DrawOverlay(settings.display.uiScale, config::FloatVMUs, true);
renderer->DrawOSD(false);
EndFrame(overlayCmdBuffer);
} catch (const InvalidVulkanContext& err) {
@ -935,8 +934,6 @@ void VulkanContext::term()
return;
WaitIdle();
imguiDriver.reset();
ImGui_ImplVulkan_Shutdown();
gui_term();
if (device && pipelineCache)
{
std::vector<u8> cacheData = device->getPipelineCacheData(*pipelineCache);
@ -1176,7 +1173,7 @@ void ImGui_ImplVulkan_RenderDrawData(ImDrawData *draw_data)
vmuCmdBuffer = context->PrepareOverlay(true, false);
context->BeginRenderPass();
context->PresentLastFrame();
context->DrawOverlay(gui_get_scaling(), true, false);
context->DrawOverlay(settings.display.uiScale, true, false);
}
// Record Imgui Draw Data and draw funcs into command buffer
ImGui_ImplVulkan_RenderDrawData(draw_data, (VkCommandBuffer)context->GetCurrentCommandBuffer());

View File

@ -24,6 +24,10 @@
class VulkanDriver final : public ImGuiDriver
{
public:
~VulkanDriver() {
ImGui_ImplVulkan_Shutdown();
}
void newFrame() override {
}

View File

@ -467,11 +467,9 @@ bool sdl_recreate_window(u32 flags)
if (SetProcessDpiAwareness) {
SetProcessDpiAwareness(PROCESS_PER_MONITOR_DPI_AWARE);
float ddpi;
if (SDL_GetDisplayDPI(0, &ddpi, NULL, NULL) != -1){ //SDL_WINDOWPOS_UNDEFINED is Display 0
if (SDL_GetDisplayDPI(0, &settings.display.dpi, NULL, NULL) != -1){ //SDL_WINDOWPOS_UNDEFINED is Display 0
//When using HiDPI mode, set correct DPI scaling
scaling = ddpi/96.f;
hdpiScaling = scaling;
hdpiScaling = settings.display.dpi / 96.f;
}
}
SDL_UnloadObject(shcoreDLL);
@ -484,13 +482,13 @@ bool sdl_recreate_window(u32 flags)
{
windowPos.w = 1280;
windowPos.h = 720;
scaling = 1.5f;
settings.display.uiScale = 1.5f;
}
else
{
windowPos.w = 1920;
windowPos.h = 1080;
scaling = 1.0f;
settings.display.uiScale = 1.4f;
}
#else
windowPos.x = cfgLoadInt("window", "left", windowPos.x);

View File

@ -2,7 +2,6 @@
#include "input/mouse.h"
#include "oslib/oslib.h"
#include "sdl.h"
#include "rend/gui.h"
template<bool Arcade = false, bool Gamepad = false>
class DefaultInputMapping : public InputMapping

View File

@ -354,6 +354,8 @@ struct settings_t
int height = 480;
float pointScale = 1.f;
float refreshRate = 0;
float dpi = 96.f;
float uiScale = 1.f;
} display;
struct

View File

@ -21,7 +21,6 @@
#include "input/gamepad_device.h"
#include "input/keyboard_device.h"
#include "input/mouse.h"
#include "rend/gui.h"
#include <windows.h>
#include <algorithm>

View File

@ -877,10 +877,6 @@ int CALLBACK WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLi
mainui_loop();
flycast_term();
os_UninstallFaultHandler();
#ifdef USE_SDL
sdl_window_destroy();
#else
@ -894,6 +890,9 @@ int CALLBACK WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLi
}
#endif
flycast_term();
os_UninstallFaultHandler();
return 0;
}

View File

@ -1,6 +1,5 @@
#include "input/gamepad_device.h"
#include "input/mouse.h"
#include "rend/gui.h"
#include <windows.h>
#include <xinput.h>

View File

@ -175,8 +175,7 @@ bool EGLGraphicsContext::init()
#ifdef TARGET_PANDORA
fbdev = open("/dev/fb0", O_RDONLY);
#else
swapOnVSync = config::VSync;
eglSwapInterval(display, (int)swapOnVSync);
setSwapInterval();
#endif
postInit();
@ -210,10 +209,19 @@ void EGLGraphicsContext::swap()
{
do_swap_automation();
if (swapOnVSync == (settings.input.fastForwardMode || !config::VSync))
{
swapOnVSync = (!settings.input.fastForwardMode && config::VSync);
eglSwapInterval(display, (int)swapOnVSync);
}
setSwapInterval();
eglSwapBuffers(display, surface);
}
void EGLGraphicsContext::setSwapInterval()
{
swapOnVSync = (!settings.input.fastForwardMode && config::VSync);
int swapInterval;
if (settings.display.refreshRate > 60.f)
swapInterval = settings.display.refreshRate / 60.f;
else
swapInterval = 1;
eglSwapInterval(display, swapOnVSync ? swapInterval : 0);
}
#endif // USE_EGL

View File

@ -43,6 +43,7 @@ public:
private:
bool makeCurrent();
void setSwapInterval();
EGLDisplay display = EGL_NO_DISPLAY;
EGLSurface surface = EGL_NO_SURFACE;

View File

@ -21,7 +21,6 @@
#include "gl_context.h"
#include "rend/gles/opengl_driver.h"
#include "rend/gui.h"
void GLGraphicsContext::findGLVersion()
{
@ -44,17 +43,13 @@ void GLGraphicsContext::postInit()
{
instance = this;
findGLVersion();
#ifndef LIBRETRO
gui_init();
imguiDriver = std::unique_ptr<ImGuiDriver>(new OpenGLDriver());
#endif
resetUIDriver();
}
void GLGraphicsContext::preTerm()
{
#ifndef LIBRETRO
imguiDriver.reset();
gui_term();
#endif
instance = nullptr;
}
@ -66,3 +61,10 @@ std::string GLGraphicsContext::getDriverName() {
std::string GLGraphicsContext::getDriverVersion() {
return (const char *)glGetString(GL_VERSION);
}
void GLGraphicsContext::resetUIDriver()
{
#ifndef LIBRETRO
imguiDriver = std::unique_ptr<ImGuiDriver>(new OpenGLDriver());
#endif
}

View File

@ -42,6 +42,7 @@ public:
}
std::string getDriverName() override;
std::string getDriverVersion() override;
void resetUIDriver();
bool hasPerPixel() override
{

View File

@ -83,7 +83,7 @@ bool SDLGLGraphicsContext::init()
float hdpi, vdpi;
if (!SDL_GetDisplayDPI(SDL_GetWindowDisplayIndex(sdlWindow), nullptr, &hdpi, &vdpi))
screen_dpi = (int)roundf(std::max(hdpi, vdpi));
settings.display.dpi = roundf(std::max(hdpi, vdpi));
INFO_LOG(RENDERER, "Created SDL Window and GL Context successfully");
@ -135,13 +135,12 @@ void SDLGLGraphicsContext::swap()
// Check if drawable has been resized
SDL_GL_GetDrawableSize((SDL_Window *)window, &settings.display.width, &settings.display.height);
#ifdef __SWITCH__
float newScaling = settings.display.height == 720 ? 1.5f : 1.0f;
if (newScaling != scaling)
float newScaling = settings.display.height == 720 ? 1.5f : 1.4f;
if (newScaling != settings.display.uiScale)
{
// Restart the UI to take the new scaling factor into account
scaling = newScaling;
gui_term();
gui_init();
settings.display.uiScale = newScaling;
resetUIDriver();
}
#endif
}

View File

@ -20,7 +20,6 @@
*/
#ifndef LIBRETRO
#include "context.h"
#include "rend/gui.h"
#include "cfg/option.h"
#include "gl_context.h"

View File

@ -25,7 +25,7 @@ public final class JNIdc
public static native void setupMic(SipEmulator sip);
public static native int getVirtualGamepadVibration();
public static native void screenDpi(int screenDpi);
public static native void screenCharacteristics(float screenDpi, float refreshRate);
public static native void guiOpenSettings();
public static native boolean guiIsOpen();
public static native boolean guiIsContentBrowser();

View File

@ -57,10 +57,6 @@ public class NativeGLView extends SurfaceView implements SurfaceHolder.Callback
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
DisplayMetrics dm = context.getResources().getDisplayMetrics();
Log.i("flycast", "Display density: " + dm.xdpi + " x " + dm.ydpi + " dpi");
JNIdc.screenDpi((int)Math.max(dm.xdpi, dm.ydpi));
this.setLayerType(LAYER_TYPE_HARDWARE, null);
}
@ -69,6 +65,9 @@ public class NativeGLView extends SurfaceView implements SurfaceHolder.Callback
{
super.onLayout(changed, left, top, right, bottom);
vjoyDelegate.layout(getWidth(), getHeight());
DisplayMetrics dm = getContext().getResources().getDisplayMetrics();
Log.i("flycast", "Display density: " + dm.xdpi + " x " + dm.ydpi + " dpi. Refresh rate: " + getDisplay().getRefreshRate());
JNIdc.screenCharacteristics(Math.max(dm.xdpi, dm.ydpi), getDisplay().getRefreshRate());
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
// Get the display cutouts if any
WindowInsets insets = getRootWindowInsets();

View File

@ -81,9 +81,10 @@ extern "C" JNIEXPORT jint JNICALL Java_com_reicast_emulator_emu_JNIdc_getVirtual
return (jint)config::VirtualGamepadVibration;
}
extern "C" JNIEXPORT void JNICALL Java_com_reicast_emulator_emu_JNIdc_screenDpi(JNIEnv *env, jobject obj, jint screenDpi)
extern "C" JNIEXPORT void JNICALL Java_com_reicast_emulator_emu_JNIdc_screenCharacteristics(JNIEnv *env, jobject obj, jfloat screenDpi, jfloat refreshRate)
{
screen_dpi = screenDpi;
settings.display.dpi = screenDpi;
settings.display.refreshRate = refreshRate;
}
std::shared_ptr<AndroidMouse> mouse;
@ -214,11 +215,7 @@ extern "C" JNIEXPORT jstring JNICALL Java_com_reicast_emulator_emu_JNIdc_initEnv
EventManager::listen(Event::Resume, emuEventCallback);
jstring msg = NULL;
int rc = flycast_init(0, NULL);
if (rc == -4)
msg = env->NewStringUTF("Cannot find configuration");
else if (rc == 69)
msg = env->NewStringUTF("Invalid command line");
else if (rc == -1)
if (rc == -1)
msg = env->NewStringUTF("Memory initialization failed");
return msg;
}

View File

@ -164,8 +164,6 @@ static void updateAudioSession(Event event, void *)
@end
extern int screen_dpi;
@implementation FlycastViewController {
UITextField *textField;
BOOL showingKeyboard;
@ -312,7 +310,7 @@ extern int screen_dpi;
if ([[UIScreen mainScreen] respondsToSelector:@selector(scale)]) {
scale = [[UIScreen mainScreen] scale];
}
screen_dpi = roundf(160 * scale);
settings.display.dpi = 160.f * scale;
initRenderApi();
mainui_init();

View File

@ -14,7 +14,6 @@
#include "types.h"
#include "log/LogManager.h"
#include "rend/gui.h"
#if defined(USE_SDL)
#include "sdl/sdl.h"
#endif
@ -126,9 +125,9 @@ extern "C" int SDL_main(int argc, char *argv[])
mainui_loop();
sdl_window_destroy();
emu_flycast_term();
os_UninstallFaultHandler();
sdl_window_destroy();
return 0;
}

View File

@ -3161,9 +3161,3 @@ void gui_display_notification(const char *msg, int duration)
retromsg.frames = duration / 17;
environ_cb(RETRO_ENVIRONMENT_SET_MESSAGE, &retromsg);
}
void gui_init() {
}
void gui_term() {
}

View File

@ -82,7 +82,7 @@ struct retro_core_option_v2_category option_cats_us[] = {
{
"performance",
"Performance",
"Configure threaded rendering, integer division optimisations and frame skip settings."
"Configure threaded rendering and frame skip settings."
},
{
"hacks",