Implemented string view changes for internal drawing functions and added wrapping support and parameters for draw functions.

pull/28/head
sigonasr2 12 months ago
parent 08e60f2351
commit d29f7d47bd
  1. 10
      Crawler/InventoryConsumableWindow.cpp
  2. 6
      Crawler/MenuComponent.cpp
  3. 16
      Crawler/MenuLabel.h
  4. 28
      Crawler/State_GameRun.cpp
  5. 2
      Crawler/Version.h
  6. 146
      Crawler/olcPGEX_ViewPort.h
  7. 286
      Crawler/olcPixelGameEngine.h
  8. BIN
      x64/Release/Crawler.exe

@ -55,7 +55,7 @@ void Menu::InitializeConsumableInventoryWindow(){
inventoryWindow->I(A::LOADOUT_SLOT)=0; inventoryWindow->I(A::LOADOUT_SLOT)=0;
auto consumableWindow=inventoryWindow->ADD("inventory",InventoryScrollableWindowComponent)({{1,20},{windowSize.x,96.f}},"Consumables","itemName","itemDescription", auto consumableWindow=inventoryWindow->ADD("inventory",InventoryScrollableWindowComponent)({{0,15},{windowSize.x,96.f}},"Consumables","itemName","itemDescription",
[&](MenuFuncData data){ [&](MenuFuncData data){
MenuItemButton*button=(MenuItemButton*)data.component; MenuItemButton*button=(MenuItemButton*)data.component;
data.game->ClearLoadoutItem(data.menu.I(A::LOADOUT_SLOT)); data.game->ClearLoadoutItem(data.menu.I(A::LOADOUT_SLOT));
@ -81,9 +81,9 @@ void Menu::InitializeConsumableInventoryWindow(){
Menu::AddInventoryListener(consumableWindow,"Consumables"); Menu::AddInventoryListener(consumableWindow,"Consumables");
//We don't have to actually populate the inventory list because now when an item gets added, it will automatically add the correct component in for us. //We don't have to actually populate the inventory list because now when an item gets added, it will automatically add the correct component in for us.
inventoryWindow->ADD("Inventory Type Label",MenuLabel)({{0,0},{windowSize.x-1,18}},"Consumables",2,ComponentAttr::SHADOW|ComponentAttr::BACKGROUND|ComponentAttr::OUTLINE)END; inventoryWindow->ADD("Inventory Type Label",MenuLabel)({{0,-5},{windowSize.x-1,18}},"Consumables",2,ComponentAttr::SHADOW|ComponentAttr::BACKGROUND|ComponentAttr::OUTLINE)END;
inventoryWindow->ADD("itemName",MenuLabel)(geom2d::rect<float>(vf2d{2,95.f},{windowSize.x-4,windowSize.y-108}),"",1,ComponentAttr::SHADOW)END; inventoryWindow->ADD("itemName",MenuLabel)(geom2d::rect<float>(vf2d{2,90.f},{windowSize.x-4,windowSize.y-108}),"",1,ComponentAttr::SHADOW)END;
inventoryWindow->ADD("itemDescription",MenuLabel)(geom2d::rect<float>(vf2d{2,122.f},{windowSize.x-4,windowSize.y-108}),"",1,ComponentAttr::SHADOW)END; inventoryWindow->ADD("itemDescription",MenuLabel)(geom2d::rect<float>(vf2d{2,117.f},{windowSize.x-4,windowSize.y-108}),"",1,ComponentAttr::SHADOW)END;
auto okButton=inventoryWindow->ADD("OK Button",MenuComponent)({{windowSize.x/2-24,178.f},{48,12}},"Ok",[](MenuFuncData data){Menu::CloseMenu();return true;})END; auto okButton=inventoryWindow->ADD("OK Button",MenuComponent)({{windowSize.x/2-24,173.f},{48,12}},"Ok",[](MenuFuncData data){Menu::CloseMenu();return true;})END;
} }

@ -119,13 +119,15 @@ void MenuComponent::DrawDecal(ViewPort&window,bool focused){
} }
if(showDefaultLabel){ if(showDefaultLabel){
vf2d adjustedScale=labelScaling; vf2d adjustedScale=labelScaling;
vi2d labelTextSize=game->GetTextSizeProp(label,rect.size.x);
if(fitToLabel){ if(fitToLabel){
float sizeRatio=((game->GetTextSizeProp(label)*adjustedScale).x)/(rect.size.x-2); float sizeRatio=((labelTextSize*adjustedScale).x)/(rect.size.x-2);
if(sizeRatio>1){ if(sizeRatio>1){
adjustedScale.x/=sizeRatio; adjustedScale.x/=sizeRatio;
} }
} }
window.DrawStringPropDecal(rect.pos+V(A::DRAW_OFFSET)+rect.size/2-vf2d(game->GetTextSizeProp(label))/2.f*adjustedScale,label,WHITE,adjustedScale); window.DrawStringPropDecal(rect.pos+V(A::DRAW_OFFSET)+rect.size/2-vf2d(labelTextSize)/2.f*adjustedScale,label,WHITE,adjustedScale,rect.size.x);
} }
if(selected){ if(selected){
switch(selectionType){ switch(selectionType){

@ -66,27 +66,25 @@ protected:
} }
inline virtual void DrawDecal(ViewPort&window,bool focused)override{ inline virtual void DrawDecal(ViewPort&window,bool focused)override{
MenuComponent::DrawDecal(window,focused); MenuComponent::DrawDecal(window,focused);
std::string adjustedText=label;
if(!fitToLabel){
adjustedText=util::WrapText(game,label,int(rect.size.x),true,{float(scale),float(scale)});
}
vf2d adjustedScale={scale,scale}; vf2d adjustedScale={scale,scale};
vf2d labelTextSize=game->GetTextSizeProp(label,rect.size.x);
if(fitToLabel){ if(fitToLabel){
float sizeRatio=((game->GetTextSizeProp(label)*adjustedScale).x)/(rect.size.x-2); float sizeRatio=((labelTextSize*adjustedScale).x)/(rect.size.x-2);
if(sizeRatio>1){ if(sizeRatio>1){
adjustedScale.x/=sizeRatio; adjustedScale.x/=sizeRatio;
} }
} }
vf2d drawPos=rect.middle()-vf2d{game->GetTextSizeProp(adjustedText)}*float(adjustedScale.x)/2; //Assume centered. vf2d drawPos=rect.middle()-vf2d{labelTextSize}*float(adjustedScale.x)/2; //Assume centered.
if(!centered){ if(!centered){
drawPos=vf2d{rect.pos.x+2,rect.middle().y-game->GetTextSizeProp(adjustedText).y/2}; //We should at least vertically align here. drawPos=vf2d{rect.pos.x+2,rect.middle().y-labelTextSize.y/2}; //We should at least vertically align here.
} }
if(shadow){ if(shadow){
window.DrawShadowStringPropDecal(drawPos,adjustedText,WHITE,BLACK,adjustedScale); window.DrawShadowStringPropDecal(drawPos,label,WHITE,BLACK,adjustedScale,rect.size.x);
}else{ }else{
window.DrawStringPropDecal(drawPos,adjustedText,WHITE,adjustedScale); window.DrawStringPropDecal(drawPos,label,WHITE,adjustedScale,rect.size.x);
} }
} }
}; };

@ -50,7 +50,7 @@ void State_GameRun::OnStateChange(GameState*prevState){
Menu::CloseAllMenus(); Menu::CloseAllMenus();
} }
game->GetPlayer()->SetState(State::NORMAL); game->GetPlayer()->SetState(State::NORMAL);
port=ViewPort::rectViewPort({0,0},{72,100},{75,100}); port=ViewPort::rectViewPort({0,0},{240,240},{24,24});
} }
void State_GameRun::OnUserUpdate(Crawler*game){ void State_GameRun::OnUserUpdate(Crawler*game){
game->bossDisplayTimer=std::max(0.f,game->bossDisplayTimer-game->GetElapsedTime()); game->bossDisplayTimer=std::max(0.f,game->bossDisplayTimer-game->GetElapsedTime());
@ -76,20 +76,20 @@ void State_GameRun::OnUserUpdate(Crawler*game){
} }
void State_GameRun::Draw(Crawler*game){ void State_GameRun::Draw(Crawler*game){
game->RenderHud(); game->RenderHud();
//FontTest(); //Enable to test font coloring. FontTest(); //Enable to test font coloring.
} }
void State_GameRun::FontTest(){ void State_GameRun::FontTest(){
port.DrawStringDecal({8,8},"#FFFFFFThis is a #000066test of hex"); port.DrawStringDecal({8,24*0},"#FF0000This is a #BFA6F9test of hex",WHITE,{1,1},72);
port.DrawStringDecal({8,16},"#FF0000This is a #BFA6F9test of hex"); port.DrawStringDecal({8,24*1},"#00FF00This is a #E9A6F9test of hex",WHITE,{1,1},72);
port.DrawStringDecal({8,24},"#00FF00This is a #E9A6F9test of hex"); port.DrawStringDecal({8,24*2},"#0000FFThis is a #F9E8A6test of hex",WHITE,{1,1},72);
port.DrawStringDecal({8,32},"#0000FFThis is a #F9E8A6test of hex"); port.DrawShadowStringDecal({8,24*3},"#FFFFFFThis is a #000066test of hex",WHITE,BLACK,{1,1},72);
port.DrawShadowStringDecal({8,40},"#FFFFFFThis is a #000066test of hex"); port.DrawShadowStringDecal({8,24*4},"#FF0000This is a #BFA6F9test of hex",WHITE,BLACK,{1,1},72);
port.DrawShadowStringDecal({8,48},"#FF0000This is a #BFA6F9test of hex"); port.DrawShadowStringPropDecal({8,24*5},"#00FF00This is a #E9A6F9test of hex",WHITE,BLACK,{1,1},72);
port.DrawShadowStringDecal({8,56},"#00FF00This is a #E9A6F9test of hex"); port.DrawShadowStringPropDecal({8,24*6},"#0000FFThis is a #F9E8A6test of hex",WHITE,BLACK,{1,1},72);
port.DrawShadowStringDecal({8,64},"#0000FFThis is a #F9E8A6test of hex"); /*port.DrawShadowStringDecal(VisualNovel::font,{8,24*7},U"#FFFFFFThis is a #000066test of hex",WHITE,BLACK,{1,1},72);
port.DrawShadowStringDecal(VisualNovel::font,{8,72},U"#FFFFFFThis is a #000066test of hex"); port.DrawShadowStringDecal(VisualNovel::font,{8,24*8},U"#FF0000This is a #BFA6F9test of hex",WHITE,BLACK,{1,1},72);
port.DrawShadowStringDecal(VisualNovel::font,{8,80},U"#FF0000This is a #BFA6F9test of hex"); port.DrawShadowStringDecal(VisualNovel::font,{8,24*9},U"#00FF00This is a #E9A6F9test of hex",WHITE,BLACK,{1,1},72);
port.DrawShadowStringDecal(VisualNovel::font,{8,88},U"#00FF00This is a #E9A6F9test of hex"); port.DrawShadowStringDecal(VisualNovel::font,{8,24*10},U"#0000FFThis is a #F9E8A6test of hex",WHITE,BLACK,{1,1},72);*/
port.DrawShadowStringDecal(VisualNovel::font,{8,96},U"#0000FFThis is a #F9E8A6test of hex"); port.drawEdges();
} }

@ -39,7 +39,7 @@ All rights reserved.
#define VERSION_MAJOR 0 #define VERSION_MAJOR 0
#define VERSION_MINOR 2 #define VERSION_MINOR 2
#define VERSION_PATCH 1 #define VERSION_PATCH 1
#define VERSION_BUILD 4274 #define VERSION_BUILD 4334
#define stringify(a) stringify_(a) #define stringify(a) stringify_(a)
#define stringify_(a) #a #define stringify_(a) #a

@ -116,11 +116,11 @@ namespace olc {
const vf2d &pos2, const vf2d &pos2,
Pixel p = WHITE) const; Pixel p = WHITE) const;
// Draws a multiline string as a decal, with tinting and scaling // Draws a multiline string as a decal, with tinting and scaling
void DrawStringDecal(const olc::vf2d& pos, const std::string& sText, const Pixel col = olc::WHITE, const olc::vf2d& scale = { 1.0f, 1.0f }); void DrawStringDecal(const olc::vf2d& pos, std::string_view sText, const Pixel col = olc::WHITE, const olc::vf2d& scale = { 1.0f, 1.0f },const float width=std::numeric_limits<float>::max(),const bool colorOverride=false);
void DrawStringDecal(Font&font, const olc::vf2d& pos, const std::u32string& sText, const Pixel col = olc::WHITE, const olc::vf2d& scale = { 1.0f, 1.0f }); void DrawStringDecal(Font&font, const olc::vf2d& pos, const std::u32string& sText, const Pixel col = olc::WHITE, const olc::vf2d& scale = { 1.0f, 1.0f });
void DrawStringPropDecal(const olc::vf2d& pos, const std::string& sText, const Pixel col = olc::WHITE, const olc::vf2d& scale = { 1.0f, 1.0f }); void DrawStringPropDecal(const olc::vf2d& pos, std::string_view sText, const Pixel col = olc::WHITE, const olc::vf2d& scale = { 1.0f, 1.0f }, const float width=std::numeric_limits<float>::max(),const bool colorOverride=false);
void DrawShadowStringDecal(const olc::vf2d& pos, const std::string& sText, const Pixel col = olc::WHITE, const Pixel shadowCol = olc::BLACK, const olc::vf2d& scale = { 1.0f, 1.0f },const float shadowSizeFactor=1); void DrawShadowStringDecal(const olc::vf2d& pos, std::string_view sText, const Pixel col = olc::WHITE, const Pixel shadowCol = olc::BLACK, const olc::vf2d& scale = { 1.0f, 1.0f },const float width=std::numeric_limits<float>::max(),const float shadowSizeFactor=1);
void DrawShadowStringPropDecal(const olc::vf2d& pos, const std::string& sText, const Pixel col = olc::WHITE, const Pixel shadowCol = olc::BLACK, const olc::vf2d& scale = { 1.0f, 1.0f },const float shadowSizeFactor=1); void DrawShadowStringPropDecal(const olc::vf2d& pos, std::string_view sText, const Pixel col = olc::WHITE, const Pixel shadowCol = olc::BLACK, const olc::vf2d& scale = { 1.0f, 1.0f },const float width=std::numeric_limits<float>::max(),const float shadowSizeFactor=1);
void DrawShadowStringDecal(Font&font, const olc::vf2d& pos, const std::u32string& sText, const Pixel col = olc::WHITE, const Pixel shadowCol = olc::BLACK, const olc::vf2d& scale = { 1.0f, 1.0f },const float shadowSizeFactor=1); void DrawShadowStringDecal(Font&font, const olc::vf2d& pos, const std::u32string& sText, const Pixel col = olc::WHITE, const Pixel shadowCol = olc::BLACK, const olc::vf2d& scale = { 1.0f, 1.0f },const float shadowSizeFactor=1);
void DrawDropShadowStringDecal(Font&font, const olc::vf2d& pos, const std::u32string& sText, const Pixel col = olc::WHITE, const Pixel shadowCol = olc::BLACK, const olc::vf2d& scale = { 1.0f, 1.0f }); void DrawDropShadowStringDecal(Font&font, const olc::vf2d& pos, const std::u32string& sText, const Pixel col = olc::WHITE, const Pixel shadowCol = olc::BLACK, const olc::vf2d& scale = { 1.0f, 1.0f });
@ -628,8 +628,12 @@ float olc::ViewPort::directionFromLine(vf2d lineA, vf2d lineB, vf2d point) {
- (point.x - lineA.x) * (lineB.y - lineA.y); - (point.x - lineA.x) * (lineB.y - lineA.y);
} }
void olc::ViewPort::DrawStringDecal(const olc::vf2d& pos, const std::string& sText, const Pixel col, const olc::vf2d& scale){ void olc::ViewPort::DrawStringDecal(const olc::vf2d& pos, std::string_view sText, const Pixel col, const olc::vf2d& scale, const float width,const bool colorOverride){
olc::vf2d spos = { 0.0f, 0.0f }; static std::vector<PixelGameEngine::StringDecalData>letters;
letters.clear();
bool wrappingOccurred=false;
olc::vf2d planningMarker = { 0.0f, 0.0f };
olc::vf2d drawingMarker = { 0.0f, 0.0f };
Pixel textCol=col; Pixel textCol=col;
const auto hexToNumber=[](char c){ const auto hexToNumber=[](char c){
if(c<='9')return c-'0'; if(c<='9')return c-'0';
@ -642,19 +646,44 @@ void olc::ViewPort::DrawStringDecal(const olc::vf2d& pos, const std::string& sTe
skip--; skip--;
continue; continue;
} }
if(c==' '||c=='\t'){
for(PixelGameEngine::StringDecalData&letter:letters){
DrawPartialDecal(pos + drawingMarker, pge->GetFontDecal(), letter.sourcePos, letter.sourceSize, scale, letter.col);
drawingMarker.x += 8.0f * scale.x;
}
letters.clear();
wrappingOccurred=false;
}
if(wrappingOccurred){
if(c!=' '&&c!='\t'){
wrappingOccurred=false;
}else{
continue;
}
}
if(c=='\r')continue; //Ignore carriage returns. Stupid Linux. if(c=='\r')continue; //Ignore carriage returns. Stupid Linux.
if (c == '\n') if (c == '\n')
{ {
spos.x = 0; spos.y += 8.0f * scale.y; planningMarker.x = 0; planningMarker.y += 8.0f * scale.y;
}
else if (c == ' ')
{
drawingMarker.x += 8.0f * scale.x;
planningMarker.x += 8.0f * scale.x;
} }
else if (c == '\t') else if (c == '\t')
{ {
spos.x += 8.0f * float(nTabSizeInSpaces) * scale.x; drawingMarker.x += 8.0f * float(nTabSizeInSpaces) * scale.x;
planningMarker.x += 8.0f * float(nTabSizeInSpaces) * scale.x;
} }
else if (c>=-128&&c<-105) else if (c>=-128&&c<-105)
{ {
textCol={PixelGameEngine::charToColor[c].r,PixelGameEngine::charToColor[c].g,PixelGameEngine::charToColor[c].b,col.a}; textCol={PixelGameEngine::charToColor[c].r,PixelGameEngine::charToColor[c].g,PixelGameEngine::charToColor[c].b,col.a};
} }
else if (c==PixelGameEngine::Reset[0])
{
textCol=col;
}
else if (c=='#') else if (c=='#')
{ {
skip=6; skip=6;
@ -672,15 +701,35 @@ void olc::ViewPort::DrawStringDecal(const olc::vf2d& pos, const std::string& sTe
textCol.b+=hexToNumber(sText[index+i]); textCol.b+=hexToNumber(sText[index+i]);
} }
} }
if(textCol==WHITE)textCol=col;
} }
else else
{ {
int32_t ox = (c - 32) % 16; int32_t ox = (c - 32) % 16;
int32_t oy = (c - 32) / 16; int32_t oy = (c - 32) / 16;
DrawPartialDecal(pos + spos, pge->GetFontDecal(), {float(ox) * 8.0f, float(oy) * 8.0f}, {8.0f, 8.0f}, scale, textCol); planningMarker.x += 8.0f * scale.x;
spos.x += 8.0f * scale.x; 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);
drawingMarker.x += 8.0f * scale.x;
}
letters.clear();
}
planningMarker.x = 0; planningMarker.y += 8.0f * scale.y;
drawingMarker=planningMarker;
wrappingOccurred=true;
for(PixelGameEngine::StringDecalData&letter:letters){
planningMarker.x += 8.0f * scale.x;
}
}
letters.emplace_back(c,vf2d{ float(ox) * 8.0f, float(oy) * 8.0f }, vf2d{ 8.0f, 8.0f },colorOverride?col:textCol);
} }
} }
for(PixelGameEngine::StringDecalData&letter:letters){
DrawPartialDecal(pos + drawingMarker, pge->GetFontDecal(), letter.sourcePos, letter.sourceSize, scale, letter.col);
drawingMarker.x += 8.0f * scale.x;
}
} }
void olc::ViewPort::DrawStringDecal(Font&font, const olc::vf2d& pos, const std::u32string& sText, const Pixel col, const olc::vf2d& scale){ void olc::ViewPort::DrawStringDecal(Font&font, const olc::vf2d& pos, const std::u32string& sText, const Pixel col, const olc::vf2d& scale){
@ -705,8 +754,12 @@ void olc::ViewPort::DrawStringDecal(Font&font, const olc::vf2d& pos, const std::
DrawDecal(pos,garbageCollector[key].decal,scale/4,col); DrawDecal(pos,garbageCollector[key].decal,scale/4,col);
} }
void olc::ViewPort::DrawStringPropDecal(const olc::vf2d& pos, const std::string& sText, const Pixel col, const olc::vf2d& scale){ void olc::ViewPort::DrawStringPropDecal(const olc::vf2d& pos, std::string_view sText, const Pixel col, const olc::vf2d& scale,const float width,const bool colorOverride){
olc::vf2d spos = { 0.0f, 0.0f }; static std::vector<PixelGameEngine::StringDecalData>letters;
letters.clear();
bool wrappingOccurred=false;
olc::vf2d planningMarker = { 0.0f, 0.0f };
olc::vf2d drawingMarker = { 0.0f, 0.0f };
Pixel textCol=col; Pixel textCol=col;
const auto hexToNumber=[](char c){ const auto hexToNumber=[](char c){
if(c<='9')return c-'0'; if(c<='9')return c-'0';
@ -719,14 +772,35 @@ void olc::ViewPort::DrawStringPropDecal(const olc::vf2d& pos, const std::string&
skip--; skip--;
continue; continue;
} }
if(c==' '||c=='\t'){
for(PixelGameEngine::StringDecalData&letter:letters){
DrawPartialDecal(pos + drawingMarker, pge->GetFontDecal(), letter.sourcePos, letter.sourceSize, scale, letter.col);
drawingMarker.x += float(pge->vFontSpacing[letter.c - 32].y) * scale.x;
}
letters.clear();
wrappingOccurred=false;
}
if(wrappingOccurred){
if(c!=' '&&c!='\t'){
wrappingOccurred=false;
}else{
continue;
}
}
if(c=='\r')continue; //Ignore carriage returns. Stupid Linux. if(c=='\r')continue; //Ignore carriage returns. Stupid Linux.
if (c == '\n') if (c == '\n')
{ {
spos.x = 0; spos.y += 8.0f * scale.y; planningMarker.x = 0; planningMarker.y += 8.0f * scale.y;
}
else if (c == ' ')
{
drawingMarker.x += float(pge->vFontSpacing[' ' - 32].y) * scale.x;
planningMarker.x += float(pge->vFontSpacing[' ' - 32].y) * scale.x;
} }
else if (c == '\t') else if (c == '\t')
{ {
spos.x += 8.0f * float(nTabSizeInSpaces) * scale.x; drawingMarker.x += 8.0f * float(nTabSizeInSpaces) * scale.x;
planningMarker.x += 8.0f * float(nTabSizeInSpaces) * scale.x;
} }
else if (c>=-128&&c<-105) else if (c>=-128&&c<-105)
{ {
@ -753,45 +827,57 @@ void olc::ViewPort::DrawStringPropDecal(const olc::vf2d& pos, const std::string&
textCol.b+=hexToNumber(sText[index+i]); textCol.b+=hexToNumber(sText[index+i]);
} }
} }
if(textCol==WHITE)textCol=col;
} }
else else
{ {
int32_t ox = (c - 32) % 16; int32_t ox = (c - 32) % 16;
int32_t oy = (c - 32) / 16; int32_t oy = (c - 32) / 16;
DrawPartialDecal(pos + spos, pge->GetFontDecal(), { float(ox) * 8.0f + float(pge->vFontSpacing[c - 32].x), float(oy) * 8.0f }, { float(pge->vFontSpacing[c - 32].y), 8.0f }, scale, textCol); planningMarker.x += float(pge->vFontSpacing[c - 32].y) * scale.x;
spos.x += float(pge->vFontSpacing[c - 32].y) * scale.x; 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);
drawingMarker.x += float(pge->vFontSpacing[letter.c - 32].y) * scale.x;
}
letters.clear();
}
planningMarker.x = 0; planningMarker.y += 8.0f * scale.y;
drawingMarker=planningMarker;
wrappingOccurred=true;
for(PixelGameEngine::StringDecalData&letter:letters){
planningMarker.x += float(pge->vFontSpacing[letter.c - 32].y) * scale.x;
}
}
letters.emplace_back(c,vf2d{ float(ox) * 8.0f + float(pge->vFontSpacing[c - 32].x), float(oy) * 8.0f }, vf2d{ float(pge->vFontSpacing[c - 32].y), 8.0f },colorOverride?col:textCol);
} }
} }
for(PixelGameEngine::StringDecalData&letter:letters){
DrawPartialDecal(pos + drawingMarker, pge->GetFontDecal(), letter.sourcePos, letter.sourceSize, scale, letter.col);
drawingMarker.x += float(pge->vFontSpacing[letter.c - 32].y) * scale.x;
}
} }
void olc::ViewPort::DrawShadowStringDecal(const olc::vf2d& pos, const std::string& sText, const Pixel col, const Pixel shadowCol, const olc::vf2d& scale,const float shadowSizeFactor){ void olc::ViewPort::DrawShadowStringDecal(const olc::vf2d& pos, std::string_view sText, const Pixel col, const Pixel shadowCol, const olc::vf2d& scale,const float width,const float shadowSizeFactor){
std::string strippedText=sText;
std::erase_if(strippedText,[](char chr){return chr<0;});
int skip=0;
std::erase_if(strippedText,[&](char chr){if(skip>0){skip--;return true;}if(chr=='#'){skip=6;return true;}return false;});
for(float y=-shadowSizeFactor;y<=shadowSizeFactor+0.1;y+=shadowSizeFactor/2){ for(float y=-shadowSizeFactor;y<=shadowSizeFactor+0.1;y+=shadowSizeFactor/2){
for(float x=-shadowSizeFactor;x<=shadowSizeFactor+0.1;x+=shadowSizeFactor/2){ for(float x=-shadowSizeFactor;x<=shadowSizeFactor+0.1;x+=shadowSizeFactor/2){
if(x!=0||y!=0){ if(x!=0||y!=0){
DrawStringDecal(pos+vf2d{x,y}, strippedText, shadowCol,scale); DrawStringDecal(pos+vf2d{x,y}, sText, shadowCol,scale,width,true);
} }
} }
} }
DrawStringDecal(pos, sText, col,scale); DrawStringDecal(pos, sText, col,scale,width);
} }
void olc::ViewPort::DrawShadowStringPropDecal(const olc::vf2d& pos, const std::string& sText, const Pixel col, const Pixel shadowCol, const olc::vf2d& scale,const float shadowSizeFactor){ void olc::ViewPort::DrawShadowStringPropDecal(const olc::vf2d& pos, std::string_view sText, const Pixel col, const Pixel shadowCol, const olc::vf2d& scale,const float width,const float shadowSizeFactor){
std::string strippedText=sText;
std::erase_if(strippedText,[](char chr){return chr<0;});
int skip=0;
std::erase_if(strippedText,[&](char chr){if(skip>0){skip--;return true;}if(chr=='#'){skip=6;return true;}return false;});
for(float y=-shadowSizeFactor;y<=shadowSizeFactor+0.1;y+=shadowSizeFactor/2){ for(float y=-shadowSizeFactor;y<=shadowSizeFactor+0.1;y+=shadowSizeFactor/2){
for(float x=-shadowSizeFactor;x<=shadowSizeFactor+0.1;x+=shadowSizeFactor/2){ for(float x=-shadowSizeFactor;x<=shadowSizeFactor+0.1;x+=shadowSizeFactor/2){
if(x!=0||y!=0){ if(x!=0||y!=0){
DrawStringPropDecal(pos+vf2d{x,y}, strippedText, shadowCol,scale); DrawStringPropDecal(pos+vf2d{x,y}, sText, shadowCol,scale,width,true);
} }
} }
} }
DrawStringPropDecal(pos, sText, col,scale); DrawStringPropDecal(pos, sText, col,scale,width);
} }
void olc::ViewPort::DrawShadowStringDecal(Font&font, const olc::vf2d& pos, const std::u32string& sText, const Pixel col, const Pixel shadowCol, const olc::vf2d& scale,const float shadowSizeFactor){ void olc::ViewPort::DrawShadowStringDecal(Font&font, const olc::vf2d& pos, const std::u32string& sText, const Pixel col, const Pixel shadowCol, const olc::vf2d& scale,const float shadowSizeFactor){

@ -385,6 +385,7 @@ return 0;
#include <cmath> #include <cmath>
#include <cstdint> #include <cstdint>
#include <string> #include <string>
#include <string_view>
#include <iostream> #include <iostream>
#include <streambuf> #include <streambuf>
#include <sstream> #include <sstream>
@ -747,9 +748,6 @@ namespace olc
// O------------------------------------------------------------------------------O // O------------------------------------------------------------------------------O
// | olc::ResourcePack - A virtual scrambled filesystem to pack your assets into | // | olc::ResourcePack - A virtual scrambled filesystem to pack your assets into |
// O------------------------------------------------------------------------------O // O------------------------------------------------------------------------------O
@ -968,6 +966,14 @@ namespace olc
// O------------------------------------------------------------------------------O // O------------------------------------------------------------------------------O
class PixelGameEngine class PixelGameEngine
{ {
struct StringDecalData{
char c;
vf2d sourcePos;
vf2d sourceSize;
Pixel col;
StringDecalData(char c,vf2d sourcePos,vf2d sourceSize,Pixel col)
:c(c),sourcePos(sourcePos),sourceSize(sourceSize),col(col){};
};
public: public:
PixelGameEngine(); PixelGameEngine();
virtual ~PixelGameEngine(); virtual ~PixelGameEngine();
@ -1114,8 +1120,8 @@ 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 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 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); 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(const std::string& s); olc::vi2d GetTextSize(std::string_view s,const int width=std::numeric_limits<int>::max());
olc::vi2d GetTextSizeProp(const std::string& s); olc::vi2d GetTextSizeProp(std::string_view s,const int width=std::numeric_limits<int>::max());
void DrawString(const olc::vi2d& pos, const std::string& sText, Pixel col = olc::WHITE, uint32_t 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); void DrawString(int32_t x, int32_t y, const std::string& sText, Pixel col = olc::WHITE, uint32_t scale = 1);
@ -1141,9 +1147,9 @@ namespace olc
void DrawRotatedDecal(const olc::vf2d& pos, olc::Decal* decal, const float fAngle, const olc::vf2d& center = { 0.0f, 0.0f }, const olc::vf2d& scale = { 1.0f,1.0f }, const olc::Pixel& tint = olc::WHITE); void DrawRotatedDecal(const olc::vf2d& pos, olc::Decal* decal, const float fAngle, const olc::vf2d& center = { 0.0f, 0.0f }, const olc::vf2d& scale = { 1.0f,1.0f }, const olc::Pixel& tint = olc::WHITE);
void DrawPartialRotatedDecal(const olc::vf2d& pos, olc::Decal* decal, const float fAngle, const olc::vf2d& center, const olc::vf2d& source_pos, const olc::vf2d& source_size, const olc::vf2d& scale = { 1.0f, 1.0f }, const olc::Pixel& tint = olc::WHITE); void DrawPartialRotatedDecal(const olc::vf2d& pos, olc::Decal* decal, const float fAngle, const olc::vf2d& center, const olc::vf2d& source_pos, const olc::vf2d& source_size, const olc::vf2d& scale = { 1.0f, 1.0f }, const olc::Pixel& tint = olc::WHITE);
// Draws a multiline string as a decal, with tiniting and scaling // Draws a multiline string as a decal, with tiniting and scaling
void DrawStringDecal(const olc::vf2d& pos, const std::string& sText, const Pixel col = olc::WHITE, const olc::vf2d& scale = { 1.0f, 1.0f }); void DrawStringDecal(const olc::vf2d& pos, std::string_view sText, const Pixel col = olc::WHITE, const olc::vf2d& scale = { 1.0f, 1.0f },const float width=std::numeric_limits<float>::max(),const bool colorOverride=false);
void DrawStringDecal(Font&font, const olc::vf2d& pos, const std::u32string& sText, const Pixel col = olc::WHITE, const olc::vf2d& scale = { 1.0f, 1.0f }); void DrawStringDecal(Font&font, const olc::vf2d& pos, const std::u32string& sText, const Pixel col = olc::WHITE, const olc::vf2d& scale = { 1.0f, 1.0f });
void DrawStringPropDecal(const olc::vf2d& pos, const std::string& sText, const Pixel col = olc::WHITE, const olc::vf2d& scale = { 1.0f, 1.0f }); void DrawStringPropDecal(const olc::vf2d& pos, std::string_view sText, const Pixel col = olc::WHITE, const olc::vf2d& scale = { 1.0f, 1.0f }, const float width=std::numeric_limits<float>::max(),const bool colorOverride=false);
void DrawShadowStringDecal(const olc::vf2d& pos, const std::string& sText, const Pixel col = olc::WHITE, const Pixel shadowCol = olc::BLACK, const olc::vf2d& scale = { 1.0f, 1.0f },const float shadowSizeFactor=1); void DrawShadowStringDecal(const olc::vf2d& pos, const std::string& sText, const Pixel col = olc::WHITE, const Pixel shadowCol = olc::BLACK, const olc::vf2d& scale = { 1.0f, 1.0f },const float shadowSizeFactor=1);
void DrawShadowStringPropDecal(const olc::vf2d& pos, const std::string& sText, const Pixel col = olc::WHITE, const Pixel shadowCol = olc::BLACK, const olc::vf2d& scale = { 1.0f, 1.0f },const float shadowSizeFactor=1); void DrawShadowStringPropDecal(const olc::vf2d& pos, const std::string& sText, const Pixel col = olc::WHITE, const Pixel shadowCol = olc::BLACK, const olc::vf2d& scale = { 1.0f, 1.0f },const float shadowSizeFactor=1);
void DrawShadowStringDecal(Font&font, const olc::vf2d& pos, const std::u32string& sText, const Pixel col = olc::WHITE, const Pixel shadowCol = olc::BLACK, const olc::vf2d& scale = { 1.0f, 1.0f },const float shadowSizeFactor=1); void DrawShadowStringDecal(Font&font, const olc::vf2d& pos, const std::u32string& sText, const Pixel col = olc::WHITE, const Pixel shadowCol = olc::BLACK, const olc::vf2d& scale = { 1.0f, 1.0f },const float shadowSizeFactor=1);
@ -3344,9 +3350,13 @@ namespace olc
void PixelGameEngine::DrawPartialWarpedDecal(olc::Decal* decal, const olc::vf2d(&pos)[4], const olc::vf2d& source_pos, const olc::vf2d& source_size, const olc::Pixel& tint) void PixelGameEngine::DrawPartialWarpedDecal(olc::Decal* decal, const olc::vf2d(&pos)[4], const olc::vf2d& source_pos, const olc::vf2d& source_size, const olc::Pixel& tint)
{ DrawPartialWarpedDecal(decal, &pos[0], source_pos, source_size, tint); } { DrawPartialWarpedDecal(decal, &pos[0], source_pos, source_size, tint); }
void PixelGameEngine::DrawStringDecal(const olc::vf2d& pos, const std::string& sText, const Pixel col, const olc::vf2d& scale) void PixelGameEngine::DrawStringDecal(const olc::vf2d& pos, std::string_view sText, const Pixel col, const olc::vf2d& scale,const float width,const bool colorOverride)
{ {
olc::vf2d spos = { 0.0f, 0.0f }; static std::vector<PixelGameEngine::StringDecalData>letters;
letters.clear();
bool wrappingOccurred=false;
olc::vf2d planningMarker = { 0.0f, 0.0f };
olc::vf2d drawingMarker = { 0.0f, 0.0f };
Pixel textCol=col; Pixel textCol=col;
const auto hexToNumber=[](char c){ const auto hexToNumber=[](char c){
if(c<='9')return c-'0'; if(c<='9')return c-'0';
@ -3359,18 +3369,43 @@ namespace olc
skip--; skip--;
continue; continue;
} }
if(c==' '||c=='\t'){
for(PixelGameEngine::StringDecalData&letter:letters){
DrawPartialDecal(pos + drawingMarker, fontRenderable.Decal(), letter.sourcePos, letter.sourceSize, scale, letter.col);
drawingMarker.x += 8.0f * scale.x;
}
letters.clear();
wrappingOccurred=false;
}
if(wrappingOccurred){
if(c!=' '&&c!='\t'){
wrappingOccurred=false;
}else{
continue;
}
}
if(c=='\r')continue; //Ignore carriage returns. Stupid Linux. if(c=='\r')continue; //Ignore carriage returns. Stupid Linux.
if (c == '\n') if (c == '\n')
{ {
spos.x = 0; spos.y += 8.0f * scale.y; planningMarker.x = 0; planningMarker.y += 8.0f * scale.y;
}
else if (c == ' ')
{
drawingMarker.x += 8.0f * scale.x;
planningMarker.x += 8.0f * scale.x;
} }
else if (c == '\t') else if (c == '\t')
{ {
spos.x += 8.0f * float(nTabSizeInSpaces) * scale.x; drawingMarker.x += 8.0f * float(nTabSizeInSpaces) * scale.x;
planningMarker.x += 8.0f * float(nTabSizeInSpaces) * scale.x;
} }
else if (c>=-128&&c<-105) else if (c>=-128&&c<-105)
{ {
textCol={charToColor[c].r,charToColor[c].g,charToColor[c].b,col.a}; textCol={PixelGameEngine::charToColor[c].r,PixelGameEngine::charToColor[c].g,PixelGameEngine::charToColor[c].b,col.a};
}
else if (c==PixelGameEngine::Reset[0])
{
textCol=col;
} }
else if (c=='#') else if (c=='#')
{ {
@ -3389,20 +3424,44 @@ namespace olc
textCol.b+=hexToNumber(sText[index+i]); textCol.b+=hexToNumber(sText[index+i]);
} }
} }
if(textCol==WHITE)textCol=col;
} }
else else
{ {
int32_t ox = (c - 32) % 16; int32_t ox = (c - 32) % 16;
int32_t oy = (c - 32) / 16; int32_t oy = (c - 32) / 16;
DrawPartialDecal(pos + spos, fontRenderable.Decal(), {float(ox) * 8.0f, float(oy) * 8.0f}, {8.0f, 8.0f}, scale, textCol); planningMarker.x += 8.0f * scale.x;
spos.x += 8.0f * scale.x; 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);
drawingMarker.x += 8.0f * scale.x;
}
letters.clear();
}
planningMarker.x = 0; planningMarker.y += 8.0f * scale.y;
drawingMarker=planningMarker;
wrappingOccurred=true;
for(PixelGameEngine::StringDecalData&letter:letters){
planningMarker.x += 8.0f * scale.x;
}
}
letters.emplace_back(c,vf2d{ float(ox) * 8.0f, float(oy) * 8.0f }, vf2d{ 8.0f, 8.0f },colorOverride?col:textCol);
} }
} }
for(PixelGameEngine::StringDecalData&letter:letters){
DrawPartialDecal(pos + drawingMarker, fontRenderable.Decal(), letter.sourcePos, letter.sourceSize, scale, letter.col);
drawingMarker.x += 8.0f * scale.x;
}
} }
void PixelGameEngine::DrawStringPropDecal(const olc::vf2d& pos, const std::string& sText, const Pixel col, const olc::vf2d& scale) void PixelGameEngine::DrawStringPropDecal(const olc::vf2d& pos, std::string_view sText, const Pixel col, const olc::vf2d& scale, const float width,const bool colorOverride)
{ {
olc::vf2d spos = { 0.0f, 0.0f }; static std::vector<PixelGameEngine::StringDecalData>letters;
letters.clear();
bool wrappingOccurred=false;
olc::vf2d planningMarker = { 0.0f, 0.0f };
olc::vf2d drawingMarker = { 0.0f, 0.0f };
Pixel textCol=col; Pixel textCol=col;
const auto hexToNumber=[](char c){ const auto hexToNumber=[](char c){
if(c<='9')return c-'0'; if(c<='9')return c-'0';
@ -3415,20 +3474,41 @@ namespace olc
skip--; skip--;
continue; continue;
} }
if(c==' '||c=='\t'){
for(PixelGameEngine::StringDecalData&letter:letters){
DrawPartialDecal(pos + drawingMarker, GetFontDecal(), letter.sourcePos, letter.sourceSize, scale, letter.col);
drawingMarker.x += float(vFontSpacing[letter.c - 32].y) * scale.x;
}
letters.clear();
wrappingOccurred=false;
}
if(wrappingOccurred){
if(c!=' '&&c!='\t'){
wrappingOccurred=false;
}else{
continue;
}
}
if(c=='\r')continue; //Ignore carriage returns. Stupid Linux. if(c=='\r')continue; //Ignore carriage returns. Stupid Linux.
if (c == '\n') if (c == '\n')
{ {
spos.x = 0; spos.y += 8.0f * scale.y; planningMarker.x = 0; planningMarker.y += 8.0f * scale.y;
}
else if (c == ' ')
{
drawingMarker.x += float(vFontSpacing[' ' - 32].y) * scale.x;
planningMarker.x += float(vFontSpacing[' ' - 32].y) * scale.x;
} }
else if (c == '\t') else if (c == '\t')
{ {
spos.x += 8.0f * float(nTabSizeInSpaces) * scale.x; drawingMarker.x += 8.0f * float(nTabSizeInSpaces) * scale.x;
planningMarker.x += 8.0f * float(nTabSizeInSpaces) * scale.x;
} }
else if (c>=-128&&c<-105) else if (c>=-128&&c<-105)
{ {
textCol={charToColor[c].r,charToColor[c].g,charToColor[c].b,col.a}; textCol={PixelGameEngine::charToColor[c].r,PixelGameEngine::charToColor[c].g,PixelGameEngine::charToColor[c].b,col.a};
} }
else if (c==Reset[0]) else if (c==PixelGameEngine::Reset[0])
{ {
textCol=col; textCol=col;
} }
@ -3449,15 +3529,35 @@ namespace olc
textCol.b+=hexToNumber(sText[index+i]); textCol.b+=hexToNumber(sText[index+i]);
} }
} }
if(textCol==WHITE)textCol=col;
} }
else else
{ {
int32_t ox = (c - 32) % 16; int32_t ox = (c - 32) % 16;
int32_t oy = (c - 32) / 16; int32_t oy = (c - 32) / 16;
DrawPartialDecal(pos + spos, fontRenderable.Decal(), { float(ox) * 8.0f + float(vFontSpacing[c - 32].x), float(oy) * 8.0f }, { float(vFontSpacing[c - 32].y), 8.0f }, scale, textCol); planningMarker.x += float(vFontSpacing[c - 32].y) * scale.x;
spos.x += float(vFontSpacing[c - 32].y) * scale.x; 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);
drawingMarker.x += float(vFontSpacing[letter.c - 32].y) * scale.x;
}
letters.clear();
}
planningMarker.x = 0; planningMarker.y += 8.0f * scale.y;
drawingMarker=planningMarker;
wrappingOccurred=true;
for(PixelGameEngine::StringDecalData&letter:letters){
planningMarker.x += float(vFontSpacing[letter.c - 32].y) * scale.x;
}
}
letters.emplace_back(c,vf2d{ float(ox) * 8.0f + float(vFontSpacing[c - 32].x), float(oy) * 8.0f }, vf2d{ float(vFontSpacing[c - 32].y), 8.0f },colorOverride?col:textCol);
} }
} }
for(PixelGameEngine::StringDecalData&letter:letters){
DrawPartialDecal(pos + drawingMarker, GetFontDecal(), letter.sourcePos, letter.sourceSize, scale, letter.col);
drawingMarker.x += float(vFontSpacing[letter.c - 32].y) * scale.x;
}
} }
void PixelGameEngine::DrawShadowStringDecal(const olc::vf2d& pos, const std::string& sText, const Pixel col, const Pixel shadowCol, const olc::vf2d& scale,const float shadowSizeFactor){ void PixelGameEngine::DrawShadowStringDecal(const olc::vf2d& pos, const std::string& sText, const Pixel col, const Pixel shadowCol, const olc::vf2d& scale,const float shadowSizeFactor){
@ -3664,30 +3764,76 @@ namespace olc
DrawRotatedStringPropDecal(pos, sText,fAngle,center,col,scale); DrawRotatedStringPropDecal(pos, sText,fAngle,center,col,scale);
} }
olc::vi2d PixelGameEngine::GetTextSize(const std::string& s) olc::vi2d PixelGameEngine::GetTextSize(std::string_view s,const int width)
{ {
olc::vi2d size = { 0,1 }; int lettersWidth=0;
olc::vi2d pos = { 0,1 }; int maxWidth=0;
for (int skip=0;auto c : s) bool wrappingOccurred=false;
olc::vf2d planningMarker = { 0.0f, 0.0f };
olc::vf2d drawingMarker = { 0.0f, 0.0f };
for (int skip=0,index=-1;auto c : s)
{ {
index++;
if(skip){ if(skip){
skip--; skip--;
continue; continue;
} }
if(c==' '||c=='\t'){
drawingMarker.x+=lettersWidth;
lettersWidth=0;
wrappingOccurred=false;
}
if(wrappingOccurred){
if(c!=' '&&c!='\t'){
wrappingOccurred=false;
maxWidth=std::max(maxWidth,int(drawingMarker.x));
}else{
continue;
}
}
if(c=='\r')continue; //Ignore carriage returns. Stupid Linux. if(c=='\r')continue; //Ignore carriage returns. Stupid Linux.
if (c == '\n') { pos.y++; pos.x = 0; } if (c == '\n')
else if (c == '\t') { pos.x += nTabSizeInSpaces; } {
else if(c<0)continue; planningMarker.x = 0; planningMarker.y += 8.0f;
}
else if (c == ' ')
{
drawingMarker.x += 8.0f;
planningMarker.x += 8.0f;
}
else if (c == '\t')
{
drawingMarker.x += 8.0f * float(nTabSizeInSpaces);
planningMarker.x += 8.0f * float(nTabSizeInSpaces);
}
else if (c>=-128&&c<-105||c==PixelGameEngine::Reset[0])
{
continue;
}
else if (c=='#') else if (c=='#')
{ {
skip=6; skip=6;
continue;
} }
else pos.x++; else
size.x = std::max(size.x, pos.x); {
size.y = std::max(size.y, pos.y); planningMarker.x += 8.0f;
if(planningMarker.x>=width){
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));
}
planningMarker.x = 0; planningMarker.y += 8.0f;
drawingMarker=planningMarker;
wrappingOccurred=true;
planningMarker.x+=lettersWidth;
}
lettersWidth+=8.0f;
}
} }
return size * 8; drawingMarker.x += lettersWidth;
maxWidth=std::max(maxWidth,int(drawingMarker.x));
return {maxWidth,int(planningMarker.y+8)};
} }
void PixelGameEngine::DrawString(const olc::vi2d& pos, const std::string& sText, Pixel col, uint32_t scale) void PixelGameEngine::DrawString(const olc::vi2d& pos, const std::string& sText, Pixel col, uint32_t scale)
@ -3779,32 +3925,76 @@ namespace olc
SetPixelMode(m); SetPixelMode(m);
} }
olc::vi2d PixelGameEngine::GetTextSizeProp(const std::string& s) olc::vi2d PixelGameEngine::GetTextSizeProp(std::string_view s,const int width)
{ {
olc::vi2d size = { 0,1 }; int lettersWidth=0;
olc::vi2d pos = { 0,1 }; int maxWidth=0;
for (int skip=0;auto c : s) bool wrappingOccurred=false;
olc::vf2d planningMarker = { 0.0f, 0.0f };
olc::vf2d drawingMarker = { 0.0f, 0.0f };
for (int skip=0,index=-1;auto c : s)
{ {
index++;
if(skip){ if(skip){
skip--; skip--;
continue; continue;
} }
if(c==' '||c=='\t'){
drawingMarker.x+=lettersWidth;
lettersWidth=0;
wrappingOccurred=false;
maxWidth=std::max(maxWidth,int(drawingMarker.x));
}
if(wrappingOccurred){
if(c!=' '&&c!='\t'){
wrappingOccurred=false;
}else{
continue;
}
}
if(c=='\r')continue; //Ignore carriage returns. Stupid Linux. if(c=='\r')continue; //Ignore carriage returns. Stupid Linux.
if (c == '\n') { pos.y += 1; pos.x = 0; } if (c == '\n')
else if (c == '\t') { pos.x += nTabSizeInSpaces * 8; } {
else if(c<0)continue; planningMarker.x = 0; planningMarker.y += 8.0f;
}
else if (c == ' ')
{
drawingMarker.x += vFontSpacing[c-32].y;
planningMarker.x += vFontSpacing[c-32].y;
}
else if (c == '\t')
{
drawingMarker.x += 8.0f * float(nTabSizeInSpaces);
planningMarker.x += 8.0f * float(nTabSizeInSpaces);
}
else if (c>=-128&&c<-105||c==PixelGameEngine::Reset[0])
{
continue;
}
else if (c=='#') else if (c=='#')
{ {
skip=6; skip=6;
continue;
} }
else pos.x += vFontSpacing[c - 32].y; else
size.x = std::max(size.x, pos.x); {
size.y = std::max(size.y, pos.y); planningMarker.x += vFontSpacing[c-32].y;
if(planningMarker.x>=width){
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));
}
planningMarker.x = 0; planningMarker.y += 8.0f;
drawingMarker=planningMarker;
wrappingOccurred=true;
planningMarker.x+=lettersWidth;
}
lettersWidth+=vFontSpacing[c-32].y;
}
} }
drawingMarker.x += lettersWidth;
size.y *= 8; maxWidth=std::max(maxWidth,int(drawingMarker.x));
return size; return {maxWidth,int(planningMarker.y+8)};
} }
void PixelGameEngine::DrawStringProp(const olc::vi2d& pos, const std::string& sText, Pixel col, uint32_t scale) void PixelGameEngine::DrawStringProp(const olc::vi2d& pos, const std::string& sText, Pixel col, uint32_t scale)

Binary file not shown.
Loading…
Cancel
Save