diff --git a/Code/Framework/AzCore/AzCore/std/math.h b/Code/Framework/AzCore/AzCore/std/math.h index 0ad7c93aca..9e9be7944a 100644 --- a/Code/Framework/AzCore/AzCore/std/math.h +++ b/Code/Framework/AzCore/AzCore/std/math.h @@ -1,14 +1,14 @@ /* -* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or -* its licensors. -* -* For complete copyright and license terms please see the LICENSE at the root of this -* distribution (the "License"). All use of this software is governed by the License, -* or, if provided, by the license below or the license accompanying this file. Do not -* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* -*/ + * All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or + * its licensors. + * + * For complete copyright and license terms please see the LICENSE at the root of this + * distribution (the "License"). All use of this software is governed by the License, + * or, if provided, by the license below or the license accompanying this file. Do not + * remove or modify any license notices. This file is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * + */ #pragma once @@ -17,4 +17,15 @@ namespace AZStd { using std::abs; -} + using std::acos; + using std::asin; + using std::atan; + using std::atan2; + using std::cos; + using std::exp2; + using std::fmod; + using std::round; + using std::sin; + using std::sqrt; + using std::tan; +} // namespace AZStd diff --git a/Code/Framework/AzFramework/AzFramework/Viewport/CameraInput.cpp b/Code/Framework/AzFramework/AzFramework/Viewport/CameraInput.cpp index e9dace3433..4c95865938 100644 --- a/Code/Framework/AzFramework/AzFramework/Viewport/CameraInput.cpp +++ b/Code/Framework/AzFramework/AzFramework/Viewport/CameraInput.cpp @@ -29,14 +29,14 @@ namespace AzFramework AZ_CVAR(float, ed_cameraSystemOrbitDollyScrollSpeed, 0.02f, nullptr, AZ::ConsoleFunctorFlags::Null, ""); AZ_CVAR(float, ed_cameraSystemOrbitDollyCursorSpeed, 0.01f, nullptr, AZ::ConsoleFunctorFlags::Null, ""); AZ_CVAR(float, ed_cameraSystemScrollTranslateSpeed, 0.02f, nullptr, AZ::ConsoleFunctorFlags::Null, ""); - AZ_CVAR(float, ed_cameraSystemDefaultOrbitDistance, 60.0f, nullptr, AZ::ConsoleFunctorFlags::Null, ""); - AZ_CVAR(float, ed_cameraSystemMaxOrbitDistance, 100.0f, nullptr, AZ::ConsoleFunctorFlags::Null, ""); + AZ_CVAR(float, ed_cameraSystemMaxOrbitDistance, 60.0f, nullptr, AZ::ConsoleFunctorFlags::Null, ""); AZ_CVAR(float, ed_cameraSystemLookSmoothness, 5.0f, nullptr, AZ::ConsoleFunctorFlags::Null, ""); AZ_CVAR(float, ed_cameraSystemTranslateSmoothness, 5.0f, nullptr, AZ::ConsoleFunctorFlags::Null, ""); AZ_CVAR(float, ed_cameraSystemRotateSpeed, 0.005f, nullptr, AZ::ConsoleFunctorFlags::Null, ""); AZ_CVAR(float, ed_cameraSystemPanSpeed, 0.01f, nullptr, AZ::ConsoleFunctorFlags::Null, ""); AZ_CVAR(bool, ed_cameraSystemPanInvertX, true, nullptr, AZ::ConsoleFunctorFlags::Null, ""); AZ_CVAR(bool, ed_cameraSystemPanInvertY, true, nullptr, AZ::ConsoleFunctorFlags::Null, ""); + AZ_CVAR(float, ed_cameraSystemLookDeadzone, 2.0f, nullptr, AZ::ConsoleFunctorFlags::Null, ""); AZ_CVAR( AZ::CVarFixedString, ed_cameraSystemTranslateForwardKey, "keyboard_key_alphanumeric_W", nullptr, AZ::ConsoleFunctorFlags::Null, ""); @@ -125,22 +125,22 @@ namespace AzFramework { if (orientation.GetElement(2, 0) > -1.0f) { - x = std::atan2(orientation.GetElement(2, 1), orientation.GetElement(2, 2)); - y = std::asin(-orientation.GetElement(2, 0)); - z = std::atan2(orientation.GetElement(1, 0), orientation.GetElement(0, 0)); + x = AZStd::atan2(orientation.GetElement(2, 1), orientation.GetElement(2, 2)); + y = AZStd::asin(-orientation.GetElement(2, 0)); + z = AZStd::atan2(orientation.GetElement(1, 0), orientation.GetElement(0, 0)); } else { x = 0.0f; y = AZ::Constants::Pi * 0.5f; - z = -std::atan2(-orientation.GetElement(2, 1), orientation.GetElement(1, 1)); + z = -AZStd::atan2(-orientation.GetElement(2, 1), orientation.GetElement(1, 1)); } } else { x = 0.0f; y = -AZ::Constants::Pi * 0.5f; - z = std::atan2(-orientation.GetElement(1, 2), orientation.GetElement(1, 1)); + z = AZStd::atan2(-orientation.GetElement(1, 2), orientation.GetElement(1, 1)); } return {x, y, z}; @@ -150,31 +150,35 @@ namespace AzFramework { const auto eulerAngles = AzFramework::EulerAngles(AZ::Matrix3x3::CreateFromTransform(transform)); - camera.m_lookAt = transform.GetTranslation(); camera.m_pitch = eulerAngles.GetX(); camera.m_yaw = eulerAngles.GetZ(); + // note: m_lookDist is negative so we must invert it here + camera.m_lookAt = transform.GetTranslation() + (camera.Rotation().GetBasisY() * -camera.m_lookDist); + } + + static ScreenVector CursorDelta(const AZStd::optional& currentPosition, const AZStd::optional& lastPosition) + { + return currentPosition.has_value() && lastPosition.has_value() ? currentPosition.value() - lastPosition.value() + : ScreenVector(0, 0); } bool CameraSystem::HandleEvents(const InputEvent& event) { - if (const auto& cursor_motion = AZStd::get_if(&event)) + if (const auto& cursor = AZStd::get_if(&event)) { - m_currentCursorPosition = cursor_motion->m_position; + m_currentCursorPosition = cursor->m_position; } else if (const auto& scroll = AZStd::get_if(&event)) { m_scrollDelta = scroll->m_delta; } - return m_cameras.HandleEvents(event); + return m_cameras.HandleEvents(event, CursorDelta(m_currentCursorPosition, m_lastCursorPosition), m_scrollDelta); } Camera CameraSystem::StepCamera(const Camera& targetCamera, const float deltaTime) { - const auto cursorDelta = m_currentCursorPosition.has_value() && m_lastCursorPosition.has_value() - ? m_currentCursorPosition.value() - m_lastCursorPosition.value() - : ScreenVector(0, 0); - + const auto cursorDelta = CursorDelta(m_currentCursorPosition, m_lastCursorPosition); if (m_currentCursorPosition.has_value()) { m_lastCursorPosition = m_currentCursorPosition; @@ -192,18 +196,18 @@ namespace AzFramework m_idleCameraInputs.push_back(AZStd::move(cameraInput)); } - bool Cameras::HandleEvents(const InputEvent& event) + bool Cameras::HandleEvents(const InputEvent& event, const ScreenVector& cursorDelta, float scrollDelta) { bool handling = false; for (auto& cameraInput : m_activeCameraInputs) { - cameraInput->HandleEvents(event); + cameraInput->HandleEvents(event, cursorDelta, scrollDelta); handling = !cameraInput->Idle() || handling; } for (auto& cameraInput : m_idleCameraInputs) { - cameraInput->HandleEvents(event); + cameraInput->HandleEvents(event, cursorDelta, scrollDelta); } return handling; @@ -215,8 +219,8 @@ namespace AzFramework { auto& cameraInput = m_idleCameraInputs[i]; const bool canBegin = cameraInput->Beginning() && - std::all_of(m_activeCameraInputs.cbegin(), m_activeCameraInputs.cend(), - [](const auto& input) { return !input->Exclusive(); }) && + AZStd::all_of(m_activeCameraInputs.cbegin(), m_activeCameraInputs.cend(), + [](const auto& input) { return !input->Exclusive(); }) && (!cameraInput->Exclusive() || (cameraInput->Exclusive() && m_activeCameraInputs.empty())); if (canBegin) @@ -271,7 +275,7 @@ namespace AzFramework } } - void RotateCameraInput::HandleEvents(const InputEvent& event) + void RotateCameraInput::HandleEvents(const InputEvent& event, const ScreenVector& cursorDelta, [[maybe_unused]] float scrollDelta) { if (const auto& input = AZStd::get_if(&event)) { @@ -279,14 +283,27 @@ namespace AzFramework { if (input->m_state == InputChannel::State::Began) { - BeginActivation(); + m_tryingToBegin = true; + m_moveAccumulator = 0.0f; } else if (input->m_state == InputChannel::State::Ended) { + m_tryingToBegin = false; EndActivation(); } } } + + if (m_tryingToBegin) + { + // only allow the action to begin if the mouse has been moved a small amount + m_moveAccumulator += ScreenVectorLength(cursorDelta); + if (m_moveAccumulator > ed_cameraSystemLookDeadzone) + { + BeginActivation(); + m_tryingToBegin = false; + } + } } Camera RotateCameraInput::StepCamera( @@ -298,7 +315,7 @@ namespace AzFramework nextCamera.m_pitch -= float(cursorDelta.m_y) * ed_cameraSystemRotateSpeed; nextCamera.m_yaw -= float(cursorDelta.m_x) * ed_cameraSystemRotateSpeed; - const auto clampRotation = [](const float angle) { return std::fmod(angle + AZ::Constants::TwoPi, AZ::Constants::TwoPi); }; + const auto clampRotation = [](const float angle) { return AZStd::fmod(angle + AZ::Constants::TwoPi, AZ::Constants::TwoPi); }; nextCamera.m_yaw = clampRotation(nextCamera.m_yaw); // clamp pitch to be +-90 degrees @@ -307,7 +324,8 @@ namespace AzFramework return nextCamera; } - void PanCameraInput::HandleEvents(const InputEvent& event) + void PanCameraInput::HandleEvents( + const InputEvent& event, [[maybe_unused]] const ScreenVector& cursorDelta, [[maybe_unused]] float scrollDelta) { if (const auto& input = AZStd::get_if(&event)) { @@ -382,7 +400,8 @@ namespace AzFramework return TranslationType::Nil; } - void TranslateCameraInput::HandleEvents(const InputEvent& event) + void TranslateCameraInput::HandleEvents( + const InputEvent& event, [[maybe_unused]] const ScreenVector& cursorDelta, [[maybe_unused]] float scrollDelta) { if (const auto& input = AZStd::get_if(&event)) { @@ -478,7 +497,7 @@ namespace AzFramework m_boost = false; } - void OrbitCameraInput::HandleEvents(const InputEvent& event) + void OrbitCameraInput::HandleEvents(const InputEvent& event, const ScreenVector& cursorDelta, float scrollDelta) { if (const auto* input = AZStd::get_if(&event)) { @@ -497,7 +516,7 @@ namespace AzFramework if (Active()) { - m_orbitCameras.HandleEvents(event); + m_orbitCameras.HandleEvents(event, cursorDelta, scrollDelta); } } @@ -509,8 +528,10 @@ namespace AzFramework if (Beginning()) { float hit_distance = 0.0f; - if (AZ::Plane::CreateFromNormalAndPoint(AZ::Vector3::CreateAxisZ(), AZ::Vector3::CreateAxisZ(ed_cameraSystemDefaultPlaneHeight)) - .CastRay(targetCamera.Translation(), targetCamera.Rotation().GetBasisY(), hit_distance)) + AZ::Plane::CreateFromNormalAndPoint(AZ::Vector3::CreateAxisZ(), AZ::Vector3::CreateAxisZ(ed_cameraSystemDefaultPlaneHeight)) + .CastRay(targetCamera.Translation(), targetCamera.Rotation().GetBasisY(), hit_distance); + + if (hit_distance > 0.0f) { hit_distance = AZStd::min(hit_distance, ed_cameraSystemMaxOrbitDistance); nextCamera.m_lookDist = -hit_distance; @@ -539,7 +560,8 @@ namespace AzFramework return nextCamera; } - void OrbitDollyScrollCameraInput::HandleEvents(const InputEvent& event) + void OrbitDollyScrollCameraInput::HandleEvents( + const InputEvent& event, [[maybe_unused]] const ScreenVector& cursorDelta, [[maybe_unused]] float scrollDelta) { if (const auto* scroll = AZStd::get_if(&event)) { @@ -557,7 +579,8 @@ namespace AzFramework return nextCamera; } - void OrbitDollyCursorMoveCameraInput::HandleEvents(const InputEvent& event) + void OrbitDollyCursorMoveCameraInput::HandleEvents( + const InputEvent& event, [[maybe_unused]] const ScreenVector& cursorDelta, [[maybe_unused]] float scrollDelta) { if (const auto& input = AZStd::get_if(&event)) { @@ -584,7 +607,8 @@ namespace AzFramework return nextCamera; } - void ScrollTranslationCameraInput::HandleEvents(const InputEvent& event) + void ScrollTranslationCameraInput::HandleEvents( + const InputEvent& event, [[maybe_unused]] const ScreenVector& cursorDelta, [[maybe_unused]] float scrollDelta) { if (const auto* scroll = AZStd::get_if(&event)) { @@ -610,7 +634,7 @@ namespace AzFramework Camera SmoothCamera(const Camera& currentCamera, const Camera& targetCamera, const float deltaTime) { - const auto clamp_rotation = [](const float angle) { return std::fmod(angle + AZ::Constants::TwoPi, AZ::Constants::TwoPi); }; + const auto clamp_rotation = [](const float angle) { return AZStd::fmod(angle + AZ::Constants::TwoPi, AZ::Constants::TwoPi); }; // keep yaw in 0 - 360 range float targetYaw = clamp_rotation(targetCamera.m_yaw); @@ -621,7 +645,7 @@ namespace AzFramework // ensure smooth transition when moving across 0 - 360 boundary const float yawDelta = targetYaw - currentYaw; - if (std::abs(yawDelta) >= AZ::Constants::Pi) + if (AZStd::abs(yawDelta) >= AZ::Constants::Pi) { targetYaw -= AZ::Constants::TwoPi * sign(yawDelta); } @@ -629,12 +653,12 @@ namespace AzFramework Camera camera; // note: the math for the lerp smoothing implementation for camera rotation and translation was inspired by this excellent // article by Scott Lembcke: https://www.gamasutra.com/blogs/ScottLembcke/20180404/316046/Improved_Lerp_Smoothing.php - const float lookRate = std::exp2(ed_cameraSystemLookSmoothness); - const float lookT = std::exp2(-lookRate * deltaTime); + const float lookRate = AZStd::exp2(ed_cameraSystemLookSmoothness); + const float lookT = AZStd::exp2(-lookRate * deltaTime); camera.m_pitch = AZ::Lerp(targetCamera.m_pitch, currentCamera.m_pitch, lookT); camera.m_yaw = AZ::Lerp(targetYaw, currentYaw, lookT); - const float moveRate = std::exp2(ed_cameraSystemTranslateSmoothness); - const float moveT = std::exp2(-moveRate * deltaTime); + const float moveRate = AZStd::exp2(ed_cameraSystemTranslateSmoothness); + const float moveT = AZStd::exp2(-moveRate * deltaTime); camera.m_lookDist = AZ::Lerp(targetCamera.m_lookDist, currentCamera.m_lookDist, moveT); camera.m_lookAt = targetCamera.m_lookAt.Lerp(currentCamera.m_lookAt, moveT); return camera; @@ -655,7 +679,7 @@ namespace AzFramework const auto* position = inputChannel.GetCustomData(); AZ_Assert(position, "Expected PositionData2D but found nullptr"); - return CursorMotionEvent{ScreenPoint( + return CursorEvent{ScreenPoint( position->m_normalizedPosition.GetX() * windowSize.m_width, position->m_normalizedPosition.GetY() * windowSize.m_height)}; } else if (inputChannelId == InputDeviceMouse::Movement::Z) diff --git a/Code/Framework/AzFramework/AzFramework/Viewport/CameraInput.h b/Code/Framework/AzFramework/AzFramework/Viewport/CameraInput.h index 6ccd7c43eb..6475753017 100644 --- a/Code/Framework/AzFramework/AzFramework/Viewport/CameraInput.h +++ b/Code/Framework/AzFramework/AzFramework/Viewport/CameraInput.h @@ -70,7 +70,7 @@ namespace AzFramework void UpdateCameraFromTransform(Camera& camera, const AZ::Transform& transform); - struct CursorMotionEvent + struct CursorEvent { ScreenPoint m_position; }; @@ -86,7 +86,7 @@ namespace AzFramework InputChannel::State m_state; //!< Channel state. (e.g. Begin/update/end event). }; - using InputEvent = AZStd::variant; + using InputEvent = AZStd::variant; class CameraInput { @@ -147,7 +147,7 @@ namespace AzFramework ResetImpl(); } - virtual void HandleEvents(const InputEvent& event) = 0; + virtual void HandleEvents(const InputEvent& event, const ScreenVector& cursorDelta, float scrollDelta) = 0; virtual Camera StepCamera(const Camera& targetCamera, const ScreenVector& cursorDelta, float scrollDelta, float deltaTime) = 0; virtual bool Exclusive() const @@ -170,7 +170,7 @@ namespace AzFramework { public: void AddCamera(AZStd::shared_ptr cameraInput); - bool HandleEvents(const InputEvent& event); + bool HandleEvents(const InputEvent& event, const ScreenVector& cursorDelta, float scrollDelta); Camera StepCamera(const Camera& targetCamera, const ScreenVector& cursorDelta, float scrollDelta, float deltaTime); void Reset(); @@ -201,11 +201,13 @@ namespace AzFramework { } - void HandleEvents(const InputEvent& event) override; + void HandleEvents(const InputEvent& event, const ScreenVector& cursorDelta, float scrollDelta) override; Camera StepCamera(const Camera& targetCamera, const ScreenVector& cursorDelta, float scrollDelta, float deltaTime) override; private: InputChannelId m_rotateChannelId; + float m_moveAccumulator = 0.0f; + bool m_tryingToBegin = false; }; struct PanAxes @@ -243,7 +245,7 @@ namespace AzFramework , m_panChannelId(panChannelId) { } - void HandleEvents(const InputEvent& event) override; + void HandleEvents(const InputEvent& event, const ScreenVector& cursorDelta, float scrollDelta) override; Camera StepCamera(const Camera& targetCamera, const ScreenVector& cursorDelta, float scrollDelta, float deltaTime) override; private: @@ -285,7 +287,7 @@ namespace AzFramework : m_translationAxesFn(AZStd::move(translationAxesFn)) { } - void HandleEvents(const InputEvent& event) override; + void HandleEvents(const InputEvent& event, const ScreenVector& cursorDelta, float scrollDelta) override; Camera StepCamera(const Camera& targetCamera, const ScreenVector& cursorDelta, float scrollDelta, float deltaTime) override; void ResetImpl() override; @@ -354,7 +356,7 @@ namespace AzFramework class OrbitDollyScrollCameraInput : public CameraInput { public: - void HandleEvents(const InputEvent& event) override; + void HandleEvents(const InputEvent& event, const ScreenVector& cursorDelta, float scrollDelta) override; Camera StepCamera(const Camera& targetCamera, const ScreenVector& cursorDelta, float scrollDelta, float deltaTime) override; }; @@ -364,7 +366,7 @@ namespace AzFramework explicit OrbitDollyCursorMoveCameraInput(const InputChannelId dollyChannelId) : m_dollyChannelId(dollyChannelId) {} - void HandleEvents(const InputEvent& event) override; + void HandleEvents(const InputEvent& event, const ScreenVector& cursorDelta, float scrollDelta) override; Camera StepCamera(const Camera& targetCamera, const ScreenVector& cursorDelta, float scrollDelta, float deltaTime) override; private: @@ -374,14 +376,14 @@ namespace AzFramework class ScrollTranslationCameraInput : public CameraInput { public: - void HandleEvents(const InputEvent& event) override; + void HandleEvents(const InputEvent& event, const ScreenVector& cursorDelta, float scrollDelta) override; Camera StepCamera(const Camera& targetCamera, const ScreenVector& cursorDelta, float scrollDelta, float deltaTime) override; }; class OrbitCameraInput : public CameraInput { public: - void HandleEvents(const InputEvent& event) override; + void HandleEvents(const InputEvent& event, const ScreenVector& cursorDelta, float scrollDelta) override; Camera StepCamera(const Camera& targetCamera, const ScreenVector& cursorDelta, float scrollDelta, float deltaTime) override; bool Exclusive() const override { diff --git a/Code/Framework/AzFramework/AzFramework/Viewport/ScreenGeometry.h b/Code/Framework/AzFramework/AzFramework/Viewport/ScreenGeometry.h index d3ae4e16f3..c48b1a5878 100644 --- a/Code/Framework/AzFramework/AzFramework/Viewport/ScreenGeometry.h +++ b/Code/Framework/AzFramework/AzFramework/Viewport/ScreenGeometry.h @@ -134,11 +134,16 @@ namespace AzFramework return !operator==(lhs, rhs); } + inline float ScreenVectorLength(const ScreenVector& screenVector) + { + return aznumeric_cast(AZStd::sqrt(screenVector.m_x * screenVector.m_x + screenVector.m_y * screenVector.m_y)); + } + inline ScreenPoint ScreenPointFromNDC(const AZ::Vector3& screenNDC, const AZ::Vector2& viewportSize) { return ScreenPoint( - aznumeric_caster(std::round(screenNDC.GetX() * viewportSize.GetX())), - aznumeric_caster(std::round((1.0f - screenNDC.GetY()) * viewportSize.GetY()))); + aznumeric_caster(AZStd::round(screenNDC.GetX() * viewportSize.GetX())), + aznumeric_caster(AZStd::round((1.0f - screenNDC.GetY()) * viewportSize.GetY()))); } inline AZ::Vector2 NDCFromScreenPoint(const ScreenPoint& screenPoint, const AZ::Vector2& viewportSize) diff --git a/Code/Framework/AzToolsFramework/Tests/Viewport/ViewportScreenTests.cpp b/Code/Framework/AzToolsFramework/Tests/Viewport/ViewportScreenTests.cpp index 8b3a564c4d..8f4133de63 100644 --- a/Code/Framework/AzToolsFramework/Tests/Viewport/ViewportScreenTests.cpp +++ b/Code/Framework/AzToolsFramework/Tests/Viewport/ViewportScreenTests.cpp @@ -211,6 +211,15 @@ namespace UnitTest EXPECT_EQ(screenPoint, ScreenPoint(45, 170)); } + TEST(ViewportScreen, ScreenVectorLengthReturned) + { + using AzFramework::ScreenVector; + + EXPECT_NEAR(AzFramework::ScreenVectorLength(ScreenVector(1, 1)), 1.41421f, 0.001f); + EXPECT_NEAR(AzFramework::ScreenVectorLength(ScreenVector(3, 4)), 5.0f, 0.001f); + EXPECT_NEAR(AzFramework::ScreenVectorLength(ScreenVector(12, 15)), 19.20937f, 0.001f); + } + TEST(ViewportScreen, CanGetCameraTransformFromCameraViewAndBack) { const auto screenDimensions = AZ::Vector2(1024.0f, 768.0f); diff --git a/Code/Sandbox/Editor/CryEditDoc.cpp b/Code/Sandbox/Editor/CryEditDoc.cpp index 83f7b482ae..64c830474f 100644 --- a/Code/Sandbox/Editor/CryEditDoc.cpp +++ b/Code/Sandbox/Editor/CryEditDoc.cpp @@ -579,14 +579,13 @@ void CCryEditDoc::SerializeViewSettings(CXmlArchive& xmlAr) view->getAttr(viewerAnglesName.toUtf8().constData(), va); } - CViewport* pVP = GetIEditor()->GetViewManager()->GetView(i); + Matrix34 tm = Matrix34::CreateRotationXYZ(va); + tm.SetTranslation(vp); - - if (pVP) + auto viewportContextManager = AZ::Interface::Get(); + if (auto viewportContext = viewportContextManager->GetViewportContextById(i)) { - Matrix34 tm = Matrix34::CreateRotationXYZ(va); - tm.SetTranslation(vp); - pVP->SetViewTM(tm); + viewportContext->SetCameraTransform(LYTransformToAZTransform(tm)); } // Load grid. diff --git a/Code/Sandbox/Editor/EditorViewportWidget.cpp b/Code/Sandbox/Editor/EditorViewportWidget.cpp index 3803867870..db37653cf1 100644 --- a/Code/Sandbox/Editor/EditorViewportWidget.cpp +++ b/Code/Sandbox/Editor/EditorViewportWidget.cpp @@ -453,8 +453,11 @@ void EditorViewportWidget::Update() } m_updatingCameraPosition = true; - auto transform = LYTransformToAZTransform(m_Camera.GetMatrix()); - m_renderViewport->GetViewportContext()->SetCameraTransform(transform); + if (!ed_useNewCameraSystem) + { + m_renderViewport->GetViewportContext()->SetCameraTransform(LYTransformToAZTransform(m_Camera.GetMatrix())); + } + AZ::Matrix4x4 clipMatrix; AZ::MakePerspectiveFovMatrixRH( clipMatrix, diff --git a/Code/Sandbox/Editor/ModernViewportCameraController.cpp b/Code/Sandbox/Editor/ModernViewportCameraController.cpp index 1c2771514f..f5df8d48ca 100644 --- a/Code/Sandbox/Editor/ModernViewportCameraController.cpp +++ b/Code/Sandbox/Editor/ModernViewportCameraController.cpp @@ -19,6 +19,7 @@ #include #include #include +#include #include #include @@ -64,17 +65,20 @@ namespace SandboxEditor } } - ModernViewportCameraControllerInstance::ModernViewportCameraControllerInstance(const AzFramework::ViewportId viewportId, ModernViewportCameraController* controller) + ModernViewportCameraControllerInstance::ModernViewportCameraControllerInstance( + const AzFramework::ViewportId viewportId, ModernViewportCameraController* controller) : MultiViewportControllerInstanceInterface(viewportId, controller) { controller->SetupCameras(m_cameraSystem.m_cameras); if (auto viewportContext = RetrieveViewportContext(GetViewportId())) { - auto handleCameraChange = [this](const AZ::Matrix4x4& matrix) { - UpdateCameraFromTransform( - m_targetCamera, - AZ::Transform::CreateFromMatrix3x3AndTranslation(AZ::Matrix3x3::CreateFromMatrix4x4(matrix), matrix.GetTranslation())); + auto handleCameraChange = [this, viewportContext](const AZ::Matrix4x4&) { + if (!m_updatingTransform) + { + UpdateCameraFromTransform(m_targetCamera, viewportContext->GetCameraTransform()); + m_camera = m_targetCamera; + } }; m_cameraViewMatrixChangeHandler = AZ::RPI::ViewportContext::MatrixChangedEvent::Handler(handleCameraChange); @@ -124,6 +128,8 @@ namespace SandboxEditor { if (auto viewportContext = RetrieveViewportContext(GetViewportId())) { + m_updatingTransform = true; + if (m_cameraMode == CameraMode::Control) { m_targetCamera = m_cameraSystem.StepCamera(m_targetCamera, event.m_deltaTime.count()); @@ -155,6 +161,8 @@ namespace SandboxEditor viewportContext->SetCameraTransform(current); } + + m_updatingTransform = false; } } diff --git a/Code/Sandbox/Editor/ModernViewportCameraController.h b/Code/Sandbox/Editor/ModernViewportCameraController.h index b1ff8d1039..edc034a78a 100644 --- a/Code/Sandbox/Editor/ModernViewportCameraController.h +++ b/Code/Sandbox/Editor/ModernViewportCameraController.h @@ -20,14 +20,13 @@ namespace SandboxEditor { class ModernViewportCameraControllerInstance; - class ModernViewportCameraController - : public AzFramework::MultiViewportController + class ModernViewportCameraController : public AzFramework::MultiViewportController { public: using CameraListBuilder = AZStd::function; + //! Sets the camera list builder callback used to populate new ModernViewportCameraControllerInstances void SetCameraListBuilderCallback(const CameraListBuilder& builder); - //! Sets up a camera list based on this controller's CameraListBuilderCallback void SetupCameras(AzFramework::Cameras& cameras); @@ -35,9 +34,9 @@ namespace SandboxEditor CameraListBuilder m_cameraListBuilder; }; - class ModernViewportCameraControllerInstance final - : public AzFramework::MultiViewportControllerInstanceInterface - , private AzFramework::ViewportDebugDisplayEventBus::Handler + class ModernViewportCameraControllerInstance final + : public AzFramework::MultiViewportControllerInstanceInterface, + private AzFramework::ViewportDebugDisplayEventBus::Handler { public: explicit ModernViewportCameraControllerInstance(AzFramework::ViewportId viewportId, ModernViewportCameraController* controller); @@ -65,6 +64,7 @@ namespace SandboxEditor AZ::Transform m_transformEnd = AZ::Transform::CreateIdentity(); float m_animationT = 0.0f; CameraMode m_cameraMode = CameraMode::Control; + bool m_updatingTransform = false; AZ::RPI::ViewportContext::MatrixChangedEvent::Handler m_cameraViewMatrixChangeHandler; }; diff --git a/Gems/Atom/RPI/Code/Source/RPI.Public/ViewportContext.cpp b/Gems/Atom/RPI/Code/Source/RPI.Public/ViewportContext.cpp index 4bccd48b66..cc25fb39ba 100644 --- a/Gems/Atom/RPI/Code/Source/RPI.Public/ViewportContext.cpp +++ b/Gems/Atom/RPI/Code/Source/RPI.Public/ViewportContext.cpp @@ -205,6 +205,7 @@ namespace AZ { const auto view = GetDefaultView(); view->SetCameraTransform(AZ::Matrix3x4::CreateFromTransform(transform.GetOrthogonalized())); + m_viewMatrixChangedEvent.Signal(view->GetWorldToViewMatrix()); } void ViewportContext::SetDefaultView(ViewPtr view)