use crate::ty::{AnimFn, AnimFnType};
#[derive(Clone, Copy)]
pub struct Animation {
pub out_seg: AnimationSegment,
pub in_seg: AnimationSegment,
}
impl Animation {
pub const EMPTY: Self =
Animation::from_segments(AnimationSegment::EMPTY, AnimationSegment::EMPTY);
pub const fn new(duration: f32, out_fn: AnimFnType, in_fn: AnimFnType) -> Self {
let segment_duration = duration / 2.0;
let out_seg = AnimationSegment::new(segment_duration, out_fn);
let in_seg = AnimationSegment::new(segment_duration, in_fn);
Self { out_seg, in_seg }
}
pub const fn new_out(duration: f32, out_fn: AnimFnType) -> Self {
let out_seg = AnimationSegment::new(duration, out_fn);
let in_seg = AnimationSegment::EMPTY;
Self { out_seg, in_seg }
}
pub const fn new_in(duration: f32, out_fn: AnimFnType) -> Self {
let out_seg = AnimationSegment::EMPTY;
let in_seg = AnimationSegment::new(duration, out_fn);
Self { out_seg, in_seg }
}
pub const fn from_segments(out_seg: AnimationSegment, in_seg: AnimationSegment) -> Self {
Self { out_seg, in_seg }
}
pub const fn duration(&self) -> f32 {
self.out_seg.duration + self.in_seg.duration
}
}
impl Default for Animation {
fn default() -> Self {
Self {
out_seg: Default::default(),
in_seg: Default::default(),
}
}
}
#[derive(Clone, Copy)]
pub struct AnimationSegment {
pub duration: f32,
pub anim_fn: AnimFnType,
}
impl AnimationSegment {
const EMPTY: Self = AnimationSegment {
duration: 0.0,
anim_fn: |_, _| {},
};
pub const fn new(duration: f32, anim_fn: AnimFnType) -> Self {
Self { duration, anim_fn }
}
pub fn duration(&self) -> f32 {
self.duration
}
pub fn duration_mut(&mut self) -> f32 {
self.duration
}
pub fn anim_fn(&self) -> AnimFnType {
self.anim_fn
}
fn scope_animation<R>(
ui: &mut egui::Ui,
id: egui::Id,
anim_fn: impl FnOnce(&mut egui::Ui),
add_contents: impl FnOnce(&mut egui::Ui) -> R,
) -> R {
let layer_id = egui::LayerId::new(ui.layer_id().order, id);
ui.scope_builder(
egui::UiBuilder::new()
.id_salt("animation_scope")
.layer_id(layer_id),
|ui| {
anim_fn(ui);
add_contents(ui)
},
)
.inner
}
pub(super) fn animate<R>(
&self,
ui: &mut egui::Ui,
id: egui::Id,
normal: f32,
add_contents: impl FnOnce(&mut egui::Ui) -> R,
) -> R {
Self::scope_animation(ui, id, |ui| self.anim_fn.tick(ui, normal), add_contents)
}
}
impl Default for AnimationSegment {
fn default() -> Self {
Self::EMPTY
}
}