/* * 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 #include #include #include #include #include // 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 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 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 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 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 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 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 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 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 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(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(AZ::EntityId entityId) {}; //! Called when an element is pressed. Will be an invalid entity id if no interactable was //! pressed. virtual void OnCanvasMultiTouchPressed(AZ::EntityId entityId, 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(AZ::EntityId entityId, int multiTouchIndex) {}; //! Called when an element starts being hovered virtual void OnCanvasHoverStart(AZ::EntityId entityId) {}; //! Called when an element ends being hovered virtual void OnCanvasHoverEnd(AZ::EntityId entityId) {}; //! Called when the enter key is pressed virtual void OnCanvasEnterPressed(AZ::EntityId entityId) {}; //! Called when the enter key is released virtual void OnCanvasEnterReleased(AZ::EntityId entityId) {}; }; typedef AZ::EBus UiCanvasInputNotificationBus;