/* * 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 <IGameFramework.h> #include <AzCore/Component/Component.h> #include <AzCore/Component/EntityBus.h> #include <AzCore/RTTI/TypeInfo.h> #include <LyShine/Bus/UiCanvasBus.h> #include <LyShine/Bus/UiInteractableBus.h> #include <LyShine/Bus/UiAnimationBus.h> #include <LyShine/Bus/UiEditorCanvasBus.h> #include <LyShine/UiEntityContext.h> #include <LyShine/UiComponentTypes.h> #include "UiElementComponent.h" #include "UiSerialize.h" #include "Animation/UiAnimationSystem.h" #include "UiLayoutManager.h" #include "UiNavigationHelpers.h" #include "RenderGraph.h" #ifndef _RELEASE #include "LyShineDebug.h" #endif #include "TextureAtlas/TextureAtlas.h" #include "TextureAtlas/TextureAtlasBus.h" #include "TextureAtlas/TextureAtlasNotificationBus.h" namespace AZ { class SerializeContext; } struct SDepthTexture; //////////////////////////////////////////////////////////////////////////////////////////////////// class UiCanvasComponent : public AZ::Component , public UiCanvasBus::Handler , public AZ::EntityBus::Handler , public UiAnimationBus::Handler , public UiInteractableActiveNotificationBus::Handler , public ISystem::CrySystemNotificationBus::Handler , public IGameFrameworkListener , public IUiAnimationListener , public UiEditorCanvasBus::Handler , public UiCanvasComponentImplementationBus::Handler { public: // constants static const AZ::Vector2 s_defaultCanvasSize; static const AZ::Color s_defaultGuideColor; public: // member functions AZ_COMPONENT(UiCanvasComponent, LyShine::UiCanvasComponentUuid, AZ::Component); //! Constructor, constructed by the LyShine class UiCanvasComponent(); ~UiCanvasComponent() override; // UiCanvasInterface const AZStd::string& GetPathname() override; LyShine::CanvasId GetCanvasId() override; AZ::u64 GetUniqueCanvasId() override; int GetDrawOrder() override; void SetDrawOrder(int drawOrder) override; bool GetKeepLoadedOnLevelUnload() override; void SetKeepLoadedOnLevelUnload(bool keepLoaded) override; void RecomputeChangedLayouts() override; int GetNumChildElements() override; AZ::Entity* GetChildElement(int index) override; AZ::EntityId GetChildElementEntityId(int index) override; LyShine::EntityArray GetChildElements() override; AZStd::vector<AZ::EntityId> GetChildElementEntityIds() override; AZ::Entity* CreateChildElement(const LyShine::NameType& name) override; AZ::Entity* FindElementById(LyShine::ElementId id) override; AZ::Entity* FindElementByName(const LyShine::NameType& name) override; void FindElementsByName(const LyShine::NameType& name, LyShine::EntityArray& result) override; AZ::EntityId FindElementEntityIdByName(const LyShine::NameType& name) override; AZ::Entity* FindElementByHierarchicalName(const LyShine::NameType& name) override; void FindElements(AZStd::function<bool(const AZ::Entity*)> predicate, LyShine::EntityArray& result) override; AZ::Entity* PickElement(AZ::Vector2 point) override; LyShine::EntityArray PickElements(const AZ::Vector2& bound0, const AZ::Vector2& bound1) override; AZ::EntityId FindInteractableToHandleEvent(AZ::Vector2 point) override; bool SaveToXml(const string& assetIdPathname, const string& sourceAssetPathname) override; bool SaveAsPrefab(const string& pathname, AZ::Entity* entity) override; UiCanvasInterface::ErrorCode CheckElementValidToSaveAsPrefab(AZ::Entity* entity) override; AZ::Entity* LoadFromPrefab(const string& pathname, bool makeUniqueName, AZ::Entity* optionalInsertionPoint) override; void FixupCreatedEntities(LyShine::EntityArray topLevelEntities, bool makeUniqueNamesAndIds, AZ::Entity* optionalInsertionPoint) override; void AddElement(AZ::Entity* element, AZ::Entity* parent, AZ::Entity* insertBefore) override; void ReinitializeElements() override; AZStd::string SaveToXmlString() override; AZStd::string GetUniqueChildName(AZ::EntityId parentEntityId, AZStd::string baseName, const LyShine::EntityArray* includeChildren) override; AZ::Entity* CloneElement(AZ::Entity* sourceEntity, AZ::Entity* parentEntity) override; AZ::EntityId CloneElementEntityId(AZ::EntityId sourceEntity, AZ::EntityId parentEntity, AZ::EntityId insertBefore) override; AZ::Entity* CloneCanvas(const AZ::Vector2& canvasSize) override; void SetCanvasToViewportMatrix(const AZ::Matrix4x4& matrix) override; const AZ::Matrix4x4& GetCanvasToViewportMatrix() override; void GetViewportToCanvasMatrix(AZ::Matrix4x4& matrix) override; AZ::Vector2 GetCanvasSize() override; void SetCanvasSize(const AZ::Vector2& canvasSize) override; void SetTargetCanvasSize(bool isInGame, const AZ::Vector2& targetCanvasSize) override; AZ::Vector2 GetDeviceScale() override; bool GetIsPixelAligned() override; void SetIsPixelAligned(bool isPixelAligned) override; bool GetIsTextPixelAligned() override; void SetIsTextPixelAligned(bool isTextPixelAligned) override; IUiAnimationSystem* GetAnimationSystem() override; bool GetEnabled() override; void SetEnabled(bool enabled) override; bool GetIsRenderToTexture() override; void SetIsRenderToTexture(bool isRenderToTexture) override; AZStd::string GetRenderTargetName() override; void SetRenderTargetName(const AZStd::string& name) override; bool GetIsPositionalInputSupported() override; void SetIsPositionalInputSupported(bool isSupported) override; bool GetIsConsumingAllInputEvents() override; void SetIsConsumingAllInputEvents(bool isConsuming) override; bool GetIsMultiTouchSupported() override; void SetIsMultiTouchSupported(bool isSupported) override; bool GetIsNavigationSupported() override; void SetIsNavigationSupported(bool isSupported) override; float GetNavigationThreshold() override; void SetNavigationThreshold(float navigationThreshold) override; AZ::u64 GetNavigationRepeatDelay() override; void SetNavigationRepeatDelay(AZ::u64 navigationRepeatDelay) override; AZ::u64 GetNavigationRepeatPeriod() override; void SetNavigationRepeatPeriod(AZ::u64 navigationRepeatPeriod) override; AzFramework::LocalUserId GetLocalUserIdInputFilter() override; void SetLocalUserIdInputFilter(AzFramework::LocalUserId localUserId) override; bool HandleInputEvent(const AzFramework::InputChannel::Snapshot& inputSnapshot, const AZ::Vector2* viewportPos = nullptr, AzFramework::ModifierKeyMask activeModifierKeys = AzFramework::ModifierKeyMask::None) override; bool HandleTextEvent(const AZStd::string& textUTF8) override; bool HandleInputPositionalEvent(const AzFramework::InputChannel::Snapshot& inputSnapshot, AZ::Vector2 viewportPos) override; AZ::Vector2 GetMousePosition() override; AZ::EntityId GetTooltipDisplayElement() override; void SetTooltipDisplayElement(AZ::EntityId entityId) override; void ForceFocusInteractable(AZ::EntityId interactableId) override; void ForceActiveInteractable(AZ::EntityId interactableId, bool shouldStayActive, AZ::Vector2 point) override; AZ::EntityId GetHoverInteractable() override; void ForceHoverInteractable(AZ::EntityId interactableId) override; void ClearAllInteractables() override; void ForceEnterInputEventOnInteractable(AZ::EntityId interactableId) override; // ~UiCanvasInterface // EntityEvents void OnEntityDeactivated(const AZ::EntityId& entityId) override; // ~EntityEvents // UiAnimationInterface void StartSequence(const AZStd::string& sequenceName) override; void PlaySequenceRange(const AZStd::string& sequenceName, float startTime, float endTime) override; void StopSequence(const AZStd::string& sequenceName) override; void AbortSequence(const AZStd::string& sequenceName) override; void PauseSequence(const AZStd::string& sequenceName) override; void ResumeSequence(const AZStd::string& sequenceName) override; void ResetSequence(const AZStd::string& sequenceName) override; float GetSequencePlayingSpeed(const AZStd::string& sequenceName) override; void SetSequencePlayingSpeed(const AZStd::string& sequenceName, float speed) override; float GetSequencePlayingTime(const AZStd::string& sequenceName) override; bool IsSequencePlaying(const AZStd::string& sequenceName) override; float GetSequenceLength(const AZStd::string& sequenceName) override; void SetSequenceStopBehavior(IUiAnimationSystem::ESequenceStopBehavior stopBehavior) override; // ~UiAnimationInterface // UiInteractableActiveNotifications void ActiveCancelled() override; void ActiveChanged(AZ::EntityId m_newActiveInteractable, bool shouldStayActive) override; // ~UiInteractableActiveNotifications // IGameFrameworkListener / ISystem::CrySystemNotifications void OnPreRender() override; // ~IGameFrameworkListener / ISystem::CrySystemNotifications // IUiAnimationListener void OnUiAnimationEvent(EUiAnimationEvent uiAnimationEvent, IUiAnimSequence* pAnimSequence) override; void OnUiTrackEvent(AZStd::string eventName, AZStd::string valueName, IUiAnimSequence* pAnimSequence) override; // ~IUiAnimationListener // UiEditorCanvasInterface bool GetIsSnapEnabled() override; void SetIsSnapEnabled(bool enabled) override; float GetSnapDistance() override; void SetSnapDistance(float distance) override; float GetSnapRotationDegrees() override; void SetSnapRotationDegrees(float degrees) override; AZStd::vector<float> GetHorizontalGuidePositions() override; void AddHorizontalGuide(float position) override; void RemoveHorizontalGuide(int index) override; void SetHorizontalGuidePosition(int index, float position) override; AZStd::vector<float> GetVerticalGuidePositions() override; void AddVerticalGuide(float position) override; void RemoveVerticalGuide(int index) override; void SetVerticalGuidePosition(int index, float position) override; void RemoveAllGuides() override; AZ::Color GetGuideColor() override; void SetGuideColor(const AZ::Color& color) override; bool GetGuidesAreLocked() override; void SetGuidesAreLocked(bool areLocked) override; bool CheckForOrphanedElements() override; void RecoverOrphanedElements() override; void RemoveOrphanedElements() override; void UpdateCanvasInEditorViewport(float deltaTime, bool isInGame) override; void RenderCanvasInEditorViewport(bool isInGame, AZ::Vector2 viewportSize) override; // ~UiEditorCanvasInterface // UiCanvasComponentImplementationInterface void MarkRenderGraphDirty() override; // ~UiCanvasComponentImplementationInterface void UpdateCanvas(float deltaTime, bool isInGame); void RenderCanvas(bool isInGame, AZ::Vector2 viewportSize); AZ::Entity* GetRootElement() const; LyShine::ElementId GenerateId(); //! Clone this canvas's entity and return the Canvas component //! (used when it is loaded from in game or for preview mode etc) UiCanvasComponent* CloneAndInitializeCanvas(UiEntityContext* entityContext, const AZStd::string& assetIdPathname, const AZ::Vector2* canvasSize = nullptr); //! Deactivate all elements. Used when queuing a canvas up for deletion void DeactivateElements(); AZ::Vector2 GetTargetCanvasSize(); //! Get the mapping from editor EntityId to game EntityId. This will be empty for canvases loaded for editing AZ::SliceComponent::EntityIdToEntityIdMap GetEditorToGameEntityIdMap() { return m_editorToGameEntityIdMap; } void ScheduleElementForTransformRecompute(UiElementComponent* elementComponent); void UnscheduleElementForTransformRecompute(UiElementComponent* elementComponent); //! Queue an element to be destroyed at end of frame void ScheduleElementDestroy(AZ::EntityId entityId); #ifndef _RELEASE struct DebugInfoNumElements { int m_numElements; int m_numEnabledElements; int m_numRenderElements; int m_numRenderControlElements; int m_numImageElements; int m_numTextElements; int m_numMaskElements; int m_numFaderElements; int m_numInteractableElements; int m_numUpdateElements; }; void GetDebugInfoInteractables(AZ::EntityId& activeInteractable, AZ::EntityId& hoverInteractable) const; void GetDebugInfoNumElements(DebugInfoNumElements& info) const; void GetDebugInfoRenderGraph(LyShineDebug::DebugInfoRenderGraph& info) const; void DebugInfoCountChildren(const AZ::EntityId entity, bool parentEnabled, DebugInfoNumElements& info) const; void DebugReportDrawCalls(AZ::IO::HandleType fileHandle, LyShineDebug::DebugInfoDrawCallReport& reportInfo, void* context) const; void DebugDisplayElemBounds(IDraw2d* draw2d) const; void DebugDisplayChildElemBounds(IDraw2d* draw2d, const AZ::EntityId entity) const; #endif public: // static member functions static void GetProvidedServices(AZ::ComponentDescriptor::DependencyArrayType& provided) { provided.push_back(AZ_CRC("UiCanvasService", 0x2c8e8f87)); } static void GetIncompatibleServices(AZ::ComponentDescriptor::DependencyArrayType& incompatible) { incompatible.push_back(AZ_CRC("UiCanvasService", 0x2c8e8f87)); } static void GetRequiredServices(AZ::ComponentDescriptor::DependencyArrayType& required) { } static void Reflect(AZ::ReflectContext* context); // TODO: Move these static functions into a CanvasManager class static void Initialize(); static void Shutdown(); static UiCanvasComponent* CreateCanvasInternal(UiEntityContext* entityContext, bool forEditor); static UiCanvasComponent* LoadCanvasInternal(const string& pathToOpen, bool forEditor, const string& assetIdPathname, UiEntityContext* entityContext, const AZ::SliceComponent::EntityIdToEntityIdMap* previousRemapTable = nullptr, AZ::EntityId previousCanvasId = AZ::EntityId()); static UiCanvasComponent* FixupReloadedCanvasForEditorInternal(AZ::Entity* newCanvasEntity, AZ::Entity* rootSliceEntity, UiEntityContext* entityContext, LyShine::CanvasId existingId, const AZStd::string& existingPathname); protected: // member functions // AZ::Component void Init() override; void Activate() override; void Deactivate() override; // ~AZ::Component private: // member functions AZ_DISABLE_COPY_MOVE(UiCanvasComponent); // Texture Atlas loading void LoadAtlases(); void UnloadAtlases(); void ReloadAtlases(); // handle events for this canvas bool HandleHoverInputEvent(AZ::Vector2 point); bool HandleKeyInputEvent(const AzFramework::InputChannel::Snapshot& inputSnapshot, AzFramework::ModifierKeyMask activeModifierKeys = AzFramework::ModifierKeyMask::None); bool HandleNavigationInputEvent(UiNavigationHelpers::Command command, const AzFramework::InputChannel::Snapshot& inputSnapshot); bool HandleEnterInputEvent(UiNavigationHelpers::Command command, const AzFramework::InputChannel::Snapshot& inputSnapshot); bool HandleBackInputEvent(UiNavigationHelpers::Command command, const AzFramework::InputChannel::Snapshot& inputSnapshot); // A key was pressed to deactivate the active interactable bool DeactivateInteractableByKeyInput(const AzFramework::InputChannel::Snapshot& inputSnapshot); // A key was pressed to transfer hover to the ancestor interactable bool PassHoverToAncestorByKeyInput(const AzFramework::InputChannel::Snapshot& inputSnapshot); // Code shared by all positional input events bool HandlePrimaryPress(AZ::Vector2 point); bool HandlePrimaryUpdate(AZ::Vector2 point); bool HandlePrimaryRelease(AZ::Vector2 point); bool HandleMultiTouchPress(AZ::Vector2 point, int multiTouchIndex); bool HandleMultiTouchRelease(AZ::Vector2 point, int multiTouchIndex); bool HandleMultiTouchUpdated(AZ::Vector2 point, int multiTouchIndex); bool IsInteractableActiveOrPressed(AZ::EntityId interactableId) const; // Functions to change the hover and active interactables void SetHoverInteractable(AZ::EntityId interactableId); void ClearHoverInteractable(); void SetActiveInteractable(AZ::EntityId newActiveInteractable, bool shouldStayActive); void ClearActiveInteractable(); //! Check if the hover interactable is set to auto-activate, and if so activate it void CheckHoverInteractableAndAutoActivate(AZ::EntityId prevHoverInteractable = AZ::EntityId(), UiNavigationHelpers::Command command = UiNavigationHelpers::Command::Unknown, bool forceAutoActivate = false); //! Check if the active interactable has a descendant interactable. If it does, //! make the descendant the hover interactable and clear the active interactable void CheckActiveInteractableAndPassHoverToDescendant(AZ::EntityId prevHoverInteractable = AZ::EntityId(), UiNavigationHelpers::Command command = UiNavigationHelpers::Command::Unknown); //! Find the first interactable ancestor of the specified element AZ::EntityId FindAncestorInteractable(AZ::EntityId entityId); //! Get the first hover interactable, defaulting to the one set by the canvas AZ::EntityId GetFirstHoverInteractable(); //! Find the first interactable to receive focus AZ::EntityId FindFirstHoverInteractable(AZ::EntityId parentElement = AZ::EntityId()); //! Set the hover interactable on canvas load void SetFirstHoverInteractable(); //! Due to differences in their serialization systems we need to do some work before save void PrepareAnimationSystemForCanvasSave(); //! Due to differences in their serialization systems we need to do some work after load void RestoreAnimationSystemAfterCanvasLoad(bool remapIds, UiElementComponent::EntityIdMap* entityIdMap); //! Get a list of entity IDs for this element and all its descendant elements AZStd::vector<AZ::EntityId> GetEntityIdsOfElementAndDescendants(AZ::Entity* entity); //! Calculate the target canvas size and uniform scale void SetTargetCanvasSizeAndUniformScale(bool isInGame, AZ::Vector2 canvasSize); //! Check if an element name is unique bool IsElementNameUnique(const AZStd::string& elementName, const LyShine::EntityArray& elements); //! Methods used for controlling the Edit Context (the properties pane) using EntityComboBoxVec = AZStd::vector< AZStd::pair< AZ::EntityId, AZStd::string > >; EntityComboBoxVec PopulateNavigableEntityList(); EntityComboBoxVec PopulateTooltipDisplayEntityList(); void OnPixelAlignmentChange(); void OnTextPixelAlignmentChange(); void CreateRenderTarget(); void DestroyRenderTarget(); void RenderCanvasToTexture(); bool SaveCanvasToFile(const string& pathname, AZ::DataStream::StreamType streamType); bool SaveCanvasToStream(AZ::IO::GenericStream& stream, AZ::DataStream::StreamType streamType); //! Notify elements that their canvas space rect has changed since the last update, and recompute invalid layouts void SendRectChangeNotificationsAndRecomputeLayouts(); //! Notify elements that their canvas space rect has changed since the last update void SendRectChangeNotifications(); //! Compute the layout for all elements. Parents are computed first, then children. //! Called on canvas initialization void InitializeLayouts(); //! Call InGamePostActivate on children first, then parent void InGamePostActivateBottomUp(AZ::Entity* entity); //! Internal function for cloning an element AZ::Entity* CloneAndAddElementInternal(AZ::Entity* sourceEntity, AZ::Entity* parentEntity, AZ::Entity* insertBeforeEntity); //! Get any orphaned elements caused by old bugs void GetOrphanedElements(AZ::SliceComponent::EntityList& orphanedEntities); void DestroyScheduledElements(); private: // static member functions static AZ::u64 CreateUniqueId(); static UiCanvasComponent* FixupPostLoad(AZ::Entity* canvasEntity, AZ::Entity* rootSliceEntity, bool forEditor, UiEntityContext* entityContext, const AZ::Vector2* canvasSize = nullptr, const AZ::SliceComponent::EntityIdToEntityIdMap* previousRemapTable = nullptr, AZ::EntityId previousCanvasId = AZ::EntityId()); static bool VersionConverter(AZ::SerializeContext& context, AZ::SerializeContext::DataElementNode& classElement); private: // types typedef std::vector<UiCanvasComponent*> CanvasList; //!< Sorted by draw order private: // data AZStd::string m_pathname; //! This is an asset ID pathname AZ::u64 m_uniqueId; AZ::EntityId m_rootElement; LyShine::ElementId m_lastElementId; bool m_isPixelAligned = true; //! if true all visual elements have their vertices snapped to the nearest pixel bool m_isTextPixelAligned = true; //! if true all text is snapped to the nearest pixel AZ::EntityId m_firstHoverInteractable; bool m_isPositionalInputSupported = true; bool m_isConsumingAllInputEvents = false; bool m_isMultiTouchSupported = true; bool m_isNavigationSupported = true; float m_navigationThreshold = 0.4f; AZ::u64 m_navigationRepeatDelay = 300; AZ::u64 m_navigationRepeatPeriod = 150; AzFramework::LocalUserId m_localUserIdInputFilter = AzFramework::LocalUserIdAny; AZ::EntityId m_tooltipDisplayElement; AZ::Matrix4x4 m_canvasToViewportMatrix; AZ::Matrix4x4 m_viewportToCanvasMatrix; AZStd::vector <AzFramework::SimpleAssetReference<TextureAtlasNamespace::TextureAtlasAsset>> m_atlasPathNames; //! This is a list of filepaths for TextureAtlases AZStd::vector<TextureAtlasNamespace::TextureAtlas*> m_atlases; // In the comments below an "interactable entity" is an entity that is connected to the // UiInteractableBus //! The hover interactable is the interactable entity that the mouse cursor is currently over //! (or is selected by keyboard/controller navigation). The canvas tracks it so that it can tell //! the hover interactable that it is no longer in hover state when the cursor moves outside its bounds AZ::EntityId m_hoverInteractable; //! The active interactable is the interactable entity that the canvas considers "active". //! The active interactable is initially the interactable that handled the pressed event. //! An interactable can request to be stay active after the released event by returning //! "shouldStayActive" from HandlePressed. In this case the active interactable remains //! the active interactable until another interactable becomes active //! or until the active interactable itself requests to cancel its active status. //! If there is an active interactable when a released event is received then it //! is sent to the active interactable. //! The active interactable gets sent the mouse/touch position each frame (to support drag). //! The active interactable gets sent any character input received by the canvas. AZ::EntityId m_activeInteractable; //! If this is true the active interactable stays active after the release event bool m_activeInteractableShouldStayActive; //! True if the mouse is pressed or the enter key is down and there is an active interactable bool m_isActiveInteractablePressed; //! The last mouse position. Used to detect mouse movement AZ::Vector2 m_lastMousePosition; //! A map of all interactables that have handled a multi-touch (non-primary) pressed //! event but that are still waiting to receive the corresponding released event AZStd::unordered_map<int, AZ::EntityId> m_multiTouchInteractablesByTouchIndex; struct NavigationStatus { AZ::u64 lastNavigationTime; int navigationCount; bool allowNavigation; }; //! The status of navigation in each direction AZStd::unordered_map<UiNavigationHelpers::Command, NavigationStatus> m_navCommandStatus; LyShine::CanvasId m_id; int m_drawOrder; //! The authored canvas size, in pixels // //! While in the editor, this is the resolution that we display the canvas at. While in //! game, the authored canvas size is used to calculate m_uniformDeviceScale, which is //! used to apply the "scale to device" feature. AZ::Vector2 m_canvasSize; //! The target size of the canvas in pixels // //! The resolution that we display the canvas at. While in-game, we assume the canvas //! occupies the entire screen, so it is set to the viewport size. In the Editor, we //! set the target size to be the authored canvas size. AZ::Vector2 m_targetCanvasSize; //! The scale that will convert from canvasSize to viewportSize. //! In the editor this is always 1.0f //! In game it is the closer value to 1.0f of the two values m_viewportSize.x/m_canvasSize.x //! and m_viewportSize.y/m_canvasSize.y AZ::Vector2 m_deviceScale; //! True if this canvas is loaded in game (including for Ctrl-G in Sandbox), false if open in the UI Editor bool m_isLoadedInGame; //! This flag allows some UI canvases to stay loaded when transitioning from one level to another bool m_keepLoadedOnLevelUnload; //! True (default) if the canvas is visible and updated each frame, false otherwise bool m_enabled; //! Each canvas has its own animation system to manage all its animation sequences UiAnimationSystem m_uiAnimationSystem; UiSerialize::AnimationData m_serializedAnimationData; //! If true the canvas is not rendered to the screen but is instead rendered to a texture bool m_renderToTexture; //! The user-specified name for the render target taht we render to if m_renderToTexture is true AZStd::string m_renderTargetName; //! When rendering to a texture this is the texture ID of the render target int m_renderTargetHandle = -1; //! When rendering to a texture this is our depth surface SDepthTexture* m_renderTargetDepthSurface = nullptr; //! Each canvas has a layout manager to track and recompute layouts UiLayoutManager* m_layoutManager = nullptr; bool m_isSnapEnabled; float m_snapDistance; float m_snapRotationDegrees; //! guides (editor-only) AZStd::vector<float> m_horizontalGuidePositions; AZStd::vector<float> m_verticalGuidePositions; AZ::Color m_guideColor; bool m_guidesAreLocked; UiEntityContext* m_entityContext; AZ::SliceComponent::EntityIdToEntityIdMap m_editorToGameEntityIdMap; //! This is an optimization to avoid visiting all elements multiple times every frame to see if any of them need recomputing //! We use an intrusive_slist to avoid any memory allocations and also to cheaply be able to tell if an element is already in list using ElementComponentSlist = AZStd::intrusive_slist<UiElementComponent, AZStd::slist_base_hook<UiElementComponent>>; ElementComponentSlist m_elementsNeedingTransformRecompute; //! Holds elements that are queued up to be deleted at end of frame AZStd::vector<AZ::EntityId> m_elementsScheduledForDestroy; private: // static data //! If true update which element should be the hover interactable based on input position //! and notify the active interactable of position changes. Set to false when a key event //! occurs and back to true on mouse/touch activity. static bool s_handleHoverInputEvents; //! If true, when handling hover input events, allow clearing the hover interactable if the mouse isn't //! over any interactables. Set to false when a key event occurs and back to true when handling hover //! input events and the input position hovers over an interactable. static bool s_allowClearingHoverInteractableOnHoverInput; LyShine::RenderGraph m_renderGraph; //!< the render graph for rendering the canvas, can be cached between frames bool m_isRendering = false; };