Add "Force Integer Scaling" option for fullscreen

Also:
recreate the window when enabling resizable window, same workaround I applied to my mod for jacob1/The-Powder-Toy#24
recreate the window when toggling fullscreen, to work around some bugs where the window is sized incorrectly or the mouse position doesn't match where the cursor is
Don't capture mouse cursor when this is a debug build
This commit is contained in:
jacob1 2019-02-18 22:18:29 -05:00
parent a979917744
commit 0c6ce20880
9 changed files with 115 additions and 42 deletions

View File

@ -66,6 +66,7 @@ SDL_Texture * sdl_texture;
int scale = 1;
bool fullscreen = false;
bool altFullscreen = false;
bool forceIntegerScaling = true;
bool resizable = false;
@ -91,6 +92,10 @@ void LoadWindowPosition()
int borderTop, borderLeft;
SDL_GetWindowBordersSize(sdl_window, &borderTop, &borderLeft, nullptr, nullptr);
// Sometimes (Windows), the border size may not be reported for 200+ frames
// So just have a default of 5 to ensure the window doesn't get stuck where it can't be moved
if (borderTop == 0)
borderTop = 5;
if (savedWindowX + borderLeft > 0 && savedWindowX + borderLeft < desktopWidth
&& savedWindowY + borderTop > 0 && savedWindowY + borderTop < desktopHeight)
@ -139,6 +144,7 @@ void blit(pixel * vid)
}
#endif
void RecreateWindow();
int SDLOpen()
{
if (SDL_Init(SDL_INIT_VIDEO) < 0)
@ -147,23 +153,7 @@ int SDLOpen()
return 1;
}
unsigned int flags = 0;
if (fullscreen)
flags = altFullscreen ? SDL_WINDOW_FULLSCREEN : SDL_WINDOW_FULLSCREEN_DESKTOP;
if (resizable)
flags |= SDL_WINDOW_RESIZABLE;
sdl_window = SDL_CreateWindow("The Powder Toy", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, WINDOWW * scale, WINDOWH * scale,
flags);
sdl_renderer = SDL_CreateRenderer(sdl_window, -1, 0);
SDL_RenderSetLogicalSize(sdl_renderer, WINDOWW, WINDOWH);
//Uncomment this to force fullscreen to an integer resolution
//SDL_RenderSetIntegerScale(sdl_renderer, SDL_TRUE);
sdl_texture = SDL_CreateTexture(sdl_renderer, SDL_PIXELFORMAT_ARGB8888, SDL_TEXTUREACCESS_STREAMING, WINDOWW, WINDOWH);
if (fullscreen)
SDL_RaiseWindow(sdl_window);
//Uncomment this to enable resizing
//SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, "linear");
//SDL_SetWindowResizable(sdl_window, SDL_TRUE);
RecreateWindow();
int displayIndex = SDL_GetWindowDisplayIndex(sdl_window);
if (displayIndex >= 0)
@ -203,13 +193,29 @@ int SDLOpen()
return 0;
}
void SDLSetScreen(int scale_, bool resizable_, bool fullscreen_, bool altFullscreen_)
void SDLSetScreen(int scale_, bool resizable_, bool fullscreen_, bool altFullscreen_, bool forceIntegerScaling_)
{
// bool changingScale = scale != scale_;
bool changingFullscreen = fullscreen_ != fullscreen;
bool changingResizable = resizable != resizable_;
scale = scale_;
fullscreen = fullscreen_;
altFullscreen = altFullscreen_;
resizable = resizable_;
forceIntegerScaling = forceIntegerScaling_;
// Recreate the window when toggling fullscreen, due to occasional issues
// Also recreate it when enabling resizable windows, to fix bugs on windows,
// see https://github.com/jacob1/The-Powder-Toy/issues/24
if (changingFullscreen || (changingResizable && resizable && !fullscreen))
{
RecreateWindow();
return;
}
if (changingResizable)
SDL_RestoreWindow(sdl_window);
SDL_SetWindowSize(sdl_window, WINDOWW * scale, WINDOWH * scale);
SDL_RenderSetIntegerScale(sdl_renderer, forceIntegerScaling && fullscreen ? SDL_TRUE : SDL_FALSE);
unsigned int flags = 0;
if (fullscreen)
flags = altFullscreen ? SDL_WINDOW_FULLSCREEN : SDL_WINDOW_FULLSCREEN_DESKTOP;
@ -219,6 +225,40 @@ void SDLSetScreen(int scale_, bool resizable_, bool fullscreen_, bool altFullscr
SDL_SetWindowResizable(sdl_window, resizable ? SDL_TRUE : SDL_FALSE);
}
void RecreateWindow()
{
unsigned int flags = 0;
if (fullscreen)
flags = altFullscreen ? SDL_WINDOW_FULLSCREEN : SDL_WINDOW_FULLSCREEN_DESKTOP;
if (resizable && !fullscreen)
flags |= SDL_WINDOW_RESIZABLE;
if (sdl_texture)
SDL_DestroyTexture(sdl_texture);
if (sdl_renderer)
SDL_DestroyRenderer(sdl_renderer);
if (sdl_window)
{
SaveWindowPosition();
SDL_DestroyWindow(sdl_window);
}
sdl_window = SDL_CreateWindow("The Powder Toy", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, WINDOWW * scale, WINDOWH * scale,
flags);
sdl_renderer = SDL_CreateRenderer(sdl_window, -1, 0);
SDL_RenderSetLogicalSize(sdl_renderer, WINDOWW, WINDOWH);
if (forceIntegerScaling && fullscreen)
SDL_RenderSetIntegerScale(sdl_renderer, SDL_TRUE);
sdl_texture = SDL_CreateTexture(sdl_renderer, SDL_PIXELFORMAT_ARGB8888, SDL_TEXTUREACCESS_STREAMING, WINDOWW, WINDOWH);
SDL_RaiseWindow(sdl_window);
//Uncomment this to enable resizing
//SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, "linear");
//SDL_SetWindowResizable(sdl_window, SDL_TRUE);
if (!Client::Ref().IsFirstRun())
LoadWindowPosition();
}
unsigned int GetTicks()
{
return SDL_GetTicks();
@ -354,7 +394,9 @@ void EventProcess(SDL_Event event)
engine->onMouseClick(event.motion.x, event.motion.y, mouseButton);
mouseDown = true;
#if !defined(NDEBUG) && !defined(DEBUG)
SDL_CaptureMouse(SDL_TRUE);
#endif
break;
case SDL_MOUSEBUTTONUP:
// if mouse hasn't moved yet, sdl will send 0,0. We don't want that
@ -367,7 +409,9 @@ void EventProcess(SDL_Event event)
engine->onMouseUnclick(mousex, mousey, mouseButton);
mouseDown = false;
#if !defined(NDEBUG) && !defined(DEBUG)
SDL_CaptureMouse(SDL_FALSE);
#endif
break;
case SDL_WINDOWEVENT:
{
@ -447,10 +491,12 @@ void EngineProcess()
engine->Tick();
engine->Draw();
if (scale != engine->Scale || fullscreen != engine->Fullscreen
|| altFullscreen != engine->GetAltFullscreen() || resizable != engine->GetResizable())
if (scale != engine->Scale || fullscreen != engine->Fullscreen ||
altFullscreen != engine->GetAltFullscreen() ||
forceIntegerScaling != engine->GetForceIntegerScaling() || resizable != engine->GetResizable())
{
SDLSetScreen(engine->Scale, engine->GetResizable(), engine->Fullscreen, engine->GetAltFullscreen());
SDLSetScreen(engine->Scale, engine->GetResizable(), engine->Fullscreen, engine->GetAltFullscreen(),
engine->GetForceIntegerScaling());
}
#ifdef OGLI
@ -591,6 +637,7 @@ int main(int argc, char * argv[])
resizable = Client::Ref().GetPrefBool("Resizable", false);
fullscreen = Client::Ref().GetPrefBool("Fullscreen", false);
altFullscreen = Client::Ref().GetPrefBool("AltFullscreen", false);
forceIntegerScaling = Client::Ref().GetPrefBool("ForceIntegerScaling", true);
if(arguments["kiosk"] == "true")
@ -639,8 +686,6 @@ int main(int argc, char * argv[])
SDL_SetWindowSize(sdl_window, WINDOWW * 2, WINDOWH * 2);
showDoubleScreenDialog = true;
}
if (!Client::Ref().IsFirstRun())
LoadWindowPosition();
#ifdef OGLI
SDL_GL_SetAttribute (SDL_GL_DOUBLEBUFFER, 1);
@ -659,6 +704,7 @@ int main(int argc, char * argv[])
ui::Engine::Ref().SetResizable(resizable);
ui::Engine::Ref().Fullscreen = fullscreen;
ui::Engine::Ref().SetAltFullscreen(altFullscreen);
ui::Engine::Ref().SetForceIntegerScaling(forceIntegerScaling);
engine = &ui::Engine::Ref();
engine->SetMaxSize(desktopWidth, desktopHeight);

View File

@ -772,41 +772,25 @@ void GameSave::readOPS(char * data, int dataLength)
if (bson_iterator_type(&iter) == BSON_OBJECT)
{
int major = INT_MAX, minor = INT_MAX;
#ifdef RENDERER
int renderMajor = INT_MAX, renderMinor = INT_MAX;
#endif
bson_iterator subiter;
bson_iterator_subiterator(&iter, &subiter);
while (bson_iterator_next(&subiter))
{
if (bson_iterator_type(&subiter) == BSON_INT)
{
#ifdef RENDERER
if (!strcmp(bson_iterator_key(&subiter), "rendermajor"))
renderMajor = bson_iterator_int(&subiter);
else if (!strcmp(bson_iterator_key(&subiter), "renderminor"))
renderMinor = bson_iterator_int(&subiter);
#else
if (!strcmp(bson_iterator_key(&subiter), "major"))
major = bson_iterator_int(&subiter);
else if (!strcmp(bson_iterator_key(&subiter), "minor"))
minor = bson_iterator_int(&subiter);
#endif
}
}
#ifdef RENDERER
if (renderMajor > SAVE_VERSION || (renderMajor == SAVE_VERSION && renderMinor > MINOR_VERSION))
#elif defined(SNAPSHOT) || defined(DEBUG)
#if defined(SNAPSHOT) || defined(DEBUG)
if (major > FUTURE_SAVE_VERSION || (major == FUTURE_SAVE_VERSION && minor > FUTURE_MINOR_VERSION))
#else
if (major > SAVE_VERSION || (major == SAVE_VERSION && minor > MINOR_VERSION))
#endif
{
#ifdef RENDERER
String errorMessage = String::Build("Save from a newer version: Requires render version ", renderMajor, ".", renderMinor);
#else
String errorMessage = String::Build("Save from a newer version: Requires version ", major, ".", minor);
#endif
throw ParseException(ParseException::WrongVersion, errorMessage);
}
#if defined(SNAPSHOT) || defined(DEBUG)

View File

@ -48,6 +48,8 @@ namespace ui
inline bool GetFullscreen() { return Fullscreen; }
void SetAltFullscreen(bool altFullscreen) { this->altFullscreen = altFullscreen; }
inline bool GetAltFullscreen() { return altFullscreen; }
void SetForceIntegerScaling(bool forceIntegerScaling) { this->forceIntegerScaling = forceIntegerScaling; }
inline bool GetForceIntegerScaling() { return forceIntegerScaling; }
void SetScale(int scale) { Scale = scale; }
inline int GetScale() { return Scale; }
void SetResizable(bool resizable) { this->resizable = resizable; }
@ -84,6 +86,7 @@ namespace ui
unsigned int FrameIndex;
private:
bool altFullscreen;
bool forceIntegerScaling = true;
bool resizable;
float dt;

View File

@ -60,6 +60,11 @@ void OptionsController::SetAltFullscreen(bool altFullscreen)
model->SetAltFullscreen(altFullscreen);
}
void OptionsController::SetForceIntegerScaling(bool forceIntegerScaling)
{
model->SetForceIntegerScaling(forceIntegerScaling);
}
void OptionsController::SetShowAvatars(bool showAvatars)
{
model->SetShowAvatars(showAvatars);

View File

@ -26,6 +26,7 @@ public:
void SetEdgeMode(int edgeMode);
void SetFullscreen(bool fullscreen);
void SetAltFullscreen(bool altFullscreen);
void SetForceIntegerScaling(bool forceIntegerScaling);
void SetScale(int scale);
void SetResizable(bool resizable);
void SetFastQuit(bool fastquit);

View File

@ -137,6 +137,18 @@ void OptionsModel::SetAltFullscreen(bool altFullscreen)
notifySettingsChanged();
}
bool OptionsModel::GetForceIntegerScaling()
{
return ui::Engine::Ref().GetForceIntegerScaling();
}
void OptionsModel::SetForceIntegerScaling(bool forceIntegerScaling)
{
ui::Engine::Ref().SetForceIntegerScaling(forceIntegerScaling);
Client::Ref().SetPref("ForceIntegerScaling", forceIntegerScaling);
notifySettingsChanged();
}
bool OptionsModel::GetFastQuit()
{
return ui::Engine::Ref().GetFastQuit();

View File

@ -39,6 +39,8 @@ public:
void SetFullscreen(bool fullscreen);
bool GetAltFullscreen();
void SetAltFullscreen(bool oldFullscreen);
bool GetForceIntegerScaling();
void SetForceIntegerScaling(bool forceIntegerScaling);
bool GetFastQuit();
void SetFastQuit(bool fastquit);
virtual ~OptionsModel();

View File

@ -17,7 +17,7 @@
#include "gui/dialogues/ErrorMessage.h"
OptionsView::OptionsView():
ui::Window(ui::Point(-1, -1), ui::Point(300, 369)){
ui::Window(ui::Point(-1, -1), ui::Point(300, 389)){
ui::Label * tempLabel = new ui::Label(ui::Point(4, 5), ui::Point(Size.X-8, 14), "Simulation Options");
tempLabel->SetTextColour(style::Colour::InformationTitle);
@ -227,6 +227,24 @@ OptionsView::OptionsView():
AddComponent(tempLabel);
AddComponent(altFullscreen);
class ForceIntegerScalingAction: public ui::CheckboxAction
{
OptionsView * v;
public:
ForceIntegerScalingAction(OptionsView * v_) { v = v_; }
virtual void ActionCallback(ui::Checkbox * sender)
{
v->c->SetForceIntegerScaling(sender->GetChecked());
}
};
forceIntegerScaling = new ui::Checkbox(ui::Point(23, altFullscreen->Position.Y + 20), ui::Point(Size.X-6, 16), "Force Integer Scaling", "");
forceIntegerScaling->SetActionCallback(new ForceIntegerScalingAction(this));
tempLabel = new ui::Label(ui::Point(altFullscreen->Position.X+Graphics::textwidth(forceIntegerScaling->GetText().c_str())+20, forceIntegerScaling->Position.Y), ui::Point(Size.X-28, 16), "\bg- less blurry");
tempLabel->Appearance.HorizontalAlign = ui::Appearance::AlignLeft; tempLabel->Appearance.VerticalAlign = ui::Appearance::AlignMiddle;
AddComponent(tempLabel);
AddComponent(forceIntegerScaling);
class FastQuitAction: public ui::CheckboxAction
{
@ -236,7 +254,7 @@ OptionsView::OptionsView():
virtual void ActionCallback(ui::Checkbox * sender){ v->c->SetFastQuit(sender->GetChecked()); }
};
fastquit = new ui::Checkbox(ui::Point(8, altFullscreen->Position.Y + 20), ui::Point(Size.X-6, 16), "Fast Quit", "");
fastquit = new ui::Checkbox(ui::Point(8, forceIntegerScaling->Position.Y + 20), ui::Point(Size.X-6, 16), "Fast Quit", "");
fastquit->SetActionCallback(new FastQuitAction(this));
tempLabel = new ui::Label(ui::Point(fastquit->Position.X+Graphics::textwidth(fastquit->GetText().c_str())+20, fastquit->Position.Y), ui::Point(Size.X-28, 16), "\bg- Always exit completely when hitting close");
tempLabel->Appearance.HorizontalAlign = ui::Appearance::AlignLeft; tempLabel->Appearance.VerticalAlign = ui::Appearance::AlignMiddle;
@ -318,6 +336,7 @@ void OptionsView::NotifySettingsChanged(OptionsModel * sender)
resizable->SetChecked(sender->GetResizable());
fullscreen->SetChecked(sender->GetFullscreen());
altFullscreen->SetChecked(sender->GetAltFullscreen());
forceIntegerScaling->SetChecked(sender->GetForceIntegerScaling());
fastquit->SetChecked(sender->GetFastQuit());
showAvatars->SetChecked(sender->GetShowAvatars());
}

View File

@ -23,6 +23,7 @@ class OptionsView: public ui::Window {
ui::Checkbox * resizable;
ui::Checkbox * fullscreen;
ui::Checkbox * altFullscreen;
ui::Checkbox * forceIntegerScaling;
ui::Checkbox * fastquit;
ui::Checkbox * showAvatars;
public: