mirror of
https://github.com/Kelsidavis/WoWee.git
synced 2026-03-22 23:30:14 +00:00
Implement renderSocialFrame: compact friends panel with minimap toggle button
Shows online/AFK/DND/offline status dots, whisper/invite/remove context menus, and inline add-friend field. Minimap gets a smiley-face button (top-left) with a green dot badge when friends are online, toggling the panel.
This commit is contained in:
parent
c89dc50b6c
commit
d8f2fedae1
1 changed files with 162 additions and 0 deletions
|
|
@ -451,6 +451,7 @@ void GameScreen::render(game::GameHandler& gameHandler) {
|
||||||
renderBgInvitePopup(gameHandler);
|
renderBgInvitePopup(gameHandler);
|
||||||
renderLfgProposalPopup(gameHandler);
|
renderLfgProposalPopup(gameHandler);
|
||||||
renderGuildRoster(gameHandler);
|
renderGuildRoster(gameHandler);
|
||||||
|
renderSocialFrame(gameHandler);
|
||||||
renderBuffBar(gameHandler);
|
renderBuffBar(gameHandler);
|
||||||
renderLootWindow(gameHandler);
|
renderLootWindow(gameHandler);
|
||||||
renderGossipWindow(gameHandler);
|
renderGossipWindow(gameHandler);
|
||||||
|
|
@ -7781,6 +7782,117 @@ void GameScreen::renderGuildRoster(game::GameHandler& gameHandler) {
|
||||||
showGuildRoster_ = open;
|
showGuildRoster_ = open;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ============================================================
|
||||||
|
// Social Frame — compact online friends panel (toggled by showSocialFrame_)
|
||||||
|
// ============================================================
|
||||||
|
|
||||||
|
void GameScreen::renderSocialFrame(game::GameHandler& gameHandler) {
|
||||||
|
if (!showSocialFrame_) return;
|
||||||
|
|
||||||
|
const auto& contacts = gameHandler.getContacts();
|
||||||
|
// Count online friends for early-out
|
||||||
|
int onlineCount = 0;
|
||||||
|
for (const auto& c : contacts)
|
||||||
|
if (c.isFriend() && c.isOnline()) ++onlineCount;
|
||||||
|
|
||||||
|
auto* window = core::Application::getInstance().getWindow();
|
||||||
|
float screenW = window ? static_cast<float>(window->getWidth()) : 1280.0f;
|
||||||
|
float screenH = window ? static_cast<float>(window->getHeight()) : 720.0f;
|
||||||
|
|
||||||
|
ImGui::SetNextWindowPos(ImVec2(screenW - 230.0f, 240.0f), ImGuiCond_Once);
|
||||||
|
ImGui::SetNextWindowSize(ImVec2(220.0f, 0.0f), ImGuiCond_Always);
|
||||||
|
|
||||||
|
ImGui::PushStyleVar(ImGuiStyleVar_WindowRounding, 4.0f);
|
||||||
|
ImGui::PushStyleColor(ImGuiCol_WindowBg, ImVec4(0.1f, 0.1f, 0.1f, 0.92f));
|
||||||
|
|
||||||
|
bool open = showSocialFrame_;
|
||||||
|
if (ImGui::Begin("Friends##SocialFrame", &open,
|
||||||
|
ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoCollapse |
|
||||||
|
ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoScrollbar)) {
|
||||||
|
|
||||||
|
// Online friends
|
||||||
|
char onlineHeader[32];
|
||||||
|
snprintf(onlineHeader, sizeof(onlineHeader), "Online (%d)", onlineCount);
|
||||||
|
ImGui::TextDisabled("%s", onlineHeader);
|
||||||
|
ImGui::Separator();
|
||||||
|
|
||||||
|
int shown = 0;
|
||||||
|
for (size_t ci = 0; ci < contacts.size(); ++ci) {
|
||||||
|
const auto& c = contacts[ci];
|
||||||
|
if (!c.isFriend()) continue;
|
||||||
|
|
||||||
|
ImGui::PushID(static_cast<int>(ci));
|
||||||
|
|
||||||
|
// Status dot: green=online, yellow=AFK, orange=DND, grey=offline
|
||||||
|
ImU32 dotColor;
|
||||||
|
if (!c.isOnline()) dotColor = IM_COL32(100, 100, 100, 200);
|
||||||
|
else if (c.status == 2) dotColor = IM_COL32(255, 200, 50, 255); // AFK
|
||||||
|
else if (c.status == 3) dotColor = IM_COL32(255, 120, 50, 255); // DND
|
||||||
|
else dotColor = IM_COL32( 50, 220, 50, 255); // online
|
||||||
|
|
||||||
|
ImVec2 dotMin = ImGui::GetCursorScreenPos();
|
||||||
|
dotMin.y += 4.0f;
|
||||||
|
ImGui::GetWindowDrawList()->AddCircleFilled(
|
||||||
|
ImVec2(dotMin.x + 5.0f, dotMin.y + 5.0f), 4.5f, dotColor);
|
||||||
|
ImGui::SetCursorPosX(ImGui::GetCursorPosX() + 14.0f);
|
||||||
|
|
||||||
|
const char* displayName = c.name.empty() ? "(unknown)" : c.name.c_str();
|
||||||
|
ImVec4 nameCol = c.isOnline()
|
||||||
|
? ImVec4(0.9f, 0.9f, 0.9f, 1.0f)
|
||||||
|
: ImVec4(0.5f, 0.5f, 0.5f, 1.0f);
|
||||||
|
ImGui::TextColored(nameCol, "%s", displayName);
|
||||||
|
|
||||||
|
if (c.isOnline() && c.level > 0) {
|
||||||
|
ImGui::SameLine();
|
||||||
|
ImGui::TextDisabled("%u", c.level);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Right-click context menu
|
||||||
|
if (ImGui::BeginPopupContextItem("FriendCtx")) {
|
||||||
|
ImGui::TextDisabled("%s", displayName);
|
||||||
|
ImGui::Separator();
|
||||||
|
if (c.isOnline()) {
|
||||||
|
if (ImGui::MenuItem("Whisper")) {
|
||||||
|
showSocialFrame_ = false;
|
||||||
|
strncpy(whisperTargetBuffer, c.name.c_str(), sizeof(whisperTargetBuffer) - 1);
|
||||||
|
whisperTargetBuffer[sizeof(whisperTargetBuffer) - 1] = '\0';
|
||||||
|
selectedChatType = 4;
|
||||||
|
refocusChatInput = true;
|
||||||
|
}
|
||||||
|
if (ImGui::MenuItem("Invite to Group"))
|
||||||
|
gameHandler.inviteToGroup(c.name);
|
||||||
|
}
|
||||||
|
if (ImGui::MenuItem("Remove Friend"))
|
||||||
|
gameHandler.removeFriend(c.name);
|
||||||
|
ImGui::EndPopup();
|
||||||
|
}
|
||||||
|
|
||||||
|
++shown;
|
||||||
|
ImGui::PopID();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (shown == 0) {
|
||||||
|
ImGui::TextDisabled("No friends.");
|
||||||
|
}
|
||||||
|
|
||||||
|
ImGui::Separator();
|
||||||
|
// Add friend inline
|
||||||
|
static char addFriendBuf[64] = {};
|
||||||
|
ImGui::SetNextItemWidth(140.0f);
|
||||||
|
ImGui::InputText("##sf_addfriend", addFriendBuf, sizeof(addFriendBuf));
|
||||||
|
ImGui::SameLine();
|
||||||
|
if (ImGui::Button("+") && addFriendBuf[0] != '\0') {
|
||||||
|
gameHandler.addFriend(addFriendBuf);
|
||||||
|
addFriendBuf[0] = '\0';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ImGui::End();
|
||||||
|
showSocialFrame_ = open;
|
||||||
|
|
||||||
|
ImGui::PopStyleColor();
|
||||||
|
ImGui::PopStyleVar();
|
||||||
|
}
|
||||||
|
|
||||||
// ============================================================
|
// ============================================================
|
||||||
// Buff/Debuff Bar (Phase 3)
|
// Buff/Debuff Bar (Phase 3)
|
||||||
// ============================================================
|
// ============================================================
|
||||||
|
|
@ -11373,6 +11485,56 @@ void GameScreen::renderMinimapMarkers(game::GameHandler& gameHandler) {
|
||||||
}
|
}
|
||||||
ImGui::End();
|
ImGui::End();
|
||||||
|
|
||||||
|
// Friends button at top-left of minimap
|
||||||
|
{
|
||||||
|
const auto& contacts = gameHandler.getContacts();
|
||||||
|
int onlineCount = 0;
|
||||||
|
for (const auto& c : contacts)
|
||||||
|
if (c.isFriend() && c.isOnline()) ++onlineCount;
|
||||||
|
|
||||||
|
ImGui::SetNextWindowPos(ImVec2(centerX - mapRadius + 4.0f, centerY - mapRadius + 4.0f), ImGuiCond_Always);
|
||||||
|
ImGui::SetNextWindowSize(ImVec2(22.0f, 22.0f), ImGuiCond_Always);
|
||||||
|
ImGuiWindowFlags friendsBtnFlags = ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoResize |
|
||||||
|
ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoScrollbar |
|
||||||
|
ImGuiWindowFlags_NoBackground;
|
||||||
|
if (ImGui::Begin("##MinimapFriendsBtn", nullptr, friendsBtnFlags)) {
|
||||||
|
ImDrawList* draw = ImGui::GetWindowDrawList();
|
||||||
|
ImVec2 p = ImGui::GetCursorScreenPos();
|
||||||
|
ImVec2 sz(20.0f, 20.0f);
|
||||||
|
if (ImGui::InvisibleButton("##FriendsBtnInv", sz)) {
|
||||||
|
showSocialFrame_ = !showSocialFrame_;
|
||||||
|
}
|
||||||
|
bool hovered = ImGui::IsItemHovered();
|
||||||
|
ImU32 bg = showSocialFrame_
|
||||||
|
? IM_COL32(42, 100, 42, 230)
|
||||||
|
: IM_COL32(38, 38, 38, 210);
|
||||||
|
if (hovered) bg = showSocialFrame_ ? IM_COL32(58, 130, 58, 230) : IM_COL32(65, 65, 65, 220);
|
||||||
|
draw->AddRectFilled(p, ImVec2(p.x + sz.x, p.y + sz.y), bg, 4.0f);
|
||||||
|
draw->AddRect(ImVec2(p.x + 0.5f, p.y + 0.5f),
|
||||||
|
ImVec2(p.x + sz.x - 0.5f, p.y + sz.y - 0.5f),
|
||||||
|
IM_COL32(255, 255, 255, 42), 4.0f);
|
||||||
|
// Simple smiley-face dots as "social" icon
|
||||||
|
ImU32 fg = IM_COL32(255, 255, 255, 245);
|
||||||
|
draw->AddCircle(ImVec2(p.x + 10.0f, p.y + 10.0f), 6.5f, fg, 16, 1.2f);
|
||||||
|
draw->AddCircleFilled(ImVec2(p.x + 7.5f, p.y + 8.0f), 1.2f, fg);
|
||||||
|
draw->AddCircleFilled(ImVec2(p.x + 12.5f, p.y + 8.0f), 1.2f, fg);
|
||||||
|
draw->PathArcTo(ImVec2(p.x + 10.0f, p.y + 11.5f), 3.0f, 0.2f, 2.9f, 8);
|
||||||
|
draw->PathStroke(fg, 0, 1.2f);
|
||||||
|
// Small green dot if friends online
|
||||||
|
if (onlineCount > 0) {
|
||||||
|
draw->AddCircleFilled(ImVec2(p.x + sz.x - 3.5f, p.y + 3.5f),
|
||||||
|
3.5f, IM_COL32(50, 220, 50, 255));
|
||||||
|
}
|
||||||
|
if (hovered) {
|
||||||
|
if (onlineCount > 0)
|
||||||
|
ImGui::SetTooltip("Friends (%d online)", onlineCount);
|
||||||
|
else
|
||||||
|
ImGui::SetTooltip("Friends");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ImGui::End();
|
||||||
|
}
|
||||||
|
|
||||||
// Zoom buttons at the bottom edge of the minimap
|
// Zoom buttons at the bottom edge of the minimap
|
||||||
ImGui::SetNextWindowPos(ImVec2(centerX - 22, centerY + mapRadius - 30), ImGuiCond_Always);
|
ImGui::SetNextWindowPos(ImVec2(centerX - 22, centerY + mapRadius - 30), ImGuiCond_Always);
|
||||||
ImGui::SetNextWindowSize(ImVec2(44, 24), ImGuiCond_Always);
|
ImGui::SetNextWindowSize(ImVec2(44, 24), ImGuiCond_Always);
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue