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
monroegm-disable-blank-issue-2
Guthrie Adams 4 years ago committed by GitHub
commit ceb61d143c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -5,19 +5,20 @@
* SPDX-License-Identifier: Apache-2.0 OR MIT * SPDX-License-Identifier: Apache-2.0 OR MIT
* *
*/ */
#pragma once #pragma once
#include <Viewport/InputController/Behavior.h> #include <AtomToolsFramework/Viewport/ViewportInputBehaviorController/ViewportInputBehavior.h>
namespace MaterialEditor namespace AtomToolsFramework
{ {
//! Moves(zooms) camera back and forth towards the target //! Moves(zooms) camera back and forth towards the target
class DollyCameraBehavior final class DollyCameraBehavior final : public ViewportInputBehavior
: public Behavior
{ {
public: public:
DollyCameraBehavior() = default; DollyCameraBehavior(ViewportInputBehaviorControllerInterface* controller);
virtual ~DollyCameraBehavior() = default; virtual ~DollyCameraBehavior() = default;
protected: protected:
void TickInternal(float x, float y, float z) override; void TickInternal(float x, float y, float z) override;
float GetSensitivityX() override; float GetSensitivityX() override;
@ -27,4 +28,4 @@ namespace MaterialEditor
static constexpr float SensitivityX = 0; static constexpr float SensitivityX = 0;
static constexpr float SensitivityY = 0.005f; static constexpr float SensitivityY = 0.005f;
}; };
} // namespace MaterialEditor } // namespace AtomToolsFramework

@ -5,18 +5,18 @@
* SPDX-License-Identifier: Apache-2.0 OR MIT * SPDX-License-Identifier: Apache-2.0 OR MIT
* *
*/ */
#pragma once #pragma once
#include <Viewport/InputController/Behavior.h> #include <AtomToolsFramework/Viewport/ViewportInputBehaviorController/ViewportInputBehavior.h>
namespace MaterialEditor namespace AtomToolsFramework
{ {
//! Moves camera along its vertical and horizontal axis //! Moves camera along its vertical and horizontal axis
class MoveCameraBehavior final class MoveCameraBehavior final : public ViewportInputBehavior
: public Behavior
{ {
public: public:
MoveCameraBehavior() = default; MoveCameraBehavior(ViewportInputBehaviorControllerInterface* controller);
virtual ~MoveCameraBehavior() = default; virtual ~MoveCameraBehavior() = default;
void End() override; void End() override;
@ -29,4 +29,4 @@ namespace MaterialEditor
static constexpr float SensitivityX = 0.01f; static constexpr float SensitivityX = 0.01f;
static constexpr float SensitivityY = 0.01f; static constexpr float SensitivityY = 0.01f;
}; };
} // namespace MaterialEditor } // namespace AtomToolsFramework

@ -5,19 +5,19 @@
* SPDX-License-Identifier: Apache-2.0 OR MIT * SPDX-License-Identifier: Apache-2.0 OR MIT
* *
*/ */
#pragma once #pragma once
#include <Viewport/InputController/Behavior.h> #include <AtomToolsFramework/Viewport/ViewportInputBehaviorController/ViewportInputBehavior.h>
namespace MaterialEditor namespace AtomToolsFramework
{ {
//! Rotates the camera around target position, //! Rotates the camera around target position,
//! this can either be model center or any position in world //! this can either be model center or any position in world
class OrbitCameraBehavior final class OrbitCameraBehavior final : public ViewportInputBehavior
: public Behavior
{ {
public: public:
OrbitCameraBehavior() = default; OrbitCameraBehavior(ViewportInputBehaviorControllerInterface* controller);
virtual ~OrbitCameraBehavior() = default; virtual ~OrbitCameraBehavior() = default;
protected: protected:
@ -30,7 +30,6 @@ namespace MaterialEditor
static constexpr float SensitivityX = 0.005f; static constexpr float SensitivityX = 0.005f;
static constexpr float SensitivityY = 0.005f; static constexpr float SensitivityY = 0.005f;
bool m_aligned = false; bool m_aligned = false;
}; };
} // namespace MaterialEditor } // namespace AtomToolsFramework

@ -5,18 +5,18 @@
* SPDX-License-Identifier: Apache-2.0 OR MIT * SPDX-License-Identifier: Apache-2.0 OR MIT
* *
*/ */
#pragma once #pragma once
#include <Viewport/InputController/Behavior.h> #include <AtomToolsFramework/Viewport/ViewportInputBehaviorController/ViewportInputBehavior.h>
namespace MaterialEditor namespace AtomToolsFramework
{ {
//! Rotates camera around its own axis, allowing to look up/down/left/right //! Rotates camera around its own axis, allowing to look up/down/left/right
class PanCameraBehavior final class PanCameraBehavior final : public ViewportInputBehavior
: public Behavior
{ {
public: public:
PanCameraBehavior() = default; PanCameraBehavior(ViewportInputBehaviorControllerInterface* controller);
virtual ~PanCameraBehavior() = default; virtual ~PanCameraBehavior() = default;
void End() override; void End() override;
@ -30,4 +30,4 @@ namespace MaterialEditor
static constexpr float SensitivityX = 0.005f; static constexpr float SensitivityX = 0.005f;
static constexpr float SensitivityY = 0.005f; static constexpr float SensitivityY = 0.005f;
}; };
} // namespace MaterialEditor } // namespace AtomToolsFramework

@ -5,9 +5,10 @@
* SPDX-License-Identifier: Apache-2.0 OR MIT * SPDX-License-Identifier: Apache-2.0 OR MIT
* *
*/ */
#pragma once #pragma once
#include <Viewport/InputController/Behavior.h> #include <AtomToolsFramework/Viewport/ViewportInputBehaviorController/ViewportInputBehavior.h>
namespace AZ namespace AZ
{ {
@ -15,16 +16,15 @@ namespace AZ
{ {
class SkyBoxFeatureProcessorInterface; class SkyBoxFeatureProcessorInterface;
} }
} } // namespace AZ
namespace MaterialEditor namespace AtomToolsFramework
{ {
//! Rotates lighting and skybox around vertical axis //! Rotates lighting and skybox around vertical axis
class RotateEnvironmentBehavior final class RotateEnvironmentBehavior final : public ViewportInputBehavior
: public Behavior
{ {
public: public:
RotateEnvironmentBehavior() = default; RotateEnvironmentBehavior(ViewportInputBehaviorControllerInterface* controller);
virtual ~RotateEnvironmentBehavior() = default; virtual ~RotateEnvironmentBehavior() = default;
void Start() override; void Start() override;
@ -38,8 +38,8 @@ namespace MaterialEditor
static constexpr float SensitivityX = 0.01f; static constexpr float SensitivityX = 0.01f;
static constexpr float SensitivityY = 0; static constexpr float SensitivityY = 0;
AZ::EntityId m_iblEntityId; AZ::EntityId m_environmentEntityId;
AZ::Render::SkyBoxFeatureProcessorInterface* m_skyBoxFeatureProcessorInterface = nullptr; AZ::Render::SkyBoxFeatureProcessorInterface* m_skyBoxFeatureProcessor = {};
float m_rotation = 0; float m_rotation = {};
}; };
} // namespace MaterialEditor } // namespace AtomToolsFramework

@ -5,18 +5,18 @@
* SPDX-License-Identifier: Apache-2.0 OR MIT * SPDX-License-Identifier: Apache-2.0 OR MIT
* *
*/ */
#pragma once #pragma once
#include <Viewport/InputController/Behavior.h> #include <AtomToolsFramework/Viewport/ViewportInputBehaviorController/ViewportInputBehavior.h>
namespace MaterialEditor namespace AtomToolsFramework
{ {
//! Rotates target model in viewport //! Rotates target model in viewport
class RotateModelBehavior final class RotateModelBehavior final : public ViewportInputBehavior
: public Behavior
{ {
public: public:
RotateModelBehavior() = default; RotateModelBehavior(ViewportInputBehaviorControllerInterface* controller);
virtual ~RotateModelBehavior() = default; virtual ~RotateModelBehavior() = default;
void Start() override; void Start() override;
@ -33,4 +33,4 @@ namespace MaterialEditor
AZ::EntityId m_targetEntityId; AZ::EntityId m_targetEntityId;
AZ::Vector3 m_cameraRight = AZ::Vector3::CreateAxisX(); AZ::Vector3 m_cameraRight = AZ::Vector3::CreateAxisX();
}; };
} // namespace MaterialEditor } // namespace AtomToolsFramework

@ -5,22 +5,24 @@
* SPDX-License-Identifier: Apache-2.0 OR MIT * SPDX-License-Identifier: Apache-2.0 OR MIT
* *
*/ */
#pragma once #pragma once
#include <AzCore/Component/EntityId.h> #include <AzCore/Component/EntityId.h>
#include <AzCore/Math/Quaternion.h>
#include <AzCore/Component/TickBus.h> #include <AzCore/Component/TickBus.h>
#include <AzCore/Math/Quaternion.h>
namespace MaterialEditor namespace AtomToolsFramework
{ {
//! Performs a single type of action for MaterialEditorViewportInputController based on input class ViewportInputBehaviorControllerInterface;
//! Performs a single type of action for ViewportInputBehaviorController based on input
//! See derived behaviors for specific details //! See derived behaviors for specific details
class Behavior class ViewportInputBehavior : public AZ::TickBus::Handler
: public AZ::TickBus::Handler
{ {
public: public:
Behavior(); ViewportInputBehavior(ViewportInputBehaviorControllerInterface* controller);
virtual ~Behavior(); virtual ~ViewportInputBehavior();
virtual void Start(); virtual void Start();
virtual void End(); virtual void End();
@ -45,20 +47,21 @@ namespace MaterialEditor
//! If delta transform less than this, snap instantly //! If delta transform less than this, snap instantly
static constexpr float SnapInterval = 0.01f; static constexpr float SnapInterval = 0.01f;
//! delta x movement accumulated during current frame //! delta x movement accumulated during current frame
float m_x = 0; float m_x = {};
//! delta y movement accumulated during current frame //! delta y movement accumulated during current frame
float m_y = 0; float m_y = {};
//! delta scroll wheel accumulated during current frame //! delta scroll wheel accumulated during current frame
float m_z = 0; float m_z = {};
//! Model radius //! Model radius
float m_radius = 1.0f; float m_radius = 1.0f;
AZ::EntityId m_cameraEntityId; AZ::EntityId m_cameraEntityId;
AZ::Vector3 m_targetPosition = AZ::Vector3::CreateZero(); AZ::Vector3 m_targetPosition = AZ::Vector3::CreateZero();
float m_distanceToTarget = 0; float m_distanceToTarget = {};
ViewportInputBehaviorControllerInterface* m_controller = {};
private: private:
// AZ::TickBus::Handler interface overrides... // AZ::TickBus::Handler interface overrides...
void OnTick(float deltaTime, AZ::ScriptTimePoint time) override; void OnTick(float deltaTime, AZ::ScriptTimePoint time) override;
}; };
} // namespace MaterialEditor } // namespace AtomToolsFramework

@ -7,36 +7,51 @@
*/ */
#pragma once #pragma once
#include <AtomToolsFramework/Viewport/ViewportInputBehaviorController/ViewportInputBehavior.h>
#include <AtomToolsFramework/Viewport/ViewportInputBehaviorController/ViewportInputBehaviorControllerInterface.h>
#include <AzFramework/Input/Events/InputChannelEventListener.h> #include <AzFramework/Input/Events/InputChannelEventListener.h>
#include <AzFramework/Viewport/SingleViewportController.h> #include <AzFramework/Viewport/SingleViewportController.h>
#include <Viewport/InputController/Behavior.h>
#include <Viewport/InputController/MaterialEditorViewportInputControllerBus.h>
namespace MaterialEditor namespace AtomToolsFramework
{ {
class Behavior; class ViewportInputBehavior;
//! Provides controls for manipulating camera, model, and environment in Material Editor //! Provides controls for manipulating camera, model, and environment in Material Editor
class MaterialEditorViewportInputController class ViewportInputBehaviorController
: public AzFramework::SingleViewportController : public AzFramework::SingleViewportController
, public MaterialEditorViewportInputControllerRequestBus::Handler , public ViewportInputBehaviorControllerInterface
{ {
public: public:
AZ_TYPE_INFO(ViewportInputBehaviorController, "{569A0544-7654-4DCE-8156-00A71B408374}");
AZ_CLASS_ALLOCATOR(ViewportInputBehaviorController, AZ::SystemAllocator, 0)
AZ_DISABLE_COPY_MOVE(ViewportInputBehaviorController);
AZ_TYPE_INFO(MaterialEditorViewportInputController, "{569A0544-7654-4DCE-8156-00A71B408374}"); using KeyMask = uint32_t;
AZ_CLASS_ALLOCATOR(MaterialEditorViewportInputController, AZ::SystemAllocator, 0)
MaterialEditorViewportInputController(); enum Keys
virtual ~MaterialEditorViewportInputController(); {
None = 0,
Lmb = 1 << 0,
Mmb = 1 << 1,
Rmb = 1 << 2,
Alt = 1 << 3,
Ctrl = 1 << 4,
Shift = 1 << 5
};
ViewportInputBehaviorController(
const AZ::EntityId& cameraEntityId, const AZ::EntityId& targetEntityId, const AZ::EntityId& environmentEntityId);
virtual ~ViewportInputBehaviorController();
void Init(const AZ::EntityId& cameraEntityId, const AZ::EntityId& targetEntityId, const AZ::EntityId& iblEntityId); void AddBehavior(KeyMask mask, AZStd::shared_ptr<ViewportInputBehavior> behavior);
// MaterialEditorViewportInputControllerRequestBus::Handler interface overrides... // ViewportInputBehaviorControllerInterface overrides...
const AZ::EntityId& GetCameraEntityId() const override; const AZ::EntityId& GetCameraEntityId() const override;
const AZ::EntityId& GetTargetEntityId() const override; const AZ::EntityId& GetTargetEntityId() const override;
const AZ::EntityId& GetIblEntityId() const override; const AZ::EntityId& GetEnvironmentEntityId() const override;
const AZ::Vector3& GetTargetPosition() const override; const AZ::Vector3& GetTargetPosition() const override;
void SetTargetPosition(const AZ::Vector3& targetPosition) override; void SetTargetPosition(const AZ::Vector3& targetPosition) override;
void SetTargetBounds(const AZ::Aabb& targetBounds) override;
float GetDistanceToTarget() const override; float GetDistanceToTarget() const override;
void GetExtents(float& distanceMin, float& distanceMax) const override; void GetExtents(float& distanceMin, float& distanceMax) const override;
float GetRadius() const override; float GetRadius() const override;
@ -44,31 +59,16 @@ namespace MaterialEditor
void SetFieldOfView(float value) override; void SetFieldOfView(float value) override;
bool IsCameraCentered() const override; bool IsCameraCentered() const override;
// AzFramework::ViewportControllerInstance interface overrides... // AzFramework::ViewportControllerInstance overrides...
bool HandleInputChannelEvent(const AzFramework::ViewportControllerInputEvent& event) override; bool HandleInputChannelEvent(const AzFramework::ViewportControllerInputEvent& event) override;
void UpdateViewport(const AzFramework::ViewportControllerUpdateEvent& event) override; void UpdateViewport(const AzFramework::ViewportControllerUpdateEvent& event) override;
private: private:
using KeyMask = uint32_t;
enum Keys
{
None = 0,
Lmb = 1 << 0,
Mmb = 1 << 1,
Rmb = 1 << 2,
Alt = 1 << 3,
Ctrl = 1 << 4,
Shift = 1 << 5
};
//! Calculate min and max dist and center based on mesh size of target model //! Calculate min and max dist and center based on mesh size of target model
void CalculateExtents(); void CalculateExtents();
//! Determine which behavior to set based on mouse/keyboard input //! Determine which behavior to set based on mouse/keyboard input
void EvaluateControlBehavior(); void EvaluateControlBehavior();
bool m_initialized = false;
//! Input keys currently pressed //! Input keys currently pressed
KeyMask m_keys = None; KeyMask m_keys = None;
//! Input key sequence changed //! Input key sequence changed
@ -77,16 +77,18 @@ namespace MaterialEditor
float m_timeToBehaviorSwitchMs = 0; float m_timeToBehaviorSwitchMs = 0;
//! Current behavior of the controller //! Current behavior of the controller
AZStd::shared_ptr<Behavior> m_behavior; AZStd::shared_ptr<ViewportInputBehavior> m_behavior;
AZStd::unordered_map<KeyMask, AZStd::shared_ptr<Behavior>> m_behaviorMap; AZStd::unordered_map<KeyMask, AZStd::shared_ptr<ViewportInputBehavior>> m_behaviorMap;
AZ::EntityId m_cameraEntityId; AZ::EntityId m_cameraEntityId;
//! Target entity is looking at //! Target entity is looking at
AZ::EntityId m_targetEntityId; AZ::EntityId m_targetEntityId;
//! IBL entity for rotating environment lighting //! IBL entity for rotating environment lighting
AZ::EntityId m_iblEntityId; AZ::EntityId m_environmentEntityId;
//! Target position camera is pointed towards //! Target position camera is pointed towards
AZ::Vector3 m_targetPosition; AZ::Vector3 m_targetPosition;
//! Target bounds
AZ::Aabb m_targetBounds = AZ::Aabb::CreateFromPoint(AZ::Vector3::CreateZero());
//! Center of the model observed //! Center of the model observed
AZ::Vector3 m_modelCenter; AZ::Vector3 m_modelCenter;
//! Minimum distance from camera to target //! Minimum distance from camera to target
@ -106,4 +108,4 @@ namespace MaterialEditor
//! e.g. pressing RMB+LMB shouldn't switch into RMB behavior (or LMB behavior) first because it's virtually impossible to press both mouse buttons on the same frame //! e.g. pressing RMB+LMB shouldn't switch into RMB behavior (or LMB behavior) first because it's virtually impossible to press both mouse buttons on the same frame
static constexpr float BehaviorSwitchDelayMs = 0.1f; static constexpr float BehaviorSwitchDelayMs = 0.1f;
}; };
} // namespace MaterialEditor } // namespace AtomToolsFramework

@ -8,16 +8,15 @@
#pragma once #pragma once
#include <AzCore/EBus/EBus.h> #include <AzCore/EBus/EBus.h>
#include <AzCore/Math/Aabb.h>
#include <AzCore/Math/Vector3.h> #include <AzCore/Math/Vector3.h>
namespace MaterialEditor namespace AtomToolsFramework
{ {
class MaterialEditorViewportInputControllerRequests class ViewportInputBehaviorControllerInterface
: public AZ::EBusTraits
{ {
public: public:
static const AZ::EBusHandlerPolicy HandlerPolicy = AZ::EBusHandlerPolicy::Single; virtual ~ViewportInputBehaviorControllerInterface() = default;
static const AZ::EBusAddressPolicy AddressPolicy = AZ::EBusAddressPolicy::Single;
//! Get entityId of viewport camera //! Get entityId of viewport camera
virtual const AZ::EntityId& GetCameraEntityId() const = 0; virtual const AZ::EntityId& GetCameraEntityId() const = 0;
@ -26,7 +25,7 @@ namespace MaterialEditor
virtual const AZ::EntityId& GetTargetEntityId() const = 0; virtual const AZ::EntityId& GetTargetEntityId() const = 0;
//! Get entityId of scene's IBL entity //! Get entityId of scene's IBL entity
virtual const AZ::EntityId& GetIblEntityId() const = 0; virtual const AZ::EntityId& GetEnvironmentEntityId() const = 0;
//! Get actual position where the camera is facing //! Get actual position where the camera is facing
virtual const AZ::Vector3& GetTargetPosition() const = 0; virtual const AZ::Vector3& GetTargetPosition() const = 0;
@ -35,6 +34,10 @@ namespace MaterialEditor
//! @param targetPosition world space position to point camera at //! @param targetPosition world space position to point camera at
virtual void SetTargetPosition(const AZ::Vector3& targetPosition) = 0; virtual void SetTargetPosition(const AZ::Vector3& targetPosition) = 0;
//! Set camera target bounds
//! @param targetBounds AABB of target
virtual void SetTargetBounds(const AZ::Aabb& targetBounds) = 0;
//! Get distance between camera and its target //! Get distance between camera and its target
virtual float GetDistanceToTarget() const = 0; virtual float GetDistanceToTarget() const = 0;
@ -56,6 +59,4 @@ namespace MaterialEditor
//! Check if camera is looking directly at a model //! Check if camera is looking directly at a model
virtual bool IsCameraCentered() const = 0; virtual bool IsCameraCentered() const = 0;
}; };
} // namespace AtomToolsFramework
using MaterialEditorViewportInputControllerRequestBus = AZ::EBus<MaterialEditorViewportInputControllerRequests>;
} // namespace MaterialEditor

@ -6,21 +6,25 @@
* *
*/ */
#include <AtomToolsFramework/Viewport/ViewportInputBehaviorController/DollyCameraBehavior.h>
#include <AtomToolsFramework/Viewport/ViewportInputBehaviorController/ViewportInputBehaviorControllerInterface.h>
#include <AzCore/Component/TransformBus.h> #include <AzCore/Component/TransformBus.h>
#include <AzCore/Math/MathUtils.h> #include <AzCore/Math/MathUtils.h>
#include <AzCore/Math/Vector3.h> #include <AzCore/Math/Vector3.h>
#include <Viewport/InputController/DollyCameraBehavior.h>
#include <Viewport/InputController/MaterialEditorViewportInputController.h>
namespace MaterialEditor namespace AtomToolsFramework
{ {
DollyCameraBehavior::DollyCameraBehavior(ViewportInputBehaviorControllerInterface* controller)
: ViewportInputBehavior(controller)
{
}
void DollyCameraBehavior::TickInternal([[maybe_unused]] float x, float y, [[maybe_unused]] float z) void DollyCameraBehavior::TickInternal([[maybe_unused]] float x, float y, [[maybe_unused]] float z)
{ {
m_distanceToTarget = m_distanceToTarget + y; m_distanceToTarget = m_distanceToTarget + y;
AZ::Transform transform = AZ::Transform::CreateIdentity(); AZ::Transform transform = AZ::Transform::CreateIdentity();
AZ::TransformBus::EventResult(transform, m_cameraEntityId, &AZ::TransformBus::Events::GetLocalTM); AZ::TransformBus::EventResult(transform, m_cameraEntityId, &AZ::TransformBus::Events::GetLocalTM);
AZ::Vector3 position = m_targetPosition - AZ::Vector3 position = m_targetPosition - transform.GetRotation().TransformVector(AZ::Vector3::CreateAxisY(m_distanceToTarget));
transform.GetRotation().TransformVector(AZ::Vector3::CreateAxisY(m_distanceToTarget));
AZ::TransformBus::Event(m_cameraEntityId, &AZ::TransformBus::Events::SetLocalTranslation, position); AZ::TransformBus::Event(m_cameraEntityId, &AZ::TransformBus::Events::SetLocalTranslation, position);
} }
@ -33,4 +37,4 @@ namespace MaterialEditor
{ {
return SensitivityY; return SensitivityY;
} }
} // namespace MaterialEditor } // namespace AtomToolsFramework

@ -6,27 +6,25 @@
* *
*/ */
#include <AtomToolsFramework/Viewport/ViewportInputBehaviorController/MoveCameraBehavior.h>
#include <AtomToolsFramework/Viewport/ViewportInputBehaviorController/ViewportInputBehaviorControllerInterface.h>
#include <AzCore/Component/TransformBus.h> #include <AzCore/Component/TransformBus.h>
#include <AzCore/Math/Vector3.h> #include <AzCore/Math/Vector3.h>
#include <Viewport/InputController/MaterialEditorViewportInputControllerBus.h>
#include <Viewport/InputController/MoveCameraBehavior.h>
namespace MaterialEditor namespace AtomToolsFramework
{ {
MoveCameraBehavior::MoveCameraBehavior(ViewportInputBehaviorControllerInterface* controller)
: ViewportInputBehavior(controller)
{
}
void MoveCameraBehavior::End() void MoveCameraBehavior::End()
{ {
float distanceToTarget; float distanceToTarget = m_controller->GetDistanceToTarget();
MaterialEditorViewportInputControllerRequestBus::BroadcastResult(
distanceToTarget,
&MaterialEditorViewportInputControllerRequestBus::Handler::GetDistanceToTarget);
AZ::Transform transform = AZ::Transform::CreateIdentity(); AZ::Transform transform = AZ::Transform::CreateIdentity();
AZ::TransformBus::EventResult(transform, m_cameraEntityId, &AZ::TransformBus::Events::GetLocalTM); AZ::TransformBus::EventResult(transform, m_cameraEntityId, &AZ::TransformBus::Events::GetLocalTM);
AZ::Vector3 targetPosition = AZ::Vector3 targetPosition = transform.GetTranslation() + transform.GetBasisY() * distanceToTarget;
transform.GetTranslation() + m_controller->SetTargetPosition(targetPosition);
transform.GetBasisY() * distanceToTarget;
MaterialEditorViewportInputControllerRequestBus::Broadcast(
&MaterialEditorViewportInputControllerRequestBus::Handler::SetTargetPosition,
targetPosition);
} }
void MoveCameraBehavior::TickInternal(float x, float y, float z) void MoveCameraBehavior::TickInternal(float x, float y, float z)
@ -41,7 +39,7 @@ namespace MaterialEditor
m_targetPosition += deltaPosition; m_targetPosition += deltaPosition;
AZ::TransformBus::Event(m_cameraEntityId, &AZ::TransformBus::Events::SetLocalTranslation, position); AZ::TransformBus::Event(m_cameraEntityId, &AZ::TransformBus::Events::SetLocalTranslation, position);
Behavior::TickInternal(x, y, z); ViewportInputBehavior::TickInternal(x, y, z);
} }
float MoveCameraBehavior::GetSensitivityX() float MoveCameraBehavior::GetSensitivityX()
@ -53,4 +51,4 @@ namespace MaterialEditor
{ {
return SensitivityY; return SensitivityY;
} }
} // namespace MaterialEditor } // namespace AtomToolsFramework

@ -6,15 +6,20 @@
* *
*/ */
#include <AtomToolsFramework/Viewport/ViewportInputBehaviorController/OrbitCameraBehavior.h>
#include <AtomToolsFramework/Viewport/ViewportInputBehaviorController/ViewportInputBehaviorControllerInterface.h>
#include <AzCore/Component/TransformBus.h> #include <AzCore/Component/TransformBus.h>
#include <Viewport/InputController/MaterialEditorViewportInputController.h>
#include <Viewport/InputController/OrbitCameraBehavior.h>
namespace MaterialEditor namespace AtomToolsFramework
{ {
OrbitCameraBehavior::OrbitCameraBehavior(ViewportInputBehaviorControllerInterface* controller)
: ViewportInputBehavior(controller)
{
}
void OrbitCameraBehavior::TickInternal(float x, float y, float z) void OrbitCameraBehavior::TickInternal(float x, float y, float z)
{ {
Behavior::TickInternal(x, y, 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 // don't align camera until a movement has been made so that accidental right-click doesn't reset camera
if (!m_aligned) if (!m_aligned)
@ -27,12 +32,9 @@ namespace MaterialEditor
AZ::Quaternion rotation = transform.GetRotation(); AZ::Quaternion rotation = transform.GetRotation();
AZ::Vector3 right = transform.GetBasisX(); AZ::Vector3 right = transform.GetBasisX();
rotation = rotation =
AZ::Quaternion::CreateFromAxisAngle(AZ::Vector3::CreateAxisZ(), -x) * AZ::Quaternion::CreateFromAxisAngle(AZ::Vector3::CreateAxisZ(), -x) * AZ::Quaternion::CreateFromAxisAngle(right, -y) * rotation;
AZ::Quaternion::CreateFromAxisAngle(right, -y) *
rotation;
rotation.Normalize(); rotation.Normalize();
AZ::Vector3 position = AZ::Vector3 position = rotation.TransformVector(AZ::Vector3(0, -m_distanceToTarget, 0)) + m_targetPosition;
rotation.TransformVector(AZ::Vector3(0, -m_distanceToTarget, 0)) + m_targetPosition;
transform = AZ::Transform::CreateFromQuaternionAndTranslation(rotation, position); transform = AZ::Transform::CreateFromQuaternionAndTranslation(rotation, position);
AZ::TransformBus::Event(m_cameraEntityId, &AZ::TransformBus::Events::SetLocalTM, transform); AZ::TransformBus::Event(m_cameraEntityId, &AZ::TransformBus::Events::SetLocalTM, transform);
} }
@ -56,4 +58,4 @@ namespace MaterialEditor
AZ::TransformBus::Event(m_cameraEntityId, &AZ::TransformBus::Events::SetLocalRotationQuaternion, targetRotation); AZ::TransformBus::Event(m_cameraEntityId, &AZ::TransformBus::Events::SetLocalRotationQuaternion, targetRotation);
m_aligned = true; m_aligned = true;
} }
} // namespace MaterialEditor } // namespace AtomToolsFramework

@ -6,28 +6,26 @@
* *
*/ */
#include <AtomToolsFramework/Viewport/ViewportInputBehaviorController/PanCameraBehavior.h>
#include <AtomToolsFramework/Viewport/ViewportInputBehaviorController/ViewportInputBehaviorControllerInterface.h>
#include <AzCore/Component/TransformBus.h> #include <AzCore/Component/TransformBus.h>
#include <AzCore/Math/Quaternion.h> #include <AzCore/Math/Quaternion.h>
#include <AzCore/Math/Vector3.h> #include <AzCore/Math/Vector3.h>
#include <Viewport/InputController/MaterialEditorViewportInputControllerBus.h>
#include <Viewport/InputController/PanCameraBehavior.h>
namespace MaterialEditor namespace AtomToolsFramework
{ {
PanCameraBehavior::PanCameraBehavior(ViewportInputBehaviorControllerInterface* controller)
: ViewportInputBehavior(controller)
{
}
void PanCameraBehavior::End() void PanCameraBehavior::End()
{ {
float distanceToTarget; float distanceToTarget = m_controller->GetDistanceToTarget();
MaterialEditorViewportInputControllerRequestBus::BroadcastResult(
distanceToTarget,
&MaterialEditorViewportInputControllerRequestBus::Handler::GetDistanceToTarget);
AZ::Transform transform = AZ::Transform::CreateIdentity(); AZ::Transform transform = AZ::Transform::CreateIdentity();
AZ::TransformBus::EventResult(transform, m_cameraEntityId, &AZ::TransformBus::Events::GetLocalTM); AZ::TransformBus::EventResult(transform, m_cameraEntityId, &AZ::TransformBus::Events::GetLocalTM);
AZ::Vector3 targetPosition = AZ::Vector3 targetPosition = transform.GetTranslation() + transform.GetBasisY() * distanceToTarget;
transform.GetTranslation() + m_controller->SetTargetPosition(targetPosition);
transform.GetBasisY() * distanceToTarget;
MaterialEditorViewportInputControllerRequestBus::Broadcast(
&MaterialEditorViewportInputControllerRequestBus::Handler::SetTargetPosition,
targetPosition);
} }
void PanCameraBehavior::TickInternal(float x, float y, [[maybe_unused]] float z) void PanCameraBehavior::TickInternal(float x, float y, [[maybe_unused]] float z)
@ -37,9 +35,7 @@ namespace MaterialEditor
AZ::Quaternion rotation = transform.GetRotation(); AZ::Quaternion rotation = transform.GetRotation();
const AZ::Vector3 right = transform.GetBasisX(); const AZ::Vector3 right = transform.GetBasisX();
rotation = rotation =
AZ::Quaternion::CreateFromAxisAngle(AZ::Vector3::CreateAxisZ(), -x) * AZ::Quaternion::CreateFromAxisAngle(AZ::Vector3::CreateAxisZ(), -x) * AZ::Quaternion::CreateFromAxisAngle(right, -y) * rotation;
AZ::Quaternion::CreateFromAxisAngle(right, -y) *
rotation;
rotation.Normalize(); rotation.Normalize();
AZ::TransformBus::Event(m_cameraEntityId, &AZ::TransformBus::Events::SetLocalRotationQuaternion, rotation); AZ::TransformBus::Event(m_cameraEntityId, &AZ::TransformBus::Events::SetLocalRotationQuaternion, rotation);
} }
@ -53,4 +49,4 @@ namespace MaterialEditor
{ {
return SensitivityY; return SensitivityY;
} }
} // namespace MaterialEditor } // 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

@ -6,25 +6,27 @@
* *
*/ */
#include <AtomToolsFramework/Viewport/ViewportInputBehaviorController/RotateModelBehavior.h>
#include <AtomToolsFramework/Viewport/ViewportInputBehaviorController/ViewportInputBehaviorControllerInterface.h>
#include <AzCore/Component/TransformBus.h> #include <AzCore/Component/TransformBus.h>
#include <Viewport/InputController/MaterialEditorViewportInputController.h>
#include <Viewport/InputController/RotateModelBehavior.h>
namespace MaterialEditor namespace AtomToolsFramework
{ {
RotateModelBehavior::RotateModelBehavior(ViewportInputBehaviorControllerInterface* controller)
: ViewportInputBehavior(controller)
{
}
void RotateModelBehavior::Start() void RotateModelBehavior::Start()
{ {
Behavior::Start(); ViewportInputBehavior::Start();
MaterialEditorViewportInputControllerRequestBus::BroadcastResult( m_targetEntityId = m_controller->GetTargetEntityId();
m_targetEntityId,
&MaterialEditorViewportInputControllerRequestBus::Handler::GetTargetEntityId);
AZ_Assert(m_targetEntityId.IsValid(), "Failed to find m_targetEntityId"); AZ_Assert(m_targetEntityId.IsValid(), "Failed to find m_targetEntityId");
AZ::EntityId cameraEntityId;
MaterialEditorViewportInputControllerRequestBus::BroadcastResult( AZ::EntityId cameraEntityId = m_controller->GetCameraEntityId();
cameraEntityId,
&MaterialEditorViewportInputControllerRequestBus::Handler::GetCameraEntityId);
AZ_Assert(cameraEntityId.IsValid(), "Failed to find cameraEntityId"); AZ_Assert(cameraEntityId.IsValid(), "Failed to find cameraEntityId");
AZ::Transform transform = AZ::Transform::CreateIdentity(); AZ::Transform transform = AZ::Transform::CreateIdentity();
AZ::TransformBus::EventResult(transform, cameraEntityId, &AZ::TransformBus::Events::GetLocalTM); AZ::TransformBus::EventResult(transform, cameraEntityId, &AZ::TransformBus::Events::GetLocalTM);
m_cameraRight = transform.GetBasisX(); m_cameraRight = transform.GetBasisX();
@ -32,16 +34,14 @@ namespace MaterialEditor
void RotateModelBehavior::TickInternal(float x, float y, float z) void RotateModelBehavior::TickInternal(float x, float y, float z)
{ {
Behavior::TickInternal(x, y, z); ViewportInputBehavior::TickInternal(x, y, z);
AZ::Transform transform = AZ::Transform::CreateIdentity(); AZ::Transform transform = AZ::Transform::CreateIdentity();
AZ::TransformBus::EventResult(transform, m_targetEntityId, &AZ::TransformBus::Events::GetLocalTM); AZ::TransformBus::EventResult(transform, m_targetEntityId, &AZ::TransformBus::Events::GetLocalTM);
AZ::Quaternion rotation = transform.GetRotation(); AZ::Quaternion rotation = transform.GetRotation();
rotation = rotation = AZ::Quaternion::CreateFromAxisAngle(AZ::Vector3::CreateAxisZ(), x) *
AZ::Quaternion::CreateFromAxisAngle(AZ::Vector3::CreateAxisZ(), x) * AZ::Quaternion::CreateFromAxisAngle(m_cameraRight, y) * rotation;
AZ::Quaternion::CreateFromAxisAngle(m_cameraRight, y) *
rotation;
rotation.Normalize(); rotation.Normalize();
AZ::TransformBus::Event(m_targetEntityId, &AZ::TransformBus::Events::SetLocalRotationQuaternion, rotation); AZ::TransformBus::Event(m_targetEntityId, &AZ::TransformBus::Events::SetLocalRotationQuaternion, rotation);
@ -56,4 +56,4 @@ namespace MaterialEditor
{ {
return SensitivityY; return SensitivityY;
} }
} // namespace MaterialEditor } // namespace AtomToolsFramework

@ -6,78 +6,67 @@
* *
*/ */
#include <AtomToolsFramework/Viewport/ViewportInputBehaviorController/ViewportInputBehavior.h>
#include <AtomToolsFramework/Viewport/ViewportInputBehaviorController/ViewportInputBehaviorControllerInterface.h>
#include <AzCore/Component/TransformBus.h> #include <AzCore/Component/TransformBus.h>
#include <AzCore/Math/Vector3.h> #include <AzCore/Math/Vector3.h>
#include <Viewport/InputController/Behavior.h>
#include <Viewport/InputController/MaterialEditorViewportInputController.h>
namespace MaterialEditor namespace AtomToolsFramework
{ {
Behavior::Behavior() ViewportInputBehavior::ViewportInputBehavior(ViewportInputBehaviorControllerInterface* controller)
: m_controller(controller)
{ {
AZ::TickBus::Handler::BusConnect(); AZ::TickBus::Handler::BusConnect();
} }
Behavior::~Behavior() ViewportInputBehavior::~ViewportInputBehavior()
{ {
AZ::TickBus::Handler::BusDisconnect(); AZ::TickBus::Handler::BusDisconnect();
} }
void Behavior::Start() void ViewportInputBehavior::Start()
{ {
m_x = 0; m_x = {};
m_y = 0; m_y = {};
m_z = 0; m_z = {};
MaterialEditorViewportInputControllerRequestBus::BroadcastResult( m_cameraEntityId = m_controller->GetCameraEntityId();
m_cameraEntityId,
&MaterialEditorViewportInputControllerRequestBus::Handler::GetCameraEntityId);
AZ_Assert(m_cameraEntityId.IsValid(), "Failed to find m_cameraEntityId"); AZ_Assert(m_cameraEntityId.IsValid(), "Failed to find m_cameraEntityId");
MaterialEditorViewportInputControllerRequestBus::BroadcastResult( m_distanceToTarget = m_controller->GetDistanceToTarget();
m_distanceToTarget, m_targetPosition = m_controller->GetTargetPosition();
&MaterialEditorViewportInputControllerRequestBus::Handler::GetDistanceToTarget); m_radius = m_controller->GetRadius();
MaterialEditorViewportInputControllerRequestBus::BroadcastResult(
m_targetPosition,
&MaterialEditorViewportInputControllerRequestBus::Handler::GetTargetPosition);
MaterialEditorViewportInputControllerRequestBus::BroadcastResult(
m_radius, &MaterialEditorViewportInputControllerRequestBus::Handler::GetRadius);
} }
void Behavior::End() void ViewportInputBehavior::End()
{ {
} }
void Behavior::MoveX(float value) void ViewportInputBehavior::MoveX(float value)
{ {
m_x += value * GetSensitivityX(); m_x += value * GetSensitivityX();
} }
void Behavior::MoveY(float value) void ViewportInputBehavior::MoveY(float value)
{ {
m_y += value * GetSensitivityY(); m_y += value * GetSensitivityY();
} }
void Behavior::MoveZ(float value) void ViewportInputBehavior::MoveZ(float value)
{ {
m_z += value * GetSensitivityZ(); m_z += value * GetSensitivityZ();
} }
bool Behavior::HasDelta() const bool ViewportInputBehavior::HasDelta() const
{ {
return return AZ::GetAbs(m_x) > std::numeric_limits<float>::min() || AZ::GetAbs(m_y) > std::numeric_limits<float>::min() ||
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(); AZ::GetAbs(m_z) > std::numeric_limits<float>::min();
} }
void Behavior::TickInternal([[maybe_unused]] float x, [[maybe_unused]] float y, float z) void ViewportInputBehavior::TickInternal([[maybe_unused]] float x, [[maybe_unused]] float y, float z)
{ {
m_distanceToTarget = m_distanceToTarget - z; m_distanceToTarget = m_distanceToTarget - z;
bool isCameraCentered = false; bool isCameraCentered = m_controller->IsCameraCentered();
MaterialEditorViewportInputControllerRequestBus::BroadcastResult(
isCameraCentered,
&MaterialEditorViewportInputControllerRequestBus::Handler::IsCameraCentered);
// if camera is looking at the model (locked to the model) we don't want to zoom past the model's center // if camera is looking at the model (locked to the model) we don't want to zoom past the model's center
if (isCameraCentered) if (isCameraCentered)
@ -87,40 +76,35 @@ namespace MaterialEditor
AZ::Transform transform = AZ::Transform::CreateIdentity(); AZ::Transform transform = AZ::Transform::CreateIdentity();
AZ::TransformBus::EventResult(transform, m_cameraEntityId, &AZ::TransformBus::Events::GetLocalTM); AZ::TransformBus::EventResult(transform, m_cameraEntityId, &AZ::TransformBus::Events::GetLocalTM);
AZ::Vector3 position = m_targetPosition - AZ::Vector3 position = m_targetPosition - transform.GetRotation().TransformVector(AZ::Vector3::CreateAxisY(m_distanceToTarget));
transform.GetRotation().TransformVector(AZ::Vector3::CreateAxisY(m_distanceToTarget));
AZ::TransformBus::Event(m_cameraEntityId, &AZ::TransformBus::Events::SetLocalTranslation, position); 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 camera is not locked to the model, move its focal point so we can free look
if (!isCameraCentered) if (!isCameraCentered)
{ {
m_targetPosition += transform.GetRotation().TransformVector(AZ::Vector3::CreateAxisY(z)); m_targetPosition += transform.GetRotation().TransformVector(AZ::Vector3::CreateAxisY(z));
MaterialEditorViewportInputControllerRequestBus::Broadcast( m_controller->SetTargetPosition(m_targetPosition);
&MaterialEditorViewportInputControllerRequestBus::Handler::SetTargetPosition, m_distanceToTarget = m_controller->GetDistanceToTarget();
m_targetPosition);
MaterialEditorViewportInputControllerRequestBus::BroadcastResult(
m_distanceToTarget,
&MaterialEditorViewportInputControllerRequestBus::Handler::GetDistanceToTarget);
} }
} }
float Behavior::GetSensitivityX() float ViewportInputBehavior::GetSensitivityX()
{ {
return 0; return 0;
} }
float Behavior::GetSensitivityY() float ViewportInputBehavior::GetSensitivityY()
{ {
return 0; return 0;
} }
float Behavior::GetSensitivityZ() float ViewportInputBehavior::GetSensitivityZ()
{ {
// adjust zooming sensitivity by model size, so that large models zoom at the same speed as smaller ones // 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); return 0.001f * AZ::GetMax(0.5f, m_radius);
} }
AZ::Quaternion Behavior::LookRotation(AZ::Vector3 forward) AZ::Quaternion ViewportInputBehavior::LookRotation(AZ::Vector3 forward)
{ {
forward.Normalize(); forward.Normalize();
AZ::Vector3 right = forward.CrossZAxis(); AZ::Vector3 right = forward.CrossZAxis();
@ -132,7 +116,7 @@ namespace MaterialEditor
return rotation; return rotation;
} }
float Behavior::TakeStep(float& value, float t) float ViewportInputBehavior::TakeStep(float& value, float t)
{ {
const float absValue = AZ::GetAbs(value); const float absValue = AZ::GetAbs(value);
float step; float step;
@ -148,7 +132,7 @@ namespace MaterialEditor
return step; return step;
} }
void Behavior::OnTick(float deltaTime, [[maybe_unused]] AZ::ScriptTimePoint time) 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) // 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 // in the Tick function we then lerp them down to 0 over short time and apply delta transform to an entity
@ -163,4 +147,4 @@ namespace MaterialEditor
TickInternal(x, y, z); TickInternal(x, y, z);
} }
} }
} // namespace MaterialEditor } // namespace AtomToolsFramework

@ -6,120 +6,94 @@
* *
*/ */
#include <QApplication> #include <Atom/Feature/SkyBox/SkyBoxFeatureProcessorInterface.h>
#include <QWidget> #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/Component/TransformBus.h>
#include <AzCore/Math/Matrix4x4.h> #include <AzCore/Math/Matrix4x4.h>
#include <AzCore/Serialization/SerializeContext.h> #include <AzCore/Serialization/SerializeContext.h>
#include <AzFramework/Components/CameraBus.h> #include <AzFramework/Components/CameraBus.h>
#include <AzFramework/Input/Devices/Keyboard/InputDeviceKeyboard.h> #include <AzFramework/Input/Devices/Keyboard/InputDeviceKeyboard.h>
#include <AzFramework/Input/Devices/Mouse/InputDeviceMouse.h> #include <AzFramework/Input/Devices/Mouse/InputDeviceMouse.h>
#include <AzFramework/Viewport/ScreenGeometry.h> #include <AzFramework/Viewport/ScreenGeometry.h>
#include <AzToolsFramework/Viewport/ViewportMessages.h> #include <AzToolsFramework/Viewport/ViewportMessages.h>
#include <Atom/Feature/SkyBox/SkyBoxFeatureProcessorInterface.h> #include <QApplication>
#include <Atom/RPI.Public/RPISystemInterface.h> #include <QWidget>
#include <Atom/RPI.Public/Scene.h>
#include <Atom/RPI.Reflect/Model/ModelAsset.h>
#include <AtomLyIntegration/CommonFeatures/Mesh/MeshComponentBus.h>
#include <Viewport/InputController/DollyCameraBehavior.h>
#include <Viewport/InputController/IdleBehavior.h>
#include <Viewport/InputController/MaterialEditorViewportInputController.h>
#include <Viewport/InputController/MoveCameraBehavior.h>
#include <Viewport/InputController/OrbitCameraBehavior.h>
#include <Viewport/InputController/PanCameraBehavior.h>
#include <Viewport/InputController/RotateEnvironmentBehavior.h>
#include <Viewport/InputController/RotateModelBehavior.h>
namespace MaterialEditor namespace AtomToolsFramework
{ {
MaterialEditorViewportInputController::MaterialEditorViewportInputController() ViewportInputBehaviorController::ViewportInputBehaviorController(
const AZ::EntityId& cameraEntityId, const AZ::EntityId& targetEntityId, const AZ::EntityId& environmentEntityId)
: AzFramework::SingleViewportController() : AzFramework::SingleViewportController()
, m_cameraEntityId(cameraEntityId)
, m_targetEntityId(targetEntityId)
, m_environmentEntityId(environmentEntityId)
, m_targetPosition(AZ::Vector3::CreateZero()) , m_targetPosition(AZ::Vector3::CreateZero())
{ {
m_behaviorMap[None] = AZStd::make_shared<IdleBehavior>();
m_behaviorMap[Lmb] = AZStd::make_shared<PanCameraBehavior>();
m_behaviorMap[Mmb] = AZStd::make_shared<MoveCameraBehavior>();
m_behaviorMap[Rmb] = AZStd::make_shared<OrbitCameraBehavior>();
m_behaviorMap[Alt ^ Lmb] = AZStd::make_shared<OrbitCameraBehavior>();
m_behaviorMap[Alt ^ Mmb] = AZStd::make_shared<MoveCameraBehavior>();
m_behaviorMap[Alt ^ Rmb] = AZStd::make_shared<DollyCameraBehavior>();
m_behaviorMap[Lmb ^ Rmb] = AZStd::make_shared<DollyCameraBehavior>();
m_behaviorMap[Ctrl ^ Lmb] = AZStd::make_shared<RotateModelBehavior>();
m_behaviorMap[Shift ^ Lmb] = AZStd::make_shared<RotateEnvironmentBehavior>();
} }
MaterialEditorViewportInputController::~MaterialEditorViewportInputController() ViewportInputBehaviorController::~ViewportInputBehaviorController()
{ {
if (m_initialized)
{
MaterialEditorViewportInputControllerRequestBus::Handler::BusDisconnect();
}
} }
void MaterialEditorViewportInputController::Init(const AZ::EntityId& cameraEntityId, const AZ::EntityId& targetEntityId, const AZ::EntityId& iblEntityId) void ViewportInputBehaviorController::AddBehavior(KeyMask mask, AZStd::shared_ptr<ViewportInputBehavior> behavior)
{
if (m_initialized)
{ {
AZ_Error("MaterialEditorViewportInputController", false, "Controller already initialized."); m_behaviorMap[mask] = behavior;
return;
} }
m_initialized = true;
m_cameraEntityId = cameraEntityId;
m_targetEntityId = targetEntityId;
m_iblEntityId = iblEntityId;
MaterialEditorViewportInputControllerRequestBus::Handler::BusConnect(); const AZ::EntityId& ViewportInputBehaviorController::GetCameraEntityId() const
}
const AZ::EntityId& MaterialEditorViewportInputController::GetCameraEntityId() const
{ {
return m_cameraEntityId; return m_cameraEntityId;
} }
const AZ::EntityId& MaterialEditorViewportInputController::GetTargetEntityId() const const AZ::EntityId& ViewportInputBehaviorController::GetTargetEntityId() const
{ {
return m_targetEntityId; return m_targetEntityId;
} }
const AZ::EntityId& MaterialEditorViewportInputController::GetIblEntityId() const const AZ::EntityId& ViewportInputBehaviorController::GetEnvironmentEntityId() const
{ {
return m_iblEntityId; return m_environmentEntityId;
} }
const AZ::Vector3& MaterialEditorViewportInputController::GetTargetPosition() const const AZ::Vector3& ViewportInputBehaviorController::GetTargetPosition() const
{ {
return m_targetPosition; return m_targetPosition;
} }
void MaterialEditorViewportInputController::SetTargetPosition(const AZ::Vector3& targetPosition) void ViewportInputBehaviorController::SetTargetPosition(const AZ::Vector3& targetPosition)
{ {
m_targetPosition = targetPosition; m_targetPosition = targetPosition;
m_isCameraCentered = false; m_isCameraCentered = false;
} }
float MaterialEditorViewportInputController::GetDistanceToTarget() const void ViewportInputBehaviorController::SetTargetBounds(const AZ::Aabb& targetBounds)
{
m_targetBounds = targetBounds;
}
float ViewportInputBehaviorController::GetDistanceToTarget() const
{ {
AZ::Vector3 cameraPosition; AZ::Vector3 cameraPosition;
AZ::TransformBus::EventResult(cameraPosition, m_cameraEntityId, &AZ::TransformBus::Events::GetLocalTranslation); AZ::TransformBus::EventResult(cameraPosition, m_cameraEntityId, &AZ::TransformBus::Events::GetLocalTranslation);
return cameraPosition.GetDistance(m_targetPosition); return cameraPosition.GetDistance(m_targetPosition);
} }
void MaterialEditorViewportInputController::GetExtents(float& distanceMin, float& distanceMax) const void ViewportInputBehaviorController::GetExtents(float& distanceMin, float& distanceMax) const
{ {
distanceMin = m_distanceMin; distanceMin = m_distanceMin;
distanceMax = m_distanceMax; distanceMax = m_distanceMax;
} }
float MaterialEditorViewportInputController::GetRadius() const float ViewportInputBehaviorController::GetRadius() const
{ {
return m_radius; return m_radius;
} }
void MaterialEditorViewportInputController::UpdateViewport(const AzFramework::ViewportControllerUpdateEvent& event) void ViewportInputBehaviorController::UpdateViewport(const AzFramework::ViewportControllerUpdateEvent& event)
{ {
if (m_keysChanged) if (m_keysChanged)
{ {
@ -135,7 +109,7 @@ namespace MaterialEditor
} }
} }
bool MaterialEditorViewportInputController::HandleInputChannelEvent(const AzFramework::ViewportControllerInputEvent& event) bool ViewportInputBehaviorController::HandleInputChannelEvent(const AzFramework::ViewportControllerInputEvent& event)
{ {
using namespace AzFramework; using namespace AzFramework;
@ -145,8 +119,7 @@ namespace MaterialEditor
bool mouseOver = false; bool mouseOver = false;
AzToolsFramework::ViewportInteraction::ViewportMouseCursorRequestBus::EventResult( AzToolsFramework::ViewportInteraction::ViewportMouseCursorRequestBus::EventResult(
mouseOver, GetViewportId(), mouseOver, GetViewportId(), &AzToolsFramework::ViewportInteraction::ViewportMouseCursorRequestBus::Events::IsMouseOver);
&AzToolsFramework::ViewportInteraction::ViewportMouseCursorRequestBus::Events::IsMouseOver);
if (!m_behavior) if (!m_behavior)
{ {
@ -180,21 +153,18 @@ namespace MaterialEditor
{ {
m_keys |= Shift; m_keys |= Shift;
} }
if (inputChannelId == InputDeviceMouse::Movement::X) if (m_behavior && inputChannelId == InputDeviceMouse::Movement::X)
{ {
m_behavior->MoveX(event.m_inputChannel.GetValue()); m_behavior->MoveX(event.m_inputChannel.GetValue());
} }
else if (inputChannelId == InputDeviceMouse::Movement::Y) else if (m_behavior && inputChannelId == InputDeviceMouse::Movement::Y)
{ {
m_behavior->MoveY(event.m_inputChannel.GetValue()); m_behavior->MoveY(event.m_inputChannel.GetValue());
} }
else if (inputChannelId == InputDeviceMouse::Movement::Z) else if (m_behavior && inputChannelId == InputDeviceMouse::Movement::Z && mouseOver)
{
if (mouseOver)
{ {
m_behavior->MoveZ(event.m_inputChannel.GetValue()); m_behavior->MoveZ(event.m_inputChannel.GetValue());
} }
}
break; break;
case InputChannel::State::Ended: case InputChannel::State::Ended:
if (inputChannelId == InputDeviceMouse::Button::Left) if (inputChannelId == InputDeviceMouse::Button::Left)
@ -232,21 +202,18 @@ namespace MaterialEditor
} }
break; break;
case InputChannel::State::Updated: case InputChannel::State::Updated:
if (inputChannelId == InputDeviceMouse::Movement::X) if (m_behavior && inputChannelId == InputDeviceMouse::Movement::X)
{ {
m_behavior->MoveX(event.m_inputChannel.GetValue()); m_behavior->MoveX(event.m_inputChannel.GetValue());
} }
else if (inputChannelId == InputDeviceMouse::Movement::Y) else if (m_behavior && inputChannelId == InputDeviceMouse::Movement::Y)
{ {
m_behavior->MoveY(event.m_inputChannel.GetValue()); m_behavior->MoveY(event.m_inputChannel.GetValue());
} }
else if (inputChannelId == InputDeviceMouse::Movement::Z) else if (m_behavior && inputChannelId == InputDeviceMouse::Movement::Z && mouseOver)
{
if (mouseOver)
{ {
m_behavior->MoveZ(event.m_inputChannel.GetValue()); m_behavior->MoveZ(event.m_inputChannel.GetValue());
} }
}
break; break;
} }
@ -258,7 +225,7 @@ namespace MaterialEditor
return false; return false;
} }
void MaterialEditorViewportInputController::Reset() void ViewportInputBehaviorController::Reset()
{ {
CalculateExtents(); CalculateExtents();
@ -277,12 +244,13 @@ namespace MaterialEditor
AZ::TransformBus::Event(m_targetEntityId, &AZ::TransformBus::Events::SetLocalTM, modelTransform); AZ::TransformBus::Event(m_targetEntityId, &AZ::TransformBus::Events::SetLocalTM, modelTransform);
// reset environment // reset environment
AZ::Transform iblTransform = AZ::Transform::CreateIdentity(); AZ::Transform environmentTransform = AZ::Transform::CreateIdentity();
AZ::TransformBus::Event(m_iblEntityId, &AZ::TransformBus::Events::SetLocalTM, iblTransform); AZ::TransformBus::Event(m_environmentEntityId, &AZ::TransformBus::Events::SetLocalTM, environmentTransform);
const AZ::Matrix4x4 rotationMatrix = AZ::Matrix4x4::CreateIdentity(); const AZ::Matrix4x4 rotationMatrix = AZ::Matrix4x4::CreateIdentity();
auto skyBoxFeatureProcessorInterface = AZ::RPI::Scene::GetFeatureProcessorForEntity<AZ::Render::SkyBoxFeatureProcessorInterface>(m_iblEntityId); auto skyBoxFeatureProcessor =
skyBoxFeatureProcessorInterface->SetCubemapRotationMatrix(rotationMatrix); AZ::RPI::Scene::GetFeatureProcessorForEntity<AZ::Render::SkyBoxFeatureProcessorInterface>(m_environmentEntityId);
skyBoxFeatureProcessor->SetCubemapRotationMatrix(rotationMatrix);
if (m_behavior) if (m_behavior)
{ {
@ -291,62 +259,42 @@ namespace MaterialEditor
} }
} }
void MaterialEditorViewportInputController::SetFieldOfView(float value) void ViewportInputBehaviorController::SetFieldOfView(float value)
{ {
Camera::CameraRequestBus::Event(m_cameraEntityId, &Camera::CameraRequestBus::Events::SetFovDegrees, value); Camera::CameraRequestBus::Event(m_cameraEntityId, &Camera::CameraRequestBus::Events::SetFovDegrees, value);
} }
bool MaterialEditorViewportInputController::IsCameraCentered() const bool ViewportInputBehaviorController::IsCameraCentered() const
{ {
return m_isCameraCentered; return m_isCameraCentered;
} }
void MaterialEditorViewportInputController::CalculateExtents() void ViewportInputBehaviorController::CalculateExtents()
{ {
AZ::TransformBus::EventResult(m_modelCenter, m_targetEntityId, &AZ::TransformBus::Events::GetLocalTranslation); AZ::TransformBus::EventResult(m_modelCenter, m_targetEntityId, &AZ::TransformBus::Events::GetLocalTranslation);
m_targetBounds.GetAsSphere(m_modelCenter, m_radius);
AZ::Data::AssetId modelAssetId; m_distanceMin = m_targetBounds.GetExtents().GetMinElement() * 0.5f + DepthNear;
AZ::Render::MeshComponentRequestBus::EventResult(modelAssetId, m_targetEntityId,
&AZ::Render::MeshComponentRequestBus::Events::GetModelAssetId);
if (modelAssetId.IsValid())
{
AZ::Data::Asset<AZ::RPI::ModelAsset> modelAsset = AZ::Data::AssetManager::Instance().GetAsset(modelAssetId, azrtti_typeid<AZ::RPI::ModelAsset>(), AZ::Data::AssetLoadBehavior::PreLoad);
modelAsset.BlockUntilLoadComplete();
if (modelAsset.IsReady())
{
const AZ::Aabb& aabb = modelAsset->GetAabb();
aabb.GetAsSphere(m_modelCenter, m_radius);
m_distanceMin = 0.5f * AZ::GetMin(AZ::GetMin(aabb.GetExtents().GetX(), aabb.GetExtents().GetY()), aabb.GetExtents().GetZ()) + DepthNear;
m_distanceMax = m_radius * MaxDistanceMultiplier; m_distanceMax = m_radius * MaxDistanceMultiplier;
} }
}
}
void MaterialEditorViewportInputController::EvaluateControlBehavior() void ViewportInputBehaviorController::EvaluateControlBehavior()
{ {
AZStd::shared_ptr<Behavior> nextBehavior;
auto it = m_behaviorMap.find(m_keys); auto it = m_behaviorMap.find(m_keys);
if (it == m_behaviorMap.end()) AZStd::shared_ptr<ViewportInputBehavior> nextBehavior =
it != m_behaviorMap.end() ? it->second : AZStd::shared_ptr<ViewportInputBehavior>();
if (m_behavior != nextBehavior)
{ {
nextBehavior = m_behaviorMap[None]; if (m_behavior)
}
else
{ {
nextBehavior = it->second; m_behavior->End();
} }
if (nextBehavior == m_behavior) m_behavior = nextBehavior;
{
return;
}
if (m_behavior) if (m_behavior)
{ {
m_behavior->End();
}
m_behavior = nextBehavior;
m_behavior->Start(); m_behavior->Start();
} }
} // namespace MaterialEditor }
}
} // namespace AtomToolsFramework

@ -88,4 +88,21 @@ set(FILES
Source/PreviewRenderer/PreviewRendererCaptureState.h Source/PreviewRenderer/PreviewRendererCaptureState.h
Source/PreviewRenderer/PreviewRendererSystemComponent.cpp Source/PreviewRenderer/PreviewRendererSystemComponent.cpp
Source/PreviewRenderer/PreviewRendererSystemComponent.h Source/PreviewRenderer/PreviewRendererSystemComponent.h
Source/Viewport/ViewportInputBehaviorController/ViewportInputBehaviorController.cpp
Include/AtomToolsFramework/Viewport/ViewportInputBehaviorController/ViewportInputBehaviorController.h
Include/AtomToolsFramework/Viewport/ViewportInputBehaviorController/ViewportInputBehaviorControllerInterface.h
Source/Viewport/ViewportInputBehaviorController/ViewportInputBehavior.cpp
Include/AtomToolsFramework/Viewport/ViewportInputBehaviorController/ViewportInputBehavior.h
Source/Viewport/ViewportInputBehaviorController/DollyCameraBehavior.cpp
Include/AtomToolsFramework/Viewport/ViewportInputBehaviorController/DollyCameraBehavior.h
Source/Viewport/ViewportInputBehaviorController/MoveCameraBehavior.cpp
Include/AtomToolsFramework/Viewport/ViewportInputBehaviorController/MoveCameraBehavior.h
Source/Viewport/ViewportInputBehaviorController/PanCameraBehavior.cpp
Include/AtomToolsFramework/Viewport/ViewportInputBehaviorController/PanCameraBehavior.h
Source/Viewport/ViewportInputBehaviorController/OrbitCameraBehavior.cpp
Include/AtomToolsFramework/Viewport/ViewportInputBehaviorController/OrbitCameraBehavior.h
Source/Viewport/ViewportInputBehaviorController/RotateEnvironmentBehavior.cpp
Include/AtomToolsFramework/Viewport/ViewportInputBehaviorController/RotateEnvironmentBehavior.h
Source/Viewport/ViewportInputBehaviorController/RotateModelBehavior.cpp
Include/AtomToolsFramework/Viewport/ViewportInputBehaviorController/RotateModelBehavior.h
) )

@ -1,13 +0,0 @@
/*
* 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 <Viewport/InputController/IdleBehavior.h>
namespace MaterialEditor
{
} // namespace MaterialEditor

@ -1,22 +0,0 @@
/*
* 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 <Viewport/InputController/Behavior.h>
namespace MaterialEditor
{
//! No action taken
class IdleBehavior final
: public Behavior
{
public:
IdleBehavior() = default;
virtual ~IdleBehavior() = default;
};
} // namespace MaterialEditor

@ -1,51 +0,0 @@
/*
* 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 <AzCore/Component/TransformBus.h>
#include <Atom/Feature/SkyBox/SkyBoxFeatureProcessorInterface.h>
#include <Atom/RPI.Public/RPISystemInterface.h>
#include <Atom/RPI.Public/Scene.h>
#include <Viewport/InputController/MaterialEditorViewportInputController.h>
#include <Viewport/InputController/RotateEnvironmentBehavior.h>
namespace MaterialEditor
{
void RotateEnvironmentBehavior::Start()
{
Behavior::Start();
MaterialEditorViewportInputControllerRequestBus::BroadcastResult(
m_iblEntityId,
&MaterialEditorViewportInputControllerRequestBus::Handler::GetIblEntityId);
AZ_Assert(m_iblEntityId.IsValid(), "Failed to find m_iblEntityId");
m_skyBoxFeatureProcessorInterface = AZ::RPI::Scene::GetFeatureProcessorForEntity<AZ::Render::SkyBoxFeatureProcessorInterface>(m_iblEntityId);
}
void RotateEnvironmentBehavior::TickInternal(float x, float y, float z)
{
Behavior::TickInternal(x, y, z);
m_rotation += x;
AZ::Quaternion rotation = AZ::Quaternion::CreateFromAxisAngle(AZ::Vector3::CreateAxisZ(), m_rotation);
AZ::TransformBus::Event(m_iblEntityId, &AZ::TransformBus::Events::SetLocalRotationQuaternion, rotation);
const AZ::Matrix4x4 rotationMatrix = AZ::Matrix4x4::CreateFromQuaternion(rotation);
m_skyBoxFeatureProcessorInterface->SetCubemapRotationMatrix(rotationMatrix);
}
float RotateEnvironmentBehavior::GetSensitivityX()
{
return SensitivityX;
}
float RotateEnvironmentBehavior::GetSensitivityY()
{
return SensitivityY;
}
} // namespace MaterialEditor

@ -394,7 +394,7 @@ namespace MaterialEditor
return m_viewportSettings->m_displayMapperOperationType; return m_viewportSettings->m_displayMapperOperationType;
} }
inline void MaterialViewportComponent::OnAssetReady(AZ::Data::Asset<AZ::Data::AssetData> asset) void MaterialViewportComponent::OnAssetReady(AZ::Data::Asset<AZ::Data::AssetData> asset)
{ {
if (AZ::Data::Asset<AZ::RPI::AnyAsset> anyAsset = asset) if (AZ::Data::Asset<AZ::RPI::AnyAsset> anyAsset = asset)
{ {

@ -40,6 +40,12 @@
#include <AtomLyIntegration/CommonFeatures/PostProcess/ExposureControl/ExposureControlBus.h> #include <AtomLyIntegration/CommonFeatures/PostProcess/ExposureControl/ExposureControlBus.h>
#include <AtomLyIntegration/CommonFeatures/PostProcess/ExposureControl/ExposureControlComponentConstants.h> #include <AtomLyIntegration/CommonFeatures/PostProcess/ExposureControl/ExposureControlComponentConstants.h>
#include <AtomLyIntegration/CommonFeatures/PostProcess/PostFxLayerComponentConstants.h> #include <AtomLyIntegration/CommonFeatures/PostProcess/PostFxLayerComponentConstants.h>
#include <AtomToolsFramework/Viewport/ViewportInputBehaviorController/DollyCameraBehavior.h>
#include <AtomToolsFramework/Viewport/ViewportInputBehaviorController/MoveCameraBehavior.h>
#include <AtomToolsFramework/Viewport/ViewportInputBehaviorController/OrbitCameraBehavior.h>
#include <AtomToolsFramework/Viewport/ViewportInputBehaviorController/PanCameraBehavior.h>
#include <AtomToolsFramework/Viewport/ViewportInputBehaviorController/RotateEnvironmentBehavior.h>
#include <AtomToolsFramework/Viewport/ViewportInputBehaviorController/RotateModelBehavior.h>
#include <AzCore/Component/Component.h> #include <AzCore/Component/Component.h>
#include <AzCore/Component/Entity.h> #include <AzCore/Component/Entity.h>
#include <AzFramework/Components/NonUniformScaleComponent.h> #include <AzFramework/Components/NonUniformScaleComponent.h>
@ -64,7 +70,6 @@ namespace MaterialEditor
: AtomToolsFramework::RenderViewportWidget(parent) : AtomToolsFramework::RenderViewportWidget(parent)
, m_ui(new Ui::MaterialViewportWidget) , m_ui(new Ui::MaterialViewportWidget)
, m_toolId(toolId) , m_toolId(toolId)
, m_viewportController(AZStd::make_shared<MaterialEditorViewportInputController>())
{ {
m_ui->setupUi(this); m_ui->setupUi(this);
@ -117,31 +122,24 @@ namespace MaterialEditor
entityContextId, &AzFramework::GameEntityContextRequestBus::Events::GetGameEntityContextId); entityContextId, &AzFramework::GameEntityContextRequestBus::Events::GetGameEntityContextId);
// Configure camera // Configure camera
AzFramework::EntityContextRequestBus::EventResult( m_cameraEntity =
m_cameraEntity, entityContextId, &AzFramework::EntityContextRequestBus::Events::CreateEntity, "Cameraentity"); CreateEntity("Cameraentity", { azrtti_typeid<AzFramework::TransformComponent>(), azrtti_typeid<AZ::Debug::CameraComponent>() });
AZ_Assert(m_cameraEntity != nullptr, "Failed to create camera entity.");
// Add debug camera and controller components
AZ::Debug::CameraComponentConfig cameraConfig(GetViewportContext()->GetWindowContext()); AZ::Debug::CameraComponentConfig cameraConfig(GetViewportContext()->GetWindowContext());
cameraConfig.m_fovY = AZ::Constants::HalfPi; cameraConfig.m_fovY = AZ::Constants::HalfPi;
cameraConfig.m_depthNear = DepthNear; cameraConfig.m_depthNear = DepthNear;
m_cameraComponent = m_cameraEntity->CreateComponent(azrtti_typeid<AZ::Debug::CameraComponent>()); m_cameraEntity->Deactivate();
m_cameraComponent->SetConfiguration(cameraConfig); m_cameraEntity->FindComponent(azrtti_typeid<AZ::Debug::CameraComponent>())->SetConfiguration(cameraConfig);
m_cameraEntity->CreateComponent(azrtti_typeid<AzFramework::TransformComponent>());
m_cameraEntity->Activate(); m_cameraEntity->Activate();
// Connect camera to pipeline's default view after camera entity activated // Connect camera to pipeline's default view after camera entity activated
m_renderPipeline->SetDefaultViewFromEntity(m_cameraEntity->GetId()); m_renderPipeline->SetDefaultViewFromEntity(m_cameraEntity->GetId());
// Configure tone mapper // Configure tone mapper
AzFramework::EntityContextRequestBus::EventResult( m_postProcessEntity = CreateEntity(
m_postProcessEntity, entityContextId, &AzFramework::EntityContextRequestBus::Events::CreateEntity, "postProcessEntity"); "PostProcessEntity",
AZ_Assert(m_postProcessEntity != nullptr, "Failed to create post process entity."); { AZ::Render::PostFxLayerComponentTypeId, AZ::Render::ExposureControlComponentTypeId,
azrtti_typeid<AzFramework::TransformComponent>() });
m_postProcessEntity->CreateComponent(AZ::Render::PostFxLayerComponentTypeId);
m_postProcessEntity->CreateComponent(AZ::Render::ExposureControlComponentTypeId);
m_postProcessEntity->CreateComponent(azrtti_typeid<AzFramework::TransformComponent>());
m_postProcessEntity->Activate();
// Init directional light processor // Init directional light processor
m_directionalLightFeatureProcessor = m_scene->GetFeatureProcessor<AZ::Render::DirectionalLightFeatureProcessorInterface>(); m_directionalLightFeatureProcessor = m_scene->GetFeatureProcessor<AZ::Render::DirectionalLightFeatureProcessorInterface>();
@ -155,33 +153,19 @@ namespace MaterialEditor
m_skyboxFeatureProcessor->SetSkyboxMode(AZ::Render::SkyBoxMode::Cubemap); m_skyboxFeatureProcessor->SetSkyboxMode(AZ::Render::SkyBoxMode::Cubemap);
// Create IBL // Create IBL
AzFramework::EntityContextRequestBus::EventResult( m_iblEntity =
m_iblEntity, entityContextId, &AzFramework::EntityContextRequestBus::Events::CreateEntity, "IblEntity"); CreateEntity("IblEntity", { AZ::Render::ImageBasedLightComponentTypeId, azrtti_typeid<AzFramework::TransformComponent>() });
AZ_Assert(m_iblEntity != nullptr, "Failed to create ibl entity.");
m_iblEntity->CreateComponent(AZ::Render::ImageBasedLightComponentTypeId);
m_iblEntity->CreateComponent(azrtti_typeid<AzFramework::TransformComponent>());
m_iblEntity->Activate();
// Create model // Create model
AzFramework::EntityContextRequestBus::EventResult( m_modelEntity = CreateEntity(
m_modelEntity, entityContextId, &AzFramework::EntityContextRequestBus::Events::CreateEntity, "ViewportModel"); "ViewportModel",
AZ_Assert(m_modelEntity != nullptr, "Failed to create model entity."); { AZ::Render::MeshComponentTypeId, AZ::Render::MaterialComponentTypeId, azrtti_typeid<AzFramework::TransformComponent>() });
m_modelEntity->CreateComponent(AZ::Render::MeshComponentTypeId);
m_modelEntity->CreateComponent(AZ::Render::MaterialComponentTypeId);
m_modelEntity->CreateComponent(azrtti_typeid<AzFramework::TransformComponent>());
m_modelEntity->Activate();
// Create shadow catcher // Create shadow catcher
AzFramework::EntityContextRequestBus::EventResult( m_shadowCatcherEntity = CreateEntity(
m_shadowCatcherEntity, entityContextId, &AzFramework::EntityContextRequestBus::Events::CreateEntity, "ViewportShadowCatcher"); "ViewportShadowCatcher",
AZ_Assert(m_shadowCatcherEntity != nullptr, "Failed to create shadow catcher entity."); { AZ::Render::MeshComponentTypeId, AZ::Render::MaterialComponentTypeId, azrtti_typeid<AzFramework::TransformComponent>(),
m_shadowCatcherEntity->CreateComponent(AZ::Render::MeshComponentTypeId); azrtti_typeid<AzFramework::NonUniformScaleComponent>() });
m_shadowCatcherEntity->CreateComponent(AZ::Render::MaterialComponentTypeId);
m_shadowCatcherEntity->CreateComponent(azrtti_typeid<AzFramework::TransformComponent>());
m_shadowCatcherEntity->CreateComponent(azrtti_typeid<AzFramework::NonUniformScaleComponent>());
m_shadowCatcherEntity->Activate();
AZ::NonUniformScaleRequestBus::Event( AZ::NonUniformScaleRequestBus::Event(
m_shadowCatcherEntity->GetId(), &AZ::NonUniformScaleRequests::SetScale, AZ::Vector3{ 100, 100, 1.0 }); m_shadowCatcherEntity->GetId(), &AZ::NonUniformScaleRequests::SetScale, AZ::Vector3{ 100, 100, 1.0 });
@ -214,21 +198,19 @@ namespace MaterialEditor
} }
// Create grid // Create grid
AzFramework::EntityContextRequestBus::EventResult( m_gridEntity = CreateEntity("ViewportGrid", { AZ::Render::GridComponentTypeId, azrtti_typeid<AzFramework::TransformComponent>() });
m_gridEntity, entityContextId, &AzFramework::EntityContextRequestBus::Events::CreateEntity, "ViewportGrid");
AZ_Assert(m_gridEntity != nullptr, "Failed to create grid entity.");
AZ::Render::GridComponentConfig gridConfig; AZ::Render::GridComponentConfig gridConfig;
gridConfig.m_gridSize = 4.0f; gridConfig.m_gridSize = 4.0f;
gridConfig.m_axisColor = AZ::Color(0.1f, 0.1f, 0.1f, 1.0f); gridConfig.m_axisColor = AZ::Color(0.1f, 0.1f, 0.1f, 1.0f);
gridConfig.m_primaryColor = AZ::Color(0.1f, 0.1f, 0.1f, 1.0f); gridConfig.m_primaryColor = AZ::Color(0.1f, 0.1f, 0.1f, 1.0f);
gridConfig.m_secondaryColor = AZ::Color(0.1f, 0.1f, 0.1f, 1.0f); gridConfig.m_secondaryColor = AZ::Color(0.1f, 0.1f, 0.1f, 1.0f);
auto gridComponent = m_gridEntity->CreateComponent(AZ::Render::GridComponentTypeId); m_gridEntity->Deactivate();
gridComponent->SetConfiguration(gridConfig); m_gridEntity->FindComponent(AZ::Render::GridComponentTypeId)->SetConfiguration(gridConfig);
m_gridEntity->CreateComponent(azrtti_typeid<AzFramework::TransformComponent>());
m_gridEntity->Activate(); m_gridEntity->Activate();
SetupInputController();
OnDocumentOpened(AZ::Uuid::CreateNull()); OnDocumentOpened(AZ::Uuid::CreateNull());
// Attempt to apply the default lighting preset // Attempt to apply the default lighting preset
@ -241,8 +223,6 @@ namespace MaterialEditor
MaterialViewportRequestBus::BroadcastResult(modelPreset, &MaterialViewportRequestBus::Events::GetModelPresetSelection); MaterialViewportRequestBus::BroadcastResult(modelPreset, &MaterialViewportRequestBus::Events::GetModelPresetSelection);
OnModelPresetSelected(modelPreset); OnModelPresetSelected(modelPreset);
m_viewportController->Init(m_cameraEntity->GetId(), m_modelEntity->GetId(), m_iblEntity->GetId());
// Apply user settinngs restored since last run // Apply user settinngs restored since last run
AZStd::intrusive_ptr<MaterialViewportSettings> viewportSettings = AZStd::intrusive_ptr<MaterialViewportSettings> viewportSettings =
AZ::UserSettings::CreateFind<MaterialViewportSettings>(AZ::Crc32("MaterialViewportSettings"), AZ::UserSettings::CT_GLOBAL); AZ::UserSettings::CreateFind<MaterialViewportSettings>(AZ::Crc32("MaterialViewportSettings"), AZ::UserSettings::CT_GLOBAL);
@ -257,8 +237,6 @@ namespace MaterialEditor
MaterialViewportNotificationBus::Handler::BusConnect(); MaterialViewportNotificationBus::Handler::BusConnect();
AZ::TickBus::Handler::BusConnect(); AZ::TickBus::Handler::BusConnect();
AZ::TransformNotificationBus::MultiHandler::BusConnect(m_cameraEntity->GetId()); AZ::TransformNotificationBus::MultiHandler::BusConnect(m_cameraEntity->GetId());
GetControllerList()->Add(m_viewportController);
} }
MaterialViewportWidget::~MaterialViewportWidget() MaterialViewportWidget::~MaterialViewportWidget()
@ -269,33 +247,12 @@ namespace MaterialEditor
MaterialViewportNotificationBus::Handler::BusDisconnect(); MaterialViewportNotificationBus::Handler::BusDisconnect();
AZ::Data::AssetBus::Handler::BusDisconnect(); AZ::Data::AssetBus::Handler::BusDisconnect();
AzFramework::EntityContextId entityContextId; DestroyEntity(m_iblEntity);
AzFramework::GameEntityContextRequestBus::BroadcastResult( DestroyEntity(m_modelEntity);
entityContextId, &AzFramework::GameEntityContextRequestBus::Events::GetGameEntityContextId); DestroyEntity(m_shadowCatcherEntity);
DestroyEntity(m_gridEntity);
AzFramework::EntityContextRequestBus::Event( DestroyEntity(m_cameraEntity);
entityContextId, &AzFramework::EntityContextRequestBus::Events::DestroyEntity, m_iblEntity); DestroyEntity(m_postProcessEntity);
m_iblEntity = nullptr;
AzFramework::EntityContextRequestBus::Event(
entityContextId, &AzFramework::EntityContextRequestBus::Events::DestroyEntity, m_modelEntity);
m_modelEntity = nullptr;
AzFramework::EntityContextRequestBus::Event(
entityContextId, &AzFramework::EntityContextRequestBus::Events::DestroyEntity, m_shadowCatcherEntity);
m_shadowCatcherEntity = nullptr;
AzFramework::EntityContextRequestBus::Event(
entityContextId, &AzFramework::EntityContextRequestBus::Events::DestroyEntity, m_gridEntity);
m_gridEntity = nullptr;
AzFramework::EntityContextRequestBus::Event(
entityContextId, &AzFramework::EntityContextRequestBus::Events::DestroyEntity, m_cameraEntity);
m_cameraEntity = nullptr;
AzFramework::EntityContextRequestBus::Event(
entityContextId, &AzFramework::EntityContextRequestBus::Events::DestroyEntity, m_postProcessEntity);
m_postProcessEntity = nullptr;
for (DirectionalLightHandle& handle : m_lightHandles) for (DirectionalLightHandle& handle : m_lightHandles)
{ {
@ -315,6 +272,74 @@ namespace MaterialEditor
m_scene = nullptr; m_scene = nullptr;
} }
AZ::Entity* MaterialViewportWidget::CreateEntity(const AZStd::string& name, const AZStd::vector<AZ::Uuid>& componentTypeIds)
{
AzFramework::EntityContextId entityContextId;
AzFramework::GameEntityContextRequestBus::BroadcastResult(
entityContextId, &AzFramework::GameEntityContextRequestBus::Events::GetGameEntityContextId);
AZ::Entity* entity = {};
AzFramework::EntityContextRequestBus::EventResult(
entity, entityContextId, &AzFramework::EntityContextRequestBus::Events::CreateEntity, name.c_str());
AZ_Assert(entity != nullptr, "Failed to create post process entity: %s.", name.c_str());
if (entity)
{
for (const auto& componentTypeId : componentTypeIds)
{
entity->CreateComponent(componentTypeId);
}
entity->Activate();
}
return entity;
}
void MaterialViewportWidget::DestroyEntity(AZ::Entity*& entity)
{
AzFramework::EntityContextId entityContextId;
AzFramework::GameEntityContextRequestBus::BroadcastResult(
entityContextId, &AzFramework::GameEntityContextRequestBus::Events::GetGameEntityContextId);
AzFramework::EntityContextRequestBus::Event(entityContextId, &AzFramework::EntityContextRequestBus::Events::DestroyEntity, entity);
entity = nullptr;
}
void MaterialViewportWidget::SetupInputController()
{
using namespace AtomToolsFramework;
// Create viewport input controller and regioster its behaviors
m_viewportController.reset(
aznew ViewportInputBehaviorController(m_cameraEntity->GetId(), m_modelEntity->GetId(), m_iblEntity->GetId()));
m_viewportController->AddBehavior(
ViewportInputBehaviorController::Lmb, AZStd::make_shared<PanCameraBehavior>(m_viewportController.get()));
m_viewportController->AddBehavior(
ViewportInputBehaviorController::Mmb, AZStd::make_shared<MoveCameraBehavior>(m_viewportController.get()));
m_viewportController->AddBehavior(
ViewportInputBehaviorController::Rmb, AZStd::make_shared<OrbitCameraBehavior>(m_viewportController.get()));
m_viewportController->AddBehavior(
ViewportInputBehaviorController::Alt ^ ViewportInputBehaviorController::Lmb,
AZStd::make_shared<OrbitCameraBehavior>(m_viewportController.get()));
m_viewportController->AddBehavior(
ViewportInputBehaviorController::Alt ^ ViewportInputBehaviorController::Mmb,
AZStd::make_shared<MoveCameraBehavior>(m_viewportController.get()));
m_viewportController->AddBehavior(
ViewportInputBehaviorController::Alt ^ ViewportInputBehaviorController::Rmb,
AZStd::make_shared<DollyCameraBehavior>(m_viewportController.get()));
m_viewportController->AddBehavior(
ViewportInputBehaviorController::Lmb ^ ViewportInputBehaviorController::Rmb,
AZStd::make_shared<DollyCameraBehavior>(m_viewportController.get()));
m_viewportController->AddBehavior(
ViewportInputBehaviorController::Ctrl ^ ViewportInputBehaviorController::Lmb,
AZStd::make_shared<RotateModelBehavior>(m_viewportController.get()));
m_viewportController->AddBehavior(
ViewportInputBehaviorController::Shift ^ ViewportInputBehaviorController::Lmb,
AZStd::make_shared<RotateEnvironmentBehavior>(m_viewportController.get()));
GetControllerList()->Add(m_viewportController);
}
void MaterialViewportWidget::OnDocumentOpened(const AZ::Uuid& documentId) void MaterialViewportWidget::OnDocumentOpened(const AZ::Uuid& documentId)
{ {
AZ::Data::Instance<AZ::RPI::Material> materialInstance; AZ::Data::Instance<AZ::RPI::Material> materialInstance;
@ -436,8 +461,7 @@ namespace MaterialEditor
void MaterialViewportWidget::OnFieldOfViewChanged(float fieldOfView) void MaterialViewportWidget::OnFieldOfViewChanged(float fieldOfView)
{ {
MaterialEditorViewportInputControllerRequestBus::Broadcast( m_viewportController->SetFieldOfView(fieldOfView);
&MaterialEditorViewportInputControllerRequestBus::Handler::SetFieldOfView, fieldOfView);
} }
void MaterialViewportWidget::OnDisplayMapperOperationTypeChanged(AZ::Render::DisplayMapperOperationType operationType) void MaterialViewportWidget::OnDisplayMapperOperationTypeChanged(AZ::Render::DisplayMapperOperationType operationType)
@ -451,7 +475,9 @@ namespace MaterialEditor
{ {
if (m_modelAssetId == asset.GetId()) if (m_modelAssetId == asset.GetId())
{ {
MaterialEditorViewportInputControllerRequestBus::Broadcast(&MaterialEditorViewportInputControllerRequestBus::Handler::Reset); AZ::Data::Asset<AZ::RPI::ModelAsset> modelAsset = asset;
m_viewportController->SetTargetBounds(modelAsset->GetAabb());
m_viewportController->Reset();
AZ::Data::AssetBus::Handler::BusDisconnect(asset.GetId()); AZ::Data::AssetBus::Handler::BusDisconnect(asset.GetId());
} }
} }

@ -15,9 +15,9 @@
#include <AtomCore/Instance/Instance.h> #include <AtomCore/Instance/Instance.h>
#include <AtomToolsFramework/Document/AtomToolsDocumentNotificationBus.h> #include <AtomToolsFramework/Document/AtomToolsDocumentNotificationBus.h>
#include <AtomToolsFramework/Viewport/RenderViewportWidget.h> #include <AtomToolsFramework/Viewport/RenderViewportWidget.h>
#include <AtomToolsFramework/Viewport/ViewportInputBehaviorController/ViewportInputBehaviorController.h>
#include <AzCore/Component/TransformBus.h> #include <AzCore/Component/TransformBus.h>
#include <AzFramework/Windowing/WindowBus.h> #include <AzFramework/Windowing/WindowBus.h>
#include <Viewport/InputController/MaterialEditorViewportInputController.h>
#include <Viewport/MaterialViewportNotificationBus.h> #include <Viewport/MaterialViewportNotificationBus.h>
AZ_PUSH_DISABLE_WARNING(4251 4800, "-Wunknown-warning-option") // disable warnings spawned by QT AZ_PUSH_DISABLE_WARNING(4251 4800, "-Wunknown-warning-option") // disable warnings spawned by QT
@ -61,6 +61,10 @@ namespace MaterialEditor
~MaterialViewportWidget(); ~MaterialViewportWidget();
private: private:
AZ::Entity* CreateEntity(const AZStd::string& name, const AZStd::vector<AZ::Uuid>& componentTypeIds);
void DestroyEntity(AZ::Entity*& entity);
void SetupInputController();
// AtomToolsFramework::AtomToolsDocumentNotificationBus::Handler interface overrides... // AtomToolsFramework::AtomToolsDocumentNotificationBus::Handler interface overrides...
void OnDocumentOpened(const AZ::Uuid& documentId) override; void OnDocumentOpened(const AZ::Uuid& documentId) override;
@ -96,8 +100,6 @@ namespace MaterialEditor
AZ::Render::DisplayMapperFeatureProcessorInterface* m_displayMapperFeatureProcessor = {}; AZ::Render::DisplayMapperFeatureProcessorInterface* m_displayMapperFeatureProcessor = {};
AZ::Entity* m_cameraEntity = {}; AZ::Entity* m_cameraEntity = {};
AZ::Component* m_cameraComponent = {};
AZ::Entity* m_postProcessEntity = {}; AZ::Entity* m_postProcessEntity = {};
AZ::Entity* m_modelEntity = {}; AZ::Entity* m_modelEntity = {};
@ -114,7 +116,7 @@ namespace MaterialEditor
AZ::Entity* m_iblEntity = {}; AZ::Entity* m_iblEntity = {};
AZ::Render::SkyBoxFeatureProcessorInterface* m_skyboxFeatureProcessor = {}; AZ::Render::SkyBoxFeatureProcessorInterface* m_skyboxFeatureProcessor = {};
AZStd::shared_ptr<MaterialEditorViewportInputController> m_viewportController; AZStd::shared_ptr<AtomToolsFramework::ViewportInputBehaviorController> m_viewportController;
QScopedPointer<Ui::MaterialViewportWidget> m_ui; QScopedPointer<Ui::MaterialViewportWidget> m_ui;
}; };

@ -17,28 +17,9 @@ set(FILES
Source/Viewport/MaterialViewportModule.h Source/Viewport/MaterialViewportModule.h
Source/Viewport/MaterialViewportModule.cpp Source/Viewport/MaterialViewportModule.cpp
Source/Viewport/InputController/MaterialEditorViewportInputControllerBus.h
Source/Viewport/MaterialViewportSettings.h Source/Viewport/MaterialViewportSettings.h
Source/Viewport/MaterialViewportRequestBus.h Source/Viewport/MaterialViewportRequestBus.h
Source/Viewport/MaterialViewportNotificationBus.h Source/Viewport/MaterialViewportNotificationBus.h
Source/Viewport/InputController/MaterialEditorViewportInputController.cpp
Source/Viewport/InputController/MaterialEditorViewportInputController.h
Source/Viewport/InputController/Behavior.cpp
Source/Viewport/InputController/Behavior.h
Source/Viewport/InputController/DollyCameraBehavior.cpp
Source/Viewport/InputController/DollyCameraBehavior.h
Source/Viewport/InputController/IdleBehavior.cpp
Source/Viewport/InputController/IdleBehavior.h
Source/Viewport/InputController/MoveCameraBehavior.cpp
Source/Viewport/InputController/MoveCameraBehavior.h
Source/Viewport/InputController/PanCameraBehavior.cpp
Source/Viewport/InputController/PanCameraBehavior.h
Source/Viewport/InputController/OrbitCameraBehavior.cpp
Source/Viewport/InputController/OrbitCameraBehavior.h
Source/Viewport/InputController/RotateEnvironmentBehavior.cpp
Source/Viewport/InputController/RotateEnvironmentBehavior.h
Source/Viewport/InputController/RotateModelBehavior.cpp
Source/Viewport/InputController/RotateModelBehavior.h
Source/Viewport/MaterialViewportSettings.cpp Source/Viewport/MaterialViewportSettings.cpp
Source/Viewport/MaterialViewportComponent.cpp Source/Viewport/MaterialViewportComponent.cpp
Source/Viewport/MaterialViewportComponent.h Source/Viewport/MaterialViewportComponent.h

Loading…
Cancel
Save