diff --git a/assets/shaders/minimap_display.frag.glsl b/assets/shaders/minimap_display.frag.glsl index 3f4d42e4..476017b9 100644 --- a/assets/shaders/minimap_display.frag.glsl +++ b/assets/shaders/minimap_display.frag.glsl @@ -40,7 +40,7 @@ void main() { float cs = cos(push.rotation); float sn = sin(push.rotation); vec2 rotated = vec2(center.x * cs - center.y * sn, center.x * sn + center.y * cs); - vec2 mapUV = push.playerUV + vec2(-rotated.x, rotated.y) * push.zoomRadius * 2.0; + vec2 mapUV = push.playerUV + vec2(rotated.x, rotated.y) * push.zoomRadius * 2.0; vec4 mapColor = texture(uComposite, mapUV); diff --git a/assets/shaders/minimap_display.frag.spv b/assets/shaders/minimap_display.frag.spv index 5c0ac7b0..f33deef2 100644 Binary files a/assets/shaders/minimap_display.frag.spv and b/assets/shaders/minimap_display.frag.spv differ diff --git a/include/ui/game_screen.hpp b/include/ui/game_screen.hpp index a6ebf9c0..6c1244ae 100644 --- a/include/ui/game_screen.hpp +++ b/include/ui/game_screen.hpp @@ -192,6 +192,7 @@ private: bool pendingMinimapNpcDots = false; bool pendingShowLatencyMeter = true; bool pendingSeparateBags = true; + bool pendingShowKeyring = true; bool pendingAutoLoot = false; // Keybinding customization diff --git a/include/ui/inventory_screen.hpp b/include/ui/inventory_screen.hpp index 65ef41c9..b9c30c6c 100644 --- a/include/ui/inventory_screen.hpp +++ b/include/ui/inventory_screen.hpp @@ -39,6 +39,8 @@ public: bool isSeparateBags() const { return separateBags_; } void toggleCompactBags() { compactBags_ = !compactBags_; } bool isCompactBags() const { return compactBags_; } + void setShowKeyring(bool show) { showKeyring_ = show; } + bool isShowKeyring() const { return showKeyring_; } bool isBackpackOpen() const { return backpackOpen_; } bool isBagOpen(int idx) const { return idx >= 0 && idx < 4 ? bagOpen_[idx] : false; } @@ -79,6 +81,7 @@ private: bool bKeyWasDown = false; bool separateBags_ = true; bool compactBags_ = false; + bool showKeyring_ = true; bool backpackOpen_ = false; std::array bagOpen_{}; bool cKeyWasDown = false; diff --git a/src/rendering/minimap.cpp b/src/rendering/minimap.cpp index 0f44869b..f47264d0 100644 --- a/src/rendering/minimap.cpp +++ b/src/rendering/minimap.cpp @@ -513,14 +513,15 @@ void Minimap::render(VkCommandBuffer cmd, const Camera& playerCamera, float arrowRotation = 0.0f; if (!rotateWithCamera) { - // Prefer authoritative orientation if provided. This value is expected - // to already match minimap shader rotation convention. if (hasPlayerOrientation) { arrowRotation = playerOrientation; } else { glm::vec3 fwd = playerCamera.getForward(); - arrowRotation = std::atan2(-fwd.x, fwd.y); + arrowRotation = -std::atan2(-fwd.x, fwd.y); } + } else if (hasPlayerOrientation) { + // Show character facing relative to the rotated map + arrowRotation = playerOrientation + rotation; } MinimapDisplayPush push{}; diff --git a/src/ui/game_screen.cpp b/src/ui/game_screen.cpp index eab06871..64a6155e 100644 --- a/src/ui/game_screen.cpp +++ b/src/ui/game_screen.cpp @@ -15326,6 +15326,10 @@ void GameScreen::renderSettingsWindow() { inventoryScreen.setSeparateBags(pendingSeparateBags); saveSettings(); } + if (ImGui::Checkbox("Show Key Ring", &pendingShowKeyring)) { + inventoryScreen.setShowKeyring(pendingShowKeyring); + saveSettings(); + } ImGui::Spacing(); ImGui::Separator(); @@ -15341,6 +15345,8 @@ void GameScreen::renderSettingsWindow() { pendingMinimapNpcDots = false; pendingSeparateBags = true; inventoryScreen.setSeparateBags(true); + pendingShowKeyring = true; + inventoryScreen.setShowKeyring(true); uiOpacity_ = 0.65f; minimapRotate_ = false; minimapSquare_ = false; @@ -17244,6 +17250,7 @@ void GameScreen::saveSettings() { out << "show_dps_meter=" << (showDPSMeter_ ? 1 : 0) << "\n"; out << "show_cooldown_tracker=" << (showCooldownTracker_ ? 1 : 0) << "\n"; out << "separate_bags=" << (pendingSeparateBags ? 1 : 0) << "\n"; + out << "show_keyring=" << (pendingShowKeyring ? 1 : 0) << "\n"; out << "action_bar_scale=" << pendingActionBarScale << "\n"; out << "nameplate_scale=" << nameplateScale_ << "\n"; out << "show_action_bar2=" << (pendingShowActionBar2 ? 1 : 0) << "\n"; @@ -17365,6 +17372,9 @@ void GameScreen::loadSettings() { } else if (key == "separate_bags") { pendingSeparateBags = (std::stoi(val) != 0); inventoryScreen.setSeparateBags(pendingSeparateBags); + } else if (key == "show_keyring") { + pendingShowKeyring = (std::stoi(val) != 0); + inventoryScreen.setShowKeyring(pendingShowKeyring); } else if (key == "action_bar_scale") { pendingActionBarScale = std::clamp(std::stof(val), 0.5f, 1.5f); } else if (key == "nameplate_scale") { diff --git a/src/ui/inventory_screen.cpp b/src/ui/inventory_screen.cpp index 3d4b0c17..0c826c7d 100644 --- a/src/ui/inventory_screen.cpp +++ b/src/ui/inventory_screen.cpp @@ -1069,20 +1069,29 @@ void InventoryScreen::renderBagWindow(const char* title, bool& isOpen, ImGui::PopID(); } - if (bagIndex < 0) { - ImGui::Spacing(); - ImGui::Separator(); - ImGui::TextColored(ImVec4(0.8f, 0.8f, 0.0f, 1.0f), "Keyring"); - for (int i = 0; i < inventory.getKeyringSize(); ++i) { - if (i % columns != 0) ImGui::SameLine(); - const auto& slot = inventory.getKeyringSlot(i); - char id[32]; - snprintf(id, sizeof(id), "##skr_%d", i); - ImGui::PushID(id); - // Keyring is display-only for now. - renderItemSlot(inventory, slot, slotSize, nullptr, - SlotKind::BACKPACK, -1, game::EquipSlot::NUM_SLOTS); - ImGui::PopID(); + if (bagIndex < 0 && showKeyring_) { + constexpr float keySlotSize = 24.0f; + constexpr int keyCols = 8; + // Only show rows that contain items (round up to full row) + int lastOccupied = -1; + for (int i = inventory.getKeyringSize() - 1; i >= 0; --i) { + if (!inventory.getKeyringSlot(i).empty()) { lastOccupied = i; break; } + } + int visibleSlots = (lastOccupied < 0) ? 0 : ((lastOccupied / keyCols) + 1) * keyCols; + if (visibleSlots > 0) { + ImGui::Spacing(); + ImGui::Separator(); + ImGui::TextColored(ImVec4(0.8f, 0.8f, 0.0f, 1.0f), "Keyring"); + for (int i = 0; i < visibleSlots; ++i) { + if (i % keyCols != 0) ImGui::SameLine(); + const auto& slot = inventory.getKeyringSlot(i); + char id[32]; + snprintf(id, sizeof(id), "##skr_%d", i); + ImGui::PushID(id); + renderItemSlot(inventory, slot, keySlotSize, nullptr, + SlotKind::BACKPACK, -1, game::EquipSlot::NUM_SLOTS); + ImGui::PopID(); + } } } @@ -2042,27 +2051,28 @@ void InventoryScreen::renderBackpackPanel(game::Inventory& inventory, bool colla } } - bool keyringHasAnyItems = false; - for (int i = 0; i < inventory.getKeyringSize(); ++i) { - if (!inventory.getKeyringSlot(i).empty()) { - keyringHasAnyItems = true; - break; + if (showKeyring_) { + constexpr float keySlotSize = 24.0f; + constexpr int keyCols = 8; + int lastOccupied = -1; + for (int i = inventory.getKeyringSize() - 1; i >= 0; --i) { + if (!inventory.getKeyringSlot(i).empty()) { lastOccupied = i; break; } } - } - if (!collapseEmptySections || keyringHasAnyItems) { - ImGui::Spacing(); - ImGui::Separator(); - ImGui::TextColored(ImVec4(0.8f, 0.8f, 0.0f, 1.0f), "Keyring"); - for (int i = 0; i < inventory.getKeyringSize(); ++i) { - if (i % columns != 0) ImGui::SameLine(); - const auto& slot = inventory.getKeyringSlot(i); - char sid[32]; - snprintf(sid, sizeof(sid), "##keyring_%d", i); - ImGui::PushID(sid); - // Keyring is display-only for now. - renderItemSlot(inventory, slot, slotSize, nullptr, - SlotKind::BACKPACK, -1, game::EquipSlot::NUM_SLOTS); - ImGui::PopID(); + int visibleSlots = (lastOccupied < 0) ? 0 : ((lastOccupied / keyCols) + 1) * keyCols; + if (visibleSlots > 0) { + ImGui::Spacing(); + ImGui::Separator(); + ImGui::TextColored(ImVec4(0.8f, 0.8f, 0.0f, 1.0f), "Keyring"); + for (int i = 0; i < visibleSlots; ++i) { + if (i % keyCols != 0) ImGui::SameLine(); + const auto& slot = inventory.getKeyringSlot(i); + char sid[32]; + snprintf(sid, sizeof(sid), "##keyring_%d", i); + ImGui::PushID(sid); + renderItemSlot(inventory, slot, keySlotSize, nullptr, + SlotKind::BACKPACK, -1, game::EquipSlot::NUM_SLOTS); + ImGui::PopID(); + } } } }