diff --git a/CHANGELOG.md b/CHANGELOG.md index 072db2c..21ae2d8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,11 @@ ### Removed +## [2.9.1] - 2025-02-09 + +### Changed + - Left and right on gamepad d-pad now works again. Broken in 2.6.0. + ## [2.9.0] - 2024-05-09 ### Added diff --git a/CMakeLists.txt b/CMakeLists.txt index 00aabd0..977a976 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,4 +1,4 @@ -cmake_minimum_required(VERSION 3.5.1...3.27.4) +cmake_minimum_required(VERSION 3.5.1...3.30.3) project (blockattack) set(BIN_DIR ${blockattack_SOURCE_DIR}/Game) @@ -77,7 +77,7 @@ pkg_search_module(SDL2TTF REQUIRED SDL2_ttf) find_package(Intl REQUIRED) -find_package(Boost COMPONENTS program_options REQUIRED) +find_package(Boost COMPONENTS program_options REQUIRED NO_MODULE) include_directories(SYSTEM "source/code/Libs/imgui") diff --git a/source/code/BlockGameSdl.hpp b/source/code/BlockGameSdl.hpp index 5b4a676..7ef6ff9 100644 --- a/source/code/BlockGameSdl.hpp +++ b/source/code/BlockGameSdl.hpp @@ -89,7 +89,7 @@ public: void PrintTextCenteredBoard(int x, int y, sago::SagoTextField& field) { field.Draw(globalData.screen, x+topx+60, y+topy+20, - sago::SagoTextField::Alignment::center, sago::SagoTextField::VerticalAlignment::center); + sago::SagoTextField::Alignment::center, sago::SagoTextField::VerticalAlignment::center, &globalData.logicalResize); } void SetTopXY(int tx, int ty) { @@ -234,121 +234,8 @@ private: } } - /** - * Creates a new texture for a garabge block of size size_x*size_y at x,y and crops it. - * Also sets globalData.screen to point to the texture, so Draw now draws on the Texture. - */ - SDL_Texture* CreateGarbageTexture(int x, int y, int size_x, int size_y, SDL_Rect& dstrect, SDL_Rect& srcrect) const { - dstrect = { x, y, size_x*bsize, size_y*bsize }; - srcrect = { 0, 0, size_x*bsize, size_y*bsize }; - SDL_Rect bound = {topx, topy, BOARD_WIDTH, BOARD_HEIGHT}; - CropTexture (dstrect, srcrect, bound); - SDL_Texture* mTexture = SDL_CreateTexture( globalData.screen, SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_TARGET, size_x*bsize, size_y*bsize ); - SDL_SetRenderTarget( globalData.screen, mTexture ); - - SDL_SetRenderDrawBlendMode(globalData.screen, SDL_BLENDMODE_NONE); - SDL_SetTextureBlendMode(mTexture, SDL_BLENDMODE_BLEND); - SDL_SetRenderDrawColor(globalData.screen, 0, 0, 0, 0); - SDL_RenderFillRect(globalData.screen, NULL); - SDL_SetRenderDrawBlendMode(globalData.screen, SDL_BLENDMODE_BLEND); - return mTexture; - } - - /** - Paints a garbage block of size size_x*size_y (size in blocks) at x,y (coordinates in pixels). - The garbage block will be painted on an internal texture and rendered to screen to protect against tearing. - The result will be cropped to the playable area. - */ - void PaintGarbageBlock(int x, int y, int size_x, int size_y) const { - SDL_Rect dstrect ; - SDL_Rect srcrect ; - SDL_Texture* mTexture = CreateGarbageTexture(x, y, size_x, size_y, dstrect, srcrect); - const Sint32 draw_time = SDL_GetTicks(); - - if (size_y == 1) { - //single line - globalData.garbageML.Draw(globalData.screen, draw_time, 0, 0); - for (int i = 1; i < size_x-1; ++i) { - globalData.garbageM.Draw(globalData.screen, draw_time, i*bsize, 0); - } - globalData.garbageMR.Draw(globalData.screen, draw_time, (size_x-1)*bsize, 0); - } - if (size_y > 1) { - // Top line - globalData.garbageTL.Draw(globalData.screen, draw_time, 0, 0); - for (int i = 1; i < size_x-1; ++i) { - globalData.garbageT.Draw(globalData.screen, draw_time, i*bsize, 0); - } - globalData.garbageTR.Draw(globalData.screen, draw_time, (size_x-1)*bsize, 0); - // Middle lines (if any) - for (int j=1; j < size_y-1; ++j) { - globalData.garbageL.Draw(globalData.screen, draw_time, 0, j*bsize); - for (int i = 1; i < size_x-1; ++i) { - globalData.garbageFill.Draw(globalData.screen, draw_time, i*bsize, j*bsize); - } - globalData.garbageR.Draw(globalData.screen, draw_time, (size_x-1)*bsize, j*bsize); - } - //Buttom line - globalData.garbageBL.Draw(globalData.screen, draw_time, 0, (size_y-1)*bsize); - for (int i = 1; i < size_x-1; ++i) { - globalData.garbageB.Draw(globalData.screen, draw_time, i*bsize, (size_y-1)*bsize); - } - globalData.garbageBR.Draw(globalData.screen, draw_time, (size_x-1)*bsize, (size_y-1)*bsize); - } - - SDL_SetRenderTarget( globalData.screen, nullptr ); - SDL_RenderCopy( globalData.screen, mTexture, &srcrect, &dstrect ); - SDL_DestroyTexture(mTexture); - } - - /** - Paints a grey garbage block of size size_x (size in blocks, always 6) at x,y (coordinates in pixels). - The result will be cropped to the playable area. - */ - void PaintGreyGarbageBlock(int x, int y, int size_x) const { - const int size_y = bsize; - SDL_Rect dstrect ; - SDL_Rect srcrect ; - SDL_Texture* mTexture = CreateGarbageTexture(x, y, size_x, size_y, dstrect, srcrect); - const Sint32 draw_time = SDL_GetTicks(); - - for (int j=0; j < size_y; ++j) { - if (j==0) { - globalData.garbageGML.Draw(globalData.screen, draw_time, j*bsize, 0); - } - else if (j==5) { - globalData.garbageGMR.Draw(globalData.screen, draw_time, j*bsize, 0); - } - else { - globalData.garbageGM.Draw(globalData.screen, draw_time, j*bsize, 0); - } - } - - SDL_SetRenderTarget( globalData.screen, nullptr ); - SDL_RenderCopy( globalData.screen, mTexture, &srcrect, &dstrect ); - SDL_DestroyTexture(mTexture); - } - - std::pair getGarbageSize(int topx, int topy) const { - int size_x = 0; - int size_y = 0; - int number = board[topx][topy]; - for (int i=topy; i < 30 ; ++i) { - if (number == board[topx][i]) { - ++size_y; - } - } - for (int i=topx; i < 7 ; ++i) { - if (number == board[i][topy]) { - ++size_x; - } - } - return std::make_pair(size_x, size_y); - } - //Draws all the bricks to the board (including garbage) void PaintBricks() const { - int lastGarbageNumber = 0; for (int i=0; i<13; ++i) { for (int j=0; j<6; ++j) { int basicBrick = board[j][i]%10; //The basic brick, stored on the least significant digit @@ -363,19 +250,78 @@ private: } if ((board[j][i]/1000000)%10==1) { + int left, right, over, under; int number = board[j][i]; - if (number != lastGarbageNumber) { - const auto& garbage_size = getGarbageSize(j, i); - lastGarbageNumber = number; - PaintGarbageBlock(topx+j*bsize, topy+12*bsize-i*bsize-(garbage_size.second-1)*bsize -pixels, garbage_size.first, garbage_size.second); + if (j<1) { + left = -1; + } + else { + left = board[j-1][i]; + } + if (j>=5) { + right = -1; + } + else { + right = board[j+1][i]; + } + if (i>28) { + over = -1; + } + else { + over = board[j][i+1]; + } + if (i<1) { + under = -1; + } + else { + under = board[j][i-1]; + } + if ((left == number)&&(right == number)&&(over == number)&&(under == number)) { + DrawImgBoardBounded(globalData.garbageFill, j*bsize, bsize*12-i*bsize-pixels); + } + if ((left != number)&&(right == number)&&(over == number)&&(under == number)) { + DrawImgBoardBounded(globalData.garbageL, j*bsize, bsize*12-i*bsize-pixels); + } + if ((left == number)&&(right != number)&&(over == number)&&(under == number)) { + DrawImgBoardBounded(globalData.garbageR, j*bsize, bsize*12-i*bsize-pixels); + } + if ((left == number)&&(right == number)&&(over != number)&&(under == number)) { + DrawImgBoardBounded(globalData.garbageT, j*bsize, bsize*12-i*bsize-pixels); + } + if ((left == number)&&(right == number)&&(over == number)&&(under != number)) { + DrawImgBoardBounded(globalData.garbageB, j*bsize, bsize*12-i*bsize-pixels); + } + if ((left != number)&&(right == number)&&(over != number)&&(under == number)) { + DrawImgBoardBounded(globalData.garbageTL, j*bsize, bsize*12-i*bsize-pixels); + } + if ((left != number)&&(right == number)&&(over == number)&&(under != number)) { + DrawImgBoardBounded(globalData.garbageBL, j*bsize, bsize*12-i*bsize-pixels); + } + if ((left == number)&&(right != number)&&(over != number)&&(under == number)) { + DrawImgBoardBounded(globalData.garbageTR, j*bsize, bsize*12-i*bsize-pixels); + } + if ((left == number)&&(right != number)&&(over == number)&&(under != number)) { + DrawImgBoardBounded(globalData.garbageBR, j*bsize, bsize*12-i*bsize-pixels); + } + if ((left == number)&&(right != number)&&(over != number)&&(under != number)) { + DrawImgBoardBounded(globalData.garbageMR, j*bsize, bsize*12-i*bsize-pixels); + } + if ((left == number)&&(right == number)&&(over != number)&&(under != number)) { + DrawImgBoardBounded(globalData.garbageM, j*bsize, bsize*12-i*bsize-pixels); + } + if ((left != number)&&(right == number)&&(over != number)&&(under != number)) { + DrawImgBoardBounded(globalData.garbageML, j*bsize, bsize*12-i*bsize-pixels); } } if ((board[j][i]/1000000)%10==2) { - int number = board[j][i]; - if (number != lastGarbageNumber) { - const auto& garbage_size = getGarbageSize(j, i); - lastGarbageNumber = number; - PaintGreyGarbageBlock(topx+j*bsize, topy+12*bsize-i*bsize-(garbage_size.second-1)*bsize -pixels, garbage_size.first); + if (j==0) { + DrawImgBoardBounded(globalData.garbageGML, j*bsize, bsize*12-i*bsize-pixels); + } + else if (j==5) { + DrawImgBoardBounded(globalData.garbageGMR, j*bsize, bsize*12-i*bsize-pixels); + } + else { + DrawImgBoardBounded(globalData.garbageGM, j*bsize, bsize*12-i*bsize-pixels); } } } @@ -430,11 +376,11 @@ public: sago::SagoSprite backback = globalData.spriteHolder->GetSprite(border.border_sprite); DrawIMG(backback, globalData.screen, this->GetTopX()+border.border_sprite_offset.first, this->GetTopY()+border.border_sprite_offset.second); - this->scoreLabel.Draw(globalData.screen, this->GetTopX()+border.score_label_offset.first,this->GetTopY()+border.score_label_offset.second); - this->timeLabel.Draw(globalData.screen, this->GetTopX()+border.time_label_offset.first,this->GetTopY()+border.time_label_offset.second); - this->chainLabel.Draw(globalData.screen, this->GetTopX()+border.chain_label_offset.first,this->GetTopY()+border.chain_label_offset.second); - this->speedLabel.Draw(globalData.screen, this->GetTopX()+border.speed_label_offset.first,this->GetTopY()+border.speed_label_offset.second); - globalData.spriteHolder->GetSprite(globalData.theme.back_board).DrawScaled(globalData.screen, SDL_GetTicks(), this->GetTopX(),this->GetTopY(), BOARD_WIDTH, BOARD_HEIGHT); + this->scoreLabel.Draw(globalData.screen, this->GetTopX()+border.score_label_offset.first,this->GetTopY()+border.score_label_offset.second, sago::SagoTextField::Alignment::left, sago::SagoTextField::VerticalAlignment::top, &globalData.logicalResize); + this->timeLabel.Draw(globalData.screen, this->GetTopX()+border.time_label_offset.first,this->GetTopY()+border.time_label_offset.second, sago::SagoTextField::Alignment::left, sago::SagoTextField::VerticalAlignment::top, &globalData.logicalResize); + this->chainLabel.Draw(globalData.screen, this->GetTopX()+border.chain_label_offset.first,this->GetTopY()+border.chain_label_offset.second, sago::SagoTextField::Alignment::left, sago::SagoTextField::VerticalAlignment::top, &globalData.logicalResize); + this->speedLabel.Draw(globalData.screen, this->GetTopX()+border.speed_label_offset.first,this->GetTopY()+border.speed_label_offset.second, sago::SagoTextField::Alignment::left, sago::SagoTextField::VerticalAlignment::top, &globalData.logicalResize); + globalData.spriteHolder->GetSprite(globalData.theme.back_board).DrawScaled(globalData.screen, SDL_GetTicks(), this->GetTopX(),this->GetTopY(), BOARD_WIDTH, BOARD_HEIGHT, &globalData.logicalResize); PaintBricks(); if (stageClear) { @@ -446,7 +392,7 @@ public: static sago::SagoTextField movesPuzzleLabel; sagoTextSetHelpFont(movesPuzzleLabel); movesPuzzleLabel.SetText(strHolder); - movesPuzzleLabel.Draw(globalData.screen, topx+5, topy+5); + movesPuzzleLabel.Draw(globalData.screen, topx+5, topy+5, sago::SagoTextField::Alignment::left, sago::SagoTextField::VerticalAlignment::top, &globalData.logicalResize); } if (puzzleMode && stageButtonStatus == SBpuzzleMode) { @@ -466,7 +412,7 @@ public: static sago::SagoTextField lastPuzzleLabel; sagoTextSetHelpFont(lastPuzzleLabel); lastPuzzleLabel.SetText(_("Last puzzle")); - lastPuzzleLabel.Draw(globalData.screen, topx+5, topy+5); + lastPuzzleLabel.Draw(globalData.screen, topx+5, topy+5, sago::SagoTextField::Alignment::left, sago::SagoTextField::VerticalAlignment::top, &globalData.logicalResize); } } if (stageClear && stageButtonStatus == SBstageClear) { @@ -486,12 +432,12 @@ public: static sago::SagoTextField lastStageLabel; sagoTextSetHelpFont(lastStageLabel); lastStageLabel.SetText(_("Last stage")); - lastStageLabel.Draw(globalData.screen, topx+5, topy+5); + lastStageLabel.Draw(globalData.screen, topx+5, topy+5, sago::SagoTextField::Alignment::left, sago::SagoTextField::VerticalAlignment::top, &globalData.logicalResize); } } if (!bGameOver && stop > 20) { stopIntField.SetText(std::to_string(stop/10)); - stopIntField.Draw(globalData.screen, 240+topx, -40+topy); + stopIntField.Draw(globalData.screen, 240+topx, -40+topy, sago::SagoTextField::Alignment::left, sago::SagoTextField::VerticalAlignment::top, &globalData.logicalResize); } #if DEBUG @@ -499,7 +445,7 @@ public: sagoTextSetBlueFont(aiStatusField); strHolder = "AI_status: " + std::to_string(AIstatus)+ ", "+ std::to_string(AIlineToClear); aiStatusField.SetText(strHolder); - aiStatusField.Draw(globalData.screen, topx+5, topy+5); + aiStatusField.Draw(globalData.screen, topx+5, topy+5, sago::SagoTextField::Alignment::left, sago::SagoTextField::VerticalAlignment::top, &globalData.logicalResize); } #endif if (!bGameOver) { @@ -554,15 +500,15 @@ public: if (bGameOver) { if (hasWonTheGame) { - globalData.tbWinner.Draw(globalData.screen, topx+150, topy+200, sago::SagoTextField::Alignment::center); + globalData.tbWinner.Draw(globalData.screen, topx+150, topy+200, sago::SagoTextField::Alignment::center, &globalData.logicalResize); } else { if (bDraw) { - globalData.tbDraw.Draw(globalData.screen, topx+150, topy+200, sago::SagoTextField::Alignment::center); + globalData.tbDraw.Draw(globalData.screen, topx+150, topy+200, sago::SagoTextField::Alignment::center, &globalData.logicalResize); } else { if (this->infostring.empty()) { - globalData.tbGameOver.Draw(globalData.screen, topx+150, topy+200, sago::SagoTextField::Alignment::center); + globalData.tbGameOver.Draw(globalData.screen, topx+150, topy+200, sago::SagoTextField::Alignment::center, &globalData.logicalResize); } } } @@ -571,14 +517,14 @@ public: std::string strHolder; strHolder = std::to_string(this->GetScore()+this->GetHandicap()); player_score.SetText(strHolder); - player_score.Draw(globalData.screen, this->GetTopX()+border.score_label_offset.first,this->GetTopY()+border.score_label_offset.second+22); + player_score.Draw(globalData.screen, this->GetTopX()+border.score_label_offset.first,this->GetTopY()+border.score_label_offset.second+22, sago::SagoTextField::Alignment::left, sago::SagoTextField::VerticalAlignment::top, &globalData.logicalResize); if (this->GetAIenabled()) { player_name.SetText(_("AI")); } else { player_name.SetText(name); } - player_name.Draw(globalData.screen, this->GetTopX()+10,this->GetTopY()-34); + player_name.Draw(globalData.screen, this->GetTopX()+10,this->GetTopY()-34, sago::SagoTextField::Alignment::left, sago::SagoTextField::VerticalAlignment::top, &globalData.logicalResize); if (this->isTimeTrial()) { int tid = (int)SDL_GetTicks()-this->GetGameStartedAt(); int minutes; @@ -622,14 +568,14 @@ public: } player_time.SetText(strHolder); } - player_time.Draw(globalData.screen, this->GetTopX()+border.time_label_offset.first,this->GetTopY()+border.time_label_offset.second+22); + player_time.Draw(globalData.screen, this->GetTopX()+border.time_label_offset.first,this->GetTopY()+border.time_label_offset.second+22, sago::SagoTextField::Alignment::left, sago::SagoTextField::VerticalAlignment::top, &globalData.logicalResize); strHolder = std::to_string(this->GetChains()); player_chain.SetText(strHolder); - player_chain.Draw(globalData.screen, this->GetTopX()+border.chain_label_offset.first,this->GetTopY()+border.chain_label_offset.second+22); + player_chain.Draw(globalData.screen, this->GetTopX()+border.chain_label_offset.first,this->GetTopY()+border.chain_label_offset.second+22, sago::SagoTextField::Alignment::left, sago::SagoTextField::VerticalAlignment::top, &globalData.logicalResize); //drawspeedLevel: strHolder = std::to_string(this->GetSpeedLevel()); player_speed.SetText(strHolder); - player_speed.Draw(globalData.screen, this->GetTopX()+border.speed_label_offset.first,this->GetTopY()+border.speed_label_offset.second+22); + player_speed.Draw(globalData.screen, this->GetTopX()+border.speed_label_offset.first,this->GetTopY()+border.speed_label_offset.second+22, sago::SagoTextField::Alignment::left, sago::SagoTextField::VerticalAlignment::top, &globalData.logicalResize); if ((this->isStageClear()) &&(this->GetTopY()+700+50*(this->GetStageClearLimit()-this->GetLinesCleared())-this->GetPixels()-1<600+this->GetTopY())) { oldBubleX = this->GetTopX()+280; oldBubleY = this->GetTopY()+650+50*(this->GetStageClearLimit()-this->GetLinesCleared())-this->GetPixels()-1; @@ -647,9 +593,9 @@ public: objectiveField.SetText(_("Objective:")); sagoTextSetHelpFont(gametypeNameField); gametypeNameField.SetText(infostringName); - gametypeNameField.Draw(globalData.screen, this->GetTopX()+7,this->GetTopY()+10); - objectiveField.Draw(globalData.screen, this->GetTopX()+7, this->GetTopY()+160); - infoBox.Draw(globalData.screen, this->GetTopX()+7, this->GetTopY()+160+32); + gametypeNameField.Draw(globalData.screen, this->GetTopX()+7,this->GetTopY()+10, sago::SagoTextField::Alignment::left, sago::SagoTextField::VerticalAlignment::top, &globalData.logicalResize); + objectiveField.Draw(globalData.screen, this->GetTopX()+7, this->GetTopY()+160, sago::SagoTextField::Alignment::left, sago::SagoTextField::VerticalAlignment::top, &globalData.logicalResize); + infoBox.Draw(globalData.screen, this->GetTopX()+7, this->GetTopY()+160+32, sago::SagoTextField::Alignment::left, &globalData.logicalResize); int y = this->GetTopY()+400; static sago::SagoTextBox controldBox; @@ -657,7 +603,7 @@ public: sagoTextSetHelpFont(controldBox); controldBox.SetMaxWidth(290); controldBox.SetText(controldBoxText); - controldBox.Draw(globalData.screen, this->GetTopX()+7,y); + controldBox.Draw(globalData.screen, this->GetTopX()+7,y, sago::SagoTextField::Alignment::left, &globalData.logicalResize); } } diff --git a/source/code/DialogBox.cpp b/source/code/DialogBox.cpp index 7936b13..0e2551e 100644 --- a/source/code/DialogBox.cpp +++ b/source/code/DialogBox.cpp @@ -29,6 +29,7 @@ http://www.blockattack.net #include "MenuSystem.h" #include #include +#include "sago/SagoLogicalResize.hpp" static void setButtonFont(const sago::SagoDataHolder* holder, sago::SagoTextField& field, const char* text) { field.SetHolder(holder); @@ -52,9 +53,12 @@ static void draw_rect_cache_clear() { } -static void DrawRect(SDL_Renderer* target, int topx, int topy, int height, int width, const std::string& name) { +static void DrawRect(SDL_Renderer* target, int topx, int topy, int height, int width, const std::string& name, sago::SagoLogicalResize* resize) { const int size = 32; SDL_Rect dstrect = { topx, topy, width, height }; + if (resize) { + resize->LogicalToPhysical(dstrect); + } std::string key_name = fmt::format("{}-{}-{}", name, width, height); Uint64 new_version = globalData.spriteHolder->GetDataHolder().getVersion(); if (draw_rect_cache_version != new_version) { @@ -104,14 +108,14 @@ static void DrawRect(SDL_Renderer* target, int topx, int topy, int height, int w SDL_RenderCopy( target, mTexture, NULL, &dstrect ); } -static void DrawRectWhite(SDL_Renderer* target, int topx, int topy, int height, int width) { +static void DrawRectWhite(SDL_Renderer* target, int topx, int topy, int height, int width, sago::SagoLogicalResize* resize) { std::string name = "ui_rect_white_"; - DrawRect(target, topx, topy, height, width, name); + DrawRect(target, topx, topy, height, width, name, resize); } -void DrawRectYellow(SDL_Renderer* target, int topx, int topy, int height, int width) { +void DrawRectYellow(SDL_Renderer* target, int topx, int topy, int height, int width, sago::SagoLogicalResize* resize) { std::string name = "ui_rect_yellow_"; - DrawRect(target, topx, topy, height, width, name); + DrawRect(target, topx, topy, height, width, name, resize); } bool OpenDialogbox(int x, int y, std::string& name, const std::string& header) { @@ -160,16 +164,19 @@ bool DialogBox::IsActive() { } static bool insideRect (int x, int y, int height, int width) { - if (globalData.mousex < x) { + int mousex; + int mousey; + globalData.logicalResize.PhysicalToLogical(globalData.mousex, globalData.mousey, mousex, mousey); + if (mousex < x) { return false; } - if (globalData.mousex > x+width) { + if (mousex > x+width) { return false; } - if (globalData.mousey < y) { + if (mousey < y) { return false; } - if (globalData.mousey > y+height) { + if (mousey > y+height) { return false; } return true; @@ -182,25 +189,25 @@ void DialogBox::Draw(SDL_Renderer* target) { DrawBackground(globalData.screen); this->x = globalData.xsize/2-300; this->y = globalData.ysize/2-100; - DrawRectYellow(target, x, y, 200, 600); - headerLabel.Draw(target, x+300, y+20, sago::SagoTextField::Alignment::center); + DrawRectYellow(target, x, y, 200, 600, &globalData.logicalResize); + headerLabel.Draw(target, x+300, y+20, sago::SagoTextField::Alignment::center, sago::SagoTextField::VerticalAlignment::top, &globalData.logicalResize); if (insideRect(x+25, y+128, 50, 250)) { - DrawRectYellow(target, x+24, y+127, 52, 252); + DrawRectYellow(target, x+24, y+127, 52, 252, &globalData.logicalResize); } else { - DrawRectYellow(target, x+25, y+128, 50, 250); + DrawRectYellow(target, x+25, y+128, 50, 250, &globalData.logicalResize); } - enterLabel.Draw(target, x+150, y+140, sago::SagoTextField::Alignment::center); + enterLabel.Draw(target, x+150, y+140, sago::SagoTextField::Alignment::center, sago::SagoTextField::VerticalAlignment::top, &globalData.logicalResize); if (insideRect(x+325, y+128, 50, 250)) { - DrawRectYellow(target, x+324, y+127, 52, 252); + DrawRectYellow(target, x+324, y+127, 52, 252, &globalData.logicalResize); } else { - DrawRectYellow(target, x+325, y+128, 50, 250); + DrawRectYellow(target, x+325, y+128, 50, 250, &globalData.logicalResize); } - cancelLabel.Draw(target, x+450, y+140, sago::SagoTextField::Alignment::center); - DrawRectWhite(target, x+26, y+64, 54, 600-2*26); + cancelLabel.Draw(target, x+450, y+140, sago::SagoTextField::Alignment::center, sago::SagoTextField::VerticalAlignment::top, &globalData.logicalResize); + DrawRectWhite(target, x+26, y+64, 54, 600-2*26, &globalData.logicalResize); textField.SetText(rk->GetString()); - textField.Draw(target, x+40, y+76); + textField.Draw(target, x+40, y+76, sago::SagoTextField::Alignment::left, sago::SagoTextField::VerticalAlignment::top, &globalData.logicalResize); std::string strHolder = rk->GetString(); strHolder.erase((int)rk->CharsBeforeCursor()); @@ -208,15 +215,15 @@ void DialogBox::Draw(SDL_Renderer* target) { int width = 0; textField.GetRenderedSize( strHolder.c_str(), &width); width -= 2; - cursorLabel.Draw(target, x+40+width,y+76); + cursorLabel.Draw(target, x+40+width,y+76, sago::SagoTextField::Alignment::left, sago::SagoTextField::VerticalAlignment::top, &globalData.logicalResize); } const sago::SagoSprite& marked = globalData.spriteHolder->GetSprite("i_level_check_box_marked"); for (size_t i = 0; i(i)) { - marked.Draw(target, SDL_GetTicks(), globalData.xsize/2-400+(i%keyboardRowLimit)*40-5, globalData.ysize/2+150+(i/keyboardRowLimit)*40-5); + marked.Draw(target, SDL_GetTicks(), globalData.xsize/2-400+(i%keyboardRowLimit)*40-5, globalData.ysize/2+150+(i/keyboardRowLimit)*40-5, &globalData.logicalResize); } sago::SagoTextField& f = virtualKeyboard.gamePadCharFields.at(i); - f.Draw(target, globalData.xsize/2-400+(i%keyboardRowLimit)*40, globalData.ysize/2+150+(i/keyboardRowLimit)*40); + f.Draw(target, globalData.xsize/2-400+(i%keyboardRowLimit)*40, globalData.ysize/2+150+(i/keyboardRowLimit)*40, sago::SagoTextField::Alignment::left, sago::SagoTextField::VerticalAlignment::top, &globalData.logicalResize); } } @@ -369,7 +376,11 @@ void DialogBox::ProcessInput(const SDL_Event& event, bool& processed) { } } - if (globalData.mousex != oldmousex || globalData.mousey != oldmousey) { + int mousex; + int mousey; + globalData.logicalResize.PhysicalToLogical(globalData.mousex, globalData.mousey, mousex, mousey); + + if (mousex != oldmousex || mousey != oldmousey) { for (size_t i = 0; iGetDataHolder()); @@ -91,13 +91,13 @@ void HelpCommonState::Draw(SDL_Renderer* target) { void HelpTextBoxState::Draw(SDL_Renderer* target) { DrawBackground(target); - titleField.Draw(target, 50, 50); - DrawRectYellow(target, 40, 90, 600, 900); + titleField.Draw(target, 50, 50, sago::SagoTextField::Alignment::left, sago::SagoTextField::VerticalAlignment::top, &globalData.logicalResize); + DrawRectYellow(target, 40, 90, 600, 900, &globalData.logicalResize); infoBox.SetMaxWidth(850); - infoBox.Draw(target, 50, 100); + infoBox.Draw(target, 50, 100, sago::SagoTextField::Alignment::left, &globalData.logicalResize); if (filenameField.GetText().length() > 0) { - DrawRectYellow(target, 40, 700, 50, 900); - filenameField.Draw(target, 50, 715); + DrawRectYellow(target, 40, 700, 50, 900, &globalData.logicalResize); + filenameField.Draw(target, 50, 715, sago::SagoTextField::Alignment::left, &globalData.logicalResize); } HelpCommonState::Draw(target); } @@ -112,9 +112,13 @@ void HelpCommonState::Update() { if (SDL_GetMouseState(nullptr,nullptr)&SDL_BUTTON(1) && bMouseUp) { bMouseUp = false; + int mousex; + int mousey; + globalData.logicalResize.PhysicalToLogical(globalData.mousex, globalData.mousey, mousex, mousey); + //The Score button: - if ((globalData.mousex>globalData.xsize-buttonOffset) && (globalData.mousexglobalData.ysize-buttonOffset) && (globalData.mouseyglobalData.xsize-buttonOffset) && (mousexglobalData.ysize-buttonOffset) && (mouseyGetSprite("help_controller"); - gamepad.Draw(target, SDL_GetTicks(), globalData.xsize/2-480/2, 100); + gamepad.Draw(target, SDL_GetTicks(), globalData.xsize/2-480/2, 100, &globalData.logicalResize); SDL_SetRenderDrawColor(target, 0, 0, 0, SDL_ALPHA_OPAQUE); - SDL_RenderDrawLine(target, 100+OFFSETX, 210, globalData.xsize/2-480/2+130, 210); - SDL_RenderDrawLine(target, 100+OFFSETX, 298, globalData.xsize/2-480/2+158, 298); - SDL_RenderDrawLine(target, 100+OFFSETX, 210, 100+OFFSETX, 400); - moveLabel.Draw(target, 100+OFFSETX, 404, sago::SagoTextField::Alignment::center); + RenderDrawLine(target, 100+OFFSETX, 210, globalData.xsize/2-480/2+130, 210); + RenderDrawLine(target, 100+OFFSETX, 298, globalData.xsize/2-480/2+158, 298); + RenderDrawLine(target, 100+OFFSETX, 210, 100+OFFSETX, 400); + moveLabel.Draw(target, 100+OFFSETX, 404, sago::SagoTextField::Alignment::center, sago::SagoTextField::VerticalAlignment::top, &globalData.logicalResize); //Push lines - SDL_RenderDrawLine(target, globalData.xsize/2-480/2+140, 90, globalData.xsize/2-480/2+140, 105); - SDL_RenderDrawLine(target, globalData.xsize/2+480/2-140, 90, globalData.xsize/2+480/2-140, 105); - SDL_RenderDrawLine(target, globalData.xsize/2-480/2+140-38, 90, globalData.xsize/2+480/2-140+38, 90); - SDL_RenderDrawLine(target, globalData.xsize/2-480/2+140-38, 90, globalData.xsize/2-480/2+140-38, 110); - SDL_RenderDrawLine(target, globalData.xsize/2+480/2-140+38, 90, globalData.xsize/2+480/2-140+38, 110); - SDL_RenderDrawLine(target, globalData.xsize/2, 80, globalData.xsize/2, 90); - pushLabel.Draw(target, globalData.xsize/2, 80, sago::SagoTextField::Alignment::center, sago::SagoTextField::VerticalAlignment::bottom); + RenderDrawLine(target, globalData.xsize/2-480/2+140, 90, globalData.xsize/2-480/2+140, 105); + RenderDrawLine(target, globalData.xsize/2+480/2-140, 90, globalData.xsize/2+480/2-140, 105); + RenderDrawLine(target, globalData.xsize/2-480/2+140-38, 90, globalData.xsize/2+480/2-140+38, 90); + RenderDrawLine(target, globalData.xsize/2-480/2+140-38, 90, globalData.xsize/2-480/2+140-38, 110); + RenderDrawLine(target, globalData.xsize/2+480/2-140+38, 90, globalData.xsize/2+480/2-140+38, 110); + RenderDrawLine(target, globalData.xsize/2, 80, globalData.xsize/2, 90); + pushLabel.Draw(target, globalData.xsize/2, 80, sago::SagoTextField::Alignment::center, sago::SagoTextField::VerticalAlignment::bottom, &globalData.logicalResize); //Back lines - SDL_RenderDrawLine(target, 800+OFFSETX, 158, 800+OFFSETX, 207); - SDL_RenderDrawLine(target, 490+OFFSETX, 180, 800+OFFSETX, 180); - SDL_RenderDrawLine(target, 490+OFFSETX, 180, 490+OFFSETX, 195); - SDL_RenderDrawLine(target, 663+OFFSETX, 207, 800+OFFSETX, 207); - backLabel.Draw(target, 800+OFFSETX, 156, sago::SagoTextField::Alignment::center, sago::SagoTextField::VerticalAlignment::bottom); - SDL_RenderDrawLine(target, 625+OFFSETX, 241, 900+OFFSETX, 241); - SDL_RenderDrawLine(target, 900+OFFSETX, 241, 900+OFFSETX, 400); - switchLabel.Draw(target, 900+OFFSETX, 404, sago::SagoTextField::Alignment::center); - confirmLabel.Draw(target, 900+OFFSETX, 404+30, sago::SagoTextField::Alignment::center); - supportedControllers.Draw(target, 10, 600); + RenderDrawLine(target, 800+OFFSETX, 158, 800+OFFSETX, 207); + RenderDrawLine(target, 490+OFFSETX, 180, 800+OFFSETX, 180); + RenderDrawLine(target, 490+OFFSETX, 180, 490+OFFSETX, 195); + RenderDrawLine(target, 663+OFFSETX, 207, 800+OFFSETX, 207); + backLabel.Draw(target, 800+OFFSETX, 156, sago::SagoTextField::Alignment::center, sago::SagoTextField::VerticalAlignment::bottom, &globalData.logicalResize); + RenderDrawLine(target, 625+OFFSETX, 241, 900+OFFSETX, 241); + RenderDrawLine(target, 900+OFFSETX, 241, 900+OFFSETX, 400); + switchLabel.Draw(target, 900+OFFSETX, 404, sago::SagoTextField::Alignment::center, sago::SagoTextField::VerticalAlignment::top, &globalData.logicalResize); + confirmLabel.Draw(target, 900+OFFSETX, 404+30, sago::SagoTextField::Alignment::center, sago::SagoTextField::VerticalAlignment::top, &globalData.logicalResize); + supportedControllers.Draw(target, 10, 600, sago::SagoTextField::Alignment::left, &globalData.logicalResize); HelpCommonState::Draw(target); } diff --git a/source/code/HelpHowtoState.cpp b/source/code/HelpHowtoState.cpp index f705ed6..53716c3 100644 --- a/source/code/HelpHowtoState.cpp +++ b/source/code/HelpHowtoState.cpp @@ -48,9 +48,9 @@ static void RenderRowOfBricks(SDL_Renderer* target, const std::string& brickStr, brickChar = brickChar + 'a' - 'A'; } if (brickChar >= 'a' && brickChar <= 'g') { - globalData.bricks[brickChar - 'a'].Draw(target, tick, x+i*50, y); + globalData.bricks[brickChar - 'a'].Draw(target, tick, x+i*50, y, &globalData.logicalResize); if (bomb) { - globalData.spriteHolder->GetSprite("block_bomb").Draw(target, tick, x+i*50, y); + globalData.spriteHolder->GetSprite("block_bomb").Draw(target, tick, x+i*50, y, &globalData.logicalResize); } } } @@ -131,6 +131,12 @@ HelpHowtoState::~HelpHowtoState() { const double PI =3.141592653589793238463; +static void RenderDrawLine(SDL_Renderer * renderer, int x1, int y1, int x2, int y2) { + globalData.logicalResize.LogicalToPhysical(&x1, &y1); + globalData.logicalResize.LogicalToPhysical(&x2, &y2); + SDL_RenderDrawLine(renderer, x1, y1, x2, y2); +} + static void DrawArrow(SDL_Renderer* target, int x1, int y1, int x2, int y2) { double dx = x1-x2; double dy = y1-y2; @@ -140,33 +146,33 @@ static void DrawArrow(SDL_Renderer* target, int x1, int y1, int x2, int y2) { double angle= PI/4.0; double nx1 = dx * std::cos(angle) - dy * std::sin(angle) + x2; double ny1 = dx * std::sin(angle) + dy * std::cos(angle) + y2; - SDL_RenderDrawLine(target, x1, y1, x2, y2); - SDL_RenderDrawLine(target, nx1, ny1, x2, y2); + RenderDrawLine(target, x1, y1, x2, y2); + RenderDrawLine(target, nx1, ny1, x2, y2); nx1 = dx * std::cos(-angle) - dy * std::sin(-angle) + x2; ny1 = dx * std::sin(-angle) + dy * std::cos(-angle) + y2; - SDL_RenderDrawLine(target, nx1, ny1, x2, y2); + RenderDrawLine(target, nx1, ny1, x2, y2); } void HelpHowtoState::Draw(SDL_Renderer* target) { DrawBackground(target); SDL_SetRenderDrawColor(target, 0, 0, 0, SDL_ALPHA_OPAQUE); RenderRowOfBricks(target, switchAnimation.brickStr, 50, 50); - globalData.spriteHolder->GetSprite("cursor").Draw(target, SDL_GetTicks(), 50+switchAnimation.cursorPos*50, 50); - switchAnimationField.Draw(target, 50 +150+30, 50+25, sago::SagoTextField::Alignment::left, sago::SagoTextField::VerticalAlignment::center); + globalData.spriteHolder->GetSprite("cursor").Draw(target, SDL_GetTicks(), 50+switchAnimation.cursorPos*50, 50, &globalData.logicalResize); + switchAnimationField.Draw(target, 50 +150+30, 50+25, sago::SagoTextField::Alignment::left, sago::SagoTextField::VerticalAlignment::center, &globalData.logicalResize); RenderRowOfBricks(target, "adaa", 50, 150); - globalData.spriteHolder->GetSprite("cursor").Draw(target, SDL_GetTicks(), 50, 150); + globalData.spriteHolder->GetSprite("cursor").Draw(target, SDL_GetTicks(), 50, 150, &globalData.logicalResize); RenderRowOfBricks(target, "dAAA", 50+300, 150); DrawArrow(target, 50+200+25, 150+25, 50+300-25, 150+25); - clearRowfield.Draw(target, 600, 150+25, sago::SagoTextField::Alignment::left, sago::SagoTextField::VerticalAlignment::center); - comboField.Draw(target, 50+175, 410, sago::SagoTextField::Alignment::center); + clearRowfield.Draw(target, 600, 150+25, sago::SagoTextField::Alignment::left, sago::SagoTextField::VerticalAlignment::center, &globalData.logicalResize); + comboField.Draw(target, 50+175, 410, sago::SagoTextField::Alignment::center, sago::SagoTextField::VerticalAlignment::top, &globalData.logicalResize); MultiLineBlocks().addLine("ab").addLine("ba").addLine("ab").Render(target, 50, 250); - globalData.spriteHolder->GetSprite("cursor").Draw(target, SDL_GetTicks(), 50, 250+50); + globalData.spriteHolder->GetSprite("cursor").Draw(target, SDL_GetTicks(), 50, 250+50, &globalData.logicalResize); MultiLineBlocks().addLine("AB").addLine("AB").addLine("AB").Render(target, 50+200, 250); DrawArrow(target, 175, 325, 225, 325); MultiLineBlocks().addLine("a").addLine("b").addLine("e").Render(target, 50+400, 250); - globalData.spriteHolder->GetSprite("cursor").Draw(target, SDL_GetTicks(), 50+400, 250); + globalData.spriteHolder->GetSprite("cursor").Draw(target, SDL_GetTicks(), 50+400, 250, &globalData.logicalResize); MultiLineBlocks().addLine(" ").addLine("b").addLine("ea").Render(target, 50+400+200, 250); - dropField.Draw(target, 50+400+150, 410, sago::SagoTextField::Alignment::center); + dropField.Draw(target, 50+400+150, 410, sago::SagoTextField::Alignment::center, sago::SagoTextField::VerticalAlignment::top, &globalData.logicalResize); DrawArrow(target, 575, 325, 625, 325); DrawArrow(target, 475, 275, 525, 275); DrawArrow(target, 525, 275, 525, 375); @@ -176,12 +182,12 @@ void HelpHowtoState::Draw(SDL_Renderer* target) { MultiLineBlocks().addLine(" d").addLine(" F").addLine(" F").addLine("dFd").Render(target, 50+200, 500); MultiLineBlocks().addLine(" d").addLine(" ").addLine(" ").addLine("d d").Render(target, 50+200*2, 500); MultiLineBlocks().addLine(" ").addLine(" ").addLine(" ").addLine("DDD").Render(target, 50+200*3, 500); - globalData.spriteHolder->GetSprite("cursor").Draw(target, SDL_GetTicks(), 50, 650); + globalData.spriteHolder->GetSprite("cursor").Draw(target, SDL_GetTicks(), 50, 650, &globalData.logicalResize); DrawArrow(target, 200, 600, 250, 600); DrawArrow(target, 400, 600, 450, 600); DrawArrow(target, 600, 600, 650, 600); DrawArrow(target, 525, 525, 525, 675); - chainField.Draw(target, 400, 710, sago::SagoTextField::Alignment::center); + chainField.Draw(target, 400, 710, sago::SagoTextField::Alignment::center, sago::SagoTextField::VerticalAlignment::top, &globalData.logicalResize); HelpCommonState::Draw(target); } 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/ScoresDisplay.cpp b/source/code/ScoresDisplay.cpp index 4b2767e..e6038b9 100644 --- a/source/code/ScoresDisplay.cpp +++ b/source/code/ScoresDisplay.cpp @@ -50,7 +50,7 @@ sago::SagoTextField* ScoresDisplay::getCachedText(const std::string& text) { } void ScoresDisplay::Write(SDL_Renderer* target, int x, int y, const char* text) { - getCachedText(text)->Draw(target, x, y); + getCachedText(text)->Draw(target, x, y, sago::SagoTextField::Alignment::left, sago::SagoTextField::VerticalAlignment::top, &globalData.logicalResize); } @@ -264,18 +264,18 @@ void ScoresDisplay::Draw(SDL_Renderer* target) { const sago::SagoDataHolder* holder = &globalData.spriteHolder->GetDataHolder(); //Draw buttons: - globalData.bBack.Draw(globalData.screen, 0, backX, backY); + globalData.bBack.Draw(globalData.screen, 0, backX, backY, &globalData.logicalResize); static sago::SagoTextField backLabel; setButtonFont(holder, backLabel, _("Back")); - backLabel.Draw(globalData.screen, backX+60,backY+10, sago::SagoTextField::Alignment::center); - globalData.bNext.Draw(globalData.screen, 0, nextX, nextY); + backLabel.Draw(globalData.screen, backX+60,backY+10, sago::SagoTextField::Alignment::center, sago::SagoTextField::VerticalAlignment::top, &globalData.logicalResize); + globalData.bNext.Draw(globalData.screen, 0, nextX, nextY, &globalData.logicalResize); static sago::SagoTextField nextLabel; setButtonFont(holder, nextLabel, _("Next")); - nextLabel.Draw(globalData.screen, nextX+60, nextY+10, sago::SagoTextField::Alignment::center); + nextLabel.Draw(globalData.screen, nextX+60, nextY+10, sago::SagoTextField::Alignment::center, sago::SagoTextField::VerticalAlignment::top, &globalData.logicalResize); //Draw page number std::string pageXofY = fmt::format(_("Page {} of {}"), page+1, numberOfPages); - getCachedText(pageXofY)->Draw(globalData.screen, globalData.xsize/2, globalData.ysize-60, sago::SagoTextField::Alignment::center); + getCachedText(pageXofY)->Draw(globalData.screen, globalData.xsize/2, globalData.ysize-60, sago::SagoTextField::Alignment::center, sago::SagoTextField::VerticalAlignment::top, &globalData.logicalResize); HelpCommonState::Draw(target); } @@ -309,9 +309,12 @@ void ScoresDisplay::Update() { if (SDL_GetMouseState(nullptr,nullptr)&SDL_BUTTON(1) && bMouseUp) { bMouseUp = false; + int mousex; + int mousey; + globalData.logicalResize.PhysicalToLogical(globalData.mousex, globalData.mousey, mousex, mousey); //The back button: - if ((globalData.mousex>backX) && (globalData.mousexbackY) && (globalData.mouseybackX) && (mousexbackY) && (mouseynextX) && (globalData.mousexnextY) && (globalData.mouseynextX) && (mousexnextY) && (mousey=numberOfPages) { page = 0; diff --git a/source/code/global.hpp b/source/code/global.hpp index eb9c185..cfe4ede 100644 --- a/source/code/global.hpp +++ b/source/code/global.hpp @@ -26,6 +26,7 @@ http://www.blockattack.net #include #include "sago/SagoSpriteHolder.hpp" +#include "sago/SagoLogicalResize.hpp" #include "highscore.h" #include "sago/GameStateInterface.hpp" #include "TextManager.hpp" @@ -107,6 +108,7 @@ struct GlobalData { std::vector modList; ModInfo modinfo; Theme theme; + sago::SagoLogicalResize logicalResize; TextManager theTextManager; diff --git a/source/code/levelselect.cpp b/source/code/levelselect.cpp index 8a193f9..12b9c66 100644 --- a/source/code/levelselect.cpp +++ b/source/code/levelselect.cpp @@ -47,7 +47,7 @@ static sago::SagoTextField* getCachedText(const std::string& text) { } static void Write(SDL_Renderer* target, int x, int y, const char* text) { - getCachedText(text)->Draw(target, x, y); + getCachedText(text)->Draw(target, x, y, sago::SagoTextField::Alignment::left, sago::SagoTextField::VerticalAlignment::top, &globalData.logicalResize); } //The function that allows the player to choose PuzzleLevel @@ -80,7 +80,10 @@ int PuzzleLevelSelect(int Type) { SDL_Delay(1); auto ticks = SDL_GetTicks(); DrawBackground(globalData.screen); - globalData.iCheckBoxArea.Draw(globalData.screen,ticks,xplace,yplace); + int mousex; + int mousey; + globalData.logicalResize.PhysicalToLogical(globalData.mousex, globalData.mousey, mousex, mousey); + globalData.iCheckBoxArea.Draw(globalData.screen,ticks,xplace,yplace, &globalData.logicalResize); if (Type == 0) { Write(globalData.screen, xplace+12,yplace+2,_("Select Puzzle") ); } @@ -89,21 +92,22 @@ int PuzzleLevelSelect(int Type) { } //Now drow the fields you click in (and a V if clicked): for (int i = 0; i < nrOfLevels; i++) { - globalData.iLevelCheckBox.Draw(globalData.screen, ticks, xplace+10+(i%10)*50, yplace+60+(i/10)*50); + globalData.iLevelCheckBox.Draw(globalData.screen, ticks, xplace+10+(i%10)*50, yplace+60+(i/10)*50, &globalData.logicalResize); if (i==selected) { - globalData.iLevelCheckBoxMarked.Draw(globalData.screen, ticks, xplace+10+(i%10)*50, yplace+60+(i/10)*50); + globalData.iLevelCheckBoxMarked.Draw(globalData.screen, ticks, xplace+10+(i%10)*50, yplace+60+(i/10)*50, &globalData.logicalResize); } if (Type == 0 && PuzzleIsCleared(i)) { - globalData.iLevelCheck.Draw(globalData.screen,ticks, xplace+10+(i%10)*50, yplace+60+(i/10)*50); + globalData.iLevelCheck.Draw(globalData.screen,ticks, xplace+10+(i%10)*50, yplace+60+(i/10)*50, &globalData.logicalResize); } if (Type == 1 && IsStageCleared(i)) { - globalData.iLevelCheck.Draw(globalData.screen, ticks, xplace+10+(i%10)*50, yplace+60+(i/10)*50); + globalData.iLevelCheck.Draw(globalData.screen, ticks, xplace+10+(i%10)*50, yplace+60+(i/10)*50, &globalData.logicalResize); } } SDL_Event event; while ( SDL_PollEvent(&event) ) { UpdateMouseCoordinates(event, globalData.mousex, globalData.mousey); + globalData.logicalResize.PhysicalToLogical(globalData.mousex, globalData.mousey, mousex, mousey); if ( event.type == SDL_QUIT ) { Config::getInstance()->setShuttingDown(5); @@ -146,25 +150,25 @@ int PuzzleLevelSelect(int Type) { SDL_GetKeyboardState(nullptr); - if (globalData.mousex != oldmousex || globalData.mousey != oldmousey) { + if (mousex != oldmousex || mousey != oldmousey) { int tmpSelected = -1; int j; for (j = 0; (tmpSelected == -1) && ( (jReadSprites(globalData.modinfo.getModSpriteFiles()); @@ -274,10 +274,12 @@ void ResetFullscreen() { SDL_ShowCursor(SDL_DISABLE); } -static bool logicalRenderer = false; - void DrawBackground(SDL_Renderer* target) { SDL_RenderClear(target); + int w=1; + int h=1; + SDL_GetRendererOutputSize(target, &w, &h); + globalData.logicalResize.SetPhysicalSize(w, h); sago::SagoSprite background = globalData.spriteHolder->GetSprite(globalData.theme.background.background_sprite); if ( (double)globalData.xsize/globalData.ysize > 1.5 && globalData.theme.background.background_sprite_16x9.length()) { background = globalData.spriteHolder->GetSprite(globalData.theme.background.background_sprite_16x9); @@ -301,7 +303,9 @@ void DrawBackground(SDL_Renderer* target) { } return; } - background.DrawScaled(target, ticks, 0, 0, globalData.xsize, globalData.ysize); + SDL_Rect r = {0,0,globalData.xsize,globalData.ysize}; + globalData.logicalResize.LogicalToPhysical(r); + background.DrawScaled(target, ticks, r.x, r.y, r.w, r.h); } /** @@ -522,7 +526,7 @@ static void DrawBalls() { DrawIMG(globalData.iChainFrame, globalData.screen, x, y); getSmallInt(globalData.theTextManager.textArray[i].getText())->Draw(globalData.screen, x+12, y+7, - sago::SagoTextField::Alignment::center); + sago::SagoTextField::Alignment::center, sago::SagoTextField::VerticalAlignment::top, &globalData.logicalResize); } } } //DrawBalls @@ -739,7 +743,7 @@ void DrawEverything(int xsize, int ysize,BlockGameSdl* theGame, BlockGameSdl* th //draw exit - bExit.Draw(globalData.screen,SDL_GetTicks(), xsize-bExitOffset, ysize-bExitOffset); + bExit.Draw(globalData.screen,SDL_GetTicks(), xsize-bExitOffset, ysize-bExitOffset, &globalData.logicalResize); DrawBalls(); #if DEBUG @@ -1243,6 +1247,7 @@ int main(int argc, char* argv[]) { globalData.xsize = SIXTEEN_NINE_WIDTH; } globalData.ysize = SCREEN_HIGHT; + globalData.logicalResize = sago::SagoLogicalResize(globalData.xsize, globalData.ysize); sdlWindow = SDL_CreateWindow("Block Attack - Rise of the Blocks " VERSION_NUMBER, SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, @@ -1255,10 +1260,7 @@ int main(int argc, char* argv[]) { } SDL_Renderer* renderer = SDL_CreateRenderer(sdlWindow, -1, rendererFlags); dieOnNullptr(renderer, "Unable to create render"); - if (config.autoScale && !puzzleEditor) { - SDL_RenderSetLogicalSize(renderer, globalData.xsize, globalData.ysize); - logicalRenderer = true; - } + if (globalData.verboseLevel) { SDL_RendererInfo info; SDL_GetRendererInfo(renderer, &info); @@ -1540,6 +1542,9 @@ int runGame(Gametype gametype, int level) { globalData.theTextManager.update(); bool mustWriteScreenshot = false; + int mousex; + int mousey; + globalData.logicalResize.PhysicalToLogical(globalData.mousex, globalData.mousey, mousex, mousey); BlockGameAction a; a.tick = SDL_GetTicks(); @@ -1548,6 +1553,9 @@ int runGame(Gametype gametype, int level) { while ( SDL_PollEvent(&event) ) { UpdateMouseCoordinates(event, globalData.mousex, globalData.mousey); + int mousex; + int mousey; + globalData.logicalResize.PhysicalToLogical(globalData.mousex, globalData.mousey, mousex, mousey); if ( event.type == SDL_QUIT ) { Config::getInstance()->setShuttingDown(5); done = 1; @@ -1724,33 +1732,34 @@ int runGame(Gametype gametype, int level) { bool pressed = false; int x = 0; int y = 0; - theGame.GetBrickCoordinateFromMouse(pressed, event.button.x, event.button.y, x, y); + + theGame.GetBrickCoordinateFromMouse(pressed, mousex, mousey, x, y); if (pressed) { a.action = BlockGameAction::Action::MOUSE_DOWN; a.x = x; a.y = y; theGame.DoAction(a); } - theGame2.GetBrickCoordinateFromMouse(pressed, event.button.x, event.button.y, x, y); + theGame2.GetBrickCoordinateFromMouse(pressed, mousex, mousey, x, y); if (pressed) { a.action = BlockGameAction::Action::MOUSE_DOWN; a.x = x; a.y = y; theGame2.DoAction(a); } - mouseDownX = event.button.x; - mouseDownY = event.button.y; + mouseDownX = mousex; + mouseDownY = mousey; } if (event.button.button == SDL_BUTTON_RIGHT) { bool pressed = false; int x = 0; int y = 0; - theGame.GetBrickCoordinateFromMouse(pressed, event.button.x, event.button.y, x, y); + theGame.GetBrickCoordinateFromMouse(pressed, mousex, mousey, x, y); if (pressed) { a.action = BlockGameAction::Action::PUSH; theGame.DoAction(a); } - theGame2.GetBrickCoordinateFromMouse(pressed, event.button.x, event.button.y, x, y); + theGame2.GetBrickCoordinateFromMouse(pressed, mousex, mousey, x, y); if (pressed) { a.action = BlockGameAction::Action::PUSH; theGame2.DoAction(a); @@ -1759,8 +1768,8 @@ int runGame(Gametype gametype, int level) { } if (event.type == SDL_MOUSEBUTTONUP) { if (event.button.button == SDL_BUTTON_LEFT) { - int x = event.button.x; - int y = event.button.y; + int x = mousex; + int y = mousey; a.action = BlockGameAction::Action::MOUSE_UP; theGame.DoAction(a); theGame2.DoAction(a); @@ -1783,7 +1792,7 @@ int runGame(Gametype gametype, int level) { if (pressed) { int mx = 0; int my = 0; - theGame.GetBrickCoordinateFromMouse(pressed, event.motion.x, event.motion.y, mx, my); + theGame.GetBrickCoordinateFromMouse(pressed, mousex, mousey, mx, my); if (pressed) { if (mx != x) { a.action = BlockGameAction::Action::MOUSE_MOVE; @@ -1796,7 +1805,7 @@ int runGame(Gametype gametype, int level) { if (pressed) { int mx = 0; int my = 0; - theGame2.GetBrickCoordinateFromMouse(pressed, event.motion.x, event.motion.y, mx, my); + theGame2.GetBrickCoordinateFromMouse(pressed, mousex, mousey, mx, my); if (pressed) { if (mx != x) { a.action = BlockGameAction::Action::MOUSE_MOVE; @@ -1826,24 +1835,24 @@ int runGame(Gametype gametype, int level) { bMouseUp = false; DrawBackground(globalData.screen); - if (stageButtonStatus != SBdontShow && (globalData.mousex > theGame.GetTopX()+globalData.cordNextButton.x) - && (globalData.mousex < theGame.GetTopX()+globalData.cordNextButton.x+globalData.cordNextButton.xsize) - && (globalData.mousey > theGame.GetTopY()+globalData.cordNextButton.y) - && (globalData.mousey < theGame.GetTopY()+globalData.cordNextButton.y+globalData.cordNextButton.ysize)) { + if (stageButtonStatus != SBdontShow && (mousex > theGame.GetTopX()+globalData.cordNextButton.x) + && (mousex < theGame.GetTopX()+globalData.cordNextButton.x+globalData.cordNextButton.xsize) + && (mousey > theGame.GetTopY()+globalData.cordNextButton.y) + && (mousey < theGame.GetTopY()+globalData.cordNextButton.y+globalData.cordNextButton.ysize)) { //Clicked the next button after a stage clear or puzzle nextLevel(theGame, SDL_GetTicks()); } - if (stageButtonStatus != SBdontShow && (globalData.mousex > theGame.GetTopX()+globalData.cordRetryButton .x) - &&(globalData.mousex < theGame.GetTopX()+globalData.cordRetryButton.x+globalData.cordRetryButton.xsize) - &&(globalData.mousey > theGame.GetTopY()+globalData.cordRetryButton.y) - &&(globalData.mousey < theGame.GetTopY()+globalData.cordRetryButton.y+globalData.cordRetryButton.ysize)) { + if (stageButtonStatus != SBdontShow && (mousex > theGame.GetTopX()+globalData.cordRetryButton .x) + &&(mousex < theGame.GetTopX()+globalData.cordRetryButton.x+globalData.cordRetryButton.xsize) + &&(mousey > theGame.GetTopY()+globalData.cordRetryButton.y) + &&(mousey < theGame.GetTopY()+globalData.cordRetryButton.y+globalData.cordRetryButton.ysize)) { //Clicked the retry button retryLevel(theGame, SDL_GetTicks()); } - if (globalData.mousex > globalData.xsize-bExitOffset && globalData.mousex < globalData.xsize-bExitOffset+bExitSize && - globalData.mousey > globalData.ysize-bExitOffset && globalData.mousey < globalData.ysize-bExitOffset+bExitSize) { + if (mousex > globalData.xsize-bExitOffset && mousex < globalData.xsize-bExitOffset+bExitSize && + mousey > globalData.ysize-bExitOffset && mousey < globalData.ysize-bExitOffset+bExitSize) { done = 1; } } diff --git a/source/code/menudef_themes.cpp b/source/code/menudef_themes.cpp index e1833a1..7678ca4 100644 --- a/source/code/menudef_themes.cpp +++ b/source/code/menudef_themes.cpp @@ -74,7 +74,7 @@ public: Menu::Draw(target); game->DoPaintJob(); themeTitle.SetText(fmt::format(_("Theme: {}"), globalData.theme.theme_name)); - themeTitle.Draw(target, 10, globalData.ysize-50,sago::SagoTextField::Alignment::left); + themeTitle.Draw(target, 10, globalData.ysize-50,sago::SagoTextField::Alignment::left, sago::SagoTextField::VerticalAlignment::top, &globalData.logicalResize); } }; diff --git a/source/code/sago/SagoLogicalResize.hpp b/source/code/sago/SagoLogicalResize.hpp new file mode 100644 index 0000000..2d9074f --- /dev/null +++ b/source/code/sago/SagoLogicalResize.hpp @@ -0,0 +1,106 @@ +/* +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" + + +namespace sago { + +class SagoLogicalResize +{ +public: + SagoLogicalResize() : logical_width_(1), logical_height_(1), physical_width_(1), physical_height_(1) { SetScaleFactor(); } + SagoLogicalResize(int logical_width, int logical_height) + : logical_width_(std::max(1, logical_width)), logical_height_(std::max(1, logical_height)), physical_width_(1), physical_height_(1) { SetScaleFactor(); } + + 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(); + } + + void LogicalToPhysical(int logical_x, int logical_y, int &physical_x, int &physical_y) const + { + physical_x = logical_x; + physical_y = logical_y; + LogicalToPhysical(&physical_x, &physical_y); + } + + void LogicalToPhysical(int *x, int *y) const + { + if (x) { + *x = *x * scale_factor_ + left_margin_; + } + if (y) { + *y = *y * scale_factor_ + top_margin_; + } + } + + void LogicalToPhysical(SDL_Rect &inout) const + { + SDL_Rect input = inout; + LogicalToPhysical(&inout.x, &inout.y); + LogicalToPhysical(input.x + input.w + 1, input.y + input.h + 1, inout.w, inout.h); + inout.w -= inout.x - 1; + inout.h -= inout.y - 1; + } + + void PhysicalToLogical(int physical_x, int physical_y, int &logical_x, int &logical_y) const + { + logical_x = (physical_x - left_margin_) / scale_factor_; + logical_y = (physical_y - top_margin_) / scale_factor_; + } + + int GetTopMargin() const + { + return top_margin_; + } + + int GetLeftMargin() const + { + return left_margin_; + } + +private: + void SetScaleFactor() + { + scale_factor_ = std::min(physical_width_ / logical_width_, physical_height_ / logical_height_); + left_margin_ = (physical_width_ - logical_width_ * scale_factor_) / 2; + top_margin_ = (physical_height_ - logical_height_ * scale_factor_) / 2; + } + + double scale_factor_; + int top_margin_; + int left_margin_; + double logical_width_; + double logical_height_; + double physical_width_; + double physical_height_; +}; + +} // namespace sago \ No newline at end of file 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/SagoTextBox.cpp b/source/code/sago/SagoTextBox.cpp index 8ad56fb..41a1c6e 100644 --- a/source/code/sago/SagoTextBox.cpp +++ b/source/code/sago/SagoTextBox.cpp @@ -177,14 +177,14 @@ void SagoTextBox::UpdateCache() { data->renderedText = data->text; } -void SagoTextBox::Draw(SDL_Renderer* target, int x, int y, SagoTextField::Alignment alignment ) { +void SagoTextBox::Draw(SDL_Renderer* target, int x, int y, SagoTextField::Alignment alignment, SagoLogicalResize* resize ) { if (data->text != data->renderedText) { UpdateCache(); } TTF_Font* font = data->tex->getFontPtr(data->fontName, data->fontSize); int lineSkip = TTF_FontLineSkip(font); for (size_t i = 0; i < data->lines.size(); ++i) { - data->lines[i].Draw(target, x, y+i*lineSkip, alignment); + data->lines[i].Draw(target, x, y+i*lineSkip, alignment, sago::SagoTextField::VerticalAlignment::top, resize); } } diff --git a/source/code/sago/SagoTextBox.hpp b/source/code/sago/SagoTextBox.hpp index 6882006..4532a4a 100644 --- a/source/code/sago/SagoTextBox.hpp +++ b/source/code/sago/SagoTextBox.hpp @@ -57,7 +57,7 @@ public: */ void SetMaxWidth(int width); const std::string& GetText() const; - void Draw(SDL_Renderer* target, int x, int y, SagoTextField::Alignment alignment = SagoTextField::Alignment::left); + void Draw(SDL_Renderer* target, int x, int y, SagoTextField::Alignment alignment = SagoTextField::Alignment::left, SagoLogicalResize* resize = nullptr); void UpdateCache(); private: void AppendLineToCache(const std::string& text); 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.