Make camera controller priority customizable (#2826)

* make 'should handle' logic customizable

Signed-off-by: hultonha <hultonha@amazon.co.uk>

* updates to get priority function

Signed-off-by: hultonha <hultonha@amazon.co.uk>

* minor comment tweak

Signed-off-by: hultonha <hultonha@amazon.co.uk>
This commit is contained in:
hultonha
2021-08-05 09:45:03 +01:00
committed by GitHub
parent 7404622b48
commit 1169c82b98
3 changed files with 66 additions and 26 deletions
+7
View File
@@ -1240,6 +1240,13 @@ AZStd::shared_ptr<AtomToolsFramework::ModularViewportCameraController> CreateMod
AzFramework::ViewportId viewportId)
{
auto controller = AZStd::make_shared<AtomToolsFramework::ModularViewportCameraController>();
controller->SetCameraPriorityBuilderCallback(
[](AtomToolsFramework::CameraControllerPriorityFn& cameraControllerPriorityFn)
{
cameraControllerPriorityFn = AtomToolsFramework::DefaultCameraControllerPriority;
});
controller->SetCameraPropsBuilderCallback(
[](AzFramework::CameraProps& cameraProps)
{
@@ -18,6 +18,14 @@ namespace AtomToolsFramework
{
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<
@@ -25,23 +33,33 @@ namespace AtomToolsFramework
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 ModularViewportCameraControllerInstances
//! 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 ModularViewportCameraControllerInstances
//! 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;
CameraPropsBuilder m_cameraPropsBuilder; //!< Builder to define custom camera properties to use for things such as rotate and
//!< translate interpolation.
//! 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;
};
//! A customizable camera controller that can be configured to run a varying set of CameraInput instances.
@@ -87,6 +105,7 @@ namespace AtomToolsFramework
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.
@@ -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,12 +89,36 @@ namespace AtomToolsFramework
}
}
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()))
{
@@ -118,24 +147,9 @@ namespace AtomToolsFramework
AzFramework::ViewportDebugDisplayEventBus::Handler::BusDisconnect();
}
// what priority should the camera system respond to
static AzFramework::ViewportControllerPriority GetPriority(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;
}
bool ModularViewportCameraControllerInstance::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));
}