diff --git a/Code/Framework/AzFramework/AzFramework/Viewport/CameraInput.cpp b/Code/Framework/AzFramework/AzFramework/Viewport/CameraInput.cpp index 6bde8dac85..984526e373 100644 --- a/Code/Framework/AzFramework/AzFramework/Viewport/CameraInput.cpp +++ b/Code/Framework/AzFramework/AzFramework/Viewport/CameraInput.cpp @@ -19,7 +19,7 @@ namespace AzFramework { - void CameraSystem::HandleEvents(const InputEvent& event) + bool CameraSystem::HandleEvents(const InputEvent& event) { if (const auto& cursor_motion = AZStd::get_if(&event)) { @@ -30,7 +30,7 @@ namespace AzFramework m_scrollDelta = scroll->m_delta; } - m_cameras.HandleEvents(event); + return m_cameras.HandleEvents(event); } Camera CameraSystem::StepCamera(const Camera& targetCamera, const float deltaTime) @@ -56,17 +56,21 @@ namespace AzFramework m_idleCameraInputs.push_back(AZStd::move(cameraInput)); } - void Cameras::HandleEvents(const InputEvent& event) + bool Cameras::HandleEvents(const InputEvent& event) { + bool handling = false; for (auto& cameraInput : m_activeCameraInputs) { cameraInput->HandleEvents(event); + handling = !cameraInput->Idle() || handling; } for (auto& cameraInput : m_idleCameraInputs) { cameraInput->HandleEvents(event); } + + return handling; } Camera Cameras::StepCamera(const Camera& targetCamera, const ScreenVector& cursorDelta, float scrollDelta, const float deltaTime) @@ -504,6 +508,11 @@ namespace AzFramework const auto& inputChannelId = inputChannel.GetInputChannelId(); const auto& inputDeviceId = inputChannel.GetInputDevice().GetInputDeviceId(); + const bool wasMouseButton = + AZStd::any_of(InputDeviceMouse::Button::All.begin(), InputDeviceMouse::Button::All.end(), [inputChannelId](const auto& button) { + return button == inputChannelId; + }); + if (inputChannelId == InputDeviceMouse::SystemCursorPosition) { AZ::Vector2 systemCursorPositionNormalized = AZ::Vector2::CreateZero(); @@ -517,7 +526,7 @@ namespace AzFramework { return ScrollEvent{inputChannel.GetValue()}; } - else if (InputDeviceMouse::IsMouseDevice(inputDeviceId) || InputDeviceKeyboard::IsKeyboardDevice(inputDeviceId)) + else if ((InputDeviceMouse::IsMouseDevice(inputDeviceId) && wasMouseButton) || InputDeviceKeyboard::IsKeyboardDevice(inputDeviceId)) { return DiscreteInputEvent{inputChannelId, inputChannel.GetState()}; } diff --git a/Code/Framework/AzFramework/AzFramework/Viewport/CameraInput.h b/Code/Framework/AzFramework/AzFramework/Viewport/CameraInput.h index 2fee6dc706..cbfe603c83 100644 --- a/Code/Framework/AzFramework/AzFramework/Viewport/CameraInput.h +++ b/Code/Framework/AzFramework/AzFramework/Viewport/CameraInput.h @@ -52,7 +52,7 @@ namespace AzFramework inline AZ::Transform Camera::Transform() const { return AZ::Transform::CreateTranslation(m_lookAt) * AZ::Transform::CreateRotationZ(m_yaw) * - AZ::Transform::CreateRotationX(m_pitch) * AZ::Transform::CreateTranslation(AZ::Vector3::CreateAxisZ(m_lookDist)); + AZ::Transform::CreateRotationX(m_pitch) * AZ::Transform::CreateTranslation(AZ::Vector3::CreateAxisY(m_lookDist)); } inline AZ::Matrix3x3 Camera::Rotation() const @@ -171,7 +171,7 @@ namespace AzFramework { public: void AddCamera(AZStd::shared_ptr cameraInput); - void HandleEvents(const InputEvent& event); + bool HandleEvents(const InputEvent& event); Camera StepCamera(const Camera& targetCamera, const ScreenVector& cursorDelta, float scrollDelta, float deltaTime); void Reset(); @@ -183,7 +183,7 @@ namespace AzFramework class CameraSystem { public: - void HandleEvents(const InputEvent& event); + bool HandleEvents(const InputEvent& event); Camera StepCamera(const Camera& targetCamera, float deltaTime); Cameras m_cameras; @@ -369,7 +369,7 @@ namespace AzFramework struct Props { - float m_dollySpeed = 0.2f; + float m_dollySpeed = 0.02f; } m_props; }; @@ -393,7 +393,7 @@ namespace AzFramework struct Props { - float m_translateSpeed = 0.2f; + float m_translateSpeed = 0.02f; } m_props; }; diff --git a/Code/Sandbox/Editor/EditorViewportWidget.cpp b/Code/Sandbox/Editor/EditorViewportWidget.cpp index 25588e85a7..6a32a6abb1 100644 --- a/Code/Sandbox/Editor/EditorViewportWidget.cpp +++ b/Code/Sandbox/Editor/EditorViewportWidget.cpp @@ -1633,8 +1633,8 @@ void EditorViewportWidget::keyPressEvent(QKeyEvent* event) QCoreApplication::sendEvent(GetIEditor()->GetEditorMainWindow(), event); } - // NOTE: we keep track of keypresses and releases explicitly because the OS/Qt will insert a slight delay between sending - // keyevents when the key is held down. This is standard, but makes responding to key events for game style input silly + // NOTE: we keep track of key presses and releases explicitly because the OS/Qt will insert a slight delay between sending + // key events when the key is held down. This is standard, but makes responding to key events for game style input silly // because we want the movement to be butter smooth. if (!event->isAutoRepeat()) { @@ -2428,7 +2428,10 @@ void EditorViewportWidget::SetDefaultCamera() return; } ResetToViewSourceType(ViewSourceType::None); - gEnv->p3DEngine->GetPostEffectBaseGroup()->SetParam("Dof_Active", 0.0f); + if (gEnv->p3DEngine) + { + gEnv->p3DEngine->GetPostEffectBaseGroup()->SetParam("Dof_Active", 0.0f); + } GetViewManager()->SetCameraObjectId(m_cameraObjectId); SetName(m_defaultViewName); SetViewTM(m_defaultViewTM); diff --git a/Code/Sandbox/Editor/ModernViewportCameraController.cpp b/Code/Sandbox/Editor/ModernViewportCameraController.cpp index 80bd9416f7..09fd5be2e9 100644 --- a/Code/Sandbox/Editor/ModernViewportCameraController.cpp +++ b/Code/Sandbox/Editor/ModernViewportCameraController.cpp @@ -14,9 +14,14 @@ #include #include +#include #include +#include #include #include +#include + +AZ_CVAR(bool, ed_newCameraSystemDebug, false, nullptr, AZ::ConsoleFunctorFlags::Null, "Enable debug drawing for the new camera system"); namespace SandboxEditor { @@ -37,8 +42,17 @@ namespace SandboxEditor return viewportContext; } + struct ModernViewportCameraControllerInstance::Impl + { + AzFramework::Camera m_camera; + AzFramework::Camera m_targetCamera; + AzFramework::SmoothProps m_smoothProps; + AzFramework::CameraSystem m_cameraSystem; + }; + ModernViewportCameraControllerInstance::ModernViewportCameraControllerInstance(const AzFramework::ViewportId viewportId) : MultiViewportControllerInstanceInterface(viewportId) + , m_impl(AZStd::make_unique()) { // LYN-2315 TODO - move setup out of constructor, pass cameras in auto firstPersonRotateCamera = AZStd::make_shared(AzFramework::InputDeviceMouse::Button::Right); @@ -58,21 +72,28 @@ namespace SandboxEditor orbitCamera->m_orbitCameras.AddCamera(orbitDollyMoveCamera); orbitCamera->m_orbitCameras.AddCamera(orbitPanCamera); - m_cameraSystem.m_cameras.AddCamera(firstPersonRotateCamera); - m_cameraSystem.m_cameras.AddCamera(firstPersonPanCamera); - m_cameraSystem.m_cameras.AddCamera(firstPersonTranslateCamera); - m_cameraSystem.m_cameras.AddCamera(firstPersonWheelCamera); - m_cameraSystem.m_cameras.AddCamera(orbitCamera); + m_impl->m_cameraSystem.m_cameras.AddCamera(firstPersonRotateCamera); + m_impl->m_cameraSystem.m_cameras.AddCamera(firstPersonPanCamera); + m_impl->m_cameraSystem.m_cameras.AddCamera(firstPersonTranslateCamera); + m_impl->m_cameraSystem.m_cameras.AddCamera(firstPersonWheelCamera); + m_impl->m_cameraSystem.m_cameras.AddCamera(orbitCamera); if (const auto viewportContext = RetrieveViewportContext(viewportId)) { // set position but not orientation - m_targetCamera.m_lookAt = viewportContext->GetCameraTransform().GetTranslation(); + m_impl->m_targetCamera.m_lookAt = viewportContext->GetCameraTransform().GetTranslation(); // LYN-2315 TODO https://www.geometrictools.com/Documentation/EulerAngles.pdf - m_camera = m_targetCamera; + m_impl->m_camera = m_impl->m_targetCamera; } + + AzFramework::ViewportDebugDisplayEventBus::Handler::BusConnect(AzToolsFramework::GetEntityContextId()); + } + + ModernViewportCameraControllerInstance::~ModernViewportCameraControllerInstance() + { + AzFramework::ViewportDebugDisplayEventBus::Handler::BusDisconnect(); } bool ModernViewportCameraControllerInstance::HandleInputChannelEvent(const AzFramework::ViewportControllerInputEvent& event) @@ -80,18 +101,28 @@ namespace SandboxEditor AzFramework::WindowSize windowSize; AzFramework::WindowRequestBus::EventResult( windowSize, event.m_windowHandle, &AzFramework::WindowRequestBus::Events::GetClientAreaSize); - m_cameraSystem.HandleEvents(AzFramework::BuildInputEvent(event.m_inputChannel, windowSize)); - return true; // consume event + return m_impl->m_cameraSystem.HandleEvents(AzFramework::BuildInputEvent(event.m_inputChannel, windowSize)); } void ModernViewportCameraControllerInstance::UpdateViewport(const AzFramework::ViewportControllerUpdateEvent& event) { if (auto viewportContext = RetrieveViewportContext(GetViewportId())) { - m_targetCamera = m_cameraSystem.StepCamera(m_targetCamera, event.m_deltaTime.count()); - m_camera = AzFramework::SmoothCamera(m_camera, m_targetCamera, m_smoothProps, event.m_deltaTime.count()); + m_impl->m_targetCamera = m_impl->m_cameraSystem.StepCamera(m_impl->m_targetCamera, event.m_deltaTime.count()); + m_impl->m_camera = + AzFramework::SmoothCamera(m_impl->m_camera, m_impl->m_targetCamera, m_impl->m_smoothProps, event.m_deltaTime.count()); - viewportContext->SetCameraTransform(m_camera.Transform()); + viewportContext->SetCameraTransform(m_impl->m_camera.Transform()); + } + } + + void ModernViewportCameraControllerInstance::DisplayViewport( + [[maybe_unused]] const AzFramework::ViewportInfo& viewportInfo, AzFramework::DebugDisplayRequests& debugDisplay) + { + if (ed_newCameraSystemDebug) + { + debugDisplay.SetColor(AZ::Colors::White); + debugDisplay.DrawWireSphere(m_impl->m_targetCamera.m_lookAt, 0.5f); } } } // namespace SandboxEditor diff --git a/Code/Sandbox/Editor/ModernViewportCameraController.h b/Code/Sandbox/Editor/ModernViewportCameraController.h index c65dbc8b8a..57fdd1cb55 100644 --- a/Code/Sandbox/Editor/ModernViewportCameraController.h +++ b/Code/Sandbox/Editor/ModernViewportCameraController.h @@ -12,25 +12,28 @@ #pragma once -#include +#include #include namespace SandboxEditor { - class ModernViewportCameraControllerInstance final : public AzFramework::MultiViewportControllerInstanceInterface + class ModernViewportCameraControllerInstance final : public AzFramework::MultiViewportControllerInstanceInterface, + private AzFramework::ViewportDebugDisplayEventBus::Handler { public: explicit ModernViewportCameraControllerInstance(AzFramework::ViewportId viewportId); + ~ModernViewportCameraControllerInstance(); // MultiViewportControllerInstanceInterface overrides ... bool HandleInputChannelEvent(const AzFramework::ViewportControllerInputEvent& event) override; void UpdateViewport(const AzFramework::ViewportControllerUpdateEvent& event) override; + // AzFramework::ViewportDebugDisplayEventBus ... + void DisplayViewport(const AzFramework::ViewportInfo& viewportInfo, AzFramework::DebugDisplayRequests& debugDisplay) override; + private: - AzFramework::Camera m_camera; - AzFramework::Camera m_targetCamera; - AzFramework::SmoothProps m_smoothProps; - AzFramework::CameraSystem m_cameraSystem; + struct Impl; + AZStd::unique_ptr m_impl; }; using ModernViewportCameraController = AzFramework::MultiViewportController;