API documentation pass for CameraInput types (#1681)
* add api comments for new camera system Signed-off-by: hultonha <hultonha@amazon.co.uk>
This commit is contained in:
committed by
GitHub
parent
69f2e06134
commit
8d35f31fa6
@@ -284,6 +284,16 @@ namespace AzFramework
|
||||
m_idleCameraInputs.clear();
|
||||
}
|
||||
|
||||
bool Cameras::Exclusive() const
|
||||
{
|
||||
return AZStd::any_of(
|
||||
m_activeCameraInputs.begin(), m_activeCameraInputs.end(),
|
||||
[](const auto& cameraInput)
|
||||
{
|
||||
return cameraInput->Exclusive();
|
||||
});
|
||||
}
|
||||
|
||||
RotateCameraInput::RotateCameraInput(const InputChannelId rotateChannelId)
|
||||
: m_rotateChannelId(rotateChannelId)
|
||||
{
|
||||
@@ -361,7 +371,7 @@ namespace AzFramework
|
||||
};
|
||||
|
||||
nextCamera.m_yaw = clampRotation(nextCamera.m_yaw);
|
||||
// clamp pitch to be +-90 degrees
|
||||
// clamp pitch to be +/-90 degrees
|
||||
nextCamera.m_pitch = AZ::GetClamp(nextCamera.m_pitch, -AZ::Constants::HalfPi, AZ::Constants::HalfPi);
|
||||
|
||||
return nextCamera;
|
||||
@@ -428,7 +438,7 @@ namespace AzFramework
|
||||
return nextCamera;
|
||||
}
|
||||
|
||||
TranslateCameraInput::TranslationType TranslateCameraInput::translationFromKey(InputChannelId channelId)
|
||||
TranslateCameraInput::TranslationType TranslateCameraInput::TranslationFromKey(InputChannelId channelId)
|
||||
{
|
||||
if (channelId == CameraTranslateForwardId)
|
||||
{
|
||||
@@ -484,7 +494,7 @@ namespace AzFramework
|
||||
{
|
||||
if (input->m_state == InputChannel::State::Began)
|
||||
{
|
||||
m_translation |= translationFromKey(input->m_channelId);
|
||||
m_translation |= TranslationFromKey(input->m_channelId);
|
||||
if (m_translation != TranslationType::Nil)
|
||||
{
|
||||
BeginActivation();
|
||||
@@ -498,7 +508,7 @@ namespace AzFramework
|
||||
// ensure we don't process end events in the idle state
|
||||
else if (input->m_state == InputChannel::State::Ended && !Idle())
|
||||
{
|
||||
m_translation &= ~(translationFromKey(input->m_channelId));
|
||||
m_translation &= ~(TranslationFromKey(input->m_channelId));
|
||||
if (m_translation == TranslationType::Nil)
|
||||
{
|
||||
EndActivation();
|
||||
|
||||
@@ -23,22 +23,26 @@
|
||||
|
||||
namespace AzFramework
|
||||
{
|
||||
//! Update camera key bindings that can be overridden with AZ console vars (invoke from console to update)
|
||||
//! Updates camera key bindings that can be overridden with AZ console vars (invoke from console to update).
|
||||
void ReloadCameraKeyBindings();
|
||||
|
||||
//! Return Euler angles (pitch, roll, yaw) for the incoming orientation.
|
||||
//! Returns Euler angles (pitch, roll, yaw) for the incoming orientation.
|
||||
//! @note Order of rotation is Z, Y, X.
|
||||
AZ::Vector3 EulerAngles(const AZ::Matrix3x3& orientation);
|
||||
|
||||
//! A simple camera representation using spherical coordinates as input (pitch, yaw and look distance).
|
||||
//! The cameras transform and view can be obtained through accessor functions that use the internal
|
||||
//! spherical coordinates to calculate the position and orientation.
|
||||
struct Camera
|
||||
{
|
||||
AZ::Vector3 m_lookAt = AZ::Vector3::CreateZero(); //!< Position of camera when m_lookDist is zero,
|
||||
//!< or position of m_lookAt when m_lookDist is greater
|
||||
//!< than zero.
|
||||
float m_yaw{ 0.0 };
|
||||
float m_pitch{ 0.0 };
|
||||
float m_yaw{ 0.0 }; //!< Yaw rotation of camera (stored in radians) usually clamped to 0-360 degrees (0-2Pi radians).
|
||||
float m_pitch{ 0.0 }; //!< Pitch rotation of the camera (stored in radians) usually clamped to +/-90 degrees (-Pi/2 - Pi/2 radians).
|
||||
float m_lookDist{ 0.0 }; //!< Zero gives first person free look, otherwise orbit about m_lookAt
|
||||
|
||||
//! View camera transform (v in MVP).
|
||||
//! View camera transform (V in model-view-projection matrix (MVP)).
|
||||
AZ::Transform View() const;
|
||||
//! World camera transform.
|
||||
AZ::Transform Transform() const;
|
||||
@@ -69,9 +73,10 @@ namespace AzFramework
|
||||
return Transform().GetTranslation();
|
||||
}
|
||||
|
||||
//! Extracts Euler angles (orientation) and translation from the transform and writes the values to the camera.
|
||||
void UpdateCameraFromTransform(Camera& camera, const AZ::Transform& transform);
|
||||
|
||||
//! Generic motion type
|
||||
//! Generic motion type.
|
||||
template<typename MotionTag>
|
||||
struct MotionEvent
|
||||
{
|
||||
@@ -86,35 +91,44 @@ namespace AzFramework
|
||||
float m_delta;
|
||||
};
|
||||
|
||||
//! Represents an input event which occurs as a discrete change in state (e.g. button down, button up) rather than a continuous stream.
|
||||
//! @note Such as a key press with a down/up event as opposed to a continuous delta.
|
||||
struct DiscreteInputEvent
|
||||
{
|
||||
InputChannelId m_channelId; //!< Channel type. (e.g. Keyboard key, mouse button or other device input).
|
||||
InputChannel::State m_state; //!< Channel state. (e.g. Begin/update/end event).
|
||||
};
|
||||
|
||||
//! Represents a type-safe union of input events that are handled by the camera system.
|
||||
using InputEvent = AZStd::variant<AZStd::monostate, HorizontalMotionEvent, VerticalMotionEvent, ScrollEvent, DiscreteInputEvent>;
|
||||
|
||||
//! Base class for all camera behaviors.
|
||||
//! The core interface consists of:
|
||||
//! HandleEvents, used to receive and process incoming input events to begin, update and end a behavior.
|
||||
//! StepCamera, to update the current camera transform (position and orientation).
|
||||
class CameraInput
|
||||
{
|
||||
public:
|
||||
//! The state of activation the camera input is currently in.
|
||||
//! State changes of Activation: Idle -> Beginning -> Active -> Ending -> Idle
|
||||
enum class Activation
|
||||
{
|
||||
Idle,
|
||||
Begin,
|
||||
Active,
|
||||
End
|
||||
Idle, //!< Camera input is not currently active (initial state and transitioned to from Ending).
|
||||
Beginning, //!< Camera input is just beginning (transitioned to from Idle).
|
||||
Active, //!< Camera input is currently active and running (transitioned to from Beginning).
|
||||
Ending //!< Camera input is ending and will return to idle (transitioned to from Active).
|
||||
};
|
||||
|
||||
virtual ~CameraInput() = default;
|
||||
|
||||
bool Beginning() const
|
||||
{
|
||||
return m_activation == Activation::Begin;
|
||||
return m_activation == Activation::Beginning;
|
||||
}
|
||||
|
||||
bool Ending() const
|
||||
{
|
||||
return m_activation == Activation::End;
|
||||
return m_activation == Activation::Ending;
|
||||
}
|
||||
|
||||
bool Idle() const
|
||||
@@ -129,12 +143,12 @@ namespace AzFramework
|
||||
|
||||
void BeginActivation()
|
||||
{
|
||||
m_activation = Activation::Begin;
|
||||
m_activation = Activation::Beginning;
|
||||
}
|
||||
|
||||
void EndActivation()
|
||||
{
|
||||
m_activation = Activation::End;
|
||||
m_activation = Activation::Ending;
|
||||
}
|
||||
|
||||
void ContinueActivation()
|
||||
@@ -153,38 +167,56 @@ namespace AzFramework
|
||||
ResetImpl();
|
||||
}
|
||||
|
||||
//! Respond to input events to transition a camera input to active, handle input while running, and restore to idle when input ends.
|
||||
virtual bool HandleEvents(const InputEvent& event, const ScreenVector& cursorDelta, float scrollDelta) = 0;
|
||||
//! Use processed input events to update the state of the camera.
|
||||
//! @note targetCamera is the current target camera at the beginning of an update. The returned camera is the targetCamera + some
|
||||
//! delta to get to the next camera position and/or orientation.
|
||||
virtual Camera StepCamera(const Camera& targetCamera, const ScreenVector& cursorDelta, float scrollDelta, float deltaTime) = 0;
|
||||
|
||||
//! It is usually possible for one to many camera inputs to be running at the same time (the default), it is however possible to
|
||||
//! to make a camera input 'exclusive', so only it can run at a time. This implies that all other behaviors must have stopped before
|
||||
//! it can begin, and no other camera input can run while it is active.
|
||||
virtual bool Exclusive() const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
protected:
|
||||
//! Handle any state reset that may be required for the camera input (optional).
|
||||
virtual void ResetImpl()
|
||||
{
|
||||
}
|
||||
|
||||
private:
|
||||
Activation m_activation = Activation::Idle;
|
||||
Activation m_activation = Activation::Idle; //!< Default all camera inputs to the idle state.
|
||||
};
|
||||
|
||||
//! Properties to use to configure behavior across all types of camera.
|
||||
struct CameraProps
|
||||
{
|
||||
AZStd::function<float()> m_rotateSmoothnessFn; //!< Rotate smoothing value (useful approx range 3-6, higher values give sharper feel).
|
||||
AZStd::function<float()> m_translateSmoothnessFn; //!< Translate smoothing value (useful approx range 3-6, higher values give sharper feel).
|
||||
AZStd::function<float()>
|
||||
m_rotateSmoothnessFn; //!< Rotate smoothing value (useful approx range 3-6, higher values give sharper feel).
|
||||
AZStd::function<float()>
|
||||
m_translateSmoothnessFn; //!< Translate smoothing value (useful approx range 3-6, higher values give sharper feel).
|
||||
};
|
||||
|
||||
//! An interpolation function to smoothly interpolate all camera properties from currentCamera to targetCamera.
|
||||
//! The camera returned will be some value between current and target camera.
|
||||
//! @note The rate of interpolation can be customized with CameraProps.
|
||||
Camera SmoothCamera(const Camera& currentCamera, const Camera& targetCamera, const CameraProps& cameraProps, float deltaTime);
|
||||
|
||||
//! Manages a list of camera inputs.
|
||||
//! By default all camera inputs are added to the idle list, when a camera activates it will be added to the active list, when it
|
||||
//! deactivates it will be returned to the idle list.
|
||||
class Cameras
|
||||
{
|
||||
public:
|
||||
bool HandleEvents(const InputEvent& event, const ScreenVector& cursorDelta, float scrollDelta);
|
||||
Camera StepCamera(const Camera& targetCamera, const ScreenVector& cursorDelta, float scrollDelta, float deltaTime);
|
||||
|
||||
//! Add a camera input (behavior) to run in this set of camera inputs.
|
||||
//! The camera inputs added here will determine the overall behavior of the camera.
|
||||
void AddCamera(AZStd::shared_ptr<CameraInput> cameraInput);
|
||||
//! Reset the state of all cameras.
|
||||
void Reset();
|
||||
@@ -195,20 +227,11 @@ namespace AzFramework
|
||||
bool Exclusive() const;
|
||||
|
||||
private:
|
||||
AZStd::vector<AZStd::shared_ptr<CameraInput>> m_activeCameraInputs;
|
||||
AZStd::vector<AZStd::shared_ptr<CameraInput>> m_idleCameraInputs;
|
||||
AZStd::vector<AZStd::shared_ptr<CameraInput>> m_activeCameraInputs; //!< Active camera inputs updating the camera (empty initially).
|
||||
AZStd::vector<AZStd::shared_ptr<CameraInput>>
|
||||
m_idleCameraInputs; //!< Idle camera inputs not contributing to the update (filled initially).
|
||||
};
|
||||
|
||||
inline bool Cameras::Exclusive() const
|
||||
{
|
||||
return AZStd::any_of(
|
||||
m_activeCameraInputs.begin(), m_activeCameraInputs.end(),
|
||||
[](const auto& cameraInput)
|
||||
{
|
||||
return cameraInput->Exclusive();
|
||||
});
|
||||
}
|
||||
|
||||
//! Responsible for updating a series of cameras given various inputs.
|
||||
class CameraSystem
|
||||
{
|
||||
@@ -216,13 +239,14 @@ namespace AzFramework
|
||||
bool HandleEvents(const InputEvent& event);
|
||||
Camera StepCamera(const Camera& targetCamera, float deltaTime);
|
||||
|
||||
Cameras m_cameras;
|
||||
Cameras m_cameras; //!< Represents a collection of camera inputs that together provide a camera controller.
|
||||
|
||||
private:
|
||||
ScreenVector m_motionDelta; //!< The delta used for look/orbit/pan (rotation + translation) - two dimensional.
|
||||
float m_scrollDelta = 0.0f; //!< The delta used for dolly/movement (translation) - one dimensional.
|
||||
};
|
||||
|
||||
//! A camera input to handle motion deltas that can rotate or orbit the camera.
|
||||
class RotateCameraInput : public CameraInput
|
||||
{
|
||||
public:
|
||||
@@ -237,24 +261,28 @@ namespace AzFramework
|
||||
AZStd::function<bool()> m_invertYawFn;
|
||||
|
||||
private:
|
||||
InputChannelId m_rotateChannelId;
|
||||
ClickDetector m_clickDetector;
|
||||
InputChannelId m_rotateChannelId; //!< Input channel to begin the rotate camera input.
|
||||
ClickDetector m_clickDetector; //!< Used to determine when a sufficient motion delta has occurred to begin the input.
|
||||
};
|
||||
|
||||
//! Axes to use while panning the camera.
|
||||
struct PanAxes
|
||||
{
|
||||
AZ::Vector3 m_horizontalAxis;
|
||||
AZ::Vector3 m_verticalAxis;
|
||||
};
|
||||
|
||||
//! PanAxes build function that will return a pair of pan axes depending on the camera orientation.
|
||||
using PanAxesFn = AZStd::function<PanAxes(const Camera& camera)>;
|
||||
|
||||
//! PanAxes to use while in 'look' camera behavior (free look).
|
||||
inline PanAxes LookPan(const Camera& camera)
|
||||
{
|
||||
const AZ::Matrix3x3 orientation = camera.Rotation();
|
||||
return { orientation.GetBasisX(), orientation.GetBasisZ() };
|
||||
}
|
||||
|
||||
//! PanAxes to use while in 'orbit' camera behavior.
|
||||
inline PanAxes OrbitPan(const Camera& camera)
|
||||
{
|
||||
const AZ::Matrix3x3 orientation = camera.Rotation();
|
||||
@@ -269,6 +297,7 @@ namespace AzFramework
|
||||
return { basisX, basisY };
|
||||
}
|
||||
|
||||
//! A camera input to handle motion deltas that can pan the camera (translate in two axes).
|
||||
class PanCameraInput : public CameraInput
|
||||
{
|
||||
public:
|
||||
@@ -283,12 +312,14 @@ namespace AzFramework
|
||||
AZStd::function<bool()> m_invertPanYFn;
|
||||
|
||||
private:
|
||||
PanAxesFn m_panAxesFn;
|
||||
InputChannelId m_panChannelId;
|
||||
PanAxesFn m_panAxesFn; //!< Builder for the particular pan axes (provided in the constructor).
|
||||
InputChannelId m_panChannelId; //!< Input channel to begin the pan camera input.
|
||||
};
|
||||
|
||||
//! Axes to use while translating the camera.
|
||||
using TranslationAxesFn = AZStd::function<AZ::Matrix3x3(const Camera& camera)>;
|
||||
|
||||
//! TranslationAxes to use while in 'look' camera behavior (free look).
|
||||
inline AZ::Matrix3x3 LookTranslation(const Camera& camera)
|
||||
{
|
||||
const AZ::Matrix3x3 orientation = camera.Rotation();
|
||||
@@ -300,6 +331,7 @@ namespace AzFramework
|
||||
return AZ::Matrix3x3::CreateFromColumns(basisX, basisY, basisZ);
|
||||
}
|
||||
|
||||
//! TranslationAxes to use while in 'orbit' camera behavior.
|
||||
inline AZ::Matrix3x3 OrbitTranslation(const Camera& camera)
|
||||
{
|
||||
const AZ::Matrix3x3 orientation = camera.Rotation();
|
||||
@@ -315,6 +347,7 @@ namespace AzFramework
|
||||
return AZ::Matrix3x3::CreateFromColumns(basisX, basisY, basisZ);
|
||||
}
|
||||
|
||||
//! A camera input to handle discrete events that can translate the camera (translate in three axes).
|
||||
class TranslateCameraInput : public CameraInput
|
||||
{
|
||||
public:
|
||||
@@ -329,6 +362,7 @@ namespace AzFramework
|
||||
AZStd::function<float()> m_boostMultiplierFn;
|
||||
|
||||
private:
|
||||
//! The type of translation the camera input is performing (multiple may be active at once).
|
||||
enum class TranslationType
|
||||
{
|
||||
// clang-format off
|
||||
@@ -383,13 +417,15 @@ namespace AzFramework
|
||||
return static_cast<TranslationType>(~static_cast<std::underlying_type_t<TranslationType>>(lhs));
|
||||
}
|
||||
|
||||
static TranslationType translationFromKey(InputChannelId channelId);
|
||||
//! Converts from a generic input channel id to a concrete translation type (based on the user's key mappings).
|
||||
static TranslationType TranslationFromKey(InputChannelId channelId);
|
||||
|
||||
TranslationType m_translation = TranslationType::Nil;
|
||||
TranslationAxesFn m_translationAxesFn;
|
||||
bool m_boost = false;
|
||||
TranslationType m_translation = TranslationType::Nil; //!< Types of translation the camera input is under.
|
||||
TranslationAxesFn m_translationAxesFn; //!< Builder for translation axes.
|
||||
bool m_boost = false; //!< Is the translation speed currently being multiplied/scaled upwards.
|
||||
};
|
||||
|
||||
//! A camera input to handle discrete scroll events that can modify the camera look distance.
|
||||
class OrbitDollyScrollCameraInput : public CameraInput
|
||||
{
|
||||
public:
|
||||
@@ -402,6 +438,7 @@ namespace AzFramework
|
||||
AZStd::function<float()> m_scrollSpeedFn;
|
||||
};
|
||||
|
||||
//! A camera input to handle motion deltas that can modify the camera look distance.
|
||||
class OrbitDollyCursorMoveCameraInput : public CameraInput
|
||||
{
|
||||
public:
|
||||
@@ -417,6 +454,7 @@ namespace AzFramework
|
||||
InputChannelId m_dollyChannelId;
|
||||
};
|
||||
|
||||
//! A camera input to handle discrete scroll events that can scroll (translate) the camera along its forward axis.
|
||||
class ScrollTranslationCameraInput : public CameraInput
|
||||
{
|
||||
public:
|
||||
@@ -429,6 +467,8 @@ namespace AzFramework
|
||||
AZStd::function<float()> m_scrollSpeedFn;
|
||||
};
|
||||
|
||||
//! A camera input that doubles as its own set of camera inputs.
|
||||
//! It is 'exclusive', so does not overlap with other sibling camera inputs - it runs its own set of camera inputs as 'children'.
|
||||
class OrbitCameraInput : public CameraInput
|
||||
{
|
||||
public:
|
||||
@@ -439,13 +479,13 @@ namespace AzFramework
|
||||
Camera StepCamera(const Camera& targetCamera, const ScreenVector& cursorDelta, float scrollDelta, float deltaTime) override;
|
||||
bool Exclusive() const override;
|
||||
|
||||
Cameras m_orbitCameras;
|
||||
Cameras m_orbitCameras; //!< The camera inputs to run when this camera input is active (only these will run as it is exclusive).
|
||||
|
||||
//! Override the default behavior for how a look-at point is calculated.
|
||||
void SetLookAtFn(const LookAtFn& lookAtFn);
|
||||
|
||||
private:
|
||||
LookAtFn m_lookAtFn;
|
||||
LookAtFn m_lookAtFn; //!< The look-at behavior to use for this orbit camera (how is the look-at point calculated/retrieved).
|
||||
};
|
||||
|
||||
inline void OrbitCameraInput::SetLookAtFn(const LookAtFn& lookAtFn)
|
||||
|
||||
Reference in New Issue
Block a user