diff --git a/Crawler/CharacterAbilityPreviewComponent.h b/Crawler/CharacterAbilityPreviewComponent.h index 9abc43fc..80b7388f 100644 --- a/Crawler/CharacterAbilityPreviewComponent.h +++ b/Crawler/CharacterAbilityPreviewComponent.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}); } } }; \ No newline at end of file diff --git a/Crawler/CharacterMenuWindow.cpp b/Crawler/CharacterMenuWindow.cpp index 7457b226..a558750c 100644 --- a/Crawler/CharacterMenuWindow.cpp +++ b/Crawler/CharacterMenuWindow.cpp @@ -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); } \ No newline at end of file diff --git a/Crawler/CharacterRotatingDisplay.h b/Crawler/CharacterRotatingDisplay.h index db2678aa..eaed9816 100644 --- a/Crawler/CharacterRotatingDisplay.h +++ b/Crawler/CharacterRotatingDisplay.h @@ -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{ + virtual inline void DrawDecal(ViewPort&window,vf2d parentPos,bool focused)override{ + window.DrawWarpedDecal(icon,std::array{ 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}, diff --git a/Crawler/InventoryConsumableWindow.cpp b/Crawler/InventoryConsumableWindow.cpp index 66eba0d9..7d3e46d7 100644 --- a/Crawler/InventoryConsumableWindow.cpp +++ b/Crawler/InventoryConsumableWindow.cpp @@ -84,5 +84,4 @@ void Menu::InitializeConsumableInventoryWindow(){ inventoryWindow->ADD("itemDescription",MenuLabel)(geom2d::rect(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; } \ No newline at end of file diff --git a/Crawler/InventoryWindow.cpp b/Crawler/InventoryWindow.cpp index d9ad0e8b..fe111a7c 100644 --- a/Crawler/InventoryWindow.cpp +++ b/Crawler/InventoryWindow.cpp @@ -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 } \ No newline at end of file diff --git a/Crawler/Menu.cpp b/Crawler/Menu.cpp index ff5d12ef..87364fc9 100644 --- a/Crawler/Menu.cpp +++ b/Crawler/Menu.cpp @@ -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::vectorallComponents; 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()); } } }; diff --git a/Crawler/Menu.h b/Crawler/Menu.h index a8ec2ad4..adf9f8a3 100644 --- a/Crawler/Menu.h +++ b/Crawler/Menu.h @@ -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>inventoryListeners; //All menu components that care about inventory updates subscribe to this list indirectly (See Menu::AddInventoryListener()). static std::vectorequipStatListeners; //All menu components that care about stat/equip updates subscribe to this list indirectly (See Menu::AddStatListener()). public: diff --git a/Crawler/MenuAnimatedIconButton.h b/Crawler/MenuAnimatedIconButton.h index a3b35023..2de30e1e 100644 --- a/Crawler/MenuAnimatedIconButton.h +++ b/Crawler/MenuAnimatedIconButton.h @@ -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::rectsprRect=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); } }; \ No newline at end of file diff --git a/Crawler/MenuAnimatedIconToggleButton.h b/Crawler/MenuAnimatedIconToggleButton.h index 305084f3..9739038d 100644 --- a/Crawler/MenuAnimatedIconToggleButton.h +++ b/Crawler/MenuAnimatedIconToggleButton.h @@ -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); } } }; \ No newline at end of file diff --git a/Crawler/MenuComponent.cpp b/Crawler/MenuComponent.cpp index be1e789f..db2d44ea 100644 --- a/Crawler/MenuComponent.cpp +++ b/Crawler/MenuComponent.cpp @@ -40,6 +40,8 @@ All rights reserved. #include "drawutil.h" #include "util.h" +INCLUDE_game + using A=Attribute; MenuComponent::MenuComponent(geom2d::rectrect,std::string label,MenuFunc onClick,ButtonAttr attributes) @@ -57,7 +59,6 @@ MenuComponent::MenuComponent(geom2d::rectrect,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: "<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: "<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: "<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) }; \ No newline at end of file diff --git a/Crawler/MenuIconButton.h b/Crawler/MenuIconButton.h index f749bc97..e18a9f33 100644 --- a/Crawler/MenuIconButton.h +++ b/Crawler/MenuIconButton.h @@ -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); } } }; diff --git a/Crawler/MenuItemButton.h b/Crawler/MenuItemButton.h index 192c793c..a2cd41d6 100644 --- a/Crawler/MenuItemButton.h +++ b/Crawler/MenuItemButton.h @@ -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::rectboundingBox={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{ diff --git a/Crawler/MenuItemItemButton.h b/Crawler/MenuItemItemButton.h index 5149d680..0c7747c1 100644 --- a/Crawler/MenuItemItemButton.h +++ b/Crawler/MenuItemItemButton.h @@ -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::rectboundingBox={drawPos,textSize}; - if(PointWithinParent(this,boundingBox)){ - game->DrawShadowStringDecal(drawPos,quantityText,WHITE,BLACK,quantityTextScale,quantityTextScale.x); - } + window.DrawShadowStringDecal(drawPos,quantityText,WHITE,BLACK,quantityTextScale,quantityTextScale.x); } } }; \ No newline at end of file diff --git a/Crawler/MenuLabel.h b/Crawler/MenuLabel.h index 5bfd25d4..9e2959f7 100644 --- a/Crawler/MenuLabel.h +++ b/Crawler/MenuLabel.h @@ -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)}); } } }; \ No newline at end of file diff --git a/Crawler/PopupMenuLabel.h b/Crawler/PopupMenuLabel.h index 3fbc9351..a118bd2c 100644 --- a/Crawler/PopupMenuLabel.h +++ b/Crawler/PopupMenuLabel.h @@ -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); } } } diff --git a/Crawler/ScrollableWindowComponent.h b/Crawler/ScrollableWindowComponent.h index 6cdb32d1..e8d760d8 100644 --- a/Crawler/ScrollableWindowComponent.h +++ b/Crawler/ScrollableWindowComponent.h @@ -45,7 +45,7 @@ using A=Attribute; class ScrollableWindowComponent:public MenuComponent{ protected: - Renderable r; + ViewPort subWindow; std::vectorcomponents; 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{Menu::menus[parentMenu]->pos+rect.pos+child->rect.pos+V(A::SCROLL_OFFSET),child->rect.size},game->GetMousePos()); diff --git a/Crawler/SpawnEncounterLabel.h b/Crawler/SpawnEncounterLabel.h index 548e317c..e47e52ec 100644 --- a/Crawler/SpawnEncounterLabel.h +++ b/Crawler/SpawnEncounterLabel.h @@ -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&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}); } }; \ No newline at end of file diff --git a/Crawler/Version.h b/Crawler/Version.h index f208064c..f02867db 100644 --- a/Crawler/Version.h +++ b/Crawler/Version.h @@ -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 diff --git a/Crawler/drawutil.cpp b/Crawler/drawutil.cpp index dad473d4..6c8462ac 100644 --- a/Crawler/drawutil.cpp +++ b/Crawler/drawutil.cpp @@ -171,4 +171,37 @@ void drawutil::DrawCrosshairDecalTransformedView(olc::TransformedView&view,geom2 pos=vf2d{pos.x+crosshairExtension.x,pos.y+borderThickness}; size={borderThickness,crosshairExtension.y}; game->view.FillRectDecal(pos,size,RED); +} + +void drawutil::DrawCrosshairDecalViewPort(olc::ViewPort&window,geom2d::rectrect,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); } \ No newline at end of file diff --git a/Crawler/drawutil.h b/Crawler/drawutil.h index 57154366..81579f2c 100644 --- a/Crawler/drawutil.h +++ b/Crawler/drawutil.h @@ -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::rectrect,float accTime,float pulsatingAmt=2,float borderThickness=4); void DrawCrosshairDecal(Crawler*game,geom2d::rectrect,float accTime,float pulsatingAmt=2,float borderThickness=4); void DrawCrosshairDecalTransformedView(TransformedView&view,geom2d::rectrect,float accTime,float pulsatingAmt=2,float borderThickness=4); + void DrawCrosshairDecalViewPort(ViewPort&window,geom2d::rectrect,float accTime,float pulsatingAmt=2,float borderThickness=4); } \ No newline at end of file diff --git a/Crawler/olcPGEX_TransformedView.h b/Crawler/olcPGEX_TransformedView.h index 9860e029..169bb86a 100644 --- a/Crawler/olcPGEX_TransformedView.h +++ b/Crawler/olcPGEX_TransformedView.h @@ -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 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) diff --git a/Crawler/olcPGEX_ViewPort.h b/Crawler/olcPGEX_ViewPort.h index 7a4893e2..f8f3c3c0 100644 --- a/Crawler/olcPGEX_ViewPort.h +++ b/Crawler/olcPGEX_ViewPort.h @@ -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 w{ 1, 1, 1, 1 }; + std::vector newPos; + newPos.resize(4); std::vector 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 &pos, @@ -297,7 +323,25 @@ void olc::ViewPort::DrawPartialWarpedDecal(Decal *decal, tint, }; - drawClippedDecal(decal, pos, uvs.data(), cols.data(), 4); + std::vectorws{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 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 uvs{ @@ -408,7 +452,9 @@ void olc::ViewPort::GradientFillRectDecal(const vf2d &pos, colTR, }; - drawClippedDecal(nullptr, points.data(), uvs.data(), colors.data(), points.size()); + std::vectorw{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::vectorw{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 &pos, const std::vector &uv, const std::vector &tint) const { - drawClippedDecal(decal, pos.data(), uv.data(), tint.data(), pos.size()); + std::vectorw{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 outputList{points, points + elements}; std::vector outputUvs{uvs, uvs + elements}; + std::vector outputWs{ws, ws + elements}; std::vector 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 \ No newline at end of file diff --git a/Crawler/olcPixelGameEngine.h b/Crawler/olcPixelGameEngine.h index d9b24053..2a78e100 100644 --- a/Crawler/olcPixelGameEngine.h +++ b/Crawler/olcPixelGameEngine.h @@ -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 points = { { {pos}, {pos.x, pos.y + vNewSize.y}, {pos + vNewSize}, {pos.x + vNewSize.x, pos.y} } }; std::array uvs = { {{0,0},{0,0},{0,0},{0,0}} }; std::array cols = { {col, col, col, col} }; - DrawExplicitDecal(nullptr, points.data(), uvs.data(), cols.data(), 4); + std::array 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 points = { { {pos}, {pos.x, pos.y + vNewSize.y}, {pos + vNewSize}, {pos.x + vNewSize.x, pos.y} } }; std::array uvs = { {{0,0},{0,0},{0,0},{0,0}} }; std::array cols = { {col, col, col, col} }; - DrawExplicitDecal(nullptr, points.data(), uvs.data(), cols.data(), 4); + std::array 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 points = { { {pos}, {pos.x, pos.y + size.y}, {pos + size}, {pos.x + size.x, pos.y} } }; std::array uvs = { {{0,0},{0,0},{0,0},{0,0}} }; std::array cols = { {colTL, colBL, colBR, colTR} }; - DrawExplicitDecal(nullptr, points.data(), uvs.data(), cols.data(), 4); + std::array 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)