tr2/shell: improve moving window around

This commit is contained in:
Marcin Kurczewski 2025-04-22 21:29:41 +02:00
parent 05876ba9c4
commit 8133f72e20
7 changed files with 78 additions and 64 deletions

View file

@ -55,6 +55,8 @@
- fixed a crash on level load if an animation has no frames (#2746, regression from 0.8)
- fixed a crash in custom levels with large rooms (#2749)
- fixed flares missing the flicker effect in 60 FPS (#2806)
- fixed the viewport not always in sync with the window (#2820)
- improved performance when moving the window around
- improved pause exit dialog - it can now be canceled with escape
- removed the need to specify in the game flow levels that have no secrets (secrets will be automatically counted) (#1582)
- removed the hard-coded end-level behaviour of the bird guardian for custom levels (#1583)

View file

@ -130,31 +130,35 @@ void Shell_ExitSystemFmt(const char *fmt, ...)
Memory_FreePointer(&message);
}
int32_t Shell_GetCurrentDisplayWidth(void)
bool Shell_IsFullscreen(void)
{
SDL_DisplayMode dm;
SDL_GetCurrentDisplayMode(0, &dm);
return dm.w;
}
int32_t Shell_GetCurrentDisplayHeight(void)
{
SDL_DisplayMode dm;
SDL_GetCurrentDisplayMode(0, &dm);
return dm.h;
}
void Shell_GetWindowSize(int32_t *const out_width, int32_t *const out_height)
{
ASSERT(out_width != nullptr);
ASSERT(out_height != nullptr);
SDL_Window *const window = Shell_GetWindow();
if (window == nullptr) {
*out_width = -1;
*out_height = -1;
} else {
SDL_GetWindowSize(window, out_width, out_height);
ASSERT(window != nullptr);
const Uint32 flags = SDL_GetWindowFlags(window);
return (flags & SDL_WINDOW_FULLSCREEN_DESKTOP) != 0;
}
SHELL_SIZE Shell_GetWindowSize(void)
{
SDL_Window *const window = Shell_GetWindow();
SHELL_SIZE result = { .w = -1, .h = -1 };
if (window != nullptr) {
SDL_GetWindowSize(window, &result.w, &result.h);
}
return result;
}
SHELL_SIZE Shell_GetCurrentSize(void)
{
return Shell_IsFullscreen() ? Shell_GetCurrentDisplaySize()
: Shell_GetWindowSize();
}
SHELL_SIZE Shell_GetCurrentDisplaySize(void)
{
SDL_DisplayMode dm;
SDL_GetCurrentDisplayMode(0, &dm);
return (SHELL_SIZE) { .w = dm.w, .h = dm.h };
}
void Shell_ScheduleExit(void)

View file

@ -3,6 +3,11 @@
#include <SDL2/SDL.h>
#include <stdint.h>
typedef struct {
int32_t w;
int32_t h;
} SHELL_SIZE;
extern void Shell_Shutdown(void);
extern SDL_Window *Shell_GetWindow(void);
@ -16,9 +21,10 @@ void Shell_GetCommandLine(int *arg_count, const char ***args);
void Shell_ScheduleExit(void);
bool Shell_IsExiting(void);
int32_t Shell_GetCurrentDisplayWidth(void);
int32_t Shell_GetCurrentDisplayHeight(void);
void Shell_GetWindowSize(int32_t *out_width, int32_t *out_height);
bool Shell_IsFullscreen(void);
SHELL_SIZE Shell_GetWindowSize(void);
SHELL_SIZE Shell_GetCurrentSize(void);
SHELL_SIZE Shell_GetCurrentDisplaySize(void);
extern const char *Shell_GetConfigPath(void);
extern const char *Shell_GetGameFlowPath(void);

View file

@ -71,9 +71,10 @@ void Screen_Init(void)
}
// set the first resolution size to desktop size
const SHELL_SIZE display_size = Shell_GetCurrentDisplaySize();
res = &m_Resolutions[0];
res->width = Shell_GetCurrentDisplayWidth();
res->height = Shell_GetCurrentDisplayHeight();
res->width = display_size.w;
res->height = display_size.h;
// select matching resolution from config
if (g_Config.rendering.resolution_width > 0

View file

@ -123,9 +123,8 @@ static bool M_Play(const char *const file_name)
? 0
: g_Config.audio.sound_volume / (float)Sound_GetMaxVolume());
Video_SetSurfaceSize(
video, Shell_GetCurrentDisplayWidth(),
Shell_GetCurrentDisplayHeight());
const SHELL_SIZE display_size = Shell_GetCurrentDisplaySize();
Video_SetSurfaceSize(video, display_size.w, display_size.h);
if (g_Config.rendering.render_mode == RM_SOFTWARE) {
Video_SetSurfacePixelFormat(video, AV_PIX_FMT_RGB8);
GFX_2D_Renderer_SetPalette(renderer_2d, palette);

View file

@ -77,10 +77,12 @@ static SHELL_ARGS m_Args = {
.save_to_load = -1,
};
static SHELL_SIZE m_ViewportSize = { .w = -1, .h = -1 };
static Uint64 m_UpdateDebounce = 0;
static void M_SyncToWindow(void);
static void M_SyncFromWindow(void);
static void M_SyncFromWindow(bool update_viewport);
static bool M_MustUpdateRendererViewport(void);
static void M_RefreshRendererViewport(void);
static void M_HandleFocusGained(void);
static void M_HandleFocusLost(void);
@ -136,8 +138,9 @@ static void M_SyncToWindow(void)
height = 720;
}
if (x <= 0 || y <= 0) {
x = (Shell_GetCurrentDisplayWidth() - width) / 2;
y = (Shell_GetCurrentDisplayHeight() - height) / 2;
const SHELL_SIZE display_size = Shell_GetCurrentDisplaySize();
x = (display_size.w - width) / 2;
y = (display_size.h - height) / 2;
}
SDL_SetWindowFullscreen(g_SDLWindow, 0);
@ -147,7 +150,7 @@ static void M_SyncToWindow(void)
}
}
static void M_SyncFromWindow(void)
static void M_SyncFromWindow(const bool update_viewport)
{
// Determine if this call should sync config, i.e., skip immediate
// programmatic events
@ -177,13 +180,22 @@ static void M_SyncFromWindow(void)
}
}
// Always refresh viewport to reflect the actual window size
M_RefreshRendererViewport();
if (update_viewport || M_MustUpdateRendererViewport()) {
// Refresh viewport to reflect the actual window size
M_RefreshRendererViewport();
}
}
static bool M_MustUpdateRendererViewport(void)
{
const SHELL_SIZE size = Shell_GetCurrentSize();
return m_ViewportSize.w != size.w || m_ViewportSize.h != size.h;
}
static void M_RefreshRendererViewport(void)
{
Viewport_Reset();
m_ViewportSize = Shell_GetCurrentSize();
}
static void M_HandleFocusGained(void)
@ -201,7 +213,7 @@ static void M_HandleWindowShown(void)
static void M_HandleWindowRestored(void)
{
M_SyncFromWindow();
M_SyncFromWindow(true);
}
static void M_HandleWindowMinimized(void)
@ -211,17 +223,17 @@ static void M_HandleWindowMinimized(void)
static void M_HandleWindowMaximized(void)
{
M_SyncFromWindow();
M_SyncFromWindow(true);
}
static void M_HandleWindowMoved(const int32_t x, const int32_t y)
{
M_SyncFromWindow();
M_SyncFromWindow(false);
}
static void M_HandleWindowResized(int32_t width, int32_t height)
{
M_SyncFromWindow();
M_SyncFromWindow(true);
}
static void M_HandleKeyDown(const SDL_Event *const event)
@ -352,9 +364,9 @@ static void M_HandleConfigChange(const EVENT *const event, void *const data)
}
if (CHANGED(window.is_fullscreen) || CHANGED(window.is_maximized)
|| CHANGED(window.x) || CHANGED(window.y) || CHANGED(window.width)
|| CHANGED(window.height) || CHANGED(rendering.scaler)
|| CHANGED(rendering.sizer) || CHANGED(rendering.aspect_mode)) {
|| CHANGED(window.width) || CHANGED(window.height)
|| CHANGED(rendering.scaler) || CHANGED(rendering.sizer)
|| CHANGED(rendering.aspect_mode)) {
LOG_DEBUG("Change in settings detected");
M_SyncToWindow();
M_RefreshRendererViewport();
@ -378,7 +390,11 @@ static void M_HandleConfigChange(const EVENT *const event, void *const data)
}
}
Output_ApplyLevelSettings();
if (CHANGED(visuals.fog_start) || CHANGED(visuals.fog_end)
|| CHANGED(visuals.water_color.g) || CHANGED(visuals.water_color.b)
|| CHANGED(visuals.water_color.r)) {
Output_ApplyLevelSettings();
}
}
// TODO: refactor the hell out of me
@ -562,12 +578,6 @@ void Shell_Start(void)
M_RefreshRendererViewport();
}
bool Shell_IsFullscreen(void)
{
const Uint32 flags = SDL_GetWindowFlags(g_SDLWindow);
return (flags & SDL_WINDOW_FULLSCREEN_DESKTOP) != 0;
}
// TODO: try to call this function in a single place after introducing phases.
void Shell_ProcessEvents(void)
{

View file

@ -120,14 +120,7 @@ static void M_ApplyGameVars(const VIEWPORT *const vp)
void Viewport_Reset(void)
{
int32_t win_width;
int32_t win_height;
if (Shell_IsFullscreen()) {
win_width = Shell_GetCurrentDisplayWidth();
win_height = Shell_GetCurrentDisplayHeight();
} else {
SDL_GetWindowSize(g_SDLWindow, &win_width, &win_height);
}
const SHELL_SIZE size = Shell_GetCurrentSize();
VIEWPORT *const vp = &m_Viewport;
switch (g_Config.rendering.aspect_mode) {
@ -138,12 +131,12 @@ void Viewport_Reset(void)
vp->render_ar = 16.0 / 9.0;
break;
case AM_ANY:
vp->render_ar = win_width / (double)win_height;
vp->render_ar = size.w / (double)size.h;
break;
}
vp->width = win_width / g_Config.rendering.scaler;
vp->height = win_height / g_Config.rendering.scaler;
vp->width = size.w / g_Config.rendering.scaler;
vp->height = size.h / g_Config.rendering.scaler;
if (g_Config.rendering.aspect_mode != AM_ANY) {
vp->width = vp->height * vp->render_ar;
}
@ -171,9 +164,8 @@ void Viewport_Reset(void)
M_InitGameVars(&m_Viewport);
M_ApplyGameVars(&m_Viewport);
const int32_t win_border = win_height * (1.0 - g_Config.rendering.sizer);
Render_SetupDisplay(
win_border, win_width, win_height, vp->width, vp->height);
const int32_t win_border = size.h * (1.0 - g_Config.rendering.sizer);
Render_SetupDisplay(win_border, size.w, size.h, vp->width, vp->height);
}
const VIEWPORT *Viewport_Get(void)