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);