Skip to content

Commit 3bf125f

Browse files
committed
migrate some changes
1 parent 961fd9a commit 3bf125f

10 files changed

Lines changed: 534 additions & 102 deletions

File tree

src/lib/animation.ts

Lines changed: 148 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import { useClipId, useClipStart, useProvideClipDuration } from "./clip"
99
import { useCurrentFrame } from "./frame"
1010
import type { Easing } from "./animation/functions"
1111
import { useTimelineClips, type TimelineClip } from "./timeline"
12+
import { recordFrameScriptDebugLog } from "./debug-log"
1213

1314
type Lerp<T> = (from: T, to: T, t: number) => T
1415

@@ -98,6 +99,8 @@ export type AnimationContext = {
9899
type InternalContext = AnimationContext & {
99100
now: number
100101
maxFrame: number
102+
cancelled: boolean
103+
unresolvedClipLabels: Set<string>
101104
register: (variable: Variable<unknown>) => void
102105
}
103106

@@ -461,32 +464,17 @@ export const useAnimation = (
461464
if (!clipId) return true
462465
return isDescendantOf(clip, clipId)
463466
}
464-
for (const clip of clips) {
465-
if (!clip.label) continue
466-
const existing = map.get(clip.label)
467-
if (!existing) {
468-
map.set(clip.label, clip)
469-
continue
470-
}
471-
const nextInScope = isInScope(clip)
472-
const existingInScope = isInScope(existing)
473-
if (nextInScope && !existingInScope) {
474-
map.set(clip.label, clip)
475-
continue
476-
}
477-
if (nextInScope === existingInScope) {
478-
if (clip.start < existing.start) {
479-
map.set(clip.label, clip)
480-
continue
481-
}
482-
if (clip.start === existing.start) {
483-
const clipDepth = clip.depth ?? 0
484-
const existingDepth = existing.depth ?? 0
485-
if (clipDepth < existingDepth) {
486-
map.set(clip.label, clip)
487-
}
488-
}
489-
}
467+
const candidates = clips
468+
.filter((clip) => clip.label && !clip.pending && isInScope(clip))
469+
.sort((a, b) => {
470+
if (a.start !== b.start) return a.start - b.start
471+
const depthDelta = (a.depth ?? 0) - (b.depth ?? 0)
472+
if (depthDelta !== 0) return depthDelta
473+
return a.id.localeCompare(b.id)
474+
})
475+
for (const clip of candidates) {
476+
if (!clip.label || map.has(clip.label)) continue
477+
map.set(clip.label, clip)
490478
}
491479
return map
492480
}, [clips, clipId])
@@ -527,7 +515,10 @@ export const useAnimation = (
527515
const internal: InternalContext = {
528516
now: 0,
529517
maxFrame: 0,
518+
cancelled: false,
519+
unresolvedClipLabels: new Set(),
530520
register: (variable) => {
521+
if (internal.cancelled) return
531522
if (
532523
variable._state.ownerId != null &&
533524
variable._state.ownerId !== ownerId
@@ -549,18 +540,77 @@ export const useAnimation = (
549540
return new AnimationHandle(internal, target)
550541
},
551542
waitUntilClip: (label: string) => {
543+
if (internal.cancelled) {
544+
return new AnimationHandle(internal, internal.now)
545+
}
552546
const clip = clipLabelMap.get(label)
553547
if (!clip) {
548+
internal.unresolvedClipLabels.add(label)
549+
recordFrameScriptDebugLog("animation", "waitUntilClip:unresolved", {
550+
label,
551+
ownerId,
552+
runId,
553+
clipId,
554+
clipStart,
555+
now: internal.now,
556+
labels: Array.from(clipLabelMap.keys()),
557+
sameLabelClips: clips
558+
.filter((item) => item.label === label)
559+
.map((item) => ({
560+
id: item.id,
561+
start: item.start,
562+
end: item.end,
563+
depth: item.depth,
564+
parentId: item.parentId,
565+
pending: item.pending,
566+
})),
567+
})
554568
return new AnimationHandle(internal, internal.now)
555569
}
556570
const targetFrame = clip.start - clipStart
557571
const target = Math.max(internal.now, toFrames(targetFrame))
572+
recordFrameScriptDebugLog("animation", "waitUntilClip:resolved", {
573+
label,
574+
ownerId,
575+
runId,
576+
clipId,
577+
clipStart,
578+
now: internal.now,
579+
targetFrame,
580+
target,
581+
chosen: {
582+
id: clip.id,
583+
start: clip.start,
584+
end: clip.end,
585+
depth: clip.depth,
586+
parentId: clip.parentId,
587+
pending: clip.pending,
588+
},
589+
sameLabelClips: clips
590+
.filter((item) => item.label === label)
591+
.map((item) => ({
592+
id: item.id,
593+
start: item.start,
594+
end: item.end,
595+
depth: item.depth,
596+
parentId: item.parentId,
597+
pending: item.pending,
598+
})),
599+
})
558600
return new AnimationHandle(internal, target)
559601
},
560602
move: (variable) => {
603+
if (internal.cancelled) {
604+
return {
605+
to: () => new AnimationHandle(internal, internal.now),
606+
}
607+
}
561608
internal.register(variable as Variable<unknown>)
562609
return {
563610
to: (value, durationFrames, easing) => {
611+
if (internal.cancelled) {
612+
return new AnimationHandle(internal, internal.now)
613+
}
564614
if (isDev) {
565615
assertCompatibleValue(variable._state.kind, value)
566616
}
@@ -576,6 +626,16 @@ export const useAnimation = (
576626
to: value as VariableType,
577627
easing,
578628
})
629+
recordFrameScriptDebugLog("animation", "move", {
630+
ownerId,
631+
runId,
632+
clipId,
633+
clipStart,
634+
start,
635+
end,
636+
from,
637+
to: value,
638+
})
579639
return new AnimationHandle(internal, end + 1)
580640
},
581641
}
@@ -592,17 +652,78 @@ export const useAnimation = (
592652
}
593653

594654
const execute = async () => {
655+
recordFrameScriptDebugLog("animation", "run:start", {
656+
ownerId,
657+
runId,
658+
clipId,
659+
clipStart,
660+
clipStartContext,
661+
clipCount: clips.length,
662+
labels: Array.from(clipLabelMap.entries()).map(([label, clip]) => ({
663+
label,
664+
id: clip.id,
665+
start: clip.start,
666+
end: clip.end,
667+
depth: clip.depth,
668+
parentId: clip.parentId,
669+
pending: clip.pending,
670+
})),
671+
})
595672
try {
596673
await run(internal)
597674
} finally {
598675
// keep owner
599676
}
600677

601678
if (runIdRef.current !== runId) {
679+
recordFrameScriptDebugLog("animation", "run:stale", {
680+
ownerId,
681+
runId,
682+
currentRunId: runIdRef.current,
683+
clipId,
684+
clipStart,
685+
now: internal.now,
686+
maxFrame: internal.maxFrame,
687+
})
688+
finalize()
689+
return
690+
}
691+
if (internal.unresolvedClipLabels.size > 0) {
692+
for (const variable of variablesRef.current) {
693+
if (variable._state.ownerId === ownerId) {
694+
variable._state.segments.length = 0
695+
}
696+
}
697+
if (isDev) {
698+
console.warn(
699+
`useAnimation: waiting for clip label(s): ${Array.from(
700+
internal.unresolvedClipLabels,
701+
).join(", ")}`,
702+
)
703+
}
704+
setReady(false)
705+
recordFrameScriptDebugLog("animation", "run:unresolved", {
706+
ownerId,
707+
runId,
708+
clipId,
709+
clipStart,
710+
unresolvedClipLabels: Array.from(internal.unresolvedClipLabels),
711+
now: internal.now,
712+
maxFrame: internal.maxFrame,
713+
})
602714
finalize()
603715
return
604716
}
605717
const nextDuration = Math.max(1, Math.round(internal.maxFrame))
718+
recordFrameScriptDebugLog("animation", "run:finish", {
719+
ownerId,
720+
runId,
721+
clipId,
722+
clipStart,
723+
now: internal.now,
724+
maxFrame: internal.maxFrame,
725+
durationFrames: nextDuration,
726+
})
606727
setDurationFrames(nextDuration)
607728
setReady(true)
608729
finalize()
@@ -612,6 +733,7 @@ export const useAnimation = (
612733

613734
return () => {
614735
runIdRef.current += 1
736+
internal.cancelled = true
615737
for (const variable of variablesRef.current) {
616738
if (variable._state.ownerId === ownerId) {
617739
variable._state.ownerId = null

src/lib/character/character-unit/ast.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,9 @@ export interface DeclareAnimationNode {
7272

7373
export interface VoiceNode {
7474
type: typeof PsdCharacterElement.Voice
75-
voice: string
75+
voice?: string
76+
voiceLabel?: string | string[]
77+
voiceLabels?: string[]
7678
voiceMotion?: (
7779
segment: AudioSegment,
7880
waveform: WaveformData | null,

src/lib/character/character-unit/parser.tsx

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -269,6 +269,8 @@ const parseDeclareAnimationChildren = (
269269
const parseVoice = (self: AnyElement): VoiceNode => {
270270
const {
271271
voice,
272+
voiceLabel,
273+
voiceLabels,
272274
voiceMotion,
273275
trim,
274276
fadeInFrames,
@@ -279,6 +281,8 @@ const parseVoice = (self: AnyElement): VoiceNode => {
279281
return {
280282
type: PsdElm.Voice,
281283
voice,
284+
voiceLabel,
285+
voiceLabels,
282286
voiceMotion,
283287
trim,
284288
fadeInFrames,

src/lib/character/character-unit/psd-character-component.tsx

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -87,10 +87,12 @@ DeclareAnimation.__dslType = PsdCharacterElement.DeclareAnimation
8787
* @param voiceMotion 音声を利用したアニメーションをつける関数
8888
*/
8989
export const Voice = defineDSL<{
90-
voice: string
90+
voice?: string
91+
voiceLabel?: string | string[]
92+
voiceLabels?: string[]
9193
voiceMotion?: (
9294
segment: AudioSegment,
93-
waveform: WaveformData,
95+
waveform: WaveformData | null,
9496
variables: Record<string, Variable<VariableType>>,
9597
frames: number[],
9698
) => Record<string, any>
@@ -205,13 +207,15 @@ type MotionWithVarsProps<
205207
}
206208

207209
type VoiceMotionProps<T extends Record<string, VariableType>> = {
208-
voice: string
209210
voiceMotion: (
210211
segment: AudioSegment,
211-
waveform: WaveformData,
212+
waveform: WaveformData | null,
212213
variables: Variables<T>,
213214
frames: number[],
214215
) => Record<string, any>
216+
voice?: string
217+
voiceLabel?: string | string[]
218+
voiceLabels?: string[]
215219
trim?: Trim
216220
fadeInFrames?: number
217221
fadeOutFrames?: number
@@ -234,9 +238,11 @@ export const VoiceMotion = <T extends Record<string, VariableType> = any>(
234238
let result = (
235239
<Voice
236240
voice={props.voice}
241+
voiceLabel={props.voiceLabel}
242+
voiceLabels={props.voiceLabels}
237243
voiceMotion={(
238244
segment: AudioSegment,
239-
waveform: WaveformData,
245+
waveform: WaveformData | null,
240246
variables: Record<string, Variable<VariableType>>,
241247
frames: number[],
242248
) =>

0 commit comments

Comments
 (0)