mirror of
https://github.com/hedge-dev/UnleashedRecomp.git
synced 2025-10-30 07:11:05 +00:00
Implemented window size option
This commit is contained in:
parent
90e499cc8c
commit
31fb63ad81
8 changed files with 433 additions and 302 deletions
|
|
@ -150,6 +150,11 @@ CONFIG_DEFINE_LOCALE(BattleTheme)
|
|||
{ ELanguage::English, { "Battle Theme", "Play the Werehog battle theme during combat.\n\nThis option will apply the next time you're in combat." } }
|
||||
};
|
||||
|
||||
CONFIG_DEFINE_LOCALE(WindowSize)
|
||||
{
|
||||
{ ELanguage::English, { "Window Size", "Adjust the size of the game window in windowed mode." } }
|
||||
};
|
||||
|
||||
CONFIG_DEFINE_LOCALE(Monitor)
|
||||
{
|
||||
{ ELanguage::English, { "Monitor", "Change which monitor to display the game on." } }
|
||||
|
|
|
|||
|
|
@ -51,6 +51,12 @@ std::unordered_map<std::string, std::unordered_map<ELanguage, std::string>> g_lo
|
|||
{ ELanguage::English, "This option is not available at this location." }
|
||||
}
|
||||
},
|
||||
{
|
||||
"Options_Desc_NotAvailableFullscreen",
|
||||
{
|
||||
{ ELanguage::English, "This option is not available in fullscreen mode." }
|
||||
}
|
||||
},
|
||||
{
|
||||
"Options_Desc_NotAvailableWindowed",
|
||||
{
|
||||
|
|
|
|||
|
|
@ -80,7 +80,7 @@ static void DrawSelectionContainer(ImVec2 min, ImVec2 max)
|
|||
auto drawList = ImGui::GetForegroundDrawList();
|
||||
|
||||
static auto breatheStart = ImGui::GetTime();
|
||||
auto alpha = Lerp(1.0f, 0.75f, (sin((ImGui::GetTime() - breatheStart) * (2.0f * M_PI / (55.0f / 60.0f))) + 1.0f) / 2.0f);
|
||||
auto alpha = Lerp(1.0f, 0.65f, (sin((ImGui::GetTime() - breatheStart) * (2.0f * M_PI / (55.0f / 60.0f))) + 1.0f) / 2.0f);
|
||||
auto colour = IM_COL32(255, 255, 255, 255 * alpha);
|
||||
|
||||
auto commonWidth = Scale(11);
|
||||
|
|
|
|||
|
|
@ -1,9 +1,18 @@
|
|||
#include "game_window.h"
|
||||
#include "sdl_listener.h"
|
||||
#include <user/config.h>
|
||||
#include <SDL_syswm.h>
|
||||
#include <app.h>
|
||||
#include <gpu/video.h>
|
||||
#include <os/logger.h>
|
||||
#include <os/version.h>
|
||||
#include <ui/sdl_listener.h>
|
||||
#include <app.h>
|
||||
#include <SDL_syswm.h>
|
||||
|
||||
#if _WIN32
|
||||
#include <dwmapi.h>
|
||||
#pragma comment(lib, "dwmapi.lib")
|
||||
#endif
|
||||
|
||||
#include <res/images/game_icon.bmp.h>
|
||||
#include <res/images/game_icon_night.bmp.h>
|
||||
|
||||
bool m_isFullscreenKeyReleased = true;
|
||||
bool m_isResizing = false;
|
||||
|
|
@ -110,6 +119,7 @@ int Window_OnSDLEvent(void*, SDL_Event* event)
|
|||
|
||||
case SDL_WINDOWEVENT_RESIZED:
|
||||
m_isResizing = true;
|
||||
Config::WindowSize = -1;
|
||||
GameWindow::s_width = event->window.data1;
|
||||
GameWindow::s_height = event->window.data2;
|
||||
GameWindow::SetTitle(fmt::format("{} - [{}x{}]", GameWindow::GetTitle(), GameWindow::s_width, GameWindow::s_height).c_str());
|
||||
|
|
@ -171,6 +181,20 @@ void GameWindow::Init(const char* sdlVideoDriver)
|
|||
SetProcessDPIAware();
|
||||
#endif
|
||||
|
||||
Config::WindowSize.ApplyCallback = [](ConfigDef<int32_t>* def)
|
||||
{
|
||||
auto displayModes = GetDisplayModes();
|
||||
|
||||
// Use largest supported resolution if overflowed.
|
||||
if (def->Value >= displayModes.size())
|
||||
def->Value = displayModes.size() - 1;
|
||||
|
||||
auto& mode = displayModes[def->Value];
|
||||
auto centre = SDL_WINDOWPOS_CENTERED_DISPLAY(GetDisplay());
|
||||
|
||||
SetDimensions(mode.w, mode.h, centre, centre);
|
||||
};
|
||||
|
||||
s_x = Config::WindowX;
|
||||
s_y = Config::WindowY;
|
||||
s_width = Config::WindowWidth;
|
||||
|
|
@ -188,10 +212,10 @@ void GameWindow::Init(const char* sdlVideoDriver)
|
|||
SDL_ShowCursor(SDL_DISABLE);
|
||||
|
||||
SetDisplay(Config::Monitor);
|
||||
|
||||
SetIcon();
|
||||
SetTitle();
|
||||
SDL_SetWindowMinimumSize(s_pWindow, 640, 480);
|
||||
|
||||
SDL_SetWindowMinimumSize(s_pWindow, MIN_WIDTH, MIN_HEIGHT);
|
||||
|
||||
SDL_SysWMinfo info;
|
||||
SDL_VERSION(&info.version);
|
||||
|
|
@ -199,7 +223,6 @@ void GameWindow::Init(const char* sdlVideoDriver)
|
|||
|
||||
#if defined(_WIN32)
|
||||
s_renderWindow = info.info.win.window;
|
||||
SetDarkTitleBar(true);
|
||||
#elif defined(SDL_VULKAN_ENABLED)
|
||||
s_renderWindow = s_pWindow;
|
||||
#elif defined(__linux__)
|
||||
|
|
@ -208,6 +231,8 @@ void GameWindow::Init(const char* sdlVideoDriver)
|
|||
static_assert(false, "Unknown platform.");
|
||||
#endif
|
||||
|
||||
SetDarkTitleBar(true);
|
||||
|
||||
SDL_ShowWindow(s_pWindow);
|
||||
}
|
||||
|
||||
|
|
@ -230,3 +255,315 @@ void GameWindow::Update()
|
|||
if (g_needsResize)
|
||||
s_isChangingDisplay = false;
|
||||
}
|
||||
|
||||
SDL_Surface* GameWindow::GetIconSurface(void* pIconBmp, size_t iconSize)
|
||||
{
|
||||
auto rw = SDL_RWFromMem(pIconBmp, iconSize);
|
||||
auto surface = SDL_LoadBMP_RW(rw, 1);
|
||||
|
||||
if (!surface)
|
||||
LOGF_ERROR("Failed to load icon: {}", SDL_GetError());
|
||||
|
||||
return surface;
|
||||
}
|
||||
|
||||
void GameWindow::SetIcon(void* pIconBmp, size_t iconSize)
|
||||
{
|
||||
if (auto icon = GetIconSurface(pIconBmp, iconSize))
|
||||
{
|
||||
SDL_SetWindowIcon(s_pWindow, icon);
|
||||
SDL_FreeSurface(icon);
|
||||
}
|
||||
}
|
||||
|
||||
void GameWindow::SetIcon(bool isNight)
|
||||
{
|
||||
if (isNight)
|
||||
{
|
||||
SetIcon(g_game_icon_night, sizeof(g_game_icon_night));
|
||||
}
|
||||
else
|
||||
{
|
||||
SetIcon(g_game_icon, sizeof(g_game_icon));
|
||||
}
|
||||
}
|
||||
|
||||
const char* GameWindow::GetTitle()
|
||||
{
|
||||
return Config::Language == ELanguage::Japanese
|
||||
? "SONIC WORLD ADVENTURE"
|
||||
: "SONIC UNLEASHED";
|
||||
}
|
||||
|
||||
void GameWindow::SetTitle(const char* title)
|
||||
{
|
||||
SDL_SetWindowTitle(s_pWindow, title ? title : GetTitle());
|
||||
}
|
||||
|
||||
void GameWindow::SetDarkTitleBar(bool isEnabled)
|
||||
{
|
||||
#if _WIN32
|
||||
auto version = os::version::GetOSVersion();
|
||||
|
||||
if (version.Major < 10 || version.Build <= 17763)
|
||||
return;
|
||||
|
||||
auto flag = version.Build >= 18985
|
||||
? DWMWA_USE_IMMERSIVE_DARK_MODE
|
||||
: 19; // DWMWA_USE_IMMERSIVE_DARK_MODE_BEFORE_20H1
|
||||
|
||||
const DWORD useImmersiveDarkMode = isEnabled;
|
||||
DwmSetWindowAttribute(s_renderWindow, flag, &useImmersiveDarkMode, sizeof(useImmersiveDarkMode));
|
||||
#endif
|
||||
}
|
||||
|
||||
bool GameWindow::IsFullscreen()
|
||||
{
|
||||
return SDL_GetWindowFlags(s_pWindow) & SDL_WINDOW_FULLSCREEN_DESKTOP;
|
||||
}
|
||||
|
||||
bool GameWindow::SetFullscreen(bool isEnabled)
|
||||
{
|
||||
if (isEnabled)
|
||||
{
|
||||
SDL_SetWindowFullscreen(s_pWindow, SDL_WINDOW_FULLSCREEN_DESKTOP);
|
||||
SDL_ShowCursor(s_isFullscreenCursorVisible ? SDL_ENABLE : SDL_DISABLE);
|
||||
}
|
||||
else
|
||||
{
|
||||
SDL_SetWindowFullscreen(s_pWindow, 0);
|
||||
SDL_ShowCursor(SDL_ENABLE);
|
||||
|
||||
SetIcon(GameWindow::s_isIconNight);
|
||||
SetDimensions(Config::WindowWidth, Config::WindowHeight, Config::WindowX, Config::WindowY);
|
||||
}
|
||||
|
||||
return isEnabled;
|
||||
}
|
||||
|
||||
void GameWindow::SetFullscreenCursorVisibility(bool isVisible)
|
||||
{
|
||||
s_isFullscreenCursorVisible = isVisible;
|
||||
|
||||
if (IsFullscreen())
|
||||
{
|
||||
SDL_ShowCursor(s_isFullscreenCursorVisible ? SDL_ENABLE : SDL_DISABLE);
|
||||
}
|
||||
else
|
||||
{
|
||||
SDL_ShowCursor(SDL_ENABLE);
|
||||
}
|
||||
}
|
||||
|
||||
bool GameWindow::IsMaximised()
|
||||
{
|
||||
return SDL_GetWindowFlags(s_pWindow) & SDL_WINDOW_MAXIMIZED;
|
||||
}
|
||||
|
||||
EWindowState GameWindow::SetMaximised(bool isEnabled)
|
||||
{
|
||||
if (isEnabled)
|
||||
{
|
||||
SDL_MaximizeWindow(s_pWindow);
|
||||
}
|
||||
else
|
||||
{
|
||||
SDL_RestoreWindow(s_pWindow);
|
||||
}
|
||||
|
||||
return isEnabled
|
||||
? EWindowState::Maximised
|
||||
: EWindowState::Normal;
|
||||
}
|
||||
|
||||
SDL_Rect GameWindow::GetDimensions()
|
||||
{
|
||||
SDL_Rect rect{};
|
||||
|
||||
SDL_GetWindowPosition(s_pWindow, &rect.x, &rect.y);
|
||||
SDL_GetWindowSize(s_pWindow, &rect.w, &rect.h);
|
||||
|
||||
return rect;
|
||||
}
|
||||
|
||||
void GameWindow::SetDimensions(int w, int h, int x, int y)
|
||||
{
|
||||
s_width = w;
|
||||
s_height = h;
|
||||
s_x = x;
|
||||
s_y = y;
|
||||
|
||||
SDL_SetWindowSize(s_pWindow, w, h);
|
||||
SDL_ResizeEvent(s_pWindow, w, h);
|
||||
|
||||
SDL_SetWindowPosition(s_pWindow, x, y);
|
||||
SDL_MoveEvent(s_pWindow, x, y);
|
||||
}
|
||||
|
||||
void GameWindow::ResetDimensions()
|
||||
{
|
||||
s_x = SDL_WINDOWPOS_CENTERED;
|
||||
s_y = SDL_WINDOWPOS_CENTERED;
|
||||
s_width = DEFAULT_WIDTH;
|
||||
s_height = DEFAULT_HEIGHT;
|
||||
|
||||
Config::WindowX = s_x;
|
||||
Config::WindowY = s_y;
|
||||
Config::WindowWidth = s_width;
|
||||
Config::WindowHeight = s_height;
|
||||
}
|
||||
|
||||
uint32_t GameWindow::GetWindowFlags()
|
||||
{
|
||||
uint32_t flags = SDL_WINDOW_HIDDEN | SDL_WINDOW_RESIZABLE;
|
||||
|
||||
if (Config::WindowState == EWindowState::Maximised)
|
||||
flags |= SDL_WINDOW_MAXIMIZED;
|
||||
|
||||
if (Config::Fullscreen)
|
||||
flags |= SDL_WINDOW_FULLSCREEN_DESKTOP;
|
||||
|
||||
#ifdef SDL_VULKAN_ENABLED
|
||||
flags |= SDL_WINDOW_VULKAN;
|
||||
#endif
|
||||
|
||||
return flags;
|
||||
}
|
||||
|
||||
int GameWindow::GetDisplayCount()
|
||||
{
|
||||
auto result = SDL_GetNumVideoDisplays();
|
||||
|
||||
if (result < 0)
|
||||
{
|
||||
LOGF_ERROR("Failed to get display count: {}", SDL_GetError());
|
||||
return 1;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
int GameWindow::GetDisplay()
|
||||
{
|
||||
return SDL_GetWindowDisplayIndex(s_pWindow);
|
||||
}
|
||||
|
||||
void GameWindow::SetDisplay(int displayIndex)
|
||||
{
|
||||
if (!IsFullscreen())
|
||||
return;
|
||||
|
||||
s_isChangingDisplay = true;
|
||||
|
||||
SDL_Rect bounds;
|
||||
|
||||
if (SDL_GetDisplayBounds(displayIndex, &bounds) == 0)
|
||||
{
|
||||
SetFullscreen(false);
|
||||
SetDimensions(bounds.w, bounds.h, bounds.x, bounds.y);
|
||||
SetFullscreen(true);
|
||||
}
|
||||
else
|
||||
{
|
||||
ResetDimensions();
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<SDL_DisplayMode> GameWindow::GetDisplayModes(bool ignoreInvalidModes, bool ignoreRefreshRates)
|
||||
{
|
||||
auto result = std::vector<SDL_DisplayMode>();
|
||||
auto uniqueResolutions = std::set<std::pair<int, int>>();
|
||||
auto displayIndex = GetDisplay();
|
||||
auto modeCount = SDL_GetNumDisplayModes(displayIndex);
|
||||
|
||||
if (modeCount <= 0)
|
||||
return result;
|
||||
|
||||
for (int i = modeCount - 1; i >= 0; i--)
|
||||
{
|
||||
SDL_DisplayMode mode;
|
||||
|
||||
if (SDL_GetDisplayMode(displayIndex, i, &mode) == 0)
|
||||
{
|
||||
if (ignoreInvalidModes)
|
||||
{
|
||||
if (mode.w < MIN_WIDTH || mode.h < MIN_HEIGHT)
|
||||
continue;
|
||||
|
||||
SDL_DisplayMode desktopMode;
|
||||
|
||||
if (SDL_GetDesktopDisplayMode(displayIndex, &desktopMode) == 0)
|
||||
{
|
||||
if (mode.w >= desktopMode.w || mode.h >= desktopMode.h)
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if (ignoreRefreshRates)
|
||||
{
|
||||
auto res = std::make_pair(mode.w, mode.h);
|
||||
|
||||
if (uniqueResolutions.find(res) == uniqueResolutions.end())
|
||||
{
|
||||
uniqueResolutions.insert(res);
|
||||
result.push_back(mode);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
result.push_back(mode);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
int GameWindow::FindMatchingDisplayMode()
|
||||
{
|
||||
auto displayModes = GetDisplayModes();
|
||||
|
||||
for (int i = 0; i < displayModes.size(); i++)
|
||||
{
|
||||
auto& mode = displayModes[i];
|
||||
|
||||
if (mode.w == s_width && mode.h == s_height)
|
||||
return i;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
bool GameWindow::IsPositionValid()
|
||||
{
|
||||
auto displayCount = GetDisplayCount();
|
||||
|
||||
for (int i = 0; i < displayCount; i++)
|
||||
{
|
||||
SDL_Rect bounds;
|
||||
|
||||
if (SDL_GetDisplayBounds(i, &bounds) == 0)
|
||||
{
|
||||
auto x = s_x;
|
||||
auto y = s_y;
|
||||
|
||||
// Window spans across the entire display in windowed mode, which is invalid.
|
||||
if (!Config::Fullscreen && s_width == bounds.w && s_height == bounds.h)
|
||||
return false;
|
||||
|
||||
if (x == SDL_WINDOWPOS_CENTERED_DISPLAY(i))
|
||||
x = bounds.w / 2 - s_width / 2;
|
||||
|
||||
if (y == SDL_WINDOWPOS_CENTERED_DISPLAY(i))
|
||||
y = bounds.h / 2 - s_height / 2;
|
||||
|
||||
if (x >= bounds.x && x < bounds.x + bounds.w &&
|
||||
y >= bounds.y && y < bounds.y + bounds.h)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,20 +1,13 @@
|
|||
#pragma once
|
||||
|
||||
#include <res/images/game_icon.bmp.h>
|
||||
#include <res/images/game_icon_night.bmp.h>
|
||||
#include <os/logger.h>
|
||||
#include <os/version.h>
|
||||
#include <gpu/rhi/plume_render_interface_types.h>
|
||||
#include <ui/window_events.h>
|
||||
#include <user/config.h>
|
||||
#include <gpu/rhi/plume_render_interface_types.h>
|
||||
|
||||
#if _WIN32
|
||||
#include <dwmapi.h>
|
||||
#pragma comment(lib, "dwmapi.lib")
|
||||
#endif
|
||||
|
||||
#define DEFAULT_WIDTH 1280
|
||||
#define DEFAULT_HEIGHT 720
|
||||
#define MIN_WIDTH 640
|
||||
#define MIN_HEIGHT 480
|
||||
|
||||
class GameWindow
|
||||
{
|
||||
|
|
@ -32,277 +25,27 @@ public:
|
|||
static inline bool s_isFullscreenCursorVisible;
|
||||
static inline bool s_isChangingDisplay;
|
||||
|
||||
static SDL_Surface* GetIconSurface(void* pIconBmp, size_t iconSize)
|
||||
{
|
||||
auto rw = SDL_RWFromMem(pIconBmp, iconSize);
|
||||
auto surface = SDL_LoadBMP_RW(rw, 1);
|
||||
|
||||
if (!surface)
|
||||
LOGF_ERROR("Failed to load icon: {}", SDL_GetError());
|
||||
|
||||
return surface;
|
||||
}
|
||||
|
||||
static void SetIcon(void* pIconBmp, size_t iconSize)
|
||||
{
|
||||
if (auto icon = GetIconSurface(pIconBmp, iconSize))
|
||||
{
|
||||
SDL_SetWindowIcon(s_pWindow, icon);
|
||||
SDL_FreeSurface(icon);
|
||||
}
|
||||
}
|
||||
|
||||
static void SetIcon(bool isNight = false)
|
||||
{
|
||||
if (isNight)
|
||||
{
|
||||
SetIcon(g_game_icon_night, sizeof(g_game_icon_night));
|
||||
}
|
||||
else
|
||||
{
|
||||
SetIcon(g_game_icon, sizeof(g_game_icon));
|
||||
}
|
||||
}
|
||||
|
||||
static const char* GetTitle()
|
||||
{
|
||||
return Config::Language == ELanguage::Japanese
|
||||
? "SONIC WORLD ADVENTURE"
|
||||
: "SONIC UNLEASHED";
|
||||
}
|
||||
|
||||
static void SetTitle(const char* title = nullptr)
|
||||
{
|
||||
SDL_SetWindowTitle(s_pWindow, title ? title : GetTitle());
|
||||
}
|
||||
|
||||
static void SetDarkTitleBar(bool isEnabled)
|
||||
{
|
||||
#if _WIN32
|
||||
auto version = os::version::GetOSVersion();
|
||||
|
||||
if (version.Major < 10 || version.Build <= 17763)
|
||||
return;
|
||||
|
||||
auto flag = version.Build >= 18985
|
||||
? DWMWA_USE_IMMERSIVE_DARK_MODE
|
||||
: 19; // DWMWA_USE_IMMERSIVE_DARK_MODE_BEFORE_20H1
|
||||
|
||||
const DWORD useImmersiveDarkMode = isEnabled;
|
||||
DwmSetWindowAttribute(s_renderWindow, flag, &useImmersiveDarkMode, sizeof(useImmersiveDarkMode));
|
||||
#endif
|
||||
}
|
||||
|
||||
static bool IsFullscreen()
|
||||
{
|
||||
return SDL_GetWindowFlags(s_pWindow) & SDL_WINDOW_FULLSCREEN_DESKTOP;
|
||||
}
|
||||
|
||||
static bool SetFullscreen(bool isEnabled)
|
||||
{
|
||||
if (isEnabled)
|
||||
{
|
||||
SDL_SetWindowFullscreen(s_pWindow, SDL_WINDOW_FULLSCREEN_DESKTOP);
|
||||
SDL_ShowCursor(s_isFullscreenCursorVisible ? SDL_ENABLE : SDL_DISABLE);
|
||||
}
|
||||
else
|
||||
{
|
||||
SDL_SetWindowFullscreen(s_pWindow, 0);
|
||||
SDL_ShowCursor(SDL_ENABLE);
|
||||
|
||||
SetIcon(GameWindow::s_isIconNight);
|
||||
SetDimensions(Config::WindowWidth, Config::WindowHeight, Config::WindowX, Config::WindowY);
|
||||
}
|
||||
|
||||
return isEnabled;
|
||||
}
|
||||
|
||||
static void SetFullscreenCursorVisibility(bool isVisible)
|
||||
{
|
||||
s_isFullscreenCursorVisible = isVisible;
|
||||
|
||||
if (IsFullscreen())
|
||||
{
|
||||
SDL_ShowCursor(s_isFullscreenCursorVisible ? SDL_ENABLE : SDL_DISABLE);
|
||||
}
|
||||
else
|
||||
{
|
||||
SDL_ShowCursor(SDL_ENABLE);
|
||||
}
|
||||
}
|
||||
|
||||
static bool IsMaximised()
|
||||
{
|
||||
return SDL_GetWindowFlags(s_pWindow) & SDL_WINDOW_MAXIMIZED;
|
||||
}
|
||||
|
||||
static EWindowState SetMaximised(bool isEnabled)
|
||||
{
|
||||
if (isEnabled)
|
||||
{
|
||||
SDL_MaximizeWindow(s_pWindow);
|
||||
}
|
||||
else
|
||||
{
|
||||
SDL_RestoreWindow(s_pWindow);
|
||||
}
|
||||
|
||||
return isEnabled
|
||||
? EWindowState::Maximised
|
||||
: EWindowState::Normal;
|
||||
}
|
||||
|
||||
static SDL_Rect GetDimensions()
|
||||
{
|
||||
SDL_Rect rect{};
|
||||
|
||||
SDL_GetWindowPosition(s_pWindow, &rect.x, &rect.y);
|
||||
SDL_GetWindowSize(s_pWindow, &rect.w, &rect.h);
|
||||
|
||||
return rect;
|
||||
}
|
||||
|
||||
static void SetDimensions(int w, int h, int x = SDL_WINDOWPOS_CENTERED, int y = SDL_WINDOWPOS_CENTERED)
|
||||
{
|
||||
s_width = w;
|
||||
s_height = h;
|
||||
s_x = x;
|
||||
s_y = y;
|
||||
|
||||
SDL_SetWindowSize(s_pWindow, w, h);
|
||||
SDL_ResizeEvent(s_pWindow, w, h);
|
||||
|
||||
SDL_SetWindowPosition(s_pWindow, x, y);
|
||||
SDL_MoveEvent(s_pWindow, x, y);
|
||||
}
|
||||
|
||||
static void ResetDimensions()
|
||||
{
|
||||
s_x = SDL_WINDOWPOS_CENTERED;
|
||||
s_y = SDL_WINDOWPOS_CENTERED;
|
||||
s_width = DEFAULT_WIDTH;
|
||||
s_height = DEFAULT_HEIGHT;
|
||||
|
||||
Config::WindowX = s_x;
|
||||
Config::WindowY = s_y;
|
||||
Config::WindowWidth = s_width;
|
||||
Config::WindowHeight = s_height;
|
||||
}
|
||||
|
||||
static uint32_t GetWindowFlags()
|
||||
{
|
||||
uint32_t flags = SDL_WINDOW_HIDDEN | SDL_WINDOW_RESIZABLE;
|
||||
|
||||
if (Config::WindowState == EWindowState::Maximised)
|
||||
flags |= SDL_WINDOW_MAXIMIZED;
|
||||
|
||||
if (Config::Fullscreen)
|
||||
flags |= SDL_WINDOW_FULLSCREEN_DESKTOP;
|
||||
|
||||
#ifdef SDL_VULKAN_ENABLED
|
||||
flags |= SDL_WINDOW_VULKAN;
|
||||
#endif
|
||||
|
||||
return flags;
|
||||
}
|
||||
|
||||
static int GetDisplayCount()
|
||||
{
|
||||
auto result = SDL_GetNumVideoDisplays();
|
||||
|
||||
if (result < 0)
|
||||
{
|
||||
LOGF_ERROR("Failed to get display count: {}", SDL_GetError());
|
||||
return 1;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static int GetDisplay()
|
||||
{
|
||||
auto displayCount = GetDisplayCount();
|
||||
|
||||
for (int i = 0; i < displayCount; i++)
|
||||
{
|
||||
SDL_Rect bounds;
|
||||
|
||||
if (SDL_GetDisplayBounds(i, &bounds) == 0)
|
||||
{
|
||||
auto x = s_x;
|
||||
auto y = s_y;
|
||||
|
||||
if (x == SDL_WINDOWPOS_CENTERED)
|
||||
x = bounds.w / 2 - s_width / 2;
|
||||
|
||||
if (y == SDL_WINDOWPOS_CENTERED)
|
||||
y = bounds.h / 2 - s_height / 2;
|
||||
|
||||
if (x >= bounds.x && x < bounds.x + bounds.w &&
|
||||
y >= bounds.y && y < bounds.y + bounds.h)
|
||||
{
|
||||
return i;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void SetDisplay(int displayIndex)
|
||||
{
|
||||
if (!IsFullscreen())
|
||||
return;
|
||||
|
||||
s_isChangingDisplay = true;
|
||||
|
||||
SDL_Rect bounds;
|
||||
|
||||
if (SDL_GetDisplayBounds(displayIndex, &bounds) == 0)
|
||||
{
|
||||
SetFullscreen(false);
|
||||
SetDimensions(bounds.w, bounds.h, bounds.x, bounds.y);
|
||||
SetFullscreen(true);
|
||||
}
|
||||
else
|
||||
{
|
||||
ResetDimensions();
|
||||
}
|
||||
}
|
||||
|
||||
static bool IsPositionValid()
|
||||
{
|
||||
auto displayCount = GetDisplayCount();
|
||||
|
||||
for (int i = 0; i < displayCount; i++)
|
||||
{
|
||||
SDL_Rect bounds;
|
||||
|
||||
if (SDL_GetDisplayBounds(i, &bounds) == 0)
|
||||
{
|
||||
auto x = s_x;
|
||||
auto y = s_y;
|
||||
|
||||
if (!Config::Fullscreen && s_width == bounds.w && s_height == bounds.h)
|
||||
return false;
|
||||
|
||||
if (x == SDL_WINDOWPOS_CENTERED)
|
||||
x = bounds.w / 2 - s_width / 2;
|
||||
|
||||
if (y == SDL_WINDOWPOS_CENTERED)
|
||||
y = bounds.h / 2 - s_height / 2;
|
||||
|
||||
if (x >= bounds.x && x < bounds.x + bounds.w &&
|
||||
y >= bounds.y && y < bounds.y + bounds.h)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static void Init(const char* sdlVideoDriver);
|
||||
static SDL_Surface* GetIconSurface(void* pIconBmp, size_t iconSize);
|
||||
static void SetIcon(void* pIconBmp, size_t iconSize);
|
||||
static void SetIcon(bool isNight = false);
|
||||
static const char* GetTitle();
|
||||
static void SetTitle(const char* title = nullptr);
|
||||
static void SetDarkTitleBar(bool isEnabled);
|
||||
static bool IsFullscreen();
|
||||
static bool SetFullscreen(bool isEnabled);
|
||||
static void SetFullscreenCursorVisibility(bool isVisible);
|
||||
static bool IsMaximised();
|
||||
static EWindowState SetMaximised(bool isEnabled);
|
||||
static SDL_Rect GetDimensions();
|
||||
static void SetDimensions(int w, int h, int x = SDL_WINDOWPOS_CENTERED, int y = SDL_WINDOWPOS_CENTERED);
|
||||
static void ResetDimensions();
|
||||
static uint32_t GetWindowFlags();
|
||||
static int GetDisplayCount();
|
||||
static int GetDisplay();
|
||||
static void SetDisplay(int displayIndex);
|
||||
static std::vector<SDL_DisplayMode> GetDisplayModes(bool ignoreInvalidModes = true, bool ignoreRefreshRates = true);
|
||||
static int FindMatchingDisplayMode();
|
||||
static bool IsPositionValid();
|
||||
static void Init(const char* sdlVideoDriver = nullptr);
|
||||
static void Update();
|
||||
};
|
||||
|
|
|
|||
|
|
@ -509,10 +509,15 @@ static void DrawConfigOption(int32_t rowIndex, float yOffset, ConfigDef<T>* conf
|
|||
}
|
||||
else
|
||||
{
|
||||
// released lock, call video callbacks if value is different
|
||||
// released lock, do callbacks if value is different
|
||||
if (config->Value != s_oldValue)
|
||||
{
|
||||
VideoConfigValueChangedCallback(config);
|
||||
|
||||
if (config->ApplyCallback)
|
||||
config->ApplyCallback(config);
|
||||
}
|
||||
|
||||
Game_PlaySound("sys_worldmap_finaldecide");
|
||||
}
|
||||
}
|
||||
|
|
@ -533,13 +538,14 @@ static void DrawConfigOption(int32_t rowIndex, float yOffset, ConfigDef<T>* conf
|
|||
{
|
||||
config->MakeDefault();
|
||||
|
||||
// TODO: check if value was changed?
|
||||
VideoConfigValueChangedCallback(config);
|
||||
|
||||
// TODO: check if value was changed?
|
||||
if (config->Callback)
|
||||
config->Callback(config);
|
||||
|
||||
if (config->ApplyCallback)
|
||||
config->ApplyCallback(config);
|
||||
|
||||
Game_PlaySound("sys_worldmap_decide");
|
||||
}
|
||||
}
|
||||
|
|
@ -568,8 +574,12 @@ static void DrawConfigOption(int32_t rowIndex, float yOffset, ConfigDef<T>* conf
|
|||
|
||||
DrawTextWithMarquee(g_seuratFont, size, textPos, min, max, textColour, configName.c_str(), g_rowSelectionTime, 0.9, Scale(250.0));
|
||||
|
||||
// Show reset button if this option is accessible or not a language option.
|
||||
g_canReset = g_isControlsVisible && !g_lockedOnOption && g_selectedItem->GetName().find("Language") == std::string::npos && isAccessible;
|
||||
// large
|
||||
g_canReset = g_isControlsVisible &&
|
||||
!g_lockedOnOption &&
|
||||
g_selectedItem->GetName().find("Language") == std::string::npos &&
|
||||
g_selectedItem != &Config::WindowSize &&
|
||||
isAccessible;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -753,8 +763,11 @@ static void DrawConfigOption(int32_t rowIndex, float yOffset, ConfigDef<T>* conf
|
|||
config->Value = std::clamp(config->Value, valueMin, valueMax);
|
||||
}
|
||||
|
||||
if ((increment || decrement) && config->Callback)
|
||||
config->Callback(config);
|
||||
if (!config->ApplyCallback)
|
||||
{
|
||||
if ((increment || decrement) && config->Callback)
|
||||
config->Callback(config);
|
||||
}
|
||||
}
|
||||
|
||||
std::string valueText;
|
||||
|
|
@ -764,10 +777,32 @@ static void DrawConfigOption(int32_t rowIndex, float yOffset, ConfigDef<T>* conf
|
|||
}
|
||||
else if constexpr (std::is_same_v<T, int32_t>)
|
||||
{
|
||||
valueText = fmt::format("{}", config->Value);
|
||||
if (config == &Config::WindowSize)
|
||||
{
|
||||
auto displayModes = GameWindow::GetDisplayModes();
|
||||
|
||||
if (isSlider && config->Value >= valueMax)
|
||||
valueText = Localise("Options_Value_Max");
|
||||
// Try matching the current window size with a known configuration.
|
||||
if (config->Value < 0)
|
||||
config->Value = GameWindow::FindMatchingDisplayMode();
|
||||
|
||||
if (config->Value >= 0 && config->Value < displayModes.size())
|
||||
{
|
||||
auto displayMode = displayModes[config->Value];
|
||||
|
||||
valueText = fmt::format("{}x{}", displayMode.w, displayMode.h);
|
||||
}
|
||||
else
|
||||
{
|
||||
valueText = fmt::format("{}x{}", GameWindow::s_width, GameWindow::s_height);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
valueText = fmt::format("{}", config->Value);
|
||||
|
||||
if (isSlider && config->Value >= valueMax)
|
||||
valueText = Localise("Options_Value_Max");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -851,7 +886,9 @@ static void DrawConfigOptions()
|
|||
|
||||
case 3: // VIDEO
|
||||
{
|
||||
// TODO: expose WindowWidth/WindowHeight as WindowSize.
|
||||
DrawConfigOption(rowCount++, yOffset, &Config::WindowSize,
|
||||
!Config::Fullscreen, &Localise("Options_Desc_NotAvailableFullscreen"),
|
||||
0, 0, (int32_t)GameWindow::GetDisplayModes().size() - 1, false);
|
||||
|
||||
auto displayCount = GameWindow::GetDisplayCount();
|
||||
auto canChangeMonitor = Config::Fullscreen && displayCount > 1;
|
||||
|
|
|
|||
|
|
@ -87,6 +87,7 @@ void LoadThumbnails()
|
|||
g_configThumbnails[&Config::Subtitles] = LOAD_ZSTD_TEXTURE(g_subtitles);
|
||||
g_configThumbnails[&Config::MusicAttenuation] = LOAD_ZSTD_TEXTURE(g_music_attenuation);
|
||||
g_configThumbnails[&Config::BattleTheme] = LOAD_ZSTD_TEXTURE(g_battle_theme);
|
||||
g_configThumbnails[&Config::WindowSize] = LOAD_ZSTD_TEXTURE(g_window_size);
|
||||
g_configThumbnails[&Config::Monitor] = LOAD_ZSTD_TEXTURE(g_monitor);
|
||||
g_configThumbnails[&Config::AspectRatio] = LOAD_ZSTD_TEXTURE(g_aspect_ratio);
|
||||
g_configThumbnails[&Config::ResolutionScale] = LOAD_ZSTD_TEXTURE(g_resolution_scale);
|
||||
|
|
|
|||
|
|
@ -294,6 +294,7 @@ public:
|
|||
std::map<T, std::string> EnumTemplateReverse{};
|
||||
CONFIG_ENUM_LOCALE(T)* EnumLocale{};
|
||||
std::function<void(ConfigDef<T>*)> Callback;
|
||||
std::function<void(ConfigDef<T>*)> ApplyCallback;
|
||||
|
||||
// CONFIG_DEFINE
|
||||
ConfigDef(std::string section, std::string name, T defaultValue) : Section(section), Name(name), DefaultValue(defaultValue)
|
||||
|
|
@ -619,6 +620,7 @@ public:
|
|||
|
||||
CONFIG_DEFINE("Video", int32_t, WindowX, WINDOWPOS_CENTRED);
|
||||
CONFIG_DEFINE("Video", int32_t, WindowY, WINDOWPOS_CENTRED);
|
||||
CONFIG_DEFINE_LOCALISED("Video", int32_t, WindowSize, -1);
|
||||
CONFIG_DEFINE("Video", int32_t, WindowWidth, 1280);
|
||||
CONFIG_DEFINE("Video", int32_t, WindowHeight, 720);
|
||||
CONFIG_DEFINE_ENUM("Video", EWindowState, WindowState, EWindowState::Normal);
|
||||
|
|
@ -638,7 +640,7 @@ public:
|
|||
def->Value = std::clamp(def->Value, 0.25f, 2.0f);
|
||||
});
|
||||
|
||||
CONFIG_DEFINE_CALLBACK("Video", bool, Fullscreen, false,
|
||||
CONFIG_DEFINE_CALLBACK("Video", bool, Fullscreen, true,
|
||||
{
|
||||
def->Locale = &g_Fullscreen_locale;
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue