diff --git a/frontend/apps/artcraft/app/src/pages/PageEnigma/Editor/SceneMetadata.ts b/frontend/apps/artcraft/app/src/pages/PageEnigma/Editor/SceneMetadata.ts index b6815a41c3..21844ed16a 100644 --- a/frontend/apps/artcraft/app/src/pages/PageEnigma/Editor/SceneMetadata.ts +++ b/frontend/apps/artcraft/app/src/pages/PageEnigma/Editor/SceneMetadata.ts @@ -1,6 +1,5 @@ import { getArtStyle } from "~/enums/ArtStyle"; import { - cameraAspectRatio, cinematic, enginePreProcessing, faceDetail, @@ -11,6 +10,7 @@ import { } from "~/pages/PageEnigma/signals"; import { SceneGenereationMetaData as SceneGenerationMetaData } from "~/pages/PageEnigma/models/sceneGenerationMetadata"; import Editor from "./editor"; +import { usePageEnigmaStore } from "../PageEnigmaStore"; export const getSceneGenerationMetaData = ( editorEngine: Editor, @@ -20,7 +20,7 @@ export const getSceneGenerationMetaData = ( positivePrompt: editorEngine.positive_prompt, negativePrompt: editorEngine.negative_prompt, artisticStyle: getArtStyle(editorEngine.art_style.toString()), - cameraAspectRatio: cameraAspectRatio.value, + cameraAspectRatio: usePageEnigmaStore.getState().cameraAspectRatio, globalIPAMediaToken: globalIPAMediaToken.value || undefined, upscale: upscale.value, faceDetail: faceDetail.value, diff --git a/frontend/apps/artcraft/app/src/pages/PageEnigma/Editor/editor.ts b/frontend/apps/artcraft/app/src/pages/PageEnigma/Editor/editor.ts index 90a9fbdec3..872b144178 100644 --- a/frontend/apps/artcraft/app/src/pages/PageEnigma/Editor/editor.ts +++ b/frontend/apps/artcraft/app/src/pages/PageEnigma/Editor/editor.ts @@ -16,11 +16,6 @@ import { PointerLockControls } from "three/addons/controls/PointerLockControls.j import { EditorStates, CameraAspectRatio } from "~/pages/PageEnigma/enums"; import { AssetType, ClipGroup } from "~/enums"; import { XYZ } from "../datastructures/common"; -import { - editorState, - cameraAspectRatio, - gridVisibility, -} from "../signals/engine"; import { SceneUtils } from "./helper"; import { VideoGeneration } from "./video_generation"; import { MouseControls } from "./keybinds_controls"; @@ -698,11 +693,12 @@ class Editor { return null; } - const currentAspectRatio = cameraAspectRatio.value; + const store = usePageEnigmaStore.getState(); + const currentAspectRatio = store.cameraAspectRatio; // Store grid visibility state and hide grid - const wasGridVisible = gridVisibility.value; - gridVisibility.value = false; + const wasGridVisible = store.gridVisible; + store.setGridVisible(false); // Store and hide transform controls const wasControlVisible = this.control?.visible ?? false; @@ -810,7 +806,7 @@ class Editor { } // Restore grid visibility - gridVisibility.value = wasGridVisible; + usePageEnigmaStore.getState().setGridVisible(wasGridVisible); // Restore transform controls visibility if (this.control) { @@ -1336,7 +1332,7 @@ class Editor { async switchPreview() { if (!this.switchPreviewToggle) { this.switchPreviewToggle = true; - editorState.value = EditorStates.PREVIEW; + usePageEnigmaStore.getState().setEditorState(EditorStates.PREVIEW); await this.generateFrame(); } } @@ -1348,7 +1344,7 @@ class Editor { this.rawRenderPass ) { this.switchPreviewToggle = false; - editorState.value = EditorStates.EDIT; + usePageEnigmaStore.getState().setEditorState(EditorStates.EDIT); setTimeout(() => { // if (!this.canvasRenderCamReference) { // this.canvasRenderCamReference = diff --git a/frontend/apps/artcraft/app/src/pages/PageEnigma/Editor/helper.ts b/frontend/apps/artcraft/app/src/pages/PageEnigma/Editor/helper.ts index 8ae15a4465..c3bddf8c0d 100644 --- a/frontend/apps/artcraft/app/src/pages/PageEnigma/Editor/helper.ts +++ b/frontend/apps/artcraft/app/src/pages/PageEnigma/Editor/helper.ts @@ -2,7 +2,6 @@ import Scene from "./scene"; import Editor from "./editor"; import * as THREE from "three"; import { XYZ } from "../datastructures/common"; -import { editorState } from "../signals/engine"; import { EditorStates } from "../enums"; import { hideObjectPanel } from "../signals"; import { usePageEnigmaStore } from "../PageEnigmaStore"; @@ -141,7 +140,7 @@ export class SceneUtils { this.editor.selected = this.editor.cam_obj; this.editor.publishSelect(); this.editor.updateSelectedUI(); - editorState.value = EditorStates.CAMERA_VIEW; + usePageEnigmaStore.getState().setEditorState(EditorStates.CAMERA_VIEW); if (this.editor.activeScene.hot_items) { this.editor.activeScene.hot_items.forEach((element) => { element.visible = false; @@ -174,7 +173,7 @@ export class SceneUtils { } hideObjectPanel(); - editorState.value = EditorStates.EDIT; + usePageEnigmaStore.getState().setEditorState(EditorStates.EDIT); } } } diff --git a/frontend/apps/artcraft/app/src/pages/PageEnigma/Editor/scene.ts b/frontend/apps/artcraft/app/src/pages/PageEnigma/Editor/scene.ts index e8cab2df27..f345068b0c 100644 --- a/frontend/apps/artcraft/app/src/pages/PageEnigma/Editor/scene.ts +++ b/frontend/apps/artcraft/app/src/pages/PageEnigma/Editor/scene.ts @@ -9,7 +9,7 @@ import { MMDAnimationHelper, Water } from "three/examples/jsm/Addons.js"; import { MediaFileType } from "../enums"; import { ChromaKeyMaterial } from "./chromakey"; import { LoadWithoutCors } from "@storyteller/tauri-api"; -import { gridVisibility } from "../signals/engine"; +import { usePageEnigmaStore } from "../PageEnigmaStore"; import { InfiniteGridHelper } from "./InfiniteGridHelper"; import { cameras, selectedCameraId } from "../signals/camera"; import { MediaFilesApi } from "@storyteller/api"; @@ -91,16 +91,15 @@ class Scene { this.helper = new MMDAnimationHelper({ afterglow: 0.0 }); this.scene.userData["helper"] = this.helper; - // Subscribe to grid visibility changes - gridVisibility.subscribe((isVisible) => { - if (this.gridHelper) { - if (isVisible) { - if (!this.scene.children.includes(this.gridHelper)) { - this.scene.add(this.gridHelper); - } - } else { - this.scene.remove(this.gridHelper); + // Subscribe to grid visibility changes from the store + usePageEnigmaStore.subscribe((state, prev) => { + if (state.gridVisible === prev.gridVisible || !this.gridHelper) return; + if (state.gridVisible) { + if (!this.scene.children.includes(this.gridHelper)) { + this.scene.add(this.gridHelper); } + } else { + this.scene.remove(this.gridHelper); } }); } @@ -1093,9 +1092,9 @@ class Scene { this.scene.add(this.groundPlane); } - // Update grid visibility based on the signal + // Update grid visibility based on the store updateGridVisibility() { - if (gridVisibility.value) { + if (usePageEnigmaStore.getState().gridVisible) { if (!this.scene.children.includes(this.gridHelper)) { this.scene.add(this.gridHelper); } diff --git a/frontend/apps/artcraft/app/src/pages/PageEnigma/Editor/video_generation.ts b/frontend/apps/artcraft/app/src/pages/PageEnigma/Editor/video_generation.ts index cb32d94354..5fb4ce8483 100644 --- a/frontend/apps/artcraft/app/src/pages/PageEnigma/Editor/video_generation.ts +++ b/frontend/apps/artcraft/app/src/pages/PageEnigma/Editor/video_generation.ts @@ -1,6 +1,6 @@ import Editor from "./editor"; import { EditorStates } from "~/pages/PageEnigma/enums"; -import { editorState, previewSrc } from "../signals/engine"; +import { usePageEnigmaStore } from "../PageEnigmaStore"; import { ToastTypes, ClipType } from "~/enums"; import { Visibility } from "./api_manager.js"; @@ -109,7 +109,7 @@ export class VideoGeneration { }); } - previewSrc.value = ""; + usePageEnigmaStore.getState().setPreviewSrc(""); this.editor.rawRenderer.setSize( this.editor.render_width, @@ -132,7 +132,7 @@ export class VideoGeneration { if (!this.editor.camera_person_mode) { this.editor.switchCameraView(); - editorState.value = EditorStates.PREVIEW; + usePageEnigmaStore.getState().setEditorState(EditorStates.PREVIEW); } this.editor.generating_preview = false; @@ -146,7 +146,7 @@ export class VideoGeneration { this.editor.negative_prompt, ); - previewSrc.value = url; + usePageEnigmaStore.getState().setPreviewSrc(url); return Promise.resolve(url); } catch (err: unknown) { const errorMessage = diff --git a/frontend/apps/artcraft/app/src/pages/PageEnigma/PageEditor.tsx b/frontend/apps/artcraft/app/src/pages/PageEnigma/PageEditor.tsx index 0da1bdf762..ef924242e5 100644 --- a/frontend/apps/artcraft/app/src/pages/PageEnigma/PageEditor.tsx +++ b/frontend/apps/artcraft/app/src/pages/PageEnigma/PageEditor.tsx @@ -61,6 +61,7 @@ import { } from "~/components/signaled/TopBar/TopBar"; import { uploadPlaneFromMediaToken } from "~/components/reusable/UploadModalMedia/uploadPlane"; import { addObject, addCharacter } from "./actions"; +import { usePageEnigmaStore } from "./PageEnigmaStore"; import { AssetType, AUTH_STATUS } from "~/enums"; import { v4 as uuidv4 } from "uuid"; import { MediaItem } from "~/pages/PageEnigma/models"; @@ -106,6 +107,7 @@ export const PageEditor = () => { const tabStore = useTabStore(); const storyboardPageEnabled = useStoryboardPageEnabled(); + const camAspect = usePageEnigmaStore((s) => s.cameraAspectRatio); const handleOverlayClick = (event: React.MouseEvent) => { event.stopPropagation(); }; @@ -134,7 +136,7 @@ export const PageEditor = () => { const scaleHeight = height < 610 ? height / 610 : 1; if ( - cameraAspectRatio.value === CameraAspectRatio.VERTICAL_9_16 && + camAspect === CameraAspectRatio.VERTICAL_9_16 && outlinerIsShowing.value && height < 900 ) { @@ -145,7 +147,7 @@ export const PageEditor = () => { } if ( - cameraAspectRatio.value === CameraAspectRatio.SQUARE_1_1 && + camAspect === CameraAspectRatio.SQUARE_1_1 && pageWidth.value < 2000 ) { return scaleHeight * 0.85; diff --git a/frontend/apps/artcraft/app/src/pages/PageEnigma/comps/AspectRatioMenu/AspectRatioMenu.tsx b/frontend/apps/artcraft/app/src/pages/PageEnigma/comps/AspectRatioMenu/AspectRatioMenu.tsx index f8360705b5..5c1c7e3d65 100644 --- a/frontend/apps/artcraft/app/src/pages/PageEnigma/comps/AspectRatioMenu/AspectRatioMenu.tsx +++ b/frontend/apps/artcraft/app/src/pages/PageEnigma/comps/AspectRatioMenu/AspectRatioMenu.tsx @@ -1,4 +1,3 @@ -import { useSignals } from "@preact/signals-react/runtime"; import { faRectangle, faRectangleVertical, @@ -6,45 +5,42 @@ import { } from "@fortawesome/pro-solid-svg-icons"; import { useContext } from "react"; import { CameraAspectRatio } from "~/pages/PageEnigma/enums"; -import { cameraAspectRatio } from "~/pages/PageEnigma/signals"; import { setCameraAspect } from "~/pages/PageEnigma/actions"; +import { usePageEnigmaStore } from "~/pages/PageEnigma/PageEnigmaStore"; import { EngineContext } from "~/pages/PageEnigma/contexts/EngineContext"; import { ButtonDropdown } from "@storyteller/ui-button-dropdown"; +const ICON_BY_RATIO: Record = { + [CameraAspectRatio.HORIZONTAL_16_9]: faRectangle, + [CameraAspectRatio.VERTICAL_9_16]: faRectangleVertical, + [CameraAspectRatio.HORIZONTAL_3_2]: faRectangle, + [CameraAspectRatio.VERTICAL_2_3]: faRectangleVertical, + [CameraAspectRatio.SQUARE_1_1]: faSquare, +}; + +const LABEL_BY_RATIO: Record = { + [CameraAspectRatio.HORIZONTAL_16_9]: "16:9 Horizontal", + [CameraAspectRatio.VERTICAL_9_16]: "9:16 Vertical", + [CameraAspectRatio.HORIZONTAL_3_2]: "3:2 Horizontal", + [CameraAspectRatio.VERTICAL_2_3]: "2:3 Vertical", + [CameraAspectRatio.SQUARE_1_1]: "1:1 Squared", +}; + export const AspectRatioMenu = () => { - useSignals(); + const aspect = usePageEnigmaStore((s) => s.cameraAspectRatio); const editor = useContext(EngineContext); - const buttonIcon = - cameraAspectRatio.value === CameraAspectRatio.HORIZONTAL_16_9 - ? faRectangle - : cameraAspectRatio.value === CameraAspectRatio.VERTICAL_9_16 - ? faRectangleVertical - : cameraAspectRatio.value === CameraAspectRatio.HORIZONTAL_3_2 - ? faRectangle - : cameraAspectRatio.value === CameraAspectRatio.VERTICAL_2_3 - ? faRectangleVertical - : faSquare; - const buttonText = - cameraAspectRatio.value === CameraAspectRatio.HORIZONTAL_16_9 - ? "16:9 Horizontal" - : cameraAspectRatio.value === CameraAspectRatio.VERTICAL_9_16 - ? "9:16 Vertical" - : cameraAspectRatio.value === CameraAspectRatio.HORIZONTAL_3_2 - ? "3:2 Horizontal" - : cameraAspectRatio.value === CameraAspectRatio.VERTICAL_2_3 - ? "2:3 Vertical" - : "1:1 Squared"; const handleChangeAspectRatio = (newRatio: CameraAspectRatio) => { if (!editor) return; setCameraAspect(editor, newRatio); }; + return (
{ icon: faRectangle, className: "pl-4", description: "Horizontal", - selected: - cameraAspectRatio.value === CameraAspectRatio.HORIZONTAL_16_9, + selected: aspect === CameraAspectRatio.HORIZONTAL_16_9, onClick: () => handleChangeAspectRatio(CameraAspectRatio.HORIZONTAL_16_9), }, @@ -63,8 +58,7 @@ export const AspectRatioMenu = () => { icon: faRectangle, className: "pl-4", description: "Horizontal", - selected: - cameraAspectRatio.value === CameraAspectRatio.HORIZONTAL_3_2, + selected: aspect === CameraAspectRatio.HORIZONTAL_3_2, onClick: () => handleChangeAspectRatio(CameraAspectRatio.HORIZONTAL_3_2), }, @@ -73,8 +67,7 @@ export const AspectRatioMenu = () => { icon: faRectangleVertical, className: "pl-4", description: "Vertical", - selected: - cameraAspectRatio.value === CameraAspectRatio.VERTICAL_2_3, + selected: aspect === CameraAspectRatio.VERTICAL_2_3, onClick: () => handleChangeAspectRatio(CameraAspectRatio.VERTICAL_2_3), }, @@ -83,8 +76,7 @@ export const AspectRatioMenu = () => { icon: faRectangleVertical, className: "pl-4", description: "Vertical", - selected: - cameraAspectRatio.value === CameraAspectRatio.VERTICAL_9_16, + selected: aspect === CameraAspectRatio.VERTICAL_9_16, onClick: () => handleChangeAspectRatio(CameraAspectRatio.VERTICAL_9_16), }, @@ -93,7 +85,7 @@ export const AspectRatioMenu = () => { icon: faSquare, className: "pl-4", description: "Squared", - selected: cameraAspectRatio.value === CameraAspectRatio.SQUARE_1_1, + selected: aspect === CameraAspectRatio.SQUARE_1_1, onClick: () => handleChangeAspectRatio(CameraAspectRatio.SQUARE_1_1), }, diff --git a/frontend/apps/artcraft/app/src/pages/PageEnigma/comps/ControlPanelSceneObject/ControlPanelSceneObject.tsx b/frontend/apps/artcraft/app/src/pages/PageEnigma/comps/ControlPanelSceneObject/ControlPanelSceneObject.tsx index f86baeeb9a..88ed810caf 100644 --- a/frontend/apps/artcraft/app/src/pages/PageEnigma/comps/ControlPanelSceneObject/ControlPanelSceneObject.tsx +++ b/frontend/apps/artcraft/app/src/pages/PageEnigma/comps/ControlPanelSceneObject/ControlPanelSceneObject.tsx @@ -17,7 +17,7 @@ import { import { EngineContext } from "~/pages/PageEnigma/contexts/EngineContext"; import { InputVector } from "@storyteller/ui-input"; import { Button } from "@storyteller/ui-button"; -import { editorState } from "~/pages/PageEnigma/signals/engine"; +import { usePageEnigmaStore } from "~/pages/PageEnigma/PageEnigmaStore"; import { twMerge } from "tailwind-merge"; import { EditorStates } from "~/pages/PageEnigma/enums"; import { sanitize } from "./utils/sanitize"; @@ -43,6 +43,7 @@ const defaultAxises: Record = { export const ControlPanelSceneObject = () => { useSignals(); + const editorState = usePageEnigmaStore((s) => s.editorState); const { isShowing, currentObject } = objectPanelSignals; const editorEngine = useContext(EngineContext); @@ -114,7 +115,7 @@ export const ControlPanelSceneObject = () => { setColor(editorEngine?.selected?.userData.color); }, [currentSceneObject, editorEngine]); - if (!currentSceneObject || editorState.value === EditorStates.PREVIEW) { + if (!currentSceneObject || editorState === EditorStates.PREVIEW) { return null; } diff --git a/frontend/apps/artcraft/app/src/pages/PageEnigma/comps/Outliner/Outliner.tsx b/frontend/apps/artcraft/app/src/pages/PageEnigma/comps/Outliner/Outliner.tsx index 3e235990bb..4094cda435 100644 --- a/frontend/apps/artcraft/app/src/pages/PageEnigma/comps/Outliner/Outliner.tsx +++ b/frontend/apps/artcraft/app/src/pages/PageEnigma/comps/Outliner/Outliner.tsx @@ -23,7 +23,7 @@ import { Transition } from "@headlessui/react"; import { twMerge } from "tailwind-merge"; import { useSignals } from "@preact/signals-react/runtime"; import { EngineContext } from "../../contexts/EngineContext"; -import { cameraAspectRatio } from "../../signals"; +import { usePageEnigmaStore } from "../../PageEnigmaStore"; import { pageHeight, pageWidth } from "~/signals"; import { CameraAspectRatio } from "../../enums"; import { effect } from "@preact/signals-react"; @@ -121,6 +121,7 @@ const OutlinerItem = ({ item }: { item: SceneObject }) => { export const Outliner = () => { useSignals(); + const camAspect = usePageEnigmaStore((s) => s.cameraAspectRatio); const [searchTerm, setSearchTerm] = useState(""); const [editorHeight, setEditorHeight] = useState(0); @@ -158,9 +159,9 @@ export const Outliner = () => { const getOutlinerHeightClass = () => { if (pageWidth.value >= 2000) { - if (cameraAspectRatio.value === CameraAspectRatio.VERTICAL_9_16) { + if (camAspect === CameraAspectRatio.VERTICAL_9_16) { return `${editorHeight * 0.5 - 120}px`; - } else if (cameraAspectRatio.value === CameraAspectRatio.SQUARE_1_1) { + } else if (camAspect === CameraAspectRatio.SQUARE_1_1) { return `${editorHeight * 0.42}px`; } else { return `${editorHeight * 0.54}px`; @@ -168,9 +169,9 @@ export const Outliner = () => { } if (pageWidth.value < 2000) { - if (cameraAspectRatio.value === CameraAspectRatio.VERTICAL_9_16) { + if (camAspect === CameraAspectRatio.VERTICAL_9_16) { return `${editorHeight * 0.7 - 10}px`; - } else if (cameraAspectRatio.value === CameraAspectRatio.SQUARE_1_1) { + } else if (camAspect === CameraAspectRatio.SQUARE_1_1) { return `${editorHeight * 0.7}px`; } else { return `${editorHeight * 0.7}px`; diff --git a/frontend/apps/artcraft/app/src/pages/PageEnigma/comps/PreviewEngineCamera/PreviewEngineCamera.tsx b/frontend/apps/artcraft/app/src/pages/PageEnigma/comps/PreviewEngineCamera/PreviewEngineCamera.tsx index bea24f2981..cc2881b1b2 100644 --- a/frontend/apps/artcraft/app/src/pages/PageEnigma/comps/PreviewEngineCamera/PreviewEngineCamera.tsx +++ b/frontend/apps/artcraft/app/src/pages/PageEnigma/comps/PreviewEngineCamera/PreviewEngineCamera.tsx @@ -7,14 +7,14 @@ import { faCameraViewfinder, faSpinnerThird, } from "@fortawesome/pro-solid-svg-icons"; +import { useShallow } from "zustand/shallow"; import { - cameraAspectRatio, - editorState, editorLetterBox, toggleEditorLetterBox, sidePanelHeight, outlinerIsShowing, } from "~/pages/PageEnigma/signals"; +import { usePageEnigmaStore } from "~/pages/PageEnigma/PageEnigmaStore"; import { pageWidth } from "~/signals"; import { CameraAspectRatio, EditorStates } from "~/pages/PageEnigma/enums"; import { CameraViewCanvas } from "~/pages/PageEnigma/comps/EngineCanvases"; @@ -25,26 +25,31 @@ import { useEffect } from "react"; export const PreviewEngineCamera = () => { useSignals(); + const { camAspect, editorState } = usePageEnigmaStore( + useShallow((s) => ({ + camAspect: s.cameraAspectRatio, + editorState: s.editorState, + })), + ); const handleButtonCameraView = () => { // TODO: wire to editor.toggleCameraView() once editor.ts is migrated. }; const getLargeScreenHeightClass = () => { - if (cameraAspectRatio.value === CameraAspectRatio.VERTICAL_9_16) { + if (camAspect === CameraAspectRatio.VERTICAL_9_16) { return pageWidth.value >= 2000 ? "w-44 justify-center" : "w-36 justify-center"; - } else { - return pageWidth.value >= 2000 - ? "w-72 justify-between" - : "w-64 justify-between"; } + return pageWidth.value >= 2000 + ? "w-72 justify-between" + : "w-64 justify-between"; }; const getSmallScreenHeightClass = () => { if ( - cameraAspectRatio.value === CameraAspectRatio.VERTICAL_9_16 && + camAspect === CameraAspectRatio.VERTICAL_9_16 && sidePanelHeight.value < 2000 && outlinerIsShowing.value ) { @@ -54,23 +59,24 @@ export const PreviewEngineCamera = () => { }; const getSquareAspectRatioClass = () => { - if (cameraAspectRatio.value === CameraAspectRatio.SQUARE_1_1) { + if (camAspect === CameraAspectRatio.SQUARE_1_1) { return pageWidth.value >= 2000 ? "w-[240px] justify-between" : "w-60 justify-between"; } + return undefined; }; useEffect(() => { - console.log("Editor state changed:", editorState.value); - }, [editorState.value]); + console.log("Editor state changed:", editorState); + }, [editorState]); return (