Handled dynamic adding and removing of inventory items and syncing with menu systems.
This commit is contained in:
parent
6656e3d036
commit
04d6f42526
12
Crawler/CharacterInfoWindow.cpp
Normal file
12
Crawler/CharacterInfoWindow.cpp
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
#pragma once
|
||||||
|
#include "Crawler.h"
|
||||||
|
#include "DEFINES.h"
|
||||||
|
#include "Menu.h"
|
||||||
|
|
||||||
|
INCLUDE_game
|
||||||
|
typedef Attribute A;
|
||||||
|
|
||||||
|
void Menu::InitializeCharacterInfoWindow(){
|
||||||
|
Menu*characterInfoWindow=CreateMenu(INVENTORY,CENTERED,game->GetScreenSize()-vi2d{4,4});
|
||||||
|
|
||||||
|
}
|
@ -105,6 +105,11 @@ bool Crawler::OnUserCreate(){
|
|||||||
camera.EnableWorldBoundary(false);
|
camera.EnableWorldBoundary(false);
|
||||||
|
|
||||||
ItemInfo::InitializeItems();
|
ItemInfo::InitializeItems();
|
||||||
|
|
||||||
|
InitializeGraphics();
|
||||||
|
|
||||||
|
Menu::InitializeMenus();
|
||||||
|
|
||||||
Inventory::AddItem("Small Health Potion",16);
|
Inventory::AddItem("Small Health Potion",16);
|
||||||
Inventory::AddItem("Large Health Potion",3);
|
Inventory::AddItem("Large Health Potion",3);
|
||||||
Inventory::AddItem("Medium Mana Potion",1);
|
Inventory::AddItem("Medium Mana Potion",1);
|
||||||
@ -121,20 +126,9 @@ bool Crawler::OnUserCreate(){
|
|||||||
Inventory::AddItem("Dummy Item 11",8);
|
Inventory::AddItem("Dummy Item 11",8);
|
||||||
Inventory::AddItem("Dummy Item 12",3);
|
Inventory::AddItem("Dummy Item 12",3);
|
||||||
Inventory::AddItem("Dummy Item 13",6);
|
Inventory::AddItem("Dummy Item 13",6);
|
||||||
Inventory::AddItem("Dummy Item 14",192);
|
|
||||||
Inventory::AddItem("Dummy Item 15",35);
|
|
||||||
Inventory::AddItem("Dummy Item 16",6);
|
|
||||||
Inventory::AddItem("Dummy Item 17",3);
|
|
||||||
Inventory::AddItem("Dummy Item 18",1);
|
|
||||||
Inventory::AddItem("Dummy Item 19",8);
|
|
||||||
Inventory::AddItem("Dummy Item 20",4);
|
|
||||||
Inventory::AddItem("Bandages",10);
|
Inventory::AddItem("Bandages",10);
|
||||||
Inventory::AddItem("Blue Slime Remains",22);
|
Inventory::AddItem("Blue Slime Remains",22);
|
||||||
|
|
||||||
InitializeGraphics();
|
|
||||||
|
|
||||||
Menu::InitializeMenus();
|
|
||||||
|
|
||||||
Monster::InitializeStrategies();
|
Monster::InitializeStrategies();
|
||||||
//Animations
|
//Animations
|
||||||
sig::Animation::InitializeAnimations();
|
sig::Animation::InitializeAnimations();
|
||||||
|
@ -308,6 +308,7 @@
|
|||||||
<ClCompile Include="Animation.cpp" />
|
<ClCompile Include="Animation.cpp" />
|
||||||
<ClCompile Include="Arrow.cpp" />
|
<ClCompile Include="Arrow.cpp" />
|
||||||
<ClCompile Include="Bullet.cpp" />
|
<ClCompile Include="Bullet.cpp" />
|
||||||
|
<ClCompile Include="CharacterInfoWindow.cpp" />
|
||||||
<ClCompile Include="ChargedArrow.cpp" />
|
<ClCompile Include="ChargedArrow.cpp" />
|
||||||
<ClCompile Include="Crawler.cpp" />
|
<ClCompile Include="Crawler.cpp" />
|
||||||
<ClCompile Include="DamageNumber.cpp" />
|
<ClCompile Include="DamageNumber.cpp" />
|
||||||
@ -378,6 +379,7 @@
|
|||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Image Include="assets\heart.ico" />
|
<Image Include="assets\heart.ico" />
|
||||||
|
<Image Include="assets\menus\Character_Info.png" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ResourceCompile Include="Crawler.rc" />
|
<ResourceCompile Include="Crawler.rc" />
|
||||||
|
@ -55,6 +55,9 @@
|
|||||||
<Filter Include="Configurations\Items">
|
<Filter Include="Configurations\Items">
|
||||||
<UniqueIdentifier>{09fc0cbe-06f7-4fdf-944c-9833066bb9c8}</UniqueIdentifier>
|
<UniqueIdentifier>{09fc0cbe-06f7-4fdf-944c-9833066bb9c8}</UniqueIdentifier>
|
||||||
</Filter>
|
</Filter>
|
||||||
|
<Filter Include="Documentation\Menus">
|
||||||
|
<UniqueIdentifier>{bea40439-f3a2-42f8-be1a-c0a815007075}</UniqueIdentifier>
|
||||||
|
</Filter>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClInclude Include="olcPixelGameEngine.h">
|
<ClInclude Include="olcPixelGameEngine.h">
|
||||||
@ -326,6 +329,9 @@
|
|||||||
<ClCompile Include="InventoryWindow.cpp">
|
<ClCompile Include="InventoryWindow.cpp">
|
||||||
<Filter>Source Files\Interface</Filter>
|
<Filter>Source Files\Interface</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
|
<ClCompile Include="CharacterInfoWindow.cpp">
|
||||||
|
<Filter>Source Files\Interface</Filter>
|
||||||
|
</ClCompile>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<None Include="cpp.hint" />
|
<None Include="cpp.hint" />
|
||||||
@ -397,6 +403,9 @@
|
|||||||
<Image Include="assets\heart.ico">
|
<Image Include="assets\heart.ico">
|
||||||
<Filter>Resource Files</Filter>
|
<Filter>Resource Files</Filter>
|
||||||
</Image>
|
</Image>
|
||||||
|
<Image Include="assets\menus\Character_Info.png">
|
||||||
|
<Filter>Documentation\Menus</Filter>
|
||||||
|
</Image>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ResourceCompile Include="Crawler.rc">
|
<ResourceCompile Include="Crawler.rc">
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#include "Crawler.h"
|
#include "Crawler.h"
|
||||||
#include "DEFINES.h"
|
|
||||||
#include "olcPixelGameEngine.h"
|
#include "olcPixelGameEngine.h"
|
||||||
#include "safemap.h"
|
#include "safemap.h"
|
||||||
#include "Item.h"
|
#include "Item.h"
|
||||||
@ -8,39 +7,27 @@
|
|||||||
#include "MenuLabel.h"
|
#include "MenuLabel.h"
|
||||||
#include "ScrollableWindowComponent.h"
|
#include "ScrollableWindowComponent.h"
|
||||||
|
|
||||||
INCLUDE_GFX
|
|
||||||
typedef Attribute A;
|
typedef Attribute A;
|
||||||
|
|
||||||
void Menu::InitializeInventoryWindow(){
|
void Menu::InitializeInventoryWindow(){
|
||||||
constexpr int invWidth=5;
|
int invWidth="ThemeGlobal.InventoryWidth"_I;
|
||||||
constexpr int initialInvHeight=3;
|
int initialInvHeight="ThemeGlobal.InventoryHeight"_I;
|
||||||
|
|
||||||
constexpr int itemSpacing=8;
|
int itemSpacing="ThemeGlobal.InventoryItemSpacing"_I;
|
||||||
constexpr int buttonSize=24;
|
int buttonSize="ThemeGlobal.InventoryButtonSize"_I;
|
||||||
constexpr int totalSpacing=buttonSize+itemSpacing;
|
int totalSpacing=buttonSize+itemSpacing;
|
||||||
|
|
||||||
vf2d windowSize={totalSpacing*invWidth-itemSpacing+2+24,totalSpacing*(3+1)-itemSpacing+24}; //Need space for the button.
|
vf2d windowSize={float(totalSpacing*invWidth-itemSpacing+2+24),float(totalSpacing*(3+1)-itemSpacing+24)}; //Need space for the button.
|
||||||
|
|
||||||
Menu*inventoryWindow=CreateMenu(INVENTORY,CENTERED,windowSize);
|
Menu*inventoryWindow=CreateMenu(INVENTORY,CENTERED,windowSize);
|
||||||
|
|
||||||
ScrollableWindowComponent*inventory=new ScrollableWindowComponent(INVENTORY,{{1,0},{windowSize.x,totalSpacing*3-itemSpacing}},nullptr,[](MenuFuncData data){});
|
ScrollableWindowComponent*inventory=new ScrollableWindowComponent(INVENTORY,{{1,0},{windowSize.x,float(totalSpacing*3-itemSpacing)}},nullptr,[](MenuFuncData data){});
|
||||||
inventoryWindow->AddComponent("inventory",inventory);
|
inventoryWindow->AddComponent("inventory",inventory);
|
||||||
|
|
||||||
MenuFunc useItemFunc=[](MenuFuncData data){
|
//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.
|
||||||
MenuItemButton*button=(MenuItemButton*)data.component;
|
|
||||||
button->UseItem();
|
|
||||||
};
|
|
||||||
|
|
||||||
for(int i=0;i<Inventory::get("Consumables").size();i++){
|
MenuLabel*itemNameLabel=new MenuLabel{INVENTORY,geom2d::rect<float>(vf2d{2,float(initialInvHeight*totalSpacing-4)},windowSize),"",false,true};
|
||||||
int x=i%invWidth;
|
|
||||||
int y=i/invWidth;
|
|
||||||
int itemIndex=y*invWidth+x;
|
|
||||||
MenuItemButton*button=new MenuItemButton{INVENTORY,{{float(totalSpacing*x),float(totalSpacing*y)},{float(buttonSize),float(buttonSize)}},Inventory::get("Consumables"),itemIndex,useItemFunc};
|
|
||||||
inventory->AddComponent(inventoryWindow,"item"+std::to_string(itemIndex),button);
|
|
||||||
}
|
|
||||||
|
|
||||||
MenuLabel*itemNameLabel=new MenuLabel{INVENTORY,geom2d::rect<float>(vf2d{2,initialInvHeight*totalSpacing-4},windowSize),"",false,true};
|
|
||||||
inventoryWindow->AddComponent("itemName",itemNameLabel);
|
inventoryWindow->AddComponent("itemName",itemNameLabel);
|
||||||
MenuLabel*itemDescriptionLabel=new MenuLabel{INVENTORY,geom2d::rect<float>(vf2d{2,initialInvHeight*totalSpacing+itemSpacing},{windowSize.x-4,windowSize.y-108}),"",true,true};
|
MenuLabel*itemDescriptionLabel=new MenuLabel{INVENTORY,geom2d::rect<float>(vf2d{2,float(initialInvHeight*totalSpacing+itemSpacing)},{windowSize.x-4,windowSize.y-108}),"",true,true};
|
||||||
inventoryWindow->AddComponent("itemDescription",itemDescriptionLabel);
|
inventoryWindow->AddComponent("itemDescription",itemDescriptionLabel);
|
||||||
}
|
}
|
@ -3,6 +3,7 @@
|
|||||||
#include "safemap.h"
|
#include "safemap.h"
|
||||||
#include "DEFINES.h"
|
#include "DEFINES.h"
|
||||||
#include "Crawler.h"
|
#include "Crawler.h"
|
||||||
|
#include "Menu.h"
|
||||||
|
|
||||||
INCLUDE_game
|
INCLUDE_game
|
||||||
INCLUDE_DATA
|
INCLUDE_DATA
|
||||||
@ -159,6 +160,9 @@ void Inventory::RemoveItem(IT it,uint32_t amt){
|
|||||||
}
|
}
|
||||||
sortedList.erase(sortedList.begin()+count);
|
sortedList.erase(sortedList.begin()+count);
|
||||||
_inventory.erase(it);
|
_inventory.erase(it);
|
||||||
|
ITCategory cat=ITEM_DATA[it].category;
|
||||||
|
//Callback for GUI inventories.
|
||||||
|
Menu::InventorySlotsUpdated(cat);
|
||||||
}else{
|
}else{
|
||||||
_inventory.at(it).amt-=amt;
|
_inventory.at(it).amt-=amt;
|
||||||
}
|
}
|
||||||
@ -170,6 +174,8 @@ std::vector<IT>&Inventory::get(ITCategory itemCategory){
|
|||||||
|
|
||||||
void Inventory::InsertIntoSortedInv(IT item){
|
void Inventory::InsertIntoSortedInv(IT item){
|
||||||
sortedInv.at(ITEM_DATA[item].category).push_back(item);
|
sortedInv.at(ITEM_DATA[item].category).push_back(item);
|
||||||
|
//This should be a callback to menus that we need to update the interface with another item slot since a new one has appeared.
|
||||||
|
Menu::InventorySlotsUpdated(ITEM_DATA[item].category);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Inventory::ExecuteAction(IT item){
|
bool Inventory::ExecuteAction(IT item){
|
||||||
|
@ -2,6 +2,9 @@
|
|||||||
#include "MenuComponent.h"
|
#include "MenuComponent.h"
|
||||||
#include "DEFINES.h"
|
#include "DEFINES.h"
|
||||||
#include "safemap.h"
|
#include "safemap.h"
|
||||||
|
#include "Item.h"
|
||||||
|
#include "MenuItemButton.h"
|
||||||
|
#include "ScrollableWindowComponent.h"
|
||||||
|
|
||||||
bool Menu::MOUSE_NAVIGATION=true;
|
bool Menu::MOUSE_NAVIGATION=true;
|
||||||
std::vector<Menu*>Menu::stack;
|
std::vector<Menu*>Menu::stack;
|
||||||
@ -32,11 +35,13 @@ void Menu::InitializeMenus(){
|
|||||||
std::cout<<"WARNING! Menu Type "<<type<<" does not exist!"<<std::endl;
|
std::cout<<"WARNING! Menu Type "<<type<<" does not exist!"<<std::endl;
|
||||||
throw;
|
throw;
|
||||||
}
|
}
|
||||||
|
//Lock up everything once it's done.
|
||||||
|
menus[type]->buttons.SetInitialized();
|
||||||
|
menus[type]->keyboardButtons.SetInitialized();
|
||||||
for(auto&key:menus[type]->components){
|
for(auto&key:menus[type]->components){
|
||||||
MenuComponent*component=key.second;
|
MenuComponent*component=key.second;
|
||||||
component->AfterCreate();
|
component->AfterCreate();
|
||||||
}
|
}
|
||||||
menus[type]->components.SetInitialized(); //Lock all known components to prevent invalid access.
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -47,9 +52,33 @@ Menu*Menu::CreateMenu(MenuType type,vf2d pos,vf2d size){
|
|||||||
|
|
||||||
void Menu::AddComponent(std::string key,MenuComponent*button){
|
void Menu::AddComponent(std::string key,MenuComponent*button){
|
||||||
if(button->selectable){
|
if(button->selectable){
|
||||||
buttons[button->rect.pos.y].push_back(button);
|
buttons.Unlock();
|
||||||
|
if(buttons.count(button->rect.pos.y)){
|
||||||
|
buttons.at(button->rect.pos.y).push_back(button);
|
||||||
|
}else{
|
||||||
|
buttons[button->rect.pos.y].push_back(button);
|
||||||
|
}
|
||||||
if(button->selectableViaKeyboard){
|
if(button->selectableViaKeyboard){
|
||||||
keyboardButtons[button->rect.pos.y].push_back(button);
|
keyboardButtons.Unlock();
|
||||||
|
if(keyboardButtons.count(button->rect.pos.y)){
|
||||||
|
keyboardButtons.at(button->rect.pos.y).push_back(button);
|
||||||
|
}else{
|
||||||
|
keyboardButtons[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[button->rect.pos.y].begin(),buttons[button->rect.pos.y].end(),[](MenuComponent*c1,MenuComponent*c2){
|
||||||
|
return c1->GetPos().x<c2->GetPos().x;
|
||||||
|
});
|
||||||
|
if(keyboardButtons.count(button->rect.pos.y)){ //Keyboard buttons may not necessarily contain this key...Let's be sure.
|
||||||
|
std::sort(keyboardButtons[button->rect.pos.y].begin(),keyboardButtons[button->rect.pos.y].end(),[](MenuComponent*c1,MenuComponent*c2){
|
||||||
|
return c1->GetPos().x<c2->GetPos().x;
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}else{
|
}else{
|
||||||
displayComponents.push_back(button);
|
displayComponents.push_back(button);
|
||||||
@ -59,7 +88,9 @@ void Menu::AddComponent(std::string key,MenuComponent*button){
|
|||||||
throw;
|
throw;
|
||||||
}
|
}
|
||||||
button->name=key;
|
button->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[key]=button;
|
||||||
|
components.SetInitialized();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Menu::CheckClickAndPerformMenuSelect(Crawler*game){
|
void Menu::CheckClickAndPerformMenuSelect(Crawler*game){
|
||||||
@ -84,7 +115,6 @@ void Menu::HoverMenuSelect(Crawler*game){
|
|||||||
|
|
||||||
void Menu::MenuSelect(Crawler*game){
|
void Menu::MenuSelect(Crawler*game){
|
||||||
if(selection==vi2d{-1,-1}||buttons[selection.y][selection.x]->disabled)return;
|
if(selection==vi2d{-1,-1}||buttons[selection.y][selection.x]->disabled)return;
|
||||||
buttons[selection.y][selection.x]->onClick(MenuFuncData{*this,game,buttons[selection.y][selection.x]});
|
|
||||||
if(buttons[selection.y][selection.x]->menuDest!=MenuType::ENUM_END){
|
if(buttons[selection.y][selection.x]->menuDest!=MenuType::ENUM_END){
|
||||||
if(stack.size()<32){
|
if(stack.size()<32){
|
||||||
stack.push_back(menus[buttons[selection.y][selection.x]->menuDest]);//Navigate to the next menu.
|
stack.push_back(menus[buttons[selection.y][selection.x]->menuDest]);//Navigate to the next menu.
|
||||||
@ -93,6 +123,7 @@ void Menu::MenuSelect(Crawler*game){
|
|||||||
throw;
|
throw;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
buttons[selection.y][selection.x]->onClick(MenuFuncData{*this,game,buttons[selection.y][selection.x]});
|
||||||
}
|
}
|
||||||
|
|
||||||
void Menu::Update(Crawler*game){
|
void Menu::Update(Crawler*game){
|
||||||
@ -315,9 +346,9 @@ void Menu::KeyboardButtonNavigation(Crawler*game,vf2d menuPos){
|
|||||||
selectedItem=true;
|
selectedItem=true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if(key.first==selection.y&&
|
if(key.first==selection.y
|
||||||
//It's entirely possible this button was selected from the button selection list and may be out-of-bounds here.
|
//It's entirely possible this button was selected from the button selection list and may be out-of-bounds here.
|
||||||
selection.x>=0&&selection.x<keyboardButtons[selection.y].size()){
|
&&selection.x>=0&&selection.x<keyboardButtons[selection.y].size()){
|
||||||
found=true;
|
found=true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -528,4 +559,54 @@ void Menu::SetMouseNavigation(bool mouseNavigation){
|
|||||||
lastActiveMousePos=game->GetMousePos();
|
lastActiveMousePos=game->GetMousePos();
|
||||||
}
|
}
|
||||||
MOUSE_NAVIGATION=mouseNavigation;
|
MOUSE_NAVIGATION=mouseNavigation;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
void Menu::InventorySlotsUpdated(ITCategory cat){
|
||||||
|
//Update the inventory with a new inventory slot, since there's one additional item to interact with now.
|
||||||
|
std::vector<std::string>&inv=Inventory::get(cat);
|
||||||
|
MenuType inventoryWindow;
|
||||||
|
if(cat=="Consumables"){
|
||||||
|
inventoryWindow=INVENTORY;
|
||||||
|
}else
|
||||||
|
if(cat=="Equipment"){
|
||||||
|
//TODO: Update different inventories depending on what the item's category is.
|
||||||
|
std::cout<<"WARNING! Unimplemented inventory slot addition for category "<<cat<<"!"<<std::endl;
|
||||||
|
return; //Currenly a no-op
|
||||||
|
}else
|
||||||
|
if(cat=="Accesories"){
|
||||||
|
//TODO: Update different inventories depending on what the item's category is.
|
||||||
|
std::cout<<"WARNING! Unimplemented inventory slot addition for category "<<cat<<"!"<<std::endl;
|
||||||
|
return; //Currenly a no-op
|
||||||
|
}else
|
||||||
|
if(cat=="Materials"){
|
||||||
|
//TODO: Update different inventories depending on what the item's category is.
|
||||||
|
std::cout<<"WARNING! Unimplemented inventory slot addition for category "<<cat<<"!"<<std::endl;
|
||||||
|
return; //Currenly a no-op
|
||||||
|
}else{
|
||||||
|
throw;
|
||||||
|
std::cout<<"WARNING! Attempting to add an inventory to a category that does not exist. THIS SHOULD NOT BE HAPPENING!"<<std::endl;
|
||||||
|
}
|
||||||
|
//HACK ALERT!! We make a very bold assumption here that every inventory window will contain a ScrollableWindowComponent called "inventory"! Because it's a safemap, if it doesn't exist it will let us know as such, we won't include any extra checks here.
|
||||||
|
ScrollableWindowComponent*inventory=((ScrollableWindowComponent*)menus[inventoryWindow]->components["inventory"]);
|
||||||
|
//We only want to refresh the inventory slots if the component count no longer matches what's actually in our inventory.
|
||||||
|
if(inventory->ComponentCount()<inv.size()){//We need more space to display our items.
|
||||||
|
int invWidth="ThemeGlobal.InventoryWidth"_I;
|
||||||
|
int x=(inv.size()-1)%invWidth;
|
||||||
|
int y=(inv.size()-1)/invWidth;
|
||||||
|
int itemIndex=y*invWidth+x;
|
||||||
|
|
||||||
|
int buttonSize="ThemeGlobal.InventoryButtonSize"_I;
|
||||||
|
int totalSpacing="ThemeGlobal.InventoryItemSpacing"_I+buttonSize;
|
||||||
|
|
||||||
|
MenuFunc useItemFunc=[](MenuFuncData data){
|
||||||
|
MenuItemButton*button=(MenuItemButton*)data.component;
|
||||||
|
button->UseItem();
|
||||||
|
};
|
||||||
|
|
||||||
|
MenuItemButton*button=new MenuItemButton{inventoryWindow,{{float(totalSpacing*x),float(totalSpacing*y)},{float(buttonSize),float(buttonSize)}},Inventory::get("Consumables"),itemIndex,useItemFunc};
|
||||||
|
inventory->AddComponent(menus[inventoryWindow],"item"+std::to_string(itemIndex),button);
|
||||||
|
}else
|
||||||
|
if(inventory->ComponentCount()>inv.size()){ //There are empty spots, so let's clean up.
|
||||||
|
inventory->RemoveEmptySlots();
|
||||||
|
}
|
||||||
|
}
|
@ -1,11 +1,10 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#include "olcPixelGameEngine.h"
|
#include "Item.h"
|
||||||
#include <stack>
|
#include <stack>
|
||||||
#include "safemap.h"
|
#include "safemap.h"
|
||||||
#include "Theme.h"
|
#include "Theme.h"
|
||||||
#include "Attributable.h"
|
#include "Attributable.h"
|
||||||
#include "olcUTIL_Geometry2D.h"
|
#include "olcUTIL_Geometry2D.h"
|
||||||
#include <functional>
|
|
||||||
|
|
||||||
class Crawler;
|
class Crawler;
|
||||||
class MenuComponent;
|
class MenuComponent;
|
||||||
@ -25,8 +24,6 @@ class Menu:IAttributable{
|
|||||||
friend class Player;
|
friend class Player;
|
||||||
|
|
||||||
float buttonHoldTime=0;
|
float buttonHoldTime=0;
|
||||||
std::map<int/*Y*/,std::vector<MenuComponent*>>buttons; //Buttons are stored in rows followed by their column order.
|
|
||||||
std::map<int/*Y*/,std::vector<MenuComponent*>>keyboardButtons; //Button ordered storage for keyboard/menu
|
|
||||||
std::vector<MenuComponent*>displayComponents; //Components that are only for displaying purposes.
|
std::vector<MenuComponent*>displayComponents; //Components that are only for displaying purposes.
|
||||||
vi2d selection={-1,-1};
|
vi2d selection={-1,-1};
|
||||||
vi2d lastActiveMousePos={};
|
vi2d lastActiveMousePos={};
|
||||||
@ -50,11 +47,13 @@ public:
|
|||||||
static std::map<MenuType,Menu*>menus;
|
static std::map<MenuType,Menu*>menus;
|
||||||
vf2d pos; //Specify the upper-left corner of the window. Using CENTERED will always put this where the upper-left corner would center the window.
|
vf2d pos; //Specify the upper-left corner of the window. Using CENTERED will always put this where the upper-left corner would center the window.
|
||||||
vf2d size; //Size in tiles (24x24), every menu will be tile-based
|
vf2d size; //Size in tiles (24x24), every menu will be tile-based
|
||||||
|
safemap<int/*Y*/,std::vector<MenuComponent*>>buttons; //Buttons are stored in rows followed by their column order.
|
||||||
|
safemap<int/*Y*/,std::vector<MenuComponent*>>keyboardButtons; //Button ordered storage for keyboard/menu
|
||||||
|
|
||||||
static Theme&GetCurrentTheme();
|
static Theme&GetCurrentTheme();
|
||||||
bool UsingMouseNavigation();
|
bool UsingMouseNavigation();
|
||||||
void SetMouseNavigation(bool mouseNavigation);
|
void SetMouseNavigation(bool mouseNavigation);
|
||||||
|
static void InventorySlotsUpdated(ITCategory cat); //Called whenever an inventory item gets added to the player's inventory, thus increasing the total number of slots in our bag.
|
||||||
private:
|
private:
|
||||||
Menu(vf2d pos,vf2d size);
|
Menu(vf2d pos,vf2d size);
|
||||||
void HoverMenuSelect(Crawler*game);
|
void HoverMenuSelect(Crawler*game);
|
||||||
@ -65,6 +64,7 @@ private:
|
|||||||
static void InitializeTestMenu();
|
static void InitializeTestMenu();
|
||||||
static void InitializeTestSubMenu();
|
static void InitializeTestSubMenu();
|
||||||
static void InitializeInventoryWindow();
|
static void InitializeInventoryWindow();
|
||||||
|
static void InitializeCharacterInfoWindow();
|
||||||
//X (0-3), Y (0-2) for specific 9-patch tile (tiled version).
|
//X (0-3), Y (0-2) for specific 9-patch tile (tiled version).
|
||||||
static Renderable&GetPatchPart(int x,int y);
|
static Renderable&GetPatchPart(int x,int y);
|
||||||
|
|
||||||
|
@ -1,6 +1,8 @@
|
|||||||
#include "Crawler.h"
|
#include "Crawler.h"
|
||||||
#include "MenuComponent.h"
|
#include "MenuComponent.h"
|
||||||
|
|
||||||
|
typedef Attribute A;
|
||||||
|
|
||||||
MenuComponent::MenuComponent(MenuType parent,geom2d::rect<float>rect,std::string label,MenuFunc onClick,bool selectable,bool selectableViaKeyboard)
|
MenuComponent::MenuComponent(MenuType parent,geom2d::rect<float>rect,std::string label,MenuFunc onClick,bool selectable,bool selectableViaKeyboard)
|
||||||
:parentMenu(parent),rect(rect),label(label),menuDest(MenuType::ENUM_END),onClick(onClick),hoverEffect(0),selectable(selectable),selectableViaKeyboard(selectableViaKeyboard){}
|
:parentMenu(parent),rect(rect),label(label),menuDest(MenuType::ENUM_END),onClick(onClick),hoverEffect(0),selectable(selectable),selectableViaKeyboard(selectableViaKeyboard){}
|
||||||
|
|
||||||
@ -78,4 +80,8 @@ bool MenuComponent::PointWithinParent(MenuComponent*child,vi2d drawPos){
|
|||||||
|
|
||||||
bool MenuComponent::HandleOutsideDisabledButtonSelection(MenuComponent*disabledButton){
|
bool MenuComponent::HandleOutsideDisabledButtonSelection(MenuComponent*disabledButton){
|
||||||
return false;
|
return false;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
vf2d MenuComponent::GetPos(){
|
||||||
|
return rect.pos;
|
||||||
|
}
|
@ -25,6 +25,7 @@ protected:
|
|||||||
bool selectableViaKeyboard=true;
|
bool selectableViaKeyboard=true;
|
||||||
bool disabled=false; //If set to true, this component will not be rendered or updated.
|
bool disabled=false; //If set to true, this component will not be rendered or updated.
|
||||||
bool renderInMain=true; //If set to false, this component is the responsibility of some other windowing system and won't be rendered or updated via the main window loop.
|
bool renderInMain=true; //If set to false, this component is the responsibility of some other windowing system and won't be rendered or updated via the main window loop.
|
||||||
|
bool valid=true; //If set to false, this would cause the component to be removed.
|
||||||
virtual void Update(Crawler*game);
|
virtual void Update(Crawler*game);
|
||||||
virtual void Draw(Crawler*game,vf2d parentPos,bool focused);
|
virtual void Draw(Crawler*game,vf2d parentPos,bool focused);
|
||||||
virtual void DrawDecal(Crawler*game,vf2d parentPos,bool focused);
|
virtual void DrawDecal(Crawler*game,vf2d parentPos,bool focused);
|
||||||
@ -36,6 +37,7 @@ public:
|
|||||||
void _Update(Crawler*game);
|
void _Update(Crawler*game);
|
||||||
void _Draw(Crawler*game,vf2d parentPos,bool focused);
|
void _Draw(Crawler*game,vf2d parentPos,bool focused);
|
||||||
void _DrawDecal(Crawler*game,vf2d parentPos,bool focused);
|
void _DrawDecal(Crawler*game,vf2d parentPos,bool focused);
|
||||||
|
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.
|
//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.
|
||||||
//WARNING!!! This allocates a brand new component when successful!!! Be prepared to clear it!
|
//WARNING!!! This allocates a brand new component when successful!!! Be prepared to clear it!
|
||||||
virtual MenuComponent*PickUpDraggableItem();
|
virtual MenuComponent*PickUpDraggableItem();
|
||||||
|
@ -13,7 +13,6 @@ class MenuItemButton:public MenuIconButton{
|
|||||||
private:
|
private:
|
||||||
std::vector<IT>&invRef;
|
std::vector<IT>&invRef;
|
||||||
int inventoryIndex=0;
|
int inventoryIndex=0;
|
||||||
bool valid=false;
|
|
||||||
public:
|
public:
|
||||||
inline MenuItemButton(MenuType parent,geom2d::rect<float>rect,std::vector<IT>&invRef,int invIndex,MenuFunc onClick)
|
inline MenuItemButton(MenuType parent,geom2d::rect<float>rect,std::vector<IT>&invRef,int invIndex,MenuFunc onClick)
|
||||||
:MenuIconButton(parent,rect,invRef.size()>invIndex?ITEM_DATA.at(invRef[invIndex]).Decal():nullptr,onClick),invRef(invRef),inventoryIndex(invIndex){
|
:MenuIconButton(parent,rect,invRef.size()>invIndex?ITEM_DATA.at(invRef[invIndex]).Decal():nullptr,onClick),invRef(invRef),inventoryIndex(invIndex){
|
||||||
|
@ -127,6 +127,31 @@ protected:
|
|||||||
virtual bool GetHoverState(Crawler*game,MenuComponent*child)override{
|
virtual bool GetHoverState(Crawler*game,MenuComponent*child)override{
|
||||||
return geom2d::overlaps(geom2d::rect<float>{Menu::menus[parentMenu]->pos+rect.pos+child->rect.pos+V(A::SCROLL_OFFSET),child->rect.size},game->GetMousePos());
|
return geom2d::overlaps(geom2d::rect<float>{Menu::menus[parentMenu]->pos+rect.pos+child->rect.pos+V(A::SCROLL_OFFSET),child->rect.size},game->GetMousePos());
|
||||||
}
|
}
|
||||||
|
//Calculates the bounds of all components.
|
||||||
|
geom2d::rect<float> inline CalculateBounds(){
|
||||||
|
geom2d::rect<float>bounds;
|
||||||
|
for(MenuComponent*component:components){
|
||||||
|
if(component->rect.pos.x<bounds.pos.x){
|
||||||
|
float sizeIncrease=bounds.pos.x-component->rect.pos.x;
|
||||||
|
bounds.size.x+=sizeIncrease;
|
||||||
|
bounds.pos.x=component->rect.pos.x;
|
||||||
|
}
|
||||||
|
if(component->rect.right().start.x>bounds.right().start.x){
|
||||||
|
float sizeIncrease=component->rect.right().start.x-bounds.right().start.x;
|
||||||
|
bounds.size.x+=sizeIncrease;
|
||||||
|
}
|
||||||
|
if(component->rect.pos.y<bounds.pos.y){
|
||||||
|
float sizeIncrease=bounds.pos.y-component->rect.pos.y;
|
||||||
|
bounds.size.y+=sizeIncrease;
|
||||||
|
bounds.pos.y=component->rect.pos.y;
|
||||||
|
}
|
||||||
|
if(component->rect.bottom().start.y>bounds.bottom().start.y){
|
||||||
|
float sizeIncrease=component->rect.bottom().start.y-bounds.bottom().start.y;
|
||||||
|
bounds.size.y+=sizeIncrease;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return bounds;
|
||||||
|
}
|
||||||
public:
|
public:
|
||||||
void inline AddComponent(Menu*parentMenu,std::string key,MenuComponent*button){
|
void inline AddComponent(Menu*parentMenu,std::string key,MenuComponent*button){
|
||||||
components.push_back(button);
|
components.push_back(button);
|
||||||
@ -163,4 +188,53 @@ public:
|
|||||||
V(A::SCROLL_OFFSET).y+=rect.size.y/2;
|
V(A::SCROLL_OFFSET).y+=rect.size.y/2;
|
||||||
return true;
|
return true;
|
||||||
};
|
};
|
||||||
|
virtual inline size_t ComponentCount(){
|
||||||
|
return components.size();
|
||||||
|
}
|
||||||
|
virtual void RemoveButton(MenuComponent*button){
|
||||||
|
std::vector<MenuComponent*>&buttonList=Menu::menus[button->parentMenu]->buttons.at(button->GetPos().y);
|
||||||
|
std::vector<MenuComponent*>&keyboardButtonList=Menu::menus[button->parentMenu]->keyboardButtons.at(button->GetPos().y);
|
||||||
|
size_t removedCount=0;
|
||||||
|
removedCount+=std::erase(buttonList,button);
|
||||||
|
removedCount+=std::erase(keyboardButtonList,button);
|
||||||
|
if(removedCount!=2){
|
||||||
|
std::cout<<"WARNING! Attempted to remove buttons from button listing, but not found!";
|
||||||
|
throw;
|
||||||
|
}
|
||||||
|
if(buttonList.size()==0){
|
||||||
|
if(!Menu::menus[button->parentMenu]->buttons.erase(button->GetPos().y)){
|
||||||
|
std::cout<<"WARNING! Attempted to erase key "<<button->GetPos().y<<" from button map, but the list still exists!";
|
||||||
|
throw;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(keyboardButtonList.size()==0){
|
||||||
|
if(!Menu::menus[button->parentMenu]->keyboardButtons.erase(button->GetPos().y)){
|
||||||
|
std::cout<<"WARNING! Attempted to erase key "<<button->GetPos().y<<" from button map, but the list still exists!";
|
||||||
|
throw;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
virtual void RemoveEmptySlots(){
|
||||||
|
//Algorithm will iterate through all slots, finding blank slots. Each time a blank slot is found, all items will shift over by one, and then the last item will be removed. Repeat until all slots iterated through.
|
||||||
|
for(int i=0;i<components.size();i++){
|
||||||
|
MenuComponent*button=components[i];
|
||||||
|
button->Update(game); //We have to call update to update the validation state.
|
||||||
|
//HACK ALERT!! This only gets called on inventories...And only on inventory items, which would have the valid flag set. We only care about components that are inventory slots.
|
||||||
|
if(!button->valid){
|
||||||
|
for(int j=i;j<components.size()-1;j++){
|
||||||
|
//Take the item in the next slot and move it to this slot.
|
||||||
|
Menu::menus[components[j]->parentMenu]->components.at(components[j]->name)=components[j+1];
|
||||||
|
components[j]=components[j+1];
|
||||||
|
}
|
||||||
|
MenuComponent*lastButton=Menu::menus[components[components.size()-1]->parentMenu]->components.at(components[components.size()-1]->name);
|
||||||
|
//Now we have to fix up the keyboard button list.
|
||||||
|
RemoveButton(lastButton);
|
||||||
|
Menu::menus[components[components.size()-1]->parentMenu]->components.erase(components[components.size()-1]->name);
|
||||||
|
//Now delete the last slot.
|
||||||
|
components.erase(components.end()-1);
|
||||||
|
i--; //Subtract one from the index so we don't accidently skip slots.
|
||||||
|
}
|
||||||
|
}
|
||||||
|
bounds=CalculateBounds(); //Recalculate the bounds as it's possible the width/height of the component has changed.
|
||||||
|
}
|
||||||
};
|
};
|
@ -2,6 +2,7 @@
|
|||||||
#include "Crawler.h"
|
#include "Crawler.h"
|
||||||
#include "DEFINES.h"
|
#include "DEFINES.h"
|
||||||
#include "Menu.h"
|
#include "Menu.h"
|
||||||
|
#include "Item.h"
|
||||||
|
|
||||||
INCLUDE_MONSTER_LIST
|
INCLUDE_MONSTER_LIST
|
||||||
|
|
||||||
@ -13,6 +14,21 @@ void State_GameRun::OnUserUpdate(Crawler*game){
|
|||||||
if(game->encounterStarted&&game->totalBossEncounterMobs>0){
|
if(game->encounterStarted&&game->totalBossEncounterMobs>0){
|
||||||
game->encounterDuration+=game->GetElapsedTime();
|
game->encounterDuration+=game->GetElapsedTime();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if(game->GetKey(O).bPressed){
|
||||||
|
Inventory::AddItem("Dummy Item 14",192);
|
||||||
|
Inventory::AddItem("Dummy Item 15",35);
|
||||||
|
Inventory::AddItem("Dummy Item 16",6);
|
||||||
|
Inventory::AddItem("Dummy Item 17",3);
|
||||||
|
Inventory::AddItem("Dummy Item 18",1);
|
||||||
|
Inventory::AddItem("Dummy Item 19",8);
|
||||||
|
Inventory::AddItem("Dummy Item 20",4);
|
||||||
|
}
|
||||||
|
if(game->GetKey(P).bPressed){
|
||||||
|
Inventory::AddItem("Medium Mana Potion",1);
|
||||||
|
}
|
||||||
|
|
||||||
game->HandleUserInput(game->GetElapsedTime());
|
game->HandleUserInput(game->GetElapsedTime());
|
||||||
|
|
||||||
if(game->GetKey(T).bPressed){
|
if(game->GetKey(T).bPressed){
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
#define VERSION_MAJOR 0
|
#define VERSION_MAJOR 0
|
||||||
#define VERSION_MINOR 2
|
#define VERSION_MINOR 2
|
||||||
#define VERSION_PATCH 0
|
#define VERSION_PATCH 0
|
||||||
#define VERSION_BUILD 2127
|
#define VERSION_BUILD 2167
|
||||||
|
|
||||||
#define stringify(a) stringify_(a)
|
#define stringify(a) stringify_(a)
|
||||||
#define stringify_(a) #a
|
#define stringify_(a) #a
|
||||||
|
@ -13,6 +13,15 @@ ThemeGlobal
|
|||||||
|
|
||||||
# How far the mouse has to move before mouse mode becomes active from keyboard/controller input mode.
|
# How far the mouse has to move before mouse mode becomes active from keyboard/controller input mode.
|
||||||
MouseActivationDistance = 8
|
MouseActivationDistance = 8
|
||||||
|
|
||||||
|
# How many slots wide the inventory list is.
|
||||||
|
InventoryWidth = 5
|
||||||
|
# How tall the view is for the inventory window (before scrolling)
|
||||||
|
InventoryHeight = 3
|
||||||
|
# Space between each item slot.
|
||||||
|
InventoryItemSpacing = 8
|
||||||
|
# Size of each button.
|
||||||
|
InventoryButtonSize = 24
|
||||||
}
|
}
|
||||||
|
|
||||||
Themes
|
Themes
|
||||||
|
BIN
Crawler/assets/menus/Character_Info.png
Normal file
BIN
Crawler/assets/menus/Character_Info.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 25 KiB |
@ -6,7 +6,7 @@ class safemap{
|
|||||||
std::map<T,O>map;
|
std::map<T,O>map;
|
||||||
bool initialized=false;
|
bool initialized=false;
|
||||||
public:
|
public:
|
||||||
O&operator[](T key){
|
O&operator[](T key){
|
||||||
if(initialized&&map.count(key)==0){
|
if(initialized&&map.count(key)==0){
|
||||||
std::cout<<"WARNING! Trying to get non-existent key "<<key<<"!"<<std::endl;
|
std::cout<<"WARNING! Trying to get non-existent key "<<key<<"!"<<std::endl;
|
||||||
throw;
|
throw;
|
||||||
@ -35,6 +35,10 @@ public:
|
|||||||
size_t size(){
|
size_t size(){
|
||||||
return map.size();
|
return map.size();
|
||||||
}
|
}
|
||||||
|
//Unlocks the map so items can be added to it again. USE WITH CAUTION! And make sure to lock the map again.
|
||||||
|
void Unlock(){
|
||||||
|
initialized=false;
|
||||||
|
}
|
||||||
//Clears the entire map and unlocks the map so items can be added to it again.
|
//Clears the entire map and unlocks the map so items can be added to it again.
|
||||||
void Reset(){
|
void Reset(){
|
||||||
initialized=false;
|
initialized=false;
|
||||||
@ -46,6 +50,9 @@ public:
|
|||||||
auto end()const{
|
auto end()const{
|
||||||
return map.end();
|
return map.end();
|
||||||
}
|
}
|
||||||
|
size_t erase(const T&key){
|
||||||
|
return map.erase(key);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
//A class that has an initialization lock so that when the lock is activated, any further gets that are missing items in it will report themselves for easier debugging detection.
|
//A class that has an initialization lock so that when the lock is activated, any further gets that are missing items in it will report themselves for easier debugging detection.
|
||||||
|
Loading…
x
Reference in New Issue
Block a user