From e744112206f7e13b4f358510c887ef1421ed33b9 Mon Sep 17 00:00:00 2001 From: sigonasr2 Date: Sun, 10 Dec 2023 19:14:37 -0600 Subject: [PATCH] GUI template/macro usage refactor. --- Crawler/CREDITS | 3 + Crawler/CharacterAbilityPreviewComponent.h | 4 +- Crawler/CharacterInfoWindow.cpp | 36 +-- Crawler/CharacterMenuWindow.cpp | 276 ++++++++---------- Crawler/CharacterRotatingDisplay.h | 4 +- Crawler/ClassSelectionWindow.cpp | 49 ++-- Crawler/Crawler.cpp | 6 +- Crawler/Crawler.vcxproj | 6 +- Crawler/Crawler.vcxproj.filters | 9 +- ...untersSpawnListScrollableWindowComponent.h | 7 +- Crawler/EquipSlotButton.h | 4 +- Crawler/InventoryConsumableWindow.cpp | 22 +- Crawler/InventoryScrollableWindowComponent.h | 7 +- Crawler/{TestMenu.cpp => InventoryWindow.cpp} | 49 ++-- Crawler/ItemLoadoutWindow.cpp | 27 +- Crawler/LevelCompleteWindow.cpp | 48 +-- Crawler/Menu.cpp | 62 +--- Crawler/Menu.h | 98 ++++++- Crawler/MenuAnimatedIconButton.h | 4 +- Crawler/MenuAnimatedIconToggleButton.h | 4 +- Crawler/MenuComponent.cpp | 8 +- Crawler/MenuComponent.h | 4 +- Crawler/MenuIconButton.h | 8 +- Crawler/MenuItemButton.h | 6 +- Crawler/MenuItemItemButton.h | 8 +- Crawler/MenuLabel.h | 4 +- Crawler/OverworldMapLevelWindow.cpp | 27 +- Crawler/OverworldMenuWindow.cpp | 24 +- Crawler/PopupMenuLabel.h | 8 +- Crawler/ScrollableWindowComponent.h | 24 +- Crawler/SpawnEncounterLabel.h | 4 +- Crawler/StatLabel.h | 4 +- Crawler/TestSubMenu.cpp | 104 ------- Crawler/Version.h | 2 +- 34 files changed, 390 insertions(+), 570 deletions(-) rename Crawler/{TestMenu.cpp => InventoryWindow.cpp} (64%) delete mode 100644 Crawler/TestSubMenu.cpp diff --git a/Crawler/CREDITS b/Crawler/CREDITS index bb8b619a..4971096a 100644 --- a/Crawler/CREDITS +++ b/Crawler/CREDITS @@ -1,3 +1,6 @@ +The inspiration that started it all, Pokemon-based Nico Yazawa sprite: +https://www.deviantart.com/kirbysmith/art/Nico-Yazawa-Love-Live-Pokemon-Sprites-548007023 + *** Minifantasy - Tiny Overworld v1.0 *** Minifantasy is an original idea by Krishna Palacio diff --git a/Crawler/CharacterAbilityPreviewComponent.h b/Crawler/CharacterAbilityPreviewComponent.h index 3677f76d..9abc43fc 100644 --- a/Crawler/CharacterAbilityPreviewComponent.h +++ b/Crawler/CharacterAbilityPreviewComponent.h @@ -50,8 +50,8 @@ INCLUDE_GFX class CharacterAbilityPreviewComponent:public MenuLabel{ Ability*ability; public: - inline CharacterAbilityPreviewComponent(MenuType parent,geom2d::rectrect,Ability*ability) - :MenuLabel(parent,rect,"",1,ComponentAttr::OUTLINE|ComponentAttr::BACKGROUND),ability(ability){} + inline CharacterAbilityPreviewComponent(geom2d::rectrect,Ability*ability) + :MenuLabel(rect,"",1,ComponentAttr::OUTLINE|ComponentAttr::BACKGROUND),ability(ability){} protected: virtual void inline Update(Crawler*game)override{ MenuLabel::Update(game); diff --git a/Crawler/CharacterInfoWindow.cpp b/Crawler/CharacterInfoWindow.cpp index 2e18fc83..9af1b068 100644 --- a/Crawler/CharacterInfoWindow.cpp +++ b/Crawler/CharacterInfoWindow.cpp @@ -53,39 +53,23 @@ void Menu::InitializeClassInfoWindow(){ Menu*classSelectionWindow=Menu::menus[CLASS_SELECTION]; ClassInfo data=classutils::GetClassInfo(classSelectionWindow->S(A::CLASS_SELECTION)); - MenuLabel*label=NEW MenuLabel(CLASS_INFO,{{0,0},{classInfoWindow->size.x-1,24}},data.className,2,ComponentAttr::SHADOW|ComponentAttr::OUTLINE|ComponentAttr::BACKGROUND); + auto label=classInfoWindow->ADD("Class Name",MenuLabel)({{0,0},{classInfoWindow->size.x-1,24}},data.className,2,ComponentAttr::SHADOW|ComponentAttr::OUTLINE|ComponentAttr::BACKGROUND)END; - classInfoWindow->AddComponent("Class Name",label); - - CharacterRotatingDisplay*classDisplay=NEW CharacterRotatingDisplay(CLASS_INFO,{{15,48},{72,120}},GFX[data.classFullImgName].Decal()); - - classInfoWindow->AddComponent("Rotating Character Display",classDisplay); + classInfoWindow->ADD("Rotating Character Display",CharacterRotatingDisplay)({{15,48},{72,120}},GFX[data.classFullImgName].Decal())END; vf2d healthDisplayLabelPos={classInfoWindow->size.x/3,label->GetPos().y+24}; vf2d labelSize={2*classInfoWindow->size.x/3-1,16}; - MenuLabel*baseStatsLabel=NEW MenuLabel(CLASS_INFO,{{0,label->GetPos().y+24},{classInfoWindow->size.x/3,labelSize.y}},"Base Stats",1,ComponentAttr::SHADOW|ComponentAttr::OUTLINE); - - MenuLabel*healthDisplayLabel=NEW MenuLabel(CLASS_INFO,{healthDisplayLabelPos+vf2d{0,16*0},labelSize},"Health: "+std::to_string(data.baseHealth)+" + "+std::to_string(data.healthGrowthRate).substr(0,3)+" per level",1,ComponentAttr::LEFT_ALIGN|ComponentAttr::SHADOW|ComponentAttr::OUTLINE); - MenuLabel*atkDisplayLabel=NEW MenuLabel(CLASS_INFO,{healthDisplayLabelPos+vf2d{0,16*1},labelSize},"Attack: "+std::to_string(data.baseAtk)+" + "+std::to_string(data.atkGrowthRate).substr(0,3)+" per level",1,ComponentAttr::LEFT_ALIGN|ComponentAttr::SHADOW|ComponentAttr::OUTLINE); - - classInfoWindow->AddComponent("Base Stats Text",baseStatsLabel); - classInfoWindow->AddComponent("Health Display Text",healthDisplayLabel); - classInfoWindow->AddComponent("Attack Display Text",atkDisplayLabel); + classInfoWindow->ADD("Base Stats Text",MenuLabel)({{0,label->GetPos().y+24},{classInfoWindow->size.x/3,labelSize.y}},"Base Stats",1,ComponentAttr::SHADOW|ComponentAttr::OUTLINE)END; + classInfoWindow->ADD("Health Display Text",MenuLabel)({healthDisplayLabelPos+vf2d{0,16*0},labelSize},"Health: "+std::to_string(data.baseHealth)+" + "+std::to_string(data.healthGrowthRate).substr(0,3)+" per level",1,ComponentAttr::LEFT_ALIGN|ComponentAttr::SHADOW|ComponentAttr::OUTLINE)END; + classInfoWindow->ADD("Attack Display Text",MenuLabel)({healthDisplayLabelPos+vf2d{0,16*1},labelSize},"Attack: "+std::to_string(data.baseAtk)+" + "+std::to_string(data.atkGrowthRate).substr(0,3)+" per level",1,ComponentAttr::LEFT_ALIGN|ComponentAttr::SHADOW|ComponentAttr::OUTLINE)END; vf2d abilityIconOffsets = {0,32}; - CharacterAbilityPreviewComponent*ability1=NEW CharacterAbilityPreviewComponent(CLASS_INFO,{healthDisplayLabelPos+vf2d{0,32*0}+abilityIconOffsets,labelSize*vf2d{1,2}},data.ability1); - CharacterAbilityPreviewComponent*ability2=NEW CharacterAbilityPreviewComponent(CLASS_INFO,{healthDisplayLabelPos+vf2d{0,32*1}+abilityIconOffsets,labelSize*vf2d{1,2}},data.ability2); - CharacterAbilityPreviewComponent*ability3=NEW CharacterAbilityPreviewComponent(CLASS_INFO,{healthDisplayLabelPos+vf2d{0,32*2}+abilityIconOffsets,labelSize*vf2d{1,2}},data.ability3); - CharacterAbilityPreviewComponent*rightClickAbility=NEW CharacterAbilityPreviewComponent(CLASS_INFO,{healthDisplayLabelPos+vf2d{0,32*3}+abilityIconOffsets,labelSize*vf2d{1,2}},data.rightClickAbility); - - classInfoWindow->AddComponent("Ability 1 Display",ability1); - classInfoWindow->AddComponent("Ability 2 Display",ability2); - classInfoWindow->AddComponent("Ability 3 Display",ability3); - classInfoWindow->AddComponent("Right Click Ability Display",rightClickAbility); - - MenuComponent*backButton=NEW MenuComponent(CLASS_INFO,{{classInfoWindow->center().x/2,healthDisplayLabelPos.y+32*4+abilityIconOffsets.y+12},{classInfoWindow->size.x/2,16}},"Back",[](MenuFuncData data){Menu::CloseMenu();return true;}); + classInfoWindow->ADD("Ability 1 Display",CharacterAbilityPreviewComponent)({healthDisplayLabelPos+vf2d{0,32*0}+abilityIconOffsets,labelSize*vf2d{1,2}},data.ability1)END; + classInfoWindow->ADD("Ability 2 Display",CharacterAbilityPreviewComponent)({healthDisplayLabelPos+vf2d{0,32*1}+abilityIconOffsets,labelSize*vf2d{1,2}},data.ability2)END; + classInfoWindow->ADD("Ability 3 Display",CharacterAbilityPreviewComponent)({healthDisplayLabelPos+vf2d{0,32*2}+abilityIconOffsets,labelSize*vf2d{1,2}},data.ability3)END; + classInfoWindow->ADD("Right Click Ability Display",CharacterAbilityPreviewComponent)({healthDisplayLabelPos+vf2d{0,32*3}+abilityIconOffsets,labelSize*vf2d{1,2}},data.rightClickAbility)END; - classInfoWindow->AddComponent("Back Button",backButton); + classInfoWindow->ADD("Back Button",MenuComponent)({{classInfoWindow->center().x/2,healthDisplayLabelPos.y+32*4+abilityIconOffsets.y+12},{classInfoWindow->size.x/2,16}},"Back",[](MenuFuncData data){Menu::CloseMenu();return true;})END; } \ No newline at end of file diff --git a/Crawler/CharacterMenuWindow.cpp b/Crawler/CharacterMenuWindow.cpp index 07bc5444..7457b226 100644 --- a/Crawler/CharacterMenuWindow.cpp +++ b/Crawler/CharacterMenuWindow.cpp @@ -56,15 +56,10 @@ void Menu::InitializeCharacterMenuWindow(){ vf2d windowSize=game->GetScreenSize()-vf2d{52,52}; Menu*characterMenuWindow=CreateMenu(CHARACTER_MENU,CENTERED,windowSize); - MenuLabel*characterLabel=NEW MenuLabel(CHARACTER_MENU,{{0,-4},{float(windowSize.x)-1,24}},"Character",2,ComponentAttr::SHADOW|ComponentAttr::OUTLINE|ComponentAttr::BACKGROUND); - characterLabel->decal=true; - - MenuComponent*equipSlotOutline=NEW MenuComponent(CHARACTER_MENU,{{0,28},{120,windowSize.y-37}},"",DO_NOTHING,ButtonAttr::UNSELECTABLE); - CharacterRotatingDisplay*charDisplay=NEW CharacterRotatingDisplay(CHARACTER_MENU,{{135,28},{90,windowSize.y-37}},GFX[classutils::GetClassInfo(game->GetPlayer()->GetClassName()).classFullImgName].Decal()); - - characterMenuWindow->AddComponent("Character Label",characterLabel); - characterMenuWindow->AddComponent("Equip Slot Outline",equipSlotOutline); - characterMenuWindow->AddComponent("Character Rotating Display",charDisplay); + 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("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; const static std::arraydisplayAttrs{ ItemAttribute::health, @@ -76,33 +71,31 @@ void Menu::InitializeCharacterMenuWindow(){ ItemAttribute::critDmgPct, }; - MenuComponent*equipSelectionOutline=NEW MenuComponent(CHARACTER_MENU,{{123,28},{120,windowSize.y-37}},"",DO_NOTHING,ButtonAttr::UNSELECTABLE); - ScrollableWindowComponent*equipmentList=NEW ScrollableWindowComponent(CHARACTER_MENU,{{123,28},{120,windowSize.y-37-24}}); - MenuComponent*equipSelectionBottomOutline=NEW MenuComponent(CHARACTER_MENU,{{123,28+(windowSize.y-37-24)},{120,24}},"",DO_NOTHING,ButtonAttr::UNSELECTABLE); - MenuComponent*equipSelectionSelectButton=NEW MenuComponent(CHARACTER_MENU,{{123+12,28+(windowSize.y-37-24)+6},{96,12}},"Select",[](MenuFuncData data){ - Component(data.component->parentMenu,"Equip Selection Outline")->Enable(false); - Component(data.component->parentMenu,"Equip List")->Enable(false); - Component(data.component->parentMenu,"Equip Selection Bottom Outline")->Enable(false); - Component(data.component->parentMenu,"Equip Selection Select Button")->Enable(false); - Component(data.component->parentMenu,"Character Rotating Display")->Enable(true); - for(int counter=0;ItemAttribute attribute:displayAttrs){ - StatLabel*statDisplayLabel=Component(CHARACTER_MENU,"Attribute "+ItemAttributable::GetDisplayInfo(attribute).name+" Label"); - statDisplayLabel->SetStatChangeAmt(0); - } - equipmentWindowOpened=false; - return true; - }); - equipSelectionSelectButton->decal=true; - equipSelectionOutline->Enable(false); - equipmentList->Enable(false); - equipSelectionBottomOutline->Enable(false); - equipSelectionSelectButton->Enable(false); + characterMenuWindow->ADD("Equip Selection Outline",MenuComponent)({{123,28},{120,windowSize.y-37}},"",DO_NOTHING,ButtonAttr::UNSELECTABLE)END + ->Enable(false); + characterMenuWindow->ADD("Equip List",ScrollableWindowComponent)({{123,28},{120,windowSize.y-37-24}})DEPTH -1 END + ->Enable(false); + characterMenuWindow->ADD("Equip Selection Bottom Outline",MenuComponent)({{123,28+(windowSize.y-37-24)},{120,24}},"",DO_NOTHING,ButtonAttr::UNSELECTABLE)END + ->Enable(false); + auto equipSelectionSelectButton=characterMenuWindow->ADD("Equip Selection Select Button",MenuComponent)({{123+12,28+(windowSize.y-37-24)+6},{96,12}},"Select", + [](MenuFuncData data){ + Component(data.component->parentMenu,"Equip Selection Outline")->Enable(false); + Component(data.component->parentMenu,"Equip List")->Enable(false); + Component(data.component->parentMenu,"Equip Selection Bottom Outline")->Enable(false); + Component(data.component->parentMenu,"Equip Selection Select Button")->Enable(false); + Component(data.component->parentMenu,"Character Rotating Display")->Enable(true); + for(int counter=0;ItemAttribute attribute:displayAttrs){ + StatLabel*statDisplayLabel=Component(CHARACTER_MENU,"Attribute "+ItemAttributable::GetDisplayInfo(attribute).name+" Label"); + statDisplayLabel->SetStatChangeAmt(0); + } + equipmentWindowOpened=false; + return true; + })END; - characterMenuWindow->AddComponent("Equip Selection Outline",equipSelectionOutline); - characterMenuWindow->AddComponent("Equip List",equipmentList,-1); - characterMenuWindow->AddComponent("Equip Selection Bottom Outline",equipSelectionBottomOutline); - characterMenuWindow->AddComponent("Equip Selection Select Button",equipSelectionSelectButton); + + equipSelectionSelectButton->decal=true; + equipSelectionSelectButton->Enable(false); const static auto GetLabelText=[](ItemAttribute attribute){ AttributeData data=ItemAttributable::GetDisplayInfo(attribute); @@ -126,139 +119,128 @@ void Menu::InitializeCharacterMenuWindow(){ } const static std::arrayslotNames{"Helmet","Weapon","Armor","Gloves","Pants","Shoes","Ring 1","Ring 2"}; EquipSlot slot=EquipSlot(equipSlot); - - EquipSlotButton*equipmentSlot=NEW EquipSlotButton(CHARACTER_MENU,{{x,y+28},{24,24}},slot,MenuType::ENUM_END, - [&](MenuFuncData data){ - EquipSlot slot=EquipSlot(data.component->I(Attribute::EQUIP_TYPE)); - - std::vector&equips=Inventory::get("Equipment"); - std::vector&accessories=Inventory::get("Accessories"); - std::vectoravailableEquipment; - std::copy_if(equips.begin(),equips.end(),std::back_inserter(availableEquipment),[&](Item&it){ - return it.GetEquipSlot()&slot; - }); - std::copy_if(accessories.begin(),accessories.end(),std::back_inserter(availableEquipment),[&](Item&it){ - return it.GetEquipSlot()&slot; - }); - - ScrollableWindowComponent*equipList=Component(data.component->parentMenu,"Equip List"); - equipList->RemoveAllComponents(); - for(int counter=0;Item&it:availableEquipment){ - float xOffset=(counter%3)*26; - Item&itemInvRef=Inventory::GetItem(it.Name()); - MenuItemItemButton*equip=NEW MenuItemItemButton(CHARACTER_MENU,{{2+xOffset,2},{24,24}},itemInvRef,MenuType::ENUM_END,[](MenuFuncData data){ - MenuItemItemButton*comp=(MenuItemItemButton*)data.component; - Inventory::EquipItem(comp->GetItem(),EquipSlot(comp->I(Attribute::EQUIP_TYPE))); - for(MenuComponent*button:((ScrollableWindowComponent*)data.parentComponent)->GetComponents()){ - MenuItemItemButton*comp=(MenuItemItemButton*)button; - comp->SetSelected(false); - } - comp->SetSelected(true); - for(int counter=0;ItemAttribute attribute:displayAttrs){ - StatLabel*statDisplayLabel=Component(CHARACTER_MENU,"Attribute "+ItemAttributable::GetDisplayInfo(attribute).name+" Label"); - statDisplayLabel->SetStatChangeAmt(0); + auto equipmentSlot=characterMenuWindow->ADD("Equip Slot "+slotNames[i],EquipSlotButton)({{x,y+28},{24,24}},slot,MenuType::ENUM_END, + [&](MenuFuncData data){ + EquipSlot slot=EquipSlot(data.component->I(Attribute::EQUIP_TYPE)); + + std::vector&equips=Inventory::get("Equipment"); + std::vector&accessories=Inventory::get("Accessories"); + std::vectoravailableEquipment; + std::copy_if(equips.begin(),equips.end(),std::back_inserter(availableEquipment),[&](Item&it){ + return it.GetEquipSlot()&slot; + }); + std::copy_if(accessories.begin(),accessories.end(),std::back_inserter(availableEquipment),[&](Item&it){ + return it.GetEquipSlot()&slot; + }); + + ScrollableWindowComponent*equipList=Component(data.component->parentMenu,"Equip List"); + equipList->RemoveAllComponents(); + for(int counter=0;Item&it:availableEquipment){ + float xOffset=(counter%3)*26; + Item&itemInvRef=Inventory::GetItem(it.Name()); + auto equip=equipList->ADD("Equip Item "+std::to_string(counter),MenuItemItemButton)({{2+xOffset,2},{24,24}},itemInvRef,MenuType::ENUM_END, + [](MenuFuncData data){ + MenuItemItemButton*comp=(MenuItemItemButton*)data.component; + Inventory::EquipItem(comp->GetItem(),EquipSlot(comp->I(Attribute::EQUIP_TYPE))); + for(MenuComponent*button:((ScrollableWindowComponent*)data.parentComponent)->GetComponents()){ + MenuItemItemButton*comp=(MenuItemItemButton*)button; + comp->SetSelected(false); + } + comp->SetSelected(true); + for(int counter=0;ItemAttribute attribute:displayAttrs){ + StatLabel*statDisplayLabel=Component(CHARACTER_MENU,"Attribute "+ItemAttributable::GetDisplayInfo(attribute).name+" Label"); + statDisplayLabel->SetStatChangeAmt(0); + } + MenuItemItemButton*equipButton=Component(CHARACTER_MENU,"Equip Slot "+slotNames[data.parentComponent->I(A::INDEXED_THEME)]); + equipButton->SetItem(comp->GetItem()); + return true; + },[&](MenuFuncData data){ + MenuItemItemButton*button=(MenuItemItemButton*)data.component; + Item&buttonItem=button->GetItem(); + std::vectorstatsBeforeEquip; + EquipSlot slot=EquipSlot(button->I(Attribute::EQUIP_TYPE)); + for(ItemAttribute attribute:displayAttrs){ + statsBeforeEquip.push_back(game->GetPlayer()->GetStat(attribute)); + } + Item*equippedItem=Inventory::GetEquip(slot); + Inventory::EquipItem(buttonItem,slot); + for(int counter=0;ItemAttribute attribute:displayAttrs){ + StatLabel*statDisplayLabel=Component(CHARACTER_MENU,"Attribute "+ItemAttributable::GetDisplayInfo(attribute).name+" Label"); + int statChangeAmt=game->GetPlayer()->GetStat(attribute)-statsBeforeEquip[counter]; + statDisplayLabel->SetStatChangeAmt(statChangeAmt); + counter++; + } + Inventory::UnequipItem(slot); + if(*equippedItem!=Item::BLANK){ + Inventory::EquipItem(*equippedItem,slot); + } + return true; + },[](MenuFuncData data){ + for(int counter=0;ItemAttribute attribute:displayAttrs){ + StatLabel*statDisplayLabel=Component(CHARACTER_MENU,"Attribute "+ItemAttributable::GetDisplayInfo(attribute).name+" Label"); + statDisplayLabel->SetStatChangeAmt(0); + counter++; + } + return true; + },"Item Name","Item Description")END; + + equip->I(Attribute::EQUIP_TYPE)=int(slot); + if(Inventory::GetEquip(slot)==&itemInvRef){ + equip->SetSelected(true); } - MenuItemItemButton*equipButton=Component(CHARACTER_MENU,"Equip Slot "+slotNames[data.parentComponent->I(A::INDEXED_THEME)]); - equipButton->SetItem(comp->GetItem()); - return true; - },[&](MenuFuncData data){ - MenuItemItemButton*button=(MenuItemItemButton*)data.component; - Item&buttonItem=button->GetItem(); - std::vectorstatsBeforeEquip; - EquipSlot slot=EquipSlot(button->I(Attribute::EQUIP_TYPE)); - for(ItemAttribute attribute:displayAttrs){ - statsBeforeEquip.push_back(game->GetPlayer()->GetStat(attribute)); - } - Item*equippedItem=Inventory::GetEquip(slot); - Inventory::EquipItem(buttonItem,slot); - for(int counter=0;ItemAttribute attribute:displayAttrs){ - StatLabel*statDisplayLabel=Component(CHARACTER_MENU,"Attribute "+ItemAttributable::GetDisplayInfo(attribute).name+" Label"); - int statChangeAmt=game->GetPlayer()->GetStat(attribute)-statsBeforeEquip[counter]; - statDisplayLabel->SetStatChangeAmt(statChangeAmt); - counter++; - } - Inventory::UnequipItem(slot); - if(*equippedItem!=Item::BLANK){ - Inventory::EquipItem(*equippedItem,slot); - } - return true; - },[](MenuFuncData data){ - for(int counter=0;ItemAttribute attribute:displayAttrs){ - StatLabel*statDisplayLabel=Component(CHARACTER_MENU,"Attribute "+ItemAttributable::GetDisplayInfo(attribute).name+" Label"); - statDisplayLabel->SetStatChangeAmt(0); - counter++; - } - return true; - },"Item Name","Item Description"); - equip->I(Attribute::EQUIP_TYPE)=int(slot); - if(Inventory::GetEquip(slot)==&itemInvRef){ - equip->SetSelected(true); + equip->SetCompactDescriptions(false); + + counter++; } - equip->SetCompactDescriptions(false); - equipList->AddComponent(Menu::menus[CHARACTER_MENU],"Equip Item "+std::to_string(counter),equip); - counter++; - } - equipList->I(Attribute::INDEXED_THEME)=data.component->I(Attribute::INDEXED_THEME); - Component(data.component->parentMenu,"Equip Selection Outline")->Enable(true); - equipList->Enable(true); - Component(data.component->parentMenu,"Equip Selection Bottom Outline")->Enable(true); - Component(data.component->parentMenu,"Equip Selection Select Button")->Enable(true); - Component(data.component->parentMenu,"Character Rotating Display")->Enable(false); - equipmentWindowOpened=true; - return true; - },[](MenuFuncData data){//On Mouse Hover - if(Component(data.component->parentMenu,"Item Equip Description")->GetLabel()!=""){ + equipList->I(Attribute::INDEXED_THEME)=data.component->I(Attribute::INDEXED_THEME); + Component(data.component->parentMenu,"Equip Selection Outline")->Enable(true); + equipList->Enable(true); + Component(data.component->parentMenu,"Equip Selection Bottom Outline")->Enable(true); + Component(data.component->parentMenu,"Equip Selection Select Button")->Enable(true); Component(data.component->parentMenu,"Character Rotating Display")->Enable(false); - } - return true; - },[](MenuFuncData data){//On Mouse Out - if(Component(data.component->parentMenu,"Item Equip Description")->GetLabel()!=""&&!equipmentWindowOpened){ - Component(data.component->parentMenu,"Character Rotating Display")->Enable(true); - } - return true; - },"Item Equip Name","Item Equip Description"); - PopupMenuLabel*equipmentLabel=NEW PopupMenuLabel(CHARACTER_MENU,{{labelX,labelY},{29,16}},slotNames[i],{0.5,1},ComponentAttr::SHADOW); + equipmentWindowOpened=true; + return true; + },[](MenuFuncData data){//On Mouse Hover + if(Component(data.component->parentMenu,"Item Equip Description")->GetLabel()!=""){ + Component(data.component->parentMenu,"Character Rotating Display")->Enable(false); + } + return true; + },[](MenuFuncData data){//On Mouse Out + if(Component(data.component->parentMenu,"Item Equip Description")->GetLabel()!=""&&!equipmentWindowOpened){ + Component(data.component->parentMenu,"Character Rotating Display")->Enable(true); + } + return true; + },"Item Equip Name","Item Equip Description")END; + equipmentSlot->I(Attribute::EQUIP_TYPE)=int(slot); equipmentSlot->I(Attribute::INDEXED_THEME)=i; equipmentSlot->SetShowQuantity(false); equipmentSlot->SetCompactDescriptions(false); equipSlot<<=1; - characterMenuWindow->AddComponent("Equip Slot "+slotNames[i],equipmentSlot); - characterMenuWindow->AddComponent("Equip Label "+slotNames[i],equipmentLabel); + characterMenuWindow->ADD("Equip Label "+slotNames[i],PopupMenuLabel)({{labelX,labelY},{29,16}},slotNames[i],{0.5,1},ComponentAttr::SHADOW)END; Menu::AddEquipStatListener(equipmentSlot); } - MenuComponent*statDisplayOutline=NEW MenuComponent(CHARACTER_MENU,{{245,28},{62,windowSize.y-37}},"",DO_NOTHING,ButtonAttr::UNSELECTABLE); - - characterMenuWindow->AddComponent("Stat Display Outline",statDisplayOutline); + characterMenuWindow->ADD("Stat Display Outline",MenuComponent)({{245,28},{62,windowSize.y-37}},"",DO_NOTHING,ButtonAttr::UNSELECTABLE)END; int yOffset=0; for(ItemAttribute attribute:displayAttrs){ std::string attrStr=GetLabelText(attribute); - StatLabel*attrLabel=NEW StatLabel(CHARACTER_MENU,{{245,28+2+float(yOffset)},{62,18}},attribute,1,ComponentAttr::SHADOW|ComponentAttr::LEFT_ALIGN); - yOffset+=20; AttributeData data=ItemAttributable::GetDisplayInfo(attribute); - characterMenuWindow->AddComponent("Attribute "+data.name+" Label",attrLabel); + auto attrLabel=characterMenuWindow->ADD("Attribute "+data.name+" Label",StatLabel)({{245,28+2+float(yOffset)},{62,18}},attribute,1,ComponentAttr::SHADOW|ComponentAttr::LEFT_ALIGN)END; Menu::AddEquipStatListener(attrLabel); + yOffset+=20; } - 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); + 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; - MenuLabel*itemNameDisplay=NEW MenuLabel(CHARACTER_MENU,{{0,28},{120,12}},"",1,ComponentAttr::BACKGROUND|ComponentAttr::LEFT_ALIGN|ComponentAttr::OUTLINE|ComponentAttr::SHADOW); - MenuLabel*itemDescriptionDisplay=NEW MenuLabel(CHARACTER_MENU,{{0,40},{120,windowSize.y-49}},"",1,ComponentAttr::BACKGROUND|ComponentAttr::LEFT_ALIGN|ComponentAttr::OUTLINE|ComponentAttr::SHADOW); - - itemNameDisplay->decal=true; - itemDescriptionDisplay->decal=true; + 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); - - MenuLabel*itemNameDisplayEquip=NEW MenuLabel(CHARACTER_MENU,{{123,28},{120,12}},"",1,ComponentAttr::BACKGROUND|ComponentAttr::LEFT_ALIGN|ComponentAttr::OUTLINE|ComponentAttr::SHADOW); - MenuLabel*itemDescriptionDisplayEquip=NEW MenuLabel(CHARACTER_MENU,{{123,40},{120,windowSize.y-49}},"",1,ComponentAttr::BACKGROUND|ComponentAttr::LEFT_ALIGN|ComponentAttr::OUTLINE|ComponentAttr::SHADOW); - - characterMenuWindow->AddComponent("Item Name",itemNameDisplay); - characterMenuWindow->AddComponent("Item Description",itemDescriptionDisplay); - characterMenuWindow->AddComponent("Item Equip Name",itemNameDisplayEquip); - characterMenuWindow->AddComponent("Item Equip Description",itemDescriptionDisplayEquip); } \ No newline at end of file diff --git a/Crawler/CharacterRotatingDisplay.h b/Crawler/CharacterRotatingDisplay.h index 9a22827a..db2678aa 100644 --- a/Crawler/CharacterRotatingDisplay.h +++ b/Crawler/CharacterRotatingDisplay.h @@ -49,8 +49,8 @@ protected: float rotatingFactor=7; float perspectiveFactor=6; public: - inline CharacterRotatingDisplay(MenuType parent,geom2d::rectrect,Decal*icon) - :MenuComponent(parent,rect,"",DO_NOTHING),icon(icon){} + inline CharacterRotatingDisplay(geom2d::rectrect,Decal*icon) + :MenuComponent(rect,"",DO_NOTHING),icon(icon){} inline void SetIcon(Decal*icon){ this->icon=icon; } diff --git a/Crawler/ClassSelectionWindow.cpp b/Crawler/ClassSelectionWindow.cpp index 2d112408..93a08238 100644 --- a/Crawler/ClassSelectionWindow.cpp +++ b/Crawler/ClassSelectionWindow.cpp @@ -53,25 +53,21 @@ void Menu::InitializeClassSelectionWindow(){ vf2d outlineSize=classSelectionWindow->size-vf2d{13,13}; - MenuLabel*classSelectionLabel=NEW MenuLabel(CLASS_SELECTION,{{4,20},{outlineSize.x,32}},"Choose a Character Class",2,ComponentAttr::SHADOW|ComponentAttr::OUTLINE|ComponentAttr::BACKGROUND); - classSelectionWindow->AddComponent("Class Selection Title Label",classSelectionLabel); + classSelectionWindow->ADD("Class Selection Title Label",MenuLabel)({{4,20},{outlineSize.x,32}},"Choose a Character Class",2,ComponentAttr::SHADOW|ComponentAttr::OUTLINE|ComponentAttr::BACKGROUND)END; - MenuLabel*outline=NEW MenuLabel(CLASS_SELECTION,{{4,4},outlineSize},"",1,ComponentAttr::OUTLINE); - - classSelectionWindow->AddComponent("Outline Border",outline); + auto outline=classSelectionWindow->ADD("Outline Border",MenuLabel)({{4,4},outlineSize},"",1,ComponentAttr::OUTLINE)END; vf2d navigationButtonSize={24*2.5f,16}; - MenuComponent*backButton=NEW MenuComponent(CLASS_SELECTION,{{4+2,outlineSize.y+4-navigationButtonSize.y-2},navigationButtonSize},"Back",[](MenuFuncData data){Menu::CloseMenu();return true;}); - classSelectionWindow->AddComponent("Back Button",backButton); - MenuComponent*confirmButton=NEW MenuComponent(CLASS_SELECTION,{{outlineSize.x+4-navigationButtonSize.x-2,outlineSize.y+4-navigationButtonSize.y-2},navigationButtonSize},"Confirm",[](MenuFuncData data){ + classSelectionWindow->ADD("Back Button",MenuComponent)({{4+2,outlineSize.y+4-navigationButtonSize.y-2},navigationButtonSize},"Back",[](MenuFuncData data){Menu::CloseMenu();return true;})END; + + classSelectionWindow->ADD("Confirm",MenuComponent)({{outlineSize.x+4-navigationButtonSize.x-2,outlineSize.y+4-navigationButtonSize.y-2},navigationButtonSize},"Confirm",[](MenuFuncData data){ std::string selectedClass=data.component->S(A::CLASS_SELECTION); data.game->ChangePlayerClass(classutils::StringToClass(selectedClass)); GameState::ChangeState(States::OVERWORLD_MAP); return true; - }); - confirmButton->disabled=true; - classSelectionWindow->AddComponent("Confirm",confirmButton); + })END + ->disabled=true; vf2d buttonPadding={2,2}; vf2d buttonSize={floor(outlineSize.y/3-buttonPadding.y*3),outlineSize.y/9-buttonPadding.y*3}; //The floor is for fixing a small pixel rounding bug. @@ -111,26 +107,27 @@ void Menu::InitializeClassSelectionWindow(){ buttonStartPos.y+(buttonSize.y+buttonPadding.y+2*outlineSize.y/9)*float(i/3), }; vf2d backgroundSize={floor(outlineSize.y/3-buttonPadding.y*3),outlineSize.y/3-buttonPadding.y*3}; //The floor is for fixing a small pixel rounding bug. - MenuLabel*backgroundOutline=NEW MenuLabel(CLASS_SELECTION,{backgroundOffsetPos,backgroundSize},"",1,ComponentAttr::OUTLINE|ComponentAttr::BACKGROUND); - MenuLabel*classLabel=NEW MenuLabel(CLASS_SELECTION,{backgroundOffsetPos,buttonSize},className,1,ComponentAttr::SHADOW); - MenuAnimatedIconToggleButton*classSprite=NEW MenuAnimatedIconToggleButton(CLASS_SELECTION,{backgroundOffsetPos+vf2d{0,12},backgroundSize+vf2d{0,-buttonSize.y-12}},classAnimationName,[](MenuFuncData data){ - data.menu.components["Confirm"]->Enable(true); - data.menu.components["Confirm"]->S(A::CLASS_SELECTION)=data.component->S(A::CLASS_SELECTION); - return true; - }); - toggleGroup.push_back(classSprite); - MenuComponent*classButton=NEW MenuComponent(CLASS_SELECTION,{offsetPos,buttonSize},"Info",CLASS_INFO, + + + classSelectionWindow->ADD(className+" Background",MenuLabel)({backgroundOffsetPos,backgroundSize},"",1,ComponentAttr::OUTLINE|ComponentAttr::BACKGROUND)END; + classSelectionWindow->ADD(className+" Button",MenuComponent)({offsetPos,buttonSize},"Info",CLASS_INFO, [](MenuFuncData data){ data.menu.S(A::CLASS_SELECTION)=data.component->S(A::CLASS_SELECTION); delete Menu::menus[CLASS_INFO]; Menu::InitializeClassInfoWindow(); return true; - }); - classSprite->S(A::CLASS_SELECTION)=classButton->S(A::CLASS_SELECTION)=className; - classSelectionWindow->AddComponent(className+" Background",backgroundOutline); - classSelectionWindow->AddComponent(className+" Button",classButton); - classSelectionWindow->AddComponent(className+" Label",classLabel); - classSelectionWindow->AddComponent(className+" Icon",classSprite); + })END + ->S(A::CLASS_SELECTION)=className; + classSelectionWindow->ADD(className+" Label",MenuLabel)({backgroundOffsetPos,buttonSize},className,1,ComponentAttr::SHADOW)END; + auto classSprite=classSelectionWindow->ADD(className+" Icon",MenuAnimatedIconToggleButton)({backgroundOffsetPos+vf2d{0,12},backgroundSize+vf2d{0,-buttonSize.y-12}},classAnimationName,[](MenuFuncData data){ + data.menu.components["Confirm"]->Enable(true); + data.menu.components["Confirm"]->S(A::CLASS_SELECTION)=data.component->S(A::CLASS_SELECTION); + return true; + })END; + + classSprite->S(A::CLASS_SELECTION)=className; + + toggleGroup.push_back(classSprite); } for(IToggleable*item:toggleGroup){ diff --git a/Crawler/Crawler.cpp b/Crawler/Crawler.cpp index 6c827a4d..6d684c27 100644 --- a/Crawler/Crawler.cpp +++ b/Crawler/Crawler.cpp @@ -445,7 +445,7 @@ void Crawler::HandleUserInput(float fElapsedTime){ } if(GetKey(I).bPressed){ - Menu::OpenMenu(INVENTORY); + Menu::OpenMenu(INVENTORY_CONSUMABLES); } if(GetKey(O).bPressed){ ItemDrop::SpawnItem(&ITEM_DATA.at("Green Slime Remains"),player->GetPos(),player->OnUpperLevel()); @@ -1232,8 +1232,8 @@ void Crawler::RenderHud(){ DrawShadowStringDecal({0,128},player->GetPos().str()); DrawShadowStringDecal({0,136},"Spd: "+std::to_string(player->GetMoveSpdMult())); DrawShadowStringDecal({0,92},"Loadout Slot 1 Qty: "+std::to_string(GetLoadoutItem(0).Amt())); - DrawShadowStringDecal({0,1},"Selection: "+Menu::menus[INVENTORY]->selection.str()); - DrawShadowStringDecal({0,12},"Button Hold Time: "+std::to_string(Menu::menus[INVENTORY]->buttonHoldTime)); + DrawShadowStringDecal({0,1},"Selection: "+Menu::menus[INVENTORY_CONSUMABLES]->selection.str()); + DrawShadowStringDecal({0,12},"Button Hold Time: "+std::to_string(Menu::menus[INVENTORY_CONSUMABLES]->buttonHoldTime)); }} void Crawler::RenderCooldowns(){ diff --git a/Crawler/Crawler.vcxproj b/Crawler/Crawler.vcxproj index e087f67a..a9d906a2 100644 --- a/Crawler/Crawler.vcxproj +++ b/Crawler/Crawler.vcxproj @@ -411,6 +411,10 @@ + + + + @@ -450,8 +454,6 @@ - - diff --git a/Crawler/Crawler.vcxproj.filters b/Crawler/Crawler.vcxproj.filters index bcdf4403..f2629c11 100644 --- a/Crawler/Crawler.vcxproj.filters +++ b/Crawler/Crawler.vcxproj.filters @@ -410,12 +410,6 @@ Source Files\Interface - - Source Files\Interface - - - Source Files\Interface - Source Files\Game States @@ -491,6 +485,9 @@ Source Files + + Source Files\Interface + diff --git a/Crawler/EncountersSpawnListScrollableWindowComponent.h b/Crawler/EncountersSpawnListScrollableWindowComponent.h index bce8cf1d..d8aaf67e 100644 --- a/Crawler/EncountersSpawnListScrollableWindowComponent.h +++ b/Crawler/EncountersSpawnListScrollableWindowComponent.h @@ -50,8 +50,8 @@ INCLUDE_LEVEL_NAMES class EncountersSpawnListScrollableWindowComponent:public ScrollableWindowComponent{ protected: public: - inline EncountersSpawnListScrollableWindowComponent(MenuType parent,geom2d::rectrect,ComponentAttr attributes=ComponentAttr::BACKGROUND|ComponentAttr::OUTLINE) - :ScrollableWindowComponent(parent,rect,attributes){} + inline EncountersSpawnListScrollableWindowComponent(geom2d::rectrect,ComponentAttr attributes=ComponentAttr::BACKGROUND|ComponentAttr::OUTLINE) + :ScrollableWindowComponent(rect,attributes){} virtual inline void UpdateSpawns(std::vector&spawns){ Menu::menus.at(parentMenu)->components.erase_if([&](auto key){ if(key.first.starts_with("Spawn ")){ @@ -64,8 +64,7 @@ public: vf2d parentPos=Menu::menus.at(OVERWORLD_LEVEL_SELECT)->pos; vf2d parentSize=Menu::menus.at(OVERWORLD_LEVEL_SELECT)->size; for(int spawn:spawns){ - SpawnEncounterLabel*spawnLabel=NEW SpawnEncounterLabel(OVERWORLD_LEVEL_SELECT,{vf2d{0,float(offsetY)},{parentSize.x,12}},MONSTER_DATA.at(spawn-1).GetDisplayName(),spawn-1); - AddComponent(Menu::menus.at(OVERWORLD_LEVEL_SELECT),"Spawn "+std::to_string(spawn),spawnLabel); + ADD("Spawn "+std::to_string(spawn),SpawnEncounterLabel)({vf2d{0,float(offsetY)},{parentSize.x,12}},MONSTER_DATA.at(spawn-1).GetDisplayName(),spawn-1)END; offsetY+=14; } } diff --git a/Crawler/EquipSlotButton.h b/Crawler/EquipSlotButton.h index d9a66f0a..7f04e6b7 100644 --- a/Crawler/EquipSlotButton.h +++ b/Crawler/EquipSlotButton.h @@ -47,8 +47,8 @@ class EquipSlotButton:public MenuItemItemButton{ private: EquipSlot slot; public: - inline EquipSlotButton(MenuType parent,geom2d::rectrect,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 EquipSlotButton(geom2d::rectrect,EquipSlot slot,MenuType menuDest,MenuFunc onClick,MenuFunc onHover,MenuFunc onMouseOut,std::string itemNameLabelName="",std::string itemDescriptionLabelName="") + :MenuItemItemButton(rect,Item::BLANK,menuDest,onClick,onHover,onMouseOut,itemNameLabelName,itemDescriptionLabelName),slot(slot){} inline void OnEquipStatsUpdate()override{ Item&equip=*Inventory::GetEquip(slot); if(!equip.IsBlank()){ diff --git a/Crawler/InventoryConsumableWindow.cpp b/Crawler/InventoryConsumableWindow.cpp index 1c3f21f3..9de6c427 100644 --- a/Crawler/InventoryConsumableWindow.cpp +++ b/Crawler/InventoryConsumableWindow.cpp @@ -55,11 +55,11 @@ void Menu::InitializeConsumableInventoryWindow(){ vf2d windowSize={float(totalSpacing*invWidth-itemSpacing+2+24),float(totalSpacing*(3+1)-itemSpacing+64)}; //Need space for the button. - Menu*inventoryWindow=CreateMenu(INVENTORY,CENTERED,windowSize); + Menu*inventoryWindow=CreateMenu(INVENTORY_CONSUMABLES,CENTERED,windowSize); inventoryWindow->I(A::LOADOUT_SLOT)=0; - InventoryScrollableWindowComponent*inventory=NEW InventoryScrollableWindowComponent(INVENTORY,{{1,20},{windowSize.x,float(totalSpacing*3-itemSpacing)}},"Consumables","itemName","itemDescription", + inventoryWindow->ADD("inventory",InventoryScrollableWindowComponent)({{1,20},{windowSize.x,float(totalSpacing*3-itemSpacing)}},"Consumables","itemName","itemDescription", [&](MenuFuncData data){ MenuItemButton*button=(MenuItemButton*)data.component; data.game->ClearLoadoutItem(data.menu.I(A::LOADOUT_SLOT)); @@ -80,21 +80,13 @@ void Menu::InitializeConsumableInventoryWindow(){ button->selected=data.menu.I(A::LOADOUT_SLOT); data.game->SetLoadoutItem(button->selected,button->GetItem().Name()); return true; - }); - inventoryWindow->AddComponent("inventory",inventory); + })END; //We don't have to actually populate the inventory list because now when an item gets added, it will automatically add the correct component in for us. - - MenuLabel*inventoryTypeLabel=NEW MenuLabel(INVENTORY,{{0,0},{windowSize.x-1,18}},"Consumables",2,ComponentAttr::SHADOW|ComponentAttr::BACKGROUND|ComponentAttr::OUTLINE); - inventoryWindow->AddComponent("Inventory Type Label",inventoryTypeLabel); - - MenuLabel*itemNameLabel=NEW MenuLabel{INVENTORY,geom2d::rect(vf2d{2,float(initialInvHeight*totalSpacing+itemSpacing-16)},{windowSize.x-4,windowSize.y-108}),"",1,ComponentAttr::SHADOW}; - inventoryWindow->AddComponent("itemName",itemNameLabel); + inventoryWindow->ADD("Inventory Type Label",MenuLabel)({{0,0},{windowSize.x-1,18}},"Consumables",2,ComponentAttr::SHADOW|ComponentAttr::BACKGROUND|ComponentAttr::OUTLINE)END; + inventoryWindow->ADD("itemName",MenuLabel)(geom2d::rect(vf2d{2,float(initialInvHeight*totalSpacing+itemSpacing-16)},{windowSize.x-4,windowSize.y-108}),"",1,ComponentAttr::SHADOW)END; float itemDescriptionLabelY=float(initialInvHeight*totalSpacing+itemSpacing); - MenuLabel*itemDescriptionLabel=NEW MenuLabel{INVENTORY,geom2d::rect(vf2d{2,itemDescriptionLabelY},{windowSize.x-4,windowSize.y-108}),"",1,ComponentAttr::SHADOW}; - inventoryWindow->AddComponent("itemDescription",itemDescriptionLabel); - - MenuComponent*okButton=NEW MenuComponent(INVENTORY,{{windowSize.x/2-24,itemDescriptionLabelY+56},{48,12}},"Ok",[](MenuFuncData data){Menu::CloseMenu();return true;}); + inventoryWindow->ADD("itemDescription",MenuLabel)(geom2d::rect(vf2d{2,itemDescriptionLabelY},{windowSize.x-4,windowSize.y-108}),"",1,ComponentAttr::SHADOW)END; - inventoryWindow->AddComponent("OK Button",okButton); + inventoryWindow->ADD("OK Button",MenuComponent)({{windowSize.x/2-24,itemDescriptionLabelY+56},{48,12}},"Ok",[](MenuFuncData data){Menu::CloseMenu();return true;})END; } \ No newline at end of file diff --git a/Crawler/InventoryScrollableWindowComponent.h b/Crawler/InventoryScrollableWindowComponent.h index 1aa85603..f2d872c9 100644 --- a/Crawler/InventoryScrollableWindowComponent.h +++ b/Crawler/InventoryScrollableWindowComponent.h @@ -53,8 +53,8 @@ private: protected: ITCategory inventoryType; public: - inline InventoryScrollableWindowComponent(MenuType parent,geom2d::rectrect,ITCategory invType,std::string itemNameLabelName,std::string itemDescriptionLabelName,std::functioninventoryButtonClickAction,bool inventoryButtonsActive=true,ComponentAttr attributes=ComponentAttr::BACKGROUND|ComponentAttr::OUTLINE) - :ScrollableWindowComponent(parent,rect,attributes),inventoryType(invType),itemNameLabelName(itemNameLabelName),itemDescriptionLabelName(itemDescriptionLabelName), + inline InventoryScrollableWindowComponent(geom2d::rectrect,ITCategory invType,std::string itemNameLabelName,std::string itemDescriptionLabelName,std::functioninventoryButtonClickAction,bool inventoryButtonsActive=true,ComponentAttr attributes=ComponentAttr::BACKGROUND|ComponentAttr::OUTLINE) + :ScrollableWindowComponent(rect,attributes),inventoryType(invType),itemNameLabelName(itemNameLabelName),itemDescriptionLabelName(itemDescriptionLabelName), inventoryButtonClickAction(inventoryButtonClickAction),inventoryButtonsActive(inventoryButtonsActive){ Menu::AddInventoryListener(this,invType); } @@ -105,8 +105,7 @@ protected: int buttonSize="ThemeGlobal.InventoryButtonSize"_I; int totalSpacing="ThemeGlobal.InventoryItemSpacing"_I+buttonSize; - MenuItemButton*button=NEW MenuItemButton{parentMenu,{{float(totalSpacing*x),float(totalSpacing*y)},{float(buttonSize),float(buttonSize)}},Inventory::get(cat),itemIndex,inventoryButtonClickAction,parentMenu,itemNameLabelName,itemDescriptionLabelName,inventoryButtonsActive?IconButtonAttr::SELECTABLE:IconButtonAttr::NOT_SELECTABLE}; - AddComponent(Menu::menus[parentMenu],"item_"+cat+"_"+std::to_string(itemIndex),button); + ADD("item_"+cat+"_"+std::to_string(itemIndex),MenuItemButton)({{float(totalSpacing*x),float(totalSpacing*y)},{float(buttonSize),float(buttonSize)}},Inventory::get(cat),itemIndex,inventoryButtonClickAction,parentMenu,itemNameLabelName,itemDescriptionLabelName,inventoryButtonsActive?IconButtonAttr::SELECTABLE:IconButtonAttr::NOT_SELECTABLE)END; }else if(components.size()>invSize){ //There are empty spots, so let's clean up. RemoveEmptySlots(); diff --git a/Crawler/TestMenu.cpp b/Crawler/InventoryWindow.cpp similarity index 64% rename from Crawler/TestMenu.cpp rename to Crawler/InventoryWindow.cpp index 3bc41fad..38eba332 100644 --- a/Crawler/TestMenu.cpp +++ b/Crawler/InventoryWindow.cpp @@ -30,35 +30,32 @@ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -Portions of this software are copyright © 2023 The FreeType +Portions of this software are copyright © 2023 The FreeType Project (www.freetype.org). Please see LICENSE_FT.txt for more information. All rights reserved. */ #pragma endregion #include "Crawler.h" -#include "MenuComponent.h" - -void Menu::InitializeTestMenu(){ - Menu*testMenu=CreateMenu(TEST,CENTERED,{24*8,24*6}); - - MenuFunc quitWindow=[](MenuFuncData data){ - data.menu.stack.clear(); - return true; - }; - - testMenu->AddComponent("Close",NEW MenuComponent(TEST,{{24*1,24*1},{24*2,24*1}},"Close",quitWindow)); - - MenuFunc doNothing=[](MenuFuncData data){return true;}; - - testMenu->AddComponent("Test",NEW MenuComponent(TEST,{{24*4,24*1},{24*3,24*1}},"Test",doNothing)); - - MenuFunc HurtPlayer=[](MenuFuncData data){ - data.game->GetPlayer()->Hurt(20,data.game->GetPlayer()->OnUpperLevel(),data.game->GetPlayer()->GetZ()); - return true; - }; - - testMenu->AddComponent("Hurt Player",NEW MenuComponent(TEST,{{24*4,24*3},{24*3,24*1}},"Hurt Player",HurtPlayer)); - - testMenu->AddComponent("Open SubMenu",NEW MenuComponent(TEST,{{24*2,24*4.5},{24*4,24*1}},"Open Another\n Menu",TEST_2,doNothing)); - +#include "DEFINES.h" +#include "Menu.h" +#include "MenuLabel.h" + +INCLUDE_game +using A=Attribute; +using enum ComponentAttr; +using ButtonAttr::UNSELECTABLE; +using ButtonAttr::UNSELECTABLE_VIA_KEYBOARD; + +struct testStruct{ + int val1; + int val2; + int val3; + testStruct(int val1,int val2,int val3){}; +}; + +void Menu::InitializeInventoryWindow(){ + Menu*inventoryWindow=CreateMenu(INVENTORY,CENTERED,game->GetScreenSize()-vi2d{52,52}); + + inventoryWindow->ADD("Inventory Label",MenuLabel)({{0,0},{inventoryWindow->size.x-1,24}},"Inventory",2,SHADOW|OUTLINE|BACKGROUND)END; + inventoryWindow->ADD("Inventory Tabs",MenuComponent)({{0,28},{72,inventoryWindow->size.x-44}},"",DO_NOTHING,UNSELECTABLE)END; } \ No newline at end of file diff --git a/Crawler/ItemLoadoutWindow.cpp b/Crawler/ItemLoadoutWindow.cpp index d33fda85..34168f94 100644 --- a/Crawler/ItemLoadoutWindow.cpp +++ b/Crawler/ItemLoadoutWindow.cpp @@ -51,28 +51,17 @@ void Menu::InitializeItemLoadoutWindow(){ float itemLoadoutWindowWidth=(game->GetScreenSize().x-5.f); - MenuLabel*loadoutLabel=NEW MenuLabel(ITEM_LOADOUT,{{0,24},{itemLoadoutWindowWidth,24}},"Loadout",2,ComponentAttr::SHADOW|ComponentAttr::BACKGROUND|ComponentAttr::OUTLINE); - - itemLoadoutWindow->AddComponent("Loadout Label",loadoutLabel); + itemLoadoutWindow->ADD("Loadout Label",MenuLabel)({{0,24},{itemLoadoutWindowWidth,24}},"Loadout",2,ComponentAttr::SHADOW|ComponentAttr::BACKGROUND|ComponentAttr::OUTLINE)END; 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 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); - MenuLabel*itemDescription=NEW MenuLabel(ITEM_LOADOUT,{{0,170},{itemLoadoutWindowWidth,24}},"",1,ComponentAttr::SHADOW); - - itemLoadoutWindow->AddComponent("Loadout Item 1",loadoutItem1); - itemLoadoutWindow->AddComponent("Loadout Item 2",loadoutItem2); - itemLoadoutWindow->AddComponent("Loadout Item 3",loadoutItem3); - - itemLoadoutWindow->AddComponent("Item Name Label",itemNameLabel); - itemLoadoutWindow->AddComponent("Item Description",itemDescription); + itemLoadoutWindow->ADD("Loadout Item 1",MenuItemItemButton)({{64,96},{48,48}},game->GetLoadoutItem(0),INVENTORY_CONSUMABLES,[](MenuFuncData data){Menu::menus.at(INVENTORY_CONSUMABLES)->I(A::LOADOUT_SLOT)=0; return true;},"Item Name Label","Item Description")END; + itemLoadoutWindow->ADD("Loadout Item 2",MenuItemItemButton)({{itemLoadoutWindowWidth/2-24,96},{48,48}},game->GetLoadoutItem(1),INVENTORY_CONSUMABLES,[](MenuFuncData data){Menu::menus.at(INVENTORY_CONSUMABLES)->I(A::LOADOUT_SLOT)=1;return true;},"Item Name Label","Item Description")END; + itemLoadoutWindow->ADD("Loadout Item 3",MenuItemItemButton)({{itemLoadoutWindowWidth-48-64,96},{48,48}},game->GetLoadoutItem(2),INVENTORY_CONSUMABLES,[](MenuFuncData data){Menu::menus.at(INVENTORY_CONSUMABLES)->I(A::LOADOUT_SLOT)=2;return true;},"Item Name Label","Item Description")END; - MenuComponent*startLevelButton=NEW MenuComponent(ITEM_LOADOUT,{{itemLoadoutWindowWidth/2-32,214},{64,16}},"Start",[](MenuFuncData data){State_OverworldMap::StartLevel();return true;}); + itemLoadoutWindow->ADD("Item Name Label",MenuLabel)({{0,158},{itemLoadoutWindowWidth,12}},"",1,ComponentAttr::SHADOW)END; + itemLoadoutWindow->ADD("Item Description",MenuLabel)({{0,170},{itemLoadoutWindowWidth,24}},"",1,ComponentAttr::SHADOW)END; - itemLoadoutWindow->AddComponent("Start Level Button",startLevelButton); + + itemLoadoutWindow->ADD("Start Level Button",MenuComponent)({{itemLoadoutWindowWidth/2-32,214},{64,16}},"Start",[](MenuFuncData data){State_OverworldMap::StartLevel();return true;})END; } \ No newline at end of file diff --git a/Crawler/LevelCompleteWindow.cpp b/Crawler/LevelCompleteWindow.cpp index 29c3a9ed..0e217540 100644 --- a/Crawler/LevelCompleteWindow.cpp +++ b/Crawler/LevelCompleteWindow.cpp @@ -51,49 +51,29 @@ void Menu::InitializeLevelCompleteWindow(){ Menu*levelCompleteWindow=Menu::CreateMenu(LEVEL_COMPLETE,windowSize.pos,windowSize.size); - MenuLabel*stageCompleteLabel=NEW MenuLabel(LEVEL_COMPLETE,{{0,4},{windowSize.size.x-1.f,20}},"Stage Completed",2,ComponentAttr::OUTLINE|ComponentAttr::BACKGROUND|ComponentAttr::SHADOW); + levelCompleteWindow->ADD("Stage Complete Label",MenuLabel)({{0,4},{windowSize.size.x-1.f,20}},"Stage Completed",2,ComponentAttr::OUTLINE|ComponentAttr::BACKGROUND|ComponentAttr::SHADOW)END; - levelCompleteWindow->AddComponent("Stage Complete Label",stageCompleteLabel); + levelCompleteWindow->ADD("Monster Loot Outline",MenuComponent)({{0,32},{windowSize.size.x-80.f,72}},"",DO_NOTHING,ButtonAttr::UNSELECTABLE)END; + levelCompleteWindow->ADD("Monster Loot Label",MenuLabel)({{0,32},{windowSize.size.x-80.f,12}},"Monster Loot",1,ComponentAttr::LEFT_ALIGN|ComponentAttr::SHADOW|ComponentAttr::OUTLINE)END; + levelCompleteWindow->ADD("Monster Loot Window",InventoryScrollableWindowComponent)({{0,44},{windowSize.size.x-80.f,60}},"Monster Loot","Monster Loot Popup Item Name","Monster Loot Popup Item Description",DO_NOTHING)END; - MenuComponent*monsterLootOutline=NEW MenuComponent(LEVEL_COMPLETE,{{0,32},{windowSize.size.x-80.f,72}},"",DO_NOTHING,ButtonAttr::UNSELECTABLE); - MenuLabel*monsterLootLabel=NEW MenuLabel(LEVEL_COMPLETE,{{0,32},{windowSize.size.x-80.f,12}},"Monster Loot",1,ComponentAttr::LEFT_ALIGN|ComponentAttr::SHADOW|ComponentAttr::OUTLINE); - InventoryScrollableWindowComponent*monsterLootWindow=NEW InventoryScrollableWindowComponent(LEVEL_COMPLETE,{{0,44},{windowSize.size.x-80.f,60}},"Monster Loot","Monster Loot Popup Item Name","Monster Loot Popup Item Description",DO_NOTHING); - - levelCompleteWindow->AddComponent("Monster Loot Outline",monsterLootOutline); - levelCompleteWindow->AddComponent("Monster Loot Label",monsterLootLabel); - levelCompleteWindow->AddComponent("Monster Loot Window",monsterLootWindow); - - MenuComponent*stageLootOutline=NEW MenuComponent(LEVEL_COMPLETE,{{0,108},{windowSize.size.x-80.f,72}},"",DO_NOTHING,ButtonAttr::UNSELECTABLE); - MenuLabel*stageLootLabel=NEW MenuLabel(LEVEL_COMPLETE,{{0,108},{windowSize.size.x-80.f,12}},"Stage Loot",1,ComponentAttr::LEFT_ALIGN|ComponentAttr::SHADOW|ComponentAttr::OUTLINE); - InventoryScrollableWindowComponent*stageLootWindow=NEW InventoryScrollableWindowComponent(LEVEL_COMPLETE,{{0,120},{windowSize.size.x-80.f,60}},"Stage Loot","Stage Loot Popup Item Name","Stage Loot Popup Item Description",DO_NOTHING); - - levelCompleteWindow->AddComponent("Stage Loot Outline",stageLootOutline); - levelCompleteWindow->AddComponent("Stage Loot Label",stageLootLabel); - levelCompleteWindow->AddComponent("Stage Loot Window",stageLootWindow); + levelCompleteWindow->ADD("Stage Loot Outline",MenuComponent)({{0,108},{windowSize.size.x-80.f,72}},"",DO_NOTHING,ButtonAttr::UNSELECTABLE)END; + levelCompleteWindow->ADD("Stage Loot Label",MenuLabel)({{0,108},{windowSize.size.x-80.f,12}},"Stage Loot",1,ComponentAttr::LEFT_ALIGN|ComponentAttr::SHADOW|ComponentAttr::OUTLINE)END; + levelCompleteWindow->ADD("Stage Loot Window",InventoryScrollableWindowComponent)({{0,120},{windowSize.size.x-80.f,60}},"Stage Loot","Stage Loot Popup Item Name","Stage Loot Popup Item Description",DO_NOTHING)END; auto nextButtonAction=[](MenuFuncData data){ Unlock::UnlockArea(State_OverworldMap::GetCurrentConnectionPoint().map); GameState::ChangeState(States::OVERWORLD_MAP,0.5f); return true; }; - - MenuComponent*detailsOutline=NEW MenuComponent(LEVEL_COMPLETE,{{windowSize.size.x-72.f,32},{71,72}},"",DO_NOTHING,ButtonAttr::UNSELECTABLE); - MenuLabel*detailsExpGain=NEW MenuLabel(LEVEL_COMPLETE,{{windowSize.size.x-72.f,104},{71,36}},"+ Exp",1,ComponentAttr::SHADOW|ComponentAttr::OUTLINE|ComponentAttr::BACKGROUND); - MenuComponent*nextButton=NEW MenuComponent(LEVEL_COMPLETE,{{windowSize.size.x-72.f,144},{71,32}},"Next",nextButtonAction); - - levelCompleteWindow->AddComponent("Level Details Outline",detailsOutline); - levelCompleteWindow->AddComponent("Level EXP Gain Outline",detailsExpGain); - levelCompleteWindow->AddComponent("Next Button",nextButton); - - PopupMenuLabel*monsterLootPopupItemName=NEW PopupMenuLabel(LEVEL_COMPLETE,{{0,108},{windowSize.size.x-80.f,12}},"",1.0f,ComponentAttr::LEFT_ALIGN|ComponentAttr::SHADOW|ComponentAttr::OUTLINE|ComponentAttr::BACKGROUND); - PopupMenuLabel*monsterLootPopupItemDescription=NEW PopupMenuLabel(LEVEL_COMPLETE,{{0,120},{windowSize.size.x-80.f,60}},"",1.0f,ComponentAttr::LEFT_ALIGN|ComponentAttr::SHADOW|ComponentAttr::OUTLINE|ComponentAttr::BACKGROUND); - levelCompleteWindow->AddComponent("Monster Loot Popup Item Name",monsterLootPopupItemName); - levelCompleteWindow->AddComponent("Monster Loot Popup Item Description",monsterLootPopupItemDescription); + levelCompleteWindow->ADD("Level Details Outline",MenuComponent)({{windowSize.size.x-72.f,32},{71,72}},"",DO_NOTHING,ButtonAttr::UNSELECTABLE)END; + levelCompleteWindow->ADD("Level EXP Gain Outline",MenuLabel)({{windowSize.size.x-72.f,104},{71,36}},"+ Exp",1,ComponentAttr::SHADOW|ComponentAttr::OUTLINE|ComponentAttr::BACKGROUND)END; + levelCompleteWindow->ADD("Next Button",MenuComponent)({{windowSize.size.x-72.f,144},{71,32}},"Next",nextButtonAction)END; - PopupMenuLabel*stageLootPopupItemName=NEW PopupMenuLabel(LEVEL_COMPLETE,{{0,32},{windowSize.size.x-80.f,12}},"",1.0f,ComponentAttr::LEFT_ALIGN|ComponentAttr::SHADOW|ComponentAttr::OUTLINE|ComponentAttr::BACKGROUND); - PopupMenuLabel*stageLootPopupItemDescription=NEW PopupMenuLabel(LEVEL_COMPLETE,{{0,44},{windowSize.size.x-80.f,60}},"",1.0f,ComponentAttr::LEFT_ALIGN|ComponentAttr::SHADOW|ComponentAttr::OUTLINE|ComponentAttr::BACKGROUND); + levelCompleteWindow->ADD("Monster Loot Popup Item Name",PopupMenuLabel)({{0,108},{windowSize.size.x-80.f,12}},"",1.0f,ComponentAttr::LEFT_ALIGN|ComponentAttr::SHADOW|ComponentAttr::OUTLINE|ComponentAttr::BACKGROUND)END; + levelCompleteWindow->ADD("Monster Loot Popup Item Description",PopupMenuLabel)({{0,120},{windowSize.size.x-80.f,60}},"",1.0f,ComponentAttr::LEFT_ALIGN|ComponentAttr::SHADOW|ComponentAttr::OUTLINE|ComponentAttr::BACKGROUND)END; - levelCompleteWindow->AddComponent("Stage Loot Popup Item Name",stageLootPopupItemName); - levelCompleteWindow->AddComponent("Stage Loot Popup Item Description",stageLootPopupItemDescription); + levelCompleteWindow->ADD("Stage Loot Popup Item Name",PopupMenuLabel)({{0,32},{windowSize.size.x-80.f,12}},"",1.0f,ComponentAttr::LEFT_ALIGN|ComponentAttr::SHADOW|ComponentAttr::OUTLINE|ComponentAttr::BACKGROUND)END; + levelCompleteWindow->ADD("Stage Loot Popup Item Description",PopupMenuLabel)({{0,44},{windowSize.size.x-80.f,60}},"",1.0f,ComponentAttr::LEFT_ALIGN|ComponentAttr::SHADOW|ComponentAttr::OUTLINE|ComponentAttr::BACKGROUND)END; } \ No newline at end of file diff --git a/Crawler/Menu.cpp b/Crawler/Menu.cpp index 225616ed..17cabb7c 100644 --- a/Crawler/Menu.cpp +++ b/Crawler/Menu.cpp @@ -86,9 +86,8 @@ Menu::~Menu(){ } void Menu::InitializeMenus(){ - stack.reserve(32); - InitializeTestMenu(); - InitializeTestSubMenu(); + #define MAX_MENUS 32 + stack.reserve(MAX_MENUS); InitializeConsumableInventoryWindow(); InitializeClassSelectionWindow(); InitializeClassInfoWindow(); @@ -98,8 +97,9 @@ void Menu::InitializeMenus(){ InitializeLevelCompleteWindow(); InitializeOverworldMenuWindow(); InitializeCharacterMenuWindow(); + InitializeInventoryWindow(); - for(MenuType type=TEST;typeAfterCreate(); } + if(menus.size()>MAX_MENUS)ERR("WARNING! Exceeded maximum expected menu count of "<0){ @@ -128,62 +129,11 @@ void Menu::InitializeMenus(){ Menu*Menu::CreateMenu(MenuType type,vf2d pos,vf2d size){ menus[type]=NEW Menu(pos,size); + menus[type]->type=type; lastMenuTypeCreated=type; return menus.at(type); } -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))){ - buttons.at(int(button->rect.pos.y)).push_back(button); - }else{ - buttons[int(button->rect.pos.y)].push_back(button); - } - if(button->selectableViaKeyboard){ - keyboardButtons.Unlock(); - if(keyboardButtons.count(int(button->rect.pos.y))){ - keyboardButtons.at(int(button->rect.pos.y)).push_back(button); - }else{ - keyboardButtons[int(button->rect.pos.y)].push_back(button); - } - } - - //We must lock the values before calling sort. Sort seems to try and create new accesses. - buttons.SetInitialized(); - keyboardButtons.SetInitialized(); - - //We make an assumption that menu components are supposed to be in left-to-right order. Sometimes we may add things out-of-order, so this fixes the problem by sorting the items afterwards. - std::sort(buttons[int(button->rect.pos.y)].begin(),buttons[int(button->rect.pos.y)].end(),[](MenuComponent*c1,MenuComponent*c2){ - return c1->GetPos().xGetPos().x; - }); - if(keyboardButtons.count(int(button->rect.pos.y))){ //Keyboard buttons may not necessarily contain this key...Let's be sure. - std::sort(keyboardButtons[int(button->rect.pos.y)].begin(),keyboardButtons[int(button->rect.pos.y)].end(),[](MenuComponent*c1,MenuComponent*c2){ - return c1->GetPos().xGetPos().x; - }); - } - }else{ - displayComponents.push_back(button); - } - - RecalculateComponentCount(); - - if(components.count(key)){ - ERR("WARNING! Key "<name=key; - components.Unlock(); //It's possible we can add a component later on, so we will make sure we remove the lock first. - components[key]=button; - components.SetInitialized(); - lastRegisteredComponent=key; - std::erase_if(Menu::unhandledComponents,[&](MenuComponent*b1){return b1==button;}); -} - void Menu::CheckClickAndPerformMenuSelect(Crawler*game){ if(game->GetMouse(Mouse::LEFT).bReleased||game->GetKey(SPACE).bReleased||game->GetKey(ENTER).bReleased){ MenuSelect(game); diff --git a/Crawler/Menu.h b/Crawler/Menu.h index cf0a52c2..567b394c 100644 --- a/Crawler/Menu.h +++ b/Crawler/Menu.h @@ -47,13 +47,21 @@ class Crawler; class MenuComponent; class ScrollableWindowComponent; +//Add a component to a menu using this macro. Follow-up with END at the end of it. +#define ADD(key,componentType) AddComponent(key,NEW componentType +#define END ) +#define DEPTH , + #define DEFAULT_DEPTH -999999 #define STARTING_DEPTH 999999 enum MenuType{ - TEST, - TEST_2, - INVENTORY, + #pragma region Enum Start //DO NOT REMOVE + /////////////////////////////////////////////////////////// + /*DO NOT REMOVE!!*/ENUM_START,/////////////////////////////// + /////////////////////////////////////////////////////////// + #pragma endregion + INVENTORY_CONSUMABLES, CLASS_INFO, CLASS_SELECTION, MAIN_MENU, @@ -62,12 +70,26 @@ enum MenuType{ LEVEL_COMPLETE, OVERWORLD_MENU, CHARACTER_MENU, + INVENTORY, + #pragma region Enum End //DO NOT REMOVE /////////////////////////////////////////////////////////// /*DO NOT REMOVE!!*/ENUM_END//////////////////////////////// /////////////////////////////////////////////////////////// + #pragma endregion }; class Menu:public IAttributable{ + static void InitializeConsumableInventoryWindow(); + static void InitializeClassInfoWindow(); + static void InitializeClassSelectionWindow(); + static void InitializeMainMenuWindow(); + static void InitializeOverworldMapLevelWindow(); + static void InitializeItemLoadoutWindow(); + static void InitializeLevelCompleteWindow(); + static void InitializeOverworldMenuWindow(); + static void InitializeCharacterMenuWindow(); + static void InitializeInventoryWindow(); + friend class Crawler; friend struct Player; friend class ItemInfo; @@ -86,7 +108,62 @@ public: //The constructor is private. Use CreateMenu() instead! Menu()=default; ~Menu(); - void AddComponent(std::string key,MenuComponent*button,int depth=DEFAULT_DEPTH); + //DO NOT USE DIRECTLY! You should be utilizing the ADD macro for adding components. + template + T*AddComponent(std::string componentKey,T*component,int depth=DEFAULT_DEPTH){ + component->parentMenu=type; + if(depth==DEFAULT_DEPTH){ + component->depth=STARTING_DEPTH-componentCount; + }else{ + component->depth=depth; + } + if(component->selectable){ + buttons.Unlock(); + if(buttons.count(int(component->rect.pos.y))){ + buttons.at(int(component->rect.pos.y)).push_back(component); + }else{ + buttons[int(component->rect.pos.y)].push_back(component); + } + if(component->selectableViaKeyboard){ + keyboardButtons.Unlock(); + if(keyboardButtons.count(int(component->rect.pos.y))){ + keyboardButtons.at(int(component->rect.pos.y)).push_back(component); + }else{ + keyboardButtons[int(component->rect.pos.y)].push_back(component); + } + } + + //We must lock the values before calling sort. Sort seems to try and create new accesses. + buttons.SetInitialized(); + keyboardButtons.SetInitialized(); + + //We make an assumption that menu components are supposed to be in left-to-right order. Sometimes we may add things out-of-order, so this fixes the problem by sorting the items afterwards. + std::sort(buttons[int(component->rect.pos.y)].begin(),buttons[int(component->rect.pos.y)].end(),[](auto c1,auto c2){ + return c1->GetPos().xGetPos().x; + }); + if(keyboardButtons.count(int(component->rect.pos.y))){ //Keyboard buttons may not necessarily contain this key...Let's be sure. + std::sort(keyboardButtons[int(component->rect.pos.y)].begin(),keyboardButtons[int(component->rect.pos.y)].end(),[](auto c1,auto c2){ + return c1->GetPos().xGetPos().x; + }); + } + }else{ + displayComponents.push_back(component); + } + + RecalculateComponentCount(); + + if(components.count(componentKey)){ + ERR("WARNING! Key "<name=componentKey; + components.Unlock(); //It's possible we can add a component later on, so we will make sure we remove the lock first. + components[componentKey]=component; + components.SetInitialized(); + lastRegisteredComponent=componentKey; + std::erase_if(Menu::unhandledComponents,[&](auto b1){return b1==component;}); + + return component; + } void Update(Crawler*game); void Draw(Crawler*game); static void InitializeMenus(); @@ -133,18 +210,6 @@ private: void CheckClickAndPerformMenuSelect(Crawler*game); //Mandatory before any menu operations! This creates and sets up the menu in memory. static Menu*CreateMenu(MenuType type,vf2d pos,vf2d size); - - static void InitializeTestMenu(); - static void InitializeTestSubMenu(); - static void InitializeConsumableInventoryWindow(); - static void InitializeClassInfoWindow(); - static void InitializeClassSelectionWindow(); - static void InitializeMainMenuWindow(); - static void InitializeOverworldMapLevelWindow(); - static void InitializeItemLoadoutWindow(); - static void InitializeLevelCompleteWindow(); - static void InitializeOverworldMenuWindow(); - static void InitializeCharacterMenuWindow(); void KeyboardButtonNavigation(Crawler*game,vf2d menuPos); static void DrawScaledWindowBackground(Crawler*game,vf2d menuPos,vf2d size,Pixel renderColor); @@ -156,6 +221,7 @@ private: bool HandleOutsideDisabledButtonSelection(MenuComponent*disabledButton); Pixel GetRenderColor(); + MenuType type; static bool MOUSE_NAVIGATION; bool cover; //A black cover for when a menu pops up to fade out the stuff behind it. diff --git a/Crawler/MenuAnimatedIconButton.h b/Crawler/MenuAnimatedIconButton.h index 48b1e461..a3b35023 100644 --- a/Crawler/MenuAnimatedIconButton.h +++ b/Crawler/MenuAnimatedIconButton.h @@ -48,8 +48,8 @@ protected: private: float animationTime=0; public: - inline MenuAnimatedIconButton(MenuType parent,geom2d::rectrect,std::string animation,MenuFunc onClick,IconButtonAttr attributes=IconButtonAttr::SELECTABLE) - :MenuIconButton(parent,rect,nullptr,onClick,attributes),animation(animation){} + inline MenuAnimatedIconButton(geom2d::rectrect,std::string animation,MenuFunc onClick,IconButtonAttr attributes=IconButtonAttr::SELECTABLE) + :MenuIconButton(rect,nullptr,onClick,attributes),animation(animation){} protected: virtual inline void Update(Crawler*game)override{ MenuIconButton::Update(game); diff --git a/Crawler/MenuAnimatedIconToggleButton.h b/Crawler/MenuAnimatedIconToggleButton.h index 5ccd3a12..305084f3 100644 --- a/Crawler/MenuAnimatedIconToggleButton.h +++ b/Crawler/MenuAnimatedIconToggleButton.h @@ -49,8 +49,8 @@ protected: private: float animationTime=0; public: - inline MenuAnimatedIconToggleButton(MenuType parent,geom2d::rectrect,std::string animation,MenuFunc onClick) - :MenuAnimatedIconButton(parent,rect,animation,[](MenuFuncData data){ + inline MenuAnimatedIconToggleButton(geom2d::rectrect,std::string animation,MenuFunc onClick) + :MenuAnimatedIconButton(rect,animation,[](MenuFuncData data){ MenuAnimatedIconToggleButton*button=(MenuAnimatedIconToggleButton*)data.component; button->Select(); button->_onClick(data); diff --git a/Crawler/MenuComponent.cpp b/Crawler/MenuComponent.cpp index 175520c1..8158a9f1 100644 --- a/Crawler/MenuComponent.cpp +++ b/Crawler/MenuComponent.cpp @@ -40,13 +40,13 @@ All rights reserved. using A=Attribute; -MenuComponent::MenuComponent(MenuType parent,geom2d::rectrect,std::string label,MenuFunc onClick,ButtonAttr attributes) - :parentMenu(parent),rect(rect),label(label),menuDest(MenuType::ENUM_END),onClick(onClick),hoverEffect(0),selectable(!(attributes&ButtonAttr::UNSELECTABLE)),selectableViaKeyboard(!(attributes&ButtonAttr::UNSELECTABLE_VIA_KEYBOARD)),memoryLeakInfo(Menu::GetMemoryLeakReportInfo()){ +MenuComponent::MenuComponent(geom2d::rectrect,std::string label,MenuFunc onClick,ButtonAttr attributes) + :rect(rect),label(label),menuDest(MenuType::ENUM_END),onClick(onClick),hoverEffect(0),selectable(!(attributes&ButtonAttr::UNSELECTABLE)),selectableViaKeyboard(!(attributes&ButtonAttr::UNSELECTABLE_VIA_KEYBOARD)),memoryLeakInfo(Menu::GetMemoryLeakReportInfo()){ Menu::unhandledComponents.push_back(this); } -MenuComponent::MenuComponent(MenuType parent,geom2d::rectrect,std::string label,MenuType menuDest,MenuFunc onClick,ButtonAttr attributes) - :MenuComponent(parent,rect,label,onClick,attributes){ +MenuComponent::MenuComponent(geom2d::rectrect,std::string label,MenuType menuDest,MenuFunc onClick,ButtonAttr attributes) + :MenuComponent(rect,label,onClick,attributes){ //NOTE: This constructor also calls the other constructor above! this->menuDest=menuDest; } diff --git a/Crawler/MenuComponent.h b/Crawler/MenuComponent.h index fee289dd..144ddae7 100644 --- a/Crawler/MenuComponent.h +++ b/Crawler/MenuComponent.h @@ -97,8 +97,8 @@ protected: public: MenuType parentMenu=MenuType::ENUM_END; MenuComponent*parentComponent=nullptr; - MenuComponent(MenuType parent,geom2d::rectrect,std::string label,MenuFunc onClick,ButtonAttr attributes=ButtonAttr::NONE); - MenuComponent(MenuType parent,geom2d::rectrect,std::string label,MenuType menuDest,MenuFunc onClick,ButtonAttr attributes=ButtonAttr::NONE); + MenuComponent(geom2d::rectrect,std::string label,MenuFunc onClick,ButtonAttr attributes=ButtonAttr::NONE); + MenuComponent(geom2d::rectrect,std::string label,MenuType menuDest,MenuFunc onClick,ButtonAttr attributes=ButtonAttr::NONE); virtual ~MenuComponent(); vf2d GetPos(); //We picked up a draggable component, we should make a copy and return it here. If a nullptr is returned here, the pickup is not allowed. diff --git a/Crawler/MenuIconButton.h b/Crawler/MenuIconButton.h index ee7c28cb..32955358 100644 --- a/Crawler/MenuIconButton.h +++ b/Crawler/MenuIconButton.h @@ -51,10 +51,10 @@ class MenuIconButton:public MenuComponent{ protected: Decal*icon; public: - inline MenuIconButton(MenuType parent,geom2d::rectrect,Decal*icon,MenuFunc onClick,IconButtonAttr attributes=IconButtonAttr::SELECTABLE) - :MenuComponent(parent,rect,"",onClick,ButtonAttr(attributes)),icon(icon){} - inline MenuIconButton(MenuType parent,geom2d::rectrect,Decal*icon,MenuType menuDest,MenuFunc onClick,IconButtonAttr attributes=IconButtonAttr::SELECTABLE) - :MenuComponent(parent,rect,"",menuDest,onClick,ButtonAttr(attributes)),icon(icon){} + inline MenuIconButton(geom2d::rectrect,Decal*icon,MenuFunc onClick,IconButtonAttr attributes=IconButtonAttr::SELECTABLE) + :MenuComponent(rect,"",onClick,ButtonAttr(attributes)),icon(icon){} + inline MenuIconButton(geom2d::rectrect,Decal*icon,MenuType menuDest,MenuFunc onClick,IconButtonAttr attributes=IconButtonAttr::SELECTABLE) + :MenuComponent(rect,"",menuDest,onClick,ButtonAttr(attributes)),icon(icon){} protected: virtual inline void Update(Crawler*game)override{ MenuComponent::Update(game); diff --git a/Crawler/MenuItemButton.h b/Crawler/MenuItemButton.h index 48230473..0fee06d3 100644 --- a/Crawler/MenuItemButton.h +++ b/Crawler/MenuItemButton.h @@ -58,8 +58,8 @@ private: std::string itemDescriptionLabelName; public: int selected=-1; //0-2 representing which loadout slot this item consumes. -1 means not selected. - inline MenuItemButton(MenuType parent,geom2d::rectrect,std::vector&invRef,int invIndex,MenuFunc onClick,MenuType itemDescriptionMenu,std::string itemNameLabelName,std::string itemDescriptionLabelName,IconButtonAttr attributes=IconButtonAttr::SELECTABLE) - :MenuIconButton(parent,rect,invRef.size()>invIndex?invRef[invIndex].Decal():nullptr,onClick,attributes),invRef(invRef),inventoryIndex(invIndex),itemDescriptionMenu(itemDescriptionMenu),itemNameLabelName(itemNameLabelName),itemDescriptionLabelName(itemDescriptionLabelName){ + inline MenuItemButton(geom2d::rectrect,std::vector&invRef,int invIndex,MenuFunc onClick,MenuType itemDescriptionMenu,std::string itemNameLabelName,std::string itemDescriptionLabelName,IconButtonAttr attributes=IconButtonAttr::SELECTABLE) + :MenuIconButton(rect,invRef.size()>invIndex?invRef[invIndex].Decal():nullptr,onClick,attributes),invRef(invRef),inventoryIndex(invIndex),itemDescriptionMenu(itemDescriptionMenu),itemNameLabelName(itemNameLabelName),itemDescriptionLabelName(itemDescriptionLabelName){ draggable=false; valid=invRef.size()>invIndex; } @@ -112,7 +112,7 @@ protected: } inline MenuComponent*PickUpDraggableItem()override final{ if(valid){ - MenuItemButton*pickUp=NEW MenuItemButton(parentMenu,rect,invRef,inventoryIndex,onClick,itemDescriptionMenu,itemNameLabelName,itemDescriptionLabelName); + MenuItemButton*pickUp=NEW MenuItemButton(rect,invRef,inventoryIndex,onClick,itemDescriptionMenu,itemNameLabelName,itemDescriptionLabelName); valid=false; return pickUp; }else{ diff --git a/Crawler/MenuItemItemButton.h b/Crawler/MenuItemItemButton.h index 6beb8b0d..ca435e43 100644 --- a/Crawler/MenuItemItemButton.h +++ b/Crawler/MenuItemItemButton.h @@ -62,13 +62,13 @@ private: bool hideQty=false; CompactText compact=COMPACT; public: - inline MenuItemItemButton(MenuType parent,geom2d::rectrect,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){ + inline MenuItemItemButton(geom2d::rectrect,Item&itemRef,MenuType menuDest,MenuFunc onClick,std::string itemNameLabelName,std::string itemDescriptionLabelName) + :MenuIconButton(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::rectrect,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){ + inline MenuItemItemButton(geom2d::rectrect,Item&itemRef,MenuType menuDest,MenuFunc onClick,MenuFunc onHover,MenuFunc onMouseOut,std::string itemNameLabelName="",std::string itemDescriptionLabelName="") + :MenuIconButton(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(); diff --git a/Crawler/MenuLabel.h b/Crawler/MenuLabel.h index 86485031..2b36e84c 100644 --- a/Crawler/MenuLabel.h +++ b/Crawler/MenuLabel.h @@ -50,8 +50,8 @@ protected: bool shadow=false; bool centered=true; public: - inline MenuLabel(MenuType parent,geom2d::rectrect,std::string label,int scale=1,ComponentAttr attributes=ComponentAttr::NONE) - :MenuComponent(parent,rect,label,MenuFunc{},ButtonAttr::UNSELECTABLE|ButtonAttr::UNSELECTABLE_VIA_KEYBOARD),scale(scale),centered(!(attributes&ComponentAttr::LEFT_ALIGN)),shadow(attributes&ComponentAttr::SHADOW){ + inline MenuLabel(geom2d::rectrect,std::string label,int scale=1,ComponentAttr attributes=ComponentAttr::NONE) + :MenuComponent(rect,label,MenuFunc{},ButtonAttr::UNSELECTABLE|ButtonAttr::UNSELECTABLE_VIA_KEYBOARD),scale(scale),centered(!(attributes&ComponentAttr::LEFT_ALIGN)),shadow(attributes&ComponentAttr::SHADOW){ border=attributes&ComponentAttr::OUTLINE; this->background=attributes&ComponentAttr::BACKGROUND; showDefaultLabel=false; diff --git a/Crawler/OverworldMapLevelWindow.cpp b/Crawler/OverworldMapLevelWindow.cpp index 9bcccfb2..b5da6627 100644 --- a/Crawler/OverworldMapLevelWindow.cpp +++ b/Crawler/OverworldMapLevelWindow.cpp @@ -55,25 +55,14 @@ void Menu::InitializeOverworldMapLevelWindow(){ State_OverworldMap*overworldMap=(State_OverworldMap*)GameState::states[States::OVERWORLD_MAP]; //HACK ALERT!! We're going to make an assumption that we are in the overworld map state. - MenuLabel*chapterLabel=NEW MenuLabel(OVERWORLD_LEVEL_SELECT,{{0,4},{windowSize.x,16}},"Chapter",1,ComponentAttr::SHADOW|ComponentAttr::LEFT_ALIGN); - MenuLabel*stageLabel=NEW MenuLabel(OVERWORLD_LEVEL_SELECT,{{0,24},{windowSize.x,16}},"Stage",1,ComponentAttr::SHADOW|ComponentAttr::LEFT_ALIGN); - MenuLabel*panel1Back=NEW MenuLabel(OVERWORLD_LEVEL_SELECT,{{0,0},{windowSize.x-1,44}},"",1,ComponentAttr::BACKGROUND|ComponentAttr::OUTLINE); + levelSelectWindow->ADD("Panel 1 Back",MenuLabel)({{0,0},{windowSize.x-1,44}},"",1,ComponentAttr::BACKGROUND|ComponentAttr::OUTLINE)END; + levelSelectWindow->ADD("Chapter Label",MenuLabel)({{0,4},{windowSize.x,16}},"Chapter",1,ComponentAttr::SHADOW|ComponentAttr::LEFT_ALIGN)END; + levelSelectWindow->ADD("Stage Label",MenuLabel)({{0,24},{windowSize.x,16}},"Stage",1,ComponentAttr::SHADOW|ComponentAttr::LEFT_ALIGN)END; - levelSelectWindow->AddComponent("Panel 1 Back",panel1Back); - levelSelectWindow->AddComponent("Chapter Label",chapterLabel); - levelSelectWindow->AddComponent("Stage Label",stageLabel); - - MenuLabel*encountersLabel=NEW MenuLabel(OVERWORLD_LEVEL_SELECT,{{0,52},{windowSize.x-1,12}},"Encounters:",1,ComponentAttr::SHADOW|ComponentAttr::LEFT_ALIGN); - EncountersSpawnListScrollableWindowComponent*spawns=NEW EncountersSpawnListScrollableWindowComponent(OVERWORLD_LEVEL_SELECT,{{1,64},{windowSize.x-2,84}},ComponentAttr::BACKGROUND); - MenuLabel*panel2Back=NEW MenuLabel(OVERWORLD_LEVEL_SELECT,{{0,52},{windowSize.x-1,96}},"",1,ComponentAttr::BACKGROUND|ComponentAttr::OUTLINE); - - levelSelectWindow->AddComponent("Panel 2 Back",panel2Back); - levelSelectWindow->AddComponent("Encounters Label",encountersLabel); - levelSelectWindow->AddComponent("Spawns List",spawns); - - MenuComponent*changeLoadoutButton=NEW MenuComponent(OVERWORLD_LEVEL_SELECT,{{0,152},{windowSize.x-1,12}},"Change Loadout",ITEM_LOADOUT,[](MenuFuncData data){return true;}); - MenuComponent*enterButton=NEW MenuComponent(OVERWORLD_LEVEL_SELECT,{{0,166},{windowSize.x-1,16}},"Enter",[](MenuFuncData data){State_OverworldMap::StartLevel();return true;}); + levelSelectWindow->ADD("Panel 2 Back",MenuLabel)({{0,52},{windowSize.x-1,96}},"",1,ComponentAttr::BACKGROUND|ComponentAttr::OUTLINE)END; + levelSelectWindow->ADD("Encounters Label",MenuLabel)({{0,52},{windowSize.x-1,12}},"Encounters:",1,ComponentAttr::SHADOW|ComponentAttr::LEFT_ALIGN)END; + levelSelectWindow->ADD("Spawns List",EncountersSpawnListScrollableWindowComponent)({{1,64},{windowSize.x-2,84}},ComponentAttr::BACKGROUND)END; - levelSelectWindow->AddComponent("Change Loadout Button",changeLoadoutButton); - levelSelectWindow->AddComponent("Enter Button",enterButton); + levelSelectWindow->ADD("Change Loadout Button",MenuComponent)({{0,152},{windowSize.x-1,12}},"Change Loadout",ITEM_LOADOUT,[](MenuFuncData data){return true;})END; + levelSelectWindow->ADD("Enter Button",MenuComponent)({{0,166},{windowSize.x-1,16}},"Enter",[](MenuFuncData data){State_OverworldMap::StartLevel();return true;})END; } \ No newline at end of file diff --git a/Crawler/OverworldMenuWindow.cpp b/Crawler/OverworldMenuWindow.cpp index c324e11a..6386e026 100644 --- a/Crawler/OverworldMenuWindow.cpp +++ b/Crawler/OverworldMenuWindow.cpp @@ -47,18 +47,14 @@ INCLUDE_GFX void Menu::InitializeOverworldMenuWindow(){ Menu*overworldMenuWindow=CreateMenu(OVERWORLD_MENU,CENTERED,vi2d{96,164}); - MenuComponent*resumeButton=NEW MenuComponent(OVERWORLD_MENU,{{4,12+28*0},{88,24}},"Resume",[](MenuFuncData data){Menu::CloseMenu();return true;}); - MenuComponent*characterButton=NEW MenuComponent(OVERWORLD_MENU,{{4,12+28*1},{88,24}},"Character",[](MenuFuncData data){ - Component(CHARACTER_MENU,"Character Rotating Display")->SetIcon(GFX[classutils::GetClassInfo(game->GetPlayer()->GetClassName()).classFullImgName].Decal()); - Menu::OpenMenu(CHARACTER_MENU); - return true;}); - MenuComponent*inventoryButton=NEW MenuComponent(OVERWORLD_MENU,{{4,12+28*2},{88,24}},"Inventory",[](MenuFuncData data){/*Menu::OpenMenu(INVENTORY_MENU);*/return true;}); - MenuComponent*settingsButton=NEW MenuComponent(OVERWORLD_MENU,{{4,12+28*3},{88,24}},"Settings",[](MenuFuncData data){/*Menu::OpenMenu(SETTINGS_MENU);*/return true;}); - MenuComponent*quitButton=NEW MenuComponent(OVERWORLD_MENU,{{4,12+28*4},{88,24}},"Quit Game",[](MenuFuncData data){game->EndGame();return true;}); - - overworldMenuWindow->AddComponent("Resume Button",resumeButton); - overworldMenuWindow->AddComponent("Character Button",characterButton); - overworldMenuWindow->AddComponent("Inventory Button",inventoryButton); - overworldMenuWindow->AddComponent("Settings Button",settingsButton); - overworldMenuWindow->AddComponent("Quit Button",quitButton); + overworldMenuWindow->ADD("Resume Button",MenuComponent)({{4,12+28*0},{88,24}},"Resume",[](MenuFuncData data){Menu::CloseMenu();return true;})END; + overworldMenuWindow->ADD("Character Button",MenuComponent)({{4,12+28*1},{88,24}},"Character", + [](MenuFuncData data){ + Component(CHARACTER_MENU,"Character Rotating Display")->SetIcon(GFX[classutils::GetClassInfo(game->GetPlayer()->GetClassName()).classFullImgName].Decal()); + Menu::OpenMenu(CHARACTER_MENU); + return true; + })END; + overworldMenuWindow->ADD("Inventory Button",MenuComponent)({{4,12+28*2},{88,24}},"Inventory",[](MenuFuncData data){Menu::OpenMenu(INVENTORY);return true;})END; + overworldMenuWindow->ADD("Settings Button",MenuComponent)({{4,12+28*3},{88,24}},"Settings",[](MenuFuncData data){/*Menu::OpenMenu(SETTINGS_MENU);*/return true;})END; + overworldMenuWindow->ADD("Quit Button",MenuComponent)({{4,12+28*4},{88,24}},"Quit Game",[](MenuFuncData data){game->EndGame();return true;})END; } \ No newline at end of file diff --git a/Crawler/PopupMenuLabel.h b/Crawler/PopupMenuLabel.h index 0c60e8c6..3fbc9351 100644 --- a/Crawler/PopupMenuLabel.h +++ b/Crawler/PopupMenuLabel.h @@ -47,11 +47,11 @@ class PopupMenuLabel:public MenuLabel{ private: vf2d scale; public: - inline PopupMenuLabel(MenuType parent,geom2d::rectrect,std::string label,float scale=1,ComponentAttr attributes=ComponentAttr::NONE) - :MenuLabel(parent,rect,label,1,attributes),scale({scale,scale}){ + inline PopupMenuLabel(geom2d::rectrect,std::string label,float scale=1,ComponentAttr attributes=ComponentAttr::NONE) + :MenuLabel(rect,label,1,attributes),scale({scale,scale}){ } - inline PopupMenuLabel(MenuType parent,geom2d::rectrect,std::string label,vf2d scale={1,1},ComponentAttr attributes=ComponentAttr::NONE) - :MenuLabel(parent,rect,label,1,attributes),scale(scale){ + inline PopupMenuLabel(geom2d::rectrect,std::string label,vf2d scale={1,1},ComponentAttr attributes=ComponentAttr::NONE) + :MenuLabel(rect,label,1,attributes),scale(scale){ } protected: virtual void inline Update(Crawler*game)override{ diff --git a/Crawler/ScrollableWindowComponent.h b/Crawler/ScrollableWindowComponent.h index c1c6a691..43451f75 100644 --- a/Crawler/ScrollableWindowComponent.h +++ b/Crawler/ScrollableWindowComponent.h @@ -59,16 +59,11 @@ protected: return geom2d::overlaps(geom2d::rect{{},rect.size},geom2d::rect{component->rect.pos+V(A::SCROLL_OFFSET)+vf2d{2,2},component->rect.size-vf2d{2,2}}); } public: - inline ScrollableWindowComponent(MenuType parent,geom2d::rectrect,ComponentAttr attributes=ComponentAttr::BACKGROUND|ComponentAttr::OUTLINE) - :MenuComponent(parent,rect,"",[](MenuFuncData data){return true;},ButtonAttr::UNSELECTABLE|ButtonAttr::UNSELECTABLE_VIA_KEYBOARD){ + inline ScrollableWindowComponent(geom2d::rectrect,ComponentAttr attributes=ComponentAttr::BACKGROUND|ComponentAttr::OUTLINE) + :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)); - 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,-1); - Menu::menus[parentMenu]->AddComponent(name+downButton->rect.pos.str()+"_"+downButton->rect.size.str(),downButton,-1); } virtual inline void RemoveAllComponents(){ while(components.size()>0){ @@ -100,6 +95,11 @@ public: delete button; } protected: + virtual inline void AfterCreate()override{ + //Let's use the internal name of this component to add unique names for sub-components. + upButton=Menu::menus[parentMenu]->ADD(name+vf2d(rect.pos+vf2d{rect.size.x-12,0}).str()+"_"+vf2d(12,12).str(),MenuComponent)({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)DEPTH -1 END; + downButton=Menu::menus[parentMenu]->ADD(name+vf2d(rect.pos+rect.size-vf2d{12,12}).str()+"_"+vf2d(12,12).str(),MenuComponent)({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)DEPTH -1 END; + } virtual inline void BeforeUpdate(Crawler*game)override{ for(MenuComponent*component:components){ component->BeforeUpdate(game); @@ -229,7 +229,8 @@ protected: return bounds; } public: - void inline AddComponent(Menu*parentMenu,std::string key,MenuComponent*button){ + template + T* AddComponent(std::string key,T*button){ components.push_back(button); button->renderInMain=false; //Now we are in control! button->parentComponent=this; @@ -253,7 +254,8 @@ public: bounds.size.y+=sizeIncrease; } - parentMenu->AddComponent(key,button); + Menu::menus[parentMenu]->AddComponent(key,button); + return button; } virtual inline bool PointWithinParent(MenuComponent*child,vi2d drawPos)override{ return geom2d::overlaps(geom2d::rect{Menu::menus[parentMenu]->pos+rect.pos,rect.size},drawPos); @@ -270,7 +272,7 @@ public: } virtual inline void Enable(bool enabled)override final{ disabled=!enabled; - upButton->Enable(enabled); - downButton->Enable(enabled); + if(upButton){upButton->Enable(enabled);} + if(downButton){downButton->Enable(enabled);} }; }; \ No newline at end of file diff --git a/Crawler/SpawnEncounterLabel.h b/Crawler/SpawnEncounterLabel.h index b88cddda..548e317c 100644 --- a/Crawler/SpawnEncounterLabel.h +++ b/Crawler/SpawnEncounterLabel.h @@ -50,8 +50,8 @@ class SpawnEncounterLabel:public MenuLabel{ Animate2D::Animationanim; Animate2D::AnimationState state; public: - inline SpawnEncounterLabel(MenuType parent,geom2d::rectrect,std::string label,int monsterID) - :MenuLabel(parent,rect,label),monsterID(monsterID){ + inline SpawnEncounterLabel(geom2d::rectrect,std::string label,int monsterID) + :MenuLabel(rect,label),monsterID(monsterID){ anim.AddState("IDLE",ANIMATION_DATA.at(MONSTER_DATA.at(monsterID).GetIdleAnimation())); anim.ChangeState(state,"IDLE"); anim.UpdateState(state,util::random(1)); diff --git a/Crawler/StatLabel.h b/Crawler/StatLabel.h index dd61f0a4..7b5fd494 100644 --- a/Crawler/StatLabel.h +++ b/Crawler/StatLabel.h @@ -49,8 +49,8 @@ private: int value=0; int statChangeAmt=0; public: - inline StatLabel(MenuType parent,geom2d::rectrect,ItemAttribute stat,int scale=1,ComponentAttr attributes=ComponentAttr::NONE) - :MenuLabel(parent,rect,"",scale,attributes),stat(stat){ + inline StatLabel(geom2d::rectrect,ItemAttribute stat,int scale=1,ComponentAttr attributes=ComponentAttr::NONE) + :MenuLabel(rect,"",scale,attributes),stat(stat){ border=attributes&ComponentAttr::OUTLINE; this->background=attributes&ComponentAttr::BACKGROUND; showDefaultLabel=false; diff --git a/Crawler/TestSubMenu.cpp b/Crawler/TestSubMenu.cpp deleted file mode 100644 index c7e26108..00000000 --- a/Crawler/TestSubMenu.cpp +++ /dev/null @@ -1,104 +0,0 @@ -#pragma region License -/* -License (OLC-3) -~~~~~~~~~~~~~~~ - -Copyright 2018 - 2023 OneLoneCoder.com - -Redistribution and use in source and binary forms, with or without modification, -are permitted provided that the following conditions are met: - -1. Redistributions or derivations of source code must retain the above copyright -notice, this list of conditions and the following disclaimer. - -2. Redistributions or derivative works in binary form must reproduce the above -copyright notice. This list of conditions and the following disclaimer must be -reproduced in the documentation and/or other materials provided with the distribution. - -3. Neither the name of the copyright holder nor the names of its contributors may -be used to endorse or promote products derived from this software without specific -prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY -EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES -OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT -SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, -INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED -TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR -BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN -ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF -SUCH DAMAGE. - -Portions of this software are copyright © 2023 The FreeType -Project (www.freetype.org). Please see LICENSE_FT.txt for more information. -All rights reserved. -*/ -#pragma endregion -#include "Crawler.h" -#include "DEFINES.h" -#include "olcPixelGameEngine.h" -#include "safemap.h" -#include "MenuIconButton.h" -#include "MenuLabel.h" - -INCLUDE_GFX -using A=Attribute; - -void Menu::InitializeTestSubMenu(){ - Menu*testSubMenu=CreateMenu(TEST_2,{30,30},{24*4,24*5}); - - MenuFunc goBack=[](MenuFuncData data){ - data.menu.stack.pop_back(); - return true; - }; - - testSubMenu->AddComponent("BACK",NEW MenuComponent(TEST_2,{{24*1,24*1},{24*2,24*1}},"Go Back",goBack)); - - int index=0; - for(auto&theme:Menu::themes){ - if(theme.displayName==Menu::themeSelection){ - testSubMenu->I(A::INDEXED_THEME)=index; - break; - } - index++; - } - - MenuFunc themePrev=[](MenuFuncData data){ - bool found=false; - data.menu.I(A::INDEXED_THEME)--; - if(data.menu.I(A::INDEXED_THEME)<0){ - data.menu.I(A::INDEXED_THEME)=int(themes.size()-1); - } - int index=0; - for(auto&theme:Menu::themes){ - if(index==data.menu.I(A::INDEXED_THEME)){ - Menu::themeSelection=theme.displayName; - ((MenuLabel*)(data.menu.components["THEME_DISPLAY"]))->SetLabel("Theme\n"+Menu::themes[themeSelection].GetThemeName()); - break; - } - index++; - } - return true; - }; - - testSubMenu->AddComponent("PREV_THEME",NEW MenuComponent(TEST_2,{{24*-0.5,24*3},{24*1,24*1}},"<",themePrev)); - - testSubMenu->AddComponent("THEME_DISPLAY",NEW MenuLabel(TEST_2,{{24*0.5,24*3},{24*3,24*1}},"Theme\n"+Menu::themes[themeSelection].GetThemeName())); - - MenuFunc themeNext=[](MenuFuncData data){ - data.menu.I(A::INDEXED_THEME)=(size_t(data.menu.I(A::INDEXED_THEME))+1)%themes.size(); - int index=0; - for(auto&theme:Menu::themes){ - if(index==data.menu.I(A::INDEXED_THEME)){ - Menu::themeSelection=theme.displayName; - ((MenuLabel*)(data.menu.components["THEME_DISPLAY"]))->SetLabel("Theme\n"+Menu::themes[themeSelection].GetThemeName()); - break; - } - index++; - } - return true; - }; - - testSubMenu->AddComponent("NEXT_THEME",NEW MenuComponent(TEST_2,{{24*3.5,24*3},{24*1,24*1}},">",themeNext)); -} \ No newline at end of file diff --git a/Crawler/Version.h b/Crawler/Version.h index 1408c2ce..81315c72 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 3692 +#define VERSION_BUILD 3722 #define stringify(a) stringify_(a) #define stringify_(a) #a