diff options
Diffstat (limited to 'CruUI/ui/animations/animation.cpp')
-rw-r--r-- | CruUI/ui/animations/animation.cpp | 227 |
1 files changed, 157 insertions, 70 deletions
diff --git a/CruUI/ui/animations/animation.cpp b/CruUI/ui/animations/animation.cpp index 26b7d5fc..9d05860a 100644 --- a/CruUI/ui/animations/animation.cpp +++ b/CruUI/ui/animations/animation.cpp @@ -5,99 +5,186 @@ namespace cru::ui::animations { - constexpr int frame_rate = 60; - constexpr double frame_step_time = 1.0 / frame_rate; - - AnimationManager::AnimationManager() - : timer_action_(new Action<>([this]() + namespace details { - for (auto& animation : animations_) + class AnimationDelegateImpl; + constexpr double frame_rate = 60; + constexpr AnimationTimeUnit frame_step_time = AnimationTimeUnit(1) / frame_rate; + + + class AnimationDelegateImpl : public virtual IAnimationDelegate { - if (animation.second->Step(frame_step_time)) - InvokeLater([=] + public: + explicit AnimationDelegateImpl(String tag) + : tag_(std::move(tag)) + { + + } + AnimationDelegateImpl(const AnimationDelegateImpl& other) = delete; + AnimationDelegateImpl(AnimationDelegateImpl&& other) = delete; + AnimationDelegateImpl& operator=(const AnimationDelegateImpl& other) = delete; + AnimationDelegateImpl& operator=(AnimationDelegateImpl&& other) = delete; + ~AnimationDelegateImpl() override = default; + + void Cancel() override + { + AnimationManager::GetInstance()->RemoveAnimation(tag_); + } + + private: + String tag_; + }; + + + class Animation : public Object + { + public: + Animation( + String tag, + AnimationTimeUnit duration, + Vector<AnimationStepHandlerPtr> step_handlers, + Vector<AnimationStartHandlerPtr> start_handlers, + Vector<ActionPtr> finish_handlers, + Vector<ActionPtr> cancel_handlers, + AnimationDelegatePtr delegate + ); + Animation(const Animation& other) = delete; + Animation(Animation&& other) = delete; + Animation& operator=(const Animation& other) = delete; + Animation& operator=(Animation&& other) = delete; + ~Animation() override; + + + // If finish or invalid, return false. + bool Step(AnimationTimeUnit time); + + String GetTag() const { - RemoveAnimation(animation.second); //TODO!!! - }); + return tag_; + } + + private: + const String tag_; + const AnimationTimeUnit duration_; + Vector<AnimationStepHandlerPtr> step_handlers_; + Vector<AnimationStartHandlerPtr> start_handlers_; + Vector<ActionPtr> finish_handlers_; + Vector<ActionPtr> cancel_handlers_; + AnimationDelegatePtr delegate_; + + AnimationTimeUnit current_time_ = AnimationTimeUnit::zero(); + }; + + AnimationManager::AnimationManager() + : timer_action_(CreateActionPtr([this]() + { + auto i = animations_.cbegin(); + while (i != animations_.cend()) + { + auto current_i = i++; + if (current_i->second->Step(frame_step_time)) + animations_.erase(current_i); + } + + if (animations_.empty()) + KillTimer(); + })) + { + } - })) - { - } + AnimationManager::~AnimationManager() + { + KillTimer(); + } - AnimationManager::~AnimationManager() - { - for (auto& animation : animations_) - delete animation.second; + AnimationDelegatePtr AnimationManager::CreateAnimation(String tag, AnimationTimeUnit duration, + Vector<AnimationStepHandlerPtr> step_handlers, Vector<AnimationStartHandlerPtr> start_handlers, + Vector<ActionPtr> finish_handlers, Vector<ActionPtr> cancel_handlers) + { + if (animations_.empty()) + SetTimer(); - if (timer_) - timer_->Cancel(); - } + auto delegate = std::make_shared<AnimationDelegateImpl>(tag); - void AnimationManager::AddAnimation(Animation* animation) - { - if (animations_.empty()) - timer_ = SetInterval(frame_step_time, timer_action_); + animations_[tag] = std::make_unique<Animation>(tag, duration, std::move(step_handlers), std::move(start_handlers), std::move(finish_handlers), std::move(cancel_handlers), delegate); - const auto find_result = animations_.find(animation->GetTag()); - if (find_result != animations_.cend()) - find_result->second->Cancel(); - animations_.insert_or_assign(animation->GetTag(), animation); - } + return delegate; + } - void AnimationManager::RemoveAnimation(Animation* animation) - { - const auto find_result = animations_.find(animation->GetTag()); - if (find_result != animations_.cend()) + void AnimationManager::RemoveAnimation(const String& tag) { - delete find_result->second; - animations_.erase(find_result); + const auto find_result = animations_.find(tag); + if (find_result != animations_.cend()) + animations_.erase(find_result); + + if (animations_.empty()) + KillTimer(); } - if (animations_.empty()) + void AnimationManager::SetTimer() { - assert(timer_); - timer_->Cancel(); - timer_ = nullptr; + if (timer_ == nullptr) + timer_ = SetInterval(std::chrono::duration_cast<std::chrono::milliseconds>(frame_step_time), timer_action_); } - } - Animation::Animation(String tag, const double duration, - const Vector<std::shared_ptr<Action<Animation*, double>>>& step_handlers, - const Vector<std::shared_ptr<Action<Animation*>>>& start_handlers, - const Vector<std::shared_ptr<Action<Animation*>>>& finish_handlers, - const Vector<std::shared_ptr<Action<Animation*>>>& cancel_handlers - ) : tag_(std::move(tag)), duration_(duration), step_handlers_(step_handlers), - start_handlers_(start_handlers), finish_handlers_(finish_handlers), cancel_handlers_(cancel_handlers) - { - AnimationManager::GetInstance()->AddAnimation(this); - } + void AnimationManager::KillTimer() + { + if (timer_ != nullptr) + { + timer_->Cancel(); + timer_ = nullptr; + } + } - bool Animation::Step(const double time) - { - current_time_ += time; - if (current_time_ > duration_) + Animation::Animation( + String tag, + AnimationTimeUnit duration, + Vector<AnimationStepHandlerPtr> step_handlers, + Vector<AnimationStartHandlerPtr> start_handlers, + Vector<ActionPtr> finish_handlers, + Vector<ActionPtr> cancel_handlers, + AnimationDelegatePtr delegate + ) : tag_(std::move(tag)), duration_(duration), + step_handlers_(std::move(step_handlers)), + start_handlers_(std::move(start_handlers)), + finish_handlers_(std::move(finish_handlers)), + cancel_handlers_(std::move(cancel_handlers)), + delegate_(std::move(delegate)) + { + + } + + Animation::~Animation() { - for (auto& handler : step_handlers_) - (*handler)(this, 1); - for (auto& handler : finish_handlers_) - (*handler)(this); - return true; + if (current_time_ < duration_) + for (auto& handler : cancel_handlers_) + (*handler)(); } - else + + bool Animation::Step(const AnimationTimeUnit time) { - for (auto& handler : step_handlers_) - (*handler)(this, current_time_ / duration_); - return false; + current_time_ += time; + if (current_time_ > duration_) + { + for (auto& handler : step_handlers_) + (*handler)(delegate_, 1); + for (auto& handler : finish_handlers_) + (*handler)(); + return true; + } + else + { + for (auto& handler : step_handlers_) + (*handler)(delegate_, current_time_ / duration_); + return false; + } } + } - void Animation::Cancel() + AnimationDelegatePtr AnimationBuilder::Start() const { - for (auto& handler : cancel_handlers_) - (*handler)(this); - InvokeLater([this] - { - AnimationManager::GetInstance()->RemoveAnimation(this); //TODO!!! - }); + return details::AnimationManager::GetInstance()->CreateAnimation(tag, duration, step_handlers_, start_handlers_, finish_handlers_, cancel_handlers_); } } |