From 8d78976904f6daccecd45bb0cb9fa19181f563b2 Mon Sep 17 00:00:00 2001 From: Kelsi Date: Fri, 3 Apr 2026 03:45:39 -0700 Subject: [PATCH] refactor(ui): extract shared helpers into ui_helpers.hpp MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit DRY up renderAuraRemaining, fmtDurationCompact, classColorVec4, classColorU32, entityClassId, classNameStr, kDispelNames, and kRaidMarkNames — duplicated across game_screen, social_panel, and combat_ui after the panel extraction refactors. --- include/ui/ui_helpers.hpp | 61 +++++++++++++++++++++++++++++++++++++++ src/ui/combat_ui.cpp | 12 ++------ src/ui/game_screen.cpp | 49 ++----------------------------- src/ui/social_panel.cpp | 45 ++--------------------------- 4 files changed, 67 insertions(+), 100 deletions(-) create mode 100644 include/ui/ui_helpers.hpp diff --git a/include/ui/ui_helpers.hpp b/include/ui/ui_helpers.hpp new file mode 100644 index 00000000..f3f6d08a --- /dev/null +++ b/include/ui/ui_helpers.hpp @@ -0,0 +1,61 @@ +#pragma once + +#include +#include +#include +#include "ui/ui_colors.hpp" +#include "game/entity.hpp" +#include "game/update_field_table.hpp" +#include "game/character.hpp" + +namespace wowee::ui::helpers { + +// ---- Duration / aura formatting ---- + +// Format a duration in seconds as compact text: "2h", "3:05", "42" +inline void fmtDurationCompact(char* buf, size_t sz, int secs) { + if (secs >= 3600) snprintf(buf, sz, "%dh", secs / 3600); + else if (secs >= 60) snprintf(buf, sz, "%d:%02d", secs / 60, secs % 60); + else snprintf(buf, sz, "%d", secs); +} + +// Render "Remaining: Xs" or "Remaining: Xm Ys" in a tooltip (light gray) +inline void renderAuraRemaining(int remainMs) { + if (remainMs <= 0) return; + int s = remainMs / 1000; + char buf[32]; + if (s < 60) snprintf(buf, sizeof(buf), "Remaining: %ds", s); + else snprintf(buf, sizeof(buf), "Remaining: %dm %ds", s / 60, s % 60); + ImGui::TextColored(colors::kLightGray, "%s", buf); +} + +// ---- Class color / name helpers ---- + +inline ImVec4 classColorVec4(uint8_t classId) { return getClassColor(classId); } +inline ImU32 classColorU32(uint8_t classId, int alpha = 255) { return getClassColorU32(classId, alpha); } + +inline const char* classNameStr(uint8_t classId) { + return game::getClassName(static_cast(classId)); +} + +// Extract class id from a unit's UNIT_FIELD_BYTES_0 update field. +// Returns 0 if the entity pointer is null or field is unset. +inline uint8_t entityClassId(const game::Entity* entity) { + if (!entity) return 0; + using UF = game::UF; + uint32_t bytes0 = entity->getField(game::fieldIndex(UF::UNIT_FIELD_BYTES_0)); + return static_cast((bytes0 >> 8) & 0xFF); +} + +// ---- Shared UI data tables ---- + +// Aura dispel-type names (indexed by dispelType 0-4) +inline constexpr const char* kDispelNames[] = { "", "Magic", "Curse", "Disease", "Poison" }; + +// Raid mark names with symbol prefixes (indexed 0-7: Star..Skull) +inline constexpr const char* kRaidMarkNames[] = { + "{*} Star", "{O} Circle", "{<>} Diamond", "{^} Triangle", + "{)} Moon", "{ } Square", "{x} Cross", "{8} Skull" +}; + +} // namespace wowee::ui::helpers diff --git a/src/ui/combat_ui.cpp b/src/ui/combat_ui.cpp index 0427f337..94b4da9d 100644 --- a/src/ui/combat_ui.cpp +++ b/src/ui/combat_ui.cpp @@ -8,6 +8,7 @@ #include "ui/settings_panel.hpp" #include "ui/spellbook_screen.hpp" #include "ui/ui_colors.hpp" +#include "ui/ui_helpers.hpp" #include "core/application.hpp" #include "core/logger.hpp" #include "core/coordinates.hpp" @@ -27,20 +28,11 @@ namespace { using namespace wowee::ui::colors; + using namespace wowee::ui::helpers; constexpr auto& kColorRed = kRed; constexpr auto& kColorGreen = kGreen; constexpr auto& kColorBrightGreen = kBrightGreen; constexpr auto& kColorYellow = kYellow; - - // Render "Remaining: Xs" or "Remaining: Xm Ys" in a tooltip (light gray) - void renderAuraRemaining(int remainMs) { - if (remainMs <= 0) return; - int s = remainMs / 1000; - char buf[32]; - if (s < 60) snprintf(buf, sizeof(buf), "Remaining: %ds", s); - else snprintf(buf, sizeof(buf), "Remaining: %dm %ds", s / 60, s % 60); - ImGui::TextColored(kLightGray, "%s", buf); - } } // anonymous namespace namespace wowee { diff --git a/src/ui/game_screen.cpp b/src/ui/game_screen.cpp index 23461ce3..d1681889 100644 --- a/src/ui/game_screen.cpp +++ b/src/ui/game_screen.cpp @@ -1,5 +1,6 @@ #include "ui/game_screen.hpp" #include "ui/ui_colors.hpp" +#include "ui/ui_helpers.hpp" #include "rendering/vk_context.hpp" #include "core/application.hpp" #include "core/appearance_composer.hpp" @@ -49,8 +50,8 @@ #include namespace { - // Common ImGui colors (aliases into local namespace for brevity) using namespace wowee::ui::colors; + using namespace wowee::ui::helpers; constexpr auto& kColorRed = kRed; constexpr auto& kColorGreen = kGreen; constexpr auto& kColorBrightGreen= kBrightGreen; @@ -58,61 +59,15 @@ namespace { constexpr auto& kColorGray = kGray; constexpr auto& kColorDarkGray = kDarkGray; - // Aura dispel-type names (indexed by dispelType 0-4) - constexpr const char* kDispelNames[] = { "", "Magic", "Curse", "Disease", "Poison" }; - // Abbreviated month names (indexed 0-11) constexpr const char* kMonthAbbrev[12] = { "Jan","Feb","Mar","Apr","May","Jun", "Jul","Aug","Sep","Oct","Nov","Dec" }; - // Raid mark names with symbol prefixes (indexed 0-7: Star..Skull) - constexpr const char* kRaidMarkNames[] = { - "{*} Star", "{O} Circle", "{<>} Diamond", "{^} Triangle", - "{)} Moon", "{ } Square", "{x} Cross", "{8} Skull" - }; - // Common ImGui window flags for popup dialogs const ImGuiWindowFlags kDialogFlags = ImGuiWindowFlags_NoCollapse | ImGuiWindowFlags_NoResize; - // Format a duration in seconds as compact text: "2h", "3:05", "42" - void fmtDurationCompact(char* buf, size_t sz, int secs) { - if (secs >= 3600) snprintf(buf, sz, "%dh", secs / 3600); - else if (secs >= 60) snprintf(buf, sz, "%d:%02d", secs / 60, secs % 60); - else snprintf(buf, sz, "%d", secs); - } - - // Render "Remaining: Xs" or "Remaining: Xm Ys" in a tooltip (light gray) - void renderAuraRemaining(int remainMs) { - if (remainMs <= 0) return; - int s = remainMs / 1000; - char buf[32]; - if (s < 60) snprintf(buf, sizeof(buf), "Remaining: %ds", s); - else snprintf(buf, sizeof(buf), "Remaining: %dm %ds", s / 60, s % 60); - ImGui::TextColored(kLightGray, "%s", buf); - } - - // Render gold/silver/copper amounts in WoW-canonical colors on the current ImGui line. - // Skips zero-value denominations (except copper, which is always shown when gold=silver=0). - // Aliases for shared class color helpers (wowee::ui namespace) - inline ImVec4 classColorVec4(uint8_t classId) { return wowee::ui::getClassColor(classId); } - inline ImU32 classColorU32(uint8_t classId, int alpha = 255) { return wowee::ui::getClassColorU32(classId, alpha); } - - // Extract class id from a unit's UNIT_FIELD_BYTES_0 update field. - // Returns 0 if the entity pointer is null or field is unset. - uint8_t entityClassId(const wowee::game::Entity* entity) { - if (!entity) return 0; - using UF = wowee::game::UF; - uint32_t bytes0 = entity->getField(wowee::game::fieldIndex(UF::UNIT_FIELD_BYTES_0)); - return static_cast((bytes0 >> 8) & 0xFF); - } - - // Alias for shared class name helper - const char* classNameStr(uint8_t classId) { - return wowee::game::getClassName(static_cast(classId)); - } - bool raySphereIntersect(const wowee::rendering::Ray& ray, const glm::vec3& center, float radius, float& tOut) { glm::vec3 oc = ray.origin - center; float b = glm::dot(oc, ray.direction); diff --git a/src/ui/social_panel.cpp b/src/ui/social_panel.cpp index 5a37fd8e..6d9af7c9 100644 --- a/src/ui/social_panel.cpp +++ b/src/ui/social_panel.cpp @@ -9,6 +9,7 @@ #include "ui/spellbook_screen.hpp" #include "ui/inventory_screen.hpp" #include "ui/ui_colors.hpp" +#include "ui/ui_helpers.hpp" #include "core/application.hpp" #include "core/logger.hpp" #include "rendering/renderer.hpp" @@ -26,55 +27,13 @@ namespace { using namespace wowee::ui::colors; + using namespace wowee::ui::helpers; constexpr auto& kColorRed = kRed; constexpr auto& kColorGreen = kGreen; constexpr auto& kColorBrightGreen = kBrightGreen; constexpr auto& kColorYellow = kYellow; constexpr auto& kColorGray = kGray; constexpr auto& kColorDarkGray = kDarkGray; - - // Render "Remaining: Xs" or "Remaining: Xm Ys" in a tooltip (light gray) - void renderAuraRemaining(int remainMs) { - if (remainMs <= 0) return; - int s = remainMs / 1000; - char buf[32]; - if (s < 60) snprintf(buf, sizeof(buf), "Remaining: %ds", s); - else snprintf(buf, sizeof(buf), "Remaining: %dm %ds", s / 60, s % 60); - ImGui::TextColored(kLightGray, "%s", buf); - } - - // Format a duration in seconds as compact text: "2h", "3:05", "42" - void fmtDurationCompact(char* buf, size_t sz, int secs) { - if (secs >= 3600) snprintf(buf, sz, "%dh", secs / 3600); - else if (secs >= 60) snprintf(buf, sz, "%d:%02d", secs / 60, secs % 60); - else snprintf(buf, sz, "%d", secs); - } - - // Aliases for shared class color helpers (wowee::ui namespace) - inline ImVec4 classColorVec4(uint8_t classId) { return wowee::ui::getClassColor(classId); } - inline ImU32 classColorU32(uint8_t classId, int alpha = 255) { return wowee::ui::getClassColorU32(classId, alpha); } - - // Extract class id from a unit's UNIT_FIELD_BYTES_0 update field. - uint8_t entityClassId(const wowee::game::Entity* entity) { - if (!entity) return 0; - using UF = wowee::game::UF; - uint32_t bytes0 = entity->getField(wowee::game::fieldIndex(UF::UNIT_FIELD_BYTES_0)); - return static_cast((bytes0 >> 8) & 0xFF); - } - - // Aura dispel-type names (indexed by dispelType 0-4) - constexpr const char* kDispelNames[] = { "", "Magic", "Curse", "Disease", "Poison" }; - - // Raid mark names with symbol prefixes (indexed 0-7: Star..Skull) - constexpr const char* kRaidMarkNames[] = { - "{*} Star", "{O} Circle", "{<>} Diamond", "{^} Triangle", - "{)} Moon", "{ } Square", "{x} Cross", "{8} Skull" - }; - - // Alias for shared class name helper - const char* classNameStr(uint8_t classId) { - return wowee::game::getClassName(static_cast(classId)); - } } // anonymous namespace namespace wowee {