diff --git a/app/pages/PageEnigma/Editor/editor.ts b/app/pages/PageEnigma/Editor/editor.ts index 7fdfce0084..5c37fad2b9 100644 --- a/app/pages/PageEnigma/Editor/editor.ts +++ b/app/pages/PageEnigma/Editor/editor.ts @@ -39,8 +39,12 @@ import { import { updateObjectPanel } from "../signals"; import { GenerationOptions } from "../models/generationOptions"; import { toEngineActions } from "../Queue/toEngineActions"; + export type EditorInitializeConfig = { sceneToken: string; + editorCanvasEl: HTMLCanvasElement; + camViewCanvasEl: HTMLCanvasElement; + sceneContainerEl: HTMLDivElement; }; class Editor { @@ -51,8 +55,9 @@ class Editor { renderer: THREE.WebGLRenderer | undefined; rawRenderer: THREE.WebGLRenderer | undefined; clock: THREE.Clock | undefined; - canvReference: HTMLCanvasElement | undefined = undefined; - canvasRenderCamReference: HTMLElement | undefined = undefined; + canvReference: HTMLCanvasElement | null = null; + canvasRenderCamReference: HTMLCanvasElement | null = null; + composer: EffectComposer | undefined; outlinePass: OutlinePass | undefined; last_cam_pos: THREE.Vector3; @@ -229,7 +234,43 @@ class Editor { return value === null || value.trim().length === 0; } - initialize({ sceneToken }: EditorInitializeConfig) { + containerMayReset() { + if (!this.container) { + console.warn( + "Editor - Container does not exist, querying from DOM via document.getElementById", + ); + this.container = document.getElementById("video-scene-container"); + } + } + engineCanvasMayReset() { + if (!this.canvReference) { + console.warn( + "Editor - Engine Canbas does not exist, querying from DOM via document.getElementById", + ); + this.canvReference = document.getElementById( + "video-scene", + ) as HTMLCanvasElement; + } + } + camViewCanvasMayReset() { + if (!this.canvasRenderCamReference) { + console.warn( + "Editor - Cam View Canvas does not exist, querying from DOM via document.getElementById", + ); + this.canvasRenderCamReference = document.getElementById( + "camera-view", + ) as HTMLCanvasElement; + } + } + updateCamViewCanvas(newCanvas: HTMLCanvasElement) { + this.canvasRenderCamReference = newCanvas; + } + initialize({ + sceneToken, + editorCanvasEl, + camViewCanvasEl, + sceneContainerEl, + }: EditorInitializeConfig) { if (!this.can_initialize) { console.log("Editor Already Initialized"); return; @@ -237,21 +278,15 @@ class Editor { this.can_initialize = false; // Gets the canvas. - this.canvReference = (document.getElementById("video-scene") ?? - undefined) as HTMLCanvasElement | undefined; - this.canvasRenderCamReference = - document.getElementById("camera-view") ?? undefined; + this.canvReference = editorCanvasEl; + this.canvasRenderCamReference = camViewCanvasEl; // Find the container element - const container = document.getElementById("video-scene-container"); - - if (container == null) { - return; - } + this.container = sceneContainerEl; // Use the container's dimensions - const width = container.offsetWidth; - const height = container.offsetHeight; + const width = this.container.offsetWidth; + const height = this.container.offsetHeight; // Sets up camera and base position. this.camera = new THREE.PerspectiveCamera(70, width / height, 0.01, 200); @@ -674,9 +709,8 @@ class Editor { 1000 / (this.cap_fps * 2), ); // Get the most FPS we can out of the renderer. - if (this.container === undefined) { - this.container = document.getElementById("video-scene-container"); - } + this.containerMayReset(); + if (!this.rendering && this.container) { if ( this.container.clientWidth + this.container.clientHeight !== @@ -773,11 +807,14 @@ class Editor { this.switchPreviewToggle = false; editorState.value = EditorStates.EDIT; setTimeout(() => { - this.canvasRenderCamReference = - document.getElementById("camera-view") ?? undefined; + // if (!this.canvasRenderCamReference) { + // this.canvasRenderCamReference = + // document.getElementById("camera-view"); + // } + this.camViewCanvasMayReset(); this.rawRenderer = new THREE.WebGLRenderer({ antialias: false, - canvas: this.canvasRenderCamReference, + canvas: this.canvasRenderCamReference || undefined, preserveDrawingBuffer: true, }); if (this.camera_person_mode) { @@ -889,7 +926,7 @@ class Editor { // Automaticly resize scene. onWindowResize() { - this.container = document.getElementById("video-scene-container"); + this.containerMayReset(); if (!this.container) return; const width = this.container.clientWidth; @@ -918,8 +955,8 @@ class Editor { } setupResizeObserver() { - const container = document.getElementById("video-scene-container"); - if (!container) { + this.containerMayReset(); + if (!this.container) { return; } @@ -935,7 +972,7 @@ class Editor { } }); - resizeObserver.observe(container); + resizeObserver.observe(this.container); } getAssetType(selected: THREE.Object3D): AssetType { diff --git a/app/pages/PageEnigma/Editor/video_generation.ts b/app/pages/PageEnigma/Editor/video_generation.ts index ea1fa33f54..01f31e56e2 100644 --- a/app/pages/PageEnigma/Editor/video_generation.ts +++ b/app/pages/PageEnigma/Editor/video_generation.ts @@ -1,5 +1,5 @@ import Editor from "./editor"; -import { EditorStates } from "~/pages/PageEnigma/enums"; +import { EditorStates, ClipType } from "~/pages/PageEnigma/enums"; import { editorState, previewSrc } from "../signals/engine"; import Queue from "~/pages/PageEnigma/Queue/Queue"; import { QueueNames } from "~/pages/PageEnigma/Queue/QueueNames"; @@ -7,7 +7,6 @@ import { fromEngineActions } from "~/pages/PageEnigma/Queue/fromEngineActions"; import { ToastTypes } from "~/enums"; import { createFFmpeg, fetchFile, FFmpeg } from "@ffmpeg/ffmpeg"; import { ClipUI } from "../datastructures/clips/clip_ui.js"; -import { ClipType } from "~/pages/PageEnigma/enums"; import { Visibility } from "./api_manager.js"; import * as THREE from "three"; import { getSceneSignals } from "~/signals"; @@ -70,13 +69,17 @@ export class VideoGeneration { previewSrc.value = url; return Promise.resolve(url); - } catch (err: any) { + } catch (err: unknown) { + const errorMessage = + err instanceof Error + ? err.message + : "Unknown Error in Generate Frame"; Queue.publish({ queueName: QueueNames.FROM_ENGINE, action: fromEngineActions.POP_A_TOAST, data: { type: ToastTypes.ERROR, - message: err.message, + message: errorMessage, }, }); } @@ -259,7 +262,7 @@ export class VideoGeneration { } const upload_token = data["media_file_token"]; - const result = await this.editor.api_manager + await this.editor.api_manager .stylizeVideo( upload_token, this.editor.art_style, @@ -287,11 +290,11 @@ export class VideoGeneration { ); } - this.editor.canvasRenderCamReference = - document.getElementById("camera-view"); + this.editor.camViewCanvasMayReset(); + this.editor.rawRenderer = new THREE.WebGLRenderer({ antialias: false, - canvas: this.editor.canvasRenderCamReference, + canvas: this.editor.canvasRenderCamReference || undefined, preserveDrawingBuffer: true, }); this.editor.activeScene.renderMode(false); diff --git a/app/pages/PageEnigma/PageEditor.tsx b/app/pages/PageEnigma/PageEditor.tsx index d23cb454f0..6ebb4b6071 100644 --- a/app/pages/PageEnigma/PageEditor.tsx +++ b/app/pages/PageEnigma/PageEditor.tsx @@ -23,6 +23,9 @@ import { editorLoader, } from "~/pages/PageEnigma/signals"; +import { EditorCanvas } from "./comps/EngineCanvases"; +import { SceneContainer } from "./comps/SceneContainer"; + export const PageEditor = () => { useSignals(); @@ -68,20 +71,10 @@ export const PageEditor = () => { }} >
-
- + + -
+ {/* Top controls */}
{ + const editorEngine = useContext(EngineContext); + + const canvasCallbackRef = useCallback( + (node: HTMLCanvasElement) => { + if (node && editorEngine && editorEngine.setEditorCanvas) { + editorEngine.setEditorCanvas(node); + } + }, + [editorEngine], + ); + + return ( + + ); +}; + +export const CameraViewCanvas = () => { + const editorEngine = useContext(EngineContext); + + const canvasCallbackRef = useCallback( + (node: HTMLCanvasElement) => { + if (node && editorEngine) { + if (!editorEngine.canvasRenderCamReference) { + editorEngine.setCamViewCanvas(node); + } else { + editorEngine.updateCamViewCanvas(node); + } + } + //else just do nothing + }, + [editorEngine], + ); + + return ; +}; diff --git a/app/pages/PageEnigma/comps/PreviewEngineCamera/index.tsx b/app/pages/PageEnigma/comps/PreviewEngineCamera/index.tsx index 6a7c5f2a8a..39ceed8bd9 100644 --- a/app/pages/PageEnigma/comps/PreviewEngineCamera/index.tsx +++ b/app/pages/PageEnigma/comps/PreviewEngineCamera/index.tsx @@ -9,6 +9,7 @@ import { editorState } from "~/pages/PageEnigma/signals/engine"; import { useSignals } from "@preact/signals-react/runtime"; import { sidePanelHeight } from "../../signals"; import { EditorStates } from "~/pages/PageEnigma/enums"; +import { CameraViewCanvas } from "../EngineCanvases"; export const PreviewEngineCamera = () => { useSignals(); @@ -60,7 +61,7 @@ export const PreviewEngineCamera = () => {
- +
diff --git a/app/pages/PageEnigma/comps/PreviewFrameImage.tsx b/app/pages/PageEnigma/comps/PreviewFrameImage.tsx index 335561c0f2..5c50944c2b 100644 --- a/app/pages/PageEnigma/comps/PreviewFrameImage.tsx +++ b/app/pages/PageEnigma/comps/PreviewFrameImage.tsx @@ -40,9 +40,9 @@ export const PreviewFrameImage = () => { } else { return ( preview of the art style that renders over the 3d scene { + useSignals(); + const editorEngine = useContext(EngineContext); + + const callbackRef = useCallback( + (node: HTMLDivElement) => { + if (node && editorEngine && editorEngine.setSceneContainer) { + editorEngine.setSceneContainer(node); + } + }, + [editorEngine], + ); + + return ( +
+ {children} +
+ ); +}; diff --git a/app/pages/PageEnigma/contexts/EngineContext/EngineContext.tsx b/app/pages/PageEnigma/contexts/EngineContext/EngineContext.tsx index e15c567e1c..c0f0c2a3c7 100644 --- a/app/pages/PageEnigma/contexts/EngineContext/EngineContext.tsx +++ b/app/pages/PageEnigma/contexts/EngineContext/EngineContext.tsx @@ -1,4 +1,16 @@ import { createContext } from "react"; import Editor from "~/pages/PageEnigma/Editor/editor"; -export const EngineContext = createContext(null); +export interface EditorExpandedI extends Editor { + setSceneContainer: React.Dispatch< + React.SetStateAction + >; + setEditorCanvas: React.Dispatch< + React.SetStateAction + >; + setCamViewCanvas: React.Dispatch< + React.SetStateAction + >; +} + +export const EngineContext = createContext(null); diff --git a/app/pages/PageEnigma/contexts/EngineContext/EngineProvider.tsx b/app/pages/PageEnigma/contexts/EngineContext/EngineProvider.tsx index 55ce6a5f14..50b435ad92 100644 --- a/app/pages/PageEnigma/contexts/EngineContext/EngineProvider.tsx +++ b/app/pages/PageEnigma/contexts/EngineContext/EngineProvider.tsx @@ -1,5 +1,5 @@ import { ReactNode, useEffect, useState } from "react"; -import { EngineContext } from "./EngineContext"; +import { EngineContext, EditorExpandedI } from "./EngineContext"; import Editor from "~/pages/PageEnigma/Editor/editor"; @@ -9,25 +9,48 @@ interface Props { } export const EngineProvider = ({ sceneToken, children }: Props) => { - const [editor, setEditor] = useState(null); - + const [editor, setEditor] = useState(null); + const [sceneContainer, setSceneContainer] = useState( + null, + ); + const [editorCanvas, setEditorCanvas] = useState( + null, + ); + const [camViewCanvas, setCamViewCanvas] = useState( + null, + ); useEffect(() => { setEditor((curr) => { if (curr !== null) { console.warn("Editor Engine already exist"); return curr; } - return new Editor(); + + class EditorExpanded extends Editor implements EditorExpandedI { + setSceneContainer = setSceneContainer; + setEditorCanvas = setEditorCanvas; + setCamViewCanvas = setCamViewCanvas; + } + return new EditorExpanded(); }); }, []); useEffect(() => { - if (editor && editor.can_initialize) { + if ( + editor && + editor.can_initialize && + editorCanvas && + camViewCanvas && + sceneContainer + ) { editor.initialize({ sceneToken: sceneToken || "", + sceneContainerEl: sceneContainer, + editorCanvasEl: editorCanvas, + camViewCanvasEl: camViewCanvas, }); } - }, [editor, sceneToken]); + }, [editor, sceneToken, editorCanvas, camViewCanvas, sceneContainer]); return ( {children}