// @ts-nocheck // ============================================================================ // MOTION GRAPHICS · OBSIDIAN ORBIT — Scene 08 / CREATE EPISODE (13s, 390f) // // "Keynote object-worship". ONE hero artifact: a DASHBOARD slab. A thick glass // slab whose face is a project dashboard — a glowing "+ Create Episode" button // gets clicked (a ripple fires), a name field TYPES a title, then a back-end // directory SKELETON self-assembles row by row on the face. Instant scaffolding, // keynote calm. The WORLD orbits (never the camera) in slow hold->ease arcs; // spec Callouts billboard on drawn leader lines at waypoints ("+ CREATE EPISODE", // "AUTO-SCAFFOLD"); the angle-tracked sheen rakes the turn; a gentle settle on // the payoff as the tree finishes locking in. // // Built ENTIRELY on the Plinth module (mirrors ObsidianOrbit.tsx's contract) + // the shared Chronixel engine. CSS-3D only, deterministic, no WebGL. // ============================================================================ import React from "react"; import { AbsoluteFill, useCurrentFrame, useVideoConfig } from "remotion"; import { Plinth, OrbitWorld, Extrude, Callout, DustMotes, } from "../../plinth/plinth"; import { C, withAlpha, ACCENT_GRAD } from "../../chronixel/theme"; import { FONT, MONO } from "../../chronixel/fonts"; import { beat, clamp01, mix, osc, enter, springAt, EASE, SPRING, } from "../../chronixel/motion"; import { Shockwave, GlowPulse, LightSweep } from "../../chronixel/fx"; import { TypeOn } from "../../chronixel/viz/text"; /* ---------------------------------------------------------------------------- A small mono eyebrow tag pinned top-left over the void — frames the beat. -------------------------------------------------------------------------- */ const Eyebrow: React.FC<{ at: number; children: React.ReactNode }> = ({ at, children, }) => { const frame = useCurrentFrame(); const { fps } = useVideoConfig(); return (
{children}
); }; /* ============================================================================ CREATE EPISODE. Hero = the DASHBOARD artifact. A glass slab whose face is a project dashboard: a glowing "+ Create Episode" button is clicked (ripple), a name field types a title, then a directory skeleton self-assembles. The world orbits in, callouts fire, and the scaffold locks in on the payoff. ========================================================================== */ export const MgOrbitScene08CreateEpisode: React.FC = () => { const frame = useCurrentFrame(); const { fps } = useVideoConfig(); const t = frame / fps; // --- beat timeline (seconds) ------------------------------------------- const CLICK = 2.4; // the "+ Create Episode" button is pressed (ripple) const TYPE = 3.0; // the name field begins typing the title const SCAFFOLD = 5.6; // the directory skeleton starts self-assembling const LOCK = 9.0; // the scaffold finishes — a calm settle payoff // --- face choreography ------------------------------------------------- const dashIn = beat(frame, fps, 0.8, 2.0, EASE.out); // dashboard fades up const btnGlow = 0.5 + 0.5 * osc(t, 1.4); // the create button breathes const pressDip = 1 - 0.06 * clamp01(1 - Math.abs(t - CLICK) / 0.18); // squash const ripple = clamp01((t - CLICK) / 0.7); // click ripple expands const rippleLife = clamp01(1 - (t - CLICK) / 0.7); // the name field appears right after the click, then the title types in. const fieldP = beat(frame, fps, CLICK + 0.15, CLICK + 0.6, EASE.backOut); // the directory tree rows assemble one at a time after SCAFFOLD. const tree = [ { label: "episode-08/", depth: 0 }, { label: "scenes/", depth: 1 }, { label: "scene-01.tsx", depth: 2 }, { label: "scene-02.tsx", depth: 2 }, { label: "assets/", depth: 1 }, { label: "render.config.ts", depth: 1 }, ]; // --- the lock-in: a gentle, weighty settle on the payoff ---------------- const stamp = springAt(frame, fps, LOCK, SPRING.HEAVY); // 0->1 settle const stampScale = mix(1.04, 1, clamp01(stamp)); // a soft, calm seat const flash = clamp01(1 - (t - LOCK) / 0.5) * (t >= LOCK ? 1 : 0); const riser = beat(frame, fps, LOCK - 1.4, LOCK, EASE.out); // build into apex const lockRing = clamp01(stamp); const ringPulse = 0.5 + 0.5 * osc(t, 3); // hold->ease orbit: shows the button face on the way in, turns to reveal the // scaffolding, then a final short arc that settles to centre (0°) at the lock. const legs = [ { arc: -18, hold: 0.7, travel: 2.4 }, // ease left to read the button { arc: 26, hold: 1.6, travel: 2.8 }, // swing across as it types/scaffolds { arc: -8, hold: 0.6, travel: 1.8 }, // lands ~0° near LOCK — settle ]; const HeroFace = (
{/* dashboard chrome — title bar */}
chronixel · dashboard
new project
{/* main body: left = create + name field, right = scaffold tree */}
{/* LEFT — the glowing "+ Create Episode" button + the name field */}
{/* the create button (with click ripple) */}
+ Create Episode {/* click ripple emanating from the press point */} {t >= CLICK && (
)}
{/* the name field that types the episode title */}
episode name
{/* RIGHT — the back-end directory skeleton self-assembling */}
scaffolding
{tree.map((row, i) => { const rp = beat( frame, fps, SCAFFOLD + i * 0.28, SCAFFOLD + i * 0.28 + 0.5, EASE.backOut, ); const isDir = row.label.endsWith("/"); return (
{/* node glyph: folder vs file */}
{row.label}
); })}
{/* lock ring that snaps tight as the scaffold finishes (calm settle) */}
); return ( One Click To Scaffold {/* riser glow swelling behind the hero into the settle */} {/* a soft flash + shockwave the instant the button is clicked */} {/* a gentle settle flash as the scaffold locks in on the payoff */} {HeroFace} {/* billboarded spec callouts firing at orbit waypoints */} {/* flat masked mirror sibling — re-renders the hero, simplified & matte */} {HeroFace} ); }; export default MgOrbitScene08CreateEpisode;