From cea84e573cc49d2fee809f6fbed6b926d027cb02 Mon Sep 17 00:00:00 2001 From: Kelsi Date: Sun, 2 Aug 2026 08:20:52 -0700 Subject: [PATCH] feat: bags, spellbook and quest log join the takeover, and their keys follow MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Each of this client's panels polls its own keybinding from inside its own draw, so a panel that is no longer drawn never sees the key — handing one over made it unopenable, which is worse than not handing it over at all. The key now reaches the replacement instead: FrameXML's own ToggleAllBags, ToggleSpellBook, ToggleQuestLog, ToggleCharacter and ToggleWorldMap. The character frame's own report from a live session shows all four of its frames built with sensible rects and hidden only because the sheet is closed, which is what made the missing key the next thing in the way. --- include/ui/framexml_takeover.hpp | 3 +++ src/core/application.cpp | 27 +++++++++++++++++++++++++++ src/ui/framexml_takeover.cpp | 10 +++++++++- src/ui/game_screen.cpp | 12 +++++++++--- 4 files changed, 48 insertions(+), 4 deletions(-) diff --git a/include/ui/framexml_takeover.hpp b/include/ui/framexml_takeover.hpp index 26fe7e5f..21c1bcf8 100644 --- a/include/ui/framexml_takeover.hpp +++ b/include/ui/framexml_takeover.hpp @@ -47,6 +47,9 @@ enum class UiElement { QuestTracker, WorldMap, CharacterFrame, + Bags, + Spellbook, + QuestLog, }; /// True when FrameXML is drawing this instead, so the client should not. diff --git a/src/core/application.cpp b/src/core/application.cpp index 64722153..8919256b 100644 --- a/src/core/application.cpp +++ b/src/core/application.cpp @@ -40,6 +40,8 @@ #include "rendering/m2_renderer.hpp" #include "rendering/minimap.hpp" #include "rendering/world_map.hpp" +#include "ui/framexml_takeover.hpp" +#include "ui/keybinding_manager.hpp" #include "rendering/quest_marker_renderer.hpp" #include "rendering/footprint_renderer.hpp" #include "rendering/loading_screen.hpp" @@ -3005,6 +3007,31 @@ void Application::render() { // is the question that was meant. const bool overClientUi = ImGui::IsWindowHovered(ImGuiHoveredFlags_AnyWindow); + // The keys that open what FrameXML now owns. + // + // Each of this client's panels polls its own keybinding from + // inside its own draw, so a panel that is no longer drawn never + // sees the key — handing one over made it unopenable. The key has + // to reach the replacement instead, which is FrameXML's own toggle + // for that panel. + { + using ui::UiElement; + using K = ui::KeybindingManager; + struct Route { UiElement element; K::Action action; const char* call; }; + static const Route kRoutes[] = { + {UiElement::Bags, K::Action::TOGGLE_BAGS, "ToggleAllBags()"}, + {UiElement::Spellbook, K::Action::TOGGLE_SPELLBOOK, "ToggleSpellBook(BOOKTYPE_SPELL)"}, + {UiElement::QuestLog, K::Action::TOGGLE_QUESTS, "ToggleQuestLog()"}, + {UiElement::CharacterFrame, K::Action::TOGGLE_CHARACTER_SCREEN, "ToggleCharacter(\"PaperDollFrame\")"}, + {UiElement::WorldMap, K::Action::TOGGLE_WORLD_MAP, "ToggleWorldMap()"}, + }; + for (const Route& r : kRoutes) { + if (!ui::frameXmlOwns(r.element)) continue; + if (!K::getInstance().isActionPressed(r.action)) continue; + engine->executeString(r.call); + } + } + // After layout, because the range follows from the rects it just // resolved, and before the mouse, so a scroll bar enabled by this // frame's range can be clicked in it. diff --git a/src/ui/framexml_takeover.cpp b/src/ui/framexml_takeover.cpp index b619aba0..cb14f8cb 100644 --- a/src/ui/framexml_takeover.cpp +++ b/src/ui/framexml_takeover.cpp @@ -14,7 +14,7 @@ namespace { struct Entry { UiElement element; std::string_view name; }; // One row per element, and the only place a name is written down. -constexpr std::array kElements{{ +constexpr std::array kElements{{ {UiElement::PlayerFrame, "playerframe"}, {UiElement::TargetFrame, "targetframe"}, {UiElement::PetFrame, "petframe"}, @@ -31,6 +31,9 @@ constexpr std::array kElements{{ {UiElement::QuestTracker, "questtracker"}, {UiElement::WorldMap, "worldmap"}, {UiElement::CharacterFrame, "characterframe"}, + {UiElement::Bags, "bags"}, + {UiElement::Spellbook, "spellbook"}, + {UiElement::QuestLog, "questlog"}, }}; /// Parsed once. An unknown name is reported rather than dropped: a typo would @@ -141,6 +144,11 @@ std::vector frameXmlCheckFrames() { "WorldMapZoneMinimapDropDown"}, {UiElement::CharacterFrame, "CharacterFrame PaperDollFrame CharacterModelFrame " "CharacterNameText CharacterHeadSlot"}, + {UiElement::Bags, "ContainerFrame1 ContainerFrame1Item1 " + "ContainerFrame1Name"}, + {UiElement::Spellbook, "SpellBookFrame SpellButton1 SpellBookSkillLineTab1"}, + {UiElement::QuestLog, "QuestLogFrame QuestLogListScrollFrame " + "QuestLogDetailScrollFrame"}, }; std::vector out; diff --git a/src/ui/game_screen.cpp b/src/ui/game_screen.cpp index e15f3127..df543171 100644 --- a/src/ui/game_screen.cpp +++ b/src/ui/game_screen.cpp @@ -555,9 +555,13 @@ void GameScreen::render(game::GameHandler& gameHandler) { renderWorldMap(gameHandler); - questLogScreen.render(gameHandler, inventoryScreen); + if (!frameXmlOwns(UiElement::QuestLog)) { + questLogScreen.render(gameHandler, inventoryScreen); + } - spellbookScreen.render(gameHandler, services_.assetManager); + if (!frameXmlOwns(UiElement::Spellbook)) { + spellbookScreen.render(gameHandler, services_.assetManager); + } // Insert spell link into chat if player shift-clicked a spellbook entry { @@ -625,7 +629,9 @@ void GameScreen::render(game::GameHandler& gameHandler) { } inventoryScreen.setGameHandler(&gameHandler); - inventoryScreen.render(gameHandler.getInventory(), gameHandler.getMoneyCopper()); + if (!frameXmlOwns(UiElement::Bags)) { + inventoryScreen.render(gameHandler.getInventory(), gameHandler.getMoneyCopper()); + } // Character screen (C key toggle handled inside render()) if (!frameXmlOwns(UiElement::CharacterFrame)) {