13#if defined(__has_include)
14# if __has_include(<source_location>)
15# include <source_location>
30 return t < 0.5f ? 2.0f *
t *
t : -1.0f + (4.0f - 2.0f *
t) *
t;
35 return t < 0.5f ? 4.0f *
t *
t *
t : (
t - 1.0f) * (2.0f *
t - 2.0f) * (2.0f *
t - 2.0f) + 1.0f;
37 inline float ease_in_expo(
float t) {
return t == 0 ? 0 : std::pow(2.0f, 10.0f * (
t - 1.0f)); }
38 inline float ease_out_expo(
float t) {
return t == 1.0f ? 1.0f : 1.0f - std::pow(2.0f, -10.0f *
t); }
40 if (
t == 0 ||
t == 1)
return t;
41 return std::pow(2.0f, -10.0f *
t) * std::sin((
t - 0.075f) * (2.0f * 3.14159f) / 0.3f) + 1.0f;
44 if (
t < 1.0f / 2.75f)
return 7.5625f *
t *
t;
45 if (
t < 2.0f / 2.75f) {
t -= 1.5f / 2.75f;
return 7.5625f *
t *
t + 0.75f; }
46 if (
t < 2.5f / 2.75f) {
t -= 2.25f / 2.75f;
return 7.5625f *
t *
t + 0.9375f; }
47 t -= 2.625f / 2.75f;
return 7.5625f *
t *
t + 0.984375f;
76 : from_(from), to_(to),
77 configured_duration_(duration_seconds),
78 duration_(duration_seconds), ease_(ease) {
79 apply_motion_policy_at_start();
85 if (duration_ <= 0.0f) {
89 float t = std::clamp(elapsed_ / duration_, 0.0f, 1.0f);
90 float eased = ease_(
t);
91 current_ = from_ + (to_ - from_) * eased;
95 float current()
const {
return current_; }
96 bool finished()
const {
return elapsed_ >= duration_; }
101 duration_ = configured_duration_;
102 apply_motion_policy_at_start();
117 std::string source_id,
118 std::string source_file = {},
119 int source_line = 0) {
121 provenance_.
source_id = std::move(source_id);
129 provenance_ = std::move(
p);
142 std::string metric_name,
144 if (provenance_.
is_set() && !opts.provenance.is_set()) {
145 opts.provenance = provenance_;
148 static_cast<double>(current_), opts);
156 void apply_motion_policy_at_start() {
165 duration_ = configured_duration_ *
static_cast<float>(
scale);
169 float from_ = 0, to_ = 0;
170 float configured_duration_ = 0;
176 motion::Provenance provenance_;
190#ifdef __cpp_lib_source_location
191#define PULP_MOTION_TWEEN(source_id, ...) \
192 ([](::pulp::view::Tween&& __pulp_tween_, \
193 const ::std::source_location __pulp_loc_ = \
194 ::std::source_location::current()) \
195 -> ::pulp::view::Tween { \
196 __pulp_tween_.set_motion_provenance( \
197 ::std::string{"tween"}, \
198 ::std::string{(source_id)}, \
199 ::std::string{__pulp_loc_.file_name()}, \
200 static_cast<int>(__pulp_loc_.line())); \
201 return __pulp_tween_; \
202 }(::pulp::view::Tween(__VA_ARGS__)))
204#define PULP_MOTION_TWEEN(source_id, ...) \
205 ([](::pulp::view::Tween&& __pulp_tween_) -> ::pulp::view::Tween { \
206 __pulp_tween_.set_motion_provenance( \
207 ::std::string{"tween"}, \
208 ::std::string{(source_id)}, \
209 ::std::string{__FILE__}, \
210 static_cast<int>(__LINE__)); \
211 return __pulp_tween_; \
212 }(::pulp::view::Tween(__VA_ARGS__)))
225 std::function<
void(
float)> on_update,
226 std::function<
void()> on_complete = {}) {
228 animations_.push_back({id, {from, to, duration, ease},
229 std::move(on_update), std::move(on_complete)});
236 std::remove_if(animations_.begin(), animations_.end(),
237 [
id](
const auto&
a) { return a.id == id.value; }),
243 for (
auto it = animations_.begin(); it != animations_.end();) {
244 it->tween.advance(dt);
245 if (it->on_update) it->on_update(it->tween.current());
247 if (it->tween.finished()) {
248 if (it->on_complete) it->on_complete();
249 it = animations_.erase(it);
256 int active_count()
const {
return static_cast<int>(animations_.size()); }
263 std::function<void(
float)> on_update;
264 std::function<void()> on_complete;
267 std::vector<Animation> animations_;
296 explicit ValueAnimation(
float initial) : current_(initial), target_(initial), from_(initial) {}
307 configured_duration_ = duration;
308 duration_ = duration;
319 duration_ = duration *
static_cast<float>(
scale);
321 if (duration_ <= 0) {
340 if (!animating_)
return false;
342 float t = std::clamp(elapsed_ / duration_, 0.0f, 1.0f);
343 current_ = from_ + (target_ - from_) * ease_(
t);
351 float value()
const {
return current_; }
366 float configured_duration_ = 0;
369 bool animating_ =
false;
390 keyframes_ = std::move(kf);
391 std::sort(keyframes_.begin(), keyframes_.end(),
401 void start() { elapsed_ = 0; running_ =
true; finished_ =
false; completed_iterations_ = 0; }
402 void stop() { running_ =
false; }
410 if (!running_ || keyframes_.size() < 2 || duration_ <= 0)
return value_;
413 float iteration_progress = elapsed_ / duration_;
415 if (iterations_ > 0 && iteration_progress >= iterations_) {
418 iteration_progress = iterations_;
425 float iter_num = std::floor(iteration_progress);
426 float t = iteration_progress - iter_num;
427 if (finished_ && iterations_ > 0.0f &&
t == 0.0f && iteration_progress > 0.0f) {
431 completed_iterations_ =
static_cast<int>(iter_num);
434 bool reversed =
false;
438 if (reversed)
t = 1.0f -
t;
441 t = ease_(std::clamp(
t, 0.0f, 1.0f));
444 value_ = interpolate(
t);
449 value_ = interpolate(reversed ? 0.0f : 1.0f);
455 float value()
const {
return value_; }
458 float interpolate(
float t)
const {
459 if (keyframes_.empty())
return 0;
460 if (
t <= keyframes_.front().offset)
return keyframes_.front().value;
461 if (
t >= keyframes_.back().offset)
return keyframes_.back().value;
463 for (
size_t i = 1;
i < keyframes_.size(); ++
i) {
464 if (
t <= keyframes_[
i].offset) {
465 float local_t = (
t - keyframes_[
i-1].offset) /
466 (keyframes_[
i].offset - keyframes_[
i-1].offset);
467 return keyframes_[
i-1].value + local_t * (keyframes_[
i].value - keyframes_[
i-1].value);
470 return keyframes_.back().value;
473 std::vector<Keyframe> keyframes_;
474 float duration_ = 1.0f;
475 float iterations_ = 1.0f;
478 int completed_iterations_ = 0;
479 bool running_ =
false;
480 bool finished_ =
false;
Definition animation.hpp:218
AnimationId animate(float from, float to, float duration, EasingFunction ease, std::function< void(float)> on_update, std::function< void()> on_complete={})
Definition animation.hpp:223
void tick(float dt)
Definition animation.hpp:242
int active_count() const
Definition animation.hpp:256
bool has_active() const
Definition animation.hpp:257
void cancel(AnimationId id)
Definition animation.hpp:234
Definition frame_clock.hpp:14
void set_iterations(float count)
Definition animation.hpp:396
void pause()
Definition animation.hpp:403
bool is_finished() const
Definition animation.hpp:406
void start()
Definition animation.hpp:401
float advance(float dt)
Advance by dt seconds, return current interpolated value.
Definition animation.hpp:409
Direction
Definition animation.hpp:384
@ reverse
Definition animation.hpp:384
@ alternate
Definition animation.hpp:384
@ normal
Definition animation.hpp:384
void stop()
Definition animation.hpp:402
void set_duration(float seconds)
Definition animation.hpp:395
float value() const
Definition animation.hpp:455
void resume()
Definition animation.hpp:404
void set_fill_mode(FillMode f)
Definition animation.hpp:398
void set_keyframes(std::vector< Keyframe > kf)
Definition animation.hpp:389
void set_easing(EasingFunction e)
Definition animation.hpp:399
void set_direction(Direction d)
Definition animation.hpp:397
bool is_running() const
Definition animation.hpp:405
FillMode
Definition animation.hpp:385
@ none
Definition animation.hpp:385
@ backwards
Definition animation.hpp:385
@ forwards
Definition animation.hpp:385
@ both
Definition animation.hpp:385
KeyframeAnimation()=default
static MotionPolicy current()
Convenience: the effective policy right now.
Definition motion_preferences.hpp:45
static double current_duration_scale()
Convenience: the effective duration scale right now.
Definition motion_preferences.hpp:48
Definition animation.hpp:72
const motion::Provenance & motion_provenance() const noexcept
Definition animation.hpp:132
bool finished() const
Definition animation.hpp:96
float advance(float dt)
Definition animation.hpp:83
void publish(std::string view_name, std::string metric_name, motion::PublishOptions opts={}) const
Publish the tween's current value through the motion publish channel under the given (view,...
Definition animation.hpp:141
float current() const
Definition animation.hpp:95
Tween(float from, float to, float duration_seconds, EasingFunction ease=easing::linear)
Definition animation.hpp:75
void set_motion_provenance(std::string source_kind, std::string source_id, std::string source_file={}, int source_line=0)
Definition animation.hpp:116
void reset()
Definition animation.hpp:98
void set_motion_provenance(motion::Provenance p)
Set the full envelope.
Definition animation.hpp:128
float value() const
Definition animation.hpp:351
bool animating() const
Definition animation.hpp:353
ValueAnimation(float initial)
Definition animation.hpp:296
void cancel()
Cancel in-flight animation, keep current value.
Definition animation.hpp:356
float target() const
Definition animation.hpp:352
bool advance(float dt)
Advance by dt. Returns true if still animating.
Definition animation.hpp:339
void set(float value)
Snap to value immediately (no animation).
Definition animation.hpp:330
void animate_to(float target, float duration, EasingFunction ease=easing::ease_out_quad)
Set a new target.
Definition animation.hpp:304
Agent-first motion observability: sample view geometry, scroll state, and arbitrary scalar values at ...
System-level reduced-motion preferences.
Definition animation.hpp:25
float ease_out_expo(float t)
Definition animation.hpp:38
float ease_in_out_cubic(float t)
Definition animation.hpp:34
float ease_in_expo(float t)
Definition animation.hpp:37
float ease_in_quad(float t)
Definition animation.hpp:27
float ease_out_quad(float t)
Definition animation.hpp:28
float ease_out_elastic(float t)
Definition animation.hpp:39
float ease_out_bounce(float t)
Definition animation.hpp:43
float linear(float t)
Definition animation.hpp:26
float ease_in_out_quad(float t)
Definition animation.hpp:29
float ease_in_cubic(float t)
Definition animation.hpp:32
float ease_out_cubic(float t)
Definition animation.hpp:33
void publish_value(std::string view_name, std::string metric_name, double value, PublishOptions opts={})
Single-component publish.
Hover-cursor tracking for platform window hosts.
Definition fwd.hpp:27
bool motion_policy_is_off()
Returns true when the current policy says "do not animate" — i.e.
Definition motion_preferences.hpp:133
@ a
Definition input_events.hpp:39
@ u
Definition input_events.hpp:41
@ d
Definition input_events.hpp:39
@ p
Definition input_events.hpp:40
@ i
Definition input_events.hpp:40
@ f
Definition input_events.hpp:39
@ b
Definition input_events.hpp:39
@ e
Definition input_events.hpp:39
@ t
Definition input_events.hpp:41
@ scale
Definition css_animation.hpp:126
EasingFunction easing_by_name(const std::string &name)
Resolve an easing function by name string. Returns linear for unknown names.
Definition animation.hpp:274
float(*)(float) EasingFunction
Definition animation.hpp:51
@ Reduced
Animate, but scale duration by duration_scale.
Definition motion_preferences.hpp:30
Definition animation.hpp:220
int value
Definition animation.hpp:220
A single keyframe: offset (0-1) and value.
Definition animation.hpp:376
float value
Definition animation.hpp:378
float offset
0.0 = start, 1.0 = end
Definition animation.hpp:377
Compile-time animation limits for optimization.
Definition animation.hpp:55
bool clamp_value
Definition animation.hpp:60
float min_value
Definition animation.hpp:56
float max_duration
Definition animation.hpp:59
float max_value
Definition animation.hpp:57
float min_duration
Definition animation.hpp:58
std::string source_file
Optional, e.g. FILE at attach site.
Definition motion.hpp:82
std::string source_kind
"tween" | "css-transition" | "animator-set" | "rAF" | "design-import" | "user" | "publish"
Definition motion.hpp:78
int source_line
Optional, e.g. LINE at attach site.
Definition motion.hpp:83
bool is_set() const noexcept
Definition motion.hpp:85
std::string source_id
Free-form id, e.g.
Definition motion.hpp:80
Definition motion.hpp:181