Kelsidavis-WoWee/include/ui/inventory_screen.hpp
Kelsi affb5f4f04 Add item support for action bar with drag-from-inventory and key/click use
Allow picking up consumables from inventory and dropping them onto action bar
slots. Items display their icon or name, can be used via click or hotkey
(1-0,-,=), and cleared with right-click. Adds useItemById to find and use
items from backpack by item ID.
2026-02-06 19:17:35 -08:00

147 lines
5.3 KiB
C++

#pragma once
#include "game/inventory.hpp"
#include "game/character.hpp"
#include "game/world_packets.hpp"
#include <GL/glew.h>
#include <imgui.h>
#include <functional>
#include <memory>
#include <unordered_map>
namespace wowee {
namespace pipeline { class AssetManager; }
namespace rendering { class CharacterPreview; class CharacterRenderer; }
namespace game { class GameHandler; }
namespace ui {
class InventoryScreen {
public:
~InventoryScreen();
/// Render bags window (B key). Positioned at bottom of screen.
void render(game::Inventory& inventory, uint64_t moneyCopper);
/// Render character screen (C key). Standalone equipment window.
void renderCharacterScreen(game::GameHandler& gameHandler);
bool isOpen() const { return open; }
void toggle() { open = !open; }
void setOpen(bool o) { open = o; }
bool isCharacterOpen() const { return characterOpen; }
void toggleCharacter() { characterOpen = !characterOpen; }
void setCharacterOpen(bool o) { characterOpen = o; }
/// Enable vendor mode: right-clicking bag items sells them.
void setVendorMode(bool enabled, game::GameHandler* handler) {
vendorMode_ = enabled;
gameHandler_ = handler;
}
void setGameHandler(game::GameHandler* handler) { gameHandler_ = handler; }
/// Set asset manager for icon/model loading
void setAssetManager(pipeline::AssetManager* am) { assetManager_ = am; }
/// Store player appearance for character preview
void setPlayerAppearance(game::Race race, game::Gender gender,
uint8_t skin, uint8_t face,
uint8_t hairStyle, uint8_t hairColor,
uint8_t facialHair);
/// Mark the character preview as needing equipment update
void markPreviewDirty() { previewDirty_ = true; }
/// Update the preview animation (call each frame)
void updatePreview(float deltaTime);
/// Returns true if equipment changed since last call, and clears the flag.
bool consumeEquipmentDirty() { bool d = equipmentDirty; equipmentDirty = false; return d; }
/// Returns true if any inventory slot changed since last call, and clears the flag.
bool consumeInventoryDirty() { bool d = inventoryDirty; inventoryDirty = false; return d; }
private:
bool open = false;
bool characterOpen = false;
bool bKeyWasDown = false;
bool cKeyWasDown = false;
bool equipmentDirty = false;
bool inventoryDirty = false;
// Vendor sell mode
bool vendorMode_ = false;
game::GameHandler* gameHandler_ = nullptr;
// Asset manager for icons and preview
pipeline::AssetManager* assetManager_ = nullptr;
// Item icon cache: displayInfoId -> GL texture
std::unordered_map<uint32_t, GLuint> iconCache_;
public:
GLuint getItemIcon(uint32_t displayInfoId);
private:
// Character model preview
std::unique_ptr<rendering::CharacterPreview> charPreview_;
bool previewInitialized_ = false;
bool previewDirty_ = false;
// Stored player appearance for preview
game::Race playerRace_ = game::Race::HUMAN;
game::Gender playerGender_ = game::Gender::MALE;
uint8_t playerSkin_ = 0;
uint8_t playerFace_ = 0;
uint8_t playerHairStyle_ = 0;
uint8_t playerHairColor_ = 0;
uint8_t playerFacialHair_ = 0;
void initPreview();
void updatePreviewEquipment(game::Inventory& inventory);
// Drag-and-drop held item state
bool holdingItem = false;
game::ItemDef heldItem;
enum class HeldSource { NONE, BACKPACK, EQUIPMENT };
HeldSource heldSource = HeldSource::NONE;
int heldBackpackIndex = -1;
game::EquipSlot heldEquipSlot = game::EquipSlot::NUM_SLOTS;
void renderEquipmentPanel(game::Inventory& inventory);
void renderBackpackPanel(game::Inventory& inventory);
void renderStatsPanel(game::Inventory& inventory, uint32_t playerLevel);
// Slot rendering with interaction support
enum class SlotKind { BACKPACK, EQUIPMENT };
void renderItemSlot(game::Inventory& inventory, const game::ItemSlot& slot,
float size, const char* label,
SlotKind kind, int backpackIndex,
game::EquipSlot equipSlot);
void renderItemTooltip(const game::ItemDef& item);
// Held item helpers
void pickupFromBackpack(game::Inventory& inv, int index);
void pickupFromEquipment(game::Inventory& inv, game::EquipSlot slot);
void placeInBackpack(game::Inventory& inv, int index);
void placeInEquipment(game::Inventory& inv, game::EquipSlot slot);
void cancelPickup(game::Inventory& inv);
game::EquipSlot getEquipSlotForType(uint8_t inventoryType, game::Inventory& inv);
void renderHeldItem();
// Drop confirmation
bool dropConfirmOpen_ = false;
int dropBackpackIndex_ = -1;
std::string dropItemName_;
public:
static ImVec4 getQualityColor(game::ItemQuality quality);
/// Returns true if the user is currently holding an item (pickup cursor).
bool isHoldingItem() const { return holdingItem; }
/// Returns the item being held (only valid when isHoldingItem() is true).
const game::ItemDef& getHeldItem() const { return heldItem; }
/// Cancel the pickup, returning the item to its original slot.
void returnHeldItem(game::Inventory& inv) { cancelPickup(inv); }
};
} // namespace ui
} // namespace wowee