@sage-rsc/talking-head-react 1.2.2 → 1.2.3
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 +725 -701
- package/package.json +1 -1
- package/src/components/SimpleTalkingAvatar.jsx +57 -2
package/dist/index.js
CHANGED
|
@@ -1,20 +1,20 @@
|
|
|
1
1
|
import { jsxs as Pe, jsx as me } from "react/jsx-runtime";
|
|
2
|
-
import { forwardRef as
|
|
3
|
-
import * as
|
|
2
|
+
import { forwardRef as He, useRef as V, useState as ce, useEffect as de, useCallback as N, useImperativeHandle as Te, useLayoutEffect as Xe } from "react";
|
|
3
|
+
import * as y from "three";
|
|
4
4
|
import { OrbitControls as Ye } from "three/addons/controls/OrbitControls.js";
|
|
5
5
|
import { GLTFLoader as je } from "three/addons/loaders/GLTFLoader.js";
|
|
6
6
|
import { DRACOLoader as Qe } from "three/addons/loaders/DRACOLoader.js";
|
|
7
7
|
import { FBXLoader as De } 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
|
-
let m,
|
|
11
|
-
const
|
|
12
|
-
new
|
|
13
|
-
new
|
|
14
|
-
new
|
|
15
|
-
const
|
|
16
|
-
new
|
|
17
|
-
const
|
|
10
|
+
let m, ae, ue;
|
|
11
|
+
const z = [0, 0, 0, 0], F = new y.Vector3(), ke = new y.Vector3(), ne = new y.Vector3(), we = new y.Vector3();
|
|
12
|
+
new y.Plane();
|
|
13
|
+
new y.Ray();
|
|
14
|
+
new y.Euler();
|
|
15
|
+
const ie = new y.Quaternion(), Oe = new y.Quaternion(), ge = new y.Matrix4(), ye = new y.Matrix4();
|
|
16
|
+
new y.Vector3();
|
|
17
|
+
const ze = new y.Vector3(0, 0, 1), Ke = new y.Vector3(1, 0, 0), Je = new y.Vector3(0, 1, 0), $e = new y.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(F).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
|
-
u.boneParent.matrixWorld.decompose(
|
|
341
|
+
u.boneParent.matrixWorld.decompose(F, ie, ne), F.copy(ze).applyQuaternion(ie).setY(0).normalize(), ie.premultiply(Oe.setFromUnitVectors(ze, F).invert()).normalize(), u.qWorldInverseYaw = ie.clone().normalize(), this.data.push(u), this.dict[h] = u;
|
|
342
342
|
try {
|
|
343
343
|
this.setValue(h, "type", s.type), this.setValue(h, "stiffness", s.stiffness), this.setValue(h, "damping", s.damping), this.setValue(h, "external", s.external), this.setValue(h, "limits", s.limits), this.setValue(h, "excludes", s.excludes), this.setValue(h, "deltaLocal", s.deltaLocal), this.setValue(h, "deltaWorld", s.deltaWorld), this.setValue(h, "pivot", s.pivot), this.setValue(h, "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], F.copy(o.vWorld), ge.copy(o.boneParent.matrixWorld), ye.copy(ge).invert(), o.vWorld.setFromMatrixPosition(ge), F.applyMatrix4(ye), F.length() > 0.5 && (console.info("Info: Unrealistic jump of " + F.length().toFixed(2) + " meters."), F.setLength(0.5)), F.applyQuaternion(o.bone.quaternion), z[0] = F.x, z[1] = F.y, z[2] = -F.z, z[3] = F.length() / 3, o.children)
|
|
360
360
|
for (n = 0, s = o.children.length; n < s; n++)
|
|
361
|
-
m = o.children[n],
|
|
362
|
-
if (m = this.opt.sensitivityFactor,
|
|
363
|
-
o.vBasis.x +
|
|
364
|
-
o.vBasis.y +
|
|
365
|
-
o.vBasis.z +
|
|
366
|
-
),
|
|
361
|
+
m = o.children[n], z[0] -= m.v[0] * t / 3, z[1] -= m.v[1] * t / 3, z[2] += m.v[2] * t / 3, z[3] -= m.v[3] * t / 3;
|
|
362
|
+
if (m = this.opt.sensitivityFactor, z[0] *= o.ext * m, z[1] *= o.ext * m, z[2] *= o.ext * m, z[3] *= o.ext * m, o.isX && (m = z[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 + z[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 = z[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 + z[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 = z[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 + z[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 = z[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 + z[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), z[0] = o.p[0], z[1] = o.p[1], z[2] = o.p[2], z[3] = o.p[3], m = this.opt.movementFactor, z[0] *= m, z[1] *= m, z[2] *= m, z[3] *= m, o.dl && (m = o.dl, z[0] += m[0], z[1] += m[1], z[2] += m[2]), o.dw && (m = o.dw, F.set(
|
|
363
|
+
o.vBasis.x + z[0],
|
|
364
|
+
o.vBasis.y + z[1],
|
|
365
|
+
o.vBasis.z + z[2]
|
|
366
|
+
), F.applyMatrix4(ge), F.x += m[0], F.y += m[1], F.z += m[2], F.applyMatrix4(ye), z[0] += F.x - o.vBasis.x, z[1] += F.y - o.vBasis.y, z[2] += F.z - o.vBasis.z), o.limits && this.opt.isLimits && (m = o.limits, m[0] && (m[0][0] !== null && z[0] < m[0][0] && (z[0] = m[0][0]), m[0][1] !== null && z[0] > m[0][1] && (z[0] = m[0][1])), m[1] && (m[1][0] !== null && z[1] < m[1][0] && (z[1] = m[1][0]), m[1][1] !== null && z[1] > m[1][1] && (z[1] = m[1][1])), m[2] && (m[2][0] !== null && z[2] < m[2][0] && (z[2] = m[2][0]), m[2][1] !== null && z[2] > m[2][1] && (z[2] = m[2][1])), m[3] && (m[3][0] !== null && z[3] < m[3][0] && (z[3] = m[3][0]), m[3][1] !== null && z[3] > m[3][1] && (z[3] = m[3][1]))), o.isPoint)
|
|
367
367
|
o.bone.position.set(
|
|
368
|
-
o.vBasis.x +
|
|
369
|
-
o.vBasis.y +
|
|
370
|
-
o.vBasis.z -
|
|
368
|
+
o.vBasis.x + z[0],
|
|
369
|
+
o.vBasis.y + z[1],
|
|
370
|
+
o.vBasis.z - z[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(F, ie, ne), F.copy(ze).applyQuaternion(ie).setY(0).normalize(), ie.premultiply(Oe.setFromUnitVectors(ze, F).invert()).normalize(), o.boneParent.quaternion.multiply(ie.invert()), o.boneParent.quaternion.multiply(o.qWorldInverseYaw)), o.isZ && (m = Math.atan(z[0] / o.l), ie.setFromAxisAngle($e, -m), o.boneParent.quaternion.multiply(ie)), o.isY && (m = o.l / 3, m = m * Math.tanh(z[1] / m), o.bone.position.setLength(o.l + m)), o.isX && (m = Math.atan(z[2] / o.l), ie.setFromAxisAngle(Ke, -m), o.boneParent.quaternion.multiply(ie)), o.isT && (m = 1.5 * Math.tanh(z[3] * 1.5), ie.setFromAxisAngle(Je, -m), o.boneParent.quaternion.multiply(ie)), 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], ne.set(0, 0, 0), m.deltaLocal && (ne.x += m.deltaLocal[0], ne.y += m.deltaLocal[1], ne.z += m.deltaLocal[2]), ne.applyMatrix4(m.bone.matrixWorld), ye.copy(o.boneParent.matrixWorld).invert(), ne.applyMatrix4(ye), F.copy(o.bone.position), !(F.distanceToSquared(ne) >= m.radiusSq) && (ue = F.length(), ae = ne.length(), !(ae > m.radius + ue) && (ae < Math.abs(m.radius - ue) || (ae = (ae * ae + ue * ue - m.radiusSq) / (2 * ae), ne.normalize(), we.copy(ne).multiplyScalar(ae), ae = Math.sqrt(ue * ue - ae * ae), F.subVectors(F, we).projectOnPlane(ne).normalize().multiplyScalar(ae), ke.subVectors(o.vBasis, we).projectOnPlane(ne).normalize(), ue = ke.dot(F), ue < 0 && (ue = Math.sqrt(ae * ae - ue * ue), ke.multiplyScalar(ue), F.add(ke)), F.add(we).normalize(), ne.copy(o.bone.position).normalize(), ie.setFromUnitVectors(ne, F), o.boneParent.quaternion.premultiply(ie), 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 y.SphereGeometry(m.radii[n], 6, 6), s = new y.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 y.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 y.BufferGeometry(), n = m.bones.map((h) => [0, 0, 0]).flat();
|
|
412
|
+
e.setAttribute("position", new y.Float32BufferAttribute(n, 3));
|
|
413
|
+
const i = new y.Color(this.opt.helperBoneColor1), s = new y.Color(this.opt.helperBoneColor2), o = m.pivots.map((h) => h && this.opt.isPivots ? [s.r, s.g, s.b] : [i.r, i.g, i.b]).flat();
|
|
414
|
+
e.setAttribute("color", new y.Float32BufferAttribute(o, 3));
|
|
415
|
+
const l = new y.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 y.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 y.BufferGeometry(), n = m.bones.map((h) => [0, 0, 0, 0, 0, 0]).flat();
|
|
427
|
+
e.setAttribute("position", new y.Float32BufferAttribute(n, 3));
|
|
428
|
+
const i = new y.Color(this.opt.helperLinkColor1), s = new y.Color(this.opt.helperLinkColor2), o = m.bones.map((h) => [i.r, i.g, i.b, s.r, s.g, s.b]).flat();
|
|
429
|
+
e.setAttribute("color", new y.Float32BufferAttribute(o, 3));
|
|
430
|
+
const l = new y.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 y.LineSegments(e, l), m.object.renderOrder = 999, m.object.matrix = this.armature.matrixWorld, m.object.matrixAutoUpdate = !1, this.scene.add(m.object);
|
|
438
438
|
}
|
|
439
439
|
}
|
|
440
440
|
/**
|
|
@@ -442,17 +442,17 @@ class et {
|
|
|
442
442
|
*/
|
|
443
443
|
updateHelpers() {
|
|
444
444
|
if (m = this.helpers.points, m.bones.length) {
|
|
445
|
-
|
|
445
|
+
ye.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
|
-
|
|
448
|
+
ge.multiplyMatrices(ye, m.bones[e].matrixWorld), F.setFromMatrixPosition(ge), t.setXYZ(e, F.x, F.y, F.z);
|
|
449
449
|
t.needsUpdate = !0, m.object.updateMatrixWorld();
|
|
450
450
|
}
|
|
451
451
|
if (m = this.helpers.lines, m.bones.length) {
|
|
452
|
-
|
|
452
|
+
ye.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
|
-
|
|
455
|
+
ge.multiplyMatrices(ye, m.bones[e].matrixWorld), F.setFromMatrixPosition(ge), t.setXYZ(n, F.x, F.y, F.z), ge.multiplyMatrices(ye, m.bones[e].parent.matrixWorld), F.setFromMatrixPosition(ge), t.setXYZ(n + 1, F.x, F.y, F.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 d = n[(h + a) * 2], c = n[(h + a) * 2 + 1], g = n[(h + a + i / 2) * 2] * r - n[(h + a + i / 2) * 2 + 1] * u, b = n[(h + a + i / 2) * 2] * u + n[(h + a + i / 2) * 2 + 1] * r;
|
|
610
610
|
n[(h + a) * 2] = d + g, n[(h + a) * 2 + 1] = c + b, n[(h + a + i / 2) * 2] = d - g, n[(h + a + i / 2) * 2 + 1] = c - b;
|
|
611
|
-
const x = r * o - u * l,
|
|
612
|
-
r = x, u =
|
|
611
|
+
const x = r * o - u * l, L = r * l + u * o;
|
|
612
|
+
r = x, u = L;
|
|
613
613
|
}
|
|
614
614
|
}
|
|
615
615
|
}
|
|
@@ -2629,14 +2629,14 @@ const ct = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
|
|
|
2629
2629
|
fr: rt,
|
|
2630
2630
|
fi: ut,
|
|
2631
2631
|
lt: ct
|
|
2632
|
-
},
|
|
2633
|
-
new
|
|
2634
|
-
new
|
|
2635
|
-
new
|
|
2636
|
-
new
|
|
2637
|
-
const mt = new
|
|
2638
|
-
new
|
|
2639
|
-
new
|
|
2632
|
+
}, K = new y.Quaternion(), Z = new y.Euler(), be = new y.Vector3(), Re = new y.Vector3(), We = new y.Box3();
|
|
2633
|
+
new y.Matrix4();
|
|
2634
|
+
new y.Matrix4();
|
|
2635
|
+
new y.Vector3();
|
|
2636
|
+
new y.Vector3(0, 0, 1);
|
|
2637
|
+
const mt = new y.Vector3(1, 0, 0);
|
|
2638
|
+
new y.Vector3(0, 1, 0);
|
|
2639
|
+
new y.Vector3(0, 0, 1);
|
|
2640
2640
|
class Be {
|
|
2641
2641
|
/**
|
|
2642
2642
|
* Avatar.
|
|
@@ -4073,22 +4073,22 @@ class Be {
|
|
|
4073
4073
|
if (this.isAvatarOnly = this.opt.avatarOnly, this.isAvatarOnly)
|
|
4074
4074
|
this.scene = this.opt.avatarOnlyScene, this.camera = this.opt.avatarOnlyCamera;
|
|
4075
4075
|
else {
|
|
4076
|
-
this.renderer = new
|
|
4077
|
-
new
|
|
4076
|
+
this.renderer = new y.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 = y.SRGBColorSpace, this.renderer.toneMapping = y.ACESFilmicToneMapping, this.renderer.shadowMap.enabled = !1, this.nodeAvatar.appendChild(this.renderer.domElement), this.camera = new y.PerspectiveCamera(10, this.nodeAvatar.clientWidth / this.nodeAvatar.clientHeight, 0.1, 2e3), this.scene = new y.Scene(), this.lightAmbient = new y.AmbientLight(
|
|
4077
|
+
new y.Color(this.opt.lightAmbientColor),
|
|
4078
4078
|
this.opt.lightAmbientIntensity
|
|
4079
|
-
), this.lightDirect = new
|
|
4080
|
-
new
|
|
4079
|
+
), this.lightDirect = new y.DirectionalLight(
|
|
4080
|
+
new y.Color(this.opt.lightDirectColor),
|
|
4081
4081
|
this.opt.lightDirectIntensity
|
|
4082
|
-
), this.lightSpot = new
|
|
4083
|
-
new
|
|
4082
|
+
), this.lightSpot = new y.SpotLight(
|
|
4083
|
+
new y.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 y.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 y.SkinnedMesh();
|
|
4092
4092
|
const s = {
|
|
4093
4093
|
LeftShoulder: null,
|
|
4094
4094
|
LeftArm: "LeftShoulder",
|
|
@@ -4102,9 +4102,9 @@ class Be {
|
|
|
4102
4102
|
RightHandMiddle1: "RightHand"
|
|
4103
4103
|
}, o = [];
|
|
4104
4104
|
Object.entries(s).forEach((l, h) => {
|
|
4105
|
-
const r = new
|
|
4105
|
+
const r = new y.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 y.Skeleton(o)), this.dynamicbones = new et(), this.isStreaming = !1, this.streamWorkletNode = null, this.streamAudioStartTime = null, this.streamWaitForAudioChunks = !0, this.streamLipsyncLang = null, this.streamLipsyncType = "visemes", this.streamLipsyncQueue = [];
|
|
4108
4108
|
}
|
|
4109
4109
|
/**
|
|
4110
4110
|
* Helper that re/creates the audio context and the other nodes.
|
|
@@ -4194,7 +4194,7 @@ class Be {
|
|
|
4194
4194
|
for (let [n, i] of Object.entries(t)) {
|
|
4195
4195
|
const s = n.split(".");
|
|
4196
4196
|
let o = Array.isArray(i.x) ? this.gaussianRandom(...i.x) : i.x, l = Array.isArray(i.y) ? this.gaussianRandom(...i.y) : i.y, h = 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 y.Vector3(o, l, h) : s[1] === "rotation" ? (n = s[0] + ".quaternion", e[n] = new y.Quaternion().setFromEuler(new y.Euler(o, l, h, "XYZ")).normalize()) : s[1] === "quaternion" && (e[n] = new y.Quaternion(o, l, h, i.w).normalize());
|
|
4198
4198
|
}
|
|
4199
4199
|
return e;
|
|
4200
4200
|
}
|
|
@@ -4226,15 +4226,15 @@ class Be {
|
|
|
4226
4226
|
for (const [r, u] of Object.entries(n))
|
|
4227
4227
|
if (s.morphTargetDictionary.hasOwnProperty(r)) {
|
|
4228
4228
|
const a = s.morphTargetDictionary[r], d = o.morphAttributes.position[a], c = o.morphAttributes.normal?.[a];
|
|
4229
|
-
l || (l = new
|
|
4229
|
+
l || (l = new y.Float32BufferAttribute(d.count * 3, 3), c && (h = new y.Float32BufferAttribute(d.count * 3, 3)));
|
|
4230
4230
|
for (let g = 0; g < d.count; g++) {
|
|
4231
|
-
const b = l.getX(g) + d.getX(g) * u, x = l.getY(g) + d.getY(g) * u,
|
|
4232
|
-
l.setXYZ(g, b, x,
|
|
4231
|
+
const b = l.getX(g) + d.getX(g) * u, x = l.getY(g) + d.getY(g) * u, L = l.getZ(g) + d.getZ(g) * u;
|
|
4232
|
+
l.setXYZ(g, b, x, L);
|
|
4233
4233
|
}
|
|
4234
4234
|
if (c)
|
|
4235
4235
|
for (let g = 0; g < d.count; g++) {
|
|
4236
|
-
const b = h.getX(g) + c.getX(g) * u, x = h.getY(g) + c.getY(g) * u,
|
|
4237
|
-
h.setXYZ(g, b, x,
|
|
4236
|
+
const b = h.getX(g) + c.getX(g) * u, x = h.getY(g) + c.getY(g) * u, L = h.getZ(g) + c.getZ(g) * u;
|
|
4237
|
+
h.setXYZ(g, b, x, L);
|
|
4238
4238
|
}
|
|
4239
4239
|
}
|
|
4240
4240
|
if (l) {
|
|
@@ -4314,7 +4314,7 @@ class Be {
|
|
|
4314
4314
|
console.error("Dynamic bones setup failed: " + r);
|
|
4315
4315
|
}
|
|
4316
4316
|
this.objectLeftToeBase = this.armature.getObjectByName("LeftToeBase"), this.objectRightToeBase = this.armature.getObjectByName("RightToeBase"), this.objectLeftEye = this.armature.getObjectByName("LeftEye"), this.objectRightEye = this.armature.getObjectByName("RightEye"), this.objectLeftArm = this.armature.getObjectByName("LeftArm"), this.objectRightArm = this.armature.getObjectByName("RightArm"), this.objectHips = this.armature.getObjectByName("Hips"), this.objectHead = this.armature.getObjectByName("Head"), this.objectNeck = this.armature.getObjectByName("Neck");
|
|
4317
|
-
const h = new
|
|
4317
|
+
const h = new y.Vector3();
|
|
4318
4318
|
this.objectLeftEye.getWorldPosition(h), this.avatarHeight = h.y + 0.2, this.viewName || this.setView(this.opt.cameraView), this.setMood(this.avatar.avatarMood || this.moodName || this.opt.avatarMood), this.avatar.body === "M" && this.poseTemplates.wide && (this.poseName = "wide", this.setPoseFromTemplate(this.poseTemplates.wide, 0), console.log("Set initial male-appropriate pose: wide")), this.initializeFBXAnimationLoader(), this.bodyMovement && this.bodyMovement !== "idle" && this.applyBodyMovementAnimation(), this.start();
|
|
4319
4319
|
}
|
|
4320
4320
|
/**
|
|
@@ -4358,14 +4358,14 @@ class Be {
|
|
|
4358
4358
|
default:
|
|
4359
4359
|
a += 12, u = u * a;
|
|
4360
4360
|
}
|
|
4361
|
-
r = r * a, this.controlsEnd = new
|
|
4361
|
+
r = r * a, this.controlsEnd = new y.Vector3(r, u, 0), this.cameraEnd = new y.Vector3(r, u, a).applyEuler(new y.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 y.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 y.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 y.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 y.Vector3(0, 1.5, 0))), t.hasOwnProperty("lightSpotDispersion") && (this.lightSpot.angle = t.lightSpotDispersion));
|
|
4369
4369
|
}
|
|
4370
4370
|
/**
|
|
4371
4371
|
* Render scene.
|
|
@@ -4400,7 +4400,7 @@ class Be {
|
|
|
4400
4400
|
if (e.x === 0 && e.y === 0 && e.z === 0) continue;
|
|
4401
4401
|
Z.set(e.x, e.y, e.z);
|
|
4402
4402
|
const n = this.poseAvatar.props[t];
|
|
4403
|
-
n.isQuaternion ? (
|
|
4403
|
+
n.isQuaternion ? (K.setFromEuler(Z), n.multiply(K)) : n.isVector3 && n.add(Z);
|
|
4404
4404
|
}
|
|
4405
4405
|
}
|
|
4406
4406
|
/**
|
|
@@ -4480,7 +4480,7 @@ class Be {
|
|
|
4480
4480
|
return Object.entries(t).forEach((i, s) => {
|
|
4481
4481
|
const o = i[0].split(".");
|
|
4482
4482
|
if (o[1] === "position" || o[1] === "rotation" || o[1] === "quaternion") {
|
|
4483
|
-
const l = o[1] === "quaternion" ? o[0] + ".rotation" : i[0], h = i[1].isQuaternion ? new
|
|
4483
|
+
const l = o[1] === "quaternion" ? o[0] + ".rotation" : i[0], h = i[1].isQuaternion ? new y.Euler().setFromQuaternion(i[1]) : i[1];
|
|
4484
4484
|
n += (s ? ", " : "") + "'" + l + "':{", n += "x:" + Math.round(h.x * e) / e, n += ", y:" + Math.round(h.y * e) / e, n += ", z:" + Math.round(h.z * e) / e, n += "}";
|
|
4485
4485
|
}
|
|
4486
4486
|
}), n += "}", n;
|
|
@@ -5157,7 +5157,7 @@ class Be {
|
|
|
5157
5157
|
{ link: "LeftForeArm", minx: -0.5, maxx: 1.5, miny: -1.5, maxy: 1.5, minz: -0.5, maxz: 3 },
|
|
5158
5158
|
{ link: "LeftArm", minx: -1.5, maxx: 1.5, miny: 0, maxy: 0, minz: -1, maxz: 3 }
|
|
5159
5159
|
]
|
|
5160
|
-
}, i.x ? new
|
|
5160
|
+
}, i.x ? new y.Vector3(i.x, i.y, i.z) : null, !0, i.d);
|
|
5161
5161
|
break;
|
|
5162
5162
|
case "handRight":
|
|
5163
5163
|
this.ikSolve({
|
|
@@ -5169,7 +5169,7 @@ class Be {
|
|
|
5169
5169
|
{ link: "RightForeArm", minx: -0.5, maxx: 1.5, miny: -1.5, maxy: 1.5, minz: -3, maxz: 0.5, maxAngle: 0.2 },
|
|
5170
5170
|
{ link: "RightArm", minx: -1.5, maxx: 1.5, miny: 0, maxy: 0, minz: -1, maxz: 3 }
|
|
5171
5171
|
]
|
|
5172
|
-
}, i.x ? new
|
|
5172
|
+
}, i.x ? new y.Vector3(i.x, i.y, i.z) : null, !0, i.d);
|
|
5173
5173
|
break;
|
|
5174
5174
|
}
|
|
5175
5175
|
if ((h || r) && (Z.setFromQuaternion(this.poseAvatar.props["Head.quaternion"]), Z.x = Math.max(-0.9, Math.min(0.9, 2 * Z.x - 0.5)), Z.y = Math.max(-0.9, Math.min(0.9, -2.5 * Z.y)), h ? (Object.assign(this.mtAvatar.eyesLookDown, { system: Z.x < 0 ? -Z.x : 0, needsUpdate: !0 }), Object.assign(this.mtAvatar.eyesLookUp, { system: Z.x < 0 ? 0 : Z.x, needsUpdate: !0 }), Object.assign(this.mtAvatar.eyeLookInLeft, { system: Z.y < 0 ? -Z.y : 0, needsUpdate: !0 }), Object.assign(this.mtAvatar.eyeLookOutLeft, { system: Z.y < 0 ? 0 : Z.y, needsUpdate: !0 }), Object.assign(this.mtAvatar.eyeLookInRight, { system: Z.y < 0 ? 0 : Z.y, needsUpdate: !0 }), Object.assign(this.mtAvatar.eyeLookOutRight, { system: Z.y < 0 ? -Z.y : 0, needsUpdate: !0 }), r && (n = -this.mtAvatar.bodyRotateY.value, i = this.gaussianRandom(-0.2, 0.2), this.animQueue.push(this.animFactory({
|
|
@@ -5193,12 +5193,12 @@ class Be {
|
|
|
5193
5193
|
eyeLookOutRight: [null, 0],
|
|
5194
5194
|
eyeContact: [0]
|
|
5195
5195
|
}
|
|
5196
|
-
})))), e > 2 * this.animFrameDur && (e = 2 * this.animFrameDur), (this.viewName !== "full" || this.isAvatarOnly) && (n = this.mtRandomized[Math.floor(Math.random() * this.mtRandomized.length)], i = this.mtAvatar[n], i.needsUpdate || Object.assign(i, { base: (this.mood.baseline[n] || 0) + (1 + l / 255) * Math.random() / 5, needsUpdate: !0 })), this.updatePoseBase(this.animClock), this.mixer && this.mixer.update(e / 1e3 * this.mixer.timeScale), this.updatePoseDelta(), (this.isSpeaking || this.isListening) && h ? l > this.volumeMax ? (this.volumeHeadBase = 0.05, Math.random() > 0.6 && (this.volumeHeadTarget = -0.05 - Math.random() / 15), this.volumeMax = l) : (this.volumeMax *= 0.92, this.volumeHeadTarget = this.volumeHeadBase - 0.9 * (this.volumeHeadBase - this.volumeHeadTarget)) : (this.volumeHeadTarget = 0, this.volumeMax = 0), n = this.volumeHeadTarget - this.volumeHeadCurrent, i = Math.abs(n), i > 1e-4 && (o = i * (this.volumeHeadEasing(Math.min(1, this.volumeHeadVelocity * e / 1e3 / i) / 2 + 0.5) - 0.5), this.volumeHeadCurrent += Math.sign(n) * Math.min(i, o)), Math.abs(this.volumeHeadCurrent) > 1e-4 && (
|
|
5196
|
+
})))), e > 2 * this.animFrameDur && (e = 2 * this.animFrameDur), (this.viewName !== "full" || this.isAvatarOnly) && (n = this.mtRandomized[Math.floor(Math.random() * this.mtRandomized.length)], i = this.mtAvatar[n], i.needsUpdate || Object.assign(i, { base: (this.mood.baseline[n] || 0) + (1 + l / 255) * Math.random() / 5, needsUpdate: !0 })), this.updatePoseBase(this.animClock), this.mixer && this.mixer.update(e / 1e3 * this.mixer.timeScale), this.updatePoseDelta(), (this.isSpeaking || this.isListening) && h ? l > this.volumeMax ? (this.volumeHeadBase = 0.05, Math.random() > 0.6 && (this.volumeHeadTarget = -0.05 - Math.random() / 15), this.volumeMax = l) : (this.volumeMax *= 0.92, this.volumeHeadTarget = this.volumeHeadBase - 0.9 * (this.volumeHeadBase - this.volumeHeadTarget)) : (this.volumeHeadTarget = 0, this.volumeMax = 0), n = this.volumeHeadTarget - this.volumeHeadCurrent, i = Math.abs(n), i > 1e-4 && (o = i * (this.volumeHeadEasing(Math.min(1, this.volumeHeadVelocity * e / 1e3 / i) / 2 + 0.5) - 0.5), this.volumeHeadCurrent += Math.sign(n) * Math.min(i, o)), Math.abs(this.volumeHeadCurrent) > 1e-4 && (K.setFromAxisAngle(mt, this.volumeHeadCurrent), this.objectNeck.quaternion.multiply(K)), We.setFromObject(this.armature), this.objectLeftToeBase.getWorldPosition(be), be.sub(this.armature.position), this.objectRightToeBase.getWorldPosition(Re), Re.sub(this.armature.position), this.objectHips.position.y -= We.min.y / 2, this.objectHips.position.x -= (be.x + Re.x) / 4, this.objectHips.position.z -= (be.z + Re.z) / 2, this.dynamicbones.update(e), this.fbxAnimationLoader && this.fbxAnimationLoader.update(), this.opt.update && this.opt.update(e), this.updateMorphTargets(e), this.isAvatarOnly)
|
|
5197
5197
|
this.stats && this.stats.end();
|
|
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 y.Spherical().setFromVector3(this.cameraStart), d = new y.Spherical().setFromVector3(this.cameraEnd);
|
|
5202
5202
|
a.phi += this.easing(this.cameraClock / 1e3) * (d.phi - a.phi), a.theta += this.easing(this.cameraClock / 1e3) * (d.theta - a.theta), a.radius += this.easing(this.cameraClock / 1e3) * (d.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), d.setFromVector3(this.controlsEnd), a.phi += this.easing(this.cameraClock / 1e3) * (d.phi - a.phi), a.theta += this.easing(this.cameraClock / 1e3) * (d.theta - a.theta), a.radius += this.easing(this.cameraClock / 1e3) * (d.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();
|
|
@@ -5264,10 +5264,10 @@ class Be {
|
|
|
5264
5264
|
let u = "", a = "", d = 0, c = [], g = [];
|
|
5265
5265
|
const b = Array.from(this.segmenter.segment(t), (x) => x.segment);
|
|
5266
5266
|
for (let x = 0; x < b.length; x++) {
|
|
5267
|
-
const
|
|
5267
|
+
const L = x === b.length - 1, O = b[x].match(l);
|
|
5268
5268
|
let p = b[x].match(s);
|
|
5269
|
-
const
|
|
5270
|
-
if (p && !
|
|
5269
|
+
const B = b[x].match(h), M = b[x].match(o);
|
|
5270
|
+
if (p && !L && !B && b[x + 1].match(s) && (p = !1), n && (u += b[x]), O && (!i || i.every((R) => x < R[0] || x > R[1])) && (a += b[x]), (M || p || L) && (a.length && (a = this.lipsyncPreProcessText(a, r), a.length && c.push({
|
|
5271
5271
|
mark: d,
|
|
5272
5272
|
word: a
|
|
5273
5273
|
})), u.length && (g.push({
|
|
@@ -5278,31 +5278,31 @@ class Be {
|
|
|
5278
5278
|
subtitles: [u]
|
|
5279
5279
|
}
|
|
5280
5280
|
}), u = ""), a.length)) {
|
|
5281
|
-
const
|
|
5282
|
-
if (
|
|
5283
|
-
const
|
|
5284
|
-
for (let
|
|
5281
|
+
const R = this.lipsyncWordsToVisemes(a, r);
|
|
5282
|
+
if (R && R.visemes && R.visemes.length) {
|
|
5283
|
+
const f = R.times[R.visemes.length - 1] + R.durations[R.visemes.length - 1];
|
|
5284
|
+
for (let C = 0; C < R.visemes.length; C++)
|
|
5285
5285
|
g.push({
|
|
5286
5286
|
mark: d,
|
|
5287
5287
|
template: { name: "viseme" },
|
|
5288
|
-
ts: [(
|
|
5288
|
+
ts: [(R.times[C] - 0.6) / f, (R.times[C] + 0.5) / f, (R.times[C] + R.durations[C] + 0.5) / f],
|
|
5289
5289
|
vs: {
|
|
5290
|
-
["viseme_" +
|
|
5290
|
+
["viseme_" + R.visemes[C]]: [null, R.visemes[C] === "PP" || R.visemes[C] === "FF" ? 0.9 : 0.6, 0]
|
|
5291
5291
|
}
|
|
5292
5292
|
});
|
|
5293
5293
|
}
|
|
5294
5294
|
a = "", d++;
|
|
5295
5295
|
}
|
|
5296
|
-
if (p ||
|
|
5297
|
-
if (c.length ||
|
|
5298
|
-
const
|
|
5296
|
+
if (p || L) {
|
|
5297
|
+
if (c.length || L && g.length) {
|
|
5298
|
+
const R = {
|
|
5299
5299
|
anim: g
|
|
5300
5300
|
};
|
|
5301
|
-
n && (
|
|
5301
|
+
n && (R.onSubtitles = n), c.length && !e.avatarMute && (R.text = c, e.avatarMood && (R.mood = e.avatarMood), e.ttsLang && (R.lang = e.ttsLang), e.ttsVoice && (R.voice = e.ttsVoice), e.ttsRate && (R.rate = e.ttsRate), e.ttsVoice && (R.pitch = e.ttsPitch), e.ttsVolume && (R.volume = e.ttsVolume)), this.speechQueue.push(R), c = [], a = "", d = 0, g = [];
|
|
5302
5302
|
}
|
|
5303
|
-
if (
|
|
5304
|
-
let
|
|
5305
|
-
|
|
5303
|
+
if (B) {
|
|
5304
|
+
let R = this.animEmojis[b[x]];
|
|
5305
|
+
R && R.link && (R = this.animEmojis[R.link]), R && this.speechQueue.push({ emoji: R });
|
|
5306
5306
|
}
|
|
5307
5307
|
this.speechQueue.push({ break: 100 });
|
|
5308
5308
|
}
|
|
@@ -5398,10 +5398,10 @@ class Be {
|
|
|
5398
5398
|
let b = 0.6 + this.convertRange(g, [0, u], [0, 0.4]);
|
|
5399
5399
|
if (u = Math.min(u, d.visemes.length * 200), c > 0)
|
|
5400
5400
|
for (let x = 0; x < d.visemes.length; x++) {
|
|
5401
|
-
const
|
|
5401
|
+
const L = r + d.times[x] / c * u, O = d.durations[x] / c * u;
|
|
5402
5402
|
o.push({
|
|
5403
5403
|
template: { name: "viseme" },
|
|
5404
|
-
ts: [
|
|
5404
|
+
ts: [L - Math.min(60, 2 * O / 3), L + Math.min(25, O / 2), L + O + Math.min(60, O / 2)],
|
|
5405
5405
|
vs: {
|
|
5406
5406
|
["viseme_" + d.visemes[x]]: [null, d.visemes[x] === "PP" || d.visemes[x] === "FF" ? 0.9 : b, 0]
|
|
5407
5407
|
}
|
|
@@ -5483,7 +5483,7 @@ class Be {
|
|
|
5483
5483
|
s.lang = o, s.rate = Math.max(0.1, Math.min(10, l)), s.pitch = Math.max(0, Math.min(2, h)), s.volume = Math.max(0, Math.min(1, r));
|
|
5484
5484
|
const u = speechSynthesis.getVoices(), a = t.voice || this.avatar.ttsVoice || this.opt.ttsVoice;
|
|
5485
5485
|
if (a && u.length > 0) {
|
|
5486
|
-
const p = u.find((
|
|
5486
|
+
const p = u.find((B) => B.name.includes(a) || B.lang === o);
|
|
5487
5487
|
p && (s.voice = p);
|
|
5488
5488
|
}
|
|
5489
5489
|
const d = i.length * 100 / s.rate, c = this.audioCtx.createBuffer(1, this.audioCtx.sampleRate * (d / 1e3), this.audioCtx.sampleRate), g = this.avatar.lipsyncLang || this.opt.lipsyncLang || "en", b = this.lipsyncPreProcessText(i, g), x = this.lipsyncWordsToVisemes(b, g);
|
|
@@ -5495,22 +5495,22 @@ class Be {
|
|
|
5495
5495
|
hasVisemes: x && x.visemes && x.visemes.length > 0,
|
|
5496
5496
|
estimatedDuration: d
|
|
5497
5497
|
});
|
|
5498
|
-
const
|
|
5498
|
+
const L = [];
|
|
5499
5499
|
if (x && x.visemes && x.visemes.length > 0) {
|
|
5500
5500
|
const p = x.times[x.visemes.length - 1] + x.durations[x.visemes.length - 1];
|
|
5501
|
-
for (let
|
|
5502
|
-
const
|
|
5503
|
-
|
|
5501
|
+
for (let B = 0; B < x.visemes.length; B++) {
|
|
5502
|
+
const M = x.visemes[B], R = x.times[B] / p, f = x.durations[B] / p, C = R * d, S = f * d;
|
|
5503
|
+
L.push({
|
|
5504
5504
|
template: { name: "viseme" },
|
|
5505
|
-
ts: [
|
|
5505
|
+
ts: [C - Math.min(60, 2 * S / 3), C + Math.min(25, S / 2), C + S + Math.min(60, S / 2)],
|
|
5506
5506
|
vs: {
|
|
5507
|
-
["viseme_" +
|
|
5507
|
+
["viseme_" + M]: [null, M === "PP" || M === "FF" ? 0.9 : 0.6, 0]
|
|
5508
5508
|
}
|
|
5509
5509
|
});
|
|
5510
5510
|
}
|
|
5511
5511
|
}
|
|
5512
|
-
const
|
|
5513
|
-
this.audioPlaylist.push({ anim:
|
|
5512
|
+
const O = [...t.anim, ...L];
|
|
5513
|
+
this.audioPlaylist.push({ anim: O, audio: c }), 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);
|
|
@@ -5577,8 +5577,8 @@ class Be {
|
|
|
5577
5577
|
const c = e.toLowerCase().split(/\s+/), g = [];
|
|
5578
5578
|
for (const b of c)
|
|
5579
5579
|
for (const x of b) {
|
|
5580
|
-
let
|
|
5581
|
-
"aeiou".includes(x) ?
|
|
5580
|
+
let L = "aa";
|
|
5581
|
+
"aeiou".includes(x) ? L = "aa" : "bp".includes(x) ? L = "PP" : "fv".includes(x) ? L = "FF" : "st".includes(x) ? L = "SS" : "dln".includes(x) ? L = "DD" : "kg".includes(x) ? L = "kk" : "rw".includes(x) && (L = "RR"), g.push(L);
|
|
5582
5582
|
}
|
|
5583
5583
|
r = {
|
|
5584
5584
|
visemes: g.map((b, x) => ({
|
|
@@ -5675,8 +5675,8 @@ class Be {
|
|
|
5675
5675
|
const c = e.toLowerCase().split(/\s+/), g = [];
|
|
5676
5676
|
for (const b of c)
|
|
5677
5677
|
for (const x of b) {
|
|
5678
|
-
let
|
|
5679
|
-
"aeiou".includes(x) ?
|
|
5678
|
+
let L = "aa";
|
|
5679
|
+
"aeiou".includes(x) ? L = "aa" : "bp".includes(x) ? L = "PP" : "fv".includes(x) ? L = "FF" : "st".includes(x) ? L = "SS" : "dln".includes(x) ? L = "DD" : "kg".includes(x) ? L = "kk" : "rw".includes(x) && (L = "RR"), g.push(L);
|
|
5680
5680
|
}
|
|
5681
5681
|
r = {
|
|
5682
5682
|
visemes: g.map((b, x) => ({
|
|
@@ -6146,7 +6146,7 @@ class Be {
|
|
|
6146
6146
|
*/
|
|
6147
6147
|
lookAtCamera(t) {
|
|
6148
6148
|
let e;
|
|
6149
|
-
if (this.speakTo && (e = new
|
|
6149
|
+
if (this.speakTo && (e = new y.Vector3(), this.speakTo.objectLeftEye?.isObject3D ? (this.speakTo.armature.objectHead, this.speakTo.objectLeftEye.updateMatrixWorld(!0), this.speakTo.objectRightEye.updateMatrixWorld(!0), be.setFromMatrixPosition(this.speakTo.objectLeftEye.matrixWorld), Re.setFromMatrixPosition(this.speakTo.objectRightEye.matrixWorld), e.addVectors(be, 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);
|
|
@@ -6159,14 +6159,14 @@ class Be {
|
|
|
6159
6159
|
this.lookAt(null, null, t);
|
|
6160
6160
|
return;
|
|
6161
6161
|
}
|
|
6162
|
-
this.objectLeftEye.updateMatrixWorld(!0), this.objectRightEye.updateMatrixWorld(!0),
|
|
6163
|
-
const n = new
|
|
6162
|
+
this.objectLeftEye.updateMatrixWorld(!0), this.objectRightEye.updateMatrixWorld(!0), be.setFromMatrixPosition(this.objectLeftEye.matrixWorld), Re.setFromMatrixPosition(this.objectRightEye.matrixWorld), be.add(Re).divideScalar(2), K.copy(this.armature.quaternion), K.multiply(this.poseTarget.props["Hips.quaternion"]), K.multiply(this.poseTarget.props["Spine.quaternion"]), K.multiply(this.poseTarget.props["Spine1.quaternion"]), K.multiply(this.poseTarget.props["Spine2.quaternion"]), K.multiply(this.poseTarget.props["Neck.quaternion"]), K.multiply(this.poseTarget.props["Head.quaternion"]);
|
|
6163
|
+
const n = new y.Vector3().subVectors(e, be).normalize(), i = Math.atan2(n.x, n.z), s = Math.asin(-n.y);
|
|
6164
6164
|
Z.set(s, i, 0, "YXZ");
|
|
6165
|
-
const l = new
|
|
6165
|
+
const l = new y.Quaternion().setFromEuler(Z), h = new y.Quaternion().copy(l).multiply(K.clone().invert());
|
|
6166
6166
|
Z.setFromQuaternion(h, "YXZ");
|
|
6167
6167
|
let r = Z.x / (40 / 24) + 0.2, u = Z.y / (9 / 4), a = Math.min(0.6, Math.max(-0.3, r)), d = Math.min(0.8, Math.max(-0.8, u)), c = (Math.random() - 0.5) / 4, g = (Math.random() - 0.5) / 4;
|
|
6168
6168
|
if (t) {
|
|
6169
|
-
let b = this.animQueue.findIndex((
|
|
6169
|
+
let b = this.animQueue.findIndex((L) => L.template.name === "lookat");
|
|
6170
6170
|
b !== -1 && this.animQueue.splice(b, 1);
|
|
6171
6171
|
const x = {
|
|
6172
6172
|
name: "lookat",
|
|
@@ -6196,23 +6196,23 @@ class Be {
|
|
|
6196
6196
|
if (!this.camera) return;
|
|
6197
6197
|
const i = this.nodeAvatar.getBoundingClientRect();
|
|
6198
6198
|
this.objectLeftEye.updateMatrixWorld(!0), this.objectRightEye.updateMatrixWorld(!0);
|
|
6199
|
-
const s = new
|
|
6199
|
+
const s = new y.Vector3().setFromMatrixPosition(this.objectLeftEye.matrixWorld), o = new y.Vector3().setFromMatrixPosition(this.objectRightEye.matrixWorld), l = new y.Vector3().addVectors(s, o).divideScalar(2);
|
|
6200
6200
|
l.project(this.camera);
|
|
6201
6201
|
let h = (l.x + 1) / 2 * i.width + i.left, r = -(l.y - 1) / 2 * i.height + i.top;
|
|
6202
|
-
t === null && (t = h), e === null && (e = r),
|
|
6203
|
-
let u = Z.x / (40 / 24), a = Z.y / (9 / 4), d = Math.min(0.4, Math.max(-0.4, this.camera.rotation.x)), c = Math.min(0.4, Math.max(-0.4, this.camera.rotation.y)), g = Math.max(window.innerWidth - h, h), b = Math.max(window.innerHeight - r, r), x = this.convertRange(e, [r - b, r + b], [-0.3, 0.6]) - u + d,
|
|
6204
|
-
x = Math.min(0.6, Math.max(-0.3, x)),
|
|
6205
|
-
let
|
|
6202
|
+
t === null && (t = h), e === null && (e = r), K.copy(this.armature.quaternion), K.multiply(this.poseTarget.props["Hips.quaternion"]), K.multiply(this.poseTarget.props["Spine.quaternion"]), K.multiply(this.poseTarget.props["Spine1.quaternion"]), K.multiply(this.poseTarget.props["Spine2.quaternion"]), K.multiply(this.poseTarget.props["Neck.quaternion"]), K.multiply(this.poseTarget.props["Head.quaternion"]), Z.setFromQuaternion(K);
|
|
6203
|
+
let u = Z.x / (40 / 24), a = Z.y / (9 / 4), d = Math.min(0.4, Math.max(-0.4, this.camera.rotation.x)), c = Math.min(0.4, Math.max(-0.4, this.camera.rotation.y)), g = Math.max(window.innerWidth - h, h), b = Math.max(window.innerHeight - r, r), x = this.convertRange(e, [r - b, r + b], [-0.3, 0.6]) - u + d, L = this.convertRange(t, [h - g, h + g], [-0.8, 0.8]) - a + c;
|
|
6204
|
+
x = Math.min(0.6, Math.max(-0.3, x)), L = Math.min(0.8, Math.max(-0.8, L));
|
|
6205
|
+
let O = (Math.random() - 0.5) / 4, p = (Math.random() - 0.5) / 4;
|
|
6206
6206
|
if (n) {
|
|
6207
|
-
let
|
|
6208
|
-
|
|
6209
|
-
const
|
|
6207
|
+
let B = this.animQueue.findIndex((R) => R.template.name === "lookat");
|
|
6208
|
+
B !== -1 && this.animQueue.splice(B, 1);
|
|
6209
|
+
const M = {
|
|
6210
6210
|
name: "lookat",
|
|
6211
6211
|
dt: [750, n],
|
|
6212
6212
|
vs: {
|
|
6213
|
-
bodyRotateX: [x +
|
|
6214
|
-
bodyRotateY: [
|
|
6215
|
-
eyesRotateX: [-3 *
|
|
6213
|
+
bodyRotateX: [x + O],
|
|
6214
|
+
bodyRotateY: [L + p],
|
|
6215
|
+
eyesRotateX: [-3 * O + 0.1],
|
|
6216
6216
|
eyesRotateY: [-5 * p],
|
|
6217
6217
|
browInnerUp: [[0, 0.7]],
|
|
6218
6218
|
mouthLeft: [[0, 0.7]],
|
|
@@ -6221,7 +6221,7 @@ class Be {
|
|
|
6221
6221
|
headMove: [0]
|
|
6222
6222
|
}
|
|
6223
6223
|
};
|
|
6224
|
-
this.animQueue.push(this.animFactory(
|
|
6224
|
+
this.animQueue.push(this.animFactory(M));
|
|
6225
6225
|
}
|
|
6226
6226
|
}
|
|
6227
6227
|
/**
|
|
@@ -6232,14 +6232,14 @@ class Be {
|
|
|
6232
6232
|
*/
|
|
6233
6233
|
touchAt(t, e) {
|
|
6234
6234
|
if (!this.camera) return;
|
|
6235
|
-
const n = this.nodeAvatar.getBoundingClientRect(), i = new
|
|
6235
|
+
const n = this.nodeAvatar.getBoundingClientRect(), i = new y.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 y.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, h = new
|
|
6242
|
+
const l = o[0].point, h = new y.Vector3(), r = new y.Vector3();
|
|
6243
6243
|
this.objectLeftArm.getWorldPosition(h), this.objectRightArm.getWorldPosition(r);
|
|
6244
6244
|
const u = h.distanceToSquared(l), a = r.distanceToSquared(l);
|
|
6245
6245
|
u < a ? (this.ikSolve({
|
|
@@ -6283,7 +6283,7 @@ class Be {
|
|
|
6283
6283
|
{ link: "LeftForeArm", minx: -0.5, maxx: 1.5, miny: -1.5, maxy: 1.5, minz: -0.5, maxz: 3 },
|
|
6284
6284
|
{ link: "LeftArm", minx: -1.5, maxx: 1.5, miny: -1.5, maxy: 1.5, minz: -1, maxz: 3 }
|
|
6285
6285
|
]
|
|
6286
|
-
}, new
|
|
6286
|
+
}, new y.Vector3(
|
|
6287
6287
|
this.gaussianRandom(0, 0.5),
|
|
6288
6288
|
this.gaussianRandom(-0.8, -0.2),
|
|
6289
6289
|
this.gaussianRandom(0, 0.5)
|
|
@@ -6295,15 +6295,15 @@ class Be {
|
|
|
6295
6295
|
{ link: "RightForeArm", minx: -0.5, maxx: 1.5, miny: -1.5, maxy: 1.5, minz: -3, maxz: 0.5 },
|
|
6296
6296
|
{ link: "RightArm" }
|
|
6297
6297
|
]
|
|
6298
|
-
}, new
|
|
6298
|
+
}, new y.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 y.Quaternion().setFromEuler(new y.Euler(0, -1 - Math.random(), 0)),
|
|
6306
|
+
"RightHand.quaternion": new y.Quaternion().setFromEuler(new y.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) => {
|
|
@@ -6388,9 +6388,9 @@ class Be {
|
|
|
6388
6388
|
let h = this.animQueue.find((a) => a.template.name === "pose");
|
|
6389
6389
|
h && (h.ts[0] = 1 / 0), Object.entries(l.pose.props).forEach((a) => {
|
|
6390
6390
|
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;
|
|
6391
|
-
}), this.mixer ? console.log("Using existing mixer for FBX animation, preserving morph targets") : (this.mixer = new
|
|
6391
|
+
}), this.mixer ? console.log("Using existing mixer for FBX animation, preserving morph targets") : (this.mixer = new y.AnimationMixer(this.armature), console.log("Created new mixer for FBX animation")), this.mixer.addEventListener("finished", this.stopAnimation.bind(this), { once: !0 });
|
|
6392
6392
|
const r = Math.ceil(n / l.clip.duration), u = this.mixer.clipAction(l.clip);
|
|
6393
|
-
u.setLoop(
|
|
6393
|
+
u.setLoop(y.LoopRepeat, r), u.clampWhenFinished = !0, this.currentFBXAction = u;
|
|
6394
6394
|
try {
|
|
6395
6395
|
u.fadeIn(0.5).play(), console.log("FBX animation started successfully:", t);
|
|
6396
6396
|
} catch (a) {
|
|
@@ -6442,39 +6442,39 @@ class Be {
|
|
|
6442
6442
|
if (a && a.animations && a.animations[i]) {
|
|
6443
6443
|
let d = a.animations[i];
|
|
6444
6444
|
const c = /* @__PURE__ */ new Set();
|
|
6445
|
-
this.armature && this.armature.traverse((
|
|
6446
|
-
(
|
|
6445
|
+
this.armature && this.armature.traverse((f) => {
|
|
6446
|
+
(f.isBone || f.type === "Bone") && c.add(f.name);
|
|
6447
6447
|
});
|
|
6448
|
-
const g = /* @__PURE__ */ new Map(), b = (
|
|
6449
|
-
if (c.has(
|
|
6450
|
-
return
|
|
6451
|
-
let
|
|
6452
|
-
if (c.has(
|
|
6453
|
-
return
|
|
6454
|
-
const
|
|
6455
|
-
if (
|
|
6456
|
-
if (
|
|
6448
|
+
const g = /* @__PURE__ */ new Map(), b = (f) => {
|
|
6449
|
+
if (c.has(f))
|
|
6450
|
+
return f;
|
|
6451
|
+
let C = f.replace(/^mixamorig/i, "").replace(/^CC_Base_/i, "").replace(/^RPM_/i, "");
|
|
6452
|
+
if (c.has(C))
|
|
6453
|
+
return C;
|
|
6454
|
+
const S = C.toLowerCase();
|
|
6455
|
+
if (S.includes("left") && S.includes("arm")) {
|
|
6456
|
+
if (S.includes("fore") || S.includes("lower")) {
|
|
6457
6457
|
if (c.has("LeftForeArm")) return "LeftForeArm";
|
|
6458
6458
|
if (c.has("LeftForearm")) return "LeftForearm";
|
|
6459
|
-
} else if (!
|
|
6459
|
+
} else if (!S.includes("fore") && !S.includes("hand") && c.has("LeftArm"))
|
|
6460
6460
|
return "LeftArm";
|
|
6461
6461
|
}
|
|
6462
|
-
if (
|
|
6463
|
-
if (
|
|
6462
|
+
if (S.includes("right") && S.includes("arm")) {
|
|
6463
|
+
if (S.includes("fore") || S.includes("lower")) {
|
|
6464
6464
|
if (c.has("RightForeArm")) return "RightForeArm";
|
|
6465
6465
|
if (c.has("RightForearm")) return "RightForearm";
|
|
6466
|
-
} else if (!
|
|
6466
|
+
} else if (!S.includes("fore") && !S.includes("hand") && c.has("RightArm"))
|
|
6467
6467
|
return "RightArm";
|
|
6468
6468
|
}
|
|
6469
|
-
if (
|
|
6469
|
+
if (S.includes("left") && S.includes("hand") && !S.includes("index") && !S.includes("thumb") && !S.includes("middle") && !S.includes("ring") && !S.includes("pinky") && c.has("LeftHand"))
|
|
6470
6470
|
return "LeftHand";
|
|
6471
|
-
if (
|
|
6471
|
+
if (S.includes("right") && S.includes("hand") && !S.includes("index") && !S.includes("thumb") && !S.includes("middle") && !S.includes("ring") && !S.includes("pinky") && c.has("RightHand"))
|
|
6472
6472
|
return "RightHand";
|
|
6473
|
-
if (
|
|
6473
|
+
if (S.includes("left") && (S.includes("shoulder") || S.includes("clavicle")) && c.has("LeftShoulder"))
|
|
6474
6474
|
return "LeftShoulder";
|
|
6475
|
-
if (
|
|
6475
|
+
if (S.includes("right") && (S.includes("shoulder") || S.includes("clavicle")) && c.has("RightShoulder"))
|
|
6476
6476
|
return "RightShoulder";
|
|
6477
|
-
const
|
|
6477
|
+
const U = {
|
|
6478
6478
|
// Arm bones - exact matches
|
|
6479
6479
|
LeftArm: "LeftArm",
|
|
6480
6480
|
leftArm: "LeftArm",
|
|
@@ -6514,65 +6514,65 @@ class Be {
|
|
|
6514
6514
|
Root: "Hips",
|
|
6515
6515
|
root: "Hips"
|
|
6516
6516
|
};
|
|
6517
|
-
if (
|
|
6518
|
-
const k =
|
|
6517
|
+
if (U[C]) {
|
|
6518
|
+
const k = U[C];
|
|
6519
6519
|
if (c.has(k))
|
|
6520
6520
|
return k;
|
|
6521
6521
|
}
|
|
6522
6522
|
for (const k of c)
|
|
6523
|
-
if (k.toLowerCase() ===
|
|
6523
|
+
if (k.toLowerCase() === S)
|
|
6524
6524
|
return k;
|
|
6525
6525
|
for (const k of c) {
|
|
6526
6526
|
const E = k.toLowerCase();
|
|
6527
|
-
if ((
|
|
6527
|
+
if ((S.includes("left") && E.includes("left") || S.includes("right") && E.includes("right")) && (S.includes("arm") && E.includes("arm") && !E.includes("fore") || S.includes("forearm") && E.includes("forearm") || S.includes("hand") && E.includes("hand") && !E.includes("index") && !E.includes("thumb") || S.includes("shoulder") && E.includes("shoulder")))
|
|
6528
6528
|
return k;
|
|
6529
6529
|
}
|
|
6530
6530
|
return null;
|
|
6531
6531
|
}, x = /* @__PURE__ */ new Set();
|
|
6532
|
-
d.tracks.forEach((
|
|
6533
|
-
const
|
|
6534
|
-
x.add(
|
|
6532
|
+
d.tracks.forEach((f) => {
|
|
6533
|
+
const C = f.name.split(".");
|
|
6534
|
+
x.add(C[0]);
|
|
6535
6535
|
}), console.log("=== Ready Player Me Animation Bone Analysis ==="), console.log("FBX bone names:", Array.from(x).sort().join(", ")), console.log("Avatar skeleton bone names:", Array.from(c).sort().join(", "));
|
|
6536
|
-
const
|
|
6537
|
-
(
|
|
6538
|
-
),
|
|
6539
|
-
(
|
|
6536
|
+
const L = Array.from(x).filter(
|
|
6537
|
+
(f) => f.toLowerCase().includes("arm") || f.toLowerCase().includes("hand") || f.toLowerCase().includes("shoulder")
|
|
6538
|
+
), O = Array.from(c).filter(
|
|
6539
|
+
(f) => f.includes("Arm") || f.includes("Hand") || f.includes("Shoulder")
|
|
6540
6540
|
);
|
|
6541
|
-
console.log("FBX arm/hand/shoulder bones:",
|
|
6542
|
-
const p = [],
|
|
6543
|
-
if (d.tracks.forEach((
|
|
6544
|
-
const
|
|
6541
|
+
console.log("FBX arm/hand/shoulder bones:", L.sort().join(", ")), console.log("Avatar arm/hand/shoulder bones:", O.sort().join(", "));
|
|
6542
|
+
const p = [], B = /* @__PURE__ */ new Set();
|
|
6543
|
+
if (d.tracks.forEach((f) => {
|
|
6544
|
+
const S = f.name.replaceAll("mixamorig", "").split("."), U = S[0], k = S[1], E = b(U);
|
|
6545
6545
|
if (E && k) {
|
|
6546
|
-
const
|
|
6547
|
-
|
|
6546
|
+
const Q = `${E}.${k}`, Y = f.clone();
|
|
6547
|
+
Y.name = Q, p.push(Y), U !== E && g.set(U, E);
|
|
6548
6548
|
} else
|
|
6549
|
-
|
|
6550
|
-
}),
|
|
6551
|
-
d = new
|
|
6549
|
+
B.add(U), (U.toLowerCase().includes("arm") || U.toLowerCase().includes("hand") || U.toLowerCase().includes("shoulder")) && console.warn(`⚠️ Arm bone "${U}" could not be mapped to avatar skeleton`);
|
|
6550
|
+
}), B.size > 0 && console.warn(`⚠️ ${B.size} bone(s) could not be mapped:`, Array.from(B).sort().join(", ")), p.length > 0) {
|
|
6551
|
+
d = new y.AnimationClip(d.name, d.duration, p), console.log(`✓ Created animation with ${p.length} mapped tracks (from ${d.tracks.length} original tracks)`), g.size > 0 && console.log(
|
|
6552
6552
|
`✓ Mapped ${g.size} bone(s):`,
|
|
6553
|
-
Array.from(g.entries()).map(([
|
|
6553
|
+
Array.from(g.entries()).map(([C, S]) => `${C}→${S}`).join(", ")
|
|
6554
6554
|
);
|
|
6555
|
-
const
|
|
6556
|
-
(
|
|
6555
|
+
const f = Array.from(g.values()).filter(
|
|
6556
|
+
(C) => C.includes("Arm") || C.includes("Hand") || C.includes("Shoulder")
|
|
6557
6557
|
);
|
|
6558
|
-
|
|
6558
|
+
f.length > 0 ? console.log(`✓ Arm bones mapped: ${f.join(", ")}`) : console.warn("⚠️ No arm bones were mapped! This may cause arm rigging issues.");
|
|
6559
6559
|
} else
|
|
6560
6560
|
console.error("❌ No tracks could be mapped! Animation may not work correctly.");
|
|
6561
|
-
const
|
|
6562
|
-
d.tracks.forEach((
|
|
6563
|
-
|
|
6564
|
-
const
|
|
6565
|
-
if (
|
|
6566
|
-
for (let
|
|
6567
|
-
|
|
6568
|
-
|
|
6569
|
-
} else
|
|
6561
|
+
const M = {};
|
|
6562
|
+
d.tracks.forEach((f) => {
|
|
6563
|
+
f.name = f.name.replaceAll("mixamorig", "");
|
|
6564
|
+
const C = f.name.split(".");
|
|
6565
|
+
if (C[1] === "position") {
|
|
6566
|
+
for (let S = 0; S < f.values.length; S++)
|
|
6567
|
+
f.values[S] = f.values[S] * s;
|
|
6568
|
+
M[f.name] = new y.Vector3(f.values[0], f.values[1], f.values[2]);
|
|
6569
|
+
} else C[1] === "quaternion" ? M[f.name] = new y.Quaternion(f.values[0], f.values[1], f.values[2], f.values[3]) : C[1] === "rotation" && (M[C[0] + ".quaternion"] = new y.Quaternion().setFromEuler(new y.Euler(f.values[0], f.values[1], f.values[2], "XYZ")).normalize());
|
|
6570
6570
|
});
|
|
6571
|
-
const
|
|
6572
|
-
|
|
6571
|
+
const R = { props: M };
|
|
6572
|
+
M["Hips.position"] && (M["Hips.position"].y < 0.5 ? R.lying = !0 : R.standing = !0), this.animClips.push({
|
|
6573
6573
|
url: t + "-" + i,
|
|
6574
6574
|
clip: d,
|
|
6575
|
-
pose:
|
|
6575
|
+
pose: R
|
|
6576
6576
|
}), this.playAnimation(t, e, n, i, s);
|
|
6577
6577
|
} else {
|
|
6578
6578
|
const d = "Animation " + t + " (ndx=" + i + ") not found";
|
|
@@ -6617,7 +6617,7 @@ class Be {
|
|
|
6617
6617
|
r.tracks.forEach((d) => {
|
|
6618
6618
|
d.name = d.name.replaceAll("mixamorig", "");
|
|
6619
6619
|
const c = d.name.split(".");
|
|
6620
|
-
c[1] === "position" ? u[d.name] = new
|
|
6620
|
+
c[1] === "position" ? u[d.name] = new y.Vector3(d.values[0] * s, d.values[1] * s, d.values[2] * s) : c[1] === "quaternion" ? u[d.name] = new y.Quaternion(d.values[0], d.values[1], d.values[2], d.values[3]) : c[1] === "rotation" && (u[c[0] + ".quaternion"] = new y.Quaternion().setFromEuler(new y.Euler(d.values[0], d.values[1], d.values[2], "XYZ")).normalize());
|
|
6621
6621
|
});
|
|
6622
6622
|
const a = { props: u };
|
|
6623
6623
|
u["Hips.position"] && (u["Hips.position"].y < 0.5 ? a.lying = !0 : a.standing = !0), this.animPoses.push({
|
|
@@ -6650,7 +6650,7 @@ class Be {
|
|
|
6650
6650
|
if (s) {
|
|
6651
6651
|
this.gestureTimeout && (clearTimeout(this.gestureTimeout), this.gestureTimeout = null);
|
|
6652
6652
|
let l = this.animQueue.findIndex((h) => h.template.name === "talkinghands");
|
|
6653
|
-
l !== -1 && (this.animQueue[l].ts = this.animQueue[l].ts.map((h) => 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
|
|
6653
|
+
l !== -1 && (this.animQueue[l].ts = this.animQueue[l].ts.map((h) => 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 y.Quaternion(0, 1, 0, 0), -0.25), this.gesture["LeftArm.quaternion"].rotateTowards(new y.Quaternion(0, 1, 0, 0), -0.25));
|
|
6654
6654
|
for (let [h, r] of Object.entries(this.gesture))
|
|
6655
6655
|
r.t = this.animClock, r.d = i, this.poseTarget.props.hasOwnProperty(h) && (this.poseTarget.props[h].copy(r), this.poseTarget.props[h].t = this.animClock, this.poseTarget.props[h].d = i);
|
|
6656
6656
|
e && Number.isFinite(e) && (this.gestureTimeout = setTimeout(this.stopGesture.bind(this, i), 1e3 * e));
|
|
@@ -6665,7 +6665,7 @@ class Be {
|
|
|
6665
6665
|
const d = [];
|
|
6666
6666
|
for (let b = 1; b < l.ts.length; b++) d.push(l.ts[b] - l.ts[b - 1]);
|
|
6667
6667
|
const c = o.template?.rescale || d.map((b) => b / u), g = e * 1e3 - u;
|
|
6668
|
-
l.ts = l.ts.map((b, x,
|
|
6668
|
+
l.ts = l.ts.map((b, x, L) => x === 0 ? h : L[x - 1] + d[x - 1] + c[x - 1] * g);
|
|
6669
6669
|
} else {
|
|
6670
6670
|
const d = e * 1e3 / u;
|
|
6671
6671
|
l.ts = l.ts.map((c) => h + d * (c - h));
|
|
@@ -6698,34 +6698,34 @@ class Be {
|
|
|
6698
6698
|
* @param {numeric} [d=null] If set, apply in d milliseconds
|
|
6699
6699
|
*/
|
|
6700
6700
|
ikSolve(t, e = null, n = !1, i = null) {
|
|
6701
|
-
const s = new
|
|
6701
|
+
const s = new y.Vector3(), o = new y.Vector3(), l = new y.Vector3(), h = new y.Vector3(), r = new y.Quaternion(), u = new y.Vector3(), a = new y.Vector3(), d = new y.Vector3(), c = this.ikMesh.getObjectByName(t.root);
|
|
6702
6702
|
c.position.setFromMatrixPosition(this.armature.getObjectByName(t.root).matrixWorld), c.quaternion.setFromRotationMatrix(this.armature.getObjectByName(t.root).matrixWorld), e && n && e.applyQuaternion(this.armature.quaternion).add(c.position);
|
|
6703
6703
|
const g = this.ikMesh.getObjectByName(t.effector), b = t.links;
|
|
6704
|
-
b.forEach((
|
|
6705
|
-
|
|
6704
|
+
b.forEach((L) => {
|
|
6705
|
+
L.bone = this.ikMesh.getObjectByName(L.link), L.bone.quaternion.copy(this.getPoseTemplateProp(L.link + ".quaternion"));
|
|
6706
6706
|
}), c.updateMatrixWorld(!0);
|
|
6707
6707
|
const x = t.iterations || 10;
|
|
6708
6708
|
if (e)
|
|
6709
|
-
for (let
|
|
6710
|
-
let
|
|
6711
|
-
for (let p = 0,
|
|
6712
|
-
const
|
|
6713
|
-
|
|
6714
|
-
let
|
|
6715
|
-
|
|
6709
|
+
for (let L = 0; L < x; L++) {
|
|
6710
|
+
let O = !1;
|
|
6711
|
+
for (let p = 0, B = b.length; p < B; p++) {
|
|
6712
|
+
const M = b[p].bone;
|
|
6713
|
+
M.matrixWorld.decompose(h, r, u), r.invert(), o.setFromMatrixPosition(g.matrixWorld), l.subVectors(o, h), l.applyQuaternion(r), l.normalize(), s.subVectors(e, h), s.applyQuaternion(r), s.normalize();
|
|
6714
|
+
let R = s.dot(l);
|
|
6715
|
+
R > 1 ? R = 1 : R < -1 && (R = -1), R = Math.acos(R), !(R < 1e-5) && (b[p].minAngle !== void 0 && R < b[p].minAngle && (R = b[p].minAngle), b[p].maxAngle !== void 0 && R > b[p].maxAngle && (R = b[p].maxAngle), a.crossVectors(l, s), a.normalize(), K.setFromAxisAngle(a, R), M.quaternion.multiply(K), M.rotation.setFromVector3(d.setFromEuler(M.rotation).clamp(new y.Vector3(
|
|
6716
6716
|
b[p].minx !== void 0 ? b[p].minx : -1 / 0,
|
|
6717
6717
|
b[p].miny !== void 0 ? b[p].miny : -1 / 0,
|
|
6718
6718
|
b[p].minz !== void 0 ? b[p].minz : -1 / 0
|
|
6719
|
-
), new
|
|
6719
|
+
), new y.Vector3(
|
|
6720
6720
|
b[p].maxx !== void 0 ? b[p].maxx : 1 / 0,
|
|
6721
6721
|
b[p].maxy !== void 0 ? b[p].maxy : 1 / 0,
|
|
6722
6722
|
b[p].maxz !== void 0 ? b[p].maxz : 1 / 0
|
|
6723
|
-
))),
|
|
6723
|
+
))), M.updateMatrixWorld(!0), O = !0);
|
|
6724
6724
|
}
|
|
6725
|
-
if (!
|
|
6725
|
+
if (!O) break;
|
|
6726
6726
|
}
|
|
6727
|
-
i && b.forEach((
|
|
6728
|
-
this.poseTarget.props[
|
|
6727
|
+
i && b.forEach((L) => {
|
|
6728
|
+
this.poseTarget.props[L.link + ".quaternion"].copy(L.bone.quaternion), this.poseTarget.props[L.link + ".quaternion"].t = this.animClock, this.poseTarget.props[L.link + ".quaternion"].d = i;
|
|
6729
6729
|
});
|
|
6730
6730
|
}
|
|
6731
6731
|
/**
|
|
@@ -6755,7 +6755,7 @@ const Ie = {
|
|
|
6755
6755
|
josh: "VR6AewLTigWG4xSOukaG"
|
|
6756
6756
|
// Male, American
|
|
6757
6757
|
}
|
|
6758
|
-
},
|
|
6758
|
+
}, Ce = {
|
|
6759
6759
|
defaultVoice: "aura-2-thalia-en",
|
|
6760
6760
|
// Thalia (Female, English)
|
|
6761
6761
|
voices: {
|
|
@@ -6775,7 +6775,7 @@ const Ie = {
|
|
|
6775
6775
|
// Male, English - Powerful
|
|
6776
6776
|
}
|
|
6777
6777
|
};
|
|
6778
|
-
function
|
|
6778
|
+
function Me() {
|
|
6779
6779
|
return {
|
|
6780
6780
|
service: "elevenlabs",
|
|
6781
6781
|
endpoint: Ie.endpoint,
|
|
@@ -6785,7 +6785,7 @@ function Ee() {
|
|
|
6785
6785
|
};
|
|
6786
6786
|
}
|
|
6787
6787
|
function kt() {
|
|
6788
|
-
const X =
|
|
6788
|
+
const X = Me(), t = [];
|
|
6789
6789
|
return Object.entries(X.voices).forEach(([e, n]) => {
|
|
6790
6790
|
t.push({
|
|
6791
6791
|
value: n,
|
|
@@ -6793,7 +6793,7 @@ function kt() {
|
|
|
6793
6793
|
});
|
|
6794
6794
|
}), t;
|
|
6795
6795
|
}
|
|
6796
|
-
const Ve =
|
|
6796
|
+
const Ve = He(({
|
|
6797
6797
|
avatarUrl: X = "/avatars/brunette.glb",
|
|
6798
6798
|
avatarBody: t = "F",
|
|
6799
6799
|
mood: e = "neutral",
|
|
@@ -6814,311 +6814,311 @@ const Ve = Me(({
|
|
|
6814
6814
|
className: g = "",
|
|
6815
6815
|
style: b = {},
|
|
6816
6816
|
animations: x = {}
|
|
6817
|
-
},
|
|
6818
|
-
const
|
|
6817
|
+
}, L) => {
|
|
6818
|
+
const O = V(null), p = V(null), B = V(r), M = V(null), R = V(null), f = V(!1), C = V({ remainingText: null, originalText: null, options: null }), S = V([]), U = V(0), [k, E] = ce(!0), [Q, Y] = ce(null), [$, re] = ce(!1), [he, oe] = ce(!1);
|
|
6819
6819
|
de(() => {
|
|
6820
|
-
|
|
6821
|
-
}, [
|
|
6822
|
-
|
|
6820
|
+
f.current = he;
|
|
6821
|
+
}, [he]), de(() => {
|
|
6822
|
+
B.current = r;
|
|
6823
6823
|
}, [r]);
|
|
6824
|
-
const
|
|
6825
|
-
let
|
|
6826
|
-
le === "browser" ?
|
|
6824
|
+
const se = Me(), le = i || se.service;
|
|
6825
|
+
let j;
|
|
6826
|
+
le === "browser" ? j = {
|
|
6827
6827
|
service: "browser",
|
|
6828
6828
|
endpoint: "",
|
|
6829
6829
|
apiKey: null,
|
|
6830
6830
|
defaultVoice: "Google US English"
|
|
6831
|
-
} : le === "elevenlabs" ?
|
|
6831
|
+
} : le === "elevenlabs" ? j = {
|
|
6832
6832
|
service: "elevenlabs",
|
|
6833
6833
|
endpoint: "https://api.elevenlabs.io/v1/text-to-speech",
|
|
6834
|
-
apiKey: o ||
|
|
6835
|
-
defaultVoice: s ||
|
|
6836
|
-
voices:
|
|
6837
|
-
} : le === "deepgram" ?
|
|
6834
|
+
apiKey: o || se.apiKey,
|
|
6835
|
+
defaultVoice: s || se.defaultVoice || Ie.defaultVoice,
|
|
6836
|
+
voices: se.voices || Ie.voices
|
|
6837
|
+
} : le === "deepgram" ? j = {
|
|
6838
6838
|
service: "deepgram",
|
|
6839
6839
|
endpoint: "https://api.deepgram.com/v1/speak",
|
|
6840
|
-
apiKey: o ||
|
|
6841
|
-
defaultVoice: s ||
|
|
6842
|
-
voices:
|
|
6843
|
-
} :
|
|
6844
|
-
...
|
|
6840
|
+
apiKey: o || se.apiKey,
|
|
6841
|
+
defaultVoice: s || se.defaultVoice || Ce.defaultVoice,
|
|
6842
|
+
voices: se.voices || Ce.voices
|
|
6843
|
+
} : j = {
|
|
6844
|
+
...se,
|
|
6845
6845
|
// Override API key if provided via props
|
|
6846
|
-
apiKey: o !== null ? o :
|
|
6846
|
+
apiKey: o !== null ? o : se.apiKey
|
|
6847
6847
|
};
|
|
6848
6848
|
const v = {
|
|
6849
6849
|
url: X,
|
|
6850
6850
|
body: t,
|
|
6851
6851
|
avatarMood: e,
|
|
6852
6852
|
ttsLang: le === "browser" ? "en-US" : n,
|
|
6853
|
-
ttsVoice: s ||
|
|
6853
|
+
ttsVoice: s || j.defaultVoice,
|
|
6854
6854
|
lipsyncLang: "en",
|
|
6855
6855
|
showFullAvatar: r,
|
|
6856
6856
|
bodyMovement: l,
|
|
6857
6857
|
movementIntensity: h
|
|
6858
|
-
},
|
|
6859
|
-
ttsEndpoint:
|
|
6860
|
-
ttsApikey:
|
|
6858
|
+
}, I = {
|
|
6859
|
+
ttsEndpoint: j.endpoint,
|
|
6860
|
+
ttsApikey: j.apiKey,
|
|
6861
6861
|
ttsService: le,
|
|
6862
6862
|
lipsyncModules: ["en"],
|
|
6863
6863
|
cameraView: u
|
|
6864
|
-
}, H =
|
|
6865
|
-
if (!(!
|
|
6864
|
+
}, H = N(async () => {
|
|
6865
|
+
if (!(!O.current || p.current))
|
|
6866
6866
|
try {
|
|
6867
|
-
if (E(!0),
|
|
6868
|
-
if (
|
|
6869
|
-
const
|
|
6870
|
-
d(
|
|
6867
|
+
if (E(!0), Y(null), p.current = new Be(O.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), x && Object.keys(x).length > 0 && (p.current.customAnimations = x), await p.current.showAvatar(v, (T) => {
|
|
6868
|
+
if (T.lengthComputable) {
|
|
6869
|
+
const D = Math.min(100, Math.round(T.loaded / T.total * 100));
|
|
6870
|
+
d(D);
|
|
6871
6871
|
}
|
|
6872
|
-
}), await new Promise((
|
|
6873
|
-
const
|
|
6874
|
-
p.current.lipsync && Object.keys(p.current.lipsync).length > 0 ?
|
|
6872
|
+
}), await new Promise((T) => {
|
|
6873
|
+
const D = () => {
|
|
6874
|
+
p.current.lipsync && Object.keys(p.current.lipsync).length > 0 ? T() : setTimeout(D, 100);
|
|
6875
6875
|
};
|
|
6876
|
-
|
|
6876
|
+
D();
|
|
6877
6877
|
}), p.current && p.current.setShowFullAvatar)
|
|
6878
6878
|
try {
|
|
6879
6879
|
p.current.setShowFullAvatar(r);
|
|
6880
|
-
} catch (
|
|
6881
|
-
console.warn("Error setting full body mode on initialization:",
|
|
6880
|
+
} catch (T) {
|
|
6881
|
+
console.warn("Error setting full body mode on initialization:", T);
|
|
6882
6882
|
}
|
|
6883
|
-
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()), E(!1),
|
|
6884
|
-
const
|
|
6883
|
+
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()), E(!1), re(!0), a(p.current);
|
|
6884
|
+
const A = () => {
|
|
6885
6885
|
document.visibilityState === "visible" ? p.current?.start() : p.current?.stop();
|
|
6886
6886
|
};
|
|
6887
|
-
return document.addEventListener("visibilitychange",
|
|
6888
|
-
document.removeEventListener("visibilitychange",
|
|
6887
|
+
return document.addEventListener("visibilitychange", A), () => {
|
|
6888
|
+
document.removeEventListener("visibilitychange", A);
|
|
6889
6889
|
};
|
|
6890
|
-
} catch (
|
|
6891
|
-
console.error("Error initializing TalkingHead:",
|
|
6890
|
+
} catch (w) {
|
|
6891
|
+
console.error("Error initializing TalkingHead:", w), Y(w.message || "Failed to initialize avatar"), E(!1), c(w);
|
|
6892
6892
|
}
|
|
6893
6893
|
}, [X, t, e, n, i, s, o, r, l, h, u]);
|
|
6894
6894
|
de(() => (H(), () => {
|
|
6895
6895
|
p.current && (p.current.stop(), p.current.dispose(), p.current = null);
|
|
6896
6896
|
}), [H]), de(() => {
|
|
6897
|
-
if (!
|
|
6898
|
-
const
|
|
6899
|
-
for (const
|
|
6897
|
+
if (!O.current || !p.current) return;
|
|
6898
|
+
const w = new ResizeObserver((T) => {
|
|
6899
|
+
for (const D of T)
|
|
6900
6900
|
p.current && p.current.onResize && p.current.onResize();
|
|
6901
6901
|
});
|
|
6902
|
-
|
|
6903
|
-
const
|
|
6902
|
+
w.observe(O.current);
|
|
6903
|
+
const A = () => {
|
|
6904
6904
|
p.current && p.current.onResize && p.current.onResize();
|
|
6905
6905
|
};
|
|
6906
|
-
return window.addEventListener("resize",
|
|
6907
|
-
|
|
6906
|
+
return window.addEventListener("resize", A), () => {
|
|
6907
|
+
w.disconnect(), window.removeEventListener("resize", A);
|
|
6908
6908
|
};
|
|
6909
|
-
}, [
|
|
6910
|
-
const P =
|
|
6909
|
+
}, [$]);
|
|
6910
|
+
const P = N(async () => {
|
|
6911
6911
|
if (p.current && p.current.audioCtx)
|
|
6912
6912
|
try {
|
|
6913
6913
|
(p.current.audioCtx.state === "suspended" || p.current.audioCtx.state === "interrupted") && (await p.current.audioCtx.resume(), console.log("Audio context resumed"));
|
|
6914
|
-
} catch (
|
|
6915
|
-
console.warn("Failed to resume audio context:",
|
|
6914
|
+
} catch (w) {
|
|
6915
|
+
console.warn("Failed to resume audio context:", w);
|
|
6916
6916
|
}
|
|
6917
|
-
}, []),
|
|
6918
|
-
if (p.current &&
|
|
6917
|
+
}, []), G = N(async (w, A = {}) => {
|
|
6918
|
+
if (p.current && $)
|
|
6919
6919
|
try {
|
|
6920
|
-
|
|
6921
|
-
const
|
|
6922
|
-
|
|
6923
|
-
const
|
|
6924
|
-
...
|
|
6925
|
-
lipsyncLang:
|
|
6920
|
+
R.current && (clearInterval(R.current), R.current = null), M.current = { text: w, options: A }, C.current = { remainingText: null, originalText: null, options: null };
|
|
6921
|
+
const T = /[!\.\?\n\p{Extended_Pictographic}]/ug, D = w.split(T).map((W) => W.trim()).filter((W) => W.length > 0);
|
|
6922
|
+
S.current = D, U.current = 0, oe(!1), f.current = !1, await P();
|
|
6923
|
+
const J = {
|
|
6924
|
+
...A,
|
|
6925
|
+
lipsyncLang: A.lipsyncLang || v.lipsyncLang || "en"
|
|
6926
6926
|
};
|
|
6927
|
-
if (
|
|
6928
|
-
const
|
|
6929
|
-
let
|
|
6930
|
-
const
|
|
6931
|
-
let
|
|
6932
|
-
|
|
6933
|
-
if (
|
|
6927
|
+
if (A.onSpeechEnd && p.current) {
|
|
6928
|
+
const W = p.current;
|
|
6929
|
+
let ee = null, Le = 0;
|
|
6930
|
+
const Ae = 1200;
|
|
6931
|
+
let xe = !1;
|
|
6932
|
+
ee = setInterval(() => {
|
|
6933
|
+
if (Le++, f.current)
|
|
6934
6934
|
return;
|
|
6935
|
-
if (
|
|
6936
|
-
if (
|
|
6937
|
-
|
|
6935
|
+
if (Le > Ae) {
|
|
6936
|
+
if (ee && (clearInterval(ee), ee = null, R.current = null), !xe && !f.current) {
|
|
6937
|
+
xe = !0;
|
|
6938
6938
|
try {
|
|
6939
|
-
|
|
6939
|
+
A.onSpeechEnd();
|
|
6940
6940
|
} catch (Ne) {
|
|
6941
6941
|
console.error("Error in onSpeechEnd callback (timeout):", Ne);
|
|
6942
6942
|
}
|
|
6943
6943
|
}
|
|
6944
6944
|
return;
|
|
6945
6945
|
}
|
|
6946
|
-
const
|
|
6947
|
-
|
|
6948
|
-
if (
|
|
6949
|
-
|
|
6946
|
+
const pe = !W.speechQueue || W.speechQueue.length === 0, Se = !W.audioPlaylist || W.audioPlaylist.length === 0;
|
|
6947
|
+
W && W.isSpeaking === !1 && pe && Se && W.isAudioPlaying === !1 && !xe && !f.current && setTimeout(() => {
|
|
6948
|
+
if (W && !f.current && W.isSpeaking === !1 && (!W.speechQueue || W.speechQueue.length === 0) && (!W.audioPlaylist || W.audioPlaylist.length === 0) && W.isAudioPlaying === !1 && !xe && !f.current) {
|
|
6949
|
+
xe = !0, ee && (clearInterval(ee), ee = null, R.current = null);
|
|
6950
6950
|
try {
|
|
6951
|
-
|
|
6951
|
+
A.onSpeechEnd();
|
|
6952
6952
|
} catch (Ze) {
|
|
6953
6953
|
console.error("Error in onSpeechEnd callback:", Ze);
|
|
6954
6954
|
}
|
|
6955
6955
|
}
|
|
6956
6956
|
}, 100);
|
|
6957
|
-
}, 100),
|
|
6957
|
+
}, 100), R.current = ee;
|
|
6958
6958
|
}
|
|
6959
|
-
p.current.lipsync && Object.keys(p.current.lipsync).length > 0 ? (p.current.setSlowdownRate && p.current.setSlowdownRate(1.05), p.current.speakText(
|
|
6960
|
-
await P(), p.current && p.current.lipsync && (p.current.setSlowdownRate && p.current.setSlowdownRate(1.05), p.current.speakText(
|
|
6959
|
+
p.current.lipsync && Object.keys(p.current.lipsync).length > 0 ? (p.current.setSlowdownRate && p.current.setSlowdownRate(1.05), p.current.speakText(w, J)) : setTimeout(async () => {
|
|
6960
|
+
await P(), p.current && p.current.lipsync && (p.current.setSlowdownRate && p.current.setSlowdownRate(1.05), p.current.speakText(w, J));
|
|
6961
6961
|
}, 100);
|
|
6962
|
-
} catch (
|
|
6963
|
-
console.error("Error speaking text:",
|
|
6962
|
+
} catch (T) {
|
|
6963
|
+
console.error("Error speaking text:", T), Y(T.message || "Failed to speak text");
|
|
6964
6964
|
}
|
|
6965
|
-
}, [
|
|
6966
|
-
p.current && (p.current.stopSpeaking(), p.current.setSlowdownRate && p.current.setSlowdownRate(1),
|
|
6967
|
-
}, []),
|
|
6965
|
+
}, [$, P, v.lipsyncLang]), te = N(() => {
|
|
6966
|
+
p.current && (p.current.stopSpeaking(), p.current.setSlowdownRate && p.current.setSlowdownRate(1), M.current = null, oe(!1));
|
|
6967
|
+
}, []), q = N(() => {
|
|
6968
6968
|
if (p.current && p.current.pauseSpeaking) {
|
|
6969
|
-
const
|
|
6970
|
-
if (
|
|
6971
|
-
|
|
6972
|
-
let
|
|
6973
|
-
if (
|
|
6974
|
-
const
|
|
6975
|
-
if (
|
|
6976
|
-
const
|
|
6977
|
-
|
|
6969
|
+
const w = p.current;
|
|
6970
|
+
if (w.isSpeaking || w.audioPlaylist && w.audioPlaylist.length > 0 || w.speechQueue && w.speechQueue.length > 0) {
|
|
6971
|
+
R.current && (clearInterval(R.current), R.current = null);
|
|
6972
|
+
let T = "";
|
|
6973
|
+
if (M.current && S.current.length > 0) {
|
|
6974
|
+
const D = S.current.length, J = w.speechQueue ? w.speechQueue.filter((Ae) => Ae && Ae.text && Array.isArray(Ae.text) && Ae.text.length > 0).length : 0, W = w.audioPlaylist && w.audioPlaylist.length > 0, ee = J + (W ? 1 : 0), Le = D - ee;
|
|
6975
|
+
if (ee > 0 && Le < D && (T = S.current.slice(Le).join(". ").trim(), !T && J > 0 && w.speechQueue)) {
|
|
6976
|
+
const xe = w.speechQueue.filter((pe) => pe && pe.text && Array.isArray(pe.text) && pe.text.length > 0).map((pe) => pe.text.map((Se) => Se.word || "").filter((Se) => Se.length > 0).join(" ")).filter((pe) => pe.length > 0).join(" ");
|
|
6977
|
+
xe && xe.trim() && (T = xe.trim());
|
|
6978
6978
|
}
|
|
6979
6979
|
}
|
|
6980
|
-
|
|
6981
|
-
remainingText:
|
|
6982
|
-
originalText:
|
|
6983
|
-
options:
|
|
6984
|
-
}),
|
|
6980
|
+
M.current && (C.current = {
|
|
6981
|
+
remainingText: T || null,
|
|
6982
|
+
originalText: M.current.text,
|
|
6983
|
+
options: M.current.options
|
|
6984
|
+
}), w.speechQueue && (w.speechQueue.length = 0), p.current.pauseSpeaking(), f.current = !0, oe(!0);
|
|
6985
6985
|
}
|
|
6986
6986
|
}
|
|
6987
|
-
}, []),
|
|
6988
|
-
if (!p.current || !
|
|
6987
|
+
}, []), _ = N(async () => {
|
|
6988
|
+
if (!p.current || !he)
|
|
6989
6989
|
return;
|
|
6990
|
-
let
|
|
6991
|
-
if (
|
|
6992
|
-
|
|
6993
|
-
else if (
|
|
6994
|
-
|
|
6990
|
+
let w = "", A = {};
|
|
6991
|
+
if (C.current && C.current.remainingText)
|
|
6992
|
+
w = C.current.remainingText, A = C.current.options || {}, C.current = { remainingText: null, originalText: null, options: null };
|
|
6993
|
+
else if (M.current && M.current.text)
|
|
6994
|
+
w = M.current.text, A = M.current.options || {};
|
|
6995
6995
|
else {
|
|
6996
|
-
console.warn("Resume called but no paused speech found"),
|
|
6996
|
+
console.warn("Resume called but no paused speech found"), oe(!1), f.current = !1;
|
|
6997
6997
|
return;
|
|
6998
6998
|
}
|
|
6999
|
-
|
|
7000
|
-
const
|
|
7001
|
-
...
|
|
7002
|
-
lipsyncLang:
|
|
6999
|
+
oe(!1), f.current = !1, await P();
|
|
7000
|
+
const T = {
|
|
7001
|
+
...A,
|
|
7002
|
+
lipsyncLang: A.lipsyncLang || v.lipsyncLang || "en"
|
|
7003
7003
|
};
|
|
7004
7004
|
try {
|
|
7005
|
-
await
|
|
7006
|
-
} catch (
|
|
7007
|
-
console.error("Error resuming speech:",
|
|
7005
|
+
await G(w, T);
|
|
7006
|
+
} catch (D) {
|
|
7007
|
+
console.error("Error resuming speech:", D), oe(!1), f.current = !1;
|
|
7008
7008
|
}
|
|
7009
|
-
}, [P,
|
|
7010
|
-
p.current && p.current.setMood(
|
|
7011
|
-
}, []),
|
|
7012
|
-
p.current && p.current.setSlowdownRate && p.current.setSlowdownRate(
|
|
7013
|
-
}, []),
|
|
7009
|
+
}, [P, he, G, v]), fe = N((w) => {
|
|
7010
|
+
p.current && p.current.setMood(w);
|
|
7011
|
+
}, []), ve = N((w) => {
|
|
7012
|
+
p.current && p.current.setSlowdownRate && p.current.setSlowdownRate(w);
|
|
7013
|
+
}, []), Fe = N((w, A = !1) => {
|
|
7014
7014
|
if (p.current && p.current.playAnimation) {
|
|
7015
|
-
if (x && x[
|
|
7015
|
+
if (x && x[w] && (w = x[w]), p.current.setShowFullAvatar)
|
|
7016
7016
|
try {
|
|
7017
|
-
p.current.setShowFullAvatar(
|
|
7018
|
-
} catch (
|
|
7019
|
-
console.warn("Error setting full body mode:",
|
|
7017
|
+
p.current.setShowFullAvatar(B.current);
|
|
7018
|
+
} catch (D) {
|
|
7019
|
+
console.warn("Error setting full body mode:", D);
|
|
7020
7020
|
}
|
|
7021
|
-
if (
|
|
7021
|
+
if (w.includes("."))
|
|
7022
7022
|
try {
|
|
7023
|
-
p.current.playAnimation(
|
|
7024
|
-
} catch (
|
|
7025
|
-
console.warn(`Failed to play ${
|
|
7023
|
+
p.current.playAnimation(w, null, 10, 0, 0.01, A);
|
|
7024
|
+
} catch (D) {
|
|
7025
|
+
console.warn(`Failed to play ${w}:`, D);
|
|
7026
7026
|
try {
|
|
7027
7027
|
p.current.setBodyMovement("idle");
|
|
7028
|
-
} catch (
|
|
7029
|
-
console.warn("Fallback animation also failed:",
|
|
7028
|
+
} catch (J) {
|
|
7029
|
+
console.warn("Fallback animation also failed:", J);
|
|
7030
7030
|
}
|
|
7031
7031
|
}
|
|
7032
7032
|
else {
|
|
7033
|
-
const
|
|
7034
|
-
let
|
|
7035
|
-
for (const
|
|
7033
|
+
const D = [".fbx", ".glb", ".gltf"];
|
|
7034
|
+
let J = !1;
|
|
7035
|
+
for (const W of D)
|
|
7036
7036
|
try {
|
|
7037
|
-
p.current.playAnimation(
|
|
7037
|
+
p.current.playAnimation(w + W, null, 10, 0, 0.01, A), J = !0;
|
|
7038
7038
|
break;
|
|
7039
7039
|
} catch {
|
|
7040
7040
|
}
|
|
7041
|
-
if (!
|
|
7042
|
-
console.warn("Animation not found:",
|
|
7041
|
+
if (!J) {
|
|
7042
|
+
console.warn("Animation not found:", w);
|
|
7043
7043
|
try {
|
|
7044
7044
|
p.current.setBodyMovement("idle");
|
|
7045
|
-
} catch (
|
|
7046
|
-
console.warn("Fallback animation also failed:",
|
|
7045
|
+
} catch (W) {
|
|
7046
|
+
console.warn("Fallback animation also failed:", W);
|
|
7047
7047
|
}
|
|
7048
7048
|
}
|
|
7049
7049
|
}
|
|
7050
7050
|
}
|
|
7051
|
-
}, [x]),
|
|
7051
|
+
}, [x]), Ee = N(() => {
|
|
7052
7052
|
p.current && p.current.onResize && p.current.onResize();
|
|
7053
7053
|
}, []);
|
|
7054
|
-
return
|
|
7055
|
-
speakText:
|
|
7056
|
-
stopSpeaking:
|
|
7057
|
-
pauseSpeaking:
|
|
7058
|
-
resumeSpeaking:
|
|
7054
|
+
return Te(L, () => ({
|
|
7055
|
+
speakText: G,
|
|
7056
|
+
stopSpeaking: te,
|
|
7057
|
+
pauseSpeaking: q,
|
|
7058
|
+
resumeSpeaking: _,
|
|
7059
7059
|
resumeAudioContext: P,
|
|
7060
|
-
setMood:
|
|
7061
|
-
setTimingAdjustment:
|
|
7062
|
-
playAnimation:
|
|
7063
|
-
isReady:
|
|
7064
|
-
isPaused:
|
|
7060
|
+
setMood: fe,
|
|
7061
|
+
setTimingAdjustment: ve,
|
|
7062
|
+
playAnimation: Fe,
|
|
7063
|
+
isReady: $,
|
|
7064
|
+
isPaused: he,
|
|
7065
7065
|
talkingHead: p.current,
|
|
7066
|
-
handleResize:
|
|
7067
|
-
setBodyMovement: (
|
|
7066
|
+
handleResize: Ee,
|
|
7067
|
+
setBodyMovement: (w) => {
|
|
7068
7068
|
if (p.current && p.current.setShowFullAvatar && p.current.setBodyMovement)
|
|
7069
7069
|
try {
|
|
7070
|
-
p.current.setShowFullAvatar(
|
|
7071
|
-
} catch (
|
|
7072
|
-
console.warn("Error setting body movement:",
|
|
7070
|
+
p.current.setShowFullAvatar(B.current), p.current.setBodyMovement(w);
|
|
7071
|
+
} catch (A) {
|
|
7072
|
+
console.warn("Error setting body movement:", A);
|
|
7073
7073
|
}
|
|
7074
7074
|
},
|
|
7075
|
-
setMovementIntensity: (
|
|
7075
|
+
setMovementIntensity: (w) => p.current?.setMovementIntensity(w),
|
|
7076
7076
|
playRandomDance: () => {
|
|
7077
7077
|
if (p.current && p.current.setShowFullAvatar && p.current.playRandomDance)
|
|
7078
7078
|
try {
|
|
7079
|
-
p.current.setShowFullAvatar(
|
|
7080
|
-
} catch (
|
|
7081
|
-
console.warn("Error playing random dance:",
|
|
7079
|
+
p.current.setShowFullAvatar(B.current), p.current.playRandomDance();
|
|
7080
|
+
} catch (w) {
|
|
7081
|
+
console.warn("Error playing random dance:", w);
|
|
7082
7082
|
}
|
|
7083
7083
|
},
|
|
7084
|
-
playReaction: (
|
|
7084
|
+
playReaction: (w) => {
|
|
7085
7085
|
if (p.current && p.current.setShowFullAvatar && p.current.playReaction)
|
|
7086
7086
|
try {
|
|
7087
|
-
p.current.setShowFullAvatar(
|
|
7088
|
-
} catch (
|
|
7089
|
-
console.warn("Error playing reaction:",
|
|
7087
|
+
p.current.setShowFullAvatar(B.current), p.current.playReaction(w);
|
|
7088
|
+
} catch (A) {
|
|
7089
|
+
console.warn("Error playing reaction:", A);
|
|
7090
7090
|
}
|
|
7091
7091
|
},
|
|
7092
7092
|
playCelebration: () => {
|
|
7093
7093
|
if (p.current && p.current.setShowFullAvatar && p.current.playCelebration)
|
|
7094
7094
|
try {
|
|
7095
|
-
p.current.setShowFullAvatar(
|
|
7096
|
-
} catch (
|
|
7097
|
-
console.warn("Error playing celebration:",
|
|
7095
|
+
p.current.setShowFullAvatar(B.current), p.current.playCelebration();
|
|
7096
|
+
} catch (w) {
|
|
7097
|
+
console.warn("Error playing celebration:", w);
|
|
7098
7098
|
}
|
|
7099
7099
|
},
|
|
7100
|
-
setShowFullAvatar: (
|
|
7100
|
+
setShowFullAvatar: (w) => {
|
|
7101
7101
|
if (p.current && p.current.setShowFullAvatar)
|
|
7102
7102
|
try {
|
|
7103
|
-
|
|
7104
|
-
} catch (
|
|
7105
|
-
console.warn("Error setting showFullAvatar:",
|
|
7103
|
+
B.current = w, p.current.setShowFullAvatar(w);
|
|
7104
|
+
} catch (A) {
|
|
7105
|
+
console.warn("Error setting showFullAvatar:", A);
|
|
7106
7106
|
}
|
|
7107
7107
|
},
|
|
7108
7108
|
lockAvatarPosition: () => {
|
|
7109
7109
|
if (p.current && p.current.lockAvatarPosition)
|
|
7110
7110
|
try {
|
|
7111
7111
|
p.current.lockAvatarPosition();
|
|
7112
|
-
} catch (
|
|
7113
|
-
console.warn("Error locking avatar position:",
|
|
7112
|
+
} catch (w) {
|
|
7113
|
+
console.warn("Error locking avatar position:", w);
|
|
7114
7114
|
}
|
|
7115
7115
|
},
|
|
7116
7116
|
unlockAvatarPosition: () => {
|
|
7117
7117
|
if (p.current && p.current.unlockAvatarPosition)
|
|
7118
7118
|
try {
|
|
7119
7119
|
p.current.unlockAvatarPosition();
|
|
7120
|
-
} catch (
|
|
7121
|
-
console.warn("Error unlocking avatar position:",
|
|
7120
|
+
} catch (w) {
|
|
7121
|
+
console.warn("Error unlocking avatar position:", w);
|
|
7122
7122
|
}
|
|
7123
7123
|
}
|
|
7124
7124
|
})), /* @__PURE__ */ Pe(
|
|
@@ -7135,7 +7135,7 @@ const Ve = Me(({
|
|
|
7135
7135
|
/* @__PURE__ */ me(
|
|
7136
7136
|
"div",
|
|
7137
7137
|
{
|
|
7138
|
-
ref:
|
|
7138
|
+
ref: O,
|
|
7139
7139
|
className: "talking-head-viewer",
|
|
7140
7140
|
style: {
|
|
7141
7141
|
width: "100%",
|
|
@@ -7153,7 +7153,7 @@ const Ve = Me(({
|
|
|
7153
7153
|
fontSize: "18px",
|
|
7154
7154
|
zIndex: 10
|
|
7155
7155
|
}, children: "Loading avatar..." }),
|
|
7156
|
-
|
|
7156
|
+
Q && /* @__PURE__ */ me("div", { className: "error-overlay", style: {
|
|
7157
7157
|
position: "absolute",
|
|
7158
7158
|
top: "50%",
|
|
7159
7159
|
left: "50%",
|
|
@@ -7164,13 +7164,13 @@ const Ve = Me(({
|
|
|
7164
7164
|
zIndex: 10,
|
|
7165
7165
|
padding: "20px",
|
|
7166
7166
|
borderRadius: "8px"
|
|
7167
|
-
}, children:
|
|
7167
|
+
}, children: Q })
|
|
7168
7168
|
]
|
|
7169
7169
|
}
|
|
7170
7170
|
);
|
|
7171
7171
|
});
|
|
7172
7172
|
Ve.displayName = "TalkingHeadAvatar";
|
|
7173
|
-
const pt =
|
|
7173
|
+
const pt = He(({
|
|
7174
7174
|
text: X = "Hello! I'm a talking avatar. How are you today?",
|
|
7175
7175
|
onLoading: t = () => {
|
|
7176
7176
|
},
|
|
@@ -7182,7 +7182,7 @@ const pt = Me(({
|
|
|
7182
7182
|
style: s = {},
|
|
7183
7183
|
avatarConfig: o = {}
|
|
7184
7184
|
}, l) => {
|
|
7185
|
-
const h =
|
|
7185
|
+
const h = V(null), r = V(null), [u, a] = ce(!0), [d, c] = ce(null), [g, b] = ce(!1), x = Me(), L = o.ttsService || x.service, O = L === "browser" ? {
|
|
7186
7186
|
endpoint: "",
|
|
7187
7187
|
apiKey: null,
|
|
7188
7188
|
defaultVoice: "Google US English"
|
|
@@ -7191,14 +7191,14 @@ const pt = Me(({
|
|
|
7191
7191
|
// Override API key if provided via avatarConfig
|
|
7192
7192
|
apiKey: o.ttsApiKey !== void 0 && o.ttsApiKey !== null ? o.ttsApiKey : x.apiKey,
|
|
7193
7193
|
// Override endpoint for ElevenLabs if service is explicitly set
|
|
7194
|
-
endpoint:
|
|
7194
|
+
endpoint: L === "elevenlabs" && o.ttsApiKey ? "https://api.elevenlabs.io/v1/text-to-speech" : x.endpoint
|
|
7195
7195
|
}, p = {
|
|
7196
7196
|
url: "/avatars/brunette.glb",
|
|
7197
7197
|
// Use brunette avatar (working glTF file)
|
|
7198
7198
|
body: "F",
|
|
7199
7199
|
avatarMood: "neutral",
|
|
7200
|
-
ttsLang:
|
|
7201
|
-
ttsVoice: o.ttsVoice ||
|
|
7200
|
+
ttsLang: L === "browser" ? "en-US" : "en",
|
|
7201
|
+
ttsVoice: o.ttsVoice || O.defaultVoice,
|
|
7202
7202
|
lipsyncLang: "en",
|
|
7203
7203
|
// English lip-sync
|
|
7204
7204
|
showFullAvatar: !0,
|
|
@@ -7206,36 +7206,36 @@ const pt = Me(({
|
|
|
7206
7206
|
bodyMovement: "idle",
|
|
7207
7207
|
movementIntensity: 0.5,
|
|
7208
7208
|
...o
|
|
7209
|
-
},
|
|
7210
|
-
ttsEndpoint:
|
|
7211
|
-
ttsApikey:
|
|
7212
|
-
ttsService:
|
|
7209
|
+
}, B = {
|
|
7210
|
+
ttsEndpoint: O.endpoint,
|
|
7211
|
+
ttsApikey: O.apiKey,
|
|
7212
|
+
ttsService: L,
|
|
7213
7213
|
lipsyncModules: ["en"],
|
|
7214
7214
|
cameraView: "upper"
|
|
7215
|
-
},
|
|
7215
|
+
}, M = N(async () => {
|
|
7216
7216
|
if (!(!h.current || r.current))
|
|
7217
7217
|
try {
|
|
7218
|
-
if (a(!0), c(null), r.current = new Be(h.current,
|
|
7219
|
-
if (
|
|
7220
|
-
const
|
|
7221
|
-
t(
|
|
7218
|
+
if (a(!0), c(null), r.current = new Be(h.current, B), await r.current.showAvatar(p, (Q) => {
|
|
7219
|
+
if (Q.lengthComputable) {
|
|
7220
|
+
const Y = Math.min(100, Math.round(Q.loaded / Q.total * 100));
|
|
7221
|
+
t(Y);
|
|
7222
7222
|
}
|
|
7223
7223
|
}), r.current.morphs && r.current.morphs.length > 0) {
|
|
7224
|
-
const
|
|
7225
|
-
console.log("Available morph targets:", Object.keys(
|
|
7226
|
-
const
|
|
7227
|
-
console.log("Viseme morph targets found:",
|
|
7224
|
+
const Q = r.current.morphs[0].morphTargetDictionary;
|
|
7225
|
+
console.log("Available morph targets:", Object.keys(Q));
|
|
7226
|
+
const Y = Object.keys(Q).filter(($) => $.startsWith("viseme_"));
|
|
7227
|
+
console.log("Viseme morph targets found:", Y), Y.length === 0 && (console.warn("No viseme morph targets found! Lip-sync will not work properly."), console.log("Expected viseme targets: viseme_aa, viseme_E, viseme_I, viseme_O, viseme_U, viseme_PP, viseme_SS, viseme_TH, viseme_DD, viseme_FF, viseme_kk, viseme_nn, viseme_RR, viseme_CH, viseme_sil"));
|
|
7228
7228
|
}
|
|
7229
|
-
if (await new Promise((
|
|
7230
|
-
const
|
|
7231
|
-
r.current.lipsync && Object.keys(r.current.lipsync).length > 0 ? (console.log("Lip-sync modules loaded:", Object.keys(r.current.lipsync)),
|
|
7229
|
+
if (await new Promise((Q) => {
|
|
7230
|
+
const Y = () => {
|
|
7231
|
+
r.current.lipsync && Object.keys(r.current.lipsync).length > 0 ? (console.log("Lip-sync modules loaded:", Object.keys(r.current.lipsync)), Q()) : (console.log("Waiting for lip-sync modules to load..."), setTimeout(Y, 100));
|
|
7232
7232
|
};
|
|
7233
|
-
|
|
7233
|
+
Y();
|
|
7234
7234
|
}), r.current && r.current.setShowFullAvatar)
|
|
7235
7235
|
try {
|
|
7236
7236
|
r.current.setShowFullAvatar(!0), console.log("Avatar initialized in full body mode");
|
|
7237
|
-
} catch (
|
|
7238
|
-
console.warn("Error setting full body mode on initialization:",
|
|
7237
|
+
} catch (Q) {
|
|
7238
|
+
console.warn("Error setting full body mode on initialization:", Q);
|
|
7239
7239
|
}
|
|
7240
7240
|
a(!1), b(!0), n(r.current);
|
|
7241
7241
|
const E = () => {
|
|
@@ -7248,10 +7248,10 @@ const pt = Me(({
|
|
|
7248
7248
|
console.error("Error initializing TalkingHead:", k), c(k.message || "Failed to initialize avatar"), a(!1), e(k);
|
|
7249
7249
|
}
|
|
7250
7250
|
}, []);
|
|
7251
|
-
de(() => (
|
|
7251
|
+
de(() => (M(), () => {
|
|
7252
7252
|
r.current && (r.current.stop(), r.current.dispose(), r.current = null);
|
|
7253
|
-
}), [
|
|
7254
|
-
const
|
|
7253
|
+
}), [M]);
|
|
7254
|
+
const R = N((k) => {
|
|
7255
7255
|
if (r.current && g)
|
|
7256
7256
|
try {
|
|
7257
7257
|
console.log("Speaking text:", k), 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(k)) : (console.warn("Lip-sync modules not ready, waiting..."), setTimeout(() => {
|
|
@@ -7262,59 +7262,59 @@ const pt = Me(({
|
|
|
7262
7262
|
}
|
|
7263
7263
|
else
|
|
7264
7264
|
console.warn("Avatar not ready for speaking. isReady:", g, "talkingHeadRef:", !!r.current);
|
|
7265
|
-
}, [g, p]),
|
|
7265
|
+
}, [g, p]), f = N(() => {
|
|
7266
7266
|
r.current && (r.current.stopSpeaking(), r.current.setSlowdownRate && (r.current.setSlowdownRate(1), console.log("Reset timing to normal")));
|
|
7267
|
-
}, []),
|
|
7267
|
+
}, []), C = N((k) => {
|
|
7268
7268
|
r.current && r.current.setMood(k);
|
|
7269
|
-
}, []),
|
|
7269
|
+
}, []), S = N((k) => {
|
|
7270
7270
|
r.current && r.current.setSlowdownRate && (r.current.setSlowdownRate(k), console.log("Timing adjustment set to:", k));
|
|
7271
|
-
}, []),
|
|
7271
|
+
}, []), U = N((k, E = !1) => {
|
|
7272
7272
|
if (r.current && r.current.playAnimation) {
|
|
7273
7273
|
if (r.current.setShowFullAvatar)
|
|
7274
7274
|
try {
|
|
7275
7275
|
r.current.setShowFullAvatar(!0);
|
|
7276
|
-
} catch (
|
|
7277
|
-
console.warn("Error setting full body mode:",
|
|
7276
|
+
} catch (Y) {
|
|
7277
|
+
console.warn("Error setting full body mode:", Y);
|
|
7278
7278
|
}
|
|
7279
7279
|
if (k.includes("."))
|
|
7280
7280
|
try {
|
|
7281
7281
|
r.current.playAnimation(k, null, 10, 0, 0.01, E), console.log("Playing animation:", k);
|
|
7282
|
-
} catch (
|
|
7283
|
-
console.log(`Failed to play ${k}:`,
|
|
7282
|
+
} catch (Y) {
|
|
7283
|
+
console.log(`Failed to play ${k}:`, Y);
|
|
7284
7284
|
try {
|
|
7285
7285
|
r.current.setBodyMovement("idle"), console.log("Fallback to idle animation");
|
|
7286
|
-
} catch (
|
|
7287
|
-
console.warn("Fallback animation also failed:",
|
|
7286
|
+
} catch ($) {
|
|
7287
|
+
console.warn("Fallback animation also failed:", $);
|
|
7288
7288
|
}
|
|
7289
7289
|
}
|
|
7290
7290
|
else {
|
|
7291
|
-
const
|
|
7292
|
-
let
|
|
7293
|
-
for (const
|
|
7291
|
+
const Y = [".fbx", ".glb", ".gltf"];
|
|
7292
|
+
let $ = !1;
|
|
7293
|
+
for (const re of Y)
|
|
7294
7294
|
try {
|
|
7295
|
-
r.current.playAnimation(k +
|
|
7295
|
+
r.current.playAnimation(k + re, null, 10, 0, 0.01, E), console.log("Playing animation:", k + re), $ = !0;
|
|
7296
7296
|
break;
|
|
7297
7297
|
} catch {
|
|
7298
|
-
console.log(`Failed to play ${k}${
|
|
7298
|
+
console.log(`Failed to play ${k}${re}, trying next format...`);
|
|
7299
7299
|
}
|
|
7300
|
-
if (
|
|
7300
|
+
if (!$) {
|
|
7301
7301
|
console.warn("Animation system not available or animation not found:", k);
|
|
7302
7302
|
try {
|
|
7303
7303
|
r.current.setBodyMovement("idle"), console.log("Fallback to idle animation");
|
|
7304
|
-
} catch (
|
|
7305
|
-
console.warn("Fallback animation also failed:",
|
|
7304
|
+
} catch (re) {
|
|
7305
|
+
console.warn("Fallback animation also failed:", re);
|
|
7306
7306
|
}
|
|
7307
7307
|
}
|
|
7308
7308
|
}
|
|
7309
7309
|
} else
|
|
7310
7310
|
console.warn("Animation system not available or animation not found:", k);
|
|
7311
7311
|
}, []);
|
|
7312
|
-
return
|
|
7313
|
-
speakText:
|
|
7314
|
-
stopSpeaking:
|
|
7315
|
-
setMood:
|
|
7316
|
-
setTimingAdjustment:
|
|
7317
|
-
playAnimation:
|
|
7312
|
+
return Te(l, () => ({
|
|
7313
|
+
speakText: R,
|
|
7314
|
+
stopSpeaking: f,
|
|
7315
|
+
setMood: C,
|
|
7316
|
+
setTimingAdjustment: S,
|
|
7317
|
+
playAnimation: U,
|
|
7318
7318
|
isReady: g,
|
|
7319
7319
|
talkingHead: r.current,
|
|
7320
7320
|
setBodyMovement: (k) => {
|
|
@@ -7411,7 +7411,7 @@ const pt = Me(({
|
|
|
7411
7411
|
] });
|
|
7412
7412
|
});
|
|
7413
7413
|
pt.displayName = "TalkingHeadComponent";
|
|
7414
|
-
const gt =
|
|
7414
|
+
const gt = He(({
|
|
7415
7415
|
text: X = null,
|
|
7416
7416
|
avatarUrl: t = "/avatars/brunette.glb",
|
|
7417
7417
|
avatarBody: e = "F",
|
|
@@ -7433,170 +7433,194 @@ const gt = Me(({
|
|
|
7433
7433
|
onSpeechEnd: b = () => {
|
|
7434
7434
|
},
|
|
7435
7435
|
className: x = "",
|
|
7436
|
-
style:
|
|
7437
|
-
animations:
|
|
7438
|
-
|
|
7439
|
-
|
|
7440
|
-
|
|
7436
|
+
style: L = {},
|
|
7437
|
+
animations: O = {},
|
|
7438
|
+
autoAnimationGroup: p = null,
|
|
7439
|
+
// e.g., "talking" - will randomly select from this group when speaking
|
|
7440
|
+
autoSpeak: B = !1
|
|
7441
|
+
}, M) => {
|
|
7442
|
+
const R = V(null), f = V(null), C = V(u), S = V(null), U = V(null), k = V(!1), E = V({ remainingText: null, originalText: null, options: null }), Q = V([]), [Y, $] = ce(!0), [re, he] = ce(null), [oe, se] = ce(!1), [le, j] = ce(!1);
|
|
7441
7443
|
de(() => {
|
|
7442
|
-
|
|
7443
|
-
}, [
|
|
7444
|
-
|
|
7444
|
+
k.current = le;
|
|
7445
|
+
}, [le]), de(() => {
|
|
7446
|
+
C.current = u;
|
|
7445
7447
|
}, [u]);
|
|
7446
|
-
const
|
|
7447
|
-
let
|
|
7448
|
-
|
|
7448
|
+
const v = Me(), I = s || v.service;
|
|
7449
|
+
let H;
|
|
7450
|
+
I === "browser" ? H = {
|
|
7449
7451
|
service: "browser",
|
|
7450
7452
|
endpoint: "",
|
|
7451
7453
|
apiKey: null,
|
|
7452
7454
|
defaultVoice: "Google US English"
|
|
7453
|
-
} :
|
|
7455
|
+
} : I === "elevenlabs" ? H = {
|
|
7454
7456
|
service: "elevenlabs",
|
|
7455
7457
|
endpoint: "https://api.elevenlabs.io/v1/text-to-speech",
|
|
7456
|
-
apiKey: l ||
|
|
7457
|
-
defaultVoice: o ||
|
|
7458
|
-
voices:
|
|
7459
|
-
} :
|
|
7458
|
+
apiKey: l || v.apiKey,
|
|
7459
|
+
defaultVoice: o || v.defaultVoice || Ie.defaultVoice,
|
|
7460
|
+
voices: v.voices || Ie.voices
|
|
7461
|
+
} : I === "deepgram" ? H = {
|
|
7460
7462
|
service: "deepgram",
|
|
7461
7463
|
endpoint: "https://api.deepgram.com/v1/speak",
|
|
7462
|
-
apiKey: l ||
|
|
7463
|
-
defaultVoice: o ||
|
|
7464
|
-
voices:
|
|
7465
|
-
} :
|
|
7466
|
-
...
|
|
7467
|
-
apiKey: l !== null ? l :
|
|
7464
|
+
apiKey: l || v.apiKey,
|
|
7465
|
+
defaultVoice: o || v.defaultVoice || Ce.defaultVoice,
|
|
7466
|
+
voices: v.voices || Ce.voices
|
|
7467
|
+
} : H = {
|
|
7468
|
+
...v,
|
|
7469
|
+
apiKey: l !== null ? l : v.apiKey
|
|
7468
7470
|
};
|
|
7469
|
-
const
|
|
7471
|
+
const P = {
|
|
7470
7472
|
url: t,
|
|
7471
7473
|
body: e,
|
|
7472
7474
|
avatarMood: n,
|
|
7473
|
-
ttsLang:
|
|
7474
|
-
ttsVoice: o ||
|
|
7475
|
+
ttsLang: I === "browser" ? "en-US" : i,
|
|
7476
|
+
ttsVoice: o || H.defaultVoice,
|
|
7475
7477
|
lipsyncLang: "en",
|
|
7476
7478
|
showFullAvatar: u,
|
|
7477
7479
|
bodyMovement: h,
|
|
7478
7480
|
movementIntensity: r
|
|
7479
|
-
},
|
|
7480
|
-
ttsEndpoint:
|
|
7481
|
-
ttsApikey:
|
|
7482
|
-
ttsService:
|
|
7481
|
+
}, G = {
|
|
7482
|
+
ttsEndpoint: H.endpoint,
|
|
7483
|
+
ttsApikey: H.apiKey,
|
|
7484
|
+
ttsService: I,
|
|
7483
7485
|
lipsyncModules: ["en"],
|
|
7484
7486
|
cameraView: a
|
|
7485
|
-
},
|
|
7486
|
-
if (!(!
|
|
7487
|
+
}, te = N(async () => {
|
|
7488
|
+
if (!(!R.current || f.current))
|
|
7487
7489
|
try {
|
|
7488
|
-
|
|
7489
|
-
url:
|
|
7490
|
-
body:
|
|
7491
|
-
avatarMood:
|
|
7492
|
-
}), await
|
|
7493
|
-
if (
|
|
7494
|
-
const
|
|
7495
|
-
c(
|
|
7490
|
+
$(!0), he(null), f.current = new Be(R.current, G), console.log("Avatar config being passed:", {
|
|
7491
|
+
url: P.url,
|
|
7492
|
+
body: P.body,
|
|
7493
|
+
avatarMood: P.avatarMood
|
|
7494
|
+
}), await f.current.showAvatar(P, (T) => {
|
|
7495
|
+
if (T.lengthComputable) {
|
|
7496
|
+
const D = Math.min(100, Math.round(T.loaded / T.total * 100));
|
|
7497
|
+
c(D);
|
|
7496
7498
|
}
|
|
7497
|
-
}),
|
|
7498
|
-
const
|
|
7499
|
-
document.visibilityState === "visible" ?
|
|
7499
|
+
}), f.current?.avatar && console.log("Avatar body after initialization:", f.current.avatar.body), $(!1), se(!0), d(f.current);
|
|
7500
|
+
const A = () => {
|
|
7501
|
+
document.visibilityState === "visible" ? f.current?.start() : f.current?.stop();
|
|
7500
7502
|
};
|
|
7501
|
-
return document.addEventListener("visibilitychange",
|
|
7502
|
-
document.removeEventListener("visibilitychange",
|
|
7503
|
+
return document.addEventListener("visibilitychange", A), () => {
|
|
7504
|
+
document.removeEventListener("visibilitychange", A);
|
|
7503
7505
|
};
|
|
7504
|
-
} catch (
|
|
7505
|
-
console.error("Error initializing TalkingHead:",
|
|
7506
|
+
} catch (A) {
|
|
7507
|
+
console.error("Error initializing TalkingHead:", A), he(A.message || "Failed to initialize avatar"), $(!1), g(A);
|
|
7506
7508
|
}
|
|
7507
7509
|
}, []);
|
|
7508
|
-
de(() => (
|
|
7509
|
-
|
|
7510
|
-
}), [
|
|
7511
|
-
const
|
|
7512
|
-
if (
|
|
7510
|
+
de(() => (te(), () => {
|
|
7511
|
+
f.current && (f.current.stop(), f.current.dispose(), f.current = null);
|
|
7512
|
+
}), [te]);
|
|
7513
|
+
const q = N(async () => {
|
|
7514
|
+
if (f.current)
|
|
7513
7515
|
try {
|
|
7514
|
-
const
|
|
7515
|
-
|
|
7516
|
-
} catch (
|
|
7517
|
-
console.warn("Failed to resume audio context:",
|
|
7516
|
+
const A = f.current.audioCtx || f.current.audioContext;
|
|
7517
|
+
A && (A.state === "suspended" || A.state === "interrupted") && (await A.resume(), console.log("Audio context resumed"));
|
|
7518
|
+
} catch (A) {
|
|
7519
|
+
console.warn("Failed to resume audio context:", A);
|
|
7518
7520
|
}
|
|
7519
|
-
}, []),
|
|
7520
|
-
if (!
|
|
7521
|
+
}, []), _ = N((A) => {
|
|
7522
|
+
if (!O || !O[A])
|
|
7523
|
+
return null;
|
|
7524
|
+
const T = O[A];
|
|
7525
|
+
if (Array.isArray(T) && T.length > 0) {
|
|
7526
|
+
const D = Math.floor(Math.random() * T.length);
|
|
7527
|
+
return T[D];
|
|
7528
|
+
}
|
|
7529
|
+
return typeof T == "string" ? T : null;
|
|
7530
|
+
}, [O]), fe = N((A, T = !1) => {
|
|
7531
|
+
const D = _(A);
|
|
7532
|
+
if (D && f.current)
|
|
7533
|
+
try {
|
|
7534
|
+
return f.current.playAnimation(D, null, 10, 0, 0.01, T), console.log(`Playing random animation from "${A}" group:`, D), D;
|
|
7535
|
+
} catch (J) {
|
|
7536
|
+
return console.warn(`Failed to play random animation from "${A}" group:`, J), null;
|
|
7537
|
+
}
|
|
7538
|
+
return null;
|
|
7539
|
+
}, [_]), ve = N(async (A, T = {}) => {
|
|
7540
|
+
if (!f.current || !oe) {
|
|
7521
7541
|
console.warn("Avatar not ready for speaking");
|
|
7522
7542
|
return;
|
|
7523
7543
|
}
|
|
7524
|
-
if (!
|
|
7544
|
+
if (!A || A.trim() === "") {
|
|
7525
7545
|
console.warn("No text provided to speak");
|
|
7526
7546
|
return;
|
|
7527
7547
|
}
|
|
7528
|
-
await
|
|
7529
|
-
const
|
|
7530
|
-
E.current =
|
|
7531
|
-
const
|
|
7532
|
-
|
|
7548
|
+
await q();
|
|
7549
|
+
const D = T.animationGroup || p;
|
|
7550
|
+
D && !T.skipAnimation && fe(D), E.current = { remainingText: null, originalText: null, options: null }, Q.current = [], S.current = { text: A, options: T }, U.current && (clearInterval(U.current), U.current = null), j(!1), k.current = !1;
|
|
7551
|
+
const J = A.split(/[.!?]+/).filter((ee) => ee.trim().length > 0);
|
|
7552
|
+
Q.current = J;
|
|
7553
|
+
const W = {
|
|
7554
|
+
lipsyncLang: T.lipsyncLang || "en",
|
|
7533
7555
|
onSpeechEnd: () => {
|
|
7534
|
-
|
|
7556
|
+
U.current && (clearInterval(U.current), U.current = null), T.onSpeechEnd && T.onSpeechEnd(), b();
|
|
7535
7557
|
}
|
|
7536
7558
|
};
|
|
7537
7559
|
try {
|
|
7538
|
-
|
|
7539
|
-
} catch (
|
|
7540
|
-
console.error("Error speaking text:",
|
|
7560
|
+
f.current.speakText(A, W);
|
|
7561
|
+
} catch (ee) {
|
|
7562
|
+
console.error("Error speaking text:", ee), he(ee.message || "Failed to speak text");
|
|
7541
7563
|
}
|
|
7542
|
-
}, [
|
|
7564
|
+
}, [oe, b, q, p, fe]);
|
|
7543
7565
|
de(() => {
|
|
7544
|
-
|
|
7545
|
-
}, [
|
|
7546
|
-
const
|
|
7547
|
-
if (
|
|
7566
|
+
oe && X && B && f.current && ve(X);
|
|
7567
|
+
}, [oe, X, B, ve]);
|
|
7568
|
+
const Fe = N(() => {
|
|
7569
|
+
if (f.current)
|
|
7548
7570
|
try {
|
|
7549
|
-
const
|
|
7550
|
-
if (
|
|
7551
|
-
|
|
7552
|
-
let
|
|
7553
|
-
|
|
7554
|
-
remainingText:
|
|
7555
|
-
originalText:
|
|
7556
|
-
options:
|
|
7557
|
-
},
|
|
7571
|
+
const A = f.current.isSpeaking || !1, T = f.current.audioPlaylist || [], D = f.current.speechQueue || [];
|
|
7572
|
+
if (A || T.length > 0 || D.length > 0) {
|
|
7573
|
+
U.current && (clearInterval(U.current), U.current = null);
|
|
7574
|
+
let J = "";
|
|
7575
|
+
D.length > 0 && (J = D.map((W) => W.text && Array.isArray(W.text) ? W.text.map((ee) => ee.word).join(" ") : W.text || "").join(" ")), E.current = {
|
|
7576
|
+
remainingText: J || null,
|
|
7577
|
+
originalText: S.current?.text || null,
|
|
7578
|
+
options: S.current?.options || null
|
|
7579
|
+
}, f.current.speechQueue.length = 0, f.current.pauseSpeaking(), j(!0), k.current = !0;
|
|
7558
7580
|
}
|
|
7559
|
-
} catch (
|
|
7560
|
-
console.warn("Error pausing speech:",
|
|
7581
|
+
} catch (A) {
|
|
7582
|
+
console.warn("Error pausing speech:", A);
|
|
7561
7583
|
}
|
|
7562
|
-
}, []),
|
|
7563
|
-
if (!(!
|
|
7584
|
+
}, []), Ee = N(async () => {
|
|
7585
|
+
if (!(!f.current || !le))
|
|
7564
7586
|
try {
|
|
7565
|
-
await
|
|
7566
|
-
const
|
|
7567
|
-
|
|
7568
|
-
} catch (
|
|
7569
|
-
console.warn("Error resuming speech:",
|
|
7587
|
+
await q(), j(!1), k.current = !1;
|
|
7588
|
+
const A = E.current?.remainingText, T = E.current?.originalText || S.current?.text, D = E.current?.options || S.current?.options || {}, J = A || T;
|
|
7589
|
+
J && ve(J, D);
|
|
7590
|
+
} catch (A) {
|
|
7591
|
+
console.warn("Error resuming speech:", A), j(!1), k.current = !1;
|
|
7570
7592
|
}
|
|
7571
|
-
}, [
|
|
7572
|
-
|
|
7593
|
+
}, [le, ve, q]), w = N(() => {
|
|
7594
|
+
f.current && (f.current.stopSpeaking(), U.current && (clearInterval(U.current), U.current = null), j(!1), k.current = !1);
|
|
7573
7595
|
}, []);
|
|
7574
|
-
return
|
|
7575
|
-
speakText:
|
|
7576
|
-
pauseSpeaking:
|
|
7577
|
-
resumeSpeaking:
|
|
7578
|
-
stopSpeaking:
|
|
7579
|
-
resumeAudioContext:
|
|
7580
|
-
isPaused: () =>
|
|
7581
|
-
setMood: (
|
|
7582
|
-
setBodyMovement: (
|
|
7583
|
-
|
|
7596
|
+
return Te(M, () => ({
|
|
7597
|
+
speakText: ve,
|
|
7598
|
+
pauseSpeaking: Fe,
|
|
7599
|
+
resumeSpeaking: Ee,
|
|
7600
|
+
stopSpeaking: w,
|
|
7601
|
+
resumeAudioContext: q,
|
|
7602
|
+
isPaused: () => le,
|
|
7603
|
+
setMood: (A) => f.current?.setMood(A),
|
|
7604
|
+
setBodyMovement: (A) => {
|
|
7605
|
+
f.current && f.current.setBodyMovement(A);
|
|
7584
7606
|
},
|
|
7585
|
-
playAnimation: (
|
|
7586
|
-
|
|
7607
|
+
playAnimation: (A, T = !1) => {
|
|
7608
|
+
f.current && f.current.playAnimation && f.current.playAnimation(A, null, 10, 0, 0.01, T);
|
|
7587
7609
|
},
|
|
7588
|
-
|
|
7589
|
-
|
|
7590
|
-
|
|
7591
|
-
|
|
7610
|
+
playRandomAnimation: (A, T = !1) => fe(A, T),
|
|
7611
|
+
getRandomAnimation: (A) => _(A),
|
|
7612
|
+
playReaction: (A) => f.current?.playReaction(A),
|
|
7613
|
+
playCelebration: () => f.current?.playCelebration(),
|
|
7614
|
+
setShowFullAvatar: (A) => {
|
|
7615
|
+
f.current && (C.current = A, f.current.setShowFullAvatar(A));
|
|
7592
7616
|
},
|
|
7593
|
-
isReady:
|
|
7594
|
-
talkingHead:
|
|
7595
|
-
})), /* @__PURE__ */ Pe("div", { className: `simple-talking-avatar-container ${x}`, style:
|
|
7617
|
+
isReady: oe,
|
|
7618
|
+
talkingHead: f.current
|
|
7619
|
+
})), /* @__PURE__ */ Pe("div", { className: `simple-talking-avatar-container ${x}`, style: L, children: [
|
|
7596
7620
|
/* @__PURE__ */ me(
|
|
7597
7621
|
"div",
|
|
7598
7622
|
{
|
|
7599
|
-
ref:
|
|
7623
|
+
ref: R,
|
|
7600
7624
|
className: "talking-head-viewer",
|
|
7601
7625
|
style: {
|
|
7602
7626
|
width: "100%",
|
|
@@ -7605,7 +7629,7 @@ const gt = Me(({
|
|
|
7605
7629
|
}
|
|
7606
7630
|
}
|
|
7607
7631
|
),
|
|
7608
|
-
|
|
7632
|
+
Y && /* @__PURE__ */ me("div", { className: "loading-overlay", style: {
|
|
7609
7633
|
position: "absolute",
|
|
7610
7634
|
top: "50%",
|
|
7611
7635
|
left: "50%",
|
|
@@ -7614,7 +7638,7 @@ const gt = Me(({
|
|
|
7614
7638
|
fontSize: "18px",
|
|
7615
7639
|
zIndex: 10
|
|
7616
7640
|
}, children: "Loading avatar..." }),
|
|
7617
|
-
|
|
7641
|
+
re && /* @__PURE__ */ me("div", { className: "error-overlay", style: {
|
|
7618
7642
|
position: "absolute",
|
|
7619
7643
|
top: "50%",
|
|
7620
7644
|
left: "50%",
|
|
@@ -7625,11 +7649,11 @@ const gt = Me(({
|
|
|
7625
7649
|
zIndex: 10,
|
|
7626
7650
|
padding: "20px",
|
|
7627
7651
|
borderRadius: "8px"
|
|
7628
|
-
}, children:
|
|
7652
|
+
}, children: re })
|
|
7629
7653
|
] });
|
|
7630
7654
|
});
|
|
7631
7655
|
gt.displayName = "SimpleTalkingAvatar";
|
|
7632
|
-
const yt =
|
|
7656
|
+
const yt = He(({
|
|
7633
7657
|
curriculumData: X = null,
|
|
7634
7658
|
avatarConfig: t = {},
|
|
7635
7659
|
animations: e = {},
|
|
@@ -7645,7 +7669,7 @@ const yt = Me(({
|
|
|
7645
7669
|
},
|
|
7646
7670
|
autoStart: h = !1
|
|
7647
7671
|
}, r) => {
|
|
7648
|
-
const u =
|
|
7672
|
+
const u = V(null), a = V({
|
|
7649
7673
|
currentModuleIndex: 0,
|
|
7650
7674
|
currentLessonIndex: 0,
|
|
7651
7675
|
currentQuestionIndex: 0,
|
|
@@ -7655,18 +7679,18 @@ const yt = Me(({
|
|
|
7655
7679
|
curriculumCompleted: !1,
|
|
7656
7680
|
score: 0,
|
|
7657
7681
|
totalQuestions: 0
|
|
7658
|
-
}), d =
|
|
7682
|
+
}), d = V({
|
|
7659
7683
|
onLessonStart: n,
|
|
7660
7684
|
onLessonComplete: i,
|
|
7661
7685
|
onQuestionAnswer: s,
|
|
7662
7686
|
onCurriculumComplete: o,
|
|
7663
7687
|
onCustomAction: l
|
|
7664
|
-
}), c =
|
|
7688
|
+
}), c = V(null), g = V(null), b = V(null), x = V(null), L = V(null), O = V(null), p = V(null), B = V(X?.curriculum || {
|
|
7665
7689
|
title: "Default Curriculum",
|
|
7666
7690
|
description: "No curriculum data provided",
|
|
7667
7691
|
language: "en",
|
|
7668
7692
|
modules: []
|
|
7669
|
-
}),
|
|
7693
|
+
}), M = V({
|
|
7670
7694
|
avatarUrl: t.avatarUrl || "/avatars/brunette.glb",
|
|
7671
7695
|
avatarBody: t.avatarBody || "F",
|
|
7672
7696
|
mood: t.mood || "happy",
|
|
@@ -7689,12 +7713,12 @@ const yt = Me(({
|
|
|
7689
7713
|
onCustomAction: l
|
|
7690
7714
|
};
|
|
7691
7715
|
}, [n, i, s, o, l]), de(() => {
|
|
7692
|
-
|
|
7716
|
+
B.current = X?.curriculum || {
|
|
7693
7717
|
title: "Default Curriculum",
|
|
7694
7718
|
description: "No curriculum data provided",
|
|
7695
7719
|
language: "en",
|
|
7696
7720
|
modules: []
|
|
7697
|
-
},
|
|
7721
|
+
}, M.current = {
|
|
7698
7722
|
avatarUrl: t.avatarUrl || "/avatars/brunette.glb",
|
|
7699
7723
|
avatarBody: t.avatarBody || "F",
|
|
7700
7724
|
mood: t.mood || "happy",
|
|
@@ -7709,11 +7733,11 @@ const yt = Me(({
|
|
|
7709
7733
|
lipsyncLang: "en"
|
|
7710
7734
|
};
|
|
7711
7735
|
}, [X, t, e]);
|
|
7712
|
-
const
|
|
7736
|
+
const R = N(() => (B.current || { modules: [] }).modules[a.current.currentModuleIndex]?.lessons[a.current.currentLessonIndex], []), f = N(() => R()?.questions[a.current.currentQuestionIndex], [R]), C = N((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, []), S = N(() => {
|
|
7713
7737
|
a.current.lessonCompleted = !0, a.current.isQuestionMode = !1;
|
|
7714
7738
|
const v = a.current.totalQuestions > 0 ? Math.round(a.current.score / a.current.totalQuestions * 100) : 100;
|
|
7715
|
-
let
|
|
7716
|
-
if (a.current.totalQuestions > 0 ?
|
|
7739
|
+
let I = "Congratulations! You've completed this lesson";
|
|
7740
|
+
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.", d.current.onLessonComplete({
|
|
7717
7741
|
moduleIndex: a.current.currentModuleIndex,
|
|
7718
7742
|
lessonIndex: a.current.currentLessonIndex,
|
|
7719
7743
|
score: a.current.score,
|
|
@@ -7733,9 +7757,9 @@ const yt = Me(({
|
|
|
7733
7757
|
} catch {
|
|
7734
7758
|
u.current.playCelebration();
|
|
7735
7759
|
}
|
|
7736
|
-
const H =
|
|
7737
|
-
u.current.speakText(
|
|
7738
|
-
lipsyncLang:
|
|
7760
|
+
const H = B.current || { modules: [] }, P = H.modules[a.current.currentModuleIndex], G = a.current.currentLessonIndex < (P?.lessons?.length || 0) - 1, te = a.current.currentModuleIndex < (H.modules?.length || 0) - 1, q = G || te, _ = M.current || { lipsyncLang: "en" };
|
|
7761
|
+
u.current.speakText(I, {
|
|
7762
|
+
lipsyncLang: _.lipsyncLang,
|
|
7739
7763
|
onSpeechEnd: () => {
|
|
7740
7764
|
d.current.onCustomAction({
|
|
7741
7765
|
type: "lessonCompleteFeedbackDone",
|
|
@@ -7744,17 +7768,17 @@ const yt = Me(({
|
|
|
7744
7768
|
score: a.current.score,
|
|
7745
7769
|
totalQuestions: a.current.totalQuestions,
|
|
7746
7770
|
percentage: v,
|
|
7747
|
-
hasNextLesson:
|
|
7771
|
+
hasNextLesson: q
|
|
7748
7772
|
});
|
|
7749
7773
|
}
|
|
7750
7774
|
});
|
|
7751
7775
|
}
|
|
7752
|
-
}, [e.lessonComplete]),
|
|
7776
|
+
}, [e.lessonComplete]), U = N(() => {
|
|
7753
7777
|
a.current.curriculumCompleted = !0;
|
|
7754
|
-
const v =
|
|
7778
|
+
const v = B.current || { modules: [] };
|
|
7755
7779
|
if (d.current.onCurriculumComplete({
|
|
7756
7780
|
modules: v.modules.length,
|
|
7757
|
-
totalLessons: v.modules.reduce((
|
|
7781
|
+
totalLessons: v.modules.reduce((I, H) => I + H.lessons.length, 0)
|
|
7758
7782
|
}), u.current) {
|
|
7759
7783
|
if (u.current.setMood("celebrating"), e.curriculumComplete)
|
|
7760
7784
|
try {
|
|
@@ -7762,94 +7786,94 @@ const yt = Me(({
|
|
|
7762
7786
|
} catch {
|
|
7763
7787
|
u.current.playCelebration();
|
|
7764
7788
|
}
|
|
7765
|
-
const
|
|
7766
|
-
u.current.speakText("Amazing! You've completed the entire curriculum! You're now ready to move on to more advanced topics. Well done!", { lipsyncLang:
|
|
7789
|
+
const I = M.current || { lipsyncLang: "en" };
|
|
7790
|
+
u.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 });
|
|
7767
7791
|
}
|
|
7768
|
-
}, [e.curriculumComplete]), k =
|
|
7769
|
-
const v =
|
|
7792
|
+
}, [e.curriculumComplete]), k = N(() => {
|
|
7793
|
+
const v = R();
|
|
7770
7794
|
a.current.isQuestionMode = !0, a.current.currentQuestionIndex = 0, a.current.totalQuestions = v?.questions?.length || 0, a.current.score = 0;
|
|
7771
|
-
const
|
|
7772
|
-
|
|
7795
|
+
const I = f();
|
|
7796
|
+
I && d.current.onCustomAction({
|
|
7773
7797
|
type: "questionStart",
|
|
7774
7798
|
moduleIndex: a.current.currentModuleIndex,
|
|
7775
7799
|
lessonIndex: a.current.currentLessonIndex,
|
|
7776
7800
|
questionIndex: a.current.currentQuestionIndex,
|
|
7777
7801
|
totalQuestions: a.current.totalQuestions,
|
|
7778
|
-
question:
|
|
7802
|
+
question: I,
|
|
7779
7803
|
score: a.current.score
|
|
7780
7804
|
});
|
|
7781
7805
|
const H = () => {
|
|
7782
|
-
if (!u.current || !
|
|
7806
|
+
if (!u.current || !I) return;
|
|
7783
7807
|
if (u.current.setMood("happy"), e.questionStart)
|
|
7784
7808
|
try {
|
|
7785
7809
|
u.current.playAnimation(e.questionStart, !0);
|
|
7786
|
-
} catch (
|
|
7787
|
-
console.warn("Failed to play questionStart animation:",
|
|
7810
|
+
} catch (G) {
|
|
7811
|
+
console.warn("Failed to play questionStart animation:", G);
|
|
7788
7812
|
}
|
|
7789
|
-
const P =
|
|
7790
|
-
|
|
7813
|
+
const P = M.current || { lipsyncLang: "en" };
|
|
7814
|
+
I.type === "code_test" ? u.current.speakText(`Let's test your coding skills! Here's your first challenge: ${I.question}`, { lipsyncLang: P.lipsyncLang }) : I.type === "multiple_choice" ? u.current.speakText(`Now let me ask you some questions. Here's the first one: ${I.question}`, { lipsyncLang: P.lipsyncLang }) : I.type === "true_false" ? u.current.speakText(`Let's start with some true or false questions. First question: ${I.question}`, { lipsyncLang: P.lipsyncLang }) : u.current.speakText(`Now let me ask you some questions. Here's the first one: ${I.question}`, { lipsyncLang: P.lipsyncLang });
|
|
7791
7815
|
};
|
|
7792
|
-
if (u.current && u.current.isReady &&
|
|
7816
|
+
if (u.current && u.current.isReady && I)
|
|
7793
7817
|
H();
|
|
7794
7818
|
else if (u.current && u.current.isReady) {
|
|
7795
|
-
const P =
|
|
7819
|
+
const P = M.current || { lipsyncLang: "en" };
|
|
7796
7820
|
u.current.speakText("Now let me ask you some questions to test your understanding.", { lipsyncLang: P.lipsyncLang });
|
|
7797
7821
|
} else {
|
|
7798
7822
|
const P = setInterval(() => {
|
|
7799
|
-
u.current && u.current.isReady && (clearInterval(P),
|
|
7823
|
+
u.current && u.current.isReady && (clearInterval(P), I && H());
|
|
7800
7824
|
}, 100);
|
|
7801
7825
|
setTimeout(() => {
|
|
7802
7826
|
clearInterval(P);
|
|
7803
7827
|
}, 5e3);
|
|
7804
7828
|
}
|
|
7805
|
-
}, [e.questionStart,
|
|
7806
|
-
const v =
|
|
7829
|
+
}, [e.questionStart, R, f]), E = N(() => {
|
|
7830
|
+
const v = R();
|
|
7807
7831
|
if (a.current.currentQuestionIndex < (v?.questions?.length || 0) - 1) {
|
|
7808
7832
|
u.current && u.current.stopSpeaking && u.current.stopSpeaking(), a.current.currentQuestionIndex += 1;
|
|
7809
|
-
const
|
|
7810
|
-
|
|
7833
|
+
const I = f();
|
|
7834
|
+
I && d.current.onCustomAction({
|
|
7811
7835
|
type: "nextQuestion",
|
|
7812
7836
|
moduleIndex: a.current.currentModuleIndex,
|
|
7813
7837
|
lessonIndex: a.current.currentLessonIndex,
|
|
7814
7838
|
questionIndex: a.current.currentQuestionIndex,
|
|
7815
7839
|
totalQuestions: a.current.totalQuestions,
|
|
7816
|
-
question:
|
|
7840
|
+
question: I,
|
|
7817
7841
|
score: a.current.score
|
|
7818
7842
|
});
|
|
7819
7843
|
const H = () => {
|
|
7820
|
-
if (!u.current || !
|
|
7844
|
+
if (!u.current || !I) return;
|
|
7821
7845
|
if (u.current.setMood("happy"), u.current.setBodyMovement("idle"), e.nextQuestion)
|
|
7822
7846
|
try {
|
|
7823
7847
|
u.current.playAnimation(e.nextQuestion, !0);
|
|
7824
|
-
} catch (
|
|
7825
|
-
console.warn("Failed to play nextQuestion animation:",
|
|
7848
|
+
} catch (_) {
|
|
7849
|
+
console.warn("Failed to play nextQuestion animation:", _);
|
|
7826
7850
|
}
|
|
7827
|
-
const P =
|
|
7828
|
-
if (
|
|
7829
|
-
const
|
|
7830
|
-
u.current.speakText(
|
|
7851
|
+
const P = M.current || { lipsyncLang: "en" }, te = R()?.questions?.length || 0, q = a.current.currentQuestionIndex >= te - 1;
|
|
7852
|
+
if (I.type === "code_test") {
|
|
7853
|
+
const _ = q ? `Great! Here's your final coding challenge: ${I.question}` : `Great! Now let's move on to your next coding challenge: ${I.question}`;
|
|
7854
|
+
u.current.speakText(_, {
|
|
7831
7855
|
lipsyncLang: P.lipsyncLang
|
|
7832
7856
|
});
|
|
7833
|
-
} else if (
|
|
7834
|
-
const
|
|
7835
|
-
u.current.speakText(
|
|
7857
|
+
} else if (I.type === "multiple_choice") {
|
|
7858
|
+
const _ = q ? `Alright! Here's your final question: ${I.question}` : `Alright! Here's your next question: ${I.question}`;
|
|
7859
|
+
u.current.speakText(_, {
|
|
7836
7860
|
lipsyncLang: P.lipsyncLang
|
|
7837
7861
|
});
|
|
7838
|
-
} else if (
|
|
7839
|
-
const
|
|
7840
|
-
u.current.speakText(
|
|
7862
|
+
} else if (I.type === "true_false") {
|
|
7863
|
+
const _ = q ? `Now let's try this final one: ${I.question}` : `Now let's try this one: ${I.question}`;
|
|
7864
|
+
u.current.speakText(_, {
|
|
7841
7865
|
lipsyncLang: P.lipsyncLang
|
|
7842
7866
|
});
|
|
7843
7867
|
} else {
|
|
7844
|
-
const
|
|
7845
|
-
u.current.speakText(
|
|
7868
|
+
const _ = q ? `Here's your final question: ${I.question}` : `Here's the next question: ${I.question}`;
|
|
7869
|
+
u.current.speakText(_, {
|
|
7846
7870
|
lipsyncLang: P.lipsyncLang
|
|
7847
7871
|
});
|
|
7848
7872
|
}
|
|
7849
7873
|
};
|
|
7850
|
-
if (u.current && u.current.isReady &&
|
|
7874
|
+
if (u.current && u.current.isReady && I)
|
|
7851
7875
|
H();
|
|
7852
|
-
else if (
|
|
7876
|
+
else if (I) {
|
|
7853
7877
|
const P = setInterval(() => {
|
|
7854
7878
|
u.current && u.current.isReady && (clearInterval(P), H());
|
|
7855
7879
|
}, 100);
|
|
@@ -7865,55 +7889,55 @@ const yt = Me(({
|
|
|
7865
7889
|
totalQuestions: a.current.totalQuestions,
|
|
7866
7890
|
score: a.current.score
|
|
7867
7891
|
});
|
|
7868
|
-
}, [e.nextQuestion,
|
|
7869
|
-
const v =
|
|
7870
|
-
if (a.current.currentLessonIndex < (
|
|
7892
|
+
}, [e.nextQuestion, R, f]), Q = N(() => {
|
|
7893
|
+
const v = B.current || { modules: [] }, I = v.modules[a.current.currentModuleIndex];
|
|
7894
|
+
if (a.current.currentLessonIndex < (I?.lessons?.length || 0) - 1) {
|
|
7871
7895
|
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;
|
|
7872
|
-
const P = v.modules[a.current.currentModuleIndex],
|
|
7896
|
+
const P = v.modules[a.current.currentModuleIndex], G = a.current.currentLessonIndex < (P?.lessons?.length || 0) - 1, te = a.current.currentModuleIndex < (v.modules?.length || 0) - 1, q = G || te;
|
|
7873
7897
|
d.current.onCustomAction({
|
|
7874
7898
|
type: "lessonStart",
|
|
7875
7899
|
moduleIndex: a.current.currentModuleIndex,
|
|
7876
7900
|
lessonIndex: a.current.currentLessonIndex,
|
|
7877
|
-
hasNextLesson:
|
|
7901
|
+
hasNextLesson: q
|
|
7878
7902
|
}), d.current.onLessonStart({
|
|
7879
7903
|
moduleIndex: a.current.currentModuleIndex,
|
|
7880
7904
|
lessonIndex: a.current.currentLessonIndex,
|
|
7881
|
-
lesson:
|
|
7905
|
+
lesson: R()
|
|
7882
7906
|
}), u.current && (u.current.setMood("happy"), u.current.setBodyMovement("idle"));
|
|
7883
7907
|
} else if (a.current.currentModuleIndex < (v.modules?.length || 0) - 1) {
|
|
7884
7908
|
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;
|
|
7885
|
-
const
|
|
7909
|
+
const G = v.modules[a.current.currentModuleIndex], te = a.current.currentLessonIndex < (G?.lessons?.length || 0) - 1, q = a.current.currentModuleIndex < (v.modules?.length || 0) - 1, _ = te || q;
|
|
7886
7910
|
d.current.onCustomAction({
|
|
7887
7911
|
type: "lessonStart",
|
|
7888
7912
|
moduleIndex: a.current.currentModuleIndex,
|
|
7889
7913
|
lessonIndex: a.current.currentLessonIndex,
|
|
7890
|
-
hasNextLesson:
|
|
7914
|
+
hasNextLesson: _
|
|
7891
7915
|
}), d.current.onLessonStart({
|
|
7892
7916
|
moduleIndex: a.current.currentModuleIndex,
|
|
7893
7917
|
lessonIndex: a.current.currentLessonIndex,
|
|
7894
|
-
lesson:
|
|
7918
|
+
lesson: R()
|
|
7895
7919
|
}), u.current && (u.current.setMood("happy"), u.current.setBodyMovement("idle"));
|
|
7896
7920
|
} else
|
|
7897
|
-
|
|
7898
|
-
}, []),
|
|
7899
|
-
const v =
|
|
7900
|
-
let
|
|
7921
|
+
L.current && L.current();
|
|
7922
|
+
}, []), Y = N(() => {
|
|
7923
|
+
const v = R();
|
|
7924
|
+
let I = null;
|
|
7901
7925
|
if (v?.avatar_script && v?.body) {
|
|
7902
|
-
const H = v.avatar_script.trim(), P = v.body.trim(),
|
|
7903
|
-
|
|
7926
|
+
const H = v.avatar_script.trim(), P = v.body.trim(), G = H.match(/[.!?]$/) ? " " : ". ";
|
|
7927
|
+
I = `${H}${G}${P}`;
|
|
7904
7928
|
} else
|
|
7905
|
-
|
|
7906
|
-
if (u.current && u.current.isReady &&
|
|
7929
|
+
I = v?.avatar_script || v?.body || null;
|
|
7930
|
+
if (u.current && u.current.isReady && I) {
|
|
7907
7931
|
a.current.isTeaching = !0, a.current.isQuestionMode = !1, a.current.score = 0, a.current.totalQuestions = 0, u.current.setMood("happy");
|
|
7908
7932
|
let H = !1;
|
|
7909
7933
|
if (e.teaching)
|
|
7910
7934
|
try {
|
|
7911
7935
|
u.current.playAnimation(e.teaching, !0), H = !0;
|
|
7912
|
-
} catch (
|
|
7913
|
-
console.warn("Failed to play teaching animation:",
|
|
7936
|
+
} catch (G) {
|
|
7937
|
+
console.warn("Failed to play teaching animation:", G);
|
|
7914
7938
|
}
|
|
7915
7939
|
H || u.current.setBodyMovement("gesturing");
|
|
7916
|
-
const P =
|
|
7940
|
+
const P = M.current || { lipsyncLang: "en" };
|
|
7917
7941
|
d.current.onLessonStart({
|
|
7918
7942
|
moduleIndex: a.current.currentModuleIndex,
|
|
7919
7943
|
lessonIndex: a.current.currentLessonIndex,
|
|
@@ -7923,7 +7947,7 @@ const yt = Me(({
|
|
|
7923
7947
|
moduleIndex: a.current.currentModuleIndex,
|
|
7924
7948
|
lessonIndex: a.current.currentLessonIndex,
|
|
7925
7949
|
lesson: v
|
|
7926
|
-
}), u.current.speakText(
|
|
7950
|
+
}), u.current.speakText(I, {
|
|
7927
7951
|
lipsyncLang: P.lipsyncLang,
|
|
7928
7952
|
onSpeechEnd: () => {
|
|
7929
7953
|
a.current.isTeaching = !1, d.current.onCustomAction({
|
|
@@ -7942,15 +7966,15 @@ const yt = Me(({
|
|
|
7942
7966
|
}
|
|
7943
7967
|
});
|
|
7944
7968
|
}
|
|
7945
|
-
}, [e.teaching,
|
|
7946
|
-
const
|
|
7969
|
+
}, [e.teaching, R]), $ = N((v) => {
|
|
7970
|
+
const I = f(), H = C(v, I);
|
|
7947
7971
|
if (H && (a.current.score += 1), d.current.onQuestionAnswer({
|
|
7948
7972
|
moduleIndex: a.current.currentModuleIndex,
|
|
7949
7973
|
lessonIndex: a.current.currentLessonIndex,
|
|
7950
7974
|
questionIndex: a.current.currentQuestionIndex,
|
|
7951
7975
|
answer: v,
|
|
7952
7976
|
isCorrect: H,
|
|
7953
|
-
question:
|
|
7977
|
+
question: I
|
|
7954
7978
|
}), u.current)
|
|
7955
7979
|
if (H) {
|
|
7956
7980
|
if (u.current.setMood("happy"), e.correct)
|
|
@@ -7960,13 +7984,13 @@ const yt = Me(({
|
|
|
7960
7984
|
u.current.setBodyMovement("happy");
|
|
7961
7985
|
}
|
|
7962
7986
|
u.current.setBodyMovement("gesturing");
|
|
7963
|
-
const
|
|
7964
|
-
a.current.currentQuestionIndex >=
|
|
7965
|
-
const
|
|
7966
|
-
console.log("[CurriculumLearning] Answer feedback - questionIndex:", a.current.currentQuestionIndex, "totalQuestions:",
|
|
7967
|
-
const
|
|
7968
|
-
u.current.speakText(
|
|
7969
|
-
lipsyncLang:
|
|
7987
|
+
const G = R()?.questions?.length || 0;
|
|
7988
|
+
a.current.currentQuestionIndex >= G - 1;
|
|
7989
|
+
const te = a.current.currentQuestionIndex < G - 1;
|
|
7990
|
+
console.log("[CurriculumLearning] Answer feedback - questionIndex:", a.current.currentQuestionIndex, "totalQuestions:", G, "hasNextQuestion:", te);
|
|
7991
|
+
const q = I.type === "code_test" ? `Great job! Your code passed all the tests! ${I.explanation || ""}` : `Excellent! That's correct! ${I.explanation || ""}`, _ = M.current || { lipsyncLang: "en" };
|
|
7992
|
+
u.current.speakText(q, {
|
|
7993
|
+
lipsyncLang: _.lipsyncLang,
|
|
7970
7994
|
onSpeechEnd: () => {
|
|
7971
7995
|
d.current.onCustomAction({
|
|
7972
7996
|
type: "answerFeedbackComplete",
|
|
@@ -7974,7 +7998,7 @@ const yt = Me(({
|
|
|
7974
7998
|
lessonIndex: a.current.currentLessonIndex,
|
|
7975
7999
|
questionIndex: a.current.currentQuestionIndex,
|
|
7976
8000
|
isCorrect: !0,
|
|
7977
|
-
hasNextQuestion:
|
|
8001
|
+
hasNextQuestion: te,
|
|
7978
8002
|
score: a.current.score,
|
|
7979
8003
|
totalQuestions: a.current.totalQuestions
|
|
7980
8004
|
});
|
|
@@ -7988,11 +8012,11 @@ const yt = Me(({
|
|
|
7988
8012
|
u.current.setBodyMovement("idle");
|
|
7989
8013
|
}
|
|
7990
8014
|
u.current.setBodyMovement("gesturing");
|
|
7991
|
-
const
|
|
7992
|
-
console.log("[CurriculumLearning] Answer feedback (incorrect) - questionIndex:", a.current.currentQuestionIndex, "totalQuestions:",
|
|
7993
|
-
const
|
|
7994
|
-
u.current.speakText(
|
|
7995
|
-
lipsyncLang:
|
|
8015
|
+
const G = R()?.questions?.length || 0, te = a.current.currentQuestionIndex >= G - 1, q = a.current.currentQuestionIndex < G - 1;
|
|
8016
|
+
console.log("[CurriculumLearning] Answer feedback (incorrect) - questionIndex:", a.current.currentQuestionIndex, "totalQuestions:", G, "hasNextQuestion:", q);
|
|
8017
|
+
const _ = 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 || ""}${te ? "" : " Let's move on to the next question."}`, fe = M.current || { lipsyncLang: "en" };
|
|
8018
|
+
u.current.speakText(_, {
|
|
8019
|
+
lipsyncLang: fe.lipsyncLang,
|
|
7996
8020
|
onSpeechEnd: () => {
|
|
7997
8021
|
d.current.onCustomAction({
|
|
7998
8022
|
type: "answerFeedbackComplete",
|
|
@@ -8000,7 +8024,7 @@ const yt = Me(({
|
|
|
8000
8024
|
lessonIndex: a.current.currentLessonIndex,
|
|
8001
8025
|
questionIndex: a.current.currentQuestionIndex,
|
|
8002
8026
|
isCorrect: !1,
|
|
8003
|
-
hasNextQuestion:
|
|
8027
|
+
hasNextQuestion: q,
|
|
8004
8028
|
score: a.current.score,
|
|
8005
8029
|
totalQuestions: a.current.totalQuestions
|
|
8006
8030
|
});
|
|
@@ -8008,26 +8032,26 @@ const yt = Me(({
|
|
|
8008
8032
|
});
|
|
8009
8033
|
}
|
|
8010
8034
|
else {
|
|
8011
|
-
const
|
|
8035
|
+
const G = R()?.questions?.length || 0;
|
|
8012
8036
|
d.current.onCustomAction({
|
|
8013
8037
|
type: "answerFeedbackComplete",
|
|
8014
8038
|
moduleIndex: a.current.currentModuleIndex,
|
|
8015
8039
|
lessonIndex: a.current.currentLessonIndex,
|
|
8016
8040
|
questionIndex: a.current.currentQuestionIndex,
|
|
8017
8041
|
isCorrect: H,
|
|
8018
|
-
hasNextQuestion: a.current.currentQuestionIndex <
|
|
8042
|
+
hasNextQuestion: a.current.currentQuestionIndex < G - 1,
|
|
8019
8043
|
score: a.current.score,
|
|
8020
8044
|
totalQuestions: a.current.totalQuestions,
|
|
8021
8045
|
avatarNotReady: !0
|
|
8022
8046
|
});
|
|
8023
8047
|
}
|
|
8024
|
-
}, [e.correct, e.incorrect,
|
|
8025
|
-
const
|
|
8048
|
+
}, [e.correct, e.incorrect, f, R, C]), re = N((v) => {
|
|
8049
|
+
const I = f();
|
|
8026
8050
|
if (!v || typeof v != "object") {
|
|
8027
8051
|
console.error("Invalid code test result format. Expected object with {passed: boolean, ...}");
|
|
8028
8052
|
return;
|
|
8029
8053
|
}
|
|
8030
|
-
if (
|
|
8054
|
+
if (I?.type !== "code_test") {
|
|
8031
8055
|
console.warn("Current question is not a code test. Use handleAnswerSelect for other question types.");
|
|
8032
8056
|
return;
|
|
8033
8057
|
}
|
|
@@ -8047,12 +8071,12 @@ const yt = Me(({
|
|
|
8047
8071
|
lessonIndex: a.current.currentLessonIndex,
|
|
8048
8072
|
questionIndex: a.current.currentQuestionIndex,
|
|
8049
8073
|
testResult: H,
|
|
8050
|
-
question:
|
|
8074
|
+
question: I
|
|
8051
8075
|
}), p.current && p.current(H);
|
|
8052
|
-
}, [
|
|
8076
|
+
}, [f, C]), he = N(() => {
|
|
8053
8077
|
if (a.current.currentQuestionIndex > 0) {
|
|
8054
8078
|
a.current.currentQuestionIndex -= 1;
|
|
8055
|
-
const v =
|
|
8079
|
+
const v = f();
|
|
8056
8080
|
v && d.current.onCustomAction({
|
|
8057
8081
|
type: "questionStart",
|
|
8058
8082
|
moduleIndex: a.current.currentModuleIndex,
|
|
@@ -8062,10 +8086,10 @@ const yt = Me(({
|
|
|
8062
8086
|
question: v,
|
|
8063
8087
|
score: a.current.score
|
|
8064
8088
|
});
|
|
8065
|
-
const
|
|
8089
|
+
const I = () => {
|
|
8066
8090
|
if (!u.current || !v) return;
|
|
8067
8091
|
u.current.setMood("happy"), u.current.setBodyMovement("idle");
|
|
8068
|
-
const H =
|
|
8092
|
+
const H = M.current || { lipsyncLang: "en" };
|
|
8069
8093
|
v.type === "code_test" ? u.current.speakText(`Let's go back to this coding challenge: ${v.question}`, {
|
|
8070
8094
|
lipsyncLang: H.lipsyncLang
|
|
8071
8095
|
}) : u.current.speakText(`Going back to: ${v.question}`, {
|
|
@@ -8073,18 +8097,18 @@ const yt = Me(({
|
|
|
8073
8097
|
});
|
|
8074
8098
|
};
|
|
8075
8099
|
if (u.current && u.current.isReady && v)
|
|
8076
|
-
|
|
8100
|
+
I();
|
|
8077
8101
|
else if (v) {
|
|
8078
8102
|
const H = setInterval(() => {
|
|
8079
|
-
u.current && u.current.isReady && (clearInterval(H),
|
|
8103
|
+
u.current && u.current.isReady && (clearInterval(H), I());
|
|
8080
8104
|
}, 100);
|
|
8081
8105
|
setTimeout(() => {
|
|
8082
8106
|
clearInterval(H);
|
|
8083
8107
|
}, 5e3);
|
|
8084
8108
|
}
|
|
8085
8109
|
}
|
|
8086
|
-
}, [
|
|
8087
|
-
const v =
|
|
8110
|
+
}, [f]), oe = N(() => {
|
|
8111
|
+
const v = B.current || { modules: [] };
|
|
8088
8112
|
if (v.modules[a.current.currentModuleIndex], a.current.currentLessonIndex > 0)
|
|
8089
8113
|
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, d.current.onCustomAction({
|
|
8090
8114
|
type: "lessonStart",
|
|
@@ -8093,7 +8117,7 @@ const yt = Me(({
|
|
|
8093
8117
|
}), d.current.onLessonStart({
|
|
8094
8118
|
moduleIndex: a.current.currentModuleIndex,
|
|
8095
8119
|
lessonIndex: a.current.currentLessonIndex,
|
|
8096
|
-
lesson:
|
|
8120
|
+
lesson: R()
|
|
8097
8121
|
}), u.current && (u.current.setMood("happy"), u.current.setBodyMovement("idle"));
|
|
8098
8122
|
else if (a.current.currentModuleIndex > 0) {
|
|
8099
8123
|
const P = v.modules[a.current.currentModuleIndex - 1];
|
|
@@ -8104,53 +8128,53 @@ const yt = Me(({
|
|
|
8104
8128
|
}), d.current.onLessonStart({
|
|
8105
8129
|
moduleIndex: a.current.currentModuleIndex,
|
|
8106
8130
|
lessonIndex: a.current.currentLessonIndex,
|
|
8107
|
-
lesson:
|
|
8131
|
+
lesson: R()
|
|
8108
8132
|
}), u.current && (u.current.setMood("happy"), u.current.setBodyMovement("idle"));
|
|
8109
8133
|
}
|
|
8110
|
-
}, [
|
|
8134
|
+
}, [R]), se = N(() => {
|
|
8111
8135
|
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;
|
|
8112
|
-
}, []), le =
|
|
8136
|
+
}, []), le = N((v) => {
|
|
8113
8137
|
console.log("Avatar is ready!", v);
|
|
8114
|
-
const
|
|
8138
|
+
const I = R(), H = I?.avatar_script || I?.body;
|
|
8115
8139
|
h && H && setTimeout(() => {
|
|
8116
8140
|
c.current && c.current();
|
|
8117
8141
|
}, 10);
|
|
8118
|
-
}, [h,
|
|
8142
|
+
}, [h, R]);
|
|
8119
8143
|
Xe(() => {
|
|
8120
|
-
c.current =
|
|
8121
|
-
}),
|
|
8144
|
+
c.current = Y, g.current = Q, b.current = S, x.current = E, L.current = U, O.current = k, p.current = $;
|
|
8145
|
+
}), Te(r, () => ({
|
|
8122
8146
|
// Curriculum control methods
|
|
8123
|
-
startTeaching:
|
|
8147
|
+
startTeaching: Y,
|
|
8124
8148
|
startQuestions: k,
|
|
8125
|
-
handleAnswerSelect:
|
|
8126
|
-
handleCodeTestResult:
|
|
8149
|
+
handleAnswerSelect: $,
|
|
8150
|
+
handleCodeTestResult: re,
|
|
8127
8151
|
nextQuestion: E,
|
|
8128
|
-
previousQuestion:
|
|
8129
|
-
nextLesson:
|
|
8130
|
-
previousLesson:
|
|
8131
|
-
completeLesson:
|
|
8132
|
-
completeCurriculum:
|
|
8133
|
-
resetCurriculum:
|
|
8152
|
+
previousQuestion: he,
|
|
8153
|
+
nextLesson: Q,
|
|
8154
|
+
previousLesson: oe,
|
|
8155
|
+
completeLesson: S,
|
|
8156
|
+
completeCurriculum: U,
|
|
8157
|
+
resetCurriculum: se,
|
|
8134
8158
|
getState: () => ({ ...a.current }),
|
|
8135
|
-
getCurrentQuestion: () =>
|
|
8136
|
-
getCurrentLesson: () =>
|
|
8159
|
+
getCurrentQuestion: () => f(),
|
|
8160
|
+
getCurrentLesson: () => R(),
|
|
8137
8161
|
// Direct access to avatar ref (always returns current value)
|
|
8138
8162
|
getAvatarRef: () => u.current,
|
|
8139
8163
|
// Convenience methods that delegate to avatar (always check current ref)
|
|
8140
|
-
speakText: async (v,
|
|
8164
|
+
speakText: async (v, I = {}) => {
|
|
8141
8165
|
await u.current?.resumeAudioContext?.();
|
|
8142
|
-
const H =
|
|
8143
|
-
u.current?.speakText(v, { ...
|
|
8166
|
+
const H = M.current || { lipsyncLang: "en" };
|
|
8167
|
+
u.current?.speakText(v, { ...I, lipsyncLang: I.lipsyncLang || H.lipsyncLang });
|
|
8144
8168
|
},
|
|
8145
8169
|
resumeAudioContext: async () => {
|
|
8146
8170
|
if (u.current?.resumeAudioContext)
|
|
8147
8171
|
return await u.current.resumeAudioContext();
|
|
8148
8172
|
const v = u.current?.talkingHead;
|
|
8149
8173
|
if (v?.audioCtx) {
|
|
8150
|
-
const
|
|
8151
|
-
if (
|
|
8174
|
+
const I = v.audioCtx;
|
|
8175
|
+
if (I.state === "suspended" || I.state === "interrupted")
|
|
8152
8176
|
try {
|
|
8153
|
-
await
|
|
8177
|
+
await I.resume(), console.log("Audio context resumed via talkingHead");
|
|
8154
8178
|
} catch (H) {
|
|
8155
8179
|
console.warn("Failed to resume audio context:", H);
|
|
8156
8180
|
}
|
|
@@ -8162,7 +8186,7 @@ const yt = Me(({
|
|
|
8162
8186
|
resumeSpeaking: async () => await u.current?.resumeSpeaking(),
|
|
8163
8187
|
isPaused: () => u.current && typeof u.current.isPaused < "u" ? u.current.isPaused : !1,
|
|
8164
8188
|
setMood: (v) => u.current?.setMood(v),
|
|
8165
|
-
playAnimation: (v,
|
|
8189
|
+
playAnimation: (v, I) => u.current?.playAnimation(v, I),
|
|
8166
8190
|
setBodyMovement: (v) => u.current?.setBodyMovement(v),
|
|
8167
8191
|
setMovementIntensity: (v) => u.current?.setMovementIntensity(v),
|
|
8168
8192
|
playRandomDance: () => u.current?.playRandomDance(),
|
|
@@ -8173,10 +8197,10 @@ const yt = Me(({
|
|
|
8173
8197
|
lockAvatarPosition: () => u.current?.lockAvatarPosition(),
|
|
8174
8198
|
unlockAvatarPosition: () => u.current?.unlockAvatarPosition(),
|
|
8175
8199
|
// Custom action trigger
|
|
8176
|
-
triggerCustomAction: (v,
|
|
8200
|
+
triggerCustomAction: (v, I) => {
|
|
8177
8201
|
d.current.onCustomAction({
|
|
8178
8202
|
type: v,
|
|
8179
|
-
...
|
|
8203
|
+
...I,
|
|
8180
8204
|
state: { ...a.current }
|
|
8181
8205
|
});
|
|
8182
8206
|
},
|
|
@@ -8184,8 +8208,8 @@ const yt = Me(({
|
|
|
8184
8208
|
handleResize: () => u.current?.handleResize(),
|
|
8185
8209
|
// Avatar readiness check (always returns current value)
|
|
8186
8210
|
isAvatarReady: () => u.current?.isReady || !1
|
|
8187
|
-
}), [
|
|
8188
|
-
const
|
|
8211
|
+
}), [Y, k, $, re, E, Q, S, U, se, f, R]);
|
|
8212
|
+
const j = M.current || {
|
|
8189
8213
|
avatarUrl: "/avatars/brunette.glb",
|
|
8190
8214
|
avatarBody: "F",
|
|
8191
8215
|
mood: "happy",
|
|
@@ -8202,18 +8226,18 @@ const yt = Me(({
|
|
|
8202
8226
|
Ve,
|
|
8203
8227
|
{
|
|
8204
8228
|
ref: u,
|
|
8205
|
-
avatarUrl:
|
|
8206
|
-
avatarBody:
|
|
8207
|
-
mood:
|
|
8208
|
-
ttsLang:
|
|
8209
|
-
ttsService:
|
|
8210
|
-
ttsVoice:
|
|
8211
|
-
ttsApiKey:
|
|
8212
|
-
bodyMovement:
|
|
8213
|
-
movementIntensity:
|
|
8214
|
-
showFullAvatar:
|
|
8229
|
+
avatarUrl: j.avatarUrl,
|
|
8230
|
+
avatarBody: j.avatarBody,
|
|
8231
|
+
mood: j.mood,
|
|
8232
|
+
ttsLang: j.ttsLang,
|
|
8233
|
+
ttsService: j.ttsService,
|
|
8234
|
+
ttsVoice: j.ttsVoice,
|
|
8235
|
+
ttsApiKey: j.ttsApiKey,
|
|
8236
|
+
bodyMovement: j.bodyMovement,
|
|
8237
|
+
movementIntensity: j.movementIntensity,
|
|
8238
|
+
showFullAvatar: j.showFullAvatar,
|
|
8215
8239
|
cameraView: "upper",
|
|
8216
|
-
animations:
|
|
8240
|
+
animations: j.animations,
|
|
8217
8241
|
onReady: le,
|
|
8218
8242
|
onLoading: () => {
|
|
8219
8243
|
},
|
|
@@ -8334,7 +8358,7 @@ export {
|
|
|
8334
8358
|
Ve as TalkingHeadAvatar,
|
|
8335
8359
|
pt as TalkingHeadComponent,
|
|
8336
8360
|
Ge as animations,
|
|
8337
|
-
|
|
8361
|
+
Me as getActiveTTSConfig,
|
|
8338
8362
|
wt as getAnimation,
|
|
8339
8363
|
kt as getVoiceOptions,
|
|
8340
8364
|
zt as hasAnimation
|