Merge pull request #7618 from aws-lumberyard-dev/Atom/guthadam/move_viewport_input_controller_from_material_editor_to_atf

Atom Tools: Extracted the viewport input controller from ME to ATF
This commit is contained in:
Guthrie Adams
2022-02-14 10:27:20 -06:00
committed by GitHub
25 changed files with 456 additions and 525 deletions
@@ -0,0 +1,40 @@
/*
* 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 <AtomToolsFramework/Viewport/ViewportInputBehaviorController/DollyCameraBehavior.h>
#include <AtomToolsFramework/Viewport/ViewportInputBehaviorController/ViewportInputBehaviorControllerInterface.h>
#include <AzCore/Component/TransformBus.h>
#include <AzCore/Math/MathUtils.h>
#include <AzCore/Math/Vector3.h>
namespace AtomToolsFramework
{
DollyCameraBehavior::DollyCameraBehavior(ViewportInputBehaviorControllerInterface* controller)
: ViewportInputBehavior(controller)
{
}
void DollyCameraBehavior::TickInternal([[maybe_unused]] float x, float y, [[maybe_unused]] float z)
{
m_distanceToTarget = m_distanceToTarget + y;
AZ::Transform transform = AZ::Transform::CreateIdentity();
AZ::TransformBus::EventResult(transform, m_cameraEntityId, &AZ::TransformBus::Events::GetLocalTM);
AZ::Vector3 position = m_targetPosition - transform.GetRotation().TransformVector(AZ::Vector3::CreateAxisY(m_distanceToTarget));
AZ::TransformBus::Event(m_cameraEntityId, &AZ::TransformBus::Events::SetLocalTranslation, position);
}
float DollyCameraBehavior::GetSensitivityX()
{
return SensitivityX;
}
float DollyCameraBehavior::GetSensitivityY()
{
return SensitivityY;
}
} // namespace AtomToolsFramework
@@ -0,0 +1,54 @@
/*
* 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 <AtomToolsFramework/Viewport/ViewportInputBehaviorController/MoveCameraBehavior.h>
#include <AtomToolsFramework/Viewport/ViewportInputBehaviorController/ViewportInputBehaviorControllerInterface.h>
#include <AzCore/Component/TransformBus.h>
#include <AzCore/Math/Vector3.h>
namespace AtomToolsFramework
{
MoveCameraBehavior::MoveCameraBehavior(ViewportInputBehaviorControllerInterface* controller)
: ViewportInputBehavior(controller)
{
}
void MoveCameraBehavior::End()
{
float distanceToTarget = m_controller->GetDistanceToTarget();
AZ::Transform transform = AZ::Transform::CreateIdentity();
AZ::TransformBus::EventResult(transform, m_cameraEntityId, &AZ::TransformBus::Events::GetLocalTM);
AZ::Vector3 targetPosition = transform.GetTranslation() + transform.GetBasisY() * distanceToTarget;
m_controller->SetTargetPosition(targetPosition);
}
void MoveCameraBehavior::TickInternal(float x, float y, float z)
{
AZ::Transform transform = AZ::Transform::CreateIdentity();
AZ::TransformBus::EventResult(transform, m_cameraEntityId, &AZ::TransformBus::Events::GetLocalTM);
AZ::Vector3 up = transform.GetBasisZ();
AZ::Vector3 right = transform.GetBasisX();
AZ::Vector3 position = transform.GetTranslation();
AZ::Vector3 deltaPosition = up * y + right * -x;
position += deltaPosition;
m_targetPosition += deltaPosition;
AZ::TransformBus::Event(m_cameraEntityId, &AZ::TransformBus::Events::SetLocalTranslation, position);
ViewportInputBehavior::TickInternal(x, y, z);
}
float MoveCameraBehavior::GetSensitivityX()
{
return SensitivityX;
}
float MoveCameraBehavior::GetSensitivityY()
{
return SensitivityY;
}
} // namespace AtomToolsFramework
@@ -0,0 +1,61 @@
/*
* 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 <AtomToolsFramework/Viewport/ViewportInputBehaviorController/OrbitCameraBehavior.h>
#include <AtomToolsFramework/Viewport/ViewportInputBehaviorController/ViewportInputBehaviorControllerInterface.h>
#include <AzCore/Component/TransformBus.h>
namespace AtomToolsFramework
{
OrbitCameraBehavior::OrbitCameraBehavior(ViewportInputBehaviorControllerInterface* controller)
: ViewportInputBehavior(controller)
{
}
void OrbitCameraBehavior::TickInternal(float x, float y, float z)
{
ViewportInputBehavior::TickInternal(x, y, z);
// don't align camera until a movement has been made so that accidental right-click doesn't reset camera
if (!m_aligned)
{
Align();
}
AZ::Transform transform = AZ::Transform::CreateIdentity();
AZ::TransformBus::EventResult(transform, m_cameraEntityId, &AZ::TransformBus::Events::GetLocalTM);
AZ::Quaternion rotation = transform.GetRotation();
AZ::Vector3 right = transform.GetBasisX();
rotation =
AZ::Quaternion::CreateFromAxisAngle(AZ::Vector3::CreateAxisZ(), -x) * AZ::Quaternion::CreateFromAxisAngle(right, -y) * rotation;
rotation.Normalize();
AZ::Vector3 position = rotation.TransformVector(AZ::Vector3(0, -m_distanceToTarget, 0)) + m_targetPosition;
transform = AZ::Transform::CreateFromQuaternionAndTranslation(rotation, position);
AZ::TransformBus::Event(m_cameraEntityId, &AZ::TransformBus::Events::SetLocalTM, transform);
}
float OrbitCameraBehavior::GetSensitivityX()
{
return SensitivityX;
}
float OrbitCameraBehavior::GetSensitivityY()
{
return SensitivityY;
}
void OrbitCameraBehavior::Align()
{
AZ::Vector3 cameraPosition = AZ::Vector3::CreateZero();
AZ::TransformBus::EventResult(cameraPosition, m_cameraEntityId, &AZ::TransformBus::Events::GetLocalTranslation);
const AZ::Vector3 delta = m_targetPosition - cameraPosition;
AZ::Quaternion targetRotation = LookRotation(delta);
AZ::TransformBus::Event(m_cameraEntityId, &AZ::TransformBus::Events::SetLocalRotationQuaternion, targetRotation);
m_aligned = true;
}
} // namespace AtomToolsFramework
@@ -0,0 +1,52 @@
/*
* 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 <AtomToolsFramework/Viewport/ViewportInputBehaviorController/PanCameraBehavior.h>
#include <AtomToolsFramework/Viewport/ViewportInputBehaviorController/ViewportInputBehaviorControllerInterface.h>
#include <AzCore/Component/TransformBus.h>
#include <AzCore/Math/Quaternion.h>
#include <AzCore/Math/Vector3.h>
namespace AtomToolsFramework
{
PanCameraBehavior::PanCameraBehavior(ViewportInputBehaviorControllerInterface* controller)
: ViewportInputBehavior(controller)
{
}
void PanCameraBehavior::End()
{
float distanceToTarget = m_controller->GetDistanceToTarget();
AZ::Transform transform = AZ::Transform::CreateIdentity();
AZ::TransformBus::EventResult(transform, m_cameraEntityId, &AZ::TransformBus::Events::GetLocalTM);
AZ::Vector3 targetPosition = transform.GetTranslation() + transform.GetBasisY() * distanceToTarget;
m_controller->SetTargetPosition(targetPosition);
}
void PanCameraBehavior::TickInternal(float x, float y, [[maybe_unused]] float z)
{
AZ::Transform transform = AZ::Transform::CreateIdentity();
AZ::TransformBus::EventResult(transform, m_cameraEntityId, &AZ::TransformBus::Events::GetLocalTM);
AZ::Quaternion rotation = transform.GetRotation();
const AZ::Vector3 right = transform.GetBasisX();
rotation =
AZ::Quaternion::CreateFromAxisAngle(AZ::Vector3::CreateAxisZ(), -x) * AZ::Quaternion::CreateFromAxisAngle(right, -y) * rotation;
rotation.Normalize();
AZ::TransformBus::Event(m_cameraEntityId, &AZ::TransformBus::Events::SetLocalRotationQuaternion, rotation);
}
float PanCameraBehavior::GetSensitivityX()
{
return SensitivityX;
}
float PanCameraBehavior::GetSensitivityY()
{
return SensitivityY;
}
} // namespace AtomToolsFramework
@@ -0,0 +1,53 @@
/*
* 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 <Atom/Feature/SkyBox/SkyBoxFeatureProcessorInterface.h>
#include <Atom/RPI.Public/RPISystemInterface.h>
#include <Atom/RPI.Public/Scene.h>
#include <AtomToolsFramework/Viewport/ViewportInputBehaviorController/RotateEnvironmentBehavior.h>
#include <AtomToolsFramework/Viewport/ViewportInputBehaviorController/ViewportInputBehaviorControllerInterface.h>
#include <AzCore/Component/TransformBus.h>
namespace AtomToolsFramework
{
RotateEnvironmentBehavior::RotateEnvironmentBehavior(ViewportInputBehaviorControllerInterface* controller)
: ViewportInputBehavior(controller)
{
}
void RotateEnvironmentBehavior::Start()
{
ViewportInputBehavior::Start();
m_environmentEntityId = m_controller->GetEnvironmentEntityId();
AZ_Assert(m_environmentEntityId.IsValid(), "Failed to find m_environmentEntityId");
m_skyBoxFeatureProcessor =
AZ::RPI::Scene::GetFeatureProcessorForEntity<AZ::Render::SkyBoxFeatureProcessorInterface>(m_environmentEntityId);
}
void RotateEnvironmentBehavior::TickInternal(float x, float y, float z)
{
ViewportInputBehavior::TickInternal(x, y, z);
m_rotation += x;
AZ::Quaternion rotation = AZ::Quaternion::CreateFromAxisAngle(AZ::Vector3::CreateAxisZ(), m_rotation);
AZ::TransformBus::Event(m_environmentEntityId, &AZ::TransformBus::Events::SetLocalRotationQuaternion, rotation);
const AZ::Matrix4x4 rotationMatrix = AZ::Matrix4x4::CreateFromQuaternion(rotation);
m_skyBoxFeatureProcessor->SetCubemapRotationMatrix(rotationMatrix);
}
float RotateEnvironmentBehavior::GetSensitivityX()
{
return SensitivityX;
}
float RotateEnvironmentBehavior::GetSensitivityY()
{
return SensitivityY;
}
} // namespace AtomToolsFramework
@@ -0,0 +1,59 @@
/*
* 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 <AtomToolsFramework/Viewport/ViewportInputBehaviorController/RotateModelBehavior.h>
#include <AtomToolsFramework/Viewport/ViewportInputBehaviorController/ViewportInputBehaviorControllerInterface.h>
#include <AzCore/Component/TransformBus.h>
namespace AtomToolsFramework
{
RotateModelBehavior::RotateModelBehavior(ViewportInputBehaviorControllerInterface* controller)
: ViewportInputBehavior(controller)
{
}
void RotateModelBehavior::Start()
{
ViewportInputBehavior::Start();
m_targetEntityId = m_controller->GetTargetEntityId();
AZ_Assert(m_targetEntityId.IsValid(), "Failed to find m_targetEntityId");
AZ::EntityId cameraEntityId = m_controller->GetCameraEntityId();
AZ_Assert(cameraEntityId.IsValid(), "Failed to find cameraEntityId");
AZ::Transform transform = AZ::Transform::CreateIdentity();
AZ::TransformBus::EventResult(transform, cameraEntityId, &AZ::TransformBus::Events::GetLocalTM);
m_cameraRight = transform.GetBasisX();
}
void RotateModelBehavior::TickInternal(float x, float y, float z)
{
ViewportInputBehavior::TickInternal(x, y, z);
AZ::Transform transform = AZ::Transform::CreateIdentity();
AZ::TransformBus::EventResult(transform, m_targetEntityId, &AZ::TransformBus::Events::GetLocalTM);
AZ::Quaternion rotation = transform.GetRotation();
rotation = AZ::Quaternion::CreateFromAxisAngle(AZ::Vector3::CreateAxisZ(), x) *
AZ::Quaternion::CreateFromAxisAngle(m_cameraRight, y) * rotation;
rotation.Normalize();
AZ::TransformBus::Event(m_targetEntityId, &AZ::TransformBus::Events::SetLocalRotationQuaternion, rotation);
}
float RotateModelBehavior::GetSensitivityX()
{
return SensitivityX;
}
float RotateModelBehavior::GetSensitivityY()
{
return SensitivityY;
}
} // namespace AtomToolsFramework
@@ -0,0 +1,150 @@
/*
* 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 <AtomToolsFramework/Viewport/ViewportInputBehaviorController/ViewportInputBehavior.h>
#include <AtomToolsFramework/Viewport/ViewportInputBehaviorController/ViewportInputBehaviorControllerInterface.h>
#include <AzCore/Component/TransformBus.h>
#include <AzCore/Math/Vector3.h>
namespace AtomToolsFramework
{
ViewportInputBehavior::ViewportInputBehavior(ViewportInputBehaviorControllerInterface* controller)
: m_controller(controller)
{
AZ::TickBus::Handler::BusConnect();
}
ViewportInputBehavior::~ViewportInputBehavior()
{
AZ::TickBus::Handler::BusDisconnect();
}
void ViewportInputBehavior::Start()
{
m_x = {};
m_y = {};
m_z = {};
m_cameraEntityId = m_controller->GetCameraEntityId();
AZ_Assert(m_cameraEntityId.IsValid(), "Failed to find m_cameraEntityId");
m_distanceToTarget = m_controller->GetDistanceToTarget();
m_targetPosition = m_controller->GetTargetPosition();
m_radius = m_controller->GetRadius();
}
void ViewportInputBehavior::End()
{
}
void ViewportInputBehavior::MoveX(float value)
{
m_x += value * GetSensitivityX();
}
void ViewportInputBehavior::MoveY(float value)
{
m_y += value * GetSensitivityY();
}
void ViewportInputBehavior::MoveZ(float value)
{
m_z += value * GetSensitivityZ();
}
bool ViewportInputBehavior::HasDelta() const
{
return AZ::GetAbs(m_x) > std::numeric_limits<float>::min() || AZ::GetAbs(m_y) > std::numeric_limits<float>::min() ||
AZ::GetAbs(m_z) > std::numeric_limits<float>::min();
}
void ViewportInputBehavior::TickInternal([[maybe_unused]] float x, [[maybe_unused]] float y, float z)
{
m_distanceToTarget = m_distanceToTarget - z;
bool isCameraCentered = m_controller->IsCameraCentered();
// if camera is looking at the model (locked to the model) we don't want to zoom past the model's center
if (isCameraCentered)
{
m_distanceToTarget = AZ::GetMax(m_distanceToTarget, 0.0f);
}
AZ::Transform transform = AZ::Transform::CreateIdentity();
AZ::TransformBus::EventResult(transform, m_cameraEntityId, &AZ::TransformBus::Events::GetLocalTM);
AZ::Vector3 position = m_targetPosition - transform.GetRotation().TransformVector(AZ::Vector3::CreateAxisY(m_distanceToTarget));
AZ::TransformBus::Event(m_cameraEntityId, &AZ::TransformBus::Events::SetLocalTranslation, position);
// if camera is not locked to the model, move its focal point so we can free look
if (!isCameraCentered)
{
m_targetPosition += transform.GetRotation().TransformVector(AZ::Vector3::CreateAxisY(z));
m_controller->SetTargetPosition(m_targetPosition);
m_distanceToTarget = m_controller->GetDistanceToTarget();
}
}
float ViewportInputBehavior::GetSensitivityX()
{
return 0;
}
float ViewportInputBehavior::GetSensitivityY()
{
return 0;
}
float ViewportInputBehavior::GetSensitivityZ()
{
// adjust zooming sensitivity by model size, so that large models zoom at the same speed as smaller ones
return 0.001f * AZ::GetMax(0.5f, m_radius);
}
AZ::Quaternion ViewportInputBehavior::LookRotation(AZ::Vector3 forward)
{
forward.Normalize();
AZ::Vector3 right = forward.CrossZAxis();
right.Normalize();
AZ::Vector3 up = right.Cross(forward);
up.Normalize();
AZ::Quaternion rotation = AZ::Quaternion::CreateFromBasis(right, forward, up);
rotation.Normalize();
return rotation;
}
float ViewportInputBehavior::TakeStep(float& value, float t)
{
const float absValue = AZ::GetAbs(value);
float step;
if (absValue < SnapInterval)
{
step = value;
}
else
{
step = AZ::Lerp(0, value, t);
}
value -= step;
return step;
}
void ViewportInputBehavior::OnTick(float deltaTime, [[maybe_unused]] AZ::ScriptTimePoint time)
{
// delta x and y values are accumulated in MoveX and MoveY functions (by dragging the mouse)
// in the Tick function we then lerp them down to 0 over short time and apply delta transform to an entity
if (HasDelta())
{
// t is a lerp amount based on time between frames (deltaTime)
// GetMin restricts how much we can lerp in case of low fps (and very high deltaTime)
const float t = AZ::GetMin(deltaTime / LerpTime, 0.5f);
const float x = TakeStep(m_x, t);
const float y = TakeStep(m_y, t);
const float z = TakeStep(m_z, t);
TickInternal(x, y, z);
}
}
} // namespace AtomToolsFramework
@@ -0,0 +1,300 @@
/*
* 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 <Atom/Feature/SkyBox/SkyBoxFeatureProcessorInterface.h>
#include <Atom/RPI.Public/RPISystemInterface.h>
#include <Atom/RPI.Public/Scene.h>
#include <Atom/RPI.Reflect/Model/ModelAsset.h>
#include <AtomToolsFramework/Viewport/ViewportInputBehaviorController/ViewportInputBehaviorController.h>
#include <AzCore/Component/TransformBus.h>
#include <AzCore/Math/Matrix4x4.h>
#include <AzCore/Serialization/SerializeContext.h>
#include <AzFramework/Components/CameraBus.h>
#include <AzFramework/Input/Devices/Keyboard/InputDeviceKeyboard.h>
#include <AzFramework/Input/Devices/Mouse/InputDeviceMouse.h>
#include <AzFramework/Viewport/ScreenGeometry.h>
#include <AzToolsFramework/Viewport/ViewportMessages.h>
#include <QApplication>
#include <QWidget>
namespace AtomToolsFramework
{
ViewportInputBehaviorController::ViewportInputBehaviorController(
const AZ::EntityId& cameraEntityId, const AZ::EntityId& targetEntityId, const AZ::EntityId& environmentEntityId)
: AzFramework::SingleViewportController()
, m_cameraEntityId(cameraEntityId)
, m_targetEntityId(targetEntityId)
, m_environmentEntityId(environmentEntityId)
, m_targetPosition(AZ::Vector3::CreateZero())
{
}
ViewportInputBehaviorController::~ViewportInputBehaviorController()
{
}
void ViewportInputBehaviorController::AddBehavior(KeyMask mask, AZStd::shared_ptr<ViewportInputBehavior> behavior)
{
m_behaviorMap[mask] = behavior;
}
const AZ::EntityId& ViewportInputBehaviorController::GetCameraEntityId() const
{
return m_cameraEntityId;
}
const AZ::EntityId& ViewportInputBehaviorController::GetTargetEntityId() const
{
return m_targetEntityId;
}
const AZ::EntityId& ViewportInputBehaviorController::GetEnvironmentEntityId() const
{
return m_environmentEntityId;
}
const AZ::Vector3& ViewportInputBehaviorController::GetTargetPosition() const
{
return m_targetPosition;
}
void ViewportInputBehaviorController::SetTargetPosition(const AZ::Vector3& targetPosition)
{
m_targetPosition = targetPosition;
m_isCameraCentered = false;
}
void ViewportInputBehaviorController::SetTargetBounds(const AZ::Aabb& targetBounds)
{
m_targetBounds = targetBounds;
}
float ViewportInputBehaviorController::GetDistanceToTarget() const
{
AZ::Vector3 cameraPosition;
AZ::TransformBus::EventResult(cameraPosition, m_cameraEntityId, &AZ::TransformBus::Events::GetLocalTranslation);
return cameraPosition.GetDistance(m_targetPosition);
}
void ViewportInputBehaviorController::GetExtents(float& distanceMin, float& distanceMax) const
{
distanceMin = m_distanceMin;
distanceMax = m_distanceMax;
}
float ViewportInputBehaviorController::GetRadius() const
{
return m_radius;
}
void ViewportInputBehaviorController::UpdateViewport(const AzFramework::ViewportControllerUpdateEvent& event)
{
if (m_keysChanged)
{
if (m_timeToBehaviorSwitchMs > 0)
{
m_timeToBehaviorSwitchMs -= event.m_deltaTime.count();
}
if (m_timeToBehaviorSwitchMs <= 0)
{
EvaluateControlBehavior();
m_keysChanged = false;
}
}
}
bool ViewportInputBehaviorController::HandleInputChannelEvent(const AzFramework::ViewportControllerInputEvent& event)
{
using namespace AzFramework;
const InputChannelId& inputChannelId = event.m_inputChannel.GetInputChannelId();
const InputChannel::State state = event.m_inputChannel.GetState();
const KeyMask keysOld = m_keys;
bool mouseOver = false;
AzToolsFramework::ViewportInteraction::ViewportMouseCursorRequestBus::EventResult(
mouseOver, GetViewportId(), &AzToolsFramework::ViewportInteraction::ViewportMouseCursorRequestBus::Events::IsMouseOver);
if (!m_behavior)
{
EvaluateControlBehavior();
}
switch (state)
{
case InputChannel::State::Began:
if (inputChannelId == InputDeviceMouse::Button::Left)
{
m_keys |= Lmb;
}
else if (inputChannelId == InputDeviceMouse::Button::Middle)
{
m_keys |= Mmb;
}
else if (inputChannelId == InputDeviceMouse::Button::Right)
{
m_keys |= Rmb;
}
else if (inputChannelId == InputDeviceKeyboard::Key::ModifierAltL)
{
m_keys |= Alt;
}
else if (inputChannelId == InputDeviceKeyboard::Key::ModifierCtrlL)
{
m_keys |= Ctrl;
}
else if (inputChannelId == InputDeviceKeyboard::Key::ModifierShiftL)
{
m_keys |= Shift;
}
if (m_behavior && inputChannelId == InputDeviceMouse::Movement::X)
{
m_behavior->MoveX(event.m_inputChannel.GetValue());
}
else if (m_behavior && inputChannelId == InputDeviceMouse::Movement::Y)
{
m_behavior->MoveY(event.m_inputChannel.GetValue());
}
else if (m_behavior && inputChannelId == InputDeviceMouse::Movement::Z && mouseOver)
{
m_behavior->MoveZ(event.m_inputChannel.GetValue());
}
break;
case InputChannel::State::Ended:
if (inputChannelId == InputDeviceMouse::Button::Left)
{
m_keys &= ~Lmb;
}
else if (inputChannelId == InputDeviceMouse::Button::Middle)
{
m_keys &= ~Mmb;
}
else if (inputChannelId == InputDeviceMouse::Button::Right)
{
m_keys &= ~Rmb;
}
else if (inputChannelId == InputDeviceKeyboard::Key::ModifierAltL)
{
m_keys &= ~Alt;
}
else if (inputChannelId == InputDeviceKeyboard::Key::ModifierCtrlL)
{
m_keys &= ~Ctrl;
}
else if (inputChannelId == InputDeviceKeyboard::Key::ModifierShiftL)
{
m_keys &= ~Shift;
}
else if (inputChannelId == InputDeviceKeyboard::Key::AlphanumericZ && (m_keys & Ctrl) == None)
{
// only reset camera if no other widget besides viewport is in focus
const auto focus = QApplication::focusWidget();
if (!focus || focus->objectName() == "Viewport")
{
Reset();
}
}
break;
case InputChannel::State::Updated:
if (m_behavior && inputChannelId == InputDeviceMouse::Movement::X)
{
m_behavior->MoveX(event.m_inputChannel.GetValue());
}
else if (m_behavior && inputChannelId == InputDeviceMouse::Movement::Y)
{
m_behavior->MoveY(event.m_inputChannel.GetValue());
}
else if (m_behavior && inputChannelId == InputDeviceMouse::Movement::Z && mouseOver)
{
m_behavior->MoveZ(event.m_inputChannel.GetValue());
}
break;
}
if (keysOld != m_keys)
{
m_keysChanged = true;
m_timeToBehaviorSwitchMs = BehaviorSwitchDelayMs;
}
return false;
}
void ViewportInputBehaviorController::Reset()
{
CalculateExtents();
// reset camera
m_targetPosition = m_modelCenter;
const float distance = m_distanceMin * StartingDistanceMultiplier;
const AZ::Quaternion cameraRotation = AZ::Quaternion::CreateFromAxisAngle(AZ::Vector3::CreateAxisZ(), StartingRotationAngle);
AZ::Vector3 cameraPosition(m_targetPosition.GetX(), m_targetPosition.GetY() - distance, m_targetPosition.GetZ());
cameraPosition = cameraRotation.TransformVector(cameraPosition);
AZ::Transform cameraTransform = AZ::Transform::CreateFromQuaternionAndTranslation(cameraRotation, cameraPosition);
AZ::TransformBus::Event(m_cameraEntityId, &AZ::TransformBus::Events::SetLocalTM, cameraTransform);
m_isCameraCentered = true;
// reset model
AZ::Transform modelTransform = AZ::Transform::CreateIdentity();
AZ::TransformBus::Event(m_targetEntityId, &AZ::TransformBus::Events::SetLocalTM, modelTransform);
// reset environment
AZ::Transform environmentTransform = AZ::Transform::CreateIdentity();
AZ::TransformBus::Event(m_environmentEntityId, &AZ::TransformBus::Events::SetLocalTM, environmentTransform);
const AZ::Matrix4x4 rotationMatrix = AZ::Matrix4x4::CreateIdentity();
auto skyBoxFeatureProcessor =
AZ::RPI::Scene::GetFeatureProcessorForEntity<AZ::Render::SkyBoxFeatureProcessorInterface>(m_environmentEntityId);
skyBoxFeatureProcessor->SetCubemapRotationMatrix(rotationMatrix);
if (m_behavior)
{
m_behavior->End();
m_behavior->Start();
}
}
void ViewportInputBehaviorController::SetFieldOfView(float value)
{
Camera::CameraRequestBus::Event(m_cameraEntityId, &Camera::CameraRequestBus::Events::SetFovDegrees, value);
}
bool ViewportInputBehaviorController::IsCameraCentered() const
{
return m_isCameraCentered;
}
void ViewportInputBehaviorController::CalculateExtents()
{
AZ::TransformBus::EventResult(m_modelCenter, m_targetEntityId, &AZ::TransformBus::Events::GetLocalTranslation);
m_targetBounds.GetAsSphere(m_modelCenter, m_radius);
m_distanceMin = m_targetBounds.GetExtents().GetMinElement() * 0.5f + DepthNear;
m_distanceMax = m_radius * MaxDistanceMultiplier;
}
void ViewportInputBehaviorController::EvaluateControlBehavior()
{
auto it = m_behaviorMap.find(m_keys);
AZStd::shared_ptr<ViewportInputBehavior> nextBehavior =
it != m_behaviorMap.end() ? it->second : AZStd::shared_ptr<ViewportInputBehavior>();
if (m_behavior != nextBehavior)
{
if (m_behavior)
{
m_behavior->End();
}
m_behavior = nextBehavior;
if (m_behavior)
{
m_behavior->Start();
}
}
}
} // namespace AtomToolsFramework