mirror of
https://github.com/storytold/artcraft.git
synced 2026-11-10 20:11:49 +00:00
Do not show Lipsync Track for Characters that are not capable of Lipsync (#313)
Adds function to check if its a lipsync object.
This commit is contained in:
1 parent
50dc150e1c
commit
b815d7ba09
4 files changed
+77
-28
No files matched your search
@@ -11,6 +11,7 @@ import { CharacterTrack, ClipGroup, ClipType } from "~/pages/PageEnigma/models";
|
||||
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
|
||||
import { faAngleDown, faAngleUp } from "@fortawesome/pro-solid-svg-icons";
|
||||
import { AddToast, ToasterContext } from "~/contexts/ToasterContext";
|
||||
import { EngineContext } from "~/contexts/EngineContext";
|
||||
import { environmentVariables } from "~/store";
|
||||
|
||||
function buildUpdaters(
|
||||
@@ -69,6 +70,8 @@ interface Props {
|
||||
|
||||
export const Character = ({ character }: Props) => {
|
||||
const { addToast } = useContext(ToasterContext);
|
||||
const editorEngine = useContext(EngineContext);
|
||||
|
||||
const {
|
||||
updateClipLipSync,
|
||||
updateClipPosition,
|
||||
@@ -148,13 +151,15 @@ export const Character = ({ character }: Props) => {
|
||||
type={ClipType.EXPRESSION}
|
||||
/>
|
||||
)}
|
||||
<TrackClips
|
||||
id={character.object_uuid}
|
||||
clips={lipSyncClips}
|
||||
updateClip={updateClipLipSync}
|
||||
group={ClipGroup.CHARACTER}
|
||||
type={ClipType.AUDIO}
|
||||
/>
|
||||
{editorEngine && editorEngine.isObjectLipsync(character.object_uuid) &&
|
||||
<TrackClips
|
||||
id={character.object_uuid}
|
||||
clips={lipSyncClips}
|
||||
updateClip={updateClipLipSync}
|
||||
group={ClipGroup.CHARACTER}
|
||||
type={ClipType.AUDIO}
|
||||
/>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
||||
@@ -0,0 +1,39 @@
|
||||
import { useContext } from "react";
|
||||
import { EngineContext } from "~/contexts/EngineContext";
|
||||
import { toggleLipSyncMute } from "~/pages/PageEnigma/store";
|
||||
import {
|
||||
faVolume,
|
||||
faVolumeSlash
|
||||
} from "@fortawesome/pro-solid-svg-icons";
|
||||
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
|
||||
import { CharacterTrack } from "~/pages/PageEnigma/models";
|
||||
|
||||
export const LipSyncSubHeader = ({
|
||||
character
|
||||
}:{
|
||||
character: CharacterTrack
|
||||
})=>{
|
||||
const editorEngine = useContext(EngineContext);
|
||||
if (editorEngine && editorEngine.isObjectLipsync(character.object_uuid)){
|
||||
return(
|
||||
<div className="flex mb-3 h-[36px] flex-col justify-center pl-[22px] text-xs font-medium text-white opacity-80">
|
||||
<div className="flex gap-3">
|
||||
Lip Sync
|
||||
<button
|
||||
className="text-md text-white transition-colors duration-100 hover:text-white/80"
|
||||
onClick={() => toggleLipSyncMute(character.object_uuid)}>
|
||||
{character.muted ? (
|
||||
<FontAwesomeIcon
|
||||
icon={faVolumeSlash}
|
||||
className="text-brand-primary transition-colors duration-100 hover:text-brand-primary/80"
|
||||
/>
|
||||
) : (
|
||||
<FontAwesomeIcon icon={faVolume} />
|
||||
)}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
@@ -17,6 +17,7 @@ import { CameraHeader } from "~/pages/PageEnigma/comps/Timeline/RowHeaders/Camer
|
||||
import { ObjectsHeader } from "~/pages/PageEnigma/comps/Timeline/RowHeaders/ObjectsHeader";
|
||||
import { CharacterHeader } from "~/pages/PageEnigma/comps/Timeline/RowHeaders/CharacterHeader";
|
||||
import { environmentVariables } from "~/store";
|
||||
import { LipSyncSubHeader } from "./LipSyncSubHeader";
|
||||
|
||||
export const RowHeaders = () => {
|
||||
useSignals();
|
||||
@@ -50,10 +51,11 @@ export const RowHeaders = () => {
|
||||
return (
|
||||
<div
|
||||
key={character.object_uuid}
|
||||
className="mb-4 w-full rounded-l-lg bg-character-groupBg"
|
||||
style={{
|
||||
height: environmentVariables.value.EXPRESSIONS ? 247 : 199,
|
||||
}}>
|
||||
className="mb-4 w-full rounded-l-lg bg-character-groupBg pb-2"
|
||||
// style={{
|
||||
// height: environmentVariables.value.EXPRESSIONS ? 247 : 199,
|
||||
// }}
|
||||
>
|
||||
<div className="h-[47px] text-xs font-medium text-white">
|
||||
<div
|
||||
className={[
|
||||
@@ -74,23 +76,7 @@ export const RowHeaders = () => {
|
||||
Expression
|
||||
</div>
|
||||
)}
|
||||
<div className="flex h-[36px] flex-col justify-center pl-[22px] text-xs font-medium text-white opacity-80">
|
||||
<div className="flex gap-3">
|
||||
Lip Sync
|
||||
<button
|
||||
className="text-md text-white transition-colors duration-100 hover:text-white/80"
|
||||
onClick={() => toggleLipSyncMute(character.object_uuid)}>
|
||||
{character.muted ? (
|
||||
<FontAwesomeIcon
|
||||
icon={faVolumeSlash}
|
||||
className="text-brand-primary transition-colors duration-100 hover:text-brand-primary/80"
|
||||
/>
|
||||
) : (
|
||||
<FontAwesomeIcon icon={faVolume} />
|
||||
)}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<LipSyncSubHeader character={character}/>
|
||||
</div>
|
||||
);
|
||||
})}
|
||||
|
||||
@@ -558,6 +558,25 @@ class Editor {
|
||||
});
|
||||
}
|
||||
|
||||
isObjectLipsync(object_uuid: string) {
|
||||
let object = this.activeScene.get_object_by_uuid(object_uuid);
|
||||
let hasLipsync = false;
|
||||
if(object){
|
||||
object.traverse((c: THREE.Object3D) => {
|
||||
if (c instanceof THREE.Mesh) {
|
||||
if (c.morphTargetInfluences && c.morphTargetDictionary) {
|
||||
const blendShapeIndexE = c.morphTargetDictionary["E"];
|
||||
console.log(c.morphTargetDictionary, blendShapeIndexE)
|
||||
if (blendShapeIndexE !== null) {
|
||||
hasLipsync = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
return hasLipsync;
|
||||
}
|
||||
|
||||
isObjectLocked(object_uuid: string) {
|
||||
let object = this.activeScene.get_object_by_uuid(object_uuid);
|
||||
if(object){
|
||||
|
||||
Reference in new issue
Block a user