2024-03-19 14:27:50 +00:00
|
|
|
// SPDX-License-Identifier: MPL-2.0
|
|
|
|
// Copyright (c) Yuxuan Shui <yshuiv7@gmail.com>
|
|
|
|
|
|
|
|
#pragma once
|
|
|
|
#include <stdbool.h>
|
|
|
|
|
|
|
|
struct animatable;
|
2024-03-21 18:00:16 +00:00
|
|
|
enum transition_event;
|
2024-03-19 14:27:50 +00:00
|
|
|
/// The interpolator function for an animatable. This function should calculate the
|
|
|
|
/// current value of the `animatable` based on its `start`, `target`, `duration` and
|
|
|
|
/// `progress`.
|
|
|
|
typedef double (*interpolator_fn)(const struct animatable *);
|
|
|
|
/// The step function for an animatable. This function should advance the animation state
|
|
|
|
/// by one step. This function is called _after_ `progress` is incremented. If `progress`
|
|
|
|
/// is 0 when the function is called, it means an animation has just started, and this
|
|
|
|
/// function should initialize the state. If `step_state` is NULL when this function is
|
|
|
|
/// called, this function should allocate and initialize `step_state`.
|
|
|
|
/// `steps` is the number of steps to advance. This is always 1 or more, unless `progress`
|
|
|
|
/// is 0 or `step_state` is NULL, in which case `steps` is 0.
|
|
|
|
typedef void (*step_fn)(struct animatable *, unsigned int steps);
|
|
|
|
|
2024-03-21 18:00:16 +00:00
|
|
|
/// Callback when the transition state changes. Callback might be called by:
|
|
|
|
/// - `animatable_set_target` generates TRANSITION_COMPLETED when the specified duration
|
|
|
|
/// is 0. also generates TRANSITION_CANCELLED if the animatable was already animating.
|
|
|
|
/// - `animatable_cancel` generates TRANSITION_CANCELED
|
|
|
|
/// - `animatable_early_stop` generates TRANSITION_STOPPED_EARLY
|
|
|
|
/// - `animatable_step` generates TRANSITION_COMPLETED when the animation is completed.
|
|
|
|
/// Callback is guaranteed to be called exactly once for each `animatable_set_target`
|
|
|
|
/// call, unless an animatable is freed before the transition is completed.
|
|
|
|
typedef void (*transition_callback_fn)(enum transition_event event, void *data);
|
|
|
|
|
|
|
|
enum transition_event {
|
|
|
|
TRANSITION_COMPLETED,
|
|
|
|
TRANSITION_CANCELED,
|
|
|
|
TRANSITION_STOPPED_EARLY,
|
|
|
|
};
|
|
|
|
|
2024-03-19 14:27:50 +00:00
|
|
|
/// The base type for step_state.
|
|
|
|
struct step_state_base {
|
|
|
|
/// The current value of the `animatable`.
|
|
|
|
/// If the `animatable` is not animated, this equals to `animatable->target`.
|
|
|
|
double current;
|
|
|
|
};
|
|
|
|
|
|
|
|
/// An animatable value
|
|
|
|
struct animatable {
|
|
|
|
/// The starting value.
|
|
|
|
/// When this `animatable` is not animated, this is the current value.
|
|
|
|
double start;
|
|
|
|
/// The target value.
|
|
|
|
/// If the `animatable` is not animated, this equals to `start`.
|
|
|
|
double target;
|
|
|
|
/// The animation duration in number of steps.
|
|
|
|
/// If the `animatable` is not animated, this is 0.
|
|
|
|
unsigned int duration;
|
|
|
|
/// The current progress of the animation. From 0 to `duration - 1`.
|
|
|
|
/// If the `animatable` is not animated, this is 0.
|
|
|
|
unsigned int progress;
|
|
|
|
|
2024-03-21 18:00:16 +00:00
|
|
|
transition_callback_fn callback;
|
|
|
|
void *callback_data;
|
|
|
|
|
2024-03-19 14:27:50 +00:00
|
|
|
/// Step function state.
|
|
|
|
struct step_state_base *step_state;
|
|
|
|
/// The function for calculating the current value. If
|
|
|
|
/// `step_state` is not NULL, the `step` function is used;
|
|
|
|
/// otherwise, the `interpolator` function is used.
|
|
|
|
union {
|
|
|
|
/// The interpolator function.
|
|
|
|
interpolator_fn interpolator;
|
|
|
|
/// The step function.
|
|
|
|
step_fn step;
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
|
|
|
// =============================== API ===============================
|
|
|
|
|
|
|
|
/// Get the current value of an `animatable`.
|
|
|
|
double animatable_get(const struct animatable *a);
|
|
|
|
/// Get the animation progress as a percentage of the total duration.
|
|
|
|
double animatable_get_progress(const struct animatable *a);
|
|
|
|
/// Advance the animation by a given number of steps.
|
|
|
|
void animatable_step(struct animatable *a, unsigned int steps);
|
|
|
|
/// Returns whether an `animatable` is currently animating.
|
|
|
|
bool animatable_is_animating(const struct animatable *a);
|
|
|
|
/// Cancel the current animation of an `animatable`. This stops the animation and
|
|
|
|
/// the `animatable` will retain its current value.
|
|
|
|
///
|
|
|
|
/// Returns true if the `animatable` was animated before this function is called.
|
|
|
|
bool animatable_cancel(struct animatable *a);
|
|
|
|
/// Cancel the current animation of an `animatable` and set its value to its target.
|
|
|
|
///
|
|
|
|
/// Returns true if the `animatable` was animated before this function is called.
|
|
|
|
bool animatable_early_stop(struct animatable *a);
|
|
|
|
/// Change the target value of an `animatable`.
|
|
|
|
/// If the `animatable` is already animating, the animation will be canceled first.
|
2024-03-21 18:00:16 +00:00
|
|
|
void animatable_set_target(struct animatable *a, double target, unsigned int duration,
|
|
|
|
transition_callback_fn cb, void *data);
|
2024-03-19 14:27:50 +00:00
|
|
|
/// Create a new animatable.
|
|
|
|
struct animatable animatable_new(double value, interpolator_fn interpolator, step_fn step);
|
|
|
|
|
|
|
|
// ========================== Interpolators ==========================
|
|
|
|
|
|
|
|
double linear_interpolator(const struct animatable *a);
|