@sage-rsc/talking-head-react 1.0.53 → 1.0.55
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/dist/index.cjs +2 -2
- package/dist/index.js +713 -689
- package/package.json +1 -1
- package/src/components/CurriculumLearning.jsx +45 -11
- package/src/lib/talkinghead.mjs +2 -2
package/dist/index.js
CHANGED
|
@@ -1,18 +1,18 @@
|
|
|
1
1
|
import { jsxs as ke, jsx as ne } from "react/jsx-runtime";
|
|
2
|
-
import { forwardRef as fe, useRef as
|
|
2
|
+
import { forwardRef as fe, useRef as G, useState as re, useEffect as le, useCallback as M, useImperativeHandle as xe, useLayoutEffect as Ee } from "react";
|
|
3
3
|
import * as f from "three";
|
|
4
4
|
import { OrbitControls as Fe } from "three/addons/controls/OrbitControls.js";
|
|
5
5
|
import { GLTFLoader as Pe } from "three/addons/loaders/GLTFLoader.js";
|
|
6
6
|
import { DRACOLoader as Be } from "three/addons/loaders/DRACOLoader.js";
|
|
7
|
-
import { FBXLoader as
|
|
7
|
+
import { FBXLoader as Re } from "three/addons/loaders/FBXLoader.js";
|
|
8
8
|
import { RoomEnvironment as De } from "three/addons/environments/RoomEnvironment.js";
|
|
9
9
|
import Oe from "three/addons/libs/stats.module.js";
|
|
10
10
|
let m, j, q;
|
|
11
|
-
const A = [0, 0, 0, 0], w = new f.Vector3(), de = new f.Vector3(),
|
|
11
|
+
const A = [0, 0, 0, 0], w = new f.Vector3(), de = new f.Vector3(), Z = new f.Vector3(), ce = new f.Vector3();
|
|
12
12
|
new f.Plane();
|
|
13
13
|
new f.Ray();
|
|
14
14
|
new f.Euler();
|
|
15
|
-
const
|
|
15
|
+
const X = new f.Quaternion(), Ie = new f.Quaternion(), $ = new f.Matrix4(), ee = new f.Matrix4();
|
|
16
16
|
new f.Vector3();
|
|
17
17
|
const me = new f.Vector3(0, 0, 1), Ne = new f.Vector3(1, 0, 0), Ue = new f.Vector3(0, 1, 0), We = new f.Vector3(0, 0, 1);
|
|
18
18
|
class Ve {
|
|
@@ -189,11 +189,11 @@ class Ve {
|
|
|
189
189
|
n.excludes = [], i.forEach((s, o) => {
|
|
190
190
|
if (!s.bone) throw new Error("Bone not specified in #" + o + " exclude.");
|
|
191
191
|
if (typeof s.bone != "string" || s.bone.length === 0) throw new Error("Bone name must be a non-empty string in #" + o + " exclude.");
|
|
192
|
-
const
|
|
193
|
-
if (!
|
|
192
|
+
const l = this.armature.getObjectByName(s.bone);
|
|
193
|
+
if (!l) throw new Error("Bone '" + s.bone + "' not found in #" + o + " exclude.");
|
|
194
194
|
if (Number.isNaN(s.radius) && s.radius >= 0) throw new Error("Radius must be a non-negative number in #" + o + " exclude.");
|
|
195
195
|
const u = {
|
|
196
|
-
bone:
|
|
196
|
+
bone: l,
|
|
197
197
|
// Bone object
|
|
198
198
|
radius: s.radius,
|
|
199
199
|
// Radius
|
|
@@ -278,7 +278,7 @@ class Ve {
|
|
|
278
278
|
const e = /* @__PURE__ */ new WeakMap();
|
|
279
279
|
this.armature.traverse((o) => {
|
|
280
280
|
e.has(o) || (e.set(o, t), t++);
|
|
281
|
-
}), this.data.sort((o,
|
|
281
|
+
}), this.data.sort((o, l) => e.get(o.bone) - e.get(l.bone)), this.data.forEach((o) => {
|
|
282
282
|
m = this.dict[o.boneParent.name], m && (m.children || (m.children = []), m.children.push(o));
|
|
283
283
|
}), this.objectsUpdate = [];
|
|
284
284
|
const i = /* @__PURE__ */ new WeakSet(), n = (o) => o.parent?.isBone ? [o, ...n(o.parent)] : [o], s = (o) => {
|
|
@@ -287,10 +287,10 @@ class Ve {
|
|
|
287
287
|
});
|
|
288
288
|
};
|
|
289
289
|
this.data.forEach((o) => {
|
|
290
|
-
s(o.bone), o.excludes && o.excludes.forEach((
|
|
291
|
-
s(
|
|
290
|
+
s(o.bone), o.excludes && o.excludes.forEach((l) => {
|
|
291
|
+
s(l.bone);
|
|
292
292
|
});
|
|
293
|
-
}), this.objectsUpdate.sort((o,
|
|
293
|
+
}), this.objectsUpdate.sort((o, l) => e.get(o) - e.get(l));
|
|
294
294
|
}
|
|
295
295
|
/**
|
|
296
296
|
* Setup dynamic bones.
|
|
@@ -306,12 +306,12 @@ class Ve {
|
|
|
306
306
|
throw this.dispose(), new Error(o);
|
|
307
307
|
};
|
|
308
308
|
n(t?.isScene, "First parameter must be Scene."), this.scene = t, n(e?.isObject3D, "Second parameter must be the armature Object3D."), this.armature = e, n(Array.isArray(i), "Third parameter must be an array of bone configs."), this.config = i, this.config.forEach((s, o) => {
|
|
309
|
-
const
|
|
310
|
-
n(s.bone,
|
|
309
|
+
const l = "Config item #" + o + ": ";
|
|
310
|
+
n(s.bone, l + "Bone not specified.");
|
|
311
311
|
const u = s.bone;
|
|
312
|
-
n(typeof u == "string" && u.length > 0,
|
|
312
|
+
n(typeof u == "string" && u.length > 0, l + "Bone name must be a non-empty string.");
|
|
313
313
|
const a = this.armature.getObjectByName(u);
|
|
314
|
-
n(a,
|
|
314
|
+
n(a, l + "Bone '" + u + "' not found."), n(a.parent?.isBone, l + "Bone must have a parent bone."), n(this.data.every((r) => r.bone !== a), l + "Bone '" + u + "' already exists."), a.updateMatrixWorld(!0);
|
|
315
315
|
const h = {
|
|
316
316
|
name: u,
|
|
317
317
|
// Bone name
|
|
@@ -338,11 +338,11 @@ class Ve {
|
|
|
338
338
|
ea: [0, 0, 0, 0]
|
|
339
339
|
// External acceleration [m/s^2]
|
|
340
340
|
};
|
|
341
|
-
h.boneParent.matrixWorld.decompose(w,
|
|
341
|
+
h.boneParent.matrixWorld.decompose(w, X, Z), w.copy(me).applyQuaternion(X).setY(0).normalize(), X.premultiply(Ie.setFromUnitVectors(me, w).invert()).normalize(), h.qWorldInverseYaw = X.clone().normalize(), this.data.push(h), this.dict[u] = h;
|
|
342
342
|
try {
|
|
343
343
|
this.setValue(u, "type", s.type), this.setValue(u, "stiffness", s.stiffness), this.setValue(u, "damping", s.damping), this.setValue(u, "external", s.external), this.setValue(u, "limits", s.limits), this.setValue(u, "excludes", s.excludes), this.setValue(u, "deltaLocal", s.deltaLocal), this.setValue(u, "deltaWorld", s.deltaWorld), this.setValue(u, "pivot", s.pivot), this.setValue(u, "helper", s.helper);
|
|
344
|
-
} catch (
|
|
345
|
-
n(!1,
|
|
344
|
+
} catch (r) {
|
|
345
|
+
n(!1, l + r);
|
|
346
346
|
}
|
|
347
347
|
}), this.sortBones(), this.start();
|
|
348
348
|
}
|
|
@@ -356,22 +356,22 @@ class Ve {
|
|
|
356
356
|
for (this.timerMs += t, t > 1e3 && (this.timerMs = 0), t /= 1e3, e = 0, n = this.objectsUpdate.length; e < n; e++)
|
|
357
357
|
o = this.objectsUpdate[e], o.updateMatrix(), o.parent === null ? o.matrixWorld.copy(o.matrix) : o.matrixWorld.multiplyMatrices(o.parent.matrixWorld, o.matrix), o.matrixWorldNeedsUpdate = !1;
|
|
358
358
|
for (e = 0, n = this.data.length; e < n; e++) {
|
|
359
|
-
if (o = this.data[e], w.copy(o.vWorld),
|
|
359
|
+
if (o = this.data[e], w.copy(o.vWorld), $.copy(o.boneParent.matrixWorld), ee.copy($).invert(), o.vWorld.setFromMatrixPosition($), w.applyMatrix4(ee), w.length() > 0.5 && (console.info("Info: Unrealistic jump of " + w.length().toFixed(2) + " meters."), w.setLength(0.5)), w.applyQuaternion(o.bone.quaternion), A[0] = w.x, A[1] = w.y, A[2] = -w.z, A[3] = w.length() / 3, o.children)
|
|
360
360
|
for (i = 0, s = o.children.length; i < s; i++)
|
|
361
361
|
m = o.children[i], A[0] -= m.v[0] * t / 3, A[1] -= m.v[1] * t / 3, A[2] += m.v[2] * t / 3, A[3] -= m.v[3] * t / 3;
|
|
362
362
|
if (m = this.opt.sensitivityFactor, A[0] *= o.ext * m, A[1] *= o.ext * m, A[2] *= o.ext * m, A[3] *= o.ext * m, o.isX && (m = A[0] / t, o.ea[0] = (m - o.ev[0]) / t, o.ev[0] = m, o.a[0] = -o.k[0] * o.p[0] - o.c[0] * o.v[0] - o.ea[0], o.p[0] += o.v[0] * t + o.a[0] * t * t / 2 + A[0], m = o.v[0] + o.a[0] * t / 2, m = -o.k[0] * o.p[0] - o.c[0] * m - o.ea[0], o.v[0] = o.v[0] + (m + o.a[0]) * t / 2), o.isY && (m = A[1] / t, o.ea[1] = (m - o.ev[1]) / t, o.ev[1] = m, o.a[1] = -o.k[1] * o.p[1] - o.c[1] * o.v[1] - o.ea[1], o.p[1] += o.v[1] * t + o.a[1] * t * t / 2 + A[1], m = o.v[1] + o.a[1] * t / 2, m = -o.k[1] * o.p[1] - o.c[1] * m - o.ea[1], o.v[1] = o.v[1] + (m + o.a[1]) * t / 2), o.isZ && (m = A[2] / t, o.ea[2] = (m - o.ev[2]) / t, o.ev[2] = m, o.a[2] = -o.k[2] * o.p[2] - o.c[2] * o.v[2] - o.ea[2], o.p[2] += o.v[2] * t + o.a[2] * t * t / 2 + A[2], m = o.v[2] + o.a[2] * t / 2, m = -o.k[2] * o.p[2] - o.c[2] * m - o.ea[2], o.v[2] = o.v[2] + (m + o.a[2]) * t / 2), o.isT && (m = A[3] / t, o.ea[3] = (m - o.ev[3]) / t, o.ev[3] = m, o.a[3] = -o.k[3] * o.p[3] - o.c[3] * o.v[3] - o.ea[3], o.p[3] += o.v[3] * t + o.a[3] * t * t / 2 + A[3], m = o.v[3] + o.a[3] * t / 2, m = -o.k[3] * o.p[3] - o.c[3] * m - o.ea[3], o.v[3] = o.v[3] + (m + o.a[3]) * t / 2), this.timerMs < this.opt.warmupMs && (o.v[0] *= 1e-4, o.p[0] *= 1e-4, o.v[1] *= 1e-4, o.p[1] *= 1e-4, o.v[2] *= 1e-4, o.p[2] *= 1e-4, o.v[3] *= 1e-4, o.p[3] *= 1e-4), A[0] = o.p[0], A[1] = o.p[1], A[2] = o.p[2], A[3] = o.p[3], m = this.opt.movementFactor, A[0] *= m, A[1] *= m, A[2] *= m, A[3] *= m, o.dl && (m = o.dl, A[0] += m[0], A[1] += m[1], A[2] += m[2]), o.dw && (m = o.dw, w.set(
|
|
363
363
|
o.vBasis.x + A[0],
|
|
364
364
|
o.vBasis.y + A[1],
|
|
365
365
|
o.vBasis.z + A[2]
|
|
366
|
-
), w.applyMatrix4(
|
|
366
|
+
), w.applyMatrix4($), w.x += m[0], w.y += m[1], w.z += m[2], w.applyMatrix4(ee), A[0] += w.x - o.vBasis.x, A[1] += w.y - o.vBasis.y, A[2] += w.z - o.vBasis.z), o.limits && this.opt.isLimits && (m = o.limits, m[0] && (m[0][0] !== null && A[0] < m[0][0] && (A[0] = m[0][0]), m[0][1] !== null && A[0] > m[0][1] && (A[0] = m[0][1])), m[1] && (m[1][0] !== null && A[1] < m[1][0] && (A[1] = m[1][0]), m[1][1] !== null && A[1] > m[1][1] && (A[1] = m[1][1])), m[2] && (m[2][0] !== null && A[2] < m[2][0] && (A[2] = m[2][0]), m[2][1] !== null && A[2] > m[2][1] && (A[2] = m[2][1])), m[3] && (m[3][0] !== null && A[3] < m[3][0] && (A[3] = m[3][0]), m[3][1] !== null && A[3] > m[3][1] && (A[3] = m[3][1]))), o.isPoint)
|
|
367
367
|
o.bone.position.set(
|
|
368
368
|
o.vBasis.x + A[0],
|
|
369
369
|
o.vBasis.y + A[1],
|
|
370
370
|
o.vBasis.z - A[2]
|
|
371
371
|
);
|
|
372
|
-
else if (o.boneParent.quaternion.copy(o.qBasis), o.pivot && this.opt.isPivots && (o.boneParent.updateWorldMatrix(!1, !1), o.boneParent.matrixWorld.decompose(w,
|
|
372
|
+
else if (o.boneParent.quaternion.copy(o.qBasis), o.pivot && this.opt.isPivots && (o.boneParent.updateWorldMatrix(!1, !1), o.boneParent.matrixWorld.decompose(w, X, Z), w.copy(me).applyQuaternion(X).setY(0).normalize(), X.premultiply(Ie.setFromUnitVectors(me, w).invert()).normalize(), o.boneParent.quaternion.multiply(X.invert()), o.boneParent.quaternion.multiply(o.qWorldInverseYaw)), o.isZ && (m = Math.atan(A[0] / o.l), X.setFromAxisAngle(We, -m), o.boneParent.quaternion.multiply(X)), o.isY && (m = o.l / 3, m = m * Math.tanh(A[1] / m), o.bone.position.setLength(o.l + m)), o.isX && (m = Math.atan(A[2] / o.l), X.setFromAxisAngle(Ne, -m), o.boneParent.quaternion.multiply(X)), o.isT && (m = 1.5 * Math.tanh(A[3] * 1.5), X.setFromAxisAngle(Ue, -m), o.boneParent.quaternion.multiply(X)), o.boneParent.updateWorldMatrix(!1, !0), o.excludes && this.opt.isExcludes)
|
|
373
373
|
for (i = 0, s = o.excludes.length; i < s; i++)
|
|
374
|
-
m = o.excludes[i],
|
|
374
|
+
m = o.excludes[i], Z.set(0, 0, 0), m.deltaLocal && (Z.x += m.deltaLocal[0], Z.y += m.deltaLocal[1], Z.z += m.deltaLocal[2]), Z.applyMatrix4(m.bone.matrixWorld), ee.copy(o.boneParent.matrixWorld).invert(), Z.applyMatrix4(ee), w.copy(o.bone.position), !(w.distanceToSquared(Z) >= m.radiusSq) && (q = w.length(), j = Z.length(), !(j > m.radius + q) && (j < Math.abs(m.radius - q) || (j = (j * j + q * q - m.radiusSq) / (2 * j), Z.normalize(), ce.copy(Z).multiplyScalar(j), j = Math.sqrt(q * q - j * j), w.subVectors(w, ce).projectOnPlane(Z).normalize().multiplyScalar(j), de.subVectors(o.vBasis, ce).projectOnPlane(Z).normalize(), q = de.dot(w), q < 0 && (q = Math.sqrt(j * j - q * q), de.multiplyScalar(q), w.add(de)), w.add(ce).normalize(), Z.copy(o.bone.position).normalize(), X.setFromUnitVectors(Z, w), o.boneParent.quaternion.premultiply(X), o.boneParent.updateWorldMatrix(!1, !0))));
|
|
375
375
|
}
|
|
376
376
|
this.helpers.isActive && this.updateHelpers();
|
|
377
377
|
}
|
|
@@ -386,7 +386,7 @@ class Ve {
|
|
|
386
386
|
(this.helpers.isShowAll || e.helper === !0) && (m.points.bones.push(e.bone), m.points.pivots.push(e.pivot), e.type !== 0 && m.lines.bones.push(e.bone), e.excludes && e.excludes.forEach((i) => {
|
|
387
387
|
let n = !1;
|
|
388
388
|
for (let s = 0; s < m.excludes.bones.length; s++)
|
|
389
|
-
if (m.excludes.bones[s] === i.bone && m.excludes.radii[s] === i.radius && !(m.excludes.deltaLocals[s] === null && i.deltaLocal !== null) && !(m.excludes.deltaLocals[s] !== null && i.deltaLocal === null) && !(m.excludes.deltaLocals[s] !== null && m.excludes.deltaLocals[s].some((o,
|
|
389
|
+
if (m.excludes.bones[s] === i.bone && m.excludes.radii[s] === i.radius && !(m.excludes.deltaLocals[s] === null && i.deltaLocal !== null) && !(m.excludes.deltaLocals[s] !== null && i.deltaLocal === null) && !(m.excludes.deltaLocals[s] !== null && m.excludes.deltaLocals[s].some((o, l) => o !== i.deltaLocal[l]))) {
|
|
390
390
|
n = !0;
|
|
391
391
|
break;
|
|
392
392
|
}
|
|
@@ -412,7 +412,7 @@ class Ve {
|
|
|
412
412
|
e.setAttribute("position", new f.Float32BufferAttribute(i, 3));
|
|
413
413
|
const n = new f.Color(this.opt.helperBoneColor1), s = new f.Color(this.opt.helperBoneColor2), o = m.pivots.map((u) => u && this.opt.isPivots ? [s.r, s.g, s.b] : [n.r, n.g, n.b]).flat();
|
|
414
414
|
e.setAttribute("color", new f.Float32BufferAttribute(o, 3));
|
|
415
|
-
const
|
|
415
|
+
const l = new f.PointsMaterial({
|
|
416
416
|
depthTest: !1,
|
|
417
417
|
depthWrite: !1,
|
|
418
418
|
toneMapped: !1,
|
|
@@ -420,21 +420,21 @@ class Ve {
|
|
|
420
420
|
size: 0.2,
|
|
421
421
|
vertexColors: !0
|
|
422
422
|
});
|
|
423
|
-
m.object = new f.Points(e,
|
|
423
|
+
m.object = new f.Points(e, l), m.object.renderOrder = 998, m.object.matrix = this.armature.matrixWorld, m.object.matrixAutoUpdate = !1, this.scene.add(m.object);
|
|
424
424
|
}
|
|
425
425
|
if (m = this.helpers.lines, m.bones.length) {
|
|
426
426
|
const e = new f.BufferGeometry(), i = m.bones.map((u) => [0, 0, 0, 0, 0, 0]).flat();
|
|
427
427
|
e.setAttribute("position", new f.Float32BufferAttribute(i, 3));
|
|
428
428
|
const n = new f.Color(this.opt.helperLinkColor1), s = new f.Color(this.opt.helperLinkColor2), o = m.bones.map((u) => [n.r, n.g, n.b, s.r, s.g, s.b]).flat();
|
|
429
429
|
e.setAttribute("color", new f.Float32BufferAttribute(o, 3));
|
|
430
|
-
const
|
|
430
|
+
const l = new f.LineBasicMaterial({
|
|
431
431
|
vertexColors: !0,
|
|
432
432
|
depthTest: !1,
|
|
433
433
|
depthWrite: !1,
|
|
434
434
|
toneMapped: !1,
|
|
435
435
|
transparent: !0
|
|
436
436
|
});
|
|
437
|
-
m.object = new f.LineSegments(e,
|
|
437
|
+
m.object = new f.LineSegments(e, l), m.object.renderOrder = 999, m.object.matrix = this.armature.matrixWorld, m.object.matrixAutoUpdate = !1, this.scene.add(m.object);
|
|
438
438
|
}
|
|
439
439
|
}
|
|
440
440
|
/**
|
|
@@ -442,17 +442,17 @@ class Ve {
|
|
|
442
442
|
*/
|
|
443
443
|
updateHelpers() {
|
|
444
444
|
if (m = this.helpers.points, m.bones.length) {
|
|
445
|
-
|
|
445
|
+
ee.copy(this.armature.matrixWorld).invert();
|
|
446
446
|
const t = m.object.geometry.getAttribute("position");
|
|
447
447
|
for (let e = 0, i = m.bones.length; e < i; e++)
|
|
448
|
-
|
|
448
|
+
$.multiplyMatrices(ee, m.bones[e].matrixWorld), w.setFromMatrixPosition($), t.setXYZ(e, w.x, w.y, w.z);
|
|
449
449
|
t.needsUpdate = !0, m.object.updateMatrixWorld();
|
|
450
450
|
}
|
|
451
451
|
if (m = this.helpers.lines, m.bones.length) {
|
|
452
|
-
|
|
452
|
+
ee.copy(this.armature.matrixWorld).invert();
|
|
453
453
|
const t = m.object.geometry.getAttribute("position");
|
|
454
454
|
for (let e = 0, i = 0, n = m.bones.length; e < n; e++, i += 2)
|
|
455
|
-
|
|
455
|
+
$.multiplyMatrices(ee, m.bones[e].matrixWorld), w.setFromMatrixPosition($), t.setXYZ(i, w.x, w.y, w.z), $.multiplyMatrices(ee, m.bones[e].parent.matrixWorld), w.setFromMatrixPosition($), t.setXYZ(i + 1, w.x, w.y, w.z);
|
|
456
456
|
t.needsUpdate = !0, m.object.updateMatrixWorld();
|
|
457
457
|
}
|
|
458
458
|
}
|
|
@@ -518,9 +518,9 @@ class Ge {
|
|
|
518
518
|
onsets: [],
|
|
519
519
|
phonemeBoundaries: []
|
|
520
520
|
}, n = 1024, s = 512, o = Math.floor((t.length - n) / s) + 1;
|
|
521
|
-
for (let
|
|
522
|
-
const u =
|
|
523
|
-
i.energy.push(
|
|
521
|
+
for (let l = 0; l < o; l++) {
|
|
522
|
+
const u = l * s, a = Math.min(u + n, t.length), h = t.slice(u, a), r = this.calculateEnergy(h);
|
|
523
|
+
i.energy.push(r);
|
|
524
524
|
const d = this.calculateSpectralCentroid(h);
|
|
525
525
|
i.spectralCentroid.push(d);
|
|
526
526
|
const c = this.calculateZeroCrossingRate(h);
|
|
@@ -576,8 +576,8 @@ class Ge {
|
|
|
576
576
|
for (let n = 0; n < 13; n++) {
|
|
577
577
|
let s = 0;
|
|
578
578
|
for (let o = 0; o < e.length / 2; o++) {
|
|
579
|
-
const
|
|
580
|
-
s +=
|
|
579
|
+
const l = Math.sqrt(e[o * 2] * e[o * 2] + e[o * 2 + 1] * e[o * 2 + 1]);
|
|
580
|
+
s += l * Math.cos(Math.PI * n * (o + 0.5) / (e.length / 2));
|
|
581
581
|
}
|
|
582
582
|
i.push(s);
|
|
583
583
|
}
|
|
@@ -597,18 +597,18 @@ class Ge {
|
|
|
597
597
|
for (; s & o; )
|
|
598
598
|
s ^= o, o >>= 1;
|
|
599
599
|
if (s ^= o, n < s) {
|
|
600
|
-
const
|
|
601
|
-
i[n * 2] = i[s * 2], i[n * 2 + 1] = i[s * 2 + 1], i[s * 2] =
|
|
600
|
+
const l = i[n * 2], u = i[n * 2 + 1];
|
|
601
|
+
i[n * 2] = i[s * 2], i[n * 2 + 1] = i[s * 2 + 1], i[s * 2] = l, i[s * 2 + 1] = u;
|
|
602
602
|
}
|
|
603
603
|
}
|
|
604
604
|
for (let n = 2; n <= e; n <<= 1) {
|
|
605
|
-
const s = -2 * Math.PI / n, o = Math.cos(s),
|
|
605
|
+
const s = -2 * Math.PI / n, o = Math.cos(s), l = Math.sin(s);
|
|
606
606
|
for (let u = 0; u < e; u += n) {
|
|
607
607
|
let a = 1, h = 0;
|
|
608
|
-
for (let
|
|
609
|
-
const d = i[(u +
|
|
610
|
-
i[(u +
|
|
611
|
-
const x = a * o - h *
|
|
608
|
+
for (let r = 0; r < n / 2; r++) {
|
|
609
|
+
const d = i[(u + r) * 2], c = i[(u + r) * 2 + 1], g = i[(u + r + n / 2) * 2] * a - i[(u + r + n / 2) * 2 + 1] * h, y = i[(u + r + n / 2) * 2] * h + i[(u + r + n / 2) * 2 + 1] * a;
|
|
610
|
+
i[(u + r) * 2] = d + g, i[(u + r) * 2 + 1] = c + y, i[(u + r + n / 2) * 2] = d - g, i[(u + r + n / 2) * 2 + 1] = c - y;
|
|
611
|
+
const x = a * o - h * l, L = a * l + h * o;
|
|
612
612
|
a = x, h = L;
|
|
613
613
|
}
|
|
614
614
|
}
|
|
@@ -624,8 +624,8 @@ class Ge {
|
|
|
624
624
|
const e = [];
|
|
625
625
|
let s = -0.1;
|
|
626
626
|
for (let o = 1; o < t.length; o++) {
|
|
627
|
-
const
|
|
628
|
-
|
|
627
|
+
const l = t[o] - t[o - 1], u = o * 0.023;
|
|
628
|
+
l > 0.1 && u - s > 0.1 && (e.push(u), s = u);
|
|
629
629
|
}
|
|
630
630
|
return e;
|
|
631
631
|
}
|
|
@@ -637,8 +637,8 @@ class Ge {
|
|
|
637
637
|
detectPhonemeBoundaries(t) {
|
|
638
638
|
const e = [], { energy: i, spectralCentroid: n, zeroCrossingRate: s } = t;
|
|
639
639
|
for (let o = 1; o < i.length; o++) {
|
|
640
|
-
const
|
|
641
|
-
u + a * 0.1 + h * 0.5 > 0.2 && e.push(
|
|
640
|
+
const l = o * 0.023, u = Math.abs(i[o] - i[o - 1]), a = Math.abs(n[o] - n[o - 1]), h = Math.abs(s[o] - s[o - 1]);
|
|
641
|
+
u + a * 0.1 + h * 0.5 > 0.2 && e.push(l);
|
|
642
642
|
}
|
|
643
643
|
return e;
|
|
644
644
|
}
|
|
@@ -663,10 +663,10 @@ class Ge {
|
|
|
663
663
|
duration: h
|
|
664
664
|
}), o += h;
|
|
665
665
|
}
|
|
666
|
-
const
|
|
666
|
+
const l = this.generateVisemeTimings(t, e, i);
|
|
667
667
|
return {
|
|
668
668
|
words: s,
|
|
669
|
-
visemes:
|
|
669
|
+
visemes: l,
|
|
670
670
|
duration: i,
|
|
671
671
|
features: t
|
|
672
672
|
};
|
|
@@ -701,27 +701,27 @@ class Ge {
|
|
|
701
701
|
const n = [], s = t.phonemeBoundaries;
|
|
702
702
|
t.onsets;
|
|
703
703
|
const o = this.textToVisemes(e);
|
|
704
|
-
let
|
|
705
|
-
for (let a = 0; a < s.length &&
|
|
706
|
-
const h = s[a],
|
|
704
|
+
let l = 0, u = 0;
|
|
705
|
+
for (let a = 0; a < s.length && l < o.length; a++) {
|
|
706
|
+
const h = s[a], r = o[l], d = t.energy[Math.floor(h / 0.023)] || 0, c = this.calculateVisemeDuration(r, d);
|
|
707
707
|
n.push({
|
|
708
|
-
viseme:
|
|
708
|
+
viseme: r,
|
|
709
709
|
startTime: u,
|
|
710
710
|
endTime: u + c,
|
|
711
711
|
duration: c,
|
|
712
712
|
intensity: Math.min(1, d * 2)
|
|
713
713
|
// Map energy to viseme intensity
|
|
714
|
-
}), u += c,
|
|
714
|
+
}), u += c, l++;
|
|
715
715
|
}
|
|
716
|
-
for (;
|
|
717
|
-
const a = o[
|
|
716
|
+
for (; l < o.length; ) {
|
|
717
|
+
const a = o[l], h = this.calculateVisemeDuration(a, 0.5);
|
|
718
718
|
n.push({
|
|
719
719
|
viseme: a,
|
|
720
720
|
startTime: u,
|
|
721
721
|
endTime: u + h,
|
|
722
722
|
duration: h,
|
|
723
723
|
intensity: 0.6
|
|
724
|
-
}), u += h,
|
|
724
|
+
}), u += h, l++;
|
|
725
725
|
}
|
|
726
726
|
return n;
|
|
727
727
|
}
|
|
@@ -774,15 +774,15 @@ class Ge {
|
|
|
774
774
|
for (const s of n) {
|
|
775
775
|
let o = 0;
|
|
776
776
|
for (; o < s.length; ) {
|
|
777
|
-
let
|
|
777
|
+
let l = !1;
|
|
778
778
|
for (let u = 3; u >= 2; u--) {
|
|
779
779
|
const a = s.substr(o, u);
|
|
780
780
|
if (e[a]) {
|
|
781
|
-
i.push(e[a]), o += u,
|
|
781
|
+
i.push(e[a]), o += u, l = !0;
|
|
782
782
|
break;
|
|
783
783
|
}
|
|
784
784
|
}
|
|
785
|
-
if (!
|
|
785
|
+
if (!l) {
|
|
786
786
|
const u = s[o];
|
|
787
787
|
e[u] && i.push(e[u]), o++;
|
|
788
788
|
}
|
|
@@ -1206,13 +1206,13 @@ class Ze {
|
|
|
1206
1206
|
};
|
|
1207
1207
|
Object.keys(this.rules).forEach((e) => {
|
|
1208
1208
|
this.rules[e] = this.rules[e].map((i) => {
|
|
1209
|
-
const n = i.indexOf("["), s = i.indexOf("]"), o = i.indexOf("="),
|
|
1209
|
+
const n = i.indexOf("["), s = i.indexOf("]"), o = i.indexOf("="), l = i.substring(0, n), u = i.substring(n + 1, s), a = i.substring(s + 1, o), h = i.substring(o + 1), r = { regex: "", move: 0, visemes: [] };
|
|
1210
1210
|
let d = "";
|
|
1211
|
-
d += [...
|
|
1211
|
+
d += [...l].map((g) => t[g] || g).join("");
|
|
1212
1212
|
const c = [...u];
|
|
1213
|
-
return c[0] = c[0].toLowerCase(), d += c.join(""),
|
|
1214
|
-
|
|
1215
|
-
}),
|
|
1213
|
+
return c[0] = c[0].toLowerCase(), d += c.join(""), r.move = c.length, d += [...a].map((g) => t[g] || g).join(""), r.regex = new RegExp(d), h.length && h.split(" ").forEach((g) => {
|
|
1214
|
+
r.visemes.push(g);
|
|
1215
|
+
}), r;
|
|
1216
1216
|
});
|
|
1217
1217
|
}), this.visemeDurations = {
|
|
1218
1218
|
aa: 0.95,
|
|
@@ -1323,9 +1323,9 @@ class Ze {
|
|
|
1323
1323
|
* @return {string} Normalized text
|
|
1324
1324
|
*/
|
|
1325
1325
|
convertDecade(t) {
|
|
1326
|
-
const e = parseInt(t), i = !isNaN(e) && t.length === 2, n = !isNaN(e) && t.length > 2 && e > 0 && e <= 3e3, s = n && e % 1e3 === 0 ? Math.floor(e / 1e3) : null, o = n && !s ? Math.floor(e / 100) : null,
|
|
1326
|
+
const e = parseInt(t), i = !isNaN(e) && t.length === 2, n = !isNaN(e) && t.length > 2 && e > 0 && e <= 3e3, s = n && e % 1e3 === 0 ? Math.floor(e / 1e3) : null, o = n && !s ? Math.floor(e / 100) : null, l = i || n ? Math.floor(e % 100 / 10) * 10 : null;
|
|
1327
1327
|
let u = [];
|
|
1328
|
-
return s ? u.push(this.convertNumberToWords(s).trim(), "thousands") : (o && u.push(this.convertNumberToWords(o).trim()),
|
|
1328
|
+
return s ? u.push(this.convertNumberToWords(s).trim(), "thousands") : (o && u.push(this.convertNumberToWords(o).trim()), l ? u.push(this.decades[l] || this.convertNumberToWords(l).trim() + "s") : o ? u.push("hundreds") : u.push(t)), u.join(" ");
|
|
1329
1329
|
}
|
|
1330
1330
|
/**
|
|
1331
1331
|
* Convert ordinal number to text.
|
|
@@ -1354,11 +1354,11 @@ class Ze {
|
|
|
1354
1354
|
const s = this.convertDecade(n);
|
|
1355
1355
|
return s === n ? i : s;
|
|
1356
1356
|
}), e = e.replace(/\b(\d+)\s*(st|nd|rd|th)(?=\s|[.,!?;:]|$)/gi, (i, n) => this.convertOrdinal(Number(n))), e = e.replace(/\b(\w*?)(\d+)([A-Za-z]+)\b/g, (i, n, s, o) => {
|
|
1357
|
-
const
|
|
1358
|
-
return `${n}${
|
|
1357
|
+
const l = this.convertNumberToWords(s);
|
|
1358
|
+
return `${n}${l} ${o}`;
|
|
1359
1359
|
}).replace(/\b([A-Za-z]+)(\d+)(\w*?)\b/g, (i, n, s, o) => {
|
|
1360
|
-
const
|
|
1361
|
-
return `${n} ${
|
|
1360
|
+
const l = this.convertNumberToWords(s);
|
|
1361
|
+
return `${n} ${l}${o}`;
|
|
1362
1362
|
}), e = e.replace(/-?(?:\d{1,3}(?:,\d{3})+|\d+)(\.\d+)?/g, (i, n) => {
|
|
1363
1363
|
let s = i, o = !1;
|
|
1364
1364
|
return /,/.test(s) && (s = s.replace(/,/g, ""), o = !0), n && (o = !0), this.convertNumberToWords(s, o);
|
|
@@ -1375,16 +1375,16 @@ class Ze {
|
|
|
1375
1375
|
for (; e.i < n.length; ) {
|
|
1376
1376
|
const s = n[e.i], o = this.rules[s];
|
|
1377
1377
|
if (o)
|
|
1378
|
-
for (let
|
|
1379
|
-
const u = o[
|
|
1378
|
+
for (let l = 0; l < o.length; l++) {
|
|
1379
|
+
const u = o[l];
|
|
1380
1380
|
if ((e.words.substring(0, e.i) + s.toLowerCase() + e.words.substring(e.i + 1)).match(u.regex)) {
|
|
1381
|
-
u.visemes.forEach((
|
|
1382
|
-
if (e.visemes.length && e.visemes[e.visemes.length - 1] ===
|
|
1383
|
-
const d = 0.7 * (this.visemeDurations[
|
|
1381
|
+
u.visemes.forEach((r) => {
|
|
1382
|
+
if (e.visemes.length && e.visemes[e.visemes.length - 1] === r) {
|
|
1383
|
+
const d = 0.7 * (this.visemeDurations[r] || 1);
|
|
1384
1384
|
e.durations[e.durations.length - 1] += d, i += d;
|
|
1385
1385
|
} else {
|
|
1386
|
-
const d = this.visemeDurations[
|
|
1387
|
-
e.visemes.push(
|
|
1386
|
+
const d = this.visemeDurations[r] || 1;
|
|
1387
|
+
e.visemes.push(r), e.times.push(i), e.durations.push(d), i += d;
|
|
1388
1388
|
}
|
|
1389
1389
|
}), e.i += u.move;
|
|
1390
1390
|
break;
|
|
@@ -1616,13 +1616,13 @@ class Ye {
|
|
|
1616
1616
|
};
|
|
1617
1617
|
Object.keys(this.rules).forEach((e) => {
|
|
1618
1618
|
this.rules[e] = this.rules[e].map((i) => {
|
|
1619
|
-
const n = i.indexOf("["), s = i.indexOf("]"), o = i.indexOf("="),
|
|
1619
|
+
const n = i.indexOf("["), s = i.indexOf("]"), o = i.indexOf("="), l = i.substring(0, n), u = i.substring(n + 1, s), a = i.substring(s + 1, o), h = i.substring(o + 1), r = { regex: "", move: 0, visemes: [] };
|
|
1620
1620
|
let d = "";
|
|
1621
|
-
d += [...
|
|
1621
|
+
d += [...l].map((g) => t[g] || g).join("");
|
|
1622
1622
|
const c = [...u];
|
|
1623
|
-
return c[0] = c[0].toLowerCase(), d += c.join(""),
|
|
1624
|
-
|
|
1625
|
-
}),
|
|
1623
|
+
return c[0] = c[0].toLowerCase(), d += c.join(""), r.move = c.length, d += [...a].map((g) => t[g] || g).join(""), r.regex = new RegExp(d), h.length && h.split(" ").forEach((g) => {
|
|
1624
|
+
r.visemes.push(g);
|
|
1625
|
+
}), r;
|
|
1626
1626
|
});
|
|
1627
1627
|
}), this.visemeDurations = {
|
|
1628
1628
|
aa: 1,
|
|
@@ -1731,7 +1731,7 @@ class Ye {
|
|
|
1731
1731
|
for (; e.i < n.length; ) {
|
|
1732
1732
|
const s = n[e.i], o = this.rules[s];
|
|
1733
1733
|
if (o) {
|
|
1734
|
-
let
|
|
1734
|
+
let l = !1;
|
|
1735
1735
|
for (let u = 0; u < o.length; u++) {
|
|
1736
1736
|
const a = o[u];
|
|
1737
1737
|
if ((e.words.substring(0, e.i) + s.toLowerCase() + e.words.substring(e.i + 1)).match(a.regex)) {
|
|
@@ -1743,11 +1743,11 @@ class Ye {
|
|
|
1743
1743
|
const c = this.visemeDurations[d] || 1;
|
|
1744
1744
|
e.visemes.push(d), e.times.push(i), e.durations.push(c), i += c;
|
|
1745
1745
|
}
|
|
1746
|
-
}), e.i += a.move,
|
|
1746
|
+
}), e.i += a.move, l = !0;
|
|
1747
1747
|
break;
|
|
1748
1748
|
}
|
|
1749
1749
|
}
|
|
1750
|
-
|
|
1750
|
+
l || (e.i++, i += this.specialDurations[s] || 0);
|
|
1751
1751
|
} else
|
|
1752
1752
|
e.i++, i += this.specialDurations[s] || 0;
|
|
1753
1753
|
}
|
|
@@ -2131,13 +2131,13 @@ class Qe {
|
|
|
2131
2131
|
};
|
|
2132
2132
|
Object.keys(this.rules).forEach((e) => {
|
|
2133
2133
|
this.rules[e] = this.rules[e].map((i) => {
|
|
2134
|
-
const n = i.indexOf("["), s = i.indexOf("]"), o = i.indexOf("="),
|
|
2134
|
+
const n = i.indexOf("["), s = i.indexOf("]"), o = i.indexOf("="), l = i.substring(0, n), u = i.substring(n + 1, s), a = i.substring(s + 1, o), h = i.substring(o + 1), r = { regex: "", move: 0, visemes: [] };
|
|
2135
2135
|
let d = "";
|
|
2136
|
-
d += [...
|
|
2136
|
+
d += [...l].map((g) => t[g] || g).join("");
|
|
2137
2137
|
const c = [...u];
|
|
2138
|
-
return c[0] = c[0].toLowerCase(), d += c.join(""),
|
|
2139
|
-
g &&
|
|
2140
|
-
}),
|
|
2138
|
+
return c[0] = c[0].toLowerCase(), d += c.join(""), r.move = c.length, d += [...a].map((g) => t[g] || g).join(""), r.regex = new RegExp(d, "i"), h.length && h.split(" ").forEach((g) => {
|
|
2139
|
+
g && r.visemes.push(g);
|
|
2140
|
+
}), r;
|
|
2141
2141
|
});
|
|
2142
2142
|
}), this.visemeDurations = {
|
|
2143
2143
|
aa: 1,
|
|
@@ -2266,7 +2266,7 @@ class Qe {
|
|
|
2266
2266
|
for (; e.i < n.length; ) {
|
|
2267
2267
|
const s = n[e.i], o = this.rules[s];
|
|
2268
2268
|
if (o) {
|
|
2269
|
-
let
|
|
2269
|
+
let l = !1;
|
|
2270
2270
|
for (let u = 0; u < o.length; u++) {
|
|
2271
2271
|
const a = o[u];
|
|
2272
2272
|
if ((e.words.substring(0, e.i) + s.toLowerCase() + e.words.substring(e.i + 1)).match(a.regex)) {
|
|
@@ -2278,11 +2278,11 @@ class Qe {
|
|
|
2278
2278
|
const c = this.visemeDurations[d] || 1;
|
|
2279
2279
|
e.visemes.push(d), e.times.push(i), e.durations.push(c), i += c;
|
|
2280
2280
|
}
|
|
2281
|
-
}), e.i += a.move,
|
|
2281
|
+
}), e.i += a.move, l = !0;
|
|
2282
2282
|
break;
|
|
2283
2283
|
}
|
|
2284
2284
|
}
|
|
2285
|
-
|
|
2285
|
+
l || (e.i++, i += this.specialDurations[s] || 0);
|
|
2286
2286
|
} else
|
|
2287
2287
|
e.i++, i += this.specialDurations[s] || 0;
|
|
2288
2288
|
}
|
|
@@ -2381,10 +2381,10 @@ class _e {
|
|
|
2381
2381
|
const e = [];
|
|
2382
2382
|
let i = parseFloat(t);
|
|
2383
2383
|
if (i === void 0) return t;
|
|
2384
|
-
let n = (s, o,
|
|
2384
|
+
let n = (s, o, l, u, a) => {
|
|
2385
2385
|
if (s < o) return s;
|
|
2386
2386
|
const h = Math.floor(s / o);
|
|
2387
|
-
return e.push(
|
|
2387
|
+
return e.push(l + (h === 1 ? u : this.numberToFinnishWords(h.toString()) + a)), s - h * o;
|
|
2388
2388
|
};
|
|
2389
2389
|
if (i < 0 && (e.push("miinus "), i = Math.abs(i)), i = n(i, 1e9, " ", "miljardi", " miljardia"), i = n(i, 1e6, " ", "miljoona", " miljoonaa"), i = n(i, 1e3, "", "tuhat", "tuhatta"), i = n(i, 100, " ", "sata", "sataa"), i > 20 && (i = n(i, 10, "", "", "kymmentä")), i >= 1) {
|
|
2390
2390
|
let s = Math.floor(i);
|
|
@@ -2395,8 +2395,8 @@ class _e {
|
|
|
2395
2395
|
if (s.length > 1) {
|
|
2396
2396
|
e.push(" pilkku");
|
|
2397
2397
|
let o = [...s[s.length - 1]];
|
|
2398
|
-
for (let
|
|
2399
|
-
e.push(" " + this.numbers[o[
|
|
2398
|
+
for (let l = 0; l < o.length; l++)
|
|
2399
|
+
e.push(" " + this.numbers[o[l]]);
|
|
2400
2400
|
}
|
|
2401
2401
|
}
|
|
2402
2402
|
return e.join("").trim();
|
|
@@ -2424,11 +2424,11 @@ class _e {
|
|
|
2424
2424
|
const o = this.visemes[n[s].toLowerCase()];
|
|
2425
2425
|
if (o)
|
|
2426
2426
|
if (e.visemes.length && e.visemes[e.visemes.length - 1] === o) {
|
|
2427
|
-
const
|
|
2428
|
-
e.durations[e.durations.length - 1] +=
|
|
2427
|
+
const l = 0.7 * (this.visemeDurations[o] || 1);
|
|
2428
|
+
e.durations[e.durations.length - 1] += l, i += l;
|
|
2429
2429
|
} else {
|
|
2430
|
-
const
|
|
2431
|
-
e.visemes.push(o), e.times.push(i), e.durations.push(
|
|
2430
|
+
const l = this.visemeDurations[o] || 1;
|
|
2431
|
+
e.visemes.push(o), e.times.push(i), e.durations.push(l), i += l;
|
|
2432
2432
|
}
|
|
2433
2433
|
else
|
|
2434
2434
|
i += this.specialDurations[n[s]] || 0;
|
|
@@ -2559,10 +2559,10 @@ class Je {
|
|
|
2559
2559
|
const e = [];
|
|
2560
2560
|
let i = parseFloat(t);
|
|
2561
2561
|
if (i === void 0) return t;
|
|
2562
|
-
let n = (s, o,
|
|
2562
|
+
let n = (s, o, l, u, a) => {
|
|
2563
2563
|
if (s < o) return s;
|
|
2564
2564
|
const h = Math.floor(s / o);
|
|
2565
|
-
return h === 1 ? e.push(this.numbers[1]) : e.push(this.numberToLithuanianWords(h.toString())), h % 10 === 1 ? e.push(
|
|
2565
|
+
return h === 1 ? e.push(this.numbers[1]) : e.push(this.numberToLithuanianWords(h.toString())), h % 10 === 1 ? e.push(l) : h % 10 === 0 || h % 100 > 10 && h % 100 < 20 ? e.push(a) : e.push(u), s - h * o;
|
|
2566
2566
|
};
|
|
2567
2567
|
i < 0 && (e.push("minus"), i = Math.abs(i)), i = n(i, 1e9, "milijardas", "milijardai", "milijardų"), i = n(i, 1e6, "milijonas", "milijonai", "milijonų"), i = n(i, 1e3, "tūkstantis", "tūkstančiai", "tūkstančių"), i = n(i, 100, "šimtas", "šimtai", "šimtų");
|
|
2568
2568
|
for (let s = this.tens.length - 1; s >= 1; s--)
|
|
@@ -2579,8 +2579,8 @@ class Je {
|
|
|
2579
2579
|
if (s.length > 1) {
|
|
2580
2580
|
e.push("kablelis");
|
|
2581
2581
|
let o = [...s[s.length - 1]];
|
|
2582
|
-
for (let
|
|
2583
|
-
e.push(this.numbers[o[
|
|
2582
|
+
for (let l = 0; l < o.length; l++)
|
|
2583
|
+
e.push(this.numbers[o[l]]);
|
|
2584
2584
|
}
|
|
2585
2585
|
}
|
|
2586
2586
|
return e.join(" ").trim();
|
|
@@ -2605,14 +2605,14 @@ class Je {
|
|
|
2605
2605
|
let e = { words: t, visemes: [], times: [], durations: [] }, i = 0;
|
|
2606
2606
|
const n = [...t];
|
|
2607
2607
|
for (let s = 0; s < n.length; s++) {
|
|
2608
|
-
const o = n[s].toLowerCase(),
|
|
2609
|
-
if (
|
|
2610
|
-
if (e.visemes.length && e.visemes[e.visemes.length - 1] ===
|
|
2608
|
+
const o = n[s].toLowerCase(), l = this.visemes[o];
|
|
2609
|
+
if (l)
|
|
2610
|
+
if (e.visemes.length && e.visemes[e.visemes.length - 1] === l) {
|
|
2611
2611
|
const u = 0.7 * (this.durations[o] || 1);
|
|
2612
2612
|
e.durations[e.durations.length - 1] += u, i += u;
|
|
2613
2613
|
} else {
|
|
2614
2614
|
const u = this.durations[o] || 1;
|
|
2615
|
-
e.visemes.push(
|
|
2615
|
+
e.visemes.push(l), e.times.push(i), e.durations.push(u), i += u;
|
|
2616
2616
|
}
|
|
2617
2617
|
else
|
|
2618
2618
|
i += this.pauses[n[s]] || 0;
|
|
@@ -2629,7 +2629,7 @@ const $e = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
|
|
|
2629
2629
|
fr: qe,
|
|
2630
2630
|
fi: Ke,
|
|
2631
2631
|
lt: $e
|
|
2632
|
-
},
|
|
2632
|
+
}, W = new f.Quaternion(), E = new f.Euler(), te = new f.Vector3(), ie = new f.Vector3(), Ae = new f.Box3();
|
|
2633
2633
|
new f.Matrix4();
|
|
2634
2634
|
new f.Matrix4();
|
|
2635
2635
|
new f.Vector3();
|
|
@@ -2712,8 +2712,8 @@ class we {
|
|
|
2712
2712
|
ttsVoice: "fi-FI-Standard-A",
|
|
2713
2713
|
ttsRate: 1,
|
|
2714
2714
|
ttsPitch: 0,
|
|
2715
|
-
ttsVolume: 0,
|
|
2716
|
-
mixerGainSpeech:
|
|
2715
|
+
ttsVolume: 0.3,
|
|
2716
|
+
mixerGainSpeech: 1.2,
|
|
2717
2717
|
mixerGainBackground: null,
|
|
2718
2718
|
lipsyncLang: "fi",
|
|
2719
2719
|
lipsyncModules: ["fi", "en", "lt"],
|
|
@@ -3568,18 +3568,18 @@ class we {
|
|
|
3568
3568
|
"LeftArm.scale": { x: 0, y: 0, z: 0 },
|
|
3569
3569
|
"RightArm.scale": { x: 0, y: 0, z: 0 }
|
|
3570
3570
|
}
|
|
3571
|
-
}, ["Left", "Right"].forEach((
|
|
3571
|
+
}, ["Left", "Right"].forEach((l) => {
|
|
3572
3572
|
["Leg", "UpLeg", "Arm", "ForeArm", "Hand"].forEach((u) => {
|
|
3573
|
-
this.poseDelta.props[
|
|
3573
|
+
this.poseDelta.props[l + u + ".quaternion"] = { x: 0, y: 0, z: 0 };
|
|
3574
3574
|
}), ["HandThumb", "HandIndex", "HandMiddle", "HandRing", "HandPinky"].forEach((u) => {
|
|
3575
|
-
this.poseDelta.props[
|
|
3575
|
+
this.poseDelta.props[l + u + "1.quaternion"] = { x: 0, y: 0, z: 0 }, this.poseDelta.props[l + u + "2.quaternion"] = { x: 0, y: 0, z: 0 }, this.poseDelta.props[l + u + "3.quaternion"] = { x: 0, y: 0, z: 0 };
|
|
3576
3576
|
});
|
|
3577
3577
|
});
|
|
3578
3578
|
const i = /* @__PURE__ */ new Set();
|
|
3579
|
-
Object.values(this.poseTemplates).forEach((
|
|
3580
|
-
Object.keys(this.propsToThreeObjects(
|
|
3581
|
-
}), Object.keys(this.poseDelta.props).forEach((
|
|
3582
|
-
i.add(
|
|
3579
|
+
Object.values(this.poseTemplates).forEach((l) => {
|
|
3580
|
+
Object.keys(this.propsToThreeObjects(l.props)).forEach((u) => i.add(u));
|
|
3581
|
+
}), Object.keys(this.poseDelta.props).forEach((l) => {
|
|
3582
|
+
i.add(l);
|
|
3583
3583
|
}), this.posePropNames = [...i], this.poseName = "side", this.poseWeightOnLeft = !0, this.gesture = null, this.poseCurrentTemplate = this.poseTemplates[this.poseName], this.poseStraight = this.propsToThreeObjects(this.poseTemplates.straight.props), this.poseBase = this.poseFactory(this.poseCurrentTemplate), this.poseTarget = this.poseFactory(this.poseCurrentTemplate), this.poseAvatar = null, this.avatarHeight = 1.7, this.animTemplateEyes = {
|
|
3584
3584
|
name: "eyes",
|
|
3585
3585
|
idle: { alt: [
|
|
@@ -3843,8 +3843,8 @@ class we {
|
|
|
3843
3843
|
speaking: { dt: [[0, 1e3, 0]], vs: { bodyRotateX: [[-0.05, 0.15, 1, 2]], bodyRotateY: [[-0.1, 0.1]], bodyRotateZ: [[-0.1, 0.1]] } }
|
|
3844
3844
|
},
|
|
3845
3845
|
this.animTemplateEyes,
|
|
3846
|
-
this.deepCopy(this.animTemplateBlink, (
|
|
3847
|
-
|
|
3846
|
+
this.deepCopy(this.animTemplateBlink, (l) => {
|
|
3847
|
+
l.alt[0].delay[0] = l.alt[1].delay[0] = 2e3;
|
|
3848
3848
|
}),
|
|
3849
3849
|
{ name: "mouth", delay: [1e3, 5e3], dt: [[100, 500], [100, 5e3, 2]], vs: { mouthLeft: [[0, 0.3, 2]], mouthRollLower: [[0, 0.3, 2]], mouthRollUpper: [[0, 0.3, 2]], mouthStretchLeft: [[0, 0.3]], mouthStretchRight: [[0, 0.3]], mouthPucker: [[0, 0.3]] } },
|
|
3850
3850
|
{ name: "misc", delay: [100, 5e3], dt: [[500, 1e3], [1e3, 5e3, 2]], vs: { eyeSquintLeft: [[0, 0.3, 2]], eyeSquintRight: [[0, 0.3, 2]], browInnerUp: [[0.3, 0.6, 2]], browOuterUpLeft: [[0.1, 0.3, 2]], browOuterUpRight: [[0.1, 0.3, 2]] } }
|
|
@@ -3975,8 +3975,8 @@ class we {
|
|
|
3975
3975
|
headRotateY: -1,
|
|
3976
3976
|
headRotateZ: -1
|
|
3977
3977
|
}, this.mtMaxDefault = 1, this.mtMaxExceptions = {}, this.mtLimits = {
|
|
3978
|
-
eyeBlinkLeft: (
|
|
3979
|
-
eyeBlinkRight: (
|
|
3978
|
+
eyeBlinkLeft: (l) => Math.max(l, (this.mtAvatar.eyesLookDown.value + this.mtAvatar.browDownLeft.value) / 2),
|
|
3979
|
+
eyeBlinkRight: (l) => Math.max(l, (this.mtAvatar.eyesLookDown.value + this.mtAvatar.browDownRight.value) / 2)
|
|
3980
3980
|
}, this.mtOnchange = {
|
|
3981
3981
|
eyesLookDown: () => {
|
|
3982
3982
|
this.mtAvatar.eyeBlinkLeft.needsUpdate = !0, this.mtAvatar.eyeBlinkRight.needsUpdate = !0;
|
|
@@ -4015,8 +4015,8 @@ class we {
|
|
|
4015
4015
|
{ key: "eyesClosed", mix: { eyeBlinkLeft: 1, eyeBlinkRight: 1 } },
|
|
4016
4016
|
{ key: "eyesLookUp", mix: { eyeLookUpLeft: 1, eyeLookUpRight: 1 } },
|
|
4017
4017
|
{ key: "eyesLookDown", mix: { eyeLookDownLeft: 1, eyeLookDownRight: 1 } }
|
|
4018
|
-
], this.animQueue = [], this.animClips = [], this.animPoses = [], this.animFrameDur = 1e3 / this.opt.modelFPS, this.animClock = 0, this.animSlowdownRate = 1, this.animTimeLast = 0, this.easing = this.sigmoidFactory(5), this.lipsync = {}, this.opt.lipsyncModules.forEach((
|
|
4019
|
-
this.lipsyncGetProcessor(
|
|
4018
|
+
], this.animQueue = [], this.animClips = [], this.animPoses = [], this.animFrameDur = 1e3 / this.opt.modelFPS, this.animClock = 0, this.animSlowdownRate = 1, this.animTimeLast = 0, this.easing = this.sigmoidFactory(5), this.lipsync = {}, this.opt.lipsyncModules.forEach((l) => {
|
|
4019
|
+
this.lipsyncGetProcessor(l);
|
|
4020
4020
|
}), this.visemeNames = [
|
|
4021
4021
|
"aa",
|
|
4022
4022
|
"E",
|
|
@@ -4036,12 +4036,12 @@ class we {
|
|
|
4036
4036
|
], this.segmenter = new Intl.Segmenter("en", { granularity: "grapheme" }), this.initAudioGraph(), this.audioPlaylist = [], this.volumeFrequencyData = new Uint8Array(16), this.volumeMax = 0, this.volumeHeadBase = 0, this.volumeHeadTarget = 0, this.volumeHeadCurrent = 0, this.volumeHeadVelocity = 0.15, this.volumeHeadEasing = this.sigmoidFactory(3), this.isListening = !1, this.listeningAnalyzer = null, this.listeningActive = !1, this.listeningVolume = 0, this.listeningSilenceThresholdLevel = this.opt.listeningSilenceThresholdLevel, this.listeningSilenceThresholdMs = this.opt.listeningSilenceThresholdMs, this.listeningSilenceDurationMax = this.opt.listeningSilenceDurationMax, this.listeningActiveThresholdLevel = this.opt.listeningActiveThresholdLevel, this.listeningActiveThresholdMs = this.opt.listeningActiveThresholdMs, this.listeningActiveDurationMax = this.opt.listeningActiveDurationMax, this.listeningTimer = 0, this.listeningTimerTotal = 0, this.dracoEnabled = this.opt.dracoEnabled, this.dracoDecoderPath = this.opt.dracoDecoderPath;
|
|
4037
4037
|
const n = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
|
|
4038
4038
|
this.b64Lookup = typeof Uint8Array > "u" ? [] : new Uint8Array(256);
|
|
4039
|
-
for (let
|
|
4039
|
+
for (let l = 0; l < n.length; l++) this.b64Lookup[n.charCodeAt(l)] = l;
|
|
4040
4040
|
if (this.stateName = "idle", this.speechQueue = [], this.isSpeaking = !1, this.isListening = !1, this.opt.ttsEndpoint) {
|
|
4041
|
-
let
|
|
4042
|
-
if (
|
|
4041
|
+
let l = new Audio();
|
|
4042
|
+
if (l.canPlayType("audio/ogg"))
|
|
4043
4043
|
this.ttsAudioEncoding = "OGG-OPUS";
|
|
4044
|
-
else if (
|
|
4044
|
+
else if (l.canPlayType("audio/mp3"))
|
|
4045
4045
|
this.ttsAudioEncoding = "MP3";
|
|
4046
4046
|
else
|
|
4047
4047
|
throw new Error("There was no support for either OGG or MP3 audio.");
|
|
@@ -4061,8 +4061,8 @@ class we {
|
|
|
4061
4061
|
0,
|
|
4062
4062
|
this.opt.lightSpotDispersion
|
|
4063
4063
|
), this.setLighting(this.opt);
|
|
4064
|
-
const
|
|
4065
|
-
|
|
4064
|
+
const l = new f.PMREMGenerator(this.renderer);
|
|
4065
|
+
l.compileEquirectangularShader(), this.scene.environment = l.fromScene(new De()).texture, this.resizeobserver = new ResizeObserver(this.onResize.bind(this)), this.resizeobserver.observe(this.nodeAvatar), this.controls = new Fe(this.camera, this.renderer.domElement), this.controls.enableZoom = this.opt.cameraZoomEnable, this.controls.enableRotate = this.opt.cameraRotateEnable, this.controls.enablePan = this.opt.cameraPanEnable, this.controls.minDistance = 2, this.controls.maxDistance = 2e3, this.controls.autoRotateSpeed = 0, this.controls.autoRotate = !1, this.controls.update(), this.cameraClock = null;
|
|
4066
4066
|
}
|
|
4067
4067
|
this.ikMesh = new f.SkinnedMesh();
|
|
4068
4068
|
const s = {
|
|
@@ -4077,9 +4077,9 @@ class we {
|
|
|
4077
4077
|
RightHand: "RightForeArm",
|
|
4078
4078
|
RightHandMiddle1: "RightHand"
|
|
4079
4079
|
}, o = [];
|
|
4080
|
-
Object.entries(s).forEach((
|
|
4080
|
+
Object.entries(s).forEach((l, u) => {
|
|
4081
4081
|
const a = new f.Bone();
|
|
4082
|
-
a.name =
|
|
4082
|
+
a.name = l[0], l[1] ? this.ikMesh.getObjectByName(l[1]).add(a) : this.ikMesh.add(a), o.push(a);
|
|
4083
4083
|
}), this.ikMesh.bind(new f.Skeleton(o)), this.dynamicbones = new Ve(), this.isStreaming = !1, this.streamWorkletNode = null, this.streamAudioStartTime = null, this.streamWaitForAudioChunks = !0, this.streamLipsyncLang = null, this.streamLipsyncType = "visemes", this.streamLipsyncQueue = [];
|
|
4084
4084
|
}
|
|
4085
4085
|
/**
|
|
@@ -4126,9 +4126,9 @@ class we {
|
|
|
4126
4126
|
let e = 3 * t.length / 4;
|
|
4127
4127
|
t[t.length - 1] === "=" && (e--, t[t.length - 2] === "=" && e--);
|
|
4128
4128
|
const i = new ArrayBuffer(e), n = new Uint8Array(i);
|
|
4129
|
-
let s, o = 0,
|
|
4129
|
+
let s, o = 0, l, u, a, h;
|
|
4130
4130
|
for (s = 0; s < t.length; s += 4)
|
|
4131
|
-
|
|
4131
|
+
l = this.b64Lookup[t.charCodeAt(s)], u = this.b64Lookup[t.charCodeAt(s + 1)], a = this.b64Lookup[t.charCodeAt(s + 2)], h = this.b64Lookup[t.charCodeAt(s + 3)], n[o++] = l << 2 | u >> 4, n[o++] = (u & 15) << 4 | a >> 2, n[o++] = (a & 3) << 6 | h & 63;
|
|
4132
4132
|
return i;
|
|
4133
4133
|
}
|
|
4134
4134
|
/**
|
|
@@ -4169,8 +4169,8 @@ class we {
|
|
|
4169
4169
|
const e = {};
|
|
4170
4170
|
for (let [i, n] of Object.entries(t)) {
|
|
4171
4171
|
const s = i.split(".");
|
|
4172
|
-
let o = Array.isArray(n.x) ? this.gaussianRandom(...n.x) : n.x,
|
|
4173
|
-
s[1] === "position" || s[1] === "scale" ? e[i] = new f.Vector3(o,
|
|
4172
|
+
let o = Array.isArray(n.x) ? this.gaussianRandom(...n.x) : n.x, l = Array.isArray(n.y) ? this.gaussianRandom(...n.y) : n.y, u = Array.isArray(n.z) ? this.gaussianRandom(...n.z) : n.z;
|
|
4173
|
+
s[1] === "position" || s[1] === "scale" ? e[i] = new f.Vector3(o, l, u) : s[1] === "rotation" ? (i = s[0] + ".quaternion", e[i] = new f.Quaternion().setFromEuler(new f.Euler(o, l, u, "XYZ")).normalize()) : s[1] === "quaternion" && (e[i] = new f.Quaternion(o, l, u, n.w).normalize());
|
|
4174
4174
|
}
|
|
4175
4175
|
return e;
|
|
4176
4176
|
}
|
|
@@ -4198,14 +4198,14 @@ class we {
|
|
|
4198
4198
|
t.forEach((s) => {
|
|
4199
4199
|
if (!n && s.morphTargetDictionary.hasOwnProperty(e)) return;
|
|
4200
4200
|
const o = s.geometry;
|
|
4201
|
-
let
|
|
4201
|
+
let l = null, u = null;
|
|
4202
4202
|
for (const [a, h] of Object.entries(i))
|
|
4203
4203
|
if (s.morphTargetDictionary.hasOwnProperty(a)) {
|
|
4204
|
-
const
|
|
4205
|
-
|
|
4204
|
+
const r = s.morphTargetDictionary[a], d = o.morphAttributes.position[r], c = o.morphAttributes.normal?.[r];
|
|
4205
|
+
l || (l = new f.Float32BufferAttribute(d.count * 3, 3), c && (u = new f.Float32BufferAttribute(d.count * 3, 3)));
|
|
4206
4206
|
for (let g = 0; g < d.count; g++) {
|
|
4207
|
-
const y =
|
|
4208
|
-
|
|
4207
|
+
const y = l.getX(g) + d.getX(g) * h, x = l.getY(g) + d.getY(g) * h, L = l.getZ(g) + d.getZ(g) * h;
|
|
4208
|
+
l.setXYZ(g, y, x, L);
|
|
4209
4209
|
}
|
|
4210
4210
|
if (c)
|
|
4211
4211
|
for (let g = 0; g < d.count; g++) {
|
|
@@ -4213,8 +4213,8 @@ class we {
|
|
|
4213
4213
|
u.setXYZ(g, y, x, L);
|
|
4214
4214
|
}
|
|
4215
4215
|
}
|
|
4216
|
-
if (
|
|
4217
|
-
o.morphAttributes.position.push(
|
|
4216
|
+
if (l) {
|
|
4217
|
+
o.morphAttributes.position.push(l), u && o.morphAttributes.normal.push(u);
|
|
4218
4218
|
const a = o.morphAttributes.position.length - 1;
|
|
4219
4219
|
s.morphTargetInfluences[a] = 0, s.morphTargetDictionary[e] = a;
|
|
4220
4220
|
}
|
|
@@ -4248,9 +4248,9 @@ class we {
|
|
|
4248
4248
|
}), this.mtExtras.forEach((a) => {
|
|
4249
4249
|
o.has(a.key) || (this.addMixedMorphTarget(this.morphs, a.key, a.mix), o.add(a.key));
|
|
4250
4250
|
});
|
|
4251
|
-
const
|
|
4251
|
+
const l = {};
|
|
4252
4252
|
if (o.forEach((a) => {
|
|
4253
|
-
|
|
4253
|
+
l[a] = {
|
|
4254
4254
|
fixed: null,
|
|
4255
4255
|
realtime: null,
|
|
4256
4256
|
system: null,
|
|
@@ -4270,17 +4270,17 @@ class we {
|
|
|
4270
4270
|
baseline: this.avatar.baseline?.hasOwnProperty(a) ? this.avatar.baseline[a] : this.mtBaselineExceptions.hasOwnProperty(a) ? this.mtBaselineExceptions[a] : this.mtBaselineDefault,
|
|
4271
4271
|
ms: [],
|
|
4272
4272
|
is: []
|
|
4273
|
-
},
|
|
4273
|
+
}, l[a].value = l[a].baseline, l[a].applied = l[a].baseline;
|
|
4274
4274
|
const h = this.mtAvatar[a];
|
|
4275
|
-
h && ["fixed", "system", "systemd", "realtime", "base", "v", "value", "applied"].forEach((
|
|
4276
|
-
|
|
4277
|
-
}), this.morphs.forEach((
|
|
4278
|
-
const d =
|
|
4279
|
-
d !== void 0 && (
|
|
4275
|
+
h && ["fixed", "system", "systemd", "realtime", "base", "v", "value", "applied"].forEach((r) => {
|
|
4276
|
+
l[a][r] = h[r];
|
|
4277
|
+
}), this.morphs.forEach((r) => {
|
|
4278
|
+
const d = r.morphTargetDictionary[a];
|
|
4279
|
+
d !== void 0 && (l[a].ms.push(r.morphTargetInfluences), l[a].is.push(d), r.morphTargetInfluences[d] = l[a].applied);
|
|
4280
4280
|
});
|
|
4281
|
-
}), this.mtAvatar =
|
|
4282
|
-
const h = a.split("."),
|
|
4283
|
-
this.poseAvatar.props[a] =
|
|
4281
|
+
}), this.mtAvatar = l, this.poseAvatar = { props: {} }, this.posePropNames.forEach((a) => {
|
|
4282
|
+
const h = a.split("."), r = this.armature.getObjectByName(h[0]);
|
|
4283
|
+
this.poseAvatar.props[a] = r[h[1]], this.poseBase.props.hasOwnProperty(a) ? this.poseAvatar.props[a].copy(this.poseBase.props[a]) : this.poseBase.props[a] = this.poseAvatar.props[a].clone(), this.poseDelta.props.hasOwnProperty(a) && !this.poseTarget.props.hasOwnProperty(a) && (this.poseTarget.props[a] = this.poseAvatar.props[a].clone()), this.poseTarget.props[a].t = this.animClock, this.poseTarget.props[a].d = 2e3;
|
|
4284
4284
|
}), this.ikMesh.traverse((a) => {
|
|
4285
4285
|
a.isBone && a.position.copy(this.armature.getObjectByName(a.name).position);
|
|
4286
4286
|
}), this.isAvatarOnly ? this.scene && this.scene.add(this.armature) : (this.scene.add(n.scene), this.scene.add(this.lightAmbient), this.scene.add(this.lightDirect), this.scene.add(this.lightSpot), this.lightSpot.target = this.armature.getObjectByName("Head")), t.hasOwnProperty("modelDynamicBones"))
|
|
@@ -4319,22 +4319,22 @@ class we {
|
|
|
4319
4319
|
return;
|
|
4320
4320
|
}
|
|
4321
4321
|
if (this.viewName = t || this.viewName, e = e || {}, this.isAvatarOnly) return;
|
|
4322
|
-
const i = e.hasOwnProperty("cameraX") ? e.cameraX : this.opt.cameraX, n = e.hasOwnProperty("cameraY") ? e.cameraY : this.opt.cameraY, s = e.hasOwnProperty("cameraDistance") ? e.cameraDistance : this.opt.cameraDistance, o = e.hasOwnProperty("cameraRotateX") ? e.cameraRotateX : this.opt.cameraRotateX,
|
|
4323
|
-
let a = -i * Math.tan(u / 2), h = (1 - n) * Math.tan(u / 2),
|
|
4322
|
+
const i = e.hasOwnProperty("cameraX") ? e.cameraX : this.opt.cameraX, n = e.hasOwnProperty("cameraY") ? e.cameraY : this.opt.cameraY, s = e.hasOwnProperty("cameraDistance") ? e.cameraDistance : this.opt.cameraDistance, o = e.hasOwnProperty("cameraRotateX") ? e.cameraRotateX : this.opt.cameraRotateX, l = e.hasOwnProperty("cameraRotateY") ? e.cameraRotateY : this.opt.cameraRotateY, u = this.camera.fov * (Math.PI / 180);
|
|
4323
|
+
let a = -i * Math.tan(u / 2), h = (1 - n) * Math.tan(u / 2), r = s;
|
|
4324
4324
|
switch (this.viewName) {
|
|
4325
4325
|
case "head":
|
|
4326
|
-
|
|
4326
|
+
r += 2, h = h * r + 4 * this.avatarHeight / 5;
|
|
4327
4327
|
break;
|
|
4328
4328
|
case "upper":
|
|
4329
|
-
|
|
4329
|
+
r += 4.5, h = h * r + 2 * this.avatarHeight / 3;
|
|
4330
4330
|
break;
|
|
4331
4331
|
case "mid":
|
|
4332
|
-
|
|
4332
|
+
r += 8, h = h * r + this.avatarHeight / 3;
|
|
4333
4333
|
break;
|
|
4334
4334
|
default:
|
|
4335
|
-
|
|
4335
|
+
r += 12, h = h * r;
|
|
4336
4336
|
}
|
|
4337
|
-
a = a *
|
|
4337
|
+
a = a * r, this.controlsEnd = new f.Vector3(a, h, 0), this.cameraEnd = new f.Vector3(a, h, r).applyEuler(new f.Euler(o, l, 0)), this.cameraClock === null && (this.controls.target.copy(this.controlsEnd), this.camera.position.copy(this.cameraEnd)), this.controlsStart = this.controls.target.clone(), this.cameraStart = this.camera.position.clone(), this.cameraClock = 0;
|
|
4338
4338
|
}
|
|
4339
4339
|
/**
|
|
4340
4340
|
* Change light colors and intensities.
|
|
@@ -4376,7 +4376,7 @@ class we {
|
|
|
4376
4376
|
if (e.x === 0 && e.y === 0 && e.z === 0) continue;
|
|
4377
4377
|
E.set(e.x, e.y, e.z);
|
|
4378
4378
|
const i = this.poseAvatar.props[t];
|
|
4379
|
-
i.isQuaternion ? (
|
|
4379
|
+
i.isQuaternion ? (W.setFromEuler(E), i.multiply(W)) : i.isVector3 && i.add(E);
|
|
4380
4380
|
}
|
|
4381
4381
|
}
|
|
4382
4382
|
/**
|
|
@@ -4431,16 +4431,16 @@ class we {
|
|
|
4431
4431
|
"HandMiddle",
|
|
4432
4432
|
"HandRing",
|
|
4433
4433
|
"HandPinky"
|
|
4434
|
-
].forEach((h,
|
|
4435
|
-
|
|
4434
|
+
].forEach((h, r) => {
|
|
4435
|
+
r === 0 ? (this.poseDelta.props[o + h + "1.quaternion"].x = 0, this.poseDelta.props[o + h + "2.quaternion"].z = (o === "Left" ? -1 : 1) * i.applied, this.poseDelta.props[o + h + "3.quaternion"].z = (o === "Left" ? -1 : 1) * i.applied) : (this.poseDelta.props[o + h + "1.quaternion"].x = i.applied, this.poseDelta.props[o + h + "2.quaternion"].x = 1.5 * i.applied, this.poseDelta.props[o + h + "3.quaternion"].x = 1.5 * i.applied);
|
|
4436
4436
|
});
|
|
4437
4437
|
break;
|
|
4438
4438
|
case "chestInhale":
|
|
4439
|
-
const
|
|
4439
|
+
const l = i.applied / 20, u = { x: l, y: l / 2, z: 3 * l }, a = { x: 1 / (1 + l) - 1, y: 1 / (1 + l / 2) - 1, z: 1 / (1 + 3 * l) - 1 };
|
|
4440
4440
|
this.poseDelta.props["Spine1.scale"] = u, this.poseDelta.props["Neck.scale"] = a, this.poseDelta.props["LeftArm.scale"] = a, this.poseDelta.props["RightArm.scale"] = a;
|
|
4441
4441
|
break;
|
|
4442
4442
|
default:
|
|
4443
|
-
for (let h = 0,
|
|
4443
|
+
for (let h = 0, r = i.ms.length; h < r; h++)
|
|
4444
4444
|
i.ms[h][i.is[h]] = i.applied;
|
|
4445
4445
|
}
|
|
4446
4446
|
}
|
|
@@ -4456,8 +4456,8 @@ class we {
|
|
|
4456
4456
|
return Object.entries(t).forEach((n, s) => {
|
|
4457
4457
|
const o = n[0].split(".");
|
|
4458
4458
|
if (o[1] === "position" || o[1] === "rotation" || o[1] === "quaternion") {
|
|
4459
|
-
const
|
|
4460
|
-
i += (s ? ", " : "") + "'" +
|
|
4459
|
+
const l = o[1] === "quaternion" ? o[0] + ".rotation" : n[0], u = n[1].isQuaternion ? new f.Euler().setFromQuaternion(n[1]) : n[1];
|
|
4460
|
+
i += (s ? ", " : "") + "'" + l + "':{", i += "x:" + Math.round(u.x * e) / e, i += ", y:" + Math.round(u.y * e) / e, i += ", z:" + Math.round(u.z * e) / e, i += "}";
|
|
4461
4461
|
}
|
|
4462
4462
|
}), i += "}", i;
|
|
4463
4463
|
}
|
|
@@ -4509,8 +4509,8 @@ class we {
|
|
|
4509
4509
|
};
|
|
4510
4510
|
for (const [n, s] of Object.entries(i.props)) {
|
|
4511
4511
|
if (this.opt.modelMovementFactor < 1 && t.standing && (n === "Hips.quaternion" || n === "Spine.quaternion" || n === "Spine1.quaternion" || n === "Spine2.quaternion" || n === "Neck.quaternion" || n === "LeftUpLeg.quaternion" || n === "LeftLeg.quaternion" || n === "RightUpLeg.quaternion" || n === "RightLeg.quaternion")) {
|
|
4512
|
-
const o = this.poseStraight[n],
|
|
4513
|
-
s.rotateTowards(o, (1 - this.opt.modelMovementFactor) *
|
|
4512
|
+
const o = this.poseStraight[n], l = s.angleTo(o);
|
|
4513
|
+
s.rotateTowards(o, (1 - this.opt.modelMovementFactor) * l);
|
|
4514
4514
|
}
|
|
4515
4515
|
s.t = this.animClock, s.d = e;
|
|
4516
4516
|
}
|
|
@@ -4527,10 +4527,10 @@ class we {
|
|
|
4527
4527
|
if (i ? (this.poseCurrentTemplate = this.poseTemplates.oneknee, setTimeout(() => {
|
|
4528
4528
|
this.setPoseFromTemplate(t, e);
|
|
4529
4529
|
}, o)) : this.poseCurrentTemplate = t || this.poseCurrentTemplate, this.poseTarget = this.poseFactory(this.poseCurrentTemplate, o), this.poseWeightOnLeft = !0, (!n && !s || n && s) && (this.poseTarget.props = this.mirrorPose(this.poseTarget.props), this.poseWeightOnLeft = !this.poseWeightOnLeft), this.gesture)
|
|
4530
|
-
for (let [
|
|
4531
|
-
this.poseTarget.props.hasOwnProperty(
|
|
4532
|
-
Object.keys(this.poseDelta.props).forEach((
|
|
4533
|
-
this.poseTarget.props.hasOwnProperty(
|
|
4530
|
+
for (let [l, u] of Object.entries(this.gesture))
|
|
4531
|
+
this.poseTarget.props.hasOwnProperty(l) && (this.poseTarget.props[l].copy(u), this.poseTarget.props[l].t = u.t, this.poseTarget.props[l].d = u.d);
|
|
4532
|
+
Object.keys(this.poseDelta.props).forEach((l) => {
|
|
4533
|
+
this.poseTarget.props.hasOwnProperty(l) || (this.poseTarget.props[l] = this.poseBase.props[l].clone(), this.poseTarget.props[l].t = this.animClock, this.poseTarget.props[l].d = o);
|
|
4534
4534
|
});
|
|
4535
4535
|
}
|
|
4536
4536
|
/**
|
|
@@ -4958,47 +4958,47 @@ class we {
|
|
|
4958
4958
|
*/
|
|
4959
4959
|
animFactory(t, e = !1, i = 1, n = 1, s = !1) {
|
|
4960
4960
|
const o = { template: t, ts: [0], vs: {} };
|
|
4961
|
-
let
|
|
4961
|
+
let l = t;
|
|
4962
4962
|
for (; ; )
|
|
4963
|
-
if (
|
|
4964
|
-
|
|
4965
|
-
else if (
|
|
4966
|
-
|
|
4967
|
-
else if (
|
|
4968
|
-
|
|
4969
|
-
else if (
|
|
4970
|
-
|
|
4971
|
-
else if (this.avatar.body &&
|
|
4972
|
-
|
|
4973
|
-
else if (
|
|
4974
|
-
let a =
|
|
4975
|
-
if (
|
|
4963
|
+
if (l.hasOwnProperty(this.stateName))
|
|
4964
|
+
l = l[this.stateName];
|
|
4965
|
+
else if (l.hasOwnProperty(this.moodName))
|
|
4966
|
+
l = l[this.moodName];
|
|
4967
|
+
else if (l.hasOwnProperty(this.poseName))
|
|
4968
|
+
l = l[this.poseName];
|
|
4969
|
+
else if (l.hasOwnProperty(this.viewName))
|
|
4970
|
+
l = l[this.viewName];
|
|
4971
|
+
else if (this.avatar.body && l.hasOwnProperty(this.avatar.body))
|
|
4972
|
+
l = l[this.avatar.body];
|
|
4973
|
+
else if (l.hasOwnProperty("alt")) {
|
|
4974
|
+
let a = l.alt[0];
|
|
4975
|
+
if (l.alt.length > 1) {
|
|
4976
4976
|
const h = Math.random();
|
|
4977
|
-
let
|
|
4978
|
-
for (let d = 0; d <
|
|
4979
|
-
let c = this.valueFn(
|
|
4980
|
-
if (
|
|
4981
|
-
a =
|
|
4977
|
+
let r = 0;
|
|
4978
|
+
for (let d = 0; d < l.alt.length; d++) {
|
|
4979
|
+
let c = this.valueFn(l.alt[d].p);
|
|
4980
|
+
if (r += c === void 0 ? (1 - r) / (l.alt.length - 1 - d) : c, h < r) {
|
|
4981
|
+
a = l.alt[d];
|
|
4982
4982
|
break;
|
|
4983
4983
|
}
|
|
4984
4984
|
}
|
|
4985
4985
|
}
|
|
4986
|
-
|
|
4986
|
+
l = a;
|
|
4987
4987
|
} else
|
|
4988
4988
|
break;
|
|
4989
|
-
let u = this.valueFn(
|
|
4990
|
-
if (Array.isArray(u) && (u = this.gaussianRandom(...u)),
|
|
4991
|
-
|
|
4992
|
-
let
|
|
4993
|
-
Array.isArray(
|
|
4989
|
+
let u = this.valueFn(l.delay) || 0;
|
|
4990
|
+
if (Array.isArray(u) && (u = this.gaussianRandom(...u)), l.hasOwnProperty("dt"))
|
|
4991
|
+
l.dt.forEach((a, h) => {
|
|
4992
|
+
let r = this.valueFn(a);
|
|
4993
|
+
Array.isArray(r) && (r = this.gaussianRandom(...r)), o.ts[h + 1] = o.ts[h] + r;
|
|
4994
4994
|
});
|
|
4995
4995
|
else {
|
|
4996
|
-
let a = Object.values(
|
|
4996
|
+
let a = Object.values(l.vs).reduce((h, r) => r.length > h ? r.length : h, 0);
|
|
4997
4997
|
o.ts = Array(a + 1).fill(0);
|
|
4998
4998
|
}
|
|
4999
4999
|
s ? o.ts = o.ts.map((a) => u + a * i) : o.ts = o.ts.map((a) => this.animClock + u + a * i);
|
|
5000
|
-
for (let [a, h] of Object.entries(
|
|
5001
|
-
const
|
|
5000
|
+
for (let [a, h] of Object.entries(l.vs)) {
|
|
5001
|
+
const r = this.getBaselineValue(a), d = h.map((c) => (c = this.valueFn(c), c === null ? null : typeof c == "function" ? c : typeof c == "string" || c instanceof String ? c.slice() : Array.isArray(c) ? a === "gesture" ? c.slice() : (r === void 0 ? 0 : r) + n * this.gaussianRandom(...c) : typeof c == "boolean" ? c : c instanceof Object && c.constructor === Object ? Object.assign({}, c) : (r === void 0 ? 0 : r) + n * c));
|
|
5002
5002
|
a === "eyesRotateY" ? (o.vs.eyeLookOutLeft = [null, ...d.map((c) => c > 0 ? c : 0)], o.vs.eyeLookInLeft = [null, ...d.map((c) => c > 0 ? 0 : -c)], o.vs.eyeLookOutRight = [null, ...d.map((c) => c > 0 ? 0 : -c)], o.vs.eyeLookInRight = [null, ...d.map((c) => c > 0 ? c : 0)]) : a === "eyesRotateX" ? (o.vs.eyesLookDown = [null, ...d.map((c) => c > 0 ? c : 0)], o.vs.eyesLookUp = [null, ...d.map((c) => c > 0 ? 0 : -c)]) : o.vs[a] = [null, ...d];
|
|
5003
5003
|
}
|
|
5004
5004
|
for (let a of Object.keys(o.vs))
|
|
@@ -5017,8 +5017,8 @@ class we {
|
|
|
5017
5017
|
*/
|
|
5018
5018
|
valueAnimationSeq(t, e, i, n, s, o = null) {
|
|
5019
5019
|
t = this.valueFn(t), e = this.valueFn(e), s < i && (s = i), s > n && (s = n);
|
|
5020
|
-
let
|
|
5021
|
-
return o && (
|
|
5020
|
+
let l = (e - t) / (n - i);
|
|
5021
|
+
return o && (l *= o((s - i) / (n - i))), l * s + (t - l * i);
|
|
5022
5022
|
}
|
|
5023
5023
|
/**
|
|
5024
5024
|
* Return gaussian distributed random value between start and end with skew.
|
|
@@ -5071,22 +5071,22 @@ class we {
|
|
|
5071
5071
|
this.animTimeLast = t;
|
|
5072
5072
|
}
|
|
5073
5073
|
e = e / this.animSlowdownRate, this.animClock += e, this.maintainLockedPosition();
|
|
5074
|
-
let i, n, s, o,
|
|
5074
|
+
let i, n, s, o, l = 0;
|
|
5075
5075
|
if (this.stats && this.stats.begin(), this.isListening) {
|
|
5076
5076
|
for (this.listeningAnalyzer.getByteFrequencyData(this.volumeFrequencyData), i = 2, s = 10; i < s; i++)
|
|
5077
|
-
this.volumeFrequencyData[i] >
|
|
5078
|
-
this.listeningVolume = (this.listeningVolume +
|
|
5077
|
+
this.volumeFrequencyData[i] > l && (l = this.volumeFrequencyData[i]);
|
|
5078
|
+
this.listeningVolume = (this.listeningVolume + l) / 2, this.listeningActive ? (this.listeningTimerTotal += e, this.listeningVolume < this.listeningSilenceThresholdLevel ? (this.listeningTimer += e, this.listeningTimer > this.listeningSilenceThresholdMs && (this.listeningOnchange && this.listeningOnchange("stop", this.listeningTimer), this.listeningActive = !1, this.listeningTimer = 0, this.listeningTimerTotal = 0)) : this.listeningTimer *= 0.5, this.listeningTimerTotal > this.listeningActiveDurationMax && (this.listeningOnchange && this.listeningOnchange("maxactive"), this.listeningTimerTotal = 0)) : (this.listeningTimerTotal += e, this.listeningVolume > this.listeningActiveThresholdLevel ? (this.listeningTimer += e, this.listeningTimer > this.listeningActiveThresholdMs && (this.listeningOnchange && this.listeningOnchange("start"), this.listeningActive = !0, this.listeningTimer = 0, this.listeningTimerTotal = 0)) : this.listeningTimer *= 0.5, this.listeningTimerTotal > this.listeningSilenceDurationMax && (this.listeningOnchange && this.listeningOnchange("maxsilence"), this.listeningTimerTotal = 0));
|
|
5079
5079
|
}
|
|
5080
5080
|
if (this.isSpeaking)
|
|
5081
|
-
for (
|
|
5082
|
-
this.volumeFrequencyData[i] >
|
|
5081
|
+
for (l = 0, this.audioAnalyzerNode.getByteFrequencyData(this.volumeFrequencyData), i = 2, s = 10; i < s; i++)
|
|
5082
|
+
this.volumeFrequencyData[i] > l && (l = this.volumeFrequencyData[i]);
|
|
5083
5083
|
let u = null, a = null;
|
|
5084
5084
|
const h = [];
|
|
5085
5085
|
for (i = 0, s = this.animQueue.length; i < s; i++) {
|
|
5086
|
-
const
|
|
5087
|
-
if (!(!
|
|
5088
|
-
for (n =
|
|
5089
|
-
for (let [d, c] of Object.entries(
|
|
5086
|
+
const r = this.animQueue[i];
|
|
5087
|
+
if (!(!r || !r.ts || !r.ts.length || this.animClock < r.ts[0])) {
|
|
5088
|
+
for (n = r.ndx || 0, o = r.ts.length; n < o && !(this.animClock < r.ts[n]); n++)
|
|
5089
|
+
for (let [d, c] of Object.entries(r.vs))
|
|
5090
5090
|
if (this.mtAvatar.hasOwnProperty(d)) {
|
|
5091
5091
|
if (c[n + 1] === null) continue;
|
|
5092
5092
|
const g = this.mtAvatar[d];
|
|
@@ -5094,26 +5094,26 @@ class we {
|
|
|
5094
5094
|
g.newvalue = c[n];
|
|
5095
5095
|
else {
|
|
5096
5096
|
g.newvalue = c[n + 1];
|
|
5097
|
-
const y =
|
|
5097
|
+
const y = r.ts[n + 1] - r.ts[n];
|
|
5098
5098
|
let x = 1;
|
|
5099
|
-
y > 1e-4 && (x = (this.animClock -
|
|
5099
|
+
y > 1e-4 && (x = (this.animClock - r.ts[n]) / y), x < 1 && (g.easing && (x = g.easing(x)), g.newvalue = (1 - x) * c[n] + x * g.newvalue), g.ref && g.ref !== r.vs && g.ref.hasOwnProperty(d) && delete g.ref[d], g.ref = r.vs;
|
|
5100
5100
|
}
|
|
5101
|
-
if (
|
|
5101
|
+
if (l)
|
|
5102
5102
|
switch (d) {
|
|
5103
5103
|
case "viseme_aa":
|
|
5104
5104
|
case "viseme_E":
|
|
5105
5105
|
case "viseme_I":
|
|
5106
5106
|
case "viseme_O":
|
|
5107
5107
|
case "viseme_U":
|
|
5108
|
-
g.newvalue *= 1 +
|
|
5108
|
+
g.newvalue *= 1 + l / 255 - 0.5;
|
|
5109
5109
|
}
|
|
5110
5110
|
g.needsUpdate = !0;
|
|
5111
5111
|
} else d === "eyeContact" && c[n] !== null && u !== !1 ? u = !!c[n] : d === "headMove" && c[n] !== null && a !== !1 ? c[n] === 0 ? a = !1 : (Math.random() < c[n] && (a = !0), c[n] = null) : c[n] !== null && (h.push({ mt: d, val: c[n] }), c[n] = null);
|
|
5112
|
-
n === o ? (
|
|
5112
|
+
n === o ? (r.hasOwnProperty("mood") && this.setMood(r.mood), r.loop ? (o = this.isSpeaking && (r.template.name === "head" || r.template.name === "eyes") ? 4 : 1, this.animQueue[i] = this.animFactory(r.template, r.loop > 0 ? r.loop - 1 : r.loop, 1, 1 / o)) : (this.animQueue.splice(i--, 1), s--)) : r.ndx = n - 1;
|
|
5113
5113
|
}
|
|
5114
5114
|
}
|
|
5115
|
-
for (let
|
|
5116
|
-
switch (n = h[
|
|
5115
|
+
for (let r = 0, d = h.length; r < d; r++)
|
|
5116
|
+
switch (n = h[r].val, h[r].mt) {
|
|
5117
5117
|
case "speak":
|
|
5118
5118
|
this.speakText(n);
|
|
5119
5119
|
break;
|
|
@@ -5180,13 +5180,13 @@ class we {
|
|
|
5180
5180
|
eyeLookOutRight: [null, 0],
|
|
5181
5181
|
eyeContact: [0]
|
|
5182
5182
|
}
|
|
5183
|
-
})))), e > 2 * this.animFrameDur && (e = 2 * this.animFrameDur), (this.viewName !== "full" || this.isAvatarOnly) && (i = this.mtRandomized[Math.floor(Math.random() * this.mtRandomized.length)], n = this.mtAvatar[i], n.needsUpdate || Object.assign(n, { base: (this.mood.baseline[i] || 0) + (1 +
|
|
5183
|
+
})))), e > 2 * this.animFrameDur && (e = 2 * this.animFrameDur), (this.viewName !== "full" || this.isAvatarOnly) && (i = this.mtRandomized[Math.floor(Math.random() * this.mtRandomized.length)], n = this.mtAvatar[i], n.needsUpdate || Object.assign(n, { base: (this.mood.baseline[i] || 0) + (1 + l / 255) * Math.random() / 5, needsUpdate: !0 })), this.updatePoseBase(this.animClock), this.mixer && this.mixer.update(e / 1e3 * this.mixer.timeScale), this.updatePoseDelta(), (this.isSpeaking || this.isListening) && u ? l > this.volumeMax ? (this.volumeHeadBase = 0.05, Math.random() > 0.6 && (this.volumeHeadTarget = -0.05 - Math.random() / 15), this.volumeMax = l) : (this.volumeMax *= 0.92, this.volumeHeadTarget = this.volumeHeadBase - 0.9 * (this.volumeHeadBase - this.volumeHeadTarget)) : (this.volumeHeadTarget = 0, this.volumeMax = 0), i = this.volumeHeadTarget - this.volumeHeadCurrent, n = Math.abs(i), n > 1e-4 && (o = n * (this.volumeHeadEasing(Math.min(1, this.volumeHeadVelocity * e / 1e3 / n) / 2 + 0.5) - 0.5), this.volumeHeadCurrent += Math.sign(i) * Math.min(n, o)), Math.abs(this.volumeHeadCurrent) > 1e-4 && (W.setFromAxisAngle(tt, this.volumeHeadCurrent), this.objectNeck.quaternion.multiply(W)), Ae.setFromObject(this.armature), this.objectLeftToeBase.getWorldPosition(te), te.sub(this.armature.position), this.objectRightToeBase.getWorldPosition(ie), ie.sub(this.armature.position), this.objectHips.position.y -= Ae.min.y / 2, this.objectHips.position.x -= (te.x + ie.x) / 4, this.objectHips.position.z -= (te.z + ie.z) / 2, this.dynamicbones.update(e), this.fbxAnimationLoader && this.fbxAnimationLoader.update(), this.opt.update && this.opt.update(e), this.updateMorphTargets(e), this.isAvatarOnly)
|
|
5184
5184
|
this.stats && this.stats.end();
|
|
5185
5185
|
else {
|
|
5186
5186
|
if (this.cameraClock !== null && this.cameraClock < 1e3) {
|
|
5187
5187
|
this.cameraClock += e, this.cameraClock > 1e3 && (this.cameraClock = 1e3);
|
|
5188
|
-
let
|
|
5189
|
-
|
|
5188
|
+
let r = new f.Spherical().setFromVector3(this.cameraStart), d = new f.Spherical().setFromVector3(this.cameraEnd);
|
|
5189
|
+
r.phi += this.easing(this.cameraClock / 1e3) * (d.phi - r.phi), r.theta += this.easing(this.cameraClock / 1e3) * (d.theta - r.theta), r.radius += this.easing(this.cameraClock / 1e3) * (d.radius - r.radius), r.makeSafe(), this.camera.position.setFromSpherical(r), this.controlsStart.x !== this.controlsEnd.x ? this.controls.target.copy(this.controlsStart.lerp(this.controlsEnd, this.easing(this.cameraClock / 1e3))) : (r.setFromVector3(this.controlsStart), d.setFromVector3(this.controlsEnd), r.phi += this.easing(this.cameraClock / 1e3) * (d.phi - r.phi), r.theta += this.easing(this.cameraClock / 1e3) * (d.theta - r.theta), r.radius += this.easing(this.cameraClock / 1e3) * (d.radius - r.radius), r.makeSafe(), this.controls.target.setFromSpherical(r)), this.controls.update();
|
|
5190
5190
|
}
|
|
5191
5191
|
this.controls.autoRotate && this.controls.update(), this.stats && this.stats.end(), this.render();
|
|
5192
5192
|
}
|
|
@@ -5247,16 +5247,16 @@ class we {
|
|
|
5247
5247
|
*/
|
|
5248
5248
|
speakText(t, e = null, i = null, n = null) {
|
|
5249
5249
|
e = e || {};
|
|
5250
|
-
const s = /[!\.\?\n\p{Extended_Pictographic}]/ug, o = /[ ]/ug,
|
|
5251
|
-
let h = "",
|
|
5250
|
+
const s = /[!\.\?\n\p{Extended_Pictographic}]/ug, o = /[ ]/ug, l = /[\p{L}\p{N},\.\p{Quotation_Mark}!€\$\+\p{Dash_Punctuation}%&\?]/ug, u = /[\p{Extended_Pictographic}]/ug, a = e.lipsyncLang || this.avatar.lipsyncLang || this.opt.lipsyncLang;
|
|
5251
|
+
let h = "", r = "", d = 0, c = [], g = [];
|
|
5252
5252
|
const y = Array.from(this.segmenter.segment(t), (x) => x.segment);
|
|
5253
5253
|
for (let x = 0; x < y.length; x++) {
|
|
5254
|
-
const L = x === y.length - 1, F = y[x].match(
|
|
5254
|
+
const L = x === y.length - 1, F = y[x].match(l);
|
|
5255
5255
|
let p = y[x].match(s);
|
|
5256
|
-
const
|
|
5257
|
-
if (p && !L && !
|
|
5256
|
+
const H = y[x].match(u), T = y[x].match(o);
|
|
5257
|
+
if (p && !L && !H && y[x + 1].match(s) && (p = !1), i && (h += y[x]), F && (!n || n.every((I) => x < I[0] || x > I[1])) && (r += y[x]), (T || p || L) && (r.length && (r = this.lipsyncPreProcessText(r, a), r.length && c.push({
|
|
5258
5258
|
mark: d,
|
|
5259
|
-
word:
|
|
5259
|
+
word: r
|
|
5260
5260
|
})), h.length && (g.push({
|
|
5261
5261
|
mark: d,
|
|
5262
5262
|
template: { name: "subtitles" },
|
|
@@ -5264,8 +5264,8 @@ class we {
|
|
|
5264
5264
|
vs: {
|
|
5265
5265
|
subtitles: [h]
|
|
5266
5266
|
}
|
|
5267
|
-
}), h = ""),
|
|
5268
|
-
const I = this.lipsyncWordsToVisemes(
|
|
5267
|
+
}), h = ""), r.length)) {
|
|
5268
|
+
const I = this.lipsyncWordsToVisemes(r, a);
|
|
5269
5269
|
if (I && I.visemes && I.visemes.length) {
|
|
5270
5270
|
const B = I.times[I.visemes.length - 1] + I.durations[I.visemes.length - 1];
|
|
5271
5271
|
for (let D = 0; D < I.visemes.length; D++)
|
|
@@ -5278,16 +5278,16 @@ class we {
|
|
|
5278
5278
|
}
|
|
5279
5279
|
});
|
|
5280
5280
|
}
|
|
5281
|
-
|
|
5281
|
+
r = "", d++;
|
|
5282
5282
|
}
|
|
5283
5283
|
if (p || L) {
|
|
5284
5284
|
if (c.length || L && g.length) {
|
|
5285
5285
|
const I = {
|
|
5286
5286
|
anim: g
|
|
5287
5287
|
};
|
|
5288
|
-
i && (I.onSubtitles = i), c.length && !e.avatarMute && (I.text = c, e.avatarMood && (I.mood = e.avatarMood), e.ttsLang && (I.lang = e.ttsLang), e.ttsVoice && (I.voice = e.ttsVoice), e.ttsRate && (I.rate = e.ttsRate), e.ttsVoice && (I.pitch = e.ttsPitch), e.ttsVolume && (I.volume = e.ttsVolume)), this.speechQueue.push(I), c = [],
|
|
5288
|
+
i && (I.onSubtitles = i), c.length && !e.avatarMute && (I.text = c, e.avatarMood && (I.mood = e.avatarMood), e.ttsLang && (I.lang = e.ttsLang), e.ttsVoice && (I.voice = e.ttsVoice), e.ttsRate && (I.rate = e.ttsRate), e.ttsVoice && (I.pitch = e.ttsPitch), e.ttsVolume && (I.volume = e.ttsVolume)), this.speechQueue.push(I), c = [], r = "", d = 0, g = [];
|
|
5289
5289
|
}
|
|
5290
|
-
if (
|
|
5290
|
+
if (H) {
|
|
5291
5291
|
let I = this.animEmojis[y[x]];
|
|
5292
5292
|
I && I.link && (I = this.animEmojis[I.link]), I && this.speechQueue.push({ emoji: I });
|
|
5293
5293
|
}
|
|
@@ -5369,9 +5369,9 @@ class we {
|
|
|
5369
5369
|
const n = e.lipsyncLang || this.avatar.lipsyncLang || this.opt.lipsyncLang, s = {};
|
|
5370
5370
|
if (t.words) {
|
|
5371
5371
|
let o = [];
|
|
5372
|
-
for (let
|
|
5373
|
-
const u = t.words[
|
|
5374
|
-
let h = t.wdurations[
|
|
5372
|
+
for (let l = 0; l < t.words.length; l++) {
|
|
5373
|
+
const u = t.words[l], a = t.wtimes[l];
|
|
5374
|
+
let h = t.wdurations[l];
|
|
5375
5375
|
if (u.length && (i && o.push({
|
|
5376
5376
|
template: { name: "subtitles" },
|
|
5377
5377
|
ts: [a],
|
|
@@ -5379,7 +5379,7 @@ class we {
|
|
|
5379
5379
|
subtitles: [" " + u]
|
|
5380
5380
|
}
|
|
5381
5381
|
}), !t.visemes)) {
|
|
5382
|
-
const
|
|
5382
|
+
const r = this.lipsyncPreProcessText(u, n), d = this.lipsyncWordsToVisemes(r, n);
|
|
5383
5383
|
if (d && d.visemes && d.visemes.length) {
|
|
5384
5384
|
const c = d.times[d.visemes.length - 1] + d.durations[d.visemes.length - 1], g = Math.min(h, Math.max(0, h - d.visemes.length * 150));
|
|
5385
5385
|
let y = 0.6 + this.convertRange(g, [0, h], [0, 0.4]);
|
|
@@ -5398,8 +5398,8 @@ class we {
|
|
|
5398
5398
|
}
|
|
5399
5399
|
}
|
|
5400
5400
|
if (t.visemes)
|
|
5401
|
-
for (let
|
|
5402
|
-
const u = t.visemes[
|
|
5401
|
+
for (let l = 0; l < t.visemes.length; l++) {
|
|
5402
|
+
const u = t.visemes[l], a = t.vtimes[l], h = t.vdurations[l];
|
|
5403
5403
|
o.push({
|
|
5404
5404
|
template: { name: "viseme" },
|
|
5405
5405
|
ts: [a - 2 * h / 3, a + h / 2, a + h + h / 2],
|
|
@@ -5409,8 +5409,8 @@ class we {
|
|
|
5409
5409
|
});
|
|
5410
5410
|
}
|
|
5411
5411
|
if (t.markers)
|
|
5412
|
-
for (let
|
|
5413
|
-
const u = t.markers[
|
|
5412
|
+
for (let l = 0; l < t.markers.length; l++) {
|
|
5413
|
+
const u = t.markers[l], a = t.mtimes[l];
|
|
5414
5414
|
o.push({
|
|
5415
5415
|
template: { name: "markers" },
|
|
5416
5416
|
ts: [a],
|
|
@@ -5434,7 +5434,7 @@ class we {
|
|
|
5434
5434
|
if (this.isAudioPlaying = !0, this.audioPlaylist.length) {
|
|
5435
5435
|
const e = this.audioPlaylist.shift();
|
|
5436
5436
|
if (this.audioCtx.state === "suspended" || this.audioCtx.state === "interrupted") {
|
|
5437
|
-
const s = this.audioCtx.resume(), o = new Promise((
|
|
5437
|
+
const s = this.audioCtx.resume(), o = new Promise((l, u) => setTimeout(() => u("p2"), 1e3));
|
|
5438
5438
|
try {
|
|
5439
5439
|
await Promise.race([s, o]);
|
|
5440
5440
|
} catch {
|
|
@@ -5466,11 +5466,11 @@ class we {
|
|
|
5466
5466
|
*/
|
|
5467
5467
|
async synthesizeWithBrowserTTS(t) {
|
|
5468
5468
|
return new Promise((e, i) => {
|
|
5469
|
-
const n = t.text.map((p) => p.word).join(" "), s = new SpeechSynthesisUtterance(n), o = t.lang || this.avatar.ttsLang || this.opt.ttsLang || "en-US",
|
|
5470
|
-
s.lang = o, s.rate = Math.max(0.1, Math.min(10,
|
|
5471
|
-
const h = speechSynthesis.getVoices(),
|
|
5472
|
-
if (
|
|
5473
|
-
const p = h.find((
|
|
5469
|
+
const n = t.text.map((p) => p.word).join(" "), s = new SpeechSynthesisUtterance(n), o = t.lang || this.avatar.ttsLang || this.opt.ttsLang || "en-US", l = (t.rate || this.avatar.ttsRate || this.opt.ttsRate || 1) + this.mood.speech.deltaRate, u = (t.pitch || this.avatar.ttsPitch || this.opt.ttsPitch || 1) + this.mood.speech.deltaPitch, a = (t.volume || this.avatar.ttsVolume || this.opt.ttsVolume || 1) + this.mood.speech.deltaVolume;
|
|
5470
|
+
s.lang = o, s.rate = Math.max(0.1, Math.min(10, l)), s.pitch = Math.max(0, Math.min(2, u)), s.volume = Math.max(0, Math.min(1, a));
|
|
5471
|
+
const h = speechSynthesis.getVoices(), r = t.voice || this.avatar.ttsVoice || this.opt.ttsVoice;
|
|
5472
|
+
if (r && h.length > 0) {
|
|
5473
|
+
const p = h.find((H) => H.name.includes(r) || H.lang === o);
|
|
5474
5474
|
p && (s.voice = p);
|
|
5475
5475
|
}
|
|
5476
5476
|
const d = n.length * 100 / s.rate, c = this.audioCtx.createBuffer(1, this.audioCtx.sampleRate * (d / 1e3), this.audioCtx.sampleRate), g = this.avatar.lipsyncLang || this.opt.lipsyncLang || "en", y = this.lipsyncPreProcessText(n, g), x = this.lipsyncWordsToVisemes(y, g);
|
|
@@ -5485,13 +5485,13 @@ class we {
|
|
|
5485
5485
|
const L = [];
|
|
5486
5486
|
if (x && x.visemes && x.visemes.length > 0) {
|
|
5487
5487
|
const p = x.times[x.visemes.length - 1] + x.durations[x.visemes.length - 1];
|
|
5488
|
-
for (let
|
|
5489
|
-
const
|
|
5488
|
+
for (let H = 0; H < x.visemes.length; H++) {
|
|
5489
|
+
const T = x.visemes[H], I = x.times[H] / p, B = x.durations[H] / p, D = I * d, Y = B * d;
|
|
5490
5490
|
L.push({
|
|
5491
5491
|
template: { name: "viseme" },
|
|
5492
|
-
ts: [D - Math.min(60, 2 *
|
|
5492
|
+
ts: [D - Math.min(60, 2 * Y / 3), D + Math.min(25, Y / 2), D + Y + Math.min(60, Y / 2)],
|
|
5493
5493
|
vs: {
|
|
5494
|
-
["viseme_" +
|
|
5494
|
+
["viseme_" + T]: [null, T === "PP" || T === "FF" ? 0.9 : 0.6, 0]
|
|
5495
5495
|
}
|
|
5496
5496
|
});
|
|
5497
5497
|
}
|
|
@@ -5529,7 +5529,7 @@ class we {
|
|
|
5529
5529
|
});
|
|
5530
5530
|
if (!s.ok)
|
|
5531
5531
|
throw new Error(`ElevenLabs TTS error: ${s.status} ${s.statusText}`);
|
|
5532
|
-
const o = await s.arrayBuffer(),
|
|
5532
|
+
const o = await s.arrayBuffer(), l = await this.audioCtx.decodeAudioData(o);
|
|
5533
5533
|
console.log("Using text-based lip-sync for debugging...");
|
|
5534
5534
|
const u = this.avatar.lipsyncLang || this.opt.lipsyncLang || "en";
|
|
5535
5535
|
let a;
|
|
@@ -5548,13 +5548,13 @@ class we {
|
|
|
5548
5548
|
a = {
|
|
5549
5549
|
visemes: c.visemes.map((g, y) => ({
|
|
5550
5550
|
viseme: g,
|
|
5551
|
-
startTime: y *
|
|
5552
|
-
endTime: (y + 1) *
|
|
5553
|
-
duration:
|
|
5551
|
+
startTime: y * l.duration / c.visemes.length,
|
|
5552
|
+
endTime: (y + 1) * l.duration / c.visemes.length,
|
|
5553
|
+
duration: l.duration / c.visemes.length,
|
|
5554
5554
|
intensity: 0.7
|
|
5555
5555
|
})),
|
|
5556
5556
|
words: [],
|
|
5557
|
-
duration:
|
|
5557
|
+
duration: l.duration,
|
|
5558
5558
|
features: { onsets: [], boundaries: [] }
|
|
5559
5559
|
};
|
|
5560
5560
|
else
|
|
@@ -5570,19 +5570,19 @@ class we {
|
|
|
5570
5570
|
a = {
|
|
5571
5571
|
visemes: g.map((y, x) => ({
|
|
5572
5572
|
viseme: y,
|
|
5573
|
-
startTime: x *
|
|
5574
|
-
endTime: (x + 1) *
|
|
5575
|
-
duration:
|
|
5573
|
+
startTime: x * l.duration / g.length,
|
|
5574
|
+
endTime: (x + 1) * l.duration / g.length,
|
|
5575
|
+
duration: l.duration / g.length,
|
|
5576
5576
|
intensity: 0.6
|
|
5577
5577
|
})),
|
|
5578
5578
|
words: [],
|
|
5579
|
-
duration:
|
|
5579
|
+
duration: l.duration,
|
|
5580
5580
|
features: { onsets: [], boundaries: [] }
|
|
5581
5581
|
};
|
|
5582
5582
|
}
|
|
5583
5583
|
console.log("ElevenLabs TTS Audio Analysis:", {
|
|
5584
5584
|
text: e,
|
|
5585
|
-
audioDuration:
|
|
5585
|
+
audioDuration: l.duration,
|
|
5586
5586
|
visemeCount: a.visemes ? a.visemes.length : 0,
|
|
5587
5587
|
wordCount: a.words ? a.words.length : 0,
|
|
5588
5588
|
features: {
|
|
@@ -5608,8 +5608,8 @@ class we {
|
|
|
5608
5608
|
console.log("ElevenLabs: Generated", h.length, "lip-sync animation frames");
|
|
5609
5609
|
} else
|
|
5610
5610
|
console.warn("ElevenLabs: No visemes available for lip-sync animation");
|
|
5611
|
-
const
|
|
5612
|
-
console.log("ElevenLabs: Combined animation frames:",
|
|
5611
|
+
const r = [...t.anim, ...h];
|
|
5612
|
+
console.log("ElevenLabs: Combined animation frames:", r.length, "(original:", t.anim.length, "+ lipsync:", h.length, ")"), this.audioPlaylist.push({ anim: r, audio: l }), this.onSubtitles = t.onSubtitles || null, this.resetLips(), t.mood && this.setMood(t.mood), this.playAudio();
|
|
5613
5613
|
}
|
|
5614
5614
|
/**
|
|
5615
5615
|
* Synthesize speech using Deepgram Aura-2 TTS
|
|
@@ -5627,7 +5627,7 @@ class we {
|
|
|
5627
5627
|
});
|
|
5628
5628
|
if (!s.ok)
|
|
5629
5629
|
throw new Error(`Deepgram TTS error: ${s.status} ${s.statusText}`);
|
|
5630
|
-
const o = await s.arrayBuffer(),
|
|
5630
|
+
const o = await s.arrayBuffer(), l = await this.audioCtx.decodeAudioData(o);
|
|
5631
5631
|
console.log("Using text-based lip-sync for Deepgram...");
|
|
5632
5632
|
const u = this.avatar.lipsyncLang || this.opt.lipsyncLang || "en";
|
|
5633
5633
|
let a;
|
|
@@ -5646,13 +5646,13 @@ class we {
|
|
|
5646
5646
|
a = {
|
|
5647
5647
|
visemes: c.visemes.map((g, y) => ({
|
|
5648
5648
|
viseme: g,
|
|
5649
|
-
startTime: y *
|
|
5650
|
-
endTime: (y + 1) *
|
|
5651
|
-
duration:
|
|
5649
|
+
startTime: y * l.duration / c.visemes.length,
|
|
5650
|
+
endTime: (y + 1) * l.duration / c.visemes.length,
|
|
5651
|
+
duration: l.duration / c.visemes.length,
|
|
5652
5652
|
intensity: 0.7
|
|
5653
5653
|
})),
|
|
5654
5654
|
words: [],
|
|
5655
|
-
duration:
|
|
5655
|
+
duration: l.duration,
|
|
5656
5656
|
features: { onsets: [], boundaries: [] }
|
|
5657
5657
|
};
|
|
5658
5658
|
else
|
|
@@ -5668,19 +5668,19 @@ class we {
|
|
|
5668
5668
|
a = {
|
|
5669
5669
|
visemes: g.map((y, x) => ({
|
|
5670
5670
|
viseme: y,
|
|
5671
|
-
startTime: x *
|
|
5672
|
-
endTime: (x + 1) *
|
|
5673
|
-
duration:
|
|
5671
|
+
startTime: x * l.duration / g.length,
|
|
5672
|
+
endTime: (x + 1) * l.duration / g.length,
|
|
5673
|
+
duration: l.duration / g.length,
|
|
5674
5674
|
intensity: 0.6
|
|
5675
5675
|
})),
|
|
5676
5676
|
words: [],
|
|
5677
|
-
duration:
|
|
5677
|
+
duration: l.duration,
|
|
5678
5678
|
features: { onsets: [], boundaries: [] }
|
|
5679
5679
|
};
|
|
5680
5680
|
}
|
|
5681
5681
|
console.log("Deepgram TTS Audio Analysis:", {
|
|
5682
5682
|
text: e,
|
|
5683
|
-
audioDuration:
|
|
5683
|
+
audioDuration: l.duration,
|
|
5684
5684
|
visemeCount: a.visemes ? a.visemes.length : 0,
|
|
5685
5685
|
wordCount: a.words ? a.words.length : 0,
|
|
5686
5686
|
features: {
|
|
@@ -5706,15 +5706,15 @@ class we {
|
|
|
5706
5706
|
console.log("Deepgram: Generated", h.length, "lip-sync animation frames");
|
|
5707
5707
|
} else
|
|
5708
5708
|
console.warn("Deepgram: No visemes available for lip-sync animation");
|
|
5709
|
-
const
|
|
5710
|
-
console.log("Deepgram: Combined animation frames:",
|
|
5709
|
+
const r = [...t.anim, ...h];
|
|
5710
|
+
console.log("Deepgram: Combined animation frames:", r.length, "(original:", t.anim.length, "+ lipsync:", h.length, ")"), this.audioPlaylist.push({ anim: r, audio: l }), this.onSubtitles = t.onSubtitles || null, this.resetLips(), t.mood && this.setMood(t.mood), this.playAudio();
|
|
5711
5711
|
}
|
|
5712
5712
|
/**
|
|
5713
5713
|
* Synthesize speech using Azure TTS
|
|
5714
5714
|
* @param {Object} line Speech line object
|
|
5715
5715
|
*/
|
|
5716
5716
|
async synthesizeWithAzureTTS(t) {
|
|
5717
|
-
const e = t.text.map((
|
|
5717
|
+
const e = t.text.map((r) => r.word).join(" "), n = `
|
|
5718
5718
|
<speak version="1.0" xmlns="http://www.w3.org/2001/10/synthesis" xml:lang="en-US">
|
|
5719
5719
|
<voice name="${t.voice || this.avatar.ttsVoice || this.opt.ttsVoice || "en-US-AriaNeural"}">
|
|
5720
5720
|
${e}
|
|
@@ -5731,12 +5731,12 @@ class we {
|
|
|
5731
5731
|
});
|
|
5732
5732
|
if (!s.ok)
|
|
5733
5733
|
throw new Error(`Azure TTS error: ${s.status} ${s.statusText}`);
|
|
5734
|
-
const o = await s.arrayBuffer(),
|
|
5734
|
+
const o = await s.arrayBuffer(), l = await this.audioCtx.decodeAudioData(o);
|
|
5735
5735
|
console.log("Analyzing audio for precise lip-sync...");
|
|
5736
|
-
const u = await this.audioAnalyzer.analyzeAudio(
|
|
5736
|
+
const u = await this.audioAnalyzer.analyzeAudio(l, e);
|
|
5737
5737
|
console.log("Azure TTS Audio Analysis:", {
|
|
5738
5738
|
text: e,
|
|
5739
|
-
audioDuration:
|
|
5739
|
+
audioDuration: l.duration,
|
|
5740
5740
|
visemeCount: u.visemes.length,
|
|
5741
5741
|
wordCount: u.words.length,
|
|
5742
5742
|
features: {
|
|
@@ -5745,8 +5745,8 @@ class we {
|
|
|
5745
5745
|
}
|
|
5746
5746
|
});
|
|
5747
5747
|
const a = [];
|
|
5748
|
-
for (let
|
|
5749
|
-
const d = u.visemes[
|
|
5748
|
+
for (let r = 0; r < u.visemes.length; r++) {
|
|
5749
|
+
const d = u.visemes[r], c = d.startTime * 1e3, g = d.duration * 1e3, y = d.intensity;
|
|
5750
5750
|
a.push({
|
|
5751
5751
|
template: { name: "viseme" },
|
|
5752
5752
|
ts: [c - Math.min(60, 2 * g / 3), c + Math.min(25, g / 2), c + g + Math.min(60, g / 2)],
|
|
@@ -5756,7 +5756,7 @@ class we {
|
|
|
5756
5756
|
});
|
|
5757
5757
|
}
|
|
5758
5758
|
const h = [...t.anim, ...a];
|
|
5759
|
-
this.audioPlaylist.push({ anim: h, audio:
|
|
5759
|
+
this.audioPlaylist.push({ anim: h, audio: l }), this.onSubtitles = t.onSubtitles || null, this.resetLips(), t.mood && this.setMood(t.mood), this.playAudio();
|
|
5760
5760
|
}
|
|
5761
5761
|
/**
|
|
5762
5762
|
* Synthesize speech using external TTS service (Google Cloud, etc.)
|
|
@@ -5764,8 +5764,8 @@ class we {
|
|
|
5764
5764
|
*/
|
|
5765
5765
|
async synthesizeWithExternalTTS(t) {
|
|
5766
5766
|
let e = "<speak>";
|
|
5767
|
-
t.text.forEach((o,
|
|
5768
|
-
|
|
5767
|
+
t.text.forEach((o, l) => {
|
|
5768
|
+
l > 0 && (e += " <mark name='" + o.mark + "'/>"), e += o.word.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'").replace(new RegExp("^\\p{Dash_Punctuation}$", "ug"), '<break time="750ms"/>');
|
|
5769
5769
|
}), e += "</speak>";
|
|
5770
5770
|
const i = {
|
|
5771
5771
|
method: "POST",
|
|
@@ -5793,7 +5793,7 @@ class we {
|
|
|
5793
5793
|
this.opt.jwtGet && typeof this.opt.jwtGet == "function" && (i.headers.Authorization = "Bearer " + await this.opt.jwtGet());
|
|
5794
5794
|
const n = await fetch(this.opt.ttsEndpoint + (this.opt.ttsApikey ? "?key=" + this.opt.ttsApikey : ""), i), s = await n.json();
|
|
5795
5795
|
if (n.status === 200 && s && s.audioContent) {
|
|
5796
|
-
const o = this.b64ToArrayBuffer(s.audioContent),
|
|
5796
|
+
const o = this.b64ToArrayBuffer(s.audioContent), l = await this.audioCtx.decodeAudioData(o);
|
|
5797
5797
|
this.speakWithHands();
|
|
5798
5798
|
const u = [0];
|
|
5799
5799
|
let a = 0;
|
|
@@ -5810,13 +5810,13 @@ class we {
|
|
|
5810
5810
|
h[c - 1].duration = g, h.push({ mark: c, time: d });
|
|
5811
5811
|
}
|
|
5812
5812
|
});
|
|
5813
|
-
let
|
|
5814
|
-
|
|
5813
|
+
let r = 1e3 * l.duration;
|
|
5814
|
+
r > this.opt.ttsTrimEnd && (r = r - this.opt.ttsTrimEnd), h[h.length - 1].duration = r - h[h.length - 1].time, t.anim.forEach((d) => {
|
|
5815
5815
|
const c = h[d.mark];
|
|
5816
5816
|
if (c)
|
|
5817
5817
|
for (let g = 0; g < d.ts.length; g++)
|
|
5818
5818
|
d.ts[g] = c.time + d.ts[g] * c.duration + this.opt.ttsTrimStart;
|
|
5819
|
-
}), this.audioPlaylist.push({ anim: t.anim, audio:
|
|
5819
|
+
}), this.audioPlaylist.push({ anim: t.anim, audio: l }), this.onSubtitles = t.onSubtitles || null, this.resetLips(), t.mood && this.setMood(t.mood), this.playAudio();
|
|
5820
5820
|
} else
|
|
5821
5821
|
this.startSpeaking(!0);
|
|
5822
5822
|
}
|
|
@@ -5882,8 +5882,8 @@ class we {
|
|
|
5882
5882
|
*/
|
|
5883
5883
|
async streamStart(t = {}, e = null, i = null, n = null, s = null) {
|
|
5884
5884
|
if (this.stopSpeaking(), this.isStreaming = !0, t.waitForAudioChunks !== void 0 && (this.streamWaitForAudioChunks = t.waitForAudioChunks), this.streamWaitForAudioChunks || (this.streamAudioStartTime = this.animClock), this.streamLipsyncQueue = [], this.streamLipsyncType = t.lipsyncType || this.streamLipsyncType || "visemes", this.streamLipsyncLang = t.lipsyncLang || this.streamLipsyncLang || this.avatar.lipsyncLang || this.opt.lipsyncLang, this.onAudioStart = e, this.onAudioEnd = i, this.onMetrics = s, t.sampleRate !== void 0) {
|
|
5885
|
-
const
|
|
5886
|
-
typeof
|
|
5885
|
+
const l = t.sampleRate;
|
|
5886
|
+
typeof l == "number" && l >= 8e3 && l <= 96e3 ? l !== this.audioCtx.sampleRate && this.initAudioGraph(l) : console.warn(
|
|
5887
5887
|
"Invalid sampleRate provided. It must be a number between 8000 and 96000 Hz."
|
|
5888
5888
|
);
|
|
5889
5889
|
}
|
|
@@ -5895,33 +5895,33 @@ class we {
|
|
|
5895
5895
|
}
|
|
5896
5896
|
if (!this.workletLoaded)
|
|
5897
5897
|
try {
|
|
5898
|
-
const
|
|
5898
|
+
const l = this.audioCtx.audioWorklet.addModule(et.href), u = new Promise(
|
|
5899
5899
|
(a, h) => setTimeout(() => h(new Error("Worklet loading timed out")), 5e3)
|
|
5900
5900
|
);
|
|
5901
|
-
await Promise.race([
|
|
5902
|
-
} catch (
|
|
5903
|
-
throw console.error("Failed to load audio worklet:",
|
|
5901
|
+
await Promise.race([l, u]), this.workletLoaded = !0;
|
|
5902
|
+
} catch (l) {
|
|
5903
|
+
throw console.error("Failed to load audio worklet:", l), new Error("Failed to initialize streaming speech");
|
|
5904
5904
|
}
|
|
5905
5905
|
this.streamWorkletNode = new AudioWorkletNode(this.audioCtx, "playback-worklet", {
|
|
5906
5906
|
processorOptions: {
|
|
5907
5907
|
sampleRate: this.audioCtx.sampleRate,
|
|
5908
5908
|
metrics: t.metrics || { enabled: !1 }
|
|
5909
5909
|
}
|
|
5910
|
-
}), this.streamWorkletNode.connect(this.audioStreamGainNode), this.streamWorkletNode.connect(this.audioAnalyzerNode), this.streamWorkletNode.port.onmessage = (
|
|
5911
|
-
if (
|
|
5910
|
+
}), this.streamWorkletNode.connect(this.audioStreamGainNode), this.streamWorkletNode.connect(this.audioAnalyzerNode), this.streamWorkletNode.port.onmessage = (l) => {
|
|
5911
|
+
if (l.data.type === "playback-started" && (this.isSpeaking = !0, this.stateName = "speaking", this.streamWaitForAudioChunks && (this.streamAudioStartTime = this.animClock), this._processStreamLipsyncQueue(), this.speakWithHands(), this.onAudioStart))
|
|
5912
5912
|
try {
|
|
5913
5913
|
this.onAudioStart?.();
|
|
5914
5914
|
} catch (u) {
|
|
5915
5915
|
console.error(u);
|
|
5916
5916
|
}
|
|
5917
|
-
if (
|
|
5917
|
+
if (l.data.type === "playback-ended" && (this._streamPause(), this.onAudioEnd))
|
|
5918
5918
|
try {
|
|
5919
5919
|
this.onAudioEnd();
|
|
5920
5920
|
} catch {
|
|
5921
5921
|
}
|
|
5922
|
-
if (this.onMetrics &&
|
|
5922
|
+
if (this.onMetrics && l.data.type === "metrics")
|
|
5923
5923
|
try {
|
|
5924
|
-
this.onMetrics(
|
|
5924
|
+
this.onMetrics(l.data);
|
|
5925
5925
|
} catch {
|
|
5926
5926
|
}
|
|
5927
5927
|
};
|
|
@@ -5932,9 +5932,9 @@ class we {
|
|
|
5932
5932
|
} catch {
|
|
5933
5933
|
}
|
|
5934
5934
|
if (this.resetLips(), this.lookAtCamera(500), t.mood && this.setMood(t.mood), this.onSubtitles = n || null, this.audioCtx.state === "suspended" || this.audioCtx.state === "interrupted") {
|
|
5935
|
-
const
|
|
5935
|
+
const l = this.audioCtx.resume(), u = new Promise((a, h) => setTimeout(() => h("p2"), 1e3));
|
|
5936
5936
|
try {
|
|
5937
|
-
await Promise.race([
|
|
5937
|
+
await Promise.race([l, u]);
|
|
5938
5938
|
} catch {
|
|
5939
5939
|
console.warn("Can't play audio. Web Audio API suspended. This is often due to calling some speak method before the first user action, which is typically prevented by the browser.");
|
|
5940
5940
|
return;
|
|
@@ -6011,14 +6011,14 @@ class we {
|
|
|
6011
6011
|
if (this.isStreaming) {
|
|
6012
6012
|
if (t.visemes && this.streamLipsyncType == "visemes")
|
|
6013
6013
|
for (let i = 0; i < t.visemes.length; i++) {
|
|
6014
|
-
const n = t.visemes[i], s = e + t.vtimes[i], o = t.vdurations[i],
|
|
6014
|
+
const n = t.visemes[i], s = e + t.vtimes[i], o = t.vdurations[i], l = {
|
|
6015
6015
|
template: { name: "viseme" },
|
|
6016
6016
|
ts: [s - 2 * o / 3, s + o / 2, s + o + o / 2],
|
|
6017
6017
|
vs: {
|
|
6018
6018
|
["viseme_" + n]: [null, n === "PP" || n === "FF" ? 0.9 : 0.6, 0]
|
|
6019
6019
|
}
|
|
6020
6020
|
};
|
|
6021
|
-
this.animQueue.push(
|
|
6021
|
+
this.animQueue.push(l);
|
|
6022
6022
|
}
|
|
6023
6023
|
if (t.words && (this.onSubtitles || this.streamLipsyncType == "words"))
|
|
6024
6024
|
for (let i = 0; i < t.words.length; i++) {
|
|
@@ -6031,10 +6031,10 @@ class we {
|
|
|
6031
6031
|
subtitles: [" " + n]
|
|
6032
6032
|
}
|
|
6033
6033
|
}), this.streamLipsyncType == "words")) {
|
|
6034
|
-
const
|
|
6034
|
+
const l = this.streamLipsyncLang || this.avatar.lipsyncLang || this.opt.lipsyncLang, u = this.lipsyncPreProcessText(n, l), a = this.lipsyncWordsToVisemes(u, l);
|
|
6035
6035
|
if (a && a.visemes && a.visemes.length) {
|
|
6036
|
-
const h = a.times[a.visemes.length - 1] + a.durations[a.visemes.length - 1],
|
|
6037
|
-
let d = 0.6 + this.convertRange(
|
|
6036
|
+
const h = a.times[a.visemes.length - 1] + a.durations[a.visemes.length - 1], r = Math.min(o, Math.max(0, o - a.visemes.length * 150));
|
|
6037
|
+
let d = 0.6 + this.convertRange(r, [0, o], [0, 0.4]);
|
|
6038
6038
|
if (o = Math.min(o, a.visemes.length * 200), h > 0)
|
|
6039
6039
|
for (let c = 0; c < a.visemes.length; c++) {
|
|
6040
6040
|
const g = e + s + a.times[c] / h * o, y = a.durations[c] / h * o;
|
|
@@ -6133,7 +6133,7 @@ class we {
|
|
|
6133
6133
|
*/
|
|
6134
6134
|
lookAtCamera(t) {
|
|
6135
6135
|
let e;
|
|
6136
|
-
if (this.speakTo && (e = new f.Vector3(), this.speakTo.objectLeftEye?.isObject3D ? (this.speakTo.armature.objectHead, this.speakTo.objectLeftEye.updateMatrixWorld(!0), this.speakTo.objectRightEye.updateMatrixWorld(!0),
|
|
6136
|
+
if (this.speakTo && (e = new f.Vector3(), this.speakTo.objectLeftEye?.isObject3D ? (this.speakTo.armature.objectHead, this.speakTo.objectLeftEye.updateMatrixWorld(!0), this.speakTo.objectRightEye.updateMatrixWorld(!0), te.setFromMatrixPosition(this.speakTo.objectLeftEye.matrixWorld), ie.setFromMatrixPosition(this.speakTo.objectRightEye.matrixWorld), e.addVectors(te, ie).divideScalar(2)) : this.speakTo.isObject3D ? this.speakTo.getWorldPosition(e) : this.speakTo.isVector3 ? e.set(this.speakTo) : this.speakTo.x && this.speakTo.y && this.speakTo.z && e.set(this.speakTo.x, this.speakTo.y, this.speakTo.z)), !e) {
|
|
6137
6137
|
if (this.avatar.hasOwnProperty("avatarIgnoreCamera")) {
|
|
6138
6138
|
if (this.avatar.avatarIgnoreCamera) {
|
|
6139
6139
|
this.lookAhead(t);
|
|
@@ -6146,12 +6146,12 @@ class we {
|
|
|
6146
6146
|
this.lookAt(null, null, t);
|
|
6147
6147
|
return;
|
|
6148
6148
|
}
|
|
6149
|
-
this.objectLeftEye.updateMatrixWorld(!0), this.objectRightEye.updateMatrixWorld(!0),
|
|
6150
|
-
const i = new f.Vector3().subVectors(e,
|
|
6149
|
+
this.objectLeftEye.updateMatrixWorld(!0), this.objectRightEye.updateMatrixWorld(!0), te.setFromMatrixPosition(this.objectLeftEye.matrixWorld), ie.setFromMatrixPosition(this.objectRightEye.matrixWorld), te.add(ie).divideScalar(2), W.copy(this.armature.quaternion), W.multiply(this.poseTarget.props["Hips.quaternion"]), W.multiply(this.poseTarget.props["Spine.quaternion"]), W.multiply(this.poseTarget.props["Spine1.quaternion"]), W.multiply(this.poseTarget.props["Spine2.quaternion"]), W.multiply(this.poseTarget.props["Neck.quaternion"]), W.multiply(this.poseTarget.props["Head.quaternion"]);
|
|
6150
|
+
const i = new f.Vector3().subVectors(e, te).normalize(), n = Math.atan2(i.x, i.z), s = Math.asin(-i.y);
|
|
6151
6151
|
E.set(s, n, 0, "YXZ");
|
|
6152
|
-
const
|
|
6152
|
+
const l = new f.Quaternion().setFromEuler(E), u = new f.Quaternion().copy(l).multiply(W.clone().invert());
|
|
6153
6153
|
E.setFromQuaternion(u, "YXZ");
|
|
6154
|
-
let a = E.x / (40 / 24) + 0.2, h = E.y / (9 / 4),
|
|
6154
|
+
let a = E.x / (40 / 24) + 0.2, h = E.y / (9 / 4), r = Math.min(0.6, Math.max(-0.3, a)), d = Math.min(0.8, Math.max(-0.8, h)), c = (Math.random() - 0.5) / 4, g = (Math.random() - 0.5) / 4;
|
|
6155
6155
|
if (t) {
|
|
6156
6156
|
let y = this.animQueue.findIndex((L) => L.template.name === "lookat");
|
|
6157
6157
|
y !== -1 && this.animQueue.splice(y, 1);
|
|
@@ -6159,7 +6159,7 @@ class we {
|
|
|
6159
6159
|
name: "lookat",
|
|
6160
6160
|
dt: [750, t],
|
|
6161
6161
|
vs: {
|
|
6162
|
-
bodyRotateX: [
|
|
6162
|
+
bodyRotateX: [r + c],
|
|
6163
6163
|
bodyRotateY: [d + g],
|
|
6164
6164
|
eyesRotateX: [-3 * c + 0.1],
|
|
6165
6165
|
eyesRotateY: [-5 * g],
|
|
@@ -6183,17 +6183,17 @@ class we {
|
|
|
6183
6183
|
if (!this.camera) return;
|
|
6184
6184
|
const n = this.nodeAvatar.getBoundingClientRect();
|
|
6185
6185
|
this.objectLeftEye.updateMatrixWorld(!0), this.objectRightEye.updateMatrixWorld(!0);
|
|
6186
|
-
const s = new f.Vector3().setFromMatrixPosition(this.objectLeftEye.matrixWorld), o = new f.Vector3().setFromMatrixPosition(this.objectRightEye.matrixWorld),
|
|
6187
|
-
|
|
6188
|
-
let u = (
|
|
6189
|
-
t === null && (t = u), e === null && (e = a),
|
|
6190
|
-
let h = E.x / (40 / 24),
|
|
6186
|
+
const s = new f.Vector3().setFromMatrixPosition(this.objectLeftEye.matrixWorld), o = new f.Vector3().setFromMatrixPosition(this.objectRightEye.matrixWorld), l = new f.Vector3().addVectors(s, o).divideScalar(2);
|
|
6187
|
+
l.project(this.camera);
|
|
6188
|
+
let u = (l.x + 1) / 2 * n.width + n.left, a = -(l.y - 1) / 2 * n.height + n.top;
|
|
6189
|
+
t === null && (t = u), e === null && (e = a), W.copy(this.armature.quaternion), W.multiply(this.poseTarget.props["Hips.quaternion"]), W.multiply(this.poseTarget.props["Spine.quaternion"]), W.multiply(this.poseTarget.props["Spine1.quaternion"]), W.multiply(this.poseTarget.props["Spine2.quaternion"]), W.multiply(this.poseTarget.props["Neck.quaternion"]), W.multiply(this.poseTarget.props["Head.quaternion"]), E.setFromQuaternion(W);
|
|
6190
|
+
let h = E.x / (40 / 24), r = E.y / (9 / 4), d = Math.min(0.4, Math.max(-0.4, this.camera.rotation.x)), c = Math.min(0.4, Math.max(-0.4, this.camera.rotation.y)), g = Math.max(window.innerWidth - u, u), y = Math.max(window.innerHeight - a, a), x = this.convertRange(e, [a - y, a + y], [-0.3, 0.6]) - h + d, L = this.convertRange(t, [u - g, u + g], [-0.8, 0.8]) - r + c;
|
|
6191
6191
|
x = Math.min(0.6, Math.max(-0.3, x)), L = Math.min(0.8, Math.max(-0.8, L));
|
|
6192
6192
|
let F = (Math.random() - 0.5) / 4, p = (Math.random() - 0.5) / 4;
|
|
6193
6193
|
if (i) {
|
|
6194
|
-
let
|
|
6195
|
-
|
|
6196
|
-
const
|
|
6194
|
+
let H = this.animQueue.findIndex((I) => I.template.name === "lookat");
|
|
6195
|
+
H !== -1 && this.animQueue.splice(H, 1);
|
|
6196
|
+
const T = {
|
|
6197
6197
|
name: "lookat",
|
|
6198
6198
|
dt: [750, i],
|
|
6199
6199
|
vs: {
|
|
@@ -6208,7 +6208,7 @@ class we {
|
|
|
6208
6208
|
headMove: [0]
|
|
6209
6209
|
}
|
|
6210
6210
|
};
|
|
6211
|
-
this.animQueue.push(this.animFactory(
|
|
6211
|
+
this.animQueue.push(this.animFactory(T));
|
|
6212
6212
|
}
|
|
6213
6213
|
}
|
|
6214
6214
|
/**
|
|
@@ -6226,10 +6226,10 @@ class we {
|
|
|
6226
6226
|
s.setFromCamera(n, this.camera);
|
|
6227
6227
|
const o = s.intersectObject(this.armature);
|
|
6228
6228
|
if (o.length > 0) {
|
|
6229
|
-
const
|
|
6229
|
+
const l = o[0].point, u = new f.Vector3(), a = new f.Vector3();
|
|
6230
6230
|
this.objectLeftArm.getWorldPosition(u), this.objectRightArm.getWorldPosition(a);
|
|
6231
|
-
const h = u.distanceToSquared(
|
|
6232
|
-
h <
|
|
6231
|
+
const h = u.distanceToSquared(l), r = a.distanceToSquared(l);
|
|
6232
|
+
h < r ? (this.ikSolve({
|
|
6233
6233
|
iterations: 20,
|
|
6234
6234
|
root: "LeftShoulder",
|
|
6235
6235
|
effector: "LeftHandMiddle1",
|
|
@@ -6238,7 +6238,7 @@ class we {
|
|
|
6238
6238
|
{ link: "LeftForeArm", minx: -0.5, maxx: 1.5, miny: -1.5, maxy: 1.5, minz: -0.5, maxz: 3, maxAngle: 0.2 },
|
|
6239
6239
|
{ link: "LeftArm", minx: -1.5, maxx: 1.5, miny: 0, maxy: 0, minz: -1, maxz: 3 }
|
|
6240
6240
|
]
|
|
6241
|
-
},
|
|
6241
|
+
}, l, !1, 1e3), this.setValue("handFistLeft", 0)) : (this.ikSolve({
|
|
6242
6242
|
iterations: 20,
|
|
6243
6243
|
root: "RightShoulder",
|
|
6244
6244
|
effector: "RightHandMiddle1",
|
|
@@ -6247,10 +6247,10 @@ class we {
|
|
|
6247
6247
|
{ link: "RightForeArm", minx: -0.5, maxx: 1.5, miny: -1.5, maxy: 1.5, minz: -3, maxz: 0.5, maxAngle: 0.2 },
|
|
6248
6248
|
{ link: "RightArm", minx: -1.5, maxx: 1.5, miny: 0, maxy: 0, minz: -1, maxz: 3 }
|
|
6249
6249
|
]
|
|
6250
|
-
},
|
|
6250
|
+
}, l, !1, 1e3), this.setValue("handFistRight", 0));
|
|
6251
6251
|
} else
|
|
6252
|
-
["LeftArm", "LeftForeArm", "LeftHand", "RightArm", "RightForeArm", "RightHand"].forEach((
|
|
6253
|
-
let u =
|
|
6252
|
+
["LeftArm", "LeftForeArm", "LeftHand", "RightArm", "RightForeArm", "RightHand"].forEach((l) => {
|
|
6253
|
+
let u = l + ".quaternion";
|
|
6254
6254
|
this.poseTarget.props[u].copy(this.getPoseTemplateProp(u)), this.poseTarget.props[u].t = this.animClock, this.poseTarget.props[u].d = 1e3;
|
|
6255
6255
|
});
|
|
6256
6256
|
return o.length > 0;
|
|
@@ -6370,18 +6370,18 @@ class we {
|
|
|
6370
6370
|
async playAnimation(t, e = null, i = 10, n = 0, s = 0.01, o = !1) {
|
|
6371
6371
|
if (!this.armature) return;
|
|
6372
6372
|
this.positionWasLocked = !o, o ? console.log("Position locking disabled for FBX animation:", t) : (this.lockAvatarPosition(), console.log("Position locked immediately before FBX animation:", t));
|
|
6373
|
-
let
|
|
6374
|
-
if (
|
|
6375
|
-
let u = this.animQueue.find((
|
|
6376
|
-
u && (u.ts[0] = 1 / 0), Object.entries(
|
|
6377
|
-
this.poseBase.props[
|
|
6373
|
+
let l = this.animClips.find((u) => u.url === t + "-" + n);
|
|
6374
|
+
if (l) {
|
|
6375
|
+
let u = this.animQueue.find((r) => r.template.name === "pose");
|
|
6376
|
+
u && (u.ts[0] = 1 / 0), Object.entries(l.pose.props).forEach((r) => {
|
|
6377
|
+
this.poseBase.props[r[0]] = r[1].clone(), this.poseTarget.props[r[0]] = r[1].clone(), this.poseTarget.props[r[0]].t = 0, this.poseTarget.props[r[0]].d = 1e3;
|
|
6378
6378
|
}), this.mixer ? console.log("Using existing mixer for FBX animation, preserving morph targets") : (this.mixer = new f.AnimationMixer(this.armature), console.log("Created new mixer for FBX animation")), this.mixer.addEventListener("finished", this.stopAnimation.bind(this), { once: !0 });
|
|
6379
|
-
const a = Math.ceil(i /
|
|
6379
|
+
const a = Math.ceil(i / l.clip.duration), h = this.mixer.clipAction(l.clip);
|
|
6380
6380
|
h.setLoop(f.LoopRepeat, a), h.clampWhenFinished = !0, this.currentFBXAction = h;
|
|
6381
6381
|
try {
|
|
6382
6382
|
h.fadeIn(0.5).play(), console.log("FBX animation started successfully:", t);
|
|
6383
|
-
} catch (
|
|
6384
|
-
console.warn("FBX animation failed to start:",
|
|
6383
|
+
} catch (r) {
|
|
6384
|
+
console.warn("FBX animation failed to start:", r), this.stopAnimation();
|
|
6385
6385
|
return;
|
|
6386
6386
|
}
|
|
6387
6387
|
if (h.getClip().tracks.length === 0) {
|
|
@@ -6403,10 +6403,10 @@ class we {
|
|
|
6403
6403
|
} catch (d) {
|
|
6404
6404
|
console.warn(`Could not verify file existence for ${t}, attempting to load anyway:`, d);
|
|
6405
6405
|
}
|
|
6406
|
-
const h = new
|
|
6407
|
-
let
|
|
6406
|
+
const h = new Re();
|
|
6407
|
+
let r;
|
|
6408
6408
|
try {
|
|
6409
|
-
|
|
6409
|
+
r = await h.loadAsync(t, e);
|
|
6410
6410
|
} catch (d) {
|
|
6411
6411
|
console.error(`Failed to load FBX animation from ${t}:`, d), console.error("Error details:", {
|
|
6412
6412
|
message: d.message,
|
|
@@ -6426,8 +6426,8 @@ class we {
|
|
|
6426
6426
|
}
|
|
6427
6427
|
return;
|
|
6428
6428
|
}
|
|
6429
|
-
if (
|
|
6430
|
-
let d =
|
|
6429
|
+
if (r && r.animations && r.animations[n]) {
|
|
6430
|
+
let d = r.animations[n];
|
|
6431
6431
|
const c = {};
|
|
6432
6432
|
d.tracks.forEach((y) => {
|
|
6433
6433
|
y.name = y.name.replaceAll("mixamorig", "");
|
|
@@ -6446,7 +6446,7 @@ class we {
|
|
|
6446
6446
|
}), this.playAnimation(t, e, i, n, s);
|
|
6447
6447
|
} else {
|
|
6448
6448
|
const d = "Animation " + t + " (ndx=" + n + ") not found";
|
|
6449
|
-
console.error(d),
|
|
6449
|
+
console.error(d), r && r.animations ? console.error(`FBX file loaded but has ${r.animations.length} animation(s), requested index ${n}`) : console.error(r ? "FBX file loaded but contains no animations" : "FBX file failed to load or is invalid");
|
|
6450
6450
|
}
|
|
6451
6451
|
}
|
|
6452
6452
|
}
|
|
@@ -6472,15 +6472,15 @@ class we {
|
|
|
6472
6472
|
if (!this.armature) return;
|
|
6473
6473
|
let o = this.poseTemplates[t];
|
|
6474
6474
|
if (!o) {
|
|
6475
|
-
const
|
|
6476
|
-
|
|
6475
|
+
const l = this.animPoses.find((u) => u.url === t + "-" + n);
|
|
6476
|
+
l && (o = l.pose);
|
|
6477
6477
|
}
|
|
6478
6478
|
if (o) {
|
|
6479
6479
|
this.poseName = t, this.mixer = null;
|
|
6480
|
-
let
|
|
6481
|
-
|
|
6480
|
+
let l = this.animQueue.find((u) => u.template.name === "pose");
|
|
6481
|
+
l && (l.ts[0] = this.animClock + i * 1e3 + 2e3), this.setPoseFromTemplate(o);
|
|
6482
6482
|
} else {
|
|
6483
|
-
let u = await new
|
|
6483
|
+
let u = await new Re().loadAsync(t, e);
|
|
6484
6484
|
if (u && u.animations && u.animations[n]) {
|
|
6485
6485
|
let a = u.animations[n];
|
|
6486
6486
|
const h = {};
|
|
@@ -6489,10 +6489,10 @@ class we {
|
|
|
6489
6489
|
const c = d.name.split(".");
|
|
6490
6490
|
c[1] === "position" ? h[d.name] = new f.Vector3(d.values[0] * s, d.values[1] * s, d.values[2] * s) : c[1] === "quaternion" ? h[d.name] = new f.Quaternion(d.values[0], d.values[1], d.values[2], d.values[3]) : c[1] === "rotation" && (h[c[0] + ".quaternion"] = new f.Quaternion().setFromEuler(new f.Euler(d.values[0], d.values[1], d.values[2], "XYZ")).normalize());
|
|
6491
6491
|
});
|
|
6492
|
-
const
|
|
6493
|
-
h["Hips.position"] && (h["Hips.position"].y < 0.5 ?
|
|
6492
|
+
const r = { props: h };
|
|
6493
|
+
h["Hips.position"] && (h["Hips.position"].y < 0.5 ? r.lying = !0 : r.standing = !0), this.animPoses.push({
|
|
6494
6494
|
url: t + "-" + n,
|
|
6495
|
-
pose:
|
|
6495
|
+
pose: r
|
|
6496
6496
|
}), this.playPose(t, e, i, n, s);
|
|
6497
6497
|
} else {
|
|
6498
6498
|
const a = "Pose " + t + " (ndx=" + n + ") not found";
|
|
@@ -6519,8 +6519,8 @@ class we {
|
|
|
6519
6519
|
let s = this.gestureTemplates[t];
|
|
6520
6520
|
if (s) {
|
|
6521
6521
|
this.gestureTimeout && (clearTimeout(this.gestureTimeout), this.gestureTimeout = null);
|
|
6522
|
-
let
|
|
6523
|
-
|
|
6522
|
+
let l = this.animQueue.findIndex((u) => u.template.name === "talkinghands");
|
|
6523
|
+
l !== -1 && (this.animQueue[l].ts = this.animQueue[l].ts.map((u) => 0)), this.gesture = this.propsToThreeObjects(s), i && (this.gesture = this.mirrorPose(this.gesture)), t === "namaste" && this.avatar.body === "M" && (this.gesture["RightArm.quaternion"].rotateTowards(new f.Quaternion(0, 1, 0, 0), -0.25), this.gesture["LeftArm.quaternion"].rotateTowards(new f.Quaternion(0, 1, 0, 0), -0.25));
|
|
6524
6524
|
for (let [u, a] of Object.entries(this.gesture))
|
|
6525
6525
|
a.t = this.animClock, a.d = n, this.poseTarget.props.hasOwnProperty(u) && (this.poseTarget.props[u].copy(a), this.poseTarget.props[u].t = this.animClock, this.poseTarget.props[u].d = n);
|
|
6526
6526
|
e && Number.isFinite(e) && (this.gestureTimeout = setTimeout(this.stopGesture.bind(this, n), 1e3 * e));
|
|
@@ -6528,20 +6528,20 @@ class we {
|
|
|
6528
6528
|
let o = this.animEmojis[t];
|
|
6529
6529
|
if (o && (o && o.link && (o = this.animEmojis[o.link]), o)) {
|
|
6530
6530
|
this.lookAtCamera(500);
|
|
6531
|
-
const
|
|
6532
|
-
if (
|
|
6533
|
-
const u =
|
|
6531
|
+
const l = this.animFactory(o);
|
|
6532
|
+
if (l.gesture = !0, e && Number.isFinite(e)) {
|
|
6533
|
+
const u = l.ts[0], h = l.ts[l.ts.length - 1] - u;
|
|
6534
6534
|
if (e * 1e3 - h > 0) {
|
|
6535
6535
|
const d = [];
|
|
6536
|
-
for (let y = 1; y <
|
|
6536
|
+
for (let y = 1; y < l.ts.length; y++) d.push(l.ts[y] - l.ts[y - 1]);
|
|
6537
6537
|
const c = o.template?.rescale || d.map((y) => y / h), g = e * 1e3 - h;
|
|
6538
|
-
|
|
6538
|
+
l.ts = l.ts.map((y, x, L) => x === 0 ? u : L[x - 1] + d[x - 1] + c[x - 1] * g);
|
|
6539
6539
|
} else {
|
|
6540
6540
|
const d = e * 1e3 / h;
|
|
6541
|
-
|
|
6541
|
+
l.ts = l.ts.map((c) => u + d * (c - u));
|
|
6542
6542
|
}
|
|
6543
6543
|
}
|
|
6544
|
-
this.animQueue.push(
|
|
6544
|
+
this.animQueue.push(l);
|
|
6545
6545
|
}
|
|
6546
6546
|
}
|
|
6547
6547
|
/**
|
|
@@ -6568,7 +6568,7 @@ class we {
|
|
|
6568
6568
|
* @param {numeric} [d=null] If set, apply in d milliseconds
|
|
6569
6569
|
*/
|
|
6570
6570
|
ikSolve(t, e = null, i = !1, n = null) {
|
|
6571
|
-
const s = new f.Vector3(), o = new f.Vector3(),
|
|
6571
|
+
const s = new f.Vector3(), o = new f.Vector3(), l = new f.Vector3(), u = new f.Vector3(), a = new f.Quaternion(), h = new f.Vector3(), r = new f.Vector3(), d = new f.Vector3(), c = this.ikMesh.getObjectByName(t.root);
|
|
6572
6572
|
c.position.setFromMatrixPosition(this.armature.getObjectByName(t.root).matrixWorld), c.quaternion.setFromRotationMatrix(this.armature.getObjectByName(t.root).matrixWorld), e && i && e.applyQuaternion(this.armature.quaternion).add(c.position);
|
|
6573
6573
|
const g = this.ikMesh.getObjectByName(t.effector), y = t.links;
|
|
6574
6574
|
y.forEach((L) => {
|
|
@@ -6578,11 +6578,11 @@ class we {
|
|
|
6578
6578
|
if (e)
|
|
6579
6579
|
for (let L = 0; L < x; L++) {
|
|
6580
6580
|
let F = !1;
|
|
6581
|
-
for (let p = 0,
|
|
6582
|
-
const
|
|
6583
|
-
|
|
6584
|
-
let I = s.dot(
|
|
6585
|
-
I > 1 ? I = 1 : I < -1 && (I = -1), I = Math.acos(I), !(I < 1e-5) && (y[p].minAngle !== void 0 && I < y[p].minAngle && (I = y[p].minAngle), y[p].maxAngle !== void 0 && I > y[p].maxAngle && (I = y[p].maxAngle),
|
|
6581
|
+
for (let p = 0, H = y.length; p < H; p++) {
|
|
6582
|
+
const T = y[p].bone;
|
|
6583
|
+
T.matrixWorld.decompose(u, a, h), a.invert(), o.setFromMatrixPosition(g.matrixWorld), l.subVectors(o, u), l.applyQuaternion(a), l.normalize(), s.subVectors(e, u), s.applyQuaternion(a), s.normalize();
|
|
6584
|
+
let I = s.dot(l);
|
|
6585
|
+
I > 1 ? I = 1 : I < -1 && (I = -1), I = Math.acos(I), !(I < 1e-5) && (y[p].minAngle !== void 0 && I < y[p].minAngle && (I = y[p].minAngle), y[p].maxAngle !== void 0 && I > y[p].maxAngle && (I = y[p].maxAngle), r.crossVectors(l, s), r.normalize(), W.setFromAxisAngle(r, I), T.quaternion.multiply(W), T.rotation.setFromVector3(d.setFromEuler(T.rotation).clamp(new f.Vector3(
|
|
6586
6586
|
y[p].minx !== void 0 ? y[p].minx : -1 / 0,
|
|
6587
6587
|
y[p].miny !== void 0 ? y[p].miny : -1 / 0,
|
|
6588
6588
|
y[p].minz !== void 0 ? y[p].minz : -1 / 0
|
|
@@ -6590,7 +6590,7 @@ class we {
|
|
|
6590
6590
|
y[p].maxx !== void 0 ? y[p].maxx : 1 / 0,
|
|
6591
6591
|
y[p].maxy !== void 0 ? y[p].maxy : 1 / 0,
|
|
6592
6592
|
y[p].maxz !== void 0 ? y[p].maxz : 1 / 0
|
|
6593
|
-
))),
|
|
6593
|
+
))), T.updateMatrixWorld(!0), F = !0);
|
|
6594
6594
|
}
|
|
6595
6595
|
if (!F) break;
|
|
6596
6596
|
}
|
|
@@ -6671,11 +6671,11 @@ const ze = fe(({
|
|
|
6671
6671
|
ttsService: n = null,
|
|
6672
6672
|
ttsVoice: s = null,
|
|
6673
6673
|
ttsApiKey: o = null,
|
|
6674
|
-
bodyMovement:
|
|
6674
|
+
bodyMovement: l = "idle",
|
|
6675
6675
|
movementIntensity: u = 0.5,
|
|
6676
6676
|
showFullAvatar: a = !0,
|
|
6677
6677
|
cameraView: h = "upper",
|
|
6678
|
-
onReady:
|
|
6678
|
+
onReady: r = () => {
|
|
6679
6679
|
},
|
|
6680
6680
|
onLoading: d = () => {
|
|
6681
6681
|
},
|
|
@@ -6685,9 +6685,9 @@ const ze = fe(({
|
|
|
6685
6685
|
style: y = {},
|
|
6686
6686
|
animations: x = {}
|
|
6687
6687
|
}, L) => {
|
|
6688
|
-
const F =
|
|
6688
|
+
const F = G(null), p = G(null), H = G(a), [T, I] = re(!0), [B, D] = re(null), [Y, oe] = re(!1);
|
|
6689
6689
|
le(() => {
|
|
6690
|
-
|
|
6690
|
+
H.current = a;
|
|
6691
6691
|
}, [a]);
|
|
6692
6692
|
const S = be(), P = n || S.service;
|
|
6693
6693
|
let O;
|
|
@@ -6713,7 +6713,7 @@ const ze = fe(({
|
|
|
6713
6713
|
// Override API key if provided via props
|
|
6714
6714
|
apiKey: o !== null ? o : S.apiKey
|
|
6715
6715
|
};
|
|
6716
|
-
const
|
|
6716
|
+
const V = {
|
|
6717
6717
|
url: N,
|
|
6718
6718
|
body: t,
|
|
6719
6719
|
avatarMood: e,
|
|
@@ -6721,7 +6721,7 @@ const ze = fe(({
|
|
|
6721
6721
|
ttsVoice: s || O.defaultVoice,
|
|
6722
6722
|
lipsyncLang: "en",
|
|
6723
6723
|
showFullAvatar: a,
|
|
6724
|
-
bodyMovement:
|
|
6724
|
+
bodyMovement: l,
|
|
6725
6725
|
movementIntensity: u
|
|
6726
6726
|
}, _ = {
|
|
6727
6727
|
ttsEndpoint: O.endpoint,
|
|
@@ -6732,85 +6732,85 @@ const ze = fe(({
|
|
|
6732
6732
|
}, K = M(async () => {
|
|
6733
6733
|
if (!(!F.current || p.current))
|
|
6734
6734
|
try {
|
|
6735
|
-
if (I(!0), D(null), p.current = new we(F.current, _), p.current.controls && (p.current.controls.enableRotate = !1, p.current.controls.enableZoom = !1, p.current.controls.enablePan = !1, p.current.controls.enableDamping = !1), x && Object.keys(x).length > 0 && (p.current.customAnimations = x), await p.current.showAvatar(
|
|
6736
|
-
if (
|
|
6737
|
-
const
|
|
6738
|
-
d(
|
|
6735
|
+
if (I(!0), D(null), p.current = new we(F.current, _), p.current.controls && (p.current.controls.enableRotate = !1, p.current.controls.enableZoom = !1, p.current.controls.enablePan = !1, p.current.controls.enableDamping = !1), x && Object.keys(x).length > 0 && (p.current.customAnimations = x), await p.current.showAvatar(V, (z) => {
|
|
6736
|
+
if (z.lengthComputable) {
|
|
6737
|
+
const C = Math.min(100, Math.round(z.loaded / z.total * 100));
|
|
6738
|
+
d(C);
|
|
6739
6739
|
}
|
|
6740
|
-
}), await new Promise((
|
|
6741
|
-
const
|
|
6742
|
-
p.current.lipsync && Object.keys(p.current.lipsync).length > 0 ?
|
|
6740
|
+
}), await new Promise((z) => {
|
|
6741
|
+
const C = () => {
|
|
6742
|
+
p.current.lipsync && Object.keys(p.current.lipsync).length > 0 ? z() : setTimeout(C, 100);
|
|
6743
6743
|
};
|
|
6744
|
-
|
|
6744
|
+
C();
|
|
6745
6745
|
}), p.current && p.current.setShowFullAvatar)
|
|
6746
6746
|
try {
|
|
6747
6747
|
p.current.setShowFullAvatar(a);
|
|
6748
|
-
} catch (
|
|
6749
|
-
console.warn("Error setting full body mode on initialization:",
|
|
6748
|
+
} catch (z) {
|
|
6749
|
+
console.warn("Error setting full body mode on initialization:", z);
|
|
6750
6750
|
}
|
|
6751
|
-
p.current && p.current.controls && (p.current.controls.enableRotate = !1, p.current.controls.enableZoom = !1, p.current.controls.enablePan = !1, p.current.controls.enableDamping = !1, p.current.controls.update()), I(!1), oe(!0),
|
|
6751
|
+
p.current && p.current.controls && (p.current.controls.enableRotate = !1, p.current.controls.enableZoom = !1, p.current.controls.enablePan = !1, p.current.controls.enableDamping = !1, p.current.controls.update()), I(!1), oe(!0), r(p.current);
|
|
6752
6752
|
const k = () => {
|
|
6753
6753
|
document.visibilityState === "visible" ? p.current?.start() : p.current?.stop();
|
|
6754
6754
|
};
|
|
6755
6755
|
return document.addEventListener("visibilitychange", k), () => {
|
|
6756
6756
|
document.removeEventListener("visibilitychange", k);
|
|
6757
6757
|
};
|
|
6758
|
-
} catch (
|
|
6759
|
-
console.error("Error initializing TalkingHead:",
|
|
6758
|
+
} catch (v) {
|
|
6759
|
+
console.error("Error initializing TalkingHead:", v), D(v.message || "Failed to initialize avatar"), I(!1), c(v);
|
|
6760
6760
|
}
|
|
6761
|
-
}, [N, t, e, i, n, s, o, a,
|
|
6761
|
+
}, [N, t, e, i, n, s, o, a, l, u, h]);
|
|
6762
6762
|
le(() => (K(), () => {
|
|
6763
6763
|
p.current && (p.current.stop(), p.current.dispose(), p.current = null);
|
|
6764
6764
|
}), [K]), le(() => {
|
|
6765
6765
|
if (!F.current || !p.current) return;
|
|
6766
|
-
const
|
|
6767
|
-
for (const
|
|
6766
|
+
const v = new ResizeObserver((z) => {
|
|
6767
|
+
for (const C of z)
|
|
6768
6768
|
p.current && p.current.onResize && p.current.onResize();
|
|
6769
6769
|
});
|
|
6770
|
-
|
|
6770
|
+
v.observe(F.current);
|
|
6771
6771
|
const k = () => {
|
|
6772
6772
|
p.current && p.current.onResize && p.current.onResize();
|
|
6773
6773
|
};
|
|
6774
6774
|
return window.addEventListener("resize", k), () => {
|
|
6775
|
-
|
|
6775
|
+
v.disconnect(), window.removeEventListener("resize", k);
|
|
6776
6776
|
};
|
|
6777
|
-
}, [
|
|
6777
|
+
}, [Y]);
|
|
6778
6778
|
const se = M(async () => {
|
|
6779
6779
|
if (p.current && p.current.audioCtx)
|
|
6780
6780
|
try {
|
|
6781
6781
|
(p.current.audioCtx.state === "suspended" || p.current.audioCtx.state === "interrupted") && (await p.current.audioCtx.resume(), console.log("Audio context resumed"));
|
|
6782
|
-
} catch (
|
|
6783
|
-
console.warn("Failed to resume audio context:",
|
|
6782
|
+
} catch (v) {
|
|
6783
|
+
console.warn("Failed to resume audio context:", v);
|
|
6784
6784
|
}
|
|
6785
|
-
}, []), pe = M(async (
|
|
6786
|
-
if (p.current &&
|
|
6785
|
+
}, []), pe = M(async (v, k = {}) => {
|
|
6786
|
+
if (p.current && Y)
|
|
6787
6787
|
try {
|
|
6788
6788
|
await se();
|
|
6789
|
-
const
|
|
6789
|
+
const z = {
|
|
6790
6790
|
...k,
|
|
6791
|
-
lipsyncLang: k.lipsyncLang ||
|
|
6791
|
+
lipsyncLang: k.lipsyncLang || V.lipsyncLang || "en"
|
|
6792
6792
|
};
|
|
6793
6793
|
if (k.onSpeechEnd && p.current) {
|
|
6794
|
-
const
|
|
6795
|
-
let
|
|
6794
|
+
const C = p.current;
|
|
6795
|
+
let U = null, J = 0;
|
|
6796
6796
|
const ye = 1200;
|
|
6797
6797
|
let he = !1;
|
|
6798
|
-
|
|
6799
|
-
if (
|
|
6800
|
-
if (
|
|
6798
|
+
U = setInterval(() => {
|
|
6799
|
+
if (J++, J > ye) {
|
|
6800
|
+
if (U && (clearInterval(U), U = null), !he) {
|
|
6801
6801
|
he = !0;
|
|
6802
6802
|
try {
|
|
6803
6803
|
k.onSpeechEnd();
|
|
6804
|
-
} catch (
|
|
6805
|
-
console.error("Error in onSpeechEnd callback (timeout):",
|
|
6804
|
+
} catch (ve) {
|
|
6805
|
+
console.error("Error in onSpeechEnd callback (timeout):", ve);
|
|
6806
6806
|
}
|
|
6807
6807
|
}
|
|
6808
6808
|
return;
|
|
6809
6809
|
}
|
|
6810
|
-
const He = !
|
|
6811
|
-
|
|
6812
|
-
if (
|
|
6813
|
-
he = !0,
|
|
6810
|
+
const He = !C.speechQueue || C.speechQueue.length === 0, Te = !C.audioPlaylist || C.audioPlaylist.length === 0;
|
|
6811
|
+
C && C.isSpeaking === !1 && He && Te && C.isAudioPlaying === !1 && !he && setTimeout(() => {
|
|
6812
|
+
if (C && C.isSpeaking === !1 && (!C.speechQueue || C.speechQueue.length === 0) && (!C.audioPlaylist || C.audioPlaylist.length === 0) && C.isAudioPlaying === !1 && !he) {
|
|
6813
|
+
he = !0, U && (clearInterval(U), U = null);
|
|
6814
6814
|
try {
|
|
6815
6815
|
k.onSpeechEnd();
|
|
6816
6816
|
} catch (Me) {
|
|
@@ -6820,57 +6820,57 @@ const ze = fe(({
|
|
|
6820
6820
|
}, 100);
|
|
6821
6821
|
}, 100);
|
|
6822
6822
|
}
|
|
6823
|
-
p.current.lipsync && Object.keys(p.current.lipsync).length > 0 ? (p.current.setSlowdownRate && p.current.setSlowdownRate(1.05), p.current.speakText(
|
|
6824
|
-
await se(), p.current && p.current.lipsync && (p.current.setSlowdownRate && p.current.setSlowdownRate(1.05), p.current.speakText(
|
|
6823
|
+
p.current.lipsync && Object.keys(p.current.lipsync).length > 0 ? (p.current.setSlowdownRate && p.current.setSlowdownRate(1.05), p.current.speakText(v, z)) : setTimeout(async () => {
|
|
6824
|
+
await se(), p.current && p.current.lipsync && (p.current.setSlowdownRate && p.current.setSlowdownRate(1.05), p.current.speakText(v, z));
|
|
6825
6825
|
}, 100);
|
|
6826
|
-
} catch (
|
|
6827
|
-
console.error("Error speaking text:",
|
|
6826
|
+
} catch (z) {
|
|
6827
|
+
console.error("Error speaking text:", z), D(z.message || "Failed to speak text");
|
|
6828
6828
|
}
|
|
6829
|
-
}, [
|
|
6829
|
+
}, [Y, se, V.lipsyncLang]), ue = M(() => {
|
|
6830
6830
|
p.current && (p.current.stopSpeaking(), p.current.setSlowdownRate && p.current.setSlowdownRate(1));
|
|
6831
|
-
}, []), ge = M((
|
|
6832
|
-
p.current && p.current.setMood(
|
|
6833
|
-
}, []), Q = M((
|
|
6834
|
-
p.current && p.current.setSlowdownRate && p.current.setSlowdownRate(
|
|
6835
|
-
}, []), b = M((
|
|
6831
|
+
}, []), ge = M((v) => {
|
|
6832
|
+
p.current && p.current.setMood(v);
|
|
6833
|
+
}, []), Q = M((v) => {
|
|
6834
|
+
p.current && p.current.setSlowdownRate && p.current.setSlowdownRate(v);
|
|
6835
|
+
}, []), b = M((v, k = !1) => {
|
|
6836
6836
|
if (p.current && p.current.playAnimation) {
|
|
6837
|
-
if (x && x[
|
|
6837
|
+
if (x && x[v] && (v = x[v]), p.current.setShowFullAvatar)
|
|
6838
6838
|
try {
|
|
6839
|
-
p.current.setShowFullAvatar(
|
|
6840
|
-
} catch (
|
|
6841
|
-
console.warn("Error setting full body mode:",
|
|
6839
|
+
p.current.setShowFullAvatar(H.current);
|
|
6840
|
+
} catch (C) {
|
|
6841
|
+
console.warn("Error setting full body mode:", C);
|
|
6842
6842
|
}
|
|
6843
|
-
if (
|
|
6843
|
+
if (v.includes("."))
|
|
6844
6844
|
try {
|
|
6845
|
-
p.current.playAnimation(
|
|
6846
|
-
} catch (
|
|
6847
|
-
console.warn(`Failed to play ${
|
|
6845
|
+
p.current.playAnimation(v, null, 10, 0, 0.01, k);
|
|
6846
|
+
} catch (C) {
|
|
6847
|
+
console.warn(`Failed to play ${v}:`, C);
|
|
6848
6848
|
try {
|
|
6849
6849
|
p.current.setBodyMovement("idle");
|
|
6850
|
-
} catch (
|
|
6851
|
-
console.warn("Fallback animation also failed:",
|
|
6850
|
+
} catch (U) {
|
|
6851
|
+
console.warn("Fallback animation also failed:", U);
|
|
6852
6852
|
}
|
|
6853
6853
|
}
|
|
6854
6854
|
else {
|
|
6855
|
-
const
|
|
6856
|
-
let
|
|
6857
|
-
for (const
|
|
6855
|
+
const C = [".fbx", ".glb", ".gltf"];
|
|
6856
|
+
let U = !1;
|
|
6857
|
+
for (const J of C)
|
|
6858
6858
|
try {
|
|
6859
|
-
p.current.playAnimation(
|
|
6859
|
+
p.current.playAnimation(v + J, null, 10, 0, 0.01, k), U = !0;
|
|
6860
6860
|
break;
|
|
6861
6861
|
} catch {
|
|
6862
6862
|
}
|
|
6863
|
-
if (!
|
|
6864
|
-
console.warn("Animation not found:",
|
|
6863
|
+
if (!U) {
|
|
6864
|
+
console.warn("Animation not found:", v);
|
|
6865
6865
|
try {
|
|
6866
6866
|
p.current.setBodyMovement("idle");
|
|
6867
|
-
} catch (
|
|
6868
|
-
console.warn("Fallback animation also failed:",
|
|
6867
|
+
} catch (J) {
|
|
6868
|
+
console.warn("Fallback animation also failed:", J);
|
|
6869
6869
|
}
|
|
6870
6870
|
}
|
|
6871
6871
|
}
|
|
6872
6872
|
}
|
|
6873
|
-
}, [x]),
|
|
6873
|
+
}, [x]), R = M(() => {
|
|
6874
6874
|
p.current && p.current.onResize && p.current.onResize();
|
|
6875
6875
|
}, []);
|
|
6876
6876
|
return xe(L, () => ({
|
|
@@ -6880,30 +6880,30 @@ const ze = fe(({
|
|
|
6880
6880
|
setMood: ge,
|
|
6881
6881
|
setTimingAdjustment: Q,
|
|
6882
6882
|
playAnimation: b,
|
|
6883
|
-
isReady:
|
|
6883
|
+
isReady: Y,
|
|
6884
6884
|
talkingHead: p.current,
|
|
6885
|
-
handleResize:
|
|
6886
|
-
setBodyMovement: (
|
|
6885
|
+
handleResize: R,
|
|
6886
|
+
setBodyMovement: (v) => {
|
|
6887
6887
|
if (p.current && p.current.setShowFullAvatar && p.current.setBodyMovement)
|
|
6888
6888
|
try {
|
|
6889
|
-
p.current.setShowFullAvatar(
|
|
6889
|
+
p.current.setShowFullAvatar(H.current), p.current.setBodyMovement(v);
|
|
6890
6890
|
} catch (k) {
|
|
6891
6891
|
console.warn("Error setting body movement:", k);
|
|
6892
6892
|
}
|
|
6893
6893
|
},
|
|
6894
|
-
setMovementIntensity: (
|
|
6894
|
+
setMovementIntensity: (v) => p.current?.setMovementIntensity(v),
|
|
6895
6895
|
playRandomDance: () => {
|
|
6896
6896
|
if (p.current && p.current.setShowFullAvatar && p.current.playRandomDance)
|
|
6897
6897
|
try {
|
|
6898
|
-
p.current.setShowFullAvatar(
|
|
6899
|
-
} catch (
|
|
6900
|
-
console.warn("Error playing random dance:",
|
|
6898
|
+
p.current.setShowFullAvatar(H.current), p.current.playRandomDance();
|
|
6899
|
+
} catch (v) {
|
|
6900
|
+
console.warn("Error playing random dance:", v);
|
|
6901
6901
|
}
|
|
6902
6902
|
},
|
|
6903
|
-
playReaction: (
|
|
6903
|
+
playReaction: (v) => {
|
|
6904
6904
|
if (p.current && p.current.setShowFullAvatar && p.current.playReaction)
|
|
6905
6905
|
try {
|
|
6906
|
-
p.current.setShowFullAvatar(
|
|
6906
|
+
p.current.setShowFullAvatar(H.current), p.current.playReaction(v);
|
|
6907
6907
|
} catch (k) {
|
|
6908
6908
|
console.warn("Error playing reaction:", k);
|
|
6909
6909
|
}
|
|
@@ -6911,15 +6911,15 @@ const ze = fe(({
|
|
|
6911
6911
|
playCelebration: () => {
|
|
6912
6912
|
if (p.current && p.current.setShowFullAvatar && p.current.playCelebration)
|
|
6913
6913
|
try {
|
|
6914
|
-
p.current.setShowFullAvatar(
|
|
6915
|
-
} catch (
|
|
6916
|
-
console.warn("Error playing celebration:",
|
|
6914
|
+
p.current.setShowFullAvatar(H.current), p.current.playCelebration();
|
|
6915
|
+
} catch (v) {
|
|
6916
|
+
console.warn("Error playing celebration:", v);
|
|
6917
6917
|
}
|
|
6918
6918
|
},
|
|
6919
|
-
setShowFullAvatar: (
|
|
6919
|
+
setShowFullAvatar: (v) => {
|
|
6920
6920
|
if (p.current && p.current.setShowFullAvatar)
|
|
6921
6921
|
try {
|
|
6922
|
-
|
|
6922
|
+
H.current = v, p.current.setShowFullAvatar(v);
|
|
6923
6923
|
} catch (k) {
|
|
6924
6924
|
console.warn("Error setting showFullAvatar:", k);
|
|
6925
6925
|
}
|
|
@@ -6928,16 +6928,16 @@ const ze = fe(({
|
|
|
6928
6928
|
if (p.current && p.current.lockAvatarPosition)
|
|
6929
6929
|
try {
|
|
6930
6930
|
p.current.lockAvatarPosition();
|
|
6931
|
-
} catch (
|
|
6932
|
-
console.warn("Error locking avatar position:",
|
|
6931
|
+
} catch (v) {
|
|
6932
|
+
console.warn("Error locking avatar position:", v);
|
|
6933
6933
|
}
|
|
6934
6934
|
},
|
|
6935
6935
|
unlockAvatarPosition: () => {
|
|
6936
6936
|
if (p.current && p.current.unlockAvatarPosition)
|
|
6937
6937
|
try {
|
|
6938
6938
|
p.current.unlockAvatarPosition();
|
|
6939
|
-
} catch (
|
|
6940
|
-
console.warn("Error unlocking avatar position:",
|
|
6939
|
+
} catch (v) {
|
|
6940
|
+
console.warn("Error unlocking avatar position:", v);
|
|
6941
6941
|
}
|
|
6942
6942
|
}
|
|
6943
6943
|
})), /* @__PURE__ */ ke(
|
|
@@ -6963,7 +6963,7 @@ const ze = fe(({
|
|
|
6963
6963
|
}
|
|
6964
6964
|
}
|
|
6965
6965
|
),
|
|
6966
|
-
|
|
6966
|
+
T && /* @__PURE__ */ ne("div", { className: "loading-overlay", style: {
|
|
6967
6967
|
position: "absolute",
|
|
6968
6968
|
top: "50%",
|
|
6969
6969
|
left: "50%",
|
|
@@ -7000,8 +7000,8 @@ const it = fe(({
|
|
|
7000
7000
|
className: n = "",
|
|
7001
7001
|
style: s = {},
|
|
7002
7002
|
avatarConfig: o = {}
|
|
7003
|
-
},
|
|
7004
|
-
const u =
|
|
7003
|
+
}, l) => {
|
|
7004
|
+
const u = G(null), a = G(null), [h, r] = re(!0), [d, c] = re(null), [g, y] = re(!1), x = be(), L = o.ttsService || x.service, F = L === "browser" ? {
|
|
7005
7005
|
endpoint: "",
|
|
7006
7006
|
apiKey: null,
|
|
7007
7007
|
defaultVoice: "Google US English"
|
|
@@ -7025,38 +7025,38 @@ const it = fe(({
|
|
|
7025
7025
|
bodyMovement: "idle",
|
|
7026
7026
|
movementIntensity: 0.5,
|
|
7027
7027
|
...o
|
|
7028
|
-
},
|
|
7028
|
+
}, H = {
|
|
7029
7029
|
ttsEndpoint: F.endpoint,
|
|
7030
7030
|
ttsApikey: F.apiKey,
|
|
7031
7031
|
ttsService: L,
|
|
7032
7032
|
lipsyncModules: ["en"],
|
|
7033
7033
|
cameraView: "upper"
|
|
7034
|
-
},
|
|
7034
|
+
}, T = M(async () => {
|
|
7035
7035
|
if (!(!u.current || a.current))
|
|
7036
7036
|
try {
|
|
7037
|
-
if (
|
|
7037
|
+
if (r(!0), c(null), a.current = new we(u.current, H), await a.current.showAvatar(p, (O) => {
|
|
7038
7038
|
if (O.lengthComputable) {
|
|
7039
|
-
const
|
|
7040
|
-
t(
|
|
7039
|
+
const V = Math.min(100, Math.round(O.loaded / O.total * 100));
|
|
7040
|
+
t(V);
|
|
7041
7041
|
}
|
|
7042
7042
|
}), a.current.morphs && a.current.morphs.length > 0) {
|
|
7043
7043
|
const O = a.current.morphs[0].morphTargetDictionary;
|
|
7044
7044
|
console.log("Available morph targets:", Object.keys(O));
|
|
7045
|
-
const
|
|
7046
|
-
console.log("Viseme morph targets found:",
|
|
7045
|
+
const V = Object.keys(O).filter((_) => _.startsWith("viseme_"));
|
|
7046
|
+
console.log("Viseme morph targets found:", V), V.length === 0 && (console.warn("No viseme morph targets found! Lip-sync will not work properly."), console.log("Expected viseme targets: viseme_aa, viseme_E, viseme_I, viseme_O, viseme_U, viseme_PP, viseme_SS, viseme_TH, viseme_DD, viseme_FF, viseme_kk, viseme_nn, viseme_RR, viseme_CH, viseme_sil"));
|
|
7047
7047
|
}
|
|
7048
7048
|
if (await new Promise((O) => {
|
|
7049
|
-
const
|
|
7050
|
-
a.current.lipsync && Object.keys(a.current.lipsync).length > 0 ? (console.log("Lip-sync modules loaded:", Object.keys(a.current.lipsync)), O()) : (console.log("Waiting for lip-sync modules to load..."), setTimeout(
|
|
7049
|
+
const V = () => {
|
|
7050
|
+
a.current.lipsync && Object.keys(a.current.lipsync).length > 0 ? (console.log("Lip-sync modules loaded:", Object.keys(a.current.lipsync)), O()) : (console.log("Waiting for lip-sync modules to load..."), setTimeout(V, 100));
|
|
7051
7051
|
};
|
|
7052
|
-
|
|
7052
|
+
V();
|
|
7053
7053
|
}), a.current && a.current.setShowFullAvatar)
|
|
7054
7054
|
try {
|
|
7055
7055
|
a.current.setShowFullAvatar(!0), console.log("Avatar initialized in full body mode");
|
|
7056
7056
|
} catch (O) {
|
|
7057
7057
|
console.warn("Error setting full body mode on initialization:", O);
|
|
7058
7058
|
}
|
|
7059
|
-
|
|
7059
|
+
r(!1), y(!0), i(a.current);
|
|
7060
7060
|
const P = () => {
|
|
7061
7061
|
document.visibilityState === "visible" ? a.current?.start() : a.current?.stop();
|
|
7062
7062
|
};
|
|
@@ -7064,12 +7064,12 @@ const it = fe(({
|
|
|
7064
7064
|
document.removeEventListener("visibilitychange", P);
|
|
7065
7065
|
};
|
|
7066
7066
|
} catch (S) {
|
|
7067
|
-
console.error("Error initializing TalkingHead:", S), c(S.message || "Failed to initialize avatar"),
|
|
7067
|
+
console.error("Error initializing TalkingHead:", S), c(S.message || "Failed to initialize avatar"), r(!1), e(S);
|
|
7068
7068
|
}
|
|
7069
7069
|
}, []);
|
|
7070
|
-
le(() => (
|
|
7070
|
+
le(() => (T(), () => {
|
|
7071
7071
|
a.current && (a.current.stop(), a.current.dispose(), a.current = null);
|
|
7072
|
-
}), [
|
|
7072
|
+
}), [T]);
|
|
7073
7073
|
const I = M((S) => {
|
|
7074
7074
|
if (a.current && g)
|
|
7075
7075
|
try {
|
|
@@ -7085,21 +7085,21 @@ const it = fe(({
|
|
|
7085
7085
|
a.current && (a.current.stopSpeaking(), a.current.setSlowdownRate && (a.current.setSlowdownRate(1), console.log("Reset timing to normal")));
|
|
7086
7086
|
}, []), D = M((S) => {
|
|
7087
7087
|
a.current && a.current.setMood(S);
|
|
7088
|
-
}, []),
|
|
7088
|
+
}, []), Y = M((S) => {
|
|
7089
7089
|
a.current && a.current.setSlowdownRate && (a.current.setSlowdownRate(S), console.log("Timing adjustment set to:", S));
|
|
7090
7090
|
}, []), oe = M((S, P = !1) => {
|
|
7091
7091
|
if (a.current && a.current.playAnimation) {
|
|
7092
7092
|
if (a.current.setShowFullAvatar)
|
|
7093
7093
|
try {
|
|
7094
7094
|
a.current.setShowFullAvatar(!0);
|
|
7095
|
-
} catch (
|
|
7096
|
-
console.warn("Error setting full body mode:",
|
|
7095
|
+
} catch (V) {
|
|
7096
|
+
console.warn("Error setting full body mode:", V);
|
|
7097
7097
|
}
|
|
7098
7098
|
if (S.includes("."))
|
|
7099
7099
|
try {
|
|
7100
7100
|
a.current.playAnimation(S, null, 10, 0, 0.01, P), console.log("Playing animation:", S);
|
|
7101
|
-
} catch (
|
|
7102
|
-
console.log(`Failed to play ${S}:`,
|
|
7101
|
+
} catch (V) {
|
|
7102
|
+
console.log(`Failed to play ${S}:`, V);
|
|
7103
7103
|
try {
|
|
7104
7104
|
a.current.setBodyMovement("idle"), console.log("Fallback to idle animation");
|
|
7105
7105
|
} catch (_) {
|
|
@@ -7107,9 +7107,9 @@ const it = fe(({
|
|
|
7107
7107
|
}
|
|
7108
7108
|
}
|
|
7109
7109
|
else {
|
|
7110
|
-
const
|
|
7110
|
+
const V = [".fbx", ".glb", ".gltf"];
|
|
7111
7111
|
let _ = !1;
|
|
7112
|
-
for (const K of
|
|
7112
|
+
for (const K of V)
|
|
7113
7113
|
try {
|
|
7114
7114
|
a.current.playAnimation(S + K, null, 10, 0, 0.01, P), console.log("Playing animation:", S + K), _ = !0;
|
|
7115
7115
|
break;
|
|
@@ -7128,11 +7128,11 @@ const it = fe(({
|
|
|
7128
7128
|
} else
|
|
7129
7129
|
console.warn("Animation system not available or animation not found:", S);
|
|
7130
7130
|
}, []);
|
|
7131
|
-
return xe(
|
|
7131
|
+
return xe(l, () => ({
|
|
7132
7132
|
speakText: I,
|
|
7133
7133
|
stopSpeaking: B,
|
|
7134
7134
|
setMood: D,
|
|
7135
|
-
setTimingAdjustment:
|
|
7135
|
+
setTimingAdjustment: Y,
|
|
7136
7136
|
playAnimation: oe,
|
|
7137
7137
|
isReady: g,
|
|
7138
7138
|
talkingHead: a.current,
|
|
@@ -7242,11 +7242,11 @@ const nt = fe(({
|
|
|
7242
7242
|
},
|
|
7243
7243
|
onCurriculumComplete: o = () => {
|
|
7244
7244
|
},
|
|
7245
|
-
onCustomAction:
|
|
7245
|
+
onCustomAction: l = () => {
|
|
7246
7246
|
},
|
|
7247
7247
|
autoStart: u = !1
|
|
7248
7248
|
}, a) => {
|
|
7249
|
-
const h =
|
|
7249
|
+
const h = G(null), r = G({
|
|
7250
7250
|
currentModuleIndex: 0,
|
|
7251
7251
|
currentLessonIndex: 0,
|
|
7252
7252
|
currentQuestionIndex: 0,
|
|
@@ -7256,18 +7256,18 @@ const nt = fe(({
|
|
|
7256
7256
|
curriculumCompleted: !1,
|
|
7257
7257
|
score: 0,
|
|
7258
7258
|
totalQuestions: 0
|
|
7259
|
-
}), d =
|
|
7259
|
+
}), d = G({
|
|
7260
7260
|
onLessonStart: i,
|
|
7261
7261
|
onLessonComplete: n,
|
|
7262
7262
|
onQuestionAnswer: s,
|
|
7263
7263
|
onCurriculumComplete: o,
|
|
7264
|
-
onCustomAction:
|
|
7265
|
-
}), c =
|
|
7264
|
+
onCustomAction: l
|
|
7265
|
+
}), c = G(null), g = G(null), y = G(null), x = G(null), L = G(null), F = G(null), p = G(null), H = G(N?.curriculum || {
|
|
7266
7266
|
title: "Default Curriculum",
|
|
7267
7267
|
description: "No curriculum data provided",
|
|
7268
7268
|
language: "en",
|
|
7269
7269
|
modules: []
|
|
7270
|
-
}),
|
|
7270
|
+
}), T = G({
|
|
7271
7271
|
avatarUrl: t.avatarUrl || "/avatars/brunette.glb",
|
|
7272
7272
|
avatarBody: t.avatarBody || "F",
|
|
7273
7273
|
mood: t.mood || "happy",
|
|
@@ -7287,15 +7287,15 @@ const nt = fe(({
|
|
|
7287
7287
|
onLessonComplete: n,
|
|
7288
7288
|
onQuestionAnswer: s,
|
|
7289
7289
|
onCurriculumComplete: o,
|
|
7290
|
-
onCustomAction:
|
|
7290
|
+
onCustomAction: l
|
|
7291
7291
|
};
|
|
7292
|
-
}, [i, n, s, o,
|
|
7293
|
-
|
|
7292
|
+
}, [i, n, s, o, l]), le(() => {
|
|
7293
|
+
H.current = N?.curriculum || {
|
|
7294
7294
|
title: "Default Curriculum",
|
|
7295
7295
|
description: "No curriculum data provided",
|
|
7296
7296
|
language: "en",
|
|
7297
7297
|
modules: []
|
|
7298
|
-
},
|
|
7298
|
+
}, T.current = {
|
|
7299
7299
|
avatarUrl: t.avatarUrl || "/avatars/brunette.glb",
|
|
7300
7300
|
avatarBody: t.avatarBody || "F",
|
|
7301
7301
|
mood: t.mood || "happy",
|
|
@@ -7310,22 +7310,22 @@ const nt = fe(({
|
|
|
7310
7310
|
lipsyncLang: "en"
|
|
7311
7311
|
};
|
|
7312
7312
|
}, [N, t, e]);
|
|
7313
|
-
const I = M(() => (
|
|
7314
|
-
|
|
7315
|
-
const b =
|
|
7316
|
-
let
|
|
7317
|
-
if (
|
|
7318
|
-
moduleIndex:
|
|
7319
|
-
lessonIndex:
|
|
7320
|
-
score:
|
|
7321
|
-
totalQuestions:
|
|
7313
|
+
const I = M(() => (H.current || { modules: [] }).modules[r.current.currentModuleIndex]?.lessons[r.current.currentLessonIndex], []), B = M(() => I()?.questions[r.current.currentQuestionIndex], [I]), D = M((b, R) => R.type === "multiple_choice" || R.type === "true_false" ? b === R.answer : R.type === "code_test" && typeof b == "object" && b !== null ? b.passed === !0 : !1, []), Y = M(() => {
|
|
7314
|
+
r.current.lessonCompleted = !0, r.current.isQuestionMode = !1;
|
|
7315
|
+
const b = r.current.totalQuestions > 0 ? Math.round(r.current.score / r.current.totalQuestions * 100) : 100;
|
|
7316
|
+
let R = "Congratulations! You've completed this lesson";
|
|
7317
|
+
if (r.current.totalQuestions > 0 ? R += ` with a score of ${r.current.score} out of ${r.current.totalQuestions} (${b}%). ` : R += "! ", b >= 80 ? R += "Excellent work! You have a great understanding of this topic." : b >= 60 ? R += "Good job! You understand most of the concepts." : R += "Keep practicing! You're making progress.", d.current.onLessonComplete({
|
|
7318
|
+
moduleIndex: r.current.currentModuleIndex,
|
|
7319
|
+
lessonIndex: r.current.currentLessonIndex,
|
|
7320
|
+
score: r.current.score,
|
|
7321
|
+
totalQuestions: r.current.totalQuestions,
|
|
7322
7322
|
percentage: b
|
|
7323
7323
|
}), d.current.onCustomAction({
|
|
7324
7324
|
type: "lessonComplete",
|
|
7325
|
-
moduleIndex:
|
|
7326
|
-
lessonIndex:
|
|
7327
|
-
score:
|
|
7328
|
-
totalQuestions:
|
|
7325
|
+
moduleIndex: r.current.currentModuleIndex,
|
|
7326
|
+
lessonIndex: r.current.currentLessonIndex,
|
|
7327
|
+
score: r.current.score,
|
|
7328
|
+
totalQuestions: r.current.totalQuestions,
|
|
7329
7329
|
percentage: b
|
|
7330
7330
|
}), h.current) {
|
|
7331
7331
|
if (h.current.setMood("happy"), e.lessonComplete)
|
|
@@ -7334,28 +7334,28 @@ const nt = fe(({
|
|
|
7334
7334
|
} catch {
|
|
7335
7335
|
h.current.playCelebration();
|
|
7336
7336
|
}
|
|
7337
|
-
const
|
|
7338
|
-
h.current.speakText(
|
|
7339
|
-
lipsyncLang:
|
|
7337
|
+
const v = H.current || { modules: [] }, k = v.modules[r.current.currentModuleIndex], z = r.current.currentLessonIndex < (k?.lessons?.length || 0) - 1, C = r.current.currentModuleIndex < (v.modules?.length || 0) - 1, U = z || C, J = T.current || { lipsyncLang: "en" };
|
|
7338
|
+
h.current.speakText(R, {
|
|
7339
|
+
lipsyncLang: J.lipsyncLang,
|
|
7340
7340
|
onSpeechEnd: () => {
|
|
7341
7341
|
d.current.onCustomAction({
|
|
7342
7342
|
type: "lessonCompleteFeedbackDone",
|
|
7343
|
-
moduleIndex:
|
|
7344
|
-
lessonIndex:
|
|
7345
|
-
score:
|
|
7346
|
-
totalQuestions:
|
|
7343
|
+
moduleIndex: r.current.currentModuleIndex,
|
|
7344
|
+
lessonIndex: r.current.currentLessonIndex,
|
|
7345
|
+
score: r.current.score,
|
|
7346
|
+
totalQuestions: r.current.totalQuestions,
|
|
7347
7347
|
percentage: b,
|
|
7348
|
-
hasNextLesson:
|
|
7348
|
+
hasNextLesson: U
|
|
7349
7349
|
});
|
|
7350
7350
|
}
|
|
7351
7351
|
});
|
|
7352
7352
|
}
|
|
7353
7353
|
}, [e.lessonComplete]), oe = M(() => {
|
|
7354
|
-
|
|
7355
|
-
const b =
|
|
7354
|
+
r.current.curriculumCompleted = !0;
|
|
7355
|
+
const b = H.current || { modules: [] };
|
|
7356
7356
|
if (d.current.onCurriculumComplete({
|
|
7357
7357
|
modules: b.modules.length,
|
|
7358
|
-
totalLessons: b.modules.reduce((
|
|
7358
|
+
totalLessons: b.modules.reduce((R, v) => R + v.lessons.length, 0)
|
|
7359
7359
|
}), h.current) {
|
|
7360
7360
|
if (h.current.setMood("celebrating"), e.curriculumComplete)
|
|
7361
7361
|
try {
|
|
@@ -7363,40 +7363,41 @@ const nt = fe(({
|
|
|
7363
7363
|
} catch {
|
|
7364
7364
|
h.current.playCelebration();
|
|
7365
7365
|
}
|
|
7366
|
-
const
|
|
7367
|
-
h.current.speakText("Amazing! You've completed the entire curriculum! You're now ready to move on to more advanced topics. Well done!", { lipsyncLang:
|
|
7366
|
+
const R = T.current || { lipsyncLang: "en" };
|
|
7367
|
+
h.current.speakText("Amazing! You've completed the entire curriculum! You're now ready to move on to more advanced topics. Well done!", { lipsyncLang: R.lipsyncLang });
|
|
7368
7368
|
}
|
|
7369
7369
|
}, [e.curriculumComplete]), S = M(() => {
|
|
7370
7370
|
const b = I();
|
|
7371
|
-
|
|
7372
|
-
const
|
|
7373
|
-
|
|
7371
|
+
r.current.isQuestionMode = !0, r.current.currentQuestionIndex = 0, r.current.totalQuestions = b?.questions?.length || 0, r.current.score = 0;
|
|
7372
|
+
const R = B();
|
|
7373
|
+
R && d.current.onCustomAction({
|
|
7374
7374
|
type: "questionStart",
|
|
7375
|
-
moduleIndex:
|
|
7376
|
-
lessonIndex:
|
|
7377
|
-
questionIndex:
|
|
7378
|
-
totalQuestions:
|
|
7379
|
-
question:
|
|
7375
|
+
moduleIndex: r.current.currentModuleIndex,
|
|
7376
|
+
lessonIndex: r.current.currentLessonIndex,
|
|
7377
|
+
questionIndex: r.current.currentQuestionIndex,
|
|
7378
|
+
totalQuestions: r.current.totalQuestions,
|
|
7379
|
+
question: R,
|
|
7380
|
+
score: r.current.score
|
|
7380
7381
|
});
|
|
7381
|
-
const
|
|
7382
|
-
if (!h.current || !
|
|
7382
|
+
const v = () => {
|
|
7383
|
+
if (!h.current || !R) return;
|
|
7383
7384
|
if (h.current.setMood("happy"), e.questionStart)
|
|
7384
7385
|
try {
|
|
7385
7386
|
h.current.playAnimation(e.questionStart, !0);
|
|
7386
|
-
} catch (
|
|
7387
|
-
console.warn("Failed to play questionStart animation:",
|
|
7387
|
+
} catch (z) {
|
|
7388
|
+
console.warn("Failed to play questionStart animation:", z);
|
|
7388
7389
|
}
|
|
7389
|
-
const k =
|
|
7390
|
-
|
|
7390
|
+
const k = T.current || { lipsyncLang: "en" };
|
|
7391
|
+
R.type === "code_test" ? h.current.speakText(`Let's test your coding skills! Here's your first challenge: ${R.question}`, { lipsyncLang: k.lipsyncLang }) : R.type === "multiple_choice" ? h.current.speakText(`Now let me ask you some questions. Here's the first one: ${R.question}`, { lipsyncLang: k.lipsyncLang }) : R.type === "true_false" ? h.current.speakText(`Let's start with some true or false questions. First question: ${R.question}`, { lipsyncLang: k.lipsyncLang }) : h.current.speakText(`Now let me ask you some questions. Here's the first one: ${R.question}`, { lipsyncLang: k.lipsyncLang });
|
|
7391
7392
|
};
|
|
7392
|
-
if (h.current && h.current.isReady &&
|
|
7393
|
-
|
|
7393
|
+
if (h.current && h.current.isReady && R)
|
|
7394
|
+
v();
|
|
7394
7395
|
else if (h.current && h.current.isReady) {
|
|
7395
|
-
const k =
|
|
7396
|
+
const k = T.current || { lipsyncLang: "en" };
|
|
7396
7397
|
h.current.speakText("Now let me ask you some questions to test your understanding.", { lipsyncLang: k.lipsyncLang });
|
|
7397
7398
|
} else {
|
|
7398
7399
|
const k = setInterval(() => {
|
|
7399
|
-
h.current && h.current.isReady && (clearInterval(k),
|
|
7400
|
+
h.current && h.current.isReady && (clearInterval(k), R && v());
|
|
7400
7401
|
}, 100);
|
|
7401
7402
|
setTimeout(() => {
|
|
7402
7403
|
clearInterval(k);
|
|
@@ -7404,41 +7405,42 @@ const nt = fe(({
|
|
|
7404
7405
|
}
|
|
7405
7406
|
}, [e.questionStart, I, B]), P = M(() => {
|
|
7406
7407
|
const b = I();
|
|
7407
|
-
if (
|
|
7408
|
-
|
|
7409
|
-
const
|
|
7410
|
-
|
|
7408
|
+
if (r.current.currentQuestionIndex < (b?.questions?.length || 0) - 1) {
|
|
7409
|
+
r.current.currentQuestionIndex += 1;
|
|
7410
|
+
const R = B();
|
|
7411
|
+
R && d.current.onCustomAction({
|
|
7411
7412
|
type: "nextQuestion",
|
|
7412
|
-
moduleIndex:
|
|
7413
|
-
lessonIndex:
|
|
7414
|
-
questionIndex:
|
|
7415
|
-
totalQuestions:
|
|
7416
|
-
question:
|
|
7413
|
+
moduleIndex: r.current.currentModuleIndex,
|
|
7414
|
+
lessonIndex: r.current.currentLessonIndex,
|
|
7415
|
+
questionIndex: r.current.currentQuestionIndex,
|
|
7416
|
+
totalQuestions: r.current.totalQuestions,
|
|
7417
|
+
question: R,
|
|
7418
|
+
score: r.current.score
|
|
7417
7419
|
});
|
|
7418
|
-
const
|
|
7419
|
-
if (!h.current || !
|
|
7420
|
+
const v = () => {
|
|
7421
|
+
if (!h.current || !R) return;
|
|
7420
7422
|
if (h.current.setMood("happy"), h.current.setBodyMovement("idle"), e.nextQuestion)
|
|
7421
7423
|
try {
|
|
7422
7424
|
h.current.playAnimation(e.nextQuestion, !0);
|
|
7423
|
-
} catch (
|
|
7424
|
-
console.warn("Failed to play nextQuestion animation:",
|
|
7425
|
+
} catch (z) {
|
|
7426
|
+
console.warn("Failed to play nextQuestion animation:", z);
|
|
7425
7427
|
}
|
|
7426
|
-
const k =
|
|
7427
|
-
|
|
7428
|
+
const k = T.current || { lipsyncLang: "en" };
|
|
7429
|
+
R.type === "code_test" ? h.current.speakText(`Great! Now let's move on to your next coding challenge: ${R.question}`, {
|
|
7428
7430
|
lipsyncLang: k.lipsyncLang
|
|
7429
|
-
}) :
|
|
7431
|
+
}) : R.type === "multiple_choice" ? h.current.speakText(`Alright! Here's your next question: ${R.question}`, {
|
|
7430
7432
|
lipsyncLang: k.lipsyncLang
|
|
7431
|
-
}) :
|
|
7433
|
+
}) : R.type === "true_false" ? h.current.speakText(`Now let's try this one: ${R.question}`, {
|
|
7432
7434
|
lipsyncLang: k.lipsyncLang
|
|
7433
|
-
}) : h.current.speakText(`Here's the next question: ${
|
|
7435
|
+
}) : h.current.speakText(`Here's the next question: ${R.question}`, {
|
|
7434
7436
|
lipsyncLang: k.lipsyncLang
|
|
7435
7437
|
});
|
|
7436
7438
|
};
|
|
7437
|
-
if (h.current && h.current.isReady &&
|
|
7438
|
-
|
|
7439
|
-
else if (
|
|
7439
|
+
if (h.current && h.current.isReady && R)
|
|
7440
|
+
v();
|
|
7441
|
+
else if (R) {
|
|
7440
7442
|
const k = setInterval(() => {
|
|
7441
|
-
h.current && h.current.isReady && (clearInterval(k),
|
|
7443
|
+
h.current && h.current.isReady && (clearInterval(k), v());
|
|
7442
7444
|
}, 100);
|
|
7443
7445
|
setTimeout(() => {
|
|
7444
7446
|
clearInterval(k);
|
|
@@ -7447,65 +7449,76 @@ const nt = fe(({
|
|
|
7447
7449
|
} else
|
|
7448
7450
|
d.current.onCustomAction({
|
|
7449
7451
|
type: "allQuestionsComplete",
|
|
7450
|
-
moduleIndex:
|
|
7451
|
-
lessonIndex:
|
|
7452
|
-
totalQuestions:
|
|
7453
|
-
score:
|
|
7452
|
+
moduleIndex: r.current.currentModuleIndex,
|
|
7453
|
+
lessonIndex: r.current.currentLessonIndex,
|
|
7454
|
+
totalQuestions: r.current.totalQuestions,
|
|
7455
|
+
score: r.current.score
|
|
7454
7456
|
});
|
|
7455
7457
|
}, [e.nextQuestion, I, B]), O = M(() => {
|
|
7456
|
-
const b =
|
|
7457
|
-
|
|
7458
|
-
|
|
7459
|
-
|
|
7460
|
-
|
|
7461
|
-
|
|
7462
|
-
|
|
7463
|
-
|
|
7464
|
-
|
|
7465
|
-
|
|
7466
|
-
|
|
7467
|
-
|
|
7468
|
-
|
|
7469
|
-
|
|
7470
|
-
|
|
7471
|
-
|
|
7472
|
-
|
|
7473
|
-
|
|
7474
|
-
|
|
7458
|
+
const b = H.current || { modules: [] }, R = b.modules[r.current.currentModuleIndex];
|
|
7459
|
+
if (r.current.currentLessonIndex < (R?.lessons?.length || 0) - 1) {
|
|
7460
|
+
r.current.currentLessonIndex += 1, r.current.currentQuestionIndex = 0, r.current.lessonCompleted = !1, r.current.isQuestionMode = !1, r.current.isTeaching = !1, r.current.score = 0, r.current.totalQuestions = 0;
|
|
7461
|
+
const k = b.modules[r.current.currentModuleIndex], z = r.current.currentLessonIndex < (k?.lessons?.length || 0) - 1, C = r.current.currentModuleIndex < (b.modules?.length || 0) - 1, U = z || C;
|
|
7462
|
+
d.current.onCustomAction({
|
|
7463
|
+
type: "lessonStart",
|
|
7464
|
+
moduleIndex: r.current.currentModuleIndex,
|
|
7465
|
+
lessonIndex: r.current.currentLessonIndex,
|
|
7466
|
+
hasNextLesson: U
|
|
7467
|
+
}), d.current.onLessonStart({
|
|
7468
|
+
moduleIndex: r.current.currentModuleIndex,
|
|
7469
|
+
lessonIndex: r.current.currentLessonIndex,
|
|
7470
|
+
lesson: I()
|
|
7471
|
+
}), h.current && (h.current.setMood("happy"), h.current.setBodyMovement("idle"));
|
|
7472
|
+
} else if (r.current.currentModuleIndex < (b.modules?.length || 0) - 1) {
|
|
7473
|
+
r.current.currentModuleIndex += 1, r.current.currentLessonIndex = 0, r.current.currentQuestionIndex = 0, r.current.lessonCompleted = !1, r.current.isQuestionMode = !1, r.current.isTeaching = !1, r.current.score = 0, r.current.totalQuestions = 0;
|
|
7474
|
+
const z = b.modules[r.current.currentModuleIndex], C = r.current.currentLessonIndex < (z?.lessons?.length || 0) - 1, U = r.current.currentModuleIndex < (b.modules?.length || 0) - 1, J = C || U;
|
|
7475
|
+
d.current.onCustomAction({
|
|
7476
|
+
type: "lessonStart",
|
|
7477
|
+
moduleIndex: r.current.currentModuleIndex,
|
|
7478
|
+
lessonIndex: r.current.currentLessonIndex,
|
|
7479
|
+
hasNextLesson: J
|
|
7480
|
+
}), d.current.onLessonStart({
|
|
7481
|
+
moduleIndex: r.current.currentModuleIndex,
|
|
7482
|
+
lessonIndex: r.current.currentLessonIndex,
|
|
7483
|
+
lesson: I()
|
|
7484
|
+
}), h.current && (h.current.setMood("happy"), h.current.setBodyMovement("idle"));
|
|
7485
|
+
} else
|
|
7486
|
+
L.current && L.current();
|
|
7487
|
+
}, []), V = M(() => {
|
|
7475
7488
|
const b = I();
|
|
7476
|
-
let
|
|
7489
|
+
let R = null;
|
|
7477
7490
|
if (b?.avatar_script && b?.body) {
|
|
7478
|
-
const
|
|
7479
|
-
|
|
7491
|
+
const v = b.avatar_script.trim(), k = b.body.trim(), z = v.match(/[.!?]$/) ? " " : ". ";
|
|
7492
|
+
R = `${v}${z}${k}`;
|
|
7480
7493
|
} else
|
|
7481
|
-
|
|
7482
|
-
if (h.current && h.current.isReady &&
|
|
7483
|
-
|
|
7484
|
-
let
|
|
7494
|
+
R = b?.avatar_script || b?.body || null;
|
|
7495
|
+
if (h.current && h.current.isReady && R) {
|
|
7496
|
+
r.current.isTeaching = !0, r.current.isQuestionMode = !1, r.current.score = 0, r.current.totalQuestions = 0, h.current.setMood("happy");
|
|
7497
|
+
let v = !1;
|
|
7485
7498
|
if (e.teaching)
|
|
7486
7499
|
try {
|
|
7487
|
-
h.current.playAnimation(e.teaching, !0),
|
|
7488
|
-
} catch (
|
|
7489
|
-
console.warn("Failed to play teaching animation:",
|
|
7500
|
+
h.current.playAnimation(e.teaching, !0), v = !0;
|
|
7501
|
+
} catch (z) {
|
|
7502
|
+
console.warn("Failed to play teaching animation:", z);
|
|
7490
7503
|
}
|
|
7491
|
-
|
|
7492
|
-
const k =
|
|
7504
|
+
v || h.current.setBodyMovement("gesturing");
|
|
7505
|
+
const k = T.current || { lipsyncLang: "en" };
|
|
7493
7506
|
d.current.onLessonStart({
|
|
7494
|
-
moduleIndex:
|
|
7495
|
-
lessonIndex:
|
|
7507
|
+
moduleIndex: r.current.currentModuleIndex,
|
|
7508
|
+
lessonIndex: r.current.currentLessonIndex,
|
|
7496
7509
|
lesson: b
|
|
7497
7510
|
}), d.current.onCustomAction({
|
|
7498
7511
|
type: "teachingStart",
|
|
7499
|
-
moduleIndex:
|
|
7500
|
-
lessonIndex:
|
|
7512
|
+
moduleIndex: r.current.currentModuleIndex,
|
|
7513
|
+
lessonIndex: r.current.currentLessonIndex,
|
|
7501
7514
|
lesson: b
|
|
7502
|
-
}), h.current.speakText(
|
|
7515
|
+
}), h.current.speakText(R, {
|
|
7503
7516
|
lipsyncLang: k.lipsyncLang,
|
|
7504
7517
|
onSpeechEnd: () => {
|
|
7505
|
-
|
|
7518
|
+
r.current.isTeaching = !1, d.current.onCustomAction({
|
|
7506
7519
|
type: "teachingComplete",
|
|
7507
|
-
moduleIndex:
|
|
7508
|
-
lessonIndex:
|
|
7520
|
+
moduleIndex: r.current.currentModuleIndex,
|
|
7521
|
+
lessonIndex: r.current.currentLessonIndex,
|
|
7509
7522
|
lesson: b,
|
|
7510
7523
|
hasQuestions: b.questions && b.questions.length > 0
|
|
7511
7524
|
});
|
|
@@ -7513,16 +7526,16 @@ const nt = fe(({
|
|
|
7513
7526
|
});
|
|
7514
7527
|
}
|
|
7515
7528
|
}, [e.teaching, I]), _ = M((b) => {
|
|
7516
|
-
const
|
|
7517
|
-
if (
|
|
7518
|
-
moduleIndex:
|
|
7519
|
-
lessonIndex:
|
|
7520
|
-
questionIndex:
|
|
7529
|
+
const R = B(), v = D(b, R);
|
|
7530
|
+
if (v && (r.current.score += 1), d.current.onQuestionAnswer({
|
|
7531
|
+
moduleIndex: r.current.currentModuleIndex,
|
|
7532
|
+
lessonIndex: r.current.currentLessonIndex,
|
|
7533
|
+
questionIndex: r.current.currentQuestionIndex,
|
|
7521
7534
|
answer: b,
|
|
7522
|
-
isCorrect:
|
|
7523
|
-
question:
|
|
7535
|
+
isCorrect: v,
|
|
7536
|
+
question: R
|
|
7524
7537
|
}), h.current)
|
|
7525
|
-
if (
|
|
7538
|
+
if (v) {
|
|
7526
7539
|
if (h.current.setMood("happy"), e.correct)
|
|
7527
7540
|
try {
|
|
7528
7541
|
h.current.playReaction("happy");
|
|
@@ -7530,17 +7543,20 @@ const nt = fe(({
|
|
|
7530
7543
|
h.current.setBodyMovement("happy");
|
|
7531
7544
|
}
|
|
7532
7545
|
h.current.setBodyMovement("gesturing");
|
|
7533
|
-
const k =
|
|
7546
|
+
const k = R.type === "code_test" ? `Great job! Your code passed all the tests! ${R.explanation || ""}` : `Excellent! That's correct! ${R.explanation || ""}`, z = T.current || { lipsyncLang: "en" };
|
|
7534
7547
|
h.current.speakText(k, {
|
|
7535
|
-
lipsyncLang:
|
|
7548
|
+
lipsyncLang: z.lipsyncLang,
|
|
7536
7549
|
onSpeechEnd: () => {
|
|
7550
|
+
const U = I()?.questions?.length || 0;
|
|
7537
7551
|
d.current.onCustomAction({
|
|
7538
7552
|
type: "answerFeedbackComplete",
|
|
7539
|
-
moduleIndex:
|
|
7540
|
-
lessonIndex:
|
|
7541
|
-
questionIndex:
|
|
7553
|
+
moduleIndex: r.current.currentModuleIndex,
|
|
7554
|
+
lessonIndex: r.current.currentLessonIndex,
|
|
7555
|
+
questionIndex: r.current.currentQuestionIndex,
|
|
7542
7556
|
isCorrect: !0,
|
|
7543
|
-
hasNextQuestion:
|
|
7557
|
+
hasNextQuestion: r.current.currentQuestionIndex < U - 1,
|
|
7558
|
+
score: r.current.score,
|
|
7559
|
+
totalQuestions: r.current.totalQuestions
|
|
7544
7560
|
});
|
|
7545
7561
|
}
|
|
7546
7562
|
});
|
|
@@ -7552,42 +7568,49 @@ const nt = fe(({
|
|
|
7552
7568
|
h.current.setBodyMovement("idle");
|
|
7553
7569
|
}
|
|
7554
7570
|
h.current.setBodyMovement("gesturing");
|
|
7555
|
-
const k =
|
|
7571
|
+
const k = R.type === "code_test" ? `Your code didn't pass all the tests. ${R.explanation || "Try again!"}` : `Not quite right, but don't worry! ${R.explanation || ""} Let's move on to the next question.`, z = T.current || { lipsyncLang: "en" };
|
|
7556
7572
|
h.current.speakText(k, {
|
|
7557
|
-
lipsyncLang:
|
|
7573
|
+
lipsyncLang: z.lipsyncLang,
|
|
7558
7574
|
onSpeechEnd: () => {
|
|
7575
|
+
const U = I()?.questions?.length || 0;
|
|
7559
7576
|
d.current.onCustomAction({
|
|
7560
7577
|
type: "answerFeedbackComplete",
|
|
7561
|
-
moduleIndex:
|
|
7562
|
-
lessonIndex:
|
|
7563
|
-
questionIndex:
|
|
7578
|
+
moduleIndex: r.current.currentModuleIndex,
|
|
7579
|
+
lessonIndex: r.current.currentLessonIndex,
|
|
7580
|
+
questionIndex: r.current.currentQuestionIndex,
|
|
7564
7581
|
isCorrect: !1,
|
|
7565
|
-
hasNextQuestion:
|
|
7582
|
+
hasNextQuestion: r.current.currentQuestionIndex < U - 1,
|
|
7583
|
+
score: r.current.score,
|
|
7584
|
+
totalQuestions: r.current.totalQuestions
|
|
7566
7585
|
});
|
|
7567
7586
|
}
|
|
7568
7587
|
});
|
|
7569
7588
|
}
|
|
7570
|
-
else
|
|
7589
|
+
else {
|
|
7590
|
+
const z = I()?.questions?.length || 0;
|
|
7571
7591
|
d.current.onCustomAction({
|
|
7572
7592
|
type: "answerFeedbackComplete",
|
|
7573
|
-
moduleIndex:
|
|
7574
|
-
lessonIndex:
|
|
7575
|
-
questionIndex:
|
|
7576
|
-
isCorrect:
|
|
7577
|
-
hasNextQuestion:
|
|
7593
|
+
moduleIndex: r.current.currentModuleIndex,
|
|
7594
|
+
lessonIndex: r.current.currentLessonIndex,
|
|
7595
|
+
questionIndex: r.current.currentQuestionIndex,
|
|
7596
|
+
isCorrect: v,
|
|
7597
|
+
hasNextQuestion: r.current.currentQuestionIndex < z - 1,
|
|
7598
|
+
score: r.current.score,
|
|
7599
|
+
totalQuestions: r.current.totalQuestions,
|
|
7578
7600
|
avatarNotReady: !0
|
|
7579
7601
|
});
|
|
7602
|
+
}
|
|
7580
7603
|
}, [e.correct, e.incorrect, B, I, D]), K = M((b) => {
|
|
7581
|
-
const
|
|
7604
|
+
const R = B();
|
|
7582
7605
|
if (!b || typeof b != "object") {
|
|
7583
7606
|
console.error("Invalid code test result format. Expected object with {passed: boolean, ...}");
|
|
7584
7607
|
return;
|
|
7585
7608
|
}
|
|
7586
|
-
if (
|
|
7609
|
+
if (R?.type !== "code_test") {
|
|
7587
7610
|
console.warn("Current question is not a code test. Use handleAnswerSelect for other question types.");
|
|
7588
7611
|
return;
|
|
7589
7612
|
}
|
|
7590
|
-
const
|
|
7613
|
+
const v = {
|
|
7591
7614
|
passed: b.passed === !0,
|
|
7592
7615
|
results: b.results || [],
|
|
7593
7616
|
output: b.output || "",
|
|
@@ -7599,83 +7622,84 @@ const nt = fe(({
|
|
|
7599
7622
|
};
|
|
7600
7623
|
d.current.onCustomAction({
|
|
7601
7624
|
type: "codeTestSubmitted",
|
|
7602
|
-
moduleIndex:
|
|
7603
|
-
lessonIndex:
|
|
7604
|
-
questionIndex:
|
|
7605
|
-
testResult:
|
|
7606
|
-
question:
|
|
7607
|
-
}), p.current && p.current(
|
|
7625
|
+
moduleIndex: r.current.currentModuleIndex,
|
|
7626
|
+
lessonIndex: r.current.currentLessonIndex,
|
|
7627
|
+
questionIndex: r.current.currentQuestionIndex,
|
|
7628
|
+
testResult: v,
|
|
7629
|
+
question: R
|
|
7630
|
+
}), p.current && p.current(v);
|
|
7608
7631
|
}, [B, D]), se = M(() => {
|
|
7609
|
-
if (
|
|
7610
|
-
|
|
7632
|
+
if (r.current.currentQuestionIndex > 0) {
|
|
7633
|
+
r.current.currentQuestionIndex -= 1;
|
|
7611
7634
|
const b = B();
|
|
7612
7635
|
b && d.current.onCustomAction({
|
|
7613
7636
|
type: "questionStart",
|
|
7614
|
-
moduleIndex:
|
|
7615
|
-
lessonIndex:
|
|
7616
|
-
questionIndex:
|
|
7617
|
-
totalQuestions:
|
|
7618
|
-
question: b
|
|
7637
|
+
moduleIndex: r.current.currentModuleIndex,
|
|
7638
|
+
lessonIndex: r.current.currentLessonIndex,
|
|
7639
|
+
questionIndex: r.current.currentQuestionIndex,
|
|
7640
|
+
totalQuestions: r.current.totalQuestions,
|
|
7641
|
+
question: b,
|
|
7642
|
+
score: r.current.score
|
|
7619
7643
|
});
|
|
7620
|
-
const
|
|
7644
|
+
const R = () => {
|
|
7621
7645
|
if (!h.current || !b) return;
|
|
7622
7646
|
h.current.setMood("happy"), h.current.setBodyMovement("idle");
|
|
7623
|
-
const
|
|
7647
|
+
const v = T.current || { lipsyncLang: "en" };
|
|
7624
7648
|
b.type === "code_test" ? h.current.speakText(`Let's go back to this coding challenge: ${b.question}`, {
|
|
7625
|
-
lipsyncLang:
|
|
7649
|
+
lipsyncLang: v.lipsyncLang
|
|
7626
7650
|
}) : h.current.speakText(`Going back to: ${b.question}`, {
|
|
7627
|
-
lipsyncLang:
|
|
7651
|
+
lipsyncLang: v.lipsyncLang
|
|
7628
7652
|
});
|
|
7629
7653
|
};
|
|
7630
7654
|
if (h.current && h.current.isReady && b)
|
|
7631
|
-
|
|
7655
|
+
R();
|
|
7632
7656
|
else if (b) {
|
|
7633
|
-
const
|
|
7634
|
-
h.current && h.current.isReady && (clearInterval(
|
|
7657
|
+
const v = setInterval(() => {
|
|
7658
|
+
h.current && h.current.isReady && (clearInterval(v), R());
|
|
7635
7659
|
}, 100);
|
|
7636
7660
|
setTimeout(() => {
|
|
7637
|
-
clearInterval(
|
|
7661
|
+
clearInterval(v);
|
|
7638
7662
|
}, 5e3);
|
|
7639
7663
|
}
|
|
7640
7664
|
}
|
|
7641
7665
|
}, [B]), pe = M(() => {
|
|
7642
|
-
const b =
|
|
7643
|
-
if (b.modules[
|
|
7644
|
-
|
|
7666
|
+
const b = H.current || { modules: [] };
|
|
7667
|
+
if (b.modules[r.current.currentModuleIndex], r.current.currentLessonIndex > 0)
|
|
7668
|
+
r.current.currentLessonIndex -= 1, r.current.currentQuestionIndex = 0, r.current.lessonCompleted = !1, r.current.isQuestionMode = !1, r.current.isTeaching = !1, r.current.score = 0, r.current.totalQuestions = 0, d.current.onCustomAction({
|
|
7645
7669
|
type: "lessonStart",
|
|
7646
|
-
moduleIndex:
|
|
7647
|
-
lessonIndex:
|
|
7670
|
+
moduleIndex: r.current.currentModuleIndex,
|
|
7671
|
+
lessonIndex: r.current.currentLessonIndex
|
|
7648
7672
|
}), d.current.onLessonStart({
|
|
7649
|
-
moduleIndex:
|
|
7650
|
-
lessonIndex:
|
|
7673
|
+
moduleIndex: r.current.currentModuleIndex,
|
|
7674
|
+
lessonIndex: r.current.currentLessonIndex,
|
|
7651
7675
|
lesson: I()
|
|
7652
7676
|
}), h.current && (h.current.setMood("happy"), h.current.setBodyMovement("idle"));
|
|
7653
|
-
else if (
|
|
7654
|
-
const k = b.modules[
|
|
7655
|
-
|
|
7677
|
+
else if (r.current.currentModuleIndex > 0) {
|
|
7678
|
+
const k = b.modules[r.current.currentModuleIndex - 1];
|
|
7679
|
+
r.current.currentModuleIndex -= 1, r.current.currentLessonIndex = (k?.lessons?.length || 1) - 1, r.current.currentQuestionIndex = 0, r.current.lessonCompleted = !1, r.current.isQuestionMode = !1, r.current.isTeaching = !1, r.current.score = 0, r.current.totalQuestions = 0, d.current.onCustomAction({
|
|
7656
7680
|
type: "lessonStart",
|
|
7657
|
-
moduleIndex:
|
|
7658
|
-
lessonIndex:
|
|
7681
|
+
moduleIndex: r.current.currentModuleIndex,
|
|
7682
|
+
lessonIndex: r.current.currentLessonIndex
|
|
7659
7683
|
}), d.current.onLessonStart({
|
|
7660
|
-
moduleIndex:
|
|
7661
|
-
lessonIndex:
|
|
7684
|
+
moduleIndex: r.current.currentModuleIndex,
|
|
7685
|
+
lessonIndex: r.current.currentLessonIndex,
|
|
7662
7686
|
lesson: I()
|
|
7663
7687
|
}), h.current && (h.current.setMood("happy"), h.current.setBodyMovement("idle"));
|
|
7664
7688
|
}
|
|
7665
7689
|
}, [I]), ue = M(() => {
|
|
7666
|
-
|
|
7690
|
+
r.current.currentModuleIndex = 0, r.current.currentLessonIndex = 0, r.current.currentQuestionIndex = 0, r.current.isTeaching = !1, r.current.isQuestionMode = !1, r.current.lessonCompleted = !1, r.current.curriculumCompleted = !1, r.current.score = 0, r.current.totalQuestions = 0;
|
|
7667
7691
|
}, []), ge = M((b) => {
|
|
7668
7692
|
console.log("Avatar is ready!", b);
|
|
7669
|
-
const
|
|
7670
|
-
u &&
|
|
7693
|
+
const R = I(), v = R?.avatar_script || R?.body;
|
|
7694
|
+
u && v && setTimeout(() => {
|
|
7671
7695
|
c.current && c.current();
|
|
7672
7696
|
}, 10);
|
|
7673
7697
|
}, [u, I]);
|
|
7674
7698
|
Ee(() => {
|
|
7675
|
-
c.current =
|
|
7699
|
+
c.current = V, g.current = O, y.current = Y, x.current = P, L.current = oe, F.current = S, p.current = _;
|
|
7676
7700
|
}), xe(a, () => ({
|
|
7677
7701
|
// Curriculum control methods
|
|
7678
|
-
startTeaching:
|
|
7702
|
+
startTeaching: V,
|
|
7679
7703
|
startQuestions: S,
|
|
7680
7704
|
handleAnswerSelect: _,
|
|
7681
7705
|
handleCodeTestResult: K,
|
|
@@ -7683,38 +7707,38 @@ const nt = fe(({
|
|
|
7683
7707
|
previousQuestion: se,
|
|
7684
7708
|
nextLesson: O,
|
|
7685
7709
|
previousLesson: pe,
|
|
7686
|
-
completeLesson:
|
|
7710
|
+
completeLesson: Y,
|
|
7687
7711
|
completeCurriculum: oe,
|
|
7688
7712
|
resetCurriculum: ue,
|
|
7689
|
-
getState: () => ({ ...
|
|
7713
|
+
getState: () => ({ ...r.current }),
|
|
7690
7714
|
getCurrentQuestion: () => B(),
|
|
7691
7715
|
getCurrentLesson: () => I(),
|
|
7692
7716
|
// Direct access to avatar ref (always returns current value)
|
|
7693
7717
|
getAvatarRef: () => h.current,
|
|
7694
7718
|
// Convenience methods that delegate to avatar (always check current ref)
|
|
7695
|
-
speakText: async (b,
|
|
7719
|
+
speakText: async (b, R = {}) => {
|
|
7696
7720
|
await h.current?.resumeAudioContext?.();
|
|
7697
|
-
const
|
|
7698
|
-
h.current?.speakText(b, { ...
|
|
7721
|
+
const v = T.current || { lipsyncLang: "en" };
|
|
7722
|
+
h.current?.speakText(b, { ...R, lipsyncLang: R.lipsyncLang || v.lipsyncLang });
|
|
7699
7723
|
},
|
|
7700
7724
|
resumeAudioContext: async () => {
|
|
7701
7725
|
if (h.current?.resumeAudioContext)
|
|
7702
7726
|
return await h.current.resumeAudioContext();
|
|
7703
7727
|
const b = h.current?.talkingHead;
|
|
7704
7728
|
if (b?.audioCtx) {
|
|
7705
|
-
const
|
|
7706
|
-
if (
|
|
7729
|
+
const R = b.audioCtx;
|
|
7730
|
+
if (R.state === "suspended" || R.state === "interrupted")
|
|
7707
7731
|
try {
|
|
7708
|
-
await
|
|
7709
|
-
} catch (
|
|
7710
|
-
console.warn("Failed to resume audio context:",
|
|
7732
|
+
await R.resume(), console.log("Audio context resumed via talkingHead");
|
|
7733
|
+
} catch (v) {
|
|
7734
|
+
console.warn("Failed to resume audio context:", v);
|
|
7711
7735
|
}
|
|
7712
7736
|
} else
|
|
7713
7737
|
console.warn("Audio context not available yet");
|
|
7714
7738
|
},
|
|
7715
7739
|
stopSpeaking: () => h.current?.stopSpeaking(),
|
|
7716
7740
|
setMood: (b) => h.current?.setMood(b),
|
|
7717
|
-
playAnimation: (b,
|
|
7741
|
+
playAnimation: (b, R) => h.current?.playAnimation(b, R),
|
|
7718
7742
|
setBodyMovement: (b) => h.current?.setBodyMovement(b),
|
|
7719
7743
|
setMovementIntensity: (b) => h.current?.setMovementIntensity(b),
|
|
7720
7744
|
playRandomDance: () => h.current?.playRandomDance(),
|
|
@@ -7725,19 +7749,19 @@ const nt = fe(({
|
|
|
7725
7749
|
lockAvatarPosition: () => h.current?.lockAvatarPosition(),
|
|
7726
7750
|
unlockAvatarPosition: () => h.current?.unlockAvatarPosition(),
|
|
7727
7751
|
// Custom action trigger
|
|
7728
|
-
triggerCustomAction: (b,
|
|
7752
|
+
triggerCustomAction: (b, R) => {
|
|
7729
7753
|
d.current.onCustomAction({
|
|
7730
7754
|
type: b,
|
|
7731
|
-
...
|
|
7732
|
-
state: { ...
|
|
7755
|
+
...R,
|
|
7756
|
+
state: { ...r.current }
|
|
7733
7757
|
});
|
|
7734
7758
|
},
|
|
7735
7759
|
// Responsive resize handler
|
|
7736
7760
|
handleResize: () => h.current?.handleResize(),
|
|
7737
7761
|
// Avatar readiness check (always returns current value)
|
|
7738
7762
|
isAvatarReady: () => h.current?.isReady || !1
|
|
7739
|
-
}), [
|
|
7740
|
-
const Q =
|
|
7763
|
+
}), [V, S, _, K, P, O, Y, oe, ue, B, I]);
|
|
7764
|
+
const Q = T.current || {
|
|
7741
7765
|
avatarUrl: "/avatars/brunette.glb",
|
|
7742
7766
|
avatarBody: "F",
|
|
7743
7767
|
mood: "happy",
|