From 0be4450e3da62918339a4cb3113da4a31d033b52 Mon Sep 17 00:00:00 2001 From: Emil Ernerfeldt Date: Fri, 5 Jul 2024 11:36:19 +0200 Subject: [PATCH] Smoother animations (#4787) This makes animations slightly smoother, especially in reactive mode --- crates/egui/src/animation_manager.rs | 4 ++-- crates/egui/src/containers/area.rs | 5 +++-- crates/egui/src/context.rs | 7 ++++++- 3 files changed, 11 insertions(+), 5 deletions(-) diff --git a/crates/egui/src/animation_manager.rs b/crates/egui/src/animation_manager.rs index fee5ad5ea8c..15002141f0b 100644 --- a/crates/egui/src/animation_manager.rs +++ b/crates/egui/src/animation_manager.rs @@ -87,8 +87,8 @@ impl AnimationManager { Some(anim) => { let time_since_toggle = (input.time - anim.toggle_time) as f32; // On the frame we toggle we don't want to return the old value, - // so we extrapolate forwards: - let time_since_toggle = time_since_toggle + input.predicted_dt; + // so we extrapolate forwards by half a frame: + let time_since_toggle = time_since_toggle + input.predicted_dt / 2.0; let current_value = remap_clamp( time_since_toggle, 0.0..=animation_time, diff --git a/crates/egui/src/containers/area.rs b/crates/egui/src/containers/area.rs index 30d1539f3d6..062261af31b 100644 --- a/crates/egui/src/containers/area.rs +++ b/crates/egui/src/containers/area.rs @@ -545,9 +545,10 @@ impl Prepared { if self.fade_in { if let Some(last_became_visible_at) = self.state.last_became_visible_at { - let age = ctx.input(|i| (i.time - last_became_visible_at) as f32 + i.predicted_dt); + let age = + ctx.input(|i| (i.time - last_became_visible_at) as f32 + i.predicted_dt / 2.0); let opacity = crate::remap_clamp(age, 0.0..=ctx.style().animation_time, 0.0..=1.0); - let opacity = emath::easing::cubic_out(opacity); // slow fade-out = quick fade-in + let opacity = emath::easing::quadratic_out(opacity); // slow fade-out = quick fade-in ui.multiply_opacity(opacity); if opacity < 1.0 { ctx.request_repaint(); diff --git a/crates/egui/src/context.rs b/crates/egui/src/context.rs index 7e1813b9ea9..f1722418adc 100644 --- a/crates/egui/src/context.rs +++ b/crates/egui/src/context.rs @@ -146,7 +146,7 @@ impl ContextImpl { fn request_repaint_after( &mut self, - delay: Duration, + mut delay: Duration, viewport_id: ViewportId, cause: RepaintCause, ) { @@ -163,6 +163,11 @@ impl ContextImpl { // Hovering a tooltip is a good example of a case where we want to repaint after a delay. } + if let Ok(predicted_frame_time) = Duration::try_from_secs_f32(viewport.input.predicted_dt) { + // Make it less likely we over-shoot the target: + delay = delay.saturating_sub(predicted_frame_time); + } + viewport.repaint.causes.push(cause); // We save some CPU time by only calling the callback if we need to.