Implemented menucomponent depth property. Fixed equipment menu labels interacting with hover events.

pull/28/head
sigonasr2 12 months ago
parent dc6ecf40c2
commit 4ac42fbd7e
  1. 13
      Crawler/CharacterMenuWindow.cpp
  2. 2
      Crawler/ClassSelectionWindow.cpp
  3. 4
      Crawler/EquipSlotButton.h
  4. 10
      Crawler/Item.cpp
  5. 4
      Crawler/Item.h
  6. 6
      Crawler/ItemLoadoutWindow.cpp
  7. 38
      Crawler/Menu.cpp
  8. 8
      Crawler/Menu.h
  9. 1
      Crawler/MenuComponent.h
  10. 37
      Crawler/MenuItemItemButton.h
  11. 8
      Crawler/ScrollableWindowComponent.h
  12. 2
      Crawler/Version.h

@ -96,7 +96,7 @@ void Menu::InitializeCharacterMenuWindow(){
equipSelectionSelectButton->Enable(false);
characterMenuWindow->AddComponent("Equip Selection Outline",equipSelectionOutline);
characterMenuWindow->AddComponent("Equip List",equipmentList);
characterMenuWindow->AddComponent("Equip List",equipmentList,-1);
characterMenuWindow->AddComponent("Equip Selection Bottom Outline",equipSelectionBottomOutline);
characterMenuWindow->AddComponent("Equip Selection Select Button",equipSelectionSelectButton);
@ -185,7 +185,7 @@ void Menu::InitializeCharacterMenuWindow(){
counter++;
}
return true;
});
},"Item Name","Item Description");
equip->I(Attribute::EQUIP_TYPE)=int(slot);
if(Inventory::GetEquip(slot)==&itemInvRef){
equip->SetSelected(true);
@ -200,7 +200,7 @@ void Menu::InitializeCharacterMenuWindow(){
Component<MenuComponent>(data.component->parentMenu,"Equip Selection Select Button")->Enable(true);
Component<CharacterRotatingDisplay>(data.component->parentMenu,"Character Rotating Display")->Enable(false);
return true;
},DO_NOTHING,DO_NOTHING);
},DO_NOTHING,DO_NOTHING,"Item Name","Item Description");
PopupMenuLabel*equipmentLabel=NEW PopupMenuLabel(CHARACTER_MENU,{{labelX,labelY},{29,16}},slotNames[i],{0.5,1},ComponentAttr::SHADOW);
equipmentSlot->I(Attribute::EQUIP_TYPE)=int(slot);
equipmentSlot->I(Attribute::INDEXED_THEME)=i;
@ -228,4 +228,11 @@ void Menu::InitializeCharacterMenuWindow(){
MenuComponent*backButton=NEW MenuComponent(CHARACTER_MENU,{{windowSize.x/2-64,windowSize.y},{128,12}},"Back",[](MenuFuncData data){Menu::stack.pop_back();return true;});
backButton->decal=true;
characterMenuWindow->AddComponent("Back button",backButton);
MenuLabel*itemNameDisplay=NEW MenuLabel(CHARACTER_MENU,{{32,windowSize.y-32},{windowSize.x-64,12}},"",1,ComponentAttr::BACKGROUND|ComponentAttr::LEFT_ALIGN|ComponentAttr::OUTLINE|ComponentAttr::SHADOW);
itemNameDisplay->decal=true;
MenuLabel*itemDescriptionDisplay=NEW MenuLabel(CHARACTER_MENU,{{32,windowSize.y-20},{windowSize.x-64,32}},"",1,ComponentAttr::BACKGROUND|ComponentAttr::LEFT_ALIGN|ComponentAttr::OUTLINE|ComponentAttr::SHADOW);
itemDescriptionDisplay->decal=true;
characterMenuWindow->AddComponent("Item Name",itemNameDisplay);
characterMenuWindow->AddComponent("Item Description",itemDescriptionDisplay);
}

@ -127,8 +127,8 @@ void Menu::InitializeClassSelectionWindow(){
return true;
});
classSprite->S(A::CLASS_SELECTION)=classButton->S(A::CLASS_SELECTION)=className;
classSelectionWindow->AddComponent(className+" Button",classButton);
classSelectionWindow->AddComponent(className+" Background",backgroundOutline);
classSelectionWindow->AddComponent(className+" Button",classButton);
classSelectionWindow->AddComponent(className+" Label",classLabel);
classSelectionWindow->AddComponent(className+" Icon",classSprite);
}

