From 188728693e47507dd4bde368334475d6cee97e44 Mon Sep 17 00:00:00 2001
From: FromTheLOLAshes
Date: Tue, 26 Mar 2024 12:50:01 +0700
Subject: [PATCH] Begin work on dragging clips to add
---
app/contexts/ClipContext/ClipContext.tsx | 18 +++
app/contexts/ClipContext/ClipProvider.tsx | 42 ++++++
app/modules/LowerPanel/LowerPanel.tsx | 6 +-
app/pages/PageEnigma/PageEnigma.tsx | 104 +-------------
app/pages/PageEnigma/PageEnigmaComponent.tsx | 98 +++++++++++++
.../PageEnigma/comps/SidePanelTabs/index.tsx | 16 ++-
app/pages/PageEnigma/comps/Timeline/Audio.tsx | 54 ++-----
.../PageEnigma/comps/Timeline/Camera.tsx | 36 +----
.../PageEnigma/comps/Timeline/Character.tsx | 133 ++++--------------
.../PageEnigma/comps/Timeline/Objects.tsx | 37 +----
.../PageEnigma/comps/Timeline/Timeline.tsx | 32 +----
app/pages/PageEnigma/comps/Timeline/Track.tsx | 78 ++++++++++
.../Timeline/utils/useMouseEventsClip.ts | 2 +-
app/routes/IdealEnigma.tsx | 16 +--
14 files changed, 322 insertions(+), 350 deletions(-)
create mode 100644 app/contexts/ClipContext/ClipContext.tsx
create mode 100644 app/contexts/ClipContext/ClipProvider.tsx
create mode 100644 app/pages/PageEnigma/PageEnigmaComponent.tsx
create mode 100644 app/pages/PageEnigma/comps/Timeline/Track.tsx
diff --git a/app/contexts/ClipContext/ClipContext.tsx b/app/contexts/ClipContext/ClipContext.tsx
new file mode 100644
index 0000000000..7b0d264c92
--- /dev/null
+++ b/app/contexts/ClipContext/ClipContext.tsx
@@ -0,0 +1,18 @@
+import { createContext } from "react";
+import { AnimationClip, AudioClip } from "~/models/track";
+
+export const ClipContext = createContext<{
+ animationClips: AnimationClip[];
+ audioClips: AudioClip[];
+ dragType: "animation" | "audio" | null;
+ dragId: string | null;
+ startDrag: (type: "animation" | "audio", id: string) => void;
+ endDrag: () => void;
+}>({
+ animationClips: [],
+ audioClips: [],
+ dragType: null,
+ dragId: null,
+ startDrag: () => {},
+ endDrag: () => {},
+});
diff --git a/app/contexts/ClipContext/ClipProvider.tsx b/app/contexts/ClipContext/ClipProvider.tsx
new file mode 100644
index 0000000000..0b541b204f
--- /dev/null
+++ b/app/contexts/ClipContext/ClipProvider.tsx
@@ -0,0 +1,42 @@
+import { ReactNode, useCallback, useEffect, useMemo, useState } from "react";
+import { ClipContext } from "./ClipContext";
+import { AnimationClip, AudioClip } from "~/models/track";
+
+interface Props {
+ children: ReactNode;
+}
+
+export const ClipProvider = ({ children }: Props) => {
+ const [state, setState] = useState<{
+ dragType: "animation" | "audio" | null;
+ dragId: string | null;
+ }>({ dragType: null, dragId: null });
+ const [animationClips, setAnimationClips] = useState([]);
+ const [audioClips, setAudioClips] = useState([]);
+
+ useEffect(() => {
+ setAnimationClips([]);
+ setAudioClips([]);
+ }, []);
+
+ const startDrag = useCallback((type: "animation" | "audio", id: string) => {
+ setState({ dragId: id, dragType: type });
+ }, []);
+
+ const endDrag = useCallback(() => {
+ setState({ dragId: null, dragType: null });
+ }, []);
+
+ const values = useMemo(() => {
+ return {
+ dragType: state.dragType,
+ dragId: state.dragId,
+ animationClips,
+ audioClips,
+ startDrag,
+ endDrag,
+ };
+ }, [state, animationClips, audioClips, startDrag, endDrag]);
+
+ return {children};
+};
diff --git a/app/modules/LowerPanel/LowerPanel.tsx b/app/modules/LowerPanel/LowerPanel.tsx
index 411a629518..680a097953 100644
--- a/app/modules/LowerPanel/LowerPanel.tsx
+++ b/app/modules/LowerPanel/LowerPanel.tsx
@@ -1,10 +1,11 @@
import { useState } from "react";
interface LowerPanelPropsI {
+ timelineHeight: number;
children: React.ReactNode;
}
-export const LowerPanel = ({ children }: LowerPanelPropsI) => {
+export const LowerPanel = ({ children, timelineHeight }: LowerPanelPropsI) => {
const [open, setOpen] = useState(false);
const handleOpen = () => {
setOpen(true);
@@ -14,10 +15,11 @@ export const LowerPanel = ({ children }: LowerPanelPropsI) => {
{children}
diff --git a/app/pages/PageEnigma/PageEnigma.tsx b/app/pages/PageEnigma/PageEnigma.tsx
index c4b35be83d..be63286bb3 100644
--- a/app/pages/PageEnigma/PageEnigma.tsx
+++ b/app/pages/PageEnigma/PageEnigma.tsx
@@ -1,104 +1,10 @@
-import { useCallback, useEffect, useRef, useState } from "react";
-
-import { faSparkles } from "@fortawesome/pro-solid-svg-icons";
-
-import { Button, ButtonLink } from "~/components";
-// import { ButtonDialogue } from "~/modules/ButtonDialogue";
-import { TopBarHelmet } from "~/modules/TopBarHelmet/TopBarHelmet";
-import { SidePanel } from "~/modules/SidePanel";
-import { Controls3D } from "./comps/Controls3D";
-import { ControlsTopButtons } from "./comps/ControlsTopButtons";
-import { ControlsVideo } from "./comps/ControlsVideo";
-import { PreviewWindow } from "./comps/PreviewWindow";
-import { Timeline } from "./comps/Timeline";
-import { SidePanelTabs } from "./comps/SidePanelTabs";
-
-import { TrackProvider } from "~/contexts/TrackContext/TrackProvider";
-import { EngineProvider } from "~/contexts/EngineProvider";
+import { ClipProvider } from "~/contexts/ClipContext/ClipProvider";
+import { PageEnigmaComponent } from "./PageEnigmaComponent";
export const PageEnigma = () => {
- const canvasRef = useRef(null);
-
- const [timelineHeight, setTimelineHeight] = useState(0);
- const timelineRef = useRef(null);
-
-
- const updateTimelineHeight = useCallback(() => {
- if (timelineRef.current) {
- setTimelineHeight(timelineRef.current.offsetHeight);
- }
- }, []);
-
- //for updating timeline/engine div height (for resizing)
- useEffect(() => {
- const observer = new ResizeObserver((entries) => {
- for (let entry of entries) {
- updateTimelineHeight();
- }
- });
-
- if (timelineRef.current) {
- observer.observe(timelineRef.current);
- }
-
- return () => observer.disconnect();
- }, [updateTimelineHeight]);
-
return (
-
-
-
-
-
-
- {/* Engine section/side panel */}
-
-
-
-
- {/* Top controls */}
-
-
- {/* Bottom controls */}
-
-
-
- {/* Side panel */}
-
-
-
-
-
- {/* Timeline */}
-
-
-
-
-
-
-
-
+
+
+
);
};
diff --git a/app/pages/PageEnigma/PageEnigmaComponent.tsx b/app/pages/PageEnigma/PageEnigmaComponent.tsx
new file mode 100644
index 0000000000..930336ccca
--- /dev/null
+++ b/app/pages/PageEnigma/PageEnigmaComponent.tsx
@@ -0,0 +1,98 @@
+import { useCallback, useEffect, useRef, useState } from "react";
+
+import { faSparkles } from "@fortawesome/pro-solid-svg-icons";
+
+import { Button } from "~/components";
+import { TopBarHelmet } from "~/modules/TopBarHelmet/TopBarHelmet";
+import { SidePanel } from "~/modules/SidePanel";
+import { Controls3D } from "./comps/Controls3D";
+import { ControlsTopButtons } from "./comps/ControlsTopButtons";
+import { ControlsVideo } from "./comps/ControlsVideo";
+import { PreviewWindow } from "./comps/PreviewWindow";
+import { Timeline } from "./comps/Timeline";
+import { SidePanelTabs } from "./comps/SidePanelTabs";
+
+import { TrackProvider } from "~/contexts/TrackContext/TrackProvider";
+import { EngineProvider } from "~/contexts/EngineProvider";
+
+export const PageEnigmaComponent = () => {
+ const canvasRef = useRef(null);
+
+ const [timelineHeight, setTimelineHeight] = useState(260);
+ const timelineRef = useRef(null);
+
+ const updateTimelineHeight = useCallback(() => {
+ if (timelineRef.current) {
+ setTimelineHeight(timelineRef.current.offsetHeight);
+ }
+ }, []);
+
+ //for updating timeline/engine div height (for resizing)
+ useEffect(() => {
+ const observer = new ResizeObserver((entries) => {
+ for (let entry of entries) {
+ updateTimelineHeight();
+ }
+ });
+
+ if (timelineRef.current) {
+ observer.observe(timelineRef.current);
+ }
+
+ return () => observer.disconnect();
+ }, [updateTimelineHeight]);
+
+ return (
+
+
+
+
+
+
+ {/* Engine section/side panel */}
+
+
+
+
+ {/* Top controls */}
+
+
+ {/* Bottom controls */}
+
+
+
+ {/* Side panel */}
+
+
+
+
+
+ {/* Timeline */}
+
+
+
+
+
+
+
+
+ );
+};
diff --git a/app/pages/PageEnigma/comps/SidePanelTabs/index.tsx b/app/pages/PageEnigma/comps/SidePanelTabs/index.tsx
index 38929885a1..ba739f09d4 100644
--- a/app/pages/PageEnigma/comps/SidePanelTabs/index.tsx
+++ b/app/pages/PageEnigma/comps/SidePanelTabs/index.tsx
@@ -1,13 +1,20 @@
import { Tabs } from "~/modules/Tabs";
import { TabStyling } from "./TabStyling";
-export const SidePanelTabs = ()=>{
- return(
+export const SidePanelTabs = () => {
+ return (
Animation Tab
,
+ children: (
+
+ ),
},
{
header: "Camera",
@@ -24,5 +31,4 @@ export const SidePanelTabs = ()=>{
]}
/>
);
-
-}
\ No newline at end of file
+};
diff --git a/app/pages/PageEnigma/comps/Timeline/Audio.tsx b/app/pages/PageEnigma/comps/Timeline/Audio.tsx
index 67ad885d2b..79a50d8a44 100644
--- a/app/pages/PageEnigma/comps/Timeline/Audio.tsx
+++ b/app/pages/PageEnigma/comps/Timeline/Audio.tsx
@@ -1,8 +1,6 @@
-import { TrackClip } from "./TrackClip";
import { useContext } from "react";
import { TrackContext } from "~/contexts/TrackContext/TrackContext";
-import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
-import { faVolume, faVolumeSlash } from "@fortawesome/pro-solid-svg-icons";
+import { Track } from "~/pages/PageEnigma/comps/Timeline/Track";
export const Audio = () => {
const { audio, updateAudio, length, scale, toggleAudioMute } =
@@ -17,48 +15,14 @@ export const Audio = () => {
>
Global Audio
-
-
- {clips.map((clip, index) => (
-
0
- ? clips[index - 1].offset + clips[index - 1].length
- : 0
- }
- max={
- index < clips.length - 1
- ? clips[index + 1].offset
- : length * 60
- }
- style="audio"
- updateClip={updateAudio}
- clip={clip}
- />
- ))}
-
- Global Audio Track
-
-
-
-
+
);
diff --git a/app/pages/PageEnigma/comps/Timeline/Camera.tsx b/app/pages/PageEnigma/comps/Timeline/Camera.tsx
index 3aff1ab2b0..17c438e1b0 100644
--- a/app/pages/PageEnigma/comps/Timeline/Camera.tsx
+++ b/app/pages/PageEnigma/comps/Timeline/Camera.tsx
@@ -1,6 +1,6 @@
-import { TrackClip } from "./TrackClip";
import { useContext } from "react";
import { TrackContext } from "~/contexts/TrackContext/TrackContext";
+import { Track } from "~/pages/PageEnigma/comps/Timeline/Track";
export const Camera = () => {
const { camera, updateCamera, length, scale } = useContext(TrackContext);
@@ -14,34 +14,12 @@ export const Camera = () => {
>
Camera
-
-
- {clips.map((clip, index) => (
-
0
- ? clips[index - 1].offset + clips[index - 1].length
- : 0
- }
- max={
- index < clips.length - 1
- ? clips[index + 1].offset
- : length * 60
- }
- style="camera"
- updateClip={updateCamera}
- clip={clip}
- />
- ))}
-
- Camera Position/Rotation
-
-
-
+
);
diff --git a/app/pages/PageEnigma/comps/Timeline/Character.tsx b/app/pages/PageEnigma/comps/Timeline/Character.tsx
index 57e538f7ba..e4fe7f8e11 100644
--- a/app/pages/PageEnigma/comps/Timeline/Character.tsx
+++ b/app/pages/PageEnigma/comps/Timeline/Character.tsx
@@ -1,8 +1,6 @@
-import { TrackClip } from "./TrackClip";
-import { useContext, useMemo } from "react";
+import { useCallback, useContext, useMemo } from "react";
import { TrackContext } from "~/contexts/TrackContext/TrackContext";
-import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
-import { faVolumeSlash, faVolume } from "@fortawesome/pro-solid-svg-icons";
+import { Track } from "~/pages/PageEnigma/comps/Timeline/Track";
function buildUpdaters(
updateCharacters: (options: {
@@ -47,6 +45,9 @@ export const Character = ({ characterId }: Props) => {
const { updateClipLipSync, updateClipPosition, updateClipAnimations } =
useMemo(() => buildUpdaters(updateCharacters), [updateCharacters]);
+ const toggleCharacterLipSyncMute = useCallback(() => {
+ toggleLipSyncMute(character?.id ?? "");
+ }, []);
if (!character) {
return false;
@@ -60,107 +61,29 @@ export const Character = ({ characterId }: Props) => {
>
Character
-
-
- {animationClips.map((clip, index) => (
-
0
- ? animationClips[index - 1].offset +
- animationClips[index - 1].length
- : 0
- }
- max={
- index < animationClips.length - 1
- ? animationClips[index + 1].offset
- : length * 60
- }
- style="character"
- updateClip={updateClipAnimations}
- clip={clip}
- />
- ))}
-
- Animation
-
-
-
-
-
- {positionClips.map((clip, index) => (
-
0
- ? positionClips[index - 1].offset +
- positionClips[index - 1].length
- : 0
- }
- max={
- index < positionClips.length - 1
- ? positionClips[index + 1].offset
- : length * 60
- }
- style="character"
- updateClip={updateClipPosition}
- clip={clip}
- />
- ))}
-
- Character Position/Rotation
-
-
-
-
-
- {lipSyncClips.map((clip, index) => (
-
0
- ? lipSyncClips[index - 1].offset +
- lipSyncClips[index - 1].length
- : 0
- }
- max={
- index < lipSyncClips.length - 1
- ? lipSyncClips[index + 1].offset
- : length * 60
- }
- style="character"
- updateClip={updateClipLipSync}
- clip={clip}
- />
- ))}
-
- Lipsync Audio Track
-
-
-
-
+
+
+
);
diff --git a/app/pages/PageEnigma/comps/Timeline/Objects.tsx b/app/pages/PageEnigma/comps/Timeline/Objects.tsx
index 7f87120f41..44d3c9efb9 100644
--- a/app/pages/PageEnigma/comps/Timeline/Objects.tsx
+++ b/app/pages/PageEnigma/comps/Timeline/Objects.tsx
@@ -1,6 +1,6 @@
-import { TrackClip } from "./TrackClip";
import { useContext } from "react";
import { TrackContext } from "~/contexts/TrackContext/TrackContext";
+import { Track } from "~/pages/PageEnigma/comps/Timeline/Track";
export const Objects = () => {
const { objects, updateObject, length, scale } = useContext(TrackContext);
@@ -14,35 +14,12 @@ export const Objects = () => {
Objects
{objects.objects.map((object) => (
-
-
- {object.clips.map((clip, index) => (
-
0
- ? object.clips[index - 1].offset +
- object.clips[index - 1].length
- : 0
- }
- max={
- index < object.clips.length - 1
- ? object.clips[index + 1].offset
- : length * 60
- }
- style="objects"
- updateClip={updateObject}
- clip={clip}
- />
- ))}
-
- Mask Position/Rotation
-
-
-
+
))}
diff --git a/app/pages/PageEnigma/comps/Timeline/Timeline.tsx b/app/pages/PageEnigma/comps/Timeline/Timeline.tsx
index 26559b8812..c09a7a8d10 100644
--- a/app/pages/PageEnigma/comps/Timeline/Timeline.tsx
+++ b/app/pages/PageEnigma/comps/Timeline/Timeline.tsx
@@ -1,20 +1,7 @@
-import {
- Fragment,
- // useCallback,
- useContext
-} from "react";
-
-import { Button } from "~/components";
-
-// import Editor from "../../js/editor";
-import { EngineContext } from "~/contexts/EngineContext";
+import { Fragment, useContext } from "react";
import { TrackContext } from "~/contexts/TrackContext/TrackContext";
-
import { LowerPanel } from "~/modules/LowerPanel";
import { Character } from "./Character";
-
-
-
import { Camera } from "./Camera";
import { Audio } from "./Audio";
import { Objects } from "./Objects";
@@ -22,16 +9,11 @@ import { useMouseEventsAnimation } from "./utils/useMouseEventsAnimation";
import { faSortDown } from "@fortawesome/pro-solid-svg-icons";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
-export const Timeline = ({
- // editorCurrent,
- // time,
-}: {
- // editorCurrent: Editor | null;
- // time: number;
-}) => {
- const editorEngine = useContext(EngineContext);
- // editorEngine replaced the engineRef.current passed as a prop
- // const { characters, updateCharacters } = useContext(TrackContext);
+interface Props {
+ timelineHeight: number;
+}
+
+export const Timeline = ({ timelineHeight }: Props) => {
const { characters, objects, scale, length } = useContext(TrackContext);
const { onPointerDown, time } = useMouseEventsAnimation();
@@ -41,7 +23,7 @@ export const Timeline = ({
return (
<>
-
+
{Array(length)
.fill(0)
diff --git a/app/pages/PageEnigma/comps/Timeline/Track.tsx b/app/pages/PageEnigma/comps/Timeline/Track.tsx
new file mode 100644
index 0000000000..038b631dd9
--- /dev/null
+++ b/app/pages/PageEnigma/comps/Timeline/Track.tsx
@@ -0,0 +1,78 @@
+import { TrackClip } from "~/pages/PageEnigma/comps/Timeline/TrackClip";
+import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
+import { faVolume, faVolumeSlash } from "@fortawesome/pro-solid-svg-icons";
+import { BaseClip } from "~/models/track";
+import { useContext } from "react";
+import { TrackContext } from "~/contexts/TrackContext/TrackContext";
+import { ClipContext } from "~/contexts/ClipContext/ClipContext";
+
+interface Props {
+ clips: BaseClip[];
+ title: string;
+ style: "character" | "audio" | "camera" | "objects";
+ type?: "animations" | "positions" | "lipSync";
+ toggleMute?: () => void;
+ muted?: boolean;
+ updateClip: (options: { id: string; length: number; offset: number }) => void;
+}
+
+export const Track = ({
+ clips,
+ toggleMute,
+ updateClip,
+ muted,
+ title,
+ style,
+ type,
+}: Props) => {
+ const { length } = useContext(TrackContext);
+ const { dragType } = useContext(ClipContext);
+ const trackType = type ?? style;
+
+ const className = dragType === trackType ? "highlight" : "";
+
+ return (
+
+
+ {clips.map((clip, index) => (
+
0 ? clips[index - 1].offset + clips[index - 1].length : 0
+ }
+ max={
+ index < clips.length - 1 ? clips[index + 1].offset : length * 60
+ }
+ style={style}
+ updateClip={updateClip}
+ clip={clip}
+ />
+ ))}
+
+ {title}
+
+ {!!toggleMute && (
+
+ )}
+
+
+ );
+};
diff --git a/app/pages/PageEnigma/comps/Timeline/utils/useMouseEventsClip.ts b/app/pages/PageEnigma/comps/Timeline/utils/useMouseEventsClip.ts
index d37ff7a6b1..883150c09c 100644
--- a/app/pages/PageEnigma/comps/Timeline/utils/useMouseEventsClip.ts
+++ b/app/pages/PageEnigma/comps/Timeline/utils/useMouseEventsClip.ts
@@ -59,7 +59,7 @@ export const useMouseEventsClip = (
) {
return;
}
- currLength.current = initLength.current - delta;
+ currLength.current = initLength.current + delta;
}
setState({ length: currLength.current, offset: currOffset.current });
},
diff --git a/app/routes/IdealEnigma.tsx b/app/routes/IdealEnigma.tsx
index b8131431c2..6fe36a7f25 100644
--- a/app/routes/IdealEnigma.tsx
+++ b/app/routes/IdealEnigma.tsx
@@ -1,9 +1,9 @@
-import { useState } from 'react';
+import { useState } from "react";
import { PageEnigma } from "../pages/PageEnigma";
-import { Button } from '~/components/Button';
+import { Button } from "~/components/Button";
-export default function IdealEnigma(){
+export default function IdealEnigma() {
//const [riddle, setRiddle] = useState
("");
//const [submitted, setSubmitted] = useState(false);
@@ -16,14 +16,13 @@ export default function IdealEnigma(){
// setSubmitted(state);
//}
-
- return
+ return ;
// if(submitted){
- // return
+ // return
// }else{
// return(
//
- //