From 41b09ab3679937765dcebbc00643e34232316f29 Mon Sep 17 00:00:00 2001 From: Quicksticks-oss Date: Thu, 28 Mar 2024 14:38:14 -0400 Subject: [PATCH 01/17] added base for multi rendering camera. --- .../ControlsTopButtons/ControlsTopButtons.tsx | 5 ++- app/pages/PageEnigma/js/editor.ts | 36 ++++++++++++++++--- 2 files changed, 34 insertions(+), 7 deletions(-) diff --git a/app/pages/PageEnigma/comps/ControlsTopButtons/ControlsTopButtons.tsx b/app/pages/PageEnigma/comps/ControlsTopButtons/ControlsTopButtons.tsx index 3cbf802527..9329cdb68f 100644 --- a/app/pages/PageEnigma/comps/ControlsTopButtons/ControlsTopButtons.tsx +++ b/app/pages/PageEnigma/comps/ControlsTopButtons/ControlsTopButtons.tsx @@ -26,8 +26,7 @@ export const ControlsTopButtons = () => { editorEngine?.start_playback(); }; const handleButtonLoad = () => { - - + editorEngine?.renderVideo(); }; const handleButtonRender = () => { editorEngine?.take_timeline_cam_clip(); @@ -95,7 +94,7 @@ export const ControlsTopButtons = () => {
- +
diff --git a/app/pages/PageEnigma/js/editor.ts b/app/pages/PageEnigma/js/editor.ts index d529603b1b..ba593cdbae 100644 --- a/app/pages/PageEnigma/js/editor.ts +++ b/app/pages/PageEnigma/js/editor.ts @@ -42,6 +42,7 @@ class Editor { version: number; activeScene: Scene; camera: any; + render_camera: any; renderer: THREE.WebGLRenderer | undefined; clock: THREE.Clock | undefined; canvReference: any; @@ -91,7 +92,9 @@ class Editor { can_initialize: boolean; dispatchAppUiState: any; // todo figure out the type - + camera_person_mode: boolean; + render_width: number; + render_height: number; // Default params. constructor() { @@ -115,6 +118,7 @@ class Editor { this.activeScene = new Scene("" + this.version); this.activeScene.initialize(); this.camera; + this.render_camera; this.renderer; this.clock; this.canvReference = null; @@ -158,6 +162,9 @@ class Editor { this.max_length = 10; // Audio Engine Test. + this.render_width = 1280; + this.render_height = 720; + this.audio_engine = new AudioEngine(); this.transform_engine = new TransformEngine(this.version); this.lipsync_engine = new LipSyncEngine(); @@ -209,6 +216,9 @@ class Editor { this.camera.position.z = 3; this.camera.position.y = 3; this.camera.position.x = -3; + + this.render_camera = new THREE.PerspectiveCamera(70, width / height, 0.1, 50); + // Base WebGL render and clock for delta time. this.renderer = new THREE.WebGLRenderer({ antialias: true, @@ -582,6 +592,7 @@ class Editor { render_mode() { this.rendering = !this.rendering; this.activeScene.render_mode(this.rendering); + console.log("works.") //if (this.rendering) { // this._remove_post_processing() @@ -590,6 +601,12 @@ class Editor { //} } + renderVideo() { + this.rendering = true; + this.activeScene.render_mode(this.rendering); + console.log("Rendering..."); + } + togglePlay() { this.playback = !this.playback; this.playback_location = 0; @@ -660,6 +677,11 @@ class Editor { } } + if(this.render_camera && this.cam_obj) { + this.render_camera.position.copy(this.cam_obj.position); + this.render_camera.rotation.copy(this.cam_obj.rotation); + } + this.timeline.update(delta_time); this.render_scene(); @@ -773,10 +795,10 @@ class Editor { // Render the scene to the camera. render_scene() { - if (this.composer != null) { + if (this.composer != null && !this.timeline.isPlaying) { this.composer.render(); - } else if (this.renderer && this.camera) { - this.renderer.render(this.activeScene.scene, this.camera); + } else if (this.renderer && this.render_camera) { + this.renderer.render(this.activeScene.scene, this.render_camera); } else { console.error("Could not render to canvas no render or composer!"); } @@ -812,6 +834,12 @@ class Editor { if (this.composer != null) { this.composer.setSize(width, height); } + + if (this.render_camera == undefined) { return; } + + //this.renderer.setSize(this.render_width, this.render_height); + this.render_camera.aspect = this.render_width / this.render_height; + this.render_camera.updateProjectionMatrix(); } onContextMenu(event: any) { From a5cd47baeb45dd28be61cf78027615435376391f Mon Sep 17 00:00:00 2001 From: wil Date: Thu, 28 Mar 2024 10:47:06 -0400 Subject: [PATCH 02/17] fixed side panel visual bugs --- app/modules/SidePanel/SidePanel.tsx | 26 +++---- .../SidePanelOld/SidePanelInnerOld.tsx | 67 ------------------- app/modules/SidePanelOld/SidePanelOld.tsx | 54 --------------- app/modules/SidePanelOld/index.tsx | 1 - app/modules/Tabs/Tabs.tsx | 6 +- .../comps/SidePanelTabs/TabStylization.tsx | 4 +- 6 files changed, 14 insertions(+), 144 deletions(-) delete mode 100644 app/modules/SidePanelOld/SidePanelInnerOld.tsx delete mode 100644 app/modules/SidePanelOld/SidePanelOld.tsx delete mode 100644 app/modules/SidePanelOld/index.tsx diff --git a/app/modules/SidePanel/SidePanel.tsx b/app/modules/SidePanel/SidePanel.tsx index 57ec64a81d..2116a17788 100644 --- a/app/modules/SidePanel/SidePanel.tsx +++ b/app/modules/SidePanel/SidePanel.tsx @@ -1,6 +1,4 @@ import { useState } from "react"; -import { Tabs } from "../Tabs"; -import { Transition } from "@headlessui/react"; import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; import { faChevronLeft, @@ -15,26 +13,20 @@ export const SidePanel = ({children}:Props) => { const [isVisible, setIsVisible] = useState(true); return ( -
+
- - - {children} - - +
+ {children} +
); diff --git a/app/modules/SidePanelOld/SidePanelInnerOld.tsx b/app/modules/SidePanelOld/SidePanelInnerOld.tsx deleted file mode 100644 index 3112e81c5d..0000000000 --- a/app/modules/SidePanelOld/SidePanelInnerOld.tsx +++ /dev/null @@ -1,67 +0,0 @@ -import { useCallback, useLayoutEffect, useState } from "react"; -import { Dialog } from "@headlessui/react"; - -import { faXmark } from "@fortawesome/pro-solid-svg-icons"; -import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; - -import { TOP_BAR_HEIGHT } from "~/constants"; - -export const SidePanelInner = ({ - title, - children, - closeCallback, -}: { - title?: string; - children: React.ReactNode; - closeCallback: () => void; -}) => { - const [height, setHeight] = useState(0); - const handleWindowResize = useCallback(() => { - if (window) { - setHeight(Math.ceil((window.innerHeight * 3) / 4) - TOP_BAR_HEIGHT); - } - return 0; - }, []); - - useLayoutEffect(() => { - handleWindowResize(); - window.addEventListener("resize", handleWindowResize); - return () => { - window.removeEventListener("resize", handleWindowResize); - }; - }, [handleWindowResize]); - - return ( -
-
-
- {!title && } - {title && ( - - {title} - - )} -
- -
-
-
-
{children}
-
- ); -}; diff --git a/app/modules/SidePanelOld/SidePanelOld.tsx b/app/modules/SidePanelOld/SidePanelOld.tsx deleted file mode 100644 index b46e9841c7..0000000000 --- a/app/modules/SidePanelOld/SidePanelOld.tsx +++ /dev/null @@ -1,54 +0,0 @@ -import { Fragment, useState } from "react"; -import { Dialog, Transition } from "@headlessui/react"; -import { faGears } from "@fortawesome/pro-solid-svg-icons"; -import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; - -import { Button } from "~/components/Button"; - -import { SidePanelInner } from "./SidePanelInnerOld"; - -interface SidePanelPropsI { - title?: string; - children: React.ReactNode; -} - -export const SidePanel = ({ title, children }: SidePanelPropsI) => { - const [open, setOpen] = useState(false); - const handleOpen = () => setOpen(true); - const handleClose = () => setOpen(false); - - return ( - <> - - - -
- -
-
-
- - - - {children} - - - -
-
-
-
-
- - ); -}; diff --git a/app/modules/SidePanelOld/index.tsx b/app/modules/SidePanelOld/index.tsx deleted file mode 100644 index 5f4f8914f6..0000000000 --- a/app/modules/SidePanelOld/index.tsx +++ /dev/null @@ -1 +0,0 @@ -export { SidePanel } from "./SidePanelOld"; diff --git a/app/modules/Tabs/Tabs.tsx b/app/modules/Tabs/Tabs.tsx index 3a83dfbd65..b2ddd3e65b 100644 --- a/app/modules/Tabs/Tabs.tsx +++ b/app/modules/Tabs/Tabs.tsx @@ -19,7 +19,7 @@ export const Tabs = ({ tabs: tabProps }: { tabs: TabType[] }) => { ); return ( -
+
{tabs.map((tab, idx) => ( @@ -31,9 +31,9 @@ export const Tabs = ({ tabs: tabProps }: { tabs: TabType[] }) => { ))} - + {tabs.map((tab, idx) => ( - + {tab.children} ))} diff --git a/app/pages/PageEnigma/comps/SidePanelTabs/TabStylization.tsx b/app/pages/PageEnigma/comps/SidePanelTabs/TabStylization.tsx index a356416e55..7cdad47d87 100644 --- a/app/pages/PageEnigma/comps/SidePanelTabs/TabStylization.tsx +++ b/app/pages/PageEnigma/comps/SidePanelTabs/TabStylization.tsx @@ -32,7 +32,7 @@ export const TabStylization = ()=>{ } } return( - <> +

Select Base Stylizer

{ }
- +
); } \ No newline at end of file From 9bef1022b684189b574dd4d4cb4cf4f377a1a65e Mon Sep 17 00:00:00 2001 From: wil Date: Wed, 27 Mar 2024 23:53:48 -0400 Subject: [PATCH 03/17] change all loading transitions to use headlessui transitions --- app/components/LoadingBar.tsx | 69 +++++++++++++++-- app/components/LoadingDots.tsx | 77 +++++++------------ app/pages/PageEnigma/PageEnigmaComponent.tsx | 3 +- .../comps/PreviewEngineCamera/index.tsx | 2 +- app/pages/PageEnigma/reducer/index.tsx | 2 +- app/pages/PageEnigma/reducer/types.tsx | 2 +- app/root.tsx | 33 ++++---- app/routes/ComponentLibrary.tsx | 59 ++++++++++---- 8 files changed, 151 insertions(+), 96 deletions(-) diff --git a/app/components/LoadingBar.tsx b/app/components/LoadingBar.tsx index 90a112df5c..7fb2e0eb77 100644 --- a/app/components/LoadingBar.tsx +++ b/app/components/LoadingBar.tsx @@ -1,9 +1,12 @@ +import { useEffect, useState } from 'react'; +import { Transition } from '@headlessui/react'; import { twMerge } from 'tailwind-merge'; -import { H4 } from '.'; + interface LoadingBarProps{ label?: string; progress?: number; + isShowing?: boolean; variant?: string; message?: string; wrapperClassName?: string; @@ -11,12 +14,57 @@ interface LoadingBarProps{ } export const LoadingBar = ({ label, - progress = 0, + progress: propsProgress = 0, + isShowing = true, variant = 'primary', message, wrapperClassName : propsWrapperClassName, - useFakeTimer = (1000 * 60) //defaults to 1min + useFakeTimer }: LoadingBarProps) => { + const [progress, setProgress] = useState(propsProgress); + + // this takes the real progress coming from parent + useEffect(()=>{ + setProgress(propsProgress); + }, [propsProgress]); + + // this sets a fake progress, it goes to 96% + // in the amount of miliseconds provided by the flag + useEffect(()=>{ + let loop: NodeJS.Timeout; + if(useFakeTimer){ + if(useFakeTimer >= 30000){ + // this math produce 96 cuts so the progress bar updates more + loop = setInterval(function step(){ + setProgress((curr)=>{ + if(curr<96){ + return curr + 3 + }else{ + clearInterval(loop); + return curr; + } + }) + },Math.round(useFakeTimer/96)*3); + }else{ + // this math produce less cuts if useFakeTimer predicts + // a shorter load time, shorter thatn 30s + const progressPerInterval = useFakeTimer/500 + loop = loop = setInterval(function step(){ + setProgress((curr)=>{ + if(curr + progressPerInterval < 96){ + return curr + progressPerInterval + }else if (curr< 96 && curr + progressPerInterval >= 96){ + return 96; + }else{ + clearInterval(loop); + return curr; + } + }) + }, 300); + } + } + return () => clearInterval(loop); + }, []); function getVariantClassNames(variant: string) { switch (variant) { @@ -40,7 +88,16 @@ export const LoadingBar = ({ ); return ( -
+ {label && }
- {message &&

{message}

} -
+ {message &&

{message}

} +
); } \ No newline at end of file diff --git a/app/components/LoadingDots.tsx b/app/components/LoadingDots.tsx index 3abfa49eb6..2a1c53e4fa 100644 --- a/app/components/LoadingDots.tsx +++ b/app/components/LoadingDots.tsx @@ -1,22 +1,19 @@ import { useState, useEffect } from 'react'; +import { Transition } from '@headlessui/react'; import { twMerge } from 'tailwind-merge'; import { H4 } from '.'; interface LoadingDotsProps { className?: string; - show?: boolean; - transition?: boolean; - transitionDuration?: number; + isShowing?: boolean; }; interface LoadingDotsInnerProps { className?: string; - show?: boolean; + isShowing?: boolean; type?: 'typing'|'bricks'; message?: string; - transition?: boolean; - transitionDuration?: number; }; export const LoadingDotsTyping = (props: LoadingDotsProps)=>{ @@ -32,54 +29,34 @@ export const LoadingDotsBricks = (props: LoadingDotsProps)=>{ export function LoadingDots({ className, - show=true, - transition = false, + isShowing=true, type = 'typing', message, - transitionDuration = 1000, }: LoadingDotsInnerProps){ - const [state, setState] = useState<'loading'|'loaded'|'completed'>('loading'); - const transitionClasses = - (transition ? `transition-opacity duration-${transitionDuration} `: "") - + (state === 'loading' ? 'opacity-100' : 'opacity-0'); + const classNames = twMerge("w-full h-full flex flex-col justify-center items-center bg-ui-background gap-6", className); - const classNames = twMerge("w-full h-full flex flex-col justify-center items-center bg-ui-background gap-6",transitionClasses, className); - useEffect(()=>{ - if(!show){ - if(transition){ - setState((curr)=>{ - if (curr === 'loading') return 'loaded' - else return curr; - }); - setTimeout(()=>setState('completed'), 2000); - } else { - setState('completed'); + return( + + { type==='typing' && +
} - }else{ - setState((curr) => { - if (curr!=='loading') return 'loading'; - else return curr; - }); - } - }, [show, transition]); - - if(state!== 'completed'){ - return( -
- { type==='typing' && -
- } - { type==='bricks' && -
- } - { - message && -

{message}

- } -
- ); - }else{ - return null; - } + { type==='bricks' && +
+ } + { + message && +

{message}

+ } +
+ ); }; diff --git a/app/pages/PageEnigma/PageEnigmaComponent.tsx b/app/pages/PageEnigma/PageEnigmaComponent.tsx index 702a51d6d1..58389e8920 100644 --- a/app/pages/PageEnigma/PageEnigmaComponent.tsx +++ b/app/pages/PageEnigma/PageEnigmaComponent.tsx @@ -66,10 +66,9 @@ export const PageEnigmaComponent = () => { }
diff --git a/app/pages/PageEnigma/comps/PreviewEngineCamera/index.tsx b/app/pages/PageEnigma/comps/PreviewEngineCamera/index.tsx index 324a2bcad9..8630ed50d9 100644 --- a/app/pages/PageEnigma/comps/PreviewEngineCamera/index.tsx +++ b/app/pages/PageEnigma/comps/PreviewEngineCamera/index.tsx @@ -29,7 +29,7 @@ export const PreviewEngineCamera = ()=>{ src="/resources/uiAssets/video_player_placeholder.gif" />
- +
diff --git a/app/pages/PageEnigma/reducer/index.tsx b/app/pages/PageEnigma/reducer/index.tsx index e44636d058..48da7e99b6 100644 --- a/app/pages/PageEnigma/reducer/index.tsx +++ b/app/pages/PageEnigma/reducer/index.tsx @@ -5,7 +5,7 @@ const initialState:State = { timelineHeight: 260, viewMode: VIEW_MODES.EDITOR, showEditorLoader: { - isShow:true, + isShowing:true, message: 'loading Editor Engine 🦊' } } diff --git a/app/pages/PageEnigma/reducer/types.tsx b/app/pages/PageEnigma/reducer/types.tsx index a9d259ac08..e40e32c2e3 100644 --- a/app/pages/PageEnigma/reducer/types.tsx +++ b/app/pages/PageEnigma/reducer/types.tsx @@ -9,7 +9,7 @@ export type State = { viewMode: ViewModes; timelineHeight: number; showEditorLoader: { - isShow:boolean + isShowing:boolean; message:string|undefined; }; }; diff --git a/app/root.tsx b/app/root.tsx index a62b912903..f22de825a3 100644 --- a/app/root.tsx +++ b/app/root.tsx @@ -1,4 +1,5 @@ import { useState, useEffect } from "react"; +import { Transition } from "@headlessui/react"; import { LinksFunction } from "@remix-run/deno"; import { Links, @@ -47,13 +48,11 @@ export const links: LinksFunction = () => [ export default function App() { const [topBarInnerComponent, setTopBarInnerComponent] = useState(null); - const [isLoaded, setIsLoaded] = useState<'loading'|'loaded'|'completed'>('loading'); + const [showLoader, setShowLoader] = useState(true); useEffect(()=>{ - setIsLoaded('loaded'); - setTimeout(()=>setIsLoaded('completed'), 2000); + setTimeout(()=>setShowLoader(false), 2500); },[]); - return ( @@ -63,15 +62,7 @@ export default function App() { - {isLoaded !== 'completed' && - - } + - -
+ + ); }; \ No newline at end of file diff --git a/app/routes/ComponentLibrary.tsx b/app/routes/ComponentLibrary.tsx index acc2188c52..6024c6ec4a 100644 --- a/app/routes/ComponentLibrary.tsx +++ b/app/routes/ComponentLibrary.tsx @@ -1,4 +1,4 @@ -import { useState, useEffect } from "react"; +import { useCallback, useEffect, useRef, useState } from "react"; import { Button, ButtonLink, @@ -11,20 +11,28 @@ import { export default function ComponentLibrary () { const [progress, setProgress] = useState(0); + const loopRef = useRef(null); + + const pushProgressBar: ()=>void = useCallback(()=>{ + loopRef.current = setInterval(function timer(){ + setProgress((curr)=>{ + if (curr < 100){ + return curr+10; + }else{ + if(loopRef.current) + clearInterval(loopRef.current); + return curr; + } + })} + , 3000); + }, []); useEffect(()=>{ - if(progress === 0){ - const loop = setInterval(function timer(){ - setProgress((curr)=>{ - if (curr < 100){ - return curr+10; - }else{ - clearTimeout(loop); - return curr; - } - })} - , 3000); + pushProgressBar(); + return ()=>{ + if(loopRef.current) + clearInterval(loopRef.current) } - }, [progress]); + },[progress]); return(
@@ -57,14 +65,31 @@ export default function ComponentLibrary () {

Loading Bar

-
- - +
+ +
+ +
From d63092b8e896ccfe3c59f92ae481beac27e15477 Mon Sep 17 00:00:00 2001 From: wil Date: Thu, 28 Mar 2024 10:50:02 -0400 Subject: [PATCH 04/17] update all to use new side panel --- app/pages/PageCube/PageCube.tsx | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/app/pages/PageCube/PageCube.tsx b/app/pages/PageCube/PageCube.tsx index 54faf66a60..f6d2062e5a 100644 --- a/app/pages/PageCube/PageCube.tsx +++ b/app/pages/PageCube/PageCube.tsx @@ -1,4 +1,4 @@ -import { useCallback, useContext, useEffect, useRef, useState } from "react"; +import { useCallback, useEffect, useRef, useState } from "react"; import { faChevronLeft } from "@fortawesome/pro-solid-svg-icons"; @@ -6,7 +6,7 @@ import { Button } from "~/components/Button"; import { ButtonLink } from "~/components/ButtonLink"; import { TopBarHelmet } from "~/modules/TopBarHelmet"; -import { SidePanel } from "~/modules/SidePanelOld"; +import { SidePanel } from "~/modules/SidePanel"; import { SceneWithCube } from "./SceneWithCube"; export const PageCube = () => { @@ -64,7 +64,7 @@ export const PageCube = () => {

Ration X: {rotationX ? rotationX : ""}

Ration Y: {rotationY ? rotationY : ""}

- +

Side Panel Context

From 72f5dfc2d305a561f611867ea986db9b99c619b0 Mon Sep 17 00:00:00 2001 From: wil Date: Thu, 28 Mar 2024 11:29:11 -0400 Subject: [PATCH 05/17] element need top to have position fixed instead of absolute --- app/pages/PageEnigma/comps/SidePanelTabs/ClipElement.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/pages/PageEnigma/comps/SidePanelTabs/ClipElement.tsx b/app/pages/PageEnigma/comps/SidePanelTabs/ClipElement.tsx index c8f6e6fba5..f924827677 100644 --- a/app/pages/PageEnigma/comps/SidePanelTabs/ClipElement.tsx +++ b/app/pages/PageEnigma/comps/SidePanelTabs/ClipElement.tsx @@ -96,7 +96,7 @@ export const ClipElement = ({ clip, type }: Props) => {
Date: Thu, 28 Mar 2024 11:38:06 -0400 Subject: [PATCH 06/17] unfixed sidebar scrolling --- app/modules/Tabs/Tabs.tsx | 2 +- app/pages/PageEnigma/comps/SidePanelTabs/ClipElement.tsx | 2 +- app/pages/PageEnigma/comps/SidePanelTabs/TabStylization.tsx | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/app/modules/Tabs/Tabs.tsx b/app/modules/Tabs/Tabs.tsx index b2ddd3e65b..9b32021140 100644 --- a/app/modules/Tabs/Tabs.tsx +++ b/app/modules/Tabs/Tabs.tsx @@ -31,7 +31,7 @@ export const Tabs = ({ tabs: tabProps }: { tabs: TabType[] }) => { ))} - + {tabs.map((tab, idx) => ( {tab.children} diff --git a/app/pages/PageEnigma/comps/SidePanelTabs/ClipElement.tsx b/app/pages/PageEnigma/comps/SidePanelTabs/ClipElement.tsx index f924827677..c8f6e6fba5 100644 --- a/app/pages/PageEnigma/comps/SidePanelTabs/ClipElement.tsx +++ b/app/pages/PageEnigma/comps/SidePanelTabs/ClipElement.tsx @@ -96,7 +96,7 @@ export const ClipElement = ({ clip, type }: Props) => {
{ } } return( -
+

Select Base Stylizer

Date: Thu, 28 Mar 2024 13:36:15 -0400 Subject: [PATCH 07/17] loading bar in editor, with dispatch functions, and other housekeeping things --- app/components/LoadingBar.tsx | 42 ++++++++++++---- app/pages/PageEnigma/PageEnigmaComponent.tsx | 25 +++++++--- .../ControlsTopButtons/ControlsTopButtons.tsx | 50 ++++++++++++++++--- .../comps/SidePanelTabs/TabStylization.tsx | 12 ++--- .../PageEnigma/contexts/AppUiContext.tsx | 9 ++-- app/pages/PageEnigma/js/editor.ts | 15 +++--- app/pages/PageEnigma/reducer/index.tsx | 18 ------- .../reducers/appUiReducer/index.tsx | 16 ++++++ .../appUiReducer}/reducer.tsx | 24 +++++++-- .../appUiReducer}/types.tsx | 23 ++++++++- .../reducers/appUiReducer/values.tsx | 14 ++++++ app/pages/PageEnigma/reducers/index.tsx | 20 ++++++++ tailwind.config.ts | 15 ++++++ 13 files changed, 218 insertions(+), 65 deletions(-) delete mode 100644 app/pages/PageEnigma/reducer/index.tsx create mode 100644 app/pages/PageEnigma/reducers/appUiReducer/index.tsx rename app/pages/PageEnigma/{reducer => reducers/appUiReducer}/reducer.tsx (60%) rename app/pages/PageEnigma/{reducer => reducers/appUiReducer}/types.tsx (62%) create mode 100644 app/pages/PageEnigma/reducers/appUiReducer/values.tsx create mode 100644 app/pages/PageEnigma/reducers/index.tsx diff --git a/app/components/LoadingBar.tsx b/app/components/LoadingBar.tsx index 7fb2e0eb77..2d2ab8177e 100644 --- a/app/components/LoadingBar.tsx +++ b/app/components/LoadingBar.tsx @@ -4,22 +4,30 @@ import { twMerge } from 'tailwind-merge'; interface LoadingBarProps{ + id?: string; + wrapperClassName?:string; + innerWrapperClassName?: string; + progressBackgroundClassName?: string; + progressClassName?: string; label?: string; progress?: number; isShowing?: boolean; variant?: string; message?: string; - wrapperClassName?: string; useFakeTimer?: number; } export const LoadingBar = ({ + wrapperClassName : propsWrapperClassName, + innerWrapperClassName: propsInnerWrapperClassName, + progressBackgroundClassName: propsProgressBackgroundClassName, + progressClassName : propsProgressClassName, label, progress: propsProgress = 0, isShowing = true, variant = 'primary', message, - wrapperClassName : propsWrapperClassName, - useFakeTimer + useFakeTimer, + ...rest }: LoadingBarProps) => { const [progress, setProgress] = useState(propsProgress); @@ -79,12 +87,21 @@ export const LoadingBar = ({ } const wrapperClassName = twMerge( - "w-full h-full flex flex-col justify-center items-center bg-ui-background p-4 gap-4", + "w-full h-full relative bg-ui-background", propsWrapperClassName, ) + const innerWrapperClassName = twMerge( + "w-full h-full p-4 gap-4 m-auto flex flex-col justify-center items-center", + propsInnerWrapperClassName, + ); + const progressBackgroundClassName = twMerge( + "w-full bg-gray-500 rounded-full h-2.5", + propsProgressBackgroundClassName + ); const progressClassName = twMerge( "h-2.5 rounded-full transition-all duration-1000", getVariantClassNames(variant), + propsProgressClassName ); return ( @@ -97,15 +114,18 @@ export const LoadingBar = ({ leave="transition-opacity duration-1000" leaveFrom="opacity-100" leaveTo="opacity-0" + {...rest} > - {label && } -
-
+
+ {label && } +
+
+
+ {message &&

{message}

}
- {message &&

{message}

} ); } \ No newline at end of file diff --git a/app/pages/PageEnigma/PageEnigmaComponent.tsx b/app/pages/PageEnigma/PageEnigmaComponent.tsx index 58389e8920..bdfbc8feb3 100644 --- a/app/pages/PageEnigma/PageEnigmaComponent.tsx +++ b/app/pages/PageEnigma/PageEnigmaComponent.tsx @@ -1,8 +1,8 @@ -import { useEffect, useReducer } from "react"; +import { useReducer } from "react"; import { faSparkles } from "@fortawesome/pro-solid-svg-icons"; -import { Button, LoadingDots } from "~/components"; +import { Button, LoadingBar, LoadingDots } from "~/components"; import { TopBarHelmet } from "~/modules/TopBarHelmet/TopBarHelmet"; import { SidePanel } from "~/modules/SidePanel"; import { Controls3D } from "./comps/Controls3D"; @@ -14,12 +14,11 @@ import { SidePanelTabs } from "./comps/SidePanelTabs"; import { EngineProvider } from "./contexts/EngineProvider"; import { AppUIProvider } from "./contexts/AppUiContext"; -import { reducer, initialState, ACTION_TYPES } from "./reducer"; -import { VIEW_MODES } from "./reducer/types"; +import { appUiReducer, appUiInitialStateValues, APPUI_ACTION_TYPES, APPUI_VIEW_MODES } from "./reducers"; import { ViewSideBySide } from "./comps/ViewSideBySide"; export const PageEnigmaComponent = () => { - const [appUiState, dispatchAppUiState] = useReducer(reducer, initialState); + const [appUiState, dispatchAppUiState] = useReducer(appUiReducer, appUiInitialStateValues); return ( @@ -39,7 +38,7 @@ export const PageEnigmaComponent = () => { // style={{ height: `calc(100% - 260px` }} >
-
+
{
{ - appUiState.viewMode === VIEW_MODES.SIDE_BY_SIDE && + appUiState.viewMode === APPUI_VIEW_MODES.SIDE_BY_SIDE && } +
{/* Side panel */} diff --git a/app/pages/PageEnigma/comps/ControlsTopButtons/ControlsTopButtons.tsx b/app/pages/PageEnigma/comps/ControlsTopButtons/ControlsTopButtons.tsx index 9329cdb68f..315c5981b6 100644 --- a/app/pages/PageEnigma/comps/ControlsTopButtons/ControlsTopButtons.tsx +++ b/app/pages/PageEnigma/comps/ControlsTopButtons/ControlsTopButtons.tsx @@ -1,10 +1,13 @@ import { useContext, useState } from "react"; -import { Button, H4, Input } from "~/components"; +import { Button, Input } from "~/components"; import { ButtonDialogue } from "~/modules/ButtonDialogue"; +import { AppUiContext } from "../../contexts/AppUiContext"; import { EngineContext } from "../../contexts/EngineContext"; +import { APPUI_ACTION_TYPES } from "../../reducers"; export const ControlsTopButtons = () => { const editorEngine = useContext(EngineContext); + const [ appUiState, dispatchAppUiState ] = useContext(AppUiContext); const [sceneName, setSceneName] = useState(""); const [sceneToken, setSceneToken] = useState(""); @@ -18,13 +21,33 @@ export const ControlsTopButtons = () => { editorEngine?.loadScene(sceneToken); }; + const handleButtonPlayBack = () => { + editorEngine?.start_playback(); + }; + + const handleButtonTest = () => { + if(appUiState?.showEditorLoadingBar.isShowing){ + dispatchAppUiState({ + type: APPUI_ACTION_TYPES.HIDE_EDITOR_LOADINGBAR, + }); + }else{ + dispatchAppUiState({ + type: APPUI_ACTION_TYPES.SHOW_EDITOR_LOADINGBAR, + payload:{ + showEditorLoadingBar: { + message: 'display of LoadingBar triggered by Test Button' + } + } + + }); + } + }; + + const handleButtonCameraView = () => { editorEngine?.switchCameraView(); }; - const handleButtonPlayBack = () => { - editorEngine?.start_playback(); - }; const handleButtonLoad = () => { editorEngine?.renderVideo(); }; @@ -35,6 +58,13 @@ export const ControlsTopButtons = () => { editorEngine?.start_playback(); }; + // const handleButtonCameraView = () => { + // editorEngine?.change_camera_view(); + // }; + + // const handleButtonLoad = () => {}; + // const handleButtonRender = () => {}; + return (
@@ -94,9 +124,15 @@ export const ControlsTopButtons = () => {
- - - + {/* + */} +
); diff --git a/app/pages/PageEnigma/comps/SidePanelTabs/TabStylization.tsx b/app/pages/PageEnigma/comps/SidePanelTabs/TabStylization.tsx index 64d013c105..85d1fc5dea 100644 --- a/app/pages/PageEnigma/comps/SidePanelTabs/TabStylization.tsx +++ b/app/pages/PageEnigma/comps/SidePanelTabs/TabStylization.tsx @@ -8,8 +8,8 @@ import { } from "~/components" import { AppUiContext } from '../../contexts/AppUiContext'; -import { ACTION_TYPES } from '../../reducer'; -import { VIEW_MODES } from '../../reducer/types'; +import { APPUI_ACTION_TYPES } from '../../reducers'; +import { APPUI_VIEW_MODES } from '../../reducers'; export const TabStylization = ()=>{ const [appUiState, dispatchAppUiState] = useContext(AppUiContext); @@ -23,10 +23,10 @@ export const TabStylization = ()=>{ const handleChangeViewMode = ()=>{ if(dispatchAppUiState!==null){ dispatchAppUiState({ - type: ACTION_TYPES.ON_CHANGE_VIEW_MODE, + type: APPUI_ACTION_TYPES.ON_CHANGE_VIEW_MODE, payload: { - viewMode: appUiState?.viewMode === VIEW_MODES.SIDE_BY_SIDE - ? VIEW_MODES.EDITOR : VIEW_MODES.SIDE_BY_SIDE, + viewMode: appUiState?.viewMode === APPUI_VIEW_MODES.SIDE_BY_SIDE + ? APPUI_VIEW_MODES.EDITOR : APPUI_VIEW_MODES.SIDE_BY_SIDE, } }) } @@ -77,7 +77,7 @@ export const TabStylization = ()=>{
diff --git a/app/pages/PageEnigma/contexts/AppUiContext.tsx b/app/pages/PageEnigma/contexts/AppUiContext.tsx index 0544b3e844..f46d63e884 100644 --- a/app/pages/PageEnigma/contexts/AppUiContext.tsx +++ b/app/pages/PageEnigma/contexts/AppUiContext.tsx @@ -1,13 +1,16 @@ import { createContext, Dispatch, ReactNode } from "react"; -import { State, Action } from "../reducer"; +import { AppUiState, AppUiAction } from "../reducers"; -export const AppUiContext = createContext<[State|null, Dispatch|null]>([null,null]); +export const AppUiContext = createContext<[ + AppUiState | null, + Dispatch +]>([ null ,()=>{}]); export const AppUIProvider = ({ value, children, }:{ - value:[State, Dispatch], + value:[AppUiState, Dispatch], children: ReactNode })=>{ return ( diff --git a/app/pages/PageEnigma/js/editor.ts b/app/pages/PageEnigma/js/editor.ts index ba593cdbae..a669ea2c00 100644 --- a/app/pages/PageEnigma/js/editor.ts +++ b/app/pages/PageEnigma/js/editor.ts @@ -19,8 +19,8 @@ import { TimeLine, TimelineDataState } from "./timeline.js"; import { ClipUI } from "../datastructures/clips/clip_offset.js"; import { LipSyncEngine } from "./lip_sync_engine.js"; import { AnimationEngine } from "./animation_engine.js"; -import { ACTION_TYPES } from "../reducer"; import { PointerLockControls } from 'three/addons/controls/PointerLockControls.js'; +import { APPUI_ACTION_TYPES } from "../reducers"; class EditorState { // { @@ -92,7 +92,6 @@ class Editor { can_initialize: boolean; dispatchAppUiState: any; // todo figure out the type - camera_person_mode: boolean; render_width: number; render_height: number; @@ -195,7 +194,7 @@ class Editor { // Show Loader this.dispatchAppUiState({ - type: ACTION_TYPES.SHOW_EDITOR_LOADER + type: APPUI_ACTION_TYPES.SHOW_EDITOR_LOADER }); if (this.can_initialize == false) { @@ -278,7 +277,7 @@ class Editor { // hide loader this.dispatchAppUiState({ - type: ACTION_TYPES.HIDE_EDITOR_LOADER + type: APPUI_ACTION_TYPES.HIDE_EDITOR_LOADER }); } @@ -286,7 +285,7 @@ class Editor { // Token comes in from the front end to load the scene from the site. public async loadScene(scene_media_token: string) { this.dispatchAppUiState({ - type: ACTION_TYPES.SHOW_EDITOR_LOADER + type: APPUI_ACTION_TYPES.SHOW_EDITOR_LOADER }); if (scene_media_token != null) { @@ -325,7 +324,7 @@ class Editor { }); this.dispatchAppUiState({ - type: ACTION_TYPES.HIDE_EDITOR_LOADER + type: APPUI_ACTION_TYPES.HIDE_EDITOR_LOADER }); this.cam_obj = this.activeScene.get_object_by_name("::CAM::"); @@ -335,7 +334,7 @@ class Editor { // remove controls when saving scene. this.removeTransformControls(); this.dispatchAppUiState({ - type: ACTION_TYPES.SHOW_EDITOR_LOADER + type: APPUI_ACTION_TYPES.SHOW_EDITOR_LOADER }); console.log(`saveScene => SceneMediaToken:${this.current_scene_media_token} SceneGLBMediaToken:${this.current_scene_glb_media_token}`); @@ -359,7 +358,7 @@ class Editor { } this.dispatchAppUiState({ - type: ACTION_TYPES.HIDE_EDITOR_LOADER + type: APPUI_ACTION_TYPES.HIDE_EDITOR_LOADER }); } diff --git a/app/pages/PageEnigma/reducer/index.tsx b/app/pages/PageEnigma/reducer/index.tsx deleted file mode 100644 index 48da7e99b6..0000000000 --- a/app/pages/PageEnigma/reducer/index.tsx +++ /dev/null @@ -1,18 +0,0 @@ -import {State, Action, ACTION_TYPES, VIEW_MODES} from './types'; -import {reducer} from './reducer'; - -const initialState:State = { - timelineHeight: 260, - viewMode: VIEW_MODES.EDITOR, - showEditorLoader: { - isShowing:true, - message: 'loading Editor Engine 🦊' - } -} - -export type {State, Action}; -export { - ACTION_TYPES, - initialState, - reducer, -} \ No newline at end of file diff --git a/app/pages/PageEnigma/reducers/appUiReducer/index.tsx b/app/pages/PageEnigma/reducers/appUiReducer/index.tsx new file mode 100644 index 0000000000..3c94ae01c3 --- /dev/null +++ b/app/pages/PageEnigma/reducers/appUiReducer/index.tsx @@ -0,0 +1,16 @@ +import {State, Action, ACTION_TYPES, VIEW_MODES} from './types'; +import {reducer} from './reducer'; + +import { initialStateValues } from './values'; + +export type { + State as AppUiState, + Action as AppUiAction, +}; + +export { + VIEW_MODES as APPUI_VIEW_MODES, + ACTION_TYPES as APPUI_ACTION_TYPES, + initialStateValues as appUiInitialStateValues, + reducer as appUiReducer, +} \ No newline at end of file diff --git a/app/pages/PageEnigma/reducer/reducer.tsx b/app/pages/PageEnigma/reducers/appUiReducer/reducer.tsx similarity index 60% rename from app/pages/PageEnigma/reducer/reducer.tsx rename to app/pages/PageEnigma/reducers/appUiReducer/reducer.tsx index 7062c2b4b5..63881a7a4b 100644 --- a/app/pages/PageEnigma/reducer/reducer.tsx +++ b/app/pages/PageEnigma/reducers/appUiReducer/reducer.tsx @@ -6,8 +6,8 @@ export function reducer(state: State, action: Action): State { return{ ...state, showEditorLoader: { - isShow: true, - message: action.payload?.showEditorLoader.message || undefined, + isShowing: true, + message: action.payload?.showEditorLoader.message, }, } } @@ -15,11 +15,29 @@ export function reducer(state: State, action: Action): State { return{ ...state, showEditorLoader: { - isShow: false, + isShowing: false, message: state.showEditorLoader.message }, } } + case ACTION_TYPES.SHOW_EDITOR_LOADINGBAR:{ + return{ + ...state, + showEditorLoadingBar: { + ...action.payload?.showEditorLoadingBar, + isShowing: true, + }, + } + } + case ACTION_TYPES.HIDE_EDITOR_LOADINGBAR:{ + return{ + ...state, + showEditorLoadingBar: { + ...state.showEditorLoadingBar, + isShowing: false, + }, + } + } case ACTION_TYPES.ON_TIMELINE_RESIZE:{ return{ ...state, diff --git a/app/pages/PageEnigma/reducer/types.tsx b/app/pages/PageEnigma/reducers/appUiReducer/types.tsx similarity index 62% rename from app/pages/PageEnigma/reducer/types.tsx rename to app/pages/PageEnigma/reducers/appUiReducer/types.tsx index e40e32c2e3..8b658fcbb4 100644 --- a/app/pages/PageEnigma/reducer/types.tsx +++ b/app/pages/PageEnigma/reducers/appUiReducer/types.tsx @@ -10,8 +10,15 @@ export type State = { timelineHeight: number; showEditorLoader: { isShowing:boolean; - message:string|undefined; + message?:string; }; + showEditorLoadingBar:{ + isShowing: boolean; + label?: string; + message?: string; + progress?: number; + useFakeTimer?: number; + } }; @@ -20,6 +27,8 @@ export enum ACTION_TYPES { ON_CHANGE_VIEW_MODE = "on_change_view_mode", SHOW_EDITOR_LOADER = "show_editor_loader", HIDE_EDITOR_LOADER = "hide_editor_loader", + SHOW_EDITOR_LOADINGBAR = "show_editor_loadingbar", + HIDE_EDITOR_LOADINGBAR = "hide_editor_loadingbar", }; export type Action = @@ -32,6 +41,18 @@ export type Action = } } } + | {type: ACTION_TYPES.HIDE_EDITOR_LOADINGBAR,} + | { + type: ACTION_TYPES.SHOW_EDITOR_LOADINGBAR, + payload?:{ + showEditorLoadingBar: { + label?: string; + message?: string; + progress?: number; + useFake?: boolean; + } + } + } | { type: ACTION_TYPES.ON_TIMELINE_RESIZE, payload: { diff --git a/app/pages/PageEnigma/reducers/appUiReducer/values.tsx b/app/pages/PageEnigma/reducers/appUiReducer/values.tsx new file mode 100644 index 0000000000..25aa12acab --- /dev/null +++ b/app/pages/PageEnigma/reducers/appUiReducer/values.tsx @@ -0,0 +1,14 @@ +import {State, VIEW_MODES} from './types'; + +export const initialStateValues : State = { + timelineHeight: 260, + viewMode: VIEW_MODES.EDITOR, + showEditorLoader: { + isShowing:true, + message: 'loading Editor Engine 🦊' + }, + showEditorLoadingBar: { + isShowing:false, + progress:0, + } +} \ No newline at end of file diff --git a/app/pages/PageEnigma/reducers/index.tsx b/app/pages/PageEnigma/reducers/index.tsx new file mode 100644 index 0000000000..c670c51556 --- /dev/null +++ b/app/pages/PageEnigma/reducers/index.tsx @@ -0,0 +1,20 @@ +import { + AppUiState, + AppUiAction, + APPUI_ACTION_TYPES, + APPUI_VIEW_MODES, + appUiInitialStateValues, + appUiReducer, +} from './appUiReducer'; + +export type { + AppUiState, + AppUiAction +}; + +export { + APPUI_VIEW_MODES, + APPUI_ACTION_TYPES, + appUiInitialStateValues, + appUiReducer, +} \ No newline at end of file diff --git a/tailwind.config.ts b/tailwind.config.ts index 7eb8a62827..482b42e119 100644 --- a/tailwind.config.ts +++ b/tailwind.config.ts @@ -47,6 +47,21 @@ export default { "900": "#464762", "950": "#39394c", }, + "brand-tertiary": { + //Aquamarine Blue + DEFAULT: "#1cb6be", //=300 + '50': '#eefdfc', + '100': '#d4f9f8', + '200': '#aef3f3', + '300': '#62e4e6', + '400': '#38d3d8', + '500': '#1cb6be', + '600': '#1a94a0', + '700': '#1c7682', + '800': '#1f616b', + '900': '#1e505b', + '950': '#0e353e', + }, danger: { //copper rust DEFAULT: "#8f4951", //=700 From 150e61ea10cab36efce66dbde8bec91e3d821426 Mon Sep 17 00:00:00 2001 From: wil Date: Thu, 28 Mar 2024 13:59:43 -0400 Subject: [PATCH 08/17] loading bar logic and example --- app/pages/PageEnigma/PageEnigmaComponent.tsx | 1 - .../ControlsTopButtons/ControlsTopButtons.tsx | 27 +++++++++++++++++-- .../reducers/appUiReducer/reducer.tsx | 9 +++++++ .../reducers/appUiReducer/types.tsx | 13 ++++++++- 4 files changed, 46 insertions(+), 4 deletions(-) diff --git a/app/pages/PageEnigma/PageEnigmaComponent.tsx b/app/pages/PageEnigma/PageEnigmaComponent.tsx index bdfbc8feb3..8465f1d683 100644 --- a/app/pages/PageEnigma/PageEnigmaComponent.tsx +++ b/app/pages/PageEnigma/PageEnigmaComponent.tsx @@ -77,7 +77,6 @@ export const PageEnigmaComponent = () => { message={appUiState.showEditorLoadingBar.message} label={appUiState.showEditorLoadingBar.label} progress={appUiState.showEditorLoadingBar.progress} - useFakeTimer={30000} />
diff --git a/app/pages/PageEnigma/comps/ControlsTopButtons/ControlsTopButtons.tsx b/app/pages/PageEnigma/comps/ControlsTopButtons/ControlsTopButtons.tsx index 315c5981b6..76949ab418 100644 --- a/app/pages/PageEnigma/comps/ControlsTopButtons/ControlsTopButtons.tsx +++ b/app/pages/PageEnigma/comps/ControlsTopButtons/ControlsTopButtons.tsx @@ -27,15 +27,38 @@ export const ControlsTopButtons = () => { const handleButtonTest = () => { if(appUiState?.showEditorLoadingBar.isShowing){ + //TO GO TO A HUNDRED AND DISAPPER dispatchAppUiState({ - type: APPUI_ACTION_TYPES.HIDE_EDITOR_LOADINGBAR, + type: APPUI_ACTION_TYPES.UPDATE_EDITOR_LOADINGBAR, + payload:{ + showEditorLoadingBar: { + progress: 100, + } + } }); + setTimeout(() => { + dispatchAppUiState({ + type: APPUI_ACTION_TYPES.HIDE_EDITOR_LOADINGBAR, + }); + }, 1000); + //END :TO GO TO A HUNDRED AND DISAPPER + + //EAMPLE OF CHANING LOADING MESSAGE + // dispatchAppUiState({ + // type: APPUI_ACTION_TYPES.UPDATE_EDITOR_LOADINGBAR, + // payload:{ + // showEditorLoadingBar: { + // message: "new message", + // } + // } + // }); }else{ dispatchAppUiState({ type: APPUI_ACTION_TYPES.SHOW_EDITOR_LOADINGBAR, payload:{ showEditorLoadingBar: { - message: 'display of LoadingBar triggered by Test Button' + message: 'display of LoadingBar triggered by Test Button', + progress: 10, } } diff --git a/app/pages/PageEnigma/reducers/appUiReducer/reducer.tsx b/app/pages/PageEnigma/reducers/appUiReducer/reducer.tsx index 63881a7a4b..c632ebfef2 100644 --- a/app/pages/PageEnigma/reducers/appUiReducer/reducer.tsx +++ b/app/pages/PageEnigma/reducers/appUiReducer/reducer.tsx @@ -29,6 +29,15 @@ export function reducer(state: State, action: Action): State { }, } } + case ACTION_TYPES.UPDATE_EDITOR_LOADINGBAR:{ + return{ + ...state, + showEditorLoadingBar: { + ...state.showEditorLoadingBar, + ...action.payload?.showEditorLoadingBar, + }, + } + } case ACTION_TYPES.HIDE_EDITOR_LOADINGBAR:{ return{ ...state, diff --git a/app/pages/PageEnigma/reducers/appUiReducer/types.tsx b/app/pages/PageEnigma/reducers/appUiReducer/types.tsx index 8b658fcbb4..5e07b24b3f 100644 --- a/app/pages/PageEnigma/reducers/appUiReducer/types.tsx +++ b/app/pages/PageEnigma/reducers/appUiReducer/types.tsx @@ -28,6 +28,7 @@ export enum ACTION_TYPES { SHOW_EDITOR_LOADER = "show_editor_loader", HIDE_EDITOR_LOADER = "hide_editor_loader", SHOW_EDITOR_LOADINGBAR = "show_editor_loadingbar", + UPDATE_EDITOR_LOADINGBAR = "update_editor_loadingbar", HIDE_EDITOR_LOADINGBAR = "hide_editor_loadingbar", }; @@ -49,7 +50,17 @@ export type Action = label?: string; message?: string; progress?: number; - useFake?: boolean; + useFakeTimer?: number; + } + } + } + | { + type: ACTION_TYPES.UPDATE_EDITOR_LOADINGBAR, + payload:{ + showEditorLoadingBar: { + label?: string; + message?: string; + progress?: number; } } } From e7b8e1b2f41650401599f1ac1b9935b7190c6efb Mon Sep 17 00:00:00 2001 From: wil Date: Thu, 28 Mar 2024 14:05:02 -0400 Subject: [PATCH 09/17] update props --- app/pages/PageEnigma/comps/ViewSideBySide/index.tsx | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/app/pages/PageEnigma/comps/ViewSideBySide/index.tsx b/app/pages/PageEnigma/comps/ViewSideBySide/index.tsx index 788f31d297..bcad3ada4c 100644 --- a/app/pages/PageEnigma/comps/ViewSideBySide/index.tsx +++ b/app/pages/PageEnigma/comps/ViewSideBySide/index.tsx @@ -1,7 +1,4 @@ -import { - useEffect, - useState, -} from "react"; +import { useEffect, useState, } from "react"; import { LoadingDotsBricks } from "~/components"; @@ -42,7 +39,7 @@ export const ViewSideBySide = ()=>{
- +
) From d557c52e9921e64148df31b5e228759b799b12da Mon Sep 17 00:00:00 2001 From: Quicksticks-oss Date: Thu, 28 Mar 2024 15:29:45 -0400 Subject: [PATCH 10/17] added generate button in Helmet Innter --- app/pages/PageEnigma/PageEnigmaComponent.tsx | 15 +++--- .../ControlsTopButtons/ControlsTopButtons.tsx | 16 ++---- .../comps/ControlsVideo/ControlsVideo.tsx | 7 +++ app/pages/PageEnigma/comps/HelmetInnter.tsx | 17 ++++++ .../comps/PreviewEngineCamera/index.tsx | 2 +- app/pages/PageEnigma/js/editor.ts | 52 +++++++++---------- 6 files changed, 63 insertions(+), 46 deletions(-) create mode 100644 app/pages/PageEnigma/comps/HelmetInnter.tsx diff --git a/app/pages/PageEnigma/PageEnigmaComponent.tsx b/app/pages/PageEnigma/PageEnigmaComponent.tsx index 8465f1d683..08151954ac 100644 --- a/app/pages/PageEnigma/PageEnigmaComponent.tsx +++ b/app/pages/PageEnigma/PageEnigmaComponent.tsx @@ -11,6 +11,7 @@ import { ControlsVideo } from "./comps/ControlsVideo"; import { PreviewEngineCamera } from "./comps/PreviewEngineCamera"; import { Timeline } from "./comps/Timeline"; import { SidePanelTabs } from "./comps/SidePanelTabs"; +import { HelmetInner } from "./comps/HelmetInnter"; import { EngineProvider } from "./contexts/EngineProvider"; import { AppUIProvider } from "./contexts/AppUiContext"; @@ -19,23 +20,23 @@ import { ViewSideBySide } from "./comps/ViewSideBySide"; export const PageEnigmaComponent = () => { const [appUiState, dispatchAppUiState] = useReducer(appUiReducer, appUiInitialStateValues); - + return (
- - - - + + + +
{/* Engine section/side panel */}
@@ -79,7 +80,7 @@ export const PageEnigmaComponent = () => { progress={appUiState.showEditorLoadingBar.progress} />
- + {/* Side panel */} diff --git a/app/pages/PageEnigma/comps/ControlsTopButtons/ControlsTopButtons.tsx b/app/pages/PageEnigma/comps/ControlsTopButtons/ControlsTopButtons.tsx index 76949ab418..d42bc7f46d 100644 --- a/app/pages/PageEnigma/comps/ControlsTopButtons/ControlsTopButtons.tsx +++ b/app/pages/PageEnigma/comps/ControlsTopButtons/ControlsTopButtons.tsx @@ -21,10 +21,6 @@ export const ControlsTopButtons = () => { editorEngine?.loadScene(sceneToken); }; - const handleButtonPlayBack = () => { - editorEngine?.start_playback(); - }; - const handleButtonTest = () => { if(appUiState?.showEditorLoadingBar.isShowing){ //TO GO TO A HUNDRED AND DISAPPER @@ -72,13 +68,11 @@ export const ControlsTopButtons = () => { }; const handleButtonLoad = () => { - editorEngine?.renderVideo(); - }; - const handleButtonRender = () => { editorEngine?.take_timeline_cam_clip(); }; - const handleButtonPlay = () => { - editorEngine?.start_playback(); + + const handleButtonRender = () => { + editorEngine?.generateVideo(); }; // const handleButtonCameraView = () => { @@ -147,8 +141,8 @@ export const ControlsTopButtons = () => {
- {/* - */} + + + ) +} \ No newline at end of file diff --git a/app/pages/PageEnigma/comps/PreviewEngineCamera/index.tsx b/app/pages/PageEnigma/comps/PreviewEngineCamera/index.tsx index 8630ed50d9..fb8e695aee 100644 --- a/app/pages/PageEnigma/comps/PreviewEngineCamera/index.tsx +++ b/app/pages/PageEnigma/comps/PreviewEngineCamera/index.tsx @@ -8,7 +8,7 @@ export const PreviewEngineCamera = ()=>{ const [showLoader, setShowLoader] = useState(true); useEffect(()=>{ - setTimeout(()=>setShowLoader(false), 5000); + setTimeout(()=>setShowLoader(false), 500); },[]); return (
SceneMediaToken:${this.current_scene_media_token} SceneGLBMediaToken:${this.current_scene_glb_media_token}`); @@ -600,12 +600,6 @@ class Editor { //} } - renderVideo() { - this.rendering = true; - this.activeScene.render_mode(this.rendering); - console.log("Rendering..."); - } - togglePlay() { this.playback = !this.playback; this.playback_location = 0; @@ -683,19 +677,12 @@ class Editor { this.timeline.update(delta_time); - this.render_scene(); + this.renderScene(); if (this.capturer != null) { this.capturer.capture(this.renderer.domElement); } // Record scene. } - start_playback() { - this.timeline.isPlaying = true; - if(!this.camera_person_mode) { - this.switchCameraView(); - } - } - change_mode(type: any) { if (this.control == undefined) { return; @@ -762,17 +749,27 @@ class Editor { document.body.removeChild(downloadLink); } + generateVideo() { + console.log("Generating video..."); + this.startPlayback(); + this._initializeRecording(); + this.rendering = true; + this.activeScene.render_mode(this.rendering); + } + startPlayback() { - this.playback_location = 0; - this._initialize_recording(); + this.timeline.isPlaying = true; + if(!this.camera_person_mode) { + this.switchCameraView(); + } } // Initializes transform x y z changes. - _initialize_control() { + _initializeControl() { if (this.control == undefined) { return; } - this.control.addEventListener("change", this.render_scene.bind(this)); + this.control.addEventListener("change", this.renderScene.bind(this)); this.control.addEventListener("dragging-changed", (event: any) => { if (this.orbitControls == undefined) { return; @@ -786,17 +783,17 @@ class Editor { this.activeScene.scene.add(this.control); } - // Initializes CCapture for capturing the scene to send over to backend. - _initialize_recording() { + _initializeRecording() { this.frame_buffer = []; this.render_timer = 0; } // Render the scene to the camera. - render_scene() { - if (this.composer != null && !this.timeline.isPlaying) { + renderScene() { + if (this.composer != null && !this.rendering) { this.composer.render(); } else if (this.renderer && this.render_camera) { + this.renderer.setSize(this.render_width, this.render_height); this.renderer.render(this.activeScene.scene, this.render_camera); } else { console.error("Could not render to canvas no render or composer!"); @@ -807,10 +804,11 @@ class Editor { let imgData = this.renderer.domElement.toDataURL(); this.frame_buffer.push(imgData); this.render_timer += this.clock.getDelta(); - if (this.playback_location >= this.fps_number * 3) { + if (this.timeline.isPlaying == false) { this.stopPlayback(); this.playback_location = 0; this.rendering = false; + this.onWindowResize(); } } } From 821325289430bb7bd7145324ae5b5c1144595c70 Mon Sep 17 00:00:00 2001 From: wil Date: Thu, 28 Mar 2024 15:47:11 -0400 Subject: [PATCH 11/17] making the helmet inner an entire component --- app/pages/PageEnigma/PageEnigmaComponent.tsx | 127 +++++++++---------- app/pages/PageEnigma/comps/Helmet.tsx | 24 ++++ app/pages/PageEnigma/comps/HelmetInnter.tsx | 17 --- 3 files changed, 84 insertions(+), 84 deletions(-) create mode 100644 app/pages/PageEnigma/comps/Helmet.tsx delete mode 100644 app/pages/PageEnigma/comps/HelmetInnter.tsx diff --git a/app/pages/PageEnigma/PageEnigmaComponent.tsx b/app/pages/PageEnigma/PageEnigmaComponent.tsx index 08151954ac..308892683b 100644 --- a/app/pages/PageEnigma/PageEnigmaComponent.tsx +++ b/app/pages/PageEnigma/PageEnigmaComponent.tsx @@ -1,9 +1,6 @@ import { useReducer } from "react"; -import { faSparkles } from "@fortawesome/pro-solid-svg-icons"; - -import { Button, LoadingBar, LoadingDots } from "~/components"; -import { TopBarHelmet } from "~/modules/TopBarHelmet/TopBarHelmet"; +import { LoadingBar, LoadingDots } from "~/components"; import { SidePanel } from "~/modules/SidePanel"; import { Controls3D } from "./comps/Controls3D"; import { ControlsTopButtons } from "./comps/ControlsTopButtons"; @@ -11,7 +8,7 @@ import { ControlsVideo } from "./comps/ControlsVideo"; import { PreviewEngineCamera } from "./comps/PreviewEngineCamera"; import { Timeline } from "./comps/Timeline"; import { SidePanelTabs } from "./comps/SidePanelTabs"; -import { HelmetInner } from "./comps/HelmetInnter"; +import { Helmet } from "./comps/Helmet"; import { EngineProvider } from "./contexts/EngineProvider"; import { AppUIProvider } from "./contexts/AppUiContext"; @@ -23,75 +20,71 @@ export const PageEnigmaComponent = () => { return ( -
- - - - - + + + -
- {/* Engine section/side panel */} -
-
-
- +
+ {/* Engine section/side panel */} +
+
+
+ - {/* Top controls */} -
-
- - -
-
- - {/* Bottom controls */} -
- - + {/* Top controls */} +
+
+ +
- { - appUiState.viewMode === APPUI_VIEW_MODES.SIDE_BY_SIDE && - - } - - -
- {/* Side panel */} - - - + {/* Bottom controls */} +
+ + +
+
+ { + appUiState.viewMode === APPUI_VIEW_MODES.SIDE_BY_SIDE && + + } + +
- {/* Timeline */} - + {/* Side panel */} + + +
- - -
+ + {/* Timeline */} + +
+ + ); }; diff --git a/app/pages/PageEnigma/comps/Helmet.tsx b/app/pages/PageEnigma/comps/Helmet.tsx new file mode 100644 index 0000000000..a14e44a4de --- /dev/null +++ b/app/pages/PageEnigma/comps/Helmet.tsx @@ -0,0 +1,24 @@ +import { useContext, useEffect, useState } from "react"; +import { faSparkles } from "@fortawesome/pro-solid-svg-icons"; +import { TopBarHelmet } from "~/modules/TopBarHelmet/TopBarHelmet"; +import { Button } from "~/components"; +import { EngineContext } from "../contexts/EngineContext"; + +export const Helmet = () => { + const [helmetKey, setHelmetKey] = useState(Date.now()); + const engineContext = useContext(EngineContext); + + const handleGenerateVideo = () => { + engineContext?.generateVideo(); + }; + + useEffect(()=>{ + setHelmetKey(Date.now()); + },[engineContext]); + + return ( + + + + ); +} \ No newline at end of file diff --git a/app/pages/PageEnigma/comps/HelmetInnter.tsx b/app/pages/PageEnigma/comps/HelmetInnter.tsx deleted file mode 100644 index c7d389c4f3..0000000000 --- a/app/pages/PageEnigma/comps/HelmetInnter.tsx +++ /dev/null @@ -1,17 +0,0 @@ -import { useContext } from "react"; -import { faSparkles } from "@fortawesome/pro-solid-svg-icons"; -import { Button } from "~/components"; -import { EngineContext } from "../contexts/EngineContext"; - -export const HelmetInner = () => { - const engineContext = useContext(EngineContext); - - const handleGenerateVideo = () => { - console.log(engineContext) - engineContext?.generateVideo(); - } - - return ( - - ) -} \ No newline at end of file From ac55bdcf31768dda461e2c43c3d5ac1d6784854e Mon Sep 17 00:00:00 2001 From: Quicksticks-oss Date: Thu, 28 Mar 2024 15:50:02 -0400 Subject: [PATCH 12/17] added capture stuff --- app/pages/PageEnigma/js/editor.ts | 3 --- 1 file changed, 3 deletions(-) diff --git a/app/pages/PageEnigma/js/editor.ts b/app/pages/PageEnigma/js/editor.ts index c95dcceac6..ce3361db95 100644 --- a/app/pages/PageEnigma/js/editor.ts +++ b/app/pages/PageEnigma/js/editor.ts @@ -678,9 +678,6 @@ class Editor { this.timeline.update(delta_time); this.renderScene(); - if (this.capturer != null) { - this.capturer.capture(this.renderer.domElement); - } // Record scene. } change_mode(type: any) { From 05ba728530993a64ce878d3d88c70d29075ac4a4 Mon Sep 17 00:00:00 2001 From: Quicksticks-oss Date: Thu, 28 Mar 2024 17:13:45 -0400 Subject: [PATCH 13/17] completed lipsync audio crossover. --- app/pages/PageEnigma/js/api_manager.ts | 2 +- app/pages/PageEnigma/js/editor.ts | 64 ++++++++++++++++++++++++-- app/pages/PageEnigma/js/timeline.ts | 2 +- 3 files changed, 62 insertions(+), 6 deletions(-) diff --git a/app/pages/PageEnigma/js/api_manager.ts b/app/pages/PageEnigma/js/api_manager.ts index ab3fa0a2ff..b6a6c45425 100644 --- a/app/pages/PageEnigma/js/api_manager.ts +++ b/app/pages/PageEnigma/js/api_manager.ts @@ -133,7 +133,7 @@ class APIManager { * @param media_file_token * @returns */ - private async getMediaFile(media_file_token: string): Promise { + public async getMediaFile(media_file_token: string): Promise { let api_base_url = "https://api.fakeyou.com"; let url = `${api_base_url}/v1/media_files/file/${media_file_token}`; let response = await fetch(url); diff --git a/app/pages/PageEnigma/js/editor.ts b/app/pages/PageEnigma/js/editor.ts index ce3361db95..7644ef30cd 100644 --- a/app/pages/PageEnigma/js/editor.ts +++ b/app/pages/PageEnigma/js/editor.ts @@ -728,17 +728,73 @@ class Editor { "" + this.cap_fps, "-i", "image%d.png", - "output.mp4", + "0tmp.mp4", ); - let output = await ffmpeg.FS("readFile", "output.mp4"); + + let itteration = 0; + + for (const clip of this.timeline.timelineItems) { + if (clip.type == "lipsync") { + console.log(clip.media_id) + for (const [key, value] of Object.entries(this.lipsync_engine.clips)) { + if(clip.object_uuid == key && clip.media_id == value.media_id) { + await ffmpeg.FS('writeFile', itteration+"tmp.wav", await fetchFile(await this.api_manager.getMediaFile(value.media_id))); + let video_og = itteration+'tmp.mp4'; + let wav_name = itteration+'tmp.wav'; + let new_video = (itteration+1)+'tmp.mp4'; + let startFrame = clip.start_offset; + let endFrame = clip.ending_offset; + + const startTime = startFrame / this.cap_fps; + const endTime = endFrame / this.cap_fps; + let end = endTime-startTime; + + let audioSegment = "new_"+wav_name; + + await ffmpeg.run('-i', wav_name, '-ss', '0', '-to', ''+end, audioSegment); + await ffmpeg.run( + '-i', video_og, + '-itsoffset', `${startTime}`, + '-i', audioSegment, + '-c:v', 'copy', + '-c:a', 'aac', + '-strict', 'experimental', + new_video + ); + itteration += 1 + } + } + } + }; + + for (const [key, value] of Object.entries(this.lipsync_engine.clips)) { + console.log(key, value); + if (value.audio_data) { + //await ffmpeg.FS('writeFile', itteration+"tmp.wav", await fetchFile(await this.api_manager.getMediaFile(value.media_id))); + //let mp4_og = itteration+'tmp.mp4'; + //let wav_name = itteration+'tmp.wav'; + //let new_wav = (itteration+1)+'tmp.mp4'; + //let startFrame = 0; + //let endFrame = 60; + //let startTime = startFrame / this.cap_fps; + //let endTime = endFrame / this.cap_fps; + //await ffmpeg.run('-i', mp4_og, '-ss', startTime.toString(), '-i', wav_name, '-to', endTime.toString(), '-c:v', 'copy', '-c:a', 'aac', new_wav); + //itteration += 1 + } + } + + let output = await ffmpeg.FS("readFile", itteration+"tmp.mp4"); // Create a Blob from the output file for downloading const blob = new Blob([output.buffer], { type: "video/mp4" }); const url = URL.createObjectURL(blob); - await this.api_manager.uploadMedia(blob, "output.mp4"); + + //let data = await this.api_manager.uploadMedia(blob, "tmp.wav"); + //console.log(data); // Create a link to download the file + const downloadLink = document.createElement("a"); downloadLink.href = url; - downloadLink.download = "output.mp4"; + downloadLink.download = "tmp.mp4"; document.body.appendChild(downloadLink); downloadLink.click(); // Clean up diff --git a/app/pages/PageEnigma/js/timeline.ts b/app/pages/PageEnigma/js/timeline.ts index 208a7e20e9..28d260f348 100644 --- a/app/pages/PageEnigma/js/timeline.ts +++ b/app/pages/PageEnigma/js/timeline.ts @@ -72,7 +72,7 @@ export class TimeLine { scene: Scene) { this.timelineItems = [] - this.timeLineLimit = 60 * 10 // 10 seconds + this.timeLineLimit = 60 * 5 // 10 seconds this.isPlaying = false this.scrubberPosition = 0 // in frames into the tl From 33f7acb43ef7ca2139d616514ed9840ba869a759 Mon Sep 17 00:00:00 2001 From: Quicksticks-oss Date: Thu, 28 Mar 2024 17:19:24 -0400 Subject: [PATCH 14/17] base lipsync audio to video. --- app/pages/PageEnigma/js/editor.ts | 71 +++++++++++++++---------------- 1 file changed, 35 insertions(+), 36 deletions(-) diff --git a/app/pages/PageEnigma/js/editor.ts b/app/pages/PageEnigma/js/editor.ts index 7644ef30cd..52e7993639 100644 --- a/app/pages/PageEnigma/js/editor.ts +++ b/app/pages/PageEnigma/js/editor.ts @@ -188,7 +188,7 @@ class Editor { } - initialize(config:any) { + initialize(config: any) { //setup reactland Callbacks this.dispatchAppUiState = config.dispatchAppUiState @@ -264,10 +264,9 @@ class Editor { this.renderer.domElement.addEventListener("mousedown", this.onMouseDown.bind(this), false); this.renderer.domElement.addEventListener("mouseup", this.onMouseUp.bind(this), false); this.renderer.domElement.addEventListener("onContextMenu", this.onContextMenu.bind(this), false); - + this.cam_obj = this.activeScene.get_object_by_name("::CAM::"); - if(this.cam_obj) - { + if (this.cam_obj) { this.add_transform_clip_base("Camera Object", this.cam_obj, 0, 150) } @@ -298,7 +297,7 @@ class Editor { - if(load_scene_state_response.data == null) { return; } + if (load_scene_state_response.data == null) { return; } // Load these so you can rewrite the scene glb using it's token. this.current_scene_media_token = load_scene_state_response.data["scene_media_file_token"] this.current_scene_glb_media_token = load_scene_state_response.data["scene_glb_media_file_token"] @@ -306,7 +305,7 @@ class Editor { const loaded_scene = load_scene_state_response.data["scene"] this.current_scene_media_token_id = load_scene_state_response.data["media_file_token"] console.log(`loadScene => SceneMediaToken:${this.current_scene_media_token} SceneGLBMediaToken:${this.current_scene_glb_media_token}`); - + this.activeScene.scene.children = loaded_scene.children; @@ -337,7 +336,7 @@ class Editor { type: APPUI_ACTION_TYPES.SHOW_EDITOR_LOADER }); console.log(`saveScene => SceneMediaToken:${this.current_scene_media_token} SceneGLBMediaToken:${this.current_scene_glb_media_token}`); - + const result = await this.api_manager.saveSceneState( this.activeScene.scene, name, @@ -351,14 +350,14 @@ class Editor { if (scene_media_token != null) { this.current_scene_media_token = scene_media_token } - - const scene_glb_media_token = result.data["scene_glb_media_file_token"] + + const scene_glb_media_token = result.data["scene_glb_media_file_token"] if (scene_glb_media_token != null) { this.current_scene_glb_media_token = scene_glb_media_token - } + } this.dispatchAppUiState({ - type: APPUI_ACTION_TYPES.HIDE_EDITOR_LOADER + type: APPUI_ACTION_TYPES.HIDE_EDITOR_LOADER }); } @@ -430,17 +429,17 @@ class Editor { switchCameraView() { this.camera_person_mode = !this.camera_person_mode; if (this.cam_obj) { - if(this.camera_person_mode) { + if (this.camera_person_mode) { this.last_cam_pos.copy(this.camera.position); this.last_cam_rot.copy(this.camera.rotation); this.camera.position.copy(this.cam_obj.position); this.camera.rotation.copy(this.cam_obj.rotation); - if(this.orbitControls) { this.orbitControls.enabled = false; } - if(this.lockControls) { this.activeScene.scene.add(this.lockControls.getObject()); } - if(this.cameraViewControls) { this.cameraViewControls.enabled = true; } + if (this.orbitControls) { this.orbitControls.enabled = false; } + if (this.lockControls) { this.activeScene.scene.add(this.lockControls.getObject()); } + if (this.cameraViewControls) { this.cameraViewControls.enabled = true; } - if(this.activeScene.hot_items){ + if (this.activeScene.hot_items) { this.activeScene.hot_items.forEach(element => { element.visible = false; }); @@ -448,10 +447,10 @@ class Editor { } else { this.camera.position.copy(this.last_cam_pos); this.camera.rotation.copy(this.last_cam_rot); - if(this.orbitControls) { this.orbitControls.enabled = true; } - if(this.lockControls) { this.activeScene.scene.remove(this.lockControls.getObject()); } - if(this.cameraViewControls) { this.cameraViewControls.enabled = false; } - if(this.activeScene.hot_items){ + if (this.orbitControls) { this.orbitControls.enabled = true; } + if (this.lockControls) { this.activeScene.scene.remove(this.lockControls.getObject()); } + if (this.cameraViewControls) { this.cameraViewControls.enabled = false; } + if (this.activeScene.hot_items) { this.activeScene.hot_items.forEach(element => { element.visible = true; }); @@ -460,7 +459,7 @@ class Editor { } } - async add_transform_clip_base(name: string = "New Clip", object: THREE.Object3D, start_offset:number, end_offset:number) { + async add_transform_clip_base(name: string = "New Clip", object: THREE.Object3D, start_offset: number, end_offset: number) { this.timeline.addPlayableClip( new ClipUI(1.0, "transform", "clip2", object.uuid, object.uuid, start_offset, end_offset), ); @@ -637,8 +636,8 @@ class Editor { } take_timeline_cam_clip() { - if(this.cam_obj == null) { return; } - if(!this.camera_person_mode) { return; } + if (this.cam_obj == null) { return; } + if (!this.camera_person_mode) { return; } this.transform_engine.addFrame(this.cam_obj, this.transform_engine.clips[this.cam_obj.uuid].length); console.log("Camera frame taken."); this.activeScene.createPoint(this.cam_obj.position, false); @@ -670,7 +669,7 @@ class Editor { } } - if(this.render_camera && this.cam_obj) { + if (this.render_camera && this.cam_obj) { this.render_camera.position.copy(this.cam_obj.position); this.render_camera.rotation.copy(this.cam_obj.rotation); } @@ -737,21 +736,21 @@ class Editor { if (clip.type == "lipsync") { console.log(clip.media_id) for (const [key, value] of Object.entries(this.lipsync_engine.clips)) { - if(clip.object_uuid == key && clip.media_id == value.media_id) { - await ffmpeg.FS('writeFile', itteration+"tmp.wav", await fetchFile(await this.api_manager.getMediaFile(value.media_id))); - let video_og = itteration+'tmp.mp4'; - let wav_name = itteration+'tmp.wav'; - let new_video = (itteration+1)+'tmp.mp4'; + if (clip.object_uuid == key && clip.media_id == value.media_id) { + await ffmpeg.FS('writeFile', itteration + "tmp.wav", await fetchFile(await this.api_manager.getMediaFile(value.media_id))); + let video_og = itteration + 'tmp.mp4'; + let wav_name = itteration + 'tmp.wav'; + let new_video = (itteration + 1) + 'tmp.mp4'; let startFrame = clip.start_offset; let endFrame = clip.ending_offset; const startTime = startFrame / this.cap_fps; const endTime = endFrame / this.cap_fps; - let end = endTime-startTime; + let end = endTime - startTime; - let audioSegment = "new_"+wav_name; + let audioSegment = "new_" + wav_name; - await ffmpeg.run('-i', wav_name, '-ss', '0', '-to', ''+end, audioSegment); + await ffmpeg.run('-i', wav_name, '-ss', '0', '-to', '' + end, audioSegment); await ffmpeg.run( '-i', video_og, '-itsoffset', `${startTime}`, @@ -760,13 +759,13 @@ class Editor { '-c:a', 'aac', '-strict', 'experimental', new_video - ); + ); itteration += 1 } } } }; - + for (const [key, value] of Object.entries(this.lipsync_engine.clips)) { console.log(key, value); if (value.audio_data) { @@ -783,7 +782,7 @@ class Editor { } } - let output = await ffmpeg.FS("readFile", itteration+"tmp.mp4"); + let output = await ffmpeg.FS("readFile", itteration + "tmp.mp4"); // Create a Blob from the output file for downloading const blob = new Blob([output.buffer], { type: "video/mp4" }); const url = URL.createObjectURL(blob); @@ -812,7 +811,7 @@ class Editor { startPlayback() { this.timeline.isPlaying = true; - if(!this.camera_person_mode) { + if (!this.camera_person_mode) { this.switchCameraView(); } } From d5507bff8ae590a3435b4fcca8dae96a641c3d5e Mon Sep 17 00:00:00 2001 From: Quicksticks-oss Date: Fri, 29 Mar 2024 00:22:48 -0400 Subject: [PATCH 15/17] added audio to video. --- .../datastructures/clips/animation_clip.ts | 3 - app/pages/PageEnigma/js/editor.ts | 142 +++++++++++------- app/pages/PageEnigma/js/timeline.ts | 12 +- 3 files changed, 96 insertions(+), 61 deletions(-) diff --git a/app/pages/PageEnigma/datastructures/clips/animation_clip.ts b/app/pages/PageEnigma/datastructures/clips/animation_clip.ts index 50110653d4..30d9bf91e1 100644 --- a/app/pages/PageEnigma/datastructures/clips/animation_clip.ts +++ b/app/pages/PageEnigma/datastructures/clips/animation_clip.ts @@ -74,19 +74,16 @@ export class AnimationClip { this.clip_action.play(); } } - console.log("Play") } } step(deltatime: number) { if (this.mixer == null) { return; } this.mixer?.update(deltatime); - console.log("Update") } stop() { this.mixer?.stopAllAction(); - console.log("stop.") } toJSON(): string { diff --git a/app/pages/PageEnigma/js/editor.ts b/app/pages/PageEnigma/js/editor.ts index 52e7993639..4ab37b0796 100644 --- a/app/pages/PageEnigma/js/editor.ts +++ b/app/pages/PageEnigma/js/editor.ts @@ -12,7 +12,7 @@ import { SMAAPass } from "three/addons/postprocessing/SMAAPass.js"; import { SAOPass } from "three/addons/postprocessing/SAOPass.js"; import { UnrealBloomPass } from "three/addons/postprocessing/UnrealBloomPass.js"; import { BokehPass } from "three/addons/postprocessing/BokehPass.js"; -import { createFFmpeg, fetchFile } from "@ffmpeg/ffmpeg"; +import { FFmpeg, createFFmpeg, fetchFile } from "@ffmpeg/ffmpeg"; import AudioEngine from "./audio_engine.js"; import TransformEngine from "./transform_engine.js"; import { TimeLine, TimelineDataState } from "./timeline.js"; @@ -517,6 +517,18 @@ class Editor { 400, ), ); + + + this.audio_engine.loadClip("m_h33vytxs5eqqqf07nsy14qzrf9ww4v"); + + await this.timeline.addPlayableClip(new ClipUI( + 1.0, + "audio", + "AudioClip", + "m_h33vytxs5eqqqf07nsy14qzrf9ww4v", + "", + 0, + 50)); } // Configure post processing. @@ -710,6 +722,56 @@ class Editor { return blob; } + async convertAudioClip(itteration: number, ffmpeg: FFmpeg, clip: ClipUI) { + let video_og = itteration + 'tmp.mp4'; + let wav_name = itteration + 'tmp.wav'; + let new_video = (itteration + 1) + 'tmp.mp4'; + let startFrame = clip.start_offset; + let endFrame = clip.ending_offset; + + + if (endFrame > this.timeline.timeLineLimit) { + endFrame = this.timeline.timeLineLimit; + } + if (startFrame > this.timeline.timeLineLimit) { + startFrame = this.timeline.timeLineLimit-1; + } + + const startTime = startFrame / this.cap_fps; + const endTime = endFrame / this.cap_fps; + let end = endTime - startTime; + + let duration = this.timeline.timeLineLimit / this.cap_fps; + + let audioSegment = "as_" + wav_name; + await ffmpeg.FS('writeFile', wav_name, await fetchFile(await this.api_manager.getMediaFile(clip.media_id))); + await ffmpeg.run('-i', + wav_name, + '-ss', '0', + '-to', '' + end, + "-max_muxing_queue_size", "999999", + audioSegment); + + await ffmpeg.run('-i', video_og,"-max_muxing_queue_size", "999999", `${itteration}empty_tmp.wav`); + + await ffmpeg.run( + '-i', `${itteration}empty_tmp.wav`, + '-i', audioSegment, + '-filter_complex', "[1:a]adelay="+startTime*1000+"|"+startTime*1000+"[a1];[0:a][a1]amix=inputs=2[a]", + "-map", "[a]", + `${itteration}final_tmp.wav`) + + await ffmpeg.run( + '-i', video_og, + '-i', `${itteration}final_tmp.wav`, + '-c:v', 'copy', + '-c:a', 'aac', + '-map', '0:v:0', + '-map', '1:a:0', + '-strict', 'experimental', + new_video) + } + async stopPlayback() { this.render_mode(); let ffmpeg = createFFmpeg({ log: true }); @@ -727,82 +789,53 @@ class Editor { "" + this.cap_fps, "-i", "image%d.png", - "0tmp.mp4", + "-f", + "lavfi", + "-i", + "anullsrc", // This adds a silent audio track + "-max_muxing_queue_size", + "999999", + "-c:v", + "libx264", // Specify video codec (optional, but recommended for MP4) + "-c:a", + "aac", // Specify audio codec (optional, but recommended for MP4) + "-shortest", // Ensure output duration matches the shortest stream (video or audio) + "0tmp.mp4" ); + let itteration = 0; for (const clip of this.timeline.timelineItems) { - if (clip.type == "lipsync") { - console.log(clip.media_id) - for (const [key, value] of Object.entries(this.lipsync_engine.clips)) { - if (clip.object_uuid == key && clip.media_id == value.media_id) { - await ffmpeg.FS('writeFile', itteration + "tmp.wav", await fetchFile(await this.api_manager.getMediaFile(value.media_id))); - let video_og = itteration + 'tmp.mp4'; - let wav_name = itteration + 'tmp.wav'; - let new_video = (itteration + 1) + 'tmp.mp4'; - let startFrame = clip.start_offset; - let endFrame = clip.ending_offset; - - const startTime = startFrame / this.cap_fps; - const endTime = endFrame / this.cap_fps; - let end = endTime - startTime; - - let audioSegment = "new_" + wav_name; - - await ffmpeg.run('-i', wav_name, '-ss', '0', '-to', '' + end, audioSegment); - await ffmpeg.run( - '-i', video_og, - '-itsoffset', `${startTime}`, - '-i', audioSegment, - '-c:v', 'copy', - '-c:a', 'aac', - '-strict', 'experimental', - new_video - ); - itteration += 1 - } - } + if (clip.type == "lipsync" || clip.type == "audio") { + await this.convertAudioClip(itteration, ffmpeg, clip); + itteration += 1; } }; - for (const [key, value] of Object.entries(this.lipsync_engine.clips)) { - console.log(key, value); - if (value.audio_data) { - //await ffmpeg.FS('writeFile', itteration+"tmp.wav", await fetchFile(await this.api_manager.getMediaFile(value.media_id))); - //let mp4_og = itteration+'tmp.mp4'; - //let wav_name = itteration+'tmp.wav'; - //let new_wav = (itteration+1)+'tmp.mp4'; - //let startFrame = 0; - //let endFrame = 60; - //let startTime = startFrame / this.cap_fps; - //let endTime = endFrame / this.cap_fps; - //await ffmpeg.run('-i', mp4_og, '-ss', startTime.toString(), '-i', wav_name, '-to', endTime.toString(), '-c:v', 'copy', '-c:a', 'aac', new_wav); - //itteration += 1 - } - } - let output = await ffmpeg.FS("readFile", itteration + "tmp.mp4"); // Create a Blob from the output file for downloading const blob = new Blob([output.buffer], { type: "video/mp4" }); const url = URL.createObjectURL(blob); - - //let data = await this.api_manager.uploadMedia(blob, "tmp.wav"); - //console.log(data); - // Create a link to download the file - const downloadLink = document.createElement("a"); downloadLink.href = url; - downloadLink.download = "tmp.mp4"; + downloadLink.download = "render.mp4"; document.body.appendChild(downloadLink); downloadLink.click(); // Clean up URL.revokeObjectURL(url); document.body.removeChild(downloadLink); + + + let data = await this.api_manager.uploadMedia(blob, "tmp.wav"); + console.log(data); + // Create a link to download the file + } generateVideo() { console.log("Generating video..."); + if (this.rendering) { return; } this.startPlayback(); this._initializeRecording(); this.rendering = true; @@ -811,6 +844,7 @@ class Editor { startPlayback() { this.timeline.isPlaying = true; + this.timeline.scrubberPosition = 0; if (!this.camera_person_mode) { this.switchCameraView(); } diff --git a/app/pages/PageEnigma/js/timeline.ts b/app/pages/PageEnigma/js/timeline.ts index 28d260f348..55573b039b 100644 --- a/app/pages/PageEnigma/js/timeline.ts +++ b/app/pages/PageEnigma/js/timeline.ts @@ -72,7 +72,7 @@ export class TimeLine { scene: Scene) { this.timelineItems = [] - this.timeLineLimit = 60 * 5 // 10 seconds + this.timeLineLimit = 60 * 5 // 5 seconds this.isPlaying = false this.scrubberPosition = 0 // in frames into the tl @@ -151,7 +151,7 @@ export class TimeLine { else if (element.type == "animation") { } else if (element.type == "lipsync") { - + this.lipSyncEngine.clips[element.object_uuid].reset(); } else { this.stop() @@ -184,8 +184,12 @@ export class TimeLine { } } else if (element.type == "audio") { - // global audio track - this.audioEngine.playClip(element.media_id) + if(this.scrubberPosition+1 >= element.ending_offset){ + this.audioEngine.stopClip(element.media_id); + } + else { + this.audioEngine.playClip(element.media_id); + } } else if (element.type == "lipsync") { if(this.scrubberPosition+1 >= element.ending_offset){ From e90e63140bd213eceda5ed211a93a198bc342ced Mon Sep 17 00:00:00 2001 From: Quicksticks-oss Date: Fri, 29 Mar 2024 00:23:42 -0400 Subject: [PATCH 16/17] added scene items visibility to false in render --- app/pages/PageEnigma/js/editor.ts | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/app/pages/PageEnigma/js/editor.ts b/app/pages/PageEnigma/js/editor.ts index 4ab37b0796..04df254668 100644 --- a/app/pages/PageEnigma/js/editor.ts +++ b/app/pages/PageEnigma/js/editor.ts @@ -840,6 +840,11 @@ class Editor { this._initializeRecording(); this.rendering = true; this.activeScene.render_mode(this.rendering); + if (this.activeScene.hot_items) { + this.activeScene.hot_items.forEach(element => { + element.visible = false; + }); + } } startPlayback() { From 9e0c8365ca8ee3af58d3aa00586c7aaac73b86a8 Mon Sep 17 00:00:00 2001 From: Quicksticks-oss Date: Fri, 29 Mar 2024 00:50:05 -0400 Subject: [PATCH 17/17] Updated merge. --- .../comps/ControlsTopButtons/ControlsTopButtons.tsx | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/app/pages/PageEnigma/comps/ControlsTopButtons/ControlsTopButtons.tsx b/app/pages/PageEnigma/comps/ControlsTopButtons/ControlsTopButtons.tsx index 6e0df6b68b..01670a0220 100644 --- a/app/pages/PageEnigma/comps/ControlsTopButtons/ControlsTopButtons.tsx +++ b/app/pages/PageEnigma/comps/ControlsTopButtons/ControlsTopButtons.tsx @@ -79,6 +79,10 @@ export const ControlsTopButtons = () => { editorEngine?.generateVideo(); }; + const handleButtonTakeFrame = () => { + editorEngine?.take_timeline_cam_clip(); + }; + // const handleButtonCameraView = () => { // editorEngine?.change_camera_view(); // }; @@ -146,9 +150,9 @@ export const ControlsTopButtons = () => {
- - - + + + {/* */}