Skip to main content

deckcraft_render/
morph_path.rs

1//! Morph of an outline: a frame shape whose geometry turns from the old shape's into its own (a
2//! circle into a star), with the points aligned by `deckcraft_geom::morph`.
3
4use deckcraft_geom::Xfrm;
5use deckcraft_geom::morph::{Fade, GeometryMorph};
6use deckcraft_geom::preset::Geometry;
7use deckcraft_model::{Geom, Shape, ShapeId};
8use kurbo::Vec2;
9
10use crate::shape_geometry;
11
12/// A frame shape (see [`crate::render_blend`]) whose outline morphs from `from` into its own
13/// geometry.
14#[derive(Clone, Debug, PartialEq)]
15pub struct PathMorph {
16    pub id: ShapeId,
17    /// The old shape's geometry.
18    pub from: Geom,
19    /// The boxes of the old and the new shape on their own slides.
20    pub from_box: Xfrm,
21    pub to_box: Xfrm,
22    /// Progress, 0..1 (already eased).
23    pub t: f64,
24}
25
26/// `now / own`, or 1 when that is no usable scale (a line's zero height).
27fn ratio(now: f64, own: f64) -> f64 {
28    let r = now / own;
29    if own.abs() > 1e-9 && r.is_finite() {
30        r
31    } else {
32        1.0
33    }
34}
35
36/// The geometry of frame shape `s` at its current size `w` x `h`: both outlines are built at their
37/// own sizes (so the alignment does not change while the box grows), then scaled into the box.
38/// With a [`Fade`] per sub-path.
39pub(crate) fn geometry(pm: &PathMorph, s: &Shape, w: f64, h: f64) -> (Geometry, Vec<Fade>) {
40    let a = shape_geometry(
41        &Shape {
42            geom: pm.from.clone(),
43            ..Shape::default()
44        },
45        pm.from_box.w,
46        pm.from_box.h,
47    );
48    let b = shape_geometry(s, pm.to_box.w, pm.to_box.h);
49    let scale = |x: Xfrm| Vec2::new(ratio(w, x.w), ratio(h, x.h));
50    GeometryMorph::new(&a, &b).at(pm.t, scale(pm.from_box), scale(pm.to_box))
51}