@ -1122,8 +1122,8 @@ namespace olc
void DrawShadowStringProp ( const olc : : vi2d & pos , std : : string_view sText , 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 ) ;
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 < int > : : max ( ) , const float scale = 1 ) ;
olc : : vi2d GetWrappedTextSizeProp ( std : : string_view s , const float width = std : : numeric_limits < int > : : max ( ) , const float scale = 1 ) ;
olc : : vi2d GetWrappedTextSize ( std : : string_view s , const float width = std : : numeric_limits < int > : : max ( ) , const vf2d scale = { 1 , 1 } ) ;
olc : : vi2d GetWrappedTextSizeProp ( std : : string_view s , const float width = std : : numeric_limits < int > : : max ( ) , const vf2d scale = { 1 , 1 } ) ;
void DrawString ( const olc : : vi2d & pos , std : : string_view sText , Pixel col = olc : : WHITE , uint32_t scale = 1 , const float width = std : : numeric_limits < float > : : max ( ) , const bool colorOverride = false ) ;
void DrawString ( int32_t x , int32_t y , std : : string_view sText , Pixel col = olc : : WHITE , uint32_t scale = 1 , const float width = std : : numeric_limits < float > : : max ( ) , const bool colorOverride = false ) ;
@ -1149,9 +1149,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 , 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 ( 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 disableDynamicScaling = 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 , 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 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 disableDynamicScaling = 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 ) ;
@ -2195,10 +2195,10 @@ namespace olc
{ return bHasInputFocus ; }
HWButton PixelGameEngine : : GetKey ( Key k ) const
{ return pKeyboardState [ k ] ; }
{ return IsFocused ( ) ? pKeyboardState [ k ] : HWButton { } ; }
HWButton PixelGameEngine : : GetMouse ( uint32_t b ) const
{ return pMouseState [ b ] ; }
{ return IsFocused ( ) ? pMouseState [ b ] : HWButton { } ; }
int32_t PixelGameEngine : : GetMouseX ( ) const
{ return vMousePos . x ; }
@ -2210,7 +2210,7 @@ namespace olc
{ return vMousePos ; }
int32_t PixelGameEngine : : GetMouseWheel ( ) const
{ return nMouseWheelDelta ; }
{ return IsFocused ( ) ? nMouseWheelDelta : 0 ; }
int32_t PixelGameEngine : : ScreenWidth ( ) const
{ return vScreenSize . x ; }
@ -3352,221 +3352,77 @@ 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 , std : : string_view sText , const Pixel col , const olc : : vf2d & scale , const float width , const bool colorOverride )
void PixelGameEngine : : DrawStringDecal ( const olc : : vf2d & pos , std : : string_view sText , const Pixel col , const olc : : vf2d & scale , const float width , const bool disableDynamicScaling )
{
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 ' ;
return ( c - ' A ' ) + 10 ;
struct DecalData {
Decal * decal ;
float expireTime = 0.0f ;
} ;
for ( int skip = 0 , index = - 1 ; auto c : sText )
{
index + + ;
if ( skip ) {
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 ' )
{
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 ' )
{
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 ;
textCol = BLACK ;
for ( int i = 1 ; i < 7 ; i + + ) {
if ( i < 3 ) {
textCol . r * = 16 ;
textCol . r + = hexToNumber ( sText [ index + i ] ) ;
} else
if ( i < 5 ) {
textCol . g * = 16 ;
textCol . g + = hexToNumber ( sText [ index + i ] ) ;
} else {
textCol . b * = 16 ;
textCol . b + = hexToNumber ( sText [ index + i ] ) ;
}
}
if ( textCol = = WHITE ) textCol = col ;
}
else
{
int32_t ox = ( c - 32 ) % 16 ;
int32_t oy = ( c - 32 ) / 16 ;
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 ) ;
if ( sText . length ( ) = = 0 ) return ;
static std : : map < std : : string , DecalData > garbageCollector ;
std : : string key { sText } ;
if ( ! disableDynamicScaling ) {
key + = scale . str ( ) ;
}
if ( ! garbageCollector . count ( key ) ) { //If the text key already exists, don't have to recreate the decal, just update the expire time.
vi2d imageSize = GetWrappedTextSize ( sText , width , scale ) ;
Decal * newDecal = new Decal ( new Sprite ( imageSize . x / scale . x , imageSize . y / scale . x ) ) ;
garbageCollector [ key ] . decal = newDecal ;
SetDrawTarget ( newDecal - > sprite ) ;
Clear ( BLANK ) ;
DrawString ( { 0 , 0 } , sText , WHITE , 1U , width / scale . x ) ;
SetDrawTarget ( nullptr ) ;
newDecal - > Update ( ) ;
}
for ( PixelGameEngine : : StringDecalData & letter : letters ) {
DrawPartialDecal ( pos + drawingMarker , fontRenderable . Decal ( ) , letter . sourcePos , letter . sourceSize , scale , letter . col ) ;
drawingMarker . x + = 8.0f * scale . x ;
garbageCollector [ key ] . expireTime = GetRuntime ( ) + 120.0f ;
std : : erase_if ( garbageCollector , [ & ] ( auto & key ) {
if ( key . second . expireTime < GetRuntime ( ) ) {
delete key . second . decal ;
return true ;
}
return false ;
} ) ;
DrawDecal ( pos , garbageCollector [ key ] . decal , scale , col ) ;
}
void PixelGameEngine : : DrawStringPropDecal ( const olc : : vf2d & pos , std : : string_view sText , const Pixel col , const olc : : vf2d & scale , const float width , const bool colorOverride )
void PixelGameEngine : : DrawStringPropDecal ( const olc : : vf2d & pos , std : : string_view sText , const Pixel col , const olc : : vf2d & scale , const float width , const bool disableDynamicScaling )
{
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 ' ;
return ( c - ' A ' ) + 10 ;
struct DecalData {
Decal * decal ;
float expireTime = 0.0f ;
} ;
for ( int skip = 0 , index = - 1 ; auto c : sText )
{
index + + ;
if ( skip ) {
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 ' )
{
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 ' )
{
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 ;
textCol = BLACK ;
for ( int i = 1 ; i < 7 ; i + + ) {
if ( i < 3 ) {
textCol . r * = 16 ;
textCol . r + = hexToNumber ( sText [ index + i ] ) ;
} else
if ( i < 5 ) {
textCol . g * = 16 ;
textCol . g + = hexToNumber ( sText [ index + i ] ) ;
} else {
textCol . b * = 16 ;
textCol . b + = hexToNumber ( sText [ index + i ] ) ;
}
}
if ( textCol = = WHITE ) textCol = col ;
}
else
{
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 ( 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 ) ;
if ( sText . length ( ) = = 0 ) return ;
static std : : map < std : : string , DecalData > garbageCollector ;
std : : string key { sText } ;
if ( ! disableDynamicScaling ) {
key + = scale . str ( ) ;
}
if ( ! garbageCollector . count ( key ) ) { //If the text key already exists, don't have to recreate the decal, just update the expire time.
vi2d imageSize = GetWrappedTextSizeProp ( sText , width , scale ) ;
Decal * newDecal = new Decal ( new Sprite ( imageSize . x / scale . x , imageSize . y / scale . x ) ) ;
garbageCollector [ key ] . decal = newDecal ;
SetDrawTarget ( newDecal - > sprite ) ;
Clear ( BLANK ) ;
DrawStringProp ( { 0 , 0 } , sText , WHITE , 1U , width / scale . x ) ;
SetDrawTarget ( nullptr ) ;
newDecal - > Update ( ) ;
}
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 ;
garbageCollector [ key ] . expireTime = GetRuntime ( ) + 120.0f ;
std : : erase_if ( garbageCollector , [ & ] ( auto & key ) {
if ( key . second . expireTime < GetRuntime ( ) ) {
delete key . second . decal ;
return true ;
}
return false ;
} ) ;
DrawDecal ( pos , garbageCollector [ key ] . decal , scale , col ) ;
}
void PixelGameEngine : : 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 } , sText , shadowCol , scale , width , true ) ;
DrawStringDecal ( pos + vf2d { x , y } , sText , shadowCol , scale , width ) ;
}
}
}
@ -3653,7 +3509,7 @@ namespace olc
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 } , sText , shadowCol , scale , width , true ) ;
DrawStringPropDecal ( pos + vf2d { x , y } , sText , shadowCol , scale , width ) ;
}
}
}
@ -3750,9 +3606,12 @@ namespace olc
DrawRotatedStringPropDecal ( pos , sText , fAngle , center , col , scale ) ;
}
olc : : vi2d PixelGameEngine : : GetWrappedTextSize ( std : : string_view s , const float width , const float scale )
olc : : vi2d PixelGameEngine : : GetWrappedTextSize ( std : : string_view s , const float width , const vf2d scale )
{
float adjustedWidth = width / scale ;
float adjustedWidth = width ;
if ( width ! = std : : numeric_limits < float > : : max ( ) ) {
adjustedWidth / = scale . x ;
}
int lettersWidth = 0 ;
float maxWidth = 0 ;
bool wrappingOccurred = false ;
@ -3819,6 +3678,7 @@ namespace olc
}
}
drawingMarker . x + = lettersWidth ;
maxWidth = std : : max ( maxWidth , drawingMarker . x ) ;
return vi2d ( vf2d { maxWidth , planningMarker . y + 8 } * scale ) ;
}
@ -3993,9 +3853,12 @@ namespace olc
return size ;
}
olc : : vi2d PixelGameEngine : : GetWrappedTextSizeProp ( std : : string_view s , const float width , const float scale )
olc : : vi2d PixelGameEngine : : GetWrappedTextSizeProp ( std : : string_view s , const float width , const vf2d scale )
{
float adjustedWidth = width / scale ;
float adjustedWidth = width ;
if ( width ! = std : : numeric_limits < float > : : max ( ) ) {
adjustedWidth / = scale . x ;
}
int lettersWidth = 0 ;
float maxWidth = 0 ;
bool wrappingOccurred = false ;