animation: Tweak clamped duration logic

This commit is contained in:
Ivan Molodetskikh
2024-04-10 12:09:54 +04:00
parent 5383a0591f
commit 0cd149c939
2 changed files with 13 additions and 7 deletions
+7 -1
View File
@@ -17,6 +17,8 @@ pub struct Animation {
to: f64,
duration: Duration,
/// Time until the animation first reaches `to`.
///
/// Best effort; not always exactly precise.
clamped_duration: Duration,
start_time: Duration,
current_time: Duration,
@@ -117,12 +119,14 @@ impl Animation {
}
pub fn spring(spring: Spring) -> Self {
let _span = tracy_client::span!("Animation::spring");
// 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 = spring.duration();
let clamped_duration = spring.clamped_duration();
let clamped_duration = spring.clamped_duration().unwrap_or(duration);
let kind = Kind::Spring(spring);
Self {
@@ -266,6 +270,8 @@ impl Animation {
}
/// Returns a value that stops at the target value after first reaching it.
///
/// Best effort; not always exactly precise.
pub fn clamped_value(&self) -> f64 {
if self.is_clamped_done() {
return self.to;
+6 -6
View File
@@ -97,15 +97,15 @@ impl Spring {
}
/// Computes and returns the duration until the spring reaches its target position.
pub fn clamped_duration(&self) -> Duration {
pub fn clamped_duration(&self) -> Option<Duration> {
let beta = self.params.damping / (2. * self.params.mass);
if beta.abs() <= f64::EPSILON || beta < 0. {
return Duration::MAX;
return Some(Duration::MAX);
}
if (self.to - self.from).abs() <= f64::EPSILON {
return Duration::ZERO;
return Some(Duration::ZERO);
}
// The first frame is not that important and we avoid finding the trivial 0 for in-place
@@ -116,15 +116,15 @@ impl Spring {
while (self.to - self.from > f64::EPSILON && self.to - y > self.params.epsilon)
|| (self.from - self.to > f64::EPSILON && y - self.to > self.params.epsilon)
{
if i > 1000 {
return Duration::ZERO;
if i > 3000 {
return None;
}
i += 1;
y = self.oscillate(f64::from(i) / 1000.);
}
Duration::from_millis(u64::from(i))
Some(Duration::from_millis(u64::from(i)))
}
/// Returns the spring position at a given time in seconds.