Implemented window size option

This commit is contained in:
Hyper 2025-01-03 02:04:24 +00:00
parent 90e499cc8c
commit 31fb63ad81
8 changed files with 433 additions and 302 deletions

View file

@ -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." } }

View file

@ -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",
{

View file

@ -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);

View file

@ -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;
}

View file

@ -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();
};

View file

@ -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;

View file

@ -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);

View file

@ -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;