+3
@@ -96,7 +96,10 @@ namespace AtomToolsFramework
|
||||
void OnExceptionMessage(AZStd::string_view message) override;
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
//! Executable target name generally used as a prefix for logging and other saved files
|
||||
virtual AZStd::string GetBuildTargetName() const;
|
||||
|
||||
//! List of filters for assets that need to be pre-built to run the application
|
||||
virtual AZStd::vector<AZStd::string> GetCriticalAssetFilters() const;
|
||||
|
||||
virtual void LoadSettings();
|
||||
|
||||
+61
-26
@@ -16,37 +16,62 @@
|
||||
|
||||
namespace AtomToolsFramework
|
||||
{
|
||||
class ModernViewportCameraControllerInstance;
|
||||
class ModularViewportCameraControllerInstance;
|
||||
|
||||
//! A function object to represent returning a camera controller priority.
|
||||
using CameraControllerPriorityFn =
|
||||
AZStd::function<AzFramework::ViewportControllerPriority(const AzFramework::CameraSystem& cameraSystem)>;
|
||||
|
||||
//! The default behavior for what priority the camera controller should respond to events at.
|
||||
//! @note This can change based on the state of the camera controller/system.
|
||||
AzFramework::ViewportControllerPriority DefaultCameraControllerPriority(const AzFramework::CameraSystem& cameraSystem);
|
||||
|
||||
//! Builder class to create and configure a ModularViewportCameraControllerInstance.
|
||||
class ModularViewportCameraController
|
||||
: public AzFramework::MultiViewportController<
|
||||
ModernViewportCameraControllerInstance, AzFramework::ViewportControllerPriority::DispatchToAllPriorities>
|
||||
ModularViewportCameraControllerInstance,
|
||||
AzFramework::ViewportControllerPriority::DispatchToAllPriorities>
|
||||
{
|
||||
public:
|
||||
friend ModularViewportCameraControllerInstance;
|
||||
|
||||
using CameraListBuilder = AZStd::function<void(AzFramework::Cameras&)>;
|
||||
using CameraPropsBuilder = AZStd::function<void(AzFramework::CameraProps&)>;
|
||||
using CameraPriorityBuilder = AZStd::function<void(CameraControllerPriorityFn&)>;
|
||||
|
||||
//! Sets the camera list builder callback used to populate new ModernViewportCameraControllerInstances
|
||||
//! Sets the camera list builder callback used to populate new ModularViewportCameraControllerInstances.
|
||||
void SetCameraListBuilderCallback(const CameraListBuilder& builder);
|
||||
//! Sets the camera props builder callback used to populate new ModernViewportCameraControllerInstances
|
||||
//! Sets the camera props builder callback used to populate new ModularViewportCameraControllerInstances.
|
||||
void SetCameraPropsBuilderCallback(const CameraPropsBuilder& builder);
|
||||
//! Sets up a camera list based on this controller's CameraListBuilderCallback
|
||||
void SetupCameras(AzFramework::Cameras& cameras);
|
||||
//! Sets up properties shared across all cameras
|
||||
void SetupCameraProperies(AzFramework::CameraProps& cameraProps);
|
||||
//! Sets the camera controller priority builder callback used to populate new ModularViewportCameraControllerInstances.
|
||||
void SetCameraPriorityBuilderCallback(const CameraPriorityBuilder& builder);
|
||||
|
||||
private:
|
||||
//! Sets up a camera list based on this controller's CameraListBuilderCallback.
|
||||
void SetupCameras(AzFramework::Cameras& cameras);
|
||||
//! Sets up properties shared across all cameras.
|
||||
void SetupCameraProperties(AzFramework::CameraProps& cameraProps);
|
||||
//! Sets up how the camera controller should decide at what priority level to respond to.
|
||||
void SetupCameraControllerPriority(CameraControllerPriorityFn& cameraPriorityFn);
|
||||
|
||||
//! Builder to generate a list of CameraInputs to run in the ModularViewportCameraControllerInstance.
|
||||
CameraListBuilder m_cameraListBuilder;
|
||||
//! Builder to define custom camera properties to use for things such as rotate and translate interpolation.
|
||||
CameraPropsBuilder m_cameraPropsBuilder;
|
||||
//! Builder to define what priority level the camera controller should respond to events at.
|
||||
CameraPriorityBuilder m_cameraControllerPriorityBuilder;
|
||||
};
|
||||
|
||||
class ModernViewportCameraControllerInstance final
|
||||
: public AzFramework::MultiViewportControllerInstanceInterface<ModularViewportCameraController>,
|
||||
public ModularViewportCameraControllerRequestBus::Handler,
|
||||
private AzFramework::ViewportDebugDisplayEventBus::Handler
|
||||
//! A customizable camera controller that can be configured to run a varying set of CameraInput instances.
|
||||
//! The controller can also be animated from its current transform to a new translation and orientation.
|
||||
class ModularViewportCameraControllerInstance final
|
||||
: public AzFramework::MultiViewportControllerInstanceInterface<ModularViewportCameraController>
|
||||
, public ModularViewportCameraControllerRequestBus::Handler
|
||||
, private AzFramework::ViewportDebugDisplayEventBus::Handler
|
||||
{
|
||||
public:
|
||||
explicit ModernViewportCameraControllerInstance(AzFramework::ViewportId viewportId, ModularViewportCameraController* controller);
|
||||
~ModernViewportCameraControllerInstance() override;
|
||||
explicit ModularViewportCameraControllerInstance(AzFramework::ViewportId viewportId, ModularViewportCameraController* controller);
|
||||
~ModularViewportCameraControllerInstance() override;
|
||||
|
||||
// MultiViewportControllerInstanceInterface overrides ...
|
||||
bool HandleInputChannelEvent(const AzFramework::ViewportControllerInputEvent& event) override;
|
||||
@@ -60,25 +85,35 @@ namespace AtomToolsFramework
|
||||
// AzFramework::ViewportDebugDisplayEventBus overrides ...
|
||||
void DisplayViewport(const AzFramework::ViewportInfo& viewportInfo, AzFramework::DebugDisplayRequests& debugDisplay) override;
|
||||
|
||||
//! The current mode the camera controller is in.
|
||||
enum class CameraMode
|
||||
{
|
||||
Control,
|
||||
Animation
|
||||
Control, //!< The camera is being driven by user input.
|
||||
Animation //!< The camera is being animated (interpolated) from one transform to another.
|
||||
};
|
||||
|
||||
AzFramework::Camera m_camera;
|
||||
AzFramework::Camera m_targetCamera;
|
||||
AzFramework::CameraSystem m_cameraSystem;
|
||||
AzFramework::CameraProps m_cameraProps;
|
||||
//! Encapsulates an animation (interpolation) between two transforms.
|
||||
struct CameraAnimation
|
||||
{
|
||||
//! The transform of the camera at the start of the animation.
|
||||
AZ::Transform m_transformStart = AZ::Transform::CreateIdentity();
|
||||
AZ::Transform m_transformEnd = AZ::Transform::CreateIdentity(); //!< The transform of the camera at the end of the animation.
|
||||
float m_time = 0.0f; //!< The interpolation amount between the start and end transforms (in the range 0.0 - 1.0).
|
||||
};
|
||||
|
||||
AZ::Transform m_transformStart = AZ::Transform::CreateIdentity();
|
||||
AZ::Transform m_transformEnd = AZ::Transform::CreateIdentity();
|
||||
float m_animationT = 0.0f;
|
||||
CameraMode m_cameraMode = CameraMode::Control;
|
||||
AzFramework::Camera m_camera; //!< The current camera state (pitch/yaw/position/look-distance).
|
||||
AzFramework::Camera m_targetCamera; //!< The target (next) camera state that m_camera is catching up to.
|
||||
AzFramework::CameraSystem m_cameraSystem; //!< The camera system responsible for managing all CameraInputs.
|
||||
AzFramework::CameraProps m_cameraProps; //!< Camera properties to control rotate and translate smoothness.
|
||||
CameraControllerPriorityFn m_priorityFn; //!< Controls at what priority the camera controller should respond to events.
|
||||
|
||||
CameraAnimation m_cameraAnimation; //!< Camera animation state (used during CameraMode::Animation).
|
||||
CameraMode m_cameraMode = CameraMode::Control; //!< The current mode the camera is operating in.
|
||||
AZStd::optional<AZ::Vector3> m_lookAtAfterInterpolation; //!< The look at point after an interpolation has finished.
|
||||
//!< Will be cleared when the view changes (camera looks away).
|
||||
bool m_updatingTransform = false;
|
||||
|
||||
//! Flag to prevent circular updates of the camera transform (while the viewport transform is being updated internally).
|
||||
bool m_updatingTransformInternally = false;
|
||||
//! Listen for camera view changes outside of the camera controller.
|
||||
AZ::RPI::ViewportContext::MatrixChangedEvent::Handler m_cameraViewMatrixChangeHandler;
|
||||
};
|
||||
} // namespace AtomToolsFramework
|
||||
|
||||
+52
-37
@@ -68,6 +68,11 @@ namespace AtomToolsFramework
|
||||
m_cameraPropsBuilder = builder;
|
||||
}
|
||||
|
||||
void ModularViewportCameraController::SetCameraPriorityBuilderCallback(const CameraPriorityBuilder& builder)
|
||||
{
|
||||
m_cameraControllerPriorityBuilder = builder;
|
||||
}
|
||||
|
||||
void ModularViewportCameraController::SetupCameras(AzFramework::Cameras& cameras)
|
||||
{
|
||||
if (m_cameraListBuilder)
|
||||
@@ -76,7 +81,7 @@ namespace AtomToolsFramework
|
||||
}
|
||||
}
|
||||
|
||||
void ModularViewportCameraController::SetupCameraProperies(AzFramework::CameraProps& cameraProps)
|
||||
void ModularViewportCameraController::SetupCameraProperties(AzFramework::CameraProps& cameraProps)
|
||||
{
|
||||
if (m_cameraPropsBuilder)
|
||||
{
|
||||
@@ -84,18 +89,43 @@ namespace AtomToolsFramework
|
||||
}
|
||||
}
|
||||
|
||||
ModernViewportCameraControllerInstance::ModernViewportCameraControllerInstance(
|
||||
void ModularViewportCameraController::SetupCameraControllerPriority(CameraControllerPriorityFn& cameraPriorityFn)
|
||||
{
|
||||
if (m_cameraControllerPriorityBuilder)
|
||||
{
|
||||
m_cameraControllerPriorityBuilder(cameraPriorityFn);
|
||||
}
|
||||
}
|
||||
|
||||
// what priority should the camera system respond to
|
||||
AzFramework::ViewportControllerPriority DefaultCameraControllerPriority(const AzFramework::CameraSystem& cameraSystem)
|
||||
{
|
||||
// ModernViewportCameraControllerInstance receives events at all priorities, when it is in 'exclusive' mode
|
||||
// or it is actively handling events (essentially when the camera system is 'active' and responding to inputs)
|
||||
// it should only respond to the highest priority
|
||||
if (cameraSystem.m_cameras.Exclusive() || cameraSystem.HandlingEvents())
|
||||
{
|
||||
return AzFramework::ViewportControllerPriority::Highest;
|
||||
}
|
||||
|
||||
// otherwise it should only respond to normal priority events
|
||||
return AzFramework::ViewportControllerPriority::Normal;
|
||||
}
|
||||
|
||||
ModularViewportCameraControllerInstance::ModularViewportCameraControllerInstance(
|
||||
const AzFramework::ViewportId viewportId, ModularViewportCameraController* controller)
|
||||
: MultiViewportControllerInstanceInterface<ModularViewportCameraController>(viewportId, controller)
|
||||
{
|
||||
controller->SetupCameras(m_cameraSystem.m_cameras);
|
||||
controller->SetupCameraProperies(m_cameraProps);
|
||||
controller->SetupCameraProperties(m_cameraProps);
|
||||
controller->SetupCameraControllerPriority(m_priorityFn);
|
||||
|
||||
if (auto viewportContext = RetrieveViewportContext(GetViewportId()))
|
||||
{
|
||||
auto handleCameraChange = [this, viewportContext](const AZ::Matrix4x4&)
|
||||
{
|
||||
if (!m_updatingTransform)
|
||||
// ignore these updates if the camera is being updated internally
|
||||
if (!m_updatingTransformInternally)
|
||||
{
|
||||
UpdateCameraFromTransform(m_targetCamera, viewportContext->GetCameraTransform());
|
||||
m_camera = m_targetCamera;
|
||||
@@ -111,30 +141,15 @@ namespace AtomToolsFramework
|
||||
ModularViewportCameraControllerRequestBus::Handler::BusConnect(viewportId);
|
||||
}
|
||||
|
||||
ModernViewportCameraControllerInstance::~ModernViewportCameraControllerInstance()
|
||||
ModularViewportCameraControllerInstance::~ModularViewportCameraControllerInstance()
|
||||
{
|
||||
ModularViewportCameraControllerRequestBus::Handler::BusDisconnect();
|
||||
AzFramework::ViewportDebugDisplayEventBus::Handler::BusDisconnect();
|
||||
}
|
||||
|
||||
// what priority should the camera system respond to
|
||||
static AzFramework::ViewportControllerPriority GetPriority(const AzFramework::CameraSystem& cameraSystem)
|
||||
bool ModularViewportCameraControllerInstance::HandleInputChannelEvent(const AzFramework::ViewportControllerInputEvent& event)
|
||||
{
|
||||
// ModernViewportCameraControllerInstance receives events at all priorities, when it is in 'exclusive' mode
|
||||
// or it is actively handling events (essentially when the camera system is 'active' and responding to inputs)
|
||||
// it should only respond to the highest priority
|
||||
if (cameraSystem.m_cameras.Exclusive() || cameraSystem.HandlingEvents())
|
||||
{
|
||||
return AzFramework::ViewportControllerPriority::Highest;
|
||||
}
|
||||
|
||||
// otherwise it should only respond to normal priority events
|
||||
return AzFramework::ViewportControllerPriority::Normal;
|
||||
}
|
||||
|
||||
bool ModernViewportCameraControllerInstance::HandleInputChannelEvent(const AzFramework::ViewportControllerInputEvent& event)
|
||||
{
|
||||
if (event.m_priority == GetPriority(m_cameraSystem))
|
||||
if (event.m_priority == m_priorityFn(m_cameraSystem))
|
||||
{
|
||||
return m_cameraSystem.HandleEvents(AzFramework::BuildInputEvent(event.m_inputChannel));
|
||||
}
|
||||
@@ -142,7 +157,7 @@ namespace AtomToolsFramework
|
||||
return false;
|
||||
}
|
||||
|
||||
void ModernViewportCameraControllerInstance::UpdateViewport(const AzFramework::ViewportControllerUpdateEvent& event)
|
||||
void ModularViewportCameraControllerInstance::UpdateViewport(const AzFramework::ViewportControllerUpdateEvent& event)
|
||||
{
|
||||
// only update for a single priority (normal is the default)
|
||||
if (event.m_priority != AzFramework::ViewportControllerPriority::Normal)
|
||||
@@ -152,7 +167,7 @@ namespace AtomToolsFramework
|
||||
|
||||
if (auto viewportContext = RetrieveViewportContext(GetViewportId()))
|
||||
{
|
||||
m_updatingTransform = true;
|
||||
m_updatingTransformInternally = true;
|
||||
|
||||
if (m_cameraMode == CameraMode::Control)
|
||||
{
|
||||
@@ -180,10 +195,12 @@ namespace AtomToolsFramework
|
||||
return t * t * t * (t * (t * 6.0f - 15.0f) + 10.0f);
|
||||
};
|
||||
|
||||
const float transitionT = smootherStepFn(m_animationT);
|
||||
const auto& [transformStart, transformEnd, animationTime] = m_cameraAnimation;
|
||||
|
||||
const float transitionTime = smootherStepFn(animationTime);
|
||||
const AZ::Transform current = AZ::Transform::CreateFromQuaternionAndTranslation(
|
||||
m_transformStart.GetRotation().Slerp(m_transformEnd.GetRotation(), transitionT),
|
||||
m_transformStart.GetTranslation().Lerp(m_transformEnd.GetTranslation(), transitionT));
|
||||
transformStart.GetRotation().Slerp(transformEnd.GetRotation(), transitionTime),
|
||||
transformStart.GetTranslation().Lerp(transformEnd.GetTranslation(), transitionTime));
|
||||
|
||||
const AZ::Vector3 eulerAngles = AzFramework::EulerAngles(AZ::Matrix3x3::CreateFromTransform(current));
|
||||
m_camera.m_pitch = eulerAngles.GetX();
|
||||
@@ -191,21 +208,21 @@ namespace AtomToolsFramework
|
||||
m_camera.m_lookAt = current.GetTranslation();
|
||||
m_targetCamera = m_camera;
|
||||
|
||||
if (m_animationT >= 1.0f)
|
||||
if (animationTime >= 1.0f)
|
||||
{
|
||||
m_cameraMode = CameraMode::Control;
|
||||
}
|
||||
|
||||
m_animationT = AZ::GetClamp(m_animationT + event.m_deltaTime.count(), 0.0f, 1.0f);
|
||||
m_cameraAnimation.m_time = AZ::GetClamp(animationTime + event.m_deltaTime.count(), 0.0f, 1.0f);
|
||||
|
||||
viewportContext->SetCameraTransform(current);
|
||||
}
|
||||
|
||||
m_updatingTransform = false;
|
||||
m_updatingTransformInternally = false;
|
||||
}
|
||||
}
|
||||
|
||||
void ModernViewportCameraControllerInstance::DisplayViewport(
|
||||
void ModularViewportCameraControllerInstance::DisplayViewport(
|
||||
[[maybe_unused]] const AzFramework::ViewportInfo& viewportInfo, AzFramework::DebugDisplayRequests& debugDisplay)
|
||||
{
|
||||
if (const float alpha = AZStd::min(-m_camera.m_lookDist / 5.0f, 1.0f); alpha > AZ::Constants::FloatEpsilon)
|
||||
@@ -216,16 +233,14 @@ namespace AtomToolsFramework
|
||||
}
|
||||
}
|
||||
|
||||
void ModernViewportCameraControllerInstance::InterpolateToTransform(const AZ::Transform& worldFromLocal, const float lookAtDistance)
|
||||
void ModularViewportCameraControllerInstance::InterpolateToTransform(const AZ::Transform& worldFromLocal, const float lookAtDistance)
|
||||
{
|
||||
m_animationT = 0.0f;
|
||||
m_cameraMode = CameraMode::Animation;
|
||||
m_transformStart = m_camera.Transform();
|
||||
m_transformEnd = worldFromLocal;
|
||||
m_lookAtAfterInterpolation = m_transformEnd.GetTranslation() + m_transformEnd.GetBasisY() * lookAtDistance;
|
||||
m_cameraAnimation = CameraAnimation{ m_camera.Transform(), worldFromLocal, 0.0f };
|
||||
m_lookAtAfterInterpolation = worldFromLocal.GetTranslation() + worldFromLocal.GetBasisY() * lookAtDistance;
|
||||
}
|
||||
|
||||
AZStd::optional<AZ::Vector3> ModernViewportCameraControllerInstance::LookAtAfterInterpolation() const
|
||||
AZStd::optional<AZ::Vector3> ModularViewportCameraControllerInstance::LookAtAfterInterpolation() const
|
||||
{
|
||||
return m_lookAtAfterInterpolation;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user