diff --git a/Code/Editor/EditorModularViewportCameraComposer.cpp b/Code/Editor/EditorModularViewportCameraComposer.cpp new file mode 100644 index 0000000000..2eab1c5611 --- /dev/null +++ b/Code/Editor/EditorModularViewportCameraComposer.cpp @@ -0,0 +1,286 @@ +/* + * Copyright (c) Contributors to the Open 3D Engine Project. + * For complete copyright and license terms please see the LICENSE at the root of this distribution. + * + * SPDX-License-Identifier: Apache-2.0 OR MIT + * + */ + +#include + +#include +#include +#include +#include +#include + +namespace SandboxEditor +{ + static AzFramework::TranslateCameraInputChannelIds BuildTranslateCameraInputChannelIds() + { + AzFramework::TranslateCameraInputChannelIds translateCameraInputChannelIds; + translateCameraInputChannelIds.m_leftChannelId = SandboxEditor::CameraTranslateLeftChannelId(); + translateCameraInputChannelIds.m_rightChannelId = SandboxEditor::CameraTranslateRightChannelId(); + translateCameraInputChannelIds.m_forwardChannelId = SandboxEditor::CameraTranslateForwardChannelId(); + translateCameraInputChannelIds.m_backwardChannelId = SandboxEditor::CameraTranslateBackwardChannelId(); + translateCameraInputChannelIds.m_upChannelId = SandboxEditor::CameraTranslateUpChannelId(); + translateCameraInputChannelIds.m_downChannelId = SandboxEditor::CameraTranslateDownChannelId(); + translateCameraInputChannelIds.m_boostChannelId = SandboxEditor::CameraTranslateBoostChannelId(); + + return translateCameraInputChannelIds; + } + + EditorModularViewportCameraComposer::EditorModularViewportCameraComposer(const AzFramework::ViewportId viewportId) + : m_viewportId(viewportId) + { + EditorModularViewportCameraComposerNotificationBus::Handler::BusConnect(viewportId); + } + + EditorModularViewportCameraComposer::~EditorModularViewportCameraComposer() + { + EditorModularViewportCameraComposerNotificationBus::Handler::BusDisconnect(); + } + + AZStd::shared_ptr EditorModularViewportCameraComposer:: + CreateModularViewportCameraController() + { + SetupCameras(); + + auto controller = AZStd::make_shared(); + + controller->SetCameraViewportContextBuilderCallback( + [viewportId = m_viewportId](AZStd::unique_ptr& cameraViewportContext) + { + cameraViewportContext = AZStd::make_unique(viewportId); + }); + + controller->SetCameraPriorityBuilderCallback( + [](AtomToolsFramework::CameraControllerPriorityFn& cameraControllerPriorityFn) + { + cameraControllerPriorityFn = AtomToolsFramework::DefaultCameraControllerPriority; + }); + + controller->SetCameraPropsBuilderCallback( + [](AzFramework::CameraProps& cameraProps) + { + cameraProps.m_rotateSmoothnessFn = [] + { + return SandboxEditor::CameraRotateSmoothness(); + }; + + cameraProps.m_translateSmoothnessFn = [] + { + return SandboxEditor::CameraTranslateSmoothness(); + }; + + cameraProps.m_rotateSmoothingEnabledFn = [] + { + return SandboxEditor::CameraRotateSmoothingEnabled(); + }; + + cameraProps.m_translateSmoothingEnabledFn = [] + { + return SandboxEditor::CameraTranslateSmoothingEnabled(); + }; + }); + + controller->SetCameraListBuilderCallback( + [viewportId = m_viewportId, this](AzFramework::Cameras& cameras) + { + cameras.AddCamera(m_firstPersonRotateCamera); + cameras.AddCamera(m_firstPersonPanCamera); + cameras.AddCamera(m_firstPersonTranslateCamera); + cameras.AddCamera(m_firstPersonScrollCamera); + cameras.AddCamera(m_orbitCamera); + }); + + return controller; + } + + void EditorModularViewportCameraComposer::SetupCameras() + { + const auto hideCursor = [viewportId = m_viewportId] + { + if (SandboxEditor::CameraCaptureCursorForLook()) + { + AzToolsFramework::ViewportInteraction::ViewportMouseCursorRequestBus::Event( + viewportId, &AzToolsFramework::ViewportInteraction::ViewportMouseCursorRequestBus::Events::BeginCursorCapture); + } + }; + const auto showCursor = [viewportId = m_viewportId] + { + if (SandboxEditor::CameraCaptureCursorForLook()) + { + AzToolsFramework::ViewportInteraction::ViewportMouseCursorRequestBus::Event( + viewportId, &AzToolsFramework::ViewportInteraction::ViewportMouseCursorRequestBus::Events::EndCursorCapture); + } + }; + + m_firstPersonRotateCamera = AZStd::make_shared(SandboxEditor::CameraFreeLookChannelId()); + + m_firstPersonRotateCamera->m_rotateSpeedFn = [] + { + return SandboxEditor::CameraRotateSpeed(); + }; + + // default behavior is to hide the cursor but this can be disabled (useful for remote desktop) + // note: See CaptureCursorLook in the Settings Registry + m_firstPersonRotateCamera->SetActivationBeganFn(hideCursor); + m_firstPersonRotateCamera->SetActivationEndedFn(showCursor); + + m_firstPersonPanCamera = + AZStd::make_shared(SandboxEditor::CameraFreePanChannelId(), AzFramework::LookPan); + + m_firstPersonPanCamera->m_panSpeedFn = [] + { + return SandboxEditor::CameraPanSpeed(); + }; + + m_firstPersonPanCamera->m_invertPanXFn = [] + { + return SandboxEditor::CameraPanInvertedX(); + }; + + m_firstPersonPanCamera->m_invertPanYFn = [] + { + return SandboxEditor::CameraPanInvertedY(); + }; + + const auto translateCameraInputChannelIds = BuildTranslateCameraInputChannelIds(); + + m_firstPersonTranslateCamera = + AZStd::make_shared(AzFramework::LookTranslation, translateCameraInputChannelIds); + + m_firstPersonTranslateCamera->m_translateSpeedFn = [] + { + return SandboxEditor::CameraTranslateSpeed(); + }; + + m_firstPersonTranslateCamera->m_boostMultiplierFn = [] + { + return SandboxEditor::CameraBoostMultiplier(); + }; + + m_firstPersonScrollCamera = AZStd::make_shared(); + + m_firstPersonScrollCamera->m_scrollSpeedFn = [] + { + return SandboxEditor::CameraScrollSpeed(); + }; + + m_orbitCamera = AZStd::make_shared(SandboxEditor::CameraOrbitChannelId()); + + m_orbitCamera->SetLookAtFn( + [viewportId = m_viewportId](const AZ::Vector3& position, const AZ::Vector3& direction) -> AZStd::optional + { + AZStd::optional lookAtAfterInterpolation; + AtomToolsFramework::ModularViewportCameraControllerRequestBus::EventResult( + lookAtAfterInterpolation, viewportId, + &AtomToolsFramework::ModularViewportCameraControllerRequestBus::Events::LookAtAfterInterpolation); + + // initially attempt to use the last set look at point after an interpolation has finished + if (lookAtAfterInterpolation.has_value()) + { + return *lookAtAfterInterpolation; + } + + const float RayDistance = 1000.0f; + AzFramework::RenderGeometry::RayRequest ray; + ray.m_startWorldPosition = position; + ray.m_endWorldPosition = position + direction * RayDistance; + ray.m_onlyVisible = true; + + AzFramework::RenderGeometry::RayResult renderGeometryIntersectionResult; + AzFramework::RenderGeometry::IntersectorBus::EventResult( + renderGeometryIntersectionResult, AzToolsFramework::GetEntityContextId(), + &AzFramework::RenderGeometry::IntersectorBus::Events::RayIntersect, ray); + + // attempt a ray intersection with any visible mesh and return the intersection position if successful + if (renderGeometryIntersectionResult) + { + return renderGeometryIntersectionResult.m_worldPosition; + } + + // if there is no selection or no intersection, fallback to default camera orbit behavior (ground plane + // intersection) + return {}; + }); + + m_orbitRotateCamera = AZStd::make_shared(SandboxEditor::CameraOrbitLookChannelId()); + + m_orbitRotateCamera->m_rotateSpeedFn = [] + { + return SandboxEditor::CameraRotateSpeed(); + }; + + m_orbitRotateCamera->m_invertYawFn = [] + { + return SandboxEditor::CameraOrbitYawRotationInverted(); + }; + + m_orbitTranslateCamera = + AZStd::make_shared(AzFramework::OrbitTranslation, translateCameraInputChannelIds); + + m_orbitTranslateCamera->m_translateSpeedFn = [] + { + return SandboxEditor::CameraTranslateSpeed(); + }; + + m_orbitTranslateCamera->m_boostMultiplierFn = [] + { + return SandboxEditor::CameraBoostMultiplier(); + }; + + m_orbitDollyScrollCamera = AZStd::make_shared(); + + m_orbitDollyScrollCamera->m_scrollSpeedFn = [] + { + return SandboxEditor::CameraScrollSpeed(); + }; + + m_orbitDollyMoveCamera = + AZStd::make_shared(SandboxEditor::CameraOrbitDollyChannelId()); + + m_orbitDollyMoveCamera->m_cursorSpeedFn = [] + { + return SandboxEditor::CameraDollyMotionSpeed(); + }; + + m_orbitPanCamera = AZStd::make_shared(SandboxEditor::CameraOrbitPanChannelId(), AzFramework::OrbitPan); + + m_orbitPanCamera->m_panSpeedFn = [] + { + return SandboxEditor::CameraPanSpeed(); + }; + + m_orbitPanCamera->m_invertPanXFn = [] + { + return SandboxEditor::CameraPanInvertedX(); + }; + + m_orbitPanCamera->m_invertPanYFn = [] + { + return SandboxEditor::CameraPanInvertedY(); + }; + + m_orbitCamera->m_orbitCameras.AddCamera(m_orbitRotateCamera); + m_orbitCamera->m_orbitCameras.AddCamera(m_orbitTranslateCamera); + m_orbitCamera->m_orbitCameras.AddCamera(m_orbitDollyScrollCamera); + m_orbitCamera->m_orbitCameras.AddCamera(m_orbitDollyMoveCamera); + m_orbitCamera->m_orbitCameras.AddCamera(m_orbitPanCamera); + } + + void EditorModularViewportCameraComposer::OnEditorModularViewportCameraComposerSettingsChanged() + { + const auto translateCameraInputChannelIds = BuildTranslateCameraInputChannelIds(); + m_firstPersonTranslateCamera->SetTranslateCameraInputChannelIds(translateCameraInputChannelIds); + m_orbitTranslateCamera->SetTranslateCameraInputChannelIds(translateCameraInputChannelIds); + + m_firstPersonPanCamera->SetPanInputChannelId(SandboxEditor::CameraFreePanChannelId()); + m_orbitPanCamera->SetPanInputChannelId(SandboxEditor::CameraOrbitPanChannelId()); + m_firstPersonRotateCamera->SetRotateInputChannelId(SandboxEditor::CameraFreeLookChannelId()); + m_orbitRotateCamera->SetRotateInputChannelId(SandboxEditor::CameraOrbitLookChannelId()); + m_orbitCamera->SetOrbitInputChannelId(SandboxEditor::CameraOrbitChannelId()); + m_orbitDollyMoveCamera->SetDollyInputChannelId(SandboxEditor::CameraOrbitDollyChannelId()); + } +} // namespace SandboxEditor diff --git a/Code/Editor/EditorModularViewportCameraComposer.h b/Code/Editor/EditorModularViewportCameraComposer.h new file mode 100644 index 0000000000..cb223d39e6 --- /dev/null +++ b/Code/Editor/EditorModularViewportCameraComposer.h @@ -0,0 +1,48 @@ +/* + * Copyright (c) Contributors to the Open 3D Engine Project. + * For complete copyright and license terms please see the LICENSE at the root of this distribution. + * + * SPDX-License-Identifier: Apache-2.0 OR MIT + * + */ + +#pragma once + +#include +#include +#include +#include + +namespace SandboxEditor +{ + //! Type responsible for building the editor's modular viewport camera controller. + class EditorModularViewportCameraComposer : private EditorModularViewportCameraComposerNotificationBus::Handler + { + public: + SANDBOX_API explicit EditorModularViewportCameraComposer(AzFramework::ViewportId viewportId); + SANDBOX_API ~EditorModularViewportCameraComposer(); + + //! Build a ModularViewportCameraController from the associated camera inputs. + SANDBOX_API AZStd::shared_ptr CreateModularViewportCameraController(); + + private: + //! Setup all internal camera inputs. + void SetupCameras(); + + // EditorModularViewportCameraComposerNotificationBus overrides ... + void OnEditorModularViewportCameraComposerSettingsChanged() override; + + AZStd::shared_ptr m_firstPersonRotateCamera; + AZStd::shared_ptr m_firstPersonPanCamera; + AZStd::shared_ptr m_firstPersonTranslateCamera; + AZStd::shared_ptr m_firstPersonScrollCamera; + AZStd::shared_ptr m_orbitCamera; + AZStd::shared_ptr m_orbitRotateCamera; + AZStd::shared_ptr m_orbitTranslateCamera; + AZStd::shared_ptr m_orbitDollyScrollCamera; + AZStd::shared_ptr m_orbitDollyMoveCamera; + AZStd::shared_ptr m_orbitPanCamera; + + AzFramework::ViewportId m_viewportId; + }; +} // namespace SandboxEditor diff --git a/Code/Editor/EditorModularViewportCameraComposerBus.h b/Code/Editor/EditorModularViewportCameraComposerBus.h new file mode 100644 index 0000000000..ac760b8a9a --- /dev/null +++ b/Code/Editor/EditorModularViewportCameraComposerBus.h @@ -0,0 +1,31 @@ +/* + * Copyright (c) Contributors to the Open 3D Engine Project. + * For complete copyright and license terms please see the LICENSE at the root of this distribution. + * + * SPDX-License-Identifier: Apache-2.0 OR MIT + * + */ + +#pragma once + +#include +#include +#include + +namespace SandboxEditor +{ + //! Notifications for changes to the editor modular viewport camera controller. + class EditorModularViewportCameraComposerNotifications + { + public: + //! Notify any listeners when changes have been made to the modular viewport camera settings. + //! @note This is used to update any cached input channels when controls are modified. + virtual void OnEditorModularViewportCameraComposerSettingsChanged() = 0; + + protected: + ~EditorModularViewportCameraComposerNotifications() = default; + }; + + using EditorModularViewportCameraComposerNotificationBus = + AZ::EBus; +} // namespace SandboxEditor diff --git a/Code/Editor/EditorPreferencesPageViewportMovement.cpp b/Code/Editor/EditorPreferencesPageViewportMovement.cpp index 06bcd13c60..74abb3f207 100644 --- a/Code/Editor/EditorPreferencesPageViewportMovement.cpp +++ b/Code/Editor/EditorPreferencesPageViewportMovement.cpp @@ -10,12 +10,54 @@ #include "EditorPreferencesPageViewportMovement.h" +#include +#include +#include +#include #include +#include // Editor #include "EditorViewportSettings.h" #include "Settings.h" +static AZStd::vector GetInputNamesByDevice(const AzFramework::InputDeviceId inputDeviceId) +{ + AzFramework::InputDeviceRequests::InputChannelIdSet availableInputChannelIds; + AzFramework::InputDeviceRequestBus::Event( + inputDeviceId, &AzFramework::InputDeviceRequests::GetInputChannelIds, availableInputChannelIds); + + AZStd::vector inputChannelNames; + for (const AzFramework::InputChannelId& inputChannelId : availableInputChannelIds) + { + inputChannelNames.push_back(inputChannelId.GetName()); + } + + AZStd::sort(inputChannelNames.begin(), inputChannelNames.end()); + + return inputChannelNames; +} + +static AZStd::vector GetEditorInputNames() +{ + // function static to defer having to call GetInputNamesByDevice for every CameraInputSettings member + static bool inputNamesGenerated = false; + static AZStd::vector inputNames; + + if (!inputNamesGenerated) + { + AZStd::vector keyboardInputNames = GetInputNamesByDevice(AzFramework::InputDeviceKeyboard::Id); + AZStd::vector mouseInputNames = GetInputNamesByDevice(AzFramework::InputDeviceMouse::Id); + + inputNames.insert(inputNames.end(), mouseInputNames.begin(), mouseInputNames.end()); + inputNames.insert(inputNames.end(), keyboardInputNames.begin(), keyboardInputNames.end()); + + inputNamesGenerated = true; + } + + return inputNames; +} + void CEditorPreferencesPage_ViewportMovement::Reflect(AZ::SerializeContext& serialize) { serialize.Class() @@ -35,12 +77,30 @@ void CEditorPreferencesPage_ViewportMovement::Reflect(AZ::SerializeContext& seri ->Field("PanInvertedX", &CameraMovementSettings::m_panInvertedX) ->Field("PanInvertedY", &CameraMovementSettings::m_panInvertedY); - serialize.Class()->Version(1)->Field( - "CameraMovementSettings", &CEditorPreferencesPage_ViewportMovement::m_cameraMovementSettings); + serialize.Class() + ->Version(1) + ->Field("TranslateForward", &CameraInputSettings::m_translateForwardChannelId) + ->Field("TranslateBackward", &CameraInputSettings::m_translateBackwardChannelId) + ->Field("TranslateLeft", &CameraInputSettings::m_translateLeftChannelId) + ->Field("TranslateRight", &CameraInputSettings::m_translateRightChannelId) + ->Field("TranslateUp", &CameraInputSettings::m_translateUpChannelId) + ->Field("TranslateDown", &CameraInputSettings::m_translateDownChannelId) + ->Field("Boost", &CameraInputSettings::m_boostChannelId) + ->Field("Orbit", &CameraInputSettings::m_orbitChannelId) + ->Field("FreeLook", &CameraInputSettings::m_freeLookChannelId) + ->Field("FreePan", &CameraInputSettings::m_freePanChannelId) + ->Field("OrbitLook", &CameraInputSettings::m_orbitLookChannelId) + ->Field("OrbitDolly", &CameraInputSettings::m_orbitDollyChannelId) + ->Field("OrbitPan", &CameraInputSettings::m_orbitPanChannelId); + + serialize.Class() + ->Version(1) + ->Field("CameraMovementSettings", &CEditorPreferencesPage_ViewportMovement::m_cameraMovementSettings) + ->Field("CameraInputSettings", &CEditorPreferencesPage_ViewportMovement::m_cameraInputSettings); if (AZ::EditContext* editContext = serialize.GetEditContext()) { - editContext->Class("Camera Settings", "") + editContext->Class("Camera Movement Settings", "") ->DataElement( AZ::Edit::UIHandlers::SpinBox, &CameraMovementSettings::m_translateSpeed, "Camera Movement Speed", "Camera movement speed") ->Attribute(AZ::Edit::Attributes::Min, 0.01f) @@ -94,12 +154,68 @@ void CEditorPreferencesPage_ViewportMovement::Reflect(AZ::SerializeContext& seri AZ::Edit::UIHandlers::CheckBox, &CameraMovementSettings::m_captureCursorLook, "Camera Capture Look Cursor", "Should the cursor be captured (hidden) while performing free look"); + editContext->Class("Camera Input Settings", "") + ->DataElement( + AZ::Edit::UIHandlers::ComboBox, &CameraInputSettings::m_translateForwardChannelId, "Translate Forward", + "Key/button to move the camera forward") + ->Attribute(AZ::Edit::Attributes::StringList, &GetEditorInputNames) + ->DataElement( + AZ::Edit::UIHandlers::ComboBox, &CameraInputSettings::m_translateBackwardChannelId, "Translate Backward", + "Key/button to move the camera backward") + ->Attribute(AZ::Edit::Attributes::StringList, &GetEditorInputNames) + ->DataElement( + AZ::Edit::UIHandlers::ComboBox, &CameraInputSettings::m_translateLeftChannelId, "Translate Left", + "Key/button to move the camera left") + ->Attribute(AZ::Edit::Attributes::StringList, &GetEditorInputNames) + ->DataElement( + AZ::Edit::UIHandlers::ComboBox, &CameraInputSettings::m_translateRightChannelId, "Translate Right", + "Key/button to move the camera right") + ->Attribute(AZ::Edit::Attributes::StringList, &GetEditorInputNames) + ->DataElement( + AZ::Edit::UIHandlers::ComboBox, &CameraInputSettings::m_translateUpChannelId, "Translate Up", + "Key/button to move the camera up") + ->Attribute(AZ::Edit::Attributes::StringList, &GetEditorInputNames) + ->DataElement( + AZ::Edit::UIHandlers::ComboBox, &CameraInputSettings::m_translateDownChannelId, "Translate Down", + "Key/button to move the camera down") + ->Attribute(AZ::Edit::Attributes::StringList, &GetEditorInputNames) + ->DataElement( + AZ::Edit::UIHandlers::ComboBox, &CameraInputSettings::m_boostChannelId, "Boost", + "Key/button to move the camera more quickly") + ->Attribute(AZ::Edit::Attributes::StringList, &GetEditorInputNames) + ->DataElement( + AZ::Edit::UIHandlers::ComboBox, &CameraInputSettings::m_orbitChannelId, "Orbit", + "Key/button to begin the camera orbit behavior") + ->Attribute(AZ::Edit::Attributes::StringList, &GetEditorInputNames) + ->DataElement( + AZ::Edit::UIHandlers::ComboBox, &CameraInputSettings::m_freeLookChannelId, "Free Look", + "Key/button to begin camera free look") + ->Attribute(AZ::Edit::Attributes::StringList, &GetEditorInputNames) + ->DataElement( + AZ::Edit::UIHandlers::ComboBox, &CameraInputSettings::m_freePanChannelId, "Free Pan", "Key/button to begin camera free pan") + ->Attribute(AZ::Edit::Attributes::StringList, &GetEditorInputNames) + ->DataElement( + AZ::Edit::UIHandlers::ComboBox, &CameraInputSettings::m_orbitLookChannelId, "Orbit Look", + "Key/button to begin camera orbit look") + ->Attribute(AZ::Edit::Attributes::StringList, &GetEditorInputNames) + ->DataElement( + AZ::Edit::UIHandlers::ComboBox, &CameraInputSettings::m_orbitDollyChannelId, "Orbit Dolly", + "Key/button to begin camera orbit dolly") + ->Attribute(AZ::Edit::Attributes::StringList, &GetEditorInputNames) + ->DataElement( + AZ::Edit::UIHandlers::ComboBox, &CameraInputSettings::m_orbitPanChannelId, "Orbit Pan", + "Key/button to begin camera orbit pan") + ->Attribute(AZ::Edit::Attributes::StringList, &GetEditorInputNames); + editContext->Class("Viewport Preferences", "Viewport Preferences") ->ClassElement(AZ::Edit::ClassElements::EditorData, "") ->Attribute(AZ::Edit::Attributes::Visibility, AZ_CRC("PropertyVisibility_ShowChildrenOnly", 0xef428f20)) ->DataElement( AZ::Edit::UIHandlers::Default, &CEditorPreferencesPage_ViewportMovement::m_cameraMovementSettings, - "Camera Movement Settings", "Camera Movement Settings"); + "Camera Movement Settings", "Camera Movement Settings") + ->DataElement( + AZ::Edit::UIHandlers::Default, &CEditorPreferencesPage_ViewportMovement::m_cameraInputSettings, "Camera Input Settings", + "Camera Input Settings"); } } @@ -135,6 +251,23 @@ void CEditorPreferencesPage_ViewportMovement::OnApply() SandboxEditor::SetCameraOrbitYawRotationInverted(m_cameraMovementSettings.m_orbitYawRotationInverted); SandboxEditor::SetCameraPanInvertedX(m_cameraMovementSettings.m_panInvertedX); SandboxEditor::SetCameraPanInvertedY(m_cameraMovementSettings.m_panInvertedY); + + SandboxEditor::SetCameraTranslateForwardChannelId(m_cameraInputSettings.m_translateForwardChannelId); + SandboxEditor::SetCameraTranslateBackwardChannelId(m_cameraInputSettings.m_translateBackwardChannelId); + SandboxEditor::SetCameraTranslateLeftChannelId(m_cameraInputSettings.m_translateLeftChannelId); + SandboxEditor::SetCameraTranslateRightChannelId(m_cameraInputSettings.m_translateRightChannelId); + SandboxEditor::SetCameraTranslateUpChannelId(m_cameraInputSettings.m_translateUpChannelId); + SandboxEditor::SetCameraTranslateDownChannelId(m_cameraInputSettings.m_translateDownChannelId); + SandboxEditor::SetCameraTranslateBoostChannelId(m_cameraInputSettings.m_boostChannelId); + SandboxEditor::SetCameraOrbitChannelId(m_cameraInputSettings.m_orbitChannelId); + SandboxEditor::SetCameraFreeLookChannelId(m_cameraInputSettings.m_freeLookChannelId); + SandboxEditor::SetCameraFreePanChannelId(m_cameraInputSettings.m_freePanChannelId); + SandboxEditor::SetCameraOrbitLookChannelId(m_cameraInputSettings.m_orbitLookChannelId); + SandboxEditor::SetCameraOrbitDollyChannelId(m_cameraInputSettings.m_orbitDollyChannelId); + SandboxEditor::SetCameraOrbitPanChannelId(m_cameraInputSettings.m_orbitPanChannelId); + + SandboxEditor::EditorModularViewportCameraComposerNotificationBus::Broadcast( + &SandboxEditor::EditorModularViewportCameraComposerNotificationBus::Events::OnEditorModularViewportCameraComposerSettingsChanged); } void CEditorPreferencesPage_ViewportMovement::InitializeSettings() @@ -153,4 +286,18 @@ void CEditorPreferencesPage_ViewportMovement::InitializeSettings() m_cameraMovementSettings.m_orbitYawRotationInverted = SandboxEditor::CameraOrbitYawRotationInverted(); m_cameraMovementSettings.m_panInvertedX = SandboxEditor::CameraPanInvertedX(); m_cameraMovementSettings.m_panInvertedY = SandboxEditor::CameraPanInvertedY(); + + m_cameraInputSettings.m_translateForwardChannelId = SandboxEditor::CameraTranslateForwardChannelId().GetName(); + m_cameraInputSettings.m_translateBackwardChannelId = SandboxEditor::CameraTranslateBackwardChannelId().GetName(); + m_cameraInputSettings.m_translateLeftChannelId = SandboxEditor::CameraTranslateLeftChannelId().GetName(); + m_cameraInputSettings.m_translateRightChannelId = SandboxEditor::CameraTranslateRightChannelId().GetName(); + m_cameraInputSettings.m_translateUpChannelId = SandboxEditor::CameraTranslateUpChannelId().GetName(); + m_cameraInputSettings.m_translateDownChannelId = SandboxEditor::CameraTranslateDownChannelId().GetName(); + m_cameraInputSettings.m_boostChannelId = SandboxEditor::CameraTranslateBoostChannelId().GetName(); + m_cameraInputSettings.m_orbitChannelId = SandboxEditor::CameraOrbitChannelId().GetName(); + m_cameraInputSettings.m_freeLookChannelId = SandboxEditor::CameraFreeLookChannelId().GetName(); + m_cameraInputSettings.m_freePanChannelId = SandboxEditor::CameraFreePanChannelId().GetName(); + m_cameraInputSettings.m_orbitLookChannelId = SandboxEditor::CameraOrbitLookChannelId().GetName(); + m_cameraInputSettings.m_orbitDollyChannelId = SandboxEditor::CameraOrbitDollyChannelId().GetName(); + m_cameraInputSettings.m_orbitPanChannelId = SandboxEditor::CameraOrbitPanChannelId().GetName(); } diff --git a/Code/Editor/EditorPreferencesPageViewportMovement.h b/Code/Editor/EditorPreferencesPageViewportMovement.h index a973c34f1a..b7482fb048 100644 --- a/Code/Editor/EditorPreferencesPageViewportMovement.h +++ b/Code/Editor/EditorPreferencesPageViewportMovement.h @@ -79,6 +79,27 @@ private: } }; + struct CameraInputSettings + { + AZ_TYPE_INFO(struct CameraInputSettings, "{A250FAD4-662E-4896-B030-D4ED03679377}") + + AZStd::string m_translateForwardChannelId; + AZStd::string m_translateBackwardChannelId; + AZStd::string m_translateLeftChannelId; + AZStd::string m_translateRightChannelId; + AZStd::string m_translateUpChannelId; + AZStd::string m_translateDownChannelId; + AZStd::string m_boostChannelId; + AZStd::string m_orbitChannelId; + AZStd::string m_freeLookChannelId; + AZStd::string m_freePanChannelId; + AZStd::string m_orbitLookChannelId; + AZStd::string m_orbitDollyChannelId; + AZStd::string m_orbitPanChannelId; + }; + CameraMovementSettings m_cameraMovementSettings; + CameraInputSettings m_cameraInputSettings; + QIcon m_icon; }; diff --git a/Code/Editor/EditorViewportSettings.cpp b/Code/Editor/EditorViewportSettings.cpp index 38831a1de4..872454412d 100644 --- a/Code/Editor/EditorViewportSettings.cpp +++ b/Code/Editor/EditorViewportSettings.cpp @@ -63,7 +63,11 @@ namespace SandboxEditor AZStd::remove_cvref_t value = AZStd::forward(defaultValue); if (const auto* registry = AZ::SettingsRegistry::Get()) { - registry->Get(value, setting); + T potentialValue; + if (registry->Get(potentialValue, setting)) + { + value = AZStd::move(potentialValue); + } } return value; @@ -363,7 +367,7 @@ namespace SandboxEditor void SetCameraTranslateBoostChannelId(AZStd::string_view cameraTranslateBoostId) { - SetRegistry(CameraTranslateDownIdSetting, cameraTranslateBoostId); + SetRegistry(CameraTranslateBoostIdSetting, cameraTranslateBoostId); } AzFramework::InputChannelId CameraOrbitChannelId() @@ -371,7 +375,7 @@ namespace SandboxEditor return AzFramework::InputChannelId(GetRegistry(CameraOrbitIdSetting, AZStd::string("keyboard_key_modifier_alt_l")).c_str()); } - void SetCameraOrbitChannelChannelId(AZStd::string_view cameraOrbitId) + void SetCameraOrbitChannelId(AZStd::string_view cameraOrbitId) { SetRegistry(CameraOrbitIdSetting, cameraOrbitId); } diff --git a/Code/Editor/EditorViewportSettings.h b/Code/Editor/EditorViewportSettings.h index 83004d52af..3da8c465fb 100644 --- a/Code/Editor/EditorViewportSettings.h +++ b/Code/Editor/EditorViewportSettings.h @@ -111,7 +111,7 @@ namespace SandboxEditor SANDBOX_API void SetCameraTranslateBoostChannelId(AZStd::string_view cameraTranslateBoostId); SANDBOX_API AzFramework::InputChannelId CameraOrbitChannelId(); - SANDBOX_API void SetCameraOrbitChannelChannelId(AZStd::string_view cameraOrbitId); + SANDBOX_API void SetCameraOrbitChannelId(AZStd::string_view cameraOrbitId); SANDBOX_API AzFramework::InputChannelId CameraFreeLookChannelId(); SANDBOX_API void SetCameraFreeLookChannelId(AZStd::string_view cameraFreeLookId); diff --git a/Code/Editor/EditorViewportWidget.cpp b/Code/Editor/EditorViewportWidget.cpp index c6750550e8..44ac159c87 100644 --- a/Code/Editor/EditorViewportWidget.cpp +++ b/Code/Editor/EditorViewportWidget.cpp @@ -50,7 +50,6 @@ // AtomToolsFramework #include -#include // CryCommon #include @@ -1030,220 +1029,6 @@ bool EditorViewportWidget::ShowingWorldSpace() return BuildKeyboardModifiers(QGuiApplication::queryKeyboardModifiers()).Shift(); } -AZStd::shared_ptr CreateModularViewportCameraController( - const AzFramework::ViewportId viewportId) -{ - auto controller = AZStd::make_shared(); - - controller->SetCameraViewportContextBuilderCallback( - [viewportId](AZStd::unique_ptr& cameraViewportContext) - { - cameraViewportContext = AZStd::make_unique(viewportId); - }); - - controller->SetCameraPriorityBuilderCallback( - [](AtomToolsFramework::CameraControllerPriorityFn& cameraControllerPriorityFn) - { - cameraControllerPriorityFn = AtomToolsFramework::DefaultCameraControllerPriority; - }); - - controller->SetCameraPropsBuilderCallback( - [](AzFramework::CameraProps& cameraProps) - { - cameraProps.m_rotateSmoothnessFn = [] - { - return SandboxEditor::CameraRotateSmoothness(); - }; - - cameraProps.m_translateSmoothnessFn = [] - { - return SandboxEditor::CameraTranslateSmoothness(); - }; - - cameraProps.m_rotateSmoothingEnabledFn = [] - { - return SandboxEditor::CameraRotateSmoothingEnabled(); - }; - - cameraProps.m_translateSmoothingEnabledFn = [] - { - return SandboxEditor::CameraTranslateSmoothingEnabled(); - }; - }); - - controller->SetCameraListBuilderCallback( - [viewportId](AzFramework::Cameras& cameras) - { - const auto hideCursor = [viewportId] - { - if (SandboxEditor::CameraCaptureCursorForLook()) - { - AzToolsFramework::ViewportInteraction::ViewportMouseCursorRequestBus::Event( - viewportId, &AzToolsFramework::ViewportInteraction::ViewportMouseCursorRequestBus::Events::BeginCursorCapture); - } - }; - const auto showCursor = [viewportId] - { - if (SandboxEditor::CameraCaptureCursorForLook()) - { - AzToolsFramework::ViewportInteraction::ViewportMouseCursorRequestBus::Event( - viewportId, &AzToolsFramework::ViewportInteraction::ViewportMouseCursorRequestBus::Events::EndCursorCapture); - } - }; - - auto firstPersonRotateCamera = AZStd::make_shared(SandboxEditor::CameraFreeLookChannelId()); - firstPersonRotateCamera->m_rotateSpeedFn = [] - { - return SandboxEditor::CameraRotateSpeed(); - }; - - // default behavior is to hide the cursor but this can be disabled (useful for remote desktop) - // note: See CaptureCursorLook in the Settings Registry - firstPersonRotateCamera->SetActivationBeganFn(hideCursor); - firstPersonRotateCamera->SetActivationEndedFn(showCursor); - - auto firstPersonPanCamera = - AZStd::make_shared(SandboxEditor::CameraFreePanChannelId(), AzFramework::LookPan); - firstPersonPanCamera->m_panSpeedFn = [] - { - return SandboxEditor::CameraPanSpeed(); - }; - firstPersonPanCamera->m_invertPanXFn = [] - { - return SandboxEditor::CameraPanInvertedX(); - }; - firstPersonPanCamera->m_invertPanYFn = [] - { - return SandboxEditor::CameraPanInvertedY(); - }; - - AzFramework::TranslateCameraInputChannels translateCameraInputChannels; - translateCameraInputChannels.m_leftChannelId = SandboxEditor::CameraTranslateLeftChannelId(); - translateCameraInputChannels.m_rightChannelId = SandboxEditor::CameraTranslateRightChannelId(); - translateCameraInputChannels.m_forwardChannelId = SandboxEditor::CameraTranslateForwardChannelId(); - translateCameraInputChannels.m_backwardChannelId = SandboxEditor::CameraTranslateBackwardChannelId(); - translateCameraInputChannels.m_upChannelId = SandboxEditor::CameraTranslateUpChannelId(); - translateCameraInputChannels.m_downChannelId = SandboxEditor::CameraTranslateDownChannelId(); - translateCameraInputChannels.m_boostChannelId = SandboxEditor::CameraTranslateBoostChannelId(); - - auto firstPersonTranslateCamera = - AZStd::make_shared(AzFramework::LookTranslation, translateCameraInputChannels); - firstPersonTranslateCamera->m_translateSpeedFn = [] - { - return SandboxEditor::CameraTranslateSpeed(); - }; - firstPersonTranslateCamera->m_boostMultiplierFn = [] - { - return SandboxEditor::CameraBoostMultiplier(); - }; - - auto firstPersonWheelCamera = AZStd::make_shared(); - firstPersonWheelCamera->m_scrollSpeedFn = [] - { - return SandboxEditor::CameraScrollSpeed(); - }; - - auto orbitCamera = AZStd::make_shared(SandboxEditor::CameraOrbitChannelId()); - orbitCamera->SetLookAtFn( - [viewportId](const AZ::Vector3& position, const AZ::Vector3& direction) -> AZStd::optional - { - AZStd::optional lookAtAfterInterpolation; - AtomToolsFramework::ModularViewportCameraControllerRequestBus::EventResult( - lookAtAfterInterpolation, viewportId, - &AtomToolsFramework::ModularViewportCameraControllerRequestBus::Events::LookAtAfterInterpolation); - - // initially attempt to use the last set look at point after an interpolation has finished - if (lookAtAfterInterpolation.has_value()) - { - return *lookAtAfterInterpolation; - } - - const float RayDistance = 1000.0f; - AzFramework::RenderGeometry::RayRequest ray; - ray.m_startWorldPosition = position; - ray.m_endWorldPosition = position + direction * RayDistance; - ray.m_onlyVisible = true; - - AzFramework::RenderGeometry::RayResult renderGeometryIntersectionResult; - AzFramework::RenderGeometry::IntersectorBus::EventResult( - renderGeometryIntersectionResult, AzToolsFramework::GetEntityContextId(), - &AzFramework::RenderGeometry::IntersectorBus::Events::RayIntersect, ray); - - // attempt a ray intersection with any visible mesh and return the intersection position if successful - if (renderGeometryIntersectionResult) - { - return renderGeometryIntersectionResult.m_worldPosition; - } - - // if there is no selection or no intersection, fallback to default camera orbit behavior (ground plane - // intersection) - return {}; - }); - - auto orbitRotateCamera = AZStd::make_shared(SandboxEditor::CameraOrbitLookChannelId()); - orbitRotateCamera->m_rotateSpeedFn = [] - { - return SandboxEditor::CameraRotateSpeed(); - }; - orbitRotateCamera->m_invertYawFn = [] - { - return SandboxEditor::CameraOrbitYawRotationInverted(); - }; - - auto orbitTranslateCamera = - AZStd::make_shared(AzFramework::OrbitTranslation, translateCameraInputChannels); - orbitTranslateCamera->m_translateSpeedFn = [] - { - return SandboxEditor::CameraTranslateSpeed(); - }; - orbitTranslateCamera->m_boostMultiplierFn = [] - { - return SandboxEditor::CameraBoostMultiplier(); - }; - - auto orbitDollyWheelCamera = AZStd::make_shared(); - orbitDollyWheelCamera->m_scrollSpeedFn = [] - { - return SandboxEditor::CameraScrollSpeed(); - }; - - auto orbitDollyMoveCamera = - AZStd::make_shared(SandboxEditor::CameraOrbitDollyChannelId()); - orbitDollyMoveCamera->m_cursorSpeedFn = [] - { - return SandboxEditor::CameraDollyMotionSpeed(); - }; - - auto orbitPanCamera = AZStd::make_shared(SandboxEditor::CameraOrbitPanChannelId(), AzFramework::OrbitPan); - orbitPanCamera->m_panSpeedFn = [] - { - return SandboxEditor::CameraPanSpeed(); - }; - orbitPanCamera->m_invertPanXFn = [] - { - return SandboxEditor::CameraPanInvertedX(); - }; - orbitPanCamera->m_invertPanYFn = [] - { - return SandboxEditor::CameraPanInvertedY(); - }; - - orbitCamera->m_orbitCameras.AddCamera(orbitRotateCamera); - orbitCamera->m_orbitCameras.AddCamera(orbitTranslateCamera); - orbitCamera->m_orbitCameras.AddCamera(orbitDollyWheelCamera); - orbitCamera->m_orbitCameras.AddCamera(orbitDollyMoveCamera); - orbitCamera->m_orbitCameras.AddCamera(orbitPanCamera); - - cameras.AddCamera(firstPersonRotateCamera); - cameras.AddCamera(firstPersonPanCamera); - cameras.AddCamera(firstPersonTranslateCamera); - cameras.AddCamera(firstPersonWheelCamera); - cameras.AddCamera(orbitCamera); - }); - - return controller; -} - void EditorViewportWidget::SetViewportId(int id) { CViewport::SetViewportId(id); @@ -1288,7 +1073,8 @@ void EditorViewportWidget::SetViewportId(int id) m_renderViewport->GetControllerList()->Add(AZStd::make_shared()); - m_renderViewport->GetControllerList()->Add(CreateModularViewportCameraController(AzFramework::ViewportId(id))); + m_editorModularViewportCameraComposer = AZStd::make_unique(AzFramework::ViewportId(id)); + m_renderViewport->GetControllerList()->Add(m_editorModularViewportCameraComposer->CreateModularViewportCameraController()); m_renderViewport->SetViewportSettings(&g_EditorViewportSettings); diff --git a/Code/Editor/EditorViewportWidget.h b/Code/Editor/EditorViewportWidget.h index d4bb14ad3b..9da5e3f9a1 100644 --- a/Code/Editor/EditorViewportWidget.h +++ b/Code/Editor/EditorViewportWidget.h @@ -19,6 +19,7 @@ #include "Undo/Undo.h" #include "Util/PredefinedAspectRatios.h" #include "EditorViewportSettings.h" +#include "EditorModularViewportCameraComposer.h" #include #include @@ -369,6 +370,8 @@ private: // This widget holds a reference to the manipulator manage because its responsible for drawing manipulators AZStd::shared_ptr m_manipulatorManager; + AZStd::unique_ptr m_editorModularViewportCameraComposer; + // Helper for getting EditorEntityNotificationBus events AZStd::unique_ptr m_editorEntityNotifications; @@ -389,7 +392,3 @@ private: AZ_POP_DISABLE_DLL_EXPORT_MEMBER_WARNING }; - -//! Creates a modular camera controller in the configuration used by the editor viewport. -SANDBOX_API AZStd::shared_ptr CreateModularViewportCameraController( - const AzFramework::ViewportId viewportId); diff --git a/Code/Editor/Lib/Tests/test_ModularViewportCameraController.cpp b/Code/Editor/Lib/Tests/test_ModularViewportCameraController.cpp index 7309110c4d..ce5564c7f6 100644 --- a/Code/Editor/Lib/Tests/test_ModularViewportCameraController.cpp +++ b/Code/Editor/Lib/Tests/test_ModularViewportCameraController.cpp @@ -139,7 +139,8 @@ namespace UnitTest m_viewportMouseCursorRequests.Connect(TestViewportId, m_inputChannelMapper.get()); // create editor modular camera - auto controller = CreateModularViewportCameraController(TestViewportId); + m_editorModularViewportCameraComposer = AZStd::make_unique(TestViewportId); + auto controller = m_editorModularViewportCameraComposer->CreateModularViewportCameraController(); // set some overrides for the test controller->SetCameraViewportContextBuilderCallback( @@ -169,6 +170,7 @@ namespace UnitTest void HaltCollaborators() { + m_editorModularViewportCameraComposer.reset(); m_mockWindowRequests.Disconnect(); m_viewportMouseCursorRequests.Disconnect(); m_cameraViewportContextView = nullptr; @@ -212,6 +214,7 @@ namespace UnitTest ViewportMouseCursorRequestImpl m_viewportMouseCursorRequests; AtomToolsFramework::ModularCameraViewportContext* m_cameraViewportContextView = nullptr; AZStd::unique_ptr m_settingsRegistry; + AZStd::unique_ptr m_editorModularViewportCameraComposer; }; const AzFramework::ViewportId ModularViewportCameraControllerFixture::TestViewportId = AzFramework::ViewportId(0); diff --git a/Code/Editor/editor_lib_files.cmake b/Code/Editor/editor_lib_files.cmake index bc8f835fc7..24634b245d 100644 --- a/Code/Editor/editor_lib_files.cmake +++ b/Code/Editor/editor_lib_files.cmake @@ -787,6 +787,9 @@ set(FILES EditorViewportSettings.h EditorViewportCamera.cpp EditorViewportCamera.h + EditorModularViewportCameraComposer.cpp + EditorModularViewportCameraComposer.h + EditorModularViewportCameraComposerBus.h ViewportManipulatorController.cpp ViewportManipulatorController.h TopRendererWnd.cpp diff --git a/Code/Framework/AzFramework/AzFramework/Viewport/CameraInput.cpp b/Code/Framework/AzFramework/AzFramework/Viewport/CameraInput.cpp index fac1e45920..89338a355f 100644 --- a/Code/Framework/AzFramework/AzFramework/Viewport/CameraInput.cpp +++ b/Code/Framework/AzFramework/AzFramework/Viewport/CameraInput.cpp @@ -332,6 +332,11 @@ namespace AzFramework return nextCamera; } + void RotateCameraInput::SetRotateInputChannelId(const InputChannelId& rotateChannelId) + { + m_rotateChannelId = rotateChannelId; + } + PanCameraInput::PanCameraInput(const InputChannelId& panChannelId, PanAxesFn panAxesFn) : m_panAxesFn(AZStd::move(panAxesFn)) , m_panChannelId(panChannelId) @@ -379,35 +384,40 @@ namespace AzFramework return nextCamera; } + void PanCameraInput::SetPanInputChannelId(const InputChannelId& panChannelId) + { + m_panChannelId = panChannelId; + } + TranslateCameraInput::TranslationType TranslateCameraInput::TranslationFromKey( - const InputChannelId& channelId, const TranslateCameraInputChannels& translateCameraInputChannels) + const InputChannelId& channelId, const TranslateCameraInputChannelIds& translateCameraInputChannelIds) { - if (channelId == translateCameraInputChannels.m_forwardChannelId) + if (channelId == translateCameraInputChannelIds.m_forwardChannelId) { return TranslationType::Forward; } - if (channelId == translateCameraInputChannels.m_backwardChannelId) + if (channelId == translateCameraInputChannelIds.m_backwardChannelId) { return TranslationType::Backward; } - if (channelId == translateCameraInputChannels.m_leftChannelId) + if (channelId == translateCameraInputChannelIds.m_leftChannelId) { return TranslationType::Left; } - if (channelId == translateCameraInputChannels.m_rightChannelId) + if (channelId == translateCameraInputChannelIds.m_rightChannelId) { return TranslationType::Right; } - if (channelId == translateCameraInputChannels.m_downChannelId) + if (channelId == translateCameraInputChannelIds.m_downChannelId) { return TranslationType::Down; } - if (channelId == translateCameraInputChannels.m_upChannelId) + if (channelId == translateCameraInputChannelIds.m_upChannelId) { return TranslationType::Up; } @@ -416,9 +426,9 @@ namespace AzFramework } TranslateCameraInput::TranslateCameraInput( - TranslationAxesFn translationAxesFn, const TranslateCameraInputChannels& translateCameraInputChannels) + TranslationAxesFn translationAxesFn, const TranslateCameraInputChannelIds& translateCameraInputChannelIds) : m_translationAxesFn(AZStd::move(translationAxesFn)) - , m_translateCameraInputChannels(translateCameraInputChannels) + , m_translateCameraInputChannelIds(translateCameraInputChannelIds) { m_translateSpeedFn = []() constexpr { @@ -438,13 +448,13 @@ namespace AzFramework { if (input->m_state == InputChannel::State::Began) { - m_translation |= TranslationFromKey(input->m_channelId, m_translateCameraInputChannels); + m_translation |= TranslationFromKey(input->m_channelId, m_translateCameraInputChannelIds); if (m_translation != TranslationType::Nil) { BeginActivation(); } - if (input->m_channelId == m_translateCameraInputChannels.m_boostChannelId) + if (input->m_channelId == m_translateCameraInputChannelIds.m_boostChannelId) { m_boost = true; } @@ -452,12 +462,12 @@ namespace AzFramework // ensure we don't process end events in the idle state else if (input->m_state == InputChannel::State::Ended && !Idle()) { - m_translation &= ~(TranslationFromKey(input->m_channelId, m_translateCameraInputChannels)); + m_translation &= ~(TranslationFromKey(input->m_channelId, m_translateCameraInputChannelIds)); if (m_translation == TranslationType::Nil) { EndActivation(); } - if (input->m_channelId == m_translateCameraInputChannels.m_boostChannelId) + if (input->m_channelId == m_translateCameraInputChannelIds.m_boostChannelId) { m_boost = false; } @@ -529,6 +539,11 @@ namespace AzFramework m_boost = false; } + void TranslateCameraInput::SetTranslateCameraInputChannelIds(const TranslateCameraInputChannelIds& translateCameraInputChannelIds) + { + m_translateCameraInputChannelIds = translateCameraInputChannelIds; + } + OrbitCameraInput::OrbitCameraInput(const InputChannelId& orbitChannelId) : m_orbitChannelId(orbitChannelId) { @@ -620,6 +635,11 @@ namespace AzFramework return nextCamera; } + void OrbitCameraInput::SetOrbitInputChannelId(const InputChannelId& orbitChanneId) + { + m_orbitChannelId = orbitChanneId; + } + OrbitDollyScrollCameraInput::OrbitDollyScrollCameraInput() { m_scrollSpeedFn = []() constexpr @@ -678,6 +698,11 @@ namespace AzFramework return nextCamera; } + void OrbitDollyCursorMoveCameraInput::SetDollyInputChannelId(const InputChannelId& dollyChannelId) + { + m_dollyChannelId = dollyChannelId; + } + ScrollTranslationCameraInput::ScrollTranslationCameraInput() { m_scrollSpeedFn = []() constexpr diff --git a/Code/Framework/AzFramework/AzFramework/Viewport/CameraInput.h b/Code/Framework/AzFramework/AzFramework/Viewport/CameraInput.h index ec383fa8ef..69e8b66434 100644 --- a/Code/Framework/AzFramework/AzFramework/Viewport/CameraInput.h +++ b/Code/Framework/AzFramework/AzFramework/Viewport/CameraInput.h @@ -303,6 +303,8 @@ namespace AzFramework bool HandleEvents(const InputEvent& event, const ScreenVector& cursorDelta, float scrollDelta) override; Camera StepCamera(const Camera& targetCamera, const ScreenVector& cursorDelta, float scrollDelta, float deltaTime) override; + void SetRotateInputChannelId(const InputChannelId& rotateChannelId); + AZStd::function m_rotateSpeedFn; AZStd::function m_invertPitchFn; AZStd::function m_invertYawFn; @@ -355,6 +357,8 @@ namespace AzFramework bool HandleEvents(const InputEvent& event, const ScreenVector& cursorDelta, float scrollDelta) override; Camera StepCamera(const Camera& targetCamera, const ScreenVector& cursorDelta, float scrollDelta, float deltaTime) override; + void SetPanInputChannelId(const InputChannelId& panChannelId); + AZStd::function m_panSpeedFn; AZStd::function m_invertPanXFn; AZStd::function m_invertPanYFn; @@ -398,7 +402,7 @@ namespace AzFramework } //! Groups all camera translation inputs. - struct TranslateCameraInputChannels + struct TranslateCameraInputChannelIds { InputChannelId m_forwardChannelId; InputChannelId m_backwardChannelId; @@ -414,13 +418,15 @@ namespace AzFramework { public: explicit TranslateCameraInput( - TranslationAxesFn translationAxesFn, const TranslateCameraInputChannels& translateCameraInputChannels); + TranslationAxesFn translationAxesFn, const TranslateCameraInputChannelIds& translateCameraInputChannelIds); // CameraInput overrides ... bool 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; + void SetTranslateCameraInputChannelIds(const TranslateCameraInputChannelIds& translateCameraInputChannelIds); + AZStd::function m_translateSpeedFn; AZStd::function m_boostMultiplierFn; @@ -482,11 +488,11 @@ namespace AzFramework //! Converts from a generic input channel id to a concrete translation type (based on the user's key mappings). TranslationType TranslationFromKey( - const InputChannelId& channelId, const TranslateCameraInputChannels& translateCameraInputChannels); + const InputChannelId& channelId, const TranslateCameraInputChannelIds& translateCameraInputChannelIds); TranslationType m_translation = TranslationType::Nil; //!< Types of translation the camera input is under. TranslationAxesFn m_translationAxesFn; //!< Builder for translation axes. - TranslateCameraInputChannels m_translateCameraInputChannels; //!< Input channel ids that map to internal translation types. + TranslateCameraInputChannelIds m_translateCameraInputChannelIds; //!< Input channel ids that map to internal translation types. bool m_boost = false; //!< Is the translation speed currently being multiplied/scaled upwards. }; @@ -513,6 +519,8 @@ namespace AzFramework bool HandleEvents(const InputEvent& event, const ScreenVector& cursorDelta, float scrollDelta) override; Camera StepCamera(const Camera& targetCamera, const ScreenVector& cursorDelta, float scrollDelta, float deltaTime) override; + void SetDollyInputChannelId(const InputChannelId& dollyChannelId); + AZStd::function m_cursorSpeedFn; private: @@ -548,6 +556,8 @@ namespace AzFramework Camera StepCamera(const Camera& targetCamera, const ScreenVector& cursorDelta, float scrollDelta, float deltaTime) override; bool Exclusive() const override; + void SetOrbitInputChannelId(const InputChannelId& orbitChanneId); + Cameras m_orbitCameras; //!< The camera inputs to run when this camera input is active (only these will run as it is exclusive). //! Override the default behavior for how a look-at point is calculated. diff --git a/Code/Framework/AzFramework/Tests/CameraInputTests.cpp b/Code/Framework/AzFramework/Tests/CameraInputTests.cpp index ef340a41a5..486cca2af0 100644 --- a/Code/Framework/AzFramework/Tests/CameraInputTests.cpp +++ b/Code/Framework/AzFramework/Tests/CameraInputTests.cpp @@ -35,23 +35,23 @@ namespace UnitTest m_cameraSystem = AZStd::make_shared(); - m_translateCameraInputChannels.m_leftChannelId = AzFramework::InputChannelId("keyboard_key_alphanumeric_A"); - m_translateCameraInputChannels.m_rightChannelId = AzFramework::InputChannelId("keyboard_key_alphanumeric_D"); - m_translateCameraInputChannels.m_forwardChannelId = AzFramework::InputChannelId("keyboard_key_alphanumeric_W"); - m_translateCameraInputChannels.m_backwardChannelId = AzFramework::InputChannelId("keyboard_key_alphanumeric_S"); - m_translateCameraInputChannels.m_upChannelId = AzFramework::InputChannelId("keyboard_key_alphanumeric_E"); - m_translateCameraInputChannels.m_downChannelId = AzFramework::InputChannelId("keyboard_key_alphanumeric_Q"); - m_translateCameraInputChannels.m_boostChannelId = AzFramework::InputChannelId("keyboard_key_modifier_shift_l"); + m_translateCameraInputChannelIds.m_leftChannelId = AzFramework::InputChannelId("keyboard_key_alphanumeric_A"); + m_translateCameraInputChannelIds.m_rightChannelId = AzFramework::InputChannelId("keyboard_key_alphanumeric_D"); + m_translateCameraInputChannelIds.m_forwardChannelId = AzFramework::InputChannelId("keyboard_key_alphanumeric_W"); + m_translateCameraInputChannelIds.m_backwardChannelId = AzFramework::InputChannelId("keyboard_key_alphanumeric_S"); + m_translateCameraInputChannelIds.m_upChannelId = AzFramework::InputChannelId("keyboard_key_alphanumeric_E"); + m_translateCameraInputChannelIds.m_downChannelId = AzFramework::InputChannelId("keyboard_key_alphanumeric_Q"); + m_translateCameraInputChannelIds.m_boostChannelId = AzFramework::InputChannelId("keyboard_key_modifier_shift_l"); m_firstPersonRotateCamera = AZStd::make_shared(AzFramework::InputDeviceMouse::Button::Right); m_firstPersonTranslateCamera = - AZStd::make_shared(AzFramework::LookTranslation, m_translateCameraInputChannels); + AZStd::make_shared(AzFramework::LookTranslation, m_translateCameraInputChannelIds); auto orbitCamera = AZStd::make_shared(AzFramework::InputChannelId("keyboard_key_modifier_alt_l")); auto orbitRotateCamera = AZStd::make_shared(AzFramework::InputDeviceMouse::Button::Left); auto orbitTranslateCamera = - AZStd::make_shared(AzFramework::OrbitTranslation, m_translateCameraInputChannels); + AZStd::make_shared(AzFramework::OrbitTranslation, m_translateCameraInputChannelIds); orbitCamera->m_orbitCameras.AddCamera(orbitRotateCamera); orbitCamera->m_orbitCameras.AddCamera(orbitTranslateCamera); @@ -77,7 +77,7 @@ namespace UnitTest AllocatorsTestFixture::TearDown(); } - AzFramework::TranslateCameraInputChannels m_translateCameraInputChannels; + AzFramework::TranslateCameraInputChannelIds m_translateCameraInputChannelIds; AZStd::shared_ptr m_firstPersonRotateCamera; AZStd::shared_ptr m_firstPersonTranslateCamera; }; @@ -112,7 +112,7 @@ namespace UnitTest }); HandleEventAndUpdate( - AzFramework::DiscreteInputEvent{ m_translateCameraInputChannels.m_forwardChannelId, AzFramework::InputChannel::State::Began }); + AzFramework::DiscreteInputEvent{ m_translateCameraInputChannelIds.m_forwardChannelId, AzFramework::InputChannel::State::Began }); EXPECT_TRUE(activationBegan); } @@ -208,9 +208,9 @@ namespace UnitTest }); HandleEventAndUpdate( - AzFramework::DiscreteInputEvent{ m_translateCameraInputChannels.m_forwardChannelId, AzFramework::InputChannel::State::Began }); + AzFramework::DiscreteInputEvent{ m_translateCameraInputChannelIds.m_forwardChannelId, AzFramework::InputChannel::State::Began }); HandleEventAndUpdate( - AzFramework::DiscreteInputEvent{ m_translateCameraInputChannels.m_forwardChannelId, AzFramework::InputChannel::State::Ended }); + AzFramework::DiscreteInputEvent{ m_translateCameraInputChannelIds.m_forwardChannelId, AzFramework::InputChannel::State::Ended }); EXPECT_TRUE(activationBegan); EXPECT_TRUE(activationEnded); @@ -226,7 +226,7 @@ namespace UnitTest }); HandleEventAndUpdate( - AzFramework::DiscreteInputEvent{ m_translateCameraInputChannels.m_forwardChannelId, AzFramework::InputChannel::State::Began }); + AzFramework::DiscreteInputEvent{ m_translateCameraInputChannelIds.m_forwardChannelId, AzFramework::InputChannel::State::Began }); m_cameraSystem->m_cameras.Clear();