mirror of
https://github.com/storytold/artcraft.git
synced 2026-11-09 19:41:32 +00:00
Fix delete
This commit is contained in:
1 parent
565280f2df
commit
2a21759e24
9 files changed
+114
-59
No files matched your search
@@ -16,11 +16,21 @@ import { TimerGrid } from "~/pages/PageEnigma/comps/TimerGrid/TimerGrid";
|
||||
import { Scrubber } from "~/pages/PageEnigma/comps/Scrubber/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";
|
||||
import { Clip, Keyframe } from "~/pages/PageEnigma/models/track";
|
||||
|
||||
function getItemType(item: Clip | Keyframe | null) {
|
||||
if (!item) {
|
||||
return "";
|
||||
}
|
||||
return (item as Clip).clip_uuid ? "clip" : "keyframe";
|
||||
}
|
||||
|
||||
export const Timeline = () => {
|
||||
useSignals();
|
||||
const { selectedItem } = useContext(TrackContext);
|
||||
const [dialogOpen, setDialogOpen] = useState(false);
|
||||
const { deleteKeyframe } = useUpdateKeyframe();
|
||||
|
||||
// implement the code to handle incoming messages from the Engine
|
||||
useQueueHandler();
|
||||
@@ -32,6 +42,8 @@ export const Timeline = () => {
|
||||
const onDeleteAsk = useCallback(
|
||||
(event: KeyboardEvent) => {
|
||||
if (["Backspace", "Delete"].indexOf(event.key) > -1 && selectedItem) {
|
||||
event.stopPropagation();
|
||||
event.preventDefault();
|
||||
setDialogOpen(true);
|
||||
}
|
||||
},
|
||||
@@ -39,9 +51,10 @@ export const Timeline = () => {
|
||||
);
|
||||
|
||||
const onDelete = useCallback(() => {
|
||||
deleteCharacterClip(selectedItem!);
|
||||
deleteAudioClip(selectedItem!);
|
||||
}, [selectedItem]);
|
||||
deleteCharacterClip(selectedItem as Clip);
|
||||
deleteAudioClip(selectedItem as Clip);
|
||||
deleteKeyframe(selectedItem as Keyframe);
|
||||
}, [selectedItem, deleteKeyframe]);
|
||||
|
||||
useEffect(() => {
|
||||
document.addEventListener("keydown", onDeleteAsk);
|
||||
@@ -69,7 +82,7 @@ export const Timeline = () => {
|
||||
</LowerPanel>
|
||||
<ConfirmationModal
|
||||
title="Delete Clip"
|
||||
text="Are you sure you want to delete the selected clip?"
|
||||
text={`Are you sure you want to delete the selected ${getItemType(selectedItem)}?`}
|
||||
open={dialogOpen}
|
||||
onClose={() => setDialogOpen(false)}
|
||||
onOk={() => {
|
||||
|
||||
@@ -1,13 +1,8 @@
|
||||
import { useMouseEventsClip } from "./utils/useMouseEventsClip";
|
||||
import { TrackContext } from "~/pages/PageEnigma/contexts/TrackContext/TrackContext";
|
||||
import { useCallback, useContext, useState } from "react";
|
||||
import { useContext, useState } from "react";
|
||||
import { scale } from "~/pages/PageEnigma/store";
|
||||
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
|
||||
import { faPlay } from "@fortawesome/pro-solid-svg-icons";
|
||||
import { Clip } from "~/pages/PageEnigma/models/track";
|
||||
import Queue from "~/pages/PageEnigma/Queue/Queue";
|
||||
import { QueueNames } from "~/pages/PageEnigma/Queue/QueueNames";
|
||||
import { toEngineActions } from "~/pages/PageEnigma/Queue/toEngineActions";
|
||||
|
||||
interface Props {
|
||||
min: number;
|
||||
@@ -31,24 +26,26 @@ export const TrackClip = ({ clip, min, max, style, updateClip }: Props) => {
|
||||
setState,
|
||||
);
|
||||
|
||||
const selectedClipId = (selectedItem as Clip | null)?.clip_uuid ?? "";
|
||||
|
||||
const { length, offset } = state;
|
||||
|
||||
const onPlayClick = useCallback(
|
||||
(event: React.MouseEvent<HTMLButtonElement>) => {
|
||||
event.stopPropagation();
|
||||
event.preventDefault();
|
||||
Queue.publish({
|
||||
queueName: QueueNames.TO_ENGINE,
|
||||
action: toEngineActions.PLAY_CLIP,
|
||||
data: clip,
|
||||
});
|
||||
},
|
||||
[clip],
|
||||
);
|
||||
// const onPlayClick = useCallback(
|
||||
// (event: React.MouseEvent<HTMLButtonElement>) => {
|
||||
// event.stopPropagation();
|
||||
// event.preventDefault();
|
||||
// Queue.publish({
|
||||
// queueName: QueueNames.TO_ENGINE,
|
||||
// action: toEngineActions.PLAY_CLIP,
|
||||
// data: clip,
|
||||
// });
|
||||
// },
|
||||
// [clip],
|
||||
// );
|
||||
|
||||
const classes = [
|
||||
"absolute",
|
||||
clip.clip_uuid === selectedItem
|
||||
clip.clip_uuid === selectedClipId
|
||||
? `bg-${style}-selected`
|
||||
: `bg-${style}-clip`,
|
||||
];
|
||||
@@ -71,7 +68,7 @@ export const TrackClip = ({ clip, min, max, style, updateClip }: Props) => {
|
||||
...classes,
|
||||
"rounded-l-lg",
|
||||
"block h-full",
|
||||
clip.clip_uuid === selectedItem
|
||||
clip.clip_uuid === selectedClipId
|
||||
? "border border-b-2 border-l-2 border-r-0 border-t-2 border-white focus-visible:outline-0"
|
||||
: "",
|
||||
].join(" ")}
|
||||
@@ -81,13 +78,13 @@ export const TrackClip = ({ clip, min, max, style, updateClip }: Props) => {
|
||||
cursor: "w-resize",
|
||||
}}
|
||||
onPointerDown={(event) => onPointerDown(event, "left")}
|
||||
onClick={() => selectItem(clip.clip_uuid)}
|
||||
onClick={() => selectItem(clip)}
|
||||
/>
|
||||
<button
|
||||
className={[
|
||||
...classes,
|
||||
"block h-full",
|
||||
clip.clip_uuid === selectedItem
|
||||
clip.clip_uuid === selectedClipId
|
||||
? "border border-b-2 border-l-0 border-r-0 border-t-2 border-white focus-visible:outline-0"
|
||||
: "",
|
||||
].join(" ")}
|
||||
@@ -97,14 +94,14 @@ export const TrackClip = ({ clip, min, max, style, updateClip }: Props) => {
|
||||
cursor: "move",
|
||||
}}
|
||||
onPointerDown={(event) => onPointerDown(event, "drag")}
|
||||
onClick={() => selectItem(clip.clip_uuid)}
|
||||
onClick={() => selectItem(clip)}
|
||||
/>
|
||||
<button
|
||||
className={[
|
||||
...classes,
|
||||
"rounded-r-lg",
|
||||
"block h-full",
|
||||
clip.clip_uuid === selectedItem
|
||||
clip.clip_uuid === selectedClipId
|
||||
? "border border-b-2 border-l-0 border-r-2 border-t-2 border-white focus-visible:outline-0"
|
||||
: "",
|
||||
].join(" ")}
|
||||
@@ -114,7 +111,7 @@ export const TrackClip = ({ clip, min, max, style, updateClip }: Props) => {
|
||||
cursor: "e-resize",
|
||||
}}
|
||||
onPointerDown={(event) => onPointerDown(event, "right")}
|
||||
onClick={() => selectItem(clip.clip_uuid)}
|
||||
onClick={() => selectItem(clip)}
|
||||
/>
|
||||
{/*{selectedItem === clip.clip_uuid && (*/}
|
||||
{/* <button*/}
|
||||
|
||||
@@ -32,9 +32,12 @@ export const TrackKeyFrame = ({
|
||||
setOffset,
|
||||
});
|
||||
|
||||
const selectedKeyframeId =
|
||||
(selectedItem as Keyframe | null)?.keyframe_uuid ?? "";
|
||||
|
||||
const classes = [
|
||||
"absolute",
|
||||
keyframe.keyframe_uuid === selectedItem
|
||||
keyframe.keyframe_uuid === selectedKeyframeId
|
||||
? `bg-${style}-selected`
|
||||
: `bg-${style}-clip`,
|
||||
];
|
||||
@@ -46,7 +49,7 @@ export const TrackKeyFrame = ({
|
||||
...classes,
|
||||
"rounded-l-lg",
|
||||
"block h-full",
|
||||
keyframe.keyframe_uuid === selectedItem
|
||||
keyframe.keyframe_uuid === selectedKeyframeId
|
||||
? "border border-b-2 border-l-2 border-r-0 border-t-2 border-white focus-visible:outline-0"
|
||||
: "",
|
||||
].join(" ")}
|
||||
@@ -56,7 +59,7 @@ export const TrackKeyFrame = ({
|
||||
cursor: "w-resize",
|
||||
}}
|
||||
onPointerDown={(event) => onPointerDown(event, "left")}
|
||||
onClick={() => selectItem(keyframe.keyframe_uuid)}
|
||||
onClick={() => selectItem(keyframe)}
|
||||
>
|
||||
<FontAwesomeIcon icon={faSortUpDown} />
|
||||
</button>
|
||||
|
||||
@@ -1,12 +1,9 @@
|
||||
import { createContext } from "react";
|
||||
import {
|
||||
AudioGroup,
|
||||
CameraGroup,
|
||||
CharacterGroup,
|
||||
ObjectGroup,
|
||||
MediaClip,
|
||||
Keyframe,
|
||||
QueueKeyframe,
|
||||
Clip,
|
||||
} from "~/pages/PageEnigma/models/track";
|
||||
|
||||
export const TrackContext = createContext<{
|
||||
@@ -15,8 +12,8 @@ export const TrackContext = createContext<{
|
||||
deleteKeyframe: (keyframe: Keyframe) => void;
|
||||
|
||||
// current - only select one item - will be replaced
|
||||
selectedItem: string | null;
|
||||
selectItem: (itemId: string) => void;
|
||||
selectedItem: Clip | Keyframe | null;
|
||||
selectItem: (item: Clip | Keyframe) => void;
|
||||
|
||||
// sidebar clips
|
||||
animationClips: MediaClip[];
|
||||
|
||||
@@ -1,6 +1,11 @@
|
||||
import { TrackContext } from "~/pages/PageEnigma/contexts/TrackContext/TrackContext";
|
||||
import { ReactNode, useCallback, useEffect, useMemo, useState } from "react";
|
||||
import { ClipType, MediaClip } from "~/pages/PageEnigma/models/track";
|
||||
import {
|
||||
ClipType,
|
||||
Keyframe,
|
||||
Clip,
|
||||
MediaClip,
|
||||
} from "~/pages/PageEnigma/models/track";
|
||||
import useUpdateDragDrop from "~/pages/PageEnigma/contexts/TrackContext/utils/useUpdateDragDrop";
|
||||
import {
|
||||
addCharacterAnimation,
|
||||
@@ -22,9 +27,12 @@ export const TrackProvider = ({ children }: Props) => {
|
||||
|
||||
const { endDrag, ...dragDrop } = useUpdateDragDrop();
|
||||
|
||||
const [selectedItem, setSelectedClip] = useState<string | null>(null);
|
||||
const selectItem = useCallback((clipId: string | null) => {
|
||||
setSelectedClip(clipId);
|
||||
const [selectedItem, setSelectedItem] = useState<Clip | Keyframe | null>(
|
||||
null,
|
||||
);
|
||||
const selectItem = useCallback((item: Clip | Keyframe) => {
|
||||
console.log("item", item);
|
||||
setSelectedItem(item);
|
||||
}, []);
|
||||
|
||||
const [animationClips, setAnimationClips] = useState<MediaClip[]>([]);
|
||||
@@ -98,7 +106,36 @@ export const TrackProvider = ({ children }: Props) => {
|
||||
name: "Walk",
|
||||
},
|
||||
]);
|
||||
setAudioClips([]);
|
||||
setAudioClips([
|
||||
{
|
||||
version: 1,
|
||||
media_id: uuid.v4(),
|
||||
type: ClipType.ANIMATION,
|
||||
length: 25,
|
||||
name: "Sing",
|
||||
},
|
||||
{
|
||||
version: 1,
|
||||
media_id: uuid.v4(),
|
||||
type: ClipType.AUDIO,
|
||||
length: 25,
|
||||
name: "Chatter",
|
||||
},
|
||||
{
|
||||
version: 1,
|
||||
media_id: uuid.v4(),
|
||||
type: ClipType.AUDIO,
|
||||
length: 25,
|
||||
name: "Talk",
|
||||
},
|
||||
{
|
||||
version: 1,
|
||||
media_id: uuid.v4(),
|
||||
type: ClipType.AUDIO,
|
||||
length: 25,
|
||||
name: "Yell",
|
||||
},
|
||||
]);
|
||||
setScale(1);
|
||||
setLength(12);
|
||||
}, []);
|
||||
|
||||
@@ -36,6 +36,7 @@ export default function useUpdateKeyframe() {
|
||||
}, []);
|
||||
|
||||
const deleteKeyframe = useCallback((keyframe: Keyframe) => {
|
||||
console.log("del", keyframe);
|
||||
DELETE_KEYFRAME[keyframe.group](keyframe);
|
||||
}, []);
|
||||
|
||||
|
||||
@@ -115,17 +115,17 @@ export function selectAudioClip(clipId: string) {
|
||||
};
|
||||
}
|
||||
|
||||
export function deleteAudioClip(clipId: string) {
|
||||
export function deleteAudioClip(clip: Clip) {
|
||||
const oldAudioGroup = audioGroup.value;
|
||||
audioGroup.value = {
|
||||
...oldAudioGroup,
|
||||
clips: [
|
||||
...oldAudioGroup.clips.filter((clip) => {
|
||||
if (clip.clip_uuid === clipId) {
|
||||
...oldAudioGroup.clips.filter((row) => {
|
||||
if (row.clip_uuid === clip.clip_uuid) {
|
||||
Queue.publish({
|
||||
queueName: QueueNames.TO_ENGINE,
|
||||
action: toEngineActions.DELETE_CLIP,
|
||||
data: clip!,
|
||||
data: row,
|
||||
});
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -283,27 +283,27 @@ export function selectCharacterClip(clipId: string) {
|
||||
}));
|
||||
}
|
||||
|
||||
export function deleteCharacterClip(clipId: string) {
|
||||
export function deleteCharacterClip(clip: Clip) {
|
||||
const oldCharacterGroups = characterGroups.value;
|
||||
characterGroups.value = oldCharacterGroups.map((character) => ({
|
||||
...character,
|
||||
animationClips: character.animationClips.filter((clip) => {
|
||||
if (clip.clip_uuid === clipId) {
|
||||
animationClips: character.animationClips.filter((row) => {
|
||||
if (row.clip_uuid === clip.clip_uuid) {
|
||||
Queue.publish({
|
||||
queueName: QueueNames.TO_ENGINE,
|
||||
action: toEngineActions.DELETE_CLIP,
|
||||
data: clip!,
|
||||
data: row,
|
||||
});
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}),
|
||||
lipSyncClips: character.lipSyncClips.filter((clip) => {
|
||||
if (clip.clip_uuid === clipId) {
|
||||
lipSyncClips: character.lipSyncClips.filter((row) => {
|
||||
if (row.clip_uuid === clip.clip_uuid) {
|
||||
Queue.publish({
|
||||
queueName: QueueNames.TO_ENGINE,
|
||||
action: toEngineActions.DELETE_CLIP,
|
||||
data: clip!,
|
||||
data: row,
|
||||
});
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -4,7 +4,6 @@ import {
|
||||
ObjectGroup,
|
||||
QueueKeyframe,
|
||||
} from "~/pages/PageEnigma/models/track";
|
||||
import { useCallback } from "react";
|
||||
import * as uuid from "uuid";
|
||||
import Queue from "~/pages/PageEnigma/Queue/Queue";
|
||||
import { QueueNames } from "~/pages/PageEnigma/Queue/QueueNames";
|
||||
@@ -31,7 +30,6 @@ export function updateObject({ id, offset }: { id: string; offset: number }) {
|
||||
}
|
||||
|
||||
export function addObjectKeyframe(keyframe: QueueKeyframe, offset: number) {
|
||||
console.log(keyframe, offset);
|
||||
const oldObjectGroup = objectGroup.value;
|
||||
const obj = oldObjectGroup.objects.find(
|
||||
(row) => row.object_uuid === keyframe.object_uuid,
|
||||
@@ -80,14 +78,23 @@ export function deleteObjectKeyframe(keyframe: Keyframe) {
|
||||
const obj = oldObjectGroup.objects.find(
|
||||
(row) => row.object_uuid === keyframe.object_uuid,
|
||||
);
|
||||
console.log("delete", obj);
|
||||
if (!obj) {
|
||||
return oldObjectGroup;
|
||||
}
|
||||
|
||||
const newKeyframes = [
|
||||
...obj.keyframes.filter(
|
||||
(row) => row.keyframe_uuid !== keyframe.keyframe_uuid,
|
||||
),
|
||||
...obj.keyframes.filter((row) => {
|
||||
if (row.keyframe_uuid === keyframe.keyframe_uuid) {
|
||||
Queue.publish({
|
||||
queueName: QueueNames.TO_ENGINE,
|
||||
action: toEngineActions.DELETE_KEYFRAME,
|
||||
data: row,
|
||||
});
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}),
|
||||
];
|
||||
|
||||
if (newKeyframes.length) {
|
||||
|
||||
Reference in new issue
Block a user