diff --git a/source/code/MenuSystem.cpp b/source/code/MenuSystem.cpp index aa990be..aca7ffe 100644 --- a/source/code/MenuSystem.cpp +++ b/source/code/MenuSystem.cpp @@ -108,14 +108,14 @@ bool Button::isPopOnRun() const { static void drawToScreen(const Button& b) { if (b.marked) { - globalData.spriteHolder->GetSprite(b.standardButton.menu_marked).Draw(globalData.screen, SDL_GetTicks(), b.x, b.y); + globalData.spriteHolder->GetSprite(b.standardButton.menu_marked).Draw(globalData.screen, SDL_GetTicks(), b.x, b.y, &globalData.logicalResize); } else { - globalData.spriteHolder->GetSprite(b.standardButton.menu_unmarked).Draw(globalData.screen, SDL_GetTicks(), b.x, b.y); + globalData.spriteHolder->GetSprite(b.standardButton.menu_unmarked).Draw(globalData.screen, SDL_GetTicks(), b.x, b.y, &globalData.logicalResize); } b.standardButton.getLabel(b.getLabel(), b.marked)->Draw(globalData.screen, b.x+b.standardButton.xsize/2,b.y+b.standardButton.ysize/2, - sago::SagoTextField::Alignment::center, sago::SagoTextField::VerticalAlignment::center); + sago::SagoTextField::Alignment::center, sago::SagoTextField::VerticalAlignment::center, &globalData.logicalResize); } @@ -132,7 +132,7 @@ void Menu::drawSelf(SDL_Renderer* target) { drawToScreen(*b); } drawToScreen(exit); - exit.standardButton.getLabel(title, false)->Draw(target, 50, 50); + exit.standardButton.getLabel(title, false)->Draw(target, 50, 50, sago::SagoTextField::Alignment::left, sago::SagoTextField::VerticalAlignment::top, &globalData.logicalResize); } @@ -330,25 +330,28 @@ void Menu::Update() { if ( (buttonState&SDL_BUTTON(1))==0) { bMouseUp=true; } + int mousex = globalData.mousex; + int mousey = globalData.mousey; + globalData.logicalResize.PhysicalToLogical(globalData.mousex, globalData.mousey, mousex, mousey); - if (abs(globalData.mousex-oldmousex)>5 || abs(globalData.mousey-oldmousey)>5) { + if (abs(mousex-oldmousex)>5 || abs(mousey-oldmousey)>5) { for (int i=0; i< (int)buttons.size(); ++i) { - if (isClicked(*buttons.at(i), globalData.mousex, globalData.mousey)) { + if (isClicked(*buttons.at(i), mousex, mousey)) { marked = i; } } - if (isClicked(exit, globalData.mousex, globalData.mousey)) { + if (isClicked(exit, mousex, mousey)) { marked = buttons.size(); } - oldmousex = globalData.mousex; - oldmousey = globalData.mousey; + oldmousex = mousex; + oldmousey = mousey; } //mouse clicked if ( (buttonState&SDL_BUTTON(1) )==SDL_BUTTON(1) && bMouseUp) { bMouseUp = false; for (int i=0; i< (int)buttons.size(); ++i) { - if (isClicked(*buttons.at(i), globalData.mousex, globalData.mousey)) { + if (isClicked(*buttons.at(i), mousex, mousey)) { buttons.at(i)->doAction(); if (buttons.at(i)->isPopOnRun()) { running = false; @@ -357,7 +360,7 @@ void Menu::Update() { return; } } - if (isClicked(exit, globalData.mousex, globalData.mousey)) { + if (isClicked(exit, mousex, mousey)) { running = false; } } diff --git a/source/code/sago/SagoLogicalResize.hpp b/source/code/sago/SagoLogicalResize.hpp index 96698ed..03df630 100644 --- a/source/code/sago/SagoLogicalResize.hpp +++ b/source/code/sago/SagoLogicalResize.hpp @@ -1,3 +1,28 @@ +/* +Copyright (c) 2025 Poul Sander + +Permission is hereby granted, free of charge, to any person +obtaining a copy of this software and associated documentation files +(the "Software"), to deal in the Software without restriction, +including without limitation the rights to use, copy, modify, merge, +publish, distribute, sublicense, and/or sell copies of the Software, +and to permit persons to whom the Software is furnished to do so, +subject to the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS +BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN +ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +*/ + +#pragma once #include #include "SDL.h" @@ -13,6 +38,7 @@ public: void SetPhysicalSize(int physical_width, int physical_height) { + //Physical size must be at least 1. Less than 1 is not drawn anyway and it prevents division by zero. physical_width_ = std::max(1, physical_width); physical_height_ = std::max(1, physical_height); SetScaleFactor(); diff --git a/source/code/sago/SagoSprite.cpp b/source/code/sago/SagoSprite.cpp index c116e3e..3fbb337 100644 --- a/source/code/sago/SagoSprite.cpp +++ b/source/code/sago/SagoSprite.cpp @@ -65,20 +65,20 @@ SagoSprite::~SagoSprite() { delete data; } -void SagoSprite::Draw(SDL_Renderer* target, Sint32 frameTime, int x, int y) const { - DrawScaled(target, frameTime, x, y, data->imgCord.w, data->imgCord.h); +void SagoSprite::Draw(SDL_Renderer* target, Sint32 frameTime, int x, int y, SagoLogicalResize* resize) const { + DrawScaled(target, frameTime, x, y, data->imgCord.w, data->imgCord.h, resize); } -void SagoSprite::DrawRotated(SDL_Renderer* target, Sint32 frameTime, int x, int y, const double angleRadian) const { +void SagoSprite::DrawRotated(SDL_Renderer* target, Sint32 frameTime, int x, int y, const double angleRadian, SagoLogicalResize* resize) const { SDL_Point center = {this->data->origin.x, this->data->origin.y}; - DrawScaledAndRotated(target, frameTime, x, y, data->imgCord.w, data->imgCord.h, angleRadian, ¢er, SDL_FLIP_NONE); + DrawScaledAndRotated(target, frameTime, x, y, data->imgCord.w, data->imgCord.h, angleRadian, ¢er, SDL_FLIP_NONE, resize); } -void SagoSprite::DrawScaled(SDL_Renderer* target, Sint32 frameTime, int x, int y, int w, int h) const { - DrawScaledAndRotated(target, frameTime, x, y, w, h, 0.0, nullptr, SDL_FLIP_NONE); +void SagoSprite::DrawScaled(SDL_Renderer* target, Sint32 frameTime, int x, int y, int w, int h, SagoLogicalResize* resize) const { + DrawScaledAndRotated(target, frameTime, x, y, w, h, 0.0, nullptr, SDL_FLIP_NONE, resize); } -void SagoSprite::DrawScaledAndRotated(SDL_Renderer* target, Sint32 frameTime, int x, int y, int w, int h, const double angleRadian, const SDL_Point* center, const SDL_RendererFlip flip) const { +void SagoSprite::DrawScaledAndRotated(SDL_Renderer* target, Sint32 frameTime, int x, int y, int w, int h, const double angleRadian, const SDL_Point* center, const SDL_RendererFlip flip, SagoLogicalResize* resize) const { if (!data->tex.get()) { std::cerr << "Texture is null!\n"; } @@ -94,10 +94,13 @@ void SagoSprite::DrawScaledAndRotated(SDL_Renderer* target, Sint32 frameTime, in pos.h = h; } double angleDegress = angleRadian/M_PI*180.0; + if (resize) { + resize->LogicalToPhysical(pos); + } SDL_RenderCopyEx(target, data->tex.get(), &rect, &pos, angleDegress, center, flip); } -void SagoSprite::Draw(SDL_Renderer* target, Sint32 frameTime, int x, int y, const SDL_Rect& part) const { +void SagoSprite::Draw(SDL_Renderer* target, Sint32 frameTime, int x, int y, const SDL_Rect& part, SagoLogicalResize* resize) const { SDL_Rect rect = data->imgCord; rect.x+=rect.w*((frameTime/data->aniFrameTime)%data->aniFrames); rect.x += part.x; @@ -107,16 +110,19 @@ void SagoSprite::Draw(SDL_Renderer* target, Sint32 frameTime, int x, int y, cons SDL_Rect pos = rect; pos.x = x - this->data->origin.x; pos.y = y - this->data->origin.y; + if (resize) { + resize->LogicalToPhysical(pos); + } SDL_RenderCopy(target, data->tex.get(), &rect, &pos); } -void SagoSprite::DrawProgressive(SDL_Renderer* target, float progress, int x, int y) const { +void SagoSprite::DrawProgressive(SDL_Renderer* target, float progress, int x, int y, SagoLogicalResize* resize) const { Sint32 frameNumber = progress*data->aniFrames; Sint32 frameTime = frameNumber*data->aniFrameTime; - Draw(target, frameTime, x, y); + Draw(target, frameTime, x, y, resize); } -void SagoSprite::DrawBounded(SDL_Renderer* target, Sint32 frameTime, int x, int y, const SDL_Rect& bounds) const { +void SagoSprite::DrawBounded(SDL_Renderer* target, Sint32 frameTime, int x, int y, const SDL_Rect& bounds, SagoLogicalResize* resize) const { SDL_Rect rect = data->imgCord; rect.x+=rect.w*((frameTime/data->aniFrameTime)%data->aniFrames); SDL_Rect pos = rect; @@ -159,6 +165,9 @@ void SagoSprite::DrawBounded(SDL_Renderer* target, Sint32 frameTime, int x, int rect.h -= absDiff; } + if (resize) { + resize->LogicalToPhysical(pos); + } SDL_RenderCopy(target, data->tex.get(), &rect, &pos); } diff --git a/source/code/sago/SagoSprite.hpp b/source/code/sago/SagoSprite.hpp index 57c4e17..3ac01f3 100644 --- a/source/code/sago/SagoSprite.hpp +++ b/source/code/sago/SagoSprite.hpp @@ -26,6 +26,7 @@ SOFTWARE. #define SAGOSPRITE_HPP #include "SagoDataHolder.hpp" +#include "SagoLogicalResize.hpp" namespace sago { @@ -41,7 +42,7 @@ public: * @param x Place to draw the sprite * @param y Place to draw the sprite */ - void Draw(SDL_Renderer* target, Sint32 frameTime, int x, int y) const; + void Draw(SDL_Renderer* target, Sint32 frameTime, int x, int y, SagoLogicalResize* resize = nullptr) const; /** * Draws the sprite to a given render window @@ -51,7 +52,7 @@ public: * @param y Place to draw the sprite * @param angleRadian Angle to rotate the sprite around origin before drawing */ - void DrawRotated(SDL_Renderer* target, Sint32 frameTime, int x, int y, const double angleRadian) const; + void DrawRotated(SDL_Renderer* target, Sint32 frameTime, int x, int y, const double angleRadian, SagoLogicalResize* resize = nullptr) const; /** * Draws part of the sprite to a given render window @@ -61,7 +62,7 @@ public: * @param y Place to draw the sprite * @param part the part of the sprite that should be drawn. */ - void Draw(SDL_Renderer* target, Sint32 frameTime, int x, int y, const SDL_Rect& part) const; + void Draw(SDL_Renderer* target, Sint32 frameTime, int x, int y, const SDL_Rect& part, SagoLogicalResize* resize = nullptr) const; /** * Draws the wprite to the given renderer but makes sure to not draw outside th bounds given @@ -71,7 +72,7 @@ public: * @param y Place to draw the sprite * @param bounds A recagular area that we must not draw outside. */ - void DrawBounded(SDL_Renderer* target, Sint32 frameTime, int x, int y, const SDL_Rect& bounds) const; + void DrawBounded(SDL_Renderer* target, Sint32 frameTime, int x, int y, const SDL_Rect& bounds, SagoLogicalResize* resize = nullptr) const; /** * Draws the sprite to a given render window @@ -80,11 +81,11 @@ public: * @param x Place to draw the sprite * @param y Place to draw the sprite */ - void DrawProgressive(SDL_Renderer* target, float progress, int x, int y) const; + void DrawProgressive(SDL_Renderer* target, float progress, int x, int y, SagoLogicalResize* resize = nullptr) const; - void DrawScaled(SDL_Renderer* target, Sint32 frameTime, int x, int y, int w, int h) const; + void DrawScaled(SDL_Renderer* target, Sint32 frameTime, int x, int y, int w, int h, SagoLogicalResize* resize = nullptr) const; void DrawScaledAndRotated(SDL_Renderer* target, Sint32 frameTime, int x, int y, int w, int h, - const double angleRadian, const SDL_Point* center, const SDL_RendererFlip flip) const; + const double angleRadian, const SDL_Point* center, const SDL_RendererFlip flip, SagoLogicalResize* resize = nullptr) const; /** * Set a different origin. Normally it is the top left cornor. But in some cases you might want to center the origin or tranform it for other reasons diff --git a/source/code/sago/SagoTextField.cpp b/source/code/sago/SagoTextField.cpp index 85e63fa..eef904a 100644 --- a/source/code/sago/SagoTextField.cpp +++ b/source/code/sago/SagoTextField.cpp @@ -193,7 +193,7 @@ void SagoTextField::GetRenderedSize(const char* text, int* w, int* h) { } } -void SagoTextField::Draw(SDL_Renderer* target, int x, int y, Alignment alignment, VerticalAlignment verticalAlignment) { +void SagoTextField::Draw(SDL_Renderer* target, int x, int y, Alignment alignment, VerticalAlignment verticalAlignment, SagoLogicalResize* resize) { if (data->text.empty()) { return; } @@ -224,8 +224,14 @@ void SagoTextField::Draw(SDL_Renderer* target, int x, int y, Alignment alignment int outlineTexH = 0; SDL_QueryTexture(data->outlineTexture, NULL, NULL, &outlineTexW, &outlineTexH); SDL_Rect dstrectOutline = { x-(data->outline), y-(data->outline), outlineTexW, outlineTexH }; + if (resize) { + resize->LogicalToPhysical(dstrectOutline); + } SDL_RenderCopy(target, data->outlineTexture, NULL, &dstrectOutline); } + if (resize) { + resize->LogicalToPhysical(dstrect); + } SDL_RenderCopy(target, data->texture, NULL, &dstrect); } diff --git a/source/code/sago/SagoTextField.hpp b/source/code/sago/SagoTextField.hpp index c97846f..9230ce5 100644 --- a/source/code/sago/SagoTextField.hpp +++ b/source/code/sago/SagoTextField.hpp @@ -26,6 +26,7 @@ SOFTWARE. #define SAGOTEXTFIELD_HPP #include "SagoDataHolder.hpp" +#include "SagoLogicalResize.hpp" namespace sago { @@ -109,7 +110,7 @@ public: enum class Alignment { left = 0, right=1, center = 2 }; enum class VerticalAlignment { top = 0, center = 1, bottom = 2}; - void Draw(SDL_Renderer* target, int x, int y, Alignment alignment = Alignment::left, VerticalAlignment verticalAlignment = VerticalAlignment::top); + void Draw(SDL_Renderer* target, int x, int y, Alignment alignment = Alignment::left, VerticalAlignment verticalAlignment = VerticalAlignment::top, SagoLogicalResize* resize = nullptr); /** * Updates the cache.