mirror of
https://github.com/Kelsidavis/WoWee.git
synced 2026-04-17 17:43:52 +00:00
feat: show party member dots on world map with name labels and class colors
This commit is contained in:
parent
6dc630c1d8
commit
e2f36f6ac5
3 changed files with 64 additions and 0 deletions
|
|
@ -3,6 +3,7 @@
|
||||||
#include <vulkan/vulkan.h>
|
#include <vulkan/vulkan.h>
|
||||||
#include <vk_mem_alloc.h>
|
#include <vk_mem_alloc.h>
|
||||||
#include <glm/glm.hpp>
|
#include <glm/glm.hpp>
|
||||||
|
#include <cstdint>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
|
|
@ -17,6 +18,13 @@ class VkContext;
|
||||||
class VkTexture;
|
class VkTexture;
|
||||||
class VkRenderTarget;
|
class VkRenderTarget;
|
||||||
|
|
||||||
|
/// Party member dot passed in from the UI layer for world map overlay.
|
||||||
|
struct WorldMapPartyDot {
|
||||||
|
glm::vec3 renderPos; ///< Position in render-space coordinates
|
||||||
|
uint32_t color; ///< RGBA packed color (IM_COL32 format)
|
||||||
|
std::string name; ///< Member name (shown as tooltip on hover)
|
||||||
|
};
|
||||||
|
|
||||||
struct WorldMapZone {
|
struct WorldMapZone {
|
||||||
uint32_t wmaID = 0;
|
uint32_t wmaID = 0;
|
||||||
uint32_t areaID = 0; // 0 = continent level
|
uint32_t areaID = 0; // 0 = continent level
|
||||||
|
|
@ -47,6 +55,7 @@ public:
|
||||||
|
|
||||||
void setMapName(const std::string& name);
|
void setMapName(const std::string& name);
|
||||||
void setServerExplorationMask(const std::vector<uint32_t>& masks, bool hasData);
|
void setServerExplorationMask(const std::vector<uint32_t>& masks, bool hasData);
|
||||||
|
void setPartyDots(std::vector<WorldMapPartyDot> dots) { partyDots_ = std::move(dots); }
|
||||||
bool isOpen() const { return open; }
|
bool isOpen() const { return open; }
|
||||||
void close() { open = false; }
|
void close() { open = false; }
|
||||||
|
|
||||||
|
|
@ -113,6 +122,9 @@ private:
|
||||||
// Texture storage (owns all VkTexture objects for zone tiles)
|
// Texture storage (owns all VkTexture objects for zone tiles)
|
||||||
std::vector<std::unique_ptr<VkTexture>> zoneTextures;
|
std::vector<std::unique_ptr<VkTexture>> zoneTextures;
|
||||||
|
|
||||||
|
// Party member dots (set each frame from the UI layer)
|
||||||
|
std::vector<WorldMapPartyDot> partyDots_;
|
||||||
|
|
||||||
// Exploration / fog of war
|
// Exploration / fog of war
|
||||||
std::vector<uint32_t> serverExplorationMask;
|
std::vector<uint32_t> serverExplorationMask;
|
||||||
bool hasServerExplorationMask = false;
|
bool hasServerExplorationMask = false;
|
||||||
|
|
|
||||||
|
|
@ -1017,6 +1017,33 @@ void WorldMap::renderImGuiOverlay(const glm::vec3& playerRenderPos, int screenWi
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Party member dots
|
||||||
|
if (currentIdx >= 0 && viewLevel != ViewLevel::WORLD) {
|
||||||
|
ImFont* font = ImGui::GetFont();
|
||||||
|
for (const auto& dot : partyDots_) {
|
||||||
|
glm::vec2 uv = renderPosToMapUV(dot.renderPos, currentIdx);
|
||||||
|
if (uv.x < 0.0f || uv.x > 1.0f || uv.y < 0.0f || uv.y > 1.0f) continue;
|
||||||
|
float px = imgMin.x + uv.x * displayW;
|
||||||
|
float py = imgMin.y + uv.y * displayH;
|
||||||
|
drawList->AddCircleFilled(ImVec2(px, py), 5.0f, dot.color);
|
||||||
|
drawList->AddCircle(ImVec2(px, py), 5.0f, IM_COL32(0, 0, 0, 200), 0, 1.5f);
|
||||||
|
// Name tooltip on hover
|
||||||
|
if (!dot.name.empty()) {
|
||||||
|
ImVec2 mp = ImGui::GetMousePos();
|
||||||
|
float dx = mp.x - px, dy = mp.y - py;
|
||||||
|
if (dx * dx + dy * dy <= 49.0f) { // radius 7 px hit area
|
||||||
|
ImGui::SetTooltip("%s", dot.name.c_str());
|
||||||
|
}
|
||||||
|
// Draw name label above the dot
|
||||||
|
ImVec2 nameSz = font->CalcTextSizeA(ImGui::GetFontSize(), FLT_MAX, 0.0f, dot.name.c_str());
|
||||||
|
float tx = px - nameSz.x * 0.5f;
|
||||||
|
float ty = py - nameSz.y - 7.0f;
|
||||||
|
drawList->AddText(ImVec2(tx + 1.0f, ty + 1.0f), IM_COL32(0, 0, 0, 180), dot.name.c_str());
|
||||||
|
drawList->AddText(ImVec2(tx, ty), IM_COL32(255, 255, 255, 220), dot.name.c_str());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Hover coordinate display — show WoW coordinates under cursor
|
// Hover coordinate display — show WoW coordinates under cursor
|
||||||
if (currentIdx >= 0 && viewLevel != ViewLevel::WORLD) {
|
if (currentIdx >= 0 && viewLevel != ViewLevel::WORLD) {
|
||||||
auto& io = ImGui::GetIO();
|
auto& io = ImGui::GetIO();
|
||||||
|
|
|
||||||
|
|
@ -6139,6 +6139,31 @@ void GameScreen::renderWorldMap(game::GameHandler& gameHandler) {
|
||||||
gameHandler.getPlayerExploredZoneMasks(),
|
gameHandler.getPlayerExploredZoneMasks(),
|
||||||
gameHandler.hasPlayerExploredZoneMasks());
|
gameHandler.hasPlayerExploredZoneMasks());
|
||||||
|
|
||||||
|
// Party member dots on world map
|
||||||
|
{
|
||||||
|
std::vector<rendering::WorldMapPartyDot> dots;
|
||||||
|
if (gameHandler.isInGroup()) {
|
||||||
|
const auto& partyData = gameHandler.getPartyData();
|
||||||
|
for (const auto& member : partyData.members) {
|
||||||
|
if (!member.isOnline || !member.hasPartyStats) continue;
|
||||||
|
if (member.posX == 0 && member.posY == 0) continue;
|
||||||
|
// posY → canonical X (north), posX → canonical Y (west)
|
||||||
|
float wowX = static_cast<float>(member.posY);
|
||||||
|
float wowY = static_cast<float>(member.posX);
|
||||||
|
glm::vec3 rpos = core::coords::canonicalToRender(glm::vec3(wowX, wowY, 0.0f));
|
||||||
|
auto ent = gameHandler.getEntityManager().getEntity(member.guid);
|
||||||
|
uint8_t cid = entityClassId(ent.get());
|
||||||
|
ImU32 col = (cid != 0)
|
||||||
|
? classColorU32(cid, 230)
|
||||||
|
: (member.guid == partyData.leaderGuid
|
||||||
|
? IM_COL32(255, 210, 0, 230)
|
||||||
|
: IM_COL32(100, 180, 255, 230));
|
||||||
|
dots.push_back({ rpos, col, member.name });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
wm->setPartyDots(std::move(dots));
|
||||||
|
}
|
||||||
|
|
||||||
glm::vec3 playerPos = renderer->getCharacterPosition();
|
glm::vec3 playerPos = renderer->getCharacterPosition();
|
||||||
auto* window = app.getWindow();
|
auto* window = app.getWindow();
|
||||||
int screenW = window ? window->getWidth() : 1280;
|
int screenW = window ? window->getWidth() : 1280;
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue