Fix crash when hovering over lock/unlock buttons in the accessories menu on the Merchant menu. Fix size of icons in merchant menus. Enable/Disable increase/decrease buttons on shermans's consumable crafting menu as appropriate. Labels in merchant window and inventory window properly update their item descriptions with flashing / changing colors as needed. Text rendering system no longer eats away at memory for text strings that are equivalent but have different HTML color codes. Release Build 8066.
This commit is contained in:
parent
13854574c9
commit
5a8a3d64e9
@ -397,6 +397,10 @@
|
||||
</SubType>
|
||||
</ClInclude>
|
||||
<ClInclude Include="MenuDefinitions.h" />
|
||||
<ClInclude Include="MenuItemLabel.h">
|
||||
<SubType>
|
||||
</SubType>
|
||||
</ClInclude>
|
||||
<ClInclude Include="MenuType.h">
|
||||
<SubType>
|
||||
</SubType>
|
||||
|
@ -480,6 +480,9 @@
|
||||
<ClInclude Include="AccessoryRowItemDisplay.h">
|
||||
<Filter>Header Files\Interface</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="MenuItemLabel.h">
|
||||
<Filter>Header Files\Interface</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="Player.cpp">
|
||||
|
@ -341,6 +341,8 @@ bool AiL::OnUserUpdate(float fElapsedTime){
|
||||
}else lastMouseMovement+=fElapsedTime;
|
||||
if(!GamePaused()){
|
||||
GameState::STATE->OnUserUpdate(this);
|
||||
}else{
|
||||
ClearTimedOutGarbage();
|
||||
}
|
||||
LoadingScreen::Update();
|
||||
InputListener::Update();
|
||||
@ -2361,6 +2363,11 @@ void AiL::_PrepareLevel(MapName map,MusicChange changeMusic){
|
||||
Audio::UpdateBGMVolume();
|
||||
return true;
|
||||
});
|
||||
|
||||
LoadingScreen::AddPhase([&](){
|
||||
ClearGarbage();
|
||||
return true;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -64,7 +64,7 @@ void Menu::InitializeBuyItemWindow(){
|
||||
|
||||
if(qty==99||pricePerItem*(qty+1)>game->GetPlayer()->GetMoney()){
|
||||
Component<MenuComponent>(BUY_ITEM,"Increase buy amount Button")->SetGrayedOut(true);
|
||||
Menu::menus[BUY_ITEM]->SetSelection(static_cast<std::weak_ptr<MenuComponent>>(Component<MenuComponent>(BUY_ITEM,"Decrease buy amount Button")));
|
||||
Menu::menus[BUY_ITEM]->SetSelection("Decrease buy amount Button"sv);
|
||||
}else{
|
||||
Component<MenuComponent>(BUY_ITEM,"Increase buy amount Button")->SetGrayedOut(false);
|
||||
}
|
||||
|
@ -59,9 +59,23 @@ void Menu::InitializeConsumableCraftItemWindow(){
|
||||
|
||||
const std::string&item=Component<MenuLabel>(CONSUMABLE_CRAFT_ITEM,"Item Name Header")->GetString(A::ITEM_NAME);
|
||||
bool canCraft=Item(qty,item).CanEnhanceItem(qty);
|
||||
bool canCraftOneHigher=Item(qty+1,item).CanEnhanceItem(qty+1);
|
||||
|
||||
std::string colorCode="";
|
||||
if(!canCraft)colorCode="#FF0000";
|
||||
if(qty==99||!canCraftOneHigher){
|
||||
Component<MenuComponent>(CONSUMABLE_CRAFT_ITEM,"Increase Craft amount Button")->SetGrayedOut(true);
|
||||
Menu::menus[CONSUMABLE_CRAFT_ITEM]->SetSelection("Decrease Craft amount Button"sv);
|
||||
}else{
|
||||
Component<MenuComponent>(CONSUMABLE_CRAFT_ITEM,"Increase Craft amount Button")->SetGrayedOut(false);
|
||||
}
|
||||
|
||||
if(qty<=1){
|
||||
Component<MenuComponent>(CONSUMABLE_CRAFT_ITEM,"Decrease Craft amount Button")->SetGrayedOut(true);
|
||||
Menu::menus[CONSUMABLE_CRAFT_ITEM]->SetSelection("Increase Craft amount Button"sv);
|
||||
}else{
|
||||
Component<MenuComponent>(CONSUMABLE_CRAFT_ITEM,"Decrease Craft amount Button")->SetGrayedOut(false);
|
||||
}
|
||||
Component<RequiredMaterialsList>(CONSUMABLE_CRAFT_ITEM,"Required Materials List")->SetQuantity(qty);
|
||||
Component<MenuComponent>(CONSUMABLE_CRAFT_ITEM,"Craft Button")->SetGrayedOut(!canCraft);
|
||||
};
|
||||
|
@ -69,6 +69,7 @@ void Menu::InitializeConsumableCraftingWindow(){
|
||||
Component<RequiredMaterialsList>(CONSUMABLE_CRAFT_ITEM,"Required Materials List")->SetItem(item);
|
||||
Component<MenuComponent>(CONSUMABLE_CRAFT_ITEM,"Craft Button")->SetGrayedOut(!item.lock()->CanEnhanceItem());
|
||||
if(item.lock()->GetEnhancementInfo()[0].chapterAvailable<=game->GetCurrentChapter()){
|
||||
Component<MenuComponent>(CONSUMABLE_CRAFT_ITEM,"Decrease Craft amount Button")->SetGrayedOut(true);
|
||||
Menu::OpenMenu(CONSUMABLE_CRAFT_ITEM);
|
||||
}else{
|
||||
SoundEffect::PlaySFX("Locked Item",SoundEffect::CENTERED);
|
||||
|
@ -59,6 +59,18 @@ public:
|
||||
itemRef=Item::BLANK;
|
||||
}
|
||||
}
|
||||
virtual inline void Update(AiL*game)override{
|
||||
MenuIconButton::Update(game);
|
||||
valid=!ISBLANK(itemRef);
|
||||
|
||||
if(!valid){
|
||||
icon=nullptr;
|
||||
}
|
||||
|
||||
if(hovered){
|
||||
UpdateLabel();
|
||||
}
|
||||
}
|
||||
inline const EquipSlot GetSlot()const{
|
||||
return slot;
|
||||
}
|
||||
|
@ -206,7 +206,8 @@ void Menu::InitializeInventoryWindow(){
|
||||
{game->KEY_CONFIRM,{[](MenuFuncData data){
|
||||
if(!data.menu.GetSelection().expired()&&
|
||||
!data.menu.GetSelection().lock()->parentComponent.expired()&&
|
||||
data.menu.GetSelection().lock()->parentComponent.lock()->GetName()=="Inventory Display - Accessories"){
|
||||
data.menu.GetSelection().lock()->parentComponent.lock()->GetName()=="Inventory Display - Accessories"
|
||||
&&data.component.lock()->GetSubcomponentParent().expired()){
|
||||
if(DYNAMIC_POINTER_CAST<AccessoryRowItemDisplay>(data.menu.GetSelection().lock())->GetItem().lock()->IsLocked()){
|
||||
return "Unlock";
|
||||
}else{
|
||||
@ -225,7 +226,8 @@ void Menu::InitializeInventoryWindow(){
|
||||
{game->KEY_SELECT,{[](MenuFuncData data){
|
||||
if(!data.menu.GetSelection().expired()&&
|
||||
!data.menu.GetSelection().lock()->parentComponent.expired()&&
|
||||
data.menu.GetSelection().lock()->parentComponent.lock()->GetName()=="Inventory Display - Accessories"){
|
||||
data.menu.GetSelection().lock()->parentComponent.lock()->GetName()=="Inventory Display - Accessories"
|
||||
&&data.component.lock()->GetSubcomponentParent().expired()){
|
||||
if(DYNAMIC_POINTER_CAST<AccessoryRowItemDisplay>(data.menu.GetSelection().lock())->GetItem().lock()->IsLocked()){
|
||||
return "Unlock";
|
||||
}else{
|
||||
|
@ -149,9 +149,7 @@ protected:
|
||||
if(!valid){
|
||||
icon=nullptr;
|
||||
}
|
||||
if(hovered){
|
||||
UpdateLabel();
|
||||
}
|
||||
UpdateLabel();
|
||||
}
|
||||
virtual inline void DrawDecal(ViewPort&window,bool focused)override{
|
||||
MenuIconButton::DrawDecal(window,focused);
|
||||
|
75
Adventures in Lestoria/MenuItemLabel.h
Normal file
75
Adventures in Lestoria/MenuItemLabel.h
Normal file
@ -0,0 +1,75 @@
|
||||
#pragma region License
|
||||
/*
|
||||
License (OLC-3)
|
||||
~~~~~~~~~~~~~~~
|
||||
|
||||
Copyright 2024 Joshua Sigona <sigonasr2@gmail.com>
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
|
||||
1. Redistributions or derivations of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
|
||||
2. Redistributions or derivative works in binary form must reproduce the above
|
||||
copyright notice. This list of conditions and the following disclaimer must be
|
||||
reproduced in the documentation and/or other materials provided with the distribution.
|
||||
|
||||
3. Neither the name of the copyright holder nor the names of its contributors may
|
||||
be used to endorse or promote products derived from this software without specific
|
||||
prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
|
||||
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
|
||||
SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
|
||||
TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
|
||||
BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
SUCH DAMAGE.
|
||||
|
||||
Portions of this software are copyright © 2024 The FreeType
|
||||
Project (www.freetype.org). Please see LICENSE_FT.txt for more information.
|
||||
All rights reserved.
|
||||
*/
|
||||
#pragma endregion
|
||||
#pragma once
|
||||
|
||||
#include "MenuLabel.h"
|
||||
#include "Item.h"
|
||||
|
||||
namespace ItemLabelDescriptionType{
|
||||
enum ItemDescriptionType{
|
||||
ITEM_DESCRIPTION,
|
||||
ITEM_NAME
|
||||
};
|
||||
};
|
||||
|
||||
using namespace ItemLabelDescriptionType;
|
||||
|
||||
class MenuItemLabel:public MenuLabel{
|
||||
std::weak_ptr<Item>itemRef;
|
||||
ItemDescriptionType labelType;
|
||||
public:
|
||||
inline MenuItemLabel(geom2d::rect<float>rect,std::weak_ptr<Item>itemRef,ItemDescriptionType labelType=ITEM_DESCRIPTION,float scale=1,ComponentAttr attributes=ComponentAttr::NONE)
|
||||
:MenuLabel(rect,"",scale,attributes),itemRef(itemRef),labelType(labelType){}
|
||||
inline virtual void Update(AiL*game)override{
|
||||
MenuLabel::Update(game);
|
||||
|
||||
if(!itemRef.expired()){
|
||||
switch(labelType){
|
||||
case ITEM_DESCRIPTION:{
|
||||
SetLabel(itemRef.lock()->Description(NON_COMPACT));
|
||||
}break;
|
||||
case ITEM_NAME:{
|
||||
SetLabel(itemRef.lock()->DisplayName());
|
||||
}break;
|
||||
}
|
||||
}
|
||||
}
|
||||
inline virtual void SetItem(std::weak_ptr<Item>itemRef){
|
||||
this->itemRef=itemRef;
|
||||
}
|
||||
};
|
@ -109,6 +109,7 @@ void Menu::InitializeMerchantWindow(){
|
||||
|
||||
auto inventoryDisplay=merchantWindow->ADD("Merchant Inventory Display",RowInventoryScrollableWindowComponent)(geom2d::rect<float>{{2,28},{220,merchantWindow->size.y-44}},"Item Name Label","Item Description Label",
|
||||
[](MenuFuncData data){
|
||||
if(!data.component.lock()->GetSubcomponentParent().expired())return true; //We do not do anything if it's not the actual item.
|
||||
std::weak_ptr<RowItemDisplay>item=DYNAMIC_POINTER_CAST<RowItemDisplay>(data.component.lock());
|
||||
|
||||
int qty=1;
|
||||
@ -138,6 +139,7 @@ void Menu::InitializeMerchantWindow(){
|
||||
return true;
|
||||
},
|
||||
[](MenuFuncData data){
|
||||
if(!data.component.lock()->GetSubcomponentParent().expired())return true; //We do not do anything if it's not the actual item.
|
||||
Component<MenuItemItemButton>(data.menu.GetType(),"Item Icon")->SetItem(DYNAMIC_POINTER_CAST<RowItemDisplay>(data.component.lock())->GetItem());
|
||||
data.menu.I(A::MERCHANT_ITEM_SLOT)=data.parentComponent.lock()->GetComponentIndex(data.component);
|
||||
return true;
|
||||
@ -189,6 +191,7 @@ void Menu::InitializeMerchantWindow(){
|
||||
|
||||
auto inventoryDisplay=merchantWindow->ADD("Inventory Display - "+category,RowInventoryScrollableWindowComponent)(geom2d::rect<float>{{72,28},{150,merchantWindow->size.y-44}},"Item Name Label","Item Description Label",
|
||||
[](MenuFuncData data){
|
||||
if(!data.component.lock()->GetSubcomponentParent().expired())return true; //We do not do anything if it's not the actual item.
|
||||
std::weak_ptr<RowItemDisplay>item=DYNAMIC_POINTER_CAST<RowItemDisplay>(data.component.lock());
|
||||
if(item.lock()->GetItem().lock()->IsLocked()){
|
||||
SoundEffect::PlaySFX("Locked Item",SoundEffect::CENTERED);
|
||||
@ -221,6 +224,7 @@ void Menu::InitializeMerchantWindow(){
|
||||
return true;
|
||||
},
|
||||
[](MenuFuncData data){
|
||||
if(!data.component.lock()->GetSubcomponentParent().expired())return true; //We do not do anything if it's not the actual item.
|
||||
Component<MenuItemItemButton>(data.menu.GetType(),"Item Icon")->SetItem(DYNAMIC_POINTER_CAST<RowItemDisplay>(data.component.lock())->GetItem());
|
||||
data.menu.I(A::ITEM_SLOT)=data.parentComponent.lock()->GetComponentIndex(data.component);
|
||||
return true;
|
||||
@ -252,7 +256,8 @@ void Menu::InitializeMerchantWindow(){
|
||||
#pragma region Inventory Description
|
||||
float inventoryDescriptionWidth=merchantWindow->pos.x+merchantWindow->size.x-26-224;
|
||||
merchantWindow->ADD("Item Description Outline",MenuLabel)(geom2d::rect<float>{{224,28},{inventoryDescriptionWidth,merchantWindow->size.y-44}},"",1,ComponentAttr::LEFT_ALIGN|ComponentAttr::OUTLINE|ComponentAttr::BACKGROUND)END;
|
||||
merchantWindow->ADD("Item Icon",MenuItemItemButton)(geom2d::rect<float>{{226+inventoryDescriptionWidth/2-24,30},{48,48}},Item::BLANK,DO_NOTHING,"","",IconButtonAttr::NOT_SELECTABLE)END;
|
||||
merchantWindow->ADD("Item Icon",MenuItemItemButton)(geom2d::rect<float>{{226+inventoryDescriptionWidth/2-24,30},{48,48}},Item::BLANK,DO_NOTHING,"Item Name Label","Item Description Label",IconButtonAttr::NOT_SELECTABLE)END
|
||||
->SetIconScale({2.f,2.f});
|
||||
merchantWindow->ADD("Item Name Label",MenuLabel)(geom2d::rect<float>{{226,84},{inventoryDescriptionWidth-6,12}},"",0.75f,ComponentAttr::LEFT_ALIGN|ComponentAttr::SHADOW)END;
|
||||
merchantWindow->ADD("Item Description Label",MenuLabel)(geom2d::rect<float>{{226,94},{inventoryDescriptionWidth-6,merchantWindow->size.y-44-66}},"",0.5f,ComponentAttr::LEFT_ALIGN|ComponentAttr::SHADOW)END;
|
||||
#pragma endregion
|
||||
@ -358,7 +363,8 @@ void Menu::InitializeMerchantWindow(){
|
||||
{game->KEY_SELECT,{[](MenuFuncData data){
|
||||
if(!data.menu.GetSelection().expired()&&
|
||||
!data.menu.GetSelection().lock()->parentComponent.expired()&&
|
||||
data.menu.GetSelection().lock()->parentComponent.lock()->GetName()=="Inventory Display - Accessories"){
|
||||
data.menu.GetSelection().lock()->parentComponent.lock()->GetName()=="Inventory Display - Accessories"&&
|
||||
data.menu.GetSelection().lock()->GetSubcomponentParent().expired()){
|
||||
if(DYNAMIC_POINTER_CAST<AccessoryRowItemDisplay>(data.menu.GetSelection().lock())->GetItem().lock()->IsLocked()){
|
||||
return "Unlock";
|
||||
}else{
|
||||
@ -369,8 +375,8 @@ void Menu::InitializeMerchantWindow(){
|
||||
},[](MenuType type){
|
||||
if(!Menu::menus[type]->GetSelection().expired()&&
|
||||
!Menu::menus[type]->GetSelection().lock()->parentComponent.expired()&&
|
||||
Menu::menus[type]->GetSelection().lock()->parentComponent.lock()->GetName()=="Inventory Display - Accessories"
|
||||
&&Menu::menus[type]->GetSelection().lock()->GetSubcomponentParent().expired()){
|
||||
Menu::menus[type]->GetSelection().lock()->parentComponent.lock()->GetName()=="Inventory Display - Accessories"&&
|
||||
Menu::menus[type]->GetSelection().lock()->GetSubcomponentParent().expired()){
|
||||
DYNAMIC_POINTER_CAST<AccessoryRowItemDisplay>(Menu::menus[type]->GetSelection().lock())->GetLockButton().lock()->Click();
|
||||
}
|
||||
}}},
|
||||
|
@ -51,7 +51,8 @@ INCLUDE_GFX
|
||||
void Menu::InitializePauseWindow(){
|
||||
Menu*pauseWindow=CreateMenu(MenuType::PAUSE,CENTERED,vi2d{96,140});
|
||||
|
||||
pauseWindow->ADD("Resume Button",MenuComponent)(geom2d::rect<float>{{6.f,0.f},{84.f,24.f}},"Resume",[](MenuFuncData data){
|
||||
pauseWindow->ADD("Resume Button",MenuComponent)(geom2d::rect<float>{{6.f,0.f},{84.f,24.f}},"Resume",[](MenuFuncData data){void ClearGarbage();
|
||||
game->ClearGarbage();
|
||||
Menu::CloseMenu();
|
||||
return true;
|
||||
},ButtonAttr::FIT_TO_LABEL)END;
|
||||
|
@ -10,4 +10,8 @@ should gemstones dropp from boss stages aswell? (Maybe lower droprate?)
|
||||
|
||||
Funny text colors with text color override on blacksmith menu
|
||||
|
||||
Toggle for displaying error messages
|
||||
Toggle for displaying error messages
|
||||
|
||||
Fix size of icons in merchant menus.
|
||||
Sherman's consumable crafting menu needs enabling/disabling of +/- buttons
|
||||
Label doesn't constantly update in the merchant window.
|
@ -39,7 +39,7 @@ All rights reserved.
|
||||
#define VERSION_MAJOR 0
|
||||
#define VERSION_MINOR 5
|
||||
#define VERSION_PATCH 1
|
||||
#define VERSION_BUILD 8038
|
||||
#define VERSION_BUILD 8066
|
||||
|
||||
#define stringify(a) stringify_(a)
|
||||
#define stringify_(a) #a
|
||||
|
@ -628,202 +628,181 @@ float olc::ViewPort::directionFromLine(vf2d lineA, vf2d lineB, vf2d point) {
|
||||
}
|
||||
|
||||
void olc::ViewPort::DrawStringDecal(const olc::vf2d& pos, std::string_view sText, const Pixel col, const olc::vf2d& scale, const float width,const bool disableDynamicScaling){
|
||||
struct DecalData{
|
||||
Decal*decal;
|
||||
float expireTime=0.0f;
|
||||
};
|
||||
if(sText.length()==0)return;
|
||||
static std::map<std::string,DecalData>garbageCollector;
|
||||
std::string key{sText};
|
||||
std::string key{"DSD_"+std::string(pge->stripCol(sText))};
|
||||
key+=std::to_string(width);
|
||||
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.
|
||||
if(!pge->garbageCollector.count(key)||pge->garbageCollector[key].originalStr!=sText){ //If the text key already exists, don't have to recreate the decal, just update the expire time.
|
||||
vi2d imageSize=pge->GetWrappedTextSize(sText,width,scale);
|
||||
Decal*newDecal=new Decal(new Sprite(imageSize.x/scale.x,imageSize.y/scale.x));
|
||||
garbageCollector[key].decal=newDecal;
|
||||
Decal*newDecal=nullptr;
|
||||
if(!pge->garbageCollector.count(key)){
|
||||
newDecal=new Decal(new Sprite(imageSize.x/scale.x,imageSize.y/scale.x));
|
||||
pge->garbageCollector[key].decal=newDecal;
|
||||
}else{
|
||||
newDecal=pge->garbageCollector[key].decal;
|
||||
}
|
||||
pge->garbageCollector[key].originalStr=sText;
|
||||
pge->SetDrawTarget(newDecal->sprite);
|
||||
pge->Clear(BLANK);
|
||||
pge->DrawString({0,0},sText,WHITE,1U,width/scale.x);
|
||||
pge->SetDrawTarget(nullptr);
|
||||
newDecal->Update();
|
||||
}
|
||||
garbageCollector[key].expireTime=pge->GetRuntime()+120.0f;
|
||||
std::erase_if(garbageCollector,[&](auto&key){
|
||||
if(key.second.expireTime<pge->GetRuntime()){
|
||||
delete key.second.decal;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
});
|
||||
DrawDecal(pos,garbageCollector[key].decal,scale,col);
|
||||
pge->garbageCollector[key].expireTime=pge->GetRuntime()+120.0f;
|
||||
DrawDecal(pos,pge->garbageCollector[key].decal,scale,col);
|
||||
}
|
||||
|
||||
void olc::ViewPort::DrawStringDecal(Font&font, const olc::vf2d& pos, const std::u32string& sText, const Pixel col, const olc::vf2d& scale){
|
||||
struct DecalData{
|
||||
Decal*decal;
|
||||
float expireTime=0.0f;
|
||||
};
|
||||
if(sText.length()==0)return;
|
||||
static std::map<std::u32string,DecalData>garbageCollector;
|
||||
std::u32string key=font.GetFontName()+U"_"+sText;
|
||||
if(!garbageCollector.count(key)){ //If the text key already exists, don't have to recreate the decal, just update the expire time.
|
||||
garbageCollector[key].decal=font.RenderStringToDecal(sText,WHITE);
|
||||
}
|
||||
garbageCollector[key].expireTime=pge->GetRuntime()+120.0f;
|
||||
std::erase_if(garbageCollector,[&](auto&key){
|
||||
if(key.second.expireTime<pge->GetRuntime()){
|
||||
delete key.second.decal;
|
||||
return true;
|
||||
std::u32string Ukey=U"DSD_"+font.GetFontName()+U"_"+pge->stripCol(sText);
|
||||
std::string key=std::string(Ukey.begin(),Ukey.end());
|
||||
if(!pge->garbageCollector.count(key)||pge->garbageCollector[key].originalStr!=std::string(sText.begin(),sText.end())){ //If the text key already exists, don't have to recreate the decal, just update the expire time.
|
||||
if(pge->garbageCollector.count(key)){
|
||||
delete pge->garbageCollector[key].decal;
|
||||
}
|
||||
return false;
|
||||
});
|
||||
DrawDecal(pos,garbageCollector[key].decal,scale/4,col);
|
||||
pge->garbageCollector[key].decal=font.RenderStringToDecal(sText,WHITE);
|
||||
pge->garbageCollector[key].originalStr=std::string(sText.begin(),sText.end());
|
||||
}
|
||||
pge->garbageCollector[key].expireTime=pge->GetRuntime()+120.0f;
|
||||
DrawDecal(pos,pge->garbageCollector[key].decal,scale/4,col);
|
||||
}
|
||||
|
||||
void olc::ViewPort::DrawStringPropDecal(const olc::vf2d& pos, std::string_view sText, const Pixel col, const olc::vf2d& scale,const float width,const bool disableDynamicScaling){
|
||||
struct DecalData{
|
||||
Decal*decal;
|
||||
float expireTime=0.0f;
|
||||
};
|
||||
if(sText.length()==0)return;
|
||||
static std::map<std::string,DecalData>garbageCollector;
|
||||
std::string key{sText};
|
||||
std::string key{"DSPD"+std::string(pge->stripCol(sText))};
|
||||
key+=std::to_string(width);
|
||||
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.
|
||||
if(!pge->garbageCollector.count(key)||pge->garbageCollector[key].originalStr!=sText){ //If the text key already exists, don't have to recreate the decal, just update the expire time.
|
||||
vi2d imageSize=pge->GetWrappedTextSizeProp(sText,width,scale);
|
||||
Decal*newDecal=new Decal(new Sprite(imageSize.x/scale.x,imageSize.y/scale.x));
|
||||
garbageCollector[key].decal=newDecal;
|
||||
Decal*newDecal=nullptr;
|
||||
if(!pge->garbageCollector.count(key)){
|
||||
newDecal=new Decal(new Sprite(imageSize.x/scale.x,imageSize.y/scale.x));
|
||||
pge->garbageCollector[key].decal=newDecal;
|
||||
}else{
|
||||
newDecal=pge->garbageCollector[key].decal;
|
||||
}
|
||||
pge->garbageCollector[key].originalStr=sText;
|
||||
pge->SetDrawTarget(newDecal->sprite);
|
||||
pge->Clear(BLANK);
|
||||
pge->DrawStringProp({0,0},sText,WHITE,1U,width/scale.x);
|
||||
pge->SetDrawTarget(nullptr);
|
||||
newDecal->Update();
|
||||
}
|
||||
garbageCollector[key].expireTime=pge->GetRuntime()+120.0f;
|
||||
std::erase_if(garbageCollector,[&](auto&key){
|
||||
if(key.second.expireTime<pge->GetRuntime()){
|
||||
delete key.second.decal;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
});
|
||||
DrawDecal(pos,garbageCollector[key].decal,scale,col);
|
||||
pge->garbageCollector[key].expireTime=pge->GetRuntime()+120.0f;
|
||||
DrawDecal(pos,pge->garbageCollector[key].decal,scale,col);
|
||||
}
|
||||
|
||||
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,const bool disableDynamicScaling){
|
||||
struct DecalData{
|
||||
Decal*decal;
|
||||
float expireTime=0.0f;
|
||||
};
|
||||
if(sText.length()==0)return;
|
||||
static std::map<std::string,DecalData>garbageCollector;
|
||||
std::string key{sText};
|
||||
key+=std::to_string(width);
|
||||
if(!disableDynamicScaling){
|
||||
key+=scale.str();
|
||||
if(sText.length()==0)return;
|
||||
std::string key{"DSSD_"+std::string(pge->stripCol(sText))};
|
||||
key+=std::to_string(width);
|
||||
if(!disableDynamicScaling){
|
||||
key+=scale.str();
|
||||
}
|
||||
if(!pge->garbageCollector.count(key)||pge->garbageCollector[key].originalStr!=sText){ //If the text key already exists, don't have to recreate the decal, just update the expire time.
|
||||
vi2d imageSize=pge->GetWrappedTextSize(sText,width,scale);
|
||||
Decal*newDecal=nullptr;
|
||||
if(!pge->garbageCollector.count(key)){
|
||||
newDecal=new Decal(new Sprite(imageSize.x/scale.x,imageSize.y/scale.x));
|
||||
pge->garbageCollector[key].decal=newDecal;
|
||||
}else{
|
||||
newDecal=pge->garbageCollector[key].decal;
|
||||
}
|
||||
if(!garbageCollector.count(key)){ //If the text key already exists, don't have to recreate the decal, just update the expire time.
|
||||
vi2d imageSize=pge->GetWrappedTextSize(sText,width,scale);
|
||||
Decal*newDecal=new Decal(new Sprite(imageSize.x/scale.x,imageSize.x/scale.x));
|
||||
garbageCollector[key].decal=newDecal;
|
||||
pge->SetDrawTarget(newDecal->sprite);
|
||||
pge->Clear(BLANK);
|
||||
pge->DrawString({0,0},sText,WHITE,1U,width/scale.x);
|
||||
newDecal->Update();
|
||||
vf2d adjustedShadowSizeFactor=vf2d{shadowSizeFactor,shadowSizeFactor}*4/scale;
|
||||
Decal*newShadowDecal=new Decal(new Sprite((imageSize.x/scale.x*4)+adjustedShadowSizeFactor.x*2,(imageSize.x/scale.x*4)+adjustedShadowSizeFactor.y*2));
|
||||
garbageCollector[key+"_SHADOW"].decal=newShadowDecal;
|
||||
pge->SetDrawTarget(newShadowDecal->sprite);
|
||||
pge->Clear(BLANK);
|
||||
for(float y=-adjustedShadowSizeFactor.y;y<=adjustedShadowSizeFactor.y+0.1;y+=adjustedShadowSizeFactor.y/2){
|
||||
for(float x=-adjustedShadowSizeFactor.x;x<=adjustedShadowSizeFactor.x+0.1;x+=adjustedShadowSizeFactor.x/2){
|
||||
if(x!=0||y!=0){
|
||||
pge->DrawString(vf2d{x,y}+adjustedShadowSizeFactor, sText, WHITE,4U,width/scale.x*4);
|
||||
}
|
||||
pge->garbageCollector[key].originalStr=sText;
|
||||
pge->SetDrawTarget(newDecal->sprite);
|
||||
pge->Clear(BLANK);
|
||||
pge->DrawString({0,0},sText,WHITE,1U,width/scale.x);
|
||||
newDecal->Update();
|
||||
vf2d adjustedShadowSizeFactor=vf2d{shadowSizeFactor,shadowSizeFactor}*4/scale;
|
||||
Decal*newShadowDecal=nullptr;
|
||||
if(!pge->garbageCollector.count(key+"_SHADOW")){
|
||||
newShadowDecal=new Decal(new Sprite((imageSize.x/scale.x*4)+adjustedShadowSizeFactor.x*2,(imageSize.x/scale.x*4)+adjustedShadowSizeFactor.y*2));
|
||||
pge->garbageCollector[key+"_SHADOW"].decal=newShadowDecal;
|
||||
}else{
|
||||
newShadowDecal=pge->garbageCollector[key+"_SHADOW"].decal;
|
||||
}
|
||||
pge->SetDrawTarget(newShadowDecal->sprite);
|
||||
pge->Clear(BLANK);
|
||||
for(float y=-adjustedShadowSizeFactor.y;y<=adjustedShadowSizeFactor.y+0.1;y+=adjustedShadowSizeFactor.y/2){
|
||||
for(float x=-adjustedShadowSizeFactor.x;x<=adjustedShadowSizeFactor.x+0.1;x+=adjustedShadowSizeFactor.x/2){
|
||||
if(x!=0||y!=0){
|
||||
pge->DrawString(vf2d{x,y}+adjustedShadowSizeFactor, sText, WHITE,4U,width/scale.x*4);
|
||||
}
|
||||
}
|
||||
pge->SetDrawTarget(nullptr);
|
||||
newShadowDecal->Update();
|
||||
}
|
||||
garbageCollector[key].expireTime=pge->GetRuntime()+120.0f;
|
||||
garbageCollector[key+"_SHADOW"].expireTime=pge->GetRuntime()+120.0f;
|
||||
std::erase_if(garbageCollector,[&](auto&key){
|
||||
if(key.second.expireTime<pge->GetRuntime()){
|
||||
delete key.second.decal;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
});
|
||||
DrawDecal(pos-vf2d{shadowSizeFactor,shadowSizeFactor},garbageCollector[key+"_SHADOW"].decal,scale/4,shadowCol);
|
||||
DrawDecal(pos,garbageCollector[key].decal,scale,col);
|
||||
pge->SetDrawTarget(nullptr);
|
||||
newShadowDecal->Update();
|
||||
}
|
||||
pge->garbageCollector[key].expireTime=pge->GetRuntime()+120.0f;
|
||||
pge->garbageCollector[key+"_SHADOW"].expireTime=pge->GetRuntime()+120.0f;
|
||||
DrawDecal(pos-vf2d{shadowSizeFactor,shadowSizeFactor},pge->garbageCollector[key+"_SHADOW"].decal,scale/4,shadowCol);
|
||||
DrawDecal(pos,pge->garbageCollector[key].decal,scale,col);
|
||||
}
|
||||
|
||||
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,const bool disableDynamicScaling){
|
||||
struct DecalData{
|
||||
Decal*decal;
|
||||
float expireTime=0.0f;
|
||||
};
|
||||
if(sText.length()==0)return;
|
||||
static std::map<std::string,DecalData>garbageCollector;
|
||||
std::string key{sText};
|
||||
key+=std::to_string(width);
|
||||
if(!disableDynamicScaling){
|
||||
key+=scale.str();
|
||||
if(sText.length()==0)return;
|
||||
std::string key{"DSSPD"+std::string(pge->stripCol(sText))};
|
||||
key+=std::to_string(width);
|
||||
if(!disableDynamicScaling){
|
||||
key+=scale.str();
|
||||
}
|
||||
if(!pge->garbageCollector.count(key)||pge->garbageCollector[key].originalStr!=sText){ //If the text key already exists, don't have to recreate the decal, just update the expire time.
|
||||
vi2d imageSize=pge->GetWrappedTextSizeProp(sText,width,scale);
|
||||
Decal*newDecal=nullptr;
|
||||
if(!pge->garbageCollector.count(key)){
|
||||
newDecal=new Decal(new Sprite(imageSize.x/scale.x,imageSize.y/scale.x));
|
||||
pge->garbageCollector[key].decal=newDecal;
|
||||
}else{
|
||||
newDecal=pge->garbageCollector[key].decal;
|
||||
}
|
||||
if(!garbageCollector.count(key)){ //If the text key already exists, don't have to recreate the decal, just update the expire time.
|
||||
vi2d imageSize=pge->GetWrappedTextSizeProp(sText,width,scale);
|
||||
Decal*newDecal=new Decal(new Sprite(imageSize.x/scale.x,imageSize.x/scale.x));
|
||||
garbageCollector[key].decal=newDecal;
|
||||
pge->SetDrawTarget(newDecal->sprite);
|
||||
pge->Clear(BLANK);
|
||||
pge->DrawStringProp({0,0},sText,WHITE,1U,width/scale.x);
|
||||
newDecal->Update();
|
||||
vf2d adjustedShadowSizeFactor=vf2d{shadowSizeFactor,shadowSizeFactor}*4/scale;
|
||||
Decal*newShadowDecal=new Decal(new Sprite((imageSize.x/scale.x*4)+adjustedShadowSizeFactor.x*2,(imageSize.x/scale.x*4)+adjustedShadowSizeFactor.y*2));
|
||||
garbageCollector[key+"_SHADOW"].decal=newShadowDecal;
|
||||
pge->SetDrawTarget(newShadowDecal->sprite);
|
||||
pge->Clear(BLANK);
|
||||
for(float y=-adjustedShadowSizeFactor.y;y<=adjustedShadowSizeFactor.y+0.1;y+=adjustedShadowSizeFactor.y/2){
|
||||
for(float x=-adjustedShadowSizeFactor.x;x<=adjustedShadowSizeFactor.x+0.1;x+=adjustedShadowSizeFactor.x/2){
|
||||
if(x!=0||y!=0){
|
||||
pge->DrawStringProp(vf2d{x,y}+adjustedShadowSizeFactor, sText, WHITE,4U,width/scale.x*4);
|
||||
}
|
||||
pge->garbageCollector[key].originalStr=sText;
|
||||
pge->SetDrawTarget(newDecal->sprite);
|
||||
pge->Clear(BLANK);
|
||||
pge->DrawStringProp({0,0},sText,WHITE,1U,width/scale.x);
|
||||
newDecal->Update();
|
||||
vf2d adjustedShadowSizeFactor=vf2d{shadowSizeFactor,shadowSizeFactor}*4/scale;
|
||||
Decal*newShadowDecal=nullptr;
|
||||
if(!pge->garbageCollector.count(key+"_SHADOW")){
|
||||
newShadowDecal=new Decal(new Sprite((imageSize.x/scale.x*4)+adjustedShadowSizeFactor.x*2,(imageSize.x/scale.x*4)+adjustedShadowSizeFactor.y*2));
|
||||
pge->garbageCollector[key+"_SHADOW"].decal=newShadowDecal;
|
||||
}else{
|
||||
newShadowDecal=pge->garbageCollector[key+"_SHADOW"].decal;
|
||||
}
|
||||
pge->SetDrawTarget(newShadowDecal->sprite);
|
||||
pge->Clear(BLANK);
|
||||
for(float y=-adjustedShadowSizeFactor.y;y<=adjustedShadowSizeFactor.y+0.1;y+=adjustedShadowSizeFactor.y/2){
|
||||
for(float x=-adjustedShadowSizeFactor.x;x<=adjustedShadowSizeFactor.x+0.1;x+=adjustedShadowSizeFactor.x/2){
|
||||
if(x!=0||y!=0){
|
||||
pge->DrawStringProp(vf2d{x,y}+adjustedShadowSizeFactor, sText, WHITE,4U,width/scale.x*4);
|
||||
}
|
||||
}
|
||||
pge->SetDrawTarget(nullptr);
|
||||
newShadowDecal->Update();
|
||||
}
|
||||
garbageCollector[key].expireTime=pge->GetRuntime()+120.0f;
|
||||
garbageCollector[key+"_SHADOW"].expireTime=pge->GetRuntime()+120.0f;
|
||||
std::erase_if(garbageCollector,[&](auto&key){
|
||||
if(key.second.expireTime<pge->GetRuntime()){
|
||||
delete key.second.decal;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
});
|
||||
DrawDecal(pos-vf2d{shadowSizeFactor,shadowSizeFactor},garbageCollector[key+"_SHADOW"].decal,scale/4,shadowCol);
|
||||
DrawDecal(pos,garbageCollector[key].decal,scale,col);
|
||||
pge->SetDrawTarget(nullptr);
|
||||
newShadowDecal->Update();
|
||||
}
|
||||
pge->garbageCollector[key].expireTime=pge->GetRuntime()+120.0f;
|
||||
pge->garbageCollector[key+"_SHADOW"].expireTime=pge->GetRuntime()+120.0f;
|
||||
DrawDecal(pos-vf2d{shadowSizeFactor,shadowSizeFactor},pge->garbageCollector[key+"_SHADOW"].decal,scale/4,shadowCol);
|
||||
DrawDecal(pos,pge->garbageCollector[key].decal,scale,col);
|
||||
}
|
||||
|
||||
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){
|
||||
struct DecalData{
|
||||
Decal*decal;
|
||||
float expireTime=0.0f;
|
||||
};
|
||||
if(sText.length()==0)return;
|
||||
static std::map<std::u32string,DecalData>garbageCollector;
|
||||
std::u32string key=font.GetFontName()+U"_"+sText;
|
||||
if(!garbageCollector.count(key)){ //If the text key already exists, don't have to recreate the decal, just update the expire time.
|
||||
garbageCollector[key].decal=font.RenderStringToDecal(sText,WHITE);
|
||||
std::u32string Ukey=U"DSSD_"+font.GetFontName()+U"_"+pge->stripCol(sText);
|
||||
std::string key=std::string(Ukey.begin(),Ukey.end());
|
||||
if(!pge->garbageCollector.count(key)||pge->garbageCollector[key].originalStr!=std::string(sText.begin(),sText.end())){ //If the text key already exists, don't have to recreate the decal, just update the expire time.
|
||||
if(pge->garbageCollector.count(key)){
|
||||
delete pge->garbageCollector[key].decal;
|
||||
}
|
||||
pge->garbageCollector[key].decal=font.RenderStringToDecal(sText,WHITE);
|
||||
pge->garbageCollector[key].originalStr=std::string(sText.begin(),sText.end());
|
||||
}
|
||||
garbageCollector[key].expireTime=pge->GetRuntime()+120.0f;
|
||||
std::erase_if(garbageCollector,[&](auto&key){
|
||||
pge->garbageCollector[key].expireTime=pge->GetRuntime()+120.0f;
|
||||
std::erase_if(pge->garbageCollector,[&](auto&key){
|
||||
if(key.second.expireTime<pge->GetRuntime()){
|
||||
delete key.second.decal;
|
||||
return true;
|
||||
@ -833,36 +812,29 @@ void olc::ViewPort::DrawShadowStringDecal(Font&font, const olc::vf2d& pos, const
|
||||
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){
|
||||
DrawDecal(pos+vf2d{x,y},garbageCollector[key].decal,scale/4,shadowCol);
|
||||
DrawDecal(pos+vf2d{x,y},pge->garbageCollector[key].decal,scale/4,shadowCol);
|
||||
}
|
||||
}
|
||||
}
|
||||
DrawDecal(pos,garbageCollector[key].decal,scale/4,col);
|
||||
DrawDecal(pos,pge->garbageCollector[key].decal,scale/4,col);
|
||||
}
|
||||
|
||||
void olc::ViewPort::DrawDropShadowStringDecal(Font&font, const olc::vf2d& pos, const std::u32string& sText, const Pixel col, const Pixel shadowCol, const olc::vf2d& scale){
|
||||
struct DecalData{
|
||||
Decal*decal;
|
||||
float expireTime=0.0f;
|
||||
};
|
||||
if(sText.length()==0)return;
|
||||
static std::map<std::u32string,DecalData>garbageCollector;
|
||||
std::u32string key=font.GetFontName()+U"_"+sText;
|
||||
if(!garbageCollector.count(key)){ //If the text key already exists, don't have to recreate the decal, just update the expire time.
|
||||
garbageCollector[key].decal=font.RenderStringToDecal(sText,WHITE);
|
||||
}
|
||||
garbageCollector[key].expireTime=pge->GetRuntime()+120.0f;
|
||||
std::erase_if(garbageCollector,[&](auto&key){
|
||||
if(key.second.expireTime<pge->GetRuntime()){
|
||||
delete key.second.decal;
|
||||
return true;
|
||||
std::u32string Ukey=U"DDSSD_"+font.GetFontName()+U"_"+pge->stripCol(sText);
|
||||
std::string key=std::string(Ukey.begin(),Ukey.end());
|
||||
if(!pge->garbageCollector.count(key)||pge->garbageCollector[key].originalStr!=std::string(sText.begin(),sText.end())){ //If the text key already exists, don't have to recreate the decal, just update the expire time.
|
||||
if(pge->garbageCollector.count(key)){
|
||||
delete pge->garbageCollector[key].decal;
|
||||
}
|
||||
return false;
|
||||
});
|
||||
DrawDecal(pos+vf2d{0,0.5f},garbageCollector[key].decal,scale/4,shadowCol);
|
||||
DrawDecal(pos+vf2d{0.5f,0},garbageCollector[key].decal,scale/4,shadowCol);
|
||||
DrawDecal(pos+vf2d{0.5f,0.5f},garbageCollector[key].decal,scale/4,shadowCol);
|
||||
DrawDecal(pos,garbageCollector[key].decal,scale/4,col);
|
||||
pge->garbageCollector[key].decal=font.RenderStringToDecal(sText,WHITE);
|
||||
pge->garbageCollector[key].originalStr=std::string(sText.begin(),sText.end());
|
||||
}
|
||||
pge->garbageCollector[key].expireTime=pge->GetRuntime()+120.0f;
|
||||
DrawDecal(pos+vf2d{0,0.5f},pge->garbageCollector[key].decal,scale/4,shadowCol);
|
||||
DrawDecal(pos+vf2d{0.5f,0},pge->garbageCollector[key].decal,scale/4,shadowCol);
|
||||
DrawDecal(pos+vf2d{0.5f,0.5f},pge->garbageCollector[key].decal,scale/4,shadowCol);
|
||||
DrawDecal(pos,pge->garbageCollector[key].decal,scale/4,col);
|
||||
}
|
||||
|
||||
void olc::ViewPort::DrawRectDecal(const olc::vf2d& pos, const olc::vf2d& size, const olc::Pixel col)const{
|
||||
|
@ -981,6 +981,7 @@ namespace olc
|
||||
// O------------------------------------------------------------------------------O
|
||||
class PixelGameEngine
|
||||
{
|
||||
friend class ViewPort;
|
||||
struct StringDecalData{
|
||||
char c;
|
||||
vf2d sourcePos;
|
||||
@ -1021,6 +1022,9 @@ namespace olc
|
||||
|
||||
|
||||
public: // Hardware Interfaces
|
||||
void ClearGarbage();
|
||||
void ClearTimedOutGarbage();
|
||||
|
||||
// Returns true if window is currently in focus
|
||||
bool IsFocused() const;
|
||||
// Get the state of a specific keyboard button
|
||||
@ -1349,6 +1353,13 @@ namespace olc
|
||||
olc::vi2d vDroppedFilesPointCache;
|
||||
uint8_t mosaic=1;
|
||||
uint8_t nTextEntryCharLimit=std::numeric_limits<uint8_t>::max();
|
||||
struct DecalData{
|
||||
Decal*decal=nullptr;
|
||||
float expireTime=0.0f;
|
||||
std::string originalStr;
|
||||
};
|
||||
std::unordered_map<std::string,DecalData>garbageCollector;
|
||||
bool requestClear=false;
|
||||
|
||||
// Command Console Specific
|
||||
bool bConsoleShow = false;
|
||||
@ -1363,6 +1374,9 @@ namespace olc
|
||||
std::list<std::string> sCommandHistory;
|
||||
std::list<std::string>::iterator sCommandHistoryIt;
|
||||
|
||||
std::string stripCol(std::string_view originalText);
|
||||
std::u32string stripCol(std::u32string_view originalText);
|
||||
|
||||
// Text Entry Specific
|
||||
bool bTextEntryEnable = false;
|
||||
std::string sTextEntryString = "";
|
||||
@ -2240,6 +2254,42 @@ namespace olc
|
||||
|
||||
uint32_t PixelGameEngine::GetFPS() const
|
||||
{ return nLastFPS; }
|
||||
void PixelGameEngine::ClearGarbage(){
|
||||
requestClear=true;
|
||||
}
|
||||
void PixelGameEngine::ClearTimedOutGarbage(){
|
||||
std::erase_if(garbageCollector,[&](auto&key){
|
||||
if(key.second.expireTime<GetRuntime()){
|
||||
delete key.second.decal;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
});
|
||||
}
|
||||
|
||||
std::string PixelGameEngine::stripCol(std::string_view originalText){
|
||||
std::string newStr{""};
|
||||
for(int i=0;i<originalText.length();i++){
|
||||
if(originalText[i]=='#'){
|
||||
i+=6;
|
||||
continue;
|
||||
}
|
||||
newStr+=originalText[i];
|
||||
}
|
||||
return newStr;
|
||||
}
|
||||
|
||||
std::u32string PixelGameEngine::stripCol(std::u32string_view originalText){
|
||||
std::u32string newStr{U""};
|
||||
for(int i=0;i<originalText.length();i++){
|
||||
if(originalText[i]=='#'){
|
||||
i+=6;
|
||||
continue;
|
||||
}
|
||||
newStr+=originalText[i];
|
||||
}
|
||||
return newStr;
|
||||
}
|
||||
|
||||
bool PixelGameEngine::IsFocused() const
|
||||
{ return bHasInputFocus; }
|
||||
@ -3437,21 +3487,22 @@ namespace olc
|
||||
|
||||
void PixelGameEngine::DrawStringDecal(const olc::vf2d& pos, std::string_view sText, const Pixel col, const olc::vf2d& scale,const float width,const bool disableDynamicScaling)
|
||||
{
|
||||
struct DecalData{
|
||||
Decal*decal=nullptr;
|
||||
float expireTime=0.0f;
|
||||
};
|
||||
if(sText.length()==0)return;
|
||||
static std::map<std::string,DecalData>garbageCollector;
|
||||
std::string key{sText};
|
||||
std::string key{"DSD"+std::string(stripCol(sText))};
|
||||
key+=std::to_string(width);
|
||||
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.
|
||||
if(!garbageCollector.count(key)||garbageCollector[key].originalStr!=sText){ //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;
|
||||
Decal*newDecal=nullptr;
|
||||
if(!garbageCollector.count(key)){
|
||||
newDecal=new Decal(new Sprite(imageSize.x/scale.x,imageSize.y/scale.x));
|
||||
garbageCollector[key].decal=newDecal;
|
||||
}else{
|
||||
newDecal=garbageCollector[key].decal;
|
||||
}
|
||||
garbageCollector[key].originalStr=sText;
|
||||
SetDrawTarget(newDecal->sprite);
|
||||
Clear(BLANK);
|
||||
DrawString({0,0},sText,WHITE,1U,width/scale.x);
|
||||
@ -3459,33 +3510,27 @@ namespace olc
|
||||
newDecal->Update();
|
||||
}
|
||||
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 disableDynamicScaling)
|
||||
{
|
||||
struct DecalData{
|
||||
Decal*decal=nullptr;
|
||||
float expireTime=0.0f;
|
||||
};
|
||||
if(sText.length()==0)return;
|
||||
static std::map<std::string,DecalData>garbageCollector;
|
||||
std::string key{sText};
|
||||
std::string key{"DSPD_"+std::string(stripCol(sText))};
|
||||
key+=std::to_string(width);
|
||||
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.
|
||||
if(!garbageCollector.count(key)||garbageCollector[key].originalStr!=sText){ //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;
|
||||
Decal*newDecal=nullptr;
|
||||
if(!garbageCollector.count(key)){
|
||||
newDecal=new Decal(new Sprite(imageSize.x/scale.x,imageSize.y/scale.x));
|
||||
garbageCollector[key].decal=newDecal;
|
||||
}else{
|
||||
newDecal=garbageCollector[key].decal;
|
||||
}
|
||||
garbageCollector[key].originalStr=sText;
|
||||
SetDrawTarget(newDecal->sprite);
|
||||
Clear(BLANK);
|
||||
DrawStringProp({0,0},sText,WHITE,1U,width/scale.x);
|
||||
@ -3493,39 +3538,38 @@ namespace olc
|
||||
newDecal->Update();
|
||||
}
|
||||
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,const bool disableDynamicScaling){
|
||||
struct DecalData{
|
||||
Decal*decal=nullptr;
|
||||
float expireTime=0.0f;
|
||||
};
|
||||
if(sText.length()==0)return;
|
||||
static std::map<std::string,DecalData>garbageCollector;
|
||||
std::string key{sText};
|
||||
std::string key{"DSSD_"+std::string(stripCol(sText))};
|
||||
key+=std::to_string(width);
|
||||
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.
|
||||
if(!garbageCollector.count(key)||garbageCollector[key].originalStr!=sText){ //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.x/scale.x));
|
||||
garbageCollector[key].decal=newDecal;
|
||||
Decal*newDecal=nullptr;
|
||||
if(!garbageCollector.count(key)){
|
||||
newDecal=new Decal(new Sprite(imageSize.x/scale.x,imageSize.y/scale.x));
|
||||
garbageCollector[key].decal=newDecal;
|
||||
}else{
|
||||
newDecal=garbageCollector[key].decal;
|
||||
}
|
||||
garbageCollector[key].originalStr=sText;
|
||||
SetDrawTarget(newDecal->sprite);
|
||||
Clear(BLANK);
|
||||
DrawString({0,0},sText,WHITE,1U,width/scale.x);
|
||||
newDecal->Update();
|
||||
vf2d adjustedShadowSizeFactor=vf2d{shadowSizeFactor,shadowSizeFactor}*4/scale;
|
||||
Decal*newShadowDecal=new Decal(new Sprite((imageSize.x/scale.x*4)+adjustedShadowSizeFactor.x*2,(imageSize.x/scale.x*4)+adjustedShadowSizeFactor.y*2));
|
||||
garbageCollector[key+"_SHADOW"].decal=newShadowDecal;
|
||||
Decal*newShadowDecal=nullptr;
|
||||
if(!garbageCollector.count(key+"_SHADOW")){
|
||||
newShadowDecal=new Decal(new Sprite((imageSize.x/scale.x*4)+adjustedShadowSizeFactor.x*2,(imageSize.x/scale.x*4)+adjustedShadowSizeFactor.y*2));
|
||||
garbageCollector[key+"_SHADOW"].decal=newShadowDecal;
|
||||
}else{
|
||||
newShadowDecal=garbageCollector[key+"_SHADOW"].decal;
|
||||
}
|
||||
SetDrawTarget(newShadowDecal->sprite);
|
||||
Clear(BLANK);
|
||||
for(float y=-adjustedShadowSizeFactor.y;y<=adjustedShadowSizeFactor.y+0.1;y+=adjustedShadowSizeFactor.y/2){
|
||||
@ -3540,58 +3584,37 @@ namespace olc
|
||||
}
|
||||
garbageCollector[key].expireTime=GetRuntime()+120.0f;
|
||||
garbageCollector[key+"_SHADOW"].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-vf2d{shadowSizeFactor,shadowSizeFactor},garbageCollector[key+"_SHADOW"].decal,scale/4,shadowCol);
|
||||
DrawDecal(pos,garbageCollector[key].decal,scale,col);
|
||||
}
|
||||
|
||||
void PixelGameEngine::DrawStringDecal(Font&font, const olc::vf2d& pos, const std::u32string& sText, const Pixel col, const olc::vf2d& scale){
|
||||
struct DecalData{
|
||||
Decal*decal=nullptr;
|
||||
float expireTime=0.0f;
|
||||
};
|
||||
if(sText.length()==0)return;
|
||||
static std::map<std::u32string,DecalData>garbageCollector;
|
||||
std::u32string key=font.GetFontName()+U"_"+sText;
|
||||
if(!garbageCollector.count(key)){ //If the text key already exists, don't have to recreate the decal, just update the expire time.
|
||||
std::u32string Ukey=U"DSD_"+font.GetFontName()+U"_"+stripCol(sText);
|
||||
std::string key=std::string(Ukey.begin(),Ukey.end());
|
||||
if(!garbageCollector.count(key)||garbageCollector[key].originalStr!=std::string(sText.begin(),sText.end())){ //If the text key already exists, don't have to recreate the decal, just update the expire time.
|
||||
if(garbageCollector.count(key)){
|
||||
delete garbageCollector[key].decal;
|
||||
}
|
||||
garbageCollector[key].decal=font.RenderStringToDecal(sText,WHITE);
|
||||
garbageCollector[key].originalStr=std::string(sText.begin(),sText.end());
|
||||
}
|
||||
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/4,col);
|
||||
}
|
||||
|
||||
void PixelGameEngine::DrawShadowStringDecal(Font&font, const olc::vf2d& pos, const std::u32string& sText, const Pixel col, const Pixel shadowCol, const olc::vf2d& scale,const float shadowSizeFactor){
|
||||
struct DecalData{
|
||||
Decal*decal=nullptr;
|
||||
float expireTime=0.0f;
|
||||
};
|
||||
if(sText.length()==0)return;
|
||||
static std::map<std::u32string,DecalData>garbageCollector;
|
||||
std::u32string key=font.GetFontName()+U"_"+sText;
|
||||
if(!garbageCollector.count(key)){ //If the text key already exists, don't have to recreate the decal, just update the expire time.
|
||||
std::u32string Ukey=U"DSSD_"+font.GetFontName()+U"_"+stripCol(sText);
|
||||
std::string key=std::string(Ukey.begin(),Ukey.end());
|
||||
if(!garbageCollector.count(key)||garbageCollector[key].originalStr!=std::string(sText.begin(),sText.end())){ //If the text key already exists, don't have to recreate the decal, just update the expire time.
|
||||
if(garbageCollector.count(key)){
|
||||
delete garbageCollector[key].decal;
|
||||
}
|
||||
garbageCollector[key].decal=font.RenderStringToDecal(sText,WHITE);
|
||||
garbageCollector[key].originalStr=std::string(sText.begin(),sText.end());
|
||||
}
|
||||
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;
|
||||
});
|
||||
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){
|
||||
@ -3603,24 +3626,17 @@ namespace olc
|
||||
}
|
||||
|
||||
void PixelGameEngine::DrawDropShadowStringDecal(Font&font, const olc::vf2d& pos, const std::u32string& sText, const Pixel col, const Pixel shadowCol, const olc::vf2d& scale){
|
||||
struct DecalData{
|
||||
Decal*decal=nullptr;
|
||||
float expireTime=0.0f;
|
||||
};
|
||||
if(sText.length()==0)return;
|
||||
static std::map<std::u32string,DecalData>garbageCollector;
|
||||
std::u32string key=font.GetFontName()+U"_"+sText;
|
||||
if(!garbageCollector.count(key)){ //If the text key already exists, don't have to recreate the decal, just update the expire time.
|
||||
std::u32string Ukey=U"DDSSD_"+font.GetFontName()+U"_"+stripCol(sText);
|
||||
std::string key=std::string(Ukey.begin(),Ukey.end());
|
||||
if(!garbageCollector.count(key)||garbageCollector[key].originalStr!=std::string(sText.begin(),sText.end())){ //If the text key already exists, don't have to recreate the decal, just update the expire time.
|
||||
if(garbageCollector.count(key)){
|
||||
delete garbageCollector[key].decal;
|
||||
}
|
||||
garbageCollector[key].decal=font.RenderStringToDecal(sText,WHITE);
|
||||
garbageCollector[key].originalStr=std::string(sText.begin(),sText.end());
|
||||
}
|
||||
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+vf2d{0,0.5f},garbageCollector[key].decal,scale/4,shadowCol);
|
||||
DrawDecal(pos+vf2d{0.5f,0},garbageCollector[key].decal,scale/4,shadowCol);
|
||||
DrawDecal(pos+vf2d{0.5f,0.5f},garbageCollector[key].decal,scale/4,shadowCol);
|
||||
@ -3628,28 +3644,34 @@ namespace olc
|
||||
}
|
||||
|
||||
void PixelGameEngine::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,const bool disableDynamicScaling){
|
||||
struct DecalData{
|
||||
Decal*decal=nullptr;
|
||||
float expireTime=0.0f;
|
||||
};
|
||||
if(sText.length()==0)return;
|
||||
static std::map<std::string,DecalData>garbageCollector;
|
||||
std::string key{sText};
|
||||
std::string key{"DSSPD_"+std::string(stripCol(sText))};
|
||||
key+=std::to_string(width);
|
||||
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.
|
||||
if(!garbageCollector.count(key)||garbageCollector[key].originalStr!=sText){ //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.x/scale.x));
|
||||
garbageCollector[key].decal=newDecal;
|
||||
Decal*newDecal=nullptr;
|
||||
if(!garbageCollector.count(key)){
|
||||
newDecal=new Decal(new Sprite(imageSize.x/scale.x,imageSize.y/scale.x));
|
||||
garbageCollector[key].decal=newDecal;
|
||||
}else{
|
||||
newDecal=garbageCollector[key].decal;
|
||||
}
|
||||
garbageCollector[key].originalStr=sText;
|
||||
SetDrawTarget(newDecal->sprite);
|
||||
Clear(BLANK);
|
||||
DrawStringProp({0,0},sText,WHITE,1U,width/scale.x);
|
||||
newDecal->Update();
|
||||
vf2d adjustedShadowSizeFactor=vf2d{shadowSizeFactor,shadowSizeFactor}*4/scale;
|
||||
Decal*newShadowDecal=new Decal(new Sprite((imageSize.x/scale.x*4)+adjustedShadowSizeFactor.x*2,(imageSize.x/scale.x*4)+adjustedShadowSizeFactor.y*2));
|
||||
garbageCollector[key+"_SHADOW"].decal=newShadowDecal;
|
||||
Decal*newShadowDecal=nullptr;
|
||||
if(!garbageCollector.count(key+"_SHADOW")){
|
||||
newShadowDecal=new Decal(new Sprite((imageSize.x/scale.x*4)+adjustedShadowSizeFactor.x*2,(imageSize.x/scale.x*4)+adjustedShadowSizeFactor.y*2));
|
||||
garbageCollector[key+"_SHADOW"].decal=newShadowDecal;
|
||||
}else{
|
||||
newShadowDecal=garbageCollector[key+"_SHADOW"].decal;
|
||||
}
|
||||
SetDrawTarget(newShadowDecal->sprite);
|
||||
Clear(BLANK);
|
||||
for(float y=-adjustedShadowSizeFactor.y;y<=adjustedShadowSizeFactor.y+0.1;y+=adjustedShadowSizeFactor.y/2){
|
||||
@ -3664,13 +3686,6 @@ namespace olc
|
||||
}
|
||||
garbageCollector[key].expireTime=GetRuntime()+120.0f;
|
||||
garbageCollector[key+"_SHADOW"].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-vf2d{shadowSizeFactor,shadowSizeFactor},garbageCollector[key+"_SHADOW"].decal,scale/4,shadowCol);
|
||||
DrawDecal(pos,garbageCollector[key].decal,scale,col);
|
||||
}
|
||||
@ -4827,7 +4842,13 @@ namespace olc
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if(requestClear||garbageCollector.size()>5000){
|
||||
std::for_each(garbageCollector.begin(),garbageCollector.end(),[&](auto&key){
|
||||
delete key.second.decal;
|
||||
});
|
||||
garbageCollector.clear();
|
||||
requestClear=false;
|
||||
}
|
||||
|
||||
// Present Graphics to screen
|
||||
renderer->DisplayFrame();
|
||||
|
Binary file not shown.
Loading…
x
Reference in New Issue
Block a user