mirror of
https://github.com/Kelsidavis/WoWee.git
synced 2026-07-31 09:49:53 -04:00
feat(ui): add combined bags toggle
This commit is contained in:
@@ -48,7 +48,7 @@ public:
|
||||
SettingsPanel& settingsPanel,
|
||||
SpellbookScreen& spellbookScreen,
|
||||
SpellIconFn getSpellIcon);
|
||||
void renderBagBar(game::GameHandler& gameHandler,
|
||||
bool renderBagBar(game::GameHandler& gameHandler,
|
||||
SettingsPanel& settingsPanel,
|
||||
InventoryScreen& inventoryScreen);
|
||||
void renderXpBar(game::GameHandler& gameHandler,
|
||||
|
||||
@@ -36,6 +36,8 @@ public:
|
||||
void toggleBag(int idx);
|
||||
void openAllBags();
|
||||
void closeAllBags();
|
||||
/// Toggle between independently positioned bag windows and one continuous grid.
|
||||
void toggleCombinedBags();
|
||||
void setSeparateBags(bool sep) { separateBags_ = sep; }
|
||||
bool isSeparateBags() const { return separateBags_; }
|
||||
void toggleCompactBags() { compactBags_ = !compactBags_; }
|
||||
|
||||
@@ -1248,20 +1248,21 @@ void ActionBarPanel::renderStanceBar(game::GameHandler& gameHandler,
|
||||
ImGui::PopStyleVar(4);
|
||||
}
|
||||
|
||||
void ActionBarPanel::renderBagBar(game::GameHandler& gameHandler,
|
||||
SettingsPanel& /*settingsPanel*/,
|
||||
bool ActionBarPanel::renderBagBar(game::GameHandler& gameHandler,
|
||||
SettingsPanel& settingsPanel,
|
||||
InventoryScreen& inventoryScreen) {
|
||||
ImVec2 displaySize = ImGui::GetIO().DisplaySize;
|
||||
float screenW = displaySize.x > 0.0f ? displaySize.x : 1280.0f;
|
||||
float screenH = displaySize.y > 0.0f ? displaySize.y : 720.0f;
|
||||
auto* assetMgr = services_.assetManager;
|
||||
bool settingChanged = false;
|
||||
|
||||
float slotSize = 42.0f;
|
||||
float spacing = 4.0f;
|
||||
float padding = 6.0f;
|
||||
|
||||
// 5 slots: backpack + 4 bags
|
||||
float barW = 5 * slotSize + 4 * spacing + padding * 2;
|
||||
// Mode toggle + backpack + 4 bags
|
||||
float barW = 6 * slotSize + 5 * spacing + padding * 2;
|
||||
float barH = slotSize + padding * 2;
|
||||
|
||||
// Position in bottom right corner
|
||||
@@ -1284,6 +1285,20 @@ void ActionBarPanel::renderBagBar(game::GameHandler& gameHandler,
|
||||
if (ImGui::Begin("##BagBar", nullptr, flags)) {
|
||||
auto& inv = gameHandler.getInventory();
|
||||
|
||||
// Keep this next to the bags so changing layouts never requires a trip
|
||||
// through settings. The saved setting remains the single source of truth.
|
||||
const bool combined = !inventoryScreen.isSeparateBags();
|
||||
if (ImGui::Button(combined ? "Split" : "All", ImVec2(slotSize, slotSize))) {
|
||||
inventoryScreen.toggleCombinedBags();
|
||||
settingsPanel.pendingSeparateBags = inventoryScreen.isSeparateBags();
|
||||
settingChanged = true;
|
||||
}
|
||||
if (ImGui::IsItemHovered()) {
|
||||
ImGui::SetTooltip(combined
|
||||
? "Split into separate bag windows"
|
||||
: "Combine all bag slots into one window");
|
||||
}
|
||||
|
||||
// Load backpack icon if needed
|
||||
if (!backpackIconTexture_ && assetMgr && assetMgr->isInitialized()) {
|
||||
auto blpData = assetMgr->readFile("Interface\\Buttons\\Button-Backpack-Up.blp");
|
||||
@@ -1303,7 +1318,7 @@ void ActionBarPanel::renderBagBar(game::GameHandler& gameHandler,
|
||||
|
||||
// Slots 1-4: Bag slots (leftmost)
|
||||
for (int i = 0; i < 4; ++i) {
|
||||
if (i > 0) ImGui::SameLine(0, spacing);
|
||||
ImGui::SameLine(0, spacing);
|
||||
ImGui::PushID(i + 1);
|
||||
|
||||
game::EquipSlot bagSlot = static_cast<game::EquipSlot>(static_cast<int>(game::EquipSlot::BAG1) + i);
|
||||
@@ -1524,6 +1539,7 @@ void ActionBarPanel::renderBagBar(game::GameHandler& gameHandler,
|
||||
fg->AddRect(p0, p1, IM_COL32(200, 200, 200, 255), 0.0f, 0, 2.0f);
|
||||
}
|
||||
}
|
||||
return settingChanged;
|
||||
}
|
||||
|
||||
void ActionBarPanel::renderXpBar(game::GameHandler& gameHandler,
|
||||
|
||||
@@ -414,7 +414,8 @@ void GameScreen::render(game::GameHandler& gameHandler) {
|
||||
[this](uint32_t id, pipeline::AssetManager* am) { return getSpellIcon(id, am); });
|
||||
actionBarPanel_.renderStanceBar(gameHandler, settingsPanel_, spellbookScreen,
|
||||
[this](uint32_t id, pipeline::AssetManager* am) { return getSpellIcon(id, am); });
|
||||
actionBarPanel_.renderBagBar(gameHandler, settingsPanel_, inventoryScreen);
|
||||
if (actionBarPanel_.renderBagBar(gameHandler, settingsPanel_, inventoryScreen))
|
||||
saveSettings();
|
||||
renderMicroMenu(gameHandler);
|
||||
actionBarPanel_.renderXpBar(gameHandler, settingsPanel_);
|
||||
actionBarPanel_.renderRepBar(gameHandler, settingsPanel_);
|
||||
|
||||
@@ -815,6 +815,20 @@ void InventoryScreen::closeAllBags() {
|
||||
for (auto& b : bagOpen_) b = false;
|
||||
}
|
||||
|
||||
void InventoryScreen::toggleCombinedBags() {
|
||||
if (separateBags_) {
|
||||
// Consolidating is an explicit request to see the inventory, even when
|
||||
// all of the individual windows happened to be closed.
|
||||
separateBags_ = false;
|
||||
open = true;
|
||||
} else {
|
||||
// Restore every physical bag as a visible, independently movable window.
|
||||
separateBags_ = true;
|
||||
openAllBags();
|
||||
open = true;
|
||||
}
|
||||
}
|
||||
|
||||
bool InventoryScreen::bagHasAnyItems(const game::Inventory& inventory, int bagIndex) const {
|
||||
int bagSize = inventory.getBagSize(bagIndex);
|
||||
if (bagSize <= 0) return false;
|
||||
@@ -1006,15 +1020,33 @@ void InventoryScreen::renderAggregateBags(game::Inventory& inventory, uint64_t m
|
||||
|
||||
constexpr float slotSize = 40.0f;
|
||||
constexpr int columns = 6;
|
||||
int rows = (inventory.getBackpackSize() + columns - 1) / columns;
|
||||
float bagContentH = rows * (slotSize + 4.0f) + 40.0f;
|
||||
|
||||
int totalSlots = inventory.getBackpackSize();
|
||||
int usedSlots = 0;
|
||||
for (int slot = 0; slot < inventory.getBackpackSize(); ++slot)
|
||||
usedSlots += !inventory.getBackpackSlot(slot).empty();
|
||||
for (int bag = 0; bag < game::Inventory::NUM_BAG_SLOTS; bag++) {
|
||||
int bagSize = inventory.getBagSize(bag);
|
||||
if (bagSize <= 0) continue;
|
||||
if (compactBags_ && !bagHasAnyItems(inventory, bag)) continue;
|
||||
int bagRows = (bagSize + columns - 1) / columns;
|
||||
bagContentH += bagRows * (slotSize + 4.0f) + 30.0f;
|
||||
totalSlots += bagSize;
|
||||
for (int slot = 0; slot < bagSize; ++slot)
|
||||
usedSlots += !inventory.getBagSlot(bag, slot).empty();
|
||||
}
|
||||
|
||||
int rows = (totalSlots + columns - 1) / columns;
|
||||
float bagContentH = rows * (slotSize + 4.0f) + 40.0f;
|
||||
int visibleKeySlots = 0;
|
||||
if (showKeyring_) {
|
||||
constexpr int keyColumns = 8;
|
||||
int lastOccupied = -1;
|
||||
for (int slot = inventory.getKeyringSize() - 1; slot >= 0; --slot) {
|
||||
if (!inventory.getKeyringSlot(slot).empty()) { lastOccupied = slot; break; }
|
||||
}
|
||||
visibleKeySlots = lastOccupied < 0 ? 0 : ((lastOccupied / keyColumns) + 1) * keyColumns;
|
||||
if (visibleKeySlots > 0) {
|
||||
constexpr float keySlotSize = 24.0f;
|
||||
const int keyRows = (visibleKeySlots + keyColumns - 1) / keyColumns;
|
||||
bagContentH += 30.0f + keyRows * (keySlotSize + 4.0f);
|
||||
}
|
||||
}
|
||||
|
||||
float windowW = columns * (slotSize + 4.0f) + 30.0f;
|
||||
@@ -1029,7 +1061,9 @@ void InventoryScreen::renderAggregateBags(game::Inventory& inventory, uint64_t m
|
||||
ImGuiWindowFlags flags = ImGuiWindowFlags_NoCollapse | ImGuiWindowFlags_NoResize;
|
||||
if (holdingItem || pickupPending_) flags |= ImGuiWindowFlags_NoMove;
|
||||
|
||||
bool windowVisible = ImGui::Begin("Bags", &open, flags);
|
||||
char windowTitle[64];
|
||||
snprintf(windowTitle, sizeof(windowTitle), "All Bags (%d/%d)###Bags", usedSlots, totalSlots);
|
||||
bool windowVisible = ImGui::Begin(windowTitle, &open, flags);
|
||||
if (!windowVisible) {
|
||||
ImGui::End();
|
||||
return;
|
||||
@@ -1043,7 +1077,43 @@ void InventoryScreen::renderAggregateBags(game::Inventory& inventory, uint64_t m
|
||||
ImGui::SetWindowPos(ImVec2(posX, posY));
|
||||
}
|
||||
|
||||
renderBackpackPanel(inventory, compactBags_);
|
||||
// Draw one uninterrupted grid while retaining each slot's real container
|
||||
// and index for pickup, use, split, destroy, and server swap operations.
|
||||
int gridIndex = 0;
|
||||
auto renderCombinedSlot = [&](const game::ItemSlot& slot, int backpackIndex,
|
||||
int bagIndex, int bagSlotIndex) {
|
||||
if (gridIndex % columns != 0) ImGui::SameLine();
|
||||
ImGui::PushID(gridIndex);
|
||||
renderItemSlot(inventory, slot, slotSize, nullptr,
|
||||
SlotKind::BACKPACK, backpackIndex, game::EquipSlot::NUM_SLOTS,
|
||||
bagIndex, bagSlotIndex);
|
||||
ImGui::PopID();
|
||||
++gridIndex;
|
||||
};
|
||||
|
||||
for (int slot = 0; slot < inventory.getBackpackSize(); ++slot)
|
||||
renderCombinedSlot(inventory.getBackpackSlot(slot), slot, -1, -1);
|
||||
for (int bag = 0; bag < game::Inventory::NUM_BAG_SLOTS; ++bag) {
|
||||
const int bagSize = inventory.getBagSize(bag);
|
||||
if (bagSize <= 0) continue;
|
||||
for (int slot = 0; slot < bagSize; ++slot)
|
||||
renderCombinedSlot(inventory.getBagSlot(bag, slot), -1, bag, slot);
|
||||
}
|
||||
|
||||
if (visibleKeySlots > 0) {
|
||||
constexpr float keySlotSize = 24.0f;
|
||||
constexpr int keyColumns = 8;
|
||||
ImGui::Spacing();
|
||||
ImGui::Separator();
|
||||
ImGui::TextColored(ui::colors::kDarkYellow, "Keyring");
|
||||
for (int slot = 0; slot < visibleKeySlots; ++slot) {
|
||||
if (slot % keyColumns != 0) ImGui::SameLine();
|
||||
ImGui::PushID(10000 + slot);
|
||||
renderItemSlot(inventory, inventory.getKeyringSlot(slot), keySlotSize, nullptr,
|
||||
SlotKind::BACKPACK, -1, game::EquipSlot::NUM_SLOTS);
|
||||
ImGui::PopID();
|
||||
}
|
||||
}
|
||||
|
||||
ImGui::Spacing();
|
||||
uint64_t gold = moneyCopper / 10000;
|
||||
@@ -1053,18 +1123,6 @@ void InventoryScreen::renderAggregateBags(game::Inventory& inventory, uint64_t m
|
||||
static_cast<unsigned long long>(gold),
|
||||
static_cast<unsigned long long>(silver),
|
||||
static_cast<unsigned long long>(copper));
|
||||
ImGui::SameLine();
|
||||
const char* collapseLabel = compactBags_ ? "Expand Empty" : "Collapse Empty";
|
||||
const float btnW = 92.0f;
|
||||
const float rightMargin = 8.0f;
|
||||
float rightX = ImGui::GetWindowContentRegionMax().x - btnW - rightMargin;
|
||||
if (rightX > ImGui::GetCursorPosX()) ImGui::SetCursorPosX(rightX);
|
||||
if (ImGui::SmallButton(collapseLabel)) {
|
||||
compactBags_ = !compactBags_;
|
||||
}
|
||||
if (ImGui::IsItemHovered()) {
|
||||
ImGui::SetTooltip("Toggle empty bag section visibility");
|
||||
}
|
||||
ImGui::End();
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user