mirror of
https://github.com/niri-wm/niri.git
synced 2026-06-23 02:05:33 +07:00
feat: cubic-bezier curve for animation (#2059)
* feat: bezier curve for animation * fixes --------- Co-authored-by: Ivan Molodetskikh <yalterz@gmail.com>
This commit is contained in:
@@ -0,0 +1,60 @@
|
||||
use keyframe::EasingFunction;
|
||||
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
pub struct CubicBezier {
|
||||
x1: f64,
|
||||
y1: f64,
|
||||
x2: f64,
|
||||
y2: f64,
|
||||
}
|
||||
|
||||
impl CubicBezier {
|
||||
pub fn new(x1: f64, y1: f64, x2: f64, y2: f64) -> Self {
|
||||
Self { x1, y1, x2, y2 }
|
||||
}
|
||||
|
||||
// Based on libadwaita (LGPL-2.1-or-later):
|
||||
// https://gitlab.gnome.org/GNOME/libadwaita/-/blob/1.7.6/src/adw-easing.c?ref_type=tags#L469-531
|
||||
|
||||
fn x_for_t(&self, t: f64) -> f64 {
|
||||
let omt = 1. - t;
|
||||
3. * omt * omt * t * self.x1 + 3. * omt * t * t * self.x2 + t * t * t
|
||||
}
|
||||
|
||||
fn y_for_t(&self, t: f64) -> f64 {
|
||||
let omt = 1. - t;
|
||||
3. * omt * omt * t * self.y1 + 3. * omt * t * t * self.y2 + t * t * t
|
||||
}
|
||||
|
||||
fn t_for_x(&self, x: f64) -> f64 {
|
||||
let mut min_t = 0.;
|
||||
let mut max_t = 1.;
|
||||
|
||||
for _ in 0..=30 {
|
||||
let guess_t = (min_t + max_t) / 2.;
|
||||
let guess_x = self.x_for_t(guess_t);
|
||||
|
||||
if x < guess_x {
|
||||
max_t = guess_t;
|
||||
} else {
|
||||
min_t = guess_t;
|
||||
}
|
||||
}
|
||||
|
||||
(min_t + max_t) / 2.
|
||||
}
|
||||
}
|
||||
|
||||
impl EasingFunction for CubicBezier {
|
||||
fn y(&self, x: f64) -> f64 {
|
||||
if x <= f64::EPSILON {
|
||||
return 0.;
|
||||
}
|
||||
|
||||
if 1. - f64::EPSILON <= x {
|
||||
return 1.;
|
||||
}
|
||||
|
||||
self.y_for_t(self.t_for_x(x))
|
||||
}
|
||||
}
|
||||
@@ -3,6 +3,9 @@ use std::time::Duration;
|
||||
use keyframe::functions::{EaseOutCubic, EaseOutQuad};
|
||||
use keyframe::EasingFunction;
|
||||
|
||||
mod bezier;
|
||||
use bezier::CubicBezier;
|
||||
|
||||
mod spring;
|
||||
pub use spring::{Spring, SpringParams};
|
||||
|
||||
@@ -43,6 +46,7 @@ pub enum Curve {
|
||||
EaseOutQuad,
|
||||
EaseOutCubic,
|
||||
EaseOutExpo,
|
||||
CubicBezier(CubicBezier),
|
||||
}
|
||||
|
||||
impl Animation {
|
||||
@@ -342,6 +346,7 @@ impl Curve {
|
||||
Curve::EaseOutQuad => EaseOutQuad.y(x),
|
||||
Curve::EaseOutCubic => EaseOutCubic.y(x),
|
||||
Curve::EaseOutExpo => 1. - 2f64.powf(-10. * x),
|
||||
Curve::CubicBezier(b) => b.y(x),
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -353,6 +358,9 @@ impl From<niri_config::animations::Curve> for Curve {
|
||||
niri_config::animations::Curve::EaseOutQuad => Curve::EaseOutQuad,
|
||||
niri_config::animations::Curve::EaseOutCubic => Curve::EaseOutCubic,
|
||||
niri_config::animations::Curve::EaseOutExpo => Curve::EaseOutExpo,
|
||||
niri_config::animations::Curve::CubicBezier(x1, y1, x2, y2) => {
|
||||
Curve::CubicBezier(CubicBezier::new(x1, y1, x2, y2))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user