Extern `gameScreen`, remove `screenbuffer`
I know earlier I removed the gameScreen extern in favor of using
screenbuffer, but that was only to be consistent. After further
consideration, I have found that it's actually really stupid.
There's no reason to be accessing it through screenbuffer, and it's
probably an artifact of 2.0-2.2 passing stack-allocated otherwise-global
classes everywhere through function arguments. Also, it leads to stupid
bugs where screenbuffer could potentially be NULL, which has already
resulted in various annoying crashes in the past. Although those could
be fixed by simply initializing screenbuffer at the very top of main(),
but, why not just scrap the whole thing anyway?
So that's what I'm doing.
As a nice side effect, I've removed the transitive include of Screen.h
from Graphics.h. This could've been done already since it only includes
it for the pointer anyway, but it's still good to do it now.
2021-12-25 08:56:47 +01:00
|
|
|
#define GAMESCREEN_DEFINITION
|
2020-01-01 21:29:24 +01:00
|
|
|
#include "Screen.h"
|
|
|
|
|
2021-02-27 19:44:01 +01:00
|
|
|
#include <SDL.h>
|
2020-07-19 21:43:29 +02:00
|
|
|
|
2022-12-01 07:30:16 +01:00
|
|
|
#include "Alloc.h"
|
2022-03-13 01:46:58 +01:00
|
|
|
#include "Constants.h"
|
2023-01-29 08:41:44 +01:00
|
|
|
#include "Exit.h"
|
2020-01-01 21:29:24 +01:00
|
|
|
#include "FileSystemUtils.h"
|
2021-04-23 01:19:20 +02:00
|
|
|
#include "Game.h"
|
2023-01-07 19:28:07 +01:00
|
|
|
#include "Graphics.h"
|
2020-01-01 21:29:24 +01:00
|
|
|
#include "GraphicsUtil.h"
|
2023-01-16 21:59:48 +01:00
|
|
|
#include "InterimVersion.h"
|
2023-01-07 19:28:07 +01:00
|
|
|
#include "Render.h"
|
2021-02-24 00:21:29 +01:00
|
|
|
#include "Vlogging.h"
|
2020-01-01 21:29:24 +01:00
|
|
|
|
2021-12-25 09:18:51 +01:00
|
|
|
void ScreenSettings_default(struct ScreenSettings* _this)
|
2020-11-13 01:29:11 +01:00
|
|
|
{
|
Store display index of window to settings
I have this annoying issue where the game will open on the wrong monitor
in fullscreen mode, because that monitor is considered to be display 0,
whereas the primary monitor I want is display 1.
To mitigate this somewhat, the game now stores the display index that it
was closed on, and will save it to settings. Then the next time the game
opens, it will open on that display index. This should work pretty well
as long as you aren't changing your monitor setup constantly.
Of course, none of this applies if your window manager is busted. For
example, on GNOME Wayland, which is what I use, in windowed mode the
game will always open on the monitor the cursor is on, and it won't even
be centered in the monitor. But it works fine if I use XWayland via
SDL_VIDEODRIVER=x11.
2023-03-21 08:23:42 +01:00
|
|
|
_this->windowDisplay = 0;
|
2023-01-16 21:45:40 +01:00
|
|
|
_this->windowWidth = SCREEN_WIDTH_PIXELS * 2;
|
|
|
|
_this->windowHeight = SCREEN_HEIGHT_PIXELS * 2;
|
2021-12-25 09:18:51 +01:00
|
|
|
_this->fullscreen = false;
|
|
|
|
_this->useVsync = true; // Now that uncapped is the default...
|
2021-12-26 08:11:17 +01:00
|
|
|
_this->scalingMode = SCALING_INTEGER;
|
2021-12-25 09:18:51 +01:00
|
|
|
_this->linearFilter = false;
|
|
|
|
_this->badSignal = false;
|
2020-11-13 01:29:11 +01:00
|
|
|
}
|
|
|
|
|
2021-12-25 09:18:51 +01:00
|
|
|
void Screen::init(const struct ScreenSettings* settings)
|
2020-11-13 01:29:11 +01:00
|
|
|
{
|
2021-09-07 03:56:39 +02:00
|
|
|
m_window = NULL;
|
|
|
|
m_renderer = NULL;
|
Store display index of window to settings
I have this annoying issue where the game will open on the wrong monitor
in fullscreen mode, because that monitor is considered to be display 0,
whereas the primary monitor I want is display 1.
To mitigate this somewhat, the game now stores the display index that it
was closed on, and will save it to settings. Then the next time the game
opens, it will open on that display index. This should work pretty well
as long as you aren't changing your monitor setup constantly.
Of course, none of this applies if your window manager is busted. For
example, on GNOME Wayland, which is what I use, in windowed mode the
game will always open on the monitor the cursor is on, and it won't even
be centered in the monitor. But it works fine if I use XWayland via
SDL_VIDEODRIVER=x11.
2023-03-21 08:23:42 +01:00
|
|
|
windowDisplay = settings->windowDisplay;
|
Persist windowed mode size through fullscreen mode
Previously, the game would not store the size of the window itself, and
would always call SDL_GetRendererOutputSize() (via
Screen::GetWindowSize()) to figure out the size of the window. The only
problem is, this would return the size of the whole monitor if the game
was in fullscreen mode. And the only place where the original windowed
mode size was stored would be in SDL itself, but that wouldn't persist
after the game was closed.
So, if you exited the game while in fullscreen mode, then your window
size would get set to the size of your monitor (1920 by 1080 in my
case). Then when you opened the game and toggled fullscreen off, it
would go back to the default window size, which is 640 by 480.
This is made worse, however, if you were in forced fullscreen mode when
you previously exited the game in windowed mode. In that case, the game
saves the size of 1920 by 1080, but doesn't save that you were in
fullscreen mode, so opening the game not in forced fullscreen mode would
result in you having a 1920 by 1080 window, but in windowed mode.
Meaning that not even fullscreening and unfullscreening would put the
game window back to normal size.
The solution, of course, is to just store the window size ourselves,
like any other screen setting, and only use GetWindowSize() if needed.
And just to make things clear, I've also renamed the GetWindowSize()
function to GetScreenSize(), because if it was named "window" it could
lead one to think that it would always return the size of the screen in
windowed mode, when in fact it returns the size of the screen whatever
mode it is in - fullscreen size if in fullscreen mode and window size if
in windowed mode.
And doing this also fixes the FIXME above Screen::isForcedFullscreen().
2023-03-21 04:59:37 +01:00
|
|
|
windowWidth = settings->windowWidth;
|
|
|
|
windowHeight = settings->windowHeight;
|
2021-12-25 09:18:51 +01:00
|
|
|
isWindowed = !settings->fullscreen;
|
|
|
|
scalingMode = settings->scalingMode;
|
|
|
|
isFiltered = settings->linearFilter;
|
Persist windowed mode size through fullscreen mode
Previously, the game would not store the size of the window itself, and
would always call SDL_GetRendererOutputSize() (via
Screen::GetWindowSize()) to figure out the size of the window. The only
problem is, this would return the size of the whole monitor if the game
was in fullscreen mode. And the only place where the original windowed
mode size was stored would be in SDL itself, but that wouldn't persist
after the game was closed.
So, if you exited the game while in fullscreen mode, then your window
size would get set to the size of your monitor (1920 by 1080 in my
case). Then when you opened the game and toggled fullscreen off, it
would go back to the default window size, which is 640 by 480.
This is made worse, however, if you were in forced fullscreen mode when
you previously exited the game in windowed mode. In that case, the game
saves the size of 1920 by 1080, but doesn't save that you were in
fullscreen mode, so opening the game not in forced fullscreen mode would
result in you having a 1920 by 1080 window, but in windowed mode.
Meaning that not even fullscreening and unfullscreening would put the
game window back to normal size.
The solution, of course, is to just store the window size ourselves,
like any other screen setting, and only use GetWindowSize() if needed.
And just to make things clear, I've also renamed the GetWindowSize()
function to GetScreenSize(), because if it was named "window" it could
lead one to think that it would always return the size of the screen in
windowed mode, when in fact it returns the size of the screen whatever
mode it is in - fullscreen size if in fullscreen mode and window size if
in windowed mode.
And doing this also fixes the FIXME above Screen::isForcedFullscreen().
2023-03-21 04:59:37 +01:00
|
|
|
badSignalEffect = settings->badSignal;
|
2021-12-25 09:18:51 +01:00
|
|
|
vsync = settings->useVsync;
|
2021-09-07 03:56:39 +02:00
|
|
|
|
|
|
|
SDL_SetHintWithPriority(
|
|
|
|
SDL_HINT_RENDER_SCALE_QUALITY,
|
|
|
|
isFiltered ? "linear" : "nearest",
|
|
|
|
SDL_HINT_OVERRIDE
|
|
|
|
);
|
|
|
|
SDL_SetHintWithPriority(
|
|
|
|
SDL_HINT_RENDER_VSYNC,
|
|
|
|
vsync ? "1" : "0",
|
|
|
|
SDL_HINT_OVERRIDE
|
|
|
|
);
|
|
|
|
|
|
|
|
// Uncomment this next line when you need to debug -flibit
|
|
|
|
// SDL_SetHintWithPriority(SDL_HINT_RENDER_DRIVER, "software", SDL_HINT_OVERRIDE);
|
2023-01-07 19:28:07 +01:00
|
|
|
|
|
|
|
m_window = SDL_CreateWindow(
|
|
|
|
"VVVVVV",
|
Store display index of window to settings
I have this annoying issue where the game will open on the wrong monitor
in fullscreen mode, because that monitor is considered to be display 0,
whereas the primary monitor I want is display 1.
To mitigate this somewhat, the game now stores the display index that it
was closed on, and will save it to settings. Then the next time the game
opens, it will open on that display index. This should work pretty well
as long as you aren't changing your monitor setup constantly.
Of course, none of this applies if your window manager is busted. For
example, on GNOME Wayland, which is what I use, in windowed mode the
game will always open on the monitor the cursor is on, and it won't even
be centered in the monitor. But it works fine if I use XWayland via
SDL_VIDEODRIVER=x11.
2023-03-21 08:23:42 +01:00
|
|
|
SDL_WINDOWPOS_CENTERED_DISPLAY(windowDisplay),
|
|
|
|
SDL_WINDOWPOS_CENTERED_DISPLAY(windowDisplay),
|
2023-01-16 21:45:40 +01:00
|
|
|
SCREEN_WIDTH_PIXELS * 2,
|
|
|
|
SCREEN_HEIGHT_PIXELS * 2,
|
2023-01-07 19:28:07 +01:00
|
|
|
SDL_WINDOW_HIDDEN | SDL_WINDOW_RESIZABLE | SDL_WINDOW_ALLOW_HIGHDPI
|
2021-09-07 03:56:39 +02:00
|
|
|
);
|
2023-01-07 19:28:07 +01:00
|
|
|
|
2023-01-29 08:41:44 +01:00
|
|
|
if (m_window == NULL)
|
|
|
|
{
|
|
|
|
vlog_error("Could not create window: %s", SDL_GetError());
|
|
|
|
VVV_exit(1);
|
|
|
|
}
|
|
|
|
|
2023-01-07 19:28:07 +01:00
|
|
|
m_renderer = SDL_CreateRenderer(m_window, -1, SDL_RENDERER_ACCELERATED | SDL_RENDERER_TARGETTEXTURE);
|
|
|
|
|
2023-01-29 08:41:44 +01:00
|
|
|
if (m_renderer == NULL)
|
|
|
|
{
|
|
|
|
vlog_error("Could not create renderer: %s", SDL_GetError());
|
|
|
|
VVV_exit(1);
|
|
|
|
}
|
|
|
|
|
2023-01-16 21:59:48 +01:00
|
|
|
#ifdef INTERIM_VERSION_EXISTS
|
|
|
|
/* Branch name limits are ill-defined but on GitHub it's ~256 chars
|
|
|
|
* ( https://stackoverflow.com/a/24014513/ ).
|
|
|
|
* Really though, just don't use super long branch names. */
|
|
|
|
char title[256];
|
|
|
|
SDL_snprintf(title, sizeof(title), "VVVVVV [%s]", BRANCH_NAME);
|
|
|
|
SDL_SetWindowTitle(m_window, title);
|
|
|
|
#else
|
2021-09-07 03:56:39 +02:00
|
|
|
SDL_SetWindowTitle(m_window, "VVVVVV");
|
2023-01-16 21:59:48 +01:00
|
|
|
#endif
|
2021-09-07 03:56:39 +02:00
|
|
|
|
2023-01-29 08:37:24 +01:00
|
|
|
SDL_SetWindowMinimumSize(m_window, SCREEN_WIDTH_PIXELS, SCREEN_HEIGHT_PIXELS);
|
|
|
|
|
2021-09-07 03:56:39 +02:00
|
|
|
LoadIcon();
|
|
|
|
|
Persist windowed mode size through fullscreen mode
Previously, the game would not store the size of the window itself, and
would always call SDL_GetRendererOutputSize() (via
Screen::GetWindowSize()) to figure out the size of the window. The only
problem is, this would return the size of the whole monitor if the game
was in fullscreen mode. And the only place where the original windowed
mode size was stored would be in SDL itself, but that wouldn't persist
after the game was closed.
So, if you exited the game while in fullscreen mode, then your window
size would get set to the size of your monitor (1920 by 1080 in my
case). Then when you opened the game and toggled fullscreen off, it
would go back to the default window size, which is 640 by 480.
This is made worse, however, if you were in forced fullscreen mode when
you previously exited the game in windowed mode. In that case, the game
saves the size of 1920 by 1080, but doesn't save that you were in
fullscreen mode, so opening the game not in forced fullscreen mode would
result in you having a 1920 by 1080 window, but in windowed mode.
Meaning that not even fullscreening and unfullscreening would put the
game window back to normal size.
The solution, of course, is to just store the window size ourselves,
like any other screen setting, and only use GetWindowSize() if needed.
And just to make things clear, I've also renamed the GetWindowSize()
function to GetScreenSize(), because if it was named "window" it could
lead one to think that it would always return the size of the screen in
windowed mode, when in fact it returns the size of the screen whatever
mode it is in - fullscreen size if in fullscreen mode and window size if
in windowed mode.
And doing this also fixes the FIXME above Screen::isForcedFullscreen().
2023-03-21 04:59:37 +01:00
|
|
|
ResizeScreen(windowWidth, windowHeight);
|
2020-01-01 21:29:24 +01:00
|
|
|
}
|
|
|
|
|
Explicitly declare void for all void parameter functions (#628)
Apparently in C, if you have `void test();`, it's completely okay to do
`test(2);`. The function will take in the argument, but just discard it
and throw it away. It's like a trash can, and a rude one at that. If you
declare it like `void test(void);`, this is prevented.
This is not a problem in C++ - doing `void test();` and `test(2);` is
guaranteed to result in a compile error (this also means that right now,
at least in all `.cpp` files, nobody is ever calling a void parameter
function with arguments and having their arguments be thrown away).
However, we may not be using C++ in the future, so I just want to lay
down the precedent that if a function takes in no arguments, you must
explicitly declare it as such.
I would've added `-Wstrict-prototypes`, but it produces an annoying
warning message saying it doesn't work in C++ mode if you're compiling
in C++ mode. So it can be added later.
2021-02-25 23:23:59 +01:00
|
|
|
void Screen::destroy(void)
|
2021-02-16 02:47:11 +01:00
|
|
|
{
|
2021-09-07 03:56:39 +02:00
|
|
|
/* Order matters! */
|
2022-12-01 07:30:16 +01:00
|
|
|
VVV_freefunc(SDL_DestroyRenderer, m_renderer);
|
|
|
|
VVV_freefunc(SDL_DestroyWindow, m_window);
|
2021-02-16 02:47:11 +01:00
|
|
|
}
|
|
|
|
|
2021-12-25 09:18:51 +01:00
|
|
|
void Screen::GetSettings(struct ScreenSettings* settings)
|
2020-12-22 01:34:16 +01:00
|
|
|
{
|
Store display index of window to settings
I have this annoying issue where the game will open on the wrong monitor
in fullscreen mode, because that monitor is considered to be display 0,
whereas the primary monitor I want is display 1.
To mitigate this somewhat, the game now stores the display index that it
was closed on, and will save it to settings. Then the next time the game
opens, it will open on that display index. This should work pretty well
as long as you aren't changing your monitor setup constantly.
Of course, none of this applies if your window manager is busted. For
example, on GNOME Wayland, which is what I use, in windowed mode the
game will always open on the monitor the cursor is on, and it won't even
be centered in the monitor. But it works fine if I use XWayland via
SDL_VIDEODRIVER=x11.
2023-03-21 08:23:42 +01:00
|
|
|
windowDisplay = SDL_GetWindowDisplayIndex(m_window);
|
|
|
|
if (windowDisplay < 0)
|
|
|
|
{
|
|
|
|
vlog_error("Error: could not get display index: %s", SDL_GetError());
|
|
|
|
windowDisplay = 0;
|
|
|
|
}
|
|
|
|
settings->windowDisplay = windowDisplay;
|
Persist windowed mode size through fullscreen mode
Previously, the game would not store the size of the window itself, and
would always call SDL_GetRendererOutputSize() (via
Screen::GetWindowSize()) to figure out the size of the window. The only
problem is, this would return the size of the whole monitor if the game
was in fullscreen mode. And the only place where the original windowed
mode size was stored would be in SDL itself, but that wouldn't persist
after the game was closed.
So, if you exited the game while in fullscreen mode, then your window
size would get set to the size of your monitor (1920 by 1080 in my
case). Then when you opened the game and toggled fullscreen off, it
would go back to the default window size, which is 640 by 480.
This is made worse, however, if you were in forced fullscreen mode when
you previously exited the game in windowed mode. In that case, the game
saves the size of 1920 by 1080, but doesn't save that you were in
fullscreen mode, so opening the game not in forced fullscreen mode would
result in you having a 1920 by 1080 window, but in windowed mode.
Meaning that not even fullscreening and unfullscreening would put the
game window back to normal size.
The solution, of course, is to just store the window size ourselves,
like any other screen setting, and only use GetWindowSize() if needed.
And just to make things clear, I've also renamed the GetWindowSize()
function to GetScreenSize(), because if it was named "window" it could
lead one to think that it would always return the size of the screen in
windowed mode, when in fact it returns the size of the screen whatever
mode it is in - fullscreen size if in fullscreen mode and window size if
in windowed mode.
And doing this also fixes the FIXME above Screen::isForcedFullscreen().
2023-03-21 04:59:37 +01:00
|
|
|
settings->windowWidth = windowWidth;
|
|
|
|
settings->windowHeight = windowHeight;
|
2020-12-22 01:34:16 +01:00
|
|
|
|
2021-09-07 03:56:39 +02:00
|
|
|
settings->fullscreen = !isWindowed;
|
|
|
|
settings->useVsync = vsync;
|
2021-12-23 04:54:59 +01:00
|
|
|
settings->scalingMode = scalingMode;
|
2021-09-07 03:56:39 +02:00
|
|
|
settings->linearFilter = isFiltered;
|
|
|
|
settings->badSignal = badSignalEffect;
|
2020-12-22 01:34:16 +01:00
|
|
|
}
|
|
|
|
|
Use `LoadImage` in `LoadIcon`
This de-duplicates the code, simplifying the codebase and reducing the
number of code paths that needs to be maintained. It also adds
robustness checks to LoadIcon that weren't there before (checking that
loading the file succeeded and that decoding the file also succeeded).
Now, you might think that loading the image with alpha will change
things in some way. But actually, I tested it, and I'm pretty sure it
doesn't. Since my window manager, i3, doesn't display icons, I've had to
resort to this hacky multi-liner
( https://unix.stackexchange.com/a/48866 ) to dump the icon to a PAM
file. I don't know what a PAM file is and all my various attempts to
convert it into something readable failed. But what I did instead was
just grab the icon of the game before this commit (on 2.3, just to be
extra sure), and `diff`ed it with the grabbed icon now, and they end up
being the exact same file. So there's literally no difference.
The only other consideration is that LoadImage needs to be exported,
since it's implemented in GraphicsResources.cpp. I just opted to
forward-declare it right before LoadIcon in Screen.cpp, since it's
really the only other time it's used. No need to create a new header
file for it or anything.
2021-12-25 10:27:33 +01:00
|
|
|
#ifdef __APPLE__
|
|
|
|
/* Apple doesn't like icons anymore... */
|
Explicitly declare void for all void parameter functions (#628)
Apparently in C, if you have `void test();`, it's completely okay to do
`test(2);`. The function will take in the argument, but just discard it
and throw it away. It's like a trash can, and a rude one at that. If you
declare it like `void test(void);`, this is prevented.
This is not a problem in C++ - doing `void test();` and `test(2);` is
guaranteed to result in a compile error (this also means that right now,
at least in all `.cpp` files, nobody is ever calling a void parameter
function with arguments and having their arguments be thrown away).
However, we may not be using C++ in the future, so I just want to lay
down the precedent that if a function takes in no arguments, you must
explicitly declare it as such.
I would've added `-Wstrict-prototypes`, but it produces an annoying
warning message saying it doesn't work in C++ mode if you're compiling
in C++ mode. So it can be added later.
2021-02-25 23:23:59 +01:00
|
|
|
void Screen::LoadIcon(void)
|
2020-11-01 04:25:27 +01:00
|
|
|
{
|
Use `LoadImage` in `LoadIcon`
This de-duplicates the code, simplifying the codebase and reducing the
number of code paths that needs to be maintained. It also adds
robustness checks to LoadIcon that weren't there before (checking that
loading the file succeeded and that decoding the file also succeeded).
Now, you might think that loading the image with alpha will change
things in some way. But actually, I tested it, and I'm pretty sure it
doesn't. Since my window manager, i3, doesn't display icons, I've had to
resort to this hacky multi-liner
( https://unix.stackexchange.com/a/48866 ) to dump the icon to a PAM
file. I don't know what a PAM file is and all my various attempts to
convert it into something readable failed. But what I did instead was
just grab the icon of the game before this commit (on 2.3, just to be
extra sure), and `diff`ed it with the grabbed icon now, and they end up
being the exact same file. So there's literally no difference.
The only other consideration is that LoadImage needs to be exported,
since it's implemented in GraphicsResources.cpp. I just opted to
forward-declare it right before LoadIcon in Screen.cpp, since it's
really the only other time it's used. No need to create a new header
file for it or anything.
2021-12-25 10:27:33 +01:00
|
|
|
|
|
|
|
}
|
|
|
|
#else
|
2023-01-07 19:28:07 +01:00
|
|
|
SDL_Surface* LoadImageSurface(const char* filename);
|
Use `LoadImage` in `LoadIcon`
This de-duplicates the code, simplifying the codebase and reducing the
number of code paths that needs to be maintained. It also adds
robustness checks to LoadIcon that weren't there before (checking that
loading the file succeeded and that decoding the file also succeeded).
Now, you might think that loading the image with alpha will change
things in some way. But actually, I tested it, and I'm pretty sure it
doesn't. Since my window manager, i3, doesn't display icons, I've had to
resort to this hacky multi-liner
( https://unix.stackexchange.com/a/48866 ) to dump the icon to a PAM
file. I don't know what a PAM file is and all my various attempts to
convert it into something readable failed. But what I did instead was
just grab the icon of the game before this commit (on 2.3, just to be
extra sure), and `diff`ed it with the grabbed icon now, and they end up
being the exact same file. So there's literally no difference.
The only other consideration is that LoadImage needs to be exported,
since it's implemented in GraphicsResources.cpp. I just opted to
forward-declare it right before LoadIcon in Screen.cpp, since it's
really the only other time it's used. No need to create a new header
file for it or anything.
2021-12-25 10:27:33 +01:00
|
|
|
|
|
|
|
void Screen::LoadIcon(void)
|
|
|
|
{
|
2023-01-07 19:28:07 +01:00
|
|
|
SDL_Surface* icon = LoadImageSurface("VVVVVV.png");
|
Use `LoadImage` in `LoadIcon`
This de-duplicates the code, simplifying the codebase and reducing the
number of code paths that needs to be maintained. It also adds
robustness checks to LoadIcon that weren't there before (checking that
loading the file succeeded and that decoding the file also succeeded).
Now, you might think that loading the image with alpha will change
things in some way. But actually, I tested it, and I'm pretty sure it
doesn't. Since my window manager, i3, doesn't display icons, I've had to
resort to this hacky multi-liner
( https://unix.stackexchange.com/a/48866 ) to dump the icon to a PAM
file. I don't know what a PAM file is and all my various attempts to
convert it into something readable failed. But what I did instead was
just grab the icon of the game before this commit (on 2.3, just to be
extra sure), and `diff`ed it with the grabbed icon now, and they end up
being the exact same file. So there's literally no difference.
The only other consideration is that LoadImage needs to be exported,
since it's implemented in GraphicsResources.cpp. I just opted to
forward-declare it right before LoadIcon in Screen.cpp, since it's
really the only other time it's used. No need to create a new header
file for it or anything.
2021-12-25 10:27:33 +01:00
|
|
|
if (icon == NULL)
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
2021-09-07 03:56:39 +02:00
|
|
|
SDL_SetWindowIcon(m_window, icon);
|
2022-12-01 07:30:16 +01:00
|
|
|
VVV_freefunc(SDL_FreeSurface, icon);
|
2020-11-01 04:25:27 +01:00
|
|
|
}
|
Use `LoadImage` in `LoadIcon`
This de-duplicates the code, simplifying the codebase and reducing the
number of code paths that needs to be maintained. It also adds
robustness checks to LoadIcon that weren't there before (checking that
loading the file succeeded and that decoding the file also succeeded).
Now, you might think that loading the image with alpha will change
things in some way. But actually, I tested it, and I'm pretty sure it
doesn't. Since my window manager, i3, doesn't display icons, I've had to
resort to this hacky multi-liner
( https://unix.stackexchange.com/a/48866 ) to dump the icon to a PAM
file. I don't know what a PAM file is and all my various attempts to
convert it into something readable failed. But what I did instead was
just grab the icon of the game before this commit (on 2.3, just to be
extra sure), and `diff`ed it with the grabbed icon now, and they end up
being the exact same file. So there's literally no difference.
The only other consideration is that LoadImage needs to be exported,
since it's implemented in GraphicsResources.cpp. I just opted to
forward-declare it right before LoadIcon in Screen.cpp, since it's
really the only other time it's used. No need to create a new header
file for it or anything.
2021-12-25 10:27:33 +01:00
|
|
|
#endif /* __APPLE__ */
|
2020-11-01 04:25:27 +01:00
|
|
|
|
2020-03-13 23:22:37 +01:00
|
|
|
void Screen::ResizeScreen(int x, int y)
|
2020-01-01 21:29:24 +01:00
|
|
|
{
|
Store display index of window to settings
I have this annoying issue where the game will open on the wrong monitor
in fullscreen mode, because that monitor is considered to be display 0,
whereas the primary monitor I want is display 1.
To mitigate this somewhat, the game now stores the display index that it
was closed on, and will save it to settings. Then the next time the game
opens, it will open on that display index. This should work pretty well
as long as you aren't changing your monitor setup constantly.
Of course, none of this applies if your window manager is busted. For
example, on GNOME Wayland, which is what I use, in windowed mode the
game will always open on the monitor the cursor is on, and it won't even
be centered in the monitor. But it works fine if I use XWayland via
SDL_VIDEODRIVER=x11.
2023-03-21 08:23:42 +01:00
|
|
|
windowDisplay = SDL_GetWindowDisplayIndex(m_window);
|
|
|
|
if (windowDisplay < 0)
|
|
|
|
{
|
|
|
|
vlog_error("Error: could not get display index: %s", SDL_GetError());
|
|
|
|
windowDisplay = 0;
|
|
|
|
}
|
|
|
|
|
2021-09-07 03:56:39 +02:00
|
|
|
if (x != -1 && y != -1)
|
|
|
|
{
|
|
|
|
// This is a user resize!
|
Persist windowed mode size through fullscreen mode
Previously, the game would not store the size of the window itself, and
would always call SDL_GetRendererOutputSize() (via
Screen::GetWindowSize()) to figure out the size of the window. The only
problem is, this would return the size of the whole monitor if the game
was in fullscreen mode. And the only place where the original windowed
mode size was stored would be in SDL itself, but that wouldn't persist
after the game was closed.
So, if you exited the game while in fullscreen mode, then your window
size would get set to the size of your monitor (1920 by 1080 in my
case). Then when you opened the game and toggled fullscreen off, it
would go back to the default window size, which is 640 by 480.
This is made worse, however, if you were in forced fullscreen mode when
you previously exited the game in windowed mode. In that case, the game
saves the size of 1920 by 1080, but doesn't save that you were in
fullscreen mode, so opening the game not in forced fullscreen mode would
result in you having a 1920 by 1080 window, but in windowed mode.
Meaning that not even fullscreening and unfullscreening would put the
game window back to normal size.
The solution, of course, is to just store the window size ourselves,
like any other screen setting, and only use GetWindowSize() if needed.
And just to make things clear, I've also renamed the GetWindowSize()
function to GetScreenSize(), because if it was named "window" it could
lead one to think that it would always return the size of the screen in
windowed mode, when in fact it returns the size of the screen whatever
mode it is in - fullscreen size if in fullscreen mode and window size if
in windowed mode.
And doing this also fixes the FIXME above Screen::isForcedFullscreen().
2023-03-21 04:59:37 +01:00
|
|
|
windowWidth = x;
|
|
|
|
windowHeight = y;
|
2021-09-07 03:56:39 +02:00
|
|
|
}
|
|
|
|
|
2021-12-26 07:55:55 +01:00
|
|
|
if (!isWindowed || isForcedFullscreen())
|
2021-09-07 03:56:39 +02:00
|
|
|
{
|
|
|
|
int result = SDL_SetWindowFullscreen(m_window, SDL_WINDOW_FULLSCREEN_DESKTOP);
|
2023-01-07 19:28:07 +01:00
|
|
|
recacheTextures();
|
2021-09-07 03:56:39 +02:00
|
|
|
if (result != 0)
|
|
|
|
{
|
|
|
|
vlog_error("Error: could not set the game to fullscreen mode: %s", SDL_GetError());
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
int result = SDL_SetWindowFullscreen(m_window, 0);
|
|
|
|
if (result != 0)
|
|
|
|
{
|
2023-08-23 03:03:10 +02:00
|
|
|
recacheTextures();
|
2021-09-07 03:56:39 +02:00
|
|
|
vlog_error("Error: could not set the game to windowed mode: %s", SDL_GetError());
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if (x != -1 && y != -1)
|
|
|
|
{
|
Persist windowed mode size through fullscreen mode
Previously, the game would not store the size of the window itself, and
would always call SDL_GetRendererOutputSize() (via
Screen::GetWindowSize()) to figure out the size of the window. The only
problem is, this would return the size of the whole monitor if the game
was in fullscreen mode. And the only place where the original windowed
mode size was stored would be in SDL itself, but that wouldn't persist
after the game was closed.
So, if you exited the game while in fullscreen mode, then your window
size would get set to the size of your monitor (1920 by 1080 in my
case). Then when you opened the game and toggled fullscreen off, it
would go back to the default window size, which is 640 by 480.
This is made worse, however, if you were in forced fullscreen mode when
you previously exited the game in windowed mode. In that case, the game
saves the size of 1920 by 1080, but doesn't save that you were in
fullscreen mode, so opening the game not in forced fullscreen mode would
result in you having a 1920 by 1080 window, but in windowed mode.
Meaning that not even fullscreening and unfullscreening would put the
game window back to normal size.
The solution, of course, is to just store the window size ourselves,
like any other screen setting, and only use GetWindowSize() if needed.
And just to make things clear, I've also renamed the GetWindowSize()
function to GetScreenSize(), because if it was named "window" it could
lead one to think that it would always return the size of the screen in
windowed mode, when in fact it returns the size of the screen whatever
mode it is in - fullscreen size if in fullscreen mode and window size if
in windowed mode.
And doing this also fixes the FIXME above Screen::isForcedFullscreen().
2023-03-21 04:59:37 +01:00
|
|
|
SDL_SetWindowSize(m_window, windowWidth, windowHeight);
|
Store display index of window to settings
I have this annoying issue where the game will open on the wrong monitor
in fullscreen mode, because that monitor is considered to be display 0,
whereas the primary monitor I want is display 1.
To mitigate this somewhat, the game now stores the display index that it
was closed on, and will save it to settings. Then the next time the game
opens, it will open on that display index. This should work pretty well
as long as you aren't changing your monitor setup constantly.
Of course, none of this applies if your window manager is busted. For
example, on GNOME Wayland, which is what I use, in windowed mode the
game will always open on the monitor the cursor is on, and it won't even
be centered in the monitor. But it works fine if I use XWayland via
SDL_VIDEODRIVER=x11.
2023-03-21 08:23:42 +01:00
|
|
|
SDL_SetWindowPosition(
|
|
|
|
m_window,
|
|
|
|
SDL_WINDOWPOS_CENTERED_DISPLAY(windowDisplay),
|
|
|
|
SDL_WINDOWPOS_CENTERED_DISPLAY(windowDisplay)
|
|
|
|
);
|
2021-09-07 03:56:39 +02:00
|
|
|
}
|
2023-08-23 03:03:10 +02:00
|
|
|
recacheTextures();
|
2021-09-07 03:56:39 +02:00
|
|
|
}
|
2020-01-01 21:29:24 +01:00
|
|
|
}
|
|
|
|
|
Explicitly declare void for all void parameter functions (#628)
Apparently in C, if you have `void test();`, it's completely okay to do
`test(2);`. The function will take in the argument, but just discard it
and throw it away. It's like a trash can, and a rude one at that. If you
declare it like `void test(void);`, this is prevented.
This is not a problem in C++ - doing `void test();` and `test(2);` is
guaranteed to result in a compile error (this also means that right now,
at least in all `.cpp` files, nobody is ever calling a void parameter
function with arguments and having their arguments be thrown away).
However, we may not be using C++ in the future, so I just want to lay
down the precedent that if a function takes in no arguments, you must
explicitly declare it as such.
I would've added `-Wstrict-prototypes`, but it produces an annoying
warning message saying it doesn't work in C++ mode if you're compiling
in C++ mode. So it can be added later.
2021-02-25 23:23:59 +01:00
|
|
|
void Screen::ResizeToNearestMultiple(void)
|
Add "resize to nearest" graphics option
If you want your game window to simply be exactly 320x240, or 640x480,
or 960x720 etc. then it's really annoying that there's no easy way to do
this (to clarify, this is different from integer mode, which controls
the size of the game INSIDE the window). The easiest way would be having
to close the game, go into unlock.vvv, and edit the window size
manually. VCE has a 1x/2x/3x/4x graphics option to solve this, although
it does not account for actual monitor size (those 1x/2x/3x/4x modes are
all you get, whether or not you have a monitor too small for some of
them or too big for any of them to be what you want).
I discussed this with flibit, and he said that VCE's approach (if it
accounted for monitor size) wouldn't work on high-retina displays or
high DPIs, because getting the actual multiplier to account for those
monitors is kind of a pain. So the next best thing would be to add an
option that resizes to the nearest perfect multiple of 320x240. That way
you could simply resize the window and let the game correct any
imperfect dimensions automatically.
2020-06-30 07:02:21 +02:00
|
|
|
{
|
2021-09-07 03:56:39 +02:00
|
|
|
int w, h;
|
Persist windowed mode size through fullscreen mode
Previously, the game would not store the size of the window itself, and
would always call SDL_GetRendererOutputSize() (via
Screen::GetWindowSize()) to figure out the size of the window. The only
problem is, this would return the size of the whole monitor if the game
was in fullscreen mode. And the only place where the original windowed
mode size was stored would be in SDL itself, but that wouldn't persist
after the game was closed.
So, if you exited the game while in fullscreen mode, then your window
size would get set to the size of your monitor (1920 by 1080 in my
case). Then when you opened the game and toggled fullscreen off, it
would go back to the default window size, which is 640 by 480.
This is made worse, however, if you were in forced fullscreen mode when
you previously exited the game in windowed mode. In that case, the game
saves the size of 1920 by 1080, but doesn't save that you were in
fullscreen mode, so opening the game not in forced fullscreen mode would
result in you having a 1920 by 1080 window, but in windowed mode.
Meaning that not even fullscreening and unfullscreening would put the
game window back to normal size.
The solution, of course, is to just store the window size ourselves,
like any other screen setting, and only use GetWindowSize() if needed.
And just to make things clear, I've also renamed the GetWindowSize()
function to GetScreenSize(), because if it was named "window" it could
lead one to think that it would always return the size of the screen in
windowed mode, when in fact it returns the size of the screen whatever
mode it is in - fullscreen size if in fullscreen mode and window size if
in windowed mode.
And doing this also fixes the FIXME above Screen::isForcedFullscreen().
2023-03-21 04:59:37 +01:00
|
|
|
GetScreenSize(&w, &h);
|
2021-09-07 03:56:39 +02:00
|
|
|
|
|
|
|
// Check aspect ratio first
|
|
|
|
bool using_width;
|
|
|
|
int usethisdimension, usethisratio;
|
|
|
|
|
|
|
|
if ((float) w / (float) h > 4.0 / 3.0)
|
|
|
|
{
|
|
|
|
// Width is bigger, so it's limited by height
|
|
|
|
usethisdimension = h;
|
2022-03-13 01:46:58 +01:00
|
|
|
usethisratio = SCREEN_HEIGHT_PIXELS;
|
2021-09-07 03:56:39 +02:00
|
|
|
using_width = false;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
// Height is bigger, so it's limited by width. Or we're exactly 4:3 already
|
|
|
|
usethisdimension = w;
|
2022-03-13 01:46:58 +01:00
|
|
|
usethisratio = SCREEN_WIDTH_PIXELS;
|
2021-09-07 03:56:39 +02:00
|
|
|
using_width = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
int floor = (usethisdimension / usethisratio) * usethisratio;
|
|
|
|
int ceiling = floor + usethisratio;
|
|
|
|
|
|
|
|
int final_dimension;
|
|
|
|
|
|
|
|
if (usethisdimension - floor < ceiling - usethisdimension)
|
|
|
|
{
|
|
|
|
// Floor is nearest
|
|
|
|
final_dimension = floor;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
// Ceiling is nearest. Or we're exactly on a multiple already
|
|
|
|
final_dimension = ceiling;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (final_dimension == 0)
|
|
|
|
{
|
|
|
|
// We're way too small!
|
2022-03-13 01:46:58 +01:00
|
|
|
ResizeScreen(SCREEN_WIDTH_PIXELS, SCREEN_HEIGHT_PIXELS);
|
2021-09-07 03:56:39 +02:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (using_width)
|
|
|
|
{
|
|
|
|
ResizeScreen(final_dimension, final_dimension / 4 * 3);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
ResizeScreen(final_dimension * 4 / 3, final_dimension);
|
|
|
|
}
|
Add "resize to nearest" graphics option
If you want your game window to simply be exactly 320x240, or 640x480,
or 960x720 etc. then it's really annoying that there's no easy way to do
this (to clarify, this is different from integer mode, which controls
the size of the game INSIDE the window). The easiest way would be having
to close the game, go into unlock.vvv, and edit the window size
manually. VCE has a 1x/2x/3x/4x graphics option to solve this, although
it does not account for actual monitor size (those 1x/2x/3x/4x modes are
all you get, whether or not you have a monitor too small for some of
them or too big for any of them to be what you want).
I discussed this with flibit, and he said that VCE's approach (if it
accounted for monitor size) wouldn't work on high-retina displays or
high DPIs, because getting the actual multiplier to account for those
monitors is kind of a pain. So the next best thing would be to add an
option that resizes to the nearest perfect multiple of 320x240. That way
you could simply resize the window and let the game correct any
imperfect dimensions automatically.
2020-06-30 07:02:21 +02:00
|
|
|
}
|
|
|
|
|
Persist windowed mode size through fullscreen mode
Previously, the game would not store the size of the window itself, and
would always call SDL_GetRendererOutputSize() (via
Screen::GetWindowSize()) to figure out the size of the window. The only
problem is, this would return the size of the whole monitor if the game
was in fullscreen mode. And the only place where the original windowed
mode size was stored would be in SDL itself, but that wouldn't persist
after the game was closed.
So, if you exited the game while in fullscreen mode, then your window
size would get set to the size of your monitor (1920 by 1080 in my
case). Then when you opened the game and toggled fullscreen off, it
would go back to the default window size, which is 640 by 480.
This is made worse, however, if you were in forced fullscreen mode when
you previously exited the game in windowed mode. In that case, the game
saves the size of 1920 by 1080, but doesn't save that you were in
fullscreen mode, so opening the game not in forced fullscreen mode would
result in you having a 1920 by 1080 window, but in windowed mode.
Meaning that not even fullscreening and unfullscreening would put the
game window back to normal size.
The solution, of course, is to just store the window size ourselves,
like any other screen setting, and only use GetWindowSize() if needed.
And just to make things clear, I've also renamed the GetWindowSize()
function to GetScreenSize(), because if it was named "window" it could
lead one to think that it would always return the size of the screen in
windowed mode, when in fact it returns the size of the screen whatever
mode it is in - fullscreen size if in fullscreen mode and window size if
in windowed mode.
And doing this also fixes the FIXME above Screen::isForcedFullscreen().
2023-03-21 04:59:37 +01:00
|
|
|
void Screen::GetScreenSize(int* x, int* y)
|
2020-01-01 21:29:24 +01:00
|
|
|
{
|
2022-03-13 01:47:23 +01:00
|
|
|
if (SDL_GetRendererOutputSize(m_renderer, x, y) != 0)
|
|
|
|
{
|
|
|
|
vlog_error("Could not get window size: %s", SDL_GetError());
|
|
|
|
/* Initialize to safe defaults */
|
|
|
|
*x = SCREEN_WIDTH_PIXELS;
|
|
|
|
*y = SCREEN_HEIGHT_PIXELS;
|
|
|
|
}
|
2020-01-01 21:29:24 +01:00
|
|
|
}
|
|
|
|
|
Always update scaling before rendering
This fixes the following bug that only occurs on Wayland: If the game is
configured to be fullscreened and in stretch mode, on startup, it won't
be in stretch mode. It will appear to be in letterbox mode, but the game
still thinks it's in stretch mode.
This is because during the ResizeScreen() call on startup, for whatever
reason, the window size will be reported to be the default size (640 by
480) instead of the screen resolution of the monitor, as one would
expect from being in fullscreen. It seems like when the game queries the
window size, the window isn't actually in fullscreen at that time, even
though this is after fullscreen has been set to true.
To fix this, I decided to always update the logical size before
SDL_RenderPresent() is called. To make this neater, I put the scaling
code in its own function named UpdateScaling().
This bug has existed since 2.3 and does not occur on X11. I tested this
on GNOME Wayland, and for testing it on X11, I used Openbox in a Xephyr
session while running VVVVVV with SDL_VIDEODRIVER=x11.
2023-03-21 04:31:31 +01:00
|
|
|
void Screen::UpdateScaling(void)
|
|
|
|
{
|
|
|
|
int width;
|
|
|
|
int height;
|
|
|
|
if (scalingMode == SCALING_STRETCH)
|
|
|
|
{
|
Persist windowed mode size through fullscreen mode
Previously, the game would not store the size of the window itself, and
would always call SDL_GetRendererOutputSize() (via
Screen::GetWindowSize()) to figure out the size of the window. The only
problem is, this would return the size of the whole monitor if the game
was in fullscreen mode. And the only place where the original windowed
mode size was stored would be in SDL itself, but that wouldn't persist
after the game was closed.
So, if you exited the game while in fullscreen mode, then your window
size would get set to the size of your monitor (1920 by 1080 in my
case). Then when you opened the game and toggled fullscreen off, it
would go back to the default window size, which is 640 by 480.
This is made worse, however, if you were in forced fullscreen mode when
you previously exited the game in windowed mode. In that case, the game
saves the size of 1920 by 1080, but doesn't save that you were in
fullscreen mode, so opening the game not in forced fullscreen mode would
result in you having a 1920 by 1080 window, but in windowed mode.
Meaning that not even fullscreening and unfullscreening would put the
game window back to normal size.
The solution, of course, is to just store the window size ourselves,
like any other screen setting, and only use GetWindowSize() if needed.
And just to make things clear, I've also renamed the GetWindowSize()
function to GetScreenSize(), because if it was named "window" it could
lead one to think that it would always return the size of the screen in
windowed mode, when in fact it returns the size of the screen whatever
mode it is in - fullscreen size if in fullscreen mode and window size if
in windowed mode.
And doing this also fixes the FIXME above Screen::isForcedFullscreen().
2023-03-21 04:59:37 +01:00
|
|
|
GetScreenSize(&width, &height);
|
Always update scaling before rendering
This fixes the following bug that only occurs on Wayland: If the game is
configured to be fullscreened and in stretch mode, on startup, it won't
be in stretch mode. It will appear to be in letterbox mode, but the game
still thinks it's in stretch mode.
This is because during the ResizeScreen() call on startup, for whatever
reason, the window size will be reported to be the default size (640 by
480) instead of the screen resolution of the monitor, as one would
expect from being in fullscreen. It seems like when the game queries the
window size, the window isn't actually in fullscreen at that time, even
though this is after fullscreen has been set to true.
To fix this, I decided to always update the logical size before
SDL_RenderPresent() is called. To make this neater, I put the scaling
code in its own function named UpdateScaling().
This bug has existed since 2.3 and does not occur on X11. I tested this
on GNOME Wayland, and for testing it on X11, I used Openbox in a Xephyr
session while running VVVVVV with SDL_VIDEODRIVER=x11.
2023-03-21 04:31:31 +01:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
width = SCREEN_WIDTH_PIXELS;
|
|
|
|
height = SCREEN_HEIGHT_PIXELS;
|
|
|
|
}
|
|
|
|
int result = SDL_RenderSetLogicalSize(m_renderer, width, height);
|
|
|
|
if (result != 0)
|
|
|
|
{
|
|
|
|
vlog_error("Error: could not set logical size: %s", SDL_GetError());
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
result = SDL_RenderSetIntegerScale(m_renderer, (SDL_bool) (scalingMode == SCALING_INTEGER));
|
|
|
|
if (result != 0)
|
|
|
|
{
|
|
|
|
vlog_error("Error: could not set scale: %s", SDL_GetError());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-03-18 23:24:14 +01:00
|
|
|
void Screen::RenderPresent(void)
|
2020-01-01 21:29:24 +01:00
|
|
|
{
|
Always update scaling before rendering
This fixes the following bug that only occurs on Wayland: If the game is
configured to be fullscreened and in stretch mode, on startup, it won't
be in stretch mode. It will appear to be in letterbox mode, but the game
still thinks it's in stretch mode.
This is because during the ResizeScreen() call on startup, for whatever
reason, the window size will be reported to be the default size (640 by
480) instead of the screen resolution of the monitor, as one would
expect from being in fullscreen. It seems like when the game queries the
window size, the window isn't actually in fullscreen at that time, even
though this is after fullscreen has been set to true.
To fix this, I decided to always update the logical size before
SDL_RenderPresent() is called. To make this neater, I put the scaling
code in its own function named UpdateScaling().
This bug has existed since 2.3 and does not occur on X11. I tested this
on GNOME Wayland, and for testing it on X11, I used Openbox in a Xephyr
session while running VVVVVV with SDL_VIDEODRIVER=x11.
2023-03-21 04:31:31 +01:00
|
|
|
/* In certain cases, the window size might mismatch with the logical size.
|
|
|
|
* So it's better to just always call this. */
|
|
|
|
UpdateScaling();
|
|
|
|
|
2021-09-07 03:56:39 +02:00
|
|
|
SDL_RenderPresent(m_renderer);
|
2023-01-07 19:28:07 +01:00
|
|
|
graphics.clear();
|
2020-01-01 21:29:24 +01:00
|
|
|
}
|
|
|
|
|
Explicitly declare void for all void parameter functions (#628)
Apparently in C, if you have `void test();`, it's completely okay to do
`test(2);`. The function will take in the argument, but just discard it
and throw it away. It's like a trash can, and a rude one at that. If you
declare it like `void test(void);`, this is prevented.
This is not a problem in C++ - doing `void test();` and `test(2);` is
guaranteed to result in a compile error (this also means that right now,
at least in all `.cpp` files, nobody is ever calling a void parameter
function with arguments and having their arguments be thrown away).
However, we may not be using C++ in the future, so I just want to lay
down the precedent that if a function takes in no arguments, you must
explicitly declare it as such.
I would've added `-Wstrict-prototypes`, but it produces an annoying
warning message saying it doesn't work in C++ mode if you're compiling
in C++ mode. So it can be added later.
2021-02-25 23:23:59 +01:00
|
|
|
void Screen::toggleFullScreen(void)
|
2020-01-01 21:29:24 +01:00
|
|
|
{
|
2021-09-07 03:56:39 +02:00
|
|
|
isWindowed = !isWindowed;
|
Persist windowed mode size through fullscreen mode
Previously, the game would not store the size of the window itself, and
would always call SDL_GetRendererOutputSize() (via
Screen::GetWindowSize()) to figure out the size of the window. The only
problem is, this would return the size of the whole monitor if the game
was in fullscreen mode. And the only place where the original windowed
mode size was stored would be in SDL itself, but that wouldn't persist
after the game was closed.
So, if you exited the game while in fullscreen mode, then your window
size would get set to the size of your monitor (1920 by 1080 in my
case). Then when you opened the game and toggled fullscreen off, it
would go back to the default window size, which is 640 by 480.
This is made worse, however, if you were in forced fullscreen mode when
you previously exited the game in windowed mode. In that case, the game
saves the size of 1920 by 1080, but doesn't save that you were in
fullscreen mode, so opening the game not in forced fullscreen mode would
result in you having a 1920 by 1080 window, but in windowed mode.
Meaning that not even fullscreening and unfullscreening would put the
game window back to normal size.
The solution, of course, is to just store the window size ourselves,
like any other screen setting, and only use GetWindowSize() if needed.
And just to make things clear, I've also renamed the GetWindowSize()
function to GetScreenSize(), because if it was named "window" it could
lead one to think that it would always return the size of the screen in
windowed mode, when in fact it returns the size of the screen whatever
mode it is in - fullscreen size if in fullscreen mode and window size if
in windowed mode.
And doing this also fixes the FIXME above Screen::isForcedFullscreen().
2023-03-21 04:59:37 +01:00
|
|
|
ResizeScreen(windowWidth, windowHeight);
|
2021-09-07 03:56:39 +02:00
|
|
|
|
|
|
|
if (game.currentmenuname == Menu::graphicoptions)
|
|
|
|
{
|
|
|
|
/* Recreate menu to update "resize to nearest" */
|
|
|
|
game.createmenu(game.currentmenuname, true);
|
|
|
|
}
|
2020-01-01 21:29:24 +01:00
|
|
|
}
|
|
|
|
|
2021-12-23 04:54:59 +01:00
|
|
|
void Screen::toggleScalingMode(void)
|
2020-01-01 21:29:24 +01:00
|
|
|
{
|
2021-12-26 08:05:14 +01:00
|
|
|
scalingMode = (scalingMode + 1) % NUM_SCALING_MODES;
|
Always update scaling before rendering
This fixes the following bug that only occurs on Wayland: If the game is
configured to be fullscreened and in stretch mode, on startup, it won't
be in stretch mode. It will appear to be in letterbox mode, but the game
still thinks it's in stretch mode.
This is because during the ResizeScreen() call on startup, for whatever
reason, the window size will be reported to be the default size (640 by
480) instead of the screen resolution of the monitor, as one would
expect from being in fullscreen. It seems like when the game queries the
window size, the window isn't actually in fullscreen at that time, even
though this is after fullscreen has been set to true.
To fix this, I decided to always update the logical size before
SDL_RenderPresent() is called. To make this neater, I put the scaling
code in its own function named UpdateScaling().
This bug has existed since 2.3 and does not occur on X11. I tested this
on GNOME Wayland, and for testing it on X11, I used Openbox in a Xephyr
session while running VVVVVV with SDL_VIDEODRIVER=x11.
2023-03-21 04:31:31 +01:00
|
|
|
UpdateScaling();
|
2020-01-01 21:29:24 +01:00
|
|
|
}
|
|
|
|
|
Explicitly declare void for all void parameter functions (#628)
Apparently in C, if you have `void test();`, it's completely okay to do
`test(2);`. The function will take in the argument, but just discard it
and throw it away. It's like a trash can, and a rude one at that. If you
declare it like `void test(void);`, this is prevented.
This is not a problem in C++ - doing `void test();` and `test(2);` is
guaranteed to result in a compile error (this also means that right now,
at least in all `.cpp` files, nobody is ever calling a void parameter
function with arguments and having their arguments be thrown away).
However, we may not be using C++ in the future, so I just want to lay
down the precedent that if a function takes in no arguments, you must
explicitly declare it as such.
I would've added `-Wstrict-prototypes`, but it produces an annoying
warning message saying it doesn't work in C++ mode if you're compiling
in C++ mode. So it can be added later.
2021-02-25 23:23:59 +01:00
|
|
|
void Screen::toggleLinearFilter(void)
|
2020-01-01 21:29:24 +01:00
|
|
|
{
|
2021-09-07 03:56:39 +02:00
|
|
|
isFiltered = !isFiltered;
|
|
|
|
SDL_SetHintWithPriority(
|
|
|
|
SDL_HINT_RENDER_SCALE_QUALITY,
|
|
|
|
isFiltered ? "linear" : "nearest",
|
|
|
|
SDL_HINT_OVERRIDE
|
|
|
|
);
|
2023-01-07 19:28:07 +01:00
|
|
|
SDL_DestroyTexture(graphics.gameTexture);
|
|
|
|
graphics.gameTexture = SDL_CreateTexture(
|
2021-09-07 03:56:39 +02:00
|
|
|
m_renderer,
|
|
|
|
SDL_PIXELFORMAT_ARGB8888,
|
2023-01-07 19:28:07 +01:00
|
|
|
SDL_TEXTUREACCESS_TARGET,
|
2022-03-13 01:46:58 +01:00
|
|
|
SCREEN_WIDTH_PIXELS,
|
|
|
|
SCREEN_HEIGHT_PIXELS
|
2021-09-07 03:56:39 +02:00
|
|
|
);
|
2023-01-07 19:28:07 +01:00
|
|
|
|
|
|
|
if (graphics.gameTexture == NULL)
|
|
|
|
{
|
|
|
|
vlog_error("Could not create game texture: %s", SDL_GetError());
|
|
|
|
return;
|
|
|
|
}
|
2020-01-01 21:29:24 +01:00
|
|
|
}
|
2020-07-02 06:19:40 +02:00
|
|
|
|
2021-09-15 05:23:22 +02:00
|
|
|
void Screen::toggleVSync(void)
|
2020-07-02 06:19:40 +02:00
|
|
|
{
|
2021-09-15 05:23:22 +02:00
|
|
|
vsync = !vsync;
|
|
|
|
SDL_RenderSetVSync(m_renderer, (int) vsync);
|
2023-01-07 19:28:07 +01:00
|
|
|
|
|
|
|
recacheTextures();
|
|
|
|
}
|
|
|
|
|
|
|
|
void Screen::recacheTextures(void)
|
|
|
|
{
|
|
|
|
// Fix for d3d9, which clears target textures sometimes (ex. toggling vsync, switching fullscreen, etc...)
|
|
|
|
|
|
|
|
// Signal cached textures to be redrawn fully
|
|
|
|
graphics.backgrounddrawn = false;
|
|
|
|
graphics.foregrounddrawn = false;
|
|
|
|
graphics.towerbg.tdrawback = true;
|
|
|
|
graphics.titlebg.tdrawback = true;
|
|
|
|
|
|
|
|
if (game.ingame_titlemode)
|
|
|
|
{
|
|
|
|
// Redraw the cached gameplay texture if we're in the in-game menu.
|
|
|
|
// Additionally, reset alpha so things don't jitter when re-entering gameplay.
|
|
|
|
float oldAlpha = graphics.alpha;
|
|
|
|
graphics.alpha = 0;
|
|
|
|
gamerender();
|
|
|
|
graphics.alpha = oldAlpha;
|
|
|
|
}
|
2020-07-02 06:19:40 +02:00
|
|
|
}
|
2021-12-26 07:55:55 +01:00
|
|
|
|
|
|
|
bool Screen::isForcedFullscreen(void)
|
|
|
|
{
|
|
|
|
/* This is just a check to see if we're on a desktop or tenfoot setup.
|
|
|
|
* If you're working on a tenfoot-only build, add a def that always
|
|
|
|
* returns true!
|
|
|
|
*/
|
|
|
|
return SDL_GetHintBoolean("SteamTenfoot", SDL_FALSE);
|
|
|
|
}
|