UiMaskComponent.h 9.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215
  1. /*
  2. * Copyright (c) Contributors to the Open 3D Engine Project.
  3. * For complete copyright and license terms please see the LICENSE at the root of this distribution.
  4. *
  5. * SPDX-License-Identifier: Apache-2.0 OR MIT
  6. *
  7. */
  8. #pragma once
  9. #include <LyShine/Bus/UiRenderControlBus.h>
  10. #include <LyShine/Bus/UiMaskBus.h>
  11. #include <LyShine/Bus/UiInteractionMaskBus.h>
  12. #include <LyShine/Bus/UiTransformBus.h>
  13. #include <LyShine/UiComponentTypes.h>
  14. #include <LyShine/IRenderGraph.h>
  15. #include <LyShine/UiRenderFormats.h>
  16. #include <AzCore/Component/Component.h>
  17. #include <Atom/RHI.Reflect/AttachmentId.h>
  18. ////////////////////////////////////////////////////////////////////////////////////////////////////
  19. class UiMaskComponent
  20. : public AZ::Component
  21. , public UiRenderControlBus::Handler
  22. , public UiMaskBus::Handler
  23. , public UiInteractionMaskBus::Handler
  24. , public UiTransformChangeNotificationBus::Handler
  25. {
  26. public: // member functions
  27. AZ_COMPONENT(UiMaskComponent, LyShine::UiMaskComponentUuid, AZ::Component);
  28. UiMaskComponent();
  29. ~UiMaskComponent() override;
  30. // UiRenderControlInterface
  31. void Render(LyShine::IRenderGraph* renderGraph, UiElementInterface* elementInterface,
  32. UiRenderInterface* renderInterface, int numChildren, bool isInGame) override;
  33. // ~UiRenderControlInterface
  34. // UiMaskInterface
  35. bool GetIsMaskingEnabled() override;
  36. void SetIsMaskingEnabled(bool enableMasking) override;
  37. bool GetIsInteractionMaskingEnabled() override;
  38. void SetIsInteractionMaskingEnabled(bool enableMasking) override;
  39. bool GetDrawBehind() override;
  40. void SetDrawBehind(bool drawMaskVisualBehindChildren) override;
  41. bool GetDrawInFront() override;
  42. void SetDrawInFront(bool drawMaskVisualInFrontOfChildren) override;
  43. bool GetUseAlphaTest() override;
  44. void SetUseAlphaTest(bool useAlphaTest) override;
  45. bool GetUseRenderToTexture() override;
  46. void SetUseRenderToTexture(bool useRenderToTexture) override;
  47. // ~UiMaskInterface
  48. // UiInteractionMaskInterface
  49. bool IsPointMasked(AZ::Vector2 point) override;
  50. // ~UiInteractionMaskInterface
  51. // UiTransformChangeNotification
  52. void OnCanvasSpaceRectChanged(AZ::EntityId entityId, const UiTransformInterface::Rect& oldRect, const UiTransformInterface::Rect& newRect) override;
  53. void OnTransformToViewportChanged() override;
  54. // ~UiTransformChangeNotification
  55. public: // static member functions
  56. static void GetProvidedServices(AZ::ComponentDescriptor::DependencyArrayType& provided)
  57. {
  58. provided.push_back(AZ_CRC("UiMaskService", 0x806f6dac));
  59. provided.push_back(AZ_CRC("UiRenderControlService", 0x4e302454));
  60. }
  61. static void GetIncompatibleServices(AZ::ComponentDescriptor::DependencyArrayType& incompatible)
  62. {
  63. incompatible.push_back(AZ_CRC("UiRenderControlService", 0x4e302454));
  64. }
  65. static void GetRequiredServices(AZ::ComponentDescriptor::DependencyArrayType& required)
  66. {
  67. // Note that the UiVisualService is not required because a child mask element can be used instead.
  68. required.push_back(AZ_CRC("UiElementService", 0x3dca7ad4));
  69. required.push_back(AZ_CRC("UiTransformService", 0x3a838e34));
  70. }
  71. static void Reflect(AZ::ReflectContext* context);
  72. protected: // member functions
  73. // AZ::Component
  74. void Activate() override;
  75. void Deactivate() override;
  76. // ~AZ::Component
  77. AZ_DISABLE_COPY_MOVE(UiMaskComponent);
  78. private: // member functions
  79. //! Method used to populate the drop down for the m_childMaskElement property field
  80. using EntityComboBoxVec = AZStd::vector< AZStd::pair< AZ::EntityId, AZStd::string > >;
  81. EntityComboBoxVec PopulateChildEntityList();
  82. //! Mark the render graph as dirty, this should be done when any change is made affects the structure of the graph
  83. void MarkRenderGraphDirty();
  84. //! Called when a property changed in property pane that invalidates render settings
  85. void OnEditorRenderSettingChange();
  86. //! Called when something changed that invalidates render target
  87. void OnRenderTargetChange();
  88. //! When m_useRenderToTexture is true this is used to create the render targets and depth surface or resize them if they exist
  89. void CreateOrResizeRenderTarget(const AZ::Vector2& pixelAlignedTopLeft, const AZ::Vector2& pixelAlignedBottomRight);
  90. //! Destroy the render targets and depth surface that are used when m_useRenderToTexture is true
  91. void DestroyRenderTarget();
  92. //! Update cached primitive vertices
  93. void UpdateCachedPrimitive(const AZ::Vector2& pixelAlignedTopLeft, const AZ::Vector2& pixelAlignedBottomRight);
  94. // compute pixel aligned bounds of element in viewport space
  95. void ComputePixelAlignedBounds(AZ::Vector2& pixelAlignedTopLeft, AZ::Vector2& pixelAlignedBottomRight);
  96. //! Some properties are only visible when this is a stencil mask as opposed to a gradient mask
  97. bool IsStencilMask();
  98. // render the element and its children using stencil mask
  99. void RenderUsingStencilMask(LyShine::IRenderGraph* renderGraph, UiElementInterface* elementInterface,
  100. UiRenderInterface* renderInterface, UiElementInterface* childMaskElementInterface, int numChildren, bool isInGame);
  101. // render the element and its children using render-to-texture and an alpha gradient mask
  102. void RenderUsingGradientMask(LyShine::IRenderGraph* renderGraph, UiElementInterface* elementInterface,
  103. UiRenderInterface* renderInterface, UiElementInterface* childMaskElementInterface, int numChildren, bool isInGame);
  104. // render a disabled mask (in case where we don't have both draw behind and draw in front enabled)
  105. void RenderDisabledMask(LyShine::IRenderGraph* renderGraph, UiElementInterface* elementInterface,
  106. UiRenderInterface* renderInterface, UiElementInterface* childMaskElementInterface, int numChildren, bool isInGame);
  107. // render a disabled mask (in case where we do have both draw behind and draw in front enabled
  108. void RenderDisabledMaskWithDoubleRender(LyShine::IRenderGraph* renderGraph, UiElementInterface* elementInterface,
  109. UiRenderInterface* renderInterface, UiElementInterface* childMaskElementInterface, int numChildren, bool isInGame);
  110. // render this element's component and the child mask element
  111. void RenderMaskPrimitives(LyShine::IRenderGraph* renderGraph,
  112. UiRenderInterface* renderInterface, UiElementInterface* childMaskElementInterface, bool isInGame);
  113. // render this element's child elements (excluding the child mask element)
  114. void RenderContentPrimitives(LyShine::IRenderGraph* renderGraph, UiElementInterface* elementInterface,
  115. UiElementInterface* childMaskElementInterface, int numChildren, bool isInGame);
  116. // validate that nested mask configurations are valid during rendering and output a warning if not
  117. bool ValidateMaskConfiguration(const LyShine::IRenderGraph* renderGraph);
  118. // Get the element interface child mask element after checking that the configuration of it is valid
  119. // output a warning if not (used during render).
  120. UiElementInterface* GetValidatedChildMaskElement();
  121. private: // data
  122. // Serialized members
  123. //! flag allows for easy debugging, also can be used to turn mask on/off from C++
  124. //! or in an animation.
  125. bool m_enableMasking;
  126. //! flags to control whether the mask is drawn to color buffer as well as to the
  127. //! stencil in the first and second passes
  128. bool m_drawMaskVisualBehindChildren;
  129. bool m_drawMaskVisualInFrontOfChildren;
  130. //! Whether to enable alphatest when drawing mask visual.
  131. bool m_useAlphaTest;
  132. //! Whether to mask interaction
  133. bool m_maskInteraction;
  134. //! An optional child element that defines additional mask visuals
  135. AZ::EntityId m_childMaskElement;
  136. bool m_useRenderToTexture = false; //!< If true, render this element and children to a separate render target and fade that
  137. // Non-serialized members
  138. //! This is generated from the entity ID and cached
  139. AZStd::string m_renderTargetName;
  140. //! This is generated from the entity ID and cached
  141. AZStd::string m_maskRenderTargetName;
  142. //! When rendering to a texture this is the attachment image for the render target
  143. AZ::RHI::AttachmentId m_contentAttachmentImageId;
  144. //! When rendering to a texture this is the texture ID of the render target
  145. //! When rendering to a texture this is the attachment image for the render target
  146. AZ::RHI::AttachmentId m_maskAttachmentImageId;
  147. //! The positions used for the render to texture viewport and to render the render target to the screen
  148. AZ::Vector2 m_viewportTopLeft = AZ::Vector2::CreateZero();
  149. AZ::Vector2 m_viewportSize = AZ::Vector2::CreateZero();
  150. // currently allocated size of render target
  151. int m_renderTargetWidth = 0;
  152. int m_renderTargetHeight = 0;
  153. //! cached rendering data for performance optimization of rendering the render target to screen
  154. LyShine::UiPrimitive m_cachedPrimitive;
  155. #ifndef _RELEASE
  156. //! This variable is only used to prevent spamming a warning message each frame (for nested stencil masks)
  157. bool m_reportedNestedStencilWarning = false;
  158. //! This variable is only used to prevent spamming a warning message each frame (for invalid child mask elements)
  159. bool m_reportedInvalidChildMaskElementWarning = false;
  160. #endif
  161. };