mirror of
https://github.com/storytold/deckcraft.git
synced 2026-10-25 19:17:06 -06:00
- ui-egui: title bar, ribbon with every tab (Home, Insert, Draw, Design, Transitions, Animations, Slide Show, Record, Review, View) plus contextual Shape/Picture Format, Table Design/Layout, Chart Design, Playback and Slide Master tabs; thumbnail pane with sections and drag reorder; canvas with selection handles, smart guides, marquee, in-place text editing; notes pane; status bar with views and zoom; task panes (Format Shape, Background, Animation, Selection, Comments, Design Ideas); dialogs; Slide Sorter, Notes Page, Outline view; command palette; control channel - anim: timelines for every animation effect, transition layers for every transition, morph pairing, show navigation (hidden slides, custom shows, loops) - show: full-screen slide show with transitions, animations, pen, black/white screens, presenter view window, rehearse timings, reading view - icons: 238 original icons drawn in code - render: filters force single-threaded rendering (regression test), panic guard - engine: chart type/data/options, SmartArt-style graphics - apps/slidecraft: desktop host with control server, file dialogs, clipboard images - placeholder app icon rendered by SlideCraft itself Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
76 lines
2.2 KiB
Rust
76 lines
2.2 KiB
Rust
//! Time easing: acceleration / deceleration fractions and bounce.
|
|
|
|
use crate::clampf;
|
|
|
|
/// Map linear progress `p` (0..1) through PowerPoint-style easing: `accel` and `decel` are the
|
|
/// fractions of the duration spent speeding up and slowing down (velocity ramps linearly);
|
|
/// `bounce` (0..1) makes the last part of the motion bounce against the end.
|
|
pub fn ease(p: f64, accel: f64, decel: f64, bounce: f64) -> f64 {
|
|
let p = clampf(p, 0.0, 1.0, 0.0);
|
|
let mut a = clampf(accel, 0.0, 1.0, 0.0);
|
|
let mut d = clampf(decel, 0.0, 1.0, 0.0);
|
|
if a + d > 1.0 {
|
|
let s = a + d;
|
|
a /= s;
|
|
d /= s;
|
|
}
|
|
let v = 2.0 / (2.0 - a - d);
|
|
let mut y = if a > 0.0 && p < a {
|
|
v * p * p / (2.0 * a)
|
|
} else if d > 0.0 && p > 1.0 - d {
|
|
let q = 1.0 - p;
|
|
1.0 - v * q * q / (2.0 * d)
|
|
} else {
|
|
v * a / 2.0 + v * (p - a)
|
|
};
|
|
let b = clampf(bounce, 0.0, 1.0, 0.0);
|
|
if b > 0.0 {
|
|
// Reach the end early, then bounce back with decaying hops over the last `b` fraction.
|
|
let hit = 1.0 - b;
|
|
if p < hit {
|
|
let q = if hit > 0.0 { p / hit } else { 1.0 };
|
|
y = q * q;
|
|
} else {
|
|
let s = (p - hit) / b;
|
|
y = 1.0 - bounce_hops(s) * 0.25;
|
|
}
|
|
}
|
|
clampf(y, -1.0, 2.0, 0.0)
|
|
}
|
|
|
|
/// Decaying hops for s in 0..1: 0 at the ends of each hop, peaks shrinking.
|
|
fn bounce_hops(s: f64) -> f64 {
|
|
let s = clampf(s, 0.0, 1.0, 1.0);
|
|
let hops = 3.0;
|
|
let k = (s * hops).floor().min(hops - 1.0);
|
|
let local = s * hops - k;
|
|
let amp = 0.5f64.powf(k);
|
|
amp * (local * std::f64::consts::PI).sin()
|
|
}
|
|
|
|
/// Classic bounce-out: falls to 1 and bounces with decaying height.
|
|
pub(crate) fn bounce_out(p: f64) -> f64 {
|
|
let p = clampf(p, 0.0, 1.0, 0.0);
|
|
let n = 7.5625;
|
|
let d = 2.75;
|
|
let y = if p < 1.0 / d {
|
|
n * p * p
|
|
} else if p < 2.0 / d {
|
|
let q = p - 1.5 / d;
|
|
n * q * q + 0.75
|
|
} else if p < 2.5 / d {
|
|
let q = p - 2.25 / d;
|
|
n * q * q + 0.9375
|
|
} else {
|
|
let q = p - 2.625 / d;
|
|
n * q * q + 0.984375
|
|
};
|
|
y.min(1.0)
|
|
}
|
|
|
|
/// Smooth ease-in-out (cubic smoothstep).
|
|
pub(crate) fn smooth(p: f64) -> f64 {
|
|
let p = clampf(p, 0.0, 1.0, 0.0);
|
|
p * p * (3.0 - 2.0 * p)
|
|
}
|