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.
This commit is contained in:
Kelsi 2026-02-23 08:09:27 -08:00
parent 5cfb0817ed
commit b70f08d14f
4 changed files with 26 additions and 4 deletions

View file

@ -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

View file

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

View file

@ -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) {

View file

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