From a26d86d0b0a928ce9218b02b443ea920372529e0 Mon Sep 17 00:00:00 2001 From: sigonasr2 Date: Thu, 21 Dec 2023 10:26:18 -0600 Subject: [PATCH] Separate GetTextSize and GetWrappedTextSize functions for clarity. Fix sizing comparisons for wrapping text. Fixed issue with menu destinations not properly being assigned on certain buttons. --- Crawler/InventoryWindow.cpp | 4 +- Crawler/MenuComponent.cpp | 6 +-- Crawler/MenuComponent.h | 12 ++--- Crawler/MenuItemButton.h | 2 +- Crawler/MenuItemItemButton.h | 2 +- Crawler/MenuLabel.h | 9 ++-- Crawler/MerchantWindow.cpp | 4 +- Crawler/PlayerMoneyLabel.h | 1 + Crawler/Version.h | 2 +- Crawler/olcPGEX_ViewPort.h | 4 +- Crawler/olcPixelGameEngine.h | 93 +++++++++++++++++++++++++++++------- 11 files changed, 99 insertions(+), 40 deletions(-) diff --git a/Crawler/InventoryWindow.cpp b/Crawler/InventoryWindow.cpp index c9dd404e..48031b2b 100644 --- a/Crawler/InventoryWindow.cpp +++ b/Crawler/InventoryWindow.cpp @@ -125,11 +125,11 @@ void Menu::InitializeInventoryWindow(){ #pragma endregion #pragma region Money Display - vf2d moneyIconPos={224+inventoryDescriptionWidth-24,28+inventoryWindow->size.y-44+8}; + vf2d moneyIconPos={224+inventoryDescriptionWidth-24,28+inventoryWindow->size.y-44+6}; auto moneyIcon=inventoryWindow->ADD("Money Icon",MenuIconButton)({moneyIconPos,{24,24}},GFX["money.png"].Decal(),DO_NOTHING,IconButtonAttr::NOT_SELECTABLE|IconButtonAttr::NO_OUTLINE|IconButtonAttr::NO_BACKGROUND)END; std::string moneyText=std::to_string(game->GetPlayer()->GetMoney()); vf2d moneyTextSize=game->GetTextSizeProp(moneyText)*2; - auto moneyDisplay=inventoryWindow->ADD("Money Label",PlayerMoneyLabel)({moneyIconPos-vf2d{2+moneyTextSize.x,0},moneyTextSize},2,SHADOW|LEFT_ALIGN)END; + auto moneyDisplay=inventoryWindow->ADD("Money Label",PlayerMoneyLabel)({moneyIconPos-vf2d{2+moneyTextSize.x,-2},moneyTextSize},2,SHADOW|LEFT_ALIGN)END; moneyDisplay->SetRightAlignment(true); Player::AddMoneyListener(moneyDisplay); #pragma endregion diff --git a/Crawler/MenuComponent.cpp b/Crawler/MenuComponent.cpp index 931260d1..e3ef4365 100644 --- a/Crawler/MenuComponent.cpp +++ b/Crawler/MenuComponent.cpp @@ -119,15 +119,15 @@ void MenuComponent::DrawDecal(ViewPort&window,bool focused){ } if(showDefaultLabel){ vf2d adjustedScale=labelScaling; - vi2d labelTextSize=game->GetTextSizeProp(label,rect.size.x); + vi2d labelTextSize=vf2d(game->GetTextSizeProp(label))*adjustedScale; if(fitToLabel){ - float sizeRatio=((labelTextSize*adjustedScale).x)/(rect.size.x-2); + float sizeRatio=((vf2d(labelTextSize)*adjustedScale).x)/(rect.size.x-2); if(sizeRatio>1){ adjustedScale.x/=sizeRatio; } } - window.DrawStringPropDecal(rect.pos+V(A::DRAW_OFFSET)+rect.size/2-vf2d(labelTextSize)/2.f*adjustedScale,label,WHITE,adjustedScale,rect.size.x); + window.DrawStringPropDecal(rect.pos+V(A::DRAW_OFFSET)+rect.size/2-vf2d(labelTextSize)/2.f,label,WHITE,adjustedScale); } if(selected){ switch(selectionType){ diff --git a/Crawler/MenuComponent.h b/Crawler/MenuComponent.h index 6139c848..59d9f602 100644 --- a/Crawler/MenuComponent.h +++ b/Crawler/MenuComponent.h @@ -47,12 +47,12 @@ enum class ButtonAttr{ }; enum class ComponentAttr{ - NONE= 0b00000, - LEFT_ALIGN= 0b00001, //Labels are centered by default. - SHADOW= 0b00010, //Adds shadows to the label text. - OUTLINE= 0b00100, //Adds an outline around the component. - BACKGROUND= 0b01000, //Renders the background of the menu theme for this component. - FIT_TO_LABEL= 0b10000, //Scales the text horizontally to fit the label if the text takes up more space rather than wrapping. + NONE= 0b000000, + LEFT_ALIGN= 0b000001, //Labels are centered by default. + SHADOW= 0b000010, //Adds shadows to the label text. + OUTLINE= 0b000100, //Adds an outline around the component. + BACKGROUND= 0b001000, //Renders the background of the menu theme for this component. + FIT_TO_LABEL= 0b010000, //Scales the text horizontally to fit the label if the text takes up more space rather than wrapping. }; enum class SelectionType{ diff --git a/Crawler/MenuItemButton.h b/Crawler/MenuItemButton.h index cdea42b4..cefbfe40 100644 --- a/Crawler/MenuItemButton.h +++ b/Crawler/MenuItemButton.h @@ -141,7 +141,7 @@ protected: vf2d textSize=vf2d(game->GetTextSizeProp(quantityText))*quantityTextScale; vf2d drawPos=rect.pos+rect.size-textSize; if(itemQuantity!=INFINITE){ - window.DrawShadowStringDecal(drawPos,quantityText,WHITE,BLACK,quantityTextScale,quantityTextScale.x); + window.DrawShadowStringDecal(drawPos,quantityText,WHITE,BLACK,quantityTextScale); } } } diff --git a/Crawler/MenuItemItemButton.h b/Crawler/MenuItemItemButton.h index 3d882266..68eb8c77 100644 --- a/Crawler/MenuItemItemButton.h +++ b/Crawler/MenuItemItemButton.h @@ -140,7 +140,7 @@ protected: vf2d textSize=vf2d(game->GetTextSizeProp(quantityText))*quantityTextScale; vf2d drawPos=rect.pos+rect.size-textSize; if(itemRef.get().Amt()!=INFINITE){ - window.DrawShadowStringDecal(drawPos,quantityText,WHITE,BLACK,quantityTextScale,quantityTextScale.x); + window.DrawShadowStringDecal(drawPos,quantityText,WHITE,BLACK,quantityTextScale); } } } diff --git a/Crawler/MenuLabel.h b/Crawler/MenuLabel.h index 314ed5dd..67a71580 100644 --- a/Crawler/MenuLabel.h +++ b/Crawler/MenuLabel.h @@ -67,24 +67,25 @@ protected: inline virtual void DrawDecal(ViewPort&window,bool focused)override{ MenuComponent::DrawDecal(window,focused); vf2d adjustedScale={scale,scale}; - vf2d labelTextSize=game->GetTextSizeProp(label,rect.size.x); + vf2d labelTextSize=vf2d(game->GetWrappedTextSizeProp(label,rect.size.x,adjustedScale.x)); if(fitToLabel){ float sizeRatio=((labelTextSize*adjustedScale).x)/(rect.size.x-2); if(sizeRatio>1){ adjustedScale.x/=sizeRatio; } + labelTextSize=vf2d(game->GetTextSizeProp(label)*adjustedScale); } - vf2d drawPos=rect.middle()-vf2d{labelTextSize}*float(adjustedScale.x)/2; //Assume centered. + vf2d drawPos=rect.middle()-vf2d{labelTextSize}/2; //Assume centered. if(!centered){ drawPos=vf2d{rect.pos.x+2,rect.middle().y-labelTextSize.y/2}; //We should at least vertically align here. } if(shadow){ - window.DrawShadowStringPropDecal(drawPos,label,WHITE,BLACK,adjustedScale,rect.size.x); + window.DrawShadowStringPropDecal(drawPos,label,WHITE,BLACK,adjustedScale,fitToLabel?std::numeric_limits::max():rect.size.x); }else{ - window.DrawStringPropDecal(drawPos,label,WHITE,adjustedScale,rect.size.x); + window.DrawStringPropDecal(drawPos,label,WHITE,adjustedScale,fitToLabel?std::numeric_limits::max():rect.size.x); } } }; \ No newline at end of file diff --git a/Crawler/MerchantWindow.cpp b/Crawler/MerchantWindow.cpp index 17ae43e4..8e644b41 100644 --- a/Crawler/MerchantWindow.cpp +++ b/Crawler/MerchantWindow.cpp @@ -103,11 +103,11 @@ void Menu::InitializeMerchantWindow(){ #pragma endregion #pragma region Money Display - vf2d moneyIconPos={224+inventoryDescriptionWidth-24,28+merchantWindow->size.y-44+8}; + vf2d moneyIconPos={224+inventoryDescriptionWidth-24,28+merchantWindow->size.y-44+6}; auto moneyIcon=merchantWindow->ADD("Money Icon",MenuIconButton)({moneyIconPos,{24,24}},GFX["money.png"].Decal(),DO_NOTHING,IconButtonAttr::NOT_SELECTABLE|IconButtonAttr::NO_OUTLINE|IconButtonAttr::NO_BACKGROUND)END; std::string moneyText=std::to_string(game->GetPlayer()->GetMoney()); vf2d moneyTextSize=game->GetTextSizeProp(moneyText)*2; - auto moneyDisplay=merchantWindow->ADD("Money Label",PlayerMoneyLabel)({moneyIconPos-vf2d{2+moneyTextSize.x,0},moneyTextSize},2,ComponentAttr::SHADOW|ComponentAttr::LEFT_ALIGN)END; + auto moneyDisplay=merchantWindow->ADD("Money Label",PlayerMoneyLabel)({moneyIconPos-vf2d{2+moneyTextSize.x,-2},moneyTextSize},2,ComponentAttr::SHADOW|ComponentAttr::LEFT_ALIGN)END; moneyDisplay->SetRightAlignment(true); Player::AddMoneyListener(moneyDisplay); #pragma endregion diff --git a/Crawler/PlayerMoneyLabel.h b/Crawler/PlayerMoneyLabel.h index f9ea3c32..13747d04 100644 --- a/Crawler/PlayerMoneyLabel.h +++ b/Crawler/PlayerMoneyLabel.h @@ -53,6 +53,7 @@ public: std::string moneyText=std::to_string(newMoney); vf2d moneyTextSize=game->GetTextSizeProp(moneyText)*scale; rect.pos.x=anchorPointX-moneyTextSize.x; + rect.size=moneyTextSize; } inline void SetRightAlignment(bool rightAligned){ diff --git a/Crawler/Version.h b/Crawler/Version.h index bd6ae5da..70a8ef33 100644 --- a/Crawler/Version.h +++ b/Crawler/Version.h @@ -39,7 +39,7 @@ All rights reserved. #define VERSION_MAJOR 0 #define VERSION_MINOR 2 #define VERSION_PATCH 1 -#define VERSION_BUILD 4334 +#define VERSION_BUILD 4372 #define stringify(a) stringify_(a) #define stringify_(a) #a diff --git a/Crawler/olcPGEX_ViewPort.h b/Crawler/olcPGEX_ViewPort.h index 43bfb70a..290b60cb 100644 --- a/Crawler/olcPGEX_ViewPort.h +++ b/Crawler/olcPGEX_ViewPort.h @@ -708,7 +708,7 @@ void olc::ViewPort::DrawStringDecal(const olc::vf2d& pos, std::string_view sText int32_t ox = (c - 32) % 16; int32_t oy = (c - 32) / 16; planningMarker.x += 8.0f * scale.x; - if(planningMarker.x>=width){ + if(planningMarker.x>width){ if(drawingMarker.x==0){ //The text has overflowed a full line, so we have to dump the line. for(PixelGameEngine::StringDecalData&letter:letters){ DrawPartialDecal(pos + drawingMarker, pge->GetFontDecal(), letter.sourcePos, letter.sourceSize, scale, letter.col); @@ -834,7 +834,7 @@ void olc::ViewPort::DrawStringPropDecal(const olc::vf2d& pos, std::string_view s int32_t ox = (c - 32) % 16; int32_t oy = (c - 32) / 16; planningMarker.x += float(pge->vFontSpacing[c - 32].y) * scale.x; - if(planningMarker.x>=width){ + if(planningMarker.x>width){ if(drawingMarker.x==0){ //The text has overflowed a full line, so we have to dump the line. for(PixelGameEngine::StringDecalData&letter:letters){ DrawPartialDecal(pos + drawingMarker, pge->GetFontDecal(), letter.sourcePos, letter.sourceSize, scale, letter.col); diff --git a/Crawler/olcPixelGameEngine.h b/Crawler/olcPixelGameEngine.h index 5eadcf8d..340f42de 100644 --- a/Crawler/olcPixelGameEngine.h +++ b/Crawler/olcPixelGameEngine.h @@ -1120,8 +1120,10 @@ namespace olc void DrawShadowString(const olc::vi2d& pos, const std::string& sText, Pixel col = olc::WHITE, const Pixel shadowCol = olc::BLACK, const olc::vf2d& scale = { 1.0f, 1.0f },const float shadowSizeFactor=1); void DrawStringProp(int32_t x, int32_t y, const std::string& sText, Pixel col = olc::WHITE, uint32_t scale = 1); void DrawShadowStringProp(const olc::vi2d& pos, const std::string& sText, Pixel col = olc::WHITE, const Pixel shadowCol = olc::BLACK, const olc::vf2d& scale = { 1.0f, 1.0f },const float shadowSizeFactor=1); - olc::vi2d GetTextSize(std::string_view s,const int width=std::numeric_limits::max()); - olc::vi2d GetTextSizeProp(std::string_view s,const int width=std::numeric_limits::max()); + olc::vi2d GetTextSize(std::string_view s); + olc::vi2d GetTextSizeProp(std::string_view s); + olc::vi2d GetWrappedTextSize(std::string_view s,const float width=std::numeric_limits::max(),const float scale=1); + olc::vi2d GetWrappedTextSizeProp(std::string_view s,const float width=std::numeric_limits::max(),const float scale=1); void DrawString(const olc::vi2d& pos, const std::string& sText, Pixel col = olc::WHITE, uint32_t scale = 1); void DrawString(int32_t x, int32_t y, const std::string& sText, Pixel col = olc::WHITE, uint32_t scale = 1); @@ -3431,7 +3433,7 @@ namespace olc int32_t ox = (c - 32) % 16; int32_t oy = (c - 32) / 16; planningMarker.x += 8.0f * scale.x; - if(planningMarker.x>=width){ + if(planningMarker.x>width){ if(drawingMarker.x==0){ //The text has overflowed a full line, so we have to dump the line. for(PixelGameEngine::StringDecalData&letter:letters){ DrawPartialDecal(pos + drawingMarker, fontRenderable.Decal(), letter.sourcePos, letter.sourceSize, scale, letter.col); @@ -3536,7 +3538,7 @@ namespace olc int32_t ox = (c - 32) % 16; int32_t oy = (c - 32) / 16; planningMarker.x += float(vFontSpacing[c - 32].y) * scale.x; - if(planningMarker.x>=width){ + if(planningMarker.x>width){ if(drawingMarker.x==0){ //The text has overflowed a full line, so we have to dump the line. for(PixelGameEngine::StringDecalData&letter:letters){ DrawPartialDecal(pos + drawingMarker, GetFontDecal(), letter.sourcePos, letter.sourceSize, scale, letter.col); @@ -3764,10 +3766,11 @@ namespace olc DrawRotatedStringPropDecal(pos, sText,fAngle,center,col,scale); } - olc::vi2d PixelGameEngine::GetTextSize(std::string_view s,const int width) + olc::vi2d PixelGameEngine::GetWrappedTextSize(std::string_view s,const float width,const float scale) { + float adjustedWidth=width/scale; int lettersWidth=0; - int maxWidth=0; + float maxWidth=0; bool wrappingOccurred=false; olc::vf2d planningMarker = { 0.0f, 0.0f }; olc::vf2d drawingMarker = { 0.0f, 0.0f }; @@ -3786,7 +3789,7 @@ namespace olc if(wrappingOccurred){ if(c!=' '&&c!='\t'){ wrappingOccurred=false; - maxWidth=std::max(maxWidth,int(drawingMarker.x)); + maxWidth=std::max(maxWidth,drawingMarker.x); }else{ continue; } @@ -3817,11 +3820,11 @@ namespace olc else { planningMarker.x += 8.0f; - if(planningMarker.x>=width){ + if(planningMarker.x>adjustedWidth){ if(drawingMarker.x==0){ //The text has overflowed a full line, so we have to dump the line. drawingMarker.x+=lettersWidth; lettersWidth=0; - maxWidth=std::max(maxWidth,int(drawingMarker.x)); + maxWidth=std::max(maxWidth,drawingMarker.x); } planningMarker.x = 0; planningMarker.y += 8.0f; drawingMarker=planningMarker; @@ -3832,8 +3835,33 @@ namespace olc } } drawingMarker.x += lettersWidth; - maxWidth=std::max(maxWidth,int(drawingMarker.x)); - return {maxWidth,int(planningMarker.y+8)}; + return vi2d(vf2d{maxWidth,planningMarker.y+8}*scale); + } + + olc::vi2d PixelGameEngine::GetTextSize(std::string_view s) + { + olc::vi2d size = { 0,1 }; + olc::vi2d pos = { 0,1 }; + for (int skip=0;auto c : s) + { + if(skip){ + skip--; + continue; + } + if(c=='\r')continue; //Ignore carriage returns. Stupid Linux. + if (c == '\n') { pos.y++; pos.x = 0; } + else if (c == '\t') { pos.x += nTabSizeInSpaces; } + else if(c<0)continue; + else if (c=='#') + { + skip=6; + continue; + } + else pos.x++; + size.x = std::max(size.x, pos.x); + size.y = std::max(size.y, pos.y); + } + return size * 8; } void PixelGameEngine::DrawString(const olc::vi2d& pos, const std::string& sText, Pixel col, uint32_t scale) @@ -3925,10 +3953,39 @@ namespace olc SetPixelMode(m); } - olc::vi2d PixelGameEngine::GetTextSizeProp(std::string_view s,const int width) + olc::vi2d PixelGameEngine::GetTextSizeProp(std::string_view s) + { + olc::vi2d size = { 0,1 }; + olc::vi2d pos = { 0,1 }; + for (int skip=0;auto c : s) + { + if(skip){ + skip--; + continue; + } + if(c=='\r')continue; //Ignore carriage returns. Stupid Linux. + if (c == '\n') { pos.y += 1; pos.x = 0; } + else if (c == '\t') { pos.x += nTabSizeInSpaces * 8; } + else if(c<0)continue; + else if (c=='#') + { + skip=6; + continue; + } + else pos.x += vFontSpacing[c - 32].y; + size.x = std::max(size.x, pos.x); + size.y = std::max(size.y, pos.y); + } + + size.y *= 8; + return size; + } + + olc::vi2d PixelGameEngine::GetWrappedTextSizeProp(std::string_view s,const float width,const float scale) { + float adjustedWidth=width/scale; int lettersWidth=0; - int maxWidth=0; + float maxWidth=0; bool wrappingOccurred=false; olc::vf2d planningMarker = { 0.0f, 0.0f }; olc::vf2d drawingMarker = { 0.0f, 0.0f }; @@ -3943,7 +4000,7 @@ namespace olc drawingMarker.x+=lettersWidth; lettersWidth=0; wrappingOccurred=false; - maxWidth=std::max(maxWidth,int(drawingMarker.x)); + maxWidth=std::max(maxWidth,drawingMarker.x); } if(wrappingOccurred){ if(c!=' '&&c!='\t'){ @@ -3978,11 +4035,11 @@ namespace olc else { planningMarker.x += vFontSpacing[c-32].y; - if(planningMarker.x>=width){ + if(planningMarker.x>adjustedWidth){ if(drawingMarker.x==0){ //The text has overflowed a full line, so we have to dump the line. drawingMarker.x+=lettersWidth; lettersWidth=0; - maxWidth=std::max(maxWidth,int(drawingMarker.x)); + maxWidth=std::max(maxWidth,drawingMarker.x); } planningMarker.x = 0; planningMarker.y += 8.0f; drawingMarker=planningMarker; @@ -3993,8 +4050,8 @@ namespace olc } } drawingMarker.x += lettersWidth; - maxWidth=std::max(maxWidth,int(drawingMarker.x)); - return {maxWidth,int(planningMarker.y+8)}; + maxWidth=std::max(maxWidth,drawingMarker.x); + return vi2d(vf2d{maxWidth,planningMarker.y+8}*scale); } void PixelGameEngine::DrawStringProp(const olc::vi2d& pos, const std::string& sText, Pixel col, uint32_t scale)