mirror of
https://github.com/storytold/artcraft.git
synced 2026-11-03 17:08:13 +00:00
Some code cleanup, get keyframes working
This commit is contained in:
1 parent
9347782812
commit
565280f2df
16 files changed
+653
-563
No files matched your search
@@ -1,11 +1,11 @@
|
||||
import { twMerge } from "tailwind-merge";
|
||||
import { H4 } from ".";
|
||||
|
||||
import { ArtStyle } from "~/pages/PageEnigma/js/api_manager";
|
||||
|
||||
interface ItemPickerProps extends React.ImgHTMLAttributes<HTMLImageElement> {
|
||||
label: string
|
||||
label: ArtStyle;
|
||||
selected: boolean;
|
||||
onSelected : (val:string)=>void;
|
||||
onSelected: (picked: ArtStyle) => void;
|
||||
}
|
||||
|
||||
export const ItemPicker = ({
|
||||
@@ -13,20 +13,22 @@ export const ItemPicker = ({
|
||||
selected = false,
|
||||
onSelected,
|
||||
...imgProps
|
||||
}:ItemPickerProps) => {
|
||||
|
||||
const handleSelected = ()=>{
|
||||
}: ItemPickerProps) => {
|
||||
const handleSelected = () => {
|
||||
onSelected(label);
|
||||
};
|
||||
|
||||
return (
|
||||
<div
|
||||
className={twMerge("relative border-2 rounded-lg overflow-hidden cursor-pointer transition-colors ease-in-out", selected ? "border-brand-primary" : "border-ui-border")}
|
||||
className={twMerge(
|
||||
"relative cursor-pointer overflow-hidden rounded-lg border-2 transition-colors ease-in-out",
|
||||
selected ? "border-brand-primary" : "border-ui-border",
|
||||
)}
|
||||
onClick={handleSelected}
|
||||
>
|
||||
<img className="aspect-square min-w-20" {...imgProps} />
|
||||
<div className="bg-gradient-to-t from-gray-700 absolute top-0 left-0 w-full h-full"/>
|
||||
<div className="absolute left-0 top-0 h-full w-full bg-gradient-to-t from-gray-700" />
|
||||
<H4 className="absolute bottom-0 left-2 drop-shadow-md">{label}</H4>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
);
|
||||
};
|
||||
@@ -1,10 +1,18 @@
|
||||
import { PageEnigmaComponent } from "./PageEnigmaComponent";
|
||||
import { TrackProvider } from "~/pages/PageEnigma/contexts/TrackContext/TrackProvider";
|
||||
import { AppUIProvider } from "~/pages/PageEnigma/contexts/AppUiContext";
|
||||
import { EngineProvider } from "~/pages/PageEnigma/contexts/EngineProvider";
|
||||
import { DragComponent } from "~/pages/PageEnigma/comps/DragComponent/DragComponent";
|
||||
|
||||
export const PageEnigma = () => {
|
||||
return (
|
||||
<TrackProvider>
|
||||
<PageEnigmaComponent />
|
||||
<AppUIProvider>
|
||||
<EngineProvider>
|
||||
<PageEnigmaComponent />
|
||||
</EngineProvider>
|
||||
</AppUIProvider>
|
||||
<DragComponent />
|
||||
</TrackProvider>
|
||||
);
|
||||
};
|
||||
@@ -1,4 +1,4 @@
|
||||
import { useReducer } from "react";
|
||||
import { useContext } from "react";
|
||||
|
||||
import { faSparkles } from "@fortawesome/pro-solid-svg-icons";
|
||||
|
||||
@@ -15,23 +15,14 @@ import { ViewSideBySide } from "./comps/ViewSideBySide";
|
||||
import { SidePanelTabs } from "./comps/SidePanelTabs";
|
||||
import { Timeline } from "./comps/Timeline";
|
||||
|
||||
import { EngineProvider } from "./contexts/EngineProvider";
|
||||
import { AppUIProvider } from "./contexts/AppUiContext";
|
||||
import {
|
||||
appUiReducer,
|
||||
appUiInitialStateValues,
|
||||
APPUI_VIEW_MODES,
|
||||
} from "./reducers";
|
||||
import { APPUI_VIEW_MODES } from "./reducers";
|
||||
import { timelineHeight } from "~/pages/PageEnigma/store";
|
||||
import { useSignals } from "@preact/signals-react/runtime";
|
||||
import { DragComponent } from "~/pages/PageEnigma/comps/DragComponent/DragComponent";
|
||||
import { AppUiContext } from "~/pages/PageEnigma/contexts/AppUiContext";
|
||||
|
||||
export const PageEnigmaComponent = () => {
|
||||
useSignals();
|
||||
const [appUiState, dispatchAppUiState] = useReducer(
|
||||
appUiReducer,
|
||||
appUiInitialStateValues,
|
||||
);
|
||||
const [appUiState] = useContext(AppUiContext);
|
||||
|
||||
//To prevent the click event from propagating to the canvas: TODO: HANDLE THIS BETTER?
|
||||
const handleOverlayClick = (event: React.MouseEvent<HTMLDivElement>) => {
|
||||
@@ -45,82 +36,77 @@ export const PageEnigmaComponent = () => {
|
||||
<Button icon={faSparkles}>Generate Movie</Button>
|
||||
</TopBarHelmet>
|
||||
|
||||
<AppUIProvider value={[appUiState, dispatchAppUiState]}>
|
||||
<EngineProvider>
|
||||
<div style={{ height: "calc(100vh - 68px)" }}>
|
||||
{/* Engine section/side panel */}
|
||||
<div style={{ height: "calc(100vh - 68px)" }}>
|
||||
{/* Engine section/side panel */}
|
||||
<div
|
||||
id="engine-n-panels-wrapper"
|
||||
className="flex"
|
||||
style={{ height: `calc(100% - ${lowerHeight}px)` }}
|
||||
>
|
||||
<div className="relative w-full overflow-hidden bg-transparent">
|
||||
<div
|
||||
id="engine-n-panels-wrapper"
|
||||
className="flex"
|
||||
style={{ height: `calc(100% - ${lowerHeight}px)` }}
|
||||
className={
|
||||
appUiState.viewMode === APPUI_VIEW_MODES.SIDE_BY_SIDE
|
||||
? "invisible"
|
||||
: ""
|
||||
}
|
||||
>
|
||||
<div className="relative w-full overflow-hidden bg-transparent">
|
||||
<div
|
||||
className={
|
||||
appUiState.viewMode === APPUI_VIEW_MODES.SIDE_BY_SIDE
|
||||
? "invisible"
|
||||
: ""
|
||||
}
|
||||
>
|
||||
<canvas id="video-scene" width="1280px" height="720px" />
|
||||
<canvas id="video-scene" width="1280px" height="720px" />
|
||||
|
||||
{/* Top controls */}
|
||||
<div
|
||||
className="absolute left-0 top-0 w-full"
|
||||
onClick={handleOverlayClick}
|
||||
>
|
||||
<div className="grid grid-cols-3 gap-4">
|
||||
<ControlsTopButtons />
|
||||
<Controls3D />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Bottom controls */}
|
||||
<div
|
||||
className="absolute bottom-0 left-0 w-full"
|
||||
onClick={handleOverlayClick}
|
||||
>
|
||||
<PreviewEngineCamera />
|
||||
<ControlsVideo />
|
||||
<ControlPanelSceneObject />
|
||||
</div>
|
||||
{/* Top controls */}
|
||||
<div
|
||||
className="absolute left-0 top-0 w-full"
|
||||
onClick={handleOverlayClick}
|
||||
>
|
||||
<div className="grid grid-cols-3 gap-4">
|
||||
<ControlsTopButtons />
|
||||
<Controls3D />
|
||||
</div>
|
||||
{appUiState.viewMode === APPUI_VIEW_MODES.SIDE_BY_SIDE && (
|
||||
<ViewSideBySide />
|
||||
)}
|
||||
<LoadingDots
|
||||
className="absolute left-0 top-0"
|
||||
isShowing={appUiState.showEditorLoader.isShowing}
|
||||
type="bricks"
|
||||
message={appUiState.showEditorLoader.message}
|
||||
/>
|
||||
<LoadingBar
|
||||
id="editor-loading-bar"
|
||||
wrapperClassName="absolute top-0 left-0"
|
||||
innerWrapperClassName="max-w-screen-sm"
|
||||
isShowing={appUiState.showEditorLoadingBar.isShowing}
|
||||
message={appUiState.showEditorLoadingBar.message}
|
||||
label={appUiState.showEditorLoadingBar.label}
|
||||
progress={appUiState.showEditorLoadingBar.progress}
|
||||
/>
|
||||
</div>
|
||||
|
||||
{/* Side panel */}
|
||||
<div onClick={handleOverlayClick}>
|
||||
<SidePanel>
|
||||
<SidePanelTabs />
|
||||
</SidePanel>
|
||||
{/* Bottom controls */}
|
||||
<div
|
||||
className="absolute bottom-0 left-0 w-full"
|
||||
onClick={handleOverlayClick}
|
||||
>
|
||||
<PreviewEngineCamera />
|
||||
<ControlsVideo />
|
||||
<ControlPanelSceneObject />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Timeline */}
|
||||
<div onClick={handleOverlayClick}>
|
||||
<Timeline />
|
||||
</div>
|
||||
{appUiState.viewMode === APPUI_VIEW_MODES.SIDE_BY_SIDE && (
|
||||
<ViewSideBySide />
|
||||
)}
|
||||
<LoadingDots
|
||||
className="absolute left-0 top-0"
|
||||
isShowing={appUiState.showEditorLoader.isShowing}
|
||||
type="bricks"
|
||||
message={appUiState.showEditorLoader.message}
|
||||
/>
|
||||
<LoadingBar
|
||||
id="editor-loading-bar"
|
||||
wrapperClassName="absolute top-0 left-0"
|
||||
innerWrapperClassName="max-w-screen-sm"
|
||||
isShowing={appUiState.showEditorLoadingBar.isShowing}
|
||||
message={appUiState.showEditorLoadingBar.message}
|
||||
label={appUiState.showEditorLoadingBar.label}
|
||||
progress={appUiState.showEditorLoadingBar.progress}
|
||||
/>
|
||||
</div>
|
||||
</EngineProvider>
|
||||
</AppUIProvider>
|
||||
<DragComponent />
|
||||
|
||||
{/* Side panel */}
|
||||
<div onClick={handleOverlayClick}>
|
||||
<SidePanel>
|
||||
<SidePanelTabs />
|
||||
</SidePanel>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Timeline */}
|
||||
<div onClick={handleOverlayClick}>
|
||||
<Timeline />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
@@ -20,36 +20,30 @@ import { QueueKeyframe } from "~/pages/PageEnigma/models/track";
|
||||
export const ControlPanelSceneObject = () => {
|
||||
const [appUiState, dispatchAppUiState] = useContext(AppUiContext);
|
||||
|
||||
const position = appUiState?.currentSceneObject.objectVectors.position;
|
||||
const rotation = appUiState?.currentSceneObject.objectVectors.rotation;
|
||||
const scale = appUiState?.currentSceneObject.objectVectors.scale;
|
||||
const currentSceneObject = appUiState?.currentSceneObject;
|
||||
|
||||
const handlePositionChange = (xyz: XYZ) => {
|
||||
if (appUiState) {
|
||||
if (currentSceneObject == null) {
|
||||
console.log("Missing Scene Object Position");
|
||||
return;
|
||||
}
|
||||
|
||||
dispatchAppUiState({
|
||||
type: ACTION_TYPES.UPDATE_CONTROLPANELS_SCENEOBJECT,
|
||||
payload: {
|
||||
currentSceneObject: {
|
||||
group: currentSceneObject.group,
|
||||
object_uuid: currentSceneObject.object_uuid,
|
||||
object_name: currentSceneObject.object_name,
|
||||
version: currentSceneObject.version,
|
||||
objectVectors: {
|
||||
position: { ...xyz },
|
||||
rotation: appUiState.currentSceneObject.objectVectors.rotation,
|
||||
scale: appUiState.currentSceneObject.objectVectors.scale,
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
if (!currentSceneObject) {
|
||||
console.log("Missing Scene Object Position");
|
||||
return;
|
||||
}
|
||||
|
||||
dispatchAppUiState({
|
||||
type: ACTION_TYPES.UPDATE_CONTROLPANELS_SCENEOBJECT,
|
||||
payload: {
|
||||
group: currentSceneObject.group,
|
||||
object_uuid: currentSceneObject.object_uuid,
|
||||
object_name: currentSceneObject.object_name,
|
||||
version: currentSceneObject.version,
|
||||
objectVectors: {
|
||||
position: { ...xyz },
|
||||
rotation: appUiState?.controlPanel.currentSceneObject?.objectVectors
|
||||
?.rotation ?? { x: 0, y: 0, z: 0 },
|
||||
scale: appUiState?.controlPanel.currentSceneObject?.objectVectors
|
||||
?.scale ?? { x: 0, y: 0, z: 0 },
|
||||
},
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
const handleRotationChange = (xyz: XYZ) => {
|
||||
if (appUiState) {
|
||||
if (currentSceneObject == null) {
|
||||
@@ -60,21 +54,22 @@ export const ControlPanelSceneObject = () => {
|
||||
dispatchAppUiState({
|
||||
type: ACTION_TYPES.UPDATE_CONTROLPANELS_SCENEOBJECT,
|
||||
payload: {
|
||||
currentSceneObject: {
|
||||
group: currentSceneObject.group,
|
||||
object_uuid: currentSceneObject.object_uuid,
|
||||
object_name: currentSceneObject.object_name,
|
||||
version: currentSceneObject.version,
|
||||
objectVectors: {
|
||||
position: appUiState.currentSceneObject.objectVectors.position,
|
||||
rotation: { ...xyz },
|
||||
scale: appUiState.currentSceneObject.objectVectors.scale,
|
||||
},
|
||||
group: currentSceneObject.group,
|
||||
object_uuid: currentSceneObject.object_uuid,
|
||||
object_name: currentSceneObject.object_name,
|
||||
version: currentSceneObject.version,
|
||||
objectVectors: {
|
||||
position:
|
||||
appUiState.controlPanel.currentSceneObject.objectVectors.position,
|
||||
rotation: { ...xyz },
|
||||
scale:
|
||||
appUiState.controlPanel.currentSceneObject.objectVectors.scale,
|
||||
},
|
||||
},
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
const handleScaleChange = (xyz: XYZ) => {
|
||||
if (appUiState) {
|
||||
if (currentSceneObject == null) {
|
||||
@@ -84,16 +79,16 @@ export const ControlPanelSceneObject = () => {
|
||||
dispatchAppUiState({
|
||||
type: ACTION_TYPES.UPDATE_CONTROLPANELS_SCENEOBJECT,
|
||||
payload: {
|
||||
currentSceneObject: {
|
||||
group: currentSceneObject.group,
|
||||
object_uuid: currentSceneObject.object_uuid,
|
||||
object_name: currentSceneObject.object_name,
|
||||
version: currentSceneObject.version,
|
||||
objectVectors: {
|
||||
position: appUiState.currentSceneObject.objectVectors.position,
|
||||
rotation: appUiState.currentSceneObject.objectVectors.rotation,
|
||||
scale: { ...xyz },
|
||||
},
|
||||
group: currentSceneObject.group,
|
||||
object_uuid: currentSceneObject.object_uuid,
|
||||
object_name: currentSceneObject.object_name,
|
||||
version: currentSceneObject.version,
|
||||
objectVectors: {
|
||||
position:
|
||||
appUiState.controlPanel.currentSceneObject.objectVectors.position,
|
||||
rotation:
|
||||
appUiState.controlPanel.currentSceneObject.objectVectors.rotation,
|
||||
scale: { ...xyz },
|
||||
},
|
||||
},
|
||||
});
|
||||
@@ -145,9 +140,19 @@ export const ControlPanelSceneObject = () => {
|
||||
}
|
||||
};
|
||||
|
||||
if (!appUiState.controlPanel.currentSceneObject) {
|
||||
return null;
|
||||
}
|
||||
const position =
|
||||
appUiState.controlPanel.currentSceneObject.objectVectors.position;
|
||||
const rotation =
|
||||
appUiState.controlPanel.currentSceneObject.objectVectors.rotation;
|
||||
const scale = appUiState.controlPanel.currentSceneObject.objectVectors.scale;
|
||||
const currentSceneObject = appUiState.controlPanel.currentSceneObject;
|
||||
|
||||
return (
|
||||
<Transition
|
||||
show={appUiState?.currentSceneObject.isShowing}
|
||||
show={appUiState?.controlPanel.isShowing}
|
||||
className="absolute bottom-0 right-0 m-4 flex h-fit w-fit flex-col gap-2 rounded-lg border border-ui-panel-border bg-ui-panel p-4 text-white"
|
||||
enter="transition-opacity duration-100"
|
||||
enterFrom="opacity-0"
|
||||
|
||||
@@ -4,10 +4,11 @@ import { ButtonDialogue } from "~/modules/ButtonDialogue";
|
||||
import { AppUiContext } from "../../contexts/AppUiContext";
|
||||
import { EngineContext } from "../../contexts/EngineContext";
|
||||
import { APPUI_ACTION_TYPES } from "../../reducers";
|
||||
import { ClipGroup } from "~/pages/PageEnigma/models/track";
|
||||
|
||||
export const ControlsTopButtons = () => {
|
||||
const editorEngine = useContext(EngineContext);
|
||||
const [ appUiState, dispatchAppUiState ] = useContext(AppUiContext);
|
||||
const [appUiState, dispatchAppUiState] = useContext(AppUiContext);
|
||||
const [sceneName, setSceneName] = useState<string>("");
|
||||
const [sceneToken, setSceneToken] = useState<string>("");
|
||||
|
||||
@@ -22,8 +23,8 @@ export const ControlsTopButtons = () => {
|
||||
};
|
||||
|
||||
const handleButtonTest = () => {
|
||||
editorEngine?.testStylizeRequest()
|
||||
|
||||
editorEngine?.testStylizeRequest();
|
||||
|
||||
// if(appUiState?.showEditorLoadingBar.isShowing){
|
||||
//TO GO TO A HUNDRED AND DISAPPER
|
||||
// dispatchAppUiState({
|
||||
@@ -41,15 +42,15 @@ export const ControlsTopButtons = () => {
|
||||
// }, 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",
|
||||
// }
|
||||
// }
|
||||
// });
|
||||
//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,
|
||||
@@ -59,31 +60,33 @@ export const ControlsTopButtons = () => {
|
||||
// progress: 10,
|
||||
// }
|
||||
// }
|
||||
|
||||
|
||||
// });
|
||||
//}
|
||||
};
|
||||
|
||||
const handleObjectPanelTest = () => {
|
||||
if (appUiState?.currentSceneObject.isShowing) {
|
||||
if (appUiState?.controlPanel.isShowing) {
|
||||
dispatchAppUiState({
|
||||
type: APPUI_ACTION_TYPES.HIDE_CONTROLPANELS_SCENEOBJECT
|
||||
type: APPUI_ACTION_TYPES.HIDE_CONTROLPANELS_SCENEOBJECT,
|
||||
});
|
||||
}else{
|
||||
} else {
|
||||
dispatchAppUiState({
|
||||
type:APPUI_ACTION_TYPES.SHOW_CONTROLPANELS_SCENEOBJECT,
|
||||
payload:{
|
||||
currentSceneObject:{
|
||||
objectVectors: {
|
||||
position: {x:1,y:2,z:3},
|
||||
rotation: {x:4,y:5,z:6},
|
||||
scale: {x:7,y:8,z:9},
|
||||
}
|
||||
}
|
||||
}
|
||||
type: APPUI_ACTION_TYPES.SHOW_CONTROLPANELS_SCENEOBJECT,
|
||||
payload: {
|
||||
group: ClipGroup.OBJECT,
|
||||
object_name: "",
|
||||
object_uuid: "",
|
||||
version: "1",
|
||||
objectVectors: {
|
||||
position: { x: 1, y: 2, z: 3 },
|
||||
rotation: { x: 4, y: 5, z: 6 },
|
||||
scale: { x: 7, y: 8, z: 9 },
|
||||
},
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const handleButtonCameraView = () => {
|
||||
editorEngine?.switchCameraView();
|
||||
@@ -111,40 +114,44 @@ export const ControlsTopButtons = () => {
|
||||
<div className="flex flex-col gap-2 pl-3 pt-3">
|
||||
<div className="flex gap-2">
|
||||
<ButtonDialogue
|
||||
buttonProps={{
|
||||
variant: "secondary",
|
||||
label: "Load Scene",
|
||||
}}
|
||||
title="Load Scene"
|
||||
confirmButtonProps={{
|
||||
label: "Load",
|
||||
disabled: sceneToken === "" ? true : false,
|
||||
onClick: handleButtonLoadScene,
|
||||
}}
|
||||
>
|
||||
buttonProps={{
|
||||
variant: "secondary",
|
||||
label: "Load Scene",
|
||||
}}
|
||||
title="Load Scene"
|
||||
confirmButtonProps={{
|
||||
label: "Load",
|
||||
disabled: sceneToken === "",
|
||||
onClick: handleButtonLoadScene,
|
||||
}}
|
||||
>
|
||||
<Input
|
||||
label="Please provide the Token of the scene you wished to load:"
|
||||
onChange={(e)=>{setSceneToken(e.target.value)}}
|
||||
onChange={(e) => {
|
||||
setSceneToken(e.target.value);
|
||||
}}
|
||||
/>
|
||||
</ButtonDialogue>
|
||||
|
||||
<ButtonDialogue
|
||||
buttonProps={{
|
||||
variant: "secondary",
|
||||
label: "Save Scene",
|
||||
}}
|
||||
title="Save Scene"
|
||||
confirmButtonProps={{
|
||||
label: "Save",
|
||||
disabled: sceneName === "" ? true : false,
|
||||
onClick: handleButtonSave,
|
||||
}}
|
||||
>
|
||||
<Input
|
||||
label="Please Enter a name for your scene"
|
||||
onChange={(e)=>{setSceneName(e.target.value)}}
|
||||
/>
|
||||
</ButtonDialogue>
|
||||
<ButtonDialogue
|
||||
buttonProps={{
|
||||
variant: "secondary",
|
||||
label: "Save Scene",
|
||||
}}
|
||||
title="Save Scene"
|
||||
confirmButtonProps={{
|
||||
label: "Save",
|
||||
disabled: sceneName === "",
|
||||
onClick: handleButtonSave,
|
||||
}}
|
||||
>
|
||||
<Input
|
||||
label="Please Enter a name for your scene"
|
||||
onChange={(e) => {
|
||||
setSceneName(e.target.value);
|
||||
}}
|
||||
/>
|
||||
</ButtonDialogue>
|
||||
|
||||
<ButtonDialogue
|
||||
buttonProps={{
|
||||
@@ -172,7 +179,6 @@ export const ControlsTopButtons = () => {
|
||||
</Button>
|
||||
</div>
|
||||
<div className="flex gap-2">
|
||||
|
||||
<Button onClick={handleButtonSingleFrame}>Render Single Frame</Button>
|
||||
<Button onClick={handleButtonTakeFrame}>Take Frame</Button>
|
||||
<Button onClick={handleButtonRender}>Render</Button>
|
||||
@@ -181,7 +187,7 @@ export const ControlsTopButtons = () => {
|
||||
<Button
|
||||
onClick={handleButtonTest}
|
||||
className="bg-brand-tertiary hover:bg-brand-teriary-400 focus-visible:outline-brand-tertiary"
|
||||
style={{zIndex:9001}}
|
||||
style={{ zIndex: 9001 }}
|
||||
>
|
||||
Test
|
||||
</Button>
|
||||
|
||||
@@ -1,105 +1,114 @@
|
||||
import { useContext, useState } from 'react';
|
||||
import { useContext, useState } from "react";
|
||||
|
||||
import {
|
||||
Button,
|
||||
H4,
|
||||
ItemPicker,
|
||||
Textarea
|
||||
} from "~/components"
|
||||
import { Button, H4, ItemPicker, Textarea } from "~/components";
|
||||
|
||||
import { AppUiContext } from '../../contexts/AppUiContext';
|
||||
import { APPUI_ACTION_TYPES } from '../../reducers';
|
||||
import { APPUI_VIEW_MODES } from '../../reducers';
|
||||
import { EngineContext } from '../../contexts/EngineContext';
|
||||
import { ArtStyle } from '../../js/api_manager';
|
||||
export const TabStylization = ()=>{
|
||||
import { AppUiContext } from "../../contexts/AppUiContext";
|
||||
import { APPUI_ACTION_TYPES, APPUI_VIEW_MODES } from "../../reducers";
|
||||
import { EngineContext } from "../../contexts/EngineContext";
|
||||
import { ArtStyle } from "../../js/api_manager";
|
||||
|
||||
export const TabStylization = () => {
|
||||
const [appUiState, dispatchAppUiState] = useContext(AppUiContext);
|
||||
const [ selection, setSelection ] = useState<string>("Anime");
|
||||
const [selection, setSelection] = useState<string>("Anime");
|
||||
|
||||
const editorEngine = useContext(EngineContext);
|
||||
|
||||
const handlePickingStylizer = (picked:ArtStyle)=>{
|
||||
const handlePickingStylizer = (picked: ArtStyle) => {
|
||||
console.log(`Picked style: ${picked}`);
|
||||
if (editorEngine == null) { console.log("Editor is null"); return;}
|
||||
editorEngine.art_style = picked
|
||||
if (editorEngine == null) {
|
||||
console.log("Editor is null");
|
||||
return;
|
||||
}
|
||||
editorEngine.art_style = picked;
|
||||
setSelection(picked);
|
||||
}
|
||||
};
|
||||
|
||||
const onChangeHandlerNegative = (e:React.ChangeEvent<HTMLInputElement>) => {
|
||||
if (editorEngine == null) { console.log("Editor is null"); return;}
|
||||
editorEngine.negative_prompt = e.target.value
|
||||
console.log(e.target.value)
|
||||
}
|
||||
const onChangeHandlerNegative = (
|
||||
e: React.ChangeEvent<HTMLTextAreaElement>,
|
||||
) => {
|
||||
if (editorEngine == null) {
|
||||
console.log("Editor is null");
|
||||
return;
|
||||
}
|
||||
editorEngine.negative_prompt = e.target.value;
|
||||
console.log(e.target.value);
|
||||
};
|
||||
|
||||
const onChangeHandlerPositive = (e:React.ChangeEvent<HTMLInputElement>) => {
|
||||
if (editorEngine == null) { console.log("Editor is null"); return;}
|
||||
editorEngine.positive_prompt = e.target.value
|
||||
console.log(e.target.value)
|
||||
}
|
||||
const handleChangeViewMode = ()=>{
|
||||
if(dispatchAppUiState!==null){
|
||||
const onChangeHandlerPositive = (
|
||||
e: React.ChangeEvent<HTMLTextAreaElement>,
|
||||
) => {
|
||||
if (editorEngine == null) {
|
||||
console.log("Editor is null");
|
||||
return;
|
||||
}
|
||||
editorEngine.positive_prompt = e.target.value;
|
||||
console.log(e.target.value);
|
||||
};
|
||||
const handleChangeViewMode = () => {
|
||||
if (dispatchAppUiState !== null) {
|
||||
dispatchAppUiState({
|
||||
type: APPUI_ACTION_TYPES.ON_CHANGE_VIEW_MODE,
|
||||
payload: {
|
||||
viewMode: appUiState?.viewMode === APPUI_VIEW_MODES.SIDE_BY_SIDE
|
||||
? APPUI_VIEW_MODES.EDITOR : APPUI_VIEW_MODES.SIDE_BY_SIDE,
|
||||
}
|
||||
})
|
||||
viewMode:
|
||||
appUiState?.viewMode === APPUI_VIEW_MODES.SIDE_BY_SIDE
|
||||
? APPUI_VIEW_MODES.EDITOR
|
||||
: APPUI_VIEW_MODES.SIDE_BY_SIDE,
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
||||
return(
|
||||
<div className="gap-2 w-full h-full overflow-scroll">
|
||||
};
|
||||
return (
|
||||
<div className="h-full w-full gap-2 overflow-scroll">
|
||||
<H4>Select Base Stylizer</H4>
|
||||
<div className="flex gap-2 my-2">
|
||||
<div className="my-2 flex gap-2">
|
||||
<ItemPicker
|
||||
label="Anime"
|
||||
selected={(selection === ArtStyle.Anime2DFlat)}
|
||||
label={ArtStyle.Anime2_5D}
|
||||
selected={selection === ArtStyle.Anime2DFlat}
|
||||
onSelected={handlePickingStylizer}
|
||||
src="/resources/avatars/0.webp"
|
||||
/>
|
||||
<ItemPicker
|
||||
label="Pixel"
|
||||
label={ArtStyle.PixelArt}
|
||||
selected={selection === ArtStyle.PixelArt}
|
||||
onSelected={handlePickingStylizer}
|
||||
src="/resources/avatars/1.webp"
|
||||
/>
|
||||
<ItemPicker
|
||||
label="Pixar"
|
||||
label={ArtStyle.Cartoon3D}
|
||||
selected={selection === ArtStyle.Cartoon3D}
|
||||
onSelected={handlePickingStylizer}
|
||||
src="/resources/avatars/2.webp"
|
||||
/>
|
||||
<ItemPicker
|
||||
label="Stylized"
|
||||
label={ArtStyle.ComicBook}
|
||||
selected={selection === ArtStyle.ComicBook}
|
||||
onSelected={handlePickingStylizer}
|
||||
src="/resources/avatars/3.webp"
|
||||
/>
|
||||
</div>
|
||||
<H4>Enter a Prompt</H4>
|
||||
<div className="flex gap-2 my-2">
|
||||
<div className="my-2 flex gap-2">
|
||||
<Textarea
|
||||
className="w-full h-32"
|
||||
className="h-32 w-full"
|
||||
placeholder="Type here to describe your scene"
|
||||
onChange={onChangeHandlerPositive}
|
||||
/>
|
||||
</div>
|
||||
<H4>Negative Prompt</H4>
|
||||
<div className="flex gap-2 my-2">
|
||||
<div className="my-2 flex gap-2">
|
||||
<Textarea
|
||||
className="w-full h-32"
|
||||
className="h-32 w-full"
|
||||
placeholder="Type here to filter out the things you don't want in the scene"
|
||||
onChange={onChangeHandlerNegative}
|
||||
/>
|
||||
</div>
|
||||
<div className="flex gap-2 mt-6 justify-center">
|
||||
<div className="mt-6 flex justify-center gap-2">
|
||||
<Button onClick={handleChangeViewMode}>
|
||||
{
|
||||
appUiState?.viewMode === APPUI_VIEW_MODES.SIDE_BY_SIDE
|
||||
? "Back to Scene" : "Preview Side by Side"
|
||||
}
|
||||
{appUiState?.viewMode === APPUI_VIEW_MODES.SIDE_BY_SIDE
|
||||
? "Back to Scene"
|
||||
: "Preview Side by Side"}
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
};
|
||||
@@ -51,7 +51,6 @@ export const Timeline = () => {
|
||||
};
|
||||
}, [onDeleteAsk]);
|
||||
|
||||
console.log("timeline");
|
||||
return (
|
||||
<>
|
||||
<LowerPanel>
|
||||
|
||||
@@ -37,7 +37,6 @@ export function useQueueHandler() {
|
||||
console.log("TO TIMELINE", action, data);
|
||||
switch (action) {
|
||||
case toTimelineActions.ADD_KEYFRAME:
|
||||
console.log(1);
|
||||
addKeyframe(data as QueueKeyframe, currentTime.value);
|
||||
break;
|
||||
default:
|
||||
|
||||
@@ -1,19 +1,20 @@
|
||||
import { createContext, Dispatch, ReactNode } from "react";
|
||||
import { AppUiState, AppUiAction } from "../reducers";
|
||||
import { createContext, Dispatch, ReactNode, useReducer } from "react";
|
||||
import {
|
||||
AppUiState,
|
||||
AppUiAction,
|
||||
appUiReducer,
|
||||
appUiInitialStateValues,
|
||||
} from "../reducers";
|
||||
|
||||
export const AppUiContext = createContext<[
|
||||
AppUiState | null,
|
||||
Dispatch<AppUiAction>
|
||||
]>([ null ,()=>{}]);
|
||||
export const AppUiContext = createContext<[AppUiState, Dispatch<AppUiAction>]>([
|
||||
appUiInitialStateValues,
|
||||
() => {},
|
||||
]);
|
||||
|
||||
export const AppUIProvider = ({ children }: { children: ReactNode }) => {
|
||||
const value = useReducer(appUiReducer, appUiInitialStateValues);
|
||||
|
||||
export const AppUIProvider = ({
|
||||
value,
|
||||
children,
|
||||
}:{
|
||||
value:[AppUiState, Dispatch<AppUiAction>],
|
||||
children: ReactNode
|
||||
})=>{
|
||||
return (
|
||||
<AppUiContext.Provider value={value}>{children}</AppUiContext.Provider>
|
||||
);
|
||||
}
|
||||
};
|
||||
@@ -5,31 +5,38 @@ import {
|
||||
Keyframe,
|
||||
} from "~/pages/PageEnigma/models/track";
|
||||
import {
|
||||
addCameraKeyframe,
|
||||
addCharacterKeyframe,
|
||||
addObjectKeyframe,
|
||||
deleteCameraKeyframe,
|
||||
deleteCharacterKeyframe,
|
||||
deleteObjectKeyframe,
|
||||
} from "~/pages/PageEnigma/store";
|
||||
|
||||
const ADD_KEYFRAME: Record<
|
||||
ClipGroup,
|
||||
(keyframe: QueueKeyframe, offset: number) => void
|
||||
> = {
|
||||
[ClipGroup.CAMERA]: addCameraKeyframe,
|
||||
[ClipGroup.CHARACTER]: addCharacterKeyframe,
|
||||
[ClipGroup.OBJECT]: addObjectKeyframe,
|
||||
[ClipGroup.GLOBAL_AUDIO]: () => {},
|
||||
};
|
||||
|
||||
const DELETE_KEYFRAME: Record<ClipGroup, (keyframe: Keyframe) => void> = {
|
||||
[ClipGroup.CAMERA]: deleteCameraKeyframe,
|
||||
[ClipGroup.CHARACTER]: deleteCharacterKeyframe,
|
||||
[ClipGroup.OBJECT]: deleteObjectKeyframe,
|
||||
[ClipGroup.GLOBAL_AUDIO]: () => {},
|
||||
};
|
||||
|
||||
export default function useUpdateKeyframe() {
|
||||
const addKeyframe = useCallback((keyframe: QueueKeyframe, offset: number) => {
|
||||
console.log(keyframe, offset);
|
||||
if (keyframe.group === ClipGroup.OBJECT) {
|
||||
console.log(2);
|
||||
addObjectKeyframe(keyframe, offset);
|
||||
}
|
||||
if (keyframe.group === ClipGroup.CHARACTER) {
|
||||
addCharacterKeyframe(keyframe, offset);
|
||||
}
|
||||
ADD_KEYFRAME[keyframe.group](keyframe, offset);
|
||||
}, []);
|
||||
|
||||
const deleteKeyframe = useCallback((keyframe: Keyframe) => {
|
||||
if (keyframe.group === ClipGroup.OBJECT) {
|
||||
deleteObjectKeyframe(keyframe);
|
||||
}
|
||||
if (keyframe.group === ClipGroup.CHARACTER) {
|
||||
deleteCharacterKeyframe(keyframe);
|
||||
}
|
||||
DELETE_KEYFRAME[keyframe.group](keyframe);
|
||||
}, []);
|
||||
|
||||
return {
|
||||
|
||||
+214
-127
@@ -3,7 +3,7 @@ import { OrbitControls } from "three/addons/controls/OrbitControls.js";
|
||||
import { FreeCam } from "./free_cam";
|
||||
import { TransformControls } from "three/addons/controls/TransformControls.js";
|
||||
import Scene from "./scene.js";
|
||||
import { APIManager, ArtStyle, Visibility } from "./api_manager.js";
|
||||
import { APIManager, ArtStyle, Visibility } from "./api_manager.js";
|
||||
import { EffectComposer } from "three/addons/postprocessing/EffectComposer.js";
|
||||
import { RenderPass } from "three/addons/postprocessing/RenderPass.js";
|
||||
import { OutlinePass } from "three/addons/postprocessing/OutlinePass.js";
|
||||
@@ -101,7 +101,7 @@ class Editor {
|
||||
|
||||
positive_prompt: string;
|
||||
negative_prompt: string;
|
||||
art_style:ArtStyle;
|
||||
art_style: ArtStyle;
|
||||
// Default params.
|
||||
constructor() {
|
||||
console.log(
|
||||
@@ -111,9 +111,8 @@ class Editor {
|
||||
// Special async react lifecycle fix
|
||||
// For making sure the editor only gets created onece.
|
||||
this.can_initialize = false;
|
||||
let one_element = document.getElementById("created-one-element");
|
||||
this.can_initialize = true;
|
||||
let newElement = document.createElement("div");
|
||||
const newElement = document.createElement("div");
|
||||
newElement.id = "created-one-element";
|
||||
document.body.appendChild(newElement);
|
||||
// life cycle fix
|
||||
@@ -198,9 +197,10 @@ class Editor {
|
||||
this.current_scene_glb_media_token = null;
|
||||
|
||||
// stylization parameters
|
||||
this.positive_prompt = "((masterpiece, best quality, 8K, detailed)), colorful, epic, fantasy, (fox, red fox:1.2), no humans, 1other, ((koi pond)), outdoors, pond, rocks, stones, koi fish, ((watercolor))), lilypad, fish swimming around."
|
||||
this.negative_prompt = ""
|
||||
this.art_style = ArtStyle.Anime2DFlat
|
||||
this.positive_prompt =
|
||||
"((masterpiece, best quality, 8K, detailed)), colorful, epic, fantasy, (fox, red fox:1.2), no humans, 1other, ((koi pond)), outdoors, pond, rocks, stones, koi fish, ((watercolor))), lilypad, fish swimming around.";
|
||||
this.negative_prompt = "";
|
||||
this.art_style = ArtStyle.Anime2DFlat;
|
||||
}
|
||||
|
||||
initialize(config: any) {
|
||||
@@ -212,7 +212,6 @@ class Editor {
|
||||
// type: APPUI_ACTION_TYPES.SHOW_EDITOR_LOADER
|
||||
// });
|
||||
|
||||
|
||||
if (this.can_initialize == false) {
|
||||
console.log("Editor Already Initialized");
|
||||
return;
|
||||
@@ -224,15 +223,20 @@ class Editor {
|
||||
this.canvasRenderCamReference = document.getElementById("camera-view");
|
||||
|
||||
// Base width and height.
|
||||
let width = this.canvReference.width;
|
||||
let height = this.canvReference.height;
|
||||
const width = this.canvReference.width;
|
||||
const height = this.canvReference.height;
|
||||
// Sets up camera and base position.
|
||||
this.camera = new THREE.PerspectiveCamera(70, width / height, 0.15, 30);
|
||||
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.15, 30);
|
||||
this.render_camera = new THREE.PerspectiveCamera(
|
||||
70,
|
||||
width / height,
|
||||
0.15,
|
||||
30,
|
||||
);
|
||||
|
||||
// Base WebGL render and clock for delta time.
|
||||
this.renderer = new THREE.WebGLRenderer({
|
||||
@@ -291,9 +295,21 @@ class Editor {
|
||||
|
||||
this._test_demo();
|
||||
|
||||
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.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,
|
||||
);
|
||||
|
||||
// saving state of the scene
|
||||
this.current_scene_media_token = null;
|
||||
@@ -317,7 +333,13 @@ class Editor {
|
||||
|
||||
this.cam_obj = this.activeScene.get_object_by_name("::CAM::");
|
||||
if (this.cam_obj) {
|
||||
this.addTransformClipBase("Camera Object", "camera", this.cam_obj, 0, 150);
|
||||
this.addTransformClipBase(
|
||||
"Camera Object",
|
||||
"camera",
|
||||
this.cam_obj,
|
||||
0,
|
||||
150,
|
||||
);
|
||||
}
|
||||
|
||||
console.log(this.cam_obj);
|
||||
@@ -338,22 +360,27 @@ class Editor {
|
||||
|
||||
// Token comes in from the front end to load the scene from the site.
|
||||
public async testBatchRequest() {
|
||||
const result = await this.api_manager.getMediaBatch(["m_8fmp9hrvsqcryzka1fra597kg42s50", "m_z4jzbst3xfh64h0qn4bqh4afenfps9"]);
|
||||
const result = await this.api_manager.getMediaBatch([
|
||||
"m_8fmp9hrvsqcryzka1fra597kg42s50",
|
||||
"m_z4jzbst3xfh64h0qn4bqh4afenfps9",
|
||||
]);
|
||||
console.log(result);
|
||||
}
|
||||
|
||||
public async testTestTimelineEvents() {
|
||||
}
|
||||
public async testTestTimelineEvents() {}
|
||||
|
||||
public async testStylizeRequest() {
|
||||
const result = await this.api_manager.stylizeVideo(
|
||||
"mu_6wy1570a0c3c0tpkkncf4tsvb5234",
|
||||
this.art_style,
|
||||
this.positive_prompt,
|
||||
this.negative_prompt,
|
||||
Visibility.Public).catch(error=> {
|
||||
console.log(error);
|
||||
});
|
||||
const result = await this.api_manager
|
||||
.stylizeVideo(
|
||||
"mu_6wy1570a0c3c0tpkkncf4tsvb5234",
|
||||
this.art_style,
|
||||
this.positive_prompt,
|
||||
this.negative_prompt,
|
||||
Visibility.Public,
|
||||
)
|
||||
.catch((error) => {
|
||||
console.log(error);
|
||||
});
|
||||
console.log(result);
|
||||
}
|
||||
|
||||
@@ -378,7 +405,9 @@ class Editor {
|
||||
|
||||
const loaded_scene = load_scene_state_response.data["scene"];
|
||||
|
||||
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"];
|
||||
@@ -395,9 +424,9 @@ class Editor {
|
||||
child.parent = this.activeScene.scene;
|
||||
|
||||
if (child.type == "DirectionalLight") {
|
||||
let pos = child.position;
|
||||
let rot = child.rotation;
|
||||
let light = this.activeScene._create_base_lighting();
|
||||
const pos = child.position;
|
||||
const rot = child.rotation;
|
||||
const light = this.activeScene._create_base_lighting();
|
||||
light.position.set(pos.x, pos.y, pos.z);
|
||||
light.rotation.set(rot.x, rot.y, rot.z);
|
||||
this.activeScene.scene.remove(child);
|
||||
@@ -468,7 +497,7 @@ class Editor {
|
||||
async _serialize_timeline() {
|
||||
// note the database from the server is the source of truth for all the data.
|
||||
// Test code here
|
||||
let object: any = await this.activeScene.load_glb(
|
||||
const object: any = await this.activeScene.load_glb(
|
||||
"./resources/models/fox/fox.glb",
|
||||
);
|
||||
|
||||
@@ -494,7 +523,16 @@ class Editor {
|
||||
|
||||
// media id for this is up in the air but when a path is created you should be able to store and delete it
|
||||
this.timeline.addPlayableClip(
|
||||
new ClipUI(1.0, "transform", "character", "clip2", object.uuid, object.uuid, 0, 150),
|
||||
new ClipUI(
|
||||
1.0,
|
||||
"transform",
|
||||
"character",
|
||||
"clip2",
|
||||
object.uuid,
|
||||
object.uuid,
|
||||
0,
|
||||
150,
|
||||
),
|
||||
);
|
||||
|
||||
// media id for this as well it can be downloaded
|
||||
@@ -519,7 +557,7 @@ class Editor {
|
||||
|
||||
switchCameraView() {
|
||||
this.camera_person_mode = !this.camera_person_mode;
|
||||
console.log("camera")
|
||||
console.log("camera");
|
||||
if (this.cam_obj) {
|
||||
if (this.camera_person_mode) {
|
||||
this.last_cam_pos.copy(this.camera.position);
|
||||
@@ -536,12 +574,11 @@ class Editor {
|
||||
if (this.cameraViewControls) {
|
||||
this.cameraViewControls.enabled = true;
|
||||
}
|
||||
this.cam_obj.scale.set(0,0,0);
|
||||
this.cam_obj.scale.set(0, 0, 0);
|
||||
if (this.activeScene.hot_items) {
|
||||
this.activeScene.hot_items.forEach((element) => {
|
||||
element.visible = false;
|
||||
});
|
||||
|
||||
}
|
||||
} else {
|
||||
this.camera.position.copy(this.last_cam_pos);
|
||||
@@ -555,7 +592,7 @@ class Editor {
|
||||
if (this.cameraViewControls) {
|
||||
this.cameraViewControls.enabled = false;
|
||||
}
|
||||
this.cam_obj.scale.set(1,1,1);
|
||||
this.cam_obj.scale.set(1, 1, 1);
|
||||
if (this.activeScene.hot_items) {
|
||||
this.activeScene.hot_items.forEach((element) => {
|
||||
element.visible = true;
|
||||
@@ -579,7 +616,7 @@ class Editor {
|
||||
group,
|
||||
name,
|
||||
object.uuid, // object id here ...
|
||||
object.uuid,// Need to change to media id ....
|
||||
object.uuid, // Need to change to media id ....
|
||||
offset,
|
||||
length,
|
||||
),
|
||||
@@ -590,7 +627,7 @@ class Editor {
|
||||
async _test_demo() {
|
||||
// note the database from the server is the source of truth for all the data.
|
||||
// Test code here
|
||||
let object: any = await this.activeScene.load_glb(
|
||||
const object: any = await this.activeScene.load_glb(
|
||||
"./resources/models/fox/fox.glb",
|
||||
);
|
||||
|
||||
@@ -651,8 +688,8 @@ class Editor {
|
||||
|
||||
// Configure post processing.
|
||||
_configurePostProcessing() {
|
||||
let width = this.canvReference.width;
|
||||
let height = this.canvReference.height;
|
||||
const width = this.canvReference.width;
|
||||
const height = this.canvReference.height;
|
||||
|
||||
if (this.renderer == undefined || this.camera == undefined) {
|
||||
return;
|
||||
@@ -714,7 +751,7 @@ class Editor {
|
||||
}
|
||||
|
||||
create_parim(name: string) {
|
||||
let uuid = this.activeScene.instantiate(name);
|
||||
const uuid = this.activeScene.instantiate(name);
|
||||
}
|
||||
|
||||
renderMode() {
|
||||
@@ -756,11 +793,16 @@ class Editor {
|
||||
|
||||
// Basicly Unity 3D's update loop.
|
||||
updateLoop(time: number) {
|
||||
|
||||
if (this.cam_obj == undefined) {
|
||||
this.cam_obj = this.activeScene.get_object_by_name("::CAM::");
|
||||
if (this.cam_obj) {
|
||||
this.addTransformClipBase("Camera Object", "camera", this.cam_obj, 0, 150)
|
||||
this.addTransformClipBase(
|
||||
"Camera Object",
|
||||
"camera",
|
||||
this.cam_obj,
|
||||
0,
|
||||
150,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -773,7 +815,7 @@ class Editor {
|
||||
return;
|
||||
}
|
||||
|
||||
let delta_time = this.clock.getDelta();
|
||||
const delta_time = this.clock.getDelta();
|
||||
|
||||
if (this.cameraViewControls && this.camera_person_mode) {
|
||||
this.cameraViewControls.update(5 * delta_time);
|
||||
@@ -813,13 +855,12 @@ class Editor {
|
||||
}
|
||||
|
||||
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';
|
||||
const video_og = itteration + "tmp.mp4";
|
||||
const wav_name = itteration + "tmp.wav";
|
||||
const new_video = itteration + 1 + "tmp.mp4";
|
||||
let startFrame = clip.offset;
|
||||
let endFrame = clip.length;
|
||||
|
||||
|
||||
if (endFrame > this.timeline.timeline_limit) {
|
||||
endFrame = this.timeline.timeline_limit;
|
||||
}
|
||||
@@ -829,42 +870,72 @@ class Editor {
|
||||
|
||||
const startTime = startFrame / this.cap_fps;
|
||||
const endTime = endFrame / this.cap_fps;
|
||||
let end = endTime - startTime;
|
||||
const end = endTime - startTime;
|
||||
|
||||
let duration = this.timeline.timeline_limit / 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',
|
||||
const audioSegment = "as_" + wav_name;
|
||||
await ffmpeg.FS(
|
||||
"writeFile",
|
||||
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 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', `${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`)
|
||||
"-i",
|
||||
video_og,
|
||||
"-max_muxing_queue_size",
|
||||
"999999",
|
||||
`${itteration}empty_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)
|
||||
"-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(compile_audio: boolean = true) {
|
||||
this.renderMode();
|
||||
let ffmpeg = createFFmpeg({ log: true });
|
||||
const ffmpeg = createFFmpeg({ log: true });
|
||||
await ffmpeg.load();
|
||||
for (let index = 0; index < this.frame_buffer.length; index++) {
|
||||
const element = this.frame_buffer[index];
|
||||
@@ -890,10 +961,9 @@ class Editor {
|
||||
"-c:a",
|
||||
"aac", // Specify audio codec (optional, but recommended for MP4)
|
||||
"-shortest", // Ensure output duration matches the shortest stream (video or audio)
|
||||
"0tmp.mp4"
|
||||
"0tmp.mp4",
|
||||
);
|
||||
|
||||
|
||||
let itteration = 0;
|
||||
|
||||
if (compile_audio) {
|
||||
@@ -902,10 +972,10 @@ class Editor {
|
||||
await this.convertAudioClip(itteration, ffmpeg, clip);
|
||||
itteration += 1;
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
let output = await ffmpeg.FS("readFile", itteration + "tmp.mp4");
|
||||
const 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);
|
||||
@@ -918,11 +988,9 @@ class Editor {
|
||||
URL.revokeObjectURL(url);
|
||||
document.body.removeChild(downloadLink);
|
||||
|
||||
|
||||
let data = await this.api_manager.uploadMedia(blob, "tmp.wav");
|
||||
const data = await this.api_manager.uploadMedia(blob, "tmp.wav");
|
||||
console.log(data);
|
||||
// Create a link to download the file
|
||||
|
||||
}
|
||||
|
||||
async generateFrame() {
|
||||
@@ -931,7 +999,7 @@ class Editor {
|
||||
this.generating_preview = true;
|
||||
this.activeScene.renderMode(true);
|
||||
if (this.activeScene.hot_items) {
|
||||
this.activeScene.hot_items.forEach(element => {
|
||||
this.activeScene.hot_items.forEach((element) => {
|
||||
element.visible = false;
|
||||
});
|
||||
}
|
||||
@@ -943,37 +1011,41 @@ class Editor {
|
||||
|
||||
this.renderer.setSize(this.render_width, this.render_height);
|
||||
this.renderer.render(this.activeScene.scene, this.render_camera);
|
||||
let imgData = this.renderer.domElement.toDataURL();
|
||||
const imgData = this.renderer.domElement.toDataURL();
|
||||
this.activeScene.renderMode(false);
|
||||
this.onWindowResize();
|
||||
|
||||
const rawPreview: HTMLVideoElement | null = document.getElementById("raw-preview") as HTMLVideoElement;
|
||||
const rawPreview: HTMLVideoElement | null = document.getElementById(
|
||||
"raw-preview",
|
||||
) as HTMLVideoElement;
|
||||
if (rawPreview) {
|
||||
rawPreview.src = imgData;
|
||||
|
||||
|
||||
let ffmpeg = createFFmpeg({ log: false });
|
||||
const ffmpeg = createFFmpeg({ log: false });
|
||||
await ffmpeg.load();
|
||||
await ffmpeg.FS(
|
||||
"writeFile",
|
||||
`render.png`,
|
||||
await fetchFile(imgData),
|
||||
);
|
||||
await ffmpeg.run('-i', `render.png`, 'render.mp4');
|
||||
let output = await ffmpeg.FS("readFile", 'render.mp4');
|
||||
await ffmpeg.FS("writeFile", `render.png`, await fetchFile(imgData));
|
||||
await ffmpeg.run("-i", `render.png`, "render.mp4");
|
||||
const output = await ffmpeg.FS("readFile", "render.mp4");
|
||||
const blob = new Blob([output.buffer], { type: "video/mp4" });
|
||||
|
||||
let url = await this.api_manager.uploadMediaFrameGeneration(blob, "render.mp4", "anime_ghibli", "((masterpiece, best quality, 8K, detailed)), colorful, epic, fantasy, (fox, red fox:1.2), no humans, 1other, ((koi pond)), outdoors, pond, rocks, stones, koi fish, ((watercolor))), lilypad, fish swimming around.", "");
|
||||
const url = await this.api_manager.uploadMediaFrameGeneration(
|
||||
blob,
|
||||
"render.mp4",
|
||||
"anime_ghibli",
|
||||
"((masterpiece, best quality, 8K, detailed)), colorful, epic, fantasy, (fox, red fox:1.2), no humans, 1other, ((koi pond)), outdoors, pond, rocks, stones, koi fish, ((watercolor))), lilypad, fish swimming around.",
|
||||
"",
|
||||
);
|
||||
console.log(url);
|
||||
|
||||
const stylePreview: HTMLVideoElement | null = document.getElementById("stylized-preview") as HTMLVideoElement;
|
||||
const stylePreview: HTMLVideoElement | null = document.getElementById(
|
||||
"stylized-preview",
|
||||
) as HTMLVideoElement;
|
||||
if (stylePreview) {
|
||||
stylePreview.src = url;
|
||||
stylePreview.width = rawPreview.width;
|
||||
stylePreview.height = rawPreview.height;
|
||||
}
|
||||
else {
|
||||
console.log("No style preview window.")
|
||||
} else {
|
||||
console.log("No style preview window.");
|
||||
}
|
||||
|
||||
this.generating_preview = false;
|
||||
@@ -981,9 +1053,8 @@ class Editor {
|
||||
return new Promise((resolve, reject) => {
|
||||
resolve(url);
|
||||
});
|
||||
}
|
||||
else {
|
||||
console.log("No raw preview window.")
|
||||
} else {
|
||||
console.log("No raw preview window.");
|
||||
}
|
||||
this.generating_preview = false;
|
||||
}
|
||||
@@ -991,14 +1062,16 @@ class Editor {
|
||||
|
||||
generateVideo() {
|
||||
console.log("Generating video...");
|
||||
if (this.rendering) { return; }
|
||||
if (this.rendering) {
|
||||
return;
|
||||
}
|
||||
this.startPlayback();
|
||||
this.frame_buffer = [];
|
||||
this.render_timer = 0;
|
||||
this.rendering = true;
|
||||
this.activeScene.renderMode(this.rendering);
|
||||
if (this.activeScene.hot_items) {
|
||||
this.activeScene.hot_items.forEach(element => {
|
||||
this.activeScene.hot_items.forEach((element) => {
|
||||
element.visible = false;
|
||||
});
|
||||
}
|
||||
@@ -1046,7 +1119,7 @@ class Editor {
|
||||
|
||||
if (this.rendering && this.renderer && this.clock) {
|
||||
this.playback_location++;
|
||||
let imgData = this.renderer.domElement.toDataURL();
|
||||
const imgData = this.renderer.domElement.toDataURL();
|
||||
this.frame_buffer.push(imgData);
|
||||
this.render_timer += this.clock.getDelta();
|
||||
if (this.timeline.is_playing == false) {
|
||||
@@ -1060,35 +1133,47 @@ class Editor {
|
||||
}
|
||||
|
||||
updateSelectedUI() {
|
||||
if (this.selected == undefined) { return; }
|
||||
if (this.selected == undefined) {
|
||||
return;
|
||||
}
|
||||
|
||||
const pos = this.selected.position;
|
||||
const rot = this.selected.rotation;
|
||||
const scale = this.selected.scale;
|
||||
|
||||
let pos = this.selected.position;
|
||||
let rot = this.selected.rotation;
|
||||
let scale = this.selected.scale;
|
||||
|
||||
this.dispatchAppUiState({
|
||||
type: APPUI_ACTION_TYPES.SHOW_CONTROLPANELS_SCENEOBJECT,
|
||||
payload: {
|
||||
currentSceneObject: {
|
||||
group: "object", // TODO: add meta data to determine what it is a camera or a object or a character into prefab clips
|
||||
object_uuid: this.selected.uuid,
|
||||
object_name: this.selected.name,
|
||||
version: this.version,
|
||||
objectVectors: {
|
||||
position: { x: parseFloat(pos.x.toFixed(2)), y: parseFloat(pos.y.toFixed(2)), z: parseFloat(pos.z.toFixed(2)) },
|
||||
rotation: { x: parseFloat(rot.x.toFixed(2)), y: parseFloat(rot.y.toFixed(2)), z: parseFloat(rot.z.toFixed(2)) },
|
||||
scale: { x: parseFloat(scale.x.toFixed(2)), y: parseFloat(scale.y.toFixed(2)), z: parseFloat(scale.z.toFixed(2)) },
|
||||
}
|
||||
}
|
||||
}
|
||||
group: "object", // TODO: add meta data to determine what it is a camera or a object or a character into prefab clips
|
||||
object_uuid: this.selected.uuid,
|
||||
object_name: this.selected.name,
|
||||
version: this.version,
|
||||
objectVectors: {
|
||||
position: {
|
||||
x: parseFloat(pos.x.toFixed(2)),
|
||||
y: parseFloat(pos.y.toFixed(2)),
|
||||
z: parseFloat(pos.z.toFixed(2)),
|
||||
},
|
||||
rotation: {
|
||||
x: parseFloat(rot.x.toFixed(2)),
|
||||
y: parseFloat(rot.y.toFixed(2)),
|
||||
z: parseFloat(rot.z.toFixed(2)),
|
||||
},
|
||||
scale: {
|
||||
x: parseFloat(scale.x.toFixed(2)),
|
||||
y: parseFloat(scale.y.toFixed(2)),
|
||||
z: parseFloat(scale.z.toFixed(2)),
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
// Automaticly resize scene.
|
||||
onWindowResize() {
|
||||
// Calculate the maximum possible dimensions while maintaining the aspect ratio
|
||||
let width = window.innerWidth; // / aspect_adjust
|
||||
let height = window.innerHeight; // / aspectRatio
|
||||
const width = window.innerWidth; // / aspect_adjust
|
||||
const height = window.innerHeight; // / aspectRatio
|
||||
|
||||
if (this.camera == undefined || this.renderer == undefined) {
|
||||
return;
|
||||
@@ -1103,7 +1188,9 @@ class Editor {
|
||||
this.composer.setSize(width, height);
|
||||
}
|
||||
|
||||
if (this.render_camera == undefined) { return; }
|
||||
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;
|
||||
@@ -1148,7 +1235,7 @@ class Editor {
|
||||
}
|
||||
|
||||
this.raycaster.setFromCamera(this.mouse, this.camera);
|
||||
let interactable: any[] = [];
|
||||
const interactable: any[] = [];
|
||||
this.activeScene.scene.children.forEach((child: THREE.Object3D) => {
|
||||
if (child.name != "") {
|
||||
if (child.type == "Mesh" || child.type == "Object3D") {
|
||||
@@ -1156,7 +1243,7 @@ class Editor {
|
||||
}
|
||||
}
|
||||
});
|
||||
let intersects = this.raycaster.intersectObjects(interactable, true);
|
||||
const intersects = this.raycaster.intersectObjects(interactable, true);
|
||||
|
||||
if (intersects.length > 0) {
|
||||
if (intersects[0].object.type != "GridHelper") {
|
||||
@@ -1180,7 +1267,7 @@ class Editor {
|
||||
} else if (this.transform_interaction == false) {
|
||||
this.removeTransformControls();
|
||||
this.dispatchAppUiState({
|
||||
type: APPUI_ACTION_TYPES.HIDE_CONTROLPANELS_SCENEOBJECT
|
||||
type: APPUI_ACTION_TYPES.HIDE_CONTROLPANELS_SCENEOBJECT,
|
||||
});
|
||||
} else {
|
||||
this.transform_interaction = false;
|
||||
|
||||
@@ -1,107 +1,95 @@
|
||||
import { State, Action, ACTION_TYPES} from './types';
|
||||
import { State, Action, ACTION_TYPES } from "./types";
|
||||
|
||||
export function reducer(state: State, action: Action): State {
|
||||
switch(action.type){
|
||||
|
||||
case ACTION_TYPES.SHOW_CONTROLPANELS_SCENEOBJECT:{
|
||||
return{
|
||||
switch (action.type) {
|
||||
case ACTION_TYPES.SHOW_CONTROLPANELS_SCENEOBJECT: {
|
||||
console.log("pay", action.payload);
|
||||
return {
|
||||
...state,
|
||||
currentSceneObject: {
|
||||
group:action.payload.currentSceneObject.group,
|
||||
object_name:action.payload.currentSceneObject.object_name,
|
||||
object_uuid:action.payload.currentSceneObject.object_uuid,
|
||||
version:action.payload.currentSceneObject.version,
|
||||
controlPanel: {
|
||||
isShowing: true,
|
||||
objectVectors: {...action.payload.currentSceneObject.objectVectors},
|
||||
currentSceneObject: action.payload,
|
||||
},
|
||||
}
|
||||
};
|
||||
}
|
||||
case ACTION_TYPES.UPDATE_CONTROLPANELS_SCENEOBJECT:{
|
||||
return{
|
||||
case ACTION_TYPES.UPDATE_CONTROLPANELS_SCENEOBJECT: {
|
||||
return {
|
||||
...state,
|
||||
currentSceneObject: {
|
||||
group:action.payload.currentSceneObject.group,
|
||||
object_name:action.payload.currentSceneObject.object_name,
|
||||
object_uuid:action.payload.currentSceneObject.object_uuid,
|
||||
version:action.payload.currentSceneObject.version,
|
||||
isShowing: state.currentSceneObject.isShowing,
|
||||
objectVectors: {...action.payload.currentSceneObject.objectVectors},
|
||||
controlPanel: {
|
||||
isShowing: state.controlPanel.isShowing,
|
||||
currentSceneObject: action.payload,
|
||||
},
|
||||
}
|
||||
};
|
||||
}
|
||||
case ACTION_TYPES.HIDE_CONTROLPANELS_SCENEOBJECT:{
|
||||
return{
|
||||
case ACTION_TYPES.HIDE_CONTROLPANELS_SCENEOBJECT: {
|
||||
return {
|
||||
...state,
|
||||
currentSceneObject: {
|
||||
group:action.payload.currentSceneObject.group,
|
||||
object_name:action.payload.currentSceneObject.object_name,
|
||||
object_uuid:action.payload.currentSceneObject.object_uuid,
|
||||
version:action.payload.currentSceneObject.version,
|
||||
controlPanel: {
|
||||
...state.controlPanel,
|
||||
isShowing: false,
|
||||
objectVectors: state.currentSceneObject.objectVectors,
|
||||
},
|
||||
}
|
||||
};
|
||||
}
|
||||
case ACTION_TYPES.SHOW_EDITOR_LOADER:{
|
||||
return{
|
||||
case ACTION_TYPES.SHOW_EDITOR_LOADER: {
|
||||
return {
|
||||
...state,
|
||||
showEditorLoader: {
|
||||
isShowing: true,
|
||||
message: action.payload?.showEditorLoader.message,
|
||||
},
|
||||
}
|
||||
};
|
||||
}
|
||||
case ACTION_TYPES.HIDE_EDITOR_LOADER:{
|
||||
return{
|
||||
case ACTION_TYPES.HIDE_EDITOR_LOADER: {
|
||||
return {
|
||||
...state,
|
||||
showEditorLoader: {
|
||||
isShowing: false,
|
||||
message: state.showEditorLoader.message
|
||||
message: state.showEditorLoader.message,
|
||||
},
|
||||
}
|
||||
};
|
||||
}
|
||||
case ACTION_TYPES.SHOW_EDITOR_LOADINGBAR:{
|
||||
return{
|
||||
case ACTION_TYPES.SHOW_EDITOR_LOADINGBAR: {
|
||||
return {
|
||||
...state,
|
||||
showEditorLoadingBar: {
|
||||
...action.payload?.showEditorLoadingBar,
|
||||
isShowing: true,
|
||||
},
|
||||
}
|
||||
};
|
||||
}
|
||||
case ACTION_TYPES.UPDATE_EDITOR_LOADINGBAR:{
|
||||
return{
|
||||
case ACTION_TYPES.UPDATE_EDITOR_LOADINGBAR: {
|
||||
return {
|
||||
...state,
|
||||
showEditorLoadingBar: {
|
||||
...state.showEditorLoadingBar,
|
||||
...action.payload?.showEditorLoadingBar,
|
||||
},
|
||||
}
|
||||
};
|
||||
}
|
||||
case ACTION_TYPES.HIDE_EDITOR_LOADINGBAR:{
|
||||
return{
|
||||
case ACTION_TYPES.HIDE_EDITOR_LOADINGBAR: {
|
||||
return {
|
||||
...state,
|
||||
showEditorLoadingBar: {
|
||||
...state.showEditorLoadingBar,
|
||||
isShowing: false,
|
||||
},
|
||||
}
|
||||
};
|
||||
}
|
||||
case ACTION_TYPES.ON_TIMELINE_RESIZE:{
|
||||
return{
|
||||
case ACTION_TYPES.ON_TIMELINE_RESIZE: {
|
||||
return {
|
||||
...state,
|
||||
timelineHeight: action.payload.timelineHeight,
|
||||
}
|
||||
};
|
||||
}
|
||||
case ACTION_TYPES.ON_CHANGE_VIEW_MODE:{
|
||||
case ACTION_TYPES.ON_CHANGE_VIEW_MODE: {
|
||||
console.log(action);
|
||||
return{
|
||||
return {
|
||||
...state,
|
||||
viewMode: action.payload.viewMode
|
||||
}
|
||||
viewMode: action.payload.viewMode,
|
||||
};
|
||||
}
|
||||
default:{
|
||||
default: {
|
||||
return state; //no change
|
||||
}
|
||||
}// end switch
|
||||
} // end switch
|
||||
}
|
||||
@@ -1,37 +1,41 @@
|
||||
import { Simple3DVector } from "../../datastructures/common";
|
||||
import { ClipGroup } from "../../models/track";
|
||||
export enum VIEW_MODES {
|
||||
EDITOR = 'editor',
|
||||
SIDE_BY_SIDE = 'side-by-side'
|
||||
};
|
||||
EDITOR = "editor",
|
||||
SIDE_BY_SIDE = "side-by-side",
|
||||
}
|
||||
|
||||
type ViewModes = VIEW_MODES.EDITOR | VIEW_MODES.SIDE_BY_SIDE;
|
||||
|
||||
export type ControlPanel = {
|
||||
isShowing: boolean;
|
||||
currentSceneObject: SceneObject;
|
||||
};
|
||||
export type SceneObject = {
|
||||
group: ClipGroup; // TODO: add meta data to determine what it is a camera or a object or a character into prefab clips
|
||||
object_uuid: string;
|
||||
object_name: string;
|
||||
version: string;
|
||||
objectVectors: Simple3DVector;
|
||||
};
|
||||
|
||||
export type State = {
|
||||
viewMode: ViewModes;
|
||||
timelineHeight: number;
|
||||
showEditorLoader: {
|
||||
isShowing:boolean;
|
||||
message?:string;
|
||||
isShowing: boolean;
|
||||
message?: string;
|
||||
};
|
||||
showEditorLoadingBar:{
|
||||
showEditorLoadingBar: {
|
||||
isShowing: boolean;
|
||||
label?: string;
|
||||
message?: string;
|
||||
progress?: number;
|
||||
useFakeTimer?: number;
|
||||
}
|
||||
currentSceneObject:{
|
||||
group: ClipGroup, // TODO: add meta data to determine what it is a camera or a object or a character into prefab clips
|
||||
object_uuid: string,
|
||||
object_name: string,
|
||||
version: string
|
||||
isShowing: boolean;
|
||||
objectVectors: Simple3DVector;
|
||||
}
|
||||
};
|
||||
controlPanel: ControlPanel;
|
||||
};
|
||||
|
||||
|
||||
export enum ACTION_TYPES {
|
||||
ON_TIMELINE_RESIZE = "on_timeline_resize",
|
||||
ON_CHANGE_VIEW_MODE = "on_change_view_mode",
|
||||
@@ -43,86 +47,61 @@ export enum ACTION_TYPES {
|
||||
SHOW_CONTROLPANELS_SCENEOBJECT = "show_controlpanels_sceneobject",
|
||||
UPDATE_CONTROLPANELS_SCENEOBJECT = "update_controlpanels_sceneobject",
|
||||
HIDE_CONTROLPANELS_SCENEOBJECT = "hide_controlpanels_sceneobject",
|
||||
};
|
||||
}
|
||||
|
||||
export type Action =
|
||||
| { // Not sure why we need this but type script won't stop complaning fix wil.
|
||||
type: ACTION_TYPES.HIDE_CONTROLPANELS_SCENEOBJECT,
|
||||
payload:{
|
||||
currentSceneObject: {
|
||||
group: ClipGroup,
|
||||
object_uuid: string,
|
||||
object_name: string,
|
||||
version: string,
|
||||
objectVectors: Simple3DVector;
|
||||
| {
|
||||
// Not sure why we need this but type script won't stop complaning fix wil.
|
||||
type: ACTION_TYPES.HIDE_CONTROLPANELS_SCENEOBJECT;
|
||||
}
|
||||
| {
|
||||
type: ACTION_TYPES.UPDATE_CONTROLPANELS_SCENEOBJECT;
|
||||
payload: SceneObject;
|
||||
}
|
||||
| {
|
||||
type: ACTION_TYPES.SHOW_CONTROLPANELS_SCENEOBJECT;
|
||||
payload: SceneObject;
|
||||
}
|
||||
| { type: ACTION_TYPES.HIDE_EDITOR_LOADER }
|
||||
| {
|
||||
type: ACTION_TYPES.SHOW_EDITOR_LOADER;
|
||||
payload?: {
|
||||
showEditorLoader: {
|
||||
message: string | undefined;
|
||||
};
|
||||
};
|
||||
}
|
||||
}
|
||||
| { type: ACTION_TYPES.HIDE_EDITOR_LOADINGBAR }
|
||||
| {
|
||||
type: ACTION_TYPES.UPDATE_CONTROLPANELS_SCENEOBJECT,
|
||||
payload:{
|
||||
currentSceneObject: {
|
||||
group: ClipGroup,
|
||||
object_uuid: string,
|
||||
object_name: string,
|
||||
version: string,
|
||||
objectVectors: Simple3DVector;
|
||||
};
|
||||
}
|
||||
}
|
||||
| {
|
||||
type: ACTION_TYPES.SHOW_CONTROLPANELS_SCENEOBJECT,
|
||||
payload:{
|
||||
currentSceneObject: {
|
||||
group: ClipGroup,
|
||||
object_uuid: string,
|
||||
object_name: string,
|
||||
version: string,
|
||||
objectVectors: Simple3DVector;
|
||||
};
|
||||
}
|
||||
}
|
||||
| {type: ACTION_TYPES.HIDE_EDITOR_LOADER,}
|
||||
| {
|
||||
type: ACTION_TYPES.SHOW_EDITOR_LOADER,
|
||||
payload?:{
|
||||
showEditorLoader: {
|
||||
message:string|undefined;
|
||||
}
|
||||
}
|
||||
}
|
||||
| {type: ACTION_TYPES.HIDE_EDITOR_LOADINGBAR,}
|
||||
| {
|
||||
type: ACTION_TYPES.SHOW_EDITOR_LOADINGBAR,
|
||||
payload?:{
|
||||
type: ACTION_TYPES.SHOW_EDITOR_LOADINGBAR;
|
||||
payload?: {
|
||||
showEditorLoadingBar: {
|
||||
label?: string;
|
||||
message?: string;
|
||||
progress?: number;
|
||||
useFakeTimer?: number;
|
||||
}
|
||||
}
|
||||
};
|
||||
};
|
||||
}
|
||||
| {
|
||||
type: ACTION_TYPES.UPDATE_EDITOR_LOADINGBAR,
|
||||
payload:{
|
||||
type: ACTION_TYPES.UPDATE_EDITOR_LOADINGBAR;
|
||||
payload: {
|
||||
showEditorLoadingBar: {
|
||||
label?: string;
|
||||
message?: string;
|
||||
progress?: number;
|
||||
}
|
||||
}
|
||||
};
|
||||
};
|
||||
}
|
||||
| {
|
||||
type: ACTION_TYPES.ON_TIMELINE_RESIZE,
|
||||
type: ACTION_TYPES.ON_TIMELINE_RESIZE;
|
||||
payload: {
|
||||
timelineHeight: number
|
||||
}
|
||||
timelineHeight: number;
|
||||
};
|
||||
}
|
||||
| {
|
||||
type: ACTION_TYPES.ON_CHANGE_VIEW_MODE,
|
||||
payload: {
|
||||
viewMode: ViewModes
|
||||
}
|
||||
}
|
||||
;
|
||||
type: ACTION_TYPES.ON_CHANGE_VIEW_MODE;
|
||||
payload: {
|
||||
viewMode: ViewModes;
|
||||
};
|
||||
};
|
||||
@@ -1,23 +1,30 @@
|
||||
import {State, VIEW_MODES} from './types';
|
||||
import { State, VIEW_MODES } from "./types";
|
||||
import { ClipGroup } from "~/pages/PageEnigma/models/track";
|
||||
|
||||
export const initialStateValues : State = {
|
||||
export const initialStateValues: State = {
|
||||
timelineHeight: 260,
|
||||
viewMode: VIEW_MODES.EDITOR,
|
||||
showEditorLoader: {
|
||||
isShowing:false,
|
||||
message: 'Loading Editor Engine 🦊'
|
||||
isShowing: false,
|
||||
message: "Loading Editor Engine 🦊",
|
||||
},
|
||||
showEditorLoadingBar: {
|
||||
isShowing:true,
|
||||
progress:5,
|
||||
message: 'Loading Editor Engine 🦊'
|
||||
isShowing: true,
|
||||
progress: 5,
|
||||
message: "Loading Editor Engine 🦊",
|
||||
},
|
||||
currentSceneObject:{
|
||||
isShowing:false,
|
||||
objectVectors:{
|
||||
position:{x:0,y:0,z:0},
|
||||
rotation:{x:0,y:0,z:0},
|
||||
scale:{x:0,y:0,z:0},
|
||||
}
|
||||
}
|
||||
}
|
||||
controlPanel: {
|
||||
isShowing: false,
|
||||
currentSceneObject: {
|
||||
group: ClipGroup.OBJECT,
|
||||
object_name: "",
|
||||
object_uuid: "",
|
||||
version: "1",
|
||||
objectVectors: {
|
||||
position: { x: 0, y: 0, z: 0 },
|
||||
rotation: { x: 0, y: 0, z: 0 },
|
||||
scale: { x: 0, y: 0, z: 0 },
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
@@ -78,13 +78,13 @@ export function selectCameraKeyframe(keyframeId: string) {
|
||||
};
|
||||
}
|
||||
|
||||
export function deleteCameraKeyframe(keyframeId: string) {
|
||||
export function deleteCameraKeyframe(deleteKeyframe: Keyframe) {
|
||||
const oldCameraGroup = cameraGroup.value;
|
||||
cameraGroup.value = {
|
||||
...oldCameraGroup,
|
||||
keyframes: [
|
||||
...oldCameraGroup.keyframes.filter((keyframe) => {
|
||||
if (keyframe.keyframe_uuid === keyframeId) {
|
||||
if (keyframe.keyframe_uuid === deleteKeyframe.keyframe_uuid) {
|
||||
Queue.publish({
|
||||
queueName: QueueNames.TO_ENGINE,
|
||||
action: toEngineActions.DELETE_KEYFRAME,
|
||||
|
||||
@@ -6,6 +6,9 @@ import {
|
||||
} from "~/pages/PageEnigma/models/track";
|
||||
import { useCallback } from "react";
|
||||
import * as uuid from "uuid";
|
||||
import Queue from "~/pages/PageEnigma/Queue/Queue";
|
||||
import { QueueNames } from "~/pages/PageEnigma/Queue/QueueNames";
|
||||
import { toEngineActions } from "~/pages/PageEnigma/Queue/toEngineActions";
|
||||
|
||||
export const objectGroup = signal<ObjectGroup>({
|
||||
id: "OB1",
|
||||
@@ -39,7 +42,7 @@ export function addObjectKeyframe(keyframe: QueueKeyframe, offset: number) {
|
||||
name: keyframe.object_name ?? "unknown",
|
||||
keyframes: [] as Keyframe[],
|
||||
};
|
||||
newObject.keyframes.push({
|
||||
const newKeyframe = {
|
||||
version: keyframe.version,
|
||||
keyframe_uuid: uuid.v4(),
|
||||
group: keyframe.group,
|
||||
@@ -49,13 +52,13 @@ export function addObjectKeyframe(keyframe: QueueKeyframe, offset: number) {
|
||||
rotation: keyframe.rotation,
|
||||
scale: keyframe.scale,
|
||||
selected: false,
|
||||
} as Keyframe);
|
||||
} as Keyframe;
|
||||
newObject.keyframes.push(newKeyframe);
|
||||
console.log(newObject);
|
||||
newObject.keyframes.sort(
|
||||
(keyframeA, keyframeB) => keyframeA.offset - keyframeB.offset,
|
||||
);
|
||||
|
||||
console.log(4);
|
||||
objectGroup.value = {
|
||||
...oldObjectGroup,
|
||||
objects: [
|
||||
@@ -65,7 +68,11 @@ export function addObjectKeyframe(keyframe: QueueKeyframe, offset: number) {
|
||||
newObject,
|
||||
].sort((objA, objB) => (objA.object_uuid < objB.object_uuid ? -1 : 1)),
|
||||
};
|
||||
console.log("T", objectGroup.value);
|
||||
Queue.publish({
|
||||
queueName: QueueNames.TO_ENGINE,
|
||||
action: toEngineActions.ADD_KEYFRAME,
|
||||
data: newKeyframe,
|
||||
});
|
||||
}
|
||||
|
||||
export function deleteObjectKeyframe(keyframe: Keyframe) {
|
||||
|
||||
Reference in new issue
Block a user