From 5435b867275b9b2c96f6802e753ef079cb036a6d Mon Sep 17 00:00:00 2001 From: Rodrigo Date: Tue, 5 Aug 2025 16:45:07 +0100 Subject: [PATCH 1/5] canvas renderer primitives (wip) --- .gitignore | 3 +- apps/web/package.json | 2 + apps/web/src/app/editor/[project_id]/page.tsx | 4 +- apps/web/src/components/editor-header.tsx | 25 ++--- .../editor/renderer/canvas-preview-panel.tsx | 104 ++++++++++++++++++ .../editor/renderer/export-dialog.tsx | 104 ++++++++++++++++++ .../editor/renderer/scene-preview-canvas.tsx | 41 +++++++ apps/web/src/hooks/use-raf-loop.ts | 20 ++++ apps/web/src/lib/renderer/nodes/base-node.ts | 29 +++++ apps/web/src/lib/renderer/nodes/color-node.ts | 20 ++++ apps/web/src/lib/renderer/nodes/scene-node.ts | 11 ++ .../lib/renderer/nodes/time-offset-node.ts | 16 +++ .../src/lib/renderer/nodes/timecode-node.ts | 20 ++++ apps/web/src/lib/renderer/nodes/video-node.ts | 50 +++++++++ apps/web/src/lib/renderer/scene-builder.ts | 44 ++++++++ apps/web/src/lib/renderer/scene-exporter.ts | 80 ++++++++++++++ apps/web/src/lib/renderer/scene-renderer.ts | 64 +++++++++++ apps/web/src/stores/renderer-store.ts | 12 ++ bun.lock | 8 +- 19 files changed, 639 insertions(+), 18 deletions(-) create mode 100644 apps/web/src/components/editor/renderer/canvas-preview-panel.tsx create mode 100644 apps/web/src/components/editor/renderer/export-dialog.tsx create mode 100644 apps/web/src/components/editor/renderer/scene-preview-canvas.tsx create mode 100644 apps/web/src/hooks/use-raf-loop.ts create mode 100644 apps/web/src/lib/renderer/nodes/base-node.ts create mode 100644 apps/web/src/lib/renderer/nodes/color-node.ts create mode 100644 apps/web/src/lib/renderer/nodes/scene-node.ts create mode 100644 apps/web/src/lib/renderer/nodes/time-offset-node.ts create mode 100644 apps/web/src/lib/renderer/nodes/timecode-node.ts create mode 100644 apps/web/src/lib/renderer/nodes/video-node.ts create mode 100644 apps/web/src/lib/renderer/scene-builder.ts create mode 100644 apps/web/src/lib/renderer/scene-exporter.ts create mode 100644 apps/web/src/lib/renderer/scene-renderer.ts create mode 100644 apps/web/src/stores/renderer-store.ts diff --git a/.gitignore b/.gitignore index 030fd134d..80450f69b 100644 --- a/.gitignore +++ b/.gitignore @@ -27,4 +27,5 @@ node_modules *.env # cursor -bun.lockb \ No newline at end of file +bun.lockb +.DS_Store \ No newline at end of file diff --git a/apps/web/package.json b/apps/web/package.json index d99476430..8007a6ac3 100644 --- a/apps/web/package.json +++ b/apps/web/package.json @@ -38,6 +38,7 @@ "dotenv": "^16.5.0", "drizzle-orm": "^0.44.2", "embla-carousel-react": "^8.5.1", + "eventemitter3": "^5.0.1", "feed": "^5.1.0", "framer-motion": "^11.13.1", "input-otp": "^1.4.1", @@ -65,6 +66,7 @@ "tailwind-merge": "^2.5.5", "tailwindcss-animate": "^1.0.7", "unified": "^11.0.5", + "use-deep-compare-effect": "^1.8.1", "vaul": "^1.1.1", "zod": "^3.25.67", "zustand": "^5.0.2" diff --git a/apps/web/src/app/editor/[project_id]/page.tsx b/apps/web/src/app/editor/[project_id]/page.tsx index cae8e779c..158c1c1bc 100644 --- a/apps/web/src/app/editor/[project_id]/page.tsx +++ b/apps/web/src/app/editor/[project_id]/page.tsx @@ -17,6 +17,7 @@ import { useProjectStore } from "@/stores/project-store"; import { EditorProvider } from "@/components/editor-provider"; import { usePlaybackControls } from "@/hooks/use-playback-controls"; import { Onboarding } from "@/components/onboarding"; +import { CanvasPreviewPanel } from "@/components/editor/renderer/canvas-preview-panel"; export default function Editor() { const { @@ -189,7 +190,8 @@ export default function Editor() { onResize={setPreviewPanel} className="min-w-0 min-h-0 flex-1" > - + {/* */} + diff --git a/apps/web/src/components/editor-header.tsx b/apps/web/src/components/editor-header.tsx index 77202c367..719afb9f1 100644 --- a/apps/web/src/components/editor-header.tsx +++ b/apps/web/src/components/editor-header.tsx @@ -29,6 +29,7 @@ import { useRouter } from "next/navigation"; import { FaDiscord } from "react-icons/fa6"; import { useTheme } from "next-themes"; import { usePlaybackStore } from "@/stores/playback-store"; +import { ExportDialog } from "./editor/renderer/export-dialog"; export function EditorHeader() { const { getTotalDuration } = useTimelineStore(); @@ -39,13 +40,6 @@ export function EditorHeader() { const router = useRouter(); const { theme, setTheme } = useTheme(); - const handleExport = () => { - // TODO: Implement export functionality - // NOTE: This is already being worked on - console.log("Export project"); - window.open("https://youtube.com/watch?v=dQw4w9WgXcQ", "_blank"); - }; - const handleNameSave = async (newName: string) => { console.log("handleNameSave", newName); if (activeProject && newName.trim() && newName !== activeProject.name) { @@ -148,14 +142,15 @@ export function EditorHeader() { const rightContent = (