feat: added more interpolation options
added the following interpolation options: - cubic ease-in-out - cosine - exponential
This commit is contained in:
parent
1d75337471
commit
cdb14a76d6
1 changed files with 79 additions and 6 deletions
85
src/lib.rs
85
src/lib.rs
|
@ -34,6 +34,17 @@ pub struct Config {
|
||||||
pub disable_timeout: u32,
|
pub disable_timeout: u32,
|
||||||
pub gamma_backend: GammaBackend,
|
pub gamma_backend: GammaBackend,
|
||||||
pub temp_backend: TempBackend,
|
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)]
|
#[derive(Debug, PartialEq, Copy, Clone)]
|
||||||
|
@ -70,6 +81,8 @@ impl Default for Config {
|
||||||
notification_timeout: 5000,
|
notification_timeout: 5000,
|
||||||
gamma_backend: GammaBackend::Hyprctl,
|
gamma_backend: GammaBackend::Hyprctl,
|
||||||
temp_backend: TempBackend::Hyprctl,
|
temp_backend: TempBackend::Hyprctl,
|
||||||
|
interpolation_temp: Interpolation::Linear,
|
||||||
|
interpolation_gamma: Interpolation::Linear,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -83,6 +96,7 @@ pub enum ConfigError {
|
||||||
InvalidGamma(String),
|
InvalidGamma(String),
|
||||||
InvalidGammaBackend(String),
|
InvalidGammaBackend(String),
|
||||||
InvalidTempBackend(String),
|
InvalidTempBackend(String),
|
||||||
|
InvalidInterpolation(String),
|
||||||
DuplicateKey(String),
|
DuplicateKey(String),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -230,6 +244,20 @@ impl Config {
|
||||||
return Err(ConfigError::InvalidTime(value.to_string()));
|
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]
|
/// Linearly interpolate between start and end by factor [0.0, 1.0]
|
||||||
pub fn interpolate(start: u16, end: u16, factor: f64) -> u16 {
|
pub fn interpolate_linear(start: u16, end: u16, factor: f64) -> u16 {
|
||||||
trace!("interpolate({start}, {end}, {factor})");
|
trace!("interpolate_linear({start}, {end}, {factor})");
|
||||||
if end < start {
|
if end < start {
|
||||||
(end as f64 + (start - end) as f64 * (1.0 - factor)).round() as u16
|
(end as f64 + (start - end) as f64 * (1.0 - factor)).round() as u16
|
||||||
} else {
|
} 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
|
/// Compute current temperature and gamma based on provided time
|
||||||
pub fn compute_settings(now: Time, config: &Config) -> (u16, u16) {
|
pub fn compute_settings(now: Time, config: &Config) -> (u16, u16) {
|
||||||
trace!("compute_settings({now:?})");
|
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)
|
/ (config.sunset_end - config.sunset_start) as f64)
|
||||||
.clamp(0.0, 1.0);
|
.clamp(0.0, 1.0);
|
||||||
(
|
(
|
||||||
interpolate(config.temp_day, config.temp_night, factor),
|
interpolate_value(config.temp_day, config.temp_night, factor, &config.interpolation_temp),
|
||||||
interpolate(config.gamma_day, config.gamma_night, factor),
|
interpolate_value(config.gamma_day, config.gamma_night, factor, &config.interpolation_gamma),
|
||||||
)
|
)
|
||||||
} else if (time_in_hours >= config.sunrise_start as f64)
|
} else if (time_in_hours >= config.sunrise_start as f64)
|
||||||
&& (time_in_hours <= config.sunrise_end 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)
|
/ (config.sunrise_end - config.sunrise_start) as f64)
|
||||||
.clamp(0.0, 1.0);
|
.clamp(0.0, 1.0);
|
||||||
(
|
(
|
||||||
interpolate(config.temp_day, config.temp_night, factor),
|
interpolate_value(config.temp_day, config.temp_night, factor, &config.interpolation_temp),
|
||||||
interpolate(config.gamma_day, config.gamma_night, factor),
|
interpolate_value(config.gamma_day, config.gamma_night, factor, &config.interpolation_gamma),
|
||||||
)
|
)
|
||||||
} else if time_in_hours > config.sunset_end as f64
|
} else if time_in_hours > config.sunset_end as f64
|
||||||
|| time_in_hours < config.sunrise_start as f64
|
|| time_in_hours < config.sunrise_start as f64
|
||||||
|
|
Loading…
Reference in a new issue