2026-02-02 12:24:50 -08:00
|
|
|
#include "ui/character_screen.hpp"
|
2026-02-12 14:55:27 -08:00
|
|
|
#include "rendering/character_preview.hpp"
|
|
|
|
|
#include "pipeline/asset_manager.hpp"
|
|
|
|
|
#include "core/application.hpp"
|
|
|
|
|
#include "core/logger.hpp"
|
2026-02-02 12:24:50 -08:00
|
|
|
#include <imgui.h>
|
Fix vendor buying, improve character select, parallelize WMO culling, and optimize collision
- Fix CMSG_BUY_ITEM count field from uint8 to uint32 (server silently dropped undersized packets)
- Character select screen: remember last selected character, two-column layout with details panel, double-click to enter world, responsive window sizing
- Fix stale character data between logins by replacing static init flag with per-character GUID tracking
- Parallelize WMO visibility culling across worker threads (same pattern as M2 renderer)
- Optimize WMO collision queries with world-space group bounds early rejection in getFloorHeight, checkWallCollision, isInsideWMO, and raycastBoundingBoxes
- Reduce camera ground samples from 5 to 3 movement-aligned probes
- Add WMO interior lighting, unlit materials, vertex color multiply, and alpha blending support
2026-02-07 15:29:19 -08:00
|
|
|
#include <cstdlib>
|
|
|
|
|
#include <filesystem>
|
|
|
|
|
#include <fstream>
|
2026-02-02 12:24:50 -08:00
|
|
|
#include <iomanip>
|
|
|
|
|
#include <sstream>
|
|
|
|
|
|
|
|
|
|
namespace wowee { namespace ui {
|
|
|
|
|
|
|
|
|
|
CharacterScreen::CharacterScreen() {
|
|
|
|
|
}
|
|
|
|
|
|
2026-02-12 14:55:27 -08:00
|
|
|
static uint64_t hashEquipment(const std::vector<game::EquipmentItem>& eq) {
|
|
|
|
|
// FNV-1a 64-bit over (displayModel, inventoryType, enchantment)
|
|
|
|
|
uint64_t h = 1469598103934665603ull;
|
|
|
|
|
auto mix8 = [&](uint8_t b) {
|
|
|
|
|
h ^= b;
|
|
|
|
|
h *= 1099511628211ull;
|
|
|
|
|
};
|
|
|
|
|
auto mix32 = [&](uint32_t v) {
|
|
|
|
|
mix8(static_cast<uint8_t>(v & 0xFF));
|
|
|
|
|
mix8(static_cast<uint8_t>((v >> 8) & 0xFF));
|
|
|
|
|
mix8(static_cast<uint8_t>((v >> 16) & 0xFF));
|
|
|
|
|
mix8(static_cast<uint8_t>((v >> 24) & 0xFF));
|
|
|
|
|
};
|
|
|
|
|
for (const auto& it : eq) {
|
|
|
|
|
mix32(it.displayModel);
|
|
|
|
|
mix8(it.inventoryType);
|
|
|
|
|
mix32(it.enchantment);
|
|
|
|
|
}
|
|
|
|
|
return h;
|
|
|
|
|
}
|
|
|
|
|
|
2026-02-02 12:24:50 -08:00
|
|
|
void CharacterScreen::render(game::GameHandler& gameHandler) {
|
2026-02-12 14:55:27 -08:00
|
|
|
ImGuiViewport* vp = ImGui::GetMainViewport();
|
|
|
|
|
const ImVec2 pad(24.0f, 24.0f);
|
|
|
|
|
ImVec2 winSize(vp->Size.x - pad.x * 2.0f, vp->Size.y - pad.y * 2.0f);
|
|
|
|
|
if (winSize.x < 860.0f) winSize.x = 860.0f;
|
|
|
|
|
if (winSize.y < 620.0f) winSize.y = 620.0f;
|
|
|
|
|
|
|
|
|
|
ImGui::SetNextWindowPos(ImVec2(vp->Pos.x + (vp->Size.x - winSize.x) * 0.5f,
|
|
|
|
|
vp->Pos.y + (vp->Size.y - winSize.y) * 0.5f),
|
|
|
|
|
ImGuiCond_Always);
|
|
|
|
|
ImGui::SetNextWindowSize(winSize, ImGuiCond_Always);
|
|
|
|
|
|
|
|
|
|
ImGui::Begin("Character Selection", nullptr,
|
|
|
|
|
ImGuiWindowFlags_NoCollapse | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoMove);
|
|
|
|
|
|
|
|
|
|
// Ensure we can render a preview even if the state transition hook didn't inject the AssetManager.
|
|
|
|
|
if (!assetManager_) {
|
|
|
|
|
assetManager_ = core::Application::getInstance().getAssetManager();
|
|
|
|
|
}
|
2026-02-02 12:24:50 -08:00
|
|
|
|
|
|
|
|
// Get character list
|
|
|
|
|
const auto& characters = gameHandler.getCharacters();
|
|
|
|
|
|
2026-02-12 14:55:27 -08:00
|
|
|
// Request character list if not available.
|
|
|
|
|
// Also show a loading state while CHAR_LIST_REQUESTED is in-flight (characters may be cleared to avoid stale UI).
|
|
|
|
|
if (characters.empty() &&
|
|
|
|
|
(gameHandler.getState() == game::WorldState::READY ||
|
|
|
|
|
gameHandler.getState() == game::WorldState::CHAR_LIST_REQUESTED)) {
|
2026-02-02 12:24:50 -08:00
|
|
|
ImGui::Text("Loading characters...");
|
2026-02-12 14:55:27 -08:00
|
|
|
if (gameHandler.getState() == game::WorldState::READY) {
|
|
|
|
|
gameHandler.requestCharacterList();
|
|
|
|
|
}
|
Fix vendor buying, improve character select, parallelize WMO culling, and optimize collision
- Fix CMSG_BUY_ITEM count field from uint8 to uint32 (server silently dropped undersized packets)
- Character select screen: remember last selected character, two-column layout with details panel, double-click to enter world, responsive window sizing
- Fix stale character data between logins by replacing static init flag with per-character GUID tracking
- Parallelize WMO visibility culling across worker threads (same pattern as M2 renderer)
- Optimize WMO collision queries with world-space group bounds early rejection in getFloorHeight, checkWallCollision, isInsideWMO, and raycastBoundingBoxes
- Reduce camera ground samples from 5 to 3 movement-aligned probes
- Add WMO interior lighting, unlit materials, vertex color multiply, and alpha blending support
2026-02-07 15:29:19 -08:00
|
|
|
ImGui::End();
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2026-02-14 20:20:43 -08:00
|
|
|
// Handle disconnected state with no characters received
|
|
|
|
|
if (characters.empty() &&
|
|
|
|
|
(gameHandler.getState() == game::WorldState::DISCONNECTED ||
|
|
|
|
|
gameHandler.getState() == game::WorldState::FAILED)) {
|
|
|
|
|
ImGui::TextColored(ImVec4(1.0f, 0.4f, 0.4f, 1.0f), "Disconnected from server.");
|
|
|
|
|
ImGui::TextWrapped("The server closed the connection before sending the character list.");
|
|
|
|
|
ImGui::Spacing();
|
|
|
|
|
if (ImGui::Button("Back", ImVec2(120, 36))) { if (onBack) onBack(); }
|
|
|
|
|
ImGui::End();
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
Fix vendor buying, improve character select, parallelize WMO culling, and optimize collision
- Fix CMSG_BUY_ITEM count field from uint8 to uint32 (server silently dropped undersized packets)
- Character select screen: remember last selected character, two-column layout with details panel, double-click to enter world, responsive window sizing
- Fix stale character data between logins by replacing static init flag with per-character GUID tracking
- Parallelize WMO visibility culling across worker threads (same pattern as M2 renderer)
- Optimize WMO collision queries with world-space group bounds early rejection in getFloorHeight, checkWallCollision, isInsideWMO, and raycastBoundingBoxes
- Reduce camera ground samples from 5 to 3 movement-aligned probes
- Add WMO interior lighting, unlit materials, vertex color multiply, and alpha blending support
2026-02-07 15:29:19 -08:00
|
|
|
if (characters.empty()) {
|
2026-02-02 12:24:50 -08:00
|
|
|
ImGui::Text("No characters available.");
|
Fix vendor buying, improve character select, parallelize WMO culling, and optimize collision
- Fix CMSG_BUY_ITEM count field from uint8 to uint32 (server silently dropped undersized packets)
- Character select screen: remember last selected character, two-column layout with details panel, double-click to enter world, responsive window sizing
- Fix stale character data between logins by replacing static init flag with per-character GUID tracking
- Parallelize WMO visibility culling across worker threads (same pattern as M2 renderer)
- Optimize WMO collision queries with world-space group bounds early rejection in getFloorHeight, checkWallCollision, isInsideWMO, and raycastBoundingBoxes
- Reduce camera ground samples from 5 to 3 movement-aligned probes
- Add WMO interior lighting, unlit materials, vertex color multiply, and alpha blending support
2026-02-07 15:29:19 -08:00
|
|
|
// Bottom buttons even when empty
|
|
|
|
|
ImGui::Spacing();
|
|
|
|
|
if (ImGui::Button("Back", ImVec2(120, 36))) { if (onBack) onBack(); }
|
|
|
|
|
ImGui::SameLine();
|
|
|
|
|
if (ImGui::Button("Refresh", ImVec2(120, 36))) {
|
|
|
|
|
if (gameHandler.getState() == game::WorldState::READY ||
|
|
|
|
|
gameHandler.getState() == game::WorldState::CHAR_LIST_RECEIVED) {
|
|
|
|
|
gameHandler.requestCharacterList();
|
|
|
|
|
setStatus("Refreshing character list...");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
ImGui::SameLine();
|
|
|
|
|
if (ImGui::Button("Create Character", ImVec2(160, 36))) { if (onCreateCharacter) onCreateCharacter(); }
|
|
|
|
|
ImGui::End();
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2026-02-12 14:55:27 -08:00
|
|
|
// If the list refreshed, keep selection stable by GUID.
|
|
|
|
|
if (selectedCharacterGuid != 0) {
|
|
|
|
|
const bool needReselect =
|
|
|
|
|
(selectedCharacterIndex < 0) ||
|
|
|
|
|
(selectedCharacterIndex >= static_cast<int>(characters.size())) ||
|
|
|
|
|
(characters[static_cast<size_t>(selectedCharacterIndex)].guid != selectedCharacterGuid);
|
|
|
|
|
if (needReselect) {
|
|
|
|
|
for (size_t i = 0; i < characters.size(); ++i) {
|
|
|
|
|
if (characters[i].guid == selectedCharacterGuid) {
|
|
|
|
|
selectedCharacterIndex = static_cast<int>(i);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
Fix vendor buying, improve character select, parallelize WMO culling, and optimize collision
- Fix CMSG_BUY_ITEM count field from uint8 to uint32 (server silently dropped undersized packets)
- Character select screen: remember last selected character, two-column layout with details panel, double-click to enter world, responsive window sizing
- Fix stale character data between logins by replacing static init flag with per-character GUID tracking
- Parallelize WMO visibility culling across worker threads (same pattern as M2 renderer)
- Optimize WMO collision queries with world-space group bounds early rejection in getFloorHeight, checkWallCollision, isInsideWMO, and raycastBoundingBoxes
- Reduce camera ground samples from 5 to 3 movement-aligned probes
- Add WMO interior lighting, unlit materials, vertex color multiply, and alpha blending support
2026-02-07 15:29:19 -08:00
|
|
|
// Restore last-selected character (once per screen visit)
|
|
|
|
|
if (!restoredLastCharacter) {
|
2026-02-09 22:51:13 -08:00
|
|
|
// Priority 1: Select newly created character if set
|
|
|
|
|
if (!newlyCreatedCharacterName.empty()) {
|
Fix vendor buying, improve character select, parallelize WMO culling, and optimize collision
- Fix CMSG_BUY_ITEM count field from uint8 to uint32 (server silently dropped undersized packets)
- Character select screen: remember last selected character, two-column layout with details panel, double-click to enter world, responsive window sizing
- Fix stale character data between logins by replacing static init flag with per-character GUID tracking
- Parallelize WMO visibility culling across worker threads (same pattern as M2 renderer)
- Optimize WMO collision queries with world-space group bounds early rejection in getFloorHeight, checkWallCollision, isInsideWMO, and raycastBoundingBoxes
- Reduce camera ground samples from 5 to 3 movement-aligned probes
- Add WMO interior lighting, unlit materials, vertex color multiply, and alpha blending support
2026-02-07 15:29:19 -08:00
|
|
|
for (size_t i = 0; i < characters.size(); ++i) {
|
2026-02-09 22:51:13 -08:00
|
|
|
if (characters[i].name == newlyCreatedCharacterName) {
|
Fix vendor buying, improve character select, parallelize WMO culling, and optimize collision
- Fix CMSG_BUY_ITEM count field from uint8 to uint32 (server silently dropped undersized packets)
- Character select screen: remember last selected character, two-column layout with details panel, double-click to enter world, responsive window sizing
- Fix stale character data between logins by replacing static init flag with per-character GUID tracking
- Parallelize WMO visibility culling across worker threads (same pattern as M2 renderer)
- Optimize WMO collision queries with world-space group bounds early rejection in getFloorHeight, checkWallCollision, isInsideWMO, and raycastBoundingBoxes
- Reduce camera ground samples from 5 to 3 movement-aligned probes
- Add WMO interior lighting, unlit materials, vertex color multiply, and alpha blending support
2026-02-07 15:29:19 -08:00
|
|
|
selectedCharacterIndex = static_cast<int>(i);
|
2026-02-09 22:51:13 -08:00
|
|
|
selectedCharacterGuid = characters[i].guid;
|
|
|
|
|
saveLastCharacter(characters[i].guid);
|
|
|
|
|
newlyCreatedCharacterName.clear();
|
Fix vendor buying, improve character select, parallelize WMO culling, and optimize collision
- Fix CMSG_BUY_ITEM count field from uint8 to uint32 (server silently dropped undersized packets)
- Character select screen: remember last selected character, two-column layout with details panel, double-click to enter world, responsive window sizing
- Fix stale character data between logins by replacing static init flag with per-character GUID tracking
- Parallelize WMO visibility culling across worker threads (same pattern as M2 renderer)
- Optimize WMO collision queries with world-space group bounds early rejection in getFloorHeight, checkWallCollision, isInsideWMO, and raycastBoundingBoxes
- Reduce camera ground samples from 5 to 3 movement-aligned probes
- Add WMO interior lighting, unlit materials, vertex color multiply, and alpha blending support
2026-02-07 15:29:19 -08:00
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2026-02-09 22:51:13 -08:00
|
|
|
// Priority 2: Restore last selected character
|
|
|
|
|
if (selectedCharacterIndex < 0) {
|
|
|
|
|
uint64_t lastGuid = loadLastCharacter();
|
|
|
|
|
if (lastGuid != 0) {
|
|
|
|
|
for (size_t i = 0; i < characters.size(); ++i) {
|
|
|
|
|
if (characters[i].guid == lastGuid) {
|
|
|
|
|
selectedCharacterIndex = static_cast<int>(i);
|
|
|
|
|
selectedCharacterGuid = lastGuid;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
Fix vendor buying, improve character select, parallelize WMO culling, and optimize collision
- Fix CMSG_BUY_ITEM count field from uint8 to uint32 (server silently dropped undersized packets)
- Character select screen: remember last selected character, two-column layout with details panel, double-click to enter world, responsive window sizing
- Fix stale character data between logins by replacing static init flag with per-character GUID tracking
- Parallelize WMO visibility culling across worker threads (same pattern as M2 renderer)
- Optimize WMO collision queries with world-space group bounds early rejection in getFloorHeight, checkWallCollision, isInsideWMO, and raycastBoundingBoxes
- Reduce camera ground samples from 5 to 3 movement-aligned probes
- Add WMO interior lighting, unlit materials, vertex color multiply, and alpha blending support
2026-02-07 15:29:19 -08:00
|
|
|
// Fall back to first character if nothing matched
|
|
|
|
|
if (selectedCharacterIndex < 0) {
|
Fix camera orbit, deselect, chat formatting, loot/vendor bugs, critter hostility, and character screen
Smooth idle camera orbit without jump at loop boundary, click empty space to
deselect target, auto-target when attacked, fix critter hostility so neutral
factions aren't flagged red, add armor/stats to item templates, fix loot
iterator invalidation, show item template names as fallback, position drop
confirmation at cursor, remove [SYSTEM] chat prefix, show NPC names in monster
say/yell, and prevent auto-login on character select screen.
2026-02-06 16:40:44 -08:00
|
|
|
selectedCharacterIndex = 0;
|
|
|
|
|
selectedCharacterGuid = characters[0].guid;
|
|
|
|
|
}
|
Fix vendor buying, improve character select, parallelize WMO culling, and optimize collision
- Fix CMSG_BUY_ITEM count field from uint8 to uint32 (server silently dropped undersized packets)
- Character select screen: remember last selected character, two-column layout with details panel, double-click to enter world, responsive window sizing
- Fix stale character data between logins by replacing static init flag with per-character GUID tracking
- Parallelize WMO visibility culling across worker threads (same pattern as M2 renderer)
- Optimize WMO collision queries with world-space group bounds early rejection in getFloorHeight, checkWallCollision, isInsideWMO, and raycastBoundingBoxes
- Reduce camera ground samples from 5 to 3 movement-aligned probes
- Add WMO interior lighting, unlit materials, vertex color multiply, and alpha blending support
2026-02-07 15:29:19 -08:00
|
|
|
restoredLastCharacter = true;
|
|
|
|
|
}
|
Fix camera orbit, deselect, chat formatting, loot/vendor bugs, critter hostility, and character screen
Smooth idle camera orbit without jump at loop boundary, click empty space to
deselect target, auto-target when attacked, fix critter hostility so neutral
factions aren't flagged red, add armor/stats to item templates, fix loot
iterator invalidation, show item template names as fallback, position drop
confirmation at cursor, remove [SYSTEM] chat prefix, show NPC names in monster
say/yell, and prevent auto-login on character select screen.
2026-02-06 16:40:44 -08:00
|
|
|
|
Fix vendor buying, improve character select, parallelize WMO culling, and optimize collision
- Fix CMSG_BUY_ITEM count field from uint8 to uint32 (server silently dropped undersized packets)
- Character select screen: remember last selected character, two-column layout with details panel, double-click to enter world, responsive window sizing
- Fix stale character data between logins by replacing static init flag with per-character GUID tracking
- Parallelize WMO visibility culling across worker threads (same pattern as M2 renderer)
- Optimize WMO collision queries with world-space group bounds early rejection in getFloorHeight, checkWallCollision, isInsideWMO, and raycastBoundingBoxes
- Reduce camera ground samples from 5 to 3 movement-aligned probes
- Add WMO interior lighting, unlit materials, vertex color multiply, and alpha blending support
2026-02-07 15:29:19 -08:00
|
|
|
// Status message
|
|
|
|
|
if (!statusMessage.empty()) {
|
2026-02-17 13:59:29 -08:00
|
|
|
ImVec4 color = statusIsError ? ImVec4(1.0f, 0.3f, 0.3f, 1.0f) : ImVec4(0.3f, 1.0f, 0.3f, 1.0f);
|
|
|
|
|
ImGui::PushStyleColor(ImGuiCol_Text, color);
|
Fix vendor buying, improve character select, parallelize WMO culling, and optimize collision
- Fix CMSG_BUY_ITEM count field from uint8 to uint32 (server silently dropped undersized packets)
- Character select screen: remember last selected character, two-column layout with details panel, double-click to enter world, responsive window sizing
- Fix stale character data between logins by replacing static init flag with per-character GUID tracking
- Parallelize WMO visibility culling across worker threads (same pattern as M2 renderer)
- Optimize WMO collision queries with world-space group bounds early rejection in getFloorHeight, checkWallCollision, isInsideWMO, and raycastBoundingBoxes
- Reduce camera ground samples from 5 to 3 movement-aligned probes
- Add WMO interior lighting, unlit materials, vertex color multiply, and alpha blending support
2026-02-07 15:29:19 -08:00
|
|
|
ImGui::TextWrapped("%s", statusMessage.c_str());
|
|
|
|
|
ImGui::PopStyleColor();
|
|
|
|
|
ImGui::Spacing();
|
|
|
|
|
}
|
2026-02-02 12:24:50 -08:00
|
|
|
|
Fix vendor buying, improve character select, parallelize WMO culling, and optimize collision
- Fix CMSG_BUY_ITEM count field from uint8 to uint32 (server silently dropped undersized packets)
- Character select screen: remember last selected character, two-column layout with details panel, double-click to enter world, responsive window sizing
- Fix stale character data between logins by replacing static init flag with per-character GUID tracking
- Parallelize WMO visibility culling across worker threads (same pattern as M2 renderer)
- Optimize WMO collision queries with world-space group bounds early rejection in getFloorHeight, checkWallCollision, isInsideWMO, and raycastBoundingBoxes
- Reduce camera ground samples from 5 to 3 movement-aligned probes
- Add WMO interior lighting, unlit materials, vertex color multiply, and alpha blending support
2026-02-07 15:29:19 -08:00
|
|
|
// ── Two-column layout: character list (left) | details (right) ──
|
|
|
|
|
float availW = ImGui::GetContentRegionAvail().x;
|
2026-02-12 14:55:27 -08:00
|
|
|
float detailPanelW = 360.0f;
|
Fix vendor buying, improve character select, parallelize WMO culling, and optimize collision
- Fix CMSG_BUY_ITEM count field from uint8 to uint32 (server silently dropped undersized packets)
- Character select screen: remember last selected character, two-column layout with details panel, double-click to enter world, responsive window sizing
- Fix stale character data between logins by replacing static init flag with per-character GUID tracking
- Parallelize WMO visibility culling across worker threads (same pattern as M2 renderer)
- Optimize WMO collision queries with world-space group bounds early rejection in getFloorHeight, checkWallCollision, isInsideWMO, and raycastBoundingBoxes
- Reduce camera ground samples from 5 to 3 movement-aligned probes
- Add WMO interior lighting, unlit materials, vertex color multiply, and alpha blending support
2026-02-07 15:29:19 -08:00
|
|
|
float listW = availW - detailPanelW - ImGui::GetStyle().ItemSpacing.x;
|
|
|
|
|
if (listW < 300.0f) { listW = availW; detailPanelW = 0.0f; }
|
2026-02-02 12:24:50 -08:00
|
|
|
|
Fix vendor buying, improve character select, parallelize WMO culling, and optimize collision
- Fix CMSG_BUY_ITEM count field from uint8 to uint32 (server silently dropped undersized packets)
- Character select screen: remember last selected character, two-column layout with details panel, double-click to enter world, responsive window sizing
- Fix stale character data between logins by replacing static init flag with per-character GUID tracking
- Parallelize WMO visibility culling across worker threads (same pattern as M2 renderer)
- Optimize WMO collision queries with world-space group bounds early rejection in getFloorHeight, checkWallCollision, isInsideWMO, and raycastBoundingBoxes
- Reduce camera ground samples from 5 to 3 movement-aligned probes
- Add WMO interior lighting, unlit materials, vertex color multiply, and alpha blending support
2026-02-07 15:29:19 -08:00
|
|
|
float listH = ImGui::GetContentRegionAvail().y - 50.0f; // reserve bottom row for buttons
|
2026-02-02 12:24:50 -08:00
|
|
|
|
Fix vendor buying, improve character select, parallelize WMO culling, and optimize collision
- Fix CMSG_BUY_ITEM count field from uint8 to uint32 (server silently dropped undersized packets)
- Character select screen: remember last selected character, two-column layout with details panel, double-click to enter world, responsive window sizing
- Fix stale character data between logins by replacing static init flag with per-character GUID tracking
- Parallelize WMO visibility culling across worker threads (same pattern as M2 renderer)
- Optimize WMO collision queries with world-space group bounds early rejection in getFloorHeight, checkWallCollision, isInsideWMO, and raycastBoundingBoxes
- Reduce camera ground samples from 5 to 3 movement-aligned probes
- Add WMO interior lighting, unlit materials, vertex color multiply, and alpha blending support
2026-02-07 15:29:19 -08:00
|
|
|
// ── Left: Character list ──
|
|
|
|
|
ImGui::BeginChild("CharList", ImVec2(listW, listH), true);
|
|
|
|
|
ImGui::Text("Characters");
|
|
|
|
|
ImGui::Separator();
|
2026-02-02 12:24:50 -08:00
|
|
|
|
Fix vendor buying, improve character select, parallelize WMO culling, and optimize collision
- Fix CMSG_BUY_ITEM count field from uint8 to uint32 (server silently dropped undersized packets)
- Character select screen: remember last selected character, two-column layout with details panel, double-click to enter world, responsive window sizing
- Fix stale character data between logins by replacing static init flag with per-character GUID tracking
- Parallelize WMO visibility culling across worker threads (same pattern as M2 renderer)
- Optimize WMO collision queries with world-space group bounds early rejection in getFloorHeight, checkWallCollision, isInsideWMO, and raycastBoundingBoxes
- Reduce camera ground samples from 5 to 3 movement-aligned probes
- Add WMO interior lighting, unlit materials, vertex color multiply, and alpha blending support
2026-02-07 15:29:19 -08:00
|
|
|
if (ImGui::BeginTable("CharactersTable", 5,
|
|
|
|
|
ImGuiTableFlags_Borders | ImGuiTableFlags_RowBg |
|
|
|
|
|
ImGuiTableFlags_ScrollY | ImGuiTableFlags_SizingStretchProp)) {
|
|
|
|
|
ImGui::TableSetupColumn("Name", ImGuiTableColumnFlags_WidthStretch, 2.0f);
|
|
|
|
|
ImGui::TableSetupColumn("Level", ImGuiTableColumnFlags_WidthFixed, 45.0f);
|
|
|
|
|
ImGui::TableSetupColumn("Race", ImGuiTableColumnFlags_WidthStretch, 1.0f);
|
|
|
|
|
ImGui::TableSetupColumn("Class", ImGuiTableColumnFlags_WidthStretch, 1.2f);
|
|
|
|
|
ImGui::TableSetupColumn("Zone", ImGuiTableColumnFlags_WidthFixed, 55.0f);
|
|
|
|
|
ImGui::TableSetupScrollFreeze(0, 1);
|
|
|
|
|
ImGui::TableHeadersRow();
|
|
|
|
|
|
|
|
|
|
for (size_t i = 0; i < characters.size(); ++i) {
|
|
|
|
|
const auto& character = characters[i];
|
|
|
|
|
ImGui::TableNextRow();
|
|
|
|
|
ImGui::TableSetColumnIndex(0);
|
|
|
|
|
|
|
|
|
|
bool isSelected = (selectedCharacterIndex == static_cast<int>(i));
|
|
|
|
|
ImVec4 factionColor = getFactionColor(character.race);
|
|
|
|
|
ImGui::PushStyleColor(ImGuiCol_Text, factionColor);
|
|
|
|
|
|
|
|
|
|
ImGui::PushID(static_cast<int>(i));
|
|
|
|
|
if (ImGui::Selectable(character.name.c_str(), isSelected,
|
|
|
|
|
ImGuiSelectableFlags_SpanAllColumns)) {
|
|
|
|
|
selectedCharacterIndex = static_cast<int>(i);
|
|
|
|
|
selectedCharacterGuid = character.guid;
|
|
|
|
|
saveLastCharacter(character.guid);
|
|
|
|
|
}
|
2026-02-02 12:24:50 -08:00
|
|
|
|
Fix vendor buying, improve character select, parallelize WMO culling, and optimize collision
- Fix CMSG_BUY_ITEM count field from uint8 to uint32 (server silently dropped undersized packets)
- Character select screen: remember last selected character, two-column layout with details panel, double-click to enter world, responsive window sizing
- Fix stale character data between logins by replacing static init flag with per-character GUID tracking
- Parallelize WMO visibility culling across worker threads (same pattern as M2 renderer)
- Optimize WMO collision queries with world-space group bounds early rejection in getFloorHeight, checkWallCollision, isInsideWMO, and raycastBoundingBoxes
- Reduce camera ground samples from 5 to 3 movement-aligned probes
- Add WMO interior lighting, unlit materials, vertex color multiply, and alpha blending support
2026-02-07 15:29:19 -08:00
|
|
|
// Double-click to enter world
|
|
|
|
|
if (ImGui::IsItemHovered() && ImGui::IsMouseDoubleClicked(0)) {
|
|
|
|
|
selectedCharacterIndex = static_cast<int>(i);
|
|
|
|
|
selectedCharacterGuid = character.guid;
|
|
|
|
|
saveLastCharacter(character.guid);
|
|
|
|
|
characterSelected = true;
|
|
|
|
|
gameHandler.selectCharacter(character.guid);
|
|
|
|
|
if (onCharacterSelected) onCharacterSelected(character.guid);
|
|
|
|
|
}
|
|
|
|
|
ImGui::PopID();
|
|
|
|
|
ImGui::PopStyleColor();
|
2026-02-02 12:24:50 -08:00
|
|
|
|
Fix vendor buying, improve character select, parallelize WMO culling, and optimize collision
- Fix CMSG_BUY_ITEM count field from uint8 to uint32 (server silently dropped undersized packets)
- Character select screen: remember last selected character, two-column layout with details panel, double-click to enter world, responsive window sizing
- Fix stale character data between logins by replacing static init flag with per-character GUID tracking
- Parallelize WMO visibility culling across worker threads (same pattern as M2 renderer)
- Optimize WMO collision queries with world-space group bounds early rejection in getFloorHeight, checkWallCollision, isInsideWMO, and raycastBoundingBoxes
- Reduce camera ground samples from 5 to 3 movement-aligned probes
- Add WMO interior lighting, unlit materials, vertex color multiply, and alpha blending support
2026-02-07 15:29:19 -08:00
|
|
|
ImGui::TableSetColumnIndex(1);
|
|
|
|
|
ImGui::Text("%d", character.level);
|
2026-02-02 12:24:50 -08:00
|
|
|
|
Fix vendor buying, improve character select, parallelize WMO culling, and optimize collision
- Fix CMSG_BUY_ITEM count field from uint8 to uint32 (server silently dropped undersized packets)
- Character select screen: remember last selected character, two-column layout with details panel, double-click to enter world, responsive window sizing
- Fix stale character data between logins by replacing static init flag with per-character GUID tracking
- Parallelize WMO visibility culling across worker threads (same pattern as M2 renderer)
- Optimize WMO collision queries with world-space group bounds early rejection in getFloorHeight, checkWallCollision, isInsideWMO, and raycastBoundingBoxes
- Reduce camera ground samples from 5 to 3 movement-aligned probes
- Add WMO interior lighting, unlit materials, vertex color multiply, and alpha blending support
2026-02-07 15:29:19 -08:00
|
|
|
ImGui::TableSetColumnIndex(2);
|
|
|
|
|
ImGui::Text("%s", game::getRaceName(character.race));
|
2026-02-02 12:24:50 -08:00
|
|
|
|
Fix vendor buying, improve character select, parallelize WMO culling, and optimize collision
- Fix CMSG_BUY_ITEM count field from uint8 to uint32 (server silently dropped undersized packets)
- Character select screen: remember last selected character, two-column layout with details panel, double-click to enter world, responsive window sizing
- Fix stale character data between logins by replacing static init flag with per-character GUID tracking
- Parallelize WMO visibility culling across worker threads (same pattern as M2 renderer)
- Optimize WMO collision queries with world-space group bounds early rejection in getFloorHeight, checkWallCollision, isInsideWMO, and raycastBoundingBoxes
- Reduce camera ground samples from 5 to 3 movement-aligned probes
- Add WMO interior lighting, unlit materials, vertex color multiply, and alpha blending support
2026-02-07 15:29:19 -08:00
|
|
|
ImGui::TableSetColumnIndex(3);
|
|
|
|
|
ImGui::Text("%s", game::getClassName(character.characterClass));
|
2026-02-02 12:24:50 -08:00
|
|
|
|
Fix vendor buying, improve character select, parallelize WMO culling, and optimize collision
- Fix CMSG_BUY_ITEM count field from uint8 to uint32 (server silently dropped undersized packets)
- Character select screen: remember last selected character, two-column layout with details panel, double-click to enter world, responsive window sizing
- Fix stale character data between logins by replacing static init flag with per-character GUID tracking
- Parallelize WMO visibility culling across worker threads (same pattern as M2 renderer)
- Optimize WMO collision queries with world-space group bounds early rejection in getFloorHeight, checkWallCollision, isInsideWMO, and raycastBoundingBoxes
- Reduce camera ground samples from 5 to 3 movement-aligned probes
- Add WMO interior lighting, unlit materials, vertex color multiply, and alpha blending support
2026-02-07 15:29:19 -08:00
|
|
|
ImGui::TableSetColumnIndex(4);
|
|
|
|
|
ImGui::Text("%d", character.zoneId);
|
|
|
|
|
}
|
2026-02-02 12:24:50 -08:00
|
|
|
|
Fix vendor buying, improve character select, parallelize WMO culling, and optimize collision
- Fix CMSG_BUY_ITEM count field from uint8 to uint32 (server silently dropped undersized packets)
- Character select screen: remember last selected character, two-column layout with details panel, double-click to enter world, responsive window sizing
- Fix stale character data between logins by replacing static init flag with per-character GUID tracking
- Parallelize WMO visibility culling across worker threads (same pattern as M2 renderer)
- Optimize WMO collision queries with world-space group bounds early rejection in getFloorHeight, checkWallCollision, isInsideWMO, and raycastBoundingBoxes
- Reduce camera ground samples from 5 to 3 movement-aligned probes
- Add WMO interior lighting, unlit materials, vertex color multiply, and alpha blending support
2026-02-07 15:29:19 -08:00
|
|
|
ImGui::EndTable();
|
|
|
|
|
}
|
|
|
|
|
ImGui::EndChild();
|
2026-02-02 12:24:50 -08:00
|
|
|
|
Fix vendor buying, improve character select, parallelize WMO culling, and optimize collision
- Fix CMSG_BUY_ITEM count field from uint8 to uint32 (server silently dropped undersized packets)
- Character select screen: remember last selected character, two-column layout with details panel, double-click to enter world, responsive window sizing
- Fix stale character data between logins by replacing static init flag with per-character GUID tracking
- Parallelize WMO visibility culling across worker threads (same pattern as M2 renderer)
- Optimize WMO collision queries with world-space group bounds early rejection in getFloorHeight, checkWallCollision, isInsideWMO, and raycastBoundingBoxes
- Reduce camera ground samples from 5 to 3 movement-aligned probes
- Add WMO interior lighting, unlit materials, vertex color multiply, and alpha blending support
2026-02-07 15:29:19 -08:00
|
|
|
// ── Right: Details panel ──
|
|
|
|
|
if (detailPanelW > 0.0f &&
|
|
|
|
|
selectedCharacterIndex >= 0 &&
|
|
|
|
|
selectedCharacterIndex < static_cast<int>(characters.size())) {
|
2026-02-02 12:24:50 -08:00
|
|
|
|
Fix vendor buying, improve character select, parallelize WMO culling, and optimize collision
- Fix CMSG_BUY_ITEM count field from uint8 to uint32 (server silently dropped undersized packets)
- Character select screen: remember last selected character, two-column layout with details panel, double-click to enter world, responsive window sizing
- Fix stale character data between logins by replacing static init flag with per-character GUID tracking
- Parallelize WMO visibility culling across worker threads (same pattern as M2 renderer)
- Optimize WMO collision queries with world-space group bounds early rejection in getFloorHeight, checkWallCollision, isInsideWMO, and raycastBoundingBoxes
- Reduce camera ground samples from 5 to 3 movement-aligned probes
- Add WMO interior lighting, unlit materials, vertex color multiply, and alpha blending support
2026-02-07 15:29:19 -08:00
|
|
|
const auto& character = characters[selectedCharacterIndex];
|
2026-02-02 12:24:50 -08:00
|
|
|
|
2026-02-12 14:55:27 -08:00
|
|
|
// Keep the 3D preview in sync with the selected character.
|
|
|
|
|
if (assetManager_ && assetManager_->isInitialized()) {
|
|
|
|
|
if (!preview_) {
|
|
|
|
|
preview_ = std::make_unique<rendering::CharacterPreview>();
|
|
|
|
|
}
|
|
|
|
|
if (!previewInitialized_) {
|
|
|
|
|
previewInitialized_ = preview_->initialize(assetManager_);
|
|
|
|
|
if (!previewInitialized_) {
|
|
|
|
|
LOG_WARNING("CharacterScreen: failed to init CharacterPreview");
|
|
|
|
|
preview_.reset();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (preview_) {
|
|
|
|
|
const uint64_t equipHash = hashEquipment(character.equipment);
|
|
|
|
|
const bool changed =
|
|
|
|
|
(previewGuid_ != character.guid) ||
|
|
|
|
|
(previewAppearanceBytes_ != character.appearanceBytes) ||
|
|
|
|
|
(previewFacialFeatures_ != character.facialFeatures) ||
|
|
|
|
|
(previewUseFemaleModel_ != character.useFemaleModel) ||
|
2026-02-13 16:53:28 -08:00
|
|
|
(previewEquipHash_ != equipHash);
|
2026-02-12 14:55:27 -08:00
|
|
|
|
|
|
|
|
if (changed) {
|
|
|
|
|
uint8_t skin = character.appearanceBytes & 0xFF;
|
|
|
|
|
uint8_t face = (character.appearanceBytes >> 8) & 0xFF;
|
|
|
|
|
uint8_t hairStyle = (character.appearanceBytes >> 16) & 0xFF;
|
|
|
|
|
uint8_t hairColor = (character.appearanceBytes >> 24) & 0xFF;
|
|
|
|
|
|
|
|
|
|
if (preview_->loadCharacter(character.race, character.gender,
|
|
|
|
|
skin, face, hairStyle, hairColor,
|
|
|
|
|
character.facialFeatures, character.useFemaleModel)) {
|
|
|
|
|
preview_->applyEquipment(character.equipment);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
previewGuid_ = character.guid;
|
|
|
|
|
previewAppearanceBytes_ = character.appearanceBytes;
|
|
|
|
|
previewFacialFeatures_ = character.facialFeatures;
|
|
|
|
|
previewUseFemaleModel_ = character.useFemaleModel;
|
|
|
|
|
previewEquipHash_ = equipHash;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Drive preview animation and render to its FBO.
|
|
|
|
|
preview_->update(ImGui::GetIO().DeltaTime);
|
|
|
|
|
preview_->render();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
Fix vendor buying, improve character select, parallelize WMO culling, and optimize collision
- Fix CMSG_BUY_ITEM count field from uint8 to uint32 (server silently dropped undersized packets)
- Character select screen: remember last selected character, two-column layout with details panel, double-click to enter world, responsive window sizing
- Fix stale character data between logins by replacing static init flag with per-character GUID tracking
- Parallelize WMO visibility culling across worker threads (same pattern as M2 renderer)
- Optimize WMO collision queries with world-space group bounds early rejection in getFloorHeight, checkWallCollision, isInsideWMO, and raycastBoundingBoxes
- Reduce camera ground samples from 5 to 3 movement-aligned probes
- Add WMO interior lighting, unlit materials, vertex color multiply, and alpha blending support
2026-02-07 15:29:19 -08:00
|
|
|
ImGui::SameLine();
|
|
|
|
|
ImGui::BeginChild("CharDetails", ImVec2(detailPanelW, listH), true);
|
|
|
|
|
|
2026-02-12 14:55:27 -08:00
|
|
|
// 3D preview portrait
|
|
|
|
|
if (preview_ && preview_->getTextureId() != 0) {
|
|
|
|
|
float imgW = ImGui::GetContentRegionAvail().x;
|
|
|
|
|
float imgH = imgW * (static_cast<float>(preview_->getHeight()) /
|
|
|
|
|
static_cast<float>(preview_->getWidth()));
|
|
|
|
|
// Clamp to avoid taking the entire panel
|
|
|
|
|
float maxH = 320.0f;
|
|
|
|
|
if (imgH > maxH) {
|
|
|
|
|
imgH = maxH;
|
|
|
|
|
imgW = imgH * (static_cast<float>(preview_->getWidth()) /
|
|
|
|
|
static_cast<float>(preview_->getHeight()));
|
|
|
|
|
}
|
2026-02-21 19:41:21 -08:00
|
|
|
// TODO: Vulkan offscreen preview render target
|
|
|
|
|
if (preview_->getTextureId()) {
|
|
|
|
|
ImGui::Image(
|
|
|
|
|
static_cast<ImTextureID>(0),
|
|
|
|
|
ImVec2(imgW, imgH),
|
|
|
|
|
ImVec2(0.0f, 1.0f),
|
|
|
|
|
ImVec2(1.0f, 0.0f));
|
|
|
|
|
}
|
2026-02-12 14:55:27 -08:00
|
|
|
|
|
|
|
|
if (ImGui::IsItemHovered() && ImGui::IsMouseDragging(ImGuiMouseButton_Left)) {
|
|
|
|
|
preview_->rotate(ImGui::GetIO().MouseDelta.x * 0.2f);
|
|
|
|
|
}
|
|
|
|
|
ImGui::Spacing();
|
|
|
|
|
} else if (!assetManager_ || !assetManager_->isInitialized()) {
|
|
|
|
|
ImGui::TextDisabled("Preview unavailable (assets not loaded)");
|
|
|
|
|
ImGui::Spacing();
|
|
|
|
|
}
|
|
|
|
|
|
Fix vendor buying, improve character select, parallelize WMO culling, and optimize collision
- Fix CMSG_BUY_ITEM count field from uint8 to uint32 (server silently dropped undersized packets)
- Character select screen: remember last selected character, two-column layout with details panel, double-click to enter world, responsive window sizing
- Fix stale character data between logins by replacing static init flag with per-character GUID tracking
- Parallelize WMO visibility culling across worker threads (same pattern as M2 renderer)
- Optimize WMO collision queries with world-space group bounds early rejection in getFloorHeight, checkWallCollision, isInsideWMO, and raycastBoundingBoxes
- Reduce camera ground samples from 5 to 3 movement-aligned probes
- Add WMO interior lighting, unlit materials, vertex color multiply, and alpha blending support
2026-02-07 15:29:19 -08:00
|
|
|
ImGui::TextColored(getFactionColor(character.race), "%s", character.name.c_str());
|
2026-02-02 12:24:50 -08:00
|
|
|
ImGui::Separator();
|
|
|
|
|
ImGui::Spacing();
|
|
|
|
|
|
Fix vendor buying, improve character select, parallelize WMO culling, and optimize collision
- Fix CMSG_BUY_ITEM count field from uint8 to uint32 (server silently dropped undersized packets)
- Character select screen: remember last selected character, two-column layout with details panel, double-click to enter world, responsive window sizing
- Fix stale character data between logins by replacing static init flag with per-character GUID tracking
- Parallelize WMO visibility culling across worker threads (same pattern as M2 renderer)
- Optimize WMO collision queries with world-space group bounds early rejection in getFloorHeight, checkWallCollision, isInsideWMO, and raycastBoundingBoxes
- Reduce camera ground samples from 5 to 3 movement-aligned probes
- Add WMO interior lighting, unlit materials, vertex color multiply, and alpha blending support
2026-02-07 15:29:19 -08:00
|
|
|
ImGui::Text("Level %d", character.level);
|
|
|
|
|
ImGui::Text("%s", game::getRaceName(character.race));
|
|
|
|
|
ImGui::Text("%s", game::getClassName(character.characterClass));
|
|
|
|
|
ImGui::Text("%s", game::getGenderName(character.gender));
|
|
|
|
|
ImGui::Spacing();
|
|
|
|
|
ImGui::Text("Map %d, Zone %d", character.mapId, character.zoneId);
|
2026-02-02 12:24:50 -08:00
|
|
|
|
Fix vendor buying, improve character select, parallelize WMO culling, and optimize collision
- Fix CMSG_BUY_ITEM count field from uint8 to uint32 (server silently dropped undersized packets)
- Character select screen: remember last selected character, two-column layout with details panel, double-click to enter world, responsive window sizing
- Fix stale character data between logins by replacing static init flag with per-character GUID tracking
- Parallelize WMO visibility culling across worker threads (same pattern as M2 renderer)
- Optimize WMO collision queries with world-space group bounds early rejection in getFloorHeight, checkWallCollision, isInsideWMO, and raycastBoundingBoxes
- Reduce camera ground samples from 5 to 3 movement-aligned probes
- Add WMO interior lighting, unlit materials, vertex color multiply, and alpha blending support
2026-02-07 15:29:19 -08:00
|
|
|
if (character.hasGuild()) {
|
|
|
|
|
ImGui::Text("Guild ID: %d", character.guildId);
|
|
|
|
|
} else {
|
|
|
|
|
ImGui::TextDisabled("No Guild");
|
|
|
|
|
}
|
2026-02-02 12:24:50 -08:00
|
|
|
|
Fix vendor buying, improve character select, parallelize WMO culling, and optimize collision
- Fix CMSG_BUY_ITEM count field from uint8 to uint32 (server silently dropped undersized packets)
- Character select screen: remember last selected character, two-column layout with details panel, double-click to enter world, responsive window sizing
- Fix stale character data between logins by replacing static init flag with per-character GUID tracking
- Parallelize WMO visibility culling across worker threads (same pattern as M2 renderer)
- Optimize WMO collision queries with world-space group bounds early rejection in getFloorHeight, checkWallCollision, isInsideWMO, and raycastBoundingBoxes
- Reduce camera ground samples from 5 to 3 movement-aligned probes
- Add WMO interior lighting, unlit materials, vertex color multiply, and alpha blending support
2026-02-07 15:29:19 -08:00
|
|
|
if (character.hasPet()) {
|
2026-02-02 12:24:50 -08:00
|
|
|
ImGui::Spacing();
|
Fix vendor buying, improve character select, parallelize WMO culling, and optimize collision
- Fix CMSG_BUY_ITEM count field from uint8 to uint32 (server silently dropped undersized packets)
- Character select screen: remember last selected character, two-column layout with details panel, double-click to enter world, responsive window sizing
- Fix stale character data between logins by replacing static init flag with per-character GUID tracking
- Parallelize WMO visibility culling across worker threads (same pattern as M2 renderer)
- Optimize WMO collision queries with world-space group bounds early rejection in getFloorHeight, checkWallCollision, isInsideWMO, and raycastBoundingBoxes
- Reduce camera ground samples from 5 to 3 movement-aligned probes
- Add WMO interior lighting, unlit materials, vertex color multiply, and alpha blending support
2026-02-07 15:29:19 -08:00
|
|
|
ImGui::Text("Pet Lv%d (Family %d)", character.pet.level, character.pet.family);
|
|
|
|
|
}
|
2026-02-02 12:24:50 -08:00
|
|
|
|
Fix vendor buying, improve character select, parallelize WMO culling, and optimize collision
- Fix CMSG_BUY_ITEM count field from uint8 to uint32 (server silently dropped undersized packets)
- Character select screen: remember last selected character, two-column layout with details panel, double-click to enter world, responsive window sizing
- Fix stale character data between logins by replacing static init flag with per-character GUID tracking
- Parallelize WMO visibility culling across worker threads (same pattern as M2 renderer)
- Optimize WMO collision queries with world-space group bounds early rejection in getFloorHeight, checkWallCollision, isInsideWMO, and raycastBoundingBoxes
- Reduce camera ground samples from 5 to 3 movement-aligned probes
- Add WMO interior lighting, unlit materials, vertex color multiply, and alpha blending support
2026-02-07 15:29:19 -08:00
|
|
|
ImGui::Spacing();
|
|
|
|
|
ImGui::Separator();
|
|
|
|
|
ImGui::Spacing();
|
2026-02-02 12:24:50 -08:00
|
|
|
|
Fix vendor buying, improve character select, parallelize WMO culling, and optimize collision
- Fix CMSG_BUY_ITEM count field from uint8 to uint32 (server silently dropped undersized packets)
- Character select screen: remember last selected character, two-column layout with details panel, double-click to enter world, responsive window sizing
- Fix stale character data between logins by replacing static init flag with per-character GUID tracking
- Parallelize WMO visibility culling across worker threads (same pattern as M2 renderer)
- Optimize WMO collision queries with world-space group bounds early rejection in getFloorHeight, checkWallCollision, isInsideWMO, and raycastBoundingBoxes
- Reduce camera ground samples from 5 to 3 movement-aligned probes
- Add WMO interior lighting, unlit materials, vertex color multiply, and alpha blending support
2026-02-07 15:29:19 -08:00
|
|
|
// Enter World button — full width
|
|
|
|
|
float btnW = ImGui::GetContentRegionAvail().x;
|
2026-02-14 20:20:43 -08:00
|
|
|
bool disconnected = (gameHandler.getState() == game::WorldState::DISCONNECTED ||
|
|
|
|
|
gameHandler.getState() == game::WorldState::FAILED);
|
|
|
|
|
if (disconnected) {
|
|
|
|
|
ImGui::TextColored(ImVec4(1.0f, 0.6f, 0.3f, 1.0f), "Connection lost — click Back to reconnect");
|
|
|
|
|
}
|
|
|
|
|
if (disconnected) ImGui::BeginDisabled();
|
Fix vendor buying, improve character select, parallelize WMO culling, and optimize collision
- Fix CMSG_BUY_ITEM count field from uint8 to uint32 (server silently dropped undersized packets)
- Character select screen: remember last selected character, two-column layout with details panel, double-click to enter world, responsive window sizing
- Fix stale character data between logins by replacing static init flag with per-character GUID tracking
- Parallelize WMO visibility culling across worker threads (same pattern as M2 renderer)
- Optimize WMO collision queries with world-space group bounds early rejection in getFloorHeight, checkWallCollision, isInsideWMO, and raycastBoundingBoxes
- Reduce camera ground samples from 5 to 3 movement-aligned probes
- Add WMO interior lighting, unlit materials, vertex color multiply, and alpha blending support
2026-02-07 15:29:19 -08:00
|
|
|
if (ImGui::Button("Enter World", ImVec2(btnW, 44))) {
|
|
|
|
|
characterSelected = true;
|
|
|
|
|
saveLastCharacter(character.guid);
|
|
|
|
|
std::stringstream ss;
|
|
|
|
|
ss << "Entering world with " << character.name << "...";
|
|
|
|
|
setStatus(ss.str());
|
|
|
|
|
gameHandler.selectCharacter(character.guid);
|
|
|
|
|
if (onCharacterSelected) onCharacterSelected(character.guid);
|
|
|
|
|
}
|
2026-02-14 20:20:43 -08:00
|
|
|
if (disconnected) ImGui::EndDisabled();
|
2026-02-02 12:24:50 -08:00
|
|
|
|
Fix vendor buying, improve character select, parallelize WMO culling, and optimize collision
- Fix CMSG_BUY_ITEM count field from uint8 to uint32 (server silently dropped undersized packets)
- Character select screen: remember last selected character, two-column layout with details panel, double-click to enter world, responsive window sizing
- Fix stale character data between logins by replacing static init flag with per-character GUID tracking
- Parallelize WMO visibility culling across worker threads (same pattern as M2 renderer)
- Optimize WMO collision queries with world-space group bounds early rejection in getFloorHeight, checkWallCollision, isInsideWMO, and raycastBoundingBoxes
- Reduce camera ground samples from 5 to 3 movement-aligned probes
- Add WMO interior lighting, unlit materials, vertex color multiply, and alpha blending support
2026-02-07 15:29:19 -08:00
|
|
|
ImGui::EndChild();
|
2026-02-06 03:24:46 -08:00
|
|
|
}
|
|
|
|
|
|
Fix vendor buying, improve character select, parallelize WMO culling, and optimize collision
- Fix CMSG_BUY_ITEM count field from uint8 to uint32 (server silently dropped undersized packets)
- Character select screen: remember last selected character, two-column layout with details panel, double-click to enter world, responsive window sizing
- Fix stale character data between logins by replacing static init flag with per-character GUID tracking
- Parallelize WMO visibility culling across worker threads (same pattern as M2 renderer)
- Optimize WMO collision queries with world-space group bounds early rejection in getFloorHeight, checkWallCollision, isInsideWMO, and raycastBoundingBoxes
- Reduce camera ground samples from 5 to 3 movement-aligned probes
- Add WMO interior lighting, unlit materials, vertex color multiply, and alpha blending support
2026-02-07 15:29:19 -08:00
|
|
|
// ── Bottom button row ──
|
|
|
|
|
ImGui::Spacing();
|
|
|
|
|
if (ImGui::Button("Back", ImVec2(120, 36))) { if (onBack) onBack(); }
|
2026-02-06 03:24:46 -08:00
|
|
|
ImGui::SameLine();
|
Fix vendor buying, improve character select, parallelize WMO culling, and optimize collision
- Fix CMSG_BUY_ITEM count field from uint8 to uint32 (server silently dropped undersized packets)
- Character select screen: remember last selected character, two-column layout with details panel, double-click to enter world, responsive window sizing
- Fix stale character data between logins by replacing static init flag with per-character GUID tracking
- Parallelize WMO visibility culling across worker threads (same pattern as M2 renderer)
- Optimize WMO collision queries with world-space group bounds early rejection in getFloorHeight, checkWallCollision, isInsideWMO, and raycastBoundingBoxes
- Reduce camera ground samples from 5 to 3 movement-aligned probes
- Add WMO interior lighting, unlit materials, vertex color multiply, and alpha blending support
2026-02-07 15:29:19 -08:00
|
|
|
if (ImGui::Button("Refresh", ImVec2(120, 36))) {
|
2026-02-02 12:24:50 -08:00
|
|
|
if (gameHandler.getState() == game::WorldState::READY ||
|
|
|
|
|
gameHandler.getState() == game::WorldState::CHAR_LIST_RECEIVED) {
|
|
|
|
|
gameHandler.requestCharacterList();
|
|
|
|
|
setStatus("Refreshing character list...");
|
|
|
|
|
}
|
|
|
|
|
}
|
2026-02-05 14:13:48 -08:00
|
|
|
ImGui::SameLine();
|
Fix vendor buying, improve character select, parallelize WMO culling, and optimize collision
- Fix CMSG_BUY_ITEM count field from uint8 to uint32 (server silently dropped undersized packets)
- Character select screen: remember last selected character, two-column layout with details panel, double-click to enter world, responsive window sizing
- Fix stale character data between logins by replacing static init flag with per-character GUID tracking
- Parallelize WMO visibility culling across worker threads (same pattern as M2 renderer)
- Optimize WMO collision queries with world-space group bounds early rejection in getFloorHeight, checkWallCollision, isInsideWMO, and raycastBoundingBoxes
- Reduce camera ground samples from 5 to 3 movement-aligned probes
- Add WMO interior lighting, unlit materials, vertex color multiply, and alpha blending support
2026-02-07 15:29:19 -08:00
|
|
|
if (ImGui::Button("Create Character", ImVec2(160, 36))) {
|
|
|
|
|
if (onCreateCharacter) onCreateCharacter();
|
2026-02-05 14:13:48 -08:00
|
|
|
}
|
|
|
|
|
|
2026-02-07 15:58:18 -08:00
|
|
|
// Delete button — small, red, far right, only when a character is selected
|
|
|
|
|
if (selectedCharacterIndex >= 0 &&
|
|
|
|
|
selectedCharacterIndex < static_cast<int>(characters.size())) {
|
|
|
|
|
float deleteW = 80.0f;
|
|
|
|
|
ImGui::SameLine(ImGui::GetContentRegionMax().x - deleteW);
|
|
|
|
|
ImGui::PushStyleColor(ImGuiCol_Button, ImVec4(0.5f, 0.08f, 0.08f, 1.0f));
|
|
|
|
|
ImGui::PushStyleColor(ImGuiCol_ButtonHovered, ImVec4(0.7f, 0.1f, 0.1f, 1.0f));
|
|
|
|
|
ImGui::PushStyleColor(ImGuiCol_Text, ImVec4(0.9f, 0.5f, 0.5f, 1.0f));
|
|
|
|
|
if (ImGui::Button("Delete", ImVec2(deleteW, 28))) {
|
|
|
|
|
deleteConfirmStage = 1;
|
|
|
|
|
ImGui::OpenPopup("DeleteConfirm1");
|
|
|
|
|
}
|
|
|
|
|
ImGui::PopStyleColor(3);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// First confirmation popup
|
|
|
|
|
if (ImGui::BeginPopupModal("DeleteConfirm1", nullptr,
|
|
|
|
|
ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoMove)) {
|
|
|
|
|
const auto& ch = characters[selectedCharacterIndex];
|
|
|
|
|
ImGui::Text("Are you sure you want to delete");
|
|
|
|
|
ImGui::TextColored(getFactionColor(ch.race), "%s", ch.name.c_str());
|
|
|
|
|
ImGui::Text("Level %d %s %s?",
|
|
|
|
|
ch.level, game::getRaceName(ch.race), game::getClassName(ch.characterClass));
|
|
|
|
|
ImGui::Spacing();
|
|
|
|
|
ImGui::Separator();
|
|
|
|
|
ImGui::Spacing();
|
|
|
|
|
if (ImGui::Button("Yes, delete this character", ImVec2(240, 32))) {
|
|
|
|
|
ImGui::CloseCurrentPopup();
|
|
|
|
|
deleteConfirmStage = 2;
|
|
|
|
|
ImGui::OpenPopup("DeleteConfirm2");
|
|
|
|
|
}
|
|
|
|
|
ImGui::SameLine();
|
|
|
|
|
if (ImGui::Button("Cancel", ImVec2(100, 32))) {
|
|
|
|
|
deleteConfirmStage = 0;
|
|
|
|
|
ImGui::CloseCurrentPopup();
|
|
|
|
|
}
|
|
|
|
|
ImGui::EndPopup();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Second (final) confirmation popup
|
|
|
|
|
if (deleteConfirmStage == 2) {
|
|
|
|
|
ImGui::OpenPopup("DeleteConfirm2");
|
|
|
|
|
}
|
|
|
|
|
if (ImGui::BeginPopupModal("DeleteConfirm2", nullptr,
|
|
|
|
|
ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoMove)) {
|
|
|
|
|
const auto& ch = characters[selectedCharacterIndex];
|
|
|
|
|
ImGui::PushStyleColor(ImGuiCol_Text, ImVec4(1.0f, 0.3f, 0.3f, 1.0f));
|
|
|
|
|
ImGui::Text("THIS CANNOT BE UNDONE!");
|
|
|
|
|
ImGui::PopStyleColor();
|
|
|
|
|
ImGui::Spacing();
|
|
|
|
|
ImGui::Text("Are you REALLY sure you want to permanently");
|
|
|
|
|
ImGui::Text("delete %s? This character will be gone forever.", ch.name.c_str());
|
|
|
|
|
ImGui::Spacing();
|
|
|
|
|
ImGui::Separator();
|
|
|
|
|
ImGui::Spacing();
|
|
|
|
|
ImGui::PushStyleColor(ImGuiCol_Button, ImVec4(0.7f, 0.0f, 0.0f, 1.0f));
|
|
|
|
|
if (ImGui::Button("DELETE PERMANENTLY", ImVec2(240, 32))) {
|
|
|
|
|
if (onDeleteCharacter) onDeleteCharacter(ch.guid);
|
|
|
|
|
deleteConfirmStage = 0;
|
|
|
|
|
selectedCharacterIndex = -1;
|
|
|
|
|
selectedCharacterGuid = 0;
|
|
|
|
|
ImGui::CloseCurrentPopup();
|
|
|
|
|
}
|
|
|
|
|
ImGui::PopStyleColor();
|
|
|
|
|
ImGui::SameLine();
|
|
|
|
|
if (ImGui::Button("Cancel", ImVec2(100, 32))) {
|
|
|
|
|
deleteConfirmStage = 0;
|
|
|
|
|
ImGui::CloseCurrentPopup();
|
|
|
|
|
}
|
|
|
|
|
ImGui::EndPopup();
|
|
|
|
|
}
|
|
|
|
|
|
2026-02-02 12:24:50 -08:00
|
|
|
ImGui::End();
|
|
|
|
|
}
|
|
|
|
|
|
2026-02-17 13:59:29 -08:00
|
|
|
void CharacterScreen::setStatus(const std::string& message, bool isError) {
|
2026-02-02 12:24:50 -08:00
|
|
|
statusMessage = message;
|
2026-02-17 13:59:29 -08:00
|
|
|
statusIsError = isError;
|
2026-02-02 12:24:50 -08:00
|
|
|
}
|
|
|
|
|
|
2026-02-09 22:51:13 -08:00
|
|
|
void CharacterScreen::selectCharacterByName(const std::string& name) {
|
|
|
|
|
newlyCreatedCharacterName = name;
|
|
|
|
|
restoredLastCharacter = false; // Allow re-selection in render()
|
|
|
|
|
selectedCharacterIndex = -1;
|
|
|
|
|
}
|
|
|
|
|
|
2026-02-02 12:24:50 -08:00
|
|
|
ImVec4 CharacterScreen::getFactionColor(game::Race race) const {
|
|
|
|
|
// Alliance races: blue
|
|
|
|
|
if (race == game::Race::HUMAN ||
|
|
|
|
|
race == game::Race::DWARF ||
|
|
|
|
|
race == game::Race::NIGHT_ELF ||
|
|
|
|
|
race == game::Race::GNOME ||
|
|
|
|
|
race == game::Race::DRAENEI) {
|
Fix vendor buying, improve character select, parallelize WMO culling, and optimize collision
- Fix CMSG_BUY_ITEM count field from uint8 to uint32 (server silently dropped undersized packets)
- Character select screen: remember last selected character, two-column layout with details panel, double-click to enter world, responsive window sizing
- Fix stale character data between logins by replacing static init flag with per-character GUID tracking
- Parallelize WMO visibility culling across worker threads (same pattern as M2 renderer)
- Optimize WMO collision queries with world-space group bounds early rejection in getFloorHeight, checkWallCollision, isInsideWMO, and raycastBoundingBoxes
- Reduce camera ground samples from 5 to 3 movement-aligned probes
- Add WMO interior lighting, unlit materials, vertex color multiply, and alpha blending support
2026-02-07 15:29:19 -08:00
|
|
|
return ImVec4(0.3f, 0.5f, 1.0f, 1.0f);
|
2026-02-02 12:24:50 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Horde races: red
|
|
|
|
|
if (race == game::Race::ORC ||
|
|
|
|
|
race == game::Race::UNDEAD ||
|
|
|
|
|
race == game::Race::TAUREN ||
|
|
|
|
|
race == game::Race::TROLL ||
|
|
|
|
|
race == game::Race::BLOOD_ELF) {
|
Fix vendor buying, improve character select, parallelize WMO culling, and optimize collision
- Fix CMSG_BUY_ITEM count field from uint8 to uint32 (server silently dropped undersized packets)
- Character select screen: remember last selected character, two-column layout with details panel, double-click to enter world, responsive window sizing
- Fix stale character data between logins by replacing static init flag with per-character GUID tracking
- Parallelize WMO visibility culling across worker threads (same pattern as M2 renderer)
- Optimize WMO collision queries with world-space group bounds early rejection in getFloorHeight, checkWallCollision, isInsideWMO, and raycastBoundingBoxes
- Reduce camera ground samples from 5 to 3 movement-aligned probes
- Add WMO interior lighting, unlit materials, vertex color multiply, and alpha blending support
2026-02-07 15:29:19 -08:00
|
|
|
return ImVec4(1.0f, 0.3f, 0.3f, 1.0f);
|
2026-02-02 12:24:50 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return ImVec4(1.0f, 1.0f, 1.0f, 1.0f);
|
|
|
|
|
}
|
|
|
|
|
|
Fix vendor buying, improve character select, parallelize WMO culling, and optimize collision
- Fix CMSG_BUY_ITEM count field from uint8 to uint32 (server silently dropped undersized packets)
- Character select screen: remember last selected character, two-column layout with details panel, double-click to enter world, responsive window sizing
- Fix stale character data between logins by replacing static init flag with per-character GUID tracking
- Parallelize WMO visibility culling across worker threads (same pattern as M2 renderer)
- Optimize WMO collision queries with world-space group bounds early rejection in getFloorHeight, checkWallCollision, isInsideWMO, and raycastBoundingBoxes
- Reduce camera ground samples from 5 to 3 movement-aligned probes
- Add WMO interior lighting, unlit materials, vertex color multiply, and alpha blending support
2026-02-07 15:29:19 -08:00
|
|
|
std::string CharacterScreen::getConfigDir() {
|
|
|
|
|
#ifdef _WIN32
|
|
|
|
|
const char* appdata = std::getenv("APPDATA");
|
|
|
|
|
return appdata ? std::string(appdata) + "\\wowee" : ".";
|
|
|
|
|
#else
|
|
|
|
|
const char* home = std::getenv("HOME");
|
|
|
|
|
return home ? std::string(home) + "/.wowee" : ".";
|
|
|
|
|
#endif
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void CharacterScreen::saveLastCharacter(uint64_t guid) {
|
|
|
|
|
std::string dir = getConfigDir();
|
|
|
|
|
std::filesystem::create_directories(dir);
|
|
|
|
|
std::ofstream f(dir + "/last_character.cfg");
|
|
|
|
|
if (f) f << guid;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
uint64_t CharacterScreen::loadLastCharacter() {
|
|
|
|
|
std::string path = getConfigDir() + "/last_character.cfg";
|
|
|
|
|
std::ifstream f(path);
|
|
|
|
|
uint64_t guid = 0;
|
|
|
|
|
if (f) f >> guid;
|
|
|
|
|
return guid;
|
|
|
|
|
}
|
|
|
|
|
|
2026-02-02 12:24:50 -08:00
|
|
|
}} // namespace wowee::ui
|