Skip to content
Permalink
Browse files

Add "Force Integer Scaling" option for fullscreen

Also:
recreate the window when enabling resizable window, same workaround I applied to my mod for jacob1#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
  • Loading branch information...
jacob1 committed Feb 19, 2019
1 parent a979917 commit 0c6ce2088025790e2d6a04ed96ff4f226c64df5a
@@ -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);
@@ -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)
@@ -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;
@@ -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);
@@ -26,6 +26,7 @@ class OptionsController {
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);
@@ -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();
@@ -39,6 +39,8 @@ class OptionsModel {
void SetFullscreen(bool fullscreen);
bool GetAltFullscreen();
void SetAltFullscreen(bool oldFullscreen);
bool GetForceIntegerScaling();
void SetForceIntegerScaling(bool forceIntegerScaling);
bool GetFastQuit();
void SetFastQuit(bool fastquit);
virtual ~OptionsModel();
@@ -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());
}
@@ -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:

0 comments on commit 0c6ce20

Please sign in to comment.
You can’t perform that action at this time.
You signed in with another tab or window. Reload to refresh your session. You signed out in another tab or window. Reload to refresh your session.