feat: added more interpolation options

added the following interpolation options:

- cubic ease-in-out
- cosine
- exponential
This commit is contained in:
Vladimir Rubin 2025-06-09 20:24:26 +03:00
parent 1d75337471
commit cdb14a76d6
Signed by: vavakado
GPG key ID: CAB744727F36B524

View file

@ -34,6 +34,17 @@ pub struct Config {
pub disable_timeout: u32,
pub gamma_backend: GammaBackend,
pub temp_backend: TempBackend,
pub interpolation_temp: Interpolation,
pub interpolation_gamma: Interpolation,
}
#[derive(Debug, PartialEq, Copy, Clone)]
pub enum Interpolation {
Linear,
CubicEaseInOut,
Cosine,
Exponential,
}
#[derive(Debug, PartialEq, Copy, Clone)]
@ -70,6 +81,8 @@ impl Default for Config {
notification_timeout: 5000,
gamma_backend: GammaBackend::Hyprctl,
temp_backend: TempBackend::Hyprctl,
interpolation_temp: Interpolation::Linear,
interpolation_gamma: Interpolation::Linear,
}
}
}
@ -83,6 +96,7 @@ pub enum ConfigError {
InvalidGamma(String),
InvalidGammaBackend(String),
InvalidTempBackend(String),
InvalidInterpolation(String),
DuplicateKey(String),
}
@ -230,6 +244,20 @@ impl Config {
return Err(ConfigError::InvalidTime(value.to_string()));
}
}
"interpolation_temp" => match value.to_lowercase().as_str() {
"linear" => config.interpolation_temp = Interpolation::Linear,
"cubic" | "cubiceaseinout" => config.interpolation_temp = Interpolation::CubicEaseInOut,
"cosine" => config.interpolation_temp = Interpolation::Cosine,
"exponential" => config.interpolation_temp = Interpolation::Exponential,
_ => return Err(ConfigError::InvalidInterpolation(value.to_string())),
},
"interpolation_gamma" => match value.to_lowercase().as_str() {
"linear" => config.interpolation_gamma = Interpolation::Linear,
"cubic" | "cubiceaseinout" => config.interpolation_gamma = Interpolation::CubicEaseInOut,
"cosine" => config.interpolation_gamma = Interpolation::Cosine,
"exponential" => config.interpolation_gamma = Interpolation::Exponential,
_ => return Err(ConfigError::InvalidInterpolation(value.to_string())),
},
_ => {}
},
_ => {}
@ -256,8 +284,8 @@ impl Config {
}
/// Linearly interpolate between start and end by factor [0.0, 1.0]
pub fn interpolate(start: u16, end: u16, factor: f64) -> u16 {
trace!("interpolate({start}, {end}, {factor})");
pub fn interpolate_linear(start: u16, end: u16, factor: f64) -> u16 {
trace!("interpolate_linear({start}, {end}, {factor})");
if end < start {
(end as f64 + (start - end) as f64 * (1.0 - factor)).round() as u16
} else {
@ -265,6 +293,51 @@ pub fn interpolate(start: u16, end: u16, factor: f64) -> u16 {
}
}
/// Cubic interpolation
fn interpolate_cubic(start: u16, end: u16, factor: f64) -> u16 {
trace!("interpolate_cubic({start}, {end}, {factor})");
let factor = factor.clamp(0.0, 1.0);
// Convert to f64 for arithmetic
let start_f = start as f64;
let end_f = end as f64;
// Cubic ease-in-out: 3t^2 - 2t^3
let t = factor;
let smooth_t = (3.0 * t * t) - (2.0 * t * t * t);
// Interpolate
let result = start_f + smooth_t * (end_f - start_f);
// Round and clamp to u16 bounds
result.round().max(0.0).min(u16::MAX as f64) as u16
}
/// Cosine interpolation
fn interpolate_cosine(start: u16, end: u16, factor: f64) -> u16 {
trace!("interpolate_cosine({start}, {end}, {factor})");
let t = (1.0 - (factor.clamp(0.0, 1.0) * std::f64::consts::PI).cos()) / 2.0;
interpolate_linear(start, end, t)
}
fn interpolate_exponential(start: u16, end: u16, factor: f64) -> u16 {
trace!("interpolate_exponential({start}, {end}, {factor})");
let t = factor.clamp(0.0, 1.0);
let t = if t < 0.5 {
0.5 * (2.0 * t).powf(3.0)
} else {
0.5 * (1.0 - (2.0 * (1.0 - t)).powf(3.0)) + 0.5
};
interpolate_linear(start, end, t)
}
/// Interpolation meta-function
fn interpolate_value(start: u16, end: u16, factor: f64, interpolation: &Interpolation) -> u16 {
trace!("interpolate_value({start}, {end}, {factor}, {interpolation:?})");
match interpolation {
Interpolation::Linear => interpolate_linear(start, end, factor),
Interpolation::CubicEaseInOut => interpolate_cubic(start, end, factor),
Interpolation::Cosine => interpolate_cosine(start, end, factor),
Interpolation::Exponential => interpolate_exponential(start, end, factor),
}
}
/// Compute current temperature and gamma based on provided time
pub fn compute_settings(now: Time, config: &Config) -> (u16, u16) {
trace!("compute_settings({now:?})");
@ -278,8 +351,8 @@ pub fn compute_settings(now: Time, config: &Config) -> (u16, u16) {
/ (config.sunset_end - config.sunset_start) as f64)
.clamp(0.0, 1.0);
(
interpolate(config.temp_day, config.temp_night, factor),
interpolate(config.gamma_day, config.gamma_night, factor),
interpolate_value(config.temp_day, config.temp_night, factor, &config.interpolation_temp),
interpolate_value(config.gamma_day, config.gamma_night, factor, &config.interpolation_gamma),
)
} else if (time_in_hours >= config.sunrise_start as f64)
&& (time_in_hours <= config.sunrise_end as f64)
@ -290,8 +363,8 @@ pub fn compute_settings(now: Time, config: &Config) -> (u16, u16) {
/ (config.sunrise_end - config.sunrise_start) as f64)
.clamp(0.0, 1.0);
(
interpolate(config.temp_day, config.temp_night, factor),
interpolate(config.gamma_day, config.gamma_night, factor),
interpolate_value(config.temp_day, config.temp_night, factor, &config.interpolation_temp),
interpolate_value(config.gamma_day, config.gamma_night, factor, &config.interpolation_gamma),
)
} else if time_in_hours > config.sunset_end as f64
|| time_in_hours < config.sunrise_start as f64