From b70f08d14fdb90f683ea75ba21536d78bd26d043 Mon Sep 17 00:00:00 2001 From: Kelsi Date: Mon, 23 Feb 2026 08:09:27 -0800 Subject: [PATCH] Add proportional zoom and reduced default max zoom with extended toggle Zoom speed now scales with distance for fine control near the character. Default max zoom out reduced from 50 to 33 units. New "Extended Camera Zoom" toggle in Gameplay settings restores the full 50-unit range. --- include/rendering/camera_controller.hpp | 6 +++++- include/ui/game_screen.hpp | 1 + src/rendering/camera_controller.cpp | 8 +++++--- src/ui/game_screen.cpp | 15 +++++++++++++++ 4 files changed, 26 insertions(+), 4 deletions(-) diff --git a/include/rendering/camera_controller.hpp b/include/rendering/camera_controller.hpp index 400383b1..c2ad22ef 100644 --- a/include/rendering/camera_controller.hpp +++ b/include/rendering/camera_controller.hpp @@ -27,6 +27,8 @@ public: float getMouseSensitivity() const { return mouseSensitivity; } void setInvertMouse(bool invert) { invertMouse = invert; } bool isInvertMouse() const { return invertMouse; } + void setExtendedZoom(bool extended) { extendedZoom_ = extended; } + bool isExtendedZoom() const { return extendedZoom_; } void setEnabled(bool enabled) { this->enabled = enabled; } void setTerrainManager(TerrainManager* tm) { terrainManager = tm; } void setWMORenderer(WMORenderer* wmo) { wmoRenderer = wmo; } @@ -137,7 +139,9 @@ private: float collisionDistance = 10.0f; // Max allowed by collision bool externalFollow_ = false; static constexpr float MIN_DISTANCE = 0.5f; // Minimum zoom (first-person threshold) - static constexpr float MAX_DISTANCE = 50.0f; // Maximum zoom out + static constexpr float MAX_DISTANCE_NORMAL = 33.0f; // Default max zoom out + static constexpr float MAX_DISTANCE_EXTENDED = 50.0f; // Extended max zoom out + bool extendedZoom_ = false; static constexpr float ZOOM_SMOOTH_SPEED = 15.0f; // How fast zoom eases static constexpr float CAM_SMOOTH_SPEED = 20.0f; // How fast camera position smooths static constexpr float PIVOT_HEIGHT = 1.8f; // Pivot at head height diff --git a/include/ui/game_screen.hpp b/include/ui/game_screen.hpp index ddcafa3b..bdf159b7 100644 --- a/include/ui/game_screen.hpp +++ b/include/ui/game_screen.hpp @@ -94,6 +94,7 @@ private: int pendingActivityVolume = 100; float pendingMouseSensitivity = 0.2f; bool pendingInvertMouse = false; + bool pendingExtendedZoom = false; int pendingUiOpacity = 65; bool pendingMinimapRotate = false; bool pendingMinimapSquare = false; diff --git a/src/rendering/camera_controller.cpp b/src/rendering/camera_controller.cpp index 050174a6..115c2970 100644 --- a/src/rendering/camera_controller.cpp +++ b/src/rendering/camera_controller.cpp @@ -1678,9 +1678,11 @@ void CameraController::teleportTo(const glm::vec3& pos) { } void CameraController::processMouseWheel(float delta) { - // Adjust user's target distance (collision may limit actual distance) - userTargetDistance -= delta * 2.0f; // 2.0 units per scroll notch - userTargetDistance = glm::clamp(userTargetDistance, MIN_DISTANCE, MAX_DISTANCE); + // Scale zoom speed proportionally to current distance for fine control up close + float zoomSpeed = glm::max(userTargetDistance * 0.15f, 0.3f); + userTargetDistance -= delta * zoomSpeed; + float maxDist = extendedZoom_ ? MAX_DISTANCE_EXTENDED : MAX_DISTANCE_NORMAL; + userTargetDistance = glm::clamp(userTargetDistance, MIN_DISTANCE, maxDist); } void CameraController::setFollowTarget(glm::vec3* target) { diff --git a/src/ui/game_screen.cpp b/src/ui/game_screen.cpp index ab1384ff..bc0489d3 100644 --- a/src/ui/game_screen.cpp +++ b/src/ui/game_screen.cpp @@ -5916,6 +5916,7 @@ void GameScreen::renderSettingsWindow() { if (auto* cameraController = renderer->getCameraController()) { pendingMouseSensitivity = cameraController->getMouseSensitivity(); pendingInvertMouse = cameraController->isInvertMouse(); + cameraController->setExtendedZoom(pendingExtendedZoom); } } pendingResIndex = 0; @@ -6275,6 +6276,16 @@ void GameScreen::renderSettingsWindow() { } saveSettings(); } + if (ImGui::Checkbox("Extended Camera Zoom", &pendingExtendedZoom)) { + if (renderer) { + if (auto* cameraController = renderer->getCameraController()) { + cameraController->setExtendedZoom(pendingExtendedZoom); + } + } + saveSettings(); + } + if (ImGui::IsItemHovered()) + ImGui::SetTooltip("Allow the camera to zoom out further than normal"); ImGui::Spacing(); ImGui::Spacing(); @@ -6354,6 +6365,7 @@ void GameScreen::renderSettingsWindow() { if (ImGui::Button("Restore Gameplay Defaults", ImVec2(-1, 0))) { pendingMouseSensitivity = kDefaultMouseSensitivity; pendingInvertMouse = kDefaultInvertMouse; + pendingExtendedZoom = false; pendingUiOpacity = 65; pendingMinimapRotate = false; pendingMinimapSquare = false; @@ -6368,6 +6380,7 @@ void GameScreen::renderSettingsWindow() { if (auto* cameraController = renderer->getCameraController()) { cameraController->setMouseSensitivity(pendingMouseSensitivity); cameraController->setInvertMouse(pendingInvertMouse); + cameraController->setExtendedZoom(pendingExtendedZoom); } if (auto* minimap = renderer->getMinimap()) { minimap->setRotateWithCamera(minimapRotate_); @@ -7085,6 +7098,7 @@ void GameScreen::saveSettings() { // Controls out << "mouse_sensitivity=" << pendingMouseSensitivity << "\n"; out << "invert_mouse=" << (pendingInvertMouse ? 1 : 0) << "\n"; + out << "extended_zoom=" << (pendingExtendedZoom ? 1 : 0) << "\n"; // Chat out << "chat_active_tab=" << activeChatTab_ << "\n"; @@ -7166,6 +7180,7 @@ void GameScreen::loadSettings() { // Controls else if (key == "mouse_sensitivity") pendingMouseSensitivity = std::clamp(std::stof(val), 0.05f, 1.0f); else if (key == "invert_mouse") pendingInvertMouse = (std::stoi(val) != 0); + else if (key == "extended_zoom") pendingExtendedZoom = (std::stoi(val) != 0); // Chat else if (key == "chat_active_tab") activeChatTab_ = std::clamp(std::stoi(val), 0, 3); else if (key == "chat_timestamps") chatShowTimestamps_ = (std::stoi(val) != 0);