Files
o3de/Code/CryEngine/CryCommon/LyShine/Bus/UiCanvasBus.h
T
2021-03-08 14:30:57 -08:00

513 lines
24 KiB
C++

/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
#pragma once
#include <AzCore/Component/ComponentBus.h>
#include <AzCore/Math/Vector2.h>
#include <AzCore/Math/Matrix4x4.h>
#include <AzFramework/Input/Channels/InputChannelDigitalWithSharedModifierKeyStates.h>
#include <AzFramework/Input/User/LocalUserId.h>
#include <LyShine/UiBase.h>
// Forward declarations
struct IUiAnimationSystem;
////////////////////////////////////////////////////////////////////////////////////////////////////
class UiCanvasInterface
: public AZ::ComponentBus
{
public: // types
enum class ErrorCode
{
NoError,
PrefabContainsExternalEntityRefs
};
public: // member functions
//! Deleting a canvas will delete all its child elements recursively and all of their components
virtual ~UiCanvasInterface() {}
//! Get the asset ID path name of this canvas. If not loaded or saved yet this will be ""
virtual const AZStd::string& GetPathname() = 0;
//! Get the ID of this canvas. This will remain the same while this canvas is loaded.
virtual LyShine::CanvasId GetCanvasId() = 0;
//! Get the unique ID of this canvas
virtual AZ::u64 GetUniqueCanvasId() = 0;
//! Get the draw order of this canvas. Rendering is back-to-front, so higher numbers render in front of lower numbers.
virtual int GetDrawOrder() = 0;
//! Set the draw order of this canvas. Rendering is back-to-front, so higher numbers render in front of lower numbers.
virtual void SetDrawOrder(int drawOrder) = 0;
//! Get the flag indicating if this canvas will stay loaded through a level unload.
virtual bool GetKeepLoadedOnLevelUnload() = 0;
//! Set the flag indicating if this canvas will stay loaded through a level unload.
virtual void SetKeepLoadedOnLevelUnload(bool keepLoaded) = 0;
//! Force a layout recompute. Layouts marked for a recompute are handled on the canvas update,
//! so this can be used if an immediate recompute is desired
virtual void RecomputeChangedLayouts() = 0;
//! Get the number child elements of this canvas
virtual int GetNumChildElements() = 0;
//! Get the specified child element, index must be less than GetNumChildElements()
virtual AZ::Entity* GetChildElement(int index) = 0;
//! Get the specified child entity Id, index must be less than GetNumChildElements()
virtual AZ::EntityId GetChildElementEntityId(int index) = 0;
//! Get the child elements of this canvas
virtual LyShine::EntityArray GetChildElements() = 0;
//! Get the child entity Ids of this canvas
virtual AZStd::vector<AZ::EntityId> GetChildElementEntityIds() = 0;
//! Create a new element that is a child of the canvas, the canvas has ownership of the child
virtual AZ::Entity* CreateChildElement(const LyShine::NameType& name) = 0;
//! Return the element on this canvas with the given id or nullptr if no match
virtual AZ::Entity* FindElementById(LyShine::ElementId id) = 0;
//! Return the first element on this canvas with the given name or nullptr if no match
virtual AZ::Entity* FindElementByName(const LyShine::NameType& name) = 0;
//! Return the first element on this canvas with the given name or nullptr if no match
virtual AZ::EntityId FindElementEntityIdByName(const LyShine::NameType& name) = 0;
//! Find all elements on this canvas with the given name
virtual void FindElementsByName(const LyShine::NameType& name, LyShine::EntityArray& result) = 0;
//! Return the element with the given hierarchical name or nullptr if no match
//! \param name, a hierarchical name relative to the root with '/' as the separator
virtual AZ::Entity* FindElementByHierarchicalName(const LyShine::NameType& name) = 0;
//! Find all elements on this canvas matching the predicate
virtual void FindElements(AZStd::function<bool(const AZ::Entity*)> predicate, LyShine::EntityArray& result) = 0;
//! Get the front-most element whose bounds include the given point in canvas space
//! \return nullptr if no match
virtual AZ::Entity* PickElement(AZ::Vector2 point) = 0;
//! Get all element whose bounds intersect with the given box in canvas space
//! \return empty EntityArray if no match
virtual LyShine::EntityArray PickElements(const AZ::Vector2& bound0, const AZ::Vector2& bound1) = 0;
//! Look for an entity with interactable component to handle an event at given point
virtual AZ::EntityId FindInteractableToHandleEvent(AZ::Vector2 point) = 0;
//! Save this canvas to the given path in XML
//! \return true if no error
virtual bool SaveToXml(const string& assetIdPathname, const string& sourceAssetPathname) = 0;
//! Save the given UI element entity to the given path as a prefab
//! \param pathname the path to save the prefab to
//! \param entity pointer to the entity to save as a prefab
//! \return true if no error
virtual bool SaveAsPrefab(const string& pathname, AZ::Entity* entity) = 0;
//! Check if it is OK to save the given UI element entity to the given path as a prefab
//! \param entity pointer to the entity to save as a prefab
//! \return errorCode which is NoError if OK to save
virtual ErrorCode CheckElementValidToSaveAsPrefab(AZ::Entity* entity) = 0;
//! Load a prefab element from the given file and optionally insert as child of given entity
//! \return the top level entity created
virtual AZ::Entity* LoadFromPrefab(const string& pathname,
bool makeUniqueName,
AZ::Entity* optionalInsertionPoint) = 0;
//! Initialize a set of entities that have been added to the canvas
//! Used when instantiating a slice or for undo/redo, copy/paste
//! \param topLevelEntities - The elements that were created
//! \param makeUniqueNamesAndIds If false the entity names and ElementIds in the string are kept, else unique ones are generated
//! \param insertionPoint The parent element for the created elements, if nullptr the root element is the parent
virtual void FixupCreatedEntities(LyShine::EntityArray topLevelEntities, bool makeUniqueNamesAndIds, AZ::Entity* optionalInsertionPoint) = 0;
//! Add an existing entity to the canvas (only for internal use from editor)
//! \param element The newly created element to add to the canvas
//! \param parent The parent element for the created element, if nullptr the root element is the parent
//! \param insertBefore The sibling element to place this element before, if nullptr then add as last child
virtual void AddElement(AZ::Entity* element, AZ::Entity* parent, AZ::Entity* insertBefore) = 0;
//! Go through all elements in the canvas and reinitialize them
//! This is done whenever a slice asset changes and the entity context is rebuilt from the root slice asset
virtual void ReinitializeElements() = 0;
//! Save this canvas to an XML string
//! \return the resulting string
virtual AZStd::string SaveToXmlString() = 0;
//! Get an element name that is unique to the children of the specified parent and to an optional array of elements
//! \param parentEntityId The entityId of the parent who's children's names must not match the returned name
//! \param baseName The name to append a unique identifier to
//! \param includedChildren An array of any other elements who's names must not match the returned name
//! \return Unique name that does not match the specified parent's children or the optional array of children
virtual AZStd::string GetUniqueChildName(AZ::EntityId parentEntityId, AZStd::string baseName, const LyShine::EntityArray* includeChildren) = 0;
//! Clone an element and add it to this canvas as a child of the given parent element
//! The entity and all its components/children are cloned and new IDs are generated
//! NOTE: Only state that is persistent/reflected is cloned
//! \param sourceEntity The entity to clone
//! \param parentEntity The parent element for the created elements, if nullptr the root element is the parent
//! \return The new entity
virtual AZ::Entity* CloneElement(AZ::Entity* sourceEntity, AZ::Entity* parentEntity) = 0;
//! Clone an element and add it to this canvas as a child of the given parent element
//! The entity and all its components/children are cloned and new IDs are generated
//! NOTE: Only state that is persistent/reflected is cloned
//! \param sourceEntity The entity to clone (may be from a different canvas)
//! \param parentEntity The parent element for the created elements, if invalid the root element is the parent
//! \param insertBefore The child of the parent element that the new element should be inserted before, if invalid the new element is the last child element
//! \return The new entity
virtual AZ::EntityId CloneElementEntityId(AZ::EntityId sourceEntity, AZ::EntityId parentEntity, AZ::EntityId insertBefore) = 0;
//! Create a clone of this canvas entity
//! \param canvasSize The resolution to display the canvas at
virtual AZ::Entity* CloneCanvas(const AZ::Vector2& canvasSize) = 0;
//! Set the transformation from canvas space to viewport space
virtual void SetCanvasToViewportMatrix(const AZ::Matrix4x4& matrix) = 0;
//! Get the transformation from canvas space to viewport space
virtual const AZ::Matrix4x4& GetCanvasToViewportMatrix() = 0;
//! Get the transformation from viewport space to canvas space
virtual void GetViewportToCanvasMatrix(AZ::Matrix4x4& matrix) = 0;
//! Returns the "target" size of the canvas (in pixels)
//
//! The target canvas size changes depending on whether you're running in
//! the UI Editor or in-game. While in-game, we assume that the canvas size
//! fills the screen, so the target canvas size is the size of the viewport.
//
//! When using the editor, however, the target size is the "authored" size of
//! the canvas. The canvas is authored in one resolution, but it may be
//! displayed by the game at whatever the game resolution is set to.
virtual AZ::Vector2 GetCanvasSize() = 0;
//! Set the authored size of the canvas (in pixels)
virtual void SetCanvasSize(const AZ::Vector2& canvasSize) = 0;
//! Set the target size of the canvas (in pixels)
//!
//! This should be called before the UpdateCanvas and RenderCanvas methods.
//! When running in game in full screen mode the target canvas size should be set to the viewport size
virtual void SetTargetCanvasSize(bool isInGame, const AZ::Vector2& targetCanvasSize) = 0;
//! Get scale to adjust for the difference between canvas size (authored size)
//! and the viewport size (target canvas size) when running on current device
virtual AZ::Vector2 GetDeviceScale() = 0;
//! Get flag that indicates whether visual element's vertices should snap to the nearest pixel
virtual bool GetIsPixelAligned() = 0;
//! Set flag that indicates whether visual element's vertices should snap to the nearest pixel
virtual void SetIsPixelAligned(bool isPixelAligned) = 0;
//! Get flag that indicates whether text should snap to the nearest pixel
virtual bool GetIsTextPixelAligned() = 0;
//! Set flag that indicates whether text should snap to the nearest pixel
virtual void SetIsTextPixelAligned(bool isTextPixelAligned) = 0;
//! Get the animation system for this canvas
virtual IUiAnimationSystem* GetAnimationSystem() = 0;
//! Get flag that governs whether the canvas is enabled
//
//! A canvas that's enabled will be updated and rendered each frame.
virtual bool GetEnabled() = 0;
//! Set flag that governs whether the canvas is enabled
//
//! A canvas that's enabled will be updated and rendered each frame.
virtual void SetEnabled(bool enabled) = 0;
//! Get flag that controls whether the canvas is rendering to a texture
virtual bool GetIsRenderToTexture() = 0;
//! Set flag that controls whether the canvas is rendering to a texture
virtual void SetIsRenderToTexture(bool isRenderToTexture) = 0;
//! Get the render target name that this canvas will render to
virtual AZStd::string GetRenderTargetName() = 0;
//! Set the render target name that this canvas will render to
virtual void SetRenderTargetName(const AZStd::string& name) = 0;
//! Get flag that controls whether this canvas automatically handles positional input (mouse/touch)
virtual bool GetIsPositionalInputSupported() = 0;
//! Set flag that controls whether this canvas automatically handles positional input (mouse/touch)
virtual void SetIsPositionalInputSupported(bool isSupported) = 0;
//! Get flag that controls whether this canvas consumes all input events while it is enabled
virtual bool GetIsConsumingAllInputEvents() = 0;
//! Set flag that controls whether this canvas consumes all input events while it is enabled
virtual void SetIsConsumingAllInputEvents(bool isConsuming) = 0;
//! Get flag that controls whether this canvas automatically handles multi-touch input
virtual bool GetIsMultiTouchSupported() = 0;
//! Set flag that controls whether this canvas automatically handles multi-touch input
virtual void SetIsMultiTouchSupported(bool isSupported) = 0;
//! Get flag that controls whether this canvas automatically handles navigation input (via keyboard/gamepad)
virtual bool GetIsNavigationSupported() = 0;
//! Set flag that controls whether this canvas automatically handles navigation input (via keyboard/gamepad)
virtual void SetIsNavigationSupported(bool isSupported) = 0;
//! Get the analog (eg. thumb-stick) input value that must be exceeded before a navigation command will be processed
virtual float GetNavigationThreshold() = 0;
//! Set the analog (eg. thumb-stick) input value that must be exceeded before a navigation command will be processed
virtual void SetNavigationThreshold(float navigationThreshold) = 0;
//! Get the delay (milliseconds) before a held navigation command will begin repeating
virtual AZ::u64 GetNavigationRepeatDelay() = 0;
//! Set the delay (milliseconds) before a held navigation command will begin repeating
virtual void SetNavigationRepeatDelay(AZ::u64 navigationRepeatDelay) = 0;
//! Get the delay (milliseconds) before a held navigation command will continue repeating
virtual AZ::u64 GetNavigationRepeatPeriod() = 0;
//! Set the delay (milliseconds) before a held navigation command will continue repeating
virtual void SetNavigationRepeatPeriod(AZ::u64 navigationRepeatPeriod) = 0;
//! Get the local user id that is being used to filter incoming input events
virtual AzFramework::LocalUserId GetLocalUserIdInputFilter() = 0;
//! Set the local user id that will be used to filter incoming input events
virtual void SetLocalUserIdInputFilter(AzFramework::LocalUserId localUserId) = 0;
//! Handle an input event for the canvas
virtual bool HandleInputEvent(const AzFramework::InputChannel::Snapshot& inputSnapshot,
const AZ::Vector2* viewportPos = nullptr,
AzFramework::ModifierKeyMask activeModifierKeys = AzFramework::ModifierKeyMask::None) = 0;
//! Handle a unicode text event for the canvas
virtual bool HandleTextEvent(const AZStd::string& textUTF8) = 0;
//! Handle a positional input event for the canvas, this could come from
//! a ray cast intersection for example
virtual bool HandleInputPositionalEvent(const AzFramework::InputChannel::Snapshot& inputSnapshot, AZ::Vector2 viewportPos) = 0;
//! Get the mouse position of the last input event
virtual AZ::Vector2 GetMousePosition() = 0;
//! Get the element to be displayed when hovering over an interactable
virtual AZ::EntityId GetTooltipDisplayElement() = 0;
//! Set the element to be displayed when hovering over an interactable
virtual void SetTooltipDisplayElement(AZ::EntityId entityId) = 0;
//! Force the active interactable for the canvas to be the given one,
//! also force AutoActivation of interactable,
//! intended for internal use by UI components
virtual void ForceFocusInteractable(AZ::EntityId interactableId) = 0;
//! Force the active interactable for the canvas to be the given one,
//! also set last mouse pos to point,
//! intended for internal use by UI components
virtual void ForceActiveInteractable(AZ::EntityId interactableId, bool shouldStayActive, AZ::Vector2 point) = 0;
//! Get the hover interactable
virtual AZ::EntityId GetHoverInteractable() = 0;
//! Force the hover interactable for the canvas to be the given one, this can be useful when using
//! keyboard/gamepad navigation and the current hover interactable is deleted by a script and the script
//! wants to specify the new hover interactable
virtual void ForceHoverInteractable(AZ::EntityId interactableId) = 0;
//! Clear all active interactables, and all hover interactables if last input was positional (mouse/touch).
//! This is intended for internal use by UI components
virtual void ClearAllInteractables() = 0;
//! Generate Enter pressed/released input events on an interactable.
//! Useful for automated testing to simulate button clicks
virtual void ForceEnterInputEventOnInteractable(AZ::EntityId interactableId) = 0;
public: // static member data
//! Only one component on an entity can implement the events
static const AZ::EBusHandlerPolicy HandlerPolicy = AZ::EBusHandlerPolicy::Single;
};
typedef AZ::EBus<UiCanvasInterface> UiCanvasBus;
////////////////////////////////////////////////////////////////////////////////////////////////////
//! The canvas component implements this bus and it is provided for C++ implementations of
//! UI components to use to talk to the canvas
class UiCanvasComponentImplementationInterface
: public AZ::ComponentBus
{
public: // member functions
virtual ~UiCanvasComponentImplementationInterface() {}
//! Mark the render graph for the canvas as dirty. This will cause the render graph to get
//! cleared and rebuilt on the next render.
virtual void MarkRenderGraphDirty() = 0;
public: // static member data
//! Only one component on an entity can implement the events
static const AZ::EBusHandlerPolicy HandlerPolicy = AZ::EBusHandlerPolicy::Single;
};
typedef AZ::EBus<UiCanvasComponentImplementationInterface> UiCanvasComponentImplementationBus;
////////////////////////////////////////////////////////////////////////////////////////////////////
//! Interface class that listeners need to implement to be notified of canvas actions
class UiCanvasActionNotification
: public AZ::ComponentBus
{
public:
//////////////////////////////////////////////////////////////////////////
// EBusTraits overrides
static const bool EnableEventQueue = true;
//////////////////////////////////////////////////////////////////////////
public: // member functions
virtual ~UiCanvasActionNotification(){}
//! Called when the canvas sends an action to the listener
virtual void OnAction(AZ::EntityId entityId, const LyShine::ActionName& actionName) = 0;
};
typedef AZ::EBus<UiCanvasActionNotification> UiCanvasNotificationBus;
////////////////////////////////////////////////////////////////////////////////////////////////////
//! Interface class that listeners need to implement to be notified when the draw order of any
//! canvas changes
class UiCanvasOrderNotification
: public AZ::EBusTraits
{
public: // member functions
static const AZ::EBusAddressPolicy AddressPolicy = AZ::EBusAddressPolicy::Single;
virtual ~UiCanvasOrderNotification(){}
//! Called when the draw order setting for a canvas changes
//! Note this is used to update the order in the UiCanvasManager so that
//! order has not been updated when this fires.
virtual void OnCanvasDrawOrderChanged(AZ::EntityId canvasEntityId) = 0;
};
typedef AZ::EBus<UiCanvasOrderNotification> UiCanvasOrderNotificationBus;
////////////////////////////////////////////////////////////////////////////////////////////////////
//! Interface class that listeners need to implement to be notified when any canvas has been
//! enabled or disabled
class UiCanvasEnabledStateNotification
: public AZ::EBusTraits
{
public: // member functions
static const AZ::EBusAddressPolicy AddressPolicy = AZ::EBusAddressPolicy::Single;
virtual ~UiCanvasEnabledStateNotification() {}
//! Called when the canvas was enabled or disabled
virtual void OnCanvasEnabledStateChanged(AZ::EntityId canvasEntityId, bool enabled) = 0;
};
typedef AZ::EBus<UiCanvasEnabledStateNotification> UiCanvasEnabledStateNotificationBus;
////////////////////////////////////////////////////////////////////////////////////////////////////
//! Interface class that listeners need to implement to be notified of canvas size or scale changes
class UiCanvasSizeNotification
: public AZ::EBusTraits
{
public:
virtual ~UiCanvasSizeNotification() {}
//! Called when the target canvas size or uniform device scale changes.
virtual void OnCanvasSizeOrScaleChange(AZ::EntityId canvasEntityId) = 0;
};
typedef AZ::EBus<UiCanvasSizeNotification> UiCanvasSizeNotificationBus;
////////////////////////////////////////////////////////////////////////////////////////////////////
//! Interface class that listeners need to implement to be notified of changes to the canvas
//! pixel alignment settings
class UiCanvasPixelAlignmentNotification
: public AZ::ComponentBus
{
public:
virtual ~UiCanvasPixelAlignmentNotification() {}
//! Called when the pixel alignment setting for the canvas changes
virtual void OnCanvasPixelAlignmentChange() {}
//! Called when the text pixel alignment setting for the canvas changes
virtual void OnCanvasTextPixelAlignmentChange() {}
};
typedef AZ::EBus<UiCanvasPixelAlignmentNotification> UiCanvasPixelAlignmentNotificationBus;
////////////////////////////////////////////////////////////////////////////////////////////////////
//! Interface class that listeners need to implement to be notified of canvas input.
//! Note that interactables already get methods called on them when they themselves are interacted
//! with. This notification bus is intended for other entities or Lua to know when some other
//! entities are interacted with.
class UiCanvasInputNotifications
: public AZ::ComponentBus
{
public: // member functions
virtual ~UiCanvasInputNotifications() {}
//! Called when an element is pressed. Will return an invalid entity id if no interactable was
//! pressed.
virtual void OnCanvasPrimaryPressed([[maybe_unused]] AZ::EntityId entityId) {};
//! Called when an element is released. The released entity that is sent is the entity that was
//! active (if any).
virtual void OnCanvasPrimaryReleased([[maybe_unused]] AZ::EntityId entityId) {};
//! Called when an element is pressed. Will be an invalid entity id if no interactable was
//! pressed.
virtual void OnCanvasMultiTouchPressed([[maybe_unused]] AZ::EntityId entityId, [[maybe_unused]] int multiTouchIndex) {};
//! Called when an element is released. The released entity that is sent is the entity that was
//! active (if any).
virtual void OnCanvasMultiTouchReleased([[maybe_unused]] AZ::EntityId entityId, [[maybe_unused]] int multiTouchIndex) {};
//! Called when an element starts being hovered
virtual void OnCanvasHoverStart([[maybe_unused]] AZ::EntityId entityId) {};
//! Called when an element ends being hovered
virtual void OnCanvasHoverEnd([[maybe_unused]] AZ::EntityId entityId) {};
//! Called when the enter key is pressed
virtual void OnCanvasEnterPressed([[maybe_unused]] AZ::EntityId entityId) {};
//! Called when the enter key is released
virtual void OnCanvasEnterReleased([[maybe_unused]] AZ::EntityId entityId) {};
};
typedef AZ::EBus<UiCanvasInputNotifications> UiCanvasInputNotificationBus;