Inventory UI dirty flag system implemented. Release Build 12821.
Some checks failed
Emscripten Build / Build_and_Deploy_Web_Build (push) Has been cancelled

This commit is contained in:
sigonasr2 2026-03-02 13:32:42 -06:00
parent 974b4ad226
commit 004c435865
10 changed files with 44 additions and 33 deletions

View File

@ -405,6 +405,7 @@ namespace ItemTests
}
TEST_METHOD(UIUpdatesWhenItemsAreReceivedTest){
Inventory::AddItem("Health Potion"s,3);
Game::Update(0.f);
for(const auto&category:Item::GetItemCategories()|std::views::filter([](const std::string&category){return DATA["ItemCategory"][category].GetString()!="!HIDE";})){
const size_t itemCount{Component<RowInventoryScrollableWindowComponent>(MenuType::INVENTORY,std::format("Inventory Display - {}",category))->GetMainComponentCount()};
Assert::AreEqual(Inventory::get(category).size(),itemCount,util::wformat("UI component count in inventory window does not match player inventory item count in category {}",category).c_str());
@ -413,6 +414,7 @@ namespace ItemTests
TEST_METHOD(UIUpdatesWhenGameFileWithItemsIsLoadedTest){
SaveFile::SetSaveFileID(-1);
SaveFile::LoadGame();
Game::Update(0.f);
for(const auto&category:Item::GetItemCategories()|std::views::filter([](const std::string&category){return DATA["ItemCategory"][category].GetString()!="!HIDE";})){
const size_t itemCount{Component<RowInventoryScrollableWindowComponent>(MenuType::INVENTORY,std::format("Inventory Display - {}",category))->GetMainComponentCount()};
Assert::AreEqual(Inventory::get(category).size(),itemCount,util::wformat("UI component count in inventory window does not match player inventory item count in category {}",category).c_str());

View File

@ -483,6 +483,7 @@ bool AiL::OnUserUpdate(float fElapsedTime){
LoadingScreen::Update();
InputListener::Update();
Tutorial::Update();
Menu::_Update();
}
if(!game->TestingModeEnabled()){
@ -3587,13 +3588,6 @@ void AiL::ReduceBossEncounterMobCount(){
void AiL::RenderMenu(){
if(Menu::stack.size()>0){
if(Menu::alreadyClicked){ //Do not run a click event for this round.
Menu::alreadyClicked=false;
}else{
if(!MenuClicksDeactivated()&&!IsConsoleShowing()){
Menu::stack.back()->Update(this);
}
}
for(Menu*menu:Menu::stack){
if(menu->cover)FillRectDecal({0,0},WINDOW_SIZE,{0,0,0,uint8_t(255*0.4)});
menu->Draw(this);
@ -4117,7 +4111,6 @@ void AiL::InitializePlayerLevelCap(){
}
void AiL::ResetGame(bool changeToMainMenu){
resettingGame=true;
if(changeToMainMenu){
GameState::ChangeState(States::MAIN_MENU,0.5f);
}
@ -4149,7 +4142,6 @@ void AiL::ResetGame(bool changeToMainMenu){
minimap.SetMinimapMode(MinimapMode::SMALL);
minimap.EraseChunkData();
ClearDecalInstances();
resettingGame=false;
}
void AiL::OnRequestCompleted(const std::string_view receivedData)const{

View File

@ -352,7 +352,6 @@ public:
void PrecacheNewLevels();
bool savingFile=false;
bool resettingGame=false;
private:
std::vector<std::unique_ptr<Effect>>foregroundEffects,backgroundEffects,foregroundEffectsToBeInserted,backgroundEffectsToBeInserted;
std::vector<TileRenderData*>tilesWithCollision,tilesWithoutCollision;

View File

@ -52,12 +52,10 @@ DEFINE(RowPlayerArmor);
#pragma region Player Inventory Updates
std::function<void(InventoryScrollableWindowComponent&component,ITCategory cat)> InventoryCreator::Player_InventorySlotsUpdate=
[](InventoryScrollableWindowComponent&component,ITCategory cat){
if(!game->savingFile&&!game->resettingGame){
size_t invSize=Inventory::get(cat).size();
component.RemoveAllComponents();
for(std::weak_ptr<Item> item:Inventory::get(cat)){
component.AddButtonOnSlotUpdate(cat);
}
size_t invSize=Inventory::get(cat).size();
component.RemoveAllComponents();
for(std::weak_ptr<Item> item:Inventory::get(cat)){
component.AddButtonOnSlotUpdate(cat);
}
};
std::function<void(InventoryScrollableWindowComponent&component,ITCategory cat)> InventoryCreator::Player_AddButtonOnSlotUpdate=

View File

@ -580,7 +580,7 @@ bool Inventory::RemoveItem(std::weak_ptr<Item>itemRef,ITCategory inventory,uint3
}
//Callback for GUI inventories.
Menu::InventorySlotsUpdated(inventory);
Menu::InventorySlotsSetDirty();
return true;
}else{
if(itemRef.lock()->IsEquippable()){ //Since equipment doesn't stack, if we have more than one piece we have to still remove that piece.
@ -597,7 +597,7 @@ bool Inventory::RemoveItem(std::weak_ptr<Item>itemRef,ITCategory inventory,uint3
size_t invSize=inv.size();
inv.erase(inv.begin()+count); //Clears it from the detected sorted inventory as well!
if(invSize-1!=inv.size())ERR(std::format("WARNING! Did not properly erase {} from sorted inventory {}",itemName,inventory));
Menu::InventorySlotsUpdated(inventory);
Menu::InventorySlotsSetDirty();
return true;
}else{
itemRef.lock()->amt-=amt; //Don't touch the sorted inventory unless this is monster loot or stage loot because there's only "1" of this item in the entry list.
@ -626,7 +626,7 @@ const std::vector<std::shared_ptr<Item>>&Inventory::get(ITCategory itemCategory)
void Inventory::InsertIntoSortedInv(std::shared_ptr<Item>itemRef){
sortedInv.at(itemRef->Category()).push_back(itemRef);
//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(itemRef->Category());
Menu::InventorySlotsSetDirty();
}
void Inventory::InsertIntoStageInventoryCategory(std::shared_ptr<Item>itemRef,const bool monsterDrop){
@ -647,7 +647,7 @@ void Inventory::InsertIntoStageInventoryCategory(std::shared_ptr<Item>itemRef,co
inv.push_back(itemRef);
}
}
Menu::InventorySlotsUpdated(stageInventoryCategory);
Menu::InventorySlotsSetDirty();
}
bool Inventory::ExecuteAction(IT item,const std::optional<vf2d>targetingPos){

View File

@ -852,4 +852,24 @@ void Menu::ScrollDown(const MenuType type,const std::string&componentName,Data&r
const bool Menu::CanModifyEquipSlots(){
return game->GetCurrentMap().GetMapType()==Map::MapType::HUB||game->GetCurrentMap().GetMapType()==Map::MapType::WORLD_MAP;
}
void Menu::InventorySlotsSetDirty(){
inventorySlotsDirty=true;
}
void Menu::_Update(){
if(inventorySlotsDirty){
for(const auto&category:Item::GetItemCategories())InventorySlotsUpdated(category);
inventorySlotsDirty=false;
}
if(Menu::stack.size()>0){
if(alreadyClicked){ //Do not run a click event for this round.
alreadyClicked=false;
}else{
if(!game->MenuClicksDeactivated()&&!game->IsConsoleShowing()){
stack.back()->Update(game);
}
}
}
}

View File

@ -172,6 +172,7 @@ public:
static void CloseMenu();
static void CloseAllMenus();
static void CleanupAllMenus();
static void _Update();
static std::vector<Menu*>stack;
static std::string themeSelection;
static safeunorderedmap<std::string,Theme>themes;
@ -192,6 +193,7 @@ public:
static void AddMerchantInventoryListener(std::weak_ptr<MenuComponent>component,ITCategory category); //Adds a component to be in a given listener category.
static void AddEquipStatListener(std::weak_ptr<MenuComponent>component); //Adds a component to be in an equip stat listener. Will receive updates whenever stats are updated via equips.
static void AddChapterListener(std::weak_ptr<MenuComponent>component); //Adds a component to be in a chapter listener. Will receive updates anytime the chapter in-game changes.
static void InventorySlotsSetDirty();
vf2d center();
//Returns the last menu type created and last registered component, in case a component is detected as memory leaking, provides this information to each component for safety.
static std::pair<MenuType,std::string>GetMemoryLeakReportInfo();
@ -249,6 +251,8 @@ private:
InputHelper helpDisplay;
inline static bool inventorySlotsDirty{false};
static bool MOUSE_NAVIGATION;
static std::weak_ptr<MenuComponent>lastHover;
static bool nextMouseNavigationIsIgnored; //This variable will blatantly ignore the next mouse move signal to set mouse navigation to true, useful when toggling between windowed and full screen.

View File

@ -80,6 +80,7 @@ const size_t SaveFile::GetOnlineSaveFileCount(){
return metadata.GetKeys().size();
}
return count;
}
const bool SaveFile::SaveGame(){
@ -439,11 +440,6 @@ const void SaveFile::LoadGame(){
game->SetQuitAllowed(false);
const auto TurnOffSavingFlagAndUpdateInventoryUIs{[](){
game->SetQuitAllowed(true);
for(auto&category:Item::GetItemCategories())Menu::InventorySlotsUpdated(category);
}};
#ifdef __EMSCRIPTEN__
if(onlineMode){
Server_GetFile([&](std::string_view response){
@ -457,7 +453,7 @@ const void SaveFile::LoadGame(){
game->SetQuitAllowed(true);
LOG("WARNING! Could not load save file!");
}
TurnOffSavingFlagAndUpdateInventoryUIs();
game->SetQuitAllowed(true);
});
}else{
emscripten_idb_async_load("/assets",("save_file_path"_S+std::format("save.{:04}",saveFileID)).c_str(),0,[&TurnOffSavingFlagAndUpdateInventoryUIs](void*arg,void*data,int length){
@ -470,7 +466,7 @@ const void SaveFile::LoadGame(){
}
file.close();
_LoadFile();
TurnOffSavingFlagAndUpdateInventoryUIs();
game->SetQuitAllowed(true);
},[](void*arg){
LOG("Failed to load Save File "<<saveFileID<<"!");
game->SetQuitAllowed(true);
@ -478,7 +474,7 @@ const void SaveFile::LoadGame(){
}
#else
_LoadFile();
TurnOffSavingFlagAndUpdateInventoryUIs();
game->SetQuitAllowed(true);
#endif
}

View File

@ -39,7 +39,7 @@ All rights reserved.
#define VERSION_MAJOR 1
#define VERSION_MINOR 3
#define VERSION_PATCH 0
#define VERSION_BUILD 12812
#define VERSION_BUILD 12821
#define stringify(a) stringify_(a)
#define stringify_(a) #a

View File

@ -1,8 +1,8 @@
INTRO_MAP = 2026-02-26 21:44:13.5486385
HUB = 2026-02-26 21:44:13.5469761
INTRO_MAP = 2026-02-27 21:53:33.6543368
HUB = 2026-02-27 21:53:33.6533357
TEST_MAP = 2026-01-26 20:40:12.7201277
BOSS_1 = 2026-02-26 21:44:13.5449625
WORLD_MAP = 2026-02-26 21:44:13.5509566
BOSS_1 = 2026-02-27 21:53:33.6513354
WORLD_MAP = 2026-02-27 21:53:33.6568368
CAMPAIGN_1_1 = 2026-01-21 20:30:58.3723266
BOSS_1_B = 2024-09-13 21:28:58.8886132
BOSS_2 = 2026-01-21 20:30:58.4312572