Skip to content

Commit

Permalink
Properly reverse bool animation if value changes before it's finished (
Browse files Browse the repository at this point in the history
…#3577)

<!--
Please read the "Making a PR" section of
[`CONTRIBUTING.md`](https://github.com/emilk/egui/blob/master/CONTRIBUTING.md)
before opening a Pull Request!

* Keep your PR:s small and focused.
* If applicable, add a screenshot or gif.
* If it is a non-trivial addition, consider adding a demo for it to
`egui_demo_lib`, or a new example.
* Do NOT open PR:s from your `master` branch, as that makes it hard for
maintainers to add commits to your PR.
* Remember to run `cargo fmt` and `cargo cranky`.
* Open the PR as a draft until you have self-reviewed it and run
`./scripts/check.sh`.
* When you have addressed a PR comment, mark it as resolved.

Please be patient! I will review your PR, but my time is limited!
-->

Closes <#3576>.
  • Loading branch information
YgorSouza authored Nov 21, 2023
1 parent 39271c3 commit 78a93f8
Showing 1 changed file with 23 additions and 27 deletions.
50 changes: 23 additions & 27 deletions crates/egui/src/animation_manager.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
use crate::{emath::remap_clamp, Id, IdMap, InputState};
use crate::{
emath::{remap_clamp, NumExt as _},
Id, IdMap, InputState,
};

#[derive(Clone, Default)]
pub(crate) struct AnimationManager {
Expand All @@ -8,10 +11,8 @@ pub(crate) struct AnimationManager {

#[derive(Clone, Debug)]
struct BoolAnim {
value: bool,

/// when did `value` last toggle?
toggle_time: f64,
last_value: f32,
last_tick: f64,
}

#[derive(Clone, Debug)]
Expand All @@ -33,38 +34,33 @@ impl AnimationManager {
id: Id,
value: bool,
) -> f32 {
let (start, end) = if value { (0.0, 1.0) } else { (1.0, 0.0) };
match self.bools.get_mut(&id) {
None => {
self.bools.insert(
id,
BoolAnim {
value,
toggle_time: -f64::INFINITY, // long time ago
last_value: end,
last_tick: input.time - input.stable_dt as f64,
},
);
if value {
1.0
} else {
0.0
}
end
}
Some(anim) => {
if anim.value != value {
anim.value = value;
anim.toggle_time = input.time;
}

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;

if value {
remap_clamp(time_since_toggle, 0.0..=animation_time, 0.0..=1.0)
let BoolAnim {
last_value,
last_tick,
} = anim;
let current_time = input.time;
let elapsed = ((current_time - *last_tick) as f32).at_most(input.stable_dt);
let new_value = *last_value + (end - start) * elapsed / animation_time;
*last_value = if new_value.is_finite() {
new_value.clamp(0.0, 1.0)
} else {
remap_clamp(time_since_toggle, 0.0..=animation_time, 1.0..=0.0)
}
end
};
*last_tick = current_time;
*last_value
}
}
}
Expand Down

0 comments on commit 78a93f8

Please sign in to comment.