Properly reverse bool animation if value changes before it's finished (#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 <https://github.com/emilk/egui/issues/3576>.
This commit is contained in:
parent
39271c3adf
commit
78a93f81f0
|
|
@ -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 {
|
||||
|
|
@ -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)]
|
||||
|
|
@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue