@lovelace_lol/embody 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +2411 -0
- package/dist/authoring/boneAuthoring.d.ts +132 -0
- package/dist/camera/annotationCameraAngles.d.ts +28 -0
- package/dist/camera/cameraRelativeGaze.d.ts +15 -0
- package/dist/camera/rustAnnotationCameraCore.d.ts +136 -0
- package/dist/cljs.cjs +362 -0
- package/dist/cljs.cjs.map +1 -0
- package/dist/cljs.d.ts +5 -0
- package/dist/cljs.js +359 -0
- package/dist/cljs.js.map +1 -0
- package/dist/core/TsClipCompiler.d.ts +51 -0
- package/dist/core/TsRuntimeCore.d.ts +40 -0
- package/dist/core/WasmRuntimeCore.d.ts +55 -0
- package/dist/core/compositeAxis.d.ts +4 -0
- package/dist/core/contracts/abi.d.ts +70 -0
- package/dist/core/contracts/clip.d.ts +44 -0
- package/dist/core/contracts/frame.d.ts +27 -0
- package/dist/core/contracts/host.d.ts +28 -0
- package/dist/core/contracts/ids.d.ts +15 -0
- package/dist/core/contracts/index.d.ts +10 -0
- package/dist/core/contracts/model.d.ts +31 -0
- package/dist/core/contracts/primitives.d.ts +17 -0
- package/dist/core/contracts/skeletonFit.d.ts +41 -0
- package/dist/core/index.d.ts +8 -0
- package/dist/core/types.d.ts +472 -0
- package/dist/core.cjs +1065 -0
- package/dist/core.cjs.map +1 -0
- package/dist/core.js +1040 -0
- package/dist/core.js.map +1 -0
- package/dist/engines/three/Embody.d.ts +373 -0
- package/dist/engines/three/ThreeAnimationRuntime.d.ts +203 -0
- package/dist/engines/three/ThreeClipAdapter.d.ts +24 -0
- package/dist/engines/three/ThreeFrameApplier.d.ts +68 -0
- package/dist/engines/three/ThreeModelInspector.d.ts +54 -0
- package/dist/engines/three/bakedClipPartitioning.d.ts +16 -0
- package/dist/engines/three/balanceUtils.d.ts +3 -0
- package/dist/engines/three/characterHost.d.ts +80 -0
- package/dist/engines/three/characterScene.d.ts +98 -0
- package/dist/engines/three/hair/HairPhysicsController.d.ts +124 -0
- package/dist/engines/three/index.d.ts +20 -0
- package/dist/engines/three/modelLoader.d.ts +61 -0
- package/dist/engines/three/profileTestScene.d.ts +52 -0
- package/dist/engines/three/types.d.ts +20 -0
- package/dist/hair/appearance.d.ts +29 -0
- package/dist/index.cjs +15431 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.ts +100 -0
- package/dist/index.js +15141 -0
- package/dist/index.js.map +1 -0
- package/dist/interfaces/Animation.d.ts +315 -0
- package/dist/interfaces/EmbodyRuntime.d.ts +90 -0
- package/dist/interfaces/Hair.d.ts +181 -0
- package/dist/interfaces/HairPhysics.d.ts +90 -0
- package/dist/interfaces/index.d.ts +11 -0
- package/dist/mappings/extendPresetWithProfile.d.ts +17 -0
- package/dist/mappings/types.d.ts +309 -0
- package/dist/mappings/visemeSystem.d.ts +26 -0
- package/dist/physics/HairPhysics.d.ts +86 -0
- package/dist/physics/RustHairPhysics.d.ts +18 -0
- package/dist/physics/index.d.ts +6 -0
- package/dist/preset.cjs +2000 -0
- package/dist/preset.cjs.map +1 -0
- package/dist/preset.js +1997 -0
- package/dist/preset.js.map +1 -0
- package/dist/presets/bettaFish.d.ts +328 -0
- package/dist/presets/cc4.d.ts +145 -0
- package/dist/presets/index.d.ts +27 -0
- package/dist/profiles/resolveProfileConfig.d.ts +36 -0
- package/dist/profiles/types.d.ts +118 -0
- package/dist/regions/normalizeRegionTree.d.ts +6 -0
- package/dist/regions/regionMapping.d.ts +17 -0
- package/dist/regions/types.d.ts +122 -0
- package/dist/skeletonTemplates/humanoidSkeletonTemplates.d.ts +32 -0
- package/dist/test/setupWasm.d.ts +1 -0
- package/dist/three.cjs +10115 -0
- package/dist/three.cjs.map +1 -0
- package/dist/three.js +10086 -0
- package/dist/three.js.map +1 -0
- package/dist/validation/analyzeModel.d.ts +68 -0
- package/dist/validation/extractModelData.d.ts +90 -0
- package/dist/validation/generateMappingCorrections.d.ts +32 -0
- package/dist/validation/geometryHelpers.d.ts +66 -0
- package/dist/validation/types.d.ts +10 -0
- package/dist/validation/validateMappings.d.ts +77 -0
- package/dist/wasm/LICENSE +21 -0
- package/dist/wasm/README.md +72 -0
- package/dist/wasm/embody_wasm.d.ts +531 -0
- package/dist/wasm/embody_wasm.js +1635 -0
- package/dist/wasm/embody_wasm_bg.wasm +0 -0
- package/dist/wasm/embody_wasm_bg.wasm.d.ts +107 -0
- package/dist/wasm.cjs +302 -0
- package/dist/wasm.cjs.map +1 -0
- package/dist/wasm.d.ts +43 -0
- package/dist/wasm.js +268 -0
- package/dist/wasm.js.map +1 -0
- package/dist/wasmTypes.d.ts +121 -0
- package/package.json +99 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/cljs.ts"],"names":[],"mappings":"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","file":"cljs.cjs","sourcesContent":["import type {\n ClipEvent,\n ClipEventListener,\n ClipHandle,\n ClipOptions,\n CurvePoint,\n CurvesMap,\n EmbodyAnimationRuntime,\n EmbodyAnimationRuntimeConnector,\n} from './core/types';\n\ntype LoopMode = 'once' | 'repeat' | 'pingpong';\ntype RuntimeStatus = 'playing' | 'paused' | 'completed' | 'stopped';\n\ntype RuntimeOptions = {\n weight: number;\n rate: number;\n loopMode: LoopMode;\n loop: boolean;\n repeatCount?: number;\n reverse: boolean;\n source: string;\n startTime: number;\n [key: string]: unknown;\n};\n\ntype RuntimeHandleState = {\n clipName: string;\n actionId?: string;\n duration: number;\n time: number;\n weight: number;\n rate: number;\n loopMode: LoopMode;\n loop: boolean;\n repeatCount?: number;\n reverse: boolean;\n source: string;\n status: RuntimeStatus;\n createdAt: number;\n updatedAt: number;\n};\n\ntype RuntimeState = {\n handles: Record<string, RuntimeHandleState>;\n order: string[];\n eventCount: number;\n lastEvent: Record<string, unknown> | null;\n lastUpdatedTime: number | null;\n config: Record<string, unknown>;\n};\n\ntype ConnectorFunction = (...args: unknown[]) => unknown;\n\nconst LOOP_MODES = new Set<LoopMode>(['once', 'repeat', 'pingpong']);\n\nfunction nowMs(): number {\n return Date.now();\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null && !Array.isArray(value);\n}\n\nfunction finiteNumber(value: unknown): value is number {\n return typeof value === 'number' && Number.isFinite(value);\n}\n\nfunction numberOr(value: unknown, fallback: number): number {\n return finiteNumber(value) ? value : fallback;\n}\n\nfunction clamp(low: number, high: number, value: unknown): number {\n const next = numberOr(value, low);\n return Math.min(high, Math.max(low, next));\n}\n\nfunction keyToString(value: unknown): string {\n if (typeof value === 'string') return value;\n if (typeof value === 'number') return String(value);\n if (typeof value === 'symbol') return value.description ?? '';\n return '';\n}\n\nfunction getConnectorFunction(\n connector: EmbodyAnimationRuntimeConnector,\n name: string\n): ConnectorFunction | null {\n const candidate = (connector as Record<string, unknown>)[name];\n return typeof candidate === 'function' ? candidate as ConnectorFunction : null;\n}\n\nfunction callFirst(\n connector: EmbodyAnimationRuntimeConnector,\n names: string[],\n ...args: unknown[]\n): unknown {\n for (const name of names) {\n const callback = getConnectorFunction(connector, name);\n if (callback) {\n return callback(...args);\n }\n }\n return undefined;\n}\n\nfunction normalizePoint(point: unknown): CurvePoint {\n const source = isRecord(point) ? point : {};\n return {\n time: numberOr(source.time ?? source.t, 0),\n intensity: numberOr(source.intensity ?? source.v, 0),\n inherit: Boolean(source.inherit),\n };\n}\n\nfunction normalizeCurves(curves: CurvesMap): CurvesMap {\n if (!isRecord(curves)) {\n return {};\n }\n\n return Object.fromEntries(\n Object.entries(curves).map(([curveId, points]) => [\n keyToString(curveId),\n (Array.isArray(points) ? points : [])\n .map(normalizePoint)\n .sort((a, b) => a.time - b.time),\n ])\n );\n}\n\nfunction calculateDuration(curves: CurvesMap, fallback: unknown): number {\n return Object.values(curves).reduce((duration, points) => {\n const last = points[points.length - 1];\n return Math.max(duration, numberOr(last?.time, duration));\n }, numberOr(fallback, 0));\n}\n\nfunction normalizeLoopMode(options: Record<string, unknown>): LoopMode {\n const mode = options.loopMode ?? options.mixerLoopMode;\n if (typeof mode === 'string' && LOOP_MODES.has(mode as LoopMode)) {\n return mode as LoopMode;\n }\n return options.loop === false ? 'once' : 'repeat';\n}\n\nfunction normalizeOptions(options?: ClipOptions): RuntimeOptions {\n const source = isRecord(options) ? options : {};\n const loopMode = normalizeLoopMode(source);\n const rate = source.playbackRate ?? source.rate ?? source.speed;\n const weight = source.weight ?? source.intensity ?? source.mixerWeight;\n\n return {\n ...source,\n weight: Math.max(0, numberOr(weight, 1)),\n rate: Math.max(0, numberOr(rate, 1)),\n loopMode,\n loop: loopMode !== 'once',\n repeatCount: finiteNumber(source.repeatCount) ? source.repeatCount : undefined,\n reverse: Boolean(source.reverse),\n source: keyToString(source.source) || 'clip',\n startTime: Math.max(0, numberOr(source.startTime, 0)),\n balance: clamp(-1, 1, source.balance),\n jawScale: Math.max(0, numberOr(source.jawScale, 1)),\n intensityScale: Math.max(0, numberOr(source.intensityScale, 1)),\n };\n}\n\nfunction makeActionId(clipName: string): string {\n return `${clipName}#${nowMs()}-${Math.floor(Math.random() * 1_000_000)}`;\n}\n\nfunction emitCommand(\n connector: EmbodyAnimationRuntimeConnector,\n op: string,\n clipName: string,\n payload: Record<string, unknown> = {}\n): Record<string, unknown> {\n const command = {\n type: 'clipCommand',\n op,\n clipName,\n timestamp: nowMs(),\n ...payload,\n };\n connector.onCommand?.(command);\n return command;\n}\n\nfunction emitState(connector: EmbodyAnimationRuntimeConnector, state: RuntimeState): void {\n connector.onState?.(snapshotState(state));\n}\n\nfunction snapshotState(state: RuntimeState): Record<string, unknown> {\n return {\n handles: Object.fromEntries(\n Object.entries(state.handles).map(([clipName, handle]) => [clipName, { ...handle }])\n ),\n order: [...state.order],\n eventCount: state.eventCount,\n lastEvent: state.lastEvent ? { ...state.lastEvent } : null,\n lastUpdatedTime: state.lastUpdatedTime,\n config: { ...state.config },\n };\n}\n\nexport function createAnimationRuntime(\n config: Record<string, unknown> | null = null,\n connector: EmbodyAnimationRuntimeConnector | null = null\n): EmbodyAnimationRuntime {\n const renderer = connector ?? {};\n const state: RuntimeState = {\n handles: {},\n order: [],\n eventCount: 0,\n lastEvent: null,\n lastUpdatedTime: null,\n config: isRecord(config) ? { ...config } : {},\n };\n const listeners = new Map<string, Set<ClipEventListener>>();\n const finishers = new Map<string, () => void>();\n\n const upsertHandle = (handle: RuntimeHandleState) => {\n state.handles[handle.clipName] = handle;\n if (!state.order.includes(handle.clipName)) {\n state.order.push(handle.clipName);\n }\n state.lastUpdatedTime = nowMs();\n };\n\n const updateHandle = (\n clipName: string,\n apply: (handle: RuntimeHandleState) => RuntimeHandleState\n ) => {\n const current = state.handles[clipName];\n if (!current) return;\n state.handles[clipName] = apply({ ...current, updatedAt: nowMs() });\n state.lastUpdatedTime = nowMs();\n };\n\n const removeHandle = (clipName: string) => {\n delete state.handles[clipName];\n state.order = state.order.filter((name) => name !== clipName);\n state.lastUpdatedTime = nowMs();\n };\n\n const notifyListeners = (clipName: string, event: ClipEvent) => {\n for (const listener of Array.from(listeners.get(clipName) ?? [])) {\n try {\n listener(event);\n } catch (error) {\n console.error('[Embody runtime] clip listener failed', error);\n }\n }\n };\n\n const resolveFinished = (clipName: string) => {\n const resolve = finishers.get(clipName);\n if (resolve) {\n resolve();\n finishers.delete(clipName);\n }\n };\n\n const makeHandle = (clipName: string): ClipHandle => {\n const finished = new Promise<void>((resolve) => {\n finishers.set(clipName, resolve);\n });\n\n return {\n clipName,\n actionId: state.handles[clipName]?.actionId,\n play: () => {\n updateHandle(clipName, (handle) => ({ ...handle, status: 'playing' }));\n emitCommand(renderer, 'play', clipName);\n callFirst(renderer, ['playClip', 'play'], clipName);\n emitState(renderer, state);\n },\n stop: () => {\n updateHandle(clipName, (handle) => ({ ...handle, status: 'stopped' }));\n emitCommand(renderer, 'stop', clipName);\n callFirst(renderer, ['stopClip', 'stop'], clipName);\n resolveFinished(clipName);\n emitState(renderer, state);\n },\n pause: () => {\n updateHandle(clipName, (handle) => ({ ...handle, status: 'paused' }));\n emitCommand(renderer, 'pause', clipName);\n callFirst(renderer, ['pauseClip', 'pause'], clipName);\n emitState(renderer, state);\n },\n resume: () => {\n updateHandle(clipName, (handle) => ({ ...handle, status: 'playing' }));\n emitCommand(renderer, 'resume', clipName);\n callFirst(renderer, ['resumeClip', 'resume'], clipName);\n emitState(renderer, state);\n },\n setWeight: (weight: number) => {\n const nextWeight = Math.max(0, numberOr(weight, 1));\n updateHandle(clipName, (handle) => ({ ...handle, weight: nextWeight }));\n emitCommand(renderer, 'setWeight', clipName, { weight: nextWeight });\n callFirst(renderer, ['setClipWeight', 'setWeight'], clipName, nextWeight);\n emitState(renderer, state);\n },\n setPlaybackRate: (rate: number) => {\n const nextRate = Math.max(0, numberOr(rate, 1));\n updateHandle(clipName, (handle) => ({ ...handle, rate: nextRate }));\n emitCommand(renderer, 'setPlaybackRate', clipName, { rate: nextRate });\n callFirst(renderer, ['setClipPlaybackRate', 'setPlaybackRate'], clipName, nextRate);\n emitState(renderer, state);\n },\n setLoop: (mode: LoopMode, repeatCount?: number) => {\n const nextMode = LOOP_MODES.has(mode) ? mode : 'repeat';\n updateHandle(clipName, (handle) => ({\n ...handle,\n loopMode: nextMode,\n loop: nextMode !== 'once',\n repeatCount,\n }));\n emitCommand(renderer, 'setLoop', clipName, { loopMode: nextMode, repeatCount });\n callFirst(renderer, ['setClipLoop', 'setLoop'], clipName, nextMode, repeatCount);\n emitState(renderer, state);\n },\n setTime: (time: number) => {\n const duration = state.handles[clipName]?.duration ?? 0;\n const nextTime = clamp(0, duration, time);\n updateHandle(clipName, (handle) => ({ ...handle, time: nextTime }));\n emitCommand(renderer, 'setTime', clipName, { time: nextTime });\n callFirst(renderer, ['setClipTime', 'setTime'], clipName, nextTime);\n emitState(renderer, state);\n },\n getTime: () => {\n const rendererTime = callFirst(renderer, ['getClipTime', 'getTime'], clipName);\n return numberOr(rendererTime, state.handles[clipName]?.time ?? 0);\n },\n getDuration: () => {\n const rendererDuration = callFirst(renderer, ['getClipDuration', 'getDuration'], clipName);\n return numberOr(rendererDuration, state.handles[clipName]?.duration ?? 0);\n },\n subscribe: (listener: ClipEventListener) => {\n const clipListeners = listeners.get(clipName) ?? new Set<ClipEventListener>();\n clipListeners.add(listener);\n listeners.set(clipName, clipListeners);\n return () => {\n clipListeners.delete(listener);\n };\n },\n finished,\n };\n };\n\n const acceptClipEvent = (event: ClipEvent | Record<string, unknown>): boolean => {\n const eventRecord: Record<string, unknown> = isRecord(event)\n ? event as Record<string, unknown>\n : {};\n const clipName = keyToString(eventRecord.clipName ?? eventRecord.name);\n if (!clipName) return true;\n\n const eventType = keyToString(eventRecord.type ?? eventRecord.event);\n const currentTime = numberOr(\n eventRecord.currentTime,\n numberOr(eventRecord.time, state.handles[clipName]?.time ?? 0)\n );\n\n if (['time', 'progress', 'frame', 'keyframe', 'seek', 'loop'].includes(eventType)) {\n updateHandle(clipName, (handle) => ({ ...handle, time: currentTime }));\n } else if (eventType === 'paused') {\n updateHandle(clipName, (handle) => ({ ...handle, status: 'paused' }));\n } else if (['resumed', 'started', 'played'].includes(eventType)) {\n updateHandle(clipName, (handle) => ({ ...handle, status: 'playing' }));\n } else if (['completed', 'finished'].includes(eventType)) {\n updateHandle(clipName, (handle) => ({\n ...handle,\n status: 'completed',\n time: handle.duration,\n }));\n resolveFinished(clipName);\n } else if (['stopped', 'removed'].includes(eventType)) {\n updateHandle(clipName, (handle) => ({ ...handle, status: 'stopped' }));\n resolveFinished(clipName);\n }\n\n state.eventCount += 1;\n state.lastEvent = { ...eventRecord, timestamp: nowMs() };\n notifyListeners(clipName, event as ClipEvent);\n emitState(renderer, state);\n return true;\n };\n\n const buildClip = (\n clipNameInput: string,\n curvesInput: CurvesMap,\n optionsInput?: ClipOptions\n ): ClipHandle | null => {\n const clipName = keyToString(clipNameInput);\n if (!clipName) return null;\n\n const curves = normalizeCurves(curvesInput);\n const options = normalizeOptions(optionsInput);\n const connectorResult = callFirst(renderer, ['buildClip', 'playClip'], clipName, curves, options);\n if (connectorResult == null || connectorResult === false) {\n return null;\n }\n\n const result = isRecord(connectorResult) ? connectorResult : {};\n const duration = calculateDuration(curves, result.duration);\n const handleState: RuntimeHandleState = {\n clipName,\n actionId: keyToString(result.actionId ?? result.id) || makeActionId(clipName),\n duration,\n time: numberOr(result.time, options.startTime),\n weight: options.weight,\n rate: options.rate,\n loopMode: options.loopMode,\n loop: options.loop,\n repeatCount: options.repeatCount,\n reverse: options.reverse,\n source: options.source,\n status: 'playing',\n createdAt: nowMs(),\n updatedAt: nowMs(),\n };\n\n upsertHandle(handleState);\n emitCommand(renderer, 'buildClip', clipName, {\n actionId: handleState.actionId,\n duration: handleState.duration,\n options,\n });\n emitState(renderer, state);\n return makeHandle(clipName);\n };\n\n return {\n snapshot: () => snapshotState(state),\n buildClip,\n playSnippet: (clipName, curves, options) => (\n buildClip(clipName, curves, { ...options, source: options?.source ?? 'snippet' })\n ),\n acceptClipEvent,\n cleanupSnippet: (clipNameInput) => {\n const clipName = keyToString(clipNameInput);\n if (!clipName) return false;\n removeHandle(clipName);\n emitCommand(renderer, 'cleanupSnippet', clipName);\n callFirst(renderer, ['cleanupSnippet', 'removeClip'], clipName);\n emitState(renderer, state);\n return true;\n },\n updateClipParams: (clipNameInput, params) => {\n const clipName = keyToString(clipNameInput);\n if (!clipName) return false;\n const source = isRecord(params) ? params : {};\n\n updateHandle(clipName, (handle) => ({\n ...handle,\n weight: finiteNumber(source.weight) ? Math.max(0, source.weight) : handle.weight,\n rate: finiteNumber(source.rate) ? Math.max(0, source.rate) : handle.rate,\n loopMode: typeof source.loopMode === 'string' && LOOP_MODES.has(source.loopMode as LoopMode)\n ? source.loopMode as LoopMode\n : handle.loopMode,\n loop: typeof source.loop === 'boolean' ? source.loop : handle.loop,\n repeatCount: finiteNumber(source.repeatCount) ? source.repeatCount : handle.repeatCount,\n reverse: typeof source.reverse === 'boolean' ? source.reverse : handle.reverse,\n }));\n emitCommand(renderer, 'updateClipParams', clipName, { params: source });\n const result = callFirst(renderer, ['updateClipParams'], clipName, source);\n emitState(renderer, state);\n return result === false ? false : true;\n },\n };\n}\n\nexport function installEmbody(\n target: Record<string, unknown> = globalThis as unknown as Record<string, unknown>\n): { createAnimationRuntime: typeof createAnimationRuntime } {\n target.createAnimationRuntime = createAnimationRuntime;\n return { createAnimationRuntime };\n}\n"]}
|
package/dist/cljs.d.ts
ADDED
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import type { EmbodyAnimationRuntime, EmbodyAnimationRuntimeConnector } from './core/types';
|
|
2
|
+
export declare function createAnimationRuntime(config?: Record<string, unknown> | null, connector?: EmbodyAnimationRuntimeConnector | null): EmbodyAnimationRuntime;
|
|
3
|
+
export declare function installEmbody(target?: Record<string, unknown>): {
|
|
4
|
+
createAnimationRuntime: typeof createAnimationRuntime;
|
|
5
|
+
};
|
package/dist/cljs.js
ADDED
|
@@ -0,0 +1,359 @@
|
|
|
1
|
+
// src/cljs.ts
|
|
2
|
+
var LOOP_MODES = /* @__PURE__ */ new Set(["once", "repeat", "pingpong"]);
|
|
3
|
+
function nowMs() {
|
|
4
|
+
return Date.now();
|
|
5
|
+
}
|
|
6
|
+
function isRecord(value) {
|
|
7
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
8
|
+
}
|
|
9
|
+
function finiteNumber(value) {
|
|
10
|
+
return typeof value === "number" && Number.isFinite(value);
|
|
11
|
+
}
|
|
12
|
+
function numberOr(value, fallback) {
|
|
13
|
+
return finiteNumber(value) ? value : fallback;
|
|
14
|
+
}
|
|
15
|
+
function clamp(low, high, value) {
|
|
16
|
+
const next = numberOr(value, low);
|
|
17
|
+
return Math.min(high, Math.max(low, next));
|
|
18
|
+
}
|
|
19
|
+
function keyToString(value) {
|
|
20
|
+
if (typeof value === "string") return value;
|
|
21
|
+
if (typeof value === "number") return String(value);
|
|
22
|
+
if (typeof value === "symbol") return value.description ?? "";
|
|
23
|
+
return "";
|
|
24
|
+
}
|
|
25
|
+
function getConnectorFunction(connector, name) {
|
|
26
|
+
const candidate = connector[name];
|
|
27
|
+
return typeof candidate === "function" ? candidate : null;
|
|
28
|
+
}
|
|
29
|
+
function callFirst(connector, names, ...args) {
|
|
30
|
+
for (const name of names) {
|
|
31
|
+
const callback = getConnectorFunction(connector, name);
|
|
32
|
+
if (callback) {
|
|
33
|
+
return callback(...args);
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
return void 0;
|
|
37
|
+
}
|
|
38
|
+
function normalizePoint(point) {
|
|
39
|
+
const source = isRecord(point) ? point : {};
|
|
40
|
+
return {
|
|
41
|
+
time: numberOr(source.time ?? source.t, 0),
|
|
42
|
+
intensity: numberOr(source.intensity ?? source.v, 0),
|
|
43
|
+
inherit: Boolean(source.inherit)
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
function normalizeCurves(curves) {
|
|
47
|
+
if (!isRecord(curves)) {
|
|
48
|
+
return {};
|
|
49
|
+
}
|
|
50
|
+
return Object.fromEntries(
|
|
51
|
+
Object.entries(curves).map(([curveId, points]) => [
|
|
52
|
+
keyToString(curveId),
|
|
53
|
+
(Array.isArray(points) ? points : []).map(normalizePoint).sort((a, b) => a.time - b.time)
|
|
54
|
+
])
|
|
55
|
+
);
|
|
56
|
+
}
|
|
57
|
+
function calculateDuration(curves, fallback) {
|
|
58
|
+
return Object.values(curves).reduce((duration, points) => {
|
|
59
|
+
const last = points[points.length - 1];
|
|
60
|
+
return Math.max(duration, numberOr(last?.time, duration));
|
|
61
|
+
}, numberOr(fallback, 0));
|
|
62
|
+
}
|
|
63
|
+
function normalizeLoopMode(options) {
|
|
64
|
+
const mode = options.loopMode ?? options.mixerLoopMode;
|
|
65
|
+
if (typeof mode === "string" && LOOP_MODES.has(mode)) {
|
|
66
|
+
return mode;
|
|
67
|
+
}
|
|
68
|
+
return options.loop === false ? "once" : "repeat";
|
|
69
|
+
}
|
|
70
|
+
function normalizeOptions(options) {
|
|
71
|
+
const source = isRecord(options) ? options : {};
|
|
72
|
+
const loopMode = normalizeLoopMode(source);
|
|
73
|
+
const rate = source.playbackRate ?? source.rate ?? source.speed;
|
|
74
|
+
const weight = source.weight ?? source.intensity ?? source.mixerWeight;
|
|
75
|
+
return {
|
|
76
|
+
...source,
|
|
77
|
+
weight: Math.max(0, numberOr(weight, 1)),
|
|
78
|
+
rate: Math.max(0, numberOr(rate, 1)),
|
|
79
|
+
loopMode,
|
|
80
|
+
loop: loopMode !== "once",
|
|
81
|
+
repeatCount: finiteNumber(source.repeatCount) ? source.repeatCount : void 0,
|
|
82
|
+
reverse: Boolean(source.reverse),
|
|
83
|
+
source: keyToString(source.source) || "clip",
|
|
84
|
+
startTime: Math.max(0, numberOr(source.startTime, 0)),
|
|
85
|
+
balance: clamp(-1, 1, source.balance),
|
|
86
|
+
jawScale: Math.max(0, numberOr(source.jawScale, 1)),
|
|
87
|
+
intensityScale: Math.max(0, numberOr(source.intensityScale, 1))
|
|
88
|
+
};
|
|
89
|
+
}
|
|
90
|
+
function makeActionId(clipName) {
|
|
91
|
+
return `${clipName}#${nowMs()}-${Math.floor(Math.random() * 1e6)}`;
|
|
92
|
+
}
|
|
93
|
+
function emitCommand(connector, op, clipName, payload = {}) {
|
|
94
|
+
const command = {
|
|
95
|
+
type: "clipCommand",
|
|
96
|
+
op,
|
|
97
|
+
clipName,
|
|
98
|
+
timestamp: nowMs(),
|
|
99
|
+
...payload
|
|
100
|
+
};
|
|
101
|
+
connector.onCommand?.(command);
|
|
102
|
+
return command;
|
|
103
|
+
}
|
|
104
|
+
function emitState(connector, state) {
|
|
105
|
+
connector.onState?.(snapshotState(state));
|
|
106
|
+
}
|
|
107
|
+
function snapshotState(state) {
|
|
108
|
+
return {
|
|
109
|
+
handles: Object.fromEntries(
|
|
110
|
+
Object.entries(state.handles).map(([clipName, handle]) => [clipName, { ...handle }])
|
|
111
|
+
),
|
|
112
|
+
order: [...state.order],
|
|
113
|
+
eventCount: state.eventCount,
|
|
114
|
+
lastEvent: state.lastEvent ? { ...state.lastEvent } : null,
|
|
115
|
+
lastUpdatedTime: state.lastUpdatedTime,
|
|
116
|
+
config: { ...state.config }
|
|
117
|
+
};
|
|
118
|
+
}
|
|
119
|
+
function createAnimationRuntime(config = null, connector = null) {
|
|
120
|
+
const renderer = connector ?? {};
|
|
121
|
+
const state = {
|
|
122
|
+
handles: {},
|
|
123
|
+
order: [],
|
|
124
|
+
eventCount: 0,
|
|
125
|
+
lastEvent: null,
|
|
126
|
+
lastUpdatedTime: null,
|
|
127
|
+
config: isRecord(config) ? { ...config } : {}
|
|
128
|
+
};
|
|
129
|
+
const listeners = /* @__PURE__ */ new Map();
|
|
130
|
+
const finishers = /* @__PURE__ */ new Map();
|
|
131
|
+
const upsertHandle = (handle) => {
|
|
132
|
+
state.handles[handle.clipName] = handle;
|
|
133
|
+
if (!state.order.includes(handle.clipName)) {
|
|
134
|
+
state.order.push(handle.clipName);
|
|
135
|
+
}
|
|
136
|
+
state.lastUpdatedTime = nowMs();
|
|
137
|
+
};
|
|
138
|
+
const updateHandle = (clipName, apply) => {
|
|
139
|
+
const current = state.handles[clipName];
|
|
140
|
+
if (!current) return;
|
|
141
|
+
state.handles[clipName] = apply({ ...current, updatedAt: nowMs() });
|
|
142
|
+
state.lastUpdatedTime = nowMs();
|
|
143
|
+
};
|
|
144
|
+
const removeHandle = (clipName) => {
|
|
145
|
+
delete state.handles[clipName];
|
|
146
|
+
state.order = state.order.filter((name) => name !== clipName);
|
|
147
|
+
state.lastUpdatedTime = nowMs();
|
|
148
|
+
};
|
|
149
|
+
const notifyListeners = (clipName, event) => {
|
|
150
|
+
for (const listener of Array.from(listeners.get(clipName) ?? [])) {
|
|
151
|
+
try {
|
|
152
|
+
listener(event);
|
|
153
|
+
} catch (error) {
|
|
154
|
+
console.error("[Embody runtime] clip listener failed", error);
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
};
|
|
158
|
+
const resolveFinished = (clipName) => {
|
|
159
|
+
const resolve = finishers.get(clipName);
|
|
160
|
+
if (resolve) {
|
|
161
|
+
resolve();
|
|
162
|
+
finishers.delete(clipName);
|
|
163
|
+
}
|
|
164
|
+
};
|
|
165
|
+
const makeHandle = (clipName) => {
|
|
166
|
+
const finished = new Promise((resolve) => {
|
|
167
|
+
finishers.set(clipName, resolve);
|
|
168
|
+
});
|
|
169
|
+
return {
|
|
170
|
+
clipName,
|
|
171
|
+
actionId: state.handles[clipName]?.actionId,
|
|
172
|
+
play: () => {
|
|
173
|
+
updateHandle(clipName, (handle) => ({ ...handle, status: "playing" }));
|
|
174
|
+
emitCommand(renderer, "play", clipName);
|
|
175
|
+
callFirst(renderer, ["playClip", "play"], clipName);
|
|
176
|
+
emitState(renderer, state);
|
|
177
|
+
},
|
|
178
|
+
stop: () => {
|
|
179
|
+
updateHandle(clipName, (handle) => ({ ...handle, status: "stopped" }));
|
|
180
|
+
emitCommand(renderer, "stop", clipName);
|
|
181
|
+
callFirst(renderer, ["stopClip", "stop"], clipName);
|
|
182
|
+
resolveFinished(clipName);
|
|
183
|
+
emitState(renderer, state);
|
|
184
|
+
},
|
|
185
|
+
pause: () => {
|
|
186
|
+
updateHandle(clipName, (handle) => ({ ...handle, status: "paused" }));
|
|
187
|
+
emitCommand(renderer, "pause", clipName);
|
|
188
|
+
callFirst(renderer, ["pauseClip", "pause"], clipName);
|
|
189
|
+
emitState(renderer, state);
|
|
190
|
+
},
|
|
191
|
+
resume: () => {
|
|
192
|
+
updateHandle(clipName, (handle) => ({ ...handle, status: "playing" }));
|
|
193
|
+
emitCommand(renderer, "resume", clipName);
|
|
194
|
+
callFirst(renderer, ["resumeClip", "resume"], clipName);
|
|
195
|
+
emitState(renderer, state);
|
|
196
|
+
},
|
|
197
|
+
setWeight: (weight) => {
|
|
198
|
+
const nextWeight = Math.max(0, numberOr(weight, 1));
|
|
199
|
+
updateHandle(clipName, (handle) => ({ ...handle, weight: nextWeight }));
|
|
200
|
+
emitCommand(renderer, "setWeight", clipName, { weight: nextWeight });
|
|
201
|
+
callFirst(renderer, ["setClipWeight", "setWeight"], clipName, nextWeight);
|
|
202
|
+
emitState(renderer, state);
|
|
203
|
+
},
|
|
204
|
+
setPlaybackRate: (rate) => {
|
|
205
|
+
const nextRate = Math.max(0, numberOr(rate, 1));
|
|
206
|
+
updateHandle(clipName, (handle) => ({ ...handle, rate: nextRate }));
|
|
207
|
+
emitCommand(renderer, "setPlaybackRate", clipName, { rate: nextRate });
|
|
208
|
+
callFirst(renderer, ["setClipPlaybackRate", "setPlaybackRate"], clipName, nextRate);
|
|
209
|
+
emitState(renderer, state);
|
|
210
|
+
},
|
|
211
|
+
setLoop: (mode, repeatCount) => {
|
|
212
|
+
const nextMode = LOOP_MODES.has(mode) ? mode : "repeat";
|
|
213
|
+
updateHandle(clipName, (handle) => ({
|
|
214
|
+
...handle,
|
|
215
|
+
loopMode: nextMode,
|
|
216
|
+
loop: nextMode !== "once",
|
|
217
|
+
repeatCount
|
|
218
|
+
}));
|
|
219
|
+
emitCommand(renderer, "setLoop", clipName, { loopMode: nextMode, repeatCount });
|
|
220
|
+
callFirst(renderer, ["setClipLoop", "setLoop"], clipName, nextMode, repeatCount);
|
|
221
|
+
emitState(renderer, state);
|
|
222
|
+
},
|
|
223
|
+
setTime: (time) => {
|
|
224
|
+
const duration = state.handles[clipName]?.duration ?? 0;
|
|
225
|
+
const nextTime = clamp(0, duration, time);
|
|
226
|
+
updateHandle(clipName, (handle) => ({ ...handle, time: nextTime }));
|
|
227
|
+
emitCommand(renderer, "setTime", clipName, { time: nextTime });
|
|
228
|
+
callFirst(renderer, ["setClipTime", "setTime"], clipName, nextTime);
|
|
229
|
+
emitState(renderer, state);
|
|
230
|
+
},
|
|
231
|
+
getTime: () => {
|
|
232
|
+
const rendererTime = callFirst(renderer, ["getClipTime", "getTime"], clipName);
|
|
233
|
+
return numberOr(rendererTime, state.handles[clipName]?.time ?? 0);
|
|
234
|
+
},
|
|
235
|
+
getDuration: () => {
|
|
236
|
+
const rendererDuration = callFirst(renderer, ["getClipDuration", "getDuration"], clipName);
|
|
237
|
+
return numberOr(rendererDuration, state.handles[clipName]?.duration ?? 0);
|
|
238
|
+
},
|
|
239
|
+
subscribe: (listener) => {
|
|
240
|
+
const clipListeners = listeners.get(clipName) ?? /* @__PURE__ */ new Set();
|
|
241
|
+
clipListeners.add(listener);
|
|
242
|
+
listeners.set(clipName, clipListeners);
|
|
243
|
+
return () => {
|
|
244
|
+
clipListeners.delete(listener);
|
|
245
|
+
};
|
|
246
|
+
},
|
|
247
|
+
finished
|
|
248
|
+
};
|
|
249
|
+
};
|
|
250
|
+
const acceptClipEvent = (event) => {
|
|
251
|
+
const eventRecord = isRecord(event) ? event : {};
|
|
252
|
+
const clipName = keyToString(eventRecord.clipName ?? eventRecord.name);
|
|
253
|
+
if (!clipName) return true;
|
|
254
|
+
const eventType = keyToString(eventRecord.type ?? eventRecord.event);
|
|
255
|
+
const currentTime = numberOr(
|
|
256
|
+
eventRecord.currentTime,
|
|
257
|
+
numberOr(eventRecord.time, state.handles[clipName]?.time ?? 0)
|
|
258
|
+
);
|
|
259
|
+
if (["time", "progress", "frame", "keyframe", "seek", "loop"].includes(eventType)) {
|
|
260
|
+
updateHandle(clipName, (handle) => ({ ...handle, time: currentTime }));
|
|
261
|
+
} else if (eventType === "paused") {
|
|
262
|
+
updateHandle(clipName, (handle) => ({ ...handle, status: "paused" }));
|
|
263
|
+
} else if (["resumed", "started", "played"].includes(eventType)) {
|
|
264
|
+
updateHandle(clipName, (handle) => ({ ...handle, status: "playing" }));
|
|
265
|
+
} else if (["completed", "finished"].includes(eventType)) {
|
|
266
|
+
updateHandle(clipName, (handle) => ({
|
|
267
|
+
...handle,
|
|
268
|
+
status: "completed",
|
|
269
|
+
time: handle.duration
|
|
270
|
+
}));
|
|
271
|
+
resolveFinished(clipName);
|
|
272
|
+
} else if (["stopped", "removed"].includes(eventType)) {
|
|
273
|
+
updateHandle(clipName, (handle) => ({ ...handle, status: "stopped" }));
|
|
274
|
+
resolveFinished(clipName);
|
|
275
|
+
}
|
|
276
|
+
state.eventCount += 1;
|
|
277
|
+
state.lastEvent = { ...eventRecord, timestamp: nowMs() };
|
|
278
|
+
notifyListeners(clipName, event);
|
|
279
|
+
emitState(renderer, state);
|
|
280
|
+
return true;
|
|
281
|
+
};
|
|
282
|
+
const buildClip = (clipNameInput, curvesInput, optionsInput) => {
|
|
283
|
+
const clipName = keyToString(clipNameInput);
|
|
284
|
+
if (!clipName) return null;
|
|
285
|
+
const curves = normalizeCurves(curvesInput);
|
|
286
|
+
const options = normalizeOptions(optionsInput);
|
|
287
|
+
const connectorResult = callFirst(renderer, ["buildClip", "playClip"], clipName, curves, options);
|
|
288
|
+
if (connectorResult == null || connectorResult === false) {
|
|
289
|
+
return null;
|
|
290
|
+
}
|
|
291
|
+
const result = isRecord(connectorResult) ? connectorResult : {};
|
|
292
|
+
const duration = calculateDuration(curves, result.duration);
|
|
293
|
+
const handleState = {
|
|
294
|
+
clipName,
|
|
295
|
+
actionId: keyToString(result.actionId ?? result.id) || makeActionId(clipName),
|
|
296
|
+
duration,
|
|
297
|
+
time: numberOr(result.time, options.startTime),
|
|
298
|
+
weight: options.weight,
|
|
299
|
+
rate: options.rate,
|
|
300
|
+
loopMode: options.loopMode,
|
|
301
|
+
loop: options.loop,
|
|
302
|
+
repeatCount: options.repeatCount,
|
|
303
|
+
reverse: options.reverse,
|
|
304
|
+
source: options.source,
|
|
305
|
+
status: "playing",
|
|
306
|
+
createdAt: nowMs(),
|
|
307
|
+
updatedAt: nowMs()
|
|
308
|
+
};
|
|
309
|
+
upsertHandle(handleState);
|
|
310
|
+
emitCommand(renderer, "buildClip", clipName, {
|
|
311
|
+
actionId: handleState.actionId,
|
|
312
|
+
duration: handleState.duration,
|
|
313
|
+
options
|
|
314
|
+
});
|
|
315
|
+
emitState(renderer, state);
|
|
316
|
+
return makeHandle(clipName);
|
|
317
|
+
};
|
|
318
|
+
return {
|
|
319
|
+
snapshot: () => snapshotState(state),
|
|
320
|
+
buildClip,
|
|
321
|
+
playSnippet: (clipName, curves, options) => buildClip(clipName, curves, { ...options, source: options?.source ?? "snippet" }),
|
|
322
|
+
acceptClipEvent,
|
|
323
|
+
cleanupSnippet: (clipNameInput) => {
|
|
324
|
+
const clipName = keyToString(clipNameInput);
|
|
325
|
+
if (!clipName) return false;
|
|
326
|
+
removeHandle(clipName);
|
|
327
|
+
emitCommand(renderer, "cleanupSnippet", clipName);
|
|
328
|
+
callFirst(renderer, ["cleanupSnippet", "removeClip"], clipName);
|
|
329
|
+
emitState(renderer, state);
|
|
330
|
+
return true;
|
|
331
|
+
},
|
|
332
|
+
updateClipParams: (clipNameInput, params) => {
|
|
333
|
+
const clipName = keyToString(clipNameInput);
|
|
334
|
+
if (!clipName) return false;
|
|
335
|
+
const source = isRecord(params) ? params : {};
|
|
336
|
+
updateHandle(clipName, (handle) => ({
|
|
337
|
+
...handle,
|
|
338
|
+
weight: finiteNumber(source.weight) ? Math.max(0, source.weight) : handle.weight,
|
|
339
|
+
rate: finiteNumber(source.rate) ? Math.max(0, source.rate) : handle.rate,
|
|
340
|
+
loopMode: typeof source.loopMode === "string" && LOOP_MODES.has(source.loopMode) ? source.loopMode : handle.loopMode,
|
|
341
|
+
loop: typeof source.loop === "boolean" ? source.loop : handle.loop,
|
|
342
|
+
repeatCount: finiteNumber(source.repeatCount) ? source.repeatCount : handle.repeatCount,
|
|
343
|
+
reverse: typeof source.reverse === "boolean" ? source.reverse : handle.reverse
|
|
344
|
+
}));
|
|
345
|
+
emitCommand(renderer, "updateClipParams", clipName, { params: source });
|
|
346
|
+
const result = callFirst(renderer, ["updateClipParams"], clipName, source);
|
|
347
|
+
emitState(renderer, state);
|
|
348
|
+
return result === false ? false : true;
|
|
349
|
+
}
|
|
350
|
+
};
|
|
351
|
+
}
|
|
352
|
+
function installEmbody(target = globalThis) {
|
|
353
|
+
target.createAnimationRuntime = createAnimationRuntime;
|
|
354
|
+
return { createAnimationRuntime };
|
|
355
|
+
}
|
|
356
|
+
|
|
357
|
+
export { createAnimationRuntime, installEmbody };
|
|
358
|
+
//# sourceMappingURL=cljs.js.map
|
|
359
|
+
//# sourceMappingURL=cljs.js.map
|
package/dist/cljs.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/cljs.ts"],"names":[],"mappings":"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","file":"cljs.js","sourcesContent":["import type {\n ClipEvent,\n ClipEventListener,\n ClipHandle,\n ClipOptions,\n CurvePoint,\n CurvesMap,\n EmbodyAnimationRuntime,\n EmbodyAnimationRuntimeConnector,\n} from './core/types';\n\ntype LoopMode = 'once' | 'repeat' | 'pingpong';\ntype RuntimeStatus = 'playing' | 'paused' | 'completed' | 'stopped';\n\ntype RuntimeOptions = {\n weight: number;\n rate: number;\n loopMode: LoopMode;\n loop: boolean;\n repeatCount?: number;\n reverse: boolean;\n source: string;\n startTime: number;\n [key: string]: unknown;\n};\n\ntype RuntimeHandleState = {\n clipName: string;\n actionId?: string;\n duration: number;\n time: number;\n weight: number;\n rate: number;\n loopMode: LoopMode;\n loop: boolean;\n repeatCount?: number;\n reverse: boolean;\n source: string;\n status: RuntimeStatus;\n createdAt: number;\n updatedAt: number;\n};\n\ntype RuntimeState = {\n handles: Record<string, RuntimeHandleState>;\n order: string[];\n eventCount: number;\n lastEvent: Record<string, unknown> | null;\n lastUpdatedTime: number | null;\n config: Record<string, unknown>;\n};\n\ntype ConnectorFunction = (...args: unknown[]) => unknown;\n\nconst LOOP_MODES = new Set<LoopMode>(['once', 'repeat', 'pingpong']);\n\nfunction nowMs(): number {\n return Date.now();\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null && !Array.isArray(value);\n}\n\nfunction finiteNumber(value: unknown): value is number {\n return typeof value === 'number' && Number.isFinite(value);\n}\n\nfunction numberOr(value: unknown, fallback: number): number {\n return finiteNumber(value) ? value : fallback;\n}\n\nfunction clamp(low: number, high: number, value: unknown): number {\n const next = numberOr(value, low);\n return Math.min(high, Math.max(low, next));\n}\n\nfunction keyToString(value: unknown): string {\n if (typeof value === 'string') return value;\n if (typeof value === 'number') return String(value);\n if (typeof value === 'symbol') return value.description ?? '';\n return '';\n}\n\nfunction getConnectorFunction(\n connector: EmbodyAnimationRuntimeConnector,\n name: string\n): ConnectorFunction | null {\n const candidate = (connector as Record<string, unknown>)[name];\n return typeof candidate === 'function' ? candidate as ConnectorFunction : null;\n}\n\nfunction callFirst(\n connector: EmbodyAnimationRuntimeConnector,\n names: string[],\n ...args: unknown[]\n): unknown {\n for (const name of names) {\n const callback = getConnectorFunction(connector, name);\n if (callback) {\n return callback(...args);\n }\n }\n return undefined;\n}\n\nfunction normalizePoint(point: unknown): CurvePoint {\n const source = isRecord(point) ? point : {};\n return {\n time: numberOr(source.time ?? source.t, 0),\n intensity: numberOr(source.intensity ?? source.v, 0),\n inherit: Boolean(source.inherit),\n };\n}\n\nfunction normalizeCurves(curves: CurvesMap): CurvesMap {\n if (!isRecord(curves)) {\n return {};\n }\n\n return Object.fromEntries(\n Object.entries(curves).map(([curveId, points]) => [\n keyToString(curveId),\n (Array.isArray(points) ? points : [])\n .map(normalizePoint)\n .sort((a, b) => a.time - b.time),\n ])\n );\n}\n\nfunction calculateDuration(curves: CurvesMap, fallback: unknown): number {\n return Object.values(curves).reduce((duration, points) => {\n const last = points[points.length - 1];\n return Math.max(duration, numberOr(last?.time, duration));\n }, numberOr(fallback, 0));\n}\n\nfunction normalizeLoopMode(options: Record<string, unknown>): LoopMode {\n const mode = options.loopMode ?? options.mixerLoopMode;\n if (typeof mode === 'string' && LOOP_MODES.has(mode as LoopMode)) {\n return mode as LoopMode;\n }\n return options.loop === false ? 'once' : 'repeat';\n}\n\nfunction normalizeOptions(options?: ClipOptions): RuntimeOptions {\n const source = isRecord(options) ? options : {};\n const loopMode = normalizeLoopMode(source);\n const rate = source.playbackRate ?? source.rate ?? source.speed;\n const weight = source.weight ?? source.intensity ?? source.mixerWeight;\n\n return {\n ...source,\n weight: Math.max(0, numberOr(weight, 1)),\n rate: Math.max(0, numberOr(rate, 1)),\n loopMode,\n loop: loopMode !== 'once',\n repeatCount: finiteNumber(source.repeatCount) ? source.repeatCount : undefined,\n reverse: Boolean(source.reverse),\n source: keyToString(source.source) || 'clip',\n startTime: Math.max(0, numberOr(source.startTime, 0)),\n balance: clamp(-1, 1, source.balance),\n jawScale: Math.max(0, numberOr(source.jawScale, 1)),\n intensityScale: Math.max(0, numberOr(source.intensityScale, 1)),\n };\n}\n\nfunction makeActionId(clipName: string): string {\n return `${clipName}#${nowMs()}-${Math.floor(Math.random() * 1_000_000)}`;\n}\n\nfunction emitCommand(\n connector: EmbodyAnimationRuntimeConnector,\n op: string,\n clipName: string,\n payload: Record<string, unknown> = {}\n): Record<string, unknown> {\n const command = {\n type: 'clipCommand',\n op,\n clipName,\n timestamp: nowMs(),\n ...payload,\n };\n connector.onCommand?.(command);\n return command;\n}\n\nfunction emitState(connector: EmbodyAnimationRuntimeConnector, state: RuntimeState): void {\n connector.onState?.(snapshotState(state));\n}\n\nfunction snapshotState(state: RuntimeState): Record<string, unknown> {\n return {\n handles: Object.fromEntries(\n Object.entries(state.handles).map(([clipName, handle]) => [clipName, { ...handle }])\n ),\n order: [...state.order],\n eventCount: state.eventCount,\n lastEvent: state.lastEvent ? { ...state.lastEvent } : null,\n lastUpdatedTime: state.lastUpdatedTime,\n config: { ...state.config },\n };\n}\n\nexport function createAnimationRuntime(\n config: Record<string, unknown> | null = null,\n connector: EmbodyAnimationRuntimeConnector | null = null\n): EmbodyAnimationRuntime {\n const renderer = connector ?? {};\n const state: RuntimeState = {\n handles: {},\n order: [],\n eventCount: 0,\n lastEvent: null,\n lastUpdatedTime: null,\n config: isRecord(config) ? { ...config } : {},\n };\n const listeners = new Map<string, Set<ClipEventListener>>();\n const finishers = new Map<string, () => void>();\n\n const upsertHandle = (handle: RuntimeHandleState) => {\n state.handles[handle.clipName] = handle;\n if (!state.order.includes(handle.clipName)) {\n state.order.push(handle.clipName);\n }\n state.lastUpdatedTime = nowMs();\n };\n\n const updateHandle = (\n clipName: string,\n apply: (handle: RuntimeHandleState) => RuntimeHandleState\n ) => {\n const current = state.handles[clipName];\n if (!current) return;\n state.handles[clipName] = apply({ ...current, updatedAt: nowMs() });\n state.lastUpdatedTime = nowMs();\n };\n\n const removeHandle = (clipName: string) => {\n delete state.handles[clipName];\n state.order = state.order.filter((name) => name !== clipName);\n state.lastUpdatedTime = nowMs();\n };\n\n const notifyListeners = (clipName: string, event: ClipEvent) => {\n for (const listener of Array.from(listeners.get(clipName) ?? [])) {\n try {\n listener(event);\n } catch (error) {\n console.error('[Embody runtime] clip listener failed', error);\n }\n }\n };\n\n const resolveFinished = (clipName: string) => {\n const resolve = finishers.get(clipName);\n if (resolve) {\n resolve();\n finishers.delete(clipName);\n }\n };\n\n const makeHandle = (clipName: string): ClipHandle => {\n const finished = new Promise<void>((resolve) => {\n finishers.set(clipName, resolve);\n });\n\n return {\n clipName,\n actionId: state.handles[clipName]?.actionId,\n play: () => {\n updateHandle(clipName, (handle) => ({ ...handle, status: 'playing' }));\n emitCommand(renderer, 'play', clipName);\n callFirst(renderer, ['playClip', 'play'], clipName);\n emitState(renderer, state);\n },\n stop: () => {\n updateHandle(clipName, (handle) => ({ ...handle, status: 'stopped' }));\n emitCommand(renderer, 'stop', clipName);\n callFirst(renderer, ['stopClip', 'stop'], clipName);\n resolveFinished(clipName);\n emitState(renderer, state);\n },\n pause: () => {\n updateHandle(clipName, (handle) => ({ ...handle, status: 'paused' }));\n emitCommand(renderer, 'pause', clipName);\n callFirst(renderer, ['pauseClip', 'pause'], clipName);\n emitState(renderer, state);\n },\n resume: () => {\n updateHandle(clipName, (handle) => ({ ...handle, status: 'playing' }));\n emitCommand(renderer, 'resume', clipName);\n callFirst(renderer, ['resumeClip', 'resume'], clipName);\n emitState(renderer, state);\n },\n setWeight: (weight: number) => {\n const nextWeight = Math.max(0, numberOr(weight, 1));\n updateHandle(clipName, (handle) => ({ ...handle, weight: nextWeight }));\n emitCommand(renderer, 'setWeight', clipName, { weight: nextWeight });\n callFirst(renderer, ['setClipWeight', 'setWeight'], clipName, nextWeight);\n emitState(renderer, state);\n },\n setPlaybackRate: (rate: number) => {\n const nextRate = Math.max(0, numberOr(rate, 1));\n updateHandle(clipName, (handle) => ({ ...handle, rate: nextRate }));\n emitCommand(renderer, 'setPlaybackRate', clipName, { rate: nextRate });\n callFirst(renderer, ['setClipPlaybackRate', 'setPlaybackRate'], clipName, nextRate);\n emitState(renderer, state);\n },\n setLoop: (mode: LoopMode, repeatCount?: number) => {\n const nextMode = LOOP_MODES.has(mode) ? mode : 'repeat';\n updateHandle(clipName, (handle) => ({\n ...handle,\n loopMode: nextMode,\n loop: nextMode !== 'once',\n repeatCount,\n }));\n emitCommand(renderer, 'setLoop', clipName, { loopMode: nextMode, repeatCount });\n callFirst(renderer, ['setClipLoop', 'setLoop'], clipName, nextMode, repeatCount);\n emitState(renderer, state);\n },\n setTime: (time: number) => {\n const duration = state.handles[clipName]?.duration ?? 0;\n const nextTime = clamp(0, duration, time);\n updateHandle(clipName, (handle) => ({ ...handle, time: nextTime }));\n emitCommand(renderer, 'setTime', clipName, { time: nextTime });\n callFirst(renderer, ['setClipTime', 'setTime'], clipName, nextTime);\n emitState(renderer, state);\n },\n getTime: () => {\n const rendererTime = callFirst(renderer, ['getClipTime', 'getTime'], clipName);\n return numberOr(rendererTime, state.handles[clipName]?.time ?? 0);\n },\n getDuration: () => {\n const rendererDuration = callFirst(renderer, ['getClipDuration', 'getDuration'], clipName);\n return numberOr(rendererDuration, state.handles[clipName]?.duration ?? 0);\n },\n subscribe: (listener: ClipEventListener) => {\n const clipListeners = listeners.get(clipName) ?? new Set<ClipEventListener>();\n clipListeners.add(listener);\n listeners.set(clipName, clipListeners);\n return () => {\n clipListeners.delete(listener);\n };\n },\n finished,\n };\n };\n\n const acceptClipEvent = (event: ClipEvent | Record<string, unknown>): boolean => {\n const eventRecord: Record<string, unknown> = isRecord(event)\n ? event as Record<string, unknown>\n : {};\n const clipName = keyToString(eventRecord.clipName ?? eventRecord.name);\n if (!clipName) return true;\n\n const eventType = keyToString(eventRecord.type ?? eventRecord.event);\n const currentTime = numberOr(\n eventRecord.currentTime,\n numberOr(eventRecord.time, state.handles[clipName]?.time ?? 0)\n );\n\n if (['time', 'progress', 'frame', 'keyframe', 'seek', 'loop'].includes(eventType)) {\n updateHandle(clipName, (handle) => ({ ...handle, time: currentTime }));\n } else if (eventType === 'paused') {\n updateHandle(clipName, (handle) => ({ ...handle, status: 'paused' }));\n } else if (['resumed', 'started', 'played'].includes(eventType)) {\n updateHandle(clipName, (handle) => ({ ...handle, status: 'playing' }));\n } else if (['completed', 'finished'].includes(eventType)) {\n updateHandle(clipName, (handle) => ({\n ...handle,\n status: 'completed',\n time: handle.duration,\n }));\n resolveFinished(clipName);\n } else if (['stopped', 'removed'].includes(eventType)) {\n updateHandle(clipName, (handle) => ({ ...handle, status: 'stopped' }));\n resolveFinished(clipName);\n }\n\n state.eventCount += 1;\n state.lastEvent = { ...eventRecord, timestamp: nowMs() };\n notifyListeners(clipName, event as ClipEvent);\n emitState(renderer, state);\n return true;\n };\n\n const buildClip = (\n clipNameInput: string,\n curvesInput: CurvesMap,\n optionsInput?: ClipOptions\n ): ClipHandle | null => {\n const clipName = keyToString(clipNameInput);\n if (!clipName) return null;\n\n const curves = normalizeCurves(curvesInput);\n const options = normalizeOptions(optionsInput);\n const connectorResult = callFirst(renderer, ['buildClip', 'playClip'], clipName, curves, options);\n if (connectorResult == null || connectorResult === false) {\n return null;\n }\n\n const result = isRecord(connectorResult) ? connectorResult : {};\n const duration = calculateDuration(curves, result.duration);\n const handleState: RuntimeHandleState = {\n clipName,\n actionId: keyToString(result.actionId ?? result.id) || makeActionId(clipName),\n duration,\n time: numberOr(result.time, options.startTime),\n weight: options.weight,\n rate: options.rate,\n loopMode: options.loopMode,\n loop: options.loop,\n repeatCount: options.repeatCount,\n reverse: options.reverse,\n source: options.source,\n status: 'playing',\n createdAt: nowMs(),\n updatedAt: nowMs(),\n };\n\n upsertHandle(handleState);\n emitCommand(renderer, 'buildClip', clipName, {\n actionId: handleState.actionId,\n duration: handleState.duration,\n options,\n });\n emitState(renderer, state);\n return makeHandle(clipName);\n };\n\n return {\n snapshot: () => snapshotState(state),\n buildClip,\n playSnippet: (clipName, curves, options) => (\n buildClip(clipName, curves, { ...options, source: options?.source ?? 'snippet' })\n ),\n acceptClipEvent,\n cleanupSnippet: (clipNameInput) => {\n const clipName = keyToString(clipNameInput);\n if (!clipName) return false;\n removeHandle(clipName);\n emitCommand(renderer, 'cleanupSnippet', clipName);\n callFirst(renderer, ['cleanupSnippet', 'removeClip'], clipName);\n emitState(renderer, state);\n return true;\n },\n updateClipParams: (clipNameInput, params) => {\n const clipName = keyToString(clipNameInput);\n if (!clipName) return false;\n const source = isRecord(params) ? params : {};\n\n updateHandle(clipName, (handle) => ({\n ...handle,\n weight: finiteNumber(source.weight) ? Math.max(0, source.weight) : handle.weight,\n rate: finiteNumber(source.rate) ? Math.max(0, source.rate) : handle.rate,\n loopMode: typeof source.loopMode === 'string' && LOOP_MODES.has(source.loopMode as LoopMode)\n ? source.loopMode as LoopMode\n : handle.loopMode,\n loop: typeof source.loop === 'boolean' ? source.loop : handle.loop,\n repeatCount: finiteNumber(source.repeatCount) ? source.repeatCount : handle.repeatCount,\n reverse: typeof source.reverse === 'boolean' ? source.reverse : handle.reverse,\n }));\n emitCommand(renderer, 'updateClipParams', clipName, { params: source });\n const result = callFirst(renderer, ['updateClipParams'], clipName, source);\n emitState(renderer, state);\n return result === false ? false : true;\n },\n };\n}\n\nexport function installEmbody(\n target: Record<string, unknown> = globalThis as unknown as Record<string, unknown>\n): { createAnimationRuntime: typeof createAnimationRuntime } {\n target.createAnimationRuntime = createAnimationRuntime;\n return { createAnimationRuntime };\n}\n"]}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import type { ChannelId, ClipChannelIR, ClipIR, ClipInterpolation, ClipTrackTarget, ClipTrackValueType, NumericArray, TrackId } from './contracts';
|
|
2
|
+
import type { CurvePoint } from './types';
|
|
3
|
+
import type { EmbodyCoreWasmModule } from '../wasmTypes';
|
|
4
|
+
export interface TsClipCompilerKeyframe {
|
|
5
|
+
readonly time: number;
|
|
6
|
+
readonly value: number | readonly number[];
|
|
7
|
+
}
|
|
8
|
+
export interface TsClipCompilerTrackInput {
|
|
9
|
+
readonly id?: TrackId;
|
|
10
|
+
readonly channelId?: ChannelId;
|
|
11
|
+
readonly target: ClipTrackTarget;
|
|
12
|
+
readonly valueType: ClipTrackValueType;
|
|
13
|
+
readonly keyframes: readonly TsClipCompilerKeyframe[];
|
|
14
|
+
readonly interpolation?: ClipInterpolation;
|
|
15
|
+
}
|
|
16
|
+
export interface TsClipCompilerInput {
|
|
17
|
+
readonly id?: string;
|
|
18
|
+
readonly name: string;
|
|
19
|
+
readonly durationSeconds?: number;
|
|
20
|
+
readonly channels?: readonly ClipChannelIR[];
|
|
21
|
+
readonly tracks: readonly TsClipCompilerTrackInput[];
|
|
22
|
+
readonly metadata?: Readonly<Record<string, unknown>>;
|
|
23
|
+
}
|
|
24
|
+
export interface TsClipCurveTarget {
|
|
25
|
+
readonly channelId?: ChannelId;
|
|
26
|
+
readonly target: ClipTrackTarget;
|
|
27
|
+
readonly valueType?: Extract<ClipTrackValueType, 'scalar'>;
|
|
28
|
+
readonly scale?: number;
|
|
29
|
+
readonly interpolation?: ClipInterpolation;
|
|
30
|
+
}
|
|
31
|
+
export interface TsClipCurvesInput {
|
|
32
|
+
readonly id?: string;
|
|
33
|
+
readonly name: string;
|
|
34
|
+
readonly curves: Record<string, readonly CurvePoint[]>;
|
|
35
|
+
readonly targets: Record<string, TsClipCurveTarget | readonly TsClipCurveTarget[]>;
|
|
36
|
+
readonly channels?: readonly ClipChannelIR[];
|
|
37
|
+
readonly durationSeconds?: number;
|
|
38
|
+
readonly intensityScale?: number;
|
|
39
|
+
readonly metadata?: Readonly<Record<string, unknown>>;
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Thin host facade over the Rust clip compiler (`compile_clip` /
|
|
43
|
+
* `compile_clip_curves`). Callers pass the Wasm module from `initEmbodyCore()`.
|
|
44
|
+
*/
|
|
45
|
+
export declare class TsClipCompiler {
|
|
46
|
+
private readonly core;
|
|
47
|
+
constructor(core: EmbodyCoreWasmModule);
|
|
48
|
+
compile(input: TsClipCompilerInput): ClipIR;
|
|
49
|
+
compileCurves(input: TsClipCurvesInput): ClipIR;
|
|
50
|
+
}
|
|
51
|
+
export declare function numericArrayToNumbers(values: NumericArray): number[];
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import type { FrameDelta, ModelDescriptor } from './contracts';
|
|
2
|
+
import type { Profile } from '../mappings/types';
|
|
3
|
+
export interface TsRuntimeCoreOptions {
|
|
4
|
+
readonly profile: Profile;
|
|
5
|
+
readonly model: ModelDescriptor;
|
|
6
|
+
}
|
|
7
|
+
export declare class TsRuntimeCore {
|
|
8
|
+
private profile;
|
|
9
|
+
private model;
|
|
10
|
+
private auValues;
|
|
11
|
+
private auBalances;
|
|
12
|
+
private visemeValues;
|
|
13
|
+
private visemeJawScales;
|
|
14
|
+
private mixWeights;
|
|
15
|
+
constructor(options: TsRuntimeCoreOptions);
|
|
16
|
+
setProfile(profile: Profile): void;
|
|
17
|
+
setModelDescriptor(model: ModelDescriptor): void;
|
|
18
|
+
setAU(id: number, value: number, balance?: number): void;
|
|
19
|
+
getAU(id: number): number;
|
|
20
|
+
setContinuum(negAU: number, posAU: number, continuumValue: number, balance?: number): void;
|
|
21
|
+
setViseme(visemeIndex: number, value: number, jawScale?: number): void;
|
|
22
|
+
setVisemeById(slotId: string, value: number, jawScale?: number): void;
|
|
23
|
+
setAUMixWeight(id: number, weight: number): void;
|
|
24
|
+
evaluateFrameDelta(deltaSeconds?: number): FrameDelta;
|
|
25
|
+
private collectAUWrites;
|
|
26
|
+
private collectVisemeWrites;
|
|
27
|
+
private collectBoneWrites;
|
|
28
|
+
private computeRotationState;
|
|
29
|
+
private evaluateCompositeTransform;
|
|
30
|
+
private computeTranslations;
|
|
31
|
+
private addMorphWrites;
|
|
32
|
+
private resolveMorphTargets;
|
|
33
|
+
private findBoneDescriptor;
|
|
34
|
+
private findAutoVisemeJawBinding;
|
|
35
|
+
private getActiveVisemeJawAmount;
|
|
36
|
+
private getCompositeAxisValueForNode;
|
|
37
|
+
private getEffectiveBoneAUValue;
|
|
38
|
+
private getAUMixWeight;
|
|
39
|
+
private isMixedAU;
|
|
40
|
+
}
|