Skip to content

feat(engine): dynamic-video foundations — transform origins, glass kit, spring presets#96

Merged
LeadcodeDev merged 3 commits into
mainfrom
feat/dynamic-foundations
Jul 19, 2026
Merged

feat(engine): dynamic-video foundations — transform origins, glass kit, spring presets#96
LeadcodeDev merged 3 commits into
mainfrom
feat/dynamic-foundations

Conversation

@LeadcodeDev

Copy link
Copy Markdown
Owner

Closes #86. Closes #87. Closes #88. First PR of the dynamic-videos wave (#95) — three workstreams grouped on one branch (shared files, single merge to arbitrate).

#86 — real transform-origin / perspective-origin: both were parsed with a hardcoded center pivot. Pure resolve_origin (px/%/keywords), three apply_transform paths (unchanged 2D, single-pivot 3D, dual-pivot 3D wrapping the perspective in its own translate pair). Absent = center, byte-identical (non-regression test). Unlocks hinge/edge 3D rotations. 7 pixel tests.

#87 — glassmorphism kit complete: gradient-border painted for real (DRRect ring + linear gradient shader, radius-aware, replaces the standard border; dead helper deleted); FilterFn::Noise{intensity, seed} via Skia fractal noise (luminance matrix × intensity, Overlay blend) in filter AND backdrop-filter — per-element frosted grain, determinism proven byte-identical. Discovery: the legacy LayerStyle is entirely dead, so backdrop-blur/inner-shadow were hard-rejected, not ignored — now accepted CssStyle compat fields with validator warnings pointing to the real syntax; skill docs corrected (they oversold all three). 10 tests.

#88 — spring easing on any preset: spring: {damping, stiffness, mass} on AnimationTiming; one generic post-pass remaps motion keyframes to the solver (opacity keeps its ease; manual overshoots collapse so the spring supplies them; oscillators untouched; bounce/elastic hardcodes become overridable defaults). HTML DSL spring:trueSpringConfig::default() (single source of truth — accepted deviation from the briefed 12/100). 10 property-level tests (position overshoots, alpha monotone, convergence at window end).

Verify: cargo test --workspace → 430 passed ✓ · cargo fmt --check ✓ · clippy gated ≤1 ✓ · 3 example scenarios validate unchanged ✓

Both properties were parsed but the paint pivot was hardcoded to the
box center. resolve_origin (pure) maps px/percent/keyword components
to absolute pivots (absent = center, byte-identical non-regression);
apply_transform gains three paths: unchanged 2D, single-pivot 3D, and
dual-pivot 3D wrapping the perspective matrix in its own translate
pair when perspective-origin differs. Keywords left/center/right/
top/bottom added additively to the length parser. Unlocks hinge/edge
rotations (3D doors, side-pivoting cards); skill 3D rule documents
the configurable pivot.
- gradient-border wired for real: css field (reusing the schema type)
  painted as a DRRect ring filled with a linear gradient shader,
  radius-aware (inner radii floored), replacing the standard border
  when both are set; the never-called components helper is deleted;
  angle follows the existing background-gradient convention
- FilterFn::Noise{intensity, seed}: Skia fractal_noise -> luminance
  color-matrix scaled by intensity -> Overlay blend over the chain,
  usable in filter AND backdrop-filter — per-element frosted grain;
  determinism proven (same seed = byte-identical frames)
- zombie resolution with a discovery: the legacy LayerStyle is
  entirely dead (zero consumers) so backdrop-blur/inner-shadow were
  hard-rejected by CssStyle deny_unknown_fields rather than silently
  ignored; they are now accepted compat fields with validator
  warnings pointing to backdrop-filter / box-shadow inset, and
  removed from the dead LayerStyle; skill docs corrected (they
  oversold all three fields)
AnimationTiming gains spring: Option<SpringConfig> (serde-additive).
A single generic post-pass (apply_spring_to_motion) remaps a preset's
motion keyframes to the spring solver — builders stay oblivious:

- motion allowlist only (translate/scale/rotation axes); opacity
  keeps its ease (alpha overshoot flashes), blur/draw_progress
  excluded (out-of-range overshoot)
- 2-keyframe motions get spring easing directly; manual-overshoot
  entrances (scale_in 0->1.08->1) collapse to endpoints so the
  spring supplies the overshoot instead of doubling it; same-endpoint
  oscillators (pulse/shake/float) are untouched (a spring to the same
  value freezes the effect)
- bounce_in/elastic_in hardcoded springs become their defaults,
  overridden by user config; duration stays the keyframe window
  (solver already runs in real seconds and clamps at window end)
- HTML DSL: spring:true coerces to {} (SpringConfig::default 15/100/1
  as the single source of truth — accepted deviation), spring:false
  absent, anything else a clear error pointing at the JSON form
@LeadcodeDev
LeadcodeDev merged commit 194057d into main Jul 19, 2026
3 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

1 participant