# pragma once
# include "Menu.h"
# include "MenuComponent.h"
# include "MenuItemButton.h"
# include "Crawler.h"
# include "ScrollableWindowComponent.h"
typedef Attribute A ;
class InventoryScrollableWindowComponent : public ScrollableWindowComponent {
protected :
public :
inline InventoryScrollableWindowComponent ( MenuType parent , geom2d : : rect < float > rect , ComponentAttr attributes = ComponentAttr : : BACKGROUND | ComponentAttr : : OUTLINE )
: ScrollableWindowComponent ( parent , rect , attributes ) { }
protected :
virtual inline 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! " ;
}
if ( buttonList . size ( ) = = 0 ) {
if ( ! Menu : : menus [ button - > parentMenu ] - > buttons . erase ( button - > GetPos ( ) . y ) ) {
ERR ( " WARNING! Attempted to erase key " < < button - > GetPos ( ) . y < < " from button map, but the list still exists! " )
}
}
if ( keyboardButtonList . size ( ) = = 0 ) {
if ( ! Menu : : menus [ button - > parentMenu ] - > keyboardButtons . erase ( button - > GetPos ( ) . y ) ) {
ERR ( " WARNING! Attempted to erase key " < < button - > GetPos ( ) . y < < " from button map, but the list still exists! " )
}
}
}
inline 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.
delete lastButton ;
}
}
bounds = CalculateBounds ( ) ; //Recalculate the bounds as it's possible the width/height of the component has changed.
}
virtual inline void OnInventorySlotsUpdate ( ITCategory cat ) override {
std : : vector < std : : string > & inv = Inventory : : get ( cat ) ;
//We only want to refresh the inventory slots if the component count no longer matches what's actually in our inventory.
if ( components . size ( ) < 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 ;
if ( ! data . game - > GetPlayer ( ) - > GetLoadoutItem ( data . menu . I ( A : : LOADOUT_SLOT ) ) . IsBlank ( ) ) { //This loadout slot seems to have an item in it already, so deselect that one first.
data . game - > GetPlayer ( ) - > ClearLoadoutItem ( data . menu . I ( A : : LOADOUT_SLOT ) ) ;
for ( MenuComponent * component : components ) {
if ( component - > GetName ( ) . starts_with ( " item " ) ) {
MenuItemButton * button = ( MenuItemButton * ) component ; //HACK ALERT! This is probably an item since we populated item lists using this name for the components. So we assume these are MenuItemButton classes.
if ( button - > selected = = data . menu . I ( A : : LOADOUT_SLOT ) ) {
button - > selected = - 1 ;
}
}
}
}
button - > selected = data . menu . I ( A : : LOADOUT_SLOT ) ;
data . game - > GetPlayer ( ) - > SetLoadoutItem ( button - > selected , button - > GetItem ( ) . Name ( ) ) ;
return true ;
} ;
MenuItemButton * button = NEW MenuItemButton { parentMenu , { { float ( totalSpacing * x ) , float ( totalSpacing * y ) } , { float ( buttonSize ) , float ( buttonSize ) } } , Inventory : : get ( " Consumables " ) , itemIndex , useItemFunc } ;
AddComponent ( Menu : : menus [ parentMenu ] , " item " + std : : to_string ( itemIndex ) , button ) ;
} else
if ( components . size ( ) > inv . size ( ) ) { //There are empty spots, so let's clean up.
RemoveEmptySlots ( ) ;
}
}
virtual inline void Cleanup ( ) override {
}
} ;