From b775dd5c541e77ecbc13640060a74a3f206434c6 Mon Sep 17 00:00:00 2001 From: Petr Ohlidal Date: Sat, 9 Mar 2024 21:25:08 +0100 Subject: [PATCH 1/3] TopMenubarUI: FOV code cleanup :wrench: --- source/main/gfx/camera/CameraManager.cpp | 17 ++++++ source/main/gfx/camera/CameraManager.h | 2 + source/main/gui/panels/GUI_TopMenubar.cpp | 74 +++++++++++++---------- source/main/gui/panels/GUI_TopMenubar.h | 1 + 4 files changed, 62 insertions(+), 32 deletions(-) diff --git a/source/main/gfx/camera/CameraManager.cpp b/source/main/gfx/camera/CameraManager.cpp index ff67bd7b3a..0b02ab94f5 100644 --- a/source/main/gfx/camera/CameraManager.cpp +++ b/source/main/gfx/camera/CameraManager.cpp @@ -1365,3 +1365,20 @@ void CameraManager::CameraBehaviorVehicleSplineUpdateSplineDisplay() } m_splinecam_mo->end(); } + +std::string ToLocalizedString(CameraManager::CameraBehaviors behavior) +{ + switch (behavior) + { + case CameraManager::CAMERA_BEHAVIOR_CHARACTER: return _LC("CameraBehavior", "Character"); + case CameraManager::CAMERA_BEHAVIOR_STATIC: return _LC("CameraBehavior", "Static"); + case CameraManager::CAMERA_BEHAVIOR_VEHICLE: return _LC("CameraBehavior", "Vehicle"); + case CameraManager::CAMERA_BEHAVIOR_VEHICLE_SPLINE: return _LC("CameraBehavior", "Vehicle Spline"); + case CameraManager::CAMERA_BEHAVIOR_VEHICLE_CINECAM: return _LC("CameraBehavior", "Vehicle CineCam"); + case CameraManager::CAMERA_BEHAVIOR_FREE: return _LC("CameraBehavior", "Free"); + case CameraManager::CAMERA_BEHAVIOR_FIXED: return _LC("CameraBehavior", "Fixed"); + case CameraManager::CAMERA_BEHAVIOR_ISOMETRIC: return _LC("CameraBehavior", "Isometric"); + case CameraManager::CAMERA_BEHAVIOR_INVALID: return _LC("CameraBehavior", "Invalid"); + default: return ""; + } +} diff --git a/source/main/gfx/camera/CameraManager.h b/source/main/gfx/camera/CameraManager.h index 2c4083f7fc..327635f2a3 100644 --- a/source/main/gfx/camera/CameraManager.h +++ b/source/main/gfx/camera/CameraManager.h @@ -152,4 +152,6 @@ class CameraManager /// @} // addtogroup Camera /// @} // addtogroup Gfx +std::string ToLocalizedString(CameraManager::CameraBehaviors behavior); + } // namespace RoR diff --git a/source/main/gui/panels/GUI_TopMenubar.cpp b/source/main/gui/panels/GUI_TopMenubar.cpp index beb4684ca6..afff043f28 100644 --- a/source/main/gui/panels/GUI_TopMenubar.cpp +++ b/source/main/gui/panels/GUI_TopMenubar.cpp @@ -560,38 +560,10 @@ void TopMenubar::Draw(float dt) { App::GetGameContext()->GetActorManager()->SetSimulationSpeed(timelapse); } - if (App::GetCameraManager()->GetCurrentBehavior() == CameraManager::CAMERA_BEHAVIOR_STATIC) - { - ImGui::Separator(); - ImGui::TextColored(GRAY_HINT_TEXT, "%s", _LC("TopMenubar", "Camera:")); - DrawGFloatSlider(App::gfx_static_cam_fov_exp, _LC("TopMenubar", "FOV"), 0.8f, 1.5f); - DrawGIntSlider(App::gfx_camera_height, _LC("TopMenubar", "Height"), 1, 50); - } - else - { - ImGui::Separator(); - ImGui::TextColored(GRAY_HINT_TEXT, "%s", _LC("TopMenubar", "Camera:")); - if (App::GetCameraManager()->GetCurrentBehavior() == CameraManager::CAMERA_BEHAVIOR_VEHICLE_CINECAM) - { - int fov = App::gfx_fov_internal->getInt(); - if (ImGui::SliderInt(_LC("TopMenubar", "FOV"), &fov, 10, 120)) - { - App::gfx_fov_internal->setVal(fov); - } - } - else - { - int fov = App::gfx_fov_external->getInt(); - if (ImGui::SliderInt(_LC("TopMenubar", "FOV"), &fov, 10, 120)) - { - App::gfx_fov_external->setVal(fov); - } - } - if (App::GetCameraManager()->GetCurrentBehavior() == CameraManager::CAMERA_BEHAVIOR_FIXED) - { - DrawGCheckbox(App::gfx_fixed_cam_tracking, _LC("TopMenubar", "Tracking")); - } - } + + ImGui::Separator(); + ImGui::TextColored(GRAY_HINT_TEXT, "%s", _LC("TopMenubar", "Camera:")); + this->DrawCameraControlsBox(); #ifdef USE_CAELUM if (App::gfx_sky_mode->getEnum() == GfxSkyMode::CAELUM) { @@ -2419,3 +2391,41 @@ void TopMenubar::DrawTuningForceRemoveControls(const int subject_id, const std:: } } + +void TopMenubar::DrawCameraControlsBox() +{ + // We have multiple presets: + // * `gfx_static_cam_fov_exp` (float) ~ A "zoom factor" of static camera; Adjust by 'Ctrl+mouse wheel' or TopMenubar/Settings. + // * `gfx_fov_internal` (int) ~ FOV of cinecam; Adjust by hotkeys EV_COMMON_FOV_{LESS/MORE/RESET}. + // * `gfx_fov_external` (int) ~ FOV of exterior cameras (3rd person, free cam, freefixed cam), adjustable by hotkeys EV_COMMON_FOV_{LESS/MORE/RESET}. + // ------------------------------------------------------------------------------------------------- + + switch (App::GetCameraManager()->GetCurrentBehavior()) + { + case CameraManager::CAMERA_BEHAVIOR_STATIC: + { + DrawGFloatSlider(App::gfx_static_cam_fov_exp, _LC("TopMenubar", "FOV"), 0.8f, 1.5f); + DrawGIntSlider(App::gfx_camera_height, _LC("TopMenubar", "Height"), 1, 50); + break; + } + + case CameraManager::CAMERA_BEHAVIOR_FIXED: + { + DrawGIntSlider(App::gfx_fov_external, _LC("TopMenubar", "FOV"), 10, 120); + DrawGCheckbox(App::gfx_fixed_cam_tracking, _LC("TopMenubar", "Tracking")); + break; + } + + case CameraManager::CAMERA_BEHAVIOR_VEHICLE_CINECAM: + { + DrawGIntSlider(App::gfx_fov_internal, _LC("TopMenubar", "FOV"), 10, 120); + break; + } + + default: + { + DrawGIntSlider(App::gfx_fov_external, _LC("TopMenubar", "FOV"), 10, 120); + break; + } + } +} diff --git a/source/main/gui/panels/GUI_TopMenubar.h b/source/main/gui/panels/GUI_TopMenubar.h index 18efbde88e..7adac6cf93 100644 --- a/source/main/gui/panels/GUI_TopMenubar.h +++ b/source/main/gui/panels/GUI_TopMenubar.h @@ -119,6 +119,7 @@ class TopMenubar void DrawActorListSinglePlayer(); void DrawMpUserToActorList(RoRnet::UserInfo &user); // Multiplayer void DrawSpecialStateBox(float top_offset); + void DrawCameraControlsBox(); // Tuning menu helpers void DrawTuningBoxedSubjectIdInline(int subject_id); From 941dd6efb74ee419ce05c14e5f4c643f905b53d6 Mon Sep 17 00:00:00 2001 From: Petr Ohlidal Date: Sun, 10 Mar 2024 22:24:22 +0100 Subject: [PATCH 2/3] :video_game: Added camera mode combobox to TopMenubar UI. --- source/main/gfx/camera/CameraManager.cpp | 30 +++++++- source/main/gfx/camera/CameraManager.h | 3 +- source/main/gui/panels/GUI_TopMenubar.cpp | 74 +++++++++++++++++-- source/main/gui/panels/GUI_TopMenubar.h | 6 +- source/main/gui/panels/GUI_VehicleButtons.cpp | 2 +- 5 files changed, 104 insertions(+), 11 deletions(-) diff --git a/source/main/gfx/camera/CameraManager.cpp b/source/main/gfx/camera/CameraManager.cpp index 0b02ab94f5..e7be9d4f3b 100644 --- a/source/main/gfx/camera/CameraManager.cpp +++ b/source/main/gfx/camera/CameraManager.cpp @@ -145,7 +145,7 @@ void CameraManager::ReCreateCameraNode() this->CreateCameraNode(); } -bool CameraManager::EvaluateSwitchBehavior() +bool CameraManager::evaluateSwitchBehavior() { switch(m_current_behavior) { @@ -255,7 +255,7 @@ void CameraManager::UpdateInputEvents(float dt) // Called every frame if ( m_current_behavior < CAMERA_BEHAVIOR_END && App::GetInputEngine()->getEventBoolValueBounce(EV_CAMERA_CHANGE) ) { - if ( (m_current_behavior == CAMERA_BEHAVIOR_INVALID) || this->EvaluateSwitchBehavior() ) + if ( (m_current_behavior == CAMERA_BEHAVIOR_INVALID) || this->evaluateSwitchBehavior() ) { this->switchToNextBehavior(); } @@ -1366,7 +1366,31 @@ void CameraManager::CameraBehaviorVehicleSplineUpdateSplineDisplay() m_splinecam_mo->end(); } -std::string ToLocalizedString(CameraManager::CameraBehaviors behavior) +void CameraManager::switchDirectlyToBehavior(CameraBehaviors new_behavior, int index) +{ + // Not all behaviors are the same; some are 'toggled' and some 'cycled'. + // * Cycled (see `EV_COMMON_CAMERA_BEHAVIOR_CYCLE`): Character, Static, Vehicle, Vehicle Spline ~ can be changed freely via `switchBehavior()` + // * Toggled (see `EV_COMMON_CAMERA_BEHAVIOR_TOGGLE`): Free, Fixed ~ must be changed via `ToggleCameraBehavior()` to keep history for hotkeys. + // -------------------------------------------------------------------------------------------------- + + switch (new_behavior) + { + case CameraManager::CAMERA_BEHAVIOR_FREE: + case CameraManager::CAMERA_BEHAVIOR_FIXED: + this->ToggleCameraBehavior(new_behavior); + break; + + case CameraManager::CAMERA_BEHAVIOR_VEHICLE_CINECAM: + this->switchBehavior(new_behavior); + break; + + default: + this->switchBehavior(new_behavior); + break; + } +} + +std::string RoR::ToLocalizedString(CameraManager::CameraBehaviors behavior) { switch (behavior) { diff --git a/source/main/gfx/camera/CameraManager.h b/source/main/gfx/camera/CameraManager.h index 327635f2a3..4b34745eec 100644 --- a/source/main/gfx/camera/CameraManager.h +++ b/source/main/gfx/camera/CameraManager.h @@ -77,7 +77,8 @@ class CameraManager void ReCreateCameraNode(); //!< Needed since we call `Ogre::SceneManager::ClearScene()` after end of sim. session void switchToNextBehavior(); - bool EvaluateSwitchBehavior(); + bool evaluateSwitchBehavior(); + void switchDirectlyToBehavior(CameraBehaviors new_behavior, int index = -1); protected: diff --git a/source/main/gui/panels/GUI_TopMenubar.cpp b/source/main/gui/panels/GUI_TopMenubar.cpp index afff043f28..7a6f8d75ee 100644 --- a/source/main/gui/panels/GUI_TopMenubar.cpp +++ b/source/main/gui/panels/GUI_TopMenubar.cpp @@ -537,7 +537,7 @@ void TopMenubar::Draw(float dt) ImGui::SetNextWindowPos(menu_pos); if (ImGui::Begin(_LC("TopMenubar", "Settings menu"), nullptr, static_cast(flags))) { - ImGui::PushItemWidth(125.f); // Width includes [+/-] buttons + ImGui::PushItemWidth(SETTINGS_ITEMWIDTH); // Width includes [+/-] buttons ImGui::TextColored(GRAY_HINT_TEXT, "%s", _LC("TopMenubar", "Audio:")); DrawGFloatSlider(App::audio_master_volume, _LC("TopMenubar", "Volume"), 0, 1); ImGui::Separator(); @@ -563,7 +563,8 @@ void TopMenubar::Draw(float dt) ImGui::Separator(); ImGui::TextColored(GRAY_HINT_TEXT, "%s", _LC("TopMenubar", "Camera:")); - this->DrawCameraControlsBox(); + this->DrawCameraBehaviorSelectionBox(); + this->DrawCameraContextSensitiveBox(); #ifdef USE_CAELUM if (App::gfx_sky_mode->getEnum() == GfxSkyMode::CAELUM) { @@ -2392,10 +2393,73 @@ void TopMenubar::DrawTuningForceRemoveControls(const int subject_id, const std:: } -void TopMenubar::DrawCameraControlsBox() +// Internal helper for `DrawCameraBehaviorSelectionBox()` +std::string CamBehaviorComboLabel(CameraManager::CameraBehaviors behavior, int index) +{ + std::string caption = ToLocalizedString(behavior); + if (index != -1) + { + caption = fmt::format("{} #{}", caption, index+1); + } + return caption; +} + +// Internal helper for `DrawCameraBehaviorSelectionBox()` +bool CamBehaviorComboItem(CameraManager::CameraBehaviors active_behavior, int active_index, CameraManager::CameraBehaviors selectable_behavior, int index = -1) +{ + const bool is_selected = (selectable_behavior == active_behavior) && (index == active_index); + if (ImGui::Selectable(CamBehaviorComboLabel(selectable_behavior, index).c_str(), is_selected)) + { + App::GetCameraManager()->switchDirectlyToBehavior(selectable_behavior); + return true; + } + return false; +} + +void TopMenubar::DrawCameraBehaviorSelectionBox() +{ + // Note we have 'cycled' vs 'toggled' camera behaviors - see comments in `CameraManager::switchDirectlyToBehavior()` + // Note the cycle-hotkey also traverses sub-elements (i.e. cinecams), see `CameraManager::evaluateSwitchBehavior()` + // ------------------------------------------------------------------------------------------------- + + CameraManager::CameraBehaviors behavior = App::GetCameraManager()->GetCurrentBehavior(); + if (App::GetGameContext()->GetPlayerActor()) + { + int index = (behavior == CameraManager::CAMERA_BEHAVIOR_VEHICLE_CINECAM) ? App::GetGameContext()->GetPlayerActor()->ar_current_cinecam : -1; + if (ImGui::BeginCombo(_LC("TopMenubar", "Behavior"), CamBehaviorComboLabel(behavior, index).c_str())) + { + CamBehaviorComboItem(behavior, index, CameraManager::CAMERA_BEHAVIOR_STATIC); + CamBehaviorComboItem(behavior, index, CameraManager::CAMERA_BEHAVIOR_VEHICLE); + for (int i = 0; i < App::GetGameContext()->GetPlayerActor()->ar_num_cinecams; i++) + { + if (CamBehaviorComboItem(behavior, index, CameraManager::CAMERA_BEHAVIOR_VEHICLE_CINECAM, i)) + { + App::GetGameContext()->GetPlayerActor()->ar_current_cinecam = i; + App::GetGameContext()->GetPlayerActor()->NotifyActorCameraChanged(); + } + } + CamBehaviorComboItem(behavior, index, CameraManager::CAMERA_BEHAVIOR_FREE); + CamBehaviorComboItem(behavior, index, CameraManager::CAMERA_BEHAVIOR_FIXED); + ImGui::EndCombo(); + } + } + else + { + if (ImGui::BeginCombo(_LC("TopMenubar", "Behavior"), ToLocalizedString(behavior).c_str())) + { + CamBehaviorComboItem(behavior, -1, CameraManager::CAMERA_BEHAVIOR_CHARACTER); + CamBehaviorComboItem(behavior, -1, CameraManager::CAMERA_BEHAVIOR_STATIC); + CamBehaviorComboItem(behavior, -1, CameraManager::CAMERA_BEHAVIOR_FREE); + CamBehaviorComboItem(behavior, -1, CameraManager::CAMERA_BEHAVIOR_FIXED); + ImGui::EndCombo(); + } + } +} + +void TopMenubar::DrawCameraContextSensitiveBox() { // We have multiple presets: - // * `gfx_static_cam_fov_exp` (float) ~ A "zoom factor" of static camera; Adjust by 'Ctrl+mouse wheel' or TopMenubar/Settings. + // * `gfx_static_cam_fov_exp` (float) ~ A "zoom factor" of static camera (the actual FOV is dynamic based on distance); Adjust by 'Ctrl+mouse wheel' or TopMenubar/Settings. // * `gfx_fov_internal` (int) ~ FOV of cinecam; Adjust by hotkeys EV_COMMON_FOV_{LESS/MORE/RESET}. // * `gfx_fov_external` (int) ~ FOV of exterior cameras (3rd person, free cam, freefixed cam), adjustable by hotkeys EV_COMMON_FOV_{LESS/MORE/RESET}. // ------------------------------------------------------------------------------------------------- @@ -2404,7 +2468,7 @@ void TopMenubar::DrawCameraControlsBox() { case CameraManager::CAMERA_BEHAVIOR_STATIC: { - DrawGFloatSlider(App::gfx_static_cam_fov_exp, _LC("TopMenubar", "FOV"), 0.8f, 1.5f); + DrawGFloatSlider(App::gfx_static_cam_fov_exp, _LC("TopMenubar", "FOV (exponent)"), 0.8f, 1.5f); DrawGIntSlider(App::gfx_camera_height, _LC("TopMenubar", "Height"), 1, 50); break; } diff --git a/source/main/gui/panels/GUI_TopMenubar.h b/source/main/gui/panels/GUI_TopMenubar.h index 7adac6cf93..d83fe9e034 100644 --- a/source/main/gui/panels/GUI_TopMenubar.h +++ b/source/main/gui/panels/GUI_TopMenubar.h @@ -53,6 +53,7 @@ class TopMenubar const ImVec4 ORANGE_TEXT = ImVec4(0.9f, 0.6f, 0.0f, 1.f); const ImVec4 RED_TEXT = ImVec4(1.00f, 0.00f, 0.00f, 1.f); const ImVec2 MENU_HOVERBOX_PADDING = ImVec2(25.f, 10.f); + const float SETTINGS_ITEMWIDTH = 150.f; enum class TopMenu { TOPMENU_NONE, TOPMENU_SIM, TOPMENU_ACTORS, TOPMENU_SAVEGAMES, TOPMENU_SETTINGS, TOPMENU_TOOLS, TOPMENU_AI, TOPMENU_TUNING }; enum class StateBox { STATEBOX_NONE, STATEBOX_REPLAY, STATEBOX_RACE, STATEBOX_LIVE_REPAIR, STATEBOX_QUICK_REPAIR }; @@ -119,7 +120,10 @@ class TopMenubar void DrawActorListSinglePlayer(); void DrawMpUserToActorList(RoRnet::UserInfo &user); // Multiplayer void DrawSpecialStateBox(float top_offset); - void DrawCameraControlsBox(); + + // Settings menu helpers + void DrawCameraBehaviorSelectionBox(); + void DrawCameraContextSensitiveBox(); // Tuning menu helpers void DrawTuningBoxedSubjectIdInline(int subject_id); diff --git a/source/main/gui/panels/GUI_VehicleButtons.cpp b/source/main/gui/panels/GUI_VehicleButtons.cpp index 0d2d9f545e..a65ae1ba7e 100644 --- a/source/main/gui/panels/GUI_VehicleButtons.cpp +++ b/source/main/gui/panels/GUI_VehicleButtons.cpp @@ -1147,7 +1147,7 @@ void VehicleButtons::DrawCameraButton() { if (ImGui::ImageButton(reinterpret_cast(m_camera_icon->getHandle()), ImVec2(24, 24))) { - if (App::GetCameraManager()->EvaluateSwitchBehavior()) + if (App::GetCameraManager()->evaluateSwitchBehavior()) { App::GetCameraManager()->switchToNextBehavior(); } From 8fdf59def6fefc9ecfa0a63551d49d82134fef14 Mon Sep 17 00:00:00 2001 From: Petr Ohlidal Date: Mon, 11 Mar 2024 04:24:10 +0100 Subject: [PATCH 3/3] :video_game: Added cvar `gfx_camera_speed` + top menu UI slider Changes: * cvar `gfx_camera_speed` replaces `CameraManager::m_cam_ratio` which was used/updated chaotically and didn't always account frame time. Default value is 4.0 like before. * New `smoothXXX()` helpers to CameraManager, replacing copypasted smoothing code. * Clarified staticcam fov exponent smoothing: Removed `Cameramanager::m_staticcam_fov_exponent` which just duplicated `gfx_static_cam_fov_exp`. Added `Cameramanager::m_staticcam_fov_exp_current` which replaces `static fovExp` (CameraManager.cpp, line 789). Comments clearly indicate what is what. --- source/main/Application.cpp | 1 + source/main/Application.h | 1 + source/main/gfx/camera/CameraManager.cpp | 64 +++++++++++------------ source/main/gfx/camera/CameraManager.h | 8 +-- source/main/gui/panels/GUI_TopMenubar.cpp | 2 + source/main/system/CVar.cpp | 1 + 6 files changed, 42 insertions(+), 35 deletions(-) diff --git a/source/main/Application.cpp b/source/main/Application.cpp index 23ddfd63d9..2c6207bcb1 100644 --- a/source/main/Application.cpp +++ b/source/main/Application.cpp @@ -234,6 +234,7 @@ CVar* gfx_shadow_quality; CVar* gfx_skidmarks_mode; CVar* gfx_sight_range; CVar* gfx_camera_height; +CVar* gfx_camera_speed; CVar* gfx_fov_external; CVar* gfx_fov_external_default; CVar* gfx_fov_internal; diff --git a/source/main/Application.h b/source/main/Application.h index 1df323f50e..01a58c1ba5 100644 --- a/source/main/Application.h +++ b/source/main/Application.h @@ -446,6 +446,7 @@ extern CVar* gfx_shadow_quality; extern CVar* gfx_skidmarks_mode; extern CVar* gfx_sight_range; extern CVar* gfx_camera_height; +extern CVar* gfx_camera_speed; extern CVar* gfx_fov_external; extern CVar* gfx_fov_external_default; extern CVar* gfx_fov_internal; diff --git a/source/main/gfx/camera/CameraManager.cpp b/source/main/gfx/camera/CameraManager.cpp index e7be9d4f3b..964f17e7d4 100644 --- a/source/main/gfx/camera/CameraManager.cpp +++ b/source/main/gfx/camera/CameraManager.cpp @@ -96,7 +96,6 @@ CameraManager::CameraManager() : , m_splinecam_mo(0) , m_splinecam_spline_pos(0.5f) , m_staticcam_force_update(false) - , m_staticcam_fov_exponent(1.0f) , m_cam_rot_x(0.0f) , m_cam_rot_y(0.3f) , m_cam_dist(5.f) @@ -104,7 +103,6 @@ CameraManager::CameraManager() : , m_cam_dist_max(0.f) , m_cam_target_direction(0.f) , m_cam_target_pitch(0.f) - , m_cam_ratio (11.f) , m_cam_look_at(Ogre::Vector3::ZERO) , m_cam_look_at_last(Ogre::Vector3::ZERO) , m_cam_look_at_smooth(Ogre::Vector3::ZERO) @@ -199,7 +197,6 @@ void CameraManager::UpdateCurrentBehavior() } case CAMERA_BEHAVIOR_STATIC: - m_staticcam_fov_exponent = App::gfx_static_cam_fov_exp->getFloat(); this->UpdateCameraBehaviorStatic(); return; @@ -335,13 +332,11 @@ void CameraManager::ResetCurrentBehavior() { m_cam_rot_y = 0.1f; m_cam_dist = 0.1f; - m_cam_ratio = 0.0f; } else { m_cam_rot_y = 0.3f; m_cam_dist = 5.0f; - m_cam_ratio = 11.0f; } m_cam_dist_min = 0; m_cam_target_pitch = 0.0f; @@ -349,7 +344,7 @@ void CameraManager::ResetCurrentBehavior() } case CAMERA_BEHAVIOR_STATIC: - m_staticcam_fov_exponent = 1.0f; + m_staticcam_fov_exp_current = 1.0f; App::gfx_static_cam_fov_exp->setVal(1.0f); return; @@ -564,7 +559,24 @@ bool CameraManager::mouseMoved(const OIS::MouseEvent& _arg) return CameraManager::CameraBehaviorOrbitMouseMoved(_arg); } - case CAMERA_BEHAVIOR_STATIC: return CameraBehaviorStaticMouseMoved(_arg); + case CAMERA_BEHAVIOR_STATIC: + { + const OIS::MouseState ms = _arg.state; + + if (ms.buttonDown(OIS::MB_Right)) + { + // Note: `gfx_static_cam_fov_exp` is the desired (target) value; current (smooth) value is `m_staticcam_fov_exp_current` + + float scale = RoR::App::GetInputEngine()->isKeyDown(OIS::KC_LMENU) ? 0.00002f : 0.0002f; + float exp = App::gfx_static_cam_fov_exp->getFloat(); + exp += ms.Z.rel * scale; + exp = Math::Clamp(exp, 0.8f, 1.50f); + App::gfx_static_cam_fov_exp->setVal(exp); + return true; + } + + return false; + } case CAMERA_BEHAVIOR_VEHICLE: return CameraBehaviorOrbitMouseMoved(_arg); case CAMERA_BEHAVIOR_VEHICLE_SPLINE: return this->CameraBehaviorVehicleSplineMouseMoved(_arg); case CAMERA_BEHAVIOR_VEHICLE_CINECAM: return CameraBehaviorOrbitMouseMoved(_arg); @@ -786,9 +798,7 @@ void CameraManager::UpdateCameraBehaviorStatic() } } - static float fovExp = m_staticcam_fov_exponent; - fovExp = (1.0f / (m_cam_ratio + 1.0f)) * m_staticcam_fov_exponent + (m_cam_ratio / (m_cam_ratio + 1.0f)) * fovExp; - + float fovExp = this->smoothFloat(m_staticcam_fov_exp_current, App::gfx_static_cam_fov_exp->getFloat(), m_cct_dt, App::gfx_camera_speed->getFloat()); float camDist = m_staticcam_position.distance(m_staticcam_look_at); float fov = atan2(20.0f, std::pow(camDist, fovExp)); @@ -797,22 +807,6 @@ void CameraManager::UpdateCameraBehaviorStatic() App::GetCameraManager()->GetCamera()->setFOVy(Radian(fov)); } -bool CameraManager::CameraBehaviorStaticMouseMoved(const OIS::MouseEvent& _arg) -{ - const OIS::MouseState ms = _arg.state; - - if (ms.buttonDown(OIS::MB_Right)) - { - float scale = RoR::App::GetInputEngine()->isKeyDown(OIS::KC_LMENU) ? 0.00002f : 0.0002f; - m_staticcam_fov_exponent += ms.Z.rel * scale; - m_staticcam_fov_exponent = Math::Clamp(m_staticcam_fov_exponent, 0.8f, 1.50f); - App::gfx_static_cam_fov_exp->setVal(m_staticcam_fov_exponent); - return true; - } - - return false; -} - void CameraManager::CameraBehaviorOrbitUpdate() { if (RoR::App::GetInputEngine()->getEventBoolValueBounce(EV_CAMERA_LOOKBACK)) @@ -916,7 +910,7 @@ void CameraManager::CameraBehaviorOrbitUpdate() Vector3 precedingLookAt = m_cam_look_at_smooth_last + camDisplacement; Vector3 precedingPosition = this->GetCameraNode()->getPosition() + camDisplacement; - Vector3 camPosition = (1.0f / (m_cam_ratio + 1.0f)) * desiredPosition + (m_cam_ratio / (m_cam_ratio + 1.0f)) * precedingPosition; + Vector3 camPosition = this->smoothVector3(precedingPosition, desiredPosition, m_cct_dt, App::gfx_camera_speed->getFloat()); if (App::GetGameContext()->GetTerrain()->GetCollisions() && App::GetGameContext()->GetTerrain()->GetCollisions()->forcecam) { @@ -931,7 +925,7 @@ void CameraManager::CameraBehaviorOrbitUpdate() this->GetCameraNode()->setPosition(camPosition); } - m_cam_look_at_smooth = (1.0f / (m_cam_ratio + 1.0f)) * m_cam_look_at + (m_cam_ratio / (m_cam_ratio + 1.0f)) * precedingLookAt; + m_cam_look_at_smooth = this->smoothVector3(precedingLookAt, m_cam_look_at, m_cct_dt, App::gfx_camera_speed->getFloat()); m_cam_look_at_last = m_cam_look_at; m_cam_look_at_smooth_last = m_cam_look_at_smooth; @@ -1068,8 +1062,6 @@ void CameraManager::UpdateCameraBehaviorVehicle() m_cam_target_pitch = -asin(dir.dotProduct(Vector3::UNIT_Y)); } - m_cam_ratio = 1.0f / (m_cct_dt * 4.0f); - m_cam_dist_min = std::min(m_cct_player_actor->getMinimalCameraRadius() * 2.0f, 33.0f); m_cam_look_at = m_cct_player_actor->getPosition(); @@ -1185,8 +1177,6 @@ bool CameraManager::CameraBehaviorVehicleSplineMouseMoved( const OIS::MouseEven { const OIS::MouseState ms = _arg.state; - m_cam_ratio = 1.0f / (m_cct_dt * 4.0f); - if (RoR::App::GetInputEngine()->isKeyDown(OIS::KC_LCONTROL) && ms.buttonDown(OIS::MB_Right)) { Real splinePosDiff = ms.X.rel * std::max(0.00005f, m_splinecam_spline_len * 0.0000001f); @@ -1390,6 +1380,16 @@ void CameraManager::switchDirectlyToBehavior(CameraBehaviors new_behavior, int i } } +float CameraManager::smoothFloat(float current, float target, float dt, float speed) const +{ + return current + (target - current) * speed * dt; +} + +Ogre::Vector3 CameraManager::smoothVector3(const Ogre::Vector3& current, const Ogre::Vector3& target, float dt, float speed) const +{ + return current + (target - current) * speed * dt; +} + std::string RoR::ToLocalizedString(CameraManager::CameraBehaviors behavior) { switch (behavior) diff --git a/source/main/gfx/camera/CameraManager.h b/source/main/gfx/camera/CameraManager.h index 4b34745eec..7d15c9d732 100644 --- a/source/main/gfx/camera/CameraManager.h +++ b/source/main/gfx/camera/CameraManager.h @@ -90,7 +90,6 @@ class CameraManager void ResetCurrentBehavior(); void DeactivateCurrentBehavior(); void UpdateCameraBehaviorStatic(); - bool CameraBehaviorStaticMouseMoved(const OIS::MouseEvent& _arg); void UpdateCameraBehaviorFree(); void UpdateCameraBehaviorFixed(); void UpdateCameraBehaviorVehicle(); @@ -104,6 +103,10 @@ class CameraManager void CameraBehaviorVehicleSplineUpdateSplineDisplay(); void CreateCameraNode(); + // Helper functions + float smoothFloat(float current, float target, float dt, float speed) const; + Ogre::Vector3 smoothVector3(const Ogre::Vector3& current, const Ogre::Vector3& target, float dt, float speed) const; + Ogre::Camera* m_camera; Ogre::SceneNode* m_camera_node; @@ -124,7 +127,6 @@ class CameraManager float m_cam_dist; float m_cam_dist_min; float m_cam_dist_max; - float m_cam_ratio; Ogre::Vector3 m_cam_look_at; bool m_cam_limit_movement; Ogre::Vector3 m_cam_look_at_last; @@ -132,7 +134,7 @@ class CameraManager Ogre::Vector3 m_cam_look_at_smooth_last; // Static cam attributes bool m_staticcam_force_update; - float m_staticcam_fov_exponent; + float m_staticcam_fov_exp_current = 1.f; //!< Smoothed value; target is cvar `gfx_static_cam_fox_exp` Ogre::Radian m_staticcam_previous_fov; Ogre::Vector3 m_staticcam_look_at; Ogre::Vector3 m_staticcam_position; diff --git a/source/main/gui/panels/GUI_TopMenubar.cpp b/source/main/gui/panels/GUI_TopMenubar.cpp index 7a6f8d75ee..65d5d385a4 100644 --- a/source/main/gui/panels/GUI_TopMenubar.cpp +++ b/source/main/gui/panels/GUI_TopMenubar.cpp @@ -2464,6 +2464,8 @@ void TopMenubar::DrawCameraContextSensitiveBox() // * `gfx_fov_external` (int) ~ FOV of exterior cameras (3rd person, free cam, freefixed cam), adjustable by hotkeys EV_COMMON_FOV_{LESS/MORE/RESET}. // ------------------------------------------------------------------------------------------------- + DrawGFloatSlider(App::gfx_camera_speed, _LC("TopMenubar", "Speed"), 1.0f, 10.0f); + switch (App::GetCameraManager()->GetCurrentBehavior()) { case CameraManager::CAMERA_BEHAVIOR_STATIC: diff --git a/source/main/system/CVar.cpp b/source/main/system/CVar.cpp index 476a9810d7..3813da8373 100644 --- a/source/main/system/CVar.cpp +++ b/source/main/system/CVar.cpp @@ -176,6 +176,7 @@ void Console::cVarSetupBuiltins() App::gfx_skidmarks_mode = this->cVarCreate("gfx_skidmarks_mode", "Skidmarks", CVAR_ARCHIVE | CVAR_TYPE_INT, "0"); App::gfx_sight_range = this->cVarCreate("gfx_sight_range", "SightRange", CVAR_ARCHIVE | CVAR_TYPE_INT, "5000"); App::gfx_camera_height = this->cVarCreate("gfx_camera_height", "Static camera height", CVAR_ARCHIVE | CVAR_TYPE_INT, "5"); + App::gfx_camera_speed = this->cVarCreate("gfx_camera_speed", "Camera smoothing speed", CVAR_ARCHIVE | CVAR_TYPE_FLOAT, "4.0"); App::gfx_fov_external = this->cVarCreate("gfx_fov_external", "", CVAR_TYPE_INT, "60"); App::gfx_fov_external_default= this->cVarCreate("gfx_fov_external_default","FOV External", CVAR_ARCHIVE | CVAR_TYPE_INT, "60"); App::gfx_fov_internal = this->cVarCreate("gfx_fov_internal", "", CVAR_TYPE_INT, "75");