diff --git a/libs/ui/include/psemek/ui/impl/move_base.hpp b/libs/ui/include/psemek/ui/impl/move_base.hpp index 023eafb9..f151f50c 100644 --- a/libs/ui/include/psemek/ui/impl/move_base.hpp +++ b/libs/ui/include/psemek/ui/impl/move_base.hpp @@ -18,12 +18,16 @@ namespace psemek::ui::impl void set_child(std::unique_ptr child) override; std::unique_ptr release_child() override; + void animate(float dt) override; void update(move const & value); private: - react::source>> offset_; + react::value> offset_; + react::value animation_speed_; react::source> child_size_constraints_; react::value size_constraints_; + + geom::vector current_offset_; }; } diff --git a/libs/ui/include/psemek/ui/move.hpp b/libs/ui/include/psemek/ui/move.hpp index bfc71df5..5e4d99ac 100644 --- a/libs/ui/include/psemek/ui/move.hpp +++ b/libs/ui/include/psemek/ui/move.hpp @@ -12,6 +12,7 @@ namespace psemek::ui { react::value child = {}; react::value> offset = geom::vector{0.f, 0.f}; + react::value animation_speed = 0.f; }; } diff --git a/libs/ui/source/impl/move_base.cpp b/libs/ui/source/impl/move_base.cpp index 8bbe8ab0..a2053d2c 100644 --- a/libs/ui/source/impl/move_base.cpp +++ b/libs/ui/source/impl/move_base.cpp @@ -17,8 +17,10 @@ namespace psemek::ui::impl move_base::move_base() : offset_({0.f, 0.f}) + , animation_speed_(0.f) , child_size_constraints_(size_constraints::max()) , size_constraints_(react::join(child_size_constraints_)) + , current_offset_{0.f, 0.f} {} void move_base::reshape(geom::box const & new_shape) @@ -26,7 +28,7 @@ namespace psemek::ui::impl single_container::reshape(new_shape); if (auto child = this->child()) - child->reshape(compute_child_shape(new_shape, **offset_)); + child->reshape(compute_child_shape(new_shape, current_offset_)); } react::value move_base::size_constraints() const @@ -49,9 +51,35 @@ namespace psemek::ui::impl return single_container::release_child(); } + void move_base::animate(float dt) + { + if (*animation_speed_ == 0.f) + { + if (current_offset_ != *offset_) + { + current_offset_ = *offset_; + reshape(shape()); + } + } + else + { + auto factor = - std::expm1(- dt * (*animation_speed_)); + auto new_offset = geom::lerp(current_offset_, *offset_, factor); + if (geom::length(current_offset_ - new_offset) < 1.f / 16.f) + new_offset = *offset_; + + if (current_offset_ != *offset_) + { + current_offset_ = new_offset; + reshape(shape()); + } + } + } + void move_base::update(move const & value) { - offset_.set(value.offset); + offset_ = value.offset; + animation_speed_ = value.animation_speed; } }