diff --git a/src/PowderToySDL.cpp b/src/PowderToySDL.cpp index 5af865015..89022d3e8 100644 --- a/src/PowderToySDL.cpp +++ b/src/PowderToySDL.cpp @@ -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); diff --git a/src/client/GameSave.cpp b/src/client/GameSave.cpp index 639a0e827..cb10a26c3 100644 --- a/src/client/GameSave.cpp +++ b/src/client/GameSave.cpp @@ -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) diff --git a/src/gui/interface/Engine.h b/src/gui/interface/Engine.h index 223b2db7b..2d7c69151 100644 --- a/src/gui/interface/Engine.h +++ b/src/gui/interface/Engine.h @@ -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; diff --git a/src/gui/options/OptionsController.cpp b/src/gui/options/OptionsController.cpp index e18141399..d592f9c09 100644 --- a/src/gui/options/OptionsController.cpp +++ b/src/gui/options/OptionsController.cpp @@ -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); diff --git a/src/gui/options/OptionsController.h b/src/gui/options/OptionsController.h index be070165a..50bab5a89 100644 --- a/src/gui/options/OptionsController.h +++ b/src/gui/options/OptionsController.h @@ -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); diff --git a/src/gui/options/OptionsModel.cpp b/src/gui/options/OptionsModel.cpp index 76f463505..cf871bce8 100644 --- a/src/gui/options/OptionsModel.cpp +++ b/src/gui/options/OptionsModel.cpp @@ -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(); diff --git a/src/gui/options/OptionsModel.h b/src/gui/options/OptionsModel.h index 3f68a6762..ad38e0651 100644 --- a/src/gui/options/OptionsModel.h +++ b/src/gui/options/OptionsModel.h @@ -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(); diff --git a/src/gui/options/OptionsView.cpp b/src/gui/options/OptionsView.cpp index a83cd0eca..3b26cab70 100644 --- a/src/gui/options/OptionsView.cpp +++ b/src/gui/options/OptionsView.cpp @@ -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()); } diff --git a/src/gui/options/OptionsView.h b/src/gui/options/OptionsView.h index a41e15e2d..f8c632d12 100644 --- a/src/gui/options/OptionsView.h +++ b/src/gui/options/OptionsView.h @@ -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: