Fix Perspective correction on ViewPort PGEX. Implement windowing system and remove sprite reliance from all menu components.

pull/28/head
sigonasr2 12 months ago
parent 4bab1397dc
commit 7a46f79f2b
  1. 20
      Crawler/CharacterAbilityPreviewComponent.h
  2. 9
      Crawler/CharacterMenuWindow.cpp
  3. 6
      Crawler/CharacterRotatingDisplay.h
  4. 1
      Crawler/InventoryConsumableWindow.cpp
  5. 12
      Crawler/InventoryWindow.cpp
  6. 41
      Crawler/Menu.cpp
  7. 3
      Crawler/Menu.h
  8. 8
      Crawler/MenuAnimatedIconButton.h
  9. 6
      Crawler/MenuAnimatedIconToggleButton.h
  10. 94
      Crawler/MenuComponent.cpp
  11. 10
      Crawler/MenuComponent.h
  12. 21
      Crawler/MenuIconButton.h
  13. 22
      Crawler/MenuItemButton.h
  14. 11
      Crawler/MenuItemItemButton.h
  15. 43
      Crawler/MenuLabel.h
  16. 15
      Crawler/PopupMenuLabel.h
  17. 30
      Crawler/ScrollableWindowComponent.h
  18. 9
      Crawler/SpawnEncounterLabel.h
  19. 2
      Crawler/Version.h
  20. 33
      Crawler/drawutil.cpp
  21. 2
      Crawler/drawutil.h
  22. 6
      Crawler/olcPGEX_TransformedView.h
  23. 83
      Crawler/olcPGEX_ViewPort.h
  24. 16
      Crawler/olcPixelGameEngine.h

@ -45,8 +45,6 @@ All rights reserved.
INCLUDE_game
INCLUDE_GFX
#define ICONPOS vi2d iconPos=parentPos+rect.pos+vi2d{5,5};
class CharacterAbilityPreviewComponent:public MenuLabel{
Ability*ability;
public:
@ -56,18 +54,8 @@ protected:
virtual void inline Update(Crawler*game)override{
MenuLabel::Update(game);
}
virtual void inline Draw(Crawler*game,vf2d parentPos)override{
MenuLabel::Draw(game,parentPos);
game->DrawRect(parentPos+rect.pos+vi2d{2,2},vi2d{int(rect.size.y)-4,int(rect.size.y)-4});
ICONPOS
game->DrawSprite(iconPos,GFX[ability->icon].Sprite());
vi2d descriptionPos=iconPos+vi2d{int(rect.size.y)-2,1};
game->DrawShadowStringProp(descriptionPos,util::WrapText(game,ability->description,int(rect.size.x-(descriptionPos.x-rect.pos.x)),true,{1,1}));
}
virtual void inline DrawDecal(Crawler*game,vf2d parentPos,bool focused)override{
ICONPOS
virtual void inline DrawDecal(ViewPort&window,vf2d parentPos,bool focused)override{
vi2d iconPos=parentPos+rect.pos+vi2d{5,5};
vi2d textPos=iconPos+vi2d{12,12};
float textWidth=game->GetTextSizeProp(ability->input->GetDisplayName()).x*0.5f+4;
@ -75,9 +63,9 @@ protected:
float boxWidth=rect.size.y-4; //No, the y is not a typo. It's a square, we use the y to determine the x.
if(textWidth>boxWidth){
game->DrawShadowStringPropDecal(textPos,ability->input->GetDisplayName(),WHITE,BLACK,{boxWidth/textWidth*0.5f,0.5});
window.DrawShadowStringPropDecal(textPos,ability->input->GetDisplayName(),WHITE,BLACK,{boxWidth/textWidth*0.5f,0.5});
}else{
game->DrawShadowStringPropDecal(textPos,ability->input->GetDisplayName(),WHITE,BLACK,{0.5,0.5});
window.DrawShadowStringPropDecal(textPos,ability->input->GetDisplayName(),WHITE,BLACK,{0.5,0.5});
}
}
};

@ -56,8 +56,7 @@ void Menu::InitializeCharacterMenuWindow(){
vf2d windowSize=game->GetScreenSize()-vf2d{52,52};
Menu*characterMenuWindow=CreateMenu(CHARACTER_MENU,CENTERED,windowSize);
characterMenuWindow->ADD("Character Label",MenuLabel)({{0,-4},{float(windowSize.x)-1,24}},"Character",2,ComponentAttr::SHADOW|ComponentAttr::OUTLINE|ComponentAttr::BACKGROUND)END
->decal=true;
characterMenuWindow->ADD("Character Label",MenuLabel)({{0,-4},{float(windowSize.x)-1,24}},"Character",2,ComponentAttr::SHADOW|ComponentAttr::OUTLINE|ComponentAttr::BACKGROUND)END;
characterMenuWindow->ADD("Equip Slot Outline",MenuComponent)({{0,28},{120,windowSize.y-37}},"",DO_NOTHING,ButtonAttr::UNSELECTABLE)END;
characterMenuWindow->ADD("Character Rotating Display",CharacterRotatingDisplay)({{135,28},{90,windowSize.y-37}},GFX[classutils::GetClassInfo(game->GetPlayer()->GetClassName()).classFullImgName].Decal())END;
@ -93,8 +92,6 @@ void Menu::InitializeCharacterMenuWindow(){
return true;
})END;
equipSelectionSelectButton->decal=true;
equipSelectionSelectButton->Enable(false);
const static auto GetLabelText=[](ItemAttribute attribute){
@ -232,15 +229,13 @@ void Menu::InitializeCharacterMenuWindow(){
yOffset+=20;
}
characterMenuWindow->ADD("Back button",MenuComponent)({{windowSize.x/2-64,windowSize.y},{128,12}},"Back",[](MenuFuncData data){Menu::stack.pop_back();return true;})END
->decal=true;
characterMenuWindow->ADD("Back button",MenuComponent)({{windowSize.x/2-64,windowSize.y},{128,12}},"Back",[](MenuFuncData data){Menu::stack.pop_back();return true;})END;
auto itemNameDisplay=characterMenuWindow->ADD("Item Name",MenuLabel)({{0,28},{120,12}},"",1,ComponentAttr::BACKGROUND|ComponentAttr::LEFT_ALIGN|ComponentAttr::OUTLINE|ComponentAttr::SHADOW)END;
auto itemDescriptionDisplay=characterMenuWindow->ADD("Item Description",MenuLabel)({{0,40},{120,windowSize.y-49}},"",1,ComponentAttr::BACKGROUND|ComponentAttr::LEFT_ALIGN|ComponentAttr::OUTLINE|ComponentAttr::SHADOW)END;
characterMenuWindow->ADD("Item Equip Name",MenuLabel)({{123,28},{120,12}},"",1,ComponentAttr::BACKGROUND|ComponentAttr::LEFT_ALIGN|ComponentAttr::OUTLINE|ComponentAttr::SHADOW)END;
characterMenuWindow->ADD("Item Equip Description",MenuLabel)({{123,40},{120,windowSize.y-49}},"",1,ComponentAttr::BACKGROUND|ComponentAttr::LEFT_ALIGN|ComponentAttr::OUTLINE|ComponentAttr::SHADOW)END;
itemNameDisplay->decal=itemDescriptionDisplay->decal=true;
itemNameDisplay->Enable(false);
itemDescriptionDisplay->Enable(false);
}

@ -62,10 +62,8 @@ protected:
timer-=2*PI;
}
}
virtual inline void Draw(Crawler*game,vf2d parentPos)override{}
virtual inline void DrawDecal(Crawler*game,vf2d parentPos,bool focused)override{
//MenuComponent::DrawDecal(game,parentPos,focused);
game->DrawWarpedDecal(icon,std::array<vf2d,4>{
virtual inline void DrawDecal(ViewPort&window,vf2d parentPos,bool focused)override{
window.DrawWarpedDecal(icon,std::array<vf2d,4>{
Menu::menus[parentMenu]->pos+rect.pos+vf2d{abs(sin(timer)),sin(float(timer+PI))}*vf2d{rotatingFactor,perspectiveFactor},
Menu::menus[parentMenu]->pos+rect.pos+vf2d{0,rect.size.y}+vf2d{abs(sin(timer)),sin(timer)}*vf2d{rotatingFactor,perspectiveFactor},
Menu::menus[parentMenu]->pos+rect.pos+rect.size+vf2d{-abs(sin(float(timer+PI))),sin(float(timer+PI))}*vf2d{rotatingFactor,perspectiveFactor},

@ -84,5 +84,4 @@ void Menu::InitializeConsumableInventoryWindow(){
inventoryWindow->ADD("itemDescription",MenuLabel)(geom2d::rect<float>(vf2d{2,112.f},{windowSize.x-4,windowSize.y-108}),"",1,ComponentAttr::SHADOW)END;
auto okButton=inventoryWindow->ADD("OK Button",MenuComponent)({{windowSize.x/2-24,158.f},{48,12}},"Ok",[](MenuFuncData data){Menu::CloseMenu();return true;})END;
okButton->decal=true;
}

@ -112,14 +112,10 @@ void Menu::InitializeInventoryWindow(){
#pragma region Inventory Description
float inventoryDescriptionWidth=inventoryWindow->pos.x+inventoryWindow->size.x-26-224;
inventoryWindow->ADD("Item Description Outline",MenuLabel)({{224,28},{inventoryDescriptionWidth,inventoryWindow->size.y-44}},"",1,LEFT_ALIGN|OUTLINE|BACKGROUND)END
->decal=true;
auto itemIcon=inventoryWindow->ADD("Item Icon",MenuItemItemButton)({{226+inventoryDescriptionWidth/2-24,30},{48,48}},Item::BLANK,MenuType::ENUM_END,DO_NOTHING,"","",IconButtonAttr::NOT_SELECTABLE)END;
itemIcon->decal=true;
inventoryWindow->ADD("Item Name Label",MenuLabel)({{226,84},{inventoryDescriptionWidth-6,12}},"",0.75f,LEFT_ALIGN|SHADOW)END
->decal=true;
inventoryWindow->ADD("Item Description Label",MenuLabel)({{226,94},{inventoryDescriptionWidth-6,inventoryWindow->size.y-44-66}},"",0.5f,LEFT_ALIGN|SHADOW)END
->decal=true;
inventoryWindow->ADD("Item Description Outline",MenuLabel)({{224,28},{inventoryDescriptionWidth,inventoryWindow->size.y-44}},"",1,LEFT_ALIGN|OUTLINE|BACKGROUND)END;
inventoryWindow->ADD("Item Icon",MenuItemItemButton)({{226+inventoryDescriptionWidth/2-24,30},{48,48}},Item::BLANK,MenuType::ENUM_END,DO_NOTHING,"","",IconButtonAttr::NOT_SELECTABLE)END;
inventoryWindow->ADD("Item Name Label",MenuLabel)({{226,84},{inventoryDescriptionWidth-6,12}},"",0.75f,LEFT_ALIGN|SHADOW)END;
inventoryWindow->ADD("Item Description Label",MenuLabel)({{226,94},{inventoryDescriptionWidth-6,inventoryWindow->size.y-44-66}},"",0.5f,LEFT_ALIGN|SHADOW)END;
#pragma endregion
}

@ -75,8 +75,7 @@ using A=Attribute;
Menu::Menu(vf2d pos,vf2d size)
:pos(pos==CENTERED?WINDOW_SIZE/2-size/2:vi2d{pos}),size(size){
r.Create(uint32_t(size.x),uint32_t(size.y));
overlay.Create(WINDOW_SIZE.x,WINDOW_SIZE.y);
this->window=ViewPort::rectViewPort({0,0},size,this->pos);
}
Menu::~Menu(){
@ -283,22 +282,10 @@ void Menu::Draw(Crawler*game){
DrawTiledWindowBackground(game,pos,size,GetRenderColor());
}
game->SetDrawTarget(r.Sprite());
Pixel::Mode prevMode=game->GetPixelMode();
game->SetPixelMode(Pixel::MASK);
game->Clear(BLANK);
std::vector<MenuComponent*>allComponents;
std::copy(displayComponents.begin(),displayComponents.end(),std::back_inserter(allComponents));
std::for_each(buttons.begin(),buttons.end(),[&](auto&pair){std::copy(pair.second.begin(),pair.second.end(),std::back_inserter(allComponents));});
std::sort(allComponents.begin(),allComponents.end(),[](MenuComponent*c1,MenuComponent*c2){return c1->depth>c2->depth;});
for(const auto&component:allComponents){
if(component->renderInMain){
component->_Draw(game);
}
}
game->SetPixelMode(prevMode);
game->SetDrawTarget(nullptr);
if(GetCurrentTheme().IsScaled()){
DrawScaledWindowBorder(game,pos,size,GetRenderColor());
@ -306,19 +293,13 @@ void Menu::Draw(Crawler*game){
DrawTiledWindowBorder(game,pos,size,GetRenderColor());
}
r.Decal()->Update();
game->DrawDecal(pos,r.Decal());
for(const auto&component:allComponents){
if(component->renderInMain){
component->_DrawDecal(game,this==Menu::stack.back());
component->_DrawDecal(window,this==Menu::stack.back());
}
}
if(draggingComponent!=nullptr){
game->SetDrawTarget(overlay.Sprite());
Pixel::Mode prevMode=game->GetPixelMode();
game->SetPixelMode(Pixel::MASK);
game->Clear(BLANK);
vf2d offsetPos=draggingComponent->rect.pos;
if(!UsingMouseNavigation()){
MenuComponent*selectedComponent=buttons[selection.y][selection.x];
@ -326,23 +307,9 @@ void Menu::Draw(Crawler*game){
if(selectedComponent->parentComponent!=nullptr){
drawOffset+=selectedComponent->parentComponent->V(A::SCROLL_OFFSET);
}
draggingComponent->Draw(game,drawOffset+pos-offsetPos+selectedComponent->rect.pos+vi2d{1,-4});
}else{
draggingComponent->Draw(game,-offsetPos+game->GetMousePos());
}
game->SetPixelMode(prevMode);
game->SetDrawTarget(nullptr);
overlay.Decal()->Update();
game->DrawDecal({0,0},overlay.Decal(),{1,1},this==Menu::stack.back()?WHITE:WHITE*"ThemeGlobal.MenuUnfocusedColorMult"_F);
if(!UsingMouseNavigation()){
MenuComponent*selectedComponent=buttons[selection.y][selection.x];
vf2d drawOffset{};
if(selectedComponent->parentComponent!=nullptr){
drawOffset+=selectedComponent->parentComponent->V(A::SCROLL_OFFSET);
}
draggingComponent->DrawDecal(game,drawOffset+pos-offsetPos+selectedComponent->rect.pos+vi2d{1,-4},this==Menu::stack.back());
draggingComponent->DrawDecal(window,drawOffset+pos-offsetPos+selectedComponent->rect.pos+vi2d{1,-4},this==Menu::stack.back());
}else{
draggingComponent->DrawDecal(game,-offsetPos+game->GetMousePos(),this==Menu::stack.back());
draggingComponent->DrawDecal(window,-offsetPos+game->GetMousePos(),this==Menu::stack.back());
}
}
};

@ -42,6 +42,7 @@ All rights reserved.
#include "Theme.h"
#include "Attributable.h"
#include "olcUTIL_Geometry2D.h"
#include "olcPGEX_ViewPort.h"
class Crawler;
class MenuComponent;
@ -101,7 +102,7 @@ class Menu:public IAttributable{
int componentCount;
MenuComponent*draggingComponent=nullptr;
Renderable r,overlay;
ViewPort window;
static safemap<ITCategory,std::vector<MenuComponent*>>inventoryListeners; //All menu components that care about inventory updates subscribe to this list indirectly (See Menu::AddInventoryListener()).
static std::vector<MenuComponent*>equipStatListeners; //All menu components that care about stat/equip updates subscribe to this list indirectly (See Menu::AddStatListener()).
public:

@ -55,10 +55,10 @@ protected:
MenuIconButton::Update(game);
animationTime+=game->GetElapsedTime();
}
virtual inline void Draw(Crawler*game,vf2d parentPos)override{
MenuComponent::Draw(game,parentPos); //INTENTIONAL! The way we draw animations is different from static images, we skip over MenuIconButton's draw!
Sprite*spr=ANIMATION_DATA[animation].GetFrame(animationTime).GetSourceImage()->Sprite();
virtual inline void DrawDecal(ViewPort&window,vf2d parentPos,bool focused)override{
MenuComponent::DrawDecal(window,parentPos,focused); //INTENTIONAL! The way we draw animations is different from static images, we skip over MenuIconButton's draw!
Decal*spr=ANIMATION_DATA[animation].GetFrame(animationTime).GetSourceImage()->Decal();
geom2d::rect<int>sprRect=ANIMATION_DATA[animation].GetFrame(animationTime).GetSourceRect();
game->DrawPartialSprite(parentPos+rect.middle()-sprRect.size/2,spr,sprRect.pos,sprRect.size,1,Sprite::Flip::NONE);
window.DrawPartialDecal(parentPos+rect.middle()-sprRect.size/2,spr,sprRect.pos,sprRect.size);
}
};

@ -63,10 +63,10 @@ protected:
hoverEffect="ThemeGlobal.HighlightTime"_F; //A hack that allows us to make it look like we have this selected.
}
}
virtual inline void Draw(Crawler*game,vf2d parentPos)override{
MenuAnimatedIconButton::Draw(game,parentPos);
virtual inline void DrawDecal(ViewPort&window,vf2d parentPos,bool focused)override{
MenuAnimatedIconButton::DrawDecal(window,parentPos,focused);
if(IsSelected()){
game->DrawRect(rect.pos+vi2d{2,2},rect.size-vi2d{4,4},YELLOW);
window.DrawRectDecal(rect.pos+vi2d{2,2},rect.size-vi2d{4,4},YELLOW);
}
}
};

@ -40,6 +40,8 @@ All rights reserved.
#include "drawutil.h"
#include "util.h"
INCLUDE_game
using A=Attribute;
MenuComponent::MenuComponent(geom2d::rect<float>rect,std::string label,MenuFunc onClick,ButtonAttr attributes)
@ -57,7 +59,6 @@ MenuComponent::MenuComponent(geom2d::rect<float>rect,std::string label,MenuType
:MenuComponent(rect,label,menuDest,onClick,attributes){
//NOTE: This constructor also calls the other constructor above!
this->labelScaling=labelScaling;
if (labelScaling!=vf2d{1,1})this->decal=true; //Since we would have to draw text smaller than an integer scale, we are forced to use a decal here.
}
MenuComponent::~MenuComponent(){
@ -92,79 +93,42 @@ void MenuComponent::_Update(Crawler*game){
}
}
void MenuComponent::Draw(Crawler*game,vf2d parentPos){
if(!decal){
if(background){
game->FillRect(rect.pos+parentPos,rect.size,PixelLerp(Menu::themes[Menu::themeSelection].GetButtonCol(),Menu::themes[Menu::themeSelection].GetHighlightCol(),hoverEffect/"ThemeGlobal.HighlightTime"_F));
}
if(selected&&selectionType==HIGHLIGHT){
game->FillRect(rect.pos+parentPos,rect.size,PixelLerp(Menu::themes[Menu::themeSelection].GetButtonCol(),Menu::themes[Menu::themeSelection].GetHighlightCol(),util::lerp(0.75f,1.0f,hoverEffect/"ThemeGlobal.HighlightTime"_F)));
}
if(border){
game->DrawRect(rect.pos+parentPos,rect.size);
}
if(showDefaultLabel){
game->DrawStringProp(rect.pos+parentPos+rect.size/2-game->GetTextSizeProp(label)/2,label);
}
if(selected){
switch(selectionType){
case CROSSHAIR:drawutil::DrawCrosshair(game,{parentPos+rect.pos,rect.size},0);break;
case INNER_BOX:game->DrawRect(rect.pos+parentPos+vi2d{1,1},rect.size-vi2d{2,2});break;
case HIGHLIGHT:break;//Not used.
default:ERR("Undefined selection type selected: "<<int(selectionType));
}
}
}
}
void MenuComponent::OnEquipStatsUpdate(){}
void MenuComponent::_Draw(Crawler*game){
_Draw(game,{0,0});
}
void MenuComponent::_Draw(Crawler*game,vf2d parentPos){
if(!disabled){
Draw(game,parentPos);
void MenuComponent::DrawDecal(ViewPort&window,vf2d parentPos,bool focused){
parentPos+=Menu::menus[parentMenu]->pos;
if(background){
window.FillRectDecal(rect.pos+parentPos,rect.size,PixelLerp(Menu::themes[Menu::themeSelection].GetButtonCol(),Menu::themes[Menu::themeSelection].GetHighlightCol(),hoverEffect/"ThemeGlobal.HighlightTime"_F));
}
}
void MenuComponent::DrawDecal(Crawler*game,vf2d parentPos,bool focused){
if(decal){
parentPos+=Menu::menus[parentMenu]->pos;
if(background){
game->FillRectDecal(rect.pos+parentPos,rect.size,PixelLerp(Menu::themes[Menu::themeSelection].GetButtonCol(),Menu::themes[Menu::themeSelection].GetHighlightCol(),hoverEffect/"ThemeGlobal.HighlightTime"_F));
}
if(selected&&selectionType==HIGHLIGHT){
game->FillRectDecal(rect.pos+parentPos,rect.size,PixelLerp(Menu::themes[Menu::themeSelection].GetButtonCol(),Menu::themes[Menu::themeSelection].GetHighlightCol(),util::lerp(0.75f,1.0f,hoverEffect/"ThemeGlobal.HighlightTime"_F)));
}
if(border){
game->FillRectDecal(rect.pos+parentPos,{rect.size.x,1});
game->FillRectDecal(rect.pos+parentPos,{1,rect.size.y});
game->FillRectDecal(rect.pos+parentPos+vf2d{rect.size.x-1,0},{1,rect.size.y});
game->FillRectDecal(rect.pos+parentPos+vf2d{0,rect.size.y-1},{rect.size.x,1});
}
if(showDefaultLabel){
game->DrawStringPropDecal(rect.pos+parentPos+rect.size/2-vf2d(game->GetTextSizeProp(label))/2.f*labelScaling,label,WHITE,labelScaling);
}
if(selected){
switch(selectionType){
case CROSSHAIR:drawutil::DrawCrosshairDecal(game,{parentPos+rect.pos,rect.size},0);break;
case INNER_BOX:game->DrawRectDecal(rect.pos+parentPos+vi2d{1,1},rect.size-vi2d{2,2});break;
case HIGHLIGHT:break;//Not used.
default:ERR("Undefined selection type selected: "<<int(selectionType));
}
}
if(selected&&selectionType==HIGHLIGHT){
window.FillRectDecal(rect.pos+parentPos,rect.size,PixelLerp(Menu::themes[Menu::themeSelection].GetButtonCol(),Menu::themes[Menu::themeSelection].GetHighlightCol(),util::lerp(0.75f,1.0f,hoverEffect/"ThemeGlobal.HighlightTime"_F)));
}
if(border){
window.FillRectDecal(rect.pos+parentPos,{rect.size.x,1});
window.FillRectDecal(rect.pos+parentPos,{1,rect.size.y});
window.FillRectDecal(rect.pos+parentPos+vf2d{rect.size.x-1,0},{1,rect.size.y});
window.FillRectDecal(rect.pos+parentPos+vf2d{0,rect.size.y-1},{rect.size.x,1});
}
if(showDefaultLabel){
window.DrawStringPropDecal(rect.pos+parentPos+rect.size/2-vf2d(game->GetTextSizeProp(label))/2.f*labelScaling,label,WHITE,labelScaling);
}
if(selected){
switch(selectionType){
case CROSSHAIR:drawutil::DrawCrosshairDecalViewPort(window,{parentPos+rect.pos,rect.size},0);break;
case INNER_BOX:window.DrawRectDecal(rect.pos+parentPos+vi2d{1,1},rect.size-vi2d{2,2});break;
case HIGHLIGHT:break;//Not used.
default:ERR("Undefined selection type selected: "<<int(selectionType));
}
}
}
void MenuComponent::_DrawDecal(Crawler*game,bool focused){
_DrawDecal(game,{0,0},focused);
void MenuComponent::_DrawDecal(ViewPort&window,bool focused){
_DrawDecal(window,{0,0},focused);
}
void MenuComponent::_DrawDecal(Crawler*game,vf2d parentPos,bool focused){
void MenuComponent::_DrawDecal(ViewPort&window,vf2d parentPos,bool focused){
if(!disabled){
DrawDecal(game,parentPos,focused);
DrawDecal(window,parentPos,focused);
}
}

@ -73,10 +73,8 @@ private:
std::pair<MenuType,std::string>memoryLeakInfo; //Used to identify memory leak hints for this component.
virtual void BeforeUpdate(Crawler*game);
void _Update(Crawler*game);
void _Draw(Crawler*game);
void _Draw(Crawler*game,vf2d parentPos);
void _DrawDecal(Crawler*game,bool focused);
void _DrawDecal(Crawler*game,vf2d parentPos,bool focused);
void _DrawDecal(ViewPort&window,bool focused);
void _DrawDecal(ViewPort&window,vf2d parentPos,bool focused);
bool selected=false;
SelectionType selectionType=CROSSHAIR;
protected:
@ -98,8 +96,7 @@ protected:
bool valid=true; //If set to false, this would cause the component to be removed.
vf2d labelScaling={1,1};
virtual void Update(Crawler*game);
virtual void Draw(Crawler*game,vf2d parentPos);
virtual void DrawDecal(Crawler*game,vf2d parentPos,bool focused);
virtual void DrawDecal(ViewPort&window,vf2d parentPos,bool focused);
virtual bool GetHoverState(Crawler*game,MenuComponent*child);
virtual void AfterCreate(); //Called after the creation of all menus finish.
//CALL THIS FOR A PARENT to check a child's DrawDecal validity!
@ -131,5 +128,4 @@ public:
virtual void SetSelectionType(SelectionType selectionType)final;
virtual void Enable(bool enabled);
virtual void Cleanup();
bool decal=false; //If set to true, will use decal rendering (For foreground shenanigans)
};

@ -59,22 +59,11 @@ protected:
virtual inline void Update(Crawler*game)override{
MenuComponent::Update(game);
}
virtual inline void Draw(Crawler*game,vf2d parentPos)override{
if(!decal){
MenuComponent::Draw(game,parentPos);
if(icon!=nullptr){
vi2d iconScale=rect.size/24;
game->DrawSprite(parentPos+rect.middle()-icon->sprite->Size()*iconScale/2,icon->sprite,iconScale.x,Sprite::Flip::NONE);
}
}
}
virtual inline void DrawDecal(Crawler*game,vf2d parentPos,bool focused)override{
if(decal){
MenuComponent::DrawDecal(game,parentPos,focused);
if(icon!=nullptr){
vf2d iconScale=rect.size/24.f;
game->DrawDecal(Menu::menus[parentMenu]->pos+parentPos+rect.middle()-icon->sprite->Size()*iconScale/2,icon,iconScale);
}
virtual inline void DrawDecal(ViewPort&window,vf2d parentPos,bool focused)override{
MenuComponent::DrawDecal(window,parentPos,focused);
if(icon!=nullptr){
vf2d iconScale=rect.size/24.f;
window.DrawDecal(Menu::menus[parentMenu]->pos+parentPos+rect.middle()-icon->sprite->Size()*iconScale/2,icon,iconScale);
}
}
};

@ -133,20 +133,10 @@ protected:
}
}
}
virtual inline void Draw(Crawler*game,vf2d parentPos)override{
if(!decal){
MenuIconButton::Draw(game,parentPos);
if(selected!=-1){
drawutil::DrawCrosshair(game,{parentPos+rect.pos,rect.size},0);
}
}
}
virtual inline void DrawDecal(Crawler*game,vf2d parentPos,bool focused)override{
if(decal){
MenuIconButton::DrawDecal(game,parentPos,focused);
if(selected!=-1){
drawutil::DrawCrosshairDecal(game,{parentPos+rect.pos,rect.size},0);
}
virtual inline void DrawDecal(ViewPort&window,vf2d parentPos,bool focused)override{
MenuIconButton::DrawDecal(window,parentPos,focused);
if(selected!=-1){
drawutil::DrawCrosshairDecalViewPort(window,{parentPos+rect.pos,rect.size},0);
}
if(valid){
int itemQuantity=Inventory::GetItemCount(invRef.at(inventoryIndex).Name()); //Normally we'd retrieve how many of this item we have from our inventory...However Monster Loot and Stage Loot inventories are special and hold their own inventory counts...
@ -158,9 +148,7 @@ protected:
vf2d textSize=vf2d(game->GetTextSizeProp(quantityText))*quantityTextScale;
vf2d drawPos=parentPos+rect.pos+rect.size-textSize;
geom2d::rect<float>boundingBox={drawPos,textSize};
if(PointWithinParent(this,boundingBox)){
game->DrawShadowStringDecal(drawPos,quantityText,WHITE,BLACK,quantityTextScale,quantityTextScale.x);
}
window.DrawShadowStringDecal(drawPos,quantityText,WHITE,BLACK,quantityTextScale,quantityTextScale.x);
}
}
inline MenuComponent*PickUpDraggableItem()override final{

@ -131,20 +131,15 @@ protected:
}
}
}
virtual inline void Draw(Crawler*game,vf2d parentPos)override{
MenuIconButton::Draw(game,parentPos);
}
virtual inline void DrawDecal(Crawler*game,vf2d parentPos,bool focused)override{
MenuIconButton::DrawDecal(game,parentPos,focused);
virtual inline void DrawDecal(ViewPort&window,vf2d parentPos,bool focused)override{
MenuIconButton::DrawDecal(window,parentPos,focused);
if(valid&&!hideQty){
std::string quantityText="x"+std::to_string(itemRef.get().Amt());
vf2d quantityTextScale=rect.size/48.f;
vf2d textSize=vf2d(game->GetTextSizeProp(quantityText))*quantityTextScale;
vf2d drawPos=Menu::menus[parentMenu]->pos+parentPos+rect.pos+rect.size-textSize;
geom2d::rect<float>boundingBox={drawPos,textSize};
if(PointWithinParent(this,boundingBox)){
game->DrawShadowStringDecal(drawPos,quantityText,WHITE,BLACK,quantityTextScale,quantityTextScale.x);
}
window.DrawShadowStringDecal(drawPos,quantityText,WHITE,BLACK,quantityTextScale,quantityTextScale.x);
}
}
};

@ -36,9 +36,10 @@ All rights reserved.
*/
#pragma endregion
#pragma once
#include "Crawler.h"
#include "MenuComponent.h"
#include "DEFINES.h"
#include "Crawler.h"
#include "olcPGEX_ViewPort.h"
#include "util.h"
INCLUDE_game
@ -55,7 +56,6 @@ public:
border=attributes&ComponentAttr::OUTLINE;
this->background=attributes&ComponentAttr::BACKGROUND;
showDefaultLabel=false;
if(fmod(scale,1)>0.001)decal=true;
}
inline virtual void SetLabel(std::string text){
label=text;
@ -64,35 +64,18 @@ protected:
virtual void inline Update(Crawler*game)override{
MenuComponent::Update(game);
}
virtual void inline Draw(Crawler*game,vf2d parentPos)override{
if(!decal){
MenuComponent::Draw(game,parentPos);
std::string wrappedText=util::WrapText(game,label,int(rect.size.x),true,{float(scale),float(scale)});
vf2d drawPos=parentPos+rect.middle()-vf2d{game->GetTextSizeProp(wrappedText)}*float(scale)/2; //Assume centered.
if(!centered){
drawPos=vf2d{rect.pos.x+2,rect.middle().y-game->GetTextSizeProp(wrappedText).y/2}+parentPos; //We should at least vertically align here.
}
if(shadow){
game->DrawShadowStringProp(drawPos,wrappedText,WHITE,BLACK,{float(scale),float(scale)});
}else{
game->DrawStringProp(drawPos,wrappedText,WHITE,scale);
}
virtual void inline DrawDecal(ViewPort&window,vf2d parentPos,bool focused)override{
MenuComponent::DrawDecal(window,parentPos,focused);
parentPos+=Menu::menus[parentMenu]->pos;
std::string wrappedText=util::WrapText(game,label,int(rect.size.x),true,{float(scale),float(scale)});
vf2d drawPos=parentPos+rect.middle()-vf2d{game->GetTextSizeProp(wrappedText)}*float(scale)/2; //Assume centered.
if(!centered){
drawPos=vf2d{rect.pos.x+2,rect.middle().y-game->GetTextSizeProp(wrappedText).y/2}+parentPos; //We should at least vertically align here.
}
}
virtual void inline DrawDecal(Crawler*game,vf2d parentPos,bool focused)override{
if(decal){
MenuComponent::DrawDecal(game,parentPos,focused);
parentPos+=Menu::menus[parentMenu]->pos;
std::string wrappedText=util::WrapText(game,label,int(rect.size.x),true,{float(scale),float(scale)});
vf2d drawPos=parentPos+rect.middle()-vf2d{game->GetTextSizeProp(wrappedText)}*float(scale)/2; //Assume centered.
if(!centered){
drawPos=vf2d{rect.pos.x+2,rect.middle().y-game->GetTextSizeProp(wrappedText).y/2}+parentPos; //We should at least vertically align here.
}
if(shadow){
game->DrawShadowStringPropDecal(drawPos,wrappedText,WHITE,BLACK,{float(scale),float(scale)});
}else{
game->DrawStringPropDecal(drawPos,wrappedText,WHITE,{float(scale),float(scale)});
}
if(shadow){
window.DrawShadowStringPropDecal(drawPos,wrappedText,WHITE,BLACK,{float(scale),float(scale)});
}else{
window.DrawStringPropDecal(drawPos,wrappedText,WHITE,{float(scale),float(scale)});
}
}
};

@ -57,28 +57,27 @@ protected:
virtual void inline Update(Crawler*game)override{
MenuLabel::Update(game);
}
virtual void inline Draw(Crawler*game,vf2d parentPos)override{}
virtual void inline DrawDecal(Crawler*game,vf2d parentPos,bool focused)override{
virtual void inline DrawDecal(ViewPort&window,vf2d parentPos,bool focused)override{
if(label.length()>0){
MenuLabel::DrawDecal(game,parentPos,focused);
MenuLabel::DrawDecal(window,parentPos,focused);
std::string wrappedText=util::WrapText(game,label,int(rect.size.x-1),true,scale);
vf2d drawPos=Menu::menus.at(parentMenu)->pos+parentPos+rect.middle()-vf2d{game->GetTextSizeProp(wrappedText)}*scale/2; //Assume centered.
if(!centered){
drawPos=Menu::menus.at(parentMenu)->pos+vf2d{rect.pos.x+2,rect.middle().y-game->GetTextSizeProp(wrappedText).y/2}+parentPos; //We should at least vertically align here.
}
if(background){
game->FillRectDecal(Menu::menus.at(parentMenu)->pos+rect.pos+parentPos,rect.size,PixelLerp(Menu::themes[Menu::themeSelection].GetButtonCol(),Menu::themes[Menu::themeSelection].GetHighlightCol(),hoverEffect/"ThemeGlobal.HighlightTime"_F));
window.FillRectDecal(Menu::menus.at(parentMenu)->pos+rect.pos+parentPos,rect.size,PixelLerp(Menu::themes[Menu::themeSelection].GetButtonCol(),Menu::themes[Menu::themeSelection].GetHighlightCol(),hoverEffect/"ThemeGlobal.HighlightTime"_F));
}
if(border){
game->DrawRectDecal(Menu::menus.at(parentMenu)->pos+rect.pos+parentPos,rect.size);
window.DrawRectDecal(Menu::menus.at(parentMenu)->pos+rect.pos+parentPos,rect.size);
}
if(showDefaultLabel){
game->DrawStringPropDecal(Menu::menus.at(parentMenu)->pos+rect.pos+parentPos+rect.size/2-game->GetTextSizeProp(label)/2,label);
window.DrawStringPropDecal(Menu::menus.at(parentMenu)->pos+rect.pos+parentPos+rect.size/2-game->GetTextSizeProp(label)/2,label);
}
if(shadow){
game->DrawShadowStringPropDecal(drawPos,wrappedText,WHITE,BLACK,scale);
window.DrawShadowStringPropDecal(drawPos,wrappedText,WHITE,BLACK,scale);
}else{
game->DrawStringPropDecal(drawPos,wrappedText,WHITE,scale);
window.DrawStringPropDecal(drawPos,wrappedText,WHITE,scale);
}
}
}

@ -45,7 +45,7 @@ using A=Attribute;
class ScrollableWindowComponent:public MenuComponent{
protected:
Renderable r;
ViewPort subWindow;
std::vector<MenuComponent*>components;
MenuComponent*upButton=nullptr;
MenuComponent*downButton=nullptr;
@ -63,7 +63,7 @@ public:
:MenuComponent(rect,"",[](MenuFuncData data){return true;},ButtonAttr::UNSELECTABLE|ButtonAttr::UNSELECTABLE_VIA_KEYBOARD){
background=attributes&ComponentAttr::BACKGROUND;
border=attributes&ComponentAttr::OUTLINE;
r.Create(uint32_t(rect.size.x),uint32_t(rect.size.y));
subWindow=ViewPort::rectViewPort({},rect.size,rect.pos);
}
virtual inline void RemoveAllComponents(){
while(components.size()>0){
@ -163,19 +163,7 @@ protected:
downButton->disabled=true;
}
}
virtual inline void Draw(Crawler*game,vf2d parentPos)override{
MenuComponent::Draw(game,parentPos);
Sprite*prevDrawTarget=game->GetDrawTarget();
game->SetDrawTarget(r.Sprite());
game->Clear(BLANK);
for(MenuComponent*component:components){
component->_Draw(game,V(A::SCROLL_OFFSET));
}
game->SetDrawTarget(prevDrawTarget);
game->DrawSprite(parentPos+rect.pos,r.Sprite());
}
inline void DrawScrollbar(Crawler*game,vf2d parentPos,bool focused){
inline void DrawScrollbar(ViewPort&window,vf2d parentPos,bool focused){
float spaceBetweenTopAndBottomArrows=rect.size.y-24;
float viewHeight=rect.size.y;
float totalContentHeight=bounds.size.y;
@ -186,19 +174,19 @@ protected:
float focusedWindowColorMult=(focused?1:"ThemeGlobal.MenuUnfocusedColorMult"_F);
game->FillRectDecal(rect.pos+parentPos+vf2d{rect.size.x-11.75f,scrollBarTop+12},{12,scrollBarHeight},PixelLerp(Menu::GetCurrentTheme().GetButtonCol(),Menu::GetCurrentTheme().GetHighlightCol(),scrollBarHoverTime/"ThemeGlobal.HighlightTime"_F)*focusedWindowColorMult);
game->DrawRectDecal(rect.pos+parentPos+vf2d{rect.size.x-11.75f,scrollBarTop+12},{12,scrollBarHeight},WHITE*focusedWindowColorMult);
window.FillRectDecal(rect.pos+parentPos+vf2d{rect.size.x-11.75f,scrollBarTop+12},{12,scrollBarHeight},PixelLerp(Menu::GetCurrentTheme().GetButtonCol(),Menu::GetCurrentTheme().GetHighlightCol(),scrollBarHoverTime/"ThemeGlobal.HighlightTime"_F)*focusedWindowColorMult);
window.DrawRectDecal(rect.pos+parentPos+vf2d{rect.size.x-11.75f,scrollBarTop+12},{12,scrollBarHeight},WHITE*focusedWindowColorMult);
}
virtual inline void DrawDecal(Crawler*game,vf2d parentPos,bool focused)override{
MenuComponent::DrawDecal(game,parentPos,focused);
virtual inline void DrawDecal(ViewPort&window,vf2d parentPos,bool focused)override{
MenuComponent::DrawDecal(window,parentPos,focused);
if(border){
game->DrawRectDecal(rect.pos+Menu::menus[parentMenu]->pos,rect.size);
}
for(MenuComponent*component:components){
component->_DrawDecal(game,rect.pos+Menu::menus[parentMenu]->pos+V(A::SCROLL_OFFSET),focused);
component->_DrawDecal(subWindow,rect.pos+Menu::menus[parentMenu]->pos+V(A::SCROLL_OFFSET),focused);
}
DrawScrollbar(game,Menu::menus[parentMenu]->pos,focused);
DrawScrollbar(window,Menu::menus[parentMenu]->pos,focused);
}
virtual bool GetHoverState(Crawler*game,MenuComponent*child)override{
return geom2d::overlaps(geom2d::rect<float>{Menu::menus[parentMenu]->pos+rect.pos+child->rect.pos+V(A::SCROLL_OFFSET),child->rect.size},game->GetMousePos());

@ -64,19 +64,16 @@ protected:
MenuComponent::Update(game);
anim.UpdateState(state,game->GetElapsedTime());
}
virtual void inline Draw(Crawler*game,vf2d parentPos)override{
}
virtual void inline DrawDecal(Crawler*game,vf2d parentPos,bool focused)override{
virtual void inline DrawDecal(ViewPort&window,vf2d parentPos,bool focused)override{
const geom2d::rect<int>&imgRect=anim.GetFrame(state).GetSourceRect();
vf2d imgSize=vf2d{rect.size.y,rect.size.y};
vf2d imgScale=imgSize/vf2d{imgRect.size};
game->DrawPartialDecal(parentPos+rect.pos,imgSize,anim.GetFrame(state).GetSourceImage()->Decal(),imgRect.pos,imgRect.size);
window.DrawPartialDecal(parentPos+rect.pos,imgSize,anim.GetFrame(state).GetSourceImage()->Decal(),imgRect.pos,imgRect.size);
float verticalAlignYOffset=(rect.size.y-8)/2;
std::string monsterName=MONSTER_DATA.at(monsterID).GetDisplayName();
vf2d monsterNameTextSize=game->GetTextSizeProp(monsterName);
float textXSpaceAvailable=rect.size.x-imgSize.x-4-16/*12 for the scrollbar*/;
float textXScaling=textXSpaceAvailable/monsterNameTextSize.x;
game->DrawShadowStringPropDecal(parentPos+rect.pos+vf2d{imgSize.x+4,verticalAlignYOffset},monsterName,WHITE,BLACK,{std::min(1.f,textXScaling),1});
window.DrawShadowStringPropDecal(parentPos+rect.pos+vf2d{imgSize.x+4,verticalAlignYOffset},monsterName,WHITE,BLACK,{std::min(1.f,textXScaling),1});
}
};

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

@ -172,3 +172,36 @@ void drawutil::DrawCrosshairDecalTransformedView(olc::TransformedView&view,geom2
size={borderThickness,crosshairExtension.y};
game->view.FillRectDecal(pos,size,RED);
}
void drawutil::DrawCrosshairDecalViewPort(olc::ViewPort&window,geom2d::rect<float>rect,float accTime,float pulsatingAmt,float borderThickness){
vf2d crosshairExtension={std::min(0.25f*rect.size.x-borderThickness/2,12.f),std::min(0.25f*rect.size.y-borderThickness/2,12.f)};
vf2d pulseAmt=vf2d{1,1}*std::abs(std::sin(accTime*3))*2;
//Lower-Left Corner
vf2d pos=rect.pos+vf2d{0,rect.size.y-borderThickness}+vf2d{-pulseAmt.x,pulseAmt.y};
vf2d size={borderThickness+crosshairExtension.x,borderThickness};
window.FillRectDecal(pos,size,RED);
pos=vf2d{pos.x,pos.y-crosshairExtension.y};
size={borderThickness,crosshairExtension.y};
window.FillRectDecal(pos,size,RED);
//Lower-Right Corner
pos=rect.pos+vf2d{rect.size.x-borderThickness-crosshairExtension.x,rect.size.y-borderThickness}+vf2d{pulseAmt.x,pulseAmt.y};
size={borderThickness+crosshairExtension.x,borderThickness};
window.FillRectDecal(pos,size,RED);
pos=vf2d{pos.x+crosshairExtension.x,pos.y-crosshairExtension.y};
size={borderThickness,crosshairExtension.y};
window.FillRectDecal(pos,size,RED);
//Upper-Left Corner
pos=rect.pos+vf2d{0,0}+vf2d{-pulseAmt.x,-pulseAmt.y};
size={borderThickness+crosshairExtension.x,borderThickness};
window.FillRectDecal(pos,size,RED);
pos=vf2d{pos.x,pos.y+borderThickness};
size={borderThickness,crosshairExtension.y};
window.FillRectDecal(pos,size,RED);
//Upper-Right Corner
pos=rect.pos+vf2d{rect.size.x-borderThickness-crosshairExtension.x,0}+vf2d{pulseAmt.x,-pulseAmt.y};
size={borderThickness+crosshairExtension.x,borderThickness};
window.FillRectDecal(pos,size,RED);
pos=vf2d{pos.x+crosshairExtension.x,pos.y+borderThickness};
size={borderThickness,crosshairExtension.y};
window.FillRectDecal(pos,size,RED);
}

@ -38,6 +38,7 @@ All rights reserved.
#pragma once
#include "olcUTIL_Geometry2D.h"
#include "olcPGEX_TransformedView.h"
#include "olcPGEX_ViewPort.h"
class Crawler;
namespace drawutil{
@ -45,4 +46,5 @@ namespace drawutil{
void DrawCrosshairTransformedView(TransformedView&view,geom2d::rect<float>rect,float accTime,float pulsatingAmt=2,float borderThickness=4);
void DrawCrosshairDecal(Crawler*game,geom2d::rect<float>rect,float accTime,float pulsatingAmt=2,float borderThickness=4);
void DrawCrosshairDecalTransformedView(TransformedView&view,geom2d::rect<float>rect,float accTime,float pulsatingAmt=2,float borderThickness=4);
void DrawCrosshairDecalViewPort(ViewPort&window,geom2d::rect<float>rect,float accTime,float pulsatingAmt=2,float borderThickness=4);
}

@ -165,7 +165,7 @@ namespace olc
void DrawPartialDecal(const olc::vf2d& pos, olc::Decal* decal, const olc::vf2d& source_pos, const olc::vf2d& source_size, const olc::vf2d& scale = { 1.0f,1.0f }, const olc::Pixel& tint = olc::WHITE);
void DrawPartialDecal(const olc::vf2d& pos, const olc::vf2d& size, olc::Decal* decal, const olc::vf2d& source_pos, const olc::vf2d& source_size, const olc::Pixel& tint = olc::WHITE);
// Draws fully user controlled 4 vertices, pos(pixels), uv(pixels), colours
void DrawExplicitDecal(olc::Decal* decal, const olc::vf2d* pos, const olc::vf2d* uv, const olc::Pixel* col, uint32_t elements = 4);
void DrawExplicitDecal(olc::Decal* decal, const olc::vf2d* pos, const olc::vf2d* uv, const olc::Pixel* col, const float* w,uint32_t elements = 4);
//// Draws a decal with 4 arbitrary points, warping the texture to look "correct"
void DrawWarpedDecal(olc::Decal* decal, const olc::vf2d(&pos)[4], const olc::Pixel& tint = olc::WHITE);
void DrawWarpedDecal(olc::Decal* decal, const olc::vf2d* pos, const olc::Pixel& tint = olc::WHITE);
@ -564,12 +564,12 @@ namespace olc
pge->DrawPartialDecal(WorldToScreen(pos), vd2d(size)* vd2d(m_vWorldScale) * vd2d(m_vRecipPixel), decal, source_pos, source_size, tint);
}
void TransformedView::DrawExplicitDecal(olc::Decal* decal, const olc::vf2d* pos, const olc::vf2d* uv, const olc::Pixel* col, uint32_t elements)
void TransformedView::DrawExplicitDecal(olc::Decal* decal, const olc::vf2d* pos, const olc::vf2d* uv, const olc::Pixel* col, const float* w, uint32_t elements)
{
std::vector<olc::vf2d> vTransformed(elements);
for (uint32_t n = 0; n < elements; n++)
vTransformed[n] = WorldToScreen(pos[n]);
pge->DrawExplicitDecal(decal, vTransformed.data(), uv, col, elements);
pge->DrawExplicitDecal(decal, vTransformed.data(), uv, col, w, elements);
}
void TransformedView::DrawWarpedDecal(olc::Decal* decal, const olc::vf2d* pos, const olc::Pixel& tint)

@ -30,6 +30,7 @@ namespace olc {
olc::Decal *decal,
const olc::vf2d &scale = {1.0f, 1.0f},
const olc::Pixel &tint = olc::WHITE) const;
void DrawRectDecal(const olc::vf2d& pos, const olc::vf2d& size, const olc::Pixel col=olc::WHITE)const;
void DrawPartialDecal(const olc::vf2d &pos,
olc::Decal *decal,
const olc::vf2d &source_pos,
@ -46,6 +47,7 @@ namespace olc {
const olc::vf2d *pos,
const olc::vf2d *uv,
const olc::Pixel *col,
const float *ws,
uint32_t elements = 4) const;
void DrawWarpedDecal(Decal *decal,
const vf2d (&pos)[4],
@ -124,6 +126,7 @@ namespace olc {
const vf2d *points,
const vf2d *uvs,
const Pixel *col,
const float *ws,
uint32_t elements = 0) const;
static float lineSegmentIntersect(vf2d lineA,
@ -226,8 +229,9 @@ void olc::ViewPort::DrawExplicitDecal(olc::Decal *decal,
const olc::vf2d *pos,
const olc::vf2d *uv,
const olc::Pixel *col,
const float *ws,
uint32_t elements) const {
drawClippedDecal(decal, pos, uv, col, elements);
drawClippedDecal(decal, pos, uv, col, ws, elements);
}
void olc::ViewPort::DrawWarpedDecal(Decal *decal,
@ -238,6 +242,9 @@ void olc::ViewPort::DrawWarpedDecal(Decal *decal,
void olc::ViewPort::DrawWarpedDecal(Decal *decal,
const vf2d *pos,
const Pixel &tint) const {
std::vector<float> w{ 1, 1, 1, 1 };
std::vector<olc::vf2d> newPos;
newPos.resize(4);
std::vector<vf2d> uvs{
{0, 0},
{0, 1},
@ -251,7 +258,26 @@ void olc::ViewPort::DrawWarpedDecal(Decal *decal,
tint,
};
drawClippedDecal(decal, pos, uvs.data(), cols.data(), 4);
olc::vf2d vInvScreenSize={ 1.0f / pge->GetScreenSize().x, 1.0f / pge->GetScreenSize().y };
olc::vf2d center;
float rd = ((pos[2].x - pos[0].x) * (pos[3].y - pos[1].y) - (pos[3].x - pos[1].x) * (pos[2].y - pos[0].y));
if (rd != 0)
{
rd = 1.0f / rd;
float rn = ((pos[3].x - pos[1].x) * (pos[0].y - pos[1].y) - (pos[3].y - pos[1].y) * (pos[0].x - pos[1].x)) * rd;
float sn = ((pos[2].x - pos[0].x) * (pos[0].y - pos[1].y) - (pos[2].y - pos[0].y) * (pos[0].x - pos[1].x)) * rd;
if (!(rn < 0.f || rn > 1.f || sn < 0.f || sn > 1.f)) center = pos[0] + rn * (pos[2] - pos[0]);
float d[4]; for (int i = 0; i < 4; i++) d[i] = (pos[i] - center).mag();
for (int i = 0; i < 4; i++)
{
float q = d[i] == 0.0f ? 1.0f : (d[i] + d[(i + 2) & 3]) / d[(i + 2) & 3];
uvs[i] *= q; w[i] *= q;
}
drawClippedDecal(decal, pos, uvs.data(), cols.data(), w.data(), 4);
}
}
void olc::ViewPort::DrawWarpedDecal(Decal *decal,
const std::array<vf2d, 4> &pos,
@ -297,7 +323,25 @@ void olc::ViewPort::DrawPartialWarpedDecal(Decal *decal,
tint,
};
drawClippedDecal(decal, pos, uvs.data(), cols.data(), 4);
std::vector<float>ws{1,1,1,1};
olc::vf2d center;
float rd = ((pos[2].x - pos[0].x) * (pos[3].y - pos[1].y) - (pos[3].x - pos[1].x) * (pos[2].y - pos[0].y));
if (rd != 0)
{
rd = 1.0f / rd;
float rn = ((pos[3].x - pos[1].x) * (pos[0].y - pos[1].y) - (pos[3].y - pos[1].y) * (pos[0].x - pos[1].x)) * rd;
float sn = ((pos[2].x - pos[0].x) * (pos[0].y - pos[1].y) - (pos[2].y - pos[0].y) * (pos[0].x - pos[1].x)) * rd;
if (!(rn < 0.f || rn > 1.f || sn < 0.f || sn > 1.f)) center = pos[0] + rn * (pos[2] - pos[0]);
float d[4]; for (int i = 0; i < 4; i++) d[i] = (pos[i] - center).mag();
for (int i = 0; i < 4; i++)
{
float q = d[i] == 0.0f ? 1.0f : (d[i] + d[(i + 2) & 3]) / d[(i + 2) & 3];
uvs[i] *= q; ws[i] *= q;
}
drawClippedDecal(decal, pos, uvs.data(), cols.data(), ws.data(), 4);
}
}
void olc::ViewPort::DrawPartialWarpedDecal(Decal *decal,
@ -369,7 +413,7 @@ void olc::ViewPort::FillRectDecal(const vf2d &pos,
pos,
{pos.x, pos.y + size.y},
pos + size,
{pos.x + size.y, pos.y},
{pos.x + size.x, pos.y},
};
std::vector<vf2d> uvs{
{0, 0},
@ -391,7 +435,7 @@ void olc::ViewPort::GradientFillRectDecal(const vf2d &pos,
pos,
{pos.x, pos.y + size.y},
pos + size,
{pos.x + size.y, pos.y},
{pos.x + size.x, pos.y},
};
std::vector<vf2d> uvs{
@ -408,7 +452,9 @@ void olc::ViewPort::GradientFillRectDecal(const vf2d &pos,
colTR,
};
drawClippedDecal(nullptr, points.data(), uvs.data(), colors.data(), points.size());
std::vector<float>w{1,1,1,1};
drawClippedDecal(nullptr, points.data(), uvs.data(), colors.data(), w.data(), points.size());
}
void olc::ViewPort::DrawPolygonDecal(Decal *decal,
@ -421,7 +467,9 @@ void olc::ViewPort::DrawPolygonDecal(Decal *decal,
colors[i] = tint;
}
drawClippedDecal(decal, pos.data(), uv.data(), colors.data(), pos.size());
std::vector<float>w{1,1,1,1};
drawClippedDecal(decal, pos.data(), uv.data(), colors.data(), w.data(), pos.size());
}
void olc::ViewPort::DrawPolygonDecal(Decal *decal,
@ -436,7 +484,8 @@ void olc::ViewPort::DrawPolygonDecal(Decal *decal,
const std::vector<vf2d> &pos,
const std::vector<vf2d> &uv,
const std::vector<Pixel> &tint) const {
drawClippedDecal(decal, pos.data(), uv.data(), tint.data(), pos.size());
std::vector<float>w{1,1,1,1};
drawClippedDecal(decal, pos.data(), uv.data(), tint.data(), w.data(), pos.size());
}
void olc::ViewPort::DrawLineDecal(const vf2d &pos1,
@ -471,9 +520,11 @@ void olc::ViewPort::drawClippedDecal(Decal *decal,
const vf2d *points,
const vf2d *uvs,
const Pixel *col,
const float *ws,
uint32_t elements) const {
std::vector<vf2d> outputList{points, points + elements};
std::vector<vf2d> outputUvs{uvs, uvs + elements};
std::vector<float> outputWs{ws, ws + elements};
std::vector<Pixel> outputCols{col, col + elements};
for (auto i = 0u; i < clipVertices.size(); i++) {
@ -482,9 +533,11 @@ void olc::ViewPort::drawClippedDecal(Decal *decal,
auto inputList{outputList};
auto inputUvs{outputUvs};
auto inputWs{outputWs};
auto inputCols{outputCols};
outputList.clear();
outputUvs.clear();
outputWs.clear();
outputCols.clear();
for (auto i = 0u; i < inputList.size(); i++) {
@ -492,6 +545,8 @@ void olc::ViewPort::drawClippedDecal(Decal *decal,
auto polygonB = inputList[(i + 1) % inputList.size()];
auto uvA = inputUvs[i];
auto uvB = inputUvs[(i + 1) % inputList.size()];
auto Wa = inputWs[i];
auto Wb = inputWs[(i + 1) % inputList.size()];
auto colA = inputCols[i];
auto colB = inputCols[(i + 1) % inputList.size()];
@ -500,6 +555,7 @@ void olc::ViewPort::drawClippedDecal(Decal *decal,
auto intersectionPoint =
polygonA + (polygonB - polygonA) * intersection;
auto intersectionUv = uvA + (uvB - uvA) * intersection;
auto intersectionW = Wa + (Wb - Wa) * intersection;
auto intersectionCol = PixelLerp(colA, colB, intersection);
float aDirection = directionFromLine(clipA, clipB, polygonA);
@ -509,14 +565,17 @@ void olc::ViewPort::drawClippedDecal(Decal *decal,
if (aDirection > 0) {
outputList.push_back(intersectionPoint);
outputUvs.push_back(intersectionUv);
outputWs.push_back(intersectionW);
outputCols.push_back(intersectionCol);
}
outputList.push_back(polygonB);
outputUvs.push_back(uvB);
outputWs.push_back(Wb);
outputCols.push_back(colB);
} else if (aDirection <= 0) {
outputList.push_back(intersectionPoint);
outputUvs.push_back(intersectionUv);
outputWs.push_back(intersectionW);
outputCols.push_back(intersectionCol);
}
}
@ -534,6 +593,7 @@ void olc::ViewPort::drawClippedDecal(Decal *decal,
outputList.data(),
outputUvs.data(),
outputCols.data(),
outputWs.data(),
outputList.size());
}
@ -772,4 +832,11 @@ void olc::ViewPort::DrawDropShadowStringDecal(Font&font, const olc::vf2d& pos, c
DrawDecal(pos,garbageCollector[key].decal,scale/4,col);
}
void olc::ViewPort::DrawRectDecal(const olc::vf2d& pos, const olc::vf2d& size, const olc::Pixel col)const{
FillRectDecal(pos,{size.x,float(pge->GetPixelSize().y)},col);
FillRectDecal(pos+vf2d{0,size.y-float(pge->GetPixelSize().y)},{size.x,float(pge->GetPixelSize().y)},col);
FillRectDecal(pos+vf2d{0,float(pge->GetPixelSize().y)},{float(pge->GetPixelSize().x),size.y-float(pge->GetPixelSize().y)*2},col);
FillRectDecal(pos+vf2d{size.x-float(pge->GetPixelSize().x),float(pge->GetPixelSize().y)},{float(pge->GetPixelSize().x),size.y-float(pge->GetPixelSize().y)*2},col);
}
#endif

@ -1128,7 +1128,7 @@ namespace olc
void DrawPartialDecal(const olc::vf2d& pos, olc::Decal* decal, const olc::vf2d& source_pos, const olc::vf2d& source_size, const olc::vf2d& scale = { 1.0f,1.0f }, const olc::Pixel& tint = olc::WHITE);
void DrawPartialDecal(const olc::vf2d& pos, const olc::vf2d& size, olc::Decal* decal, const olc::vf2d& source_pos, const olc::vf2d& source_size, const olc::Pixel& tint = olc::WHITE);
// Draws fully user controlled 4 vertices, pos(pixels), uv(pixels), colours
void DrawExplicitDecal(olc::Decal* decal, const olc::vf2d* pos, const olc::vf2d* uv, const olc::Pixel* col, uint32_t elements = 4);
void DrawExplicitDecal(olc::Decal* decal, const olc::vf2d* pos, const olc::vf2d* uv, const olc::Pixel* col, const float* w, uint32_t elements = 4);
// Draws a decal with 4 arbitrary points, warping the texture to look "correct"
void DrawWarpedDecal(olc::Decal* decal, const olc::vf2d(&pos)[4], const olc::Pixel& tint = olc::WHITE);
void DrawWarpedDecal(olc::Decal* decal, const olc::vf2d* pos, const olc::Pixel& tint = olc::WHITE);
@ -3009,7 +3009,7 @@ namespace olc
vLayers[nTargetLayer].vecDecalInstance.push_back(di);
}
void PixelGameEngine::DrawExplicitDecal(olc::Decal* decal, const olc::vf2d* pos, const olc::vf2d* uv, const olc::Pixel* col, uint32_t elements)
void PixelGameEngine::DrawExplicitDecal(olc::Decal* decal, const olc::vf2d* pos, const olc::vf2d* uv, const olc::Pixel* col, const float* w, uint32_t elements)
{
DecalInstance di;
di.decal = decal;
@ -3023,7 +3023,7 @@ namespace olc
di.pos[i] = { (pos[i].x * vInvScreenSize.x) * 2.0f - 1.0f, ((pos[i].y * vInvScreenSize.y) * 2.0f - 1.0f) * -1.0f };
di.uv[i] = uv[i];
di.tint[i] = col[i];
di.w[i] = 1.0f;
di.w[i] = w[i];
}
di.mode = nDecalMode;
di.structure = nDecalStructure;
@ -3187,9 +3187,9 @@ namespace olc
std::array<olc::vf2d, 4> points = { { {pos}, {pos.x, pos.y + vNewSize.y}, {pos + vNewSize}, {pos.x + vNewSize.x, pos.y} } };
std::array<olc::vf2d, 4> uvs = { {{0,0},{0,0},{0,0},{0,0}} };
std::array<olc::Pixel, 4> cols = { {col, col, col, col} };
DrawExplicitDecal(nullptr, points.data(), uvs.data(), cols.data(), 4);
std::array<float, 4> ws = {1,1,1,1};
DrawExplicitDecal(nullptr, points.data(), uvs.data(), cols.data(), ws.data(), 4);
SetDecalMode(m);
}
void PixelGameEngine::FillRectDecal(const olc::vf2d& pos, const olc::vf2d& size, const olc::Pixel col)
@ -3198,7 +3198,8 @@ namespace olc
std::array<olc::vf2d, 4> points = { { {pos}, {pos.x, pos.y + vNewSize.y}, {pos + vNewSize}, {pos.x + vNewSize.x, pos.y} } };
std::array<olc::vf2d, 4> uvs = { {{0,0},{0,0},{0,0},{0,0}} };
std::array<olc::Pixel, 4> cols = { {col, col, col, col} };
DrawExplicitDecal(nullptr, points.data(), uvs.data(), cols.data(), 4);
std::array<float, 4> ws = {1,1,1,1};
DrawExplicitDecal(nullptr, points.data(), uvs.data(), cols.data(), ws.data(), 4);
}
void PixelGameEngine::GradientFillRectDecal(const olc::vf2d& pos, const olc::vf2d& size, const olc::Pixel colTL, const olc::Pixel colBL, const olc::Pixel colBR, const olc::Pixel colTR)
@ -3206,7 +3207,8 @@ namespace olc
std::array<olc::vf2d, 4> points = { { {pos}, {pos.x, pos.y + size.y}, {pos + size}, {pos.x + size.x, pos.y} } };
std::array<olc::vf2d, 4> uvs = { {{0,0},{0,0},{0,0},{0,0}} };
std::array<olc::Pixel, 4> cols = { {colTL, colBL, colBR, colTR} };
DrawExplicitDecal(nullptr, points.data(), uvs.data(), cols.data(), 4);
std::array<float, 4> ws = {1,1,1,1};
DrawExplicitDecal(nullptr, points.data(), uvs.data(), cols.data(), ws.data(), 4);
}
void PixelGameEngine::DrawRotatedDecal(const olc::vf2d& pos, olc::Decal* decal, const float fAngle, const olc::vf2d& center, const olc::vf2d& scale, const olc::Pixel& tint)

Loading…
Cancel
Save