UiFlipbookAnimationComponent.h 7.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182
  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 <AzCore/Component/Component.h>
  10. #include <AzCore/Math/Transform.h>
  11. #include <AzCore/Slice/SliceAsset.h>
  12. #include <AzFramework/Entity/EntityContextBus.h>
  13. #include <LyShine/Bus/UiCanvasUpdateNotificationBus.h>
  14. #include <LyShine/Bus/UiFlipbookAnimationBus.h>
  15. #include <LyShine/Bus/UiInitializationBus.h>
  16. #include <LyShine/Bus/Sprite/UiSpriteBus.h>
  17. #include <LyShine/UiComponentTypes.h>
  18. #include "EditorPropertyTypes.h"
  19. //////////////////////////////////////////////////////////////////////////
  20. //! FlipbookAnimationComponent
  21. //! FlipbookAnimationComponent provides a way to create an animated sprite for a UI canvas
  22. //! using sprite-sheets (via the image component)
  23. class UiFlipbookAnimationComponent
  24. : public AZ::Component
  25. , public UiCanvasUpdateNotificationBus::Handler
  26. , public UiFlipbookAnimationBus::Handler
  27. , public UiInitializationBus::Handler
  28. , public UiSpriteSourceNotificationBus::Handler
  29. {
  30. public: // static functions
  31. static void GetProvidedServices(AZ::ComponentDescriptor::DependencyArrayType& provided)
  32. {
  33. provided.push_back(AZ_CRC("UiFlipbookService"));
  34. }
  35. static void GetIncompatibleServices(AZ::ComponentDescriptor::DependencyArrayType& incompatible)
  36. {
  37. incompatible.push_back(AZ_CRC("UiFlipbookService"));
  38. }
  39. static void GetRequiredServices(AZ::ComponentDescriptor::DependencyArrayType& required)
  40. {
  41. required.push_back(AZ_CRC("UiIndexableImageService"));
  42. }
  43. public: // functions
  44. AZ_COMPONENT(UiFlipbookAnimationComponent, LyShine::UiFlipbookAnimationComponentUuid);
  45. UiFlipbookAnimationComponent() = default;
  46. ~UiFlipbookAnimationComponent() override = default;
  47. //////////////////////////////////////////////////////////////////////////
  48. // AZ::Component
  49. void Activate() override;
  50. void Deactivate() override;
  51. //////////////////////////////////////////////////////////////////////////
  52. // UiCanvasUpdateNotificationBus::Handler
  53. void Update(float deltaTime) override;
  54. //////////////////////////////////////////////////////////////////////////
  55. // UiInitializationBus::Handler
  56. void InGamePostActivate() override;
  57. //////////////////////////////////////////////////////////////////////////
  58. // UiFlipbookAnimationBus::Handler
  59. void Start() override;
  60. void Stop() override;
  61. bool IsPlaying() override { return m_isPlaying; }
  62. AZ::u32 GetStartFrame() override { return m_startFrame; }
  63. void SetStartFrame(AZ::u32 startFrame) override;
  64. AZ::u32 GetEndFrame() override { return m_endFrame; }
  65. void SetEndFrame(AZ::u32 endFrame) override;
  66. AZ::u32 GetCurrentFrame() override { return m_currentFrame; }
  67. void SetCurrentFrame(AZ::u32 currentFrame) override;
  68. AZ::u32 GetLoopStartFrame() override { return m_loopStartFrame; }
  69. void SetLoopStartFrame(AZ::u32 loopStartFrame) override;
  70. UiFlipbookAnimationInterface::LoopType GetLoopType() override { return m_loopType; }
  71. void SetLoopType(UiFlipbookAnimationInterface::LoopType loopType) override;
  72. float GetFramerate() override { return m_framerate; }
  73. void SetFramerate(float framerate) override { m_framerate = AZ::GetMax<float>(0.0f, framerate); }
  74. FramerateUnits GetFramerateUnit() override { return m_framerateUnit; }
  75. void SetFramerateUnit(FramerateUnits framerateUnit) override { m_framerateUnit = framerateUnit; }
  76. float GetStartDelay() override { return m_startDelay; }
  77. void SetStartDelay(float startDelay) override { m_startDelay = AZ::GetMax<float>(0.0f, startDelay); }
  78. float GetLoopDelay() override { return m_loopDelay; }
  79. void SetLoopDelay(float loopDelay) override { m_loopDelay = AZ::GetMax<float>(0.0f, loopDelay); }
  80. float GetReverseDelay() override { return m_reverseDelay; }
  81. void SetReverseDelay(float reverseDelay) override { m_reverseDelay = AZ::GetMax<float>(0.0f, reverseDelay); }
  82. bool GetIsAutoPlay() override { return m_isAutoPlay; }
  83. void SetIsAutoPlay(bool isAutoPlay) override { m_isAutoPlay = isAutoPlay; }
  84. //////////////////////////////////////////////////////////////////////////
  85. // UiSpriteSourceNotificationBus::Handler
  86. void OnSpriteSourceChanged() override;
  87. protected: // static functions
  88. //////////////////////////////////////////////////////////////////////////
  89. // Component descriptor
  90. static void Reflect(AZ::ReflectContext* context);
  91. //////////////////////////////////////////////////////////////////////////
  92. protected: // functions
  93. //! Returns a string representation of the indices used to index sprite-sheet types.
  94. LyShine::AZu32ComboBoxVec PopulateIndexStringList() const;
  95. //! Populates a list of enumerated frame values between the start and end frame range
  96. LyShine::AZu32ComboBoxVec PopulateConstrainedIndexStringList() const;
  97. //! Total number of cells within sprite-sheet
  98. AZ::u32 GetMaxFrame() const;
  99. //! Ensures that the given frame value is valid for the associated sprite-sheet
  100. bool FrameWithinRange(AZ::u32 frameValue);
  101. //! Updates correlated frame values when the start frame value changes.
  102. void OnStartFrameChange();
  103. //! Updates correlated frame values when the end frame value changes.
  104. void OnEndFrameChange();
  105. //! Converts the frame-rate value based on the new framerate unit.
  106. void OnFramerateUnitChange();
  107. //! Returns true if this is a PingPong loop type, false otherwise.
  108. bool IsPingPongLoopType() const;
  109. //! Returns true if animation will loop, false otherwise.
  110. bool IsLoopingType() const;
  111. //! Returns the amount to delay the current (forward or reverse) loop sequence
  112. float CalculateLoopDelay() const;
  113. //! Returns the framerate in seconds-per-frame.
  114. float CalculateFramerateAsSecondsPerFrame() const { return m_framerateUnit == FramerateUnits::FPS && m_framerate != 0.0f ? 1.0f / m_framerate : m_framerate; }
  115. protected: // variables
  116. // Serialized members
  117. AZ::u32 m_startFrame = 0; //!< Start frame of animation. Can be different from "loop start" frame
  118. //!< to allow animations to have an "intro" sequence.
  119. AZ::u32 m_endFrame = 0; //!< Last frame of animation.
  120. AZ::u32 m_loopStartFrame = 0; //!< Start frame for looped animations
  121. UiFlipbookAnimationInterface::LoopType m_loopType = UiFlipbookAnimationInterface::LoopType::None;
  122. float m_framerate = 0.0f; //!< Transition speed between frames (either in FPS or seconds to wait per frame).
  123. float m_startDelay = 0.0f; //!< Number of seconds to wait before playing the flipbook (applied only once during playback).
  124. float m_loopDelay = 0.0f; //!< Number of seconds to wait before playing the loop sequence
  125. float m_reverseDelay = 0.0f; //!< Number of seconds to wait before playing the reverse loop sequence (PingPong loop types)
  126. bool m_isAutoPlay = true; //!< Whether the animation should automatically start playing.
  127. FramerateUnits m_framerateUnit = FramerateUnits::FPS; //! Units to use when defining framerate
  128. // Non-serialized members
  129. AZ::u32 m_currentFrame = 0; //!< Current sprite-sheet frame/index displayed
  130. AZ::u32 m_prevFrame = 0; //!< Previous frame displayed - used to detect intro sequences in a loop
  131. float m_elapsedTime = 0.0f; //!< Used to determine passage of time for handling frame delay
  132. bool m_isPlaying = false; //!< True if the animation is playing, false otherwise
  133. AZ::s32 m_currentLoopDirection = 1; //!< Used for PingPong loop direction (positive/negative)
  134. bool m_useStartDelay = false; //!< Keeps track of whether start delay applies or not.
  135. };