|
|
|
|
#pragma region License
|
|
|
|
|
/*
|
|
|
|
|
License (OLC-3)
|
|
|
|
|
~~~~~~~~~~~~~~~
|
|
|
|
|
|
|
|
|
|
Copyright 2024 Joshua Sigona <sigonasr2@gmail.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 <EFBFBD> 2023 The FreeType
|
|
|
|
|
Project (www.freetype.org). Please see LICENSE_FT.txt for more information.
|
|
|
|
|
All rights reserved.
|
|
|
|
|
*/
|
|
|
|
|
#pragma endregion
|
|
|
|
|
#include "InventoryCreator.h"
|
|
|
|
|
#include "RowInventoryScrollableWindowComponent.h"
|
|
|
|
|
|
|
|
|
|
#define DEFINE(SubName) InventoryCreator InventoryCreator::SubName##_InventoryUpdate(&InventoryCreator::SubName##_InventorySlotsUpdate,&InventoryCreator::SubName##_AddButtonOnSlotUpdate);
|
|
|
|
|
|
|
|
|
|
DEFINE(Player);
|
|
|
|
|
DEFINE(RowPlayer);
|
|
|
|
|
DEFINE(RowMerchant);
|
|
|
|
|
DEFINE(RowPlayerWeapons);
|
|
|
|
|
DEFINE(RowPlayerArmor);
|
|
|
|
|
|
|
|
|
|
#pragma region Player Inventory Updates
|
|
|
|
|
std::function<void(InventoryScrollableWindowComponent&component,ITCategory cat)> InventoryCreator::Player_InventorySlotsUpdate=
|
|
|
|
|
[](InventoryScrollableWindowComponent&component,ITCategory cat){
|
|
|
|
|
size_t invSize=Inventory::get(cat).size();
|
|
|
|
|
//We only want to refresh the inventory slots if the component count no longer matches what's actually in our inventory.
|
|
|
|
|
if(component.components.size()<invSize){//We need more space to display our items.
|
|
|
|
|
component.AddButtonOnSlotUpdate(cat);
|
|
|
|
|
}else
|
|
|
|
|
if(component.components.size()>invSize){ //There are empty spots, so let's clean up.
|
|
|
|
|
component.RemoveAllComponents();
|
|
|
|
|
for(std::weak_ptr<Item> item:Inventory::get(cat)){
|
|
|
|
|
component.AddButtonOnSlotUpdate(cat);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
std::function<void(InventoryScrollableWindowComponent&component,ITCategory cat)> InventoryCreator::Player_AddButtonOnSlotUpdate=
|
|
|
|
|
[](InventoryScrollableWindowComponent&component,ITCategory cat){
|
|
|
|
|
size_t invSize=component.components.size()+1;
|
|
|
|
|
int invWidth=int((component.rect.size.x-12)/(float(component.options.size.x)+component.options.padding));
|
|
|
|
|
int x=int((invSize-1)%invWidth);
|
|
|
|
|
int y=int((invSize-1)/invWidth);
|
|
|
|
|
int itemIndex=y*invWidth+x;
|
|
|
|
|
|
|
|
|
|
vf2d buttonSize=component.options.size;
|
|
|
|
|
int totalSpacing=component.options.padding+buttonSize.x;
|
|
|
|
|
|
|
|
|
|
component.ADD("item_"+cat+"_"+std::to_string(itemIndex),MenuItemButton)(geom2d::rect<float>{{float(totalSpacing*x),float(totalSpacing*y)},buttonSize},Inventory::get(cat),itemIndex,component.inventoryButtonClickAction,component.inventoryButtonHoverAction,component.inventoryButtonMouseOutAction,component.parentMenu,component.itemNameLabelName,component.itemDescriptionLabelName,component.inventoryButtonsActive?IconButtonAttr::SELECTABLE:IconButtonAttr::NOT_SELECTABLE)END
|
|
|
|
|
->SetCompactDescriptions(component.compact);
|
|
|
|
|
};
|
|
|
|
|
#pragma endregion
|
|
|
|
|
|
|
|
|
|
#pragma region Row Inventory Player Updates
|
|
|
|
|
std::function<void(InventoryScrollableWindowComponent&component,ITCategory cat)> InventoryCreator::RowPlayer_InventorySlotsUpdate=Player_InventorySlotsUpdate;
|
|
|
|
|
std::function<void(InventoryScrollableWindowComponent&component,ITCategory cat)> InventoryCreator::RowPlayer_AddButtonOnSlotUpdate=
|
|
|
|
|
[](InventoryScrollableWindowComponent&component,ITCategory cat){
|
|
|
|
|
RowInventoryScrollableWindowComponent*c=DYNAMIC_CAST<RowInventoryScrollableWindowComponent*>(&component);
|
|
|
|
|
size_t invSize=c->components.size()+1;
|
|
|
|
|
int invWidth=int(c->rect.size.x/(float(c->options.size.x)+c->options.padding));
|
|
|
|
|
int x=int((invSize-1)%invWidth);
|
|
|
|
|
int y=int((invSize-1)/invWidth);
|
|
|
|
|
int itemIndex=y*invWidth+x;
|
|
|
|
|
|
|
|
|
|
vf2d buttonSize=c->options.size;
|
|
|
|
|
vf2d totalSpacing={c->options.padding+buttonSize.x,c->options.padding+buttonSize.y};
|
|
|
|
|
|
|
|
|
|
auto newItem=c->ADD("item_"+cat+"_"+std::to_string(itemIndex),RowItemDisplay)(geom2d::rect<float>{totalSpacing*vf2d{float(x),float(y)},buttonSize},Inventory::GetInventorySlot(cat,itemIndex),c->inventoryButtonClickAction,c->itemNameLabelName,c->itemDescriptionLabelName,c->inventoryButtonsActive?ButtonAttr::NONE:ButtonAttr::UNSELECTABLE)END;
|
|
|
|
|
newItem->SetCompactDescriptions(c->compact);
|
|
|
|
|
newItem->SetPriceLabelType(c->priceLabel);
|
|
|
|
|
newItem->SetHoverFunc(c->inventoryButtonHoverAction);
|
|
|
|
|
newItem->SetMouseOutFunc(c->inventoryButtonMouseOutAction);
|
|
|
|
|
};
|
|
|
|
|
#pragma endregion
|
|
|
|
|
|
|
|
|
|
#pragma region Row Merchant Updates
|
|
|
|
|
std::function<void(InventoryScrollableWindowComponent&component,ITCategory cat)> InventoryCreator::RowMerchant_InventorySlotsUpdate=
|
|
|
|
|
[](InventoryScrollableWindowComponent&component,ITCategory cat){
|
|
|
|
|
const std::vector<std::shared_ptr<Item>>&merchantInv=Merchant::GetCurrentTravelingMerchant().GetShopItems();
|
|
|
|
|
//We only want to refresh the inventory slots if the component count no longer matches what's actually in our inventory.
|
|
|
|
|
if(component.components.size()<merchantInv.size()){//We need more space to display our items.
|
|
|
|
|
component.AddButtonOnSlotUpdate(cat);
|
|
|
|
|
}else
|
|
|
|
|
if(component.components.size()>merchantInv.size()){ //There are empty spots, so let's clean up.
|
|
|
|
|
component.RemoveAllComponents();
|
|
|
|
|
for(std::shared_ptr<Item> item:merchantInv){
|
|
|
|
|
component.AddButtonOnSlotUpdate(cat);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
std::function<void(InventoryScrollableWindowComponent&component,ITCategory cat)> InventoryCreator::RowMerchant_AddButtonOnSlotUpdate=
|
|
|
|
|
[](InventoryScrollableWindowComponent&component,ITCategory cat){
|
|
|
|
|
const std::vector<std::shared_ptr<Item>>&merchantInv=Merchant::GetCurrentTravelingMerchant().GetShopItems();
|
|
|
|
|
RowInventoryScrollableWindowComponent*c=DYNAMIC_CAST<RowInventoryScrollableWindowComponent*>(&component);
|
|
|
|
|
|
|
|
|
|
size_t invSize=c->components.size()+1;
|
|
|
|
|
int invWidth=int(c->rect.size.x/(float(c->options.size.x)+c->options.padding));
|
|
|
|
|
int x=int((invSize-1)%invWidth);
|
|
|
|
|
int y=int((invSize-1)/invWidth);
|
|
|
|
|
int itemIndex=y*invWidth+x;
|
|
|
|
|
|
|
|
|
|
vf2d buttonSize=c->options.size;
|
|
|
|
|
vf2d totalSpacing={c->options.padding+buttonSize.x,c->options.padding+buttonSize.y};
|
|
|
|
|
|
|
|
|
|
auto newItem=c->ADD("merchant_item_"+cat+"_"+std::to_string(itemIndex),RowItemDisplay)(geom2d::rect<float>{totalSpacing*vf2d{float(x),float(y)},buttonSize},Merchant::GetCurrentTravelingMerchant().GetShopItems()[itemIndex],c->inventoryButtonClickAction,c->itemNameLabelName,c->itemDescriptionLabelName,c->inventoryButtonsActive?ButtonAttr::NONE:ButtonAttr::UNSELECTABLE)END;
|
|
|
|
|
newItem->SetCompactDescriptions(c->compact);
|
|
|
|
|
newItem->SetPriceLabelType(c->priceLabel);
|
|
|
|
|
newItem->SetHoverFunc(c->inventoryButtonHoverAction);
|
|
|
|
|
newItem->SetMouseOutFunc(c->inventoryButtonMouseOutAction);
|
|
|
|
|
};
|
|
|
|
|
#pragma endregion
|
|
|
|
|
|
|
|
|
|
#pragma region Row Player Weapons Updates
|
|
|
|
|
std::function<void(InventoryScrollableWindowComponent&component,ITCategory cat)> InventoryCreator::RowPlayerWeapons_InventorySlotsUpdate=
|
|
|
|
|
[](InventoryScrollableWindowComponent&component,ITCategory cat){
|
|
|
|
|
component.RemoveAllComponents();
|
|
|
|
|
component.AddButtonOnSlotUpdate(cat);
|
|
|
|
|
};
|
|
|
|
|
std::function<void(InventoryScrollableWindowComponent&component,ITCategory cat)> InventoryCreator::RowPlayerWeapons_AddButtonOnSlotUpdate=
|
|
|
|
|
[](InventoryScrollableWindowComponent&component,ITCategory cat){
|
|
|
|
|
std::vector<std::weak_ptr<Item>>weapons;
|
|
|
|
|
std::copy_if(Inventory::get("Equipment").begin(),Inventory::get("Equipment").end(),std::back_inserter(weapons),[](std::shared_ptr<Item>item){return item->IsWeapon();});
|
|
|
|
|
|
|
|
|
|
RowInventoryScrollableWindowComponent*c=DYNAMIC_CAST<RowInventoryScrollableWindowComponent*>(&component);
|
|
|
|
|
|
|
|
|
|
vf2d buttonSize=c->options.size;
|
|
|
|
|
vf2d totalSpacing={c->options.padding+buttonSize.x,c->options.padding+buttonSize.y};
|
|
|
|
|
|
|
|
|
|
for(std::weak_ptr<Item> weapon:weapons){
|
|
|
|
|
size_t invSize=c->components.size()+1;
|
|
|
|
|
int invWidth=int(c->rect.size.x/(float(c->options.size.x)+c->options.padding));
|
|
|
|
|
int x=int((invSize-1)%invWidth);
|
|
|
|
|
int y=int((invSize-1)/invWidth);
|
|
|
|
|
int itemIndex=y*invWidth+x;
|
|
|
|
|
auto newItem=c->ADD("item_Weapon_"+std::to_string(itemIndex),RowItemDisplay)(geom2d::rect<float>{totalSpacing*vf2d{float(x),float(y)},buttonSize},weapon,c->inventoryButtonClickAction,c->itemNameLabelName,c->itemDescriptionLabelName,c->inventoryButtonsActive?ButtonAttr::NONE:ButtonAttr::UNSELECTABLE)END;
|
|
|
|
|
newItem->SetCompactDescriptions(c->compact);
|
|
|
|
|
newItem->SetPriceLabelType(c->priceLabel);
|
|
|
|
|
newItem->SetHoverFunc(c->inventoryButtonHoverAction);
|
|
|
|
|
newItem->SetMouseOutFunc(c->inventoryButtonMouseOutAction);
|
|
|
|
|
newItem->SetCheckCraftingRequirements(true);
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
#pragma endregion
|
|
|
|
|
|
|
|
|
|
#pragma region Row Player Armor Updates
|
|
|
|
|
std::function<void(InventoryScrollableWindowComponent&component,ITCategory cat)> InventoryCreator::RowPlayerArmor_InventorySlotsUpdate=
|
|
|
|
|
[](InventoryScrollableWindowComponent&component,ITCategory cat){
|
|
|
|
|
component.RemoveAllComponents();
|
|
|
|
|
component.AddButtonOnSlotUpdate(cat);
|
|
|
|
|
};
|
|
|
|
|
std::function<void(InventoryScrollableWindowComponent&component,ITCategory cat)> InventoryCreator::RowPlayerArmor_AddButtonOnSlotUpdate=
|
|
|
|
|
[](InventoryScrollableWindowComponent&component,ITCategory cat){
|
|
|
|
|
std::vector<std::weak_ptr<Item>>armor;
|
|
|
|
|
std::copy_if(Inventory::get("Equipment").begin(),Inventory::get("Equipment").end(),std::back_inserter(armor),[](std::shared_ptr<Item>item){return item->IsArmor();});
|
|
|
|
|
|
|
|
|
|
RowInventoryScrollableWindowComponent*c=DYNAMIC_CAST<RowInventoryScrollableWindowComponent*>(&component);
|
|
|
|
|
|
|
|
|
|
vf2d buttonSize=c->options.size;
|
|
|
|
|
vf2d totalSpacing={c->options.padding+buttonSize.x,c->options.padding+buttonSize.y};
|
|
|
|
|
|
|
|
|
|
for(std::weak_ptr<Item> armor:armor){
|
|
|
|
|
size_t invSize=c->components.size()+1;
|
|
|
|
|
int invWidth=int(c->rect.size.x/(float(c->options.size.x)+c->options.padding));
|
|
|
|
|
int x=int((invSize-1)%invWidth);
|
|
|
|
|
int y=int((invSize-1)/invWidth);
|
|
|
|
|
int itemIndex=y*invWidth+x;
|
|
|
|
|
auto newItem=c->ADD("item_Armor_"+std::to_string(itemIndex),RowItemDisplay)(geom2d::rect<float>{totalSpacing*vf2d{float(x),float(y)},buttonSize},armor,c->inventoryButtonClickAction,c->itemNameLabelName,c->itemDescriptionLabelName,c->inventoryButtonsActive?ButtonAttr::NONE:ButtonAttr::UNSELECTABLE)END;
|
|
|
|
|
newItem->SetCompactDescriptions(c->compact);
|
|
|
|
|
newItem->SetPriceLabelType(c->priceLabel);
|
|
|
|
|
newItem->SetHoverFunc(c->inventoryButtonHoverAction);
|
|
|
|
|
newItem->SetMouseOutFunc(c->inventoryButtonMouseOutAction);
|
|
|
|
|
newItem->SetCheckCraftingRequirements(true);
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
#pragma endregion
|