@ -47,8 +47,8 @@ class EquipSlotButton:public MenuItemItemButton{
private:
EquipSlot slot;
public:
inline EquipSlotButton(MenuType parent,geom2d::rect<float>rect,EquipSlot slot,MenuType menuDest,MenuFunc onClick,MenuFunc onHover,MenuFunc onMouseOut)
:MenuItemItemButton(parent,rect,Item::BLANK,menuDest,onClick,onHover,onMouseOut),slot(slot){}
inline EquipSlotButton(MenuType parent,geom2d::rect<float>rect,EquipSlot slot,MenuType menuDest,MenuFunc onClick,MenuFunc onHover,MenuFunc onMouseOut,std::string itemNameLabelName="",std::string itemDescriptionLabelName="")
:MenuItemItemButton(parent,rect,Item::BLANK,menuDest,onClick,onHover,onMouseOut,itemNameLabelName,itemDescriptionLabelName),slot(slot){}
inline void OnEquipStatsUpdate()override{
Item&equip=*Inventory::GetEquip(slot);
if(!equip.IsBlank()){

@ -177,7 +177,7 @@ void ItemInfo::InitializeItems(){
props.customProps=&data[key];
}
it.useFunc=scriptName;
}
}
};
ReadItems(DATA["ItemDatabase"]);
@ -187,6 +187,10 @@ void ItemInfo::InitializeItems(){
ITEM_CATEGORIES.SetInitialized();
Menu::inventoryListeners.SetInitialized();
for(auto&[name,info]:ITEM_DATA){
if(info.description.length()==0)ERR("WARNING! Item "<<info.name<<" does not have a description!");
}
std::cout<<ITEM_DATA.size()<<" items have been loaded."<<std::endl;
std::cout<<ITEM_CATEGORIES.size()<<" item categories have been loaded."<<std::endl;
}
@ -474,7 +478,7 @@ const Stats&EnhancementInfo::operator[](int level)const{
return enhancementStats[level];
}
const std::optional<const ItemSet const*>ItemInfo::ItemSet()const{
const std::optional<const ItemSet *const>ItemInfo::ItemSet()const{
if(ItemSet::sets.count(set)){
return &ItemSet::sets[set];
}
@ -565,6 +569,6 @@ const size_t EnhancementInfo::size()const{
return enhancementStats.size();
};
const std::optional<const ItemSet const*>Item::ItemSet()const{
const const const std::optional<const const const ItemSet const const const*const const const>Item::ItemSet()const const const{ //I was bored, okay?
return it->ItemSet();
};

@ -133,7 +133,7 @@ public:
bool IsBlank();
static Item BLANK;
bool operator==(const Item&rhs)const;
const std::optional<const ItemSet const*>ItemSet()const;
const std::optional<const ItemSet *const>ItemSet()const;
};
class Inventory{
@ -219,7 +219,7 @@ public:
float CastTime();
float CooldownTime();
EquipSlot Slot();
const std::optional<const ItemSet const*>ItemSet()const;
const std::optional<const ItemSet *const>ItemSet()const;
};
class ItemOverlay{

@ -57,9 +57,9 @@ void Menu::InitializeItemLoadoutWindow(){
float buttonBorderPadding=64;
MenuItemItemButton*loadoutItem1=NEW MenuItemItemButton(ITEM_LOADOUT,{{64,96},{48,48}},game->GetLoadoutItem(0),INVENTORY,[](MenuFuncData data){Menu::menus.at(INVENTORY)->I(A::LOADOUT_SLOT)=0; return true;},ITEM_LOADOUT,"Item Name Label","Item Description");
MenuItemItemButton*loadoutItem2=NEW MenuItemItemButton(ITEM_LOADOUT,{{itemLoadoutWindowWidth/2-24,96},{48,48}},game->GetLoadoutItem(1),INVENTORY,[](MenuFuncData data){Menu::menus.at(INVENTORY)->I(A::LOADOUT_SLOT)=1;return true;},ITEM_LOADOUT,"Item Name Label","Item Description");
MenuItemItemButton*loadoutItem3=NEW MenuItemItemButton(ITEM_LOADOUT,{{itemLoadoutWindowWidth-48-64,96},{48,48}},game->GetLoadoutItem(2),INVENTORY,[](MenuFuncData data){Menu::menus.at(INVENTORY)->I(A::LOADOUT_SLOT)=2;return true;},ITEM_LOADOUT,"Item Name Label","Item Description");
MenuItemItemButton*loadoutItem1=NEW MenuItemItemButton(ITEM_LOADOUT,{{64,96},{48,48}},game->GetLoadoutItem(0),INVENTORY,[](MenuFuncData data){Menu::menus.at(INVENTORY)->I(A::LOADOUT_SLOT)=0; return true;},"Item Name Label","Item Description");
MenuItemItemButton*loadoutItem2=NEW MenuItemItemButton(ITEM_LOADOUT,{{itemLoadoutWindowWidth/2-24,96},{48,48}},game->GetLoadoutItem(1),INVENTORY,[](MenuFuncData data){Menu::menus.at(INVENTORY)->I(A::LOADOUT_SLOT)=1;return true;},"Item Name Label","Item Description");
MenuItemItemButton*loadoutItem3=NEW MenuItemItemButton(ITEM_LOADOUT,{{itemLoadoutWindowWidth-48-64,96},{48,48}},game->GetLoadoutItem(2),INVENTORY,[](MenuFuncData data){Menu::menus.at(INVENTORY)->I(A::LOADOUT_SLOT)=2;return true;},"Item Name Label","Item Description");
//TODO: Make these two do something.
MenuLabel*itemNameLabel=NEW MenuLabel(ITEM_LOADOUT,{{0,158},{itemLoadoutWindowWidth,12}},"",1,ComponentAttr::SHADOW);

@ -132,7 +132,12 @@ Menu*Menu::CreateMenu(MenuType type,vf2d pos,vf2d size){
return menus.at(type);
}
void Menu::AddComponent(std::string key,MenuComponent*button){
void Menu::AddComponent(std::string key,MenuComponent*button,int depth){
if(depth==DEFAULT_DEPTH){
button->depth=STARTING_DEPTH-componentCount;
}else{
button->depth=depth;
}
if(button->selectable){
buttons.Unlock();
if(buttons.count(int(button->rect.pos.y))){
@ -165,6 +170,9 @@ void Menu::AddComponent(std::string key,MenuComponent*button){
}else{
displayComponents.push_back(button);
}
RecalculateComponentCount();
if(components.count(key)){
ERR("WARNING! Key "<<key<<" for this sub-menu already exists! Key names must be unique!")
}
@ -329,18 +337,16 @@ void Menu::Draw(Crawler*game){
Pixel::Mode prevMode=game->GetPixelMode();
game->SetPixelMode(Pixel::MASK);
game->Clear(BLANK);
for(auto&component:displayComponents){
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);
}
}
for(auto&[key,value]:buttons){
for(auto&button:value){
if(button->renderInMain){
button->_Draw(game);
}
}
}
game->SetPixelMode(prevMode);
game->SetDrawTarget(nullptr);
@ -352,18 +358,11 @@ void Menu::Draw(Crawler*game){
r.Decal()->Update();
game->DrawDecal(pos,r.Decal());
for(auto&component:displayComponents){
for(const auto&component:allComponents){
if(component->renderInMain){
component->_DrawDecal(game,this==Menu::stack.back());
}
}
for(auto&[key,value]:buttons){
for(auto&button:value){
if(button->renderInMain){
button->_DrawDecal(game,this==Menu::stack.back());
}
}
}
if(draggingComponent!=nullptr){
game->SetDrawTarget(overlay.Sprite());
@ -738,3 +737,8 @@ void Menu::DrawThemedWindow(vf2d menuPos,vf2d size,Pixel renderColor){
DrawTiledWindowBorder(game,menuPos,size,renderColor);
}
}
void Menu::RecalculateComponentCount(){
componentCount=displayComponents.size()+buttons.size();
}

@ -47,6 +47,9 @@ class Crawler;
class MenuComponent;
class ScrollableWindowComponent;
#define DEFAULT_DEPTH -999999
#define STARTING_DEPTH 999999
enum MenuType{
TEST,
TEST_2,
@ -73,6 +76,7 @@ class Menu:public IAttributable{
float buttonHoldTime=0;
vi2d selection={-1,-1};
vi2d lastActiveMousePos={};
int componentCount;
MenuComponent*draggingComponent=nullptr;
Renderable r,overlay;
@ -82,7 +86,7 @@ public:
//The constructor is private. Use CreateMenu() instead!
Menu()=default;
~Menu();
void AddComponent(std::string key,MenuComponent*button);
void AddComponent(std::string key,MenuComponent*button,int depth=DEFAULT_DEPTH);
void Update(Crawler*game);
void Draw(Crawler*game);
static void InitializeMenus();
@ -119,6 +123,7 @@ public:
//X (0-2), Y (0-2) for specific 9-patch tile (tiled version).
static Renderable&GetPatchPart(int x,int y);
void RecalculateComponentCount();
private:
Menu(vf2d pos,vf2d size);
static MenuType lastMenuTypeCreated;
@ -151,6 +156,7 @@ private:
bool HandleOutsideDisabledButtonSelection(MenuComponent*disabledButton);
Pixel GetRenderColor();
static bool MOUSE_NAVIGATION;
bool cover; //A black cover for when a menu pops up to fade out the stuff behind it.
};

@ -70,6 +70,7 @@ private:
void _DrawDecal(Crawler*game,bool focused);
void _DrawDecal(Crawler*game,vf2d parentPos,bool focused);
protected:
int depth=0;
float hoverEffect=0;
std::string name="";
geom2d::rect<float>rect;

@ -52,7 +52,6 @@ INCLUDE_ITEM_DATA
class MenuItemItemButton:public MenuIconButton{
private:
std::reference_wrapper<Item>itemRef;
MenuType itemDescriptionMenu;
std::string itemNameLabelName;
std::string itemDescriptionLabelName;
bool runHoverFunctions=false;
@ -62,13 +61,13 @@ private:
bool selected=false;
bool hideQty=false;
public:
inline MenuItemItemButton(MenuType parent,geom2d::rect<float>rect,Item&itemRef,MenuType menuDest,MenuFunc onClick,MenuType itemDescriptionMenu,std::string itemNameLabelName,std::string itemDescriptionLabelName)
:MenuIconButton(parent,rect,(!itemRef.IsBlank())?itemRef.Decal():nullptr,menuDest,onClick),itemRef(itemRef),itemDescriptionMenu(itemDescriptionMenu),itemNameLabelName(itemNameLabelName),itemDescriptionLabelName(itemDescriptionLabelName),onHover(DO_NOTHING){
inline MenuItemItemButton(MenuType parent,geom2d::rect<float>rect,Item&itemRef,MenuType menuDest,MenuFunc onClick,std::string itemNameLabelName,std::string itemDescriptionLabelName)
:MenuIconButton(parent,rect,(!itemRef.IsBlank())?itemRef.Decal():nullptr,menuDest,onClick),itemRef(itemRef),itemNameLabelName(itemNameLabelName),itemDescriptionLabelName(itemDescriptionLabelName),onHover(DO_NOTHING){
draggable=false;
valid=!itemRef.IsBlank();
}
inline MenuItemItemButton(MenuType parent,geom2d::rect<float>rect,Item&itemRef,MenuType menuDest,MenuFunc onClick,MenuFunc onHover,MenuFunc onMouseOut)
:MenuIconButton(parent,rect,(!itemRef.IsBlank())?itemRef.Decal():nullptr,menuDest,onClick),itemRef(itemRef),itemDescriptionMenu(MenuType::ENUM_END),itemNameLabelName(""),itemDescriptionLabelName(""),onHover(onHover),onMouseOut(onMouseOut){
inline MenuItemItemButton(MenuType parent,geom2d::rect<float>rect,Item&itemRef,MenuType menuDest,MenuFunc onClick,MenuFunc onHover,MenuFunc onMouseOut,std::string itemNameLabelName="",std::string itemDescriptionLabelName="")
:MenuIconButton(parent,rect,(!itemRef.IsBlank())?itemRef.Decal():nullptr,menuDest,onClick),itemRef(itemRef),itemNameLabelName(itemNameLabelName),itemDescriptionLabelName(itemDescriptionLabelName),onHover(onHover),onMouseOut(onMouseOut){
runHoverFunctions=true;
draggable=false;
valid=!itemRef.IsBlank();
@ -89,9 +88,23 @@ protected:
virtual inline void BeforeUpdate(Crawler*game)override{
if(!hovered&&runHoverFunctions&&hoverState){
hoverState=false;
if(itemNameLabelName!=""){
Component<MenuLabel>(parentMenu,itemNameLabelName)->Enable(false);
}
if(itemDescriptionLabelName!=""){
Component<MenuLabel>(parentMenu,itemDescriptionLabelName)->Enable(false);
}
onMouseOut(MenuFuncData{*Menu::menus[parentMenu],game,this,(ScrollableWindowComponent*)(parentComponent)});
}
}
virtual inline void AfterCreate()override{
if(itemNameLabelName!=""){
Component<MenuLabel>(parentMenu,itemNameLabelName)->Enable(false);
}
if(itemDescriptionLabelName!=""){
Component<MenuLabel>(parentMenu,itemDescriptionLabelName)->Enable(false);
}
}
virtual inline void Update(Crawler*game)override{
MenuIconButton::Update(game);
valid=!itemRef.get().IsBlank();
@ -108,12 +121,20 @@ protected:
}
if(hovered){
if(itemDescriptionMenu!=MenuType::ENUM_END){
Component<MenuLabel>(itemDescriptionMenu,itemNameLabelName)->label=labelNameText;
Component<MenuLabel>(itemDescriptionMenu,itemDescriptionLabelName)->label=labelDescriptionText;
if(itemNameLabelName!=""){
Component<MenuLabel>(parentMenu,itemNameLabelName)->label=labelNameText;
}
if(itemDescriptionLabelName!=""){
Component<MenuLabel>(parentMenu,itemDescriptionLabelName)->label=labelDescriptionText;
}
if(runHoverFunctions&&!hoverState){
hoverState=true;
if(itemNameLabelName!=""&&labelNameText.length()>0){
Component<MenuLabel>(parentMenu,itemNameLabelName)->Enable(true);
}
if(itemDescriptionLabelName!=""&&labelDescriptionText.length()>0){
Component<MenuLabel>(parentMenu,itemDescriptionLabelName)->Enable(true);
}
onHover(MenuFuncData{*Menu::menus[parentMenu],game,this,(ScrollableWindowComponent*)(parentComponent)});
}
}

@ -67,8 +67,8 @@ public:
upButton=NEW MenuComponent(parentMenu,{rect.pos+vf2d{rect.size.x-12,0},{12,12}},"^",[&](MenuFuncData dat){V(A::SCROLL_OFFSET).y+="ThemeGlobal.MenuButtonScrollSpeed"_I;return true;},ButtonAttr::UNSELECTABLE_VIA_KEYBOARD);
downButton=NEW MenuComponent(parentMenu,{rect.pos+rect.size-vf2d{12,12},{12,12}},"v",[&](MenuFuncData dat){V(A::SCROLL_OFFSET).y-="ThemeGlobal.MenuButtonScrollSpeed"_I;return true;},ButtonAttr::UNSELECTABLE_VIA_KEYBOARD);
//Let's use the internal name of this component to add unique names for sub-components.
Menu::menus[parentMenu]->AddComponent(name+upButton->rect.pos.str()+"_"+upButton->rect.size.str(),upButton);
Menu::menus[parentMenu]->AddComponent(name+downButton->rect.pos.str()+"_"+downButton->rect.size.str(),downButton);
Menu::menus[parentMenu]->AddComponent(name+upButton->rect.pos.str()+"_"+upButton->rect.size.str(),upButton,-1);
Menu::menus[parentMenu]->AddComponent(name+downButton->rect.pos.str()+"_"+downButton->rect.size.str(),downButton,-1);
}
virtual inline void RemoveAllComponents(){
while(components.size()>0){
@ -96,6 +96,7 @@ public:
}
Menu::menus[button->parentMenu]->components.erase(button->GetName());
components.erase(std::find(components.begin(),components.end(),button));
Menu::menus[button->parentMenu]->RecalculateComponentCount();
delete button;
}
protected:
@ -148,7 +149,8 @@ protected:
}else{
V(A::SCROLL_OFFSET).y=0;
}
std::sort(components.begin(),components.end(),[](MenuComponent*c1,MenuComponent*c2){return c1->depth>c2->depth;});
for(MenuComponent*component:components){
component->disabled=!OnScreen(component);
component->_Update(game);

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

Loading…
Cancel
Save