#pragma once #include "game/game_handler.hpp" #include "game/inventory.hpp" // WorldMap is now owned by Renderer, accessed via getWorldMap() #include "rendering/character_preview.hpp" #include "ui/inventory_screen.hpp" #include "ui/quest_log_screen.hpp" #include "ui/spellbook_screen.hpp" #include "ui/talent_screen.hpp" #include "ui/keybinding_manager.hpp" #include "ui/chat_panel.hpp" #include "ui/toast_manager.hpp" #include "ui/dialog_manager.hpp" #include "ui/settings_panel.hpp" #include "ui/combat_ui.hpp" #include "ui/social_panel.hpp" #include "ui/action_bar_panel.hpp" #include "ui/window_manager.hpp" #include "ui/ui_services.hpp" #include #include #include #include namespace wowee { namespace core { class AppearanceComposer; } namespace pipeline { class AssetManager; } namespace rendering { class Renderer; } namespace ui { /** * In-game screen UI * * Displays player info, entity list, chat, and game controls */ class GameScreen { public: GameScreen(); /** * Render the UI * @param gameHandler Reference to game handler */ void render(game::GameHandler& gameHandler); /** * Check if chat input is active */ bool isChatInputActive() const { return chatPanel_.isChatInputActive(); } void saveSettings(); void loadSettings(); // Dependency injection for extracted classes (Phase A singleton breaking) void setAppearanceComposer(core::AppearanceComposer* ac) { appearanceComposer_ = ac; } // Section 3.5: UIServices injection (Phase B singleton breaking) void setServices(const UIServices& services); private: // Injected UI services (Section 3.5 Phase B - replaces getInstance() calls) UIServices services_; // Legacy pointer for Phase A compatibility (will be removed when all callsites migrate) core::AppearanceComposer* appearanceComposer_ = nullptr; // Chat panel (extracted from GameScreen — owns all chat state and rendering) ChatPanel chatPanel_; // Toast manager (extracted from GameScreen — owns all toast/notification state and rendering) ToastManager toastManager_; // Dialog manager (extracted from GameScreen — owns all popup/dialog rendering) DialogManager dialogManager_; // Settings panel (extracted from GameScreen — owns all settings UI and config state) SettingsPanel settingsPanel_; // Combat UI (extracted from GameScreen — owns all combat overlay rendering) CombatUI combatUI_; // Social panel (extracted from GameScreen — owns all social/group UI rendering) SocialPanel socialPanel_; // Action bar panel (extracted from GameScreen — owns action/stance/bag/xp/rep bars) ActionBarPanel actionBarPanel_; // Window manager (extracted from GameScreen — owns NPC windows, popups, overlays) WindowManager windowManager_; // UI state bool showEntityWindow = false; bool showChatWindow = true; bool showMinimap_ = true; // M key toggles minimap bool showNameplates_ = true; // V key toggles enemy/NPC nameplates uint64_t nameplateCtxGuid_ = 0; // GUID of nameplate right-clicked (0 = none) ImVec2 nameplateCtxPos_{}; // Screen position of nameplate right-click uint32_t lastPlayerHp_ = 0; // Previous frame HP for damage flash detection float damageFlashAlpha_ = 0.0f; // Screen edge flash intensity (fades to 0) // UIErrorsFrame: WoW-style center-bottom error messages (spell fails, out of range, etc.) struct UIErrorEntry { std::string text; float age = 0.0f; }; std::vector uiErrors_; bool uiErrorCallbackSet_ = false; static constexpr float kUIErrorLifetime = 2.5f; bool castFailedCallbackSet_ = false; bool showPlayerInfo = false; bool showWorldMap_ = false; // W key toggles world map ImVec2 questTrackerPos_ = ImVec2(-1.0f, -1.0f); // <0 = use default ImVec2 questTrackerSize_ = ImVec2(220.0f, 200.0f); // saved size float questTrackerRightOffset_ = -1.0f; // pixels from right edge; <0 = use default bool questTrackerPosInit_ = false; /** * Render player info window */ void renderPlayerInfo(game::GameHandler& gameHandler); /** * Render entity list window */ void renderEntityList(game::GameHandler& gameHandler); /** * Render player unit frame (top-left) */ void renderPlayerFrame(game::GameHandler& gameHandler); /** * Render target frame */ void renderTargetFrame(game::GameHandler& gameHandler); void renderFocusFrame(game::GameHandler& gameHandler); /** * Render pet frame (below player frame when player has an active pet) */ void renderPetFrame(game::GameHandler& gameHandler); void renderTotemFrame(game::GameHandler& gameHandler); /** * Process targeting input (Tab, Escape, click) */ void processTargetInput(game::GameHandler& gameHandler); /** * Rebuild character geosets from current equipment state */ void updateCharacterGeosets(game::Inventory& inventory); /** * Re-composite character skin texture from current equipment */ void updateCharacterTextures(game::Inventory& inventory); void renderMirrorTimers(game::GameHandler& gameHandler); void renderUIErrors(game::GameHandler& gameHandler, float deltaTime); void renderQuestMarkers(game::GameHandler& gameHandler); void renderMinimapMarkers(game::GameHandler& gameHandler); void renderQuestObjectiveTracker(game::GameHandler& gameHandler); void renderNameplates(game::GameHandler& gameHandler); void renderDurabilityWarning(game::GameHandler& gameHandler); void takeScreenshot(game::GameHandler& gameHandler); /** * Inventory screen */ void renderWorldMap(game::GameHandler& gameHandler); InventoryScreen inventoryScreen; uint64_t inventoryScreenCharGuid_ = 0; // GUID of character inventory screen was initialized for QuestLogScreen questLogScreen; SpellbookScreen spellbookScreen; TalentScreen talentScreen; // WorldMap is now owned by Renderer (accessed via renderer->getWorldMap()) // Spell icon cache: spellId -> GL texture ID std::unordered_map spellIconCache_; // SpellIconID -> icon path (from SpellIcon.dbc) std::unordered_map spellIconPaths_; // SpellID -> SpellIconID (from Spell.dbc field 133) std::unordered_map spellIconIds_; bool spellIconDbLoaded_ = false; VkDescriptorSet getSpellIcon(uint32_t spellId, pipeline::AssetManager* am); // Death Knight rune bar: client-predicted fill (0.0=depleted, 1.0=ready) for smooth animation float runeClientFill_[6] = {1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f}; // Pet rename modal (triggered from pet frame context menu) bool petRenameOpen_ = false; char petRenameBuf_[16] = {}; // Left-click targeting: distinguish click from camera drag glm::vec2 leftClickPressPos_ = glm::vec2(0.0f); bool leftClickWasPress_ = false; bool appearanceCallbackSet_ = false; bool ghostOpacityStateKnown_ = false; bool ghostOpacityLastState_ = false; uint32_t ghostOpacityLastInstanceId_ = 0; void renderWeatherOverlay(game::GameHandler& gameHandler); public: void openDungeonFinder() { socialPanel_.showDungeonFinder_ = true; } ToastManager& toastManager() { return toastManager_; } }; } // namespace ui } // namespace wowee