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:
+40
@@ -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
|
||||
+54
@@ -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
|
||||
+61
@@ -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
|
||||
+52
@@ -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
|
||||
+53
@@ -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
|
||||
+59
@@ -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
|
||||
+150
@@ -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
|
||||
+300
@@ -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
|
||||
Reference in New Issue
Block a user