#pragma once #include #include "base.hpp" #include "timer.hpp" namespace cru::ui::animations { using AnimationTimeUnit = FloatSecond; struct IAnimationDelegate : virtual Interface { virtual void Cancel() = 0; }; using AnimationDelegatePtr = std::shared_ptr; using AnimationStepHandler = std::function; using AnimationStartHandler = std::function; using AnimationFinishHandler = std::function; using AnimationCancelHandler = std::function; namespace details { class Animation; using AnimationPtr = std::unique_ptr; class AnimationInfo { public: AnimationInfo(String tag, const AnimationTimeUnit duration) : tag(std::move(tag)), duration(duration) { } AnimationInfo(const AnimationInfo& other) = default; AnimationInfo(AnimationInfo&& other) = default; AnimationInfo& operator=(const AnimationInfo& other) = default; AnimationInfo& operator=(AnimationInfo&& other) = default; ~AnimationInfo() = default; String tag; AnimationTimeUnit duration; std::vector step_handlers{}; std::vector start_handlers{}; std::vector finish_handlers{}; std::vector cancel_handlers{}; }; class AnimationManager : public Object { public: static AnimationManager* GetInstance(); private: AnimationManager(); public: AnimationManager(const AnimationManager& other) = delete; AnimationManager(AnimationManager&& other) = delete; AnimationManager& operator=(const AnimationManager& other) = delete; AnimationManager& operator=(AnimationManager&& other) = delete; ~AnimationManager() override; AnimationDelegatePtr CreateAnimation(AnimationInfo info); void RemoveAnimation(const String& tag); private: void SetTimer(); void KillTimer(); private: std::unordered_map animations_; std::optional timer_; }; } class AnimationBuilder : public Object { public: AnimationBuilder(String tag, const AnimationTimeUnit duration) : info_(std::move(tag), duration) { } AnimationBuilder& AddStepHandler(const AnimationStepHandler& handler) { CheckValid(); info_.step_handlers.push_back(handler); return *this; } AnimationBuilder& AddStartHandler(const AnimationStartHandler& handler) { CheckValid(); info_.start_handlers.push_back(handler); return *this; } AnimationBuilder& AddFinishHandler(const AnimationFinishHandler& handler) { CheckValid(); info_.finish_handlers.push_back(handler); return *this; } AnimationBuilder& AddCancelHandler(const AnimationCancelHandler& handler) { CheckValid(); info_.cancel_handlers.push_back(handler); return *this; } AnimationDelegatePtr Start(); private: void CheckValid() const { if (!valid_) throw std::runtime_error("The animation builder is invalid."); } bool valid_ = true; details::AnimationInfo info_; }; }