Moeeldouma's picture
Deploy Eldouma Graphics — Docker Space, bring-your-own-key demo
39d98a0 verified
Raw
History Blame Contribute Delete
14.8 kB
// @ts-nocheck
// ============================================================================
// MOTION GRAPHICS · OBSIDIAN ORBIT — Scene 06 / PROJECT CREATED (11s, 330f)
//
// "Keynote object-worship". ONE hero artifact: a FILE-TREE slab. A thick glass
// slab whose face is a software file-tree — a root folder "Motion Graphics"
// that UNFOLDS open, then core files (remotion / director / episodes) CASCADE
// in one by one, each stamped with a green tick. Order-from-nothing: the empty
// slab fills with structure as the WORLD orbits (never the camera) in slow
// hold→ease arcs. Billboarded spec Callouts fire on drawn leader lines at
// waypoints ("PROJECT READY", "CORE FILES"); the angle-tracked sheen rakes the
// turn; a settle/lock-in on the apex where the tree completes — the payoff —
// then it rests, sheen tracking the final turn.
//
// 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";
const GREEN = "#54a06f"; // SEMANTIC.success — desaturated tick green
/* ----------------------------------------------------------------------------
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 (
<div
style={{
position: "absolute",
left: 120,
top: 120,
display: "flex",
alignItems: "center",
gap: 14,
fontFamily: MONO,
fontSize: 15,
letterSpacing: 5,
textTransform: "uppercase",
color: C.accent2,
...enter(frame, fps, at, { from: "left", dist: 32, blur: 0 }),
}}
>
<span
style={{
width: 30,
height: 2,
background: ACCENT_GRAD,
boxShadow: `0 0 12px ${C.accentGlow}`,
}}
/>
{children}
</div>
);
};
/* ----------------------------------------------------------------------------
A tiny folder glyph that swings OPEN as `open` goes 0→1 (the lid hinges up).
-------------------------------------------------------------------------- */
const FolderGlyph: React.FC<{ open: number; color: string }> = ({
open,
color,
}) => (
<div style={{ position: "relative", width: 30, height: 24, flexShrink: 0 }}>
{/* back wall of the folder */}
<div
style={{
position: "absolute",
inset: 0,
top: 5,
borderRadius: 4,
background: withAlpha(color, 0.22),
border: `1.5px solid ${withAlpha(color, 0.7)}`,
}}
/>
{/* tab */}
<div
style={{
position: "absolute",
left: 0,
top: 1,
width: 13,
height: 7,
borderRadius: "3px 3px 0 0",
background: withAlpha(color, 0.7),
}}
/>
{/* hinging front flap — swings open on `open` */}
<div
style={{
position: "absolute",
left: 0,
right: 0,
bottom: 0,
height: 17,
borderRadius: 4,
background: `linear-gradient(180deg, ${withAlpha(color, 0.55)}, ${withAlpha(
color,
0.28,
)})`,
border: `1.5px solid ${withAlpha(color, 0.85)}`,
transformOrigin: "50% 100%",
transform: `perspective(140px) rotateX(${(open * 62).toFixed(1)}deg)`,
boxShadow: `0 0 12px ${withAlpha(color, 0.4 * open)}`,
}}
/>
</div>
);
/* ----------------------------------------------------------------------------
A small green tick that draws in with a scale/pop.
-------------------------------------------------------------------------- */
const Tick: React.FC<{ p: number }> = ({ p }) => (
<div
style={{
position: "relative",
width: 22,
height: 22,
borderRadius: "50%",
flexShrink: 0,
background: withAlpha(GREEN, 0.18),
border: `1.5px solid ${withAlpha(GREEN, 0.6 + 0.4 * p)}`,
transform: `scale(${mix(0.3, 1, p)})`,
opacity: p,
boxShadow: `0 0 12px ${withAlpha(GREEN, 0.5 * p)}`,
}}
>
<svg
width={22}
height={22}
viewBox="0 0 22 22"
style={{ position: "absolute", inset: 0 }}
>
<path
d="M6 11.5 L9.5 15 L16 7.5"
fill="none"
stroke={GREEN}
strokeWidth={2.4}
strokeLinecap="round"
strokeLinejoin="round"
strokeDasharray={18}
strokeDashoffset={18 * (1 - p)}
style={{ filter: `drop-shadow(0 0 4px ${withAlpha(GREEN, 0.8)})` }}
/>
</svg>
</div>
);
/* ============================================================================
PROJECT CREATED. Hero = the file-tree artifact. An extruded glass slab whose
face is a software file-tree: root folder "Motion Graphics" unfolds, then the
core files cascade in (remotion / director / episodes), each green-ticked.
The world orbits in, callouts fire ("PROJECT READY", "CORE FILES"), and the
tree LOCKS complete on the apex with an impact — then settles.
========================================================================== */
export const MgOrbitScene06ProjectCreated: React.FC = () => {
const frame = useCurrentFrame();
const { fps } = useVideoConfig();
const t = frame / fps;
const LOCK = 8.2; // the apex lock-in beat (seconds) — the payoff
// --- face choreography -------------------------------------------------
const rootIn = beat(frame, fps, 1.0, 1.9, EASE.backOut); // root row drops in
const rootOpen = beat(frame, fps, 1.8, 2.7, EASE.out); // root folder unfolds
const connP = beat(frame, fps, 2.4, 3.2, EASE.out); // the tree spine draws
// core files cascade in, staggered, each with a green tick after it lands.
const files = [
{ name: "remotion", ext: "/", at: 2.9 },
{ name: "director", ext: "/", at: 3.6 },
{ name: "episodes", ext: "/", at: 4.3 },
];
// --- the lock-in: a weighty spring settle on the apex -------------------
const stamp = springAt(frame, fps, LOCK, SPRING.HEAVY); // 0→1 weighty settle
const stampScale = mix(1.12, 1, clamp01(stamp)); // slams down to rest
const flash = clamp01(1 - (t - LOCK) / 0.45) * (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 so the slab reads its face on the way in, then a final arc
// that settles to centre (0°) right at the lock — the snap-to-camera payoff.
const legs = [
{ arc: -22, hold: 0.5, travel: 2.6 },
{ arc: 30, hold: 1.2, travel: 2.8 },
{ arc: -8, hold: 0.6, travel: 1.7 }, // lands ~0° near LOCK
];
const HeroFace = (
<div
style={{
position: "absolute",
inset: 0,
padding: "40px 46px",
display: "flex",
flexDirection: "column",
justifyContent: "center",
gap: 0,
transform: `scale(${stampScale})`,
}}
>
{/* window chrome bar — reads as a file explorer panel */}
<div
style={{
display: "flex",
alignItems: "center",
gap: 8,
marginBottom: 22,
opacity: rootIn,
}}
>
<span
style={{
width: 10,
height: 10,
borderRadius: "50%",
background: withAlpha(C.accent, 0.7),
}}
/>
<span
style={{
width: 10,
height: 10,
borderRadius: "50%",
background: withAlpha("#ffffff", 0.22),
}}
/>
<span
style={{
width: 10,
height: 10,
borderRadius: "50%",
background: withAlpha("#ffffff", 0.22),
}}
/>
<div
style={{
marginLeft: 12,
fontFamily: MONO,
fontSize: 12,
letterSpacing: 2.5,
textTransform: "uppercase",
color: C.textDim,
}}
>
explorer
</div>
</div>
{/* ROOT ROW — the project folder that unfolds open */}
<div
style={{
display: "flex",
alignItems: "center",
gap: 14,
...enter(frame, fps, 1.0, { from: "up", dist: 22, blur: 0 }),
opacity: rootIn,
}}
>
<FolderGlyph open={rootOpen} color={C.accent2} />
<div
style={{
fontFamily: FONT,
fontWeight: 800,
fontSize: 38,
letterSpacing: "-0.02em",
color: C.text,
textShadow: `0 0 24px ${withAlpha(C.accent, 0.35)}`,
}}
>
Motion Graphics
</div>
<div
style={{
marginLeft: 6,
fontFamily: MONO,
fontSize: 13,
letterSpacing: 2,
color: C.accent2,
opacity: rootOpen,
}}
>
/
</div>
</div>
{/* the tree spine + the cascading core files */}
<div style={{ position: "relative", paddingLeft: 16, marginTop: 18 }}>
{/* vertical spine of the tree, drawing down from the root */}
<div
style={{
position: "absolute",
left: 16,
top: -6,
width: 2,
height: `${connP * 88}%`,
background: `linear-gradient(180deg, ${withAlpha(
C.accent2,
0.8,
)}, ${withAlpha(C.accent, 0.25)})`,
boxShadow: `0 0 8px ${withAlpha(C.accent, 0.4)}`,
}}
/>
<div
style={{
display: "flex",
flexDirection: "column",
gap: 14,
paddingLeft: 30,
}}
>
{files.map((f) => {
const rowP = beat(frame, fps, f.at, f.at + 0.6, EASE.backOut);
const tickP = beat(frame, fps, f.at + 0.5, f.at + 1.0, EASE.out);
const folderOpen = beat(frame, fps, f.at + 0.3, f.at + 0.9, EASE.out);
return (
<div
key={f.name}
style={{
position: "relative",
display: "flex",
alignItems: "center",
gap: 14,
opacity: rowP,
transform: `translateX(${((1 - rowP) * 26).toFixed(1)}px)`,
}}
>
{/* elbow connector from the spine to this row */}
<div
style={{
position: "absolute",
left: -30,
top: "50%",
width: 24,
height: 2,
transform: "translateY(-50%)",
background: withAlpha(C.accent2, 0.7 * rowP),
boxShadow: `0 0 6px ${withAlpha(C.accent, 0.4 * rowP)}`,
}}
/>
<FolderGlyph open={folderOpen} color={C.accent} />
<div
style={{
fontFamily: MONO,
fontSize: 26,
fontWeight: 600,
letterSpacing: "0.01em",
color: C.text,
}}
>
{f.name}
<span style={{ color: C.accent2 }}>{f.ext}</span>
</div>
<div style={{ flex: 1 }} />
<Tick p={tickP} />
</div>
);
})}
</div>
</div>
{/* the lock ring that snaps tight on the apex beat */}
<div
style={{
position: "absolute",
inset: 18,
borderRadius: 26,
border: `2px solid ${withAlpha(C.accent, 0.3 + 0.45 * ringPulse)}`,
opacity: lockRing,
boxShadow: `0 0 30px ${withAlpha(C.accent, 0.3 * ringPulse)}`,
pointerEvents: "none",
}}
/>
</div>
);
return (
<Plinth>
<Eyebrow at={0.3}>Project Created</Eyebrow>
{/* riser glow swelling behind the hero into the apex */}
<AbsoluteFill style={{ pointerEvents: "none", zIndex: 1 }}>
<GlowPulse
size={1000}
color={withAlpha(C.accent, 0.1 * riser)}
strength={riser}
/>
</AbsoluteFill>
{/* impact flash + shockwave on the lock-in payoff */}
<AbsoluteFill style={{ pointerEvents: "none", zIndex: 6 }}>
<GlowPulse
size={1200}
color={withAlpha(C.accent, 0.2 * flash)}
strength={flash}
/>
<Shockwave at={LOCK} size={820} />
<Shockwave at={LOCK + 0.08} size={1120} />
<LightSweep at={LOCK} dur={1.0} strength={0.16} />
</AbsoluteFill>
<OrbitWorld legs={legs} perspective={2300} bobAmp={12}>
<DustMotes layers={3} opacity={0.42} />
<Extrude w={760} h={460} depth={22} layers={16} radius={28}>
{HeroFace}
</Extrude>
{/* billboarded spec callouts firing at orbit waypoints */}
<Callout
title="Status"
value="PROJECT READY"
at={fps * 2.6}
x={0}
y={-320}
leader={120}
side="right"
/>
<Callout
title="Scaffolded"
value="CORE FILES"
at={fps * 4.6}
x={470}
y={150}
leader={150}
side="right"
/>
<Callout
title="Build Time"
value="11s"
at={fps * (LOCK + 0.3)}
x={-470}
y={140}
leader={160}
side="left"
/>
</OrbitWorld>
{/* flat masked mirror sibling — re-renders the hero, simplified & matte */}
<Plinth.Reflection>
<Extrude w={760} h={460} depth={22} layers={10} radius={28} sheen={false}>
{HeroFace}
</Extrude>
</Plinth.Reflection>
</Plinth>
);
};
export default MgOrbitScene06ProjectCreated;