aboutsummaryrefslogtreecommitdiff
path: root/src/animation
diff options
context:
space:
mode:
authorIvan Molodetskikh <yalterz@gmail.com>2024-03-04 16:01:57 +0400
committerIvan Molodetskikh <yalterz@gmail.com>2024-03-04 16:01:57 +0400
commit60b02545f3c48831381d86f1798c4d1b1b502fcd (patch)
tree6f67a6eec801d6bdcedd21308ddc61358a3c6885 /src/animation
parent2750b2038bed5495bcdfeacc7be25267d15ceab1 (diff)
downloadniri-60b02545f3c48831381d86f1798c4d1b1b502fcd.tar.gz
niri-60b02545f3c48831381d86f1798c4d1b1b502fcd.tar.bz2
niri-60b02545f3c48831381d86f1798c4d1b1b502fcd.zip
Move animation to subfolder
Diffstat (limited to 'src/animation')
-rw-r--r--src/animation/mod.rs99
1 files changed, 99 insertions, 0 deletions
diff --git a/src/animation/mod.rs b/src/animation/mod.rs
new file mode 100644
index 00000000..bb22b75c
--- /dev/null
+++ b/src/animation/mod.rs
@@ -0,0 +1,99 @@
+use std::time::Duration;
+
+use keyframe::functions::EaseOutCubic;
+use keyframe::EasingFunction;
+use portable_atomic::{AtomicF64, Ordering};
+
+use crate::utils::get_monotonic_time;
+
+pub static ANIMATION_SLOWDOWN: AtomicF64 = AtomicF64::new(1.);
+
+#[derive(Debug)]
+pub struct Animation {
+ from: f64,
+ to: f64,
+ duration: Duration,
+ start_time: Duration,
+ current_time: Duration,
+ curve: Curve,
+}
+
+#[derive(Debug, Clone, Copy)]
+pub enum Curve {
+ EaseOutCubic,
+ EaseOutExpo,
+}
+
+impl Animation {
+ pub fn new(
+ from: f64,
+ to: f64,
+ config: niri_config::Animation,
+ default: niri_config::Animation,
+ ) -> Self {
+ // FIXME: ideally we shouldn't use current time here because animations started within the
+ // same frame cycle should have the same start time to be synchronized.
+ let now = get_monotonic_time();
+
+ let duration_ms = if config.off {
+ 0
+ } else {
+ config.duration_ms.unwrap_or(default.duration_ms.unwrap())
+ };
+ let duration = Duration::from_millis(u64::from(duration_ms))
+ .mul_f64(ANIMATION_SLOWDOWN.load(Ordering::Relaxed));
+
+ let curve = Curve::from(config.curve.unwrap_or(default.curve.unwrap()));
+
+ Self {
+ from,
+ to,
+ duration,
+ start_time: now,
+ current_time: now,
+ curve,
+ }
+ }
+
+ pub fn set_current_time(&mut self, time: Duration) {
+ self.current_time = time;
+ }
+
+ pub fn is_done(&self) -> bool {
+ self.current_time >= self.start_time + self.duration
+ }
+
+ pub fn value(&self) -> f64 {
+ let passed = (self.current_time - self.start_time).as_secs_f64();
+ let total = self.duration.as_secs_f64();
+ let x = (passed / total).clamp(0., 1.);
+ self.curve.y(x) * (self.to - self.from) + self.from
+ }
+
+ pub fn to(&self) -> f64 {
+ self.to
+ }
+
+ #[cfg(test)]
+ pub fn from(&self) -> f64 {
+ self.from
+ }
+}
+
+impl Curve {
+ pub fn y(self, x: f64) -> f64 {
+ match self {
+ Curve::EaseOutCubic => EaseOutCubic.y(x),
+ Curve::EaseOutExpo => 1. - 2f64.powf(-10. * x),
+ }
+ }
+}
+
+impl From<niri_config::AnimationCurve> for Curve {
+ fn from(value: niri_config::AnimationCurve) -> Self {
+ match value {
+ niri_config::AnimationCurve::EaseOutCubic => Curve::EaseOutCubic,
+ niri_config::AnimationCurve::EaseOutExpo => Curve::EaseOutExpo,
+ }
+ }
+}