3
0

UiTransform2dComponent.h 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290
  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/UiAnimateEntityBus.h>
  10. #include <LyShine/Bus/UiTransformBus.h>
  11. #include <LyShine/Bus/UiTransform2dBus.h>
  12. #include <LyShine/Bus/UiLayoutFitterBus.h>
  13. #include <LyShine/UiComponentTypes.h>
  14. #include <LyShine/UiSerializeHelpers.h>
  15. #include <AzCore/Component/Component.h>
  16. // Only needed for internal unit-testing
  17. #include <LyShine.h>
  18. class UiCanvasComponent;
  19. class UiElementComponent;
  20. ////////////////////////////////////////////////////////////////////////////////////////////////////
  21. class UiTransform2dComponent
  22. : public AZ::Component
  23. , public UiTransformBus::Handler
  24. , public UiTransform2dBus::Handler
  25. , public UiAnimateEntityBus::Handler
  26. {
  27. public: // member functions
  28. AZ_COMPONENT(UiTransform2dComponent, LyShine::UiTransform2dComponentUuid, AZ::Component);
  29. UiTransform2dComponent();
  30. ~UiTransform2dComponent() override;
  31. // UiTransformInterface
  32. float GetZRotation() override;
  33. void SetZRotation(float rotation) override;
  34. AZ::Vector2 GetScale() override;
  35. void SetScale(AZ::Vector2 scale) override;
  36. float GetScaleX() override;
  37. void SetScaleX(float scale) override;
  38. float GetScaleY() override;
  39. void SetScaleY(float scale) override;
  40. AZ::Vector2 GetPivot() override;
  41. void SetPivot(AZ::Vector2 pivot) override;
  42. float GetPivotX() override;
  43. void SetPivotX(float pivot) override;
  44. float GetPivotY() override;
  45. void SetPivotY(float pivot) override;
  46. ScaleToDeviceMode GetScaleToDeviceMode() override;
  47. void SetScaleToDeviceMode(ScaleToDeviceMode scaleToDeviceMode) override;
  48. bool GetIsFlooringOffsets() override;
  49. void SetIsFlooringOffsets(bool isFlooringOffsets) override;
  50. void GetViewportSpacePoints(RectPoints& points) final;
  51. AZ::Vector2 GetViewportSpacePivot() final;
  52. void GetTransformToViewport(AZ::Matrix4x4& mat) final;
  53. void GetTransformFromViewport(AZ::Matrix4x4& mat) final;
  54. void RotateAndScalePoints(RectPoints& points) final;
  55. void GetCanvasSpacePoints(RectPoints& points) final;
  56. AZ::Vector2 GetCanvasSpacePivot() final;
  57. void GetTransformToCanvasSpace(AZ::Matrix4x4& mat) final;
  58. void GetTransformFromCanvasSpace(AZ::Matrix4x4& mat) final;
  59. void GetCanvasSpaceRectNoScaleRotate(Rect& rect) final;
  60. void GetCanvasSpacePointsNoScaleRotate(RectPoints& points) final;
  61. AZ::Vector2 GetCanvasSpaceSizeNoScaleRotate() final;
  62. AZ::Vector2 GetCanvasSpacePivotNoScaleRotate() final;
  63. void GetLocalTransform(AZ::Matrix4x4& mat) final;
  64. void GetLocalInverseTransform(AZ::Matrix4x4& mat) final;
  65. bool HasScaleOrRotation() final;
  66. AZ::Vector2 GetViewportPosition() final;
  67. void SetViewportPosition(const AZ::Vector2& position) final;
  68. AZ::Vector2 GetCanvasPosition() final;
  69. void SetCanvasPosition(const AZ::Vector2& position) final;
  70. AZ::Vector2 GetLocalPosition() final;
  71. void SetLocalPosition(const AZ::Vector2& position) final;
  72. float GetLocalPositionX() final;
  73. void SetLocalPositionX(float position) final;
  74. float GetLocalPositionY() final;
  75. void SetLocalPositionY(float position) final;
  76. void MoveViewportPositionBy(const AZ::Vector2& offset) final;
  77. void MoveCanvasPositionBy(const AZ::Vector2& offset) final;
  78. void MoveLocalPositionBy(const AZ::Vector2& offset) final;
  79. bool IsPointInRect(AZ::Vector2 point) final;
  80. bool BoundsAreOverlappingRect(const AZ::Vector2& bound0, const AZ::Vector2& bound1) final;
  81. void SetRecomputeFlags(Recompute recompute) final;
  82. bool HasCanvasSpaceRectChanged() final;
  83. bool HasCanvasSpaceSizeChanged() final;
  84. bool HasCanvasSpaceRectChangedByInitialization() final;
  85. void NotifyAndResetCanvasSpaceRectChange() final;
  86. // ~UiTransformInterface
  87. // UiTransform2dInterface
  88. Anchors GetAnchors() override;
  89. void SetAnchors(Anchors anchors, bool adjustOffsets, bool allowPush) override;
  90. Offsets GetOffsets() override;
  91. void SetOffsets(Offsets offsets) override;
  92. void SetPivotAndAdjustOffsets(AZ::Vector2 pivot) override;
  93. void SetLocalWidth(float width) override;
  94. float GetLocalWidth() override;
  95. void SetLocalHeight(float height) override;
  96. float GetLocalHeight() override;
  97. // ~UiTransform2dInterface
  98. // UiAninmateEntityInterface
  99. void PropertyValuesChanged() override;
  100. // ~UiAninmateEntityInterface
  101. //! This is called from the canvas component during the update if the element was scheduled for a transform recompute
  102. void RecomputeTransformsAndSendNotifications();
  103. #if defined(LYSHINE_INTERNAL_UNIT_TEST)
  104. static void UnitTest(CLyShine* lyshine, IConsoleCmdArgs* cmdArgs);
  105. #endif
  106. public: // static member functions
  107. static void GetProvidedServices(AZ::ComponentDescriptor::DependencyArrayType& provided)
  108. {
  109. provided.push_back(AZ_CRC("UiTransformService", 0x3a838e34));
  110. }
  111. static void GetIncompatibleServices(AZ::ComponentDescriptor::DependencyArrayType& incompatible)
  112. {
  113. incompatible.push_back(AZ_CRC("UiTransformService", 0x3a838e34));
  114. }
  115. static void GetRequiredServices([[maybe_unused]] AZ::ComponentDescriptor::DependencyArrayType& required)
  116. {
  117. }
  118. static void Reflect(AZ::ReflectContext* context);
  119. protected: // member functions
  120. // AZ::Component
  121. void Activate() override;
  122. void Deactivate() override;
  123. // ~AZ::Component
  124. //! Determine whether this element's transform is being overridden by a component on its parent
  125. virtual bool IsControlledByParent() const;
  126. //! Get the level of control of a layout fitter
  127. virtual UiLayoutFitterInterface::FitType GetLayoutFitterType() const;
  128. //! Determine whether this element's transform is not being overridden by a component on its parent
  129. //! This just exists to be called from the edit context setup
  130. bool IsNotControlledByParent() const;
  131. //! Get the first ancestor that has a scale to device mode affecting the same dimension as this
  132. //! element's scale to device mode
  133. AZ::EntityId GetAncestorWithSameDimensionScaleToDevice(ScaleToDeviceMode scaleToDeviceMode) const;
  134. //! Get a list of descendants that have a scale to device mode affecting the same dimension as this
  135. //! element's scale to device mode
  136. LyShine::EntityArray GetDescendantsWithSameDimensionScaleToDevice(ScaleToDeviceMode scaleToDeviceMode) const;
  137. //! Return whether there are anchors that are apart affecting the same dimension as this
  138. //! element's scale to device mode
  139. bool AreAnchorsApartInSameScaleToDeviceDimension(ScaleToDeviceMode scaleToDeviceMode) const;
  140. //! Return a short one line string that incudes a warning for the currently assigned scale to device mode.
  141. //! An empty string indicates no warnings
  142. AZStd::string GetScaleToDeviceModeWarningText() const;
  143. //! Return a tooltip string describing the warning for the currently assigned scale to device mode.
  144. //! An empty string indicates no warnings
  145. AZStd::string GetScaleToDeviceModeWarningTooltipText() const;
  146. //! This is used to dynamically change the label for the Anchor property in the properties pane
  147. //! as a way to display a "disabled" stated for this component when the transform is controlled by the
  148. //! parent.
  149. const char* GetAnchorPropertyLabel() const;
  150. //! Helper function to get the canvas entity ID for canvas containing this element
  151. AZ::EntityId GetCanvasEntityId();
  152. //! Helper function to get the canvas component for canvas containing this element
  153. UiCanvasComponent* GetCanvasComponent() const;
  154. //! ChangeNotify function for when a transform property is changed
  155. void OnTransformPropertyChanged();
  156. //! If m_recomputeTransformToViewport is true then recompute the transform and clear the flag
  157. void RecomputeTransformToViewportIfNeeded();
  158. //! If m_recomputeTransformToCanvasSpace is true then recompute the transform and clear the flag
  159. void RecomputeTransformToCanvasSpaceIfNeeded();
  160. private: // member functions
  161. AZ_DISABLE_COPY_MOVE(UiTransform2dComponent);
  162. //! Get the scale with the uniform device scale factored in, if m_scaleToDevice is true
  163. AZ::Vector2 GetScaleAdjustedForDevice();
  164. //! Calculates the rect if m_recomputeCanvasSpaceRect dirty flag is set
  165. void CalculateCanvasSpaceRect();
  166. //! Get the position of the element's anchors in canvas space
  167. AZ::Vector2 GetCanvasSpaceAnchorsCenterNoScaleRotate();
  168. // Get a pointer to this entity's UiElementComponent.
  169. UiElementComponent* GetElementComponent() const;
  170. // Get a pointer to the parent element's transform component. Returns nullptr if no parent.
  171. UiTransform2dComponent* GetParentTransformComponent() const;
  172. // Get a pointer to the given child element's transform component. Returns nullptr if no parent.
  173. UiTransform2dComponent* GetChildTransformComponent(int index) const;
  174. // Used to check that FixupPostLoad has been called
  175. bool IsFullyInitialized() const;
  176. // Display a warning that the component is not yet fully initialized
  177. void EmitNotInitializedWarning() const;
  178. // Given a scale apply the canvases device scale to it according to the m_scaleToDeviceMode setting
  179. void ApplyDeviceScale(AZ::Vector2& scale);
  180. private: // static member functions
  181. static bool VersionConverter(AZ::SerializeContext& context,
  182. AZ::SerializeContext::DataElementNode& classElement);
  183. //! Determine whether the specified scale to device mode affects horizontal scale
  184. static bool DoesScaleToDeviceModeAffectX(ScaleToDeviceMode scaleToDeviceMode);
  185. //! Determine whether the specified scale to device mode affects vertical scale
  186. static bool DoesScaleToDeviceModeAffectY(ScaleToDeviceMode scaleToDeviceMode);
  187. private: // data
  188. Anchors m_anchors; // initialized by Anchors constructor
  189. Offsets m_offsets; // initialized by Offsets constructor
  190. AZ::Vector2 m_pivot;
  191. float m_rotation;
  192. AZ::Vector2 m_scale;
  193. bool m_isFlooringOffsets = false;
  194. //! Cached transform to viewport space. Gets recalculated if the m_recomputeTransformToViewport dirty flag is set
  195. AZ::Matrix4x4 m_transformToViewport;
  196. //! Cached transform to canvas space. Gets recalculated if the m_recomputeTransformToCanvasSpace dirty flag is set
  197. AZ::Matrix4x4 m_transformToCanvasSpace;
  198. //! Cached rect in CanvasNoScaleRotateSpace.
  199. //! Gets recalculated if the m_recomputeCanvasSpaceRect dirty flag is set
  200. Rect m_rect;
  201. //! The previously cached rect in CanvasNoScaleRotateSpace.
  202. //! Initialized when m_rect is calculated for the first time.
  203. //! Updated to m_rect when a rect change notification is sent
  204. Rect m_prevRect;
  205. //! True if m_rect has been calculated
  206. bool m_rectInitialized;
  207. //! True if the rect has changed due to it being calculated for the first time. In this
  208. //! case m_prevRect will equal m_rect
  209. bool m_rectChangedByInitialization;
  210. //! If this is not set to None then the canvas scale is applied, in addition to m_scale, according to this mode
  211. ScaleToDeviceMode m_scaleToDeviceMode;
  212. //! If this is true, then the transform stored in m_transformToViewport is dirty and needs to be recomputed
  213. bool m_recomputeTransformToViewport;
  214. //! If this is true, then the transform stored in m_transformToCanvasSpace is dirty and needs to be recomputed
  215. bool m_recomputeTransformToCanvasSpace;
  216. bool m_recomputeCanvasSpaceRect;
  217. //! Pointer directly to the UiElementComponent for this entity. Cached for performance after profiling.
  218. UiElementComponent* m_elementComponent = nullptr;
  219. };