Fixed menu labels not re-updating when a blank item was assigned. Made onMouseOut callback occur when the child selected item of a RowInventoryScrollableWindowComponent was cleared. Added refinement cost displays to the Refining interface. Ready for refining action. Release Build 11461.

pull/65/head
sigonasr2 3 months ago
parent 8303665828
commit 01ec5f5390
  1. 4
      Adventures in Lestoria/ArtificerDisassembleWindow.cpp
  2. 42
      Adventures in Lestoria/ArtificerRefineWindow.cpp
  3. 5
      Adventures in Lestoria/IT.cpp
  4. 2
      Adventures in Lestoria/IT.h
  5. 6
      Adventures in Lestoria/Item.cpp
  6. 1
      Adventures in Lestoria/Item.h
  7. 4
      Adventures in Lestoria/MenuComponent.h
  8. 9
      Adventures in Lestoria/MenuDecal.h
  9. 2
      Adventures in Lestoria/MenuDefinitions.h
  10. 8
      Adventures in Lestoria/MenuItemItemButton.h
  11. 82
      Adventures in Lestoria/RowInventoryScrollableWindowComponent.h
  12. 2
      Adventures in Lestoria/Version.h
  13. BIN
      x64/Release/Adventures in Lestoria.exe

@ -109,7 +109,7 @@ void Menu::InitializeArtificerDisassembleWindow(){
EnableDisassemblyDisplay();
RowItemDisplay&item{*DYNAMIC_POINTER_CAST<RowItemDisplay>(data.component)};
Component<MenuItemItemButton>(data.menu.type,"Item Icon")->SetItem(item.GetItem().lock());
Component<MenuIconButton>(data.menu.type,"Disassembly Result")->SetIcon(GFX.at(item.GetItem().lock()->FragmentName()).Decal());
Component<MenuIconButton>(data.menu.type,"Disassembly Result")->SetIcon(GFX.at(item.GetItem().lock()->FragmentIcon().value()).Decal());
Component<MenuLabel>(data.menu.type,"Disassembly Result Title")->SetLabel(item.GetItem().lock()->FragmentName());
Component<MenuLabel>(data.menu.type,"Fragment Total Count")->SetLabel(std::format("Currently Owned: {}",Inventory::GetItemCount(item.GetItem().lock()->FragmentName())));
return true;
@ -119,7 +119,7 @@ void Menu::InitializeArtificerDisassembleWindow(){
if(childComponent){
RowItemDisplay&item{childComponent.value().get()};
Component<MenuItemItemButton>(data.menu.type,"Item Icon")->SetItem(item.GetItem().lock());
Component<MenuIconButton>(data.menu.type,"Disassembly Result")->SetIcon(GFX.at(item.GetItem().lock()->FragmentName()).Decal());
Component<MenuIconButton>(data.menu.type,"Disassembly Result")->SetIcon(GFX.at(item.GetItem().lock()->FragmentIcon().value()).Decal());
Component<MenuLabel>(data.menu.type,"Disassembly Result Title")->SetLabel(item.GetItem().lock()->FragmentName());
Component<MenuLabel>(data.menu.type,"Fragment Total Count")->SetLabel(std::format("Currently Owned: {}",Inventory::GetItemCount(item.GetItem().lock()->FragmentName())));
EnableDisassemblyDisplay();

@ -42,13 +42,14 @@ All rights reserved.
#include "MenuItemItemButton.h"
#include "MenuRefineLabel.h"
#include "PlayerMoneyLabel.h"
#include "MenuDecal.h"
INCLUDE_game
void Menu::InitializeArtificerRefineWindow(){
Menu*const artificerRefineWindow{CreateMenu(ARTIFICER_REFINE,CENTERED,game->GetScreenSize()-vi2d{52,52})};
auto disassemblyTitleLabel{artificerRefineWindow->ADD("Disassembly Title Label",MenuLabel)(geom2d::rect<float>{{0.f,-16.f},{artificerRefineWindow->size.x,24.f}},"Accessory Disassembly",2.f,ComponentAttr::SHADOW|ComponentAttr::OUTLINE|ComponentAttr::BACKGROUND)END};
auto disassemblyTitleLabel{artificerRefineWindow->ADD("Refining Title Label",MenuLabel)(geom2d::rect<float>{{0.f,-16.f},{artificerRefineWindow->size.x,24.f}},"Accessory Refinement",2.f,ComponentAttr::SHADOW|ComponentAttr::OUTLINE|ComponentAttr::BACKGROUND)END};
auto inventoryLabel{artificerRefineWindow->ADD("Accessory List Label",MenuLabel)(geom2d::rect<float>{{0.f,12.f},{180.f,12.f}},"Choose Accessory:",1.f,ComponentAttr::SHADOW|ComponentAttr::LEFT_ALIGN)END};
@ -61,10 +62,31 @@ void Menu::InitializeArtificerRefineWindow(){
const auto ResetRefineDisplay{[artificerRefineWindow](){
MenuType menuType{artificerRefineWindow->GetType()};
Component<MenuItemItemButton>(menuType,"Item Icon")->SetItem(Item::BLANK);
Component<MenuRefineLabel>(menuType,"Stats Block")->SetItem(Item::BLANK);
Component<MenuRefineLabel>(menuType,"Stats Block")->Disable();
Component<MenuLabel>(menuType,"Refine Cost Label")->Disable();
Component<MenuDecal>(menuType,"Fragment Cost Icon")->Disable();
Component<MenuLabel>(menuType,"Fragment Label")->Disable();
Component<MenuLabel>(menuType,"Fragment Money Cost Label")->Disable();
Component<MenuComponent>(menuType,"Fragment Refine Button")->Disable();
}};
const auto EnableRefineDisplay{[artificerRefineWindow](){
MenuType menuType{artificerRefineWindow->GetType()};
const std::weak_ptr<Item>&selectedItem{Component<MenuItemItemButton>(menuType,"Item Icon")->GetItem()};
Component<MenuRefineLabel>(menuType,"Stats Block")->SetItem(selectedItem);
Component<MenuRefineLabel>(menuType,"Stats Block")->Enable();
Component<MenuLabel>(menuType,"Refine Cost Label")->Enable();
Component<MenuDecal>(menuType,"Fragment Cost Icon")->Enable();
Component<MenuDecal>(menuType,"Fragment Cost Icon")->SetImage(GFX.at(selectedItem.lock()->FragmentIcon().value()));
Component<MenuLabel>(menuType,"Fragment Label")->Enable();
Component<MenuLabel>(menuType,"Fragment Money Cost Label")->Enable();
Component<MenuComponent>(menuType,"Fragment Refine Button")->Enable();
Component<MenuComponent>(menuType,"Fragment Refine Button")->SetGrayedOut(!selectedItem.lock()->CanBeRefined());
const std::string_view fragmentName{selectedItem.lock()->FragmentName()};
const Pixel fragmentItemDisplayCol{Inventory::GetItemCount(fragmentName)>="Fragment Refine Cost"_i[0]?WHITE:RED};
const Pixel moneyCostDisplayCol{game->GetPlayer()->GetMoney()>="Fragment Refine Cost"_i[1]?WHITE:RED};
Component<MenuLabel>(menuType,"Fragment Label")->SetLabel(std::format("{}{} x{} ({})",fragmentItemDisplayCol.toHTMLColorCode(),fragmentName,"Fragment Refine Cost"_i[0],Inventory::GetItemCount(fragmentName)));
Component<MenuLabel>(menuType,"Fragment Money Cost Label")->SetLabel(std::format("{}{} gold",moneyCostDisplayCol.toHTMLColorCode(),"Fragment Refine Cost"_i[1]));
}};
auto inventoryDisplay{artificerRefineWindow->ADD("Accessory List",RowInventoryScrollableWindowComponent)(geom2d::rect<float>{{0.f,28.f},{artificerRefineWindow->size.x/2-4.f,artificerRefineWindow->size.y-44}},"","",[](MenuFuncData data){
@ -74,15 +96,15 @@ void Menu::InitializeArtificerRefineWindow(){
return true;
},[EnableRefineDisplay](MenuFuncData data){OnHover:
RowItemDisplay&item{*DYNAMIC_POINTER_CAST<RowItemDisplay>(data.component)};
EnableRefineDisplay();
Component<MenuItemItemButton>(data.menu.type,"Item Icon")->SetItem(item.GetItem());
Component<MenuRefineLabel>(data.menu.type,"Stats Block")->SetItem(item.GetItem());
EnableRefineDisplay();
return true;
},[ResetRefineDisplay,EnableRefineDisplay](MenuFuncData data){OnMouseOut:
ResetRefineDisplay();
auto childComponent{DYNAMIC_POINTER_CAST<RowInventoryScrollableWindowComponent>(data.parentComponent.lock())->GetSelectedChild()};
if(childComponent){
RowItemDisplay&item{childComponent.value().get()};
Component<MenuItemItemButton>(data.menu.type,"Item Icon")->SetItem(item.GetItem());
EnableRefineDisplay();
}
return true;
@ -92,6 +114,18 @@ void Menu::InitializeArtificerRefineWindow(){
auto statsBlock{artificerRefineWindow->ADD("Stats Block",MenuRefineLabel)(geom2d::rect<float>{{artificerRefineWindow->size.x/2+4.f,104.f},{artificerRefineWindow->size.x/2-4.f,44.f}},Item::BLANK,1.f,ComponentAttr::BACKGROUND|ComponentAttr::SHADOW|ComponentAttr::OUTLINE|ComponentAttr::FIXED_WIDTH_FONT|ComponentAttr::FIT_TO_LABEL|ComponentAttr::LEFT_ALIGN)END};
auto refineCostLabel{artificerRefineWindow->ADD("Refine Cost Label",MenuLabel)(geom2d::rect<float>{{artificerRefineWindow->size.x/2+4.f,152.f},{64.f,20.f}},"Refine Cost:",1.f,ComponentAttr::SHADOW|ComponentAttr::BACKGROUND|ComponentAttr::OUTLINE)END};
auto fragmentCostIcon{artificerRefineWindow->ADD("Fragment Cost Icon",MenuDecal)(geom2d::rect<float>{{artificerRefineWindow->size.x/2+68.f,152.f},{12.f,12.f}})END};
auto fragmentDisplayLabel{artificerRefineWindow->ADD("Fragment Label",MenuLabel)(geom2d::rect<float>{{artificerRefineWindow->size.x/2+80.f,152.f},{artificerRefineWindow->size.x/2-60.f,12.f}},"",1.f,ComponentAttr::SHADOW|ComponentAttr::FIT_TO_LABEL|ComponentAttr::LEFT_ALIGN)END};
auto fragmentMoneyCostLabel{artificerRefineWindow->ADD("Fragment Money Cost Label",MenuLabel)(geom2d::rect<float>{{artificerRefineWindow->size.x/2+80.f,164.f},{artificerRefineWindow->size.x/2-60.f,12.f}},"",1.f,ComponentAttr::SHADOW|ComponentAttr::LEFT_ALIGN)END};
auto fragmentRefineButton{artificerRefineWindow->ADD("Fragment Refine Button",MenuComponent)(geom2d::rect<float>{{artificerRefineWindow->size.x/2+96.f,180.f},{artificerRefineWindow->size.x/2-76.f,12.f}},"Refine",[](MenuFuncData data){
onClick:
return true;
})END};
#pragma region Money Display
vf2d moneyIconPos{artificerRefineWindow->size.x/2-28.f,artificerRefineWindow->size.y-12.f};
auto moneyIcon=artificerRefineWindow->ADD("Money Icon",MenuIconButton)(geom2d::rect<float>{moneyIconPos,{24,24}},GFX["money.png"].Decal(),DO_NOTHING,IconButtonAttr::NOT_SELECTABLE|IconButtonAttr::NO_OUTLINE|IconButtonAttr::NO_BACKGROUND)END;

@ -49,9 +49,14 @@ IT::IT(std::string name)
itemName=ITEM_CONVERSIONS.at(name); //Convert the item if it's using an old name.
}
}
IT::IT(std::string_view name)
:IT(std::string(name)){}
IT::operator std::string(){
return itemName;
}
IT::operator std::string_view(){
return itemName;
}
std::ostream&operator<<(std::ostream&rhs,IT&item){
rhs<<item.itemName;
return rhs;

@ -49,7 +49,9 @@ class IT{
public:
IT();
IT(std::string name);
IT(std::string_view name);
operator std::string();
operator std::string_view();
const bool operator==(const std::shared_ptr<Item>&rhs);
const bool operator==(const std::weak_ptr<Item>&rhs);
friend std::ostream&operator<<(std::ostream&rhs,IT&item);

@ -405,7 +405,7 @@ void ItemInfo::InitializeItems(){
}
}
it.img=GFX.at(fragmentName).Decal();
it.name=fragmentName;
it.fragmentIcon=it.name=fragmentName;
it.description="Fragment Description"_S;
it.category="Materials";
LOG(std::format("Item Fragment {} generated...",fragmentName));
@ -1516,4 +1516,8 @@ const std::optional<std::string>&ItemInfo::FragmentIcon()const{
const Pixel Stats::GetShimmeringColor(){
return PixelLerp({255,196,60},{254,217,133},sin((70*game->GetRunTime())/2.f+0.5f));
}
const std::optional<std::string>&Item::FragmentIcon()const{
return ITEM_DATA.at(FragmentName()).FragmentIcon();
}

@ -266,6 +266,7 @@ public:
friend const bool operator==(const IT&lhs,std::shared_ptr<Item>rhs){return operator==(rhs,lhs);};
const Pixel GetDisplayNameColor()const;
static const bool SelectedEquipIsDifferent(const std::weak_ptr<Item>equipAttemptingToEquip,const EquipSlot slotToEquipTo);
const std::optional<std::string>&FragmentIcon()const;
};
class Inventory{

@ -81,8 +81,6 @@ class MenuComponent:public IAttributable{
friend class RowItemDisplay;
friend class InventoryConsumableWindow;
friend class FloatingMenuComponent;
MenuFunc onHover=[](MenuFuncData dat){return true;};
MenuFunc onMouseOut=[](MenuFuncData dat){return true;};
bool hoverState=false;
bool runHoverFunctions=false;
private:
@ -136,6 +134,8 @@ protected:
virtual void DisableOutsideWindow();
const bool IsEnabledOutsideWindow()const;
const bool IsDisabledOutsideWindow()const;
MenuFunc onHover=[](MenuFuncData dat){return true;};
MenuFunc onMouseOut=[](MenuFuncData dat){return true;};
public:
MenuType parentMenu=MenuType::ENUM_END;
std::weak_ptr<ScrollableWindowComponent>parentComponent{};

@ -41,14 +41,17 @@ All rights reserved.
class MenuDecal:public MenuComponent{
public:
inline MenuDecal(geom2d::rect<float>rect,Renderable&image,MenuFunc onClick,MenuFunc onHover)
inline MenuDecal(geom2d::rect<float>rect,std::optional<std::reference_wrapper<Renderable>>image={},MenuFunc onClick=DO_NOTHING,MenuFunc onHover=DO_NOTHING)
:image(image),MenuComponent(rect,"",onClick,ButtonAttr::NONE){
SetHoverFunc(onHover);
}
inline void DrawDecal(ViewPort&window,bool focused)override{
window.DrawDecal(rect.pos,image.Decal(),rect.size/image.Sprite()->Size());
if(image)window.DrawDecal(rect.pos,image.value().get().Decal(),rect.size/image.value().get().Sprite()->Size());
}
inline void SetImage(Renderable&renderable){
image=renderable;
}
private:
const Renderable&image;
std::optional<std::reference_wrapper<Renderable>>image;
};

@ -51,7 +51,7 @@ struct MenuFuncData{
AiL*const game;
const std::weak_ptr<MenuComponent> component;
const std::weak_ptr<ScrollableWindowComponent> parentComponent={};
MenuFuncData(Menu&menu,AiL*const game,std::weak_ptr<MenuComponent> component,std::weak_ptr<ScrollableWindowComponent>parentComponent={});
MenuFuncData(Menu&menu,AiL*const game,std::weak_ptr<MenuComponent>component,std::weak_ptr<ScrollableWindowComponent>parentComponent={});
};
using InputGroupActionDisplayName=std::variant<std::string,std::function<std::string(MenuFuncData)>>;

@ -124,12 +124,12 @@ protected:
icon=nullptr;
labelNameText="";
labelDescriptionText="";
return;
}else{
icon=const_cast<Decal*>(itemRef.lock()->Decal());
labelNameText=itemRef.lock()->DisplayName();
labelDescriptionText=itemRef.lock()->Description(compact);
}
icon=const_cast<Decal*>(itemRef.lock()->Decal());
labelNameText=itemRef.lock()->DisplayName();
labelDescriptionText=itemRef.lock()->Description(compact);
if(hideDetails){
std::for_each(labelNameText.begin(),labelNameText.end(),[](char&c){c='?';});
std::for_each(labelDescriptionText.begin(),labelDescriptionText.end(),[](char&c){c='?';});

@ -41,52 +41,54 @@ All rights reserved.
#include "InventoryCreator.h"
class RowInventoryScrollableWindowComponent:public InventoryScrollableWindowComponent{
friend class InventoryCreator;
friend class Menu;
std::weak_ptr<RowItemDisplay>selectedComponent;
friend class InventoryCreator;
friend class Menu;
std::weak_ptr<RowItemDisplay>selectedComponent;
protected:
PriceLabel::PriceLabel priceLabel=PriceLabel::NONE;
PriceLabel::PriceLabel priceLabel=PriceLabel::NONE;
public:
inline RowInventoryScrollableWindowComponent(geom2d::rect<float>rect,std::string itemNameLabelName,std::string itemDescriptionLabelName,std::function<bool(MenuFuncData)>inventoryButtonClickAction,std::function<bool(MenuFuncData)>inventoryButtonHoverAction,std::function<bool(MenuFuncData)>inventoryButtonMouseOutAction,const InventoryCreator&creator,InventoryWindowOptions options={.padding=8,.size={24,24}},bool inventoryButtonsActive=true,ComponentAttr attributes=ComponentAttr::BACKGROUND|ComponentAttr::OUTLINE)
:InventoryScrollableWindowComponent(rect,itemNameLabelName,itemDescriptionLabelName,inventoryButtonClickAction,inventoryButtonHoverAction,inventoryButtonMouseOutAction,creator,options,inventoryButtonsActive,attributes){}
virtual inline void AfterCreate()override final{
ScrollableWindowComponent::AfterCreate();
if(options.size.x>rect.size.x||options.size.y>rect.size.y)ERR(std::format("WARNING! Component {} has Inventory Option Sizes: {} which is not large enough to fit in the component whose size is {}! Please make the component larger or the items smaller.",name,options.size.str(),rect.size.str()));
}
:InventoryScrollableWindowComponent(rect,itemNameLabelName,itemDescriptionLabelName,inventoryButtonClickAction,inventoryButtonHoverAction,inventoryButtonMouseOutAction,creator,options,inventoryButtonsActive,attributes){}
virtual inline void AfterCreate()override final{
ScrollableWindowComponent::AfterCreate();
if(options.size.x>rect.size.x||options.size.y>rect.size.y)ERR(std::format("WARNING! Component {} has Inventory Option Sizes: {} which is not large enough to fit in the component whose size is {}! Please make the component larger or the items smaller.",name,options.size.str(),rect.size.str()));
}
virtual inline void SetCompactDescriptions(CompactText compact)override final{
this->compact=compact;
for(std::weak_ptr<MenuComponent>component:components){
std::weak_ptr<RowItemDisplay>itemButton=DYNAMIC_POINTER_CAST<RowItemDisplay>(component.lock());
itemButton.lock()->SetCompactDescriptions(compact);
}
}
this->compact=compact;
for(std::weak_ptr<MenuComponent>component:components){
std::weak_ptr<RowItemDisplay>itemButton=DYNAMIC_POINTER_CAST<RowItemDisplay>(component.lock());
itemButton.lock()->SetCompactDescriptions(compact);
}
}
virtual inline void SetPriceLabelType(PriceLabel::PriceLabel labelType)final{
this->priceLabel=labelType;
for(std::weak_ptr<MenuComponent>component:components){
std::weak_ptr<RowItemDisplay>itemButton=DYNAMIC_POINTER_CAST<RowItemDisplay>(component.lock());
itemButton.lock()->SetPriceLabelType(labelType);
}
}
virtual inline void SetPriceLabelType(PriceLabel::PriceLabel labelType)final{
this->priceLabel=labelType;
for(std::weak_ptr<MenuComponent>component:components){
std::weak_ptr<RowItemDisplay>itemButton=DYNAMIC_POINTER_CAST<RowItemDisplay>(component.lock());
itemButton.lock()->SetPriceLabelType(labelType);
}
}
inline void ClearSelectedChild(){
if(!selectedComponent.expired())selectedComponent.lock()->itemIsSelected=false;
selectedComponent.reset();
}
inline void ClearSelectedChild(){
std::weak_ptr<RowItemDisplay>previousSelectedComponent{selectedComponent};
if(!selectedComponent.expired())selectedComponent.lock()->itemIsSelected=false;
selectedComponent.reset();
if(!previousSelectedComponent.expired())previousSelectedComponent.lock()->onMouseOut(MenuFuncData{*Menu::menus[parentMenu],game,Menu::menus[parentMenu]->components[name],previousSelectedComponent.lock()->parentComponent}); //HACK ALERT: It's possible the selected component uses functions that set components via a mouse hover/click. This will fake a mouse out event which hopefully I set a callback to clear any menu states that were set due to mouse hover/click...
}
inline void SelectChild(std::weak_ptr<RowItemDisplay>childComponent){
selectedComponent=childComponent;
for(std::weak_ptr<MenuComponent>child:components){
RowItemDisplay&rowItem{*DYNAMIC_POINTER_CAST<RowItemDisplay>(child)};
rowItem.itemIsSelected=false;
}
selectedComponent.lock()->itemIsSelected=true;
}
inline void SelectChild(std::weak_ptr<RowItemDisplay>childComponent){
selectedComponent=childComponent;
for(std::weak_ptr<MenuComponent>child:components){
RowItemDisplay&rowItem{*DYNAMIC_POINTER_CAST<RowItemDisplay>(child)};
rowItem.itemIsSelected=false;
}
selectedComponent.lock()->itemIsSelected=true;
}
inline std::optional<std::reference_wrapper<RowItemDisplay>>GetSelectedChild()const{
if(!selectedComponent.expired()){
return *selectedComponent.lock();
}
return {};
}
inline std::optional<std::reference_wrapper<RowItemDisplay>>GetSelectedChild()const{
if(!selectedComponent.expired()){
return *selectedComponent.lock();
}
return {};
}
};

@ -39,7 +39,7 @@ All rights reserved.
#define VERSION_MAJOR 1
#define VERSION_MINOR 2
#define VERSION_PATCH 5
#define VERSION_BUILD 11440
#define VERSION_BUILD 11461
#define stringify(a) stringify_(a)
#define stringify_(a) #a

Loading…
Cancel
Save