@sage-rsc/talking-head-react 1.1.2 → 1.1.5
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 +591 -553
- package/package.json +1 -1
- package/src/lib/talkinghead.mjs +107 -8
package/dist/index.js
CHANGED
|
@@ -1,20 +1,20 @@
|
|
|
1
1
|
import { jsxs as Pe, jsx as me } from "react/jsx-runtime";
|
|
2
|
-
import { forwardRef as Me, useRef as
|
|
3
|
-
import * as
|
|
2
|
+
import { forwardRef as Me, useRef as N, useState as ce, useEffect as de, useCallback as P, useImperativeHandle as Ee, useLayoutEffect as Xe } from "react";
|
|
3
|
+
import * as b from "three";
|
|
4
4
|
import { OrbitControls as Ye } from "three/addons/controls/OrbitControls.js";
|
|
5
5
|
import { GLTFLoader as je } from "three/addons/loaders/GLTFLoader.js";
|
|
6
6
|
import { DRACOLoader as Qe } from "three/addons/loaders/DRACOLoader.js";
|
|
7
|
-
import { FBXLoader as
|
|
7
|
+
import { FBXLoader as Ne } from "three/addons/loaders/FBXLoader.js";
|
|
8
8
|
import { RoomEnvironment as qe } from "three/addons/environments/RoomEnvironment.js";
|
|
9
9
|
import _e from "three/addons/libs/stats.module.js";
|
|
10
10
|
let m, re, he;
|
|
11
|
-
const A = [0, 0, 0, 0],
|
|
12
|
-
new
|
|
13
|
-
new
|
|
14
|
-
new
|
|
15
|
-
const
|
|
16
|
-
new
|
|
17
|
-
const He = new
|
|
11
|
+
const A = [0, 0, 0, 0], z = new b.Vector3(), ze = new b.Vector3(), ie = new b.Vector3(), Ce = new b.Vector3();
|
|
12
|
+
new b.Plane();
|
|
13
|
+
new b.Ray();
|
|
14
|
+
new b.Euler();
|
|
15
|
+
const oe = new b.Quaternion(), Oe = new b.Quaternion(), fe = new b.Matrix4(), xe = new b.Matrix4();
|
|
16
|
+
new b.Vector3();
|
|
17
|
+
const He = new b.Vector3(0, 0, 1), Ke = new b.Vector3(1, 0, 0), Je = new b.Vector3(0, 1, 0), $e = new b.Vector3(0, 0, 1);
|
|
18
18
|
class et {
|
|
19
19
|
constructor(t = null) {
|
|
20
20
|
this.opt = Object.assign({
|
|
@@ -321,7 +321,7 @@ class et {
|
|
|
321
321
|
/// Bone's parent object
|
|
322
322
|
vBasis: r.position.clone(),
|
|
323
323
|
// Original local position
|
|
324
|
-
vWorld: r.parent.getWorldPosition(
|
|
324
|
+
vWorld: r.parent.getWorldPosition(z).clone(),
|
|
325
325
|
// World position, parent
|
|
326
326
|
qBasis: r.parent.quaternion.clone(),
|
|
327
327
|
// Original quaternion, parent
|
|
@@ -338,7 +338,7 @@ class et {
|
|
|
338
338
|
ea: [0, 0, 0, 0]
|
|
339
339
|
// External acceleration [m/s^2]
|
|
340
340
|
};
|
|
341
|
-
h.boneParent.matrixWorld.decompose(
|
|
341
|
+
h.boneParent.matrixWorld.decompose(z, oe, ie), z.copy(He).applyQuaternion(oe).setY(0).normalize(), oe.premultiply(Oe.setFromUnitVectors(He, z).invert()).normalize(), h.qWorldInverseYaw = oe.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
344
|
} catch (a) {
|
|
@@ -356,22 +356,22 @@ class et {
|
|
|
356
356
|
for (this.timerMs += t, t > 1e3 && (this.timerMs = 0), t /= 1e3, e = 0, i = this.objectsUpdate.length; e < i; 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, i = this.data.length; e < i; e++) {
|
|
359
|
-
if (o = this.data[e],
|
|
359
|
+
if (o = this.data[e], z.copy(o.vWorld), fe.copy(o.boneParent.matrixWorld), xe.copy(fe).invert(), o.vWorld.setFromMatrixPosition(fe), z.applyMatrix4(xe), z.length() > 0.5 && (console.info("Info: Unrealistic jump of " + z.length().toFixed(2) + " meters."), z.setLength(0.5)), z.applyQuaternion(o.bone.quaternion), A[0] = z.x, A[1] = z.y, A[2] = -z.z, A[3] = z.length() / 3, o.children)
|
|
360
360
|
for (n = 0, s = o.children.length; n < s; n++)
|
|
361
361
|
m = o.children[n], 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
|
-
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,
|
|
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, z.set(
|
|
363
363
|
o.vBasis.x + A[0],
|
|
364
364
|
o.vBasis.y + A[1],
|
|
365
365
|
o.vBasis.z + A[2]
|
|
366
|
-
),
|
|
366
|
+
), z.applyMatrix4(fe), z.x += m[0], z.y += m[1], z.z += m[2], z.applyMatrix4(xe), A[0] += z.x - o.vBasis.x, A[1] += z.y - o.vBasis.y, A[2] += z.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(
|
|
372
|
+
else if (o.boneParent.quaternion.copy(o.qBasis), o.pivot && this.opt.isPivots && (o.boneParent.updateWorldMatrix(!1, !1), o.boneParent.matrixWorld.decompose(z, oe, ie), z.copy(He).applyQuaternion(oe).setY(0).normalize(), oe.premultiply(Oe.setFromUnitVectors(He, z).invert()).normalize(), o.boneParent.quaternion.multiply(oe.invert()), o.boneParent.quaternion.multiply(o.qWorldInverseYaw)), o.isZ && (m = Math.atan(A[0] / o.l), oe.setFromAxisAngle($e, -m), o.boneParent.quaternion.multiply(oe)), 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), oe.setFromAxisAngle(Ke, -m), o.boneParent.quaternion.multiply(oe)), o.isT && (m = 1.5 * Math.tanh(A[3] * 1.5), oe.setFromAxisAngle(Je, -m), o.boneParent.quaternion.multiply(oe)), o.boneParent.updateWorldMatrix(!1, !0), o.excludes && this.opt.isExcludes)
|
|
373
373
|
for (n = 0, s = o.excludes.length; n < s; n++)
|
|
374
|
-
m = o.excludes[n],
|
|
374
|
+
m = o.excludes[n], ie.set(0, 0, 0), m.deltaLocal && (ie.x += m.deltaLocal[0], ie.y += m.deltaLocal[1], ie.z += m.deltaLocal[2]), ie.applyMatrix4(m.bone.matrixWorld), xe.copy(o.boneParent.matrixWorld).invert(), ie.applyMatrix4(xe), z.copy(o.bone.position), !(z.distanceToSquared(ie) >= m.radiusSq) && (he = z.length(), re = ie.length(), !(re > m.radius + he) && (re < Math.abs(m.radius - he) || (re = (re * re + he * he - m.radiusSq) / (2 * re), ie.normalize(), Ce.copy(ie).multiplyScalar(re), re = Math.sqrt(he * he - re * re), z.subVectors(z, Ce).projectOnPlane(ie).normalize().multiplyScalar(re), ze.subVectors(o.vBasis, Ce).projectOnPlane(ie).normalize(), he = ze.dot(z), he < 0 && (he = Math.sqrt(re * re - he * he), ze.multiplyScalar(he), z.add(ze)), z.add(Ce).normalize(), ie.copy(o.bone.position).normalize(), oe.setFromUnitVectors(ie, z), o.boneParent.quaternion.premultiply(oe), o.boneParent.updateWorldMatrix(!1, !0))));
|
|
375
375
|
}
|
|
376
376
|
this.helpers.isActive && this.updateHelpers();
|
|
377
377
|
}
|
|
@@ -393,7 +393,7 @@ class et {
|
|
|
393
393
|
i || (m.excludes.bones.push(n.bone), m.excludes.radii.push(n.radius), m.excludes.deltaLocals.push(n.deltaLocal ? [...n.deltaLocal] : null), m.excludes.objects.push(null));
|
|
394
394
|
}));
|
|
395
395
|
}), m = this.helpers.excludes, this.opt.isExcludes && m.bones.length && m.bones.forEach((e, n) => {
|
|
396
|
-
const i = new
|
|
396
|
+
const i = new b.SphereGeometry(m.radii[n], 6, 6), s = new b.MeshBasicMaterial({
|
|
397
397
|
depthTest: !1,
|
|
398
398
|
depthWrite: !1,
|
|
399
399
|
toneMapped: !1,
|
|
@@ -401,18 +401,18 @@ class et {
|
|
|
401
401
|
wireframe: !0,
|
|
402
402
|
color: this.opt.helperExcludesColor
|
|
403
403
|
});
|
|
404
|
-
m.objects[n] = new
|
|
404
|
+
m.objects[n] = new b.Mesh(i, s), m.objects[n].renderOrder = 997, e.add(m.objects[n]), m.deltaLocals[n] && m.objects[n].position.set(
|
|
405
405
|
m.deltaLocals[n][0],
|
|
406
406
|
m.deltaLocals[n][1],
|
|
407
407
|
m.deltaLocals[n][2]
|
|
408
408
|
);
|
|
409
409
|
}), m = this.helpers.points, m.bones.length) {
|
|
410
410
|
this.helpers.isActive = !0;
|
|
411
|
-
const e = new
|
|
412
|
-
e.setAttribute("position", new
|
|
413
|
-
const i = new
|
|
414
|
-
e.setAttribute("color", new
|
|
415
|
-
const l = new
|
|
411
|
+
const e = new b.BufferGeometry(), n = m.bones.map((u) => [0, 0, 0]).flat();
|
|
412
|
+
e.setAttribute("position", new b.Float32BufferAttribute(n, 3));
|
|
413
|
+
const i = new b.Color(this.opt.helperBoneColor1), s = new b.Color(this.opt.helperBoneColor2), o = m.pivots.map((u) => u && this.opt.isPivots ? [s.r, s.g, s.b] : [i.r, i.g, i.b]).flat();
|
|
414
|
+
e.setAttribute("color", new b.Float32BufferAttribute(o, 3));
|
|
415
|
+
const l = new b.PointsMaterial({
|
|
416
416
|
depthTest: !1,
|
|
417
417
|
depthWrite: !1,
|
|
418
418
|
toneMapped: !1,
|
|
@@ -420,21 +420,21 @@ class et {
|
|
|
420
420
|
size: 0.2,
|
|
421
421
|
vertexColors: !0
|
|
422
422
|
});
|
|
423
|
-
m.object = new
|
|
423
|
+
m.object = new b.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
|
-
const e = new
|
|
427
|
-
e.setAttribute("position", new
|
|
428
|
-
const i = new
|
|
429
|
-
e.setAttribute("color", new
|
|
430
|
-
const l = new
|
|
426
|
+
const e = new b.BufferGeometry(), n = m.bones.map((u) => [0, 0, 0, 0, 0, 0]).flat();
|
|
427
|
+
e.setAttribute("position", new b.Float32BufferAttribute(n, 3));
|
|
428
|
+
const i = new b.Color(this.opt.helperLinkColor1), s = new b.Color(this.opt.helperLinkColor2), o = m.bones.map((u) => [i.r, i.g, i.b, s.r, s.g, s.b]).flat();
|
|
429
|
+
e.setAttribute("color", new b.Float32BufferAttribute(o, 3));
|
|
430
|
+
const l = new b.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
|
|
437
|
+
m.object = new b.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
|
/**
|
|
@@ -445,14 +445,14 @@ class et {
|
|
|
445
445
|
xe.copy(this.armature.matrixWorld).invert();
|
|
446
446
|
const t = m.object.geometry.getAttribute("position");
|
|
447
447
|
for (let e = 0, n = m.bones.length; e < n; e++)
|
|
448
|
-
fe.multiplyMatrices(xe, m.bones[e].matrixWorld),
|
|
448
|
+
fe.multiplyMatrices(xe, m.bones[e].matrixWorld), z.setFromMatrixPosition(fe), t.setXYZ(e, z.x, z.y, z.z);
|
|
449
449
|
t.needsUpdate = !0, m.object.updateMatrixWorld();
|
|
450
450
|
}
|
|
451
451
|
if (m = this.helpers.lines, m.bones.length) {
|
|
452
452
|
xe.copy(this.armature.matrixWorld).invert();
|
|
453
453
|
const t = m.object.geometry.getAttribute("position");
|
|
454
454
|
for (let e = 0, n = 0, i = m.bones.length; e < i; e++, n += 2)
|
|
455
|
-
fe.multiplyMatrices(xe, m.bones[e].matrixWorld),
|
|
455
|
+
fe.multiplyMatrices(xe, m.bones[e].matrixWorld), z.setFromMatrixPosition(fe), t.setXYZ(n, z.x, z.y, z.z), fe.multiplyMatrices(xe, m.bones[e].parent.matrixWorld), z.setFromMatrixPosition(fe), t.setXYZ(n + 1, z.x, z.y, z.z);
|
|
456
456
|
t.needsUpdate = !0, m.object.updateMatrixWorld();
|
|
457
457
|
}
|
|
458
458
|
}
|
|
@@ -608,8 +608,8 @@ class tt {
|
|
|
608
608
|
for (let a = 0; a < i / 2; a++) {
|
|
609
609
|
const c = n[(u + a) * 2], d = n[(u + a) * 2 + 1], g = n[(u + a + i / 2) * 2] * r - n[(u + a + i / 2) * 2 + 1] * h, x = n[(u + a + i / 2) * 2] * h + n[(u + a + i / 2) * 2 + 1] * r;
|
|
610
610
|
n[(u + a) * 2] = c + g, n[(u + a) * 2 + 1] = d + x, n[(u + a + i / 2) * 2] = c - g, n[(u + a + i / 2) * 2 + 1] = d - x;
|
|
611
|
-
const
|
|
612
|
-
r =
|
|
611
|
+
const f = r * o - h * l, R = r * l + h * o;
|
|
612
|
+
r = f, h = R;
|
|
613
613
|
}
|
|
614
614
|
}
|
|
615
615
|
}
|
|
@@ -2629,14 +2629,14 @@ const ct = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
|
|
|
2629
2629
|
fr: rt,
|
|
2630
2630
|
fi: ht,
|
|
2631
2631
|
lt: ct
|
|
2632
|
-
}, Q = new
|
|
2633
|
-
new
|
|
2634
|
-
new
|
|
2635
|
-
new
|
|
2636
|
-
new
|
|
2637
|
-
const mt = new
|
|
2638
|
-
new
|
|
2639
|
-
new
|
|
2632
|
+
}, Q = new b.Quaternion(), V = new b.Euler(), ve = new b.Vector3(), Re = new b.Vector3(), We = new b.Box3();
|
|
2633
|
+
new b.Matrix4();
|
|
2634
|
+
new b.Matrix4();
|
|
2635
|
+
new b.Vector3();
|
|
2636
|
+
new b.Vector3(0, 0, 1);
|
|
2637
|
+
const mt = new b.Vector3(1, 0, 0);
|
|
2638
|
+
new b.Vector3(0, 1, 0);
|
|
2639
|
+
new b.Vector3(0, 0, 1);
|
|
2640
2640
|
class Be {
|
|
2641
2641
|
/**
|
|
2642
2642
|
* Avatar.
|
|
@@ -4073,22 +4073,22 @@ class Be {
|
|
|
4073
4073
|
if (this.isAvatarOnly = this.opt.avatarOnly, this.isAvatarOnly)
|
|
4074
4074
|
this.scene = this.opt.avatarOnlyScene, this.camera = this.opt.avatarOnlyCamera;
|
|
4075
4075
|
else {
|
|
4076
|
-
this.renderer = new
|
|
4077
|
-
new
|
|
4076
|
+
this.renderer = new b.WebGLRenderer({ antialias: !0, alpha: !0 }), this.renderer.setPixelRatio(this.opt.modelPixelRatio * window.devicePixelRatio), this.renderer.setSize(this.nodeAvatar.clientWidth, this.nodeAvatar.clientHeight), this.renderer.outputColorSpace = b.SRGBColorSpace, this.renderer.toneMapping = b.ACESFilmicToneMapping, this.renderer.shadowMap.enabled = !1, this.nodeAvatar.appendChild(this.renderer.domElement), this.camera = new b.PerspectiveCamera(10, this.nodeAvatar.clientWidth / this.nodeAvatar.clientHeight, 0.1, 2e3), this.scene = new b.Scene(), this.lightAmbient = new b.AmbientLight(
|
|
4077
|
+
new b.Color(this.opt.lightAmbientColor),
|
|
4078
4078
|
this.opt.lightAmbientIntensity
|
|
4079
|
-
), this.lightDirect = new
|
|
4080
|
-
new
|
|
4079
|
+
), this.lightDirect = new b.DirectionalLight(
|
|
4080
|
+
new b.Color(this.opt.lightDirectColor),
|
|
4081
4081
|
this.opt.lightDirectIntensity
|
|
4082
|
-
), this.lightSpot = new
|
|
4083
|
-
new
|
|
4082
|
+
), this.lightSpot = new b.SpotLight(
|
|
4083
|
+
new b.Color(this.opt.lightSpotColor),
|
|
4084
4084
|
this.opt.lightSpotIntensity,
|
|
4085
4085
|
0,
|
|
4086
4086
|
this.opt.lightSpotDispersion
|
|
4087
4087
|
), this.setLighting(this.opt);
|
|
4088
|
-
const l = new
|
|
4088
|
+
const l = new b.PMREMGenerator(this.renderer);
|
|
4089
4089
|
l.compileEquirectangularShader(), this.scene.environment = l.fromScene(new qe()).texture, this.resizeobserver = new ResizeObserver(this.onResize.bind(this)), this.resizeobserver.observe(this.nodeAvatar), this.controls = new Ye(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;
|
|
4090
4090
|
}
|
|
4091
|
-
this.ikMesh = new
|
|
4091
|
+
this.ikMesh = new b.SkinnedMesh();
|
|
4092
4092
|
const s = {
|
|
4093
4093
|
LeftShoulder: null,
|
|
4094
4094
|
LeftArm: "LeftShoulder",
|
|
@@ -4102,9 +4102,9 @@ class Be {
|
|
|
4102
4102
|
RightHandMiddle1: "RightHand"
|
|
4103
4103
|
}, o = [];
|
|
4104
4104
|
Object.entries(s).forEach((l, u) => {
|
|
4105
|
-
const r = new
|
|
4105
|
+
const r = new b.Bone();
|
|
4106
4106
|
r.name = l[0], l[1] ? this.ikMesh.getObjectByName(l[1]).add(r) : this.ikMesh.add(r), o.push(r);
|
|
4107
|
-
}), this.ikMesh.bind(new
|
|
4107
|
+
}), this.ikMesh.bind(new b.Skeleton(o)), this.dynamicbones = new et(), this.isStreaming = !1, this.streamWorkletNode = null, this.streamAudioStartTime = null, this.streamWaitForAudioChunks = !0, this.streamLipsyncLang = null, this.streamLipsyncType = "visemes", this.streamLipsyncQueue = [];
|
|
4108
4108
|
}
|
|
4109
4109
|
/**
|
|
4110
4110
|
* Helper that re/creates the audio context and the other nodes.
|
|
@@ -4194,7 +4194,7 @@ class Be {
|
|
|
4194
4194
|
for (let [n, i] of Object.entries(t)) {
|
|
4195
4195
|
const s = n.split(".");
|
|
4196
4196
|
let o = Array.isArray(i.x) ? this.gaussianRandom(...i.x) : i.x, l = Array.isArray(i.y) ? this.gaussianRandom(...i.y) : i.y, u = Array.isArray(i.z) ? this.gaussianRandom(...i.z) : i.z;
|
|
4197
|
-
s[1] === "position" || s[1] === "scale" ? e[n] = new
|
|
4197
|
+
s[1] === "position" || s[1] === "scale" ? e[n] = new b.Vector3(o, l, u) : s[1] === "rotation" ? (n = s[0] + ".quaternion", e[n] = new b.Quaternion().setFromEuler(new b.Euler(o, l, u, "XYZ")).normalize()) : s[1] === "quaternion" && (e[n] = new b.Quaternion(o, l, u, i.w).normalize());
|
|
4198
4198
|
}
|
|
4199
4199
|
return e;
|
|
4200
4200
|
}
|
|
@@ -4226,15 +4226,15 @@ class Be {
|
|
|
4226
4226
|
for (const [r, h] of Object.entries(n))
|
|
4227
4227
|
if (s.morphTargetDictionary.hasOwnProperty(r)) {
|
|
4228
4228
|
const a = s.morphTargetDictionary[r], c = o.morphAttributes.position[a], d = o.morphAttributes.normal?.[a];
|
|
4229
|
-
l || (l = new
|
|
4229
|
+
l || (l = new b.Float32BufferAttribute(c.count * 3, 3), d && (u = new b.Float32BufferAttribute(c.count * 3, 3)));
|
|
4230
4230
|
for (let g = 0; g < c.count; g++) {
|
|
4231
|
-
const x = l.getX(g) + c.getX(g) * h,
|
|
4232
|
-
l.setXYZ(g, x,
|
|
4231
|
+
const x = l.getX(g) + c.getX(g) * h, f = l.getY(g) + c.getY(g) * h, R = l.getZ(g) + c.getZ(g) * h;
|
|
4232
|
+
l.setXYZ(g, x, f, R);
|
|
4233
4233
|
}
|
|
4234
4234
|
if (d)
|
|
4235
4235
|
for (let g = 0; g < c.count; g++) {
|
|
4236
|
-
const x = u.getX(g) + d.getX(g) * h,
|
|
4237
|
-
u.setXYZ(g, x,
|
|
4236
|
+
const x = u.getX(g) + d.getX(g) * h, f = u.getY(g) + d.getY(g) * h, R = u.getZ(g) + d.getZ(g) * h;
|
|
4237
|
+
u.setXYZ(g, x, f, R);
|
|
4238
4238
|
}
|
|
4239
4239
|
}
|
|
4240
4240
|
if (l) {
|
|
@@ -4314,7 +4314,7 @@ class Be {
|
|
|
4314
4314
|
console.error("Dynamic bones setup failed: " + r);
|
|
4315
4315
|
}
|
|
4316
4316
|
this.objectLeftToeBase = this.armature.getObjectByName("LeftToeBase"), this.objectRightToeBase = this.armature.getObjectByName("RightToeBase"), this.objectLeftEye = this.armature.getObjectByName("LeftEye"), this.objectRightEye = this.armature.getObjectByName("RightEye"), this.objectLeftArm = this.armature.getObjectByName("LeftArm"), this.objectRightArm = this.armature.getObjectByName("RightArm"), this.objectHips = this.armature.getObjectByName("Hips"), this.objectHead = this.armature.getObjectByName("Head"), this.objectNeck = this.armature.getObjectByName("Neck");
|
|
4317
|
-
const u = new
|
|
4317
|
+
const u = new b.Vector3();
|
|
4318
4318
|
this.objectLeftEye.getWorldPosition(u), this.avatarHeight = u.y + 0.2, this.viewName || this.setView(this.opt.cameraView), this.setMood(this.avatar.avatarMood || this.moodName || this.opt.avatarMood), this.avatar.body === "M" && this.poseTemplates.wide && (this.poseName = "wide", this.setPoseFromTemplate(this.poseTemplates.wide, 0), console.log("Set initial male-appropriate pose: wide")), this.initializeFBXAnimationLoader(), this.bodyMovement && this.bodyMovement !== "idle" && this.applyBodyMovementAnimation(), this.start();
|
|
4319
4319
|
}
|
|
4320
4320
|
/**
|
|
@@ -4358,14 +4358,14 @@ class Be {
|
|
|
4358
4358
|
default:
|
|
4359
4359
|
a += 12, h = h * a;
|
|
4360
4360
|
}
|
|
4361
|
-
r = r * a, this.controlsEnd = new
|
|
4361
|
+
r = r * a, this.controlsEnd = new b.Vector3(r, h, 0), this.cameraEnd = new b.Vector3(r, h, a).applyEuler(new b.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;
|
|
4362
4362
|
}
|
|
4363
4363
|
/**
|
|
4364
4364
|
* Change light colors and intensities.
|
|
4365
4365
|
* @param {Object} opt Options
|
|
4366
4366
|
*/
|
|
4367
4367
|
setLighting(t) {
|
|
4368
|
-
this.isAvatarOnly || (t = t || {}, t.hasOwnProperty("lightAmbientColor") && this.lightAmbient.color.set(new
|
|
4368
|
+
this.isAvatarOnly || (t = t || {}, t.hasOwnProperty("lightAmbientColor") && this.lightAmbient.color.set(new b.Color(t.lightAmbientColor)), t.hasOwnProperty("lightAmbientIntensity") && (this.lightAmbient.intensity = t.lightAmbientIntensity, this.lightAmbient.visible = t.lightAmbientIntensity !== 0), t.hasOwnProperty("lightDirectColor") && this.lightDirect.color.set(new b.Color(t.lightDirectColor)), t.hasOwnProperty("lightDirectIntensity") && (this.lightDirect.intensity = t.lightDirectIntensity, this.lightDirect.visible = t.lightDirectIntensity !== 0), t.hasOwnProperty("lightDirectPhi") && t.hasOwnProperty("lightDirectTheta") && this.lightDirect.position.setFromSphericalCoords(2, t.lightDirectPhi, t.lightDirectTheta), t.hasOwnProperty("lightSpotColor") && this.lightSpot.color.set(new b.Color(t.lightSpotColor)), t.hasOwnProperty("lightSpotIntensity") && (this.lightSpot.intensity = t.lightSpotIntensity, this.lightSpot.visible = t.lightSpotIntensity !== 0), t.hasOwnProperty("lightSpotPhi") && t.hasOwnProperty("lightSpotTheta") && (this.lightSpot.position.setFromSphericalCoords(2, t.lightSpotPhi, t.lightSpotTheta), this.lightSpot.position.add(new b.Vector3(0, 1.5, 0))), t.hasOwnProperty("lightSpotDispersion") && (this.lightSpot.angle = t.lightSpotDispersion));
|
|
4369
4369
|
}
|
|
4370
4370
|
/**
|
|
4371
4371
|
* Render scene.
|
|
@@ -4480,7 +4480,7 @@ class Be {
|
|
|
4480
4480
|
return Object.entries(t).forEach((i, s) => {
|
|
4481
4481
|
const o = i[0].split(".");
|
|
4482
4482
|
if (o[1] === "position" || o[1] === "rotation" || o[1] === "quaternion") {
|
|
4483
|
-
const l = o[1] === "quaternion" ? o[0] + ".rotation" : i[0], u = i[1].isQuaternion ? new
|
|
4483
|
+
const l = o[1] === "quaternion" ? o[0] + ".rotation" : i[0], u = i[1].isQuaternion ? new b.Euler().setFromQuaternion(i[1]) : i[1];
|
|
4484
4484
|
n += (s ? ", " : "") + "'" + l + "':{", n += "x:" + Math.round(u.x * e) / e, n += ", y:" + Math.round(u.y * e) / e, n += ", z:" + Math.round(u.z * e) / e, n += "}";
|
|
4485
4485
|
}
|
|
4486
4486
|
}), n += "}", n;
|
|
@@ -5108,8 +5108,8 @@ class Be {
|
|
|
5108
5108
|
else {
|
|
5109
5109
|
g.newvalue = d[i + 1];
|
|
5110
5110
|
const x = a.ts[i + 1] - a.ts[i];
|
|
5111
|
-
let
|
|
5112
|
-
x > 1e-4 && (
|
|
5111
|
+
let f = 1;
|
|
5112
|
+
x > 1e-4 && (f = (this.animClock - a.ts[i]) / x), f < 1 && (g.easing && (f = g.easing(f)), g.newvalue = (1 - f) * d[i] + f * g.newvalue), g.ref && g.ref !== a.vs && g.ref.hasOwnProperty(c) && delete g.ref[c], g.ref = a.vs;
|
|
5113
5113
|
}
|
|
5114
5114
|
if (l)
|
|
5115
5115
|
switch (c) {
|
|
@@ -5157,7 +5157,7 @@ class Be {
|
|
|
5157
5157
|
{ link: "LeftForeArm", minx: -0.5, maxx: 1.5, miny: -1.5, maxy: 1.5, minz: -0.5, maxz: 3 },
|
|
5158
5158
|
{ link: "LeftArm", minx: -1.5, maxx: 1.5, miny: 0, maxy: 0, minz: -1, maxz: 3 }
|
|
5159
5159
|
]
|
|
5160
|
-
}, i.x ? new
|
|
5160
|
+
}, i.x ? new b.Vector3(i.x, i.y, i.z) : null, !0, i.d);
|
|
5161
5161
|
break;
|
|
5162
5162
|
case "handRight":
|
|
5163
5163
|
this.ikSolve({
|
|
@@ -5169,7 +5169,7 @@ class Be {
|
|
|
5169
5169
|
{ link: "RightForeArm", minx: -0.5, maxx: 1.5, miny: -1.5, maxy: 1.5, minz: -3, maxz: 0.5, maxAngle: 0.2 },
|
|
5170
5170
|
{ link: "RightArm", minx: -1.5, maxx: 1.5, miny: 0, maxy: 0, minz: -1, maxz: 3 }
|
|
5171
5171
|
]
|
|
5172
|
-
}, i.x ? new
|
|
5172
|
+
}, i.x ? new b.Vector3(i.x, i.y, i.z) : null, !0, i.d);
|
|
5173
5173
|
break;
|
|
5174
5174
|
}
|
|
5175
5175
|
if ((u || r) && (V.setFromQuaternion(this.poseAvatar.props["Head.quaternion"]), V.x = Math.max(-0.9, Math.min(0.9, 2 * V.x - 0.5)), V.y = Math.max(-0.9, Math.min(0.9, -2.5 * V.y)), u ? (Object.assign(this.mtAvatar.eyesLookDown, { system: V.x < 0 ? -V.x : 0, needsUpdate: !0 }), Object.assign(this.mtAvatar.eyesLookUp, { system: V.x < 0 ? 0 : V.x, needsUpdate: !0 }), Object.assign(this.mtAvatar.eyeLookInLeft, { system: V.y < 0 ? -V.y : 0, needsUpdate: !0 }), Object.assign(this.mtAvatar.eyeLookOutLeft, { system: V.y < 0 ? 0 : V.y, needsUpdate: !0 }), Object.assign(this.mtAvatar.eyeLookInRight, { system: V.y < 0 ? 0 : V.y, needsUpdate: !0 }), Object.assign(this.mtAvatar.eyeLookOutRight, { system: V.y < 0 ? -V.y : 0, needsUpdate: !0 }), r && (n = -this.mtAvatar.bodyRotateY.value, i = this.gaussianRandom(-0.2, 0.2), this.animQueue.push(this.animFactory({
|
|
@@ -5198,7 +5198,7 @@ class Be {
|
|
|
5198
5198
|
else {
|
|
5199
5199
|
if (this.cameraClock !== null && this.cameraClock < 1e3) {
|
|
5200
5200
|
this.cameraClock += e, this.cameraClock > 1e3 && (this.cameraClock = 1e3);
|
|
5201
|
-
let a = new
|
|
5201
|
+
let a = new b.Spherical().setFromVector3(this.cameraStart), c = new b.Spherical().setFromVector3(this.cameraEnd);
|
|
5202
5202
|
a.phi += this.easing(this.cameraClock / 1e3) * (c.phi - a.phi), a.theta += this.easing(this.cameraClock / 1e3) * (c.theta - a.theta), a.radius += this.easing(this.cameraClock / 1e3) * (c.radius - a.radius), a.makeSafe(), this.camera.position.setFromSpherical(a), this.controlsStart.x !== this.controlsEnd.x ? this.controls.target.copy(this.controlsStart.lerp(this.controlsEnd, this.easing(this.cameraClock / 1e3))) : (a.setFromVector3(this.controlsStart), c.setFromVector3(this.controlsEnd), a.phi += this.easing(this.cameraClock / 1e3) * (c.phi - a.phi), a.theta += this.easing(this.cameraClock / 1e3) * (c.theta - a.theta), a.radius += this.easing(this.cameraClock / 1e3) * (c.radius - a.radius), a.makeSafe(), this.controls.target.setFromSpherical(a)), this.controls.update();
|
|
5203
5203
|
}
|
|
5204
5204
|
this.controls.autoRotate && this.controls.update(), this.stats && this.stats.end(), this.render();
|
|
@@ -5262,12 +5262,12 @@ class Be {
|
|
|
5262
5262
|
e = e || {};
|
|
5263
5263
|
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, r = e.lipsyncLang || this.avatar.lipsyncLang || this.opt.lipsyncLang;
|
|
5264
5264
|
let h = "", a = "", c = 0, d = [], g = [];
|
|
5265
|
-
const x = Array.from(this.segmenter.segment(t), (
|
|
5266
|
-
for (let
|
|
5267
|
-
const
|
|
5268
|
-
let p = x[
|
|
5269
|
-
const
|
|
5270
|
-
if (p && !
|
|
5265
|
+
const x = Array.from(this.segmenter.segment(t), (f) => f.segment);
|
|
5266
|
+
for (let f = 0; f < x.length; f++) {
|
|
5267
|
+
const R = f === x.length - 1, F = x[f].match(l);
|
|
5268
|
+
let p = x[f].match(s);
|
|
5269
|
+
const H = x[f].match(u), k = x[f].match(o);
|
|
5270
|
+
if (p && !R && !H && x[f + 1].match(s) && (p = !1), n && (h += x[f]), F && (!i || i.every((y) => f < y[0] || f > y[1])) && (a += x[f]), (k || p || R) && (a.length && (a = this.lipsyncPreProcessText(a, r), a.length && d.push({
|
|
5271
5271
|
mark: c,
|
|
5272
5272
|
word: a
|
|
5273
5273
|
})), h.length && (g.push({
|
|
@@ -5280,28 +5280,28 @@ class Be {
|
|
|
5280
5280
|
}), h = ""), a.length)) {
|
|
5281
5281
|
const y = this.lipsyncWordsToVisemes(a, r);
|
|
5282
5282
|
if (y && y.visemes && y.visemes.length) {
|
|
5283
|
-
const
|
|
5284
|
-
for (let
|
|
5283
|
+
const T = y.times[y.visemes.length - 1] + y.durations[y.visemes.length - 1];
|
|
5284
|
+
for (let E = 0; E < y.visemes.length; E++)
|
|
5285
5285
|
g.push({
|
|
5286
5286
|
mark: c,
|
|
5287
5287
|
template: { name: "viseme" },
|
|
5288
|
-
ts: [(y.times[
|
|
5288
|
+
ts: [(y.times[E] - 0.6) / T, (y.times[E] + 0.5) / T, (y.times[E] + y.durations[E] + 0.5) / T],
|
|
5289
5289
|
vs: {
|
|
5290
|
-
["viseme_" + y.visemes[
|
|
5290
|
+
["viseme_" + y.visemes[E]]: [null, y.visemes[E] === "PP" || y.visemes[E] === "FF" ? 0.9 : 0.6, 0]
|
|
5291
5291
|
}
|
|
5292
5292
|
});
|
|
5293
5293
|
}
|
|
5294
5294
|
a = "", c++;
|
|
5295
5295
|
}
|
|
5296
|
-
if (p ||
|
|
5297
|
-
if (d.length ||
|
|
5296
|
+
if (p || R) {
|
|
5297
|
+
if (d.length || R && g.length) {
|
|
5298
5298
|
const y = {
|
|
5299
5299
|
anim: g
|
|
5300
5300
|
};
|
|
5301
5301
|
n && (y.onSubtitles = n), d.length && !e.avatarMute && (y.text = d, e.avatarMood && (y.mood = e.avatarMood), e.ttsLang && (y.lang = e.ttsLang), e.ttsVoice && (y.voice = e.ttsVoice), e.ttsRate && (y.rate = e.ttsRate), e.ttsVoice && (y.pitch = e.ttsPitch), e.ttsVolume && (y.volume = e.ttsVolume)), this.speechQueue.push(y), d = [], a = "", c = 0, g = [];
|
|
5302
5302
|
}
|
|
5303
|
-
if (
|
|
5304
|
-
let y = this.animEmojis[x[
|
|
5303
|
+
if (H) {
|
|
5304
|
+
let y = this.animEmojis[x[f]];
|
|
5305
5305
|
y && y.link && (y = this.animEmojis[y.link]), y && this.speechQueue.push({ emoji: y });
|
|
5306
5306
|
}
|
|
5307
5307
|
this.speechQueue.push({ break: 100 });
|
|
@@ -5397,13 +5397,13 @@ class Be {
|
|
|
5397
5397
|
const d = c.times[c.visemes.length - 1] + c.durations[c.visemes.length - 1], g = Math.min(h, Math.max(0, h - c.visemes.length * 150));
|
|
5398
5398
|
let x = 0.6 + this.convertRange(g, [0, h], [0, 0.4]);
|
|
5399
5399
|
if (h = Math.min(h, c.visemes.length * 200), d > 0)
|
|
5400
|
-
for (let
|
|
5401
|
-
const
|
|
5400
|
+
for (let f = 0; f < c.visemes.length; f++) {
|
|
5401
|
+
const R = r + c.times[f] / d * h, F = c.durations[f] / d * h;
|
|
5402
5402
|
o.push({
|
|
5403
5403
|
template: { name: "viseme" },
|
|
5404
|
-
ts: [
|
|
5404
|
+
ts: [R - Math.min(60, 2 * F / 3), R + Math.min(25, F / 2), R + F + Math.min(60, F / 2)],
|
|
5405
5405
|
vs: {
|
|
5406
|
-
["viseme_" + c.visemes[
|
|
5406
|
+
["viseme_" + c.visemes[f]]: [null, c.visemes[f] === "PP" || c.visemes[f] === "FF" ? 0.9 : x, 0]
|
|
5407
5407
|
}
|
|
5408
5408
|
});
|
|
5409
5409
|
}
|
|
@@ -5483,34 +5483,34 @@ class Be {
|
|
|
5483
5483
|
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, r));
|
|
5484
5484
|
const h = speechSynthesis.getVoices(), a = t.voice || this.avatar.ttsVoice || this.opt.ttsVoice;
|
|
5485
5485
|
if (a && h.length > 0) {
|
|
5486
|
-
const p = h.find((
|
|
5486
|
+
const p = h.find((H) => H.name.includes(a) || H.lang === o);
|
|
5487
5487
|
p && (s.voice = p);
|
|
5488
5488
|
}
|
|
5489
|
-
const c = i.length * 100 / s.rate, d = this.audioCtx.createBuffer(1, this.audioCtx.sampleRate * (c / 1e3), this.audioCtx.sampleRate), g = this.avatar.lipsyncLang || this.opt.lipsyncLang || "en", x = this.lipsyncPreProcessText(i, g),
|
|
5489
|
+
const c = i.length * 100 / s.rate, d = this.audioCtx.createBuffer(1, this.audioCtx.sampleRate * (c / 1e3), this.audioCtx.sampleRate), g = this.avatar.lipsyncLang || this.opt.lipsyncLang || "en", x = this.lipsyncPreProcessText(i, g), f = this.lipsyncWordsToVisemes(x, g);
|
|
5490
5490
|
console.log("Browser TTS Lip-sync Debug:", {
|
|
5491
5491
|
text: i,
|
|
5492
5492
|
lipsyncLang: g,
|
|
5493
5493
|
processedText: x,
|
|
5494
|
-
lipsyncData:
|
|
5495
|
-
hasVisemes:
|
|
5494
|
+
lipsyncData: f,
|
|
5495
|
+
hasVisemes: f && f.visemes && f.visemes.length > 0,
|
|
5496
5496
|
estimatedDuration: c
|
|
5497
5497
|
});
|
|
5498
|
-
const
|
|
5499
|
-
if (
|
|
5500
|
-
const p =
|
|
5501
|
-
for (let
|
|
5502
|
-
const
|
|
5503
|
-
|
|
5498
|
+
const R = [];
|
|
5499
|
+
if (f && f.visemes && f.visemes.length > 0) {
|
|
5500
|
+
const p = f.times[f.visemes.length - 1] + f.durations[f.visemes.length - 1];
|
|
5501
|
+
for (let H = 0; H < f.visemes.length; H++) {
|
|
5502
|
+
const k = f.visemes[H], y = f.times[H] / p, T = f.durations[H] / p, E = y * c, O = T * c;
|
|
5503
|
+
R.push({
|
|
5504
5504
|
template: { name: "viseme" },
|
|
5505
|
-
ts: [
|
|
5505
|
+
ts: [E - Math.min(60, 2 * O / 3), E + Math.min(25, O / 2), E + O + Math.min(60, O / 2)],
|
|
5506
5506
|
vs: {
|
|
5507
|
-
["viseme_" +
|
|
5507
|
+
["viseme_" + k]: [null, k === "PP" || k === "FF" ? 0.9 : 0.6, 0]
|
|
5508
5508
|
}
|
|
5509
5509
|
});
|
|
5510
5510
|
}
|
|
5511
5511
|
}
|
|
5512
|
-
const
|
|
5513
|
-
this.audioPlaylist.push({ anim:
|
|
5512
|
+
const F = [...t.anim, ...R];
|
|
5513
|
+
this.audioPlaylist.push({ anim: F, audio: d }), this.onSubtitles = t.onSubtitles || null, this.resetLips(), t.mood && this.setMood(t.mood), this.playAudio(), s.onend = () => {
|
|
5514
5514
|
e();
|
|
5515
5515
|
}, s.onerror = (p) => {
|
|
5516
5516
|
console.error("Speech synthesis error:", p.error), n(p.error);
|
|
@@ -5576,15 +5576,15 @@ class Be {
|
|
|
5576
5576
|
console.error("Text-based lip-sync failed, using fallback:", c);
|
|
5577
5577
|
const d = e.toLowerCase().split(/\s+/), g = [];
|
|
5578
5578
|
for (const x of d)
|
|
5579
|
-
for (const
|
|
5580
|
-
let
|
|
5581
|
-
"aeiou".includes(
|
|
5579
|
+
for (const f of x) {
|
|
5580
|
+
let R = "aa";
|
|
5581
|
+
"aeiou".includes(f) ? R = "aa" : "bp".includes(f) ? R = "PP" : "fv".includes(f) ? R = "FF" : "st".includes(f) ? R = "SS" : "dln".includes(f) ? R = "DD" : "kg".includes(f) ? R = "kk" : "rw".includes(f) && (R = "RR"), g.push(R);
|
|
5582
5582
|
}
|
|
5583
5583
|
r = {
|
|
5584
|
-
visemes: g.map((x,
|
|
5584
|
+
visemes: g.map((x, f) => ({
|
|
5585
5585
|
viseme: x,
|
|
5586
|
-
startTime:
|
|
5587
|
-
endTime: (
|
|
5586
|
+
startTime: f * l.duration / g.length,
|
|
5587
|
+
endTime: (f + 1) * l.duration / g.length,
|
|
5588
5588
|
duration: l.duration / g.length,
|
|
5589
5589
|
intensity: 0.6
|
|
5590
5590
|
})),
|
|
@@ -5609,12 +5609,12 @@ class Be {
|
|
|
5609
5609
|
if (r.visemes && r.visemes.length > 0) {
|
|
5610
5610
|
console.log("ElevenLabs: Generating lip-sync animation from", r.visemes.length, "visemes");
|
|
5611
5611
|
for (let c = 0; c < r.visemes.length; c++) {
|
|
5612
|
-
const d = r.visemes[c], g = d.startTime * 1e3, x = d.duration * 1e3,
|
|
5612
|
+
const d = r.visemes[c], g = d.startTime * 1e3, x = d.duration * 1e3, f = d.intensity;
|
|
5613
5613
|
h.push({
|
|
5614
5614
|
template: { name: "viseme" },
|
|
5615
5615
|
ts: [g - Math.min(60, 2 * x / 3), g + Math.min(25, x / 2), g + x + Math.min(60, x / 2)],
|
|
5616
5616
|
vs: {
|
|
5617
|
-
["viseme_" + d.viseme]: [null,
|
|
5617
|
+
["viseme_" + d.viseme]: [null, f, 0]
|
|
5618
5618
|
}
|
|
5619
5619
|
});
|
|
5620
5620
|
}
|
|
@@ -5674,15 +5674,15 @@ class Be {
|
|
|
5674
5674
|
console.error("Text-based lip-sync failed, using fallback:", c);
|
|
5675
5675
|
const d = e.toLowerCase().split(/\s+/), g = [];
|
|
5676
5676
|
for (const x of d)
|
|
5677
|
-
for (const
|
|
5678
|
-
let
|
|
5679
|
-
"aeiou".includes(
|
|
5677
|
+
for (const f of x) {
|
|
5678
|
+
let R = "aa";
|
|
5679
|
+
"aeiou".includes(f) ? R = "aa" : "bp".includes(f) ? R = "PP" : "fv".includes(f) ? R = "FF" : "st".includes(f) ? R = "SS" : "dln".includes(f) ? R = "DD" : "kg".includes(f) ? R = "kk" : "rw".includes(f) && (R = "RR"), g.push(R);
|
|
5680
5680
|
}
|
|
5681
5681
|
r = {
|
|
5682
|
-
visemes: g.map((x,
|
|
5682
|
+
visemes: g.map((x, f) => ({
|
|
5683
5683
|
viseme: x,
|
|
5684
|
-
startTime:
|
|
5685
|
-
endTime: (
|
|
5684
|
+
startTime: f * l.duration / g.length,
|
|
5685
|
+
endTime: (f + 1) * l.duration / g.length,
|
|
5686
5686
|
duration: l.duration / g.length,
|
|
5687
5687
|
intensity: 0.6
|
|
5688
5688
|
})),
|
|
@@ -5707,12 +5707,12 @@ class Be {
|
|
|
5707
5707
|
if (r.visemes && r.visemes.length > 0) {
|
|
5708
5708
|
console.log("Deepgram: Generating lip-sync animation from", r.visemes.length, "visemes");
|
|
5709
5709
|
for (let c = 0; c < r.visemes.length; c++) {
|
|
5710
|
-
const d = r.visemes[c], g = d.startTime * 1e3, x = d.duration * 1e3,
|
|
5710
|
+
const d = r.visemes[c], g = d.startTime * 1e3, x = d.duration * 1e3, f = d.intensity;
|
|
5711
5711
|
h.push({
|
|
5712
5712
|
template: { name: "viseme" },
|
|
5713
5713
|
ts: [g - Math.min(60, 2 * x / 3), g + Math.min(25, x / 2), g + x + Math.min(60, x / 2)],
|
|
5714
5714
|
vs: {
|
|
5715
|
-
["viseme_" + d.viseme]: [null,
|
|
5715
|
+
["viseme_" + d.viseme]: [null, f, 0]
|
|
5716
5716
|
}
|
|
5717
5717
|
});
|
|
5718
5718
|
}
|
|
@@ -6146,7 +6146,7 @@ class Be {
|
|
|
6146
6146
|
*/
|
|
6147
6147
|
lookAtCamera(t) {
|
|
6148
6148
|
let e;
|
|
6149
|
-
if (this.speakTo && (e = new
|
|
6149
|
+
if (this.speakTo && (e = new b.Vector3(), this.speakTo.objectLeftEye?.isObject3D ? (this.speakTo.armature.objectHead, this.speakTo.objectLeftEye.updateMatrixWorld(!0), this.speakTo.objectRightEye.updateMatrixWorld(!0), ve.setFromMatrixPosition(this.speakTo.objectLeftEye.matrixWorld), Re.setFromMatrixPosition(this.speakTo.objectRightEye.matrixWorld), e.addVectors(ve, Re).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) {
|
|
6150
6150
|
if (this.avatar.hasOwnProperty("avatarIgnoreCamera")) {
|
|
6151
6151
|
if (this.avatar.avatarIgnoreCamera) {
|
|
6152
6152
|
this.lookAhead(t);
|
|
@@ -6160,15 +6160,15 @@ class Be {
|
|
|
6160
6160
|
return;
|
|
6161
6161
|
}
|
|
6162
6162
|
this.objectLeftEye.updateMatrixWorld(!0), this.objectRightEye.updateMatrixWorld(!0), ve.setFromMatrixPosition(this.objectLeftEye.matrixWorld), Re.setFromMatrixPosition(this.objectRightEye.matrixWorld), ve.add(Re).divideScalar(2), Q.copy(this.armature.quaternion), Q.multiply(this.poseTarget.props["Hips.quaternion"]), Q.multiply(this.poseTarget.props["Spine.quaternion"]), Q.multiply(this.poseTarget.props["Spine1.quaternion"]), Q.multiply(this.poseTarget.props["Spine2.quaternion"]), Q.multiply(this.poseTarget.props["Neck.quaternion"]), Q.multiply(this.poseTarget.props["Head.quaternion"]);
|
|
6163
|
-
const n = new
|
|
6163
|
+
const n = new b.Vector3().subVectors(e, ve).normalize(), i = Math.atan2(n.x, n.z), s = Math.asin(-n.y);
|
|
6164
6164
|
V.set(s, i, 0, "YXZ");
|
|
6165
|
-
const l = new
|
|
6165
|
+
const l = new b.Quaternion().setFromEuler(V), u = new b.Quaternion().copy(l).multiply(Q.clone().invert());
|
|
6166
6166
|
V.setFromQuaternion(u, "YXZ");
|
|
6167
6167
|
let r = V.x / (40 / 24) + 0.2, h = V.y / (9 / 4), a = Math.min(0.6, Math.max(-0.3, r)), c = Math.min(0.8, Math.max(-0.8, h)), d = (Math.random() - 0.5) / 4, g = (Math.random() - 0.5) / 4;
|
|
6168
6168
|
if (t) {
|
|
6169
|
-
let x = this.animQueue.findIndex((
|
|
6169
|
+
let x = this.animQueue.findIndex((R) => R.template.name === "lookat");
|
|
6170
6170
|
x !== -1 && this.animQueue.splice(x, 1);
|
|
6171
|
-
const
|
|
6171
|
+
const f = {
|
|
6172
6172
|
name: "lookat",
|
|
6173
6173
|
dt: [750, t],
|
|
6174
6174
|
vs: {
|
|
@@ -6183,7 +6183,7 @@ class Be {
|
|
|
6183
6183
|
headMove: [0]
|
|
6184
6184
|
}
|
|
6185
6185
|
};
|
|
6186
|
-
this.animQueue.push(this.animFactory(
|
|
6186
|
+
this.animQueue.push(this.animFactory(f));
|
|
6187
6187
|
}
|
|
6188
6188
|
}
|
|
6189
6189
|
/**
|
|
@@ -6196,23 +6196,23 @@ class Be {
|
|
|
6196
6196
|
if (!this.camera) return;
|
|
6197
6197
|
const i = this.nodeAvatar.getBoundingClientRect();
|
|
6198
6198
|
this.objectLeftEye.updateMatrixWorld(!0), this.objectRightEye.updateMatrixWorld(!0);
|
|
6199
|
-
const s = new
|
|
6199
|
+
const s = new b.Vector3().setFromMatrixPosition(this.objectLeftEye.matrixWorld), o = new b.Vector3().setFromMatrixPosition(this.objectRightEye.matrixWorld), l = new b.Vector3().addVectors(s, o).divideScalar(2);
|
|
6200
6200
|
l.project(this.camera);
|
|
6201
6201
|
let u = (l.x + 1) / 2 * i.width + i.left, r = -(l.y - 1) / 2 * i.height + i.top;
|
|
6202
6202
|
t === null && (t = u), e === null && (e = r), Q.copy(this.armature.quaternion), Q.multiply(this.poseTarget.props["Hips.quaternion"]), Q.multiply(this.poseTarget.props["Spine.quaternion"]), Q.multiply(this.poseTarget.props["Spine1.quaternion"]), Q.multiply(this.poseTarget.props["Spine2.quaternion"]), Q.multiply(this.poseTarget.props["Neck.quaternion"]), Q.multiply(this.poseTarget.props["Head.quaternion"]), V.setFromQuaternion(Q);
|
|
6203
|
-
let h = V.x / (40 / 24), a = V.y / (9 / 4), c = Math.min(0.4, Math.max(-0.4, this.camera.rotation.x)), d = Math.min(0.4, Math.max(-0.4, this.camera.rotation.y)), g = Math.max(window.innerWidth - u, u), x = Math.max(window.innerHeight - r, r),
|
|
6204
|
-
|
|
6205
|
-
let
|
|
6203
|
+
let h = V.x / (40 / 24), a = V.y / (9 / 4), c = Math.min(0.4, Math.max(-0.4, this.camera.rotation.x)), d = Math.min(0.4, Math.max(-0.4, this.camera.rotation.y)), g = Math.max(window.innerWidth - u, u), x = Math.max(window.innerHeight - r, r), f = this.convertRange(e, [r - x, r + x], [-0.3, 0.6]) - h + c, R = this.convertRange(t, [u - g, u + g], [-0.8, 0.8]) - a + d;
|
|
6204
|
+
f = Math.min(0.6, Math.max(-0.3, f)), R = Math.min(0.8, Math.max(-0.8, R));
|
|
6205
|
+
let F = (Math.random() - 0.5) / 4, p = (Math.random() - 0.5) / 4;
|
|
6206
6206
|
if (n) {
|
|
6207
|
-
let
|
|
6208
|
-
|
|
6209
|
-
const
|
|
6207
|
+
let H = this.animQueue.findIndex((y) => y.template.name === "lookat");
|
|
6208
|
+
H !== -1 && this.animQueue.splice(H, 1);
|
|
6209
|
+
const k = {
|
|
6210
6210
|
name: "lookat",
|
|
6211
6211
|
dt: [750, n],
|
|
6212
6212
|
vs: {
|
|
6213
|
-
bodyRotateX: [
|
|
6214
|
-
bodyRotateY: [
|
|
6215
|
-
eyesRotateX: [-3 *
|
|
6213
|
+
bodyRotateX: [f + F],
|
|
6214
|
+
bodyRotateY: [R + p],
|
|
6215
|
+
eyesRotateX: [-3 * F + 0.1],
|
|
6216
6216
|
eyesRotateY: [-5 * p],
|
|
6217
6217
|
browInnerUp: [[0, 0.7]],
|
|
6218
6218
|
mouthLeft: [[0, 0.7]],
|
|
@@ -6221,7 +6221,7 @@ class Be {
|
|
|
6221
6221
|
headMove: [0]
|
|
6222
6222
|
}
|
|
6223
6223
|
};
|
|
6224
|
-
this.animQueue.push(this.animFactory(
|
|
6224
|
+
this.animQueue.push(this.animFactory(k));
|
|
6225
6225
|
}
|
|
6226
6226
|
}
|
|
6227
6227
|
/**
|
|
@@ -6232,14 +6232,14 @@ class Be {
|
|
|
6232
6232
|
*/
|
|
6233
6233
|
touchAt(t, e) {
|
|
6234
6234
|
if (!this.camera) return;
|
|
6235
|
-
const n = this.nodeAvatar.getBoundingClientRect(), i = new
|
|
6235
|
+
const n = this.nodeAvatar.getBoundingClientRect(), i = new b.Vector2(
|
|
6236
6236
|
(t - n.left) / n.width * 2 - 1,
|
|
6237
6237
|
-((e - n.top) / n.height) * 2 + 1
|
|
6238
|
-
), s = new
|
|
6238
|
+
), s = new b.Raycaster();
|
|
6239
6239
|
s.setFromCamera(i, this.camera);
|
|
6240
6240
|
const o = s.intersectObject(this.armature);
|
|
6241
6241
|
if (o.length > 0) {
|
|
6242
|
-
const l = o[0].point, u = new
|
|
6242
|
+
const l = o[0].point, u = new b.Vector3(), r = new b.Vector3();
|
|
6243
6243
|
this.objectLeftArm.getWorldPosition(u), this.objectRightArm.getWorldPosition(r);
|
|
6244
6244
|
const h = u.distanceToSquared(l), a = r.distanceToSquared(l);
|
|
6245
6245
|
h < a ? (this.ikSolve({
|
|
@@ -6283,7 +6283,7 @@ class Be {
|
|
|
6283
6283
|
{ link: "LeftForeArm", minx: -0.5, maxx: 1.5, miny: -1.5, maxy: 1.5, minz: -0.5, maxz: 3 },
|
|
6284
6284
|
{ link: "LeftArm", minx: -1.5, maxx: 1.5, miny: -1.5, maxy: 1.5, minz: -1, maxz: 3 }
|
|
6285
6285
|
]
|
|
6286
|
-
}, new
|
|
6286
|
+
}, new b.Vector3(
|
|
6287
6287
|
this.gaussianRandom(0, 0.5),
|
|
6288
6288
|
this.gaussianRandom(-0.8, -0.2),
|
|
6289
6289
|
this.gaussianRandom(0, 0.5)
|
|
@@ -6295,15 +6295,15 @@ class Be {
|
|
|
6295
6295
|
{ link: "RightForeArm", minx: -0.5, maxx: 1.5, miny: -1.5, maxy: 1.5, minz: -3, maxz: 0.5 },
|
|
6296
6296
|
{ link: "RightArm" }
|
|
6297
6297
|
]
|
|
6298
|
-
}, new
|
|
6298
|
+
}, new b.Vector3(
|
|
6299
6299
|
this.gaussianRandom(-0.5, 0),
|
|
6300
6300
|
this.gaussianRandom(-0.8, -0.2),
|
|
6301
6301
|
this.gaussianRandom(0, 0.5)
|
|
6302
6302
|
), !0);
|
|
6303
6303
|
const n = [], i = [];
|
|
6304
6304
|
n.push(100 + Math.round(Math.random() * 500)), i.push({ duration: 1e3, props: {
|
|
6305
|
-
"LeftHand.quaternion": new
|
|
6306
|
-
"RightHand.quaternion": new
|
|
6305
|
+
"LeftHand.quaternion": new b.Quaternion().setFromEuler(new b.Euler(0, -1 - Math.random(), 0)),
|
|
6306
|
+
"RightHand.quaternion": new b.Quaternion().setFromEuler(new b.Euler(0, 1 + Math.random(), 0))
|
|
6307
6307
|
} }), ["LeftArm", "LeftForeArm", "RightArm", "RightForeArm"].forEach((o) => {
|
|
6308
6308
|
i[0].props[o + ".quaternion"] = this.ikMesh.getObjectByName(o).quaternion.clone();
|
|
6309
6309
|
}), n.push(1e3 + Math.round(Math.random() * 500)), i.push({ duration: 2e3, props: {} }), ["LeftArm", "LeftForeArm", "RightArm", "RightForeArm", "LeftHand", "RightHand"].forEach((o) => {
|
|
@@ -6402,7 +6402,7 @@ class Be {
|
|
|
6402
6402
|
let n = t;
|
|
6403
6403
|
if (n.startsWith("CC_Base_") && (n = n.replace("CC_Base_", "")), n = n.replace(/^mixamorig/i, ""), e.has(n))
|
|
6404
6404
|
return n;
|
|
6405
|
-
if (n.match(/^Spine\d+$/)) {
|
|
6405
|
+
if (this._mappingDebugLog || (this._mappingDebugLog = /* @__PURE__ */ new Set()), this._mappingDebugLog.size < 5 && !this._mappingDebugLog.has(t) && (this._mappingDebugLog.add(t), console.debug(`Mapping attempt: "${t}" -> "${n}" (not found in available bones)`)), n.match(/^Spine\d+$/)) {
|
|
6406
6406
|
const a = n.match(/\d+/)?.[0];
|
|
6407
6407
|
if (a) {
|
|
6408
6408
|
const c = `Spine${parseInt(a)}`;
|
|
@@ -6432,6 +6432,9 @@ class Be {
|
|
|
6432
6432
|
L_Middle1: "LeftHandMiddle1",
|
|
6433
6433
|
L_Middle2: "LeftHandMiddle2",
|
|
6434
6434
|
L_Middle3: "LeftHandMiddle3",
|
|
6435
|
+
L_Mid1: "LeftHandMiddle1",
|
|
6436
|
+
L_Mid2: "LeftHandMiddle2",
|
|
6437
|
+
L_Mid3: "LeftHandMiddle3",
|
|
6435
6438
|
L_Ring1: "LeftHandRing1",
|
|
6436
6439
|
L_Ring2: "LeftHandRing2",
|
|
6437
6440
|
L_Ring3: "LeftHandRing3",
|
|
@@ -6452,6 +6455,9 @@ class Be {
|
|
|
6452
6455
|
R_Middle1: "RightHandMiddle1",
|
|
6453
6456
|
R_Middle2: "RightHandMiddle2",
|
|
6454
6457
|
R_Middle3: "RightHandMiddle3",
|
|
6458
|
+
R_Mid1: "RightHandMiddle1",
|
|
6459
|
+
R_Mid2: "RightHandMiddle2",
|
|
6460
|
+
R_Mid3: "RightHandMiddle3",
|
|
6455
6461
|
R_Ring1: "RightHandRing1",
|
|
6456
6462
|
R_Ring2: "RightHandRing2",
|
|
6457
6463
|
R_Ring3: "RightHandRing3",
|
|
@@ -6474,7 +6480,9 @@ class Be {
|
|
|
6474
6480
|
if (e.has(a))
|
|
6475
6481
|
return a;
|
|
6476
6482
|
}
|
|
6477
|
-
const s = n.toLowerCase()
|
|
6483
|
+
const s = n.toLowerCase();
|
|
6484
|
+
n.charAt(0).toUpperCase() + n.slice(1).toLowerCase();
|
|
6485
|
+
const o = s.match(/^[rl]_index(\d+)$/);
|
|
6478
6486
|
if (o) {
|
|
6479
6487
|
const a = o[1], d = `${s.startsWith("r") ? "Right" : "Left"}HandIndex${a}`;
|
|
6480
6488
|
if (e.has(d))
|
|
@@ -6492,7 +6500,7 @@ class Be {
|
|
|
6492
6500
|
if (e.has(d))
|
|
6493
6501
|
return d;
|
|
6494
6502
|
}
|
|
6495
|
-
const r = s.match(/^[rl]
|
|
6503
|
+
const r = s.match(/^[rl]_(?:middle|mid)(\d+)$/);
|
|
6496
6504
|
if (r) {
|
|
6497
6505
|
const a = r[1], d = `${s.startsWith("r") ? "Right" : "Left"}HandMiddle${a}`;
|
|
6498
6506
|
if (e.has(d))
|
|
@@ -6509,6 +6517,8 @@ class Be {
|
|
|
6509
6517
|
if (e.has(c))
|
|
6510
6518
|
return c;
|
|
6511
6519
|
}
|
|
6520
|
+
if (s.includes("upperarmtwist") || s.includes("forearmtwist") || s.includes("ribstwist") || s.includes("breast") || s.includes("twist"))
|
|
6521
|
+
return null;
|
|
6512
6522
|
if (s.match(/^[rl]_forearm/)) {
|
|
6513
6523
|
const c = `${s.startsWith("r") ? "Right" : "Left"}ForeArm`;
|
|
6514
6524
|
if (e.has(c))
|
|
@@ -6533,11 +6543,39 @@ class Be {
|
|
|
6533
6543
|
*/
|
|
6534
6544
|
filterAnimationTracks(t, e) {
|
|
6535
6545
|
const n = [], i = /* @__PURE__ */ new Set(), s = /* @__PURE__ */ new Map();
|
|
6536
|
-
return
|
|
6546
|
+
return this._loggedAvailableBones || (console.log(
|
|
6547
|
+
"Available avatar bones:",
|
|
6548
|
+
Array.from(e).sort().slice(0, 50).join(", "),
|
|
6549
|
+
e.size > 50 ? `... (${e.size} total)` : ""
|
|
6550
|
+
), this._loggedAvailableBones = !0), t.tracks.forEach((o) => {
|
|
6537
6551
|
const l = o.name.split("."), u = l[0], r = l[1], h = this.mapBoneName(u, e);
|
|
6538
6552
|
if (h) {
|
|
6539
6553
|
const a = `${h}.${r}`, c = o.clone();
|
|
6540
|
-
c.name = a
|
|
6554
|
+
c.name = a;
|
|
6555
|
+
const d = h.includes("Arm") || h.includes("Hand") || h.includes("Shoulder"), g = h.includes("ForeArm");
|
|
6556
|
+
if (d && (r === "quaternion" || r === "rotation")) {
|
|
6557
|
+
if (r === "quaternion" && c.values && c.values.length >= 4) {
|
|
6558
|
+
const x = c.times.length;
|
|
6559
|
+
for (let f = 0; f < x; f++) {
|
|
6560
|
+
const R = f * 4;
|
|
6561
|
+
if (R + 3 < c.values.length) {
|
|
6562
|
+
let F = c.values[R], p = c.values[R + 1], H = c.values[R + 2], k = c.values[R + 3];
|
|
6563
|
+
if (g || h.includes("Hand")) {
|
|
6564
|
+
const y = Math.PI, T = Math.cos(y / 2), E = Math.sin(y / 2), O = T * k - E * F, te = T * F + E * k, S = T * p - E * H, G = T * H + E * p;
|
|
6565
|
+
F = te, p = S, H = G, k = O;
|
|
6566
|
+
}
|
|
6567
|
+
c.values[R] = F, c.values[R + 1] = p, c.values[R + 2] = H, c.values[R + 3] = k;
|
|
6568
|
+
}
|
|
6569
|
+
}
|
|
6570
|
+
} else if (r === "rotation" && c.values && c.values.length >= 3) {
|
|
6571
|
+
const x = c.times.length;
|
|
6572
|
+
for (let f = 0; f < x; f++) {
|
|
6573
|
+
const R = f * 3;
|
|
6574
|
+
R + 2 < c.values.length && (g || h.includes("Hand")) && (c.values[R + 1] += Math.PI);
|
|
6575
|
+
}
|
|
6576
|
+
}
|
|
6577
|
+
}
|
|
6578
|
+
n.push(c), u !== h && s.set(u, h);
|
|
6541
6579
|
} else
|
|
6542
6580
|
i.add(u);
|
|
6543
6581
|
}), s.size > 0 && console.info(
|
|
@@ -6548,7 +6586,7 @@ class Be {
|
|
|
6548
6586
|
`FBX animation "${t.name}" contains tracks for ${i.size} bone(s) that couldn't be mapped:`,
|
|
6549
6587
|
Array.from(i).slice(0, 10).join(", "),
|
|
6550
6588
|
i.size > 10 ? "..." : ""
|
|
6551
|
-
), n.length > 0 ? console.info(`Filtered ${t.tracks.length} tracks down to ${n.length} valid tracks (${s.size} mapped)`) : console.error(`No valid tracks found for animation "${t.name}". All bones are missing or couldn't be mapped.`), n.length === 0 ? null : new
|
|
6589
|
+
), n.length > 0 ? console.info(`Filtered ${t.tracks.length} tracks down to ${n.length} valid tracks (${s.size} mapped)`) : console.error(`No valid tracks found for animation "${t.name}". All bones are missing or couldn't be mapped.`), n.length === 0 ? null : new b.AnimationClip(t.name, t.duration, n);
|
|
6552
6590
|
}
|
|
6553
6591
|
async playAnimation(t, e = null, n = 10, i = 0, s = 0.01, o = !1) {
|
|
6554
6592
|
if (!this.armature) return;
|
|
@@ -6558,9 +6596,9 @@ class Be {
|
|
|
6558
6596
|
let u = this.animQueue.find((a) => a.template.name === "pose");
|
|
6559
6597
|
u && (u.ts[0] = 1 / 0), Object.entries(l.pose.props).forEach((a) => {
|
|
6560
6598
|
this.poseBase.props[a[0]] = a[1].clone(), this.poseTarget.props[a[0]] = a[1].clone(), this.poseTarget.props[a[0]].t = 0, this.poseTarget.props[a[0]].d = 1e3;
|
|
6561
|
-
}), this.mixer ? console.log("Using existing mixer for FBX animation, preserving morph targets") : (this.mixer = new
|
|
6599
|
+
}), this.mixer ? console.log("Using existing mixer for FBX animation, preserving morph targets") : (this.mixer = new b.AnimationMixer(this.armature), console.log("Created new mixer for FBX animation")), this.mixer.addEventListener("finished", this.stopAnimation.bind(this), { once: !0 });
|
|
6562
6600
|
const r = Math.ceil(n / l.clip.duration), h = this.mixer.clipAction(l.clip);
|
|
6563
|
-
h.setLoop(
|
|
6601
|
+
h.setLoop(b.LoopRepeat, r), h.clampWhenFinished = !0, this.currentFBXAction = h;
|
|
6564
6602
|
try {
|
|
6565
6603
|
h.fadeIn(0.5).play(), console.log("FBX animation started successfully:", t);
|
|
6566
6604
|
} catch (a) {
|
|
@@ -6586,7 +6624,7 @@ class Be {
|
|
|
6586
6624
|
} catch (c) {
|
|
6587
6625
|
console.warn(`Could not verify file existence for ${t}, attempting to load anyway:`, c);
|
|
6588
6626
|
}
|
|
6589
|
-
const h = new
|
|
6627
|
+
const h = new Ne();
|
|
6590
6628
|
let a;
|
|
6591
6629
|
try {
|
|
6592
6630
|
a = await h.loadAsync(t, e);
|
|
@@ -6618,20 +6656,20 @@ class Be {
|
|
|
6618
6656
|
}
|
|
6619
6657
|
c = g;
|
|
6620
6658
|
const x = {};
|
|
6621
|
-
c.tracks.forEach((
|
|
6622
|
-
|
|
6623
|
-
const
|
|
6624
|
-
if (
|
|
6625
|
-
for (let p = 0; p <
|
|
6626
|
-
|
|
6627
|
-
x[
|
|
6628
|
-
} else
|
|
6659
|
+
c.tracks.forEach((R) => {
|
|
6660
|
+
R.name = R.name.replaceAll("mixamorig", "");
|
|
6661
|
+
const F = R.name.split(".");
|
|
6662
|
+
if (F[1] === "position") {
|
|
6663
|
+
for (let p = 0; p < R.values.length; p++)
|
|
6664
|
+
R.values[p] = R.values[p] * s;
|
|
6665
|
+
x[R.name] = new b.Vector3(R.values[0], R.values[1], R.values[2]);
|
|
6666
|
+
} else F[1] === "quaternion" ? x[R.name] = new b.Quaternion(R.values[0], R.values[1], R.values[2], R.values[3]) : F[1] === "rotation" && (x[F[0] + ".quaternion"] = new b.Quaternion().setFromEuler(new b.Euler(R.values[0], R.values[1], R.values[2], "XYZ")).normalize());
|
|
6629
6667
|
});
|
|
6630
|
-
const
|
|
6631
|
-
x["Hips.position"] && (x["Hips.position"].y < 0.5 ?
|
|
6668
|
+
const f = { props: x };
|
|
6669
|
+
x["Hips.position"] && (x["Hips.position"].y < 0.5 ? f.lying = !0 : f.standing = !0), this.animClips.push({
|
|
6632
6670
|
url: t + "-" + i,
|
|
6633
6671
|
clip: c,
|
|
6634
|
-
pose:
|
|
6672
|
+
pose: f
|
|
6635
6673
|
}), this.playAnimation(t, e, n, i, s);
|
|
6636
6674
|
} else {
|
|
6637
6675
|
const c = "Animation " + t + " (ndx=" + i + ") not found";
|
|
@@ -6669,14 +6707,14 @@ class Be {
|
|
|
6669
6707
|
let l = this.animQueue.find((u) => u.template.name === "pose");
|
|
6670
6708
|
l && (l.ts[0] = this.animClock + n * 1e3 + 2e3), this.setPoseFromTemplate(o);
|
|
6671
6709
|
} else {
|
|
6672
|
-
let u = await new
|
|
6710
|
+
let u = await new Ne().loadAsync(t, e);
|
|
6673
6711
|
if (u && u.animations && u.animations[i]) {
|
|
6674
6712
|
let r = u.animations[i];
|
|
6675
6713
|
const h = {};
|
|
6676
6714
|
r.tracks.forEach((c) => {
|
|
6677
6715
|
c.name = c.name.replaceAll("mixamorig", "");
|
|
6678
6716
|
const d = c.name.split(".");
|
|
6679
|
-
d[1] === "position" ? h[c.name] = new
|
|
6717
|
+
d[1] === "position" ? h[c.name] = new b.Vector3(c.values[0] * s, c.values[1] * s, c.values[2] * s) : d[1] === "quaternion" ? h[c.name] = new b.Quaternion(c.values[0], c.values[1], c.values[2], c.values[3]) : d[1] === "rotation" && (h[d[0] + ".quaternion"] = new b.Quaternion().setFromEuler(new b.Euler(c.values[0], c.values[1], c.values[2], "XYZ")).normalize());
|
|
6680
6718
|
});
|
|
6681
6719
|
const a = { props: h };
|
|
6682
6720
|
h["Hips.position"] && (h["Hips.position"].y < 0.5 ? a.lying = !0 : a.standing = !0), this.animPoses.push({
|
|
@@ -6709,7 +6747,7 @@ class Be {
|
|
|
6709
6747
|
if (s) {
|
|
6710
6748
|
this.gestureTimeout && (clearTimeout(this.gestureTimeout), this.gestureTimeout = null);
|
|
6711
6749
|
let l = this.animQueue.findIndex((u) => u.template.name === "talkinghands");
|
|
6712
|
-
l !== -1 && (this.animQueue[l].ts = this.animQueue[l].ts.map((u) => 0)), this.gesture = this.propsToThreeObjects(s), n && (this.gesture = this.mirrorPose(this.gesture)), t === "namaste" && this.avatar.body === "M" && (this.gesture["RightArm.quaternion"].rotateTowards(new
|
|
6750
|
+
l !== -1 && (this.animQueue[l].ts = this.animQueue[l].ts.map((u) => 0)), this.gesture = this.propsToThreeObjects(s), n && (this.gesture = this.mirrorPose(this.gesture)), t === "namaste" && this.avatar.body === "M" && (this.gesture["RightArm.quaternion"].rotateTowards(new b.Quaternion(0, 1, 0, 0), -0.25), this.gesture["LeftArm.quaternion"].rotateTowards(new b.Quaternion(0, 1, 0, 0), -0.25));
|
|
6713
6751
|
for (let [u, r] of Object.entries(this.gesture))
|
|
6714
6752
|
r.t = this.animClock, r.d = i, this.poseTarget.props.hasOwnProperty(u) && (this.poseTarget.props[u].copy(r), this.poseTarget.props[u].t = this.animClock, this.poseTarget.props[u].d = i);
|
|
6715
6753
|
e && Number.isFinite(e) && (this.gestureTimeout = setTimeout(this.stopGesture.bind(this, i), 1e3 * e));
|
|
@@ -6724,7 +6762,7 @@ class Be {
|
|
|
6724
6762
|
const c = [];
|
|
6725
6763
|
for (let x = 1; x < l.ts.length; x++) c.push(l.ts[x] - l.ts[x - 1]);
|
|
6726
6764
|
const d = o.template?.rescale || c.map((x) => x / h), g = e * 1e3 - h;
|
|
6727
|
-
l.ts = l.ts.map((x,
|
|
6765
|
+
l.ts = l.ts.map((x, f, R) => f === 0 ? u : R[f - 1] + c[f - 1] + d[f - 1] * g);
|
|
6728
6766
|
} else {
|
|
6729
6767
|
const c = e * 1e3 / h;
|
|
6730
6768
|
l.ts = l.ts.map((d) => u + c * (d - u));
|
|
@@ -6757,34 +6795,34 @@ class Be {
|
|
|
6757
6795
|
* @param {numeric} [d=null] If set, apply in d milliseconds
|
|
6758
6796
|
*/
|
|
6759
6797
|
ikSolve(t, e = null, n = !1, i = null) {
|
|
6760
|
-
const s = new
|
|
6798
|
+
const s = new b.Vector3(), o = new b.Vector3(), l = new b.Vector3(), u = new b.Vector3(), r = new b.Quaternion(), h = new b.Vector3(), a = new b.Vector3(), c = new b.Vector3(), d = this.ikMesh.getObjectByName(t.root);
|
|
6761
6799
|
d.position.setFromMatrixPosition(this.armature.getObjectByName(t.root).matrixWorld), d.quaternion.setFromRotationMatrix(this.armature.getObjectByName(t.root).matrixWorld), e && n && e.applyQuaternion(this.armature.quaternion).add(d.position);
|
|
6762
6800
|
const g = this.ikMesh.getObjectByName(t.effector), x = t.links;
|
|
6763
|
-
x.forEach((
|
|
6764
|
-
|
|
6801
|
+
x.forEach((R) => {
|
|
6802
|
+
R.bone = this.ikMesh.getObjectByName(R.link), R.bone.quaternion.copy(this.getPoseTemplateProp(R.link + ".quaternion"));
|
|
6765
6803
|
}), d.updateMatrixWorld(!0);
|
|
6766
|
-
const
|
|
6804
|
+
const f = t.iterations || 10;
|
|
6767
6805
|
if (e)
|
|
6768
|
-
for (let
|
|
6769
|
-
let
|
|
6770
|
-
for (let p = 0,
|
|
6771
|
-
const
|
|
6772
|
-
|
|
6806
|
+
for (let R = 0; R < f; R++) {
|
|
6807
|
+
let F = !1;
|
|
6808
|
+
for (let p = 0, H = x.length; p < H; p++) {
|
|
6809
|
+
const k = x[p].bone;
|
|
6810
|
+
k.matrixWorld.decompose(u, r, h), r.invert(), o.setFromMatrixPosition(g.matrixWorld), l.subVectors(o, u), l.applyQuaternion(r), l.normalize(), s.subVectors(e, u), s.applyQuaternion(r), s.normalize();
|
|
6773
6811
|
let y = s.dot(l);
|
|
6774
|
-
y > 1 ? y = 1 : y < -1 && (y = -1), y = Math.acos(y), !(y < 1e-5) && (x[p].minAngle !== void 0 && y < x[p].minAngle && (y = x[p].minAngle), x[p].maxAngle !== void 0 && y > x[p].maxAngle && (y = x[p].maxAngle), a.crossVectors(l, s), a.normalize(), Q.setFromAxisAngle(a, y),
|
|
6812
|
+
y > 1 ? y = 1 : y < -1 && (y = -1), y = Math.acos(y), !(y < 1e-5) && (x[p].minAngle !== void 0 && y < x[p].minAngle && (y = x[p].minAngle), x[p].maxAngle !== void 0 && y > x[p].maxAngle && (y = x[p].maxAngle), a.crossVectors(l, s), a.normalize(), Q.setFromAxisAngle(a, y), k.quaternion.multiply(Q), k.rotation.setFromVector3(c.setFromEuler(k.rotation).clamp(new b.Vector3(
|
|
6775
6813
|
x[p].minx !== void 0 ? x[p].minx : -1 / 0,
|
|
6776
6814
|
x[p].miny !== void 0 ? x[p].miny : -1 / 0,
|
|
6777
6815
|
x[p].minz !== void 0 ? x[p].minz : -1 / 0
|
|
6778
|
-
), new
|
|
6816
|
+
), new b.Vector3(
|
|
6779
6817
|
x[p].maxx !== void 0 ? x[p].maxx : 1 / 0,
|
|
6780
6818
|
x[p].maxy !== void 0 ? x[p].maxy : 1 / 0,
|
|
6781
6819
|
x[p].maxz !== void 0 ? x[p].maxz : 1 / 0
|
|
6782
|
-
))),
|
|
6820
|
+
))), k.updateMatrixWorld(!0), F = !0);
|
|
6783
6821
|
}
|
|
6784
|
-
if (!
|
|
6822
|
+
if (!F) break;
|
|
6785
6823
|
}
|
|
6786
|
-
i && x.forEach((
|
|
6787
|
-
this.poseTarget.props[
|
|
6824
|
+
i && x.forEach((R) => {
|
|
6825
|
+
this.poseTarget.props[R.link + ".quaternion"].copy(R.bone.quaternion), this.poseTarget.props[R.link + ".quaternion"].t = this.animClock, this.poseTarget.props[R.link + ".quaternion"].d = i;
|
|
6788
6826
|
});
|
|
6789
6827
|
}
|
|
6790
6828
|
/**
|
|
@@ -6844,16 +6882,16 @@ function Fe() {
|
|
|
6844
6882
|
};
|
|
6845
6883
|
}
|
|
6846
6884
|
function kt() {
|
|
6847
|
-
const
|
|
6848
|
-
return Object.entries(
|
|
6885
|
+
const Z = Fe(), t = [];
|
|
6886
|
+
return Object.entries(Z.voices).forEach(([e, n]) => {
|
|
6849
6887
|
t.push({
|
|
6850
6888
|
value: n,
|
|
6851
|
-
label: `${e.charAt(0).toUpperCase() + e.slice(1)} (${
|
|
6889
|
+
label: `${e.charAt(0).toUpperCase() + e.slice(1)} (${Z.service})`
|
|
6852
6890
|
});
|
|
6853
6891
|
}), t;
|
|
6854
6892
|
}
|
|
6855
6893
|
const Ve = Me(({
|
|
6856
|
-
avatarUrl:
|
|
6894
|
+
avatarUrl: Z = "/avatars/brunette.glb",
|
|
6857
6895
|
avatarBody: t = "F",
|
|
6858
6896
|
mood: e = "neutral",
|
|
6859
6897
|
ttsLang: n = "en",
|
|
@@ -6872,142 +6910,142 @@ const Ve = Me(({
|
|
|
6872
6910
|
},
|
|
6873
6911
|
className: g = "",
|
|
6874
6912
|
style: x = {},
|
|
6875
|
-
animations:
|
|
6876
|
-
},
|
|
6877
|
-
const
|
|
6913
|
+
animations: f = {}
|
|
6914
|
+
}, R) => {
|
|
6915
|
+
const F = N(null), p = N(null), H = N(r), k = N(null), y = N(null), T = N(!1), E = N({ remainingText: null, originalText: null, options: null }), O = N([]), te = N(0), [S, G] = ce(!0), [_, X] = ce(null), [$, se] = ce(!1), [ae, pe] = ce(!1);
|
|
6878
6916
|
de(() => {
|
|
6879
|
-
|
|
6917
|
+
T.current = ae;
|
|
6880
6918
|
}, [ae]), de(() => {
|
|
6881
|
-
|
|
6919
|
+
H.current = r;
|
|
6882
6920
|
}, [r]);
|
|
6883
6921
|
const ee = Fe(), le = i || ee.service;
|
|
6884
|
-
let
|
|
6885
|
-
le === "browser" ?
|
|
6922
|
+
let U;
|
|
6923
|
+
le === "browser" ? U = {
|
|
6886
6924
|
service: "browser",
|
|
6887
6925
|
endpoint: "",
|
|
6888
6926
|
apiKey: null,
|
|
6889
6927
|
defaultVoice: "Google US English"
|
|
6890
|
-
} : le === "elevenlabs" ?
|
|
6928
|
+
} : le === "elevenlabs" ? U = {
|
|
6891
6929
|
service: "elevenlabs",
|
|
6892
6930
|
endpoint: "https://api.elevenlabs.io/v1/text-to-speech",
|
|
6893
6931
|
apiKey: o || ee.apiKey,
|
|
6894
6932
|
defaultVoice: s || ee.defaultVoice || Ie.defaultVoice,
|
|
6895
6933
|
voices: ee.voices || Ie.voices
|
|
6896
|
-
} : le === "deepgram" ?
|
|
6934
|
+
} : le === "deepgram" ? U = {
|
|
6897
6935
|
service: "deepgram",
|
|
6898
6936
|
endpoint: "https://api.deepgram.com/v1/speak",
|
|
6899
6937
|
apiKey: o || ee.apiKey,
|
|
6900
6938
|
defaultVoice: s || ee.defaultVoice || Te.defaultVoice,
|
|
6901
6939
|
voices: ee.voices || Te.voices
|
|
6902
|
-
} :
|
|
6940
|
+
} : U = {
|
|
6903
6941
|
...ee,
|
|
6904
6942
|
// Override API key if provided via props
|
|
6905
6943
|
apiKey: o !== null ? o : ee.apiKey
|
|
6906
6944
|
};
|
|
6907
6945
|
const v = {
|
|
6908
|
-
url:
|
|
6946
|
+
url: Z,
|
|
6909
6947
|
body: t,
|
|
6910
6948
|
avatarMood: e,
|
|
6911
6949
|
ttsLang: le === "browser" ? "en-US" : n,
|
|
6912
|
-
ttsVoice: s ||
|
|
6950
|
+
ttsVoice: s || U.defaultVoice,
|
|
6913
6951
|
lipsyncLang: "en",
|
|
6914
6952
|
showFullAvatar: r,
|
|
6915
6953
|
bodyMovement: l,
|
|
6916
6954
|
movementIntensity: u
|
|
6917
|
-
},
|
|
6918
|
-
ttsEndpoint:
|
|
6919
|
-
ttsApikey:
|
|
6955
|
+
}, I = {
|
|
6956
|
+
ttsEndpoint: U.endpoint,
|
|
6957
|
+
ttsApikey: U.apiKey,
|
|
6920
6958
|
ttsService: le,
|
|
6921
6959
|
lipsyncModules: ["en"],
|
|
6922
6960
|
cameraView: h
|
|
6923
|
-
},
|
|
6924
|
-
if (!(!
|
|
6961
|
+
}, w = P(async () => {
|
|
6962
|
+
if (!(!F.current || p.current))
|
|
6925
6963
|
try {
|
|
6926
|
-
if (
|
|
6927
|
-
if (
|
|
6928
|
-
const J = Math.min(100, Math.round(
|
|
6964
|
+
if (G(!0), X(null), p.current = new Be(F.current, I), p.current.controls && (p.current.controls.enableRotate = !1, p.current.controls.enableZoom = !1, p.current.controls.enablePan = !1, p.current.controls.enableDamping = !1), f && Object.keys(f).length > 0 && (p.current.customAnimations = f), await p.current.showAvatar(v, (D) => {
|
|
6965
|
+
if (D.lengthComputable) {
|
|
6966
|
+
const J = Math.min(100, Math.round(D.loaded / D.total * 100));
|
|
6929
6967
|
c(J);
|
|
6930
6968
|
}
|
|
6931
|
-
}), await new Promise((
|
|
6969
|
+
}), await new Promise((D) => {
|
|
6932
6970
|
const J = () => {
|
|
6933
|
-
p.current.lipsync && Object.keys(p.current.lipsync).length > 0 ?
|
|
6971
|
+
p.current.lipsync && Object.keys(p.current.lipsync).length > 0 ? D() : setTimeout(J, 100);
|
|
6934
6972
|
};
|
|
6935
6973
|
J();
|
|
6936
6974
|
}), p.current && p.current.setShowFullAvatar)
|
|
6937
6975
|
try {
|
|
6938
6976
|
p.current.setShowFullAvatar(r);
|
|
6939
|
-
} catch (
|
|
6940
|
-
console.warn("Error setting full body mode on initialization:",
|
|
6977
|
+
} catch (D) {
|
|
6978
|
+
console.warn("Error setting full body mode on initialization:", D);
|
|
6941
6979
|
}
|
|
6942
|
-
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()),
|
|
6943
|
-
const
|
|
6980
|
+
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()), G(!1), se(!0), a(p.current);
|
|
6981
|
+
const B = () => {
|
|
6944
6982
|
document.visibilityState === "visible" ? p.current?.start() : p.current?.stop();
|
|
6945
6983
|
};
|
|
6946
|
-
return document.addEventListener("visibilitychange",
|
|
6947
|
-
document.removeEventListener("visibilitychange",
|
|
6984
|
+
return document.addEventListener("visibilitychange", B), () => {
|
|
6985
|
+
document.removeEventListener("visibilitychange", B);
|
|
6948
6986
|
};
|
|
6949
6987
|
} catch (L) {
|
|
6950
|
-
console.error("Error initializing TalkingHead:", L), X(L.message || "Failed to initialize avatar"),
|
|
6988
|
+
console.error("Error initializing TalkingHead:", L), X(L.message || "Failed to initialize avatar"), G(!1), d(L);
|
|
6951
6989
|
}
|
|
6952
|
-
}, [
|
|
6953
|
-
de(() => (
|
|
6990
|
+
}, [Z, t, e, n, i, s, o, r, l, u, h]);
|
|
6991
|
+
de(() => (w(), () => {
|
|
6954
6992
|
p.current && (p.current.stop(), p.current.dispose(), p.current = null);
|
|
6955
|
-
}), [
|
|
6956
|
-
if (!
|
|
6957
|
-
const L = new ResizeObserver((
|
|
6958
|
-
for (const J of
|
|
6993
|
+
}), [w]), de(() => {
|
|
6994
|
+
if (!F.current || !p.current) return;
|
|
6995
|
+
const L = new ResizeObserver((D) => {
|
|
6996
|
+
for (const J of D)
|
|
6959
6997
|
p.current && p.current.onResize && p.current.onResize();
|
|
6960
6998
|
});
|
|
6961
|
-
L.observe(
|
|
6962
|
-
const
|
|
6999
|
+
L.observe(F.current);
|
|
7000
|
+
const B = () => {
|
|
6963
7001
|
p.current && p.current.onResize && p.current.onResize();
|
|
6964
7002
|
};
|
|
6965
|
-
return window.addEventListener("resize",
|
|
6966
|
-
L.disconnect(), window.removeEventListener("resize",
|
|
7003
|
+
return window.addEventListener("resize", B), () => {
|
|
7004
|
+
L.disconnect(), window.removeEventListener("resize", B);
|
|
6967
7005
|
};
|
|
6968
7006
|
}, [$]);
|
|
6969
|
-
const
|
|
7007
|
+
const M = P(async () => {
|
|
6970
7008
|
if (p.current && p.current.audioCtx)
|
|
6971
7009
|
try {
|
|
6972
7010
|
(p.current.audioCtx.state === "suspended" || p.current.audioCtx.state === "interrupted") && (await p.current.audioCtx.resume(), console.log("Audio context resumed"));
|
|
6973
7011
|
} catch (L) {
|
|
6974
7012
|
console.warn("Failed to resume audio context:", L);
|
|
6975
7013
|
}
|
|
6976
|
-
}, []),
|
|
7014
|
+
}, []), W = P(async (L, B = {}) => {
|
|
6977
7015
|
if (p.current && $)
|
|
6978
7016
|
try {
|
|
6979
|
-
y.current && (clearInterval(y.current), y.current = null),
|
|
6980
|
-
const
|
|
6981
|
-
|
|
7017
|
+
y.current && (clearInterval(y.current), y.current = null), k.current = { text: L, options: B }, E.current = { remainingText: null, originalText: null, options: null };
|
|
7018
|
+
const D = /[!\.\?\n\p{Extended_Pictographic}]/ug, J = L.split(D).map((Y) => Y.trim()).filter((Y) => Y.length > 0);
|
|
7019
|
+
O.current = J, te.current = 0, pe(!1), T.current = !1, await M();
|
|
6982
7020
|
const ge = {
|
|
6983
|
-
...
|
|
6984
|
-
lipsyncLang:
|
|
7021
|
+
...B,
|
|
7022
|
+
lipsyncLang: B.lipsyncLang || v.lipsyncLang || "en"
|
|
6985
7023
|
};
|
|
6986
|
-
if (
|
|
7024
|
+
if (B.onSpeechEnd && p.current) {
|
|
6987
7025
|
const Y = p.current;
|
|
6988
7026
|
let ue = null, Se = 0;
|
|
6989
7027
|
const Ae = 1200;
|
|
6990
7028
|
let be = !1;
|
|
6991
7029
|
ue = setInterval(() => {
|
|
6992
|
-
if (Se++,
|
|
7030
|
+
if (Se++, T.current)
|
|
6993
7031
|
return;
|
|
6994
7032
|
if (Se > Ae) {
|
|
6995
|
-
if (ue && (clearInterval(ue), ue = null, y.current = null), !be && !
|
|
7033
|
+
if (ue && (clearInterval(ue), ue = null, y.current = null), !be && !T.current) {
|
|
6996
7034
|
be = !0;
|
|
6997
7035
|
try {
|
|
6998
|
-
|
|
6999
|
-
} catch (
|
|
7000
|
-
console.error("Error in onSpeechEnd callback (timeout):",
|
|
7036
|
+
B.onSpeechEnd();
|
|
7037
|
+
} catch (De) {
|
|
7038
|
+
console.error("Error in onSpeechEnd callback (timeout):", De);
|
|
7001
7039
|
}
|
|
7002
7040
|
}
|
|
7003
7041
|
return;
|
|
7004
7042
|
}
|
|
7005
7043
|
const ye = !Y.speechQueue || Y.speechQueue.length === 0, ke = !Y.audioPlaylist || Y.audioPlaylist.length === 0;
|
|
7006
|
-
Y && Y.isSpeaking === !1 && ye && ke && Y.isAudioPlaying === !1 && !be && !
|
|
7007
|
-
if (Y && !
|
|
7044
|
+
Y && Y.isSpeaking === !1 && ye && ke && Y.isAudioPlaying === !1 && !be && !T.current && setTimeout(() => {
|
|
7045
|
+
if (Y && !T.current && Y.isSpeaking === !1 && (!Y.speechQueue || Y.speechQueue.length === 0) && (!Y.audioPlaylist || Y.audioPlaylist.length === 0) && Y.isAudioPlaying === !1 && !be && !T.current) {
|
|
7008
7046
|
be = !0, ue && (clearInterval(ue), ue = null, y.current = null);
|
|
7009
7047
|
try {
|
|
7010
|
-
|
|
7048
|
+
B.onSpeechEnd();
|
|
7011
7049
|
} catch (Ze) {
|
|
7012
7050
|
console.error("Error in onSpeechEnd callback:", Ze);
|
|
7013
7051
|
}
|
|
@@ -7016,70 +7054,70 @@ const Ve = Me(({
|
|
|
7016
7054
|
}, 100), y.current = ue;
|
|
7017
7055
|
}
|
|
7018
7056
|
p.current.lipsync && Object.keys(p.current.lipsync).length > 0 ? (p.current.setSlowdownRate && p.current.setSlowdownRate(1.05), p.current.speakText(L, ge)) : setTimeout(async () => {
|
|
7019
|
-
await
|
|
7057
|
+
await M(), p.current && p.current.lipsync && (p.current.setSlowdownRate && p.current.setSlowdownRate(1.05), p.current.speakText(L, ge));
|
|
7020
7058
|
}, 100);
|
|
7021
|
-
} catch (
|
|
7022
|
-
console.error("Error speaking text:",
|
|
7059
|
+
} catch (D) {
|
|
7060
|
+
console.error("Error speaking text:", D), X(D.message || "Failed to speak text");
|
|
7023
7061
|
}
|
|
7024
|
-
}, [$,
|
|
7025
|
-
p.current && (p.current.stopSpeaking(), p.current.setSlowdownRate && p.current.setSlowdownRate(1),
|
|
7026
|
-
}, []), j =
|
|
7062
|
+
}, [$, M, v.lipsyncLang]), K = P(() => {
|
|
7063
|
+
p.current && (p.current.stopSpeaking(), p.current.setSlowdownRate && p.current.setSlowdownRate(1), k.current = null, pe(!1));
|
|
7064
|
+
}, []), j = P(() => {
|
|
7027
7065
|
if (p.current && p.current.pauseSpeaking) {
|
|
7028
7066
|
const L = p.current;
|
|
7029
7067
|
if (L.isSpeaking || L.audioPlaylist && L.audioPlaylist.length > 0 || L.speechQueue && L.speechQueue.length > 0) {
|
|
7030
7068
|
y.current && (clearInterval(y.current), y.current = null);
|
|
7031
|
-
let
|
|
7032
|
-
if (
|
|
7033
|
-
const J =
|
|
7034
|
-
if (ue > 0 && Se < J && (
|
|
7069
|
+
let D = "";
|
|
7070
|
+
if (k.current && O.current.length > 0) {
|
|
7071
|
+
const J = O.current.length, ge = L.speechQueue ? L.speechQueue.filter((Ae) => Ae && Ae.text && Array.isArray(Ae.text) && Ae.text.length > 0).length : 0, Y = L.audioPlaylist && L.audioPlaylist.length > 0, ue = ge + (Y ? 1 : 0), Se = J - ue;
|
|
7072
|
+
if (ue > 0 && Se < J && (D = O.current.slice(Se).join(". ").trim(), !D && ge > 0 && L.speechQueue)) {
|
|
7035
7073
|
const be = L.speechQueue.filter((ye) => ye && ye.text && Array.isArray(ye.text) && ye.text.length > 0).map((ye) => ye.text.map((ke) => ke.word || "").filter((ke) => ke.length > 0).join(" ")).filter((ye) => ye.length > 0).join(" ");
|
|
7036
|
-
be && be.trim() && (
|
|
7074
|
+
be && be.trim() && (D = be.trim());
|
|
7037
7075
|
}
|
|
7038
7076
|
}
|
|
7039
|
-
|
|
7040
|
-
remainingText:
|
|
7041
|
-
originalText:
|
|
7042
|
-
options:
|
|
7043
|
-
}), L.speechQueue && (L.speechQueue.length = 0), p.current.pauseSpeaking(),
|
|
7077
|
+
k.current && (E.current = {
|
|
7078
|
+
remainingText: D || null,
|
|
7079
|
+
originalText: k.current.text,
|
|
7080
|
+
options: k.current.options
|
|
7081
|
+
}), L.speechQueue && (L.speechQueue.length = 0), p.current.pauseSpeaking(), T.current = !0, pe(!0);
|
|
7044
7082
|
}
|
|
7045
7083
|
}
|
|
7046
|
-
}, []), q =
|
|
7084
|
+
}, []), q = P(async () => {
|
|
7047
7085
|
if (!p.current || !ae)
|
|
7048
7086
|
return;
|
|
7049
|
-
let L = "",
|
|
7050
|
-
if (
|
|
7051
|
-
L =
|
|
7052
|
-
else if (
|
|
7053
|
-
L =
|
|
7087
|
+
let L = "", B = {};
|
|
7088
|
+
if (E.current && E.current.remainingText)
|
|
7089
|
+
L = E.current.remainingText, B = E.current.options || {}, E.current = { remainingText: null, originalText: null, options: null };
|
|
7090
|
+
else if (k.current && k.current.text)
|
|
7091
|
+
L = k.current.text, B = k.current.options || {};
|
|
7054
7092
|
else {
|
|
7055
|
-
console.warn("Resume called but no paused speech found"), pe(!1),
|
|
7093
|
+
console.warn("Resume called but no paused speech found"), pe(!1), T.current = !1;
|
|
7056
7094
|
return;
|
|
7057
7095
|
}
|
|
7058
|
-
pe(!1),
|
|
7059
|
-
const
|
|
7060
|
-
...
|
|
7061
|
-
lipsyncLang:
|
|
7096
|
+
pe(!1), T.current = !1, await M();
|
|
7097
|
+
const D = {
|
|
7098
|
+
...B,
|
|
7099
|
+
lipsyncLang: B.lipsyncLang || v.lipsyncLang || "en"
|
|
7062
7100
|
};
|
|
7063
7101
|
try {
|
|
7064
|
-
await
|
|
7102
|
+
await W(L, D);
|
|
7065
7103
|
} catch (J) {
|
|
7066
|
-
console.error("Error resuming speech:", J), pe(!1),
|
|
7104
|
+
console.error("Error resuming speech:", J), pe(!1), T.current = !1;
|
|
7067
7105
|
}
|
|
7068
|
-
}, [
|
|
7106
|
+
}, [M, ae, W, v]), Le = P((L) => {
|
|
7069
7107
|
p.current && p.current.setMood(L);
|
|
7070
|
-
}, []), we =
|
|
7108
|
+
}, []), we = P((L) => {
|
|
7071
7109
|
p.current && p.current.setSlowdownRate && p.current.setSlowdownRate(L);
|
|
7072
|
-
}, []), C =
|
|
7110
|
+
}, []), C = P((L, B = !1) => {
|
|
7073
7111
|
if (p.current && p.current.playAnimation) {
|
|
7074
|
-
if (
|
|
7112
|
+
if (f && f[L] && (L = f[L]), p.current.setShowFullAvatar)
|
|
7075
7113
|
try {
|
|
7076
|
-
p.current.setShowFullAvatar(
|
|
7114
|
+
p.current.setShowFullAvatar(H.current);
|
|
7077
7115
|
} catch (J) {
|
|
7078
7116
|
console.warn("Error setting full body mode:", J);
|
|
7079
7117
|
}
|
|
7080
7118
|
if (L.includes("."))
|
|
7081
7119
|
try {
|
|
7082
|
-
p.current.playAnimation(L, null, 10, 0, 0.01,
|
|
7120
|
+
p.current.playAnimation(L, null, 10, 0, 0.01, B);
|
|
7083
7121
|
} catch (J) {
|
|
7084
7122
|
console.warn(`Failed to play ${L}:`, J);
|
|
7085
7123
|
try {
|
|
@@ -7093,7 +7131,7 @@ const Ve = Me(({
|
|
|
7093
7131
|
let ge = !1;
|
|
7094
7132
|
for (const Y of J)
|
|
7095
7133
|
try {
|
|
7096
|
-
p.current.playAnimation(L + Y, null, 10, 0, 0.01,
|
|
7134
|
+
p.current.playAnimation(L + Y, null, 10, 0, 0.01, B), ge = !0;
|
|
7097
7135
|
break;
|
|
7098
7136
|
} catch {
|
|
7099
7137
|
}
|
|
@@ -7107,35 +7145,35 @@ const Ve = Me(({
|
|
|
7107
7145
|
}
|
|
7108
7146
|
}
|
|
7109
7147
|
}
|
|
7110
|
-
}, [
|
|
7148
|
+
}, [f]), ne = P(() => {
|
|
7111
7149
|
p.current && p.current.onResize && p.current.onResize();
|
|
7112
7150
|
}, []);
|
|
7113
|
-
return Ee(
|
|
7114
|
-
speakText:
|
|
7151
|
+
return Ee(R, () => ({
|
|
7152
|
+
speakText: W,
|
|
7115
7153
|
stopSpeaking: K,
|
|
7116
7154
|
pauseSpeaking: j,
|
|
7117
7155
|
resumeSpeaking: q,
|
|
7118
|
-
resumeAudioContext:
|
|
7156
|
+
resumeAudioContext: M,
|
|
7119
7157
|
setMood: Le,
|
|
7120
7158
|
setTimingAdjustment: we,
|
|
7121
7159
|
playAnimation: C,
|
|
7122
7160
|
isReady: $,
|
|
7123
7161
|
isPaused: ae,
|
|
7124
7162
|
talkingHead: p.current,
|
|
7125
|
-
handleResize:
|
|
7163
|
+
handleResize: ne,
|
|
7126
7164
|
setBodyMovement: (L) => {
|
|
7127
7165
|
if (p.current && p.current.setShowFullAvatar && p.current.setBodyMovement)
|
|
7128
7166
|
try {
|
|
7129
|
-
p.current.setShowFullAvatar(
|
|
7130
|
-
} catch (
|
|
7131
|
-
console.warn("Error setting body movement:",
|
|
7167
|
+
p.current.setShowFullAvatar(H.current), p.current.setBodyMovement(L);
|
|
7168
|
+
} catch (B) {
|
|
7169
|
+
console.warn("Error setting body movement:", B);
|
|
7132
7170
|
}
|
|
7133
7171
|
},
|
|
7134
7172
|
setMovementIntensity: (L) => p.current?.setMovementIntensity(L),
|
|
7135
7173
|
playRandomDance: () => {
|
|
7136
7174
|
if (p.current && p.current.setShowFullAvatar && p.current.playRandomDance)
|
|
7137
7175
|
try {
|
|
7138
|
-
p.current.setShowFullAvatar(
|
|
7176
|
+
p.current.setShowFullAvatar(H.current), p.current.playRandomDance();
|
|
7139
7177
|
} catch (L) {
|
|
7140
7178
|
console.warn("Error playing random dance:", L);
|
|
7141
7179
|
}
|
|
@@ -7143,15 +7181,15 @@ const Ve = Me(({
|
|
|
7143
7181
|
playReaction: (L) => {
|
|
7144
7182
|
if (p.current && p.current.setShowFullAvatar && p.current.playReaction)
|
|
7145
7183
|
try {
|
|
7146
|
-
p.current.setShowFullAvatar(
|
|
7147
|
-
} catch (
|
|
7148
|
-
console.warn("Error playing reaction:",
|
|
7184
|
+
p.current.setShowFullAvatar(H.current), p.current.playReaction(L);
|
|
7185
|
+
} catch (B) {
|
|
7186
|
+
console.warn("Error playing reaction:", B);
|
|
7149
7187
|
}
|
|
7150
7188
|
},
|
|
7151
7189
|
playCelebration: () => {
|
|
7152
7190
|
if (p.current && p.current.setShowFullAvatar && p.current.playCelebration)
|
|
7153
7191
|
try {
|
|
7154
|
-
p.current.setShowFullAvatar(
|
|
7192
|
+
p.current.setShowFullAvatar(H.current), p.current.playCelebration();
|
|
7155
7193
|
} catch (L) {
|
|
7156
7194
|
console.warn("Error playing celebration:", L);
|
|
7157
7195
|
}
|
|
@@ -7159,9 +7197,9 @@ const Ve = Me(({
|
|
|
7159
7197
|
setShowFullAvatar: (L) => {
|
|
7160
7198
|
if (p.current && p.current.setShowFullAvatar)
|
|
7161
7199
|
try {
|
|
7162
|
-
|
|
7163
|
-
} catch (
|
|
7164
|
-
console.warn("Error setting showFullAvatar:",
|
|
7200
|
+
H.current = L, p.current.setShowFullAvatar(L);
|
|
7201
|
+
} catch (B) {
|
|
7202
|
+
console.warn("Error setting showFullAvatar:", B);
|
|
7165
7203
|
}
|
|
7166
7204
|
},
|
|
7167
7205
|
lockAvatarPosition: () => {
|
|
@@ -7194,7 +7232,7 @@ const Ve = Me(({
|
|
|
7194
7232
|
/* @__PURE__ */ me(
|
|
7195
7233
|
"div",
|
|
7196
7234
|
{
|
|
7197
|
-
ref:
|
|
7235
|
+
ref: F,
|
|
7198
7236
|
className: "talking-head-viewer",
|
|
7199
7237
|
style: {
|
|
7200
7238
|
width: "100%",
|
|
@@ -7230,7 +7268,7 @@ const Ve = Me(({
|
|
|
7230
7268
|
});
|
|
7231
7269
|
Ve.displayName = "TalkingHeadAvatar";
|
|
7232
7270
|
const pt = Me(({
|
|
7233
|
-
text:
|
|
7271
|
+
text: Z = "Hello! I'm a talking avatar. How are you today?",
|
|
7234
7272
|
onLoading: t = () => {
|
|
7235
7273
|
},
|
|
7236
7274
|
onError: e = () => {
|
|
@@ -7241,23 +7279,23 @@ const pt = Me(({
|
|
|
7241
7279
|
style: s = {},
|
|
7242
7280
|
avatarConfig: o = {}
|
|
7243
7281
|
}, l) => {
|
|
7244
|
-
const u =
|
|
7282
|
+
const u = N(null), r = N(null), [h, a] = ce(!0), [c, d] = ce(null), [g, x] = ce(!1), f = Fe(), R = o.ttsService || f.service, F = R === "browser" ? {
|
|
7245
7283
|
endpoint: "",
|
|
7246
7284
|
apiKey: null,
|
|
7247
7285
|
defaultVoice: "Google US English"
|
|
7248
7286
|
} : {
|
|
7249
|
-
...
|
|
7287
|
+
...f,
|
|
7250
7288
|
// Override API key if provided via avatarConfig
|
|
7251
|
-
apiKey: o.ttsApiKey !== void 0 && o.ttsApiKey !== null ? o.ttsApiKey :
|
|
7289
|
+
apiKey: o.ttsApiKey !== void 0 && o.ttsApiKey !== null ? o.ttsApiKey : f.apiKey,
|
|
7252
7290
|
// Override endpoint for ElevenLabs if service is explicitly set
|
|
7253
|
-
endpoint:
|
|
7291
|
+
endpoint: R === "elevenlabs" && o.ttsApiKey ? "https://api.elevenlabs.io/v1/text-to-speech" : f.endpoint
|
|
7254
7292
|
}, p = {
|
|
7255
7293
|
url: "/avatars/brunette.glb",
|
|
7256
7294
|
// Use brunette avatar (working glTF file)
|
|
7257
7295
|
body: "F",
|
|
7258
7296
|
avatarMood: "neutral",
|
|
7259
|
-
ttsLang:
|
|
7260
|
-
ttsVoice: o.ttsVoice ||
|
|
7297
|
+
ttsLang: R === "browser" ? "en-US" : "en",
|
|
7298
|
+
ttsVoice: o.ttsVoice || F.defaultVoice,
|
|
7261
7299
|
lipsyncLang: "en",
|
|
7262
7300
|
// English lip-sync
|
|
7263
7301
|
showFullAvatar: !0,
|
|
@@ -7265,16 +7303,16 @@ const pt = Me(({
|
|
|
7265
7303
|
bodyMovement: "idle",
|
|
7266
7304
|
movementIntensity: 0.5,
|
|
7267
7305
|
...o
|
|
7268
|
-
},
|
|
7269
|
-
ttsEndpoint:
|
|
7270
|
-
ttsApikey:
|
|
7271
|
-
ttsService:
|
|
7306
|
+
}, H = {
|
|
7307
|
+
ttsEndpoint: F.endpoint,
|
|
7308
|
+
ttsApikey: F.apiKey,
|
|
7309
|
+
ttsService: R,
|
|
7272
7310
|
lipsyncModules: ["en"],
|
|
7273
7311
|
cameraView: "upper"
|
|
7274
|
-
},
|
|
7312
|
+
}, k = P(async () => {
|
|
7275
7313
|
if (!(!u.current || r.current))
|
|
7276
7314
|
try {
|
|
7277
|
-
if (a(!0), d(null), r.current = new Be(u.current,
|
|
7315
|
+
if (a(!0), d(null), r.current = new Be(u.current, H), await r.current.showAvatar(p, (_) => {
|
|
7278
7316
|
if (_.lengthComputable) {
|
|
7279
7317
|
const X = Math.min(100, Math.round(_.loaded / _.total * 100));
|
|
7280
7318
|
t(X);
|
|
@@ -7297,37 +7335,37 @@ const pt = Me(({
|
|
|
7297
7335
|
console.warn("Error setting full body mode on initialization:", _);
|
|
7298
7336
|
}
|
|
7299
7337
|
a(!1), x(!0), n(r.current);
|
|
7300
|
-
const
|
|
7338
|
+
const G = () => {
|
|
7301
7339
|
document.visibilityState === "visible" ? r.current?.start() : r.current?.stop();
|
|
7302
7340
|
};
|
|
7303
|
-
return document.addEventListener("visibilitychange",
|
|
7304
|
-
document.removeEventListener("visibilitychange",
|
|
7341
|
+
return document.addEventListener("visibilitychange", G), () => {
|
|
7342
|
+
document.removeEventListener("visibilitychange", G);
|
|
7305
7343
|
};
|
|
7306
7344
|
} catch (S) {
|
|
7307
7345
|
console.error("Error initializing TalkingHead:", S), d(S.message || "Failed to initialize avatar"), a(!1), e(S);
|
|
7308
7346
|
}
|
|
7309
7347
|
}, []);
|
|
7310
|
-
de(() => (
|
|
7348
|
+
de(() => (k(), () => {
|
|
7311
7349
|
r.current && (r.current.stop(), r.current.dispose(), r.current = null);
|
|
7312
|
-
}), [
|
|
7313
|
-
const y =
|
|
7350
|
+
}), [k]);
|
|
7351
|
+
const y = P((S) => {
|
|
7314
7352
|
if (r.current && g)
|
|
7315
7353
|
try {
|
|
7316
7354
|
console.log("Speaking text:", S), console.log("Avatar config:", p), console.log("TalkingHead instance:", r.current), r.current.lipsync && Object.keys(r.current.lipsync).length > 0 ? (console.log("Lip-sync modules loaded:", Object.keys(r.current.lipsync)), r.current.setSlowdownRate && (r.current.setSlowdownRate(1.05), console.log("Applied timing adjustment for better lip-sync")), r.current.speakText(S)) : (console.warn("Lip-sync modules not ready, waiting..."), setTimeout(() => {
|
|
7317
7355
|
r.current && r.current.lipsync ? (console.log("Lip-sync now ready, speaking..."), r.current.setSlowdownRate && (r.current.setSlowdownRate(1.05), console.log("Applied timing adjustment for better lip-sync")), r.current.speakText(S)) : console.error("Lip-sync still not ready after waiting");
|
|
7318
7356
|
}, 500));
|
|
7319
|
-
} catch (
|
|
7320
|
-
console.error("Error speaking text:",
|
|
7357
|
+
} catch (G) {
|
|
7358
|
+
console.error("Error speaking text:", G), d(G.message || "Failed to speak text");
|
|
7321
7359
|
}
|
|
7322
7360
|
else
|
|
7323
7361
|
console.warn("Avatar not ready for speaking. isReady:", g, "talkingHeadRef:", !!r.current);
|
|
7324
|
-
}, [g, p]),
|
|
7362
|
+
}, [g, p]), T = P(() => {
|
|
7325
7363
|
r.current && (r.current.stopSpeaking(), r.current.setSlowdownRate && (r.current.setSlowdownRate(1), console.log("Reset timing to normal")));
|
|
7326
|
-
}, []),
|
|
7364
|
+
}, []), E = P((S) => {
|
|
7327
7365
|
r.current && r.current.setMood(S);
|
|
7328
|
-
}, []),
|
|
7366
|
+
}, []), O = P((S) => {
|
|
7329
7367
|
r.current && r.current.setSlowdownRate && (r.current.setSlowdownRate(S), console.log("Timing adjustment set to:", S));
|
|
7330
|
-
}, []),
|
|
7368
|
+
}, []), te = P((S, G = !1) => {
|
|
7331
7369
|
if (r.current && r.current.playAnimation) {
|
|
7332
7370
|
if (r.current.setShowFullAvatar)
|
|
7333
7371
|
try {
|
|
@@ -7337,7 +7375,7 @@ const pt = Me(({
|
|
|
7337
7375
|
}
|
|
7338
7376
|
if (S.includes("."))
|
|
7339
7377
|
try {
|
|
7340
|
-
r.current.playAnimation(S, null, 10, 0, 0.01,
|
|
7378
|
+
r.current.playAnimation(S, null, 10, 0, 0.01, G), console.log("Playing animation:", S);
|
|
7341
7379
|
} catch (X) {
|
|
7342
7380
|
console.log(`Failed to play ${S}:`, X);
|
|
7343
7381
|
try {
|
|
@@ -7351,7 +7389,7 @@ const pt = Me(({
|
|
|
7351
7389
|
let $ = !1;
|
|
7352
7390
|
for (const se of X)
|
|
7353
7391
|
try {
|
|
7354
|
-
r.current.playAnimation(S + se, null, 10, 0, 0.01,
|
|
7392
|
+
r.current.playAnimation(S + se, null, 10, 0, 0.01, G), console.log("Playing animation:", S + se), $ = !0;
|
|
7355
7393
|
break;
|
|
7356
7394
|
} catch {
|
|
7357
7395
|
console.log(`Failed to play ${S}${se}, trying next format...`);
|
|
@@ -7370,18 +7408,18 @@ const pt = Me(({
|
|
|
7370
7408
|
}, []);
|
|
7371
7409
|
return Ee(l, () => ({
|
|
7372
7410
|
speakText: y,
|
|
7373
|
-
stopSpeaking:
|
|
7374
|
-
setMood:
|
|
7375
|
-
setTimingAdjustment:
|
|
7376
|
-
playAnimation:
|
|
7411
|
+
stopSpeaking: T,
|
|
7412
|
+
setMood: E,
|
|
7413
|
+
setTimingAdjustment: O,
|
|
7414
|
+
playAnimation: te,
|
|
7377
7415
|
isReady: g,
|
|
7378
7416
|
talkingHead: r.current,
|
|
7379
7417
|
setBodyMovement: (S) => {
|
|
7380
7418
|
if (r.current && r.current.setShowFullAvatar && r.current.setBodyMovement)
|
|
7381
7419
|
try {
|
|
7382
7420
|
r.current.setShowFullAvatar(!0), r.current.setBodyMovement(S), console.log("Body movement set with full body mode:", S);
|
|
7383
|
-
} catch (
|
|
7384
|
-
console.warn("Error setting body movement:",
|
|
7421
|
+
} catch (G) {
|
|
7422
|
+
console.warn("Error setting body movement:", G);
|
|
7385
7423
|
}
|
|
7386
7424
|
},
|
|
7387
7425
|
setMovementIntensity: (S) => r.current?.setMovementIntensity(S),
|
|
@@ -7397,8 +7435,8 @@ const pt = Me(({
|
|
|
7397
7435
|
if (r.current && r.current.setShowFullAvatar && r.current.playReaction)
|
|
7398
7436
|
try {
|
|
7399
7437
|
r.current.setShowFullAvatar(!0), r.current.playReaction(S), console.log("Reaction played with full body mode:", S);
|
|
7400
|
-
} catch (
|
|
7401
|
-
console.warn("Error playing reaction:",
|
|
7438
|
+
} catch (G) {
|
|
7439
|
+
console.warn("Error playing reaction:", G);
|
|
7402
7440
|
}
|
|
7403
7441
|
},
|
|
7404
7442
|
playCelebration: () => {
|
|
@@ -7413,8 +7451,8 @@ const pt = Me(({
|
|
|
7413
7451
|
if (r.current && r.current.setShowFullAvatar)
|
|
7414
7452
|
try {
|
|
7415
7453
|
r.current.setShowFullAvatar(S), console.log("Show full avatar set to:", S);
|
|
7416
|
-
} catch (
|
|
7417
|
-
console.warn("Error setting showFullAvatar:",
|
|
7454
|
+
} catch (G) {
|
|
7455
|
+
console.warn("Error setting showFullAvatar:", G);
|
|
7418
7456
|
}
|
|
7419
7457
|
},
|
|
7420
7458
|
lockAvatarPosition: () => {
|
|
@@ -7471,7 +7509,7 @@ const pt = Me(({
|
|
|
7471
7509
|
});
|
|
7472
7510
|
pt.displayName = "TalkingHeadComponent";
|
|
7473
7511
|
const gt = Me(({
|
|
7474
|
-
text:
|
|
7512
|
+
text: Z = null,
|
|
7475
7513
|
avatarUrl: t = "/avatars/brunette.glb",
|
|
7476
7514
|
avatarBody: e = "F",
|
|
7477
7515
|
mood: n = "neutral",
|
|
@@ -7491,66 +7529,66 @@ const gt = Me(({
|
|
|
7491
7529
|
},
|
|
7492
7530
|
onSpeechEnd: x = () => {
|
|
7493
7531
|
},
|
|
7494
|
-
className:
|
|
7495
|
-
style:
|
|
7496
|
-
animations:
|
|
7532
|
+
className: f = "",
|
|
7533
|
+
style: R = {},
|
|
7534
|
+
animations: F = {},
|
|
7497
7535
|
autoSpeak: p = !1
|
|
7498
|
-
},
|
|
7499
|
-
const
|
|
7536
|
+
}, H) => {
|
|
7537
|
+
const k = N(null), y = N(null), T = N(h), E = N(null), O = N(null), te = N(!1), S = N({ remainingText: null, originalText: null, options: null }), G = N([]), [_, X] = ce(!0), [$, se] = ce(null), [ae, pe] = ce(!1), [ee, le] = ce(!1);
|
|
7500
7538
|
de(() => {
|
|
7501
|
-
|
|
7539
|
+
te.current = ee;
|
|
7502
7540
|
}, [ee]), de(() => {
|
|
7503
|
-
|
|
7541
|
+
T.current = h;
|
|
7504
7542
|
}, [h]);
|
|
7505
|
-
const
|
|
7506
|
-
let
|
|
7507
|
-
v === "browser" ?
|
|
7543
|
+
const U = Fe(), v = s || U.service;
|
|
7544
|
+
let I;
|
|
7545
|
+
v === "browser" ? I = {
|
|
7508
7546
|
service: "browser",
|
|
7509
7547
|
endpoint: "",
|
|
7510
7548
|
apiKey: null,
|
|
7511
7549
|
defaultVoice: "Google US English"
|
|
7512
|
-
} : v === "elevenlabs" ?
|
|
7550
|
+
} : v === "elevenlabs" ? I = {
|
|
7513
7551
|
service: "elevenlabs",
|
|
7514
7552
|
endpoint: "https://api.elevenlabs.io/v1/text-to-speech",
|
|
7515
|
-
apiKey: l ||
|
|
7516
|
-
defaultVoice: o ||
|
|
7517
|
-
voices:
|
|
7518
|
-
} : v === "deepgram" ?
|
|
7553
|
+
apiKey: l || U.apiKey,
|
|
7554
|
+
defaultVoice: o || U.defaultVoice || Ie.defaultVoice,
|
|
7555
|
+
voices: U.voices || Ie.voices
|
|
7556
|
+
} : v === "deepgram" ? I = {
|
|
7519
7557
|
service: "deepgram",
|
|
7520
7558
|
endpoint: "https://api.deepgram.com/v1/speak",
|
|
7521
|
-
apiKey: l ||
|
|
7522
|
-
defaultVoice: o ||
|
|
7523
|
-
voices:
|
|
7524
|
-
} :
|
|
7525
|
-
...
|
|
7526
|
-
apiKey: l !== null ? l :
|
|
7559
|
+
apiKey: l || U.apiKey,
|
|
7560
|
+
defaultVoice: o || U.defaultVoice || Te.defaultVoice,
|
|
7561
|
+
voices: U.voices || Te.voices
|
|
7562
|
+
} : I = {
|
|
7563
|
+
...U,
|
|
7564
|
+
apiKey: l !== null ? l : U.apiKey
|
|
7527
7565
|
};
|
|
7528
|
-
const
|
|
7566
|
+
const w = {
|
|
7529
7567
|
url: t,
|
|
7530
7568
|
body: e,
|
|
7531
7569
|
avatarMood: n,
|
|
7532
7570
|
ttsLang: v === "browser" ? "en-US" : i,
|
|
7533
|
-
ttsVoice: o ||
|
|
7571
|
+
ttsVoice: o || I.defaultVoice,
|
|
7534
7572
|
lipsyncLang: "en",
|
|
7535
7573
|
showFullAvatar: h,
|
|
7536
7574
|
bodyMovement: u,
|
|
7537
7575
|
movementIntensity: r
|
|
7538
|
-
},
|
|
7539
|
-
ttsEndpoint:
|
|
7540
|
-
ttsApikey:
|
|
7576
|
+
}, M = {
|
|
7577
|
+
ttsEndpoint: I.endpoint,
|
|
7578
|
+
ttsApikey: I.apiKey,
|
|
7541
7579
|
ttsService: v,
|
|
7542
7580
|
lipsyncModules: ["en"],
|
|
7543
7581
|
cameraView: a
|
|
7544
|
-
},
|
|
7545
|
-
if (!(!
|
|
7582
|
+
}, W = P(async () => {
|
|
7583
|
+
if (!(!k.current || y.current))
|
|
7546
7584
|
try {
|
|
7547
|
-
X(!0), se(null), y.current = new Be(
|
|
7548
|
-
url:
|
|
7549
|
-
body:
|
|
7550
|
-
avatarMood:
|
|
7551
|
-
}), await y.current.showAvatar(
|
|
7552
|
-
if (
|
|
7553
|
-
const L = Math.min(100, Math.round(
|
|
7585
|
+
X(!0), se(null), y.current = new Be(k.current, M), console.log("Avatar config being passed:", {
|
|
7586
|
+
url: w.url,
|
|
7587
|
+
body: w.body,
|
|
7588
|
+
avatarMood: w.avatarMood
|
|
7589
|
+
}), await y.current.showAvatar(w, (ne) => {
|
|
7590
|
+
if (ne.lengthComputable) {
|
|
7591
|
+
const L = Math.min(100, Math.round(ne.loaded / ne.total * 100));
|
|
7554
7592
|
d(L);
|
|
7555
7593
|
}
|
|
7556
7594
|
}), y.current?.avatar && console.log("Avatar body after initialization:", y.current.avatar.body), X(!1), pe(!0), c(y.current);
|
|
@@ -7564,10 +7602,10 @@ const gt = Me(({
|
|
|
7564
7602
|
console.error("Error initializing TalkingHead:", C), se(C.message || "Failed to initialize avatar"), X(!1), g(C);
|
|
7565
7603
|
}
|
|
7566
7604
|
}, []);
|
|
7567
|
-
de(() => (
|
|
7605
|
+
de(() => (W(), () => {
|
|
7568
7606
|
y.current && (y.current.stop(), y.current.dispose(), y.current = null);
|
|
7569
|
-
}), [
|
|
7570
|
-
const K =
|
|
7607
|
+
}), [W]);
|
|
7608
|
+
const K = P(async () => {
|
|
7571
7609
|
if (y.current)
|
|
7572
7610
|
try {
|
|
7573
7611
|
const C = y.current.audioCtx || y.current.audioContext;
|
|
@@ -7575,7 +7613,7 @@ const gt = Me(({
|
|
|
7575
7613
|
} catch (C) {
|
|
7576
7614
|
console.warn("Failed to resume audio context:", C);
|
|
7577
7615
|
}
|
|
7578
|
-
}, []), j =
|
|
7616
|
+
}, []), j = P(async (C, ne = {}) => {
|
|
7579
7617
|
if (!y.current || !ae) {
|
|
7580
7618
|
console.warn("Avatar not ready for speaking");
|
|
7581
7619
|
return;
|
|
@@ -7584,53 +7622,53 @@ const gt = Me(({
|
|
|
7584
7622
|
console.warn("No text provided to speak");
|
|
7585
7623
|
return;
|
|
7586
7624
|
}
|
|
7587
|
-
await K(), S.current = { remainingText: null, originalText: null, options: null },
|
|
7588
|
-
const L = C.split(/[.!?]+/).filter((
|
|
7589
|
-
|
|
7590
|
-
const
|
|
7591
|
-
lipsyncLang:
|
|
7625
|
+
await K(), S.current = { remainingText: null, originalText: null, options: null }, G.current = [], E.current = { text: C, options: ne }, O.current && (clearInterval(O.current), O.current = null), le(!1), te.current = !1;
|
|
7626
|
+
const L = C.split(/[.!?]+/).filter((D) => D.trim().length > 0);
|
|
7627
|
+
G.current = L;
|
|
7628
|
+
const B = {
|
|
7629
|
+
lipsyncLang: ne.lipsyncLang || "en",
|
|
7592
7630
|
onSpeechEnd: () => {
|
|
7593
|
-
|
|
7631
|
+
O.current && (clearInterval(O.current), O.current = null), ne.onSpeechEnd && ne.onSpeechEnd(), x();
|
|
7594
7632
|
}
|
|
7595
7633
|
};
|
|
7596
7634
|
try {
|
|
7597
|
-
y.current.speakText(C,
|
|
7598
|
-
} catch (
|
|
7599
|
-
console.error("Error speaking text:",
|
|
7635
|
+
y.current.speakText(C, B);
|
|
7636
|
+
} catch (D) {
|
|
7637
|
+
console.error("Error speaking text:", D), se(D.message || "Failed to speak text");
|
|
7600
7638
|
}
|
|
7601
7639
|
}, [ae, x, K]);
|
|
7602
7640
|
de(() => {
|
|
7603
|
-
ae &&
|
|
7604
|
-
}, [ae,
|
|
7605
|
-
const q =
|
|
7641
|
+
ae && Z && p && y.current && j(Z);
|
|
7642
|
+
}, [ae, Z, p, j]);
|
|
7643
|
+
const q = P(() => {
|
|
7606
7644
|
if (y.current)
|
|
7607
7645
|
try {
|
|
7608
|
-
const C = y.current.isSpeaking || !1,
|
|
7609
|
-
if (C ||
|
|
7610
|
-
|
|
7611
|
-
let
|
|
7612
|
-
L.length > 0 && (
|
|
7613
|
-
remainingText:
|
|
7614
|
-
originalText:
|
|
7615
|
-
options:
|
|
7616
|
-
}, y.current.speechQueue.length = 0, y.current.pauseSpeaking(), le(!0),
|
|
7646
|
+
const C = y.current.isSpeaking || !1, ne = y.current.audioPlaylist || [], L = y.current.speechQueue || [];
|
|
7647
|
+
if (C || ne.length > 0 || L.length > 0) {
|
|
7648
|
+
O.current && (clearInterval(O.current), O.current = null);
|
|
7649
|
+
let B = "";
|
|
7650
|
+
L.length > 0 && (B = L.map((D) => D.text && Array.isArray(D.text) ? D.text.map((J) => J.word).join(" ") : D.text || "").join(" ")), S.current = {
|
|
7651
|
+
remainingText: B || null,
|
|
7652
|
+
originalText: E.current?.text || null,
|
|
7653
|
+
options: E.current?.options || null
|
|
7654
|
+
}, y.current.speechQueue.length = 0, y.current.pauseSpeaking(), le(!0), te.current = !0;
|
|
7617
7655
|
}
|
|
7618
7656
|
} catch (C) {
|
|
7619
7657
|
console.warn("Error pausing speech:", C);
|
|
7620
7658
|
}
|
|
7621
|
-
}, []), Le =
|
|
7659
|
+
}, []), Le = P(async () => {
|
|
7622
7660
|
if (!(!y.current || !ee))
|
|
7623
7661
|
try {
|
|
7624
|
-
await K(), le(!1),
|
|
7625
|
-
const C = S.current?.remainingText,
|
|
7626
|
-
|
|
7662
|
+
await K(), le(!1), te.current = !1;
|
|
7663
|
+
const C = S.current?.remainingText, ne = S.current?.originalText || E.current?.text, L = S.current?.options || E.current?.options || {}, B = C || ne;
|
|
7664
|
+
B && j(B, L);
|
|
7627
7665
|
} catch (C) {
|
|
7628
|
-
console.warn("Error resuming speech:", C), le(!1),
|
|
7666
|
+
console.warn("Error resuming speech:", C), le(!1), te.current = !1;
|
|
7629
7667
|
}
|
|
7630
|
-
}, [ee, j, K]), we =
|
|
7631
|
-
y.current && (y.current.stopSpeaking(),
|
|
7668
|
+
}, [ee, j, K]), we = P(() => {
|
|
7669
|
+
y.current && (y.current.stopSpeaking(), O.current && (clearInterval(O.current), O.current = null), le(!1), te.current = !1);
|
|
7632
7670
|
}, []);
|
|
7633
|
-
return Ee(
|
|
7671
|
+
return Ee(H, () => ({
|
|
7634
7672
|
speakText: j,
|
|
7635
7673
|
pauseSpeaking: q,
|
|
7636
7674
|
resumeSpeaking: Le,
|
|
@@ -7641,21 +7679,21 @@ const gt = Me(({
|
|
|
7641
7679
|
setBodyMovement: (C) => {
|
|
7642
7680
|
y.current && y.current.setBodyMovement(C);
|
|
7643
7681
|
},
|
|
7644
|
-
playAnimation: (C,
|
|
7645
|
-
y.current && y.current.playAnimation && y.current.playAnimation(C, null, 10, 0, 0.01,
|
|
7682
|
+
playAnimation: (C, ne = !1) => {
|
|
7683
|
+
y.current && y.current.playAnimation && y.current.playAnimation(C, null, 10, 0, 0.01, ne);
|
|
7646
7684
|
},
|
|
7647
7685
|
playReaction: (C) => y.current?.playReaction(C),
|
|
7648
7686
|
playCelebration: () => y.current?.playCelebration(),
|
|
7649
7687
|
setShowFullAvatar: (C) => {
|
|
7650
|
-
y.current && (
|
|
7688
|
+
y.current && (T.current = C, y.current.setShowFullAvatar(C));
|
|
7651
7689
|
},
|
|
7652
7690
|
isReady: ae,
|
|
7653
7691
|
talkingHead: y.current
|
|
7654
|
-
})), /* @__PURE__ */ Pe("div", { className: `simple-talking-avatar-container ${
|
|
7692
|
+
})), /* @__PURE__ */ Pe("div", { className: `simple-talking-avatar-container ${f}`, style: R, children: [
|
|
7655
7693
|
/* @__PURE__ */ me(
|
|
7656
7694
|
"div",
|
|
7657
7695
|
{
|
|
7658
|
-
ref:
|
|
7696
|
+
ref: k,
|
|
7659
7697
|
className: "talking-head-viewer",
|
|
7660
7698
|
style: {
|
|
7661
7699
|
width: "100%",
|
|
@@ -7689,7 +7727,7 @@ const gt = Me(({
|
|
|
7689
7727
|
});
|
|
7690
7728
|
gt.displayName = "SimpleTalkingAvatar";
|
|
7691
7729
|
const yt = Me(({
|
|
7692
|
-
curriculumData:
|
|
7730
|
+
curriculumData: Z = null,
|
|
7693
7731
|
avatarConfig: t = {},
|
|
7694
7732
|
animations: e = {},
|
|
7695
7733
|
onLessonStart: n = () => {
|
|
@@ -7704,7 +7742,7 @@ const yt = Me(({
|
|
|
7704
7742
|
},
|
|
7705
7743
|
autoStart: u = !1
|
|
7706
7744
|
}, r) => {
|
|
7707
|
-
const h =
|
|
7745
|
+
const h = N(null), a = N({
|
|
7708
7746
|
currentModuleIndex: 0,
|
|
7709
7747
|
currentLessonIndex: 0,
|
|
7710
7748
|
currentQuestionIndex: 0,
|
|
@@ -7714,18 +7752,18 @@ const yt = Me(({
|
|
|
7714
7752
|
curriculumCompleted: !1,
|
|
7715
7753
|
score: 0,
|
|
7716
7754
|
totalQuestions: 0
|
|
7717
|
-
}), c =
|
|
7755
|
+
}), c = N({
|
|
7718
7756
|
onLessonStart: n,
|
|
7719
7757
|
onLessonComplete: i,
|
|
7720
7758
|
onQuestionAnswer: s,
|
|
7721
7759
|
onCurriculumComplete: o,
|
|
7722
7760
|
onCustomAction: l
|
|
7723
|
-
}), d =
|
|
7761
|
+
}), d = N(null), g = N(null), x = N(null), f = N(null), R = N(null), F = N(null), p = N(null), H = N(Z?.curriculum || {
|
|
7724
7762
|
title: "Default Curriculum",
|
|
7725
7763
|
description: "No curriculum data provided",
|
|
7726
7764
|
language: "en",
|
|
7727
7765
|
modules: []
|
|
7728
|
-
}),
|
|
7766
|
+
}), k = N({
|
|
7729
7767
|
avatarUrl: t.avatarUrl || "/avatars/brunette.glb",
|
|
7730
7768
|
avatarBody: t.avatarBody || "F",
|
|
7731
7769
|
mood: t.mood || "happy",
|
|
@@ -7748,12 +7786,12 @@ const yt = Me(({
|
|
|
7748
7786
|
onCustomAction: l
|
|
7749
7787
|
};
|
|
7750
7788
|
}, [n, i, s, o, l]), de(() => {
|
|
7751
|
-
|
|
7789
|
+
H.current = Z?.curriculum || {
|
|
7752
7790
|
title: "Default Curriculum",
|
|
7753
7791
|
description: "No curriculum data provided",
|
|
7754
7792
|
language: "en",
|
|
7755
7793
|
modules: []
|
|
7756
|
-
},
|
|
7794
|
+
}, k.current = {
|
|
7757
7795
|
avatarUrl: t.avatarUrl || "/avatars/brunette.glb",
|
|
7758
7796
|
avatarBody: t.avatarBody || "F",
|
|
7759
7797
|
mood: t.mood || "happy",
|
|
@@ -7767,12 +7805,12 @@ const yt = Me(({
|
|
|
7767
7805
|
animations: e,
|
|
7768
7806
|
lipsyncLang: "en"
|
|
7769
7807
|
};
|
|
7770
|
-
}, [
|
|
7771
|
-
const y =
|
|
7808
|
+
}, [Z, t, e]);
|
|
7809
|
+
const y = P(() => (H.current || { modules: [] }).modules[a.current.currentModuleIndex]?.lessons[a.current.currentLessonIndex], []), T = P(() => y()?.questions[a.current.currentQuestionIndex], [y]), E = P((v, I) => I.type === "multiple_choice" || I.type === "true_false" ? v === I.answer : I.type === "code_test" && typeof v == "object" && v !== null ? v.passed === !0 : !1, []), O = P(() => {
|
|
7772
7810
|
a.current.lessonCompleted = !0, a.current.isQuestionMode = !1;
|
|
7773
7811
|
const v = a.current.totalQuestions > 0 ? Math.round(a.current.score / a.current.totalQuestions * 100) : 100;
|
|
7774
|
-
let
|
|
7775
|
-
if (a.current.totalQuestions > 0 ?
|
|
7812
|
+
let I = "Congratulations! You've completed this lesson";
|
|
7813
|
+
if (a.current.totalQuestions > 0 ? I += ` You got ${a.current.score} correct out of ${a.current.totalQuestions} question${a.current.totalQuestions === 1 ? "" : "s"}, achieving a score of ${v} percent. ` : I += "! ", v >= 80 ? I += "Excellent work! You have a great understanding of this topic." : v >= 60 ? I += "Good job! You understand most of the concepts." : I += "Keep practicing! You're making progress.", c.current.onLessonComplete({
|
|
7776
7814
|
moduleIndex: a.current.currentModuleIndex,
|
|
7777
7815
|
lessonIndex: a.current.currentLessonIndex,
|
|
7778
7816
|
score: a.current.score,
|
|
@@ -7792,8 +7830,8 @@ const yt = Me(({
|
|
|
7792
7830
|
} catch {
|
|
7793
7831
|
h.current.playCelebration();
|
|
7794
7832
|
}
|
|
7795
|
-
const
|
|
7796
|
-
h.current.speakText(
|
|
7833
|
+
const w = H.current || { modules: [] }, M = w.modules[a.current.currentModuleIndex], W = a.current.currentLessonIndex < (M?.lessons?.length || 0) - 1, K = a.current.currentModuleIndex < (w.modules?.length || 0) - 1, j = W || K, q = k.current || { lipsyncLang: "en" };
|
|
7834
|
+
h.current.speakText(I, {
|
|
7797
7835
|
lipsyncLang: q.lipsyncLang,
|
|
7798
7836
|
onSpeechEnd: () => {
|
|
7799
7837
|
c.current.onCustomAction({
|
|
@@ -7808,12 +7846,12 @@ const yt = Me(({
|
|
|
7808
7846
|
}
|
|
7809
7847
|
});
|
|
7810
7848
|
}
|
|
7811
|
-
}, [e.lessonComplete]),
|
|
7849
|
+
}, [e.lessonComplete]), te = P(() => {
|
|
7812
7850
|
a.current.curriculumCompleted = !0;
|
|
7813
|
-
const v =
|
|
7851
|
+
const v = H.current || { modules: [] };
|
|
7814
7852
|
if (c.current.onCurriculumComplete({
|
|
7815
7853
|
modules: v.modules.length,
|
|
7816
|
-
totalLessons: v.modules.reduce((
|
|
7854
|
+
totalLessons: v.modules.reduce((I, w) => I + w.lessons.length, 0)
|
|
7817
7855
|
}), h.current) {
|
|
7818
7856
|
if (h.current.setMood("celebrating"), e.curriculumComplete)
|
|
7819
7857
|
try {
|
|
@@ -7821,99 +7859,99 @@ const yt = Me(({
|
|
|
7821
7859
|
} catch {
|
|
7822
7860
|
h.current.playCelebration();
|
|
7823
7861
|
}
|
|
7824
|
-
const
|
|
7825
|
-
h.current.speakText("Amazing! You've completed the entire curriculum! You're now ready to move on to more advanced topics. Well done!", { lipsyncLang:
|
|
7862
|
+
const I = k.current || { lipsyncLang: "en" };
|
|
7863
|
+
h.current.speakText("Amazing! You've completed the entire curriculum! You're now ready to move on to more advanced topics. Well done!", { lipsyncLang: I.lipsyncLang });
|
|
7826
7864
|
}
|
|
7827
|
-
}, [e.curriculumComplete]), S =
|
|
7865
|
+
}, [e.curriculumComplete]), S = P(() => {
|
|
7828
7866
|
const v = y();
|
|
7829
7867
|
a.current.isQuestionMode = !0, a.current.currentQuestionIndex = 0, a.current.totalQuestions = v?.questions?.length || 0, a.current.score = 0;
|
|
7830
|
-
const
|
|
7831
|
-
|
|
7868
|
+
const I = T();
|
|
7869
|
+
I && c.current.onCustomAction({
|
|
7832
7870
|
type: "questionStart",
|
|
7833
7871
|
moduleIndex: a.current.currentModuleIndex,
|
|
7834
7872
|
lessonIndex: a.current.currentLessonIndex,
|
|
7835
7873
|
questionIndex: a.current.currentQuestionIndex,
|
|
7836
7874
|
totalQuestions: a.current.totalQuestions,
|
|
7837
|
-
question:
|
|
7875
|
+
question: I,
|
|
7838
7876
|
score: a.current.score
|
|
7839
7877
|
});
|
|
7840
|
-
const
|
|
7841
|
-
if (!h.current || !
|
|
7878
|
+
const w = () => {
|
|
7879
|
+
if (!h.current || !I) return;
|
|
7842
7880
|
if (h.current.setMood("happy"), e.questionStart)
|
|
7843
7881
|
try {
|
|
7844
7882
|
h.current.playAnimation(e.questionStart, !0);
|
|
7845
|
-
} catch (
|
|
7846
|
-
console.warn("Failed to play questionStart animation:",
|
|
7883
|
+
} catch (W) {
|
|
7884
|
+
console.warn("Failed to play questionStart animation:", W);
|
|
7847
7885
|
}
|
|
7848
|
-
const
|
|
7849
|
-
|
|
7886
|
+
const M = k.current || { lipsyncLang: "en" };
|
|
7887
|
+
I.type === "code_test" ? h.current.speakText(`Let's test your coding skills! Here's your first challenge: ${I.question}`, { lipsyncLang: M.lipsyncLang }) : I.type === "multiple_choice" ? h.current.speakText(`Now let me ask you some questions. Here's the first one: ${I.question}`, { lipsyncLang: M.lipsyncLang }) : I.type === "true_false" ? h.current.speakText(`Let's start with some true or false questions. First question: ${I.question}`, { lipsyncLang: M.lipsyncLang }) : h.current.speakText(`Now let me ask you some questions. Here's the first one: ${I.question}`, { lipsyncLang: M.lipsyncLang });
|
|
7850
7888
|
};
|
|
7851
|
-
if (h.current && h.current.isReady &&
|
|
7852
|
-
|
|
7889
|
+
if (h.current && h.current.isReady && I)
|
|
7890
|
+
w();
|
|
7853
7891
|
else if (h.current && h.current.isReady) {
|
|
7854
|
-
const
|
|
7855
|
-
h.current.speakText("Now let me ask you some questions to test your understanding.", { lipsyncLang:
|
|
7892
|
+
const M = k.current || { lipsyncLang: "en" };
|
|
7893
|
+
h.current.speakText("Now let me ask you some questions to test your understanding.", { lipsyncLang: M.lipsyncLang });
|
|
7856
7894
|
} else {
|
|
7857
|
-
const
|
|
7858
|
-
h.current && h.current.isReady && (clearInterval(
|
|
7895
|
+
const M = setInterval(() => {
|
|
7896
|
+
h.current && h.current.isReady && (clearInterval(M), I && w());
|
|
7859
7897
|
}, 100);
|
|
7860
7898
|
setTimeout(() => {
|
|
7861
|
-
clearInterval(
|
|
7899
|
+
clearInterval(M);
|
|
7862
7900
|
}, 5e3);
|
|
7863
7901
|
}
|
|
7864
|
-
}, [e.questionStart, y,
|
|
7902
|
+
}, [e.questionStart, y, T]), G = P(() => {
|
|
7865
7903
|
const v = y();
|
|
7866
7904
|
if (a.current.currentQuestionIndex < (v?.questions?.length || 0) - 1) {
|
|
7867
7905
|
h.current && h.current.stopSpeaking && h.current.stopSpeaking(), a.current.currentQuestionIndex += 1;
|
|
7868
|
-
const
|
|
7869
|
-
|
|
7906
|
+
const I = T();
|
|
7907
|
+
I && c.current.onCustomAction({
|
|
7870
7908
|
type: "nextQuestion",
|
|
7871
7909
|
moduleIndex: a.current.currentModuleIndex,
|
|
7872
7910
|
lessonIndex: a.current.currentLessonIndex,
|
|
7873
7911
|
questionIndex: a.current.currentQuestionIndex,
|
|
7874
7912
|
totalQuestions: a.current.totalQuestions,
|
|
7875
|
-
question:
|
|
7913
|
+
question: I,
|
|
7876
7914
|
score: a.current.score
|
|
7877
7915
|
});
|
|
7878
|
-
const
|
|
7879
|
-
if (!h.current || !
|
|
7916
|
+
const w = () => {
|
|
7917
|
+
if (!h.current || !I) return;
|
|
7880
7918
|
if (h.current.setMood("happy"), h.current.setBodyMovement("idle"), e.nextQuestion)
|
|
7881
7919
|
try {
|
|
7882
7920
|
h.current.playAnimation(e.nextQuestion, !0);
|
|
7883
7921
|
} catch (q) {
|
|
7884
7922
|
console.warn("Failed to play nextQuestion animation:", q);
|
|
7885
7923
|
}
|
|
7886
|
-
const
|
|
7887
|
-
if (
|
|
7888
|
-
const q = j ? `Great! Here's your final coding challenge: ${
|
|
7924
|
+
const M = k.current || { lipsyncLang: "en" }, K = y()?.questions?.length || 0, j = a.current.currentQuestionIndex >= K - 1;
|
|
7925
|
+
if (I.type === "code_test") {
|
|
7926
|
+
const q = j ? `Great! Here's your final coding challenge: ${I.question}` : `Great! Now let's move on to your next coding challenge: ${I.question}`;
|
|
7889
7927
|
h.current.speakText(q, {
|
|
7890
|
-
lipsyncLang:
|
|
7928
|
+
lipsyncLang: M.lipsyncLang
|
|
7891
7929
|
});
|
|
7892
|
-
} else if (
|
|
7893
|
-
const q = j ? `Alright! Here's your final question: ${
|
|
7930
|
+
} else if (I.type === "multiple_choice") {
|
|
7931
|
+
const q = j ? `Alright! Here's your final question: ${I.question}` : `Alright! Here's your next question: ${I.question}`;
|
|
7894
7932
|
h.current.speakText(q, {
|
|
7895
|
-
lipsyncLang:
|
|
7933
|
+
lipsyncLang: M.lipsyncLang
|
|
7896
7934
|
});
|
|
7897
|
-
} else if (
|
|
7898
|
-
const q = j ? `Now let's try this final one: ${
|
|
7935
|
+
} else if (I.type === "true_false") {
|
|
7936
|
+
const q = j ? `Now let's try this final one: ${I.question}` : `Now let's try this one: ${I.question}`;
|
|
7899
7937
|
h.current.speakText(q, {
|
|
7900
|
-
lipsyncLang:
|
|
7938
|
+
lipsyncLang: M.lipsyncLang
|
|
7901
7939
|
});
|
|
7902
7940
|
} else {
|
|
7903
|
-
const q = j ? `Here's your final question: ${
|
|
7941
|
+
const q = j ? `Here's your final question: ${I.question}` : `Here's the next question: ${I.question}`;
|
|
7904
7942
|
h.current.speakText(q, {
|
|
7905
|
-
lipsyncLang:
|
|
7943
|
+
lipsyncLang: M.lipsyncLang
|
|
7906
7944
|
});
|
|
7907
7945
|
}
|
|
7908
7946
|
};
|
|
7909
|
-
if (h.current && h.current.isReady &&
|
|
7910
|
-
|
|
7911
|
-
else if (
|
|
7912
|
-
const
|
|
7913
|
-
h.current && h.current.isReady && (clearInterval(
|
|
7947
|
+
if (h.current && h.current.isReady && I)
|
|
7948
|
+
w();
|
|
7949
|
+
else if (I) {
|
|
7950
|
+
const M = setInterval(() => {
|
|
7951
|
+
h.current && h.current.isReady && (clearInterval(M), w());
|
|
7914
7952
|
}, 100);
|
|
7915
7953
|
setTimeout(() => {
|
|
7916
|
-
clearInterval(
|
|
7954
|
+
clearInterval(M);
|
|
7917
7955
|
}, 5e3);
|
|
7918
7956
|
}
|
|
7919
7957
|
} else
|
|
@@ -7924,11 +7962,11 @@ const yt = Me(({
|
|
|
7924
7962
|
totalQuestions: a.current.totalQuestions,
|
|
7925
7963
|
score: a.current.score
|
|
7926
7964
|
});
|
|
7927
|
-
}, [e.nextQuestion, y,
|
|
7928
|
-
const v =
|
|
7929
|
-
if (a.current.currentLessonIndex < (
|
|
7965
|
+
}, [e.nextQuestion, y, T]), _ = P(() => {
|
|
7966
|
+
const v = H.current || { modules: [] }, I = v.modules[a.current.currentModuleIndex];
|
|
7967
|
+
if (a.current.currentLessonIndex < (I?.lessons?.length || 0) - 1) {
|
|
7930
7968
|
a.current.currentLessonIndex += 1, a.current.currentQuestionIndex = 0, a.current.lessonCompleted = !1, a.current.isQuestionMode = !1, a.current.isTeaching = !1, a.current.score = 0, a.current.totalQuestions = 0;
|
|
7931
|
-
const
|
|
7969
|
+
const M = v.modules[a.current.currentModuleIndex], W = a.current.currentLessonIndex < (M?.lessons?.length || 0) - 1, K = a.current.currentModuleIndex < (v.modules?.length || 0) - 1, j = W || K;
|
|
7932
7970
|
c.current.onCustomAction({
|
|
7933
7971
|
type: "lessonStart",
|
|
7934
7972
|
moduleIndex: a.current.currentModuleIndex,
|
|
@@ -7941,7 +7979,7 @@ const yt = Me(({
|
|
|
7941
7979
|
}), h.current && (h.current.setMood("happy"), h.current.setBodyMovement("idle"));
|
|
7942
7980
|
} else if (a.current.currentModuleIndex < (v.modules?.length || 0) - 1) {
|
|
7943
7981
|
a.current.currentModuleIndex += 1, a.current.currentLessonIndex = 0, a.current.currentQuestionIndex = 0, a.current.lessonCompleted = !1, a.current.isQuestionMode = !1, a.current.isTeaching = !1, a.current.score = 0, a.current.totalQuestions = 0;
|
|
7944
|
-
const
|
|
7982
|
+
const W = v.modules[a.current.currentModuleIndex], K = a.current.currentLessonIndex < (W?.lessons?.length || 0) - 1, j = a.current.currentModuleIndex < (v.modules?.length || 0) - 1, q = K || j;
|
|
7945
7983
|
c.current.onCustomAction({
|
|
7946
7984
|
type: "lessonStart",
|
|
7947
7985
|
moduleIndex: a.current.currentModuleIndex,
|
|
@@ -7953,26 +7991,26 @@ const yt = Me(({
|
|
|
7953
7991
|
lesson: y()
|
|
7954
7992
|
}), h.current && (h.current.setMood("happy"), h.current.setBodyMovement("idle"));
|
|
7955
7993
|
} else
|
|
7956
|
-
|
|
7957
|
-
}, []), X =
|
|
7994
|
+
R.current && R.current();
|
|
7995
|
+
}, []), X = P(() => {
|
|
7958
7996
|
const v = y();
|
|
7959
|
-
let
|
|
7997
|
+
let I = null;
|
|
7960
7998
|
if (v?.avatar_script && v?.body) {
|
|
7961
|
-
const
|
|
7962
|
-
|
|
7999
|
+
const w = v.avatar_script.trim(), M = v.body.trim(), W = w.match(/[.!?]$/) ? " " : ". ";
|
|
8000
|
+
I = `${w}${W}${M}`;
|
|
7963
8001
|
} else
|
|
7964
|
-
|
|
7965
|
-
if (h.current && h.current.isReady &&
|
|
8002
|
+
I = v?.avatar_script || v?.body || null;
|
|
8003
|
+
if (h.current && h.current.isReady && I) {
|
|
7966
8004
|
a.current.isTeaching = !0, a.current.isQuestionMode = !1, a.current.score = 0, a.current.totalQuestions = 0, h.current.setMood("happy");
|
|
7967
|
-
let
|
|
8005
|
+
let w = !1;
|
|
7968
8006
|
if (e.teaching)
|
|
7969
8007
|
try {
|
|
7970
|
-
h.current.playAnimation(e.teaching, !0),
|
|
7971
|
-
} catch (
|
|
7972
|
-
console.warn("Failed to play teaching animation:",
|
|
8008
|
+
h.current.playAnimation(e.teaching, !0), w = !0;
|
|
8009
|
+
} catch (W) {
|
|
8010
|
+
console.warn("Failed to play teaching animation:", W);
|
|
7973
8011
|
}
|
|
7974
|
-
|
|
7975
|
-
const
|
|
8012
|
+
w || h.current.setBodyMovement("gesturing");
|
|
8013
|
+
const M = k.current || { lipsyncLang: "en" };
|
|
7976
8014
|
c.current.onLessonStart({
|
|
7977
8015
|
moduleIndex: a.current.currentModuleIndex,
|
|
7978
8016
|
lessonIndex: a.current.currentLessonIndex,
|
|
@@ -7982,8 +8020,8 @@ const yt = Me(({
|
|
|
7982
8020
|
moduleIndex: a.current.currentModuleIndex,
|
|
7983
8021
|
lessonIndex: a.current.currentLessonIndex,
|
|
7984
8022
|
lesson: v
|
|
7985
|
-
}), h.current.speakText(
|
|
7986
|
-
lipsyncLang:
|
|
8023
|
+
}), h.current.speakText(I, {
|
|
8024
|
+
lipsyncLang: M.lipsyncLang,
|
|
7987
8025
|
onSpeechEnd: () => {
|
|
7988
8026
|
a.current.isTeaching = !1, c.current.onCustomAction({
|
|
7989
8027
|
type: "teachingComplete",
|
|
@@ -8001,17 +8039,17 @@ const yt = Me(({
|
|
|
8001
8039
|
}
|
|
8002
8040
|
});
|
|
8003
8041
|
}
|
|
8004
|
-
}, [e.teaching, y]), $ =
|
|
8005
|
-
const
|
|
8006
|
-
if (
|
|
8042
|
+
}, [e.teaching, y]), $ = P((v) => {
|
|
8043
|
+
const I = T(), w = E(v, I);
|
|
8044
|
+
if (w && (a.current.score += 1), c.current.onQuestionAnswer({
|
|
8007
8045
|
moduleIndex: a.current.currentModuleIndex,
|
|
8008
8046
|
lessonIndex: a.current.currentLessonIndex,
|
|
8009
8047
|
questionIndex: a.current.currentQuestionIndex,
|
|
8010
8048
|
answer: v,
|
|
8011
|
-
isCorrect:
|
|
8012
|
-
question:
|
|
8049
|
+
isCorrect: w,
|
|
8050
|
+
question: I
|
|
8013
8051
|
}), h.current)
|
|
8014
|
-
if (
|
|
8052
|
+
if (w) {
|
|
8015
8053
|
if (h.current.setMood("happy"), e.correct)
|
|
8016
8054
|
try {
|
|
8017
8055
|
h.current.playReaction("happy");
|
|
@@ -8019,11 +8057,11 @@ const yt = Me(({
|
|
|
8019
8057
|
h.current.setBodyMovement("happy");
|
|
8020
8058
|
}
|
|
8021
8059
|
h.current.setBodyMovement("gesturing");
|
|
8022
|
-
const
|
|
8023
|
-
a.current.currentQuestionIndex >=
|
|
8024
|
-
const K = a.current.currentQuestionIndex <
|
|
8025
|
-
console.log("[CurriculumLearning] Answer feedback - questionIndex:", a.current.currentQuestionIndex, "totalQuestions:",
|
|
8026
|
-
const j =
|
|
8060
|
+
const W = y()?.questions?.length || 0;
|
|
8061
|
+
a.current.currentQuestionIndex >= W - 1;
|
|
8062
|
+
const K = a.current.currentQuestionIndex < W - 1;
|
|
8063
|
+
console.log("[CurriculumLearning] Answer feedback - questionIndex:", a.current.currentQuestionIndex, "totalQuestions:", W, "hasNextQuestion:", K);
|
|
8064
|
+
const j = I.type === "code_test" ? `Great job! Your code passed all the tests! ${I.explanation || ""}` : `Excellent! That's correct! ${I.explanation || ""}`, q = k.current || { lipsyncLang: "en" };
|
|
8027
8065
|
h.current.speakText(j, {
|
|
8028
8066
|
lipsyncLang: q.lipsyncLang,
|
|
8029
8067
|
onSpeechEnd: () => {
|
|
@@ -8047,9 +8085,9 @@ const yt = Me(({
|
|
|
8047
8085
|
h.current.setBodyMovement("idle");
|
|
8048
8086
|
}
|
|
8049
8087
|
h.current.setBodyMovement("gesturing");
|
|
8050
|
-
const
|
|
8051
|
-
console.log("[CurriculumLearning] Answer feedback (incorrect) - questionIndex:", a.current.currentQuestionIndex, "totalQuestions:",
|
|
8052
|
-
const q =
|
|
8088
|
+
const W = y()?.questions?.length || 0, K = a.current.currentQuestionIndex >= W - 1, j = a.current.currentQuestionIndex < W - 1;
|
|
8089
|
+
console.log("[CurriculumLearning] Answer feedback (incorrect) - questionIndex:", a.current.currentQuestionIndex, "totalQuestions:", W, "hasNextQuestion:", j);
|
|
8090
|
+
const q = I.type === "code_test" ? `Your code didn't pass all the tests. ${I.explanation || "Try again!"}` : `Not quite right, but don't worry! ${I.explanation || ""}${K ? "" : " Let's move on to the next question."}`, Le = k.current || { lipsyncLang: "en" };
|
|
8053
8091
|
h.current.speakText(q, {
|
|
8054
8092
|
lipsyncLang: Le.lipsyncLang,
|
|
8055
8093
|
onSpeechEnd: () => {
|
|
@@ -8067,30 +8105,30 @@ const yt = Me(({
|
|
|
8067
8105
|
});
|
|
8068
8106
|
}
|
|
8069
8107
|
else {
|
|
8070
|
-
const
|
|
8108
|
+
const W = y()?.questions?.length || 0;
|
|
8071
8109
|
c.current.onCustomAction({
|
|
8072
8110
|
type: "answerFeedbackComplete",
|
|
8073
8111
|
moduleIndex: a.current.currentModuleIndex,
|
|
8074
8112
|
lessonIndex: a.current.currentLessonIndex,
|
|
8075
8113
|
questionIndex: a.current.currentQuestionIndex,
|
|
8076
|
-
isCorrect:
|
|
8077
|
-
hasNextQuestion: a.current.currentQuestionIndex <
|
|
8114
|
+
isCorrect: w,
|
|
8115
|
+
hasNextQuestion: a.current.currentQuestionIndex < W - 1,
|
|
8078
8116
|
score: a.current.score,
|
|
8079
8117
|
totalQuestions: a.current.totalQuestions,
|
|
8080
8118
|
avatarNotReady: !0
|
|
8081
8119
|
});
|
|
8082
8120
|
}
|
|
8083
|
-
}, [e.correct, e.incorrect,
|
|
8084
|
-
const
|
|
8121
|
+
}, [e.correct, e.incorrect, T, y, E]), se = P((v) => {
|
|
8122
|
+
const I = T();
|
|
8085
8123
|
if (!v || typeof v != "object") {
|
|
8086
8124
|
console.error("Invalid code test result format. Expected object with {passed: boolean, ...}");
|
|
8087
8125
|
return;
|
|
8088
8126
|
}
|
|
8089
|
-
if (
|
|
8127
|
+
if (I?.type !== "code_test") {
|
|
8090
8128
|
console.warn("Current question is not a code test. Use handleAnswerSelect for other question types.");
|
|
8091
8129
|
return;
|
|
8092
8130
|
}
|
|
8093
|
-
const
|
|
8131
|
+
const w = {
|
|
8094
8132
|
passed: v.passed === !0,
|
|
8095
8133
|
results: v.results || [],
|
|
8096
8134
|
output: v.output || "",
|
|
@@ -8105,13 +8143,13 @@ const yt = Me(({
|
|
|
8105
8143
|
moduleIndex: a.current.currentModuleIndex,
|
|
8106
8144
|
lessonIndex: a.current.currentLessonIndex,
|
|
8107
8145
|
questionIndex: a.current.currentQuestionIndex,
|
|
8108
|
-
testResult:
|
|
8109
|
-
question:
|
|
8110
|
-
}), p.current && p.current(
|
|
8111
|
-
}, [
|
|
8146
|
+
testResult: w,
|
|
8147
|
+
question: I
|
|
8148
|
+
}), p.current && p.current(w);
|
|
8149
|
+
}, [T, E]), ae = P(() => {
|
|
8112
8150
|
if (a.current.currentQuestionIndex > 0) {
|
|
8113
8151
|
a.current.currentQuestionIndex -= 1;
|
|
8114
|
-
const v =
|
|
8152
|
+
const v = T();
|
|
8115
8153
|
v && c.current.onCustomAction({
|
|
8116
8154
|
type: "questionStart",
|
|
8117
8155
|
moduleIndex: a.current.currentModuleIndex,
|
|
@@ -8121,29 +8159,29 @@ const yt = Me(({
|
|
|
8121
8159
|
question: v,
|
|
8122
8160
|
score: a.current.score
|
|
8123
8161
|
});
|
|
8124
|
-
const
|
|
8162
|
+
const I = () => {
|
|
8125
8163
|
if (!h.current || !v) return;
|
|
8126
8164
|
h.current.setMood("happy"), h.current.setBodyMovement("idle");
|
|
8127
|
-
const
|
|
8165
|
+
const w = k.current || { lipsyncLang: "en" };
|
|
8128
8166
|
v.type === "code_test" ? h.current.speakText(`Let's go back to this coding challenge: ${v.question}`, {
|
|
8129
|
-
lipsyncLang:
|
|
8167
|
+
lipsyncLang: w.lipsyncLang
|
|
8130
8168
|
}) : h.current.speakText(`Going back to: ${v.question}`, {
|
|
8131
|
-
lipsyncLang:
|
|
8169
|
+
lipsyncLang: w.lipsyncLang
|
|
8132
8170
|
});
|
|
8133
8171
|
};
|
|
8134
8172
|
if (h.current && h.current.isReady && v)
|
|
8135
|
-
|
|
8173
|
+
I();
|
|
8136
8174
|
else if (v) {
|
|
8137
|
-
const
|
|
8138
|
-
h.current && h.current.isReady && (clearInterval(
|
|
8175
|
+
const w = setInterval(() => {
|
|
8176
|
+
h.current && h.current.isReady && (clearInterval(w), I());
|
|
8139
8177
|
}, 100);
|
|
8140
8178
|
setTimeout(() => {
|
|
8141
|
-
clearInterval(
|
|
8179
|
+
clearInterval(w);
|
|
8142
8180
|
}, 5e3);
|
|
8143
8181
|
}
|
|
8144
8182
|
}
|
|
8145
|
-
}, [
|
|
8146
|
-
const v =
|
|
8183
|
+
}, [T]), pe = P(() => {
|
|
8184
|
+
const v = H.current || { modules: [] };
|
|
8147
8185
|
if (v.modules[a.current.currentModuleIndex], a.current.currentLessonIndex > 0)
|
|
8148
8186
|
a.current.currentLessonIndex -= 1, a.current.currentQuestionIndex = 0, a.current.lessonCompleted = !1, a.current.isQuestionMode = !1, a.current.isTeaching = !1, a.current.score = 0, a.current.totalQuestions = 0, c.current.onCustomAction({
|
|
8149
8187
|
type: "lessonStart",
|
|
@@ -8155,8 +8193,8 @@ const yt = Me(({
|
|
|
8155
8193
|
lesson: y()
|
|
8156
8194
|
}), h.current && (h.current.setMood("happy"), h.current.setBodyMovement("idle"));
|
|
8157
8195
|
else if (a.current.currentModuleIndex > 0) {
|
|
8158
|
-
const
|
|
8159
|
-
a.current.currentModuleIndex -= 1, a.current.currentLessonIndex = (
|
|
8196
|
+
const M = v.modules[a.current.currentModuleIndex - 1];
|
|
8197
|
+
a.current.currentModuleIndex -= 1, a.current.currentLessonIndex = (M?.lessons?.length || 1) - 1, a.current.currentQuestionIndex = 0, a.current.lessonCompleted = !1, a.current.isQuestionMode = !1, a.current.isTeaching = !1, a.current.score = 0, a.current.totalQuestions = 0, c.current.onCustomAction({
|
|
8160
8198
|
type: "lessonStart",
|
|
8161
8199
|
moduleIndex: a.current.currentModuleIndex,
|
|
8162
8200
|
lessonIndex: a.current.currentLessonIndex
|
|
@@ -8166,52 +8204,52 @@ const yt = Me(({
|
|
|
8166
8204
|
lesson: y()
|
|
8167
8205
|
}), h.current && (h.current.setMood("happy"), h.current.setBodyMovement("idle"));
|
|
8168
8206
|
}
|
|
8169
|
-
}, [y]), ee =
|
|
8207
|
+
}, [y]), ee = P(() => {
|
|
8170
8208
|
a.current.currentModuleIndex = 0, a.current.currentLessonIndex = 0, a.current.currentQuestionIndex = 0, a.current.isTeaching = !1, a.current.isQuestionMode = !1, a.current.lessonCompleted = !1, a.current.curriculumCompleted = !1, a.current.score = 0, a.current.totalQuestions = 0;
|
|
8171
|
-
}, []), le =
|
|
8209
|
+
}, []), le = P((v) => {
|
|
8172
8210
|
console.log("Avatar is ready!", v);
|
|
8173
|
-
const
|
|
8174
|
-
u &&
|
|
8211
|
+
const I = y(), w = I?.avatar_script || I?.body;
|
|
8212
|
+
u && w && setTimeout(() => {
|
|
8175
8213
|
d.current && d.current();
|
|
8176
8214
|
}, 10);
|
|
8177
8215
|
}, [u, y]);
|
|
8178
8216
|
Xe(() => {
|
|
8179
|
-
d.current = X, g.current = _, x.current =
|
|
8217
|
+
d.current = X, g.current = _, x.current = O, f.current = G, R.current = te, F.current = S, p.current = $;
|
|
8180
8218
|
}), Ee(r, () => ({
|
|
8181
8219
|
// Curriculum control methods
|
|
8182
8220
|
startTeaching: X,
|
|
8183
8221
|
startQuestions: S,
|
|
8184
8222
|
handleAnswerSelect: $,
|
|
8185
8223
|
handleCodeTestResult: se,
|
|
8186
|
-
nextQuestion:
|
|
8224
|
+
nextQuestion: G,
|
|
8187
8225
|
previousQuestion: ae,
|
|
8188
8226
|
nextLesson: _,
|
|
8189
8227
|
previousLesson: pe,
|
|
8190
|
-
completeLesson:
|
|
8191
|
-
completeCurriculum:
|
|
8228
|
+
completeLesson: O,
|
|
8229
|
+
completeCurriculum: te,
|
|
8192
8230
|
resetCurriculum: ee,
|
|
8193
8231
|
getState: () => ({ ...a.current }),
|
|
8194
|
-
getCurrentQuestion: () =>
|
|
8232
|
+
getCurrentQuestion: () => T(),
|
|
8195
8233
|
getCurrentLesson: () => y(),
|
|
8196
8234
|
// Direct access to avatar ref (always returns current value)
|
|
8197
8235
|
getAvatarRef: () => h.current,
|
|
8198
8236
|
// Convenience methods that delegate to avatar (always check current ref)
|
|
8199
|
-
speakText: async (v,
|
|
8237
|
+
speakText: async (v, I = {}) => {
|
|
8200
8238
|
await h.current?.resumeAudioContext?.();
|
|
8201
|
-
const
|
|
8202
|
-
h.current?.speakText(v, { ...
|
|
8239
|
+
const w = k.current || { lipsyncLang: "en" };
|
|
8240
|
+
h.current?.speakText(v, { ...I, lipsyncLang: I.lipsyncLang || w.lipsyncLang });
|
|
8203
8241
|
},
|
|
8204
8242
|
resumeAudioContext: async () => {
|
|
8205
8243
|
if (h.current?.resumeAudioContext)
|
|
8206
8244
|
return await h.current.resumeAudioContext();
|
|
8207
8245
|
const v = h.current?.talkingHead;
|
|
8208
8246
|
if (v?.audioCtx) {
|
|
8209
|
-
const
|
|
8210
|
-
if (
|
|
8247
|
+
const I = v.audioCtx;
|
|
8248
|
+
if (I.state === "suspended" || I.state === "interrupted")
|
|
8211
8249
|
try {
|
|
8212
|
-
await
|
|
8213
|
-
} catch (
|
|
8214
|
-
console.warn("Failed to resume audio context:",
|
|
8250
|
+
await I.resume(), console.log("Audio context resumed via talkingHead");
|
|
8251
|
+
} catch (w) {
|
|
8252
|
+
console.warn("Failed to resume audio context:", w);
|
|
8215
8253
|
}
|
|
8216
8254
|
} else
|
|
8217
8255
|
console.warn("Audio context not available yet");
|
|
@@ -8221,7 +8259,7 @@ const yt = Me(({
|
|
|
8221
8259
|
resumeSpeaking: async () => await h.current?.resumeSpeaking(),
|
|
8222
8260
|
isPaused: () => h.current && typeof h.current.isPaused < "u" ? h.current.isPaused : !1,
|
|
8223
8261
|
setMood: (v) => h.current?.setMood(v),
|
|
8224
|
-
playAnimation: (v,
|
|
8262
|
+
playAnimation: (v, I) => h.current?.playAnimation(v, I),
|
|
8225
8263
|
setBodyMovement: (v) => h.current?.setBodyMovement(v),
|
|
8226
8264
|
setMovementIntensity: (v) => h.current?.setMovementIntensity(v),
|
|
8227
8265
|
playRandomDance: () => h.current?.playRandomDance(),
|
|
@@ -8232,10 +8270,10 @@ const yt = Me(({
|
|
|
8232
8270
|
lockAvatarPosition: () => h.current?.lockAvatarPosition(),
|
|
8233
8271
|
unlockAvatarPosition: () => h.current?.unlockAvatarPosition(),
|
|
8234
8272
|
// Custom action trigger
|
|
8235
|
-
triggerCustomAction: (v,
|
|
8273
|
+
triggerCustomAction: (v, I) => {
|
|
8236
8274
|
c.current.onCustomAction({
|
|
8237
8275
|
type: v,
|
|
8238
|
-
...
|
|
8276
|
+
...I,
|
|
8239
8277
|
state: { ...a.current }
|
|
8240
8278
|
});
|
|
8241
8279
|
},
|
|
@@ -8243,8 +8281,8 @@ const yt = Me(({
|
|
|
8243
8281
|
handleResize: () => h.current?.handleResize(),
|
|
8244
8282
|
// Avatar readiness check (always returns current value)
|
|
8245
8283
|
isAvatarReady: () => h.current?.isReady || !1
|
|
8246
|
-
}), [X, S, $, se,
|
|
8247
|
-
const
|
|
8284
|
+
}), [X, S, $, se, G, _, O, te, ee, T, y]);
|
|
8285
|
+
const U = k.current || {
|
|
8248
8286
|
avatarUrl: "/avatars/brunette.glb",
|
|
8249
8287
|
avatarBody: "F",
|
|
8250
8288
|
mood: "happy",
|
|
@@ -8261,18 +8299,18 @@ const yt = Me(({
|
|
|
8261
8299
|
Ve,
|
|
8262
8300
|
{
|
|
8263
8301
|
ref: h,
|
|
8264
|
-
avatarUrl:
|
|
8265
|
-
avatarBody:
|
|
8266
|
-
mood:
|
|
8267
|
-
ttsLang:
|
|
8268
|
-
ttsService:
|
|
8269
|
-
ttsVoice:
|
|
8270
|
-
ttsApiKey:
|
|
8271
|
-
bodyMovement:
|
|
8272
|
-
movementIntensity:
|
|
8273
|
-
showFullAvatar:
|
|
8302
|
+
avatarUrl: U.avatarUrl,
|
|
8303
|
+
avatarBody: U.avatarBody,
|
|
8304
|
+
mood: U.mood,
|
|
8305
|
+
ttsLang: U.ttsLang,
|
|
8306
|
+
ttsService: U.ttsService,
|
|
8307
|
+
ttsVoice: U.ttsVoice,
|
|
8308
|
+
ttsApiKey: U.ttsApiKey,
|
|
8309
|
+
bodyMovement: U.bodyMovement,
|
|
8310
|
+
movementIntensity: U.movementIntensity,
|
|
8311
|
+
showFullAvatar: U.showFullAvatar,
|
|
8274
8312
|
cameraView: "upper",
|
|
8275
|
-
animations:
|
|
8313
|
+
animations: U.animations,
|
|
8276
8314
|
onReady: le,
|
|
8277
8315
|
onLoading: () => {
|
|
8278
8316
|
},
|
|
@@ -8386,7 +8424,7 @@ const Ge = {
|
|
|
8386
8424
|
duration: 5e3,
|
|
8387
8425
|
description: "Excited, energetic movement"
|
|
8388
8426
|
}
|
|
8389
|
-
}, wt = (
|
|
8427
|
+
}, wt = (Z) => Ge[Z] || null, zt = (Z) => Ge.hasOwnProperty(Z);
|
|
8390
8428
|
export {
|
|
8391
8429
|
yt as CurriculumLearning,
|
|
8392
8430
|
gt as SimpleTalkingAvatar,
|