diff options
Diffstat (limited to 'CruUI/ui/animations')
-rw-r--r-- | CruUI/ui/animations/animation.cpp | 103 | ||||
-rw-r--r-- | CruUI/ui/animations/animation.h | 131 |
2 files changed, 234 insertions, 0 deletions
diff --git a/CruUI/ui/animations/animation.cpp b/CruUI/ui/animations/animation.cpp new file mode 100644 index 00000000..26b7d5fc --- /dev/null +++ b/CruUI/ui/animations/animation.cpp @@ -0,0 +1,103 @@ +#include "animation.h" + +#include <cassert> +#include <utility> + +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]() + { + for (auto& animation : animations_) + { + if (animation.second->Step(frame_step_time)) + InvokeLater([=] + { + RemoveAnimation(animation.second); //TODO!!! + }); + } + })) + { + + } + + AnimationManager::~AnimationManager() + { + for (auto& animation : animations_) + delete animation.second; + + if (timer_) + timer_->Cancel(); + } + + void AnimationManager::AddAnimation(Animation* animation) + { + if (animations_.empty()) + timer_ = SetInterval(frame_step_time, timer_action_); + + const auto find_result = animations_.find(animation->GetTag()); + if (find_result != animations_.cend()) + find_result->second->Cancel(); + animations_.insert_or_assign(animation->GetTag(), animation); + } + + void AnimationManager::RemoveAnimation(Animation* animation) + { + const auto find_result = animations_.find(animation->GetTag()); + if (find_result != animations_.cend()) + { + delete find_result->second; + animations_.erase(find_result); + } + + if (animations_.empty()) + { + assert(timer_); + timer_->Cancel(); + timer_ = nullptr; + } + } + + 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); + } + + bool Animation::Step(const double time) + { + current_time_ += time; + if (current_time_ > duration_) + { + for (auto& handler : step_handlers_) + (*handler)(this, 1); + for (auto& handler : finish_handlers_) + (*handler)(this); + return true; + } + else + { + for (auto& handler : step_handlers_) + (*handler)(this, current_time_ / duration_); + return false; + } + } + + void Animation::Cancel() + { + for (auto& handler : cancel_handlers_) + (*handler)(this); + InvokeLater([this] + { + AnimationManager::GetInstance()->RemoveAnimation(this); //TODO!!! + }); + } +} diff --git a/CruUI/ui/animations/animation.h b/CruUI/ui/animations/animation.h new file mode 100644 index 00000000..fb6ba93e --- /dev/null +++ b/CruUI/ui/animations/animation.h @@ -0,0 +1,131 @@ +#pragma once + +#include <map> + +#include "base.h" +#include "application.h" +#include "timer.h" +#include "builder.h" + +namespace cru::ui::animations +{ + class Animation; + + + class AnimationManager : public Object + { + public: + static AnimationManager* GetInstance() + { + return Application::GetInstance()->GetAnimationManager(); + } + + public: + AnimationManager(); + AnimationManager(const AnimationManager& other) = delete; + AnimationManager(AnimationManager&& other) = delete; + AnimationManager& operator=(const AnimationManager& other) = delete; + AnimationManager& operator=(AnimationManager&& other) = delete; + ~AnimationManager() override; + + void AddAnimation(Animation* animation); + void RemoveAnimation(Animation* animation); + + private: + std::map<String, Animation*> animations_; + std::shared_ptr<ITimerTask> timer_; + std::shared_ptr<Action<>> timer_action_; + }; + + class Animation : public Object + { + friend class AnimationManager; + protected: + Animation( + String tag, + 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 + ); + + public: + Animation(const Animation& other) = delete; + Animation(Animation&& other) = delete; + Animation& operator=(const Animation& other) = delete; + Animation& operator=(Animation&& other) = delete; + ~Animation() override = default; // The animation will never destroy by users. + + bool Step(double time); + void Cancel(); + String GetTag() const + { + return tag_; + } + + private: + const String tag_; + const double duration_; + Vector<std::shared_ptr<Action<Animation*, double>>> step_handlers_; + Vector<std::shared_ptr<Action<Animation*>>> start_handlers_; + Vector<std::shared_ptr<Action<Animation*>>> finish_handlers_; + Vector<std::shared_ptr<Action<Animation*>>> cancel_handlers_; + + double current_time_ = 0; + + public: + class Builder : public OneTimeBuilder<Animation> + { + public: + Builder(String tag, const double duration) + : tag(std::move(tag)), duration(duration) + { + + } + + String tag; + double duration; + + Builder& AddStepHandler(Action<Animation*, double>&& handler) + { + if (IsValid()) + step_handlers_.push_back(std::make_shared<Action<Animation*, double>>(std::move(handler))); + return *this; + } + + Builder& AddStartHandler(Action<Animation*>&& handler) + { + if (IsValid()) + start_handlers_.push_back(std::make_shared<Action<Animation*>>(std::move(handler))); + return *this; + } + + Builder& AddFinishHandler(Action<Animation*>&& handler) + { + if (IsValid()) + finish_handlers_.push_back(std::make_shared<Action<Animation*>>(std::move(handler))); + return *this; + } + + Builder& AddCancelHandler(Action<Animation*>&& handler) + { + if (IsValid()) + cancel_handlers_.push_back(std::make_shared<Action<Animation*>>(std::move(handler))); + return *this; + } + + protected: + Animation* OnCreate() override + { + return new Animation(std::move(tag), duration, step_handlers_, start_handlers_, finish_handlers_, cancel_handlers_); + } + + private: + Vector<std::shared_ptr<Action<Animation*, double>>> step_handlers_; + Vector<std::shared_ptr<Action<Animation*>>> start_handlers_; + Vector<std::shared_ptr<Action<Animation*>>> finish_handlers_; + Vector<std::shared_ptr<Action<Animation*>>> cancel_handlers_; + }; + }; +} |