#include #include #include namespace psemek::ui::impl { namespace { geom::box compute_child_shape(geom::box const & shape, geom::vector const & offset) { return shape + offset; } } 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) { single_container::reshape(new_shape); if (auto child = this->child()) child->reshape(compute_child_shape(new_shape, current_offset_)); } react::value move_base::size_constraints() const { return size_constraints_; } void move_base::set_child(std::unique_ptr child) { if (child) child_size_constraints_.set(child->size_constraints()); else child_size_constraints_.set(size_constraints::max()); single_container::set_child(std::move(child)); } std::unique_ptr move_base::release_child() { child_size_constraints_.set(size_constraints::max()); 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_ = value.offset; animation_speed_ = value.animation_speed; } }