mirror of
https://github.com/storytold/artcraft.git
synced 2026-11-04 17:38:10 +00:00
More refactor/cleanup
This commit is contained in:
1 parent
76192c782b
commit
4898233e52
21 files changed
+209
-167
No files matched your search
@@ -1,5 +1,5 @@
|
||||
import { useCallback, useContext, useEffect } from "react";
|
||||
import { MediaClip } from "~/pages/PageEnigma/models/track";
|
||||
import { ClipType, MediaClip } from "~/pages/PageEnigma/models/track";
|
||||
import { TrackContext } from "~/pages/PageEnigma/contexts/TrackContext/TrackContext";
|
||||
import {
|
||||
canDrop,
|
||||
@@ -11,7 +11,7 @@ import { useSignals } from "@preact/signals-react/runtime";
|
||||
|
||||
interface Props {
|
||||
clip: MediaClip;
|
||||
type: "animations" | "audio";
|
||||
type: ClipType;
|
||||
}
|
||||
|
||||
export const AnimationElement = ({ clip, type }: Props) => {
|
||||
|
||||
@@ -3,6 +3,7 @@ import { AnimationElement } from "./AnimationElement";
|
||||
import { TrackContext } from "~/pages/PageEnigma/contexts/TrackContext/TrackContext";
|
||||
import { useSignals } from "@preact/signals-react/runtime";
|
||||
import { timelineHeight } from "~/pages/PageEnigma/store";
|
||||
import { ClipType } from "~/pages/PageEnigma/models/track";
|
||||
|
||||
export const AnimationElements = () => {
|
||||
const { animationClips } = useContext(TrackContext);
|
||||
@@ -17,7 +18,11 @@ export const AnimationElements = () => {
|
||||
<div className="flex flex-wrap gap-3 overflow-y-auto" style={{ height }}>
|
||||
{animationClips.map((clip) => {
|
||||
return (
|
||||
<AnimationElement key={clip.media_id} clip={clip} type="animations" />
|
||||
<AnimationElement
|
||||
key={clip.media_id}
|
||||
clip={clip}
|
||||
type={ClipType.ANIMATION}
|
||||
/>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { useCallback, useContext, useEffect } from "react";
|
||||
import { MediaClip } from "~/pages/PageEnigma/models/track";
|
||||
import { ClipType, MediaClip } from "~/pages/PageEnigma/models/track";
|
||||
import { TrackContext } from "~/pages/PageEnigma/contexts/TrackContext/TrackContext";
|
||||
import {
|
||||
canDrop,
|
||||
@@ -11,7 +11,7 @@ import { useSignals } from "@preact/signals-react/runtime";
|
||||
|
||||
interface Props {
|
||||
clip: MediaClip;
|
||||
type: "animations" | "audio";
|
||||
type: ClipType;
|
||||
}
|
||||
|
||||
export const AudioElement = ({ clip, type }: Props) => {
|
||||
|
||||
@@ -7,10 +7,11 @@ import {
|
||||
updateCharacters,
|
||||
} from "~/pages/PageEnigma/store";
|
||||
import { TrackKeyFrames } from "~/pages/PageEnigma/comps/Timeline/TrackKeyFrames";
|
||||
import { ClipGroup, ClipType } from "~/pages/PageEnigma/models/track";
|
||||
|
||||
function buildUpdaters(
|
||||
updateCharacters: (options: {
|
||||
type: "animations" | "positions" | "lipSync";
|
||||
type: ClipType;
|
||||
id: string;
|
||||
length: number;
|
||||
offset: number;
|
||||
@@ -21,17 +22,17 @@ function buildUpdaters(
|
||||
length: number;
|
||||
offset: number;
|
||||
}) {
|
||||
updateCharacters({ ...options, type: "animations" });
|
||||
updateCharacters({ ...options, type: ClipType.ANIMATION });
|
||||
}
|
||||
function updateClipPosition(options: { id: string; offset: number }) {
|
||||
updateCharacters({ ...options, length: 0, type: "positions" });
|
||||
updateCharacters({ ...options, length: 0, type: ClipType.TRANSFORM });
|
||||
}
|
||||
function updateClipLipSync(options: {
|
||||
id: string;
|
||||
length: number;
|
||||
offset: number;
|
||||
}) {
|
||||
updateCharacters({ ...options, type: "lipSync" });
|
||||
updateCharacters({ ...options, type: ClipType.AUDIO });
|
||||
}
|
||||
return { updateClipLipSync, updateClipPosition, updateClipAnimations };
|
||||
}
|
||||
@@ -68,15 +69,15 @@ export const Character = ({ characterId }: Props) => {
|
||||
clips={animationClips}
|
||||
title="Animation"
|
||||
updateClip={updateClipAnimations}
|
||||
style="character"
|
||||
type="animations"
|
||||
group={ClipGroup.CHARACTER}
|
||||
type={ClipType.ANIMATION}
|
||||
/>
|
||||
<TrackKeyFrames
|
||||
id={character.id}
|
||||
keyframes={positionKeyframes}
|
||||
title="Character Position/Rotation"
|
||||
updateKeyframe={updateClipPosition}
|
||||
style="character"
|
||||
group={ClipGroup.CHARACTER}
|
||||
/>
|
||||
<TrackClips
|
||||
id={character.id}
|
||||
@@ -85,8 +86,8 @@ export const Character = ({ characterId }: Props) => {
|
||||
updateClip={updateClipLipSync}
|
||||
muted={character.muted}
|
||||
toggleMute={toggleCharacterLipSyncMute}
|
||||
style="character"
|
||||
type="lipSync"
|
||||
group={ClipGroup.CHARACTER}
|
||||
type={ClipType.AUDIO}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import { fullWidth, objectGroup, updateObject } from "~/pages/PageEnigma/store";
|
||||
import { TrackKeyFrames } from "~/pages/PageEnigma/comps/Timeline/TrackKeyFrames";
|
||||
import { ClipGroup } from "~/pages/PageEnigma/models/track";
|
||||
|
||||
export const ObjectTrack = () => {
|
||||
return (
|
||||
@@ -17,7 +18,7 @@ export const ObjectTrack = () => {
|
||||
keyframes={object.keyframes}
|
||||
title={`${object.name} Position/Rotation`}
|
||||
updateKeyframe={updateObject}
|
||||
style="objects"
|
||||
group={ClipGroup.OBJECT}
|
||||
/>
|
||||
</div>
|
||||
))}
|
||||
|
||||
File renamed without changes.
@@ -13,7 +13,7 @@ import {
|
||||
import { useQueueHandler } from "~/pages/PageEnigma/comps/Timeline/utils/useQueueHandler";
|
||||
import { useSignals } from "@preact/signals-react/runtime";
|
||||
import { TimerGrid } from "~/pages/PageEnigma/comps/TimerGrid/TimerGrid";
|
||||
import { Scrubber } from "~/pages/PageEnigma/comps/Scrubber/Scrubber";
|
||||
import { Scrubber } from "~/pages/PageEnigma/comps/Timeline/Scrubber";
|
||||
import { Characters } from "~/pages/PageEnigma/comps/Timeline/Characters";
|
||||
import { ObjectGroups } from "~/pages/PageEnigma/comps/Timeline/ObjectGroups";
|
||||
import useUpdateKeyframe from "~/pages/PageEnigma/contexts/TrackContext/utils/useUpdateKeyframe";
|
||||
|
||||
@@ -1,17 +1,17 @@
|
||||
import { useMouseEventsClip } from "./utils/useMouseEventsClip";
|
||||
import { useState } from "react";
|
||||
import { scale, selectedItem } from "~/pages/PageEnigma/store";
|
||||
import { Clip } from "~/pages/PageEnigma/models/track";
|
||||
import { Clip, ClipGroup } from "~/pages/PageEnigma/models/track";
|
||||
|
||||
interface Props {
|
||||
min: number;
|
||||
max: number;
|
||||
style: "character" | "camera" | "audio" | "objects";
|
||||
group: ClipGroup;
|
||||
clip: Clip;
|
||||
updateClip: (options: { id: string; offset: number; length: number }) => void;
|
||||
}
|
||||
|
||||
export const TrackClip = ({ clip, min, max, style, updateClip }: Props) => {
|
||||
export const TrackClip = ({ clip, min, max, group, updateClip }: Props) => {
|
||||
const [state, setState] = useState({
|
||||
length: clip.length,
|
||||
offset: clip.offset,
|
||||
@@ -31,8 +31,8 @@ export const TrackClip = ({ clip, min, max, style, updateClip }: Props) => {
|
||||
const classes = [
|
||||
"absolute",
|
||||
clip.clip_uuid === selectedClipId
|
||||
? `bg-${style}-selected`
|
||||
: `bg-${style}-clip`,
|
||||
? `bg-${group}-selected`
|
||||
: `bg-${group}-clip`,
|
||||
];
|
||||
|
||||
return (
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { TrackClip } from "~/pages/PageEnigma/comps/Timeline/TrackClip";
|
||||
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
|
||||
import { faVolume, faVolumeSlash } from "@fortawesome/pro-solid-svg-icons";
|
||||
import { Clip } from "~/pages/PageEnigma/models/track";
|
||||
import { Clip, ClipGroup, ClipType } from "~/pages/PageEnigma/models/track";
|
||||
import { PointerEvent } from "react";
|
||||
import {
|
||||
canDrop,
|
||||
@@ -17,13 +17,38 @@ interface Props {
|
||||
id: string;
|
||||
clips: Clip[];
|
||||
title: string;
|
||||
style: "character" | "audio" | "camera" | "objects";
|
||||
type?: "animations" | "positions" | "lipSync";
|
||||
group: ClipGroup;
|
||||
type?: ClipType;
|
||||
toggleMute?: () => void;
|
||||
muted?: boolean;
|
||||
updateClip: (options: { id: string; length: number; offset: number }) => void;
|
||||
}
|
||||
|
||||
function getCanBuild({
|
||||
dragType,
|
||||
type,
|
||||
group,
|
||||
}: {
|
||||
dragType: ClipType | null;
|
||||
type?: ClipType;
|
||||
group: ClipGroup;
|
||||
}) {
|
||||
if (dragType === ClipType.ANIMATION) {
|
||||
if (dragType === type) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
if (dragType === ClipType.AUDIO) {
|
||||
if (group === ClipGroup.CHARACTER && type === ClipType.AUDIO) {
|
||||
return true;
|
||||
}
|
||||
if (group === ClipGroup.GLOBAL_AUDIO) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
export const TrackClips = ({
|
||||
id,
|
||||
clips,
|
||||
@@ -31,36 +56,22 @@ export const TrackClips = ({
|
||||
updateClip,
|
||||
muted,
|
||||
title,
|
||||
style,
|
||||
group,
|
||||
type,
|
||||
}: Props) => {
|
||||
const trackType = type ?? style;
|
||||
const trackType = (type ?? group) as ClipType;
|
||||
|
||||
function onPointerOver() {
|
||||
if (dragType.value === "animations") {
|
||||
if (dragType.value !== trackType) {
|
||||
return;
|
||||
}
|
||||
if (getCanBuild({ dragType: dragType.value, type, group })) {
|
||||
dropId.value = id;
|
||||
}
|
||||
if (dragType.value === "audio") {
|
||||
if (["lipSync", "audio"].indexOf(trackType) === -1) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
dropId.value = id;
|
||||
}
|
||||
|
||||
function onPointerMove(event: PointerEvent<HTMLDivElement>) {
|
||||
if (dragType.value === "animations") {
|
||||
if (dragType.value !== trackType) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (dragType.value === "audio") {
|
||||
if (["lipSync", "audio"].indexOf(trackType) === -1) {
|
||||
return;
|
||||
}
|
||||
if (!getCanBuild({ dragType: dragType.value, type, group })) {
|
||||
return;
|
||||
}
|
||||
|
||||
const track = document.getElementById(`track-${trackType}-${id}`);
|
||||
if (!track) {
|
||||
return;
|
||||
@@ -101,7 +112,7 @@ export const TrackClips = ({
|
||||
<div className="pl-16">
|
||||
<div
|
||||
id={`track-${trackType}-${id}`}
|
||||
className={`relative mt-4 block h-9 w-full rounded-lg bg-${style}-unselected`}
|
||||
className={`relative mt-4 block h-9 w-full rounded-lg bg-${group}-unselected`}
|
||||
onPointerOver={onPointerOver}
|
||||
onPointerLeave={onPointerLeave}
|
||||
onPointerMove={onPointerMove}
|
||||
@@ -117,7 +128,7 @@ export const TrackClips = ({
|
||||
? clips[index + 1].offset
|
||||
: filmLength.value * 60
|
||||
}
|
||||
style={style}
|
||||
group={group}
|
||||
updateClip={updateClip}
|
||||
clip={clip}
|
||||
/>
|
||||
|
||||
@@ -1,28 +1,21 @@
|
||||
import { Keyframe } from "~/pages/PageEnigma/models/track";
|
||||
import { useState } from "react";
|
||||
import { scale, selectedItem } from "~/pages/PageEnigma/store";
|
||||
import { filmLength, scale, selectedItem } from "~/pages/PageEnigma/store";
|
||||
import { useMouseEventsKeyframe } from "~/pages/PageEnigma/comps/Timeline/utils/useMouseEventsKeyframe";
|
||||
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
|
||||
import { faSortUpDown } from "@fortawesome/pro-solid-svg-icons";
|
||||
import { useSignals } from "@preact/signals-react/runtime";
|
||||
|
||||
interface Props {
|
||||
min: number;
|
||||
max: number;
|
||||
keyframe: Keyframe;
|
||||
updateKeyframe: (options: { id: string; offset: number }) => void;
|
||||
}
|
||||
|
||||
export const TrackKeyFrame = ({
|
||||
keyframe,
|
||||
min,
|
||||
max,
|
||||
updateKeyframe,
|
||||
}: Props) => {
|
||||
export const TrackKeyFrame = ({ keyframe, updateKeyframe }: Props) => {
|
||||
useSignals();
|
||||
const [offset, setOffset] = useState(keyframe.offset);
|
||||
const { onPointerDown } = useMouseEventsKeyframe({
|
||||
keyframe,
|
||||
max,
|
||||
min,
|
||||
max: filmLength.value * 60,
|
||||
min: 0,
|
||||
updateKeyframe,
|
||||
setOffset,
|
||||
});
|
||||
|
||||
@@ -1,15 +1,18 @@
|
||||
import { Keyframe } from "~/pages/PageEnigma/models/track";
|
||||
import { filmLength } from "~/pages/PageEnigma/store";
|
||||
import { ClipGroup, Keyframe } from "~/pages/PageEnigma/models/track";
|
||||
import { TrackKeyFrame } from "~/pages/PageEnigma/comps/Timeline/TrackKeyFrame";
|
||||
|
||||
interface Props {
|
||||
id: string;
|
||||
keyframes: Keyframe[];
|
||||
title: string;
|
||||
style: "character" | "audio" | "camera" | "objects";
|
||||
group: ClipGroup;
|
||||
toggleMute?: () => void;
|
||||
muted?: boolean;
|
||||
updateKeyframe: (options: { id: string; offset: number }) => void;
|
||||
updateKeyframe: (options: {
|
||||
id: string;
|
||||
offset: number;
|
||||
force?: boolean;
|
||||
}) => void;
|
||||
}
|
||||
|
||||
export const TrackKeyFrames = ({
|
||||
@@ -17,23 +20,17 @@ export const TrackKeyFrames = ({
|
||||
keyframes,
|
||||
updateKeyframe,
|
||||
title,
|
||||
style,
|
||||
group,
|
||||
}: Props) => {
|
||||
return (
|
||||
<div className="pl-16">
|
||||
<div
|
||||
id={`track-${style}-${id}`}
|
||||
className={`relative mt-4 block h-9 w-full rounded-lg bg-${style}-unselected`}
|
||||
id={`track-${group}-${id}`}
|
||||
className={`relative mt-4 block h-9 w-full rounded-lg bg-${group}-unselected`}
|
||||
>
|
||||
{keyframes.map((keyframe, index) => (
|
||||
{keyframes.map((keyframe) => (
|
||||
<TrackKeyFrame
|
||||
key={keyframe.keyframe_uuid}
|
||||
min={index > 0 ? keyframes[index - 1].offset + 1 : 0}
|
||||
max={
|
||||
index < keyframes.length - 1
|
||||
? keyframes[index + 1].offset
|
||||
: filmLength.value * 60
|
||||
}
|
||||
updateKeyframe={updateKeyframe}
|
||||
keyframe={keyframe}
|
||||
/>
|
||||
|
||||
@@ -37,13 +37,11 @@ export const useMouseEventsClip = (
|
||||
if (isActive.current === "drag") {
|
||||
if (deltaOffset < min) {
|
||||
currOffset.current = min;
|
||||
return;
|
||||
} else if (deltaOffset + currLength.current > max) {
|
||||
currOffset.current = max;
|
||||
} else {
|
||||
currOffset.current = deltaOffset;
|
||||
}
|
||||
if (deltaOffset + currLength.current > max) {
|
||||
currOffset.current = max - currLength.current;
|
||||
return;
|
||||
}
|
||||
currOffset.current = deltaOffset;
|
||||
}
|
||||
if (isActive.current === "left") {
|
||||
if (initLength.current - delta < 30 || deltaOffset < min) {
|
||||
|
||||
@@ -1,6 +1,10 @@
|
||||
import React, { Dispatch, useCallback, useEffect, useRef } from "react";
|
||||
import { Keyframe } from "~/pages/PageEnigma/models/track";
|
||||
import { canDrop, scale } from "~/pages/PageEnigma/store";
|
||||
import {
|
||||
canDrop,
|
||||
scale,
|
||||
showDuplicateOffsetWarning,
|
||||
} from "~/pages/PageEnigma/store";
|
||||
import { useSignals } from "@preact/signals-react/runtime";
|
||||
|
||||
export const useMouseEventsKeyframe = ({
|
||||
@@ -40,15 +44,13 @@ export const useMouseEventsKeyframe = ({
|
||||
if (isActive.current === "drag") {
|
||||
if (deltaOffset < min) {
|
||||
currOffset.current = min;
|
||||
return;
|
||||
}
|
||||
if (deltaOffset > max) {
|
||||
} else if (deltaOffset > max) {
|
||||
currOffset.current = max;
|
||||
return;
|
||||
} else {
|
||||
currOffset.current = deltaOffset;
|
||||
}
|
||||
currOffset.current = deltaOffset;
|
||||
setOffset(currOffset.current);
|
||||
}
|
||||
setOffset(currOffset.current);
|
||||
},
|
||||
[max, min, setOffset],
|
||||
);
|
||||
|
||||
@@ -3,6 +3,7 @@ import {
|
||||
MediaClip,
|
||||
Keyframe,
|
||||
QueueKeyframe,
|
||||
ClipType,
|
||||
} from "~/pages/PageEnigma/models/track";
|
||||
|
||||
export const TrackContext = createContext<{
|
||||
@@ -15,7 +16,7 @@ export const TrackContext = createContext<{
|
||||
audioClips: MediaClip[];
|
||||
|
||||
// drag and drop
|
||||
startDrag: (type: "animations" | "audio", id: string, length: number) => void;
|
||||
startDrag: (type: ClipType, id: string, length: number) => void;
|
||||
endDrag: () => void;
|
||||
}>({
|
||||
addKeyframe: () => {},
|
||||
|
||||
@@ -1,47 +1,49 @@
|
||||
// Clip offsets represent the state of the clip on the timeline as well as what type of clip it is.
|
||||
// it is created from a media id.
|
||||
import { ClipGroup, ClipType } from "~/pages/PageEnigma/models/track";
|
||||
|
||||
export class ClipUI {
|
||||
version: number
|
||||
type: "transform" | "audio" | "animation" | "lipsync"
|
||||
group: "character" | "object" | "camera" | "global_audio"
|
||||
name: string
|
||||
media_id: string
|
||||
object_uuid: string
|
||||
offset: number // in frames
|
||||
length: number // in frames
|
||||
version: number;
|
||||
type: ClipType;
|
||||
group: ClipGroup;
|
||||
name: string;
|
||||
media_id: string;
|
||||
object_uuid: string;
|
||||
offset: number; // in frames
|
||||
length: number; // in frames
|
||||
|
||||
constructor(
|
||||
version: number,
|
||||
type: "transform" | "audio" | "animation" | "lipsync",
|
||||
group: "character" | "object" | "camera" | "global_audio",
|
||||
type: ClipType,
|
||||
group: ClipGroup,
|
||||
name: string,
|
||||
media_id: string,
|
||||
object_uuid: string,
|
||||
offset: number,
|
||||
length: number,
|
||||
) {
|
||||
this.version = version
|
||||
this.group = group // Only needed for UI
|
||||
this.version = version;
|
||||
this.group = group; // Only needed for UI
|
||||
|
||||
this.name = name // UI
|
||||
this.type = type // UI and Animation / Audio / Lipsync / : Engine
|
||||
this.name = name; // UI
|
||||
this.type = type; // UI and Animation / Audio / Lipsync / : Engine
|
||||
|
||||
this.object_uuid = object_uuid // Animation / Audio / Lipsync / : Engine
|
||||
this.media_id = media_id // Animation / Audio / Lipsync / : Engine
|
||||
this.offset = offset
|
||||
this.length = length
|
||||
this.object_uuid = object_uuid; // Animation / Audio / Lipsync / : Engine
|
||||
this.media_id = media_id; // Animation / Audio / Lipsync / : Engine
|
||||
this.offset = offset;
|
||||
this.length = length;
|
||||
}
|
||||
|
||||
toJSON(): string {
|
||||
return JSON.stringify({
|
||||
version: this.version,
|
||||
group:this.group,
|
||||
group: this.group,
|
||||
name: this.name,
|
||||
type: this.type,
|
||||
object_uuid: this.object_uuid,
|
||||
media_id: this.media_id,
|
||||
start_offset: this.offset,
|
||||
ending_offset: this.length
|
||||
})
|
||||
ending_offset: this.length,
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -54,9 +54,9 @@ export enum Visibility {
|
||||
*/
|
||||
type Data = { [key: string]: any };
|
||||
class APIManagerResponseSuccess {
|
||||
public user_message: String;
|
||||
public user_message: string;
|
||||
public data: Data | null;
|
||||
constructor(user_message: String = "", data: Data | null = null) {
|
||||
constructor(user_message: string = "", data: Data | null = null) {
|
||||
this.data = data;
|
||||
this.user_message = user_message;
|
||||
}
|
||||
@@ -74,7 +74,7 @@ class APIManagerResponseError extends Error {
|
||||
}
|
||||
|
||||
export class APIManager {
|
||||
baseUrl: String;
|
||||
baseUrl: string;
|
||||
|
||||
constructor() {
|
||||
this.baseUrl = "https://api.fakeyou.com";
|
||||
@@ -139,9 +139,9 @@ export class APIManager {
|
||||
throw new APIManagerResponseError("Failed to download file");
|
||||
}
|
||||
// Convert the response from a blob to json text
|
||||
let blob = await file_response.blob();
|
||||
const blob = await file_response.blob();
|
||||
const json_result: string = await new Promise((resolve, reject) => {
|
||||
let reader = new FileReader();
|
||||
const reader = new FileReader();
|
||||
reader.onloadend = () => resolve(JSON.parse(reader.result as string));
|
||||
reader.onerror = reject;
|
||||
reader.readAsText(blob);
|
||||
@@ -156,7 +156,7 @@ export class APIManager {
|
||||
scene_glb_media_file_token,
|
||||
);
|
||||
console.log(`GLB ${media_bucket_path}`);
|
||||
let glbLoader = new GLTFLoader();
|
||||
const glbLoader = new GLTFLoader();
|
||||
// promisify this
|
||||
const loadGlb = (
|
||||
bucket_path: string,
|
||||
@@ -188,13 +188,13 @@ export class APIManager {
|
||||
* @returns
|
||||
*/
|
||||
private async getMediaFile(media_file_token: string): Promise<string> {
|
||||
let api_base_url = "https://api.fakeyou.com";
|
||||
let url = `${api_base_url}/v1/media_files/file/${media_file_token}`;
|
||||
let response = await fetch(url);
|
||||
let json = await JSON.parse(await response.text());
|
||||
let bucketPath = json["media_file"]["public_bucket_path"];
|
||||
let media_base_url = "https://storage.googleapis.com/vocodes-public";
|
||||
let media_url = `${media_base_url}${bucketPath}`; // gets you a bucket path
|
||||
const api_base_url = "https://api.fakeyou.com";
|
||||
const url = `${api_base_url}/v1/media_files/file/${media_file_token}`;
|
||||
const response = await fetch(url);
|
||||
const json = await JSON.parse(await response.text());
|
||||
const bucketPath = json["media_file"]["public_bucket_path"];
|
||||
const media_base_url = "https://storage.googleapis.com/vocodes-public";
|
||||
const media_url = `${media_base_url}${bucketPath}`; // gets you a bucket path
|
||||
return media_url;
|
||||
}
|
||||
|
||||
@@ -218,7 +218,7 @@ export class APIManager {
|
||||
scene_glb_media_file_token: string | null,
|
||||
): Promise<string> {
|
||||
const url = `${this.baseUrl}/v1/media_files/write/engine_asset`;
|
||||
let uuid = uuidv4();
|
||||
const uuid = uuidv4();
|
||||
const form_data = new FormData();
|
||||
form_data.append("uuid_idempotency_token", uuid);
|
||||
|
||||
@@ -257,7 +257,7 @@ export class APIManager {
|
||||
timeline_state: TimelineDataState | null, // only for now.
|
||||
): Promise<string> {
|
||||
const url = `${this.baseUrl}/v1/media_files/write/scene_file`;
|
||||
let uuid = uuidv4();
|
||||
const uuid = uuidv4();
|
||||
|
||||
console.log(
|
||||
`Saving Scene scene_media_file_token:${scene_media_file_token} | scene_glb_media_file_token:${scene_glb_media_file_token}`,
|
||||
@@ -311,7 +311,7 @@ export class APIManager {
|
||||
fileName: string,
|
||||
): Promise<APIManagerResponseSuccess> {
|
||||
const url = `${this.baseUrl}/v1/media_uploads/upload`;
|
||||
let uuid = uuidv4();
|
||||
const uuid = uuidv4();
|
||||
|
||||
const formData = new FormData();
|
||||
formData.append("uuid_idempotency_token", uuid);
|
||||
@@ -346,11 +346,11 @@ export class APIManager {
|
||||
negative_prompt: string,
|
||||
): Promise<string> {
|
||||
const url = `https://funnel.tailce84f.ts.net/preview/`;
|
||||
|
||||
|
||||
const payload = {
|
||||
style: style,
|
||||
positive_prompt: positive_prompt,
|
||||
negative_prompt: negative_prompt
|
||||
negative_prompt: negative_prompt,
|
||||
};
|
||||
|
||||
const formData = new FormData();
|
||||
@@ -393,14 +393,15 @@ export class APIManager {
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
public async stylizeVideo(media_token: string,
|
||||
style: ArtStyle,
|
||||
positive_prompt:string,
|
||||
negative_prompt:string,
|
||||
visibility:Visibility) {
|
||||
let uuid = uuidv4();
|
||||
|
||||
public async stylizeVideo(
|
||||
media_token: string,
|
||||
style: ArtStyle,
|
||||
positive_prompt: string,
|
||||
negative_prompt: string,
|
||||
visibility: Visibility,
|
||||
) {
|
||||
const uuid = uuidv4();
|
||||
|
||||
const data = {
|
||||
uuid_idempotency_token: uuid,
|
||||
style: style,
|
||||
@@ -410,10 +411,10 @@ export class APIManager {
|
||||
trim_start_millis: 0,
|
||||
trim_end_millis: 3000,
|
||||
enable_lipsync: true,
|
||||
creator_set_visibility: visibility
|
||||
}
|
||||
creator_set_visibility: visibility,
|
||||
};
|
||||
|
||||
const json_data = JSON.stringify(data)
|
||||
const json_data = JSON.stringify(data);
|
||||
|
||||
const response = await fetch(`${this.baseUrl}/v1/video/enqueue_vst`, {
|
||||
method: "POST",
|
||||
@@ -435,4 +436,3 @@ export class APIManager {
|
||||
return await response.json();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,6 +11,7 @@ import Queue from "~/pages/PageEnigma/Queue/Queue";
|
||||
import { QueueNames } from "../Queue/QueueNames";
|
||||
import { toEngineActions } from "../Queue/toEngineActions";
|
||||
import { fromEngineActions } from "../Queue/fromEngineActions";
|
||||
import { ClipType } from "~/pages/PageEnigma/models/track";
|
||||
|
||||
// Every object uuid / entity has a track.
|
||||
export class TimelineCurrentState {
|
||||
@@ -169,10 +170,10 @@ export class TimeLine {
|
||||
);
|
||||
|
||||
switch (type) {
|
||||
case "animation":
|
||||
case ClipType.ANIMATION:
|
||||
this.animation_engine.load_object(object_uuid, media_id, name);
|
||||
break;
|
||||
case "transform":
|
||||
case ClipType.TRANSFORM:
|
||||
this.transform_engine.loadObject(object_uuid, data["data"]["length"]);
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -13,6 +13,11 @@ export const cameraGroup = signal<CameraGroup>({ id: "CG1", keyframes: [] });
|
||||
|
||||
export function updateCamera({ id, offset }: { id: string; offset: number }) {
|
||||
const oldCameraGroup = cameraGroup.value;
|
||||
|
||||
if (oldCameraGroup.keyframes.some((row) => row.offset === offset)) {
|
||||
return;
|
||||
}
|
||||
|
||||
const newKeyframes = [...oldCameraGroup.keyframes];
|
||||
const keyframe = newKeyframes.find((row) => row.keyframe_uuid === id);
|
||||
if (!keyframe) {
|
||||
@@ -33,7 +38,10 @@ export function updateCamera({ id, offset }: { id: string; offset: number }) {
|
||||
}
|
||||
|
||||
export function addCameraKeyframe(keyframe: QueueKeyframe, offset: number) {
|
||||
console.log("cam", keyframe);
|
||||
const oldCameraGroup = cameraGroup.value;
|
||||
if (oldCameraGroup.keyframes.some((row) => row.offset === offset)) {
|
||||
return;
|
||||
}
|
||||
const newKeyframe = {
|
||||
version: keyframe.version,
|
||||
keyframe_uuid: uuid.v4(),
|
||||
@@ -46,7 +54,6 @@ export function addCameraKeyframe(keyframe: QueueKeyframe, offset: number) {
|
||||
selected: false,
|
||||
} as Keyframe;
|
||||
|
||||
const oldCameraGroup = cameraGroup.value;
|
||||
cameraGroup.value = {
|
||||
...oldCameraGroup,
|
||||
keyframes: [...oldCameraGroup.keyframes, newKeyframe].sort(
|
||||
|
||||
@@ -28,14 +28,16 @@ export function updateCharacters({
|
||||
id,
|
||||
offset,
|
||||
length,
|
||||
force,
|
||||
}: {
|
||||
type: "animations" | "positions" | "lipSync";
|
||||
type: ClipType;
|
||||
id: string;
|
||||
length: number;
|
||||
length?: number;
|
||||
offset: number;
|
||||
force?: boolean;
|
||||
}) {
|
||||
const oldCharacterGroups = characterGroups.value;
|
||||
if (type === "animations") {
|
||||
if (type === ClipType.ANIMATION) {
|
||||
characterGroups.value = oldCharacterGroups.map((character) => {
|
||||
const newAnimationClips = [...character.animationClips];
|
||||
const clipIndex = newAnimationClips.findIndex(
|
||||
@@ -46,7 +48,7 @@ export function updateCharacters({
|
||||
}
|
||||
const clip = newAnimationClips[clipIndex];
|
||||
clip.offset = offset;
|
||||
clip.length = length;
|
||||
clip.length = length!;
|
||||
|
||||
Queue.publish({
|
||||
queueName: QueueNames.TO_ENGINE,
|
||||
@@ -61,7 +63,7 @@ export function updateCharacters({
|
||||
});
|
||||
}
|
||||
|
||||
if (type === "positions") {
|
||||
if (type === ClipType.TRANSFORM) {
|
||||
characterGroups.value = oldCharacterGroups.map((character) => {
|
||||
const newPositionKeyframes = [...character.positionKeyframes];
|
||||
const keyframeIndex = newPositionKeyframes.findIndex(
|
||||
@@ -85,7 +87,7 @@ export function updateCharacters({
|
||||
};
|
||||
});
|
||||
}
|
||||
if (type === "lipSync") {
|
||||
if (type === ClipType.AUDIO) {
|
||||
characterGroups.value = oldCharacterGroups.map((character) => {
|
||||
const newLipSyncClips = [...character.lipSyncClips];
|
||||
const clipIndex = newLipSyncClips.findIndex(
|
||||
@@ -96,7 +98,7 @@ export function updateCharacters({
|
||||
}
|
||||
const clip = newLipSyncClips[clipIndex];
|
||||
clip.offset = offset;
|
||||
clip.length = length;
|
||||
clip.length = length!;
|
||||
|
||||
Queue.publish({
|
||||
queueName: QueueNames.TO_ENGINE,
|
||||
@@ -204,6 +206,18 @@ export function addCharacterAudio({
|
||||
}
|
||||
|
||||
export function addCharacterKeyframe(keyframe: QueueKeyframe, offset: number) {
|
||||
const oldCharacterGroups = characterGroups.value;
|
||||
|
||||
if (
|
||||
oldCharacterGroups.some((characterGroup) => {
|
||||
return characterGroup.positionKeyframes.some(
|
||||
(row) => row.offset === offset,
|
||||
);
|
||||
})
|
||||
) {
|
||||
return;
|
||||
}
|
||||
|
||||
const newKeyframe = {
|
||||
version: keyframe.version,
|
||||
keyframe_uuid: uuid.v4(),
|
||||
@@ -216,7 +230,6 @@ export function addCharacterKeyframe(keyframe: QueueKeyframe, offset: number) {
|
||||
selected: false,
|
||||
} as Keyframe;
|
||||
|
||||
const oldCharacterGroups = characterGroups.value;
|
||||
characterGroups.value = oldCharacterGroups.map((character) => {
|
||||
if (character.id !== keyframe.object_uuid) {
|
||||
return { ...character };
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { signal } from "@preact/signals-core";
|
||||
import { ClipType } from "~/pages/PageEnigma/models/track";
|
||||
|
||||
export const dragType = signal<"animations" | "audio" | null>(null);
|
||||
export const dragType = signal<ClipType | null>(null);
|
||||
export const dragId = signal<string | null>(null);
|
||||
export const canDrop = signal(false);
|
||||
export const overTimeline = signal(false);
|
||||
|
||||
@@ -15,16 +15,24 @@ export const objectGroup = signal<ObjectGroup>({
|
||||
});
|
||||
|
||||
export function updateObject({ id, offset }: { id: string; offset: number }) {
|
||||
const oldObject = objectGroup.value;
|
||||
const oldObjectGroup = objectGroup.value;
|
||||
const obj = oldObjectGroup.objects.find((objectTrack) =>
|
||||
objectTrack.keyframes.some((row) => row.keyframe_uuid === id),
|
||||
);
|
||||
|
||||
if (obj && obj.keyframes.some((row) => row.offset === offset)) {
|
||||
return;
|
||||
}
|
||||
|
||||
objectGroup.value = {
|
||||
id: oldObject.id,
|
||||
objects: oldObject.objects.map((object) => ({
|
||||
id: oldObjectGroup.id,
|
||||
objects: oldObjectGroup.objects.map((object) => ({
|
||||
object_uuid: object.object_uuid,
|
||||
name: object.name,
|
||||
keyframes: object.keyframes.map((keyFrame) => {
|
||||
if (keyFrame.keyframe_uuid !== id) {
|
||||
keyframes: object.keyframes.map((keyframe) => {
|
||||
if (keyframe.keyframe_uuid !== id) {
|
||||
return {
|
||||
...keyFrame,
|
||||
...keyframe,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -32,13 +40,13 @@ export function updateObject({ id, offset }: { id: string; offset: number }) {
|
||||
queueName: QueueNames.TO_ENGINE,
|
||||
action: toEngineActions.UPDATE_KEYFRAME,
|
||||
data: {
|
||||
...keyFrame,
|
||||
...keyframe,
|
||||
offset,
|
||||
},
|
||||
});
|
||||
|
||||
return {
|
||||
...keyFrame,
|
||||
...keyframe,
|
||||
offset,
|
||||
};
|
||||
}),
|
||||
@@ -52,6 +60,10 @@ export function addObjectKeyframe(keyframe: QueueKeyframe, offset: number) {
|
||||
(row) => row.object_uuid === keyframe.object_uuid,
|
||||
);
|
||||
|
||||
if (obj && obj.keyframes.some((row) => row.offset === offset)) {
|
||||
return;
|
||||
}
|
||||
|
||||
const newObject = obj ?? {
|
||||
object_uuid: keyframe.object_uuid,
|
||||
name: keyframe.object_name ?? "unknown",
|
||||
@@ -69,19 +81,16 @@ export function addObjectKeyframe(keyframe: QueueKeyframe, offset: number) {
|
||||
selected: false,
|
||||
} as Keyframe;
|
||||
newObject.keyframes.push(newKeyframe);
|
||||
console.log(newObject);
|
||||
|
||||
newObject.keyframes.sort(
|
||||
(keyframeA, keyframeB) => keyframeA.offset - keyframeB.offset,
|
||||
);
|
||||
|
||||
objectGroup.value = {
|
||||
...oldObjectGroup,
|
||||
objects: [
|
||||
...oldObjectGroup.objects.filter(
|
||||
(object) => object.object_uuid !== keyframe.object_uuid,
|
||||
),
|
||||
newObject,
|
||||
].sort((objA, objB) => (objA.object_uuid < objB.object_uuid ? -1 : 1)),
|
||||
objects: [...oldObjectGroup.objects, newObject].sort((objA, objB) =>
|
||||
objA.object_uuid < objB.object_uuid ? -1 : 1,
|
||||
),
|
||||
};
|
||||
Queue.publish({
|
||||
queueName: QueueNames.TO_ENGINE,
|
||||
|
||||
Reference in new issue
Block a user