import React from "react"; import { AbsoluteFill, interpolate, spring, useCurrentFrame, useVideoConfig, Easing, } from "remotion"; import { ThreeCanvas } from "@remotion/three"; import { Environment, Lightformer, MeshReflectorMaterial, RoundedBox } from "@react-three/drei"; import { EffectComposer, Bloom, DepthOfField, Vignette } from "@react-three/postprocessing"; import * as THREE from "three"; import { z } from "zod"; import { colorSchema } from "../lib/branding"; import { FONT } from "../lib/fonts"; import { useLayout } from "../lib/aspect"; import { hexToRgba, rand } from "../lib/anim"; export const nowruz3DSchema = z.object({ greeting: z.string(), subtitle: z.string(), message: z.string(), ...colorSchema, }); type Props = z.infer; const GOLD = "#f5c542"; const RED = "#e23b3b"; const SKIN = "#f0b486"; const GREEN = "#4fb84f"; // ── Stylized 3D Haji Firuz (primitive-built, clay-render look) ──────────────── const HajiFiruz3D: React.FC = () => { const frame = useCurrentFrame(); const { fps } = useVideoConfig(); const enter = spring({ frame: frame - 20, fps, config: { damping: 14, stiffness: 60 } }); const bob = Math.abs(Math.sin(frame / 7)) * 0.12 * enter; const sway = Math.sin(frame / 7) * 0.08 * enter; const armSwing = Math.sin(frame / 3.2) * 0.5; const y = -0.5 + bob; return ( {/* tunic (tapered) */} {/* gold hem + sash */} {/* buttons */} {[0.75, 0.6, 0.45].map((by, i) => ( ))} {/* head */} {/* eyes */} {[-0.12, 0.12].map((ex, i) => ( ))} {/* smile */} {/* hat (cone) + band + tip */} {/* right arm (down, swings) */} {/* left arm raised with tambourine */} {Array.from({ length: 8 }).map((_, i) => ( ))} {/* legs */} {[-0.16, 0.16].map((lx, i) => ( ))} ); }; // ── Haft-Sin props ─────────────────────────────────────────────────────────── const Candle: React.FC<{ x: number; z: number }> = ({ x, z }) => { const frame = useCurrentFrame(); const flick = 1 + Math.sin(frame / 4) * 0.12; return ( ); }; const Egg: React.FC<{ x: number; z: number; color: string }> = ({ x, z, color }) => ( ); const FishBowl3D: React.FC<{ x: number; z: number }> = ({ x, z }) => { const frame = useCurrentFrame(); const fishX = Math.sin(frame / 20) * 0.12; return ( {/* water */} {/* fish */} {/* glass */} ); }; const Sabzeh3D: React.FC<{ x: number; z: number }> = ({ x, z }) => { const frame = useCurrentFrame(); return ( {Array.from({ length: 30 }).map((_, i) => { const a = rand(i) * Math.PI * 2; const r = rand(i + 5) * 0.22; const sway = Math.sin(frame / 18 + i) * 0.08; return ( ); })} ); }; const Petals3D: React.FC = () => { const frame = useCurrentFrame(); return ( {Array.from({ length: 30 }).map((_, i) => { const x = (rand(i) - 0.5) * 9; const z = (rand(i + 3) - 0.5) * 4 - 1; const fall = 4 - ((frame * (0.01 + rand(i) * 0.02) + rand(i + 7) * 6) % 7); const rot = frame * 0.03 * (1 + rand(i)); return ( ); })} ); }; // ── Scene ──────────────────────────────────────────────────────────────────── const Scene: React.FC = () => { const frame = useCurrentFrame(); const orbit = Math.sin(frame / 110) * 0.22; return ( {/* reflective floor */} ); }; export const Nowruz3D: React.FC = ({ greeting, subtitle, message, accentColor, secondaryColor, backgroundColor, textColor, }) => { const frame = useCurrentFrame(); const { width, height } = useVideoConfig(); const L = useLayout(); const gSpring = spring({ frame: frame - 120, fps: 30, config: { damping: 13, stiffness: 90 } }); const gScale = interpolate(gSpring, [0, 1], [0.6, 1]); const gOp = interpolate(frame, [120, 140], [0, 1], { extrapolateLeft: "clamp", extrapolateRight: "clamp" }); const subOp = interpolate(frame, [142, 162], [0, 1], { extrapolateLeft: "clamp", extrapolateRight: "clamp" }); const msgOp = interpolate(frame, [156, 176], [0, 1], { extrapolateLeft: "clamp", extrapolateRight: "clamp" }); return ( {/* Greeting overlay */}
{greeting}
{subtitle}
{message}
); };