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

pull/28/head
sigonasr2 11 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;
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){
MenuItemButton*button=(MenuItemButton*)data.component;
data.game->ClearLoadoutItem(data.menu.I(A::LOADOUT_SLOT));
@ -81,9 +81,9 @@ void Menu::InitializeConsumableInventoryWindow(){
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.
inventoryWindow->ADD("Inventory Type Label",MenuLabel)({{0,0},{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("itemDescription",MenuLabel)(geom2d::rect<float>(vf2d{2,122.f},{windowSize.x-4,windowSize.y-108}),"",1,ComponentAttr::SHADOW)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,90.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){
vf2d adjustedScale=labelScaling;
vi2d labelTextSize=game->GetTextSizeProp(label,rect.size.x);
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){
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){
switch(selectionType){

@ -66,27 +66,25 @@ protected:
}
inline virtual void DrawDecal(ViewPort&window,bool focused)override{
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 labelTextSize=game->GetTextSizeProp(label,rect.size.x);
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){
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){
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){
window.DrawShadowStringPropDecal(drawPos,adjustedText,WHITE,BLACK,adjustedScale);
window.DrawShadowStringPropDecal(drawPos,label,WHITE,BLACK,adjustedScale,rect.size.x);
}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();
}
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){
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){
game->RenderHud();
//FontTest(); //Enable to test font coloring.
FontTest(); //Enable to test font coloring.
}
void State_GameRun::FontTest(){
port.DrawStringDecal({8,8},"#FFFFFFThis is a #000066test of hex");
port.DrawStringDecal({8,16},"#FF0000This is a #BFA6F9test of hex");
port.DrawStringDecal({8,24},"#00FF00This is a #E9A6F9test of hex");
port.DrawStringDecal({8,32},"#0000FFThis is a #F9E8A6test of hex");
port.DrawShadowStringDecal({8,40},"#FFFFFFThis is a #000066test of hex");
port.DrawShadowStringDecal({8,48},"#FF0000This is a #BFA6F9test of hex");
port.DrawShadowStringDecal({8,56},"#00FF00This is a #E9A6F9test of hex");
port.DrawShadowStringDecal({8,64},"#0000FFThis is a #F9E8A6test of hex");
port.DrawShadowStringDecal(VisualNovel::font,{8,72},U"#FFFFFFThis is a #000066test of hex");
port.DrawShadowStringDecal(VisualNovel::font,{8,80},U"#FF0000This is a #BFA6F9test of hex");
port.DrawShadowStringDecal(VisualNovel::font,{8,88},U"#00FF00This is a #E9A6F9test of hex");
port.DrawShadowStringDecal(VisualNovel::font,{8,96},U"#0000FFThis is a #F9E8A6test of hex");
port.DrawStringDecal({8,24*0},"#FF0000This is a #BFA6F9test of hex",WHITE,{1,1},72);
port.DrawStringDecal({8,24*1},"#00FF00This is a #E9A6F9test of hex",WHITE,{1,1},72);
port.DrawStringDecal({8,24*2},"#0000FFThis is a #F9E8A6test of hex",WHITE,{1,1},72);
port.DrawShadowStringDecal({8,24*3},"#FFFFFFThis is a #000066test of hex",WHITE,BLACK,{1,1},72);
port.DrawShadowStringDecal({8,24*4},"#FF0000This is a #BFA6F9test of hex",WHITE,BLACK,{1,1},72);
port.DrawShadowStringPropDecal({8,24*5},"#00FF00This is a #E9A6F9test of hex",WHITE,BLACK,{1,1},72);
port.DrawShadowStringPropDecal({8,24*6},"#0000FFThis is a #F9E8A6test of hex",WHITE,BLACK,{1,1},72);
/*port.DrawShadowStringDecal(VisualNovel::font,{8,24*7},U"#FFFFFFThis is a #000066test of hex",WHITE,BLACK,{1,1},72);
port.DrawShadowStringDecal(VisualNovel::font,{8,24*8},U"#FF0000This is a #BFA6F9test of hex",WHITE,BLACK,{1,1},72);
port.DrawShadowStringDecal(VisualNovel::font,{8,24*9},U"#00FF00This is a #E9A6F9test of hex",WHITE,BLACK,{1,1},72);
port.DrawShadowStringDecal(VisualNovel::font,{8,24*10},U"#0000FFThis is a #F9E8A6test of hex",WHITE,BLACK,{1,1},72);*/
port.drawEdges();
}

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

@ -116,11 +116,11 @@ namespace olc {
const vf2d &pos2,
Pixel p = WHITE) const;
// 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 DrawStringPropDecal(const olc::vf2d& pos, const std::string& sText, const Pixel col = olc::WHITE, const olc::vf2d& scale = { 1.0f, 1.0f });
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 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, 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, 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 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);
}
void olc::ViewPort::DrawStringDecal(const olc::vf2d& pos, const std::string& sText, const Pixel col, const olc::vf2d& scale){
olc::vf2d spos = { 0.0f, 0.0f };
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){
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;
const auto hexToNumber=[](char c){
if(c<='9')return c-'0';
@ -642,19 +646,44 @@ void olc::ViewPort::DrawStringDecal(const olc::vf2d& pos, const std::string& sTe
skip--;
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 == '\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')
{
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)
{
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=='#')
{
skip=6;
@ -672,14 +701,34 @@ void olc::ViewPort::DrawStringDecal(const olc::vf2d& pos, const std::string& sTe
textCol.b+=hexToNumber(sText[index+i]);
}
}
if(textCol==WHITE)textCol=col;
}
else
{
int32_t ox = (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);
spos.x += 8.0f * scale.x;
planningMarker.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;
}
}
@ -705,8 +754,12 @@ void olc::ViewPort::DrawStringDecal(Font&font, const olc::vf2d& pos, const std::
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){
olc::vf2d spos = { 0.0f, 0.0f };
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){
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;
const auto hexToNumber=[](char c){
if(c<='9')return c-'0';
@ -719,14 +772,35 @@ void olc::ViewPort::DrawStringPropDecal(const olc::vf2d& pos, const std::string&
skip--;
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 == '\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')
{
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)
{
@ -753,45 +827,57 @@ void olc::ViewPort::DrawStringPropDecal(const olc::vf2d& pos, const std::string&
textCol.b+=hexToNumber(sText[index+i]);
}
}
if(textCol==WHITE)textCol=col;
}
else
{
int32_t ox = (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);
spos.x += float(pge->vFontSpacing[c - 32].y) * scale.x;
planningMarker.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){
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;});
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){
for(float y=-shadowSizeFactor;y<=shadowSizeFactor+0.1;y+=shadowSizeFactor/2){
for(float x=-shadowSizeFactor;x<=shadowSizeFactor+0.1;x+=shadowSizeFactor/2){
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){
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;});
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){
for(float y=-shadowSizeFactor;y<=shadowSizeFactor+0.1;y+=shadowSizeFactor/2){
for(float x=-shadowSizeFactor;x<=shadowSizeFactor+0.1;x+=shadowSizeFactor/2){
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){

@ -385,6 +385,7 @@ return 0;
#include <cmath>
#include <cstdint>
#include <string>
#include <string_view>
#include <iostream>
#include <streambuf>
#include <sstream>
@ -747,9 +748,6 @@ namespace olc
// O------------------------------------------------------------------------------O
// | olc::ResourcePack - A virtual scrambled filesystem to pack your assets into |
// O------------------------------------------------------------------------------O
@ -968,6 +966,14 @@ namespace olc
// O------------------------------------------------------------------------------O
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:
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 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(const std::string& s);
olc::vi2d GetTextSizeProp(const std::string& s);
olc::vi2d GetTextSize(std::string_view s,const int width=std::numeric_limits<int>::max());
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(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 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
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 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 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);
@ -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)
{ 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;
const auto hexToNumber=[](char c){
if(c<='9')return c-'0';
@ -3359,18 +3369,43 @@ namespace olc
skip--;
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 == '\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')
{
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)
{
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=='#')
{
@ -3389,20 +3424,44 @@ namespace olc
textCol.b+=hexToNumber(sText[index+i]);
}
}
if(textCol==WHITE)textCol=col;
}
else
{
int32_t ox = (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);
spos.x += 8.0f * scale.x;
planningMarker.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;
const auto hexToNumber=[](char c){
if(c<='9')return c-'0';
@ -3415,20 +3474,41 @@ namespace olc
skip--;
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 == '\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')
{
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)
{
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;
}
@ -3449,15 +3529,35 @@ namespace olc
textCol.b+=hexToNumber(sText[index+i]);
}
}
if(textCol==WHITE)textCol=col;
}
else
{
int32_t ox = (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);
spos.x += float(vFontSpacing[c - 32].y) * scale.x;
planningMarker.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){
@ -3664,30 +3764,76 @@ namespace olc
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 };
olc::vi2d pos = { 0,1 };
for (int skip=0;auto c : s)
int lettersWidth=0;
int maxWidth=0;
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){
skip--;
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 == '\n') { pos.y++; pos.x = 0; }
else if (c == '\t') { pos.x += nTabSizeInSpaces; }
else if(c<0)continue;
if (c == '\n')
{
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=='#')
{
skip=6;
continue;
}
else pos.x++;
size.x = std::max(size.x, pos.x);
size.y = std::max(size.y, pos.y);
else
{
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;
}
return size * 8;
lettersWidth+=8.0f;
}
}
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)
@ -3779,32 +3925,76 @@ namespace olc
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 };
olc::vi2d pos = { 0,1 };
for (int skip=0;auto c : s)
int lettersWidth=0;
int maxWidth=0;
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){
skip--;
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 == '\n') { pos.y += 1; pos.x = 0; }
else if (c == '\t') { pos.x += nTabSizeInSpaces * 8; }
else if(c<0)continue;
if (c == '\n')
{
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=='#')
{
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);
else
{
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;
}
size.y *= 8;
return size;
lettersWidth+=vFontSpacing[c-32].y;
}
}
drawingMarker.x += lettersWidth;
maxWidth=std::max(maxWidth,int(drawingMarker.x));
return {maxWidth,int(planningMarker.y+8)};
}
void PixelGameEngine::DrawStringProp(const olc::vi2d& pos, const std::string& sText, Pixel col, uint32_t scale)

Binary file not shown.
Loading…
Cancel
Save