@lovelace_lol/embody 0.0.6 → 0.0.8
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/README.md +541 -2394
- package/dist/index.d.ts +2 -100
- package/dist/index.js +7714 -12951
- package/dist/index.js.map +1 -1
- package/dist/three/annotations/DOMControls.d.ts +73 -0
- package/dist/three/annotations/DPthree.d.ts +113 -0
- package/dist/three/annotations/DPthree3DMarkers.d.ts +319 -0
- package/dist/three/annotations/DPthreeCameraController.d.ts +414 -0
- package/dist/three/annotations/DPthreeHTMLMarkers.d.ts +131 -0
- package/dist/three/annotations/DPthreeMarkers.d.ts +52 -0
- package/dist/three/annotations/adapter.d.ts +157 -0
- package/dist/three/annotations/animationFrameTaskScheduler.d.ts +18 -0
- package/dist/three/annotations/annotationAnchorModel.d.ts +16 -0
- package/dist/three/annotations/annotationCameraCore.d.ts +5 -0
- package/dist/three/annotations/boneResolutionProfile.d.ts +7 -0
- package/dist/three/annotations/index.d.ts +20 -0
- package/dist/three/annotations/loadFrame.d.ts +2 -0
- package/dist/three/annotations/markerSurfaceRaycast.d.ts +11 -0
- package/dist/three/annotations/markerVisibilityLifecycle.d.ts +21 -0
- package/dist/three/annotations/modelRenderPreparation.d.ts +6 -0
- package/dist/three/annotations/runtimeAnnotationPreview.d.ts +15 -0
- package/dist/three/annotations/runtimeAnnotationPreviewSide.d.ts +10 -0
- package/dist/three/annotations/runtimeAnnotationSidePreview.d.ts +5 -0
- package/dist/three/annotations/types.d.ts +262 -0
- package/dist/three/gaze.d.ts +122 -0
- package/dist/three/index.d.ts +147 -0
- package/dist/three/model.d.ts +31 -0
- package/dist/three/modelSkinning.d.ts +3 -0
- package/dist/three/reference-pose.d.ts +73 -0
- package/dist/three/scene.d.ts +253 -0
- package/dist/three/sceneRenderingBinding.d.ts +22 -0
- package/dist/three.js +7696 -8936
- package/dist/three.js.map +1 -1
- package/dist/wasm/README.md +551 -62
- package/dist/wasm/auto.d.ts +1 -0
- package/dist/wasm/embody_wasm.d.ts +388 -52
- package/dist/wasm/embody_wasm.js +1514 -119
- package/dist/wasm/embody_wasm_bg.wasm +0 -0
- package/dist/wasm/embody_wasm_bg.wasm.d.ts +115 -40
- package/dist/wasm/index.d.ts +126 -0
- package/dist/wasm.d.ts +1 -43
- package/dist/wasm.js +1043 -239
- package/dist/wasm.js.map +1 -1
- package/package.json +34 -39
- package/service-worker/character-asset-service-worker.js +295 -0
- package/dist/authoring/boneAuthoring.d.ts +0 -132
- package/dist/camera/annotationCameraAngles.d.ts +0 -28
- package/dist/camera/cameraRelativeGaze.d.ts +0 -15
- package/dist/camera/rustAnnotationCameraCore.d.ts +0 -136
- package/dist/cljs.cjs +0 -362
- package/dist/cljs.cjs.map +0 -1
- package/dist/cljs.d.ts +0 -5
- package/dist/cljs.js +0 -359
- package/dist/cljs.js.map +0 -1
- package/dist/core/TsClipCompiler.d.ts +0 -51
- package/dist/core/WasmRuntimeCore.d.ts +0 -41
- package/dist/core/compositeAxis.d.ts +0 -4
- package/dist/core/contracts/abi.d.ts +0 -70
- package/dist/core/contracts/clip.d.ts +0 -44
- package/dist/core/contracts/frame.d.ts +0 -27
- package/dist/core/contracts/host.d.ts +0 -28
- package/dist/core/contracts/ids.d.ts +0 -15
- package/dist/core/contracts/index.d.ts +0 -10
- package/dist/core/contracts/model.d.ts +0 -31
- package/dist/core/contracts/primitives.d.ts +0 -17
- package/dist/core/contracts/skeletonFit.d.ts +0 -41
- package/dist/core/index.d.ts +0 -6
- package/dist/core/types.d.ts +0 -472
- package/dist/core.cjs +0 -343
- package/dist/core.cjs.map +0 -1
- package/dist/core.js +0 -323
- package/dist/core.js.map +0 -1
- package/dist/engines/three/Embody.d.ts +0 -372
- package/dist/engines/three/ThreeAnimationRuntime.d.ts +0 -203
- package/dist/engines/three/ThreeClipAdapter.d.ts +0 -24
- package/dist/engines/three/ThreeFrameApplier.d.ts +0 -68
- package/dist/engines/three/ThreeModelInspector.d.ts +0 -54
- package/dist/engines/three/bakedClipPartitioning.d.ts +0 -16
- package/dist/engines/three/balanceUtils.d.ts +0 -3
- package/dist/engines/three/characterHost.d.ts +0 -80
- package/dist/engines/three/characterScene.d.ts +0 -98
- package/dist/engines/three/hair/HairPhysicsController.d.ts +0 -124
- package/dist/engines/three/index.d.ts +0 -20
- package/dist/engines/three/modelLoader.d.ts +0 -61
- package/dist/engines/three/profileTestScene.d.ts +0 -52
- package/dist/engines/three/types.d.ts +0 -20
- package/dist/hair/appearance.d.ts +0 -29
- package/dist/index.cjs +0 -14871
- package/dist/index.cjs.map +0 -1
- package/dist/interfaces/Animation.d.ts +0 -315
- package/dist/interfaces/EmbodyRuntime.d.ts +0 -90
- package/dist/interfaces/Hair.d.ts +0 -181
- package/dist/interfaces/HairPhysics.d.ts +0 -90
- package/dist/interfaces/index.d.ts +0 -11
- package/dist/mappings/extendPresetWithProfile.d.ts +0 -17
- package/dist/mappings/types.d.ts +0 -309
- package/dist/mappings/visemeSystem.d.ts +0 -26
- package/dist/physics/HairPhysics.d.ts +0 -86
- package/dist/physics/RustHairPhysics.d.ts +0 -18
- package/dist/physics/index.d.ts +0 -6
- package/dist/preset.cjs +0 -2005
- package/dist/preset.cjs.map +0 -1
- package/dist/preset.js +0 -2003
- package/dist/preset.js.map +0 -1
- package/dist/presets/bettaFish.d.ts +0 -328
- package/dist/presets/cc4.d.ts +0 -145
- package/dist/presets/index.d.ts +0 -30
- package/dist/presets/registry.d.ts +0 -57
- package/dist/profiles/resolveProfileConfig.d.ts +0 -36
- package/dist/profiles/rustResolvedProfile.d.ts +0 -31
- package/dist/profiles/types.d.ts +0 -118
- package/dist/regions/normalizeRegionTree.d.ts +0 -6
- package/dist/regions/regionMapping.d.ts +0 -17
- package/dist/regions/types.d.ts +0 -122
- package/dist/skeletonTemplates/humanoidSkeletonTemplates.d.ts +0 -32
- package/dist/test/setupWasm.d.ts +0 -1
- package/dist/three.cjs +0 -9550
- package/dist/three.cjs.map +0 -1
- package/dist/validation/analyzeModel.d.ts +0 -68
- package/dist/validation/extractModelData.d.ts +0 -90
- package/dist/validation/generateMappingCorrections.d.ts +0 -32
- package/dist/validation/geometryHelpers.d.ts +0 -66
- package/dist/validation/types.d.ts +0 -10
- package/dist/validation/validateMappings.d.ts +0 -77
- package/dist/wasm.cjs +0 -302
- package/dist/wasm.cjs.map +0 -1
- package/dist/wasmTypes.d.ts +0 -123
package/dist/cljs.js
DELETED
|
@@ -1,359 +0,0 @@
|
|
|
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
DELETED
|
@@ -1 +0,0 @@
|
|
|
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"]}
|
|
@@ -1,51 +0,0 @@
|
|
|
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[];
|
|
@@ -1,41 +0,0 @@
|
|
|
1
|
-
import type { BoneFrameDelta, FrameDelta, ModelDescriptor, MorphTargetFrameDelta } from './contracts';
|
|
2
|
-
import type { Profile } from '../mappings/types';
|
|
3
|
-
import type { EmbodyCoreWasmModule } from '../wasmTypes';
|
|
4
|
-
export interface WasmRuntimeCoreOptions {
|
|
5
|
-
readonly profile: Profile;
|
|
6
|
-
readonly model: ModelDescriptor;
|
|
7
|
-
readonly wasm: EmbodyCoreWasmModule;
|
|
8
|
-
readonly allowEmptyBindings?: boolean;
|
|
9
|
-
}
|
|
10
|
-
/**
|
|
11
|
-
* TypeScript facade over the host-neutral Rust Wasm RuntimeCore.
|
|
12
|
-
* JavaScript only owns JSON handoff and packed FrameDelta unpacking here.
|
|
13
|
-
*/
|
|
14
|
-
export declare class WasmRuntimeCore {
|
|
15
|
-
private readonly wasm;
|
|
16
|
-
private readonly core;
|
|
17
|
-
private readonly allowEmptyBindings;
|
|
18
|
-
private profile;
|
|
19
|
-
private model;
|
|
20
|
-
constructor(options: WasmRuntimeCoreOptions);
|
|
21
|
-
setProfile(profile: Profile): void;
|
|
22
|
-
setModelDescriptor(model: ModelDescriptor): void;
|
|
23
|
-
setAU(id: number, value: number, balance?: number): void;
|
|
24
|
-
setContinuum(negativeAU: number, positiveAU: number, value: number, balance?: number): void;
|
|
25
|
-
transitionAU(id: number, to: number, durationMs: number, balance?: number): void;
|
|
26
|
-
transitionViseme(visemeIndex: number, to: number, durationMs: number, jawScale?: number): void;
|
|
27
|
-
update(deltaSeconds: number): number;
|
|
28
|
-
activeTransitionCount(): number;
|
|
29
|
-
clearTransitions(): void;
|
|
30
|
-
getAU(id: number): number;
|
|
31
|
-
setAUMixWeight(id: number, weight: number): void;
|
|
32
|
-
setViseme(visemeIndex: number, value: number, jawScale?: number): void;
|
|
33
|
-
clear(): void;
|
|
34
|
-
evaluatePackedMorphFrameDelta(): Float32Array;
|
|
35
|
-
evaluatePackedBoneFrameDelta(): Float32Array;
|
|
36
|
-
evaluateMorphFrameDelta(deltaSeconds?: number): FrameDelta;
|
|
37
|
-
evaluateFrameDelta(deltaSeconds?: number): FrameDelta;
|
|
38
|
-
private reloadBindings;
|
|
39
|
-
}
|
|
40
|
-
export declare function unpackBoneFrameDelta(values: ArrayLike<number>): BoneFrameDelta[];
|
|
41
|
-
export declare function unpackMorphFrameDelta(values: ArrayLike<number>): MorphTargetFrameDelta[];
|
|
@@ -1,4 +0,0 @@
|
|
|
1
|
-
import type { AUSelector, BoneBinding, RotationAxis } from './types';
|
|
2
|
-
export declare function toAUList(value?: AUSelector): number[];
|
|
3
|
-
export declare function getCompositeAxisValue(axisConfig: RotationAxis | null | undefined, getValue: (auId: number) => number): number;
|
|
4
|
-
export declare function getCompositeAxisBinding(nodeKey: string, axisConfig: RotationAxis | null | undefined, direction: number, getValue: (auId: number) => number, auToBones: Record<number, BoneBinding[]>): BoneBinding | null;
|
|
@@ -1,70 +0,0 @@
|
|
|
1
|
-
import type { NumericArray } from './primitives';
|
|
2
|
-
export declare const EMBODY_CORE_ABI_VERSION = 1;
|
|
3
|
-
export declare const PACKED_MORPH_FRAME_DELTA_STRIDE = 4;
|
|
4
|
-
export declare const PACKED_MORPH_FRAME_DELTA_FIELDS: readonly ["meshId", "morphTargetId", "value", "mode"];
|
|
5
|
-
export declare const PACKED_BONE_FRAME_DELTA_STRIDE = 9;
|
|
6
|
-
export declare const PACKED_BONE_FRAME_DELTA_FIELDS: readonly ["boneId", "positionX", "positionY", "positionZ", "rotationX", "rotationY", "rotationZ", "rotationW", "flags"];
|
|
7
|
-
/** Packed bone FrameDelta flags: bit 0 = has position, bit 1 = has rotation. */
|
|
8
|
-
export declare const PACKED_BONE_FLAG_HAS_POSITION = 1;
|
|
9
|
-
export declare const PACKED_BONE_FLAG_HAS_ROTATION = 2;
|
|
10
|
-
export declare const HAIR_CONFIG_STRIDE = 11;
|
|
11
|
-
export declare const HAIR_STATE_STRIDE = 4;
|
|
12
|
-
export declare const HAIR_HEAD_STATE_STRIDE = 5;
|
|
13
|
-
export declare const HAIR_MORPH_OUTPUT_STRIDE = 6;
|
|
14
|
-
export declare const TEMPLATE_SKELETON_FIT_TRANSFORM_STRIDE = 4;
|
|
15
|
-
export declare const MESH_PROPORTIONS_STRIDE = 16;
|
|
16
|
-
export declare const TEMPLATE_SKELETON_FIT_SOLUTION_STRIDE = 10;
|
|
17
|
-
export declare const ANNOTATION_CAMERA_FRAMING_STRIDE = 7;
|
|
18
|
-
export declare const CAMERA_FLIGHT_SAMPLE_STRIDE = 7;
|
|
19
|
-
export declare const MARKER_VISIBILITY_FACTORS_STRIDE = 3;
|
|
20
|
-
export declare const MARKER_ENDPOINT_STRIDE = 3;
|
|
21
|
-
export declare const HAIR_CONFIG_FIELDS: readonly ["mass", "stiffness", "damping", "gravity", "headInfluence", "windEnabled", "windStrength", "windDirectionX", "windDirectionZ", "windTurbulence", "windFrequency"];
|
|
22
|
-
export declare const HAIR_STATE_FIELDS: readonly ["x", "z", "vx", "vz"];
|
|
23
|
-
export declare const HAIR_HEAD_STATE_FIELDS: readonly ["yaw", "pitch", "roll", "yawVelocity", "pitchVelocity"];
|
|
24
|
-
export declare const HAIR_MORPH_OUTPUT_FIELDS: readonly ["L_Hair_Left", "L_Hair_Right", "L_Hair_Front", "R_Hair_Left", "R_Hair_Right", "R_Hair_Front"];
|
|
25
|
-
export declare const TEMPLATE_SKELETON_FIT_TRANSFORM_FIELDS: readonly ["scale", "translationX", "translationY", "translationZ"];
|
|
26
|
-
export declare const MESH_PROPORTIONS_FIELDS: readonly ["minX", "minY", "minZ", "maxX", "maxY", "maxZ", "centerX", "centerY", "centerZ", "spanX", "spanY", "spanZ", "verticalHeight", "crossAxisWideSpan", "crossAxisNarrowSpan", "humanoidLikelihood"];
|
|
27
|
-
export declare const TEMPLATE_SKELETON_FIT_SOLUTION_FIELDS: readonly ["scale", "translationX", "translationY", "translationZ", "confidence", "meshHeight", "templateHeight", "meshCrossAxisWideSpan", "templateCrossAxisWideSpan", "status"];
|
|
28
|
-
export declare const ANNOTATION_CAMERA_FRAMING_FIELDS: readonly ["positionX", "positionY", "positionZ", "targetX", "targetY", "targetZ", "distance"];
|
|
29
|
-
export declare const CAMERA_FLIGHT_SAMPLE_FIELDS: readonly ["positionX", "positionY", "positionZ", "targetX", "targetY", "targetZ", "done"];
|
|
30
|
-
export declare const MARKER_VISIBILITY_FACTORS_FIELDS: readonly ["itemOpacityFactor", "labelScaleFactor", "lineOpacityFactor"];
|
|
31
|
-
export declare const MARKER_ENDPOINT_FIELDS: readonly ["x", "y", "z"];
|
|
32
|
-
export type PackedMorphFrameDeltaField = (typeof PACKED_MORPH_FRAME_DELTA_FIELDS)[number];
|
|
33
|
-
export type HairConfigField = (typeof HAIR_CONFIG_FIELDS)[number];
|
|
34
|
-
export type HairStateField = (typeof HAIR_STATE_FIELDS)[number];
|
|
35
|
-
export type HairHeadStateField = (typeof HAIR_HEAD_STATE_FIELDS)[number];
|
|
36
|
-
export type HairMorphOutputField = (typeof HAIR_MORPH_OUTPUT_FIELDS)[number];
|
|
37
|
-
export type TemplateSkeletonFitTransformField = (typeof TEMPLATE_SKELETON_FIT_TRANSFORM_FIELDS)[number];
|
|
38
|
-
export type MeshProportionsField = (typeof MESH_PROPORTIONS_FIELDS)[number];
|
|
39
|
-
export type TemplateSkeletonFitSolutionField = (typeof TEMPLATE_SKELETON_FIT_SOLUTION_FIELDS)[number];
|
|
40
|
-
export interface PackedMorphFrameDelta {
|
|
41
|
-
readonly abiVersion: typeof EMBODY_CORE_ABI_VERSION;
|
|
42
|
-
readonly stride: typeof PACKED_MORPH_FRAME_DELTA_STRIDE;
|
|
43
|
-
readonly fields: typeof PACKED_MORPH_FRAME_DELTA_FIELDS;
|
|
44
|
-
readonly values: NumericArray;
|
|
45
|
-
}
|
|
46
|
-
export interface PackedHairPhysicsState {
|
|
47
|
-
readonly stride: typeof HAIR_STATE_STRIDE;
|
|
48
|
-
readonly fields: typeof HAIR_STATE_FIELDS;
|
|
49
|
-
readonly values: NumericArray;
|
|
50
|
-
}
|
|
51
|
-
export interface PackedHairMorphOutput {
|
|
52
|
-
readonly stride: typeof HAIR_MORPH_OUTPUT_STRIDE;
|
|
53
|
-
readonly fields: typeof HAIR_MORPH_OUTPUT_FIELDS;
|
|
54
|
-
readonly values: NumericArray;
|
|
55
|
-
}
|
|
56
|
-
export interface PackedTemplateSkeletonFitTransform {
|
|
57
|
-
readonly stride: typeof TEMPLATE_SKELETON_FIT_TRANSFORM_STRIDE;
|
|
58
|
-
readonly fields: typeof TEMPLATE_SKELETON_FIT_TRANSFORM_FIELDS;
|
|
59
|
-
readonly values: NumericArray;
|
|
60
|
-
}
|
|
61
|
-
export interface PackedMeshProportions {
|
|
62
|
-
readonly stride: typeof MESH_PROPORTIONS_STRIDE;
|
|
63
|
-
readonly fields: typeof MESH_PROPORTIONS_FIELDS;
|
|
64
|
-
readonly values: NumericArray;
|
|
65
|
-
}
|
|
66
|
-
export interface PackedTemplateSkeletonFitSolution {
|
|
67
|
-
readonly stride: typeof TEMPLATE_SKELETON_FIT_SOLUTION_STRIDE;
|
|
68
|
-
readonly fields: typeof TEMPLATE_SKELETON_FIT_SOLUTION_FIELDS;
|
|
69
|
-
readonly values: NumericArray;
|
|
70
|
-
}
|
|
@@ -1,44 +0,0 @@
|
|
|
1
|
-
import type { BoneId, ChannelId, MeshId, MorphTargetId, TrackId } from './ids';
|
|
2
|
-
import type { NumericArray } from './primitives';
|
|
3
|
-
export type ClipChannelKind = 'face' | 'body' | 'scene' | 'custom';
|
|
4
|
-
export type ClipTrackValueType = 'scalar' | 'vec3' | 'quat';
|
|
5
|
-
export type ClipInterpolation = 'step' | 'linear' | 'cubic';
|
|
6
|
-
export type ClipTrackTargetKind = 'morphTarget' | 'boneTransform' | 'meshVisibility';
|
|
7
|
-
export type ClipTrackTransformProperty = 'position' | 'rotation' | 'scale';
|
|
8
|
-
export interface ClipChannelIR {
|
|
9
|
-
readonly id: ChannelId;
|
|
10
|
-
readonly kind: ClipChannelKind;
|
|
11
|
-
readonly name?: string;
|
|
12
|
-
}
|
|
13
|
-
export interface MorphTargetTrackTarget {
|
|
14
|
-
readonly kind: 'morphTarget';
|
|
15
|
-
readonly meshId: MeshId;
|
|
16
|
-
readonly morphTargetId: MorphTargetId;
|
|
17
|
-
}
|
|
18
|
-
export interface BoneTransformTrackTarget {
|
|
19
|
-
readonly kind: 'boneTransform';
|
|
20
|
-
readonly boneId: BoneId;
|
|
21
|
-
readonly property: ClipTrackTransformProperty;
|
|
22
|
-
}
|
|
23
|
-
export interface MeshVisibilityTrackTarget {
|
|
24
|
-
readonly kind: 'meshVisibility';
|
|
25
|
-
readonly meshId: MeshId;
|
|
26
|
-
}
|
|
27
|
-
export type ClipTrackTarget = MorphTargetTrackTarget | BoneTransformTrackTarget | MeshVisibilityTrackTarget;
|
|
28
|
-
export interface ClipTrackIR {
|
|
29
|
-
readonly id: TrackId;
|
|
30
|
-
readonly channelId: ChannelId;
|
|
31
|
-
readonly target: ClipTrackTarget;
|
|
32
|
-
readonly valueType: ClipTrackValueType;
|
|
33
|
-
readonly times: NumericArray;
|
|
34
|
-
readonly values: NumericArray;
|
|
35
|
-
readonly interpolation?: ClipInterpolation;
|
|
36
|
-
}
|
|
37
|
-
export interface ClipIR {
|
|
38
|
-
readonly id?: string;
|
|
39
|
-
readonly name: string;
|
|
40
|
-
readonly durationSeconds: number;
|
|
41
|
-
readonly channels: readonly ClipChannelIR[];
|
|
42
|
-
readonly tracks: readonly ClipTrackIR[];
|
|
43
|
-
readonly metadata?: Readonly<Record<string, unknown>>;
|
|
44
|
-
}
|