@sage-rsc/talking-head-react 1.1.3 → 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 +577 -547
- package/package.json +1 -1
- package/src/lib/talkinghead.mjs +80 -4
package/dist/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { jsxs as Pe, jsx as me } from "react/jsx-runtime";
|
|
2
|
-
import { forwardRef as Me, useRef as N, useState as ce, useEffect as de, useCallback 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";
|
|
@@ -8,13 +8,13 @@ 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,15 +2629,15 @@ 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
|
|
2640
|
-
class
|
|
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
|
+
class Be {
|
|
2641
2641
|
/**
|
|
2642
2642
|
* Avatar.
|
|
2643
2643
|
* @typedef {Object} Avatar
|
|
@@ -4073,22 +4073,22 @@ class De {
|
|
|
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 De {
|
|
|
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 De {
|
|
|
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 De {
|
|
|
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 De {
|
|
|
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 De {
|
|
|
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 De {
|
|
|
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 De {
|
|
|
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 De {
|
|
|
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 De {
|
|
|
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 De {
|
|
|
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 De {
|
|
|
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 De {
|
|
|
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 De {
|
|
|
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 De {
|
|
|
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 De {
|
|
|
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 De {
|
|
|
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 De {
|
|
|
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 De {
|
|
|
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 De {
|
|
|
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 De {
|
|
|
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 De {
|
|
|
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 De {
|
|
|
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 De {
|
|
|
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 De {
|
|
|
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 De {
|
|
|
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 De {
|
|
|
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) => {
|
|
@@ -6432,6 +6432,9 @@ class De {
|
|
|
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 De {
|
|
|
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",
|
|
@@ -6494,7 +6500,7 @@ class De {
|
|
|
6494
6500
|
if (e.has(d))
|
|
6495
6501
|
return d;
|
|
6496
6502
|
}
|
|
6497
|
-
const r = s.match(/^[rl]
|
|
6503
|
+
const r = s.match(/^[rl]_(?:middle|mid)(\d+)$/);
|
|
6498
6504
|
if (r) {
|
|
6499
6505
|
const a = r[1], d = `${s.startsWith("r") ? "Right" : "Left"}HandMiddle${a}`;
|
|
6500
6506
|
if (e.has(d))
|
|
@@ -6511,7 +6517,7 @@ class De {
|
|
|
6511
6517
|
if (e.has(c))
|
|
6512
6518
|
return c;
|
|
6513
6519
|
}
|
|
6514
|
-
if (s.includes("upperarmtwist") || s.includes("forearmtwist"))
|
|
6520
|
+
if (s.includes("upperarmtwist") || s.includes("forearmtwist") || s.includes("ribstwist") || s.includes("breast") || s.includes("twist"))
|
|
6515
6521
|
return null;
|
|
6516
6522
|
if (s.match(/^[rl]_forearm/)) {
|
|
6517
6523
|
const c = `${s.startsWith("r") ? "Right" : "Left"}ForeArm`;
|
|
@@ -6545,7 +6551,31 @@ class De {
|
|
|
6545
6551
|
const l = o.name.split("."), u = l[0], r = l[1], h = this.mapBoneName(u, e);
|
|
6546
6552
|
if (h) {
|
|
6547
6553
|
const a = `${h}.${r}`, c = o.clone();
|
|
6548
|
-
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);
|
|
6549
6579
|
} else
|
|
6550
6580
|
i.add(u);
|
|
6551
6581
|
}), s.size > 0 && console.info(
|
|
@@ -6556,7 +6586,7 @@ class De {
|
|
|
6556
6586
|
`FBX animation "${t.name}" contains tracks for ${i.size} bone(s) that couldn't be mapped:`,
|
|
6557
6587
|
Array.from(i).slice(0, 10).join(", "),
|
|
6558
6588
|
i.size > 10 ? "..." : ""
|
|
6559
|
-
), 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);
|
|
6560
6590
|
}
|
|
6561
6591
|
async playAnimation(t, e = null, n = 10, i = 0, s = 0.01, o = !1) {
|
|
6562
6592
|
if (!this.armature) return;
|
|
@@ -6566,9 +6596,9 @@ class De {
|
|
|
6566
6596
|
let u = this.animQueue.find((a) => a.template.name === "pose");
|
|
6567
6597
|
u && (u.ts[0] = 1 / 0), Object.entries(l.pose.props).forEach((a) => {
|
|
6568
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;
|
|
6569
|
-
}), 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 });
|
|
6570
6600
|
const r = Math.ceil(n / l.clip.duration), h = this.mixer.clipAction(l.clip);
|
|
6571
|
-
h.setLoop(
|
|
6601
|
+
h.setLoop(b.LoopRepeat, r), h.clampWhenFinished = !0, this.currentFBXAction = h;
|
|
6572
6602
|
try {
|
|
6573
6603
|
h.fadeIn(0.5).play(), console.log("FBX animation started successfully:", t);
|
|
6574
6604
|
} catch (a) {
|
|
@@ -6626,20 +6656,20 @@ class De {
|
|
|
6626
6656
|
}
|
|
6627
6657
|
c = g;
|
|
6628
6658
|
const x = {};
|
|
6629
|
-
c.tracks.forEach((
|
|
6630
|
-
|
|
6631
|
-
const
|
|
6632
|
-
if (
|
|
6633
|
-
for (let p = 0; p <
|
|
6634
|
-
|
|
6635
|
-
x[
|
|
6636
|
-
} 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());
|
|
6637
6667
|
});
|
|
6638
|
-
const
|
|
6639
|
-
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({
|
|
6640
6670
|
url: t + "-" + i,
|
|
6641
6671
|
clip: c,
|
|
6642
|
-
pose:
|
|
6672
|
+
pose: f
|
|
6643
6673
|
}), this.playAnimation(t, e, n, i, s);
|
|
6644
6674
|
} else {
|
|
6645
6675
|
const c = "Animation " + t + " (ndx=" + i + ") not found";
|
|
@@ -6684,7 +6714,7 @@ class De {
|
|
|
6684
6714
|
r.tracks.forEach((c) => {
|
|
6685
6715
|
c.name = c.name.replaceAll("mixamorig", "");
|
|
6686
6716
|
const d = c.name.split(".");
|
|
6687
|
-
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());
|
|
6688
6718
|
});
|
|
6689
6719
|
const a = { props: h };
|
|
6690
6720
|
h["Hips.position"] && (h["Hips.position"].y < 0.5 ? a.lying = !0 : a.standing = !0), this.animPoses.push({
|
|
@@ -6717,7 +6747,7 @@ class De {
|
|
|
6717
6747
|
if (s) {
|
|
6718
6748
|
this.gestureTimeout && (clearTimeout(this.gestureTimeout), this.gestureTimeout = null);
|
|
6719
6749
|
let l = this.animQueue.findIndex((u) => u.template.name === "talkinghands");
|
|
6720
|
-
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));
|
|
6721
6751
|
for (let [u, r] of Object.entries(this.gesture))
|
|
6722
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);
|
|
6723
6753
|
e && Number.isFinite(e) && (this.gestureTimeout = setTimeout(this.stopGesture.bind(this, i), 1e3 * e));
|
|
@@ -6732,7 +6762,7 @@ class De {
|
|
|
6732
6762
|
const c = [];
|
|
6733
6763
|
for (let x = 1; x < l.ts.length; x++) c.push(l.ts[x] - l.ts[x - 1]);
|
|
6734
6764
|
const d = o.template?.rescale || c.map((x) => x / h), g = e * 1e3 - h;
|
|
6735
|
-
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);
|
|
6736
6766
|
} else {
|
|
6737
6767
|
const c = e * 1e3 / h;
|
|
6738
6768
|
l.ts = l.ts.map((d) => u + c * (d - u));
|
|
@@ -6765,34 +6795,34 @@ class De {
|
|
|
6765
6795
|
* @param {numeric} [d=null] If set, apply in d milliseconds
|
|
6766
6796
|
*/
|
|
6767
6797
|
ikSolve(t, e = null, n = !1, i = null) {
|
|
6768
|
-
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);
|
|
6769
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);
|
|
6770
6800
|
const g = this.ikMesh.getObjectByName(t.effector), x = t.links;
|
|
6771
|
-
x.forEach((
|
|
6772
|
-
|
|
6801
|
+
x.forEach((R) => {
|
|
6802
|
+
R.bone = this.ikMesh.getObjectByName(R.link), R.bone.quaternion.copy(this.getPoseTemplateProp(R.link + ".quaternion"));
|
|
6773
6803
|
}), d.updateMatrixWorld(!0);
|
|
6774
|
-
const
|
|
6804
|
+
const f = t.iterations || 10;
|
|
6775
6805
|
if (e)
|
|
6776
|
-
for (let
|
|
6777
|
-
let
|
|
6778
|
-
for (let p = 0,
|
|
6779
|
-
const
|
|
6780
|
-
|
|
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();
|
|
6781
6811
|
let y = s.dot(l);
|
|
6782
|
-
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(
|
|
6783
6813
|
x[p].minx !== void 0 ? x[p].minx : -1 / 0,
|
|
6784
6814
|
x[p].miny !== void 0 ? x[p].miny : -1 / 0,
|
|
6785
6815
|
x[p].minz !== void 0 ? x[p].minz : -1 / 0
|
|
6786
|
-
), new
|
|
6816
|
+
), new b.Vector3(
|
|
6787
6817
|
x[p].maxx !== void 0 ? x[p].maxx : 1 / 0,
|
|
6788
6818
|
x[p].maxy !== void 0 ? x[p].maxy : 1 / 0,
|
|
6789
6819
|
x[p].maxz !== void 0 ? x[p].maxz : 1 / 0
|
|
6790
|
-
))),
|
|
6820
|
+
))), k.updateMatrixWorld(!0), F = !0);
|
|
6791
6821
|
}
|
|
6792
|
-
if (!
|
|
6822
|
+
if (!F) break;
|
|
6793
6823
|
}
|
|
6794
|
-
i && x.forEach((
|
|
6795
|
-
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;
|
|
6796
6826
|
});
|
|
6797
6827
|
}
|
|
6798
6828
|
/**
|
|
@@ -6852,16 +6882,16 @@ function Fe() {
|
|
|
6852
6882
|
};
|
|
6853
6883
|
}
|
|
6854
6884
|
function kt() {
|
|
6855
|
-
const
|
|
6856
|
-
return Object.entries(
|
|
6885
|
+
const Z = Fe(), t = [];
|
|
6886
|
+
return Object.entries(Z.voices).forEach(([e, n]) => {
|
|
6857
6887
|
t.push({
|
|
6858
6888
|
value: n,
|
|
6859
|
-
label: `${e.charAt(0).toUpperCase() + e.slice(1)} (${
|
|
6889
|
+
label: `${e.charAt(0).toUpperCase() + e.slice(1)} (${Z.service})`
|
|
6860
6890
|
});
|
|
6861
6891
|
}), t;
|
|
6862
6892
|
}
|
|
6863
6893
|
const Ve = Me(({
|
|
6864
|
-
avatarUrl:
|
|
6894
|
+
avatarUrl: Z = "/avatars/brunette.glb",
|
|
6865
6895
|
avatarBody: t = "F",
|
|
6866
6896
|
mood: e = "neutral",
|
|
6867
6897
|
ttsLang: n = "en",
|
|
@@ -6880,142 +6910,142 @@ const Ve = Me(({
|
|
|
6880
6910
|
},
|
|
6881
6911
|
className: g = "",
|
|
6882
6912
|
style: x = {},
|
|
6883
|
-
animations:
|
|
6884
|
-
},
|
|
6885
|
-
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);
|
|
6886
6916
|
de(() => {
|
|
6887
|
-
|
|
6917
|
+
T.current = ae;
|
|
6888
6918
|
}, [ae]), de(() => {
|
|
6889
|
-
|
|
6919
|
+
H.current = r;
|
|
6890
6920
|
}, [r]);
|
|
6891
6921
|
const ee = Fe(), le = i || ee.service;
|
|
6892
|
-
let
|
|
6893
|
-
le === "browser" ?
|
|
6922
|
+
let U;
|
|
6923
|
+
le === "browser" ? U = {
|
|
6894
6924
|
service: "browser",
|
|
6895
6925
|
endpoint: "",
|
|
6896
6926
|
apiKey: null,
|
|
6897
6927
|
defaultVoice: "Google US English"
|
|
6898
|
-
} : le === "elevenlabs" ?
|
|
6928
|
+
} : le === "elevenlabs" ? U = {
|
|
6899
6929
|
service: "elevenlabs",
|
|
6900
6930
|
endpoint: "https://api.elevenlabs.io/v1/text-to-speech",
|
|
6901
6931
|
apiKey: o || ee.apiKey,
|
|
6902
6932
|
defaultVoice: s || ee.defaultVoice || Ie.defaultVoice,
|
|
6903
6933
|
voices: ee.voices || Ie.voices
|
|
6904
|
-
} : le === "deepgram" ?
|
|
6934
|
+
} : le === "deepgram" ? U = {
|
|
6905
6935
|
service: "deepgram",
|
|
6906
6936
|
endpoint: "https://api.deepgram.com/v1/speak",
|
|
6907
6937
|
apiKey: o || ee.apiKey,
|
|
6908
6938
|
defaultVoice: s || ee.defaultVoice || Te.defaultVoice,
|
|
6909
6939
|
voices: ee.voices || Te.voices
|
|
6910
|
-
} :
|
|
6940
|
+
} : U = {
|
|
6911
6941
|
...ee,
|
|
6912
6942
|
// Override API key if provided via props
|
|
6913
6943
|
apiKey: o !== null ? o : ee.apiKey
|
|
6914
6944
|
};
|
|
6915
6945
|
const v = {
|
|
6916
|
-
url:
|
|
6946
|
+
url: Z,
|
|
6917
6947
|
body: t,
|
|
6918
6948
|
avatarMood: e,
|
|
6919
6949
|
ttsLang: le === "browser" ? "en-US" : n,
|
|
6920
|
-
ttsVoice: s ||
|
|
6950
|
+
ttsVoice: s || U.defaultVoice,
|
|
6921
6951
|
lipsyncLang: "en",
|
|
6922
6952
|
showFullAvatar: r,
|
|
6923
6953
|
bodyMovement: l,
|
|
6924
6954
|
movementIntensity: u
|
|
6925
|
-
},
|
|
6926
|
-
ttsEndpoint:
|
|
6927
|
-
ttsApikey:
|
|
6955
|
+
}, I = {
|
|
6956
|
+
ttsEndpoint: U.endpoint,
|
|
6957
|
+
ttsApikey: U.apiKey,
|
|
6928
6958
|
ttsService: le,
|
|
6929
6959
|
lipsyncModules: ["en"],
|
|
6930
6960
|
cameraView: h
|
|
6931
|
-
},
|
|
6932
|
-
if (!(!
|
|
6961
|
+
}, w = P(async () => {
|
|
6962
|
+
if (!(!F.current || p.current))
|
|
6933
6963
|
try {
|
|
6934
|
-
if (
|
|
6935
|
-
if (
|
|
6936
|
-
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));
|
|
6937
6967
|
c(J);
|
|
6938
6968
|
}
|
|
6939
|
-
}), await new Promise((
|
|
6969
|
+
}), await new Promise((D) => {
|
|
6940
6970
|
const J = () => {
|
|
6941
|
-
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);
|
|
6942
6972
|
};
|
|
6943
6973
|
J();
|
|
6944
6974
|
}), p.current && p.current.setShowFullAvatar)
|
|
6945
6975
|
try {
|
|
6946
6976
|
p.current.setShowFullAvatar(r);
|
|
6947
|
-
} catch (
|
|
6948
|
-
console.warn("Error setting full body mode on initialization:",
|
|
6977
|
+
} catch (D) {
|
|
6978
|
+
console.warn("Error setting full body mode on initialization:", D);
|
|
6949
6979
|
}
|
|
6950
|
-
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()),
|
|
6951
|
-
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 = () => {
|
|
6952
6982
|
document.visibilityState === "visible" ? p.current?.start() : p.current?.stop();
|
|
6953
6983
|
};
|
|
6954
|
-
return document.addEventListener("visibilitychange",
|
|
6955
|
-
document.removeEventListener("visibilitychange",
|
|
6984
|
+
return document.addEventListener("visibilitychange", B), () => {
|
|
6985
|
+
document.removeEventListener("visibilitychange", B);
|
|
6956
6986
|
};
|
|
6957
6987
|
} catch (L) {
|
|
6958
|
-
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);
|
|
6959
6989
|
}
|
|
6960
|
-
}, [
|
|
6961
|
-
de(() => (
|
|
6990
|
+
}, [Z, t, e, n, i, s, o, r, l, u, h]);
|
|
6991
|
+
de(() => (w(), () => {
|
|
6962
6992
|
p.current && (p.current.stop(), p.current.dispose(), p.current = null);
|
|
6963
|
-
}), [
|
|
6964
|
-
if (!
|
|
6965
|
-
const L = new ResizeObserver((
|
|
6966
|
-
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)
|
|
6967
6997
|
p.current && p.current.onResize && p.current.onResize();
|
|
6968
6998
|
});
|
|
6969
|
-
L.observe(
|
|
6970
|
-
const
|
|
6999
|
+
L.observe(F.current);
|
|
7000
|
+
const B = () => {
|
|
6971
7001
|
p.current && p.current.onResize && p.current.onResize();
|
|
6972
7002
|
};
|
|
6973
|
-
return window.addEventListener("resize",
|
|
6974
|
-
L.disconnect(), window.removeEventListener("resize",
|
|
7003
|
+
return window.addEventListener("resize", B), () => {
|
|
7004
|
+
L.disconnect(), window.removeEventListener("resize", B);
|
|
6975
7005
|
};
|
|
6976
7006
|
}, [$]);
|
|
6977
|
-
const
|
|
7007
|
+
const M = P(async () => {
|
|
6978
7008
|
if (p.current && p.current.audioCtx)
|
|
6979
7009
|
try {
|
|
6980
7010
|
(p.current.audioCtx.state === "suspended" || p.current.audioCtx.state === "interrupted") && (await p.current.audioCtx.resume(), console.log("Audio context resumed"));
|
|
6981
7011
|
} catch (L) {
|
|
6982
7012
|
console.warn("Failed to resume audio context:", L);
|
|
6983
7013
|
}
|
|
6984
|
-
}, []),
|
|
7014
|
+
}, []), W = P(async (L, B = {}) => {
|
|
6985
7015
|
if (p.current && $)
|
|
6986
7016
|
try {
|
|
6987
|
-
y.current && (clearInterval(y.current), y.current = null),
|
|
6988
|
-
const
|
|
6989
|
-
|
|
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();
|
|
6990
7020
|
const ge = {
|
|
6991
|
-
...
|
|
6992
|
-
lipsyncLang:
|
|
7021
|
+
...B,
|
|
7022
|
+
lipsyncLang: B.lipsyncLang || v.lipsyncLang || "en"
|
|
6993
7023
|
};
|
|
6994
|
-
if (
|
|
7024
|
+
if (B.onSpeechEnd && p.current) {
|
|
6995
7025
|
const Y = p.current;
|
|
6996
7026
|
let ue = null, Se = 0;
|
|
6997
7027
|
const Ae = 1200;
|
|
6998
7028
|
let be = !1;
|
|
6999
7029
|
ue = setInterval(() => {
|
|
7000
|
-
if (Se++,
|
|
7030
|
+
if (Se++, T.current)
|
|
7001
7031
|
return;
|
|
7002
7032
|
if (Se > Ae) {
|
|
7003
|
-
if (ue && (clearInterval(ue), ue = null, y.current = null), !be && !
|
|
7033
|
+
if (ue && (clearInterval(ue), ue = null, y.current = null), !be && !T.current) {
|
|
7004
7034
|
be = !0;
|
|
7005
7035
|
try {
|
|
7006
|
-
|
|
7007
|
-
} catch (
|
|
7008
|
-
console.error("Error in onSpeechEnd callback (timeout):",
|
|
7036
|
+
B.onSpeechEnd();
|
|
7037
|
+
} catch (De) {
|
|
7038
|
+
console.error("Error in onSpeechEnd callback (timeout):", De);
|
|
7009
7039
|
}
|
|
7010
7040
|
}
|
|
7011
7041
|
return;
|
|
7012
7042
|
}
|
|
7013
7043
|
const ye = !Y.speechQueue || Y.speechQueue.length === 0, ke = !Y.audioPlaylist || Y.audioPlaylist.length === 0;
|
|
7014
|
-
Y && Y.isSpeaking === !1 && ye && ke && Y.isAudioPlaying === !1 && !be && !
|
|
7015
|
-
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) {
|
|
7016
7046
|
be = !0, ue && (clearInterval(ue), ue = null, y.current = null);
|
|
7017
7047
|
try {
|
|
7018
|
-
|
|
7048
|
+
B.onSpeechEnd();
|
|
7019
7049
|
} catch (Ze) {
|
|
7020
7050
|
console.error("Error in onSpeechEnd callback:", Ze);
|
|
7021
7051
|
}
|
|
@@ -7024,70 +7054,70 @@ const Ve = Me(({
|
|
|
7024
7054
|
}, 100), y.current = ue;
|
|
7025
7055
|
}
|
|
7026
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 () => {
|
|
7027
|
-
await
|
|
7057
|
+
await M(), p.current && p.current.lipsync && (p.current.setSlowdownRate && p.current.setSlowdownRate(1.05), p.current.speakText(L, ge));
|
|
7028
7058
|
}, 100);
|
|
7029
|
-
} catch (
|
|
7030
|
-
console.error("Error speaking text:",
|
|
7059
|
+
} catch (D) {
|
|
7060
|
+
console.error("Error speaking text:", D), X(D.message || "Failed to speak text");
|
|
7031
7061
|
}
|
|
7032
|
-
}, [$,
|
|
7033
|
-
p.current && (p.current.stopSpeaking(), p.current.setSlowdownRate && p.current.setSlowdownRate(1),
|
|
7034
|
-
}, []), 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(() => {
|
|
7035
7065
|
if (p.current && p.current.pauseSpeaking) {
|
|
7036
7066
|
const L = p.current;
|
|
7037
7067
|
if (L.isSpeaking || L.audioPlaylist && L.audioPlaylist.length > 0 || L.speechQueue && L.speechQueue.length > 0) {
|
|
7038
7068
|
y.current && (clearInterval(y.current), y.current = null);
|
|
7039
|
-
let
|
|
7040
|
-
if (
|
|
7041
|
-
const J =
|
|
7042
|
-
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)) {
|
|
7043
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(" ");
|
|
7044
|
-
be && be.trim() && (
|
|
7074
|
+
be && be.trim() && (D = be.trim());
|
|
7045
7075
|
}
|
|
7046
7076
|
}
|
|
7047
|
-
|
|
7048
|
-
remainingText:
|
|
7049
|
-
originalText:
|
|
7050
|
-
options:
|
|
7051
|
-
}), 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);
|
|
7052
7082
|
}
|
|
7053
7083
|
}
|
|
7054
|
-
}, []), q =
|
|
7084
|
+
}, []), q = P(async () => {
|
|
7055
7085
|
if (!p.current || !ae)
|
|
7056
7086
|
return;
|
|
7057
|
-
let L = "",
|
|
7058
|
-
if (
|
|
7059
|
-
L =
|
|
7060
|
-
else if (
|
|
7061
|
-
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 || {};
|
|
7062
7092
|
else {
|
|
7063
|
-
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;
|
|
7064
7094
|
return;
|
|
7065
7095
|
}
|
|
7066
|
-
pe(!1),
|
|
7067
|
-
const
|
|
7068
|
-
...
|
|
7069
|
-
lipsyncLang:
|
|
7096
|
+
pe(!1), T.current = !1, await M();
|
|
7097
|
+
const D = {
|
|
7098
|
+
...B,
|
|
7099
|
+
lipsyncLang: B.lipsyncLang || v.lipsyncLang || "en"
|
|
7070
7100
|
};
|
|
7071
7101
|
try {
|
|
7072
|
-
await
|
|
7102
|
+
await W(L, D);
|
|
7073
7103
|
} catch (J) {
|
|
7074
|
-
console.error("Error resuming speech:", J), pe(!1),
|
|
7104
|
+
console.error("Error resuming speech:", J), pe(!1), T.current = !1;
|
|
7075
7105
|
}
|
|
7076
|
-
}, [
|
|
7106
|
+
}, [M, ae, W, v]), Le = P((L) => {
|
|
7077
7107
|
p.current && p.current.setMood(L);
|
|
7078
|
-
}, []), we =
|
|
7108
|
+
}, []), we = P((L) => {
|
|
7079
7109
|
p.current && p.current.setSlowdownRate && p.current.setSlowdownRate(L);
|
|
7080
|
-
}, []), C =
|
|
7110
|
+
}, []), C = P((L, B = !1) => {
|
|
7081
7111
|
if (p.current && p.current.playAnimation) {
|
|
7082
|
-
if (
|
|
7112
|
+
if (f && f[L] && (L = f[L]), p.current.setShowFullAvatar)
|
|
7083
7113
|
try {
|
|
7084
|
-
p.current.setShowFullAvatar(
|
|
7114
|
+
p.current.setShowFullAvatar(H.current);
|
|
7085
7115
|
} catch (J) {
|
|
7086
7116
|
console.warn("Error setting full body mode:", J);
|
|
7087
7117
|
}
|
|
7088
7118
|
if (L.includes("."))
|
|
7089
7119
|
try {
|
|
7090
|
-
p.current.playAnimation(L, null, 10, 0, 0.01,
|
|
7120
|
+
p.current.playAnimation(L, null, 10, 0, 0.01, B);
|
|
7091
7121
|
} catch (J) {
|
|
7092
7122
|
console.warn(`Failed to play ${L}:`, J);
|
|
7093
7123
|
try {
|
|
@@ -7101,7 +7131,7 @@ const Ve = Me(({
|
|
|
7101
7131
|
let ge = !1;
|
|
7102
7132
|
for (const Y of J)
|
|
7103
7133
|
try {
|
|
7104
|
-
p.current.playAnimation(L + Y, null, 10, 0, 0.01,
|
|
7134
|
+
p.current.playAnimation(L + Y, null, 10, 0, 0.01, B), ge = !0;
|
|
7105
7135
|
break;
|
|
7106
7136
|
} catch {
|
|
7107
7137
|
}
|
|
@@ -7115,35 +7145,35 @@ const Ve = Me(({
|
|
|
7115
7145
|
}
|
|
7116
7146
|
}
|
|
7117
7147
|
}
|
|
7118
|
-
}, [
|
|
7148
|
+
}, [f]), ne = P(() => {
|
|
7119
7149
|
p.current && p.current.onResize && p.current.onResize();
|
|
7120
7150
|
}, []);
|
|
7121
|
-
return Ee(
|
|
7122
|
-
speakText:
|
|
7151
|
+
return Ee(R, () => ({
|
|
7152
|
+
speakText: W,
|
|
7123
7153
|
stopSpeaking: K,
|
|
7124
7154
|
pauseSpeaking: j,
|
|
7125
7155
|
resumeSpeaking: q,
|
|
7126
|
-
resumeAudioContext:
|
|
7156
|
+
resumeAudioContext: M,
|
|
7127
7157
|
setMood: Le,
|
|
7128
7158
|
setTimingAdjustment: we,
|
|
7129
7159
|
playAnimation: C,
|
|
7130
7160
|
isReady: $,
|
|
7131
7161
|
isPaused: ae,
|
|
7132
7162
|
talkingHead: p.current,
|
|
7133
|
-
handleResize:
|
|
7163
|
+
handleResize: ne,
|
|
7134
7164
|
setBodyMovement: (L) => {
|
|
7135
7165
|
if (p.current && p.current.setShowFullAvatar && p.current.setBodyMovement)
|
|
7136
7166
|
try {
|
|
7137
|
-
p.current.setShowFullAvatar(
|
|
7138
|
-
} catch (
|
|
7139
|
-
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);
|
|
7140
7170
|
}
|
|
7141
7171
|
},
|
|
7142
7172
|
setMovementIntensity: (L) => p.current?.setMovementIntensity(L),
|
|
7143
7173
|
playRandomDance: () => {
|
|
7144
7174
|
if (p.current && p.current.setShowFullAvatar && p.current.playRandomDance)
|
|
7145
7175
|
try {
|
|
7146
|
-
p.current.setShowFullAvatar(
|
|
7176
|
+
p.current.setShowFullAvatar(H.current), p.current.playRandomDance();
|
|
7147
7177
|
} catch (L) {
|
|
7148
7178
|
console.warn("Error playing random dance:", L);
|
|
7149
7179
|
}
|
|
@@ -7151,15 +7181,15 @@ const Ve = Me(({
|
|
|
7151
7181
|
playReaction: (L) => {
|
|
7152
7182
|
if (p.current && p.current.setShowFullAvatar && p.current.playReaction)
|
|
7153
7183
|
try {
|
|
7154
|
-
p.current.setShowFullAvatar(
|
|
7155
|
-
} catch (
|
|
7156
|
-
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);
|
|
7157
7187
|
}
|
|
7158
7188
|
},
|
|
7159
7189
|
playCelebration: () => {
|
|
7160
7190
|
if (p.current && p.current.setShowFullAvatar && p.current.playCelebration)
|
|
7161
7191
|
try {
|
|
7162
|
-
p.current.setShowFullAvatar(
|
|
7192
|
+
p.current.setShowFullAvatar(H.current), p.current.playCelebration();
|
|
7163
7193
|
} catch (L) {
|
|
7164
7194
|
console.warn("Error playing celebration:", L);
|
|
7165
7195
|
}
|
|
@@ -7167,9 +7197,9 @@ const Ve = Me(({
|
|
|
7167
7197
|
setShowFullAvatar: (L) => {
|
|
7168
7198
|
if (p.current && p.current.setShowFullAvatar)
|
|
7169
7199
|
try {
|
|
7170
|
-
|
|
7171
|
-
} catch (
|
|
7172
|
-
console.warn("Error setting showFullAvatar:",
|
|
7200
|
+
H.current = L, p.current.setShowFullAvatar(L);
|
|
7201
|
+
} catch (B) {
|
|
7202
|
+
console.warn("Error setting showFullAvatar:", B);
|
|
7173
7203
|
}
|
|
7174
7204
|
},
|
|
7175
7205
|
lockAvatarPosition: () => {
|
|
@@ -7202,7 +7232,7 @@ const Ve = Me(({
|
|
|
7202
7232
|
/* @__PURE__ */ me(
|
|
7203
7233
|
"div",
|
|
7204
7234
|
{
|
|
7205
|
-
ref:
|
|
7235
|
+
ref: F,
|
|
7206
7236
|
className: "talking-head-viewer",
|
|
7207
7237
|
style: {
|
|
7208
7238
|
width: "100%",
|
|
@@ -7238,7 +7268,7 @@ const Ve = Me(({
|
|
|
7238
7268
|
});
|
|
7239
7269
|
Ve.displayName = "TalkingHeadAvatar";
|
|
7240
7270
|
const pt = Me(({
|
|
7241
|
-
text:
|
|
7271
|
+
text: Z = "Hello! I'm a talking avatar. How are you today?",
|
|
7242
7272
|
onLoading: t = () => {
|
|
7243
7273
|
},
|
|
7244
7274
|
onError: e = () => {
|
|
@@ -7249,23 +7279,23 @@ const pt = Me(({
|
|
|
7249
7279
|
style: s = {},
|
|
7250
7280
|
avatarConfig: o = {}
|
|
7251
7281
|
}, l) => {
|
|
7252
|
-
const u = N(null), r = N(null), [h, a] = ce(!0), [c, d] = ce(null), [g, x] = ce(!1),
|
|
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" ? {
|
|
7253
7283
|
endpoint: "",
|
|
7254
7284
|
apiKey: null,
|
|
7255
7285
|
defaultVoice: "Google US English"
|
|
7256
7286
|
} : {
|
|
7257
|
-
...
|
|
7287
|
+
...f,
|
|
7258
7288
|
// Override API key if provided via avatarConfig
|
|
7259
|
-
apiKey: o.ttsApiKey !== void 0 && o.ttsApiKey !== null ? o.ttsApiKey :
|
|
7289
|
+
apiKey: o.ttsApiKey !== void 0 && o.ttsApiKey !== null ? o.ttsApiKey : f.apiKey,
|
|
7260
7290
|
// Override endpoint for ElevenLabs if service is explicitly set
|
|
7261
|
-
endpoint:
|
|
7291
|
+
endpoint: R === "elevenlabs" && o.ttsApiKey ? "https://api.elevenlabs.io/v1/text-to-speech" : f.endpoint
|
|
7262
7292
|
}, p = {
|
|
7263
7293
|
url: "/avatars/brunette.glb",
|
|
7264
7294
|
// Use brunette avatar (working glTF file)
|
|
7265
7295
|
body: "F",
|
|
7266
7296
|
avatarMood: "neutral",
|
|
7267
|
-
ttsLang:
|
|
7268
|
-
ttsVoice: o.ttsVoice ||
|
|
7297
|
+
ttsLang: R === "browser" ? "en-US" : "en",
|
|
7298
|
+
ttsVoice: o.ttsVoice || F.defaultVoice,
|
|
7269
7299
|
lipsyncLang: "en",
|
|
7270
7300
|
// English lip-sync
|
|
7271
7301
|
showFullAvatar: !0,
|
|
@@ -7273,16 +7303,16 @@ const pt = Me(({
|
|
|
7273
7303
|
bodyMovement: "idle",
|
|
7274
7304
|
movementIntensity: 0.5,
|
|
7275
7305
|
...o
|
|
7276
|
-
},
|
|
7277
|
-
ttsEndpoint:
|
|
7278
|
-
ttsApikey:
|
|
7279
|
-
ttsService:
|
|
7306
|
+
}, H = {
|
|
7307
|
+
ttsEndpoint: F.endpoint,
|
|
7308
|
+
ttsApikey: F.apiKey,
|
|
7309
|
+
ttsService: R,
|
|
7280
7310
|
lipsyncModules: ["en"],
|
|
7281
7311
|
cameraView: "upper"
|
|
7282
|
-
},
|
|
7312
|
+
}, k = P(async () => {
|
|
7283
7313
|
if (!(!u.current || r.current))
|
|
7284
7314
|
try {
|
|
7285
|
-
if (a(!0), d(null), r.current = new
|
|
7315
|
+
if (a(!0), d(null), r.current = new Be(u.current, H), await r.current.showAvatar(p, (_) => {
|
|
7286
7316
|
if (_.lengthComputable) {
|
|
7287
7317
|
const X = Math.min(100, Math.round(_.loaded / _.total * 100));
|
|
7288
7318
|
t(X);
|
|
@@ -7305,37 +7335,37 @@ const pt = Me(({
|
|
|
7305
7335
|
console.warn("Error setting full body mode on initialization:", _);
|
|
7306
7336
|
}
|
|
7307
7337
|
a(!1), x(!0), n(r.current);
|
|
7308
|
-
const
|
|
7338
|
+
const G = () => {
|
|
7309
7339
|
document.visibilityState === "visible" ? r.current?.start() : r.current?.stop();
|
|
7310
7340
|
};
|
|
7311
|
-
return document.addEventListener("visibilitychange",
|
|
7312
|
-
document.removeEventListener("visibilitychange",
|
|
7341
|
+
return document.addEventListener("visibilitychange", G), () => {
|
|
7342
|
+
document.removeEventListener("visibilitychange", G);
|
|
7313
7343
|
};
|
|
7314
7344
|
} catch (S) {
|
|
7315
7345
|
console.error("Error initializing TalkingHead:", S), d(S.message || "Failed to initialize avatar"), a(!1), e(S);
|
|
7316
7346
|
}
|
|
7317
7347
|
}, []);
|
|
7318
|
-
de(() => (
|
|
7348
|
+
de(() => (k(), () => {
|
|
7319
7349
|
r.current && (r.current.stop(), r.current.dispose(), r.current = null);
|
|
7320
|
-
}), [
|
|
7321
|
-
const y =
|
|
7350
|
+
}), [k]);
|
|
7351
|
+
const y = P((S) => {
|
|
7322
7352
|
if (r.current && g)
|
|
7323
7353
|
try {
|
|
7324
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(() => {
|
|
7325
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");
|
|
7326
7356
|
}, 500));
|
|
7327
|
-
} catch (
|
|
7328
|
-
console.error("Error speaking text:",
|
|
7357
|
+
} catch (G) {
|
|
7358
|
+
console.error("Error speaking text:", G), d(G.message || "Failed to speak text");
|
|
7329
7359
|
}
|
|
7330
7360
|
else
|
|
7331
7361
|
console.warn("Avatar not ready for speaking. isReady:", g, "talkingHeadRef:", !!r.current);
|
|
7332
|
-
}, [g, p]),
|
|
7362
|
+
}, [g, p]), T = P(() => {
|
|
7333
7363
|
r.current && (r.current.stopSpeaking(), r.current.setSlowdownRate && (r.current.setSlowdownRate(1), console.log("Reset timing to normal")));
|
|
7334
|
-
}, []),
|
|
7364
|
+
}, []), E = P((S) => {
|
|
7335
7365
|
r.current && r.current.setMood(S);
|
|
7336
|
-
}, []),
|
|
7366
|
+
}, []), O = P((S) => {
|
|
7337
7367
|
r.current && r.current.setSlowdownRate && (r.current.setSlowdownRate(S), console.log("Timing adjustment set to:", S));
|
|
7338
|
-
}, []),
|
|
7368
|
+
}, []), te = P((S, G = !1) => {
|
|
7339
7369
|
if (r.current && r.current.playAnimation) {
|
|
7340
7370
|
if (r.current.setShowFullAvatar)
|
|
7341
7371
|
try {
|
|
@@ -7345,7 +7375,7 @@ const pt = Me(({
|
|
|
7345
7375
|
}
|
|
7346
7376
|
if (S.includes("."))
|
|
7347
7377
|
try {
|
|
7348
|
-
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);
|
|
7349
7379
|
} catch (X) {
|
|
7350
7380
|
console.log(`Failed to play ${S}:`, X);
|
|
7351
7381
|
try {
|
|
@@ -7359,7 +7389,7 @@ const pt = Me(({
|
|
|
7359
7389
|
let $ = !1;
|
|
7360
7390
|
for (const se of X)
|
|
7361
7391
|
try {
|
|
7362
|
-
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;
|
|
7363
7393
|
break;
|
|
7364
7394
|
} catch {
|
|
7365
7395
|
console.log(`Failed to play ${S}${se}, trying next format...`);
|
|
@@ -7378,18 +7408,18 @@ const pt = Me(({
|
|
|
7378
7408
|
}, []);
|
|
7379
7409
|
return Ee(l, () => ({
|
|
7380
7410
|
speakText: y,
|
|
7381
|
-
stopSpeaking:
|
|
7382
|
-
setMood:
|
|
7383
|
-
setTimingAdjustment:
|
|
7384
|
-
playAnimation:
|
|
7411
|
+
stopSpeaking: T,
|
|
7412
|
+
setMood: E,
|
|
7413
|
+
setTimingAdjustment: O,
|
|
7414
|
+
playAnimation: te,
|
|
7385
7415
|
isReady: g,
|
|
7386
7416
|
talkingHead: r.current,
|
|
7387
7417
|
setBodyMovement: (S) => {
|
|
7388
7418
|
if (r.current && r.current.setShowFullAvatar && r.current.setBodyMovement)
|
|
7389
7419
|
try {
|
|
7390
7420
|
r.current.setShowFullAvatar(!0), r.current.setBodyMovement(S), console.log("Body movement set with full body mode:", S);
|
|
7391
|
-
} catch (
|
|
7392
|
-
console.warn("Error setting body movement:",
|
|
7421
|
+
} catch (G) {
|
|
7422
|
+
console.warn("Error setting body movement:", G);
|
|
7393
7423
|
}
|
|
7394
7424
|
},
|
|
7395
7425
|
setMovementIntensity: (S) => r.current?.setMovementIntensity(S),
|
|
@@ -7405,8 +7435,8 @@ const pt = Me(({
|
|
|
7405
7435
|
if (r.current && r.current.setShowFullAvatar && r.current.playReaction)
|
|
7406
7436
|
try {
|
|
7407
7437
|
r.current.setShowFullAvatar(!0), r.current.playReaction(S), console.log("Reaction played with full body mode:", S);
|
|
7408
|
-
} catch (
|
|
7409
|
-
console.warn("Error playing reaction:",
|
|
7438
|
+
} catch (G) {
|
|
7439
|
+
console.warn("Error playing reaction:", G);
|
|
7410
7440
|
}
|
|
7411
7441
|
},
|
|
7412
7442
|
playCelebration: () => {
|
|
@@ -7421,8 +7451,8 @@ const pt = Me(({
|
|
|
7421
7451
|
if (r.current && r.current.setShowFullAvatar)
|
|
7422
7452
|
try {
|
|
7423
7453
|
r.current.setShowFullAvatar(S), console.log("Show full avatar set to:", S);
|
|
7424
|
-
} catch (
|
|
7425
|
-
console.warn("Error setting showFullAvatar:",
|
|
7454
|
+
} catch (G) {
|
|
7455
|
+
console.warn("Error setting showFullAvatar:", G);
|
|
7426
7456
|
}
|
|
7427
7457
|
},
|
|
7428
7458
|
lockAvatarPosition: () => {
|
|
@@ -7479,7 +7509,7 @@ const pt = Me(({
|
|
|
7479
7509
|
});
|
|
7480
7510
|
pt.displayName = "TalkingHeadComponent";
|
|
7481
7511
|
const gt = Me(({
|
|
7482
|
-
text:
|
|
7512
|
+
text: Z = null,
|
|
7483
7513
|
avatarUrl: t = "/avatars/brunette.glb",
|
|
7484
7514
|
avatarBody: e = "F",
|
|
7485
7515
|
mood: n = "neutral",
|
|
@@ -7499,66 +7529,66 @@ const gt = Me(({
|
|
|
7499
7529
|
},
|
|
7500
7530
|
onSpeechEnd: x = () => {
|
|
7501
7531
|
},
|
|
7502
|
-
className:
|
|
7503
|
-
style:
|
|
7504
|
-
animations:
|
|
7532
|
+
className: f = "",
|
|
7533
|
+
style: R = {},
|
|
7534
|
+
animations: F = {},
|
|
7505
7535
|
autoSpeak: p = !1
|
|
7506
|
-
},
|
|
7507
|
-
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);
|
|
7508
7538
|
de(() => {
|
|
7509
|
-
|
|
7539
|
+
te.current = ee;
|
|
7510
7540
|
}, [ee]), de(() => {
|
|
7511
|
-
|
|
7541
|
+
T.current = h;
|
|
7512
7542
|
}, [h]);
|
|
7513
|
-
const
|
|
7514
|
-
let
|
|
7515
|
-
v === "browser" ?
|
|
7543
|
+
const U = Fe(), v = s || U.service;
|
|
7544
|
+
let I;
|
|
7545
|
+
v === "browser" ? I = {
|
|
7516
7546
|
service: "browser",
|
|
7517
7547
|
endpoint: "",
|
|
7518
7548
|
apiKey: null,
|
|
7519
7549
|
defaultVoice: "Google US English"
|
|
7520
|
-
} : v === "elevenlabs" ?
|
|
7550
|
+
} : v === "elevenlabs" ? I = {
|
|
7521
7551
|
service: "elevenlabs",
|
|
7522
7552
|
endpoint: "https://api.elevenlabs.io/v1/text-to-speech",
|
|
7523
|
-
apiKey: l ||
|
|
7524
|
-
defaultVoice: o ||
|
|
7525
|
-
voices:
|
|
7526
|
-
} : v === "deepgram" ?
|
|
7553
|
+
apiKey: l || U.apiKey,
|
|
7554
|
+
defaultVoice: o || U.defaultVoice || Ie.defaultVoice,
|
|
7555
|
+
voices: U.voices || Ie.voices
|
|
7556
|
+
} : v === "deepgram" ? I = {
|
|
7527
7557
|
service: "deepgram",
|
|
7528
7558
|
endpoint: "https://api.deepgram.com/v1/speak",
|
|
7529
|
-
apiKey: l ||
|
|
7530
|
-
defaultVoice: o ||
|
|
7531
|
-
voices:
|
|
7532
|
-
} :
|
|
7533
|
-
...
|
|
7534
|
-
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
|
|
7535
7565
|
};
|
|
7536
|
-
const
|
|
7566
|
+
const w = {
|
|
7537
7567
|
url: t,
|
|
7538
7568
|
body: e,
|
|
7539
7569
|
avatarMood: n,
|
|
7540
7570
|
ttsLang: v === "browser" ? "en-US" : i,
|
|
7541
|
-
ttsVoice: o ||
|
|
7571
|
+
ttsVoice: o || I.defaultVoice,
|
|
7542
7572
|
lipsyncLang: "en",
|
|
7543
7573
|
showFullAvatar: h,
|
|
7544
7574
|
bodyMovement: u,
|
|
7545
7575
|
movementIntensity: r
|
|
7546
|
-
},
|
|
7547
|
-
ttsEndpoint:
|
|
7548
|
-
ttsApikey:
|
|
7576
|
+
}, M = {
|
|
7577
|
+
ttsEndpoint: I.endpoint,
|
|
7578
|
+
ttsApikey: I.apiKey,
|
|
7549
7579
|
ttsService: v,
|
|
7550
7580
|
lipsyncModules: ["en"],
|
|
7551
7581
|
cameraView: a
|
|
7552
|
-
},
|
|
7553
|
-
if (!(!
|
|
7582
|
+
}, W = P(async () => {
|
|
7583
|
+
if (!(!k.current || y.current))
|
|
7554
7584
|
try {
|
|
7555
|
-
X(!0), se(null), y.current = new
|
|
7556
|
-
url:
|
|
7557
|
-
body:
|
|
7558
|
-
avatarMood:
|
|
7559
|
-
}), await y.current.showAvatar(
|
|
7560
|
-
if (
|
|
7561
|
-
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));
|
|
7562
7592
|
d(L);
|
|
7563
7593
|
}
|
|
7564
7594
|
}), y.current?.avatar && console.log("Avatar body after initialization:", y.current.avatar.body), X(!1), pe(!0), c(y.current);
|
|
@@ -7572,10 +7602,10 @@ const gt = Me(({
|
|
|
7572
7602
|
console.error("Error initializing TalkingHead:", C), se(C.message || "Failed to initialize avatar"), X(!1), g(C);
|
|
7573
7603
|
}
|
|
7574
7604
|
}, []);
|
|
7575
|
-
de(() => (
|
|
7605
|
+
de(() => (W(), () => {
|
|
7576
7606
|
y.current && (y.current.stop(), y.current.dispose(), y.current = null);
|
|
7577
|
-
}), [
|
|
7578
|
-
const K =
|
|
7607
|
+
}), [W]);
|
|
7608
|
+
const K = P(async () => {
|
|
7579
7609
|
if (y.current)
|
|
7580
7610
|
try {
|
|
7581
7611
|
const C = y.current.audioCtx || y.current.audioContext;
|
|
@@ -7583,7 +7613,7 @@ const gt = Me(({
|
|
|
7583
7613
|
} catch (C) {
|
|
7584
7614
|
console.warn("Failed to resume audio context:", C);
|
|
7585
7615
|
}
|
|
7586
|
-
}, []), j =
|
|
7616
|
+
}, []), j = P(async (C, ne = {}) => {
|
|
7587
7617
|
if (!y.current || !ae) {
|
|
7588
7618
|
console.warn("Avatar not ready for speaking");
|
|
7589
7619
|
return;
|
|
@@ -7592,53 +7622,53 @@ const gt = Me(({
|
|
|
7592
7622
|
console.warn("No text provided to speak");
|
|
7593
7623
|
return;
|
|
7594
7624
|
}
|
|
7595
|
-
await K(), S.current = { remainingText: null, originalText: null, options: null },
|
|
7596
|
-
const L = C.split(/[.!?]+/).filter((
|
|
7597
|
-
|
|
7598
|
-
const
|
|
7599
|
-
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",
|
|
7600
7630
|
onSpeechEnd: () => {
|
|
7601
|
-
|
|
7631
|
+
O.current && (clearInterval(O.current), O.current = null), ne.onSpeechEnd && ne.onSpeechEnd(), x();
|
|
7602
7632
|
}
|
|
7603
7633
|
};
|
|
7604
7634
|
try {
|
|
7605
|
-
y.current.speakText(C,
|
|
7606
|
-
} catch (
|
|
7607
|
-
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");
|
|
7608
7638
|
}
|
|
7609
7639
|
}, [ae, x, K]);
|
|
7610
7640
|
de(() => {
|
|
7611
|
-
ae &&
|
|
7612
|
-
}, [ae,
|
|
7613
|
-
const q =
|
|
7641
|
+
ae && Z && p && y.current && j(Z);
|
|
7642
|
+
}, [ae, Z, p, j]);
|
|
7643
|
+
const q = P(() => {
|
|
7614
7644
|
if (y.current)
|
|
7615
7645
|
try {
|
|
7616
|
-
const C = y.current.isSpeaking || !1,
|
|
7617
|
-
if (C ||
|
|
7618
|
-
|
|
7619
|
-
let
|
|
7620
|
-
L.length > 0 && (
|
|
7621
|
-
remainingText:
|
|
7622
|
-
originalText:
|
|
7623
|
-
options:
|
|
7624
|
-
}, 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;
|
|
7625
7655
|
}
|
|
7626
7656
|
} catch (C) {
|
|
7627
7657
|
console.warn("Error pausing speech:", C);
|
|
7628
7658
|
}
|
|
7629
|
-
}, []), Le =
|
|
7659
|
+
}, []), Le = P(async () => {
|
|
7630
7660
|
if (!(!y.current || !ee))
|
|
7631
7661
|
try {
|
|
7632
|
-
await K(), le(!1),
|
|
7633
|
-
const C = S.current?.remainingText,
|
|
7634
|
-
|
|
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);
|
|
7635
7665
|
} catch (C) {
|
|
7636
|
-
console.warn("Error resuming speech:", C), le(!1),
|
|
7666
|
+
console.warn("Error resuming speech:", C), le(!1), te.current = !1;
|
|
7637
7667
|
}
|
|
7638
|
-
}, [ee, j, K]), we =
|
|
7639
|
-
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);
|
|
7640
7670
|
}, []);
|
|
7641
|
-
return Ee(
|
|
7671
|
+
return Ee(H, () => ({
|
|
7642
7672
|
speakText: j,
|
|
7643
7673
|
pauseSpeaking: q,
|
|
7644
7674
|
resumeSpeaking: Le,
|
|
@@ -7649,21 +7679,21 @@ const gt = Me(({
|
|
|
7649
7679
|
setBodyMovement: (C) => {
|
|
7650
7680
|
y.current && y.current.setBodyMovement(C);
|
|
7651
7681
|
},
|
|
7652
|
-
playAnimation: (C,
|
|
7653
|
-
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);
|
|
7654
7684
|
},
|
|
7655
7685
|
playReaction: (C) => y.current?.playReaction(C),
|
|
7656
7686
|
playCelebration: () => y.current?.playCelebration(),
|
|
7657
7687
|
setShowFullAvatar: (C) => {
|
|
7658
|
-
y.current && (
|
|
7688
|
+
y.current && (T.current = C, y.current.setShowFullAvatar(C));
|
|
7659
7689
|
},
|
|
7660
7690
|
isReady: ae,
|
|
7661
7691
|
talkingHead: y.current
|
|
7662
|
-
})), /* @__PURE__ */ Pe("div", { className: `simple-talking-avatar-container ${
|
|
7692
|
+
})), /* @__PURE__ */ Pe("div", { className: `simple-talking-avatar-container ${f}`, style: R, children: [
|
|
7663
7693
|
/* @__PURE__ */ me(
|
|
7664
7694
|
"div",
|
|
7665
7695
|
{
|
|
7666
|
-
ref:
|
|
7696
|
+
ref: k,
|
|
7667
7697
|
className: "talking-head-viewer",
|
|
7668
7698
|
style: {
|
|
7669
7699
|
width: "100%",
|
|
@@ -7697,7 +7727,7 @@ const gt = Me(({
|
|
|
7697
7727
|
});
|
|
7698
7728
|
gt.displayName = "SimpleTalkingAvatar";
|
|
7699
7729
|
const yt = Me(({
|
|
7700
|
-
curriculumData:
|
|
7730
|
+
curriculumData: Z = null,
|
|
7701
7731
|
avatarConfig: t = {},
|
|
7702
7732
|
animations: e = {},
|
|
7703
7733
|
onLessonStart: n = () => {
|
|
@@ -7728,12 +7758,12 @@ const yt = Me(({
|
|
|
7728
7758
|
onQuestionAnswer: s,
|
|
7729
7759
|
onCurriculumComplete: o,
|
|
7730
7760
|
onCustomAction: l
|
|
7731
|
-
}), d = N(null), g = N(null), x = N(null),
|
|
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 || {
|
|
7732
7762
|
title: "Default Curriculum",
|
|
7733
7763
|
description: "No curriculum data provided",
|
|
7734
7764
|
language: "en",
|
|
7735
7765
|
modules: []
|
|
7736
|
-
}),
|
|
7766
|
+
}), k = N({
|
|
7737
7767
|
avatarUrl: t.avatarUrl || "/avatars/brunette.glb",
|
|
7738
7768
|
avatarBody: t.avatarBody || "F",
|
|
7739
7769
|
mood: t.mood || "happy",
|
|
@@ -7756,12 +7786,12 @@ const yt = Me(({
|
|
|
7756
7786
|
onCustomAction: l
|
|
7757
7787
|
};
|
|
7758
7788
|
}, [n, i, s, o, l]), de(() => {
|
|
7759
|
-
|
|
7789
|
+
H.current = Z?.curriculum || {
|
|
7760
7790
|
title: "Default Curriculum",
|
|
7761
7791
|
description: "No curriculum data provided",
|
|
7762
7792
|
language: "en",
|
|
7763
7793
|
modules: []
|
|
7764
|
-
},
|
|
7794
|
+
}, k.current = {
|
|
7765
7795
|
avatarUrl: t.avatarUrl || "/avatars/brunette.glb",
|
|
7766
7796
|
avatarBody: t.avatarBody || "F",
|
|
7767
7797
|
mood: t.mood || "happy",
|
|
@@ -7775,12 +7805,12 @@ const yt = Me(({
|
|
|
7775
7805
|
animations: e,
|
|
7776
7806
|
lipsyncLang: "en"
|
|
7777
7807
|
};
|
|
7778
|
-
}, [
|
|
7779
|
-
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(() => {
|
|
7780
7810
|
a.current.lessonCompleted = !0, a.current.isQuestionMode = !1;
|
|
7781
7811
|
const v = a.current.totalQuestions > 0 ? Math.round(a.current.score / a.current.totalQuestions * 100) : 100;
|
|
7782
|
-
let
|
|
7783
|
-
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({
|
|
7784
7814
|
moduleIndex: a.current.currentModuleIndex,
|
|
7785
7815
|
lessonIndex: a.current.currentLessonIndex,
|
|
7786
7816
|
score: a.current.score,
|
|
@@ -7800,8 +7830,8 @@ const yt = Me(({
|
|
|
7800
7830
|
} catch {
|
|
7801
7831
|
h.current.playCelebration();
|
|
7802
7832
|
}
|
|
7803
|
-
const
|
|
7804
|
-
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, {
|
|
7805
7835
|
lipsyncLang: q.lipsyncLang,
|
|
7806
7836
|
onSpeechEnd: () => {
|
|
7807
7837
|
c.current.onCustomAction({
|
|
@@ -7816,12 +7846,12 @@ const yt = Me(({
|
|
|
7816
7846
|
}
|
|
7817
7847
|
});
|
|
7818
7848
|
}
|
|
7819
|
-
}, [e.lessonComplete]),
|
|
7849
|
+
}, [e.lessonComplete]), te = P(() => {
|
|
7820
7850
|
a.current.curriculumCompleted = !0;
|
|
7821
|
-
const v =
|
|
7851
|
+
const v = H.current || { modules: [] };
|
|
7822
7852
|
if (c.current.onCurriculumComplete({
|
|
7823
7853
|
modules: v.modules.length,
|
|
7824
|
-
totalLessons: v.modules.reduce((
|
|
7854
|
+
totalLessons: v.modules.reduce((I, w) => I + w.lessons.length, 0)
|
|
7825
7855
|
}), h.current) {
|
|
7826
7856
|
if (h.current.setMood("celebrating"), e.curriculumComplete)
|
|
7827
7857
|
try {
|
|
@@ -7829,99 +7859,99 @@ const yt = Me(({
|
|
|
7829
7859
|
} catch {
|
|
7830
7860
|
h.current.playCelebration();
|
|
7831
7861
|
}
|
|
7832
|
-
const
|
|
7833
|
-
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 });
|
|
7834
7864
|
}
|
|
7835
|
-
}, [e.curriculumComplete]), S =
|
|
7865
|
+
}, [e.curriculumComplete]), S = P(() => {
|
|
7836
7866
|
const v = y();
|
|
7837
7867
|
a.current.isQuestionMode = !0, a.current.currentQuestionIndex = 0, a.current.totalQuestions = v?.questions?.length || 0, a.current.score = 0;
|
|
7838
|
-
const
|
|
7839
|
-
|
|
7868
|
+
const I = T();
|
|
7869
|
+
I && c.current.onCustomAction({
|
|
7840
7870
|
type: "questionStart",
|
|
7841
7871
|
moduleIndex: a.current.currentModuleIndex,
|
|
7842
7872
|
lessonIndex: a.current.currentLessonIndex,
|
|
7843
7873
|
questionIndex: a.current.currentQuestionIndex,
|
|
7844
7874
|
totalQuestions: a.current.totalQuestions,
|
|
7845
|
-
question:
|
|
7875
|
+
question: I,
|
|
7846
7876
|
score: a.current.score
|
|
7847
7877
|
});
|
|
7848
|
-
const
|
|
7849
|
-
if (!h.current || !
|
|
7878
|
+
const w = () => {
|
|
7879
|
+
if (!h.current || !I) return;
|
|
7850
7880
|
if (h.current.setMood("happy"), e.questionStart)
|
|
7851
7881
|
try {
|
|
7852
7882
|
h.current.playAnimation(e.questionStart, !0);
|
|
7853
|
-
} catch (
|
|
7854
|
-
console.warn("Failed to play questionStart animation:",
|
|
7883
|
+
} catch (W) {
|
|
7884
|
+
console.warn("Failed to play questionStart animation:", W);
|
|
7855
7885
|
}
|
|
7856
|
-
const
|
|
7857
|
-
|
|
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 });
|
|
7858
7888
|
};
|
|
7859
|
-
if (h.current && h.current.isReady &&
|
|
7860
|
-
|
|
7889
|
+
if (h.current && h.current.isReady && I)
|
|
7890
|
+
w();
|
|
7861
7891
|
else if (h.current && h.current.isReady) {
|
|
7862
|
-
const
|
|
7863
|
-
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 });
|
|
7864
7894
|
} else {
|
|
7865
|
-
const
|
|
7866
|
-
h.current && h.current.isReady && (clearInterval(
|
|
7895
|
+
const M = setInterval(() => {
|
|
7896
|
+
h.current && h.current.isReady && (clearInterval(M), I && w());
|
|
7867
7897
|
}, 100);
|
|
7868
7898
|
setTimeout(() => {
|
|
7869
|
-
clearInterval(
|
|
7899
|
+
clearInterval(M);
|
|
7870
7900
|
}, 5e3);
|
|
7871
7901
|
}
|
|
7872
|
-
}, [e.questionStart, y,
|
|
7902
|
+
}, [e.questionStart, y, T]), G = P(() => {
|
|
7873
7903
|
const v = y();
|
|
7874
7904
|
if (a.current.currentQuestionIndex < (v?.questions?.length || 0) - 1) {
|
|
7875
7905
|
h.current && h.current.stopSpeaking && h.current.stopSpeaking(), a.current.currentQuestionIndex += 1;
|
|
7876
|
-
const
|
|
7877
|
-
|
|
7906
|
+
const I = T();
|
|
7907
|
+
I && c.current.onCustomAction({
|
|
7878
7908
|
type: "nextQuestion",
|
|
7879
7909
|
moduleIndex: a.current.currentModuleIndex,
|
|
7880
7910
|
lessonIndex: a.current.currentLessonIndex,
|
|
7881
7911
|
questionIndex: a.current.currentQuestionIndex,
|
|
7882
7912
|
totalQuestions: a.current.totalQuestions,
|
|
7883
|
-
question:
|
|
7913
|
+
question: I,
|
|
7884
7914
|
score: a.current.score
|
|
7885
7915
|
});
|
|
7886
|
-
const
|
|
7887
|
-
if (!h.current || !
|
|
7916
|
+
const w = () => {
|
|
7917
|
+
if (!h.current || !I) return;
|
|
7888
7918
|
if (h.current.setMood("happy"), h.current.setBodyMovement("idle"), e.nextQuestion)
|
|
7889
7919
|
try {
|
|
7890
7920
|
h.current.playAnimation(e.nextQuestion, !0);
|
|
7891
7921
|
} catch (q) {
|
|
7892
7922
|
console.warn("Failed to play nextQuestion animation:", q);
|
|
7893
7923
|
}
|
|
7894
|
-
const
|
|
7895
|
-
if (
|
|
7896
|
-
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}`;
|
|
7897
7927
|
h.current.speakText(q, {
|
|
7898
|
-
lipsyncLang:
|
|
7928
|
+
lipsyncLang: M.lipsyncLang
|
|
7899
7929
|
});
|
|
7900
|
-
} else if (
|
|
7901
|
-
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}`;
|
|
7902
7932
|
h.current.speakText(q, {
|
|
7903
|
-
lipsyncLang:
|
|
7933
|
+
lipsyncLang: M.lipsyncLang
|
|
7904
7934
|
});
|
|
7905
|
-
} else if (
|
|
7906
|
-
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}`;
|
|
7907
7937
|
h.current.speakText(q, {
|
|
7908
|
-
lipsyncLang:
|
|
7938
|
+
lipsyncLang: M.lipsyncLang
|
|
7909
7939
|
});
|
|
7910
7940
|
} else {
|
|
7911
|
-
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}`;
|
|
7912
7942
|
h.current.speakText(q, {
|
|
7913
|
-
lipsyncLang:
|
|
7943
|
+
lipsyncLang: M.lipsyncLang
|
|
7914
7944
|
});
|
|
7915
7945
|
}
|
|
7916
7946
|
};
|
|
7917
|
-
if (h.current && h.current.isReady &&
|
|
7918
|
-
|
|
7919
|
-
else if (
|
|
7920
|
-
const
|
|
7921
|
-
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());
|
|
7922
7952
|
}, 100);
|
|
7923
7953
|
setTimeout(() => {
|
|
7924
|
-
clearInterval(
|
|
7954
|
+
clearInterval(M);
|
|
7925
7955
|
}, 5e3);
|
|
7926
7956
|
}
|
|
7927
7957
|
} else
|
|
@@ -7932,11 +7962,11 @@ const yt = Me(({
|
|
|
7932
7962
|
totalQuestions: a.current.totalQuestions,
|
|
7933
7963
|
score: a.current.score
|
|
7934
7964
|
});
|
|
7935
|
-
}, [e.nextQuestion, y,
|
|
7936
|
-
const v =
|
|
7937
|
-
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) {
|
|
7938
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;
|
|
7939
|
-
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;
|
|
7940
7970
|
c.current.onCustomAction({
|
|
7941
7971
|
type: "lessonStart",
|
|
7942
7972
|
moduleIndex: a.current.currentModuleIndex,
|
|
@@ -7949,7 +7979,7 @@ const yt = Me(({
|
|
|
7949
7979
|
}), h.current && (h.current.setMood("happy"), h.current.setBodyMovement("idle"));
|
|
7950
7980
|
} else if (a.current.currentModuleIndex < (v.modules?.length || 0) - 1) {
|
|
7951
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;
|
|
7952
|
-
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;
|
|
7953
7983
|
c.current.onCustomAction({
|
|
7954
7984
|
type: "lessonStart",
|
|
7955
7985
|
moduleIndex: a.current.currentModuleIndex,
|
|
@@ -7961,26 +7991,26 @@ const yt = Me(({
|
|
|
7961
7991
|
lesson: y()
|
|
7962
7992
|
}), h.current && (h.current.setMood("happy"), h.current.setBodyMovement("idle"));
|
|
7963
7993
|
} else
|
|
7964
|
-
|
|
7965
|
-
}, []), X =
|
|
7994
|
+
R.current && R.current();
|
|
7995
|
+
}, []), X = P(() => {
|
|
7966
7996
|
const v = y();
|
|
7967
|
-
let
|
|
7997
|
+
let I = null;
|
|
7968
7998
|
if (v?.avatar_script && v?.body) {
|
|
7969
|
-
const
|
|
7970
|
-
|
|
7999
|
+
const w = v.avatar_script.trim(), M = v.body.trim(), W = w.match(/[.!?]$/) ? " " : ". ";
|
|
8000
|
+
I = `${w}${W}${M}`;
|
|
7971
8001
|
} else
|
|
7972
|
-
|
|
7973
|
-
if (h.current && h.current.isReady &&
|
|
8002
|
+
I = v?.avatar_script || v?.body || null;
|
|
8003
|
+
if (h.current && h.current.isReady && I) {
|
|
7974
8004
|
a.current.isTeaching = !0, a.current.isQuestionMode = !1, a.current.score = 0, a.current.totalQuestions = 0, h.current.setMood("happy");
|
|
7975
|
-
let
|
|
8005
|
+
let w = !1;
|
|
7976
8006
|
if (e.teaching)
|
|
7977
8007
|
try {
|
|
7978
|
-
h.current.playAnimation(e.teaching, !0),
|
|
7979
|
-
} catch (
|
|
7980
|
-
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);
|
|
7981
8011
|
}
|
|
7982
|
-
|
|
7983
|
-
const
|
|
8012
|
+
w || h.current.setBodyMovement("gesturing");
|
|
8013
|
+
const M = k.current || { lipsyncLang: "en" };
|
|
7984
8014
|
c.current.onLessonStart({
|
|
7985
8015
|
moduleIndex: a.current.currentModuleIndex,
|
|
7986
8016
|
lessonIndex: a.current.currentLessonIndex,
|
|
@@ -7990,8 +8020,8 @@ const yt = Me(({
|
|
|
7990
8020
|
moduleIndex: a.current.currentModuleIndex,
|
|
7991
8021
|
lessonIndex: a.current.currentLessonIndex,
|
|
7992
8022
|
lesson: v
|
|
7993
|
-
}), h.current.speakText(
|
|
7994
|
-
lipsyncLang:
|
|
8023
|
+
}), h.current.speakText(I, {
|
|
8024
|
+
lipsyncLang: M.lipsyncLang,
|
|
7995
8025
|
onSpeechEnd: () => {
|
|
7996
8026
|
a.current.isTeaching = !1, c.current.onCustomAction({
|
|
7997
8027
|
type: "teachingComplete",
|
|
@@ -8009,17 +8039,17 @@ const yt = Me(({
|
|
|
8009
8039
|
}
|
|
8010
8040
|
});
|
|
8011
8041
|
}
|
|
8012
|
-
}, [e.teaching, y]), $ =
|
|
8013
|
-
const
|
|
8014
|
-
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({
|
|
8015
8045
|
moduleIndex: a.current.currentModuleIndex,
|
|
8016
8046
|
lessonIndex: a.current.currentLessonIndex,
|
|
8017
8047
|
questionIndex: a.current.currentQuestionIndex,
|
|
8018
8048
|
answer: v,
|
|
8019
|
-
isCorrect:
|
|
8020
|
-
question:
|
|
8049
|
+
isCorrect: w,
|
|
8050
|
+
question: I
|
|
8021
8051
|
}), h.current)
|
|
8022
|
-
if (
|
|
8052
|
+
if (w) {
|
|
8023
8053
|
if (h.current.setMood("happy"), e.correct)
|
|
8024
8054
|
try {
|
|
8025
8055
|
h.current.playReaction("happy");
|
|
@@ -8027,11 +8057,11 @@ const yt = Me(({
|
|
|
8027
8057
|
h.current.setBodyMovement("happy");
|
|
8028
8058
|
}
|
|
8029
8059
|
h.current.setBodyMovement("gesturing");
|
|
8030
|
-
const
|
|
8031
|
-
a.current.currentQuestionIndex >=
|
|
8032
|
-
const K = a.current.currentQuestionIndex <
|
|
8033
|
-
console.log("[CurriculumLearning] Answer feedback - questionIndex:", a.current.currentQuestionIndex, "totalQuestions:",
|
|
8034
|
-
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" };
|
|
8035
8065
|
h.current.speakText(j, {
|
|
8036
8066
|
lipsyncLang: q.lipsyncLang,
|
|
8037
8067
|
onSpeechEnd: () => {
|
|
@@ -8055,9 +8085,9 @@ const yt = Me(({
|
|
|
8055
8085
|
h.current.setBodyMovement("idle");
|
|
8056
8086
|
}
|
|
8057
8087
|
h.current.setBodyMovement("gesturing");
|
|
8058
|
-
const
|
|
8059
|
-
console.log("[CurriculumLearning] Answer feedback (incorrect) - questionIndex:", a.current.currentQuestionIndex, "totalQuestions:",
|
|
8060
|
-
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" };
|
|
8061
8091
|
h.current.speakText(q, {
|
|
8062
8092
|
lipsyncLang: Le.lipsyncLang,
|
|
8063
8093
|
onSpeechEnd: () => {
|
|
@@ -8075,30 +8105,30 @@ const yt = Me(({
|
|
|
8075
8105
|
});
|
|
8076
8106
|
}
|
|
8077
8107
|
else {
|
|
8078
|
-
const
|
|
8108
|
+
const W = y()?.questions?.length || 0;
|
|
8079
8109
|
c.current.onCustomAction({
|
|
8080
8110
|
type: "answerFeedbackComplete",
|
|
8081
8111
|
moduleIndex: a.current.currentModuleIndex,
|
|
8082
8112
|
lessonIndex: a.current.currentLessonIndex,
|
|
8083
8113
|
questionIndex: a.current.currentQuestionIndex,
|
|
8084
|
-
isCorrect:
|
|
8085
|
-
hasNextQuestion: a.current.currentQuestionIndex <
|
|
8114
|
+
isCorrect: w,
|
|
8115
|
+
hasNextQuestion: a.current.currentQuestionIndex < W - 1,
|
|
8086
8116
|
score: a.current.score,
|
|
8087
8117
|
totalQuestions: a.current.totalQuestions,
|
|
8088
8118
|
avatarNotReady: !0
|
|
8089
8119
|
});
|
|
8090
8120
|
}
|
|
8091
|
-
}, [e.correct, e.incorrect,
|
|
8092
|
-
const
|
|
8121
|
+
}, [e.correct, e.incorrect, T, y, E]), se = P((v) => {
|
|
8122
|
+
const I = T();
|
|
8093
8123
|
if (!v || typeof v != "object") {
|
|
8094
8124
|
console.error("Invalid code test result format. Expected object with {passed: boolean, ...}");
|
|
8095
8125
|
return;
|
|
8096
8126
|
}
|
|
8097
|
-
if (
|
|
8127
|
+
if (I?.type !== "code_test") {
|
|
8098
8128
|
console.warn("Current question is not a code test. Use handleAnswerSelect for other question types.");
|
|
8099
8129
|
return;
|
|
8100
8130
|
}
|
|
8101
|
-
const
|
|
8131
|
+
const w = {
|
|
8102
8132
|
passed: v.passed === !0,
|
|
8103
8133
|
results: v.results || [],
|
|
8104
8134
|
output: v.output || "",
|
|
@@ -8113,13 +8143,13 @@ const yt = Me(({
|
|
|
8113
8143
|
moduleIndex: a.current.currentModuleIndex,
|
|
8114
8144
|
lessonIndex: a.current.currentLessonIndex,
|
|
8115
8145
|
questionIndex: a.current.currentQuestionIndex,
|
|
8116
|
-
testResult:
|
|
8117
|
-
question:
|
|
8118
|
-
}), p.current && p.current(
|
|
8119
|
-
}, [
|
|
8146
|
+
testResult: w,
|
|
8147
|
+
question: I
|
|
8148
|
+
}), p.current && p.current(w);
|
|
8149
|
+
}, [T, E]), ae = P(() => {
|
|
8120
8150
|
if (a.current.currentQuestionIndex > 0) {
|
|
8121
8151
|
a.current.currentQuestionIndex -= 1;
|
|
8122
|
-
const v =
|
|
8152
|
+
const v = T();
|
|
8123
8153
|
v && c.current.onCustomAction({
|
|
8124
8154
|
type: "questionStart",
|
|
8125
8155
|
moduleIndex: a.current.currentModuleIndex,
|
|
@@ -8129,29 +8159,29 @@ const yt = Me(({
|
|
|
8129
8159
|
question: v,
|
|
8130
8160
|
score: a.current.score
|
|
8131
8161
|
});
|
|
8132
|
-
const
|
|
8162
|
+
const I = () => {
|
|
8133
8163
|
if (!h.current || !v) return;
|
|
8134
8164
|
h.current.setMood("happy"), h.current.setBodyMovement("idle");
|
|
8135
|
-
const
|
|
8165
|
+
const w = k.current || { lipsyncLang: "en" };
|
|
8136
8166
|
v.type === "code_test" ? h.current.speakText(`Let's go back to this coding challenge: ${v.question}`, {
|
|
8137
|
-
lipsyncLang:
|
|
8167
|
+
lipsyncLang: w.lipsyncLang
|
|
8138
8168
|
}) : h.current.speakText(`Going back to: ${v.question}`, {
|
|
8139
|
-
lipsyncLang:
|
|
8169
|
+
lipsyncLang: w.lipsyncLang
|
|
8140
8170
|
});
|
|
8141
8171
|
};
|
|
8142
8172
|
if (h.current && h.current.isReady && v)
|
|
8143
|
-
|
|
8173
|
+
I();
|
|
8144
8174
|
else if (v) {
|
|
8145
|
-
const
|
|
8146
|
-
h.current && h.current.isReady && (clearInterval(
|
|
8175
|
+
const w = setInterval(() => {
|
|
8176
|
+
h.current && h.current.isReady && (clearInterval(w), I());
|
|
8147
8177
|
}, 100);
|
|
8148
8178
|
setTimeout(() => {
|
|
8149
|
-
clearInterval(
|
|
8179
|
+
clearInterval(w);
|
|
8150
8180
|
}, 5e3);
|
|
8151
8181
|
}
|
|
8152
8182
|
}
|
|
8153
|
-
}, [
|
|
8154
|
-
const v =
|
|
8183
|
+
}, [T]), pe = P(() => {
|
|
8184
|
+
const v = H.current || { modules: [] };
|
|
8155
8185
|
if (v.modules[a.current.currentModuleIndex], a.current.currentLessonIndex > 0)
|
|
8156
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({
|
|
8157
8187
|
type: "lessonStart",
|
|
@@ -8163,8 +8193,8 @@ const yt = Me(({
|
|
|
8163
8193
|
lesson: y()
|
|
8164
8194
|
}), h.current && (h.current.setMood("happy"), h.current.setBodyMovement("idle"));
|
|
8165
8195
|
else if (a.current.currentModuleIndex > 0) {
|
|
8166
|
-
const
|
|
8167
|
-
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({
|
|
8168
8198
|
type: "lessonStart",
|
|
8169
8199
|
moduleIndex: a.current.currentModuleIndex,
|
|
8170
8200
|
lessonIndex: a.current.currentLessonIndex
|
|
@@ -8174,52 +8204,52 @@ const yt = Me(({
|
|
|
8174
8204
|
lesson: y()
|
|
8175
8205
|
}), h.current && (h.current.setMood("happy"), h.current.setBodyMovement("idle"));
|
|
8176
8206
|
}
|
|
8177
|
-
}, [y]), ee =
|
|
8207
|
+
}, [y]), ee = P(() => {
|
|
8178
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;
|
|
8179
|
-
}, []), le =
|
|
8209
|
+
}, []), le = P((v) => {
|
|
8180
8210
|
console.log("Avatar is ready!", v);
|
|
8181
|
-
const
|
|
8182
|
-
u &&
|
|
8211
|
+
const I = y(), w = I?.avatar_script || I?.body;
|
|
8212
|
+
u && w && setTimeout(() => {
|
|
8183
8213
|
d.current && d.current();
|
|
8184
8214
|
}, 10);
|
|
8185
8215
|
}, [u, y]);
|
|
8186
8216
|
Xe(() => {
|
|
8187
|
-
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 = $;
|
|
8188
8218
|
}), Ee(r, () => ({
|
|
8189
8219
|
// Curriculum control methods
|
|
8190
8220
|
startTeaching: X,
|
|
8191
8221
|
startQuestions: S,
|
|
8192
8222
|
handleAnswerSelect: $,
|
|
8193
8223
|
handleCodeTestResult: se,
|
|
8194
|
-
nextQuestion:
|
|
8224
|
+
nextQuestion: G,
|
|
8195
8225
|
previousQuestion: ae,
|
|
8196
8226
|
nextLesson: _,
|
|
8197
8227
|
previousLesson: pe,
|
|
8198
|
-
completeLesson:
|
|
8199
|
-
completeCurriculum:
|
|
8228
|
+
completeLesson: O,
|
|
8229
|
+
completeCurriculum: te,
|
|
8200
8230
|
resetCurriculum: ee,
|
|
8201
8231
|
getState: () => ({ ...a.current }),
|
|
8202
|
-
getCurrentQuestion: () =>
|
|
8232
|
+
getCurrentQuestion: () => T(),
|
|
8203
8233
|
getCurrentLesson: () => y(),
|
|
8204
8234
|
// Direct access to avatar ref (always returns current value)
|
|
8205
8235
|
getAvatarRef: () => h.current,
|
|
8206
8236
|
// Convenience methods that delegate to avatar (always check current ref)
|
|
8207
|
-
speakText: async (v,
|
|
8237
|
+
speakText: async (v, I = {}) => {
|
|
8208
8238
|
await h.current?.resumeAudioContext?.();
|
|
8209
|
-
const
|
|
8210
|
-
h.current?.speakText(v, { ...
|
|
8239
|
+
const w = k.current || { lipsyncLang: "en" };
|
|
8240
|
+
h.current?.speakText(v, { ...I, lipsyncLang: I.lipsyncLang || w.lipsyncLang });
|
|
8211
8241
|
},
|
|
8212
8242
|
resumeAudioContext: async () => {
|
|
8213
8243
|
if (h.current?.resumeAudioContext)
|
|
8214
8244
|
return await h.current.resumeAudioContext();
|
|
8215
8245
|
const v = h.current?.talkingHead;
|
|
8216
8246
|
if (v?.audioCtx) {
|
|
8217
|
-
const
|
|
8218
|
-
if (
|
|
8247
|
+
const I = v.audioCtx;
|
|
8248
|
+
if (I.state === "suspended" || I.state === "interrupted")
|
|
8219
8249
|
try {
|
|
8220
|
-
await
|
|
8221
|
-
} catch (
|
|
8222
|
-
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);
|
|
8223
8253
|
}
|
|
8224
8254
|
} else
|
|
8225
8255
|
console.warn("Audio context not available yet");
|
|
@@ -8229,7 +8259,7 @@ const yt = Me(({
|
|
|
8229
8259
|
resumeSpeaking: async () => await h.current?.resumeSpeaking(),
|
|
8230
8260
|
isPaused: () => h.current && typeof h.current.isPaused < "u" ? h.current.isPaused : !1,
|
|
8231
8261
|
setMood: (v) => h.current?.setMood(v),
|
|
8232
|
-
playAnimation: (v,
|
|
8262
|
+
playAnimation: (v, I) => h.current?.playAnimation(v, I),
|
|
8233
8263
|
setBodyMovement: (v) => h.current?.setBodyMovement(v),
|
|
8234
8264
|
setMovementIntensity: (v) => h.current?.setMovementIntensity(v),
|
|
8235
8265
|
playRandomDance: () => h.current?.playRandomDance(),
|
|
@@ -8240,10 +8270,10 @@ const yt = Me(({
|
|
|
8240
8270
|
lockAvatarPosition: () => h.current?.lockAvatarPosition(),
|
|
8241
8271
|
unlockAvatarPosition: () => h.current?.unlockAvatarPosition(),
|
|
8242
8272
|
// Custom action trigger
|
|
8243
|
-
triggerCustomAction: (v,
|
|
8273
|
+
triggerCustomAction: (v, I) => {
|
|
8244
8274
|
c.current.onCustomAction({
|
|
8245
8275
|
type: v,
|
|
8246
|
-
...
|
|
8276
|
+
...I,
|
|
8247
8277
|
state: { ...a.current }
|
|
8248
8278
|
});
|
|
8249
8279
|
},
|
|
@@ -8251,8 +8281,8 @@ const yt = Me(({
|
|
|
8251
8281
|
handleResize: () => h.current?.handleResize(),
|
|
8252
8282
|
// Avatar readiness check (always returns current value)
|
|
8253
8283
|
isAvatarReady: () => h.current?.isReady || !1
|
|
8254
|
-
}), [X, S, $, se,
|
|
8255
|
-
const
|
|
8284
|
+
}), [X, S, $, se, G, _, O, te, ee, T, y]);
|
|
8285
|
+
const U = k.current || {
|
|
8256
8286
|
avatarUrl: "/avatars/brunette.glb",
|
|
8257
8287
|
avatarBody: "F",
|
|
8258
8288
|
mood: "happy",
|
|
@@ -8269,18 +8299,18 @@ const yt = Me(({
|
|
|
8269
8299
|
Ve,
|
|
8270
8300
|
{
|
|
8271
8301
|
ref: h,
|
|
8272
|
-
avatarUrl:
|
|
8273
|
-
avatarBody:
|
|
8274
|
-
mood:
|
|
8275
|
-
ttsLang:
|
|
8276
|
-
ttsService:
|
|
8277
|
-
ttsVoice:
|
|
8278
|
-
ttsApiKey:
|
|
8279
|
-
bodyMovement:
|
|
8280
|
-
movementIntensity:
|
|
8281
|
-
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,
|
|
8282
8312
|
cameraView: "upper",
|
|
8283
|
-
animations:
|
|
8313
|
+
animations: U.animations,
|
|
8284
8314
|
onReady: le,
|
|
8285
8315
|
onLoading: () => {
|
|
8286
8316
|
},
|
|
@@ -8394,7 +8424,7 @@ const Ge = {
|
|
|
8394
8424
|
duration: 5e3,
|
|
8395
8425
|
description: "Excited, energetic movement"
|
|
8396
8426
|
}
|
|
8397
|
-
}, wt = (
|
|
8427
|
+
}, wt = (Z) => Ge[Z] || null, zt = (Z) => Ge.hasOwnProperty(Z);
|
|
8398
8428
|
export {
|
|
8399
8429
|
yt as CurriculumLearning,
|
|
8400
8430
|
gt as SimpleTalkingAvatar,
|