+
+
+
@@ -53,8 +49,7 @@ export const CameraTab = () => {
diff --git a/app/pages/PageEnigma/comps/SidePanelTabs/itemTabs/ObjectsTab.tsx b/app/pages/PageEnigma/comps/SidePanelTabs/itemTabs/ObjectsTab.tsx
index 20484a6bfd..683b26a353 100644
--- a/app/pages/PageEnigma/comps/SidePanelTabs/itemTabs/ObjectsTab.tsx
+++ b/app/pages/PageEnigma/comps/SidePanelTabs/itemTabs/ObjectsTab.tsx
@@ -10,6 +10,7 @@ import { ItemElements } from "~/pages/PageEnigma/comps/SidePanelTabs/itemTabs/It
import { Button } from "~/components";
import { faCirclePlus } from "@fortawesome/pro-solid-svg-icons";
import { twMerge } from "tailwind-merge";
+import { TabTitle } from "~/pages/PageEnigma/comps/SidePanelTabs/comps/TabTitle";
import { shapeItems } from "~/pages/PageEnigma/store";
import { GetMediaByUser, GetMediaListResponse } from "~/api/media_files/GetMediaByUser";
import { AssetFilterOption, AssetType, MediaItem } from "~/pages/PageEnigma/models";
@@ -79,27 +80,26 @@ export const ObjectsTab = ({ type }: Props) => {
return (
<>
-
-
+
+
+
@@ -121,8 +119,7 @@ export const ObjectsTab = ({ type }: Props) => {
diff --git a/app/pages/PageEnigma/comps/SidePanelTabs/itemTabs/ShapeTab.tsx b/app/pages/PageEnigma/comps/SidePanelTabs/itemTabs/ShapeTab.tsx
index ed2cabfb75..844053782c 100644
--- a/app/pages/PageEnigma/comps/SidePanelTabs/itemTabs/ShapeTab.tsx
+++ b/app/pages/PageEnigma/comps/SidePanelTabs/itemTabs/ShapeTab.tsx
@@ -1,19 +1,20 @@
import { useSignals } from "@preact/signals-react/runtime";
import { ItemElements } from "~/pages/PageEnigma/comps/SidePanelTabs/itemTabs/ItemElements";
import { shapeFilter, shapeItems } from "~/pages/PageEnigma/store";
+import { TabTitle } from "~/pages/PageEnigma/comps/SidePanelTabs/comps/TabTitle";
export const ShapeTab = () => {
useSignals();
return (
- <>
-
Shapes
-
+
);
};
diff --git a/app/pages/PageEnigma/comps/SidePanelTabs/itemTabs/StylizeTab/ItemPicker.tsx b/app/pages/PageEnigma/comps/SidePanelTabs/itemTabs/StylizeTab/ItemPicker.tsx
new file mode 100644
index 0000000000..b38e1db8d8
--- /dev/null
+++ b/app/pages/PageEnigma/comps/SidePanelTabs/itemTabs/StylizeTab/ItemPicker.tsx
@@ -0,0 +1,56 @@
+import { twMerge } from "tailwind-merge";
+import { ArtStyle } from "~/pages/PageEnigma/js/api_manager";
+import { H4 } from "~/components";
+import { ImgHTMLAttributes } from "react";
+
+interface ItemPickerProps extends ImgHTMLAttributes
{
+ label: string;
+ type: ArtStyle;
+ selected: boolean;
+ onSelected: (picked: ArtStyle) => void;
+}
+
+export const ItemPicker = ({
+ label,
+ type,
+ selected = false,
+ onSelected,
+ width,
+ height,
+ ...imgProps
+}: ItemPickerProps) => {
+ const handleSelected = () => {
+ onSelected(type);
+ };
+
+ return (
+
+ );
+};
diff --git a/app/pages/PageEnigma/comps/SidePanelTabs/itemTabs/StylizeTab/Prompts.tsx b/app/pages/PageEnigma/comps/SidePanelTabs/itemTabs/StylizeTab/Prompts.tsx
new file mode 100644
index 0000000000..24a7f14690
--- /dev/null
+++ b/app/pages/PageEnigma/comps/SidePanelTabs/itemTabs/StylizeTab/Prompts.tsx
@@ -0,0 +1,90 @@
+import { ChangeEvent, useContext, useState } from "react";
+
+import { Textarea } from "~/components";
+
+import { EngineContext } from "~/contexts/EngineContext";
+import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
+import { faRandom } from "@fortawesome/pro-solid-svg-icons";
+import { RandomTexts } from "~/pages/PageEnigma/constants/RandomTexts";
+
+export const Prompts = () => {
+ const editorEngine = useContext(EngineContext);
+ const [textBufferPositive, setTextBufferPositive] = useState("");
+ const [textBufferNegative, setTextBufferNegative] = useState("");
+
+ const onChangeHandlerNegative = (event: ChangeEvent) => {
+ if (editorEngine == null) {
+ console.log("Editor is null");
+ return;
+ }
+ editorEngine.negative_prompt = event.target.value;
+ setTextBufferNegative(event.target.value);
+ };
+
+ const onChangeHandlerPositive = (event: ChangeEvent) => {
+ if (editorEngine == null) {
+ console.log("Editor is null");
+ return;
+ }
+ editorEngine.positive_prompt = event.target.value;
+ setTextBufferPositive(event.target.value);
+ };
+
+ const generateRandomTextPositive = () => {
+ const randomIndex = Math.floor(Math.random() * RandomTexts.length);
+ const randomText = RandomTexts[randomIndex];
+ setTextBufferPositive(randomText);
+ };
+
+ const generateRandomTextNegative = () => {
+ const randomIndex = Math.floor(Math.random() * RandomTexts.length);
+ const randomText = RandomTexts[randomIndex];
+ setTextBufferNegative(randomText);
+ };
+
+ return (
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ );
+};
diff --git a/app/pages/PageEnigma/comps/SidePanelTabs/itemTabs/StylizeTab/StyleButtons.tsx b/app/pages/PageEnigma/comps/SidePanelTabs/itemTabs/StylizeTab/StyleButtons.tsx
new file mode 100644
index 0000000000..a1266236e2
--- /dev/null
+++ b/app/pages/PageEnigma/comps/SidePanelTabs/itemTabs/StylizeTab/StyleButtons.tsx
@@ -0,0 +1,82 @@
+import { Button } from "~/components";
+import { faArrowsRotate, faFilm } from "@fortawesome/pro-solid-svg-icons";
+import { editorState, EditorStates } from "~/pages/PageEnigma/store/engine";
+import { useSignals } from "@preact/signals-react/runtime";
+import Queue from "~/pages/PageEnigma/Queue/Queue";
+import { QueueNames } from "~/pages/PageEnigma/Queue/QueueNames";
+import { toEngineActions } from "~/pages/PageEnigma/Queue/toEngineActions";
+
+export function StyleButtons() {
+ useSignals();
+
+ const switchPreview = async () => {
+ Queue.publish({
+ queueName: QueueNames.TO_ENGINE,
+ action: toEngineActions.ENTER_PREVIEW_STATE,
+ data: null,
+ });
+ };
+
+ const switchEdit = async () => {
+ Queue.publish({
+ queueName: QueueNames.TO_ENGINE,
+ action: toEngineActions.ENTER_EDIT_STATE,
+ data: null,
+ });
+ };
+
+ const generateMovie = async () => {
+ Queue.publish({
+ queueName: QueueNames.TO_ENGINE,
+ action: toEngineActions.GENERATE_VIDEO,
+ data: null,
+ });
+ };
+
+ console.log("state", editorState.value);
+
+ return (
+
+
+ {editorState.value === EditorStates.EDIT && (
+ <>
+
+ Render the current camera view with AI
+
+
+ >
+ )}
+ {editorState.value === EditorStates.PREVIEW && (
+
+ )}
+
+
+
+ When you're done, render your entire animation with AI
+
+
+ (This may take several minutes)
+
+
+
+
+ );
+}
diff --git a/app/pages/PageEnigma/comps/SidePanelTabs/itemTabs/StylizeTab/StyleSelection.tsx b/app/pages/PageEnigma/comps/SidePanelTabs/itemTabs/StylizeTab/StyleSelection.tsx
new file mode 100644
index 0000000000..70e7dfc647
--- /dev/null
+++ b/app/pages/PageEnigma/comps/SidePanelTabs/itemTabs/StylizeTab/StyleSelection.tsx
@@ -0,0 +1,118 @@
+import { useContext, useState } from "react";
+
+import { ButtonIcon } from "~/components";
+
+import { EngineContext } from "~/contexts/EngineContext";
+import { ArtStyle } from "~/pages/PageEnigma/js/api_manager";
+import { faAngleLeft, faAngleRight } from "@fortawesome/pro-solid-svg-icons";
+import { styleList } from "~/pages/PageEnigma/styleList";
+import { sidePanelHeight, sidePanelWidth } from "~/pages/PageEnigma/store";
+import { ItemPicker } from "./ItemPicker";
+import { useSignals } from "@preact/signals-react/runtime";
+
+export const StyleSelection = () => {
+ useSignals();
+ const [selection, setSelection] = useState(styleList[0].type);
+ const [scrollPosition, setScrollPosition] = useState(0);
+
+ const shownImageCount = Math.floor((sidePanelWidth.value - 32) / 98);
+ const imageWidth =
+ 90 + (sidePanelWidth.value - 32 - shownImageCount * 98) / shownImageCount;
+ const imageHeight = (54 * imageWidth) / 90;
+
+ const imageRows = Math.min(
+ Math.max(Math.floor((sidePanelHeight.value - 520) / imageHeight), 2),
+ 4,
+ );
+
+ const maxWidth = Math.ceil(styleList.length / imageRows);
+
+ const editorEngine = useContext(EngineContext);
+
+ const handlePickingStylizer = (picked: ArtStyle) => {
+ setSelection(picked);
+ if (editorEngine === null) {
+ console.log("Editor is null");
+ return;
+ }
+ editorEngine.art_style = picked;
+ };
+
+ return (
+
+
+
+
+
+ {[...Array(imageRows).keys()].map((_, rowCount) => (
+
+ {styleList
+ .filter((_, index) => index % imageRows === rowCount)
+ .map((style) => (
+
+ ))}
+
+ ))}
+
+
+ {scrollPosition > 0 && (
+
+
+
+ setScrollPosition(
+ Math.max(
+ scrollPosition - Math.max(shownImageCount - 1, 1),
+ 0,
+ ),
+ )
+ }
+ className="pointer-events-auto h-6 w-6 rounded-full bg-white/80 text-gray-800/75 hover:bg-white/100 hover:text-gray-800"
+ />
+
+
+ )}
+ {scrollPosition < maxWidth - shownImageCount && (
+
+
+
+ setScrollPosition(
+ Math.min(
+ scrollPosition + Math.max(shownImageCount - 1, 1),
+ maxWidth - shownImageCount,
+ ),
+ )
+ }
+ className="pointer-events-auto h-6 w-6 rounded-full bg-white/80 text-gray-800/75 hover:bg-white/100 hover:text-gray-800"
+ />
+
+
+ )}
+
+
+
+ );
+};
diff --git a/app/pages/PageEnigma/comps/SidePanelTabs/itemTabs/StylizeTab/StylizeTab.tsx b/app/pages/PageEnigma/comps/SidePanelTabs/itemTabs/StylizeTab/StylizeTab.tsx
new file mode 100644
index 0000000000..a81a270b91
--- /dev/null
+++ b/app/pages/PageEnigma/comps/SidePanelTabs/itemTabs/StylizeTab/StylizeTab.tsx
@@ -0,0 +1,21 @@
+import { TabTitle } from "~/pages/PageEnigma/comps/SidePanelTabs/comps/TabTitle";
+import { StyleSelection } from "./StyleSelection";
+import { Prompts } from "./Prompts";
+import { StyleButtons } from "./StyleButtons";
+import { sidePanelHeight } from "~/pages/PageEnigma/store";
+import { useSignals } from "@preact/signals-react/runtime";
+
+export function StylizeTab() {
+ useSignals();
+
+ return (
+
+ );
+}
diff --git a/app/pages/PageEnigma/comps/SidePanelTabs/tabList.tsx b/app/pages/PageEnigma/comps/SidePanelTabs/tabList.tsx
index 9fda05468a..38f9dadfbf 100644
--- a/app/pages/PageEnigma/comps/SidePanelTabs/tabList.tsx
+++ b/app/pages/PageEnigma/comps/SidePanelTabs/tabList.tsx
@@ -3,8 +3,8 @@ import { ObjectsTab } from "~/pages/PageEnigma/comps/SidePanelTabs/itemTabs/Obje
import { ShapeTab } from "~/pages/PageEnigma/comps/SidePanelTabs/itemTabs/ShapeTab";
import { AnimationTab } from "~/pages/PageEnigma/comps/SidePanelTabs/itemTabs/AnimationTab";
import { AudioTab } from "~/pages/PageEnigma/comps/SidePanelTabs/itemTabs/AudioTab";
-import { TabStylization } from "~/pages/PageEnigma/comps/SidePanelTabs/TabStylization";
import { CameraTab } from "./itemTabs/CameraTab";
+import { StylizeTab } from "./itemTabs/StylizeTab/StylizeTab";
export const tabList = [
{
icon: "/resources/icons/characters.png",
@@ -36,4 +36,10 @@ export const tabList = [
value: AssetType.AUDIO,
component: ,
},
+ {
+ icon: "/resources/icons/audios.png",
+ title: "AI Stylize",
+ value: AssetType.STYLE,
+ component: ,
+ },
];
diff --git a/app/pages/PageEnigma/constants/RandomTexts.ts b/app/pages/PageEnigma/constants/RandomTexts.ts
new file mode 100644
index 0000000000..6dc6fde12b
--- /dev/null
+++ b/app/pages/PageEnigma/constants/RandomTexts.ts
@@ -0,0 +1,86 @@
+export const RandomTexts = [
+ "Hello, world!",
+ "Welcome to the future.",
+ "The quick brown fox jumps over the lazy dog.",
+ "In a hole in the ground there lived a hobbit.",
+ "Once upon a time in a land far, far away.",
+ "Can't believe you've done this.",
+ "Sometimes, I wish I was an octopus, so I could slap eight people at once.",
+ "Explaining why one is right is not arguing, it's just clarifying.",
+ "Wallets are like onions; opening them brings tears.",
+ "I'm not lazy, I'm on energy-saving mode.",
+ "When life gives you melons, dyslexia might be involved.",
+ "Atoms are untrustworthy; they make up everything.",
+ "Glue history books are impossible to put down.",
+ "Time travel jokes are funny in any era, but you might have missed it.",
+ "I would lose weight, but I hate losing.",
+ "A messy room is just an open-air museum.",
+ "Trying to fail and succeeding is a real conundrum.",
+ "Procrastination is just engaging in numerous side quests.",
+ "Being early for tomorrow is a new kind of punctuality.",
+ "Adulthood is the longest test run that never ends.",
+ "Beauty sleep's advertising is misleading.",
+ "I'm on a whiskey diet. I've lost three days already.",
+ "Magical beds remember all forgotten tasks.",
+ "Pillows are the unsung heroes of hairstyling.",
+ "I'm not saying I'm Batman, but have you ever seen me and Batman in the same room?",
+ "Couches are the battlegrounds for avoiding problems.",
+ "Life's brevity demands self-laughter or outsourcing it.",
+ "Being a limited edition is far from weird.",
+ "Office chairs that spin make the job worth it.",
+ "Wake-up time defines personhood, not the time of day.",
+ "Math problems multiply in silence.",
+ "Physical conservatism is the new fitness trend.",
+ "Extra fries misunderstood as exercise is a common error.",
+ "I'm fluent in three languages: English, sarcasm, and profanity.",
+ "Multitasking involves listening, ignoring, and forgetting simultaneously.",
+ "Indecisiveness is a choice, sometimes.",
+ "I'm really good at stuff until people watch me do that stuff.",
+ "Correctness needs no argument, just explanation.",
+ "Coffee relationships are the most committed ones.",
+ "Rush hour is the greatest paradox.",
+ "I'm not bossy. I just have better ideas.",
+ "Silence and duct tape both have their merits.",
+ "I'm not procrastinating. I'm under a lot of pressure and very well could be a diamond soon.",
+ "Battery saver mode is essential for work avoidance.",
+ "Exploration is just being lost with style.",
+ "Pressing harder on a remote control seems like a valid effort when batteries are weak.",
+ "I'm convinced that bugs in software are just features in disguise.",
+ "Adulthood is getting excited about a new sponge for the kitchen, I've accepted this.",
+ "Life's too short, I always smile while I still have all my teeth.",
+ "In video games, I've learned that encountering enemies often means you're going in the right direction.",
+ "I'm often on the hunt for motivation, but it's like searching for a 404 error.",
+ "Debating with a computer, I've realized, is as effective as trying to solve algebra by chewing bubblegum.",
+ "During rush hour, I remind myself that patience is indeed a virtue.",
+ "I transformed a shy friend into a social butterfly, and now I wonder what I've unleashed.",
+ "The quest for sleep, sanity, and a peaceful hobbit life is something I'm still on.",
+ "My bed has a magical ability to remind me of forgotten tasks at night.",
+ "When the Wi-Fi goes down, I discover family members are actually nice people.",
+ "A cookie in each hand, I believe, is the true definition of a balanced diet.",
+ "Why use Google when I'm convinced someone believes they have all the answers?",
+ "Exploring the great indoors, I've found, is because outside is overrated.",
+ "I'm fluent in three languages: English, sarcasm, and late-night coding.",
+ "Why wait for a time machine when I have memories and music?",
+ "The best way to avoid chores, I've found, is to pretend not to know they exist.",
+ "If I can't find the sunshine, I've learned to be the person who switches on the light.",
+ "Realizing too late that adulthood is a trap is a lesson I've learned the hard way.",
+ "The art of being wise, I've discovered, is knowing what to overlook, like unread emails.",
+ "Why call it fast food if I have to wait in line for it?",
+ "I've discovered that my spirit animal is a sloth on weekdays.",
+ "Making a 'quick' phone call, I've realized, is never quick.",
+ "The mystery of how one sock always disappears in the laundry remains unsolved, I've noticed.",
+ "Finding out that my emergency contact is a pizza delivery service was a surprise.",
+ "The realization that autocorrect has become my worst enema... I mean, enemy, is frustrating.",
+ "Wondering why my coffee tastes like I should have made it myself is a daily ritual.",
+ "The silent joy of canceling plans is an underrated pleasure I cherish.",
+ "Discovering that my daily workout is trying to dodge spoilers online is a modern struggle.",
+ "Realizing that my phone's battery life lasts longer than my motivation is a harsh reality.",
+ "The paradox of being a perfectionist procrastinator is a real struggle I face.",
+ "Finding comfort in the fact that chocolate understands me is a sweet relief.",
+ "Realizing I'm not late, I'm just on a creative time schedule is how I cope.",
+ "Discovering that my hobby is collecting dust on my gym membership was an eye-opener.",
+ "The irony of being a tech expert but unable to fix my sleep schedule is not lost on me.",
+ "Understanding that my to-do list is more of a suggestion than a requirement helps me sleep at night.",
+ "The thrill of solving a bug in code is the coder's version of a plot twist, I've found.",
+ "Realizing that my idea of a balanced diet is having a piece of tech in both hands is a modern dilemma.",
+];
diff --git a/app/pages/PageEnigma/js/editor.ts b/app/pages/PageEnigma/js/editor.ts
index 71400770c8..cd5090920e 100644
--- a/app/pages/PageEnigma/js/editor.ts
+++ b/app/pages/PageEnigma/js/editor.ts
@@ -35,6 +35,7 @@ import { QueueNames } from "~/pages/PageEnigma/Queue/QueueNames";
import { fromEngineActions } from "~/pages/PageEnigma/Queue/fromEngineActions";
import { AssetType, MediaItem } from "~/pages/PageEnigma/models";
import { loadingBarData, loadingBarIsShowing } from "~/store/loadingBar";
+import { editorState, EditorStates } from "~/pages/PageEnigma/store/engine";
// Main editor class that will call everything else all you need to call is " initialize() ".
class Editor {
@@ -253,7 +254,9 @@ class Editor {
// Find the container element
const container = document.getElementById("video-scene-container");
- if (container == null) { return; }
+ if (container == null) {
+ return;
+ }
// Use the container's dimensions
const width = container.offsetWidth;
@@ -268,7 +271,6 @@ class Editor {
this.camera.layers.enable(0);
this.camera.layers.enable(1); // This camera does not see this layer
-
this.timeline.camera = this.camera;
this.render_camera = new THREE.PerspectiveCamera(
@@ -278,7 +280,6 @@ class Editor {
200,
);
-
this.render_camera.layers.disable(1); // This camera does not see this layer );
// Base WebGL render and clock for delta time.
@@ -328,10 +329,11 @@ class Editor {
// MIDDLE: THREE.MOUSE.ROTATE,
// RIGHT: THREE.MOUSE.PAN,
//}; // Blender Style
- this.orbitControls.mouseButtons = {
- LEFT: THREE.MOUSE.ROTATE,
- MIDDLE: THREE.MOUSE.DOLLY,
- RIGHT: THREE.MOUSE.PAN }; // Standard
+ this.orbitControls.mouseButtons = {
+ LEFT: THREE.MOUSE.ROTATE,
+ MIDDLE: THREE.MOUSE.DOLLY,
+ RIGHT: THREE.MOUSE.PAN,
+ }; // Standard
this.control = new TransformControls(this.camera, this.renderer.domElement);
this.control.space = "local"; // Local transformation mode
@@ -438,7 +440,7 @@ class Editor {
console.log(result);
}
- public async testTestTimelineEvents() { }
+ public async testTestTimelineEvents() {}
public async loadScene(scene_media_token: string) {
this.dispatchAppUiState({
@@ -589,6 +591,7 @@ class Editor {
type: APPUI_ACTION_TYPES.SHOW_CONTROLPANELS_SCENEOBJECT,
});
this.updateSelectedUI();
+ editorState.value = EditorStates.CAMERA_VIEW;
if (this.activeScene.hot_items) {
this.activeScene.hot_items.forEach((element) => {
element.visible = false;
@@ -616,6 +619,7 @@ class Editor {
this.dispatchAppUiState({
type: APPUI_ACTION_TYPES.HIDE_CONTROLPANELS_SCENEOBJECT,
});
+ editorState.value = EditorStates.EDIT;
}
}
}
@@ -812,15 +816,15 @@ class Editor {
if (this.selected === undefined) {
return 0;
}
- let posCombo =
+ const posCombo =
this.selected.position.x +
this.selected.position.y +
this.selected.position.z;
- let rotCombo =
+ const rotCombo =
this.selected.rotation.x +
this.selected.rotation.y +
this.selected.rotation.z;
- let sclCombo =
+ const sclCombo =
this.selected.scale.x + this.selected.scale.y + this.selected.scale.z;
return posCombo + rotCombo + sclCombo;
}
@@ -952,10 +956,10 @@ class Editor {
audioSegment,
"-filter_complex",
"[1:a]adelay=" +
- startTime * 1000 +
- "|" +
- startTime * 1000 +
- "[a1];[0:a][a1]amix=inputs=2[a]",
+ startTime * 1000 +
+ "|" +
+ startTime * 1000 +
+ "[a1];[0:a][a1]amix=inputs=2[a]",
"-map",
"[a]",
`${itteration}final_tmp.wav`,
@@ -1094,15 +1098,18 @@ class Editor {
const stylePreview: HTMLVideoElement | null = document.getElementById(
"styled-preview",
) as HTMLVideoElement;
- this.rawRenderer.setSize(stylePreview.width, stylePreview.height);
- this.render_camera.aspect = stylePreview.width / stylePreview.height;
+ if (stylePreview != null) {
+ this.rawRenderer.setSize(stylePreview.width, stylePreview.height);
+ this.render_camera.aspect = stylePreview.width / stylePreview.height;
+ }
}
}
- switchPreview() {
- if (this.switchPreviewToggle == false) {
+ async switchPreview() {
+ if (!this.switchPreviewToggle) {
this.switchPreviewToggle = true;
- this.generateFrame();
+ editorState.value = EditorStates.PREVIEW;
+ await this.generateFrame();
if (this.cameraViewControls) {
this.cameraViewControls.enabled = false;
}
@@ -1110,18 +1117,21 @@ class Editor {
}
switchEdit() {
- if (this.switchPreviewToggle == true) {
+ if (this.switchPreviewToggle) {
this.switchPreviewToggle = false;
- this.canvasRenderCamReference = document.getElementById("camera-view");
- this.rawRenderer = new THREE.WebGLRenderer({
- antialias: false,
- canvas: this.canvasRenderCamReference,
- preserveDrawingBuffer: true,
- });
- if (this.camera_person_mode == true) {
- this.switchCameraView();
- }
- this.activeScene.renderMode(false);
+ editorState.value = EditorStates.EDIT;
+ setTimeout(() => {
+ this.canvasRenderCamReference = document.getElementById("camera-view");
+ this.rawRenderer = new THREE.WebGLRenderer({
+ antialias: false,
+ canvas: this.canvasRenderCamReference,
+ preserveDrawingBuffer: true,
+ });
+ if (this.camera_person_mode) {
+ this.switchCameraView();
+ }
+ this.activeScene.renderMode(false);
+ }, 0);
}
}
@@ -1147,14 +1157,15 @@ class Editor {
this.activeScene.renderMode(false);
this.onWindowResize();
- this.canvasRenderCamReference = document.getElementById("raw-preview");
+ this.canvasRenderCamReference = document.getElementById("video-scene");
this.rawRenderer = new THREE.WebGLRenderer({
antialias: false,
canvas: this.canvasRenderCamReference,
preserveDrawingBuffer: true,
});
- if (this.camera_person_mode == false) {
+ if (!this.camera_person_mode) {
this.switchCameraView();
+ editorState.value = EditorStates.PREVIEW;
}
this.activeScene.renderMode(true);
@@ -1166,27 +1177,30 @@ class Editor {
const blob = new Blob([output.buffer], { type: "video/mp4" });
this.generating_preview = false;
- const url = await this.api_manager.uploadMediaFrameGeneration(
- blob,
- "render.mp4",
- this.art_style,
- this.positive_prompt,
- this.negative_prompt,
- );
- console.log(url);
+ try {
+ const url = await this.api_manager.uploadMediaFrameGeneration(
+ blob,
+ "render.mp4",
+ this.art_style,
+ this.positive_prompt,
+ this.negative_prompt,
+ );
+ console.log(url);
- const stylePreview: HTMLVideoElement | null = document.getElementById(
- "styled-preview",
- ) as HTMLVideoElement;
- if (stylePreview) {
- stylePreview.src = url;
- } else {
- console.log("No style preview window.");
+ const stylePreview: HTMLVideoElement | null = document.getElementById(
+ "video-scene",
+ ) as HTMLVideoElement;
+ if (stylePreview) {
+ stylePreview.src = url;
+ } else {
+ console.log("No style preview window.");
+ }
+
+ return Promise.resolve(url);
+ } catch (err: any) {
+ console.log(err.message);
+ return Promise.resolve("");
}
-
- return new Promise((resolve, reject) => {
- resolve(url);
- });
}
}
@@ -1316,7 +1330,7 @@ class Editor {
if (!container) return;
const resizeObserver = new ResizeObserver((entries) => {
- for (let entry of entries) {
+ for (const entry of entries) {
const { width, height } = entry.contentRect;
this.camera.aspect = width / height;
this.camera.updateProjectionMatrix();
@@ -1340,7 +1354,7 @@ class Editor {
}
if (event.button !== 0) {
- let camera_pos = new THREE.Vector3(
+ const camera_pos = new THREE.Vector3(
parseFloat(this.camera.position.x.toFixed(2)),
parseFloat(this.camera.position.y.toFixed(2)),
parseFloat(this.camera.position.z.toFixed(2)),
@@ -1350,13 +1364,17 @@ class Editor {
}
onkeydown(event: any) {
- if (event.key === 'f' && this.selected && this.orbitControls) {
+ if (event.key === "f" && this.selected && this.orbitControls) {
this.orbitControls.target.copy(this.selected.position);
this.orbitControls.maxDistance = 4;
this.orbitControls.update();
this.orbitControls.maxDistance = 999;
- } else if (event.key === ' ') {
- if(this.rendering == false && this.switchPreviewToggle == false && this.selectedCanvas){
+ } else if (event.key === " ") {
+ if (
+ this.rendering == false &&
+ this.switchPreviewToggle == false &&
+ this.selectedCanvas
+ ) {
this.startPlayback();
}
}
@@ -1375,7 +1393,7 @@ class Editor {
// When the mouse clicks the screen.
onMouseClick() {
- let camera_pos = new THREE.Vector3(
+ const camera_pos = new THREE.Vector3(
parseFloat(this.camera.position.x.toFixed(2)),
parseFloat(this.camera.position.y.toFixed(2)),
parseFloat(this.camera.position.z.toFixed(2)),
diff --git a/app/pages/PageEnigma/js/timeline.ts b/app/pages/PageEnigma/js/timeline.ts
index 0eccab06e2..9389d0eed8 100644
--- a/app/pages/PageEnigma/js/timeline.ts
+++ b/app/pages/PageEnigma/js/timeline.ts
@@ -16,6 +16,7 @@ import { fromEngineActions } from "../Queue/fromEngineActions";
import { ClipGroup, ClipType } from "~/pages/PageEnigma/models/track";
import { MediaItem } from "~/pages/PageEnigma/models";
import Editor from "~/pages/PageEnigma/js/editor";
+import { editorState, EditorStates } from "~/pages/PageEnigma/store/engine";
import EmotionEngine from "./emotion_engine";
// Every object uuid / entity has a track.
@@ -70,7 +71,7 @@ export class TimeLine {
emotion_engine: EmotionEngine,
scene: Scene,
camera: THREE.Camera,
- mouse: THREE.Vector2 | undefined
+ mouse: THREE.Vector2 | undefined,
) {
this.editorEngine = editor;
this.timeline_items = [];
@@ -156,6 +157,18 @@ export class TimeLine {
case toEngineActions.ADD_SHAPE:
await this.addShape(data);
break;
+ case toEngineActions.ENTER_PREVIEW_STATE:
+ await this.editorEngine.switchPreview();
+ break;
+ case toEngineActions.ENTER_EDIT_STATE:
+ this.editorEngine.switchEdit();
+ break;
+ case toEngineActions.TOGGLE_CAMERA_STATE:
+ this.editorEngine.switchCameraView();
+ break;
+ case toEngineActions.GENERATE_VIDEO:
+ this.editorEngine.generateVideo();
+ break;
default:
console.log("Action Not Wired", action);
}
@@ -164,8 +177,8 @@ export class TimeLine {
public async addCharacter(data: { data: MediaItem }) {
const media_id = data.data.media_id;
const name = data.data.name;
- let pos = this.getPos();
- let new_data = { ...data.data };
+ const pos = this.getPos();
+ const new_data = { ...data.data };
const obj = await this.scene.load_glb(media_id);
obj.userData["name"] = name;
@@ -217,10 +230,13 @@ export class TimeLine {
}
public getPos() {
- let raycaster = new THREE.Raycaster();
+ const raycaster = new THREE.Raycaster();
if (this.mouse && this.camera) {
raycaster.setFromCamera(this.mouse, this.camera);
- const intersects = raycaster.intersectObjects(this.scene.scene.children, false);
+ const intersects = raycaster.intersectObjects(
+ this.scene.scene.children,
+ false,
+ );
console.log(intersects);
if (intersects.length > 0) {
return intersects[0].point;
@@ -230,7 +246,7 @@ export class TimeLine {
}
public async addObject(data: { data: MediaItem }) {
- let pos = this.getPos();
+ const pos = this.getPos();
const media_id = data.data.media_id;
const name = data.data.name;
const obj = await this.scene.load_glb(media_id);
@@ -240,7 +256,7 @@ export class TimeLine {
}
public async addShape({ data }: { data: MediaItem }) {
- let pos = this.getPos();
+ const pos = this.getPos();
this.editorEngine.create_parim(data.media_id, pos);
}
@@ -297,8 +313,10 @@ export class TimeLine {
}
public deleteObject(object_uuid: string) {
- let object = this.scene.get_object_by_uuid(object_uuid);
- if (object?.name === "::CAM::") { return; }
+ const object = this.scene.get_object_by_uuid(object_uuid);
+ if (object?.name === "::CAM::") {
+ return;
+ }
this.timeline_items = this.timeline_items.filter(
(element) => element.object_uuid !== object_uuid,
);
@@ -471,15 +489,15 @@ export class TimeLine {
public async updatePlayableClip(
clip_uuid: string,
updates: AnyJson,
- ): Promise { }
+ ): Promise {}
- public async deletePlayableClip(clip_uuid: string): Promise { }
+ public async deletePlayableClip(clip_uuid: string): Promise {}
public async scrub(data: any): Promise {
if (this.is_playing) {
return;
}
- const value = Math.floor(data["data"]["currentTime"])
+ const value = Math.floor(data["data"]["currentTime"]);
this.setScrubberPosition(value);
this.update();
}
@@ -492,7 +510,7 @@ export class TimeLine {
});
}
- public async scrubberDidStop(offset_frame: number) { }
+ public async scrubberDidStop(offset_frame: number) {}
// public streaming events into the timeline from
public async setScrubberPosition(offset: number) {
this.scrubber_frame_position = offset; // in ms
@@ -623,7 +641,7 @@ export class TimeLine {
await this.animation_engine.clips[
object.uuid + element.media_id
].play(object);
- let fps = 60;
+ const fps = 60;
this.animation_engine.clips[object.uuid + element.media_id].step(
this.scrubber_frame_position / fps, // Double FPS for best result.
);
@@ -659,4 +677,4 @@ export class TimeLine {
currentTime: this.current_time,
});
}
-}
\ No newline at end of file
+}
diff --git a/app/pages/PageEnigma/store/engine.ts b/app/pages/PageEnigma/store/engine.ts
new file mode 100644
index 0000000000..abec890f79
--- /dev/null
+++ b/app/pages/PageEnigma/store/engine.ts
@@ -0,0 +1,9 @@
+import { signal } from "@preact/signals-core";
+
+export enum EditorStates {
+ EDIT,
+ CAMERA_VIEW,
+ PREVIEW,
+}
+
+export const editorState = signal(EditorStates.EDIT);
diff --git a/app/pages/PageEnigma/styleList.ts b/app/pages/PageEnigma/styleList.ts
index cdaaaa1f07..f3d0eeb06e 100644
--- a/app/pages/PageEnigma/styleList.ts
+++ b/app/pages/PageEnigma/styleList.ts
@@ -4,81 +4,81 @@ export const styleList = [
{
label: "Anime",
type: ArtStyle.Anime2_5D,
- image: "/resources/avatars/0.webp",
+ image: "/resources/placeholders/style-placeholder.png",
},
{
label: "Anime Flat",
type: ArtStyle.Anime2DFlat,
- image: "/resources/avatars/1.webp",
+ image: "/resources/placeholders/style-placeholder.png",
},
{
label: "Cartoon 3D",
type: ArtStyle.Cartoon3D,
- image: "/resources/avatars/2.webp",
+ image: "/resources/placeholders/style-placeholder.png",
},
{
label: "Comic Book",
type: ArtStyle.ComicBook,
- image: "/resources/avatars/3.webp",
+ image: "/resources/placeholders/style-placeholder.png",
},
{
label: "Ghibli",
type: ArtStyle.AnimeGhibli,
- image: "/resources/avatars/4.webp",
+ image: "/resources/placeholders/style-placeholder.png",
},
{
label: "Ink Punk",
type: ArtStyle.InkPunk,
- image: "/resources/avatars/5.webp",
+ image: "/resources/placeholders/style-placeholder.png",
},
{
label: "Ink Splash",
type: ArtStyle.InkSplash,
- image: "/resources/avatars/6.webp",
+ image: "/resources/placeholders/style-placeholder.png",
},
{
label: "Ink Black and White",
type: ArtStyle.InkBWStyle,
- image: "/resources/avatars/7.webp",
+ image: "/resources/placeholders/style-placeholder.png",
},
{
label: "Jo Jo Style",
type: ArtStyle.JojoStyle,
- image: "/resources/avatars/8.webp",
+ image: "/resources/placeholders/style-placeholder.png",
},
{
label: "Paper Origami",
type: ArtStyle.PaperOrigami,
- image: "/resources/avatars/9.webp",
+ image: "/resources/placeholders/style-placeholder.png",
},
{
label: "Pixel",
type: ArtStyle.PixelArt,
- image: "/resources/avatars/10.webp",
+ image: "/resources/placeholders/style-placeholder.png",
},
{
label: "Pop Art",
type: ArtStyle.PopArt,
- image: "/resources/avatars/11.webp",
+ image: "/resources/placeholders/style-placeholder.png",
},
{
label: "Realistic 1",
type: ArtStyle.Realistic1,
- image: "/resources/avatars/12.webp",
+ image: "/resources/placeholders/style-placeholder.png",
},
{
label: "Realistic 2",
type: ArtStyle.Realistic2,
- image: "/resources/avatars/13.webp",
+ image: "/resources/placeholders/style-placeholder.png",
},
{
label: "Anime Retro Neon",
type: ArtStyle.AnimeRetroNeon,
- image: "/resources/avatars/14.webp",
+ image: "/resources/placeholders/style-placeholder.png",
},
{
label: "Anime Standard",
type: ArtStyle.AnimeStandard,
- image: "/resources/avatars/15.webp",
+ image: "/resources/placeholders/style-placeholder.png",
},
];
diff --git a/app/styles/tailwind.css b/app/styles/tailwind.css
index d980c43d3a..4473d25b6c 100644
--- a/app/styles/tailwind.css
+++ b/app/styles/tailwind.css
@@ -4,14 +4,14 @@
@layer components {
.filter-tab {
- @apply text-nowrap rounded-lg border-2 border-assets-background bg-assets-background px-3 py-2 text-sm font-medium transition-all duration-150 hover:border-assets-background/0 hover:bg-assets-background/80;
+ @apply text-nowrap rounded-lg border-2 border-assets-background bg-assets-background px-2.5 py-1.5 text-sm font-medium text-white/80 transition-all duration-150 hover:border-assets-background/0 hover:bg-assets-background/80;
}
.filter-tab.active {
- @apply border-2 border-brand-primary hover:border-brand-primary hover:bg-assets-background;
+ @apply border-2 border-brand-primary text-white hover:border-brand-primary hover:bg-assets-background;
}
- .filter-tab.disabled {
- @apply hover:bg-assets-background disabled:text-white/50;
+ .filter-tab:disabled {
+ @apply border-transparent bg-assets-background/50 hover:border-transparent disabled:text-white/30;
}
}
diff --git a/public/resources/placeholders/style-placeholder.png b/public/resources/placeholders/style-placeholder.png
new file mode 100644
index 0000000000..26aa85367b
Binary files /dev/null and b/public/resources/placeholders/style-placeholder.png differ