@sage-rsc/talking-head-react 1.1.8 → 1.1.9
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 +839 -782
- package/package.json +1 -1
- package/src/lib/talkinghead.mjs +140 -8
package/dist/index.js
CHANGED
|
@@ -1,20 +1,20 @@
|
|
|
1
|
-
import { jsxs as Pe, jsx as
|
|
2
|
-
import { forwardRef as Me, useRef as
|
|
1
|
+
import { jsxs as Pe, jsx as pe } from "react/jsx-runtime";
|
|
2
|
+
import { forwardRef as Me, useRef as W, useState as de, useEffect as me, useCallback as N, useImperativeHandle as Fe, useLayoutEffect as Xe } from "react";
|
|
3
3
|
import * as f 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
|
-
import
|
|
10
|
-
let m,
|
|
11
|
-
const
|
|
9
|
+
import _e from "three/addons/libs/stats.module.js";
|
|
10
|
+
let m, ue, he;
|
|
11
|
+
const w = [0, 0, 0, 0], T = new f.Vector3(), ze = new f.Vector3(), ae = new f.Vector3(), Ce = new f.Vector3();
|
|
12
12
|
new f.Plane();
|
|
13
13
|
new f.Ray();
|
|
14
14
|
new f.Euler();
|
|
15
|
-
const
|
|
15
|
+
const re = new f.Quaternion(), Oe = new f.Quaternion(), fe = new f.Matrix4(), xe = new f.Matrix4();
|
|
16
16
|
new f.Vector3();
|
|
17
|
-
const He = new f.Vector3(0, 0, 1),
|
|
17
|
+
const He = new f.Vector3(0, 0, 1), Ke = new f.Vector3(1, 0, 0), Je = new f.Vector3(0, 1, 0), $e = new f.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(T).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(T, re, ae), T.copy(He).applyQuaternion(re).setY(0).normalize(), re.premultiply(Oe.setFromUnitVectors(He, T).invert()).normalize(), u.qWorldInverseYaw = re.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], T.copy(o.vWorld), fe.copy(o.boneParent.matrixWorld), xe.copy(fe).invert(), o.vWorld.setFromMatrixPosition(fe), T.applyMatrix4(xe), T.length() > 0.5 && (console.info("Info: Unrealistic jump of " + T.length().toFixed(2) + " meters."), T.setLength(0.5)), T.applyQuaternion(o.bone.quaternion), w[0] = T.x, w[1] = T.y, w[2] = -T.z, w[3] = T.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], w[0] -= m.v[0] * t / 3, w[1] -= m.v[1] * t / 3, w[2] += m.v[2] * t / 3, w[3] -= m.v[3] * t / 3;
|
|
362
|
+
if (m = this.opt.sensitivityFactor, w[0] *= o.ext * m, w[1] *= o.ext * m, w[2] *= o.ext * m, w[3] *= o.ext * m, o.isX && (m = w[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 + w[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 = w[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 + w[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 = w[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 + w[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 = w[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 + w[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), w[0] = o.p[0], w[1] = o.p[1], w[2] = o.p[2], w[3] = o.p[3], m = this.opt.movementFactor, w[0] *= m, w[1] *= m, w[2] *= m, w[3] *= m, o.dl && (m = o.dl, w[0] += m[0], w[1] += m[1], w[2] += m[2]), o.dw && (m = o.dw, T.set(
|
|
363
|
+
o.vBasis.x + w[0],
|
|
364
|
+
o.vBasis.y + w[1],
|
|
365
|
+
o.vBasis.z + w[2]
|
|
366
|
+
), T.applyMatrix4(fe), T.x += m[0], T.y += m[1], T.z += m[2], T.applyMatrix4(xe), w[0] += T.x - o.vBasis.x, w[1] += T.y - o.vBasis.y, w[2] += T.z - o.vBasis.z), o.limits && this.opt.isLimits && (m = o.limits, m[0] && (m[0][0] !== null && w[0] < m[0][0] && (w[0] = m[0][0]), m[0][1] !== null && w[0] > m[0][1] && (w[0] = m[0][1])), m[1] && (m[1][0] !== null && w[1] < m[1][0] && (w[1] = m[1][0]), m[1][1] !== null && w[1] > m[1][1] && (w[1] = m[1][1])), m[2] && (m[2][0] !== null && w[2] < m[2][0] && (w[2] = m[2][0]), m[2][1] !== null && w[2] > m[2][1] && (w[2] = m[2][1])), m[3] && (m[3][0] !== null && w[3] < m[3][0] && (w[3] = m[3][0]), m[3][1] !== null && w[3] > m[3][1] && (w[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 + w[0],
|
|
369
|
+
o.vBasis.y + w[1],
|
|
370
|
+
o.vBasis.z - w[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(T, re, ae), T.copy(He).applyQuaternion(re).setY(0).normalize(), re.premultiply(Oe.setFromUnitVectors(He, T).invert()).normalize(), o.boneParent.quaternion.multiply(re.invert()), o.boneParent.quaternion.multiply(o.qWorldInverseYaw)), o.isZ && (m = Math.atan(w[0] / o.l), re.setFromAxisAngle($e, -m), o.boneParent.quaternion.multiply(re)), o.isY && (m = o.l / 3, m = m * Math.tanh(w[1] / m), o.bone.position.setLength(o.l + m)), o.isX && (m = Math.atan(w[2] / o.l), re.setFromAxisAngle(Ke, -m), o.boneParent.quaternion.multiply(re)), o.isT && (m = 1.5 * Math.tanh(w[3] * 1.5), re.setFromAxisAngle(Je, -m), o.boneParent.quaternion.multiply(re)), 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], ae.set(0, 0, 0), m.deltaLocal && (ae.x += m.deltaLocal[0], ae.y += m.deltaLocal[1], ae.z += m.deltaLocal[2]), ae.applyMatrix4(m.bone.matrixWorld), xe.copy(o.boneParent.matrixWorld).invert(), ae.applyMatrix4(xe), T.copy(o.bone.position), !(T.distanceToSquared(ae) >= m.radiusSq) && (he = T.length(), ue = ae.length(), !(ue > m.radius + he) && (ue < Math.abs(m.radius - he) || (ue = (ue * ue + he * he - m.radiusSq) / (2 * ue), ae.normalize(), Ce.copy(ae).multiplyScalar(ue), ue = Math.sqrt(he * he - ue * ue), T.subVectors(T, Ce).projectOnPlane(ae).normalize().multiplyScalar(ue), ze.subVectors(o.vBasis, Ce).projectOnPlane(ae).normalize(), he = ze.dot(T), he < 0 && (he = Math.sqrt(ue * ue - he * he), ze.multiplyScalar(he), T.add(ze)), T.add(Ce).normalize(), ae.copy(o.bone.position).normalize(), re.setFromUnitVectors(ae, T), o.boneParent.quaternion.premultiply(re), o.boneParent.updateWorldMatrix(!1, !0))));
|
|
375
375
|
}
|
|
376
376
|
this.helpers.isActive && this.updateHelpers();
|
|
377
377
|
}
|
|
@@ -445,14 +445,14 @@ class et {
|
|
|
445
445
|
xe.copy(this.armature.matrixWorld).invert();
|
|
446
446
|
const t = m.object.geometry.getAttribute("position");
|
|
447
447
|
for (let e = 0, n = m.bones.length; e < n; e++)
|
|
448
|
-
fe.multiplyMatrices(xe, m.bones[e].matrixWorld),
|
|
448
|
+
fe.multiplyMatrices(xe, m.bones[e].matrixWorld), T.setFromMatrixPosition(fe), t.setXYZ(e, T.x, T.y, T.z);
|
|
449
449
|
t.needsUpdate = !0, m.object.updateMatrixWorld();
|
|
450
450
|
}
|
|
451
451
|
if (m = this.helpers.lines, m.bones.length) {
|
|
452
452
|
xe.copy(this.armature.matrixWorld).invert();
|
|
453
453
|
const t = m.object.geometry.getAttribute("position");
|
|
454
454
|
for (let e = 0, n = 0, i = m.bones.length; e < i; e++, n += 2)
|
|
455
|
-
fe.multiplyMatrices(xe, m.bones[e].matrixWorld),
|
|
455
|
+
fe.multiplyMatrices(xe, m.bones[e].matrixWorld), T.setFromMatrixPosition(fe), t.setXYZ(n, T.x, T.y, T.z), fe.multiplyMatrices(xe, m.bones[e].parent.matrixWorld), T.setFromMatrixPosition(fe), t.setXYZ(n + 1, T.x, T.y, T.z);
|
|
456
456
|
t.needsUpdate = !0, m.object.updateMatrixWorld();
|
|
457
457
|
}
|
|
458
458
|
}
|
|
@@ -521,10 +521,10 @@ class tt {
|
|
|
521
521
|
for (let l = 0; l < o; l++) {
|
|
522
522
|
const h = l * s, r = Math.min(h + i, t.length), u = t.slice(h, r), a = this.calculateEnergy(u);
|
|
523
523
|
n.energy.push(a);
|
|
524
|
-
const
|
|
525
|
-
n.spectralCentroid.push(
|
|
526
|
-
const
|
|
527
|
-
n.zeroCrossingRate.push(
|
|
524
|
+
const d = this.calculateSpectralCentroid(u);
|
|
525
|
+
n.spectralCentroid.push(d);
|
|
526
|
+
const c = this.calculateZeroCrossingRate(u);
|
|
527
|
+
n.zeroCrossingRate.push(c);
|
|
528
528
|
const g = this.calculateMFCC(u);
|
|
529
529
|
n.mfcc.push(g);
|
|
530
530
|
}
|
|
@@ -606,10 +606,10 @@ class tt {
|
|
|
606
606
|
for (let h = 0; h < e; h += i) {
|
|
607
607
|
let r = 1, u = 0;
|
|
608
608
|
for (let a = 0; a < i / 2; a++) {
|
|
609
|
-
const
|
|
610
|
-
n[(h + a) * 2] =
|
|
611
|
-
const x = r * o - u * l,
|
|
612
|
-
r = x, u =
|
|
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
|
+
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, S = r * l + u * o;
|
|
612
|
+
r = x, u = S;
|
|
613
613
|
}
|
|
614
614
|
}
|
|
615
615
|
}
|
|
@@ -703,15 +703,15 @@ class tt {
|
|
|
703
703
|
const o = this.textToVisemes(e);
|
|
704
704
|
let l = 0, h = 0;
|
|
705
705
|
for (let r = 0; r < s.length && l < o.length; r++) {
|
|
706
|
-
const u = s[r], a = o[l],
|
|
706
|
+
const u = s[r], a = o[l], d = t.energy[Math.floor(u / 0.023)] || 0, c = this.calculateVisemeDuration(a, d);
|
|
707
707
|
i.push({
|
|
708
708
|
viseme: a,
|
|
709
709
|
startTime: h,
|
|
710
|
-
endTime: h +
|
|
711
|
-
duration:
|
|
712
|
-
intensity: Math.min(1,
|
|
710
|
+
endTime: h + c,
|
|
711
|
+
duration: c,
|
|
712
|
+
intensity: Math.min(1, d * 2)
|
|
713
713
|
// Map energy to viseme intensity
|
|
714
|
-
}), h +=
|
|
714
|
+
}), h += c, l++;
|
|
715
715
|
}
|
|
716
716
|
for (; l < o.length; ) {
|
|
717
717
|
const r = o[l], u = this.calculateVisemeDuration(r, 0.5);
|
|
@@ -1207,10 +1207,10 @@ class nt {
|
|
|
1207
1207
|
Object.keys(this.rules).forEach((e) => {
|
|
1208
1208
|
this.rules[e] = this.rules[e].map((n) => {
|
|
1209
1209
|
const i = n.indexOf("["), s = n.indexOf("]"), o = n.indexOf("="), l = n.substring(0, i), h = n.substring(i + 1, s), r = n.substring(s + 1, o), u = n.substring(o + 1), a = { regex: "", move: 0, visemes: [] };
|
|
1210
|
-
let
|
|
1211
|
-
|
|
1212
|
-
const
|
|
1213
|
-
return
|
|
1210
|
+
let d = "";
|
|
1211
|
+
d += [...l].map((g) => t[g] || g).join("");
|
|
1212
|
+
const c = [...h];
|
|
1213
|
+
return c[0] = c[0].toLowerCase(), d += c.join(""), a.move = c.length, d += [...r].map((g) => t[g] || g).join(""), a.regex = new RegExp(d), u.length && u.split(" ").forEach((g) => {
|
|
1214
1214
|
a.visemes.push(g);
|
|
1215
1215
|
}), a;
|
|
1216
1216
|
});
|
|
@@ -1380,11 +1380,11 @@ class nt {
|
|
|
1380
1380
|
if ((e.words.substring(0, e.i) + s.toLowerCase() + e.words.substring(e.i + 1)).match(h.regex)) {
|
|
1381
1381
|
h.visemes.forEach((a) => {
|
|
1382
1382
|
if (e.visemes.length && e.visemes[e.visemes.length - 1] === a) {
|
|
1383
|
-
const
|
|
1384
|
-
e.durations[e.durations.length - 1] +=
|
|
1383
|
+
const d = 0.7 * (this.visemeDurations[a] || 1);
|
|
1384
|
+
e.durations[e.durations.length - 1] += d, n += d;
|
|
1385
1385
|
} else {
|
|
1386
|
-
const
|
|
1387
|
-
e.visemes.push(a), e.times.push(n), e.durations.push(
|
|
1386
|
+
const d = this.visemeDurations[a] || 1;
|
|
1387
|
+
e.visemes.push(a), e.times.push(n), e.durations.push(d), n += d;
|
|
1388
1388
|
}
|
|
1389
1389
|
}), e.i += h.move;
|
|
1390
1390
|
break;
|
|
@@ -1617,10 +1617,10 @@ class ot {
|
|
|
1617
1617
|
Object.keys(this.rules).forEach((e) => {
|
|
1618
1618
|
this.rules[e] = this.rules[e].map((n) => {
|
|
1619
1619
|
const i = n.indexOf("["), s = n.indexOf("]"), o = n.indexOf("="), l = n.substring(0, i), h = n.substring(i + 1, s), r = n.substring(s + 1, o), u = n.substring(o + 1), a = { regex: "", move: 0, visemes: [] };
|
|
1620
|
-
let
|
|
1621
|
-
|
|
1622
|
-
const
|
|
1623
|
-
return
|
|
1620
|
+
let d = "";
|
|
1621
|
+
d += [...l].map((g) => t[g] || g).join("");
|
|
1622
|
+
const c = [...h];
|
|
1623
|
+
return c[0] = c[0].toLowerCase(), d += c.join(""), a.move = c.length, d += [...r].map((g) => t[g] || g).join(""), a.regex = new RegExp(d), u.length && u.split(" ").forEach((g) => {
|
|
1624
1624
|
a.visemes.push(g);
|
|
1625
1625
|
}), a;
|
|
1626
1626
|
});
|
|
@@ -1735,13 +1735,13 @@ class ot {
|
|
|
1735
1735
|
for (let h = 0; h < o.length; h++) {
|
|
1736
1736
|
const r = o[h];
|
|
1737
1737
|
if ((e.words.substring(0, e.i) + s.toLowerCase() + e.words.substring(e.i + 1)).match(r.regex)) {
|
|
1738
|
-
r.visemes.forEach((
|
|
1739
|
-
if (e.visemes.length && e.visemes[e.visemes.length - 1] ===
|
|
1740
|
-
const
|
|
1741
|
-
e.durations[e.durations.length - 1] +=
|
|
1738
|
+
r.visemes.forEach((d) => {
|
|
1739
|
+
if (e.visemes.length && e.visemes[e.visemes.length - 1] === d) {
|
|
1740
|
+
const c = 0.7 * (this.visemeDurations[d] || 1);
|
|
1741
|
+
e.durations[e.durations.length - 1] += c, n += c;
|
|
1742
1742
|
} else {
|
|
1743
|
-
const
|
|
1744
|
-
e.visemes.push(
|
|
1743
|
+
const c = this.visemeDurations[d] || 1;
|
|
1744
|
+
e.visemes.push(d), e.times.push(n), e.durations.push(c), n += c;
|
|
1745
1745
|
}
|
|
1746
1746
|
}), e.i += r.move, l = !0;
|
|
1747
1747
|
break;
|
|
@@ -2132,10 +2132,10 @@ class at {
|
|
|
2132
2132
|
Object.keys(this.rules).forEach((e) => {
|
|
2133
2133
|
this.rules[e] = this.rules[e].map((n) => {
|
|
2134
2134
|
const i = n.indexOf("["), s = n.indexOf("]"), o = n.indexOf("="), l = n.substring(0, i), h = n.substring(i + 1, s), r = n.substring(s + 1, o), u = n.substring(o + 1), a = { regex: "", move: 0, visemes: [] };
|
|
2135
|
-
let
|
|
2136
|
-
|
|
2137
|
-
const
|
|
2138
|
-
return
|
|
2135
|
+
let d = "";
|
|
2136
|
+
d += [...l].map((g) => t[g] || g).join("");
|
|
2137
|
+
const c = [...h];
|
|
2138
|
+
return c[0] = c[0].toLowerCase(), d += c.join(""), a.move = c.length, d += [...r].map((g) => t[g] || g).join(""), a.regex = new RegExp(d, "i"), u.length && u.split(" ").forEach((g) => {
|
|
2139
2139
|
g && a.visemes.push(g);
|
|
2140
2140
|
}), a;
|
|
2141
2141
|
});
|
|
@@ -2270,13 +2270,13 @@ class at {
|
|
|
2270
2270
|
for (let h = 0; h < o.length; h++) {
|
|
2271
2271
|
const r = o[h];
|
|
2272
2272
|
if ((e.words.substring(0, e.i) + s.toLowerCase() + e.words.substring(e.i + 1)).match(r.regex)) {
|
|
2273
|
-
r.visemes.forEach((
|
|
2274
|
-
if (e.visemes.length && e.visemes[e.visemes.length - 1] ===
|
|
2275
|
-
const
|
|
2276
|
-
e.durations[e.durations.length - 1] +=
|
|
2273
|
+
r.visemes.forEach((d) => {
|
|
2274
|
+
if (e.visemes.length && e.visemes[e.visemes.length - 1] === d) {
|
|
2275
|
+
const c = 0.7 * (this.visemeDurations[d] || 1);
|
|
2276
|
+
e.durations[e.durations.length - 1] += c, n += c;
|
|
2277
2277
|
} else {
|
|
2278
|
-
const
|
|
2279
|
-
e.visemes.push(
|
|
2278
|
+
const c = this.visemeDurations[d] || 1;
|
|
2279
|
+
e.visemes.push(d), e.times.push(n), e.durations.push(c), n += c;
|
|
2280
2280
|
}
|
|
2281
2281
|
}), e.i += r.move, l = !0;
|
|
2282
2282
|
break;
|
|
@@ -2629,7 +2629,7 @@ const ct = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
|
|
|
2629
2629
|
fr: rt,
|
|
2630
2630
|
fi: ut,
|
|
2631
2631
|
lt: ct
|
|
2632
|
-
},
|
|
2632
|
+
}, K = new f.Quaternion(), X = new f.Euler(), ve = new f.Vector3(), Re = new f.Vector3(), We = new f.Box3();
|
|
2633
2633
|
new f.Matrix4();
|
|
2634
2634
|
new f.Matrix4();
|
|
2635
2635
|
new f.Vector3();
|
|
@@ -2763,7 +2763,7 @@ class Be {
|
|
|
2763
2763
|
avatarOnlyCamera: null,
|
|
2764
2764
|
statsNode: null,
|
|
2765
2765
|
statsStyle: null
|
|
2766
|
-
}, Object.assign(this.opt, e || {}), this.opt.statsNode && (this.stats = new
|
|
2766
|
+
}, Object.assign(this.opt, e || {}), this.opt.statsNode && (this.stats = new _e(), this.opt.statsStyle && (this.stats.dom.style.cssText = this.opt.statsStyle), this.opt.statsNode.appendChild(this.stats.dom)), this.poseTemplates = {
|
|
2767
2767
|
side: {
|
|
2768
2768
|
standing: !0,
|
|
2769
2769
|
props: {
|
|
@@ -4225,16 +4225,16 @@ class Be {
|
|
|
4225
4225
|
let l = null, h = null;
|
|
4226
4226
|
for (const [r, u] of Object.entries(n))
|
|
4227
4227
|
if (s.morphTargetDictionary.hasOwnProperty(r)) {
|
|
4228
|
-
const a = s.morphTargetDictionary[r],
|
|
4229
|
-
l || (l = new f.Float32BufferAttribute(
|
|
4230
|
-
for (let g = 0; g <
|
|
4231
|
-
const b = l.getX(g) +
|
|
4232
|
-
l.setXYZ(g, b, x,
|
|
4228
|
+
const a = s.morphTargetDictionary[r], d = o.morphAttributes.position[a], c = o.morphAttributes.normal?.[a];
|
|
4229
|
+
l || (l = new f.Float32BufferAttribute(d.count * 3, 3), c && (h = new f.Float32BufferAttribute(d.count * 3, 3)));
|
|
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, S = l.getZ(g) + d.getZ(g) * u;
|
|
4232
|
+
l.setXYZ(g, b, x, S);
|
|
4233
4233
|
}
|
|
4234
|
-
if (
|
|
4235
|
-
for (let g = 0; g <
|
|
4236
|
-
const b = h.getX(g) +
|
|
4237
|
-
h.setXYZ(g, b, x,
|
|
4234
|
+
if (c)
|
|
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, S = h.getZ(g) + c.getZ(g) * u;
|
|
4237
|
+
h.setXYZ(g, b, x, S);
|
|
4238
4238
|
}
|
|
4239
4239
|
}
|
|
4240
4240
|
if (l) {
|
|
@@ -4299,8 +4299,8 @@ class Be {
|
|
|
4299
4299
|
u && ["fixed", "system", "systemd", "realtime", "base", "v", "value", "applied"].forEach((a) => {
|
|
4300
4300
|
l[r][a] = u[a];
|
|
4301
4301
|
}), this.morphs.forEach((a) => {
|
|
4302
|
-
const
|
|
4303
|
-
|
|
4302
|
+
const d = a.morphTargetDictionary[r];
|
|
4303
|
+
d !== void 0 && (l[r].ms.push(a.morphTargetInfluences), l[r].is.push(d), a.morphTargetInfluences[d] = l[r].applied);
|
|
4304
4304
|
});
|
|
4305
4305
|
}), this.mtAvatar = l, this.poseAvatar = { props: {} }, this.posePropNames.forEach((r) => {
|
|
4306
4306
|
const u = r.split("."), a = this.armature.getObjectByName(u[0]);
|
|
@@ -4398,9 +4398,9 @@ class Be {
|
|
|
4398
4398
|
updatePoseDelta() {
|
|
4399
4399
|
for (const [t, e] of Object.entries(this.poseDelta.props)) {
|
|
4400
4400
|
if (e.x === 0 && e.y === 0 && e.z === 0) continue;
|
|
4401
|
-
|
|
4401
|
+
X.set(e.x, e.y, e.z);
|
|
4402
4402
|
const n = this.poseAvatar.props[t];
|
|
4403
|
-
n.isQuaternion ? (
|
|
4403
|
+
n.isQuaternion ? (K.setFromEuler(X), n.multiply(K)) : n.isVector3 && n.add(X);
|
|
4404
4404
|
}
|
|
4405
4405
|
}
|
|
4406
4406
|
/**
|
|
@@ -4987,10 +4987,10 @@ class Be {
|
|
|
4987
4987
|
if (l.alt.length > 1) {
|
|
4988
4988
|
const u = Math.random();
|
|
4989
4989
|
let a = 0;
|
|
4990
|
-
for (let
|
|
4991
|
-
let
|
|
4992
|
-
if (a +=
|
|
4993
|
-
r = l.alt[
|
|
4990
|
+
for (let d = 0; d < l.alt.length; d++) {
|
|
4991
|
+
let c = this.valueFn(l.alt[d].p);
|
|
4992
|
+
if (a += c === void 0 ? (1 - a) / (l.alt.length - 1 - d) : c, u < a) {
|
|
4993
|
+
r = l.alt[d];
|
|
4994
4994
|
break;
|
|
4995
4995
|
}
|
|
4996
4996
|
}
|
|
@@ -5011,8 +5011,8 @@ class Be {
|
|
|
5011
5011
|
}
|
|
5012
5012
|
s ? o.ts = o.ts.map((r) => h + r * n) : o.ts = o.ts.map((r) => this.animClock + h + r * n), l.vs && l.vs.pose && console.log("Pose being selected from vs.pose:", l.vs.pose, "for avatar body:", this.avatar?.body);
|
|
5013
5013
|
for (let [r, u] of Object.entries(l.vs)) {
|
|
5014
|
-
const a = this.getBaselineValue(r),
|
|
5015
|
-
r === "eyesRotateY" ? (o.vs.eyeLookOutLeft = [null, ...
|
|
5014
|
+
const a = this.getBaselineValue(r), d = u.map((c) => (c = this.valueFn(c), c === null ? null : typeof c == "function" ? c : typeof c == "string" || c instanceof String ? r === "pose" && this.avatar && this.avatar.body === "M" && (c === "hip" || c === "side") ? (console.log("Intercepting pose", c, "in animation factory, overriding to wide for male avatar"), "wide") : c.slice() : Array.isArray(c) ? r === "gesture" ? c.slice() : (a === void 0 ? 0 : a) + i * this.gaussianRandom(...c) : typeof c == "boolean" ? c : c instanceof Object && c.constructor === Object ? Object.assign({}, c) : (a === void 0 ? 0 : a) + i * c));
|
|
5015
|
+
r === "eyesRotateY" ? (o.vs.eyeLookOutLeft = [null, ...d.map((c) => c > 0 ? c : 0)], o.vs.eyeLookInLeft = [null, ...d.map((c) => c > 0 ? 0 : -c)], o.vs.eyeLookOutRight = [null, ...d.map((c) => c > 0 ? 0 : -c)], o.vs.eyeLookInRight = [null, ...d.map((c) => c > 0 ? c : 0)]) : r === "eyesRotateX" ? (o.vs.eyesLookDown = [null, ...d.map((c) => c > 0 ? c : 0)], o.vs.eyesLookUp = [null, ...d.map((c) => c > 0 ? 0 : -c)]) : o.vs[r] = [null, ...d];
|
|
5016
5016
|
}
|
|
5017
5017
|
for (let r of Object.keys(o.vs))
|
|
5018
5018
|
for (; o.vs[r].length <= o.ts.length; ) o.vs[r].push(o.vs[r][o.vs[r].length - 1]);
|
|
@@ -5099,20 +5099,20 @@ class Be {
|
|
|
5099
5099
|
const a = this.animQueue[n];
|
|
5100
5100
|
if (!(!a || !a.ts || !a.ts.length || this.animClock < a.ts[0])) {
|
|
5101
5101
|
for (i = a.ndx || 0, o = a.ts.length; i < o && !(this.animClock < a.ts[i]); i++)
|
|
5102
|
-
for (let [
|
|
5103
|
-
if (this.mtAvatar.hasOwnProperty(
|
|
5104
|
-
if (
|
|
5105
|
-
const g = this.mtAvatar[
|
|
5106
|
-
if (
|
|
5107
|
-
g.newvalue =
|
|
5102
|
+
for (let [d, c] of Object.entries(a.vs))
|
|
5103
|
+
if (this.mtAvatar.hasOwnProperty(d)) {
|
|
5104
|
+
if (c[i + 1] === null) continue;
|
|
5105
|
+
const g = this.mtAvatar[d];
|
|
5106
|
+
if (c[i] === null && (c[i] = g.value), i === o - 1)
|
|
5107
|
+
g.newvalue = c[i];
|
|
5108
5108
|
else {
|
|
5109
|
-
g.newvalue =
|
|
5109
|
+
g.newvalue = c[i + 1];
|
|
5110
5110
|
const b = a.ts[i + 1] - a.ts[i];
|
|
5111
5111
|
let x = 1;
|
|
5112
|
-
b > 1e-4 && (x = (this.animClock - a.ts[i]) / b), x < 1 && (g.easing && (x = g.easing(x)), g.newvalue = (1 - x) *
|
|
5112
|
+
b > 1e-4 && (x = (this.animClock - a.ts[i]) / b), x < 1 && (g.easing && (x = g.easing(x)), g.newvalue = (1 - x) * c[i] + x * g.newvalue), g.ref && g.ref !== a.vs && g.ref.hasOwnProperty(d) && delete g.ref[d], g.ref = a.vs;
|
|
5113
5113
|
}
|
|
5114
5114
|
if (l)
|
|
5115
|
-
switch (
|
|
5115
|
+
switch (d) {
|
|
5116
5116
|
case "viseme_aa":
|
|
5117
5117
|
case "viseme_E":
|
|
5118
5118
|
case "viseme_I":
|
|
@@ -5121,11 +5121,11 @@ class Be {
|
|
|
5121
5121
|
g.newvalue *= 1 + l / 255 - 0.5;
|
|
5122
5122
|
}
|
|
5123
5123
|
g.needsUpdate = !0;
|
|
5124
|
-
} else
|
|
5124
|
+
} else d === "eyeContact" && c[i] !== null && h !== !1 ? h = !!c[i] : d === "headMove" && c[i] !== null && r !== !1 ? c[i] === 0 ? r = !1 : (Math.random() < c[i] && (r = !0), c[i] = null) : c[i] !== null && (u.push({ mt: d, val: c[i] }), c[i] = null);
|
|
5125
5125
|
i === o ? (a.hasOwnProperty("mood") && this.setMood(a.mood), a.loop ? (o = this.isSpeaking && (a.template.name === "head" || a.template.name === "eyes") ? 4 : 1, this.animQueue[n] = this.animFactory(a.template, a.loop > 0 ? a.loop - 1 : a.loop, 1, 1 / o)) : (this.animQueue.splice(n--, 1), s--)) : a.ndx = i - 1;
|
|
5126
5126
|
}
|
|
5127
5127
|
}
|
|
5128
|
-
for (let a = 0,
|
|
5128
|
+
for (let a = 0, d = u.length; a < d; a++)
|
|
5129
5129
|
switch (i = u[a].val, u[a].mt) {
|
|
5130
5130
|
case "speak":
|
|
5131
5131
|
this.speakText(i);
|
|
@@ -5143,8 +5143,8 @@ class Be {
|
|
|
5143
5143
|
i && typeof i == "function" && i();
|
|
5144
5144
|
break;
|
|
5145
5145
|
case "moveto":
|
|
5146
|
-
Object.entries(i.props).forEach((
|
|
5147
|
-
|
|
5146
|
+
Object.entries(i.props).forEach((c) => {
|
|
5147
|
+
c[1] ? this.poseTarget.props[c[0]].copy(c[1]) : this.poseTarget.props[c[0]].copy(this.getPoseTemplateProp(c[0])), this.poseTarget.props[c[0]].t = this.animClock, this.poseTarget.props[c[0]].d = c[1] && c[1].d ? c[1].d : c.duration || 2e3;
|
|
5148
5148
|
});
|
|
5149
5149
|
break;
|
|
5150
5150
|
case "handLeft":
|
|
@@ -5172,7 +5172,7 @@ class Be {
|
|
|
5172
5172
|
}, i.x ? new f.Vector3(i.x, i.y, i.z) : null, !0, i.d);
|
|
5173
5173
|
break;
|
|
5174
5174
|
}
|
|
5175
|
-
if ((h || r) && (
|
|
5175
|
+
if ((h || r) && (X.setFromQuaternion(this.poseAvatar.props["Head.quaternion"]), X.x = Math.max(-0.9, Math.min(0.9, 2 * X.x - 0.5)), X.y = Math.max(-0.9, Math.min(0.9, -2.5 * X.y)), h ? (Object.assign(this.mtAvatar.eyesLookDown, { system: X.x < 0 ? -X.x : 0, needsUpdate: !0 }), Object.assign(this.mtAvatar.eyesLookUp, { system: X.x < 0 ? 0 : X.x, needsUpdate: !0 }), Object.assign(this.mtAvatar.eyeLookInLeft, { system: X.y < 0 ? -X.y : 0, needsUpdate: !0 }), Object.assign(this.mtAvatar.eyeLookOutLeft, { system: X.y < 0 ? 0 : X.y, needsUpdate: !0 }), Object.assign(this.mtAvatar.eyeLookInRight, { system: X.y < 0 ? 0 : X.y, needsUpdate: !0 }), Object.assign(this.mtAvatar.eyeLookOutRight, { system: X.y < 0 ? -X.y : 0, needsUpdate: !0 }), r && (n = -this.mtAvatar.bodyRotateY.value, i = this.gaussianRandom(-0.2, 0.2), this.animQueue.push(this.animFactory({
|
|
5176
5176
|
name: "headmove",
|
|
5177
5177
|
dt: [[1e3, 2e3], [1e3, 2e3, 1, 2], [1e3, 2e3], [1e3, 2e3, 1, 2]],
|
|
5178
5178
|
vs: {
|
|
@@ -5193,13 +5193,13 @@ 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(ve), ve.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 -= (ve.x + Re.x) / 4, this.objectHips.position.z -= (ve.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 f.Spherical().setFromVector3(this.cameraStart),
|
|
5202
|
-
a.phi += this.easing(this.cameraClock / 1e3) * (
|
|
5201
|
+
let a = new f.Spherical().setFromVector3(this.cameraStart), d = new f.Spherical().setFromVector3(this.cameraEnd);
|
|
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();
|
|
5205
5205
|
}
|
|
@@ -5261,17 +5261,17 @@ class Be {
|
|
|
5261
5261
|
speakText(t, e = null, n = null, i = null) {
|
|
5262
5262
|
e = e || {};
|
|
5263
5263
|
const s = /[!\.\?\n\p{Extended_Pictographic}]/ug, o = /[ ]/ug, l = /[\p{L}\p{N},\.\p{Quotation_Mark}!€\$\+\p{Dash_Punctuation}%&\?]/ug, h = /[\p{Extended_Pictographic}]/ug, r = e.lipsyncLang || this.avatar.lipsyncLang || this.opt.lipsyncLang;
|
|
5264
|
-
let u = "", a = "",
|
|
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 S = x === b.length - 1, V = b[x].match(l);
|
|
5268
5268
|
let p = b[x].match(s);
|
|
5269
|
-
const
|
|
5270
|
-
if (p && !
|
|
5271
|
-
mark:
|
|
5269
|
+
const P = b[x].match(h), C = b[x].match(o);
|
|
5270
|
+
if (p && !S && !P && b[x + 1].match(s) && (p = !1), n && (u += b[x]), V && (!i || i.every((y) => x < y[0] || x > y[1])) && (a += b[x]), (C || p || S) && (a.length && (a = this.lipsyncPreProcessText(a, r), a.length && c.push({
|
|
5271
|
+
mark: d,
|
|
5272
5272
|
word: a
|
|
5273
5273
|
})), u.length && (g.push({
|
|
5274
|
-
mark:
|
|
5274
|
+
mark: d,
|
|
5275
5275
|
template: { name: "subtitles" },
|
|
5276
5276
|
ts: [0],
|
|
5277
5277
|
vs: {
|
|
@@ -5280,27 +5280,27 @@ class Be {
|
|
|
5280
5280
|
}), u = ""), a.length)) {
|
|
5281
5281
|
const y = this.lipsyncWordsToVisemes(a, r);
|
|
5282
5282
|
if (y && y.visemes && y.visemes.length) {
|
|
5283
|
-
const
|
|
5284
|
-
for (let
|
|
5283
|
+
const I = y.times[y.visemes.length - 1] + y.durations[y.visemes.length - 1];
|
|
5284
|
+
for (let z = 0; z < y.visemes.length; z++)
|
|
5285
5285
|
g.push({
|
|
5286
|
-
mark:
|
|
5286
|
+
mark: d,
|
|
5287
5287
|
template: { name: "viseme" },
|
|
5288
|
-
ts: [(y.times[
|
|
5288
|
+
ts: [(y.times[z] - 0.6) / I, (y.times[z] + 0.5) / I, (y.times[z] + y.durations[z] + 0.5) / I],
|
|
5289
5289
|
vs: {
|
|
5290
|
-
["viseme_" + y.visemes[
|
|
5290
|
+
["viseme_" + y.visemes[z]]: [null, y.visemes[z] === "PP" || y.visemes[z] === "FF" ? 0.9 : 0.6, 0]
|
|
5291
5291
|
}
|
|
5292
5292
|
});
|
|
5293
5293
|
}
|
|
5294
|
-
a = "",
|
|
5294
|
+
a = "", d++;
|
|
5295
5295
|
}
|
|
5296
|
-
if (p ||
|
|
5297
|
-
if (
|
|
5296
|
+
if (p || S) {
|
|
5297
|
+
if (c.length || S && g.length) {
|
|
5298
5298
|
const y = {
|
|
5299
5299
|
anim: g
|
|
5300
5300
|
};
|
|
5301
|
-
n && (y.onSubtitles = n),
|
|
5301
|
+
n && (y.onSubtitles = n), c.length && !e.avatarMute && (y.text = c, e.avatarMood && (y.mood = e.avatarMood), e.ttsLang && (y.lang = e.ttsLang), e.ttsVoice && (y.voice = e.ttsVoice), e.ttsRate && (y.rate = e.ttsRate), e.ttsVoice && (y.pitch = e.ttsPitch), e.ttsVolume && (y.volume = e.ttsVolume)), this.speechQueue.push(y), c = [], a = "", d = 0, g = [];
|
|
5302
5302
|
}
|
|
5303
|
-
if (
|
|
5303
|
+
if (P) {
|
|
5304
5304
|
let y = this.animEmojis[b[x]];
|
|
5305
5305
|
y && y.link && (y = this.animEmojis[y.link]), y && this.speechQueue.push({ emoji: y });
|
|
5306
5306
|
}
|
|
@@ -5392,18 +5392,18 @@ class Be {
|
|
|
5392
5392
|
subtitles: [" " + h]
|
|
5393
5393
|
}
|
|
5394
5394
|
}), !t.visemes)) {
|
|
5395
|
-
const a = this.lipsyncPreProcessText(h, i),
|
|
5396
|
-
if (
|
|
5397
|
-
const
|
|
5395
|
+
const a = this.lipsyncPreProcessText(h, i), d = this.lipsyncWordsToVisemes(a, i);
|
|
5396
|
+
if (d && d.visemes && d.visemes.length) {
|
|
5397
|
+
const c = d.times[d.visemes.length - 1] + d.durations[d.visemes.length - 1], g = Math.min(u, Math.max(0, u - d.visemes.length * 150));
|
|
5398
5398
|
let b = 0.6 + this.convertRange(g, [0, u], [0, 0.4]);
|
|
5399
|
-
if (u = Math.min(u,
|
|
5400
|
-
for (let x = 0; x <
|
|
5401
|
-
const
|
|
5399
|
+
if (u = Math.min(u, d.visemes.length * 200), c > 0)
|
|
5400
|
+
for (let x = 0; x < d.visemes.length; x++) {
|
|
5401
|
+
const S = r + d.times[x] / c * u, V = d.durations[x] / c * u;
|
|
5402
5402
|
o.push({
|
|
5403
5403
|
template: { name: "viseme" },
|
|
5404
|
-
ts: [
|
|
5404
|
+
ts: [S - Math.min(60, 2 * V / 3), S + Math.min(25, V / 2), S + V + Math.min(60, V / 2)],
|
|
5405
5405
|
vs: {
|
|
5406
|
-
["viseme_" +
|
|
5406
|
+
["viseme_" + d.visemes[x]]: [null, d.visemes[x] === "PP" || d.visemes[x] === "FF" ? 0.9 : b, 0]
|
|
5407
5407
|
}
|
|
5408
5408
|
});
|
|
5409
5409
|
}
|
|
@@ -5483,34 +5483,34 @@ class Be {
|
|
|
5483
5483
|
s.lang = o, s.rate = Math.max(0.1, Math.min(10, l)), s.pitch = Math.max(0, Math.min(2, 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((P) => P.name.includes(a) || P.lang === o);
|
|
5487
5487
|
p && (s.voice = p);
|
|
5488
5488
|
}
|
|
5489
|
-
const
|
|
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);
|
|
5490
5490
|
console.log("Browser TTS Lip-sync Debug:", {
|
|
5491
5491
|
text: i,
|
|
5492
5492
|
lipsyncLang: g,
|
|
5493
5493
|
processedText: b,
|
|
5494
5494
|
lipsyncData: x,
|
|
5495
5495
|
hasVisemes: x && x.visemes && x.visemes.length > 0,
|
|
5496
|
-
estimatedDuration:
|
|
5496
|
+
estimatedDuration: d
|
|
5497
5497
|
});
|
|
5498
|
-
const
|
|
5498
|
+
const S = [];
|
|
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 P = 0; P < x.visemes.length; P++) {
|
|
5502
|
+
const C = x.visemes[P], y = x.times[P] / p, I = x.durations[P] / p, z = y * d, A = I * d;
|
|
5503
|
+
S.push({
|
|
5504
5504
|
template: { name: "viseme" },
|
|
5505
|
-
ts: [
|
|
5505
|
+
ts: [z - Math.min(60, 2 * A / 3), z + Math.min(25, A / 2), z + A + Math.min(60, A / 2)],
|
|
5506
5506
|
vs: {
|
|
5507
|
-
["viseme_" +
|
|
5507
|
+
["viseme_" + C]: [null, C === "PP" || C === "FF" ? 0.9 : 0.6, 0]
|
|
5508
5508
|
}
|
|
5509
5509
|
});
|
|
5510
5510
|
}
|
|
5511
5511
|
}
|
|
5512
|
-
const
|
|
5513
|
-
this.audioPlaylist.push({ anim:
|
|
5512
|
+
const V = [...t.anim, ...S];
|
|
5513
|
+
this.audioPlaylist.push({ anim: V, 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);
|
|
@@ -5522,7 +5522,7 @@ class Be {
|
|
|
5522
5522
|
* @param {Object} line Speech line object
|
|
5523
5523
|
*/
|
|
5524
5524
|
async synthesizeWithElevenLabsTTS(t) {
|
|
5525
|
-
const e = t.text.map((
|
|
5525
|
+
const e = t.text.map((d) => d.word).join(" "), n = t.voice || this.avatar.ttsVoice || this.opt.ttsVoice || "21m00Tcm4TlvDq8ikWAM", i = {
|
|
5526
5526
|
text: e,
|
|
5527
5527
|
model_id: "eleven_monolingual_v1",
|
|
5528
5528
|
voice_settings: {
|
|
@@ -5552,18 +5552,18 @@ class Be {
|
|
|
5552
5552
|
lipsyncKeys: this.lipsync ? Object.keys(this.lipsync) : [],
|
|
5553
5553
|
lipsyncLang: h
|
|
5554
5554
|
});
|
|
5555
|
-
const
|
|
5555
|
+
const d = this.lipsyncPreProcessText(e, h), c = this.lipsyncWordsToVisemes(d, h);
|
|
5556
5556
|
if (console.log("Lip-sync data:", {
|
|
5557
|
-
processedText:
|
|
5558
|
-
lipsyncData:
|
|
5559
|
-
hasVisemes:
|
|
5560
|
-
}),
|
|
5557
|
+
processedText: d,
|
|
5558
|
+
lipsyncData: c,
|
|
5559
|
+
hasVisemes: c && c.visemes && c.visemes.length > 0
|
|
5560
|
+
}), c && c.visemes && c.visemes.length > 0)
|
|
5561
5561
|
r = {
|
|
5562
|
-
visemes:
|
|
5562
|
+
visemes: c.visemes.map((g, b) => ({
|
|
5563
5563
|
viseme: g,
|
|
5564
|
-
startTime: b * l.duration /
|
|
5565
|
-
endTime: (b + 1) * l.duration /
|
|
5566
|
-
duration: l.duration /
|
|
5564
|
+
startTime: b * l.duration / c.visemes.length,
|
|
5565
|
+
endTime: (b + 1) * l.duration / c.visemes.length,
|
|
5566
|
+
duration: l.duration / c.visemes.length,
|
|
5567
5567
|
intensity: 0.7
|
|
5568
5568
|
})),
|
|
5569
5569
|
words: [],
|
|
@@ -5572,13 +5572,13 @@ class Be {
|
|
|
5572
5572
|
};
|
|
5573
5573
|
else
|
|
5574
5574
|
throw new Error("No visemes generated from text");
|
|
5575
|
-
} catch (
|
|
5576
|
-
console.error("Text-based lip-sync failed, using fallback:",
|
|
5577
|
-
const
|
|
5578
|
-
for (const b of
|
|
5575
|
+
} catch (d) {
|
|
5576
|
+
console.error("Text-based lip-sync failed, using fallback:", d);
|
|
5577
|
+
const c = e.toLowerCase().split(/\s+/), g = [];
|
|
5578
|
+
for (const b of c)
|
|
5579
5579
|
for (const x of b) {
|
|
5580
|
-
let
|
|
5581
|
-
"aeiou".includes(x) ?
|
|
5580
|
+
let S = "aa";
|
|
5581
|
+
"aeiou".includes(x) ? S = "aa" : "bp".includes(x) ? S = "PP" : "fv".includes(x) ? S = "FF" : "st".includes(x) ? S = "SS" : "dln".includes(x) ? S = "DD" : "kg".includes(x) ? S = "kk" : "rw".includes(x) && (S = "RR"), g.push(S);
|
|
5582
5582
|
}
|
|
5583
5583
|
r = {
|
|
5584
5584
|
visemes: g.map((b, x) => ({
|
|
@@ -5608,13 +5608,13 @@ class Be {
|
|
|
5608
5608
|
const u = [];
|
|
5609
5609
|
if (r.visemes && r.visemes.length > 0) {
|
|
5610
5610
|
console.log("ElevenLabs: Generating lip-sync animation from", r.visemes.length, "visemes");
|
|
5611
|
-
for (let
|
|
5612
|
-
const
|
|
5611
|
+
for (let d = 0; d < r.visemes.length; d++) {
|
|
5612
|
+
const c = r.visemes[d], g = c.startTime * 1e3, b = c.duration * 1e3, x = c.intensity;
|
|
5613
5613
|
u.push({
|
|
5614
5614
|
template: { name: "viseme" },
|
|
5615
5615
|
ts: [g - Math.min(60, 2 * b / 3), g + Math.min(25, b / 2), g + b + Math.min(60, b / 2)],
|
|
5616
5616
|
vs: {
|
|
5617
|
-
["viseme_" +
|
|
5617
|
+
["viseme_" + c.viseme]: [null, x, 0]
|
|
5618
5618
|
}
|
|
5619
5619
|
});
|
|
5620
5620
|
}
|
|
@@ -5629,7 +5629,7 @@ class Be {
|
|
|
5629
5629
|
* @param {Object} line Speech line object
|
|
5630
5630
|
*/
|
|
5631
5631
|
async synthesizeWithDeepgramTTS(t) {
|
|
5632
|
-
const e = t.text.map((
|
|
5632
|
+
const e = t.text.map((d) => d.word).join(" "), n = t.voice || this.avatar.ttsVoice || this.opt.ttsVoice || "aura-2-thalia-en", i = `${this.opt.ttsEndpoint}?model=${n}`, s = await fetch(i, {
|
|
5633
5633
|
method: "POST",
|
|
5634
5634
|
headers: {
|
|
5635
5635
|
Authorization: `Token ${this.opt.ttsApikey}`,
|
|
@@ -5650,18 +5650,18 @@ class Be {
|
|
|
5650
5650
|
lipsyncKeys: this.lipsync ? Object.keys(this.lipsync) : [],
|
|
5651
5651
|
lipsyncLang: h
|
|
5652
5652
|
});
|
|
5653
|
-
const
|
|
5653
|
+
const d = this.lipsyncPreProcessText(e, h), c = this.lipsyncWordsToVisemes(d, h);
|
|
5654
5654
|
if (console.log("Lip-sync data:", {
|
|
5655
|
-
processedText:
|
|
5656
|
-
lipsyncData:
|
|
5657
|
-
hasVisemes:
|
|
5658
|
-
}),
|
|
5655
|
+
processedText: d,
|
|
5656
|
+
lipsyncData: c,
|
|
5657
|
+
hasVisemes: c && c.visemes && c.visemes.length > 0
|
|
5658
|
+
}), c && c.visemes && c.visemes.length > 0)
|
|
5659
5659
|
r = {
|
|
5660
|
-
visemes:
|
|
5660
|
+
visemes: c.visemes.map((g, b) => ({
|
|
5661
5661
|
viseme: g,
|
|
5662
|
-
startTime: b * l.duration /
|
|
5663
|
-
endTime: (b + 1) * l.duration /
|
|
5664
|
-
duration: l.duration /
|
|
5662
|
+
startTime: b * l.duration / c.visemes.length,
|
|
5663
|
+
endTime: (b + 1) * l.duration / c.visemes.length,
|
|
5664
|
+
duration: l.duration / c.visemes.length,
|
|
5665
5665
|
intensity: 0.7
|
|
5666
5666
|
})),
|
|
5667
5667
|
words: [],
|
|
@@ -5670,13 +5670,13 @@ class Be {
|
|
|
5670
5670
|
};
|
|
5671
5671
|
else
|
|
5672
5672
|
throw new Error("No visemes generated from text");
|
|
5673
|
-
} catch (
|
|
5674
|
-
console.error("Text-based lip-sync failed, using fallback:",
|
|
5675
|
-
const
|
|
5676
|
-
for (const b of
|
|
5673
|
+
} catch (d) {
|
|
5674
|
+
console.error("Text-based lip-sync failed, using fallback:", d);
|
|
5675
|
+
const c = e.toLowerCase().split(/\s+/), g = [];
|
|
5676
|
+
for (const b of c)
|
|
5677
5677
|
for (const x of b) {
|
|
5678
|
-
let
|
|
5679
|
-
"aeiou".includes(x) ?
|
|
5678
|
+
let S = "aa";
|
|
5679
|
+
"aeiou".includes(x) ? S = "aa" : "bp".includes(x) ? S = "PP" : "fv".includes(x) ? S = "FF" : "st".includes(x) ? S = "SS" : "dln".includes(x) ? S = "DD" : "kg".includes(x) ? S = "kk" : "rw".includes(x) && (S = "RR"), g.push(S);
|
|
5680
5680
|
}
|
|
5681
5681
|
r = {
|
|
5682
5682
|
visemes: g.map((b, x) => ({
|
|
@@ -5706,13 +5706,13 @@ class Be {
|
|
|
5706
5706
|
const u = [];
|
|
5707
5707
|
if (r.visemes && r.visemes.length > 0) {
|
|
5708
5708
|
console.log("Deepgram: Generating lip-sync animation from", r.visemes.length, "visemes");
|
|
5709
|
-
for (let
|
|
5710
|
-
const
|
|
5709
|
+
for (let d = 0; d < r.visemes.length; d++) {
|
|
5710
|
+
const c = r.visemes[d], g = c.startTime * 1e3, b = c.duration * 1e3, x = c.intensity;
|
|
5711
5711
|
u.push({
|
|
5712
5712
|
template: { name: "viseme" },
|
|
5713
5713
|
ts: [g - Math.min(60, 2 * b / 3), g + Math.min(25, b / 2), g + b + Math.min(60, b / 2)],
|
|
5714
5714
|
vs: {
|
|
5715
|
-
["viseme_" +
|
|
5715
|
+
["viseme_" + c.viseme]: [null, x, 0]
|
|
5716
5716
|
}
|
|
5717
5717
|
});
|
|
5718
5718
|
}
|
|
@@ -5759,12 +5759,12 @@ class Be {
|
|
|
5759
5759
|
});
|
|
5760
5760
|
const r = [];
|
|
5761
5761
|
for (let a = 0; a < h.visemes.length; a++) {
|
|
5762
|
-
const
|
|
5762
|
+
const d = h.visemes[a], c = d.startTime * 1e3, g = d.duration * 1e3, b = d.intensity;
|
|
5763
5763
|
r.push({
|
|
5764
5764
|
template: { name: "viseme" },
|
|
5765
|
-
ts: [
|
|
5765
|
+
ts: [c - Math.min(60, 2 * g / 3), c + Math.min(25, g / 2), c + g + Math.min(60, g / 2)],
|
|
5766
5766
|
vs: {
|
|
5767
|
-
["viseme_" +
|
|
5767
|
+
["viseme_" + d.viseme]: [null, b, 0]
|
|
5768
5768
|
}
|
|
5769
5769
|
});
|
|
5770
5770
|
}
|
|
@@ -5810,25 +5810,25 @@ class Be {
|
|
|
5810
5810
|
this.speakWithHands();
|
|
5811
5811
|
const h = [0];
|
|
5812
5812
|
let r = 0;
|
|
5813
|
-
t.text.forEach((
|
|
5814
|
-
if (
|
|
5813
|
+
t.text.forEach((d, c) => {
|
|
5814
|
+
if (c > 0) {
|
|
5815
5815
|
let g = h[h.length - 1];
|
|
5816
|
-
s.timepoints[r] && (g = s.timepoints[r].timeSeconds * 1e3, s.timepoints[r].markName === "" +
|
|
5816
|
+
s.timepoints[r] && (g = s.timepoints[r].timeSeconds * 1e3, s.timepoints[r].markName === "" + d.mark && r++), h.push(g);
|
|
5817
5817
|
}
|
|
5818
5818
|
});
|
|
5819
5819
|
const u = [{ mark: 0, time: 0 }];
|
|
5820
|
-
h.forEach((
|
|
5821
|
-
if (
|
|
5822
|
-
let g =
|
|
5823
|
-
u[
|
|
5820
|
+
h.forEach((d, c) => {
|
|
5821
|
+
if (c > 0) {
|
|
5822
|
+
let g = d - h[c - 1];
|
|
5823
|
+
u[c - 1].duration = g, u.push({ mark: c, time: d });
|
|
5824
5824
|
}
|
|
5825
5825
|
});
|
|
5826
5826
|
let a = 1e3 * l.duration;
|
|
5827
|
-
a > this.opt.ttsTrimEnd && (a = a - this.opt.ttsTrimEnd), u[u.length - 1].duration = a - u[u.length - 1].time, t.anim.forEach((
|
|
5828
|
-
const
|
|
5829
|
-
if (
|
|
5830
|
-
for (let g = 0; g <
|
|
5831
|
-
|
|
5827
|
+
a > this.opt.ttsTrimEnd && (a = a - this.opt.ttsTrimEnd), u[u.length - 1].duration = a - u[u.length - 1].time, t.anim.forEach((d) => {
|
|
5828
|
+
const c = u[d.mark];
|
|
5829
|
+
if (c)
|
|
5830
|
+
for (let g = 0; g < d.ts.length; g++)
|
|
5831
|
+
d.ts[g] = c.time + d.ts[g] * c.duration + this.opt.ttsTrimStart;
|
|
5832
5832
|
}), this.audioPlaylist.push({ anim: t.anim, audio: l }), this.onSubtitles = t.onSubtitles || null, this.resetLips(), t.mood && this.setMood(t.mood), this.playAudio();
|
|
5833
5833
|
} else
|
|
5834
5834
|
this.startSpeaking(!0);
|
|
@@ -6047,15 +6047,15 @@ class Be {
|
|
|
6047
6047
|
const l = this.streamLipsyncLang || this.avatar.lipsyncLang || this.opt.lipsyncLang, h = this.lipsyncPreProcessText(i, l), r = this.lipsyncWordsToVisemes(h, l);
|
|
6048
6048
|
if (r && r.visemes && r.visemes.length) {
|
|
6049
6049
|
const u = r.times[r.visemes.length - 1] + r.durations[r.visemes.length - 1], a = Math.min(o, Math.max(0, o - r.visemes.length * 150));
|
|
6050
|
-
let
|
|
6050
|
+
let d = 0.6 + this.convertRange(a, [0, o], [0, 0.4]);
|
|
6051
6051
|
if (o = Math.min(o, r.visemes.length * 200), u > 0)
|
|
6052
|
-
for (let
|
|
6053
|
-
const g = e + s + r.times[
|
|
6052
|
+
for (let c = 0; c < r.visemes.length; c++) {
|
|
6053
|
+
const g = e + s + r.times[c] / u * o, b = r.durations[c] / u * o;
|
|
6054
6054
|
this.animQueue.push({
|
|
6055
6055
|
template: { name: "viseme" },
|
|
6056
6056
|
ts: [g - Math.min(60, 2 * b / 3), g + Math.min(25, b / 2), g + b + Math.min(60, b / 2)],
|
|
6057
6057
|
vs: {
|
|
6058
|
-
["viseme_" + r.visemes[
|
|
6058
|
+
["viseme_" + r.visemes[c]]: [null, r.visemes[c] === "PP" || r.visemes[c] === "FF" ? 0.9 : d, 0]
|
|
6059
6059
|
}
|
|
6060
6060
|
});
|
|
6061
6061
|
}
|
|
@@ -6159,22 +6159,22 @@ class Be {
|
|
|
6159
6159
|
this.lookAt(null, null, t);
|
|
6160
6160
|
return;
|
|
6161
6161
|
}
|
|
6162
|
-
this.objectLeftEye.updateMatrixWorld(!0), this.objectRightEye.updateMatrixWorld(!0), ve.setFromMatrixPosition(this.objectLeftEye.matrixWorld), Re.setFromMatrixPosition(this.objectRightEye.matrixWorld), ve.add(Re).divideScalar(2),
|
|
6162
|
+
this.objectLeftEye.updateMatrixWorld(!0), this.objectRightEye.updateMatrixWorld(!0), ve.setFromMatrixPosition(this.objectLeftEye.matrixWorld), Re.setFromMatrixPosition(this.objectRightEye.matrixWorld), ve.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
6163
|
const n = new f.Vector3().subVectors(e, ve).normalize(), i = Math.atan2(n.x, n.z), s = Math.asin(-n.y);
|
|
6164
|
-
|
|
6165
|
-
const l = new f.Quaternion().setFromEuler(
|
|
6166
|
-
|
|
6167
|
-
let r =
|
|
6164
|
+
X.set(s, i, 0, "YXZ");
|
|
6165
|
+
const l = new f.Quaternion().setFromEuler(X), h = new f.Quaternion().copy(l).multiply(K.clone().invert());
|
|
6166
|
+
X.setFromQuaternion(h, "YXZ");
|
|
6167
|
+
let r = X.x / (40 / 24) + 0.2, u = X.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((S) => S.template.name === "lookat");
|
|
6170
6170
|
b !== -1 && this.animQueue.splice(b, 1);
|
|
6171
6171
|
const x = {
|
|
6172
6172
|
name: "lookat",
|
|
6173
6173
|
dt: [750, t],
|
|
6174
6174
|
vs: {
|
|
6175
|
-
bodyRotateX: [a +
|
|
6176
|
-
bodyRotateY: [
|
|
6177
|
-
eyesRotateX: [-3 *
|
|
6175
|
+
bodyRotateX: [a + c],
|
|
6176
|
+
bodyRotateY: [d + g],
|
|
6177
|
+
eyesRotateX: [-3 * c + 0.1],
|
|
6178
6178
|
eyesRotateY: [-5 * g],
|
|
6179
6179
|
browInnerUp: [[0, 0.7]],
|
|
6180
6180
|
mouthLeft: [[0, 0.7]],
|
|
@@ -6199,20 +6199,20 @@ class Be {
|
|
|
6199
6199
|
const s = new f.Vector3().setFromMatrixPosition(this.objectLeftEye.matrixWorld), o = new f.Vector3().setFromMatrixPosition(this.objectRightEye.matrixWorld), l = new f.Vector3().addVectors(s, o).divideScalar(2);
|
|
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 =
|
|
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"]), X.setFromQuaternion(K);
|
|
6203
|
+
let u = X.x / (40 / 24), a = X.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, S = this.convertRange(t, [h - g, h + g], [-0.8, 0.8]) - a + c;
|
|
6204
|
+
x = Math.min(0.6, Math.max(-0.3, x)), S = Math.min(0.8, Math.max(-0.8, S));
|
|
6205
|
+
let V = (Math.random() - 0.5) / 4, p = (Math.random() - 0.5) / 4;
|
|
6206
6206
|
if (n) {
|
|
6207
|
-
let
|
|
6208
|
-
|
|
6209
|
-
const
|
|
6207
|
+
let P = this.animQueue.findIndex((y) => y.template.name === "lookat");
|
|
6208
|
+
P !== -1 && this.animQueue.splice(P, 1);
|
|
6209
|
+
const C = {
|
|
6210
6210
|
name: "lookat",
|
|
6211
6211
|
dt: [750, n],
|
|
6212
6212
|
vs: {
|
|
6213
|
-
bodyRotateX: [x +
|
|
6214
|
-
bodyRotateY: [
|
|
6215
|
-
eyesRotateX: [-3 *
|
|
6213
|
+
bodyRotateX: [x + V],
|
|
6214
|
+
bodyRotateY: [S + p],
|
|
6215
|
+
eyesRotateX: [-3 * V + 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(C));
|
|
6225
6225
|
}
|
|
6226
6226
|
}
|
|
6227
6227
|
/**
|
|
@@ -6408,51 +6408,74 @@ class Be {
|
|
|
6408
6408
|
}
|
|
6409
6409
|
let r = !1;
|
|
6410
6410
|
try {
|
|
6411
|
-
const
|
|
6412
|
-
if (r =
|
|
6413
|
-
console.error(`FBX file not found at ${t}. Status: ${
|
|
6411
|
+
const d = await fetch(t, { method: "HEAD" });
|
|
6412
|
+
if (r = d.ok, !r) {
|
|
6413
|
+
console.error(`FBX file not found at ${t}. Status: ${d.status}`), console.error("Please check:"), console.error("1. File path is correct (note: path is case-sensitive)"), console.error("2. File exists in your public folder"), console.error("3. File is accessible (not blocked by server)");
|
|
6414
6414
|
return;
|
|
6415
6415
|
}
|
|
6416
|
-
} catch (
|
|
6417
|
-
console.warn(`Could not verify file existence for ${t}, attempting to load anyway:`,
|
|
6416
|
+
} catch (d) {
|
|
6417
|
+
console.warn(`Could not verify file existence for ${t}, attempting to load anyway:`, d);
|
|
6418
6418
|
}
|
|
6419
6419
|
const u = new De();
|
|
6420
6420
|
let a;
|
|
6421
6421
|
try {
|
|
6422
6422
|
a = await u.loadAsync(t, e);
|
|
6423
|
-
} catch (
|
|
6424
|
-
console.error(`Failed to load FBX animation from ${t}:`,
|
|
6425
|
-
message:
|
|
6423
|
+
} catch (d) {
|
|
6424
|
+
console.error(`Failed to load FBX animation from ${t}:`, d), console.error("Error details:", {
|
|
6425
|
+
message: d.message,
|
|
6426
6426
|
url: t,
|
|
6427
6427
|
suggestion: "Make sure the file is a valid FBX file and the path is correct"
|
|
6428
|
-
}),
|
|
6428
|
+
}), d.message && d.message.includes("version number") && (console.error("FBX Loader Error: Cannot find version number"), console.error("This error usually means:"), console.error("1. The file is not a valid FBX file (might be GLB, corrupted, or wrong format)"), console.error("2. The file might be corrupted"), console.error("3. The file path might be incorrect"), console.error("4. The server returned an HTML error page instead of the FBX file"), console.error("5. The file might not exist at that path"), console.error(""), console.error("Solution: Please verify:"), console.error(` - File exists at: ${t}`), console.error(" - File is a valid FBX binary file"), console.error(" - File path matches your public folder structure"), console.error(" - File is not corrupted"));
|
|
6429
6429
|
try {
|
|
6430
|
-
const
|
|
6430
|
+
const c = await fetch(t), g = c.headers.get("content-type"), b = await c.text();
|
|
6431
6431
|
console.error("Response details:", {
|
|
6432
|
-
status:
|
|
6432
|
+
status: c.status,
|
|
6433
6433
|
contentType: g,
|
|
6434
6434
|
firstBytes: b.substring(0, 100),
|
|
6435
6435
|
isHTML: b.trim().startsWith("<!DOCTYPE") || b.trim().startsWith("<html")
|
|
6436
6436
|
}), (b.trim().startsWith("<!DOCTYPE") || b.trim().startsWith("<html")) && console.error("The server returned an HTML page instead of an FBX file. The file path is likely incorrect.");
|
|
6437
|
-
} catch (
|
|
6438
|
-
console.error("Could not fetch file for debugging:",
|
|
6437
|
+
} catch (c) {
|
|
6438
|
+
console.error("Could not fetch file for debugging:", c);
|
|
6439
6439
|
}
|
|
6440
6440
|
return;
|
|
6441
6441
|
}
|
|
6442
6442
|
if (a && a.animations && a.animations[i]) {
|
|
6443
|
-
let
|
|
6444
|
-
const
|
|
6443
|
+
let d = a.animations[i];
|
|
6444
|
+
const c = /* @__PURE__ */ new Set();
|
|
6445
6445
|
this.armature && this.armature.traverse((I) => {
|
|
6446
|
-
(I.isBone || I.type === "Bone") &&
|
|
6446
|
+
(I.isBone || I.type === "Bone") && c.add(I.name);
|
|
6447
6447
|
});
|
|
6448
6448
|
const g = /* @__PURE__ */ new Map(), b = (I) => {
|
|
6449
|
-
if (
|
|
6449
|
+
if (c.has(I))
|
|
6450
6450
|
return I;
|
|
6451
|
-
let
|
|
6452
|
-
if (
|
|
6453
|
-
return
|
|
6454
|
-
const
|
|
6455
|
-
|
|
6451
|
+
let z = I.replace(/^mixamorig/i, "").replace(/^CC_Base_/i, "").replace(/^RPM_/i, "");
|
|
6452
|
+
if (c.has(z))
|
|
6453
|
+
return z;
|
|
6454
|
+
const A = z.toLowerCase();
|
|
6455
|
+
if (A.includes("left") && A.includes("arm")) {
|
|
6456
|
+
if (A.includes("fore") || A.includes("lower")) {
|
|
6457
|
+
if (c.has("LeftForeArm")) return "LeftForeArm";
|
|
6458
|
+
if (c.has("LeftForearm")) return "LeftForearm";
|
|
6459
|
+
} else if (!A.includes("fore") && !A.includes("hand") && c.has("LeftArm"))
|
|
6460
|
+
return "LeftArm";
|
|
6461
|
+
}
|
|
6462
|
+
if (A.includes("right") && A.includes("arm")) {
|
|
6463
|
+
if (A.includes("fore") || A.includes("lower")) {
|
|
6464
|
+
if (c.has("RightForeArm")) return "RightForeArm";
|
|
6465
|
+
if (c.has("RightForearm")) return "RightForearm";
|
|
6466
|
+
} else if (!A.includes("fore") && !A.includes("hand") && c.has("RightArm"))
|
|
6467
|
+
return "RightArm";
|
|
6468
|
+
}
|
|
6469
|
+
if (A.includes("left") && A.includes("hand") && !A.includes("index") && !A.includes("thumb") && !A.includes("middle") && !A.includes("ring") && !A.includes("pinky") && c.has("LeftHand"))
|
|
6470
|
+
return "LeftHand";
|
|
6471
|
+
if (A.includes("right") && A.includes("hand") && !A.includes("index") && !A.includes("thumb") && !A.includes("middle") && !A.includes("ring") && !A.includes("pinky") && c.has("RightHand"))
|
|
6472
|
+
return "RightHand";
|
|
6473
|
+
if (A.includes("left") && (A.includes("shoulder") || A.includes("clavicle")) && c.has("LeftShoulder"))
|
|
6474
|
+
return "LeftShoulder";
|
|
6475
|
+
if (A.includes("right") && (A.includes("shoulder") || A.includes("clavicle")) && c.has("RightShoulder"))
|
|
6476
|
+
return "RightShoulder";
|
|
6477
|
+
const j = {
|
|
6478
|
+
// Arm bones - exact matches
|
|
6456
6479
|
LeftArm: "LeftArm",
|
|
6457
6480
|
leftArm: "LeftArm",
|
|
6458
6481
|
LEFTARM: "LeftArm",
|
|
@@ -6491,51 +6514,85 @@ class Be {
|
|
|
6491
6514
|
Root: "Hips",
|
|
6492
6515
|
root: "Hips"
|
|
6493
6516
|
};
|
|
6494
|
-
if (
|
|
6495
|
-
const
|
|
6496
|
-
if (
|
|
6497
|
-
return
|
|
6517
|
+
if (j[z]) {
|
|
6518
|
+
const k = j[z];
|
|
6519
|
+
if (c.has(k))
|
|
6520
|
+
return k;
|
|
6521
|
+
}
|
|
6522
|
+
for (const k of c)
|
|
6523
|
+
if (k.toLowerCase() === A)
|
|
6524
|
+
return k;
|
|
6525
|
+
for (const k of c) {
|
|
6526
|
+
const F = k.toLowerCase();
|
|
6527
|
+
if ((A.includes("left") && F.includes("left") || A.includes("right") && F.includes("right")) && (A.includes("arm") && F.includes("arm") && !F.includes("fore") || A.includes("forearm") && F.includes("forearm") || A.includes("hand") && F.includes("hand") && !F.includes("index") && !F.includes("thumb") || A.includes("shoulder") && F.includes("shoulder")))
|
|
6528
|
+
return k;
|
|
6498
6529
|
}
|
|
6499
|
-
for (const w of d)
|
|
6500
|
-
if (w.toLowerCase() === y.toLowerCase())
|
|
6501
|
-
return w;
|
|
6502
6530
|
return null;
|
|
6503
6531
|
}, x = /* @__PURE__ */ new Set();
|
|
6504
|
-
|
|
6505
|
-
const
|
|
6506
|
-
x.add(
|
|
6507
|
-
}), console.log("Ready Player Me FBX bone names:", Array.from(x).sort().join(", ")), console.log("Avatar skeleton bone names:", Array.from(
|
|
6508
|
-
const
|
|
6509
|
-
|
|
6510
|
-
|
|
6511
|
-
|
|
6512
|
-
|
|
6513
|
-
|
|
6532
|
+
d.tracks.forEach((I) => {
|
|
6533
|
+
const z = I.name.split(".");
|
|
6534
|
+
x.add(z[0]);
|
|
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 S = Array.from(x).filter(
|
|
6537
|
+
(I) => I.toLowerCase().includes("arm") || I.toLowerCase().includes("hand") || I.toLowerCase().includes("shoulder")
|
|
6538
|
+
), V = Array.from(c).filter(
|
|
6539
|
+
(I) => I.includes("Arm") || I.includes("Hand") || I.includes("Shoulder")
|
|
6540
|
+
);
|
|
6541
|
+
console.log("FBX arm/hand/shoulder bones:", S.sort().join(", ")), console.log("Avatar arm/hand/shoulder bones:", V.sort().join(", "));
|
|
6542
|
+
const p = [], P = /* @__PURE__ */ new Set();
|
|
6543
|
+
if (d.tracks.forEach((I) => {
|
|
6544
|
+
const A = I.name.replaceAll("mixamorig", "").split("."), j = A[0], k = A[1], F = b(j);
|
|
6545
|
+
if (F && k) {
|
|
6546
|
+
const _ = `${F}.${k}`, B = I.clone();
|
|
6547
|
+
B.name = _;
|
|
6548
|
+
const $ = F.includes("Arm") || F.includes("Hand") || F.includes("Shoulder"), ie = F.includes("Left");
|
|
6549
|
+
if ($ && (k === "quaternion" || k === "rotation") && k === "quaternion" && B.values && B.values.length >= 4) {
|
|
6550
|
+
const oe = B.times.length;
|
|
6551
|
+
for (let le = 0; le < oe; le++) {
|
|
6552
|
+
const Z = le * 4;
|
|
6553
|
+
if (Z + 3 < B.values.length) {
|
|
6554
|
+
let ne = B.values[Z], O = B.values[Z + 1], v = B.values[Z + 2], R = B.values[Z + 3];
|
|
6555
|
+
if (ie && F.includes("ForeArm")) {
|
|
6556
|
+
const H = new f.Quaternion().setFromAxisAngle(new f.Vector3(0, 1, 0), Math.PI), M = new f.Quaternion(ne, O, v, R);
|
|
6557
|
+
M.multiply(H), ne = M.x, O = M.y, v = M.z, R = M.w;
|
|
6558
|
+
}
|
|
6559
|
+
B.values[Z] = ne, B.values[Z + 1] = O, B.values[Z + 2] = v, B.values[Z + 3] = R;
|
|
6560
|
+
}
|
|
6561
|
+
}
|
|
6562
|
+
}
|
|
6563
|
+
p.push(B), j !== F && g.set(j, F);
|
|
6514
6564
|
} else
|
|
6515
|
-
|
|
6516
|
-
}),
|
|
6517
|
-
|
|
6518
|
-
|
|
6519
|
-
|
|
6520
|
-
|
|
6521
|
-
|
|
6565
|
+
P.add(j), (j.toLowerCase().includes("arm") || j.toLowerCase().includes("hand") || j.toLowerCase().includes("shoulder")) && console.warn(`⚠️ Arm bone "${j}" could not be mapped to avatar skeleton`);
|
|
6566
|
+
}), P.size > 0 && console.warn(`⚠️ ${P.size} bone(s) could not be mapped:`, Array.from(P).sort().join(", ")), p.length > 0) {
|
|
6567
|
+
d = new f.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(
|
|
6568
|
+
`✓ Mapped ${g.size} bone(s):`,
|
|
6569
|
+
Array.from(g.entries()).map(([z, A]) => `${z}→${A}`).join(", ")
|
|
6570
|
+
);
|
|
6571
|
+
const I = Array.from(g.values()).filter(
|
|
6572
|
+
(z) => z.includes("Arm") || z.includes("Hand") || z.includes("Shoulder")
|
|
6573
|
+
);
|
|
6574
|
+
I.length > 0 ? console.log(`✓ Arm bones mapped: ${I.join(", ")}`) : console.warn("⚠️ No arm bones were mapped! This may cause arm rigging issues.");
|
|
6575
|
+
} else
|
|
6576
|
+
console.error("❌ No tracks could be mapped! Animation may not work correctly.");
|
|
6577
|
+
const C = {};
|
|
6578
|
+
d.tracks.forEach((I) => {
|
|
6522
6579
|
I.name = I.name.replaceAll("mixamorig", "");
|
|
6523
|
-
const
|
|
6524
|
-
if (
|
|
6525
|
-
for (let
|
|
6526
|
-
I.values[
|
|
6527
|
-
|
|
6528
|
-
} else
|
|
6580
|
+
const z = I.name.split(".");
|
|
6581
|
+
if (z[1] === "position") {
|
|
6582
|
+
for (let A = 0; A < I.values.length; A++)
|
|
6583
|
+
I.values[A] = I.values[A] * s;
|
|
6584
|
+
C[I.name] = new f.Vector3(I.values[0], I.values[1], I.values[2]);
|
|
6585
|
+
} else z[1] === "quaternion" ? C[I.name] = new f.Quaternion(I.values[0], I.values[1], I.values[2], I.values[3]) : z[1] === "rotation" && (C[z[0] + ".quaternion"] = new f.Quaternion().setFromEuler(new f.Euler(I.values[0], I.values[1], I.values[2], "XYZ")).normalize());
|
|
6529
6586
|
});
|
|
6530
|
-
const
|
|
6531
|
-
|
|
6587
|
+
const y = { props: C };
|
|
6588
|
+
C["Hips.position"] && (C["Hips.position"].y < 0.5 ? y.lying = !0 : y.standing = !0), this.animClips.push({
|
|
6532
6589
|
url: t + "-" + i,
|
|
6533
|
-
clip:
|
|
6534
|
-
pose:
|
|
6590
|
+
clip: d,
|
|
6591
|
+
pose: y
|
|
6535
6592
|
}), this.playAnimation(t, e, n, i, s);
|
|
6536
6593
|
} else {
|
|
6537
|
-
const
|
|
6538
|
-
console.error(
|
|
6594
|
+
const d = "Animation " + t + " (ndx=" + i + ") not found";
|
|
6595
|
+
console.error(d), a && a.animations ? console.error(`FBX file loaded but has ${a.animations.length} animation(s), requested index ${i}`) : console.error(a ? "FBX file loaded but contains no animations" : "FBX file failed to load or is invalid");
|
|
6539
6596
|
}
|
|
6540
6597
|
}
|
|
6541
6598
|
}
|
|
@@ -6573,10 +6630,10 @@ class Be {
|
|
|
6573
6630
|
if (h && h.animations && h.animations[i]) {
|
|
6574
6631
|
let r = h.animations[i];
|
|
6575
6632
|
const u = {};
|
|
6576
|
-
r.tracks.forEach((
|
|
6577
|
-
|
|
6578
|
-
const
|
|
6579
|
-
|
|
6633
|
+
r.tracks.forEach((d) => {
|
|
6634
|
+
d.name = d.name.replaceAll("mixamorig", "");
|
|
6635
|
+
const c = d.name.split(".");
|
|
6636
|
+
c[1] === "position" ? u[d.name] = new f.Vector3(d.values[0] * s, d.values[1] * s, d.values[2] * s) : c[1] === "quaternion" ? u[d.name] = new f.Quaternion(d.values[0], d.values[1], d.values[2], d.values[3]) : c[1] === "rotation" && (u[c[0] + ".quaternion"] = new f.Quaternion().setFromEuler(new f.Euler(d.values[0], d.values[1], d.values[2], "XYZ")).normalize());
|
|
6580
6637
|
});
|
|
6581
6638
|
const a = { props: u };
|
|
6582
6639
|
u["Hips.position"] && (u["Hips.position"].y < 0.5 ? a.lying = !0 : a.standing = !0), this.animPoses.push({
|
|
@@ -6621,13 +6678,13 @@ class Be {
|
|
|
6621
6678
|
if (l.gesture = !0, e && Number.isFinite(e)) {
|
|
6622
6679
|
const h = l.ts[0], u = l.ts[l.ts.length - 1] - h;
|
|
6623
6680
|
if (e * 1e3 - u > 0) {
|
|
6624
|
-
const
|
|
6625
|
-
for (let b = 1; b < l.ts.length; b++)
|
|
6626
|
-
const
|
|
6627
|
-
l.ts = l.ts.map((b, x,
|
|
6681
|
+
const d = [];
|
|
6682
|
+
for (let b = 1; b < l.ts.length; b++) d.push(l.ts[b] - l.ts[b - 1]);
|
|
6683
|
+
const c = o.template?.rescale || d.map((b) => b / u), g = e * 1e3 - u;
|
|
6684
|
+
l.ts = l.ts.map((b, x, S) => x === 0 ? h : S[x - 1] + d[x - 1] + c[x - 1] * g);
|
|
6628
6685
|
} else {
|
|
6629
|
-
const
|
|
6630
|
-
l.ts = l.ts.map((
|
|
6686
|
+
const d = e * 1e3 / u;
|
|
6687
|
+
l.ts = l.ts.map((c) => h + d * (c - h));
|
|
6631
6688
|
}
|
|
6632
6689
|
}
|
|
6633
6690
|
this.animQueue.push(l);
|
|
@@ -6657,21 +6714,21 @@ class Be {
|
|
|
6657
6714
|
* @param {numeric} [d=null] If set, apply in d milliseconds
|
|
6658
6715
|
*/
|
|
6659
6716
|
ikSolve(t, e = null, n = !1, i = null) {
|
|
6660
|
-
const s = new f.Vector3(), o = new f.Vector3(), l = new f.Vector3(), h = new f.Vector3(), r = new f.Quaternion(), u = new f.Vector3(), a = new f.Vector3(),
|
|
6661
|
-
|
|
6717
|
+
const s = new f.Vector3(), o = new f.Vector3(), l = new f.Vector3(), h = new f.Vector3(), r = new f.Quaternion(), u = new f.Vector3(), a = new f.Vector3(), d = new f.Vector3(), c = this.ikMesh.getObjectByName(t.root);
|
|
6718
|
+
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);
|
|
6662
6719
|
const g = this.ikMesh.getObjectByName(t.effector), b = t.links;
|
|
6663
|
-
b.forEach((
|
|
6664
|
-
|
|
6665
|
-
}),
|
|
6720
|
+
b.forEach((S) => {
|
|
6721
|
+
S.bone = this.ikMesh.getObjectByName(S.link), S.bone.quaternion.copy(this.getPoseTemplateProp(S.link + ".quaternion"));
|
|
6722
|
+
}), c.updateMatrixWorld(!0);
|
|
6666
6723
|
const x = t.iterations || 10;
|
|
6667
6724
|
if (e)
|
|
6668
|
-
for (let
|
|
6669
|
-
let
|
|
6670
|
-
for (let p = 0,
|
|
6671
|
-
const
|
|
6672
|
-
|
|
6725
|
+
for (let S = 0; S < x; S++) {
|
|
6726
|
+
let V = !1;
|
|
6727
|
+
for (let p = 0, P = b.length; p < P; p++) {
|
|
6728
|
+
const C = b[p].bone;
|
|
6729
|
+
C.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();
|
|
6673
6730
|
let y = s.dot(l);
|
|
6674
|
-
y > 1 ? y = 1 : y < -1 && (y = -1), y = Math.acos(y), !(y < 1e-5) && (b[p].minAngle !== void 0 && y < b[p].minAngle && (y = b[p].minAngle), b[p].maxAngle !== void 0 && y > b[p].maxAngle && (y = b[p].maxAngle), a.crossVectors(l, s), a.normalize(),
|
|
6731
|
+
y > 1 ? y = 1 : y < -1 && (y = -1), y = Math.acos(y), !(y < 1e-5) && (b[p].minAngle !== void 0 && y < b[p].minAngle && (y = b[p].minAngle), b[p].maxAngle !== void 0 && y > b[p].maxAngle && (y = b[p].maxAngle), a.crossVectors(l, s), a.normalize(), K.setFromAxisAngle(a, y), C.quaternion.multiply(K), C.rotation.setFromVector3(d.setFromEuler(C.rotation).clamp(new f.Vector3(
|
|
6675
6732
|
b[p].minx !== void 0 ? b[p].minx : -1 / 0,
|
|
6676
6733
|
b[p].miny !== void 0 ? b[p].miny : -1 / 0,
|
|
6677
6734
|
b[p].minz !== void 0 ? b[p].minz : -1 / 0
|
|
@@ -6679,12 +6736,12 @@ class Be {
|
|
|
6679
6736
|
b[p].maxx !== void 0 ? b[p].maxx : 1 / 0,
|
|
6680
6737
|
b[p].maxy !== void 0 ? b[p].maxy : 1 / 0,
|
|
6681
6738
|
b[p].maxz !== void 0 ? b[p].maxz : 1 / 0
|
|
6682
|
-
))),
|
|
6739
|
+
))), C.updateMatrixWorld(!0), V = !0);
|
|
6683
6740
|
}
|
|
6684
|
-
if (!
|
|
6741
|
+
if (!V) break;
|
|
6685
6742
|
}
|
|
6686
|
-
i && b.forEach((
|
|
6687
|
-
this.poseTarget.props[
|
|
6743
|
+
i && b.forEach((S) => {
|
|
6744
|
+
this.poseTarget.props[S.link + ".quaternion"].copy(S.bone.quaternion), this.poseTarget.props[S.link + ".quaternion"].t = this.animClock, this.poseTarget.props[S.link + ".quaternion"].d = i;
|
|
6688
6745
|
});
|
|
6689
6746
|
}
|
|
6690
6747
|
/**
|
|
@@ -6734,7 +6791,7 @@ const Ie = {
|
|
|
6734
6791
|
// Male, English - Powerful
|
|
6735
6792
|
}
|
|
6736
6793
|
};
|
|
6737
|
-
function
|
|
6794
|
+
function Ee() {
|
|
6738
6795
|
return {
|
|
6739
6796
|
service: "elevenlabs",
|
|
6740
6797
|
endpoint: Ie.endpoint,
|
|
@@ -6744,16 +6801,16 @@ function Fe() {
|
|
|
6744
6801
|
};
|
|
6745
6802
|
}
|
|
6746
6803
|
function kt() {
|
|
6747
|
-
const
|
|
6748
|
-
return Object.entries(
|
|
6804
|
+
const Y = Ee(), t = [];
|
|
6805
|
+
return Object.entries(Y.voices).forEach(([e, n]) => {
|
|
6749
6806
|
t.push({
|
|
6750
6807
|
value: n,
|
|
6751
|
-
label: `${e.charAt(0).toUpperCase() + e.slice(1)} (${
|
|
6808
|
+
label: `${e.charAt(0).toUpperCase() + e.slice(1)} (${Y.service})`
|
|
6752
6809
|
});
|
|
6753
6810
|
}), t;
|
|
6754
6811
|
}
|
|
6755
6812
|
const Ve = Me(({
|
|
6756
|
-
avatarUrl:
|
|
6813
|
+
avatarUrl: Y = "/avatars/brunette.glb",
|
|
6757
6814
|
avatarBody: t = "F",
|
|
6758
6815
|
mood: e = "neutral",
|
|
6759
6816
|
ttsLang: n = "en",
|
|
@@ -6766,222 +6823,222 @@ const Ve = Me(({
|
|
|
6766
6823
|
cameraView: u = "upper",
|
|
6767
6824
|
onReady: a = () => {
|
|
6768
6825
|
},
|
|
6769
|
-
onLoading:
|
|
6826
|
+
onLoading: d = () => {
|
|
6770
6827
|
},
|
|
6771
|
-
onError:
|
|
6828
|
+
onError: c = () => {
|
|
6772
6829
|
},
|
|
6773
6830
|
className: g = "",
|
|
6774
6831
|
style: b = {},
|
|
6775
6832
|
animations: x = {}
|
|
6776
|
-
},
|
|
6777
|
-
const
|
|
6778
|
-
|
|
6779
|
-
|
|
6780
|
-
}, [
|
|
6781
|
-
|
|
6833
|
+
}, S) => {
|
|
6834
|
+
const V = W(null), p = W(null), P = W(r), C = W(null), y = W(null), I = W(!1), z = W({ remainingText: null, originalText: null, options: null }), A = W([]), j = W(0), [k, F] = de(!0), [_, B] = de(null), [$, ie] = de(!1), [oe, le] = de(!1);
|
|
6835
|
+
me(() => {
|
|
6836
|
+
I.current = oe;
|
|
6837
|
+
}, [oe]), me(() => {
|
|
6838
|
+
P.current = r;
|
|
6782
6839
|
}, [r]);
|
|
6783
|
-
const
|
|
6784
|
-
let
|
|
6785
|
-
|
|
6840
|
+
const Z = Ee(), ne = i || Z.service;
|
|
6841
|
+
let O;
|
|
6842
|
+
ne === "browser" ? O = {
|
|
6786
6843
|
service: "browser",
|
|
6787
6844
|
endpoint: "",
|
|
6788
6845
|
apiKey: null,
|
|
6789
6846
|
defaultVoice: "Google US English"
|
|
6790
|
-
} :
|
|
6847
|
+
} : ne === "elevenlabs" ? O = {
|
|
6791
6848
|
service: "elevenlabs",
|
|
6792
6849
|
endpoint: "https://api.elevenlabs.io/v1/text-to-speech",
|
|
6793
|
-
apiKey: o ||
|
|
6794
|
-
defaultVoice: s ||
|
|
6795
|
-
voices:
|
|
6796
|
-
} :
|
|
6850
|
+
apiKey: o || Z.apiKey,
|
|
6851
|
+
defaultVoice: s || Z.defaultVoice || Ie.defaultVoice,
|
|
6852
|
+
voices: Z.voices || Ie.voices
|
|
6853
|
+
} : ne === "deepgram" ? O = {
|
|
6797
6854
|
service: "deepgram",
|
|
6798
6855
|
endpoint: "https://api.deepgram.com/v1/speak",
|
|
6799
|
-
apiKey: o ||
|
|
6800
|
-
defaultVoice: s ||
|
|
6801
|
-
voices:
|
|
6802
|
-
} :
|
|
6803
|
-
...
|
|
6856
|
+
apiKey: o || Z.apiKey,
|
|
6857
|
+
defaultVoice: s || Z.defaultVoice || Te.defaultVoice,
|
|
6858
|
+
voices: Z.voices || Te.voices
|
|
6859
|
+
} : O = {
|
|
6860
|
+
...Z,
|
|
6804
6861
|
// Override API key if provided via props
|
|
6805
|
-
apiKey: o !== null ? o :
|
|
6862
|
+
apiKey: o !== null ? o : Z.apiKey
|
|
6806
6863
|
};
|
|
6807
6864
|
const v = {
|
|
6808
|
-
url:
|
|
6865
|
+
url: Y,
|
|
6809
6866
|
body: t,
|
|
6810
6867
|
avatarMood: e,
|
|
6811
|
-
ttsLang:
|
|
6812
|
-
ttsVoice: s ||
|
|
6868
|
+
ttsLang: ne === "browser" ? "en-US" : n,
|
|
6869
|
+
ttsVoice: s || O.defaultVoice,
|
|
6813
6870
|
lipsyncLang: "en",
|
|
6814
6871
|
showFullAvatar: r,
|
|
6815
6872
|
bodyMovement: l,
|
|
6816
6873
|
movementIntensity: h
|
|
6817
6874
|
}, R = {
|
|
6818
|
-
ttsEndpoint:
|
|
6819
|
-
ttsApikey:
|
|
6820
|
-
ttsService:
|
|
6875
|
+
ttsEndpoint: O.endpoint,
|
|
6876
|
+
ttsApikey: O.apiKey,
|
|
6877
|
+
ttsService: ne,
|
|
6821
6878
|
lipsyncModules: ["en"],
|
|
6822
6879
|
cameraView: u
|
|
6823
|
-
},
|
|
6824
|
-
if (!(!
|
|
6880
|
+
}, H = N(async () => {
|
|
6881
|
+
if (!(!V.current || p.current))
|
|
6825
6882
|
try {
|
|
6826
|
-
if (
|
|
6827
|
-
if (
|
|
6828
|
-
const
|
|
6829
|
-
|
|
6883
|
+
if (F(!0), B(null), p.current = new Be(V.current, R), 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, (U) => {
|
|
6884
|
+
if (U.lengthComputable) {
|
|
6885
|
+
const te = Math.min(100, Math.round(U.loaded / U.total * 100));
|
|
6886
|
+
d(te);
|
|
6830
6887
|
}
|
|
6831
|
-
}), await new Promise((
|
|
6832
|
-
const
|
|
6833
|
-
p.current.lipsync && Object.keys(p.current.lipsync).length > 0 ?
|
|
6888
|
+
}), await new Promise((U) => {
|
|
6889
|
+
const te = () => {
|
|
6890
|
+
p.current.lipsync && Object.keys(p.current.lipsync).length > 0 ? U() : setTimeout(te, 100);
|
|
6834
6891
|
};
|
|
6835
|
-
|
|
6892
|
+
te();
|
|
6836
6893
|
}), p.current && p.current.setShowFullAvatar)
|
|
6837
6894
|
try {
|
|
6838
6895
|
p.current.setShowFullAvatar(r);
|
|
6839
|
-
} catch (
|
|
6840
|
-
console.warn("Error setting full body mode on initialization:",
|
|
6896
|
+
} catch (U) {
|
|
6897
|
+
console.warn("Error setting full body mode on initialization:", U);
|
|
6841
6898
|
}
|
|
6842
|
-
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()),
|
|
6843
|
-
const
|
|
6899
|
+
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()), F(!1), ie(!0), a(p.current);
|
|
6900
|
+
const D = () => {
|
|
6844
6901
|
document.visibilityState === "visible" ? p.current?.start() : p.current?.stop();
|
|
6845
6902
|
};
|
|
6846
|
-
return document.addEventListener("visibilitychange",
|
|
6847
|
-
document.removeEventListener("visibilitychange",
|
|
6903
|
+
return document.addEventListener("visibilitychange", D), () => {
|
|
6904
|
+
document.removeEventListener("visibilitychange", D);
|
|
6848
6905
|
};
|
|
6849
6906
|
} catch (L) {
|
|
6850
|
-
console.error("Error initializing TalkingHead:", L),
|
|
6907
|
+
console.error("Error initializing TalkingHead:", L), B(L.message || "Failed to initialize avatar"), F(!1), c(L);
|
|
6851
6908
|
}
|
|
6852
|
-
}, [
|
|
6853
|
-
|
|
6909
|
+
}, [Y, t, e, n, i, s, o, r, l, h, u]);
|
|
6910
|
+
me(() => (H(), () => {
|
|
6854
6911
|
p.current && (p.current.stop(), p.current.dispose(), p.current = null);
|
|
6855
|
-
}), [
|
|
6856
|
-
if (!
|
|
6857
|
-
const L = new ResizeObserver((
|
|
6858
|
-
for (const
|
|
6912
|
+
}), [H]), me(() => {
|
|
6913
|
+
if (!V.current || !p.current) return;
|
|
6914
|
+
const L = new ResizeObserver((U) => {
|
|
6915
|
+
for (const te of U)
|
|
6859
6916
|
p.current && p.current.onResize && p.current.onResize();
|
|
6860
6917
|
});
|
|
6861
|
-
L.observe(
|
|
6862
|
-
const
|
|
6918
|
+
L.observe(V.current);
|
|
6919
|
+
const D = () => {
|
|
6863
6920
|
p.current && p.current.onResize && p.current.onResize();
|
|
6864
6921
|
};
|
|
6865
|
-
return window.addEventListener("resize",
|
|
6866
|
-
L.disconnect(), window.removeEventListener("resize",
|
|
6922
|
+
return window.addEventListener("resize", D), () => {
|
|
6923
|
+
L.disconnect(), window.removeEventListener("resize", D);
|
|
6867
6924
|
};
|
|
6868
|
-
}, [
|
|
6869
|
-
const M =
|
|
6925
|
+
}, [$]);
|
|
6926
|
+
const M = N(async () => {
|
|
6870
6927
|
if (p.current && p.current.audioCtx)
|
|
6871
6928
|
try {
|
|
6872
6929
|
(p.current.audioCtx.state === "suspended" || p.current.audioCtx.state === "interrupted") && (await p.current.audioCtx.resume(), console.log("Audio context resumed"));
|
|
6873
6930
|
} catch (L) {
|
|
6874
6931
|
console.warn("Failed to resume audio context:", L);
|
|
6875
6932
|
}
|
|
6876
|
-
}, []),
|
|
6877
|
-
if (p.current &&
|
|
6933
|
+
}, []), G = N(async (L, D = {}) => {
|
|
6934
|
+
if (p.current && $)
|
|
6878
6935
|
try {
|
|
6879
|
-
y.current && (clearInterval(y.current), y.current = null),
|
|
6880
|
-
const
|
|
6881
|
-
|
|
6936
|
+
y.current && (clearInterval(y.current), y.current = null), C.current = { text: L, options: D }, z.current = { remainingText: null, originalText: null, options: null };
|
|
6937
|
+
const U = /[!\.\?\n\p{Extended_Pictographic}]/ug, te = L.split(U).map((Q) => Q.trim()).filter((Q) => Q.length > 0);
|
|
6938
|
+
A.current = te, j.current = 0, le(!1), I.current = !1, await M();
|
|
6882
6939
|
const ge = {
|
|
6883
|
-
...
|
|
6884
|
-
lipsyncLang:
|
|
6940
|
+
...D,
|
|
6941
|
+
lipsyncLang: D.lipsyncLang || v.lipsyncLang || "en"
|
|
6885
6942
|
};
|
|
6886
|
-
if (
|
|
6887
|
-
const
|
|
6888
|
-
let
|
|
6889
|
-
const
|
|
6943
|
+
if (D.onSpeechEnd && p.current) {
|
|
6944
|
+
const Q = p.current;
|
|
6945
|
+
let ce = null, Se = 0;
|
|
6946
|
+
const Le = 1200;
|
|
6890
6947
|
let be = !1;
|
|
6891
|
-
|
|
6892
|
-
if (Se++,
|
|
6948
|
+
ce = setInterval(() => {
|
|
6949
|
+
if (Se++, I.current)
|
|
6893
6950
|
return;
|
|
6894
|
-
if (Se >
|
|
6895
|
-
if (
|
|
6951
|
+
if (Se > Le) {
|
|
6952
|
+
if (ce && (clearInterval(ce), ce = null, y.current = null), !be && !I.current) {
|
|
6896
6953
|
be = !0;
|
|
6897
6954
|
try {
|
|
6898
|
-
|
|
6955
|
+
D.onSpeechEnd();
|
|
6899
6956
|
} catch (Ne) {
|
|
6900
6957
|
console.error("Error in onSpeechEnd callback (timeout):", Ne);
|
|
6901
6958
|
}
|
|
6902
6959
|
}
|
|
6903
6960
|
return;
|
|
6904
6961
|
}
|
|
6905
|
-
const ye = !
|
|
6906
|
-
|
|
6907
|
-
if (
|
|
6908
|
-
be = !0,
|
|
6962
|
+
const ye = !Q.speechQueue || Q.speechQueue.length === 0, ke = !Q.audioPlaylist || Q.audioPlaylist.length === 0;
|
|
6963
|
+
Q && Q.isSpeaking === !1 && ye && ke && Q.isAudioPlaying === !1 && !be && !I.current && setTimeout(() => {
|
|
6964
|
+
if (Q && !I.current && Q.isSpeaking === !1 && (!Q.speechQueue || Q.speechQueue.length === 0) && (!Q.audioPlaylist || Q.audioPlaylist.length === 0) && Q.isAudioPlaying === !1 && !be && !I.current) {
|
|
6965
|
+
be = !0, ce && (clearInterval(ce), ce = null, y.current = null);
|
|
6909
6966
|
try {
|
|
6910
|
-
|
|
6967
|
+
D.onSpeechEnd();
|
|
6911
6968
|
} catch (Ze) {
|
|
6912
6969
|
console.error("Error in onSpeechEnd callback:", Ze);
|
|
6913
6970
|
}
|
|
6914
6971
|
}
|
|
6915
6972
|
}, 100);
|
|
6916
|
-
}, 100), y.current =
|
|
6973
|
+
}, 100), y.current = ce;
|
|
6917
6974
|
}
|
|
6918
6975
|
p.current.lipsync && Object.keys(p.current.lipsync).length > 0 ? (p.current.setSlowdownRate && p.current.setSlowdownRate(1.05), p.current.speakText(L, ge)) : setTimeout(async () => {
|
|
6919
6976
|
await M(), p.current && p.current.lipsync && (p.current.setSlowdownRate && p.current.setSlowdownRate(1.05), p.current.speakText(L, ge));
|
|
6920
6977
|
}, 100);
|
|
6921
|
-
} catch (
|
|
6922
|
-
console.error("Error speaking text:",
|
|
6978
|
+
} catch (U) {
|
|
6979
|
+
console.error("Error speaking text:", U), B(U.message || "Failed to speak text");
|
|
6923
6980
|
}
|
|
6924
|
-
}, [
|
|
6925
|
-
p.current && (p.current.stopSpeaking(), p.current.setSlowdownRate && p.current.setSlowdownRate(1),
|
|
6926
|
-
}, []),
|
|
6981
|
+
}, [$, M, v.lipsyncLang]), ee = N(() => {
|
|
6982
|
+
p.current && (p.current.stopSpeaking(), p.current.setSlowdownRate && p.current.setSlowdownRate(1), C.current = null, le(!1));
|
|
6983
|
+
}, []), q = N(() => {
|
|
6927
6984
|
if (p.current && p.current.pauseSpeaking) {
|
|
6928
6985
|
const L = p.current;
|
|
6929
6986
|
if (L.isSpeaking || L.audioPlaylist && L.audioPlaylist.length > 0 || L.speechQueue && L.speechQueue.length > 0) {
|
|
6930
6987
|
y.current && (clearInterval(y.current), y.current = null);
|
|
6931
|
-
let
|
|
6932
|
-
if (
|
|
6933
|
-
const
|
|
6934
|
-
if (
|
|
6988
|
+
let U = "";
|
|
6989
|
+
if (C.current && A.current.length > 0) {
|
|
6990
|
+
const te = A.current.length, ge = L.speechQueue ? L.speechQueue.filter((Le) => Le && Le.text && Array.isArray(Le.text) && Le.text.length > 0).length : 0, Q = L.audioPlaylist && L.audioPlaylist.length > 0, ce = ge + (Q ? 1 : 0), Se = te - ce;
|
|
6991
|
+
if (ce > 0 && Se < te && (U = A.current.slice(Se).join(". ").trim(), !U && ge > 0 && L.speechQueue)) {
|
|
6935
6992
|
const be = L.speechQueue.filter((ye) => ye && ye.text && Array.isArray(ye.text) && ye.text.length > 0).map((ye) => ye.text.map((ke) => ke.word || "").filter((ke) => ke.length > 0).join(" ")).filter((ye) => ye.length > 0).join(" ");
|
|
6936
|
-
be && be.trim() && (
|
|
6993
|
+
be && be.trim() && (U = be.trim());
|
|
6937
6994
|
}
|
|
6938
6995
|
}
|
|
6939
|
-
|
|
6940
|
-
remainingText:
|
|
6941
|
-
originalText:
|
|
6942
|
-
options:
|
|
6943
|
-
}), L.speechQueue && (L.speechQueue.length = 0), p.current.pauseSpeaking(),
|
|
6996
|
+
C.current && (z.current = {
|
|
6997
|
+
remainingText: U || null,
|
|
6998
|
+
originalText: C.current.text,
|
|
6999
|
+
options: C.current.options
|
|
7000
|
+
}), L.speechQueue && (L.speechQueue.length = 0), p.current.pauseSpeaking(), I.current = !0, le(!0);
|
|
6944
7001
|
}
|
|
6945
7002
|
}
|
|
6946
|
-
}, []),
|
|
6947
|
-
if (!p.current || !
|
|
7003
|
+
}, []), J = N(async () => {
|
|
7004
|
+
if (!p.current || !oe)
|
|
6948
7005
|
return;
|
|
6949
|
-
let L = "",
|
|
6950
|
-
if (
|
|
6951
|
-
L =
|
|
6952
|
-
else if (
|
|
6953
|
-
L =
|
|
7006
|
+
let L = "", D = {};
|
|
7007
|
+
if (z.current && z.current.remainingText)
|
|
7008
|
+
L = z.current.remainingText, D = z.current.options || {}, z.current = { remainingText: null, originalText: null, options: null };
|
|
7009
|
+
else if (C.current && C.current.text)
|
|
7010
|
+
L = C.current.text, D = C.current.options || {};
|
|
6954
7011
|
else {
|
|
6955
|
-
console.warn("Resume called but no paused speech found"),
|
|
7012
|
+
console.warn("Resume called but no paused speech found"), le(!1), I.current = !1;
|
|
6956
7013
|
return;
|
|
6957
7014
|
}
|
|
6958
|
-
|
|
6959
|
-
const
|
|
6960
|
-
...
|
|
6961
|
-
lipsyncLang:
|
|
7015
|
+
le(!1), I.current = !1, await M();
|
|
7016
|
+
const U = {
|
|
7017
|
+
...D,
|
|
7018
|
+
lipsyncLang: D.lipsyncLang || v.lipsyncLang || "en"
|
|
6962
7019
|
};
|
|
6963
7020
|
try {
|
|
6964
|
-
await
|
|
6965
|
-
} catch (
|
|
6966
|
-
console.error("Error resuming speech:",
|
|
7021
|
+
await G(L, U);
|
|
7022
|
+
} catch (te) {
|
|
7023
|
+
console.error("Error resuming speech:", te), le(!1), I.current = !1;
|
|
6967
7024
|
}
|
|
6968
|
-
}, [M,
|
|
7025
|
+
}, [M, oe, G, v]), Ae = N((L) => {
|
|
6969
7026
|
p.current && p.current.setMood(L);
|
|
6970
|
-
}, []), we =
|
|
7027
|
+
}, []), we = N((L) => {
|
|
6971
7028
|
p.current && p.current.setSlowdownRate && p.current.setSlowdownRate(L);
|
|
6972
|
-
}, []),
|
|
7029
|
+
}, []), E = N((L, D = !1) => {
|
|
6973
7030
|
if (p.current && p.current.playAnimation) {
|
|
6974
7031
|
if (x && x[L] && (L = x[L]), p.current.setShowFullAvatar)
|
|
6975
7032
|
try {
|
|
6976
|
-
p.current.setShowFullAvatar(
|
|
6977
|
-
} catch (
|
|
6978
|
-
console.warn("Error setting full body mode:",
|
|
7033
|
+
p.current.setShowFullAvatar(P.current);
|
|
7034
|
+
} catch (te) {
|
|
7035
|
+
console.warn("Error setting full body mode:", te);
|
|
6979
7036
|
}
|
|
6980
7037
|
if (L.includes("."))
|
|
6981
7038
|
try {
|
|
6982
|
-
p.current.playAnimation(L, null, 10, 0, 0.01,
|
|
6983
|
-
} catch (
|
|
6984
|
-
console.warn(`Failed to play ${L}:`,
|
|
7039
|
+
p.current.playAnimation(L, null, 10, 0, 0.01, D);
|
|
7040
|
+
} catch (te) {
|
|
7041
|
+
console.warn(`Failed to play ${L}:`, te);
|
|
6985
7042
|
try {
|
|
6986
7043
|
p.current.setBodyMovement("idle");
|
|
6987
7044
|
} catch (ge) {
|
|
@@ -6989,11 +7046,11 @@ const Ve = Me(({
|
|
|
6989
7046
|
}
|
|
6990
7047
|
}
|
|
6991
7048
|
else {
|
|
6992
|
-
const
|
|
7049
|
+
const te = [".fbx", ".glb", ".gltf"];
|
|
6993
7050
|
let ge = !1;
|
|
6994
|
-
for (const
|
|
7051
|
+
for (const Q of te)
|
|
6995
7052
|
try {
|
|
6996
|
-
p.current.playAnimation(L +
|
|
7053
|
+
p.current.playAnimation(L + Q, null, 10, 0, 0.01, D), ge = !0;
|
|
6997
7054
|
break;
|
|
6998
7055
|
} catch {
|
|
6999
7056
|
}
|
|
@@ -7001,41 +7058,41 @@ const Ve = Me(({
|
|
|
7001
7058
|
console.warn("Animation not found:", L);
|
|
7002
7059
|
try {
|
|
7003
7060
|
p.current.setBodyMovement("idle");
|
|
7004
|
-
} catch (
|
|
7005
|
-
console.warn("Fallback animation also failed:",
|
|
7061
|
+
} catch (Q) {
|
|
7062
|
+
console.warn("Fallback animation also failed:", Q);
|
|
7006
7063
|
}
|
|
7007
7064
|
}
|
|
7008
7065
|
}
|
|
7009
7066
|
}
|
|
7010
|
-
}, [x]),
|
|
7067
|
+
}, [x]), se = N(() => {
|
|
7011
7068
|
p.current && p.current.onResize && p.current.onResize();
|
|
7012
7069
|
}, []);
|
|
7013
|
-
return
|
|
7014
|
-
speakText:
|
|
7015
|
-
stopSpeaking:
|
|
7016
|
-
pauseSpeaking:
|
|
7017
|
-
resumeSpeaking:
|
|
7070
|
+
return Fe(S, () => ({
|
|
7071
|
+
speakText: G,
|
|
7072
|
+
stopSpeaking: ee,
|
|
7073
|
+
pauseSpeaking: q,
|
|
7074
|
+
resumeSpeaking: J,
|
|
7018
7075
|
resumeAudioContext: M,
|
|
7019
|
-
setMood:
|
|
7076
|
+
setMood: Ae,
|
|
7020
7077
|
setTimingAdjustment: we,
|
|
7021
|
-
playAnimation:
|
|
7022
|
-
isReady:
|
|
7023
|
-
isPaused:
|
|
7078
|
+
playAnimation: E,
|
|
7079
|
+
isReady: $,
|
|
7080
|
+
isPaused: oe,
|
|
7024
7081
|
talkingHead: p.current,
|
|
7025
|
-
handleResize:
|
|
7082
|
+
handleResize: se,
|
|
7026
7083
|
setBodyMovement: (L) => {
|
|
7027
7084
|
if (p.current && p.current.setShowFullAvatar && p.current.setBodyMovement)
|
|
7028
7085
|
try {
|
|
7029
|
-
p.current.setShowFullAvatar(
|
|
7030
|
-
} catch (
|
|
7031
|
-
console.warn("Error setting body movement:",
|
|
7086
|
+
p.current.setShowFullAvatar(P.current), p.current.setBodyMovement(L);
|
|
7087
|
+
} catch (D) {
|
|
7088
|
+
console.warn("Error setting body movement:", D);
|
|
7032
7089
|
}
|
|
7033
7090
|
},
|
|
7034
7091
|
setMovementIntensity: (L) => p.current?.setMovementIntensity(L),
|
|
7035
7092
|
playRandomDance: () => {
|
|
7036
7093
|
if (p.current && p.current.setShowFullAvatar && p.current.playRandomDance)
|
|
7037
7094
|
try {
|
|
7038
|
-
p.current.setShowFullAvatar(
|
|
7095
|
+
p.current.setShowFullAvatar(P.current), p.current.playRandomDance();
|
|
7039
7096
|
} catch (L) {
|
|
7040
7097
|
console.warn("Error playing random dance:", L);
|
|
7041
7098
|
}
|
|
@@ -7043,15 +7100,15 @@ const Ve = Me(({
|
|
|
7043
7100
|
playReaction: (L) => {
|
|
7044
7101
|
if (p.current && p.current.setShowFullAvatar && p.current.playReaction)
|
|
7045
7102
|
try {
|
|
7046
|
-
p.current.setShowFullAvatar(
|
|
7047
|
-
} catch (
|
|
7048
|
-
console.warn("Error playing reaction:",
|
|
7103
|
+
p.current.setShowFullAvatar(P.current), p.current.playReaction(L);
|
|
7104
|
+
} catch (D) {
|
|
7105
|
+
console.warn("Error playing reaction:", D);
|
|
7049
7106
|
}
|
|
7050
7107
|
},
|
|
7051
7108
|
playCelebration: () => {
|
|
7052
7109
|
if (p.current && p.current.setShowFullAvatar && p.current.playCelebration)
|
|
7053
7110
|
try {
|
|
7054
|
-
p.current.setShowFullAvatar(
|
|
7111
|
+
p.current.setShowFullAvatar(P.current), p.current.playCelebration();
|
|
7055
7112
|
} catch (L) {
|
|
7056
7113
|
console.warn("Error playing celebration:", L);
|
|
7057
7114
|
}
|
|
@@ -7059,9 +7116,9 @@ const Ve = Me(({
|
|
|
7059
7116
|
setShowFullAvatar: (L) => {
|
|
7060
7117
|
if (p.current && p.current.setShowFullAvatar)
|
|
7061
7118
|
try {
|
|
7062
|
-
|
|
7063
|
-
} catch (
|
|
7064
|
-
console.warn("Error setting showFullAvatar:",
|
|
7119
|
+
P.current = L, p.current.setShowFullAvatar(L);
|
|
7120
|
+
} catch (D) {
|
|
7121
|
+
console.warn("Error setting showFullAvatar:", D);
|
|
7065
7122
|
}
|
|
7066
7123
|
},
|
|
7067
7124
|
lockAvatarPosition: () => {
|
|
@@ -7091,10 +7148,10 @@ const Ve = Me(({
|
|
|
7091
7148
|
...b
|
|
7092
7149
|
},
|
|
7093
7150
|
children: [
|
|
7094
|
-
/* @__PURE__ */
|
|
7151
|
+
/* @__PURE__ */ pe(
|
|
7095
7152
|
"div",
|
|
7096
7153
|
{
|
|
7097
|
-
ref:
|
|
7154
|
+
ref: V,
|
|
7098
7155
|
className: "talking-head-viewer",
|
|
7099
7156
|
style: {
|
|
7100
7157
|
width: "100%",
|
|
@@ -7103,7 +7160,7 @@ const Ve = Me(({
|
|
|
7103
7160
|
}
|
|
7104
7161
|
}
|
|
7105
7162
|
),
|
|
7106
|
-
k && /* @__PURE__ */
|
|
7163
|
+
k && /* @__PURE__ */ pe("div", { className: "loading-overlay", style: {
|
|
7107
7164
|
position: "absolute",
|
|
7108
7165
|
top: "50%",
|
|
7109
7166
|
left: "50%",
|
|
@@ -7112,7 +7169,7 @@ const Ve = Me(({
|
|
|
7112
7169
|
fontSize: "18px",
|
|
7113
7170
|
zIndex: 10
|
|
7114
7171
|
}, children: "Loading avatar..." }),
|
|
7115
|
-
|
|
7172
|
+
_ && /* @__PURE__ */ pe("div", { className: "error-overlay", style: {
|
|
7116
7173
|
position: "absolute",
|
|
7117
7174
|
top: "50%",
|
|
7118
7175
|
left: "50%",
|
|
@@ -7123,14 +7180,14 @@ const Ve = Me(({
|
|
|
7123
7180
|
zIndex: 10,
|
|
7124
7181
|
padding: "20px",
|
|
7125
7182
|
borderRadius: "8px"
|
|
7126
|
-
}, children:
|
|
7183
|
+
}, children: _ })
|
|
7127
7184
|
]
|
|
7128
7185
|
}
|
|
7129
7186
|
);
|
|
7130
7187
|
});
|
|
7131
7188
|
Ve.displayName = "TalkingHeadAvatar";
|
|
7132
7189
|
const pt = Me(({
|
|
7133
|
-
text:
|
|
7190
|
+
text: Y = "Hello! I'm a talking avatar. How are you today?",
|
|
7134
7191
|
onLoading: t = () => {
|
|
7135
7192
|
},
|
|
7136
7193
|
onError: e = () => {
|
|
@@ -7141,7 +7198,7 @@ const pt = Me(({
|
|
|
7141
7198
|
style: s = {},
|
|
7142
7199
|
avatarConfig: o = {}
|
|
7143
7200
|
}, l) => {
|
|
7144
|
-
const h =
|
|
7201
|
+
const h = W(null), r = W(null), [u, a] = de(!0), [d, c] = de(null), [g, b] = de(!1), x = Ee(), S = o.ttsService || x.service, V = S === "browser" ? {
|
|
7145
7202
|
endpoint: "",
|
|
7146
7203
|
apiKey: null,
|
|
7147
7204
|
defaultVoice: "Google US English"
|
|
@@ -7150,14 +7207,14 @@ const pt = Me(({
|
|
|
7150
7207
|
// Override API key if provided via avatarConfig
|
|
7151
7208
|
apiKey: o.ttsApiKey !== void 0 && o.ttsApiKey !== null ? o.ttsApiKey : x.apiKey,
|
|
7152
7209
|
// Override endpoint for ElevenLabs if service is explicitly set
|
|
7153
|
-
endpoint:
|
|
7210
|
+
endpoint: S === "elevenlabs" && o.ttsApiKey ? "https://api.elevenlabs.io/v1/text-to-speech" : x.endpoint
|
|
7154
7211
|
}, p = {
|
|
7155
7212
|
url: "/avatars/brunette.glb",
|
|
7156
7213
|
// Use brunette avatar (working glTF file)
|
|
7157
7214
|
body: "F",
|
|
7158
7215
|
avatarMood: "neutral",
|
|
7159
|
-
ttsLang:
|
|
7160
|
-
ttsVoice: o.ttsVoice ||
|
|
7216
|
+
ttsLang: S === "browser" ? "en-US" : "en",
|
|
7217
|
+
ttsVoice: o.ttsVoice || V.defaultVoice,
|
|
7161
7218
|
lipsyncLang: "en",
|
|
7162
7219
|
// English lip-sync
|
|
7163
7220
|
showFullAvatar: !0,
|
|
@@ -7165,123 +7222,123 @@ const pt = Me(({
|
|
|
7165
7222
|
bodyMovement: "idle",
|
|
7166
7223
|
movementIntensity: 0.5,
|
|
7167
7224
|
...o
|
|
7168
|
-
},
|
|
7169
|
-
ttsEndpoint:
|
|
7170
|
-
ttsApikey:
|
|
7171
|
-
ttsService:
|
|
7225
|
+
}, P = {
|
|
7226
|
+
ttsEndpoint: V.endpoint,
|
|
7227
|
+
ttsApikey: V.apiKey,
|
|
7228
|
+
ttsService: S,
|
|
7172
7229
|
lipsyncModules: ["en"],
|
|
7173
7230
|
cameraView: "upper"
|
|
7174
|
-
},
|
|
7231
|
+
}, C = N(async () => {
|
|
7175
7232
|
if (!(!h.current || r.current))
|
|
7176
7233
|
try {
|
|
7177
|
-
if (a(!0),
|
|
7178
|
-
if (
|
|
7179
|
-
const
|
|
7180
|
-
t(
|
|
7234
|
+
if (a(!0), c(null), r.current = new Be(h.current, P), await r.current.showAvatar(p, (_) => {
|
|
7235
|
+
if (_.lengthComputable) {
|
|
7236
|
+
const B = Math.min(100, Math.round(_.loaded / _.total * 100));
|
|
7237
|
+
t(B);
|
|
7181
7238
|
}
|
|
7182
7239
|
}), r.current.morphs && r.current.morphs.length > 0) {
|
|
7183
|
-
const
|
|
7184
|
-
console.log("Available morph targets:", Object.keys(
|
|
7185
|
-
const
|
|
7186
|
-
console.log("Viseme morph targets found:",
|
|
7240
|
+
const _ = r.current.morphs[0].morphTargetDictionary;
|
|
7241
|
+
console.log("Available morph targets:", Object.keys(_));
|
|
7242
|
+
const B = Object.keys(_).filter(($) => $.startsWith("viseme_"));
|
|
7243
|
+
console.log("Viseme morph targets found:", B), B.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"));
|
|
7187
7244
|
}
|
|
7188
|
-
if (await new Promise((
|
|
7189
|
-
const
|
|
7190
|
-
r.current.lipsync && Object.keys(r.current.lipsync).length > 0 ? (console.log("Lip-sync modules loaded:", Object.keys(r.current.lipsync)),
|
|
7245
|
+
if (await new Promise((_) => {
|
|
7246
|
+
const B = () => {
|
|
7247
|
+
r.current.lipsync && Object.keys(r.current.lipsync).length > 0 ? (console.log("Lip-sync modules loaded:", Object.keys(r.current.lipsync)), _()) : (console.log("Waiting for lip-sync modules to load..."), setTimeout(B, 100));
|
|
7191
7248
|
};
|
|
7192
|
-
|
|
7249
|
+
B();
|
|
7193
7250
|
}), r.current && r.current.setShowFullAvatar)
|
|
7194
7251
|
try {
|
|
7195
7252
|
r.current.setShowFullAvatar(!0), console.log("Avatar initialized in full body mode");
|
|
7196
|
-
} catch (
|
|
7197
|
-
console.warn("Error setting full body mode on initialization:",
|
|
7253
|
+
} catch (_) {
|
|
7254
|
+
console.warn("Error setting full body mode on initialization:", _);
|
|
7198
7255
|
}
|
|
7199
7256
|
a(!1), b(!0), n(r.current);
|
|
7200
|
-
const
|
|
7257
|
+
const F = () => {
|
|
7201
7258
|
document.visibilityState === "visible" ? r.current?.start() : r.current?.stop();
|
|
7202
7259
|
};
|
|
7203
|
-
return document.addEventListener("visibilitychange",
|
|
7204
|
-
document.removeEventListener("visibilitychange",
|
|
7260
|
+
return document.addEventListener("visibilitychange", F), () => {
|
|
7261
|
+
document.removeEventListener("visibilitychange", F);
|
|
7205
7262
|
};
|
|
7206
7263
|
} catch (k) {
|
|
7207
|
-
console.error("Error initializing TalkingHead:", k),
|
|
7264
|
+
console.error("Error initializing TalkingHead:", k), c(k.message || "Failed to initialize avatar"), a(!1), e(k);
|
|
7208
7265
|
}
|
|
7209
7266
|
}, []);
|
|
7210
|
-
|
|
7267
|
+
me(() => (C(), () => {
|
|
7211
7268
|
r.current && (r.current.stop(), r.current.dispose(), r.current = null);
|
|
7212
|
-
}), [
|
|
7213
|
-
const y =
|
|
7269
|
+
}), [C]);
|
|
7270
|
+
const y = N((k) => {
|
|
7214
7271
|
if (r.current && g)
|
|
7215
7272
|
try {
|
|
7216
7273
|
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(() => {
|
|
7217
7274
|
r.current && r.current.lipsync ? (console.log("Lip-sync now ready, speaking..."), r.current.setSlowdownRate && (r.current.setSlowdownRate(1.05), console.log("Applied timing adjustment for better lip-sync")), r.current.speakText(k)) : console.error("Lip-sync still not ready after waiting");
|
|
7218
7275
|
}, 500));
|
|
7219
|
-
} catch (
|
|
7220
|
-
console.error("Error speaking text:",
|
|
7276
|
+
} catch (F) {
|
|
7277
|
+
console.error("Error speaking text:", F), c(F.message || "Failed to speak text");
|
|
7221
7278
|
}
|
|
7222
7279
|
else
|
|
7223
7280
|
console.warn("Avatar not ready for speaking. isReady:", g, "talkingHeadRef:", !!r.current);
|
|
7224
|
-
}, [g, p]),
|
|
7281
|
+
}, [g, p]), I = N(() => {
|
|
7225
7282
|
r.current && (r.current.stopSpeaking(), r.current.setSlowdownRate && (r.current.setSlowdownRate(1), console.log("Reset timing to normal")));
|
|
7226
|
-
}, []),
|
|
7283
|
+
}, []), z = N((k) => {
|
|
7227
7284
|
r.current && r.current.setMood(k);
|
|
7228
|
-
}, []),
|
|
7285
|
+
}, []), A = N((k) => {
|
|
7229
7286
|
r.current && r.current.setSlowdownRate && (r.current.setSlowdownRate(k), console.log("Timing adjustment set to:", k));
|
|
7230
|
-
}, []),
|
|
7287
|
+
}, []), j = N((k, F = !1) => {
|
|
7231
7288
|
if (r.current && r.current.playAnimation) {
|
|
7232
7289
|
if (r.current.setShowFullAvatar)
|
|
7233
7290
|
try {
|
|
7234
7291
|
r.current.setShowFullAvatar(!0);
|
|
7235
|
-
} catch (
|
|
7236
|
-
console.warn("Error setting full body mode:",
|
|
7292
|
+
} catch (B) {
|
|
7293
|
+
console.warn("Error setting full body mode:", B);
|
|
7237
7294
|
}
|
|
7238
7295
|
if (k.includes("."))
|
|
7239
7296
|
try {
|
|
7240
|
-
r.current.playAnimation(k, null, 10, 0, 0.01,
|
|
7241
|
-
} catch (
|
|
7242
|
-
console.log(`Failed to play ${k}:`,
|
|
7297
|
+
r.current.playAnimation(k, null, 10, 0, 0.01, F), console.log("Playing animation:", k);
|
|
7298
|
+
} catch (B) {
|
|
7299
|
+
console.log(`Failed to play ${k}:`, B);
|
|
7243
7300
|
try {
|
|
7244
7301
|
r.current.setBodyMovement("idle"), console.log("Fallback to idle animation");
|
|
7245
|
-
} catch (
|
|
7246
|
-
console.warn("Fallback animation also failed:",
|
|
7302
|
+
} catch ($) {
|
|
7303
|
+
console.warn("Fallback animation also failed:", $);
|
|
7247
7304
|
}
|
|
7248
7305
|
}
|
|
7249
7306
|
else {
|
|
7250
|
-
const
|
|
7251
|
-
let
|
|
7252
|
-
for (const
|
|
7307
|
+
const B = [".fbx", ".glb", ".gltf"];
|
|
7308
|
+
let $ = !1;
|
|
7309
|
+
for (const ie of B)
|
|
7253
7310
|
try {
|
|
7254
|
-
r.current.playAnimation(k +
|
|
7311
|
+
r.current.playAnimation(k + ie, null, 10, 0, 0.01, F), console.log("Playing animation:", k + ie), $ = !0;
|
|
7255
7312
|
break;
|
|
7256
7313
|
} catch {
|
|
7257
|
-
console.log(`Failed to play ${k}${
|
|
7314
|
+
console.log(`Failed to play ${k}${ie}, trying next format...`);
|
|
7258
7315
|
}
|
|
7259
|
-
if (
|
|
7316
|
+
if (!$) {
|
|
7260
7317
|
console.warn("Animation system not available or animation not found:", k);
|
|
7261
7318
|
try {
|
|
7262
7319
|
r.current.setBodyMovement("idle"), console.log("Fallback to idle animation");
|
|
7263
|
-
} catch (
|
|
7264
|
-
console.warn("Fallback animation also failed:",
|
|
7320
|
+
} catch (ie) {
|
|
7321
|
+
console.warn("Fallback animation also failed:", ie);
|
|
7265
7322
|
}
|
|
7266
7323
|
}
|
|
7267
7324
|
}
|
|
7268
7325
|
} else
|
|
7269
7326
|
console.warn("Animation system not available or animation not found:", k);
|
|
7270
7327
|
}, []);
|
|
7271
|
-
return
|
|
7328
|
+
return Fe(l, () => ({
|
|
7272
7329
|
speakText: y,
|
|
7273
|
-
stopSpeaking:
|
|
7274
|
-
setMood:
|
|
7275
|
-
setTimingAdjustment:
|
|
7276
|
-
playAnimation:
|
|
7330
|
+
stopSpeaking: I,
|
|
7331
|
+
setMood: z,
|
|
7332
|
+
setTimingAdjustment: A,
|
|
7333
|
+
playAnimation: j,
|
|
7277
7334
|
isReady: g,
|
|
7278
7335
|
talkingHead: r.current,
|
|
7279
7336
|
setBodyMovement: (k) => {
|
|
7280
7337
|
if (r.current && r.current.setShowFullAvatar && r.current.setBodyMovement)
|
|
7281
7338
|
try {
|
|
7282
7339
|
r.current.setShowFullAvatar(!0), r.current.setBodyMovement(k), console.log("Body movement set with full body mode:", k);
|
|
7283
|
-
} catch (
|
|
7284
|
-
console.warn("Error setting body movement:",
|
|
7340
|
+
} catch (F) {
|
|
7341
|
+
console.warn("Error setting body movement:", F);
|
|
7285
7342
|
}
|
|
7286
7343
|
},
|
|
7287
7344
|
setMovementIntensity: (k) => r.current?.setMovementIntensity(k),
|
|
@@ -7297,8 +7354,8 @@ const pt = Me(({
|
|
|
7297
7354
|
if (r.current && r.current.setShowFullAvatar && r.current.playReaction)
|
|
7298
7355
|
try {
|
|
7299
7356
|
r.current.setShowFullAvatar(!0), r.current.playReaction(k), console.log("Reaction played with full body mode:", k);
|
|
7300
|
-
} catch (
|
|
7301
|
-
console.warn("Error playing reaction:",
|
|
7357
|
+
} catch (F) {
|
|
7358
|
+
console.warn("Error playing reaction:", F);
|
|
7302
7359
|
}
|
|
7303
7360
|
},
|
|
7304
7361
|
playCelebration: () => {
|
|
@@ -7313,8 +7370,8 @@ const pt = Me(({
|
|
|
7313
7370
|
if (r.current && r.current.setShowFullAvatar)
|
|
7314
7371
|
try {
|
|
7315
7372
|
r.current.setShowFullAvatar(k), console.log("Show full avatar set to:", k);
|
|
7316
|
-
} catch (
|
|
7317
|
-
console.warn("Error setting showFullAvatar:",
|
|
7373
|
+
} catch (F) {
|
|
7374
|
+
console.warn("Error setting showFullAvatar:", F);
|
|
7318
7375
|
}
|
|
7319
7376
|
},
|
|
7320
7377
|
lockAvatarPosition: () => {
|
|
@@ -7334,7 +7391,7 @@ const pt = Me(({
|
|
|
7334
7391
|
}
|
|
7335
7392
|
}
|
|
7336
7393
|
})), /* @__PURE__ */ Pe("div", { className: `talking-head-container ${i}`, style: s, children: [
|
|
7337
|
-
/* @__PURE__ */
|
|
7394
|
+
/* @__PURE__ */ pe(
|
|
7338
7395
|
"div",
|
|
7339
7396
|
{
|
|
7340
7397
|
ref: h,
|
|
@@ -7346,7 +7403,7 @@ const pt = Me(({
|
|
|
7346
7403
|
}
|
|
7347
7404
|
}
|
|
7348
7405
|
),
|
|
7349
|
-
u && /* @__PURE__ */
|
|
7406
|
+
u && /* @__PURE__ */ pe("div", { className: "loading-overlay", style: {
|
|
7350
7407
|
position: "absolute",
|
|
7351
7408
|
top: "50%",
|
|
7352
7409
|
left: "50%",
|
|
@@ -7355,7 +7412,7 @@ const pt = Me(({
|
|
|
7355
7412
|
fontSize: "18px",
|
|
7356
7413
|
zIndex: 10
|
|
7357
7414
|
}, children: "Loading avatar..." }),
|
|
7358
|
-
|
|
7415
|
+
d && /* @__PURE__ */ pe("div", { className: "error-overlay", style: {
|
|
7359
7416
|
position: "absolute",
|
|
7360
7417
|
top: "50%",
|
|
7361
7418
|
left: "50%",
|
|
@@ -7366,12 +7423,12 @@ const pt = Me(({
|
|
|
7366
7423
|
zIndex: 10,
|
|
7367
7424
|
padding: "20px",
|
|
7368
7425
|
borderRadius: "8px"
|
|
7369
|
-
}, children:
|
|
7426
|
+
}, children: d })
|
|
7370
7427
|
] });
|
|
7371
7428
|
});
|
|
7372
7429
|
pt.displayName = "TalkingHeadComponent";
|
|
7373
7430
|
const gt = Me(({
|
|
7374
|
-
text:
|
|
7431
|
+
text: Y = null,
|
|
7375
7432
|
avatarUrl: t = "/avatars/brunette.glb",
|
|
7376
7433
|
avatarBody: e = "F",
|
|
7377
7434
|
mood: n = "neutral",
|
|
@@ -7383,26 +7440,26 @@ const gt = Me(({
|
|
|
7383
7440
|
movementIntensity: r = 0.5,
|
|
7384
7441
|
showFullAvatar: u = !1,
|
|
7385
7442
|
cameraView: a = "upper",
|
|
7386
|
-
onReady:
|
|
7443
|
+
onReady: d = () => {
|
|
7387
7444
|
},
|
|
7388
|
-
onLoading:
|
|
7445
|
+
onLoading: c = () => {
|
|
7389
7446
|
},
|
|
7390
7447
|
onError: g = () => {
|
|
7391
7448
|
},
|
|
7392
7449
|
onSpeechEnd: b = () => {
|
|
7393
7450
|
},
|
|
7394
7451
|
className: x = "",
|
|
7395
|
-
style:
|
|
7396
|
-
animations:
|
|
7452
|
+
style: S = {},
|
|
7453
|
+
animations: V = {},
|
|
7397
7454
|
autoSpeak: p = !1
|
|
7398
|
-
},
|
|
7399
|
-
const
|
|
7400
|
-
|
|
7401
|
-
|
|
7402
|
-
}, [
|
|
7403
|
-
|
|
7455
|
+
}, P) => {
|
|
7456
|
+
const C = W(null), y = W(null), I = W(u), z = W(null), A = W(null), j = W(!1), k = W({ remainingText: null, originalText: null, options: null }), F = W([]), [_, B] = de(!0), [$, ie] = de(null), [oe, le] = de(!1), [Z, ne] = de(!1);
|
|
7457
|
+
me(() => {
|
|
7458
|
+
j.current = Z;
|
|
7459
|
+
}, [Z]), me(() => {
|
|
7460
|
+
I.current = u;
|
|
7404
7461
|
}, [u]);
|
|
7405
|
-
const
|
|
7462
|
+
const O = Ee(), v = s || O.service;
|
|
7406
7463
|
let R;
|
|
7407
7464
|
v === "browser" ? R = {
|
|
7408
7465
|
service: "browser",
|
|
@@ -7412,20 +7469,20 @@ const gt = Me(({
|
|
|
7412
7469
|
} : v === "elevenlabs" ? R = {
|
|
7413
7470
|
service: "elevenlabs",
|
|
7414
7471
|
endpoint: "https://api.elevenlabs.io/v1/text-to-speech",
|
|
7415
|
-
apiKey: l ||
|
|
7416
|
-
defaultVoice: o ||
|
|
7417
|
-
voices:
|
|
7472
|
+
apiKey: l || O.apiKey,
|
|
7473
|
+
defaultVoice: o || O.defaultVoice || Ie.defaultVoice,
|
|
7474
|
+
voices: O.voices || Ie.voices
|
|
7418
7475
|
} : v === "deepgram" ? R = {
|
|
7419
7476
|
service: "deepgram",
|
|
7420
7477
|
endpoint: "https://api.deepgram.com/v1/speak",
|
|
7421
|
-
apiKey: l ||
|
|
7422
|
-
defaultVoice: o ||
|
|
7423
|
-
voices:
|
|
7478
|
+
apiKey: l || O.apiKey,
|
|
7479
|
+
defaultVoice: o || O.defaultVoice || Te.defaultVoice,
|
|
7480
|
+
voices: O.voices || Te.voices
|
|
7424
7481
|
} : R = {
|
|
7425
|
-
...
|
|
7426
|
-
apiKey: l !== null ? l :
|
|
7482
|
+
...O,
|
|
7483
|
+
apiKey: l !== null ? l : O.apiKey
|
|
7427
7484
|
};
|
|
7428
|
-
const
|
|
7485
|
+
const H = {
|
|
7429
7486
|
url: t,
|
|
7430
7487
|
body: e,
|
|
7431
7488
|
avatarMood: n,
|
|
@@ -7441,121 +7498,121 @@ const gt = Me(({
|
|
|
7441
7498
|
ttsService: v,
|
|
7442
7499
|
lipsyncModules: ["en"],
|
|
7443
7500
|
cameraView: a
|
|
7444
|
-
},
|
|
7445
|
-
if (!(!
|
|
7501
|
+
}, G = N(async () => {
|
|
7502
|
+
if (!(!C.current || y.current))
|
|
7446
7503
|
try {
|
|
7447
|
-
|
|
7448
|
-
url:
|
|
7449
|
-
body:
|
|
7450
|
-
avatarMood:
|
|
7451
|
-
}), await y.current.showAvatar(
|
|
7452
|
-
if (
|
|
7453
|
-
const L = Math.min(100, Math.round(
|
|
7454
|
-
|
|
7504
|
+
B(!0), ie(null), y.current = new Be(C.current, M), console.log("Avatar config being passed:", {
|
|
7505
|
+
url: H.url,
|
|
7506
|
+
body: H.body,
|
|
7507
|
+
avatarMood: H.avatarMood
|
|
7508
|
+
}), await y.current.showAvatar(H, (se) => {
|
|
7509
|
+
if (se.lengthComputable) {
|
|
7510
|
+
const L = Math.min(100, Math.round(se.loaded / se.total * 100));
|
|
7511
|
+
c(L);
|
|
7455
7512
|
}
|
|
7456
|
-
}), y.current?.avatar && console.log("Avatar body after initialization:", y.current.avatar.body),
|
|
7457
|
-
const
|
|
7513
|
+
}), y.current?.avatar && console.log("Avatar body after initialization:", y.current.avatar.body), B(!1), le(!0), d(y.current);
|
|
7514
|
+
const E = () => {
|
|
7458
7515
|
document.visibilityState === "visible" ? y.current?.start() : y.current?.stop();
|
|
7459
7516
|
};
|
|
7460
|
-
return document.addEventListener("visibilitychange",
|
|
7461
|
-
document.removeEventListener("visibilitychange",
|
|
7517
|
+
return document.addEventListener("visibilitychange", E), () => {
|
|
7518
|
+
document.removeEventListener("visibilitychange", E);
|
|
7462
7519
|
};
|
|
7463
|
-
} catch (
|
|
7464
|
-
console.error("Error initializing TalkingHead:",
|
|
7520
|
+
} catch (E) {
|
|
7521
|
+
console.error("Error initializing TalkingHead:", E), ie(E.message || "Failed to initialize avatar"), B(!1), g(E);
|
|
7465
7522
|
}
|
|
7466
7523
|
}, []);
|
|
7467
|
-
|
|
7524
|
+
me(() => (G(), () => {
|
|
7468
7525
|
y.current && (y.current.stop(), y.current.dispose(), y.current = null);
|
|
7469
|
-
}), [
|
|
7470
|
-
const
|
|
7526
|
+
}), [G]);
|
|
7527
|
+
const ee = N(async () => {
|
|
7471
7528
|
if (y.current)
|
|
7472
7529
|
try {
|
|
7473
|
-
const
|
|
7474
|
-
|
|
7475
|
-
} catch (
|
|
7476
|
-
console.warn("Failed to resume audio context:",
|
|
7530
|
+
const E = y.current.audioCtx || y.current.audioContext;
|
|
7531
|
+
E && (E.state === "suspended" || E.state === "interrupted") && (await E.resume(), console.log("Audio context resumed"));
|
|
7532
|
+
} catch (E) {
|
|
7533
|
+
console.warn("Failed to resume audio context:", E);
|
|
7477
7534
|
}
|
|
7478
|
-
}, []),
|
|
7479
|
-
if (!y.current || !
|
|
7535
|
+
}, []), q = N(async (E, se = {}) => {
|
|
7536
|
+
if (!y.current || !oe) {
|
|
7480
7537
|
console.warn("Avatar not ready for speaking");
|
|
7481
7538
|
return;
|
|
7482
7539
|
}
|
|
7483
|
-
if (!
|
|
7540
|
+
if (!E || E.trim() === "") {
|
|
7484
7541
|
console.warn("No text provided to speak");
|
|
7485
7542
|
return;
|
|
7486
7543
|
}
|
|
7487
|
-
await
|
|
7488
|
-
const L =
|
|
7489
|
-
|
|
7490
|
-
const
|
|
7491
|
-
lipsyncLang:
|
|
7544
|
+
await ee(), k.current = { remainingText: null, originalText: null, options: null }, F.current = [], z.current = { text: E, options: se }, A.current && (clearInterval(A.current), A.current = null), ne(!1), j.current = !1;
|
|
7545
|
+
const L = E.split(/[.!?]+/).filter((U) => U.trim().length > 0);
|
|
7546
|
+
F.current = L;
|
|
7547
|
+
const D = {
|
|
7548
|
+
lipsyncLang: se.lipsyncLang || "en",
|
|
7492
7549
|
onSpeechEnd: () => {
|
|
7493
|
-
|
|
7550
|
+
A.current && (clearInterval(A.current), A.current = null), se.onSpeechEnd && se.onSpeechEnd(), b();
|
|
7494
7551
|
}
|
|
7495
7552
|
};
|
|
7496
7553
|
try {
|
|
7497
|
-
y.current.speakText(
|
|
7498
|
-
} catch (
|
|
7499
|
-
console.error("Error speaking text:",
|
|
7554
|
+
y.current.speakText(E, D);
|
|
7555
|
+
} catch (U) {
|
|
7556
|
+
console.error("Error speaking text:", U), ie(U.message || "Failed to speak text");
|
|
7500
7557
|
}
|
|
7501
|
-
}, [
|
|
7502
|
-
|
|
7503
|
-
|
|
7504
|
-
}, [
|
|
7505
|
-
const
|
|
7558
|
+
}, [oe, b, ee]);
|
|
7559
|
+
me(() => {
|
|
7560
|
+
oe && Y && p && y.current && q(Y);
|
|
7561
|
+
}, [oe, Y, p, q]);
|
|
7562
|
+
const J = N(() => {
|
|
7506
7563
|
if (y.current)
|
|
7507
7564
|
try {
|
|
7508
|
-
const
|
|
7509
|
-
if (
|
|
7510
|
-
|
|
7511
|
-
let
|
|
7512
|
-
L.length > 0 && (
|
|
7513
|
-
remainingText:
|
|
7514
|
-
originalText:
|
|
7515
|
-
options:
|
|
7516
|
-
}, y.current.speechQueue.length = 0, y.current.pauseSpeaking(),
|
|
7565
|
+
const E = y.current.isSpeaking || !1, se = y.current.audioPlaylist || [], L = y.current.speechQueue || [];
|
|
7566
|
+
if (E || se.length > 0 || L.length > 0) {
|
|
7567
|
+
A.current && (clearInterval(A.current), A.current = null);
|
|
7568
|
+
let D = "";
|
|
7569
|
+
L.length > 0 && (D = L.map((U) => U.text && Array.isArray(U.text) ? U.text.map((te) => te.word).join(" ") : U.text || "").join(" ")), k.current = {
|
|
7570
|
+
remainingText: D || null,
|
|
7571
|
+
originalText: z.current?.text || null,
|
|
7572
|
+
options: z.current?.options || null
|
|
7573
|
+
}, y.current.speechQueue.length = 0, y.current.pauseSpeaking(), ne(!0), j.current = !0;
|
|
7517
7574
|
}
|
|
7518
|
-
} catch (
|
|
7519
|
-
console.warn("Error pausing speech:",
|
|
7575
|
+
} catch (E) {
|
|
7576
|
+
console.warn("Error pausing speech:", E);
|
|
7520
7577
|
}
|
|
7521
|
-
}, []),
|
|
7522
|
-
if (!(!y.current || !
|
|
7578
|
+
}, []), Ae = N(async () => {
|
|
7579
|
+
if (!(!y.current || !Z))
|
|
7523
7580
|
try {
|
|
7524
|
-
await
|
|
7525
|
-
const
|
|
7526
|
-
|
|
7527
|
-
} catch (
|
|
7528
|
-
console.warn("Error resuming speech:",
|
|
7581
|
+
await ee(), ne(!1), j.current = !1;
|
|
7582
|
+
const E = k.current?.remainingText, se = k.current?.originalText || z.current?.text, L = k.current?.options || z.current?.options || {}, D = E || se;
|
|
7583
|
+
D && q(D, L);
|
|
7584
|
+
} catch (E) {
|
|
7585
|
+
console.warn("Error resuming speech:", E), ne(!1), j.current = !1;
|
|
7529
7586
|
}
|
|
7530
|
-
}, [
|
|
7531
|
-
y.current && (y.current.stopSpeaking(),
|
|
7587
|
+
}, [Z, q, ee]), we = N(() => {
|
|
7588
|
+
y.current && (y.current.stopSpeaking(), A.current && (clearInterval(A.current), A.current = null), ne(!1), j.current = !1);
|
|
7532
7589
|
}, []);
|
|
7533
|
-
return
|
|
7534
|
-
speakText:
|
|
7535
|
-
pauseSpeaking:
|
|
7536
|
-
resumeSpeaking:
|
|
7590
|
+
return Fe(P, () => ({
|
|
7591
|
+
speakText: q,
|
|
7592
|
+
pauseSpeaking: J,
|
|
7593
|
+
resumeSpeaking: Ae,
|
|
7537
7594
|
stopSpeaking: we,
|
|
7538
|
-
resumeAudioContext:
|
|
7539
|
-
isPaused: () =>
|
|
7540
|
-
setMood: (
|
|
7541
|
-
setBodyMovement: (
|
|
7542
|
-
y.current && y.current.setBodyMovement(
|
|
7595
|
+
resumeAudioContext: ee,
|
|
7596
|
+
isPaused: () => Z,
|
|
7597
|
+
setMood: (E) => y.current?.setMood(E),
|
|
7598
|
+
setBodyMovement: (E) => {
|
|
7599
|
+
y.current && y.current.setBodyMovement(E);
|
|
7543
7600
|
},
|
|
7544
|
-
playAnimation: (
|
|
7545
|
-
y.current && y.current.playAnimation && y.current.playAnimation(
|
|
7601
|
+
playAnimation: (E, se = !1) => {
|
|
7602
|
+
y.current && y.current.playAnimation && y.current.playAnimation(E, null, 10, 0, 0.01, se);
|
|
7546
7603
|
},
|
|
7547
|
-
playReaction: (
|
|
7604
|
+
playReaction: (E) => y.current?.playReaction(E),
|
|
7548
7605
|
playCelebration: () => y.current?.playCelebration(),
|
|
7549
|
-
setShowFullAvatar: (
|
|
7550
|
-
y.current && (
|
|
7606
|
+
setShowFullAvatar: (E) => {
|
|
7607
|
+
y.current && (I.current = E, y.current.setShowFullAvatar(E));
|
|
7551
7608
|
},
|
|
7552
|
-
isReady:
|
|
7609
|
+
isReady: oe,
|
|
7553
7610
|
talkingHead: y.current
|
|
7554
|
-
})), /* @__PURE__ */ Pe("div", { className: `simple-talking-avatar-container ${x}`, style:
|
|
7555
|
-
/* @__PURE__ */
|
|
7611
|
+
})), /* @__PURE__ */ Pe("div", { className: `simple-talking-avatar-container ${x}`, style: S, children: [
|
|
7612
|
+
/* @__PURE__ */ pe(
|
|
7556
7613
|
"div",
|
|
7557
7614
|
{
|
|
7558
|
-
ref:
|
|
7615
|
+
ref: C,
|
|
7559
7616
|
className: "talking-head-viewer",
|
|
7560
7617
|
style: {
|
|
7561
7618
|
width: "100%",
|
|
@@ -7564,7 +7621,7 @@ const gt = Me(({
|
|
|
7564
7621
|
}
|
|
7565
7622
|
}
|
|
7566
7623
|
),
|
|
7567
|
-
|
|
7624
|
+
_ && /* @__PURE__ */ pe("div", { className: "loading-overlay", style: {
|
|
7568
7625
|
position: "absolute",
|
|
7569
7626
|
top: "50%",
|
|
7570
7627
|
left: "50%",
|
|
@@ -7573,7 +7630,7 @@ const gt = Me(({
|
|
|
7573
7630
|
fontSize: "18px",
|
|
7574
7631
|
zIndex: 10
|
|
7575
7632
|
}, children: "Loading avatar..." }),
|
|
7576
|
-
|
|
7633
|
+
$ && /* @__PURE__ */ pe("div", { className: "error-overlay", style: {
|
|
7577
7634
|
position: "absolute",
|
|
7578
7635
|
top: "50%",
|
|
7579
7636
|
left: "50%",
|
|
@@ -7584,12 +7641,12 @@ const gt = Me(({
|
|
|
7584
7641
|
zIndex: 10,
|
|
7585
7642
|
padding: "20px",
|
|
7586
7643
|
borderRadius: "8px"
|
|
7587
|
-
}, children:
|
|
7644
|
+
}, children: $ })
|
|
7588
7645
|
] });
|
|
7589
7646
|
});
|
|
7590
7647
|
gt.displayName = "SimpleTalkingAvatar";
|
|
7591
7648
|
const yt = Me(({
|
|
7592
|
-
curriculumData:
|
|
7649
|
+
curriculumData: Y = null,
|
|
7593
7650
|
avatarConfig: t = {},
|
|
7594
7651
|
animations: e = {},
|
|
7595
7652
|
onLessonStart: n = () => {
|
|
@@ -7604,7 +7661,7 @@ const yt = Me(({
|
|
|
7604
7661
|
},
|
|
7605
7662
|
autoStart: h = !1
|
|
7606
7663
|
}, r) => {
|
|
7607
|
-
const u =
|
|
7664
|
+
const u = W(null), a = W({
|
|
7608
7665
|
currentModuleIndex: 0,
|
|
7609
7666
|
currentLessonIndex: 0,
|
|
7610
7667
|
currentQuestionIndex: 0,
|
|
@@ -7614,18 +7671,18 @@ const yt = Me(({
|
|
|
7614
7671
|
curriculumCompleted: !1,
|
|
7615
7672
|
score: 0,
|
|
7616
7673
|
totalQuestions: 0
|
|
7617
|
-
}),
|
|
7674
|
+
}), d = W({
|
|
7618
7675
|
onLessonStart: n,
|
|
7619
7676
|
onLessonComplete: i,
|
|
7620
7677
|
onQuestionAnswer: s,
|
|
7621
7678
|
onCurriculumComplete: o,
|
|
7622
7679
|
onCustomAction: l
|
|
7623
|
-
}),
|
|
7680
|
+
}), c = W(null), g = W(null), b = W(null), x = W(null), S = W(null), V = W(null), p = W(null), P = W(Y?.curriculum || {
|
|
7624
7681
|
title: "Default Curriculum",
|
|
7625
7682
|
description: "No curriculum data provided",
|
|
7626
7683
|
language: "en",
|
|
7627
7684
|
modules: []
|
|
7628
|
-
}),
|
|
7685
|
+
}), C = W({
|
|
7629
7686
|
avatarUrl: t.avatarUrl || "/avatars/brunette.glb",
|
|
7630
7687
|
avatarBody: t.avatarBody || "F",
|
|
7631
7688
|
mood: t.mood || "happy",
|
|
@@ -7639,21 +7696,21 @@ const yt = Me(({
|
|
|
7639
7696
|
animations: e,
|
|
7640
7697
|
lipsyncLang: "en"
|
|
7641
7698
|
});
|
|
7642
|
-
|
|
7643
|
-
|
|
7699
|
+
me(() => {
|
|
7700
|
+
d.current = {
|
|
7644
7701
|
onLessonStart: n,
|
|
7645
7702
|
onLessonComplete: i,
|
|
7646
7703
|
onQuestionAnswer: s,
|
|
7647
7704
|
onCurriculumComplete: o,
|
|
7648
7705
|
onCustomAction: l
|
|
7649
7706
|
};
|
|
7650
|
-
}, [n, i, s, o, l]),
|
|
7651
|
-
|
|
7707
|
+
}, [n, i, s, o, l]), me(() => {
|
|
7708
|
+
P.current = Y?.curriculum || {
|
|
7652
7709
|
title: "Default Curriculum",
|
|
7653
7710
|
description: "No curriculum data provided",
|
|
7654
7711
|
language: "en",
|
|
7655
7712
|
modules: []
|
|
7656
|
-
},
|
|
7713
|
+
}, C.current = {
|
|
7657
7714
|
avatarUrl: t.avatarUrl || "/avatars/brunette.glb",
|
|
7658
7715
|
avatarBody: t.avatarBody || "F",
|
|
7659
7716
|
mood: t.mood || "happy",
|
|
@@ -7667,18 +7724,18 @@ const yt = Me(({
|
|
|
7667
7724
|
animations: e,
|
|
7668
7725
|
lipsyncLang: "en"
|
|
7669
7726
|
};
|
|
7670
|
-
}, [
|
|
7671
|
-
const y =
|
|
7727
|
+
}, [Y, t, e]);
|
|
7728
|
+
const y = N(() => (P.current || { modules: [] }).modules[a.current.currentModuleIndex]?.lessons[a.current.currentLessonIndex], []), I = N(() => y()?.questions[a.current.currentQuestionIndex], [y]), z = N((v, R) => R.type === "multiple_choice" || R.type === "true_false" ? v === R.answer : R.type === "code_test" && typeof v == "object" && v !== null ? v.passed === !0 : !1, []), A = N(() => {
|
|
7672
7729
|
a.current.lessonCompleted = !0, a.current.isQuestionMode = !1;
|
|
7673
7730
|
const v = a.current.totalQuestions > 0 ? Math.round(a.current.score / a.current.totalQuestions * 100) : 100;
|
|
7674
7731
|
let R = "Congratulations! You've completed this lesson";
|
|
7675
|
-
if (a.current.totalQuestions > 0 ? R += ` You got ${a.current.score} correct out of ${a.current.totalQuestions} question${a.current.totalQuestions === 1 ? "" : "s"}, achieving a score of ${v} percent. ` : R += "! ", v >= 80 ? R += "Excellent work! You have a great understanding of this topic." : v >= 60 ? R += "Good job! You understand most of the concepts." : R += "Keep practicing! You're making progress.",
|
|
7732
|
+
if (a.current.totalQuestions > 0 ? R += ` You got ${a.current.score} correct out of ${a.current.totalQuestions} question${a.current.totalQuestions === 1 ? "" : "s"}, achieving a score of ${v} percent. ` : R += "! ", v >= 80 ? R += "Excellent work! You have a great understanding of this topic." : v >= 60 ? R += "Good job! You understand most of the concepts." : R += "Keep practicing! You're making progress.", d.current.onLessonComplete({
|
|
7676
7733
|
moduleIndex: a.current.currentModuleIndex,
|
|
7677
7734
|
lessonIndex: a.current.currentLessonIndex,
|
|
7678
7735
|
score: a.current.score,
|
|
7679
7736
|
totalQuestions: a.current.totalQuestions,
|
|
7680
7737
|
percentage: v
|
|
7681
|
-
}),
|
|
7738
|
+
}), d.current.onCustomAction({
|
|
7682
7739
|
type: "lessonComplete",
|
|
7683
7740
|
moduleIndex: a.current.currentModuleIndex,
|
|
7684
7741
|
lessonIndex: a.current.currentLessonIndex,
|
|
@@ -7692,28 +7749,28 @@ const yt = Me(({
|
|
|
7692
7749
|
} catch {
|
|
7693
7750
|
u.current.playCelebration();
|
|
7694
7751
|
}
|
|
7695
|
-
const
|
|
7752
|
+
const H = P.current || { modules: [] }, M = H.modules[a.current.currentModuleIndex], G = a.current.currentLessonIndex < (M?.lessons?.length || 0) - 1, ee = a.current.currentModuleIndex < (H.modules?.length || 0) - 1, q = G || ee, J = C.current || { lipsyncLang: "en" };
|
|
7696
7753
|
u.current.speakText(R, {
|
|
7697
|
-
lipsyncLang:
|
|
7754
|
+
lipsyncLang: J.lipsyncLang,
|
|
7698
7755
|
onSpeechEnd: () => {
|
|
7699
|
-
|
|
7756
|
+
d.current.onCustomAction({
|
|
7700
7757
|
type: "lessonCompleteFeedbackDone",
|
|
7701
7758
|
moduleIndex: a.current.currentModuleIndex,
|
|
7702
7759
|
lessonIndex: a.current.currentLessonIndex,
|
|
7703
7760
|
score: a.current.score,
|
|
7704
7761
|
totalQuestions: a.current.totalQuestions,
|
|
7705
7762
|
percentage: v,
|
|
7706
|
-
hasNextLesson:
|
|
7763
|
+
hasNextLesson: q
|
|
7707
7764
|
});
|
|
7708
7765
|
}
|
|
7709
7766
|
});
|
|
7710
7767
|
}
|
|
7711
|
-
}, [e.lessonComplete]),
|
|
7768
|
+
}, [e.lessonComplete]), j = N(() => {
|
|
7712
7769
|
a.current.curriculumCompleted = !0;
|
|
7713
|
-
const v =
|
|
7714
|
-
if (
|
|
7770
|
+
const v = P.current || { modules: [] };
|
|
7771
|
+
if (d.current.onCurriculumComplete({
|
|
7715
7772
|
modules: v.modules.length,
|
|
7716
|
-
totalLessons: v.modules.reduce((R,
|
|
7773
|
+
totalLessons: v.modules.reduce((R, H) => R + H.lessons.length, 0)
|
|
7717
7774
|
}), u.current) {
|
|
7718
7775
|
if (u.current.setMood("celebrating"), e.curriculumComplete)
|
|
7719
7776
|
try {
|
|
@@ -7721,14 +7778,14 @@ const yt = Me(({
|
|
|
7721
7778
|
} catch {
|
|
7722
7779
|
u.current.playCelebration();
|
|
7723
7780
|
}
|
|
7724
|
-
const R =
|
|
7781
|
+
const R = C.current || { lipsyncLang: "en" };
|
|
7725
7782
|
u.current.speakText("Amazing! You've completed the entire curriculum! You're now ready to move on to more advanced topics. Well done!", { lipsyncLang: R.lipsyncLang });
|
|
7726
7783
|
}
|
|
7727
|
-
}, [e.curriculumComplete]), k =
|
|
7784
|
+
}, [e.curriculumComplete]), k = N(() => {
|
|
7728
7785
|
const v = y();
|
|
7729
7786
|
a.current.isQuestionMode = !0, a.current.currentQuestionIndex = 0, a.current.totalQuestions = v?.questions?.length || 0, a.current.score = 0;
|
|
7730
|
-
const R =
|
|
7731
|
-
R &&
|
|
7787
|
+
const R = I();
|
|
7788
|
+
R && d.current.onCustomAction({
|
|
7732
7789
|
type: "questionStart",
|
|
7733
7790
|
moduleIndex: a.current.currentModuleIndex,
|
|
7734
7791
|
lessonIndex: a.current.currentLessonIndex,
|
|
@@ -7737,36 +7794,36 @@ const yt = Me(({
|
|
|
7737
7794
|
question: R,
|
|
7738
7795
|
score: a.current.score
|
|
7739
7796
|
});
|
|
7740
|
-
const
|
|
7797
|
+
const H = () => {
|
|
7741
7798
|
if (!u.current || !R) return;
|
|
7742
7799
|
if (u.current.setMood("happy"), e.questionStart)
|
|
7743
7800
|
try {
|
|
7744
7801
|
u.current.playAnimation(e.questionStart, !0);
|
|
7745
|
-
} catch (
|
|
7746
|
-
console.warn("Failed to play questionStart animation:",
|
|
7802
|
+
} catch (G) {
|
|
7803
|
+
console.warn("Failed to play questionStart animation:", G);
|
|
7747
7804
|
}
|
|
7748
|
-
const M =
|
|
7805
|
+
const M = C.current || { lipsyncLang: "en" };
|
|
7749
7806
|
R.type === "code_test" ? u.current.speakText(`Let's test your coding skills! Here's your first challenge: ${R.question}`, { lipsyncLang: M.lipsyncLang }) : R.type === "multiple_choice" ? u.current.speakText(`Now let me ask you some questions. Here's the first one: ${R.question}`, { lipsyncLang: M.lipsyncLang }) : R.type === "true_false" ? u.current.speakText(`Let's start with some true or false questions. First question: ${R.question}`, { lipsyncLang: M.lipsyncLang }) : u.current.speakText(`Now let me ask you some questions. Here's the first one: ${R.question}`, { lipsyncLang: M.lipsyncLang });
|
|
7750
7807
|
};
|
|
7751
7808
|
if (u.current && u.current.isReady && R)
|
|
7752
|
-
|
|
7809
|
+
H();
|
|
7753
7810
|
else if (u.current && u.current.isReady) {
|
|
7754
|
-
const M =
|
|
7811
|
+
const M = C.current || { lipsyncLang: "en" };
|
|
7755
7812
|
u.current.speakText("Now let me ask you some questions to test your understanding.", { lipsyncLang: M.lipsyncLang });
|
|
7756
7813
|
} else {
|
|
7757
7814
|
const M = setInterval(() => {
|
|
7758
|
-
u.current && u.current.isReady && (clearInterval(M), R &&
|
|
7815
|
+
u.current && u.current.isReady && (clearInterval(M), R && H());
|
|
7759
7816
|
}, 100);
|
|
7760
7817
|
setTimeout(() => {
|
|
7761
7818
|
clearInterval(M);
|
|
7762
7819
|
}, 5e3);
|
|
7763
7820
|
}
|
|
7764
|
-
}, [e.questionStart, y,
|
|
7821
|
+
}, [e.questionStart, y, I]), F = N(() => {
|
|
7765
7822
|
const v = y();
|
|
7766
7823
|
if (a.current.currentQuestionIndex < (v?.questions?.length || 0) - 1) {
|
|
7767
7824
|
u.current && u.current.stopSpeaking && u.current.stopSpeaking(), a.current.currentQuestionIndex += 1;
|
|
7768
|
-
const R =
|
|
7769
|
-
R &&
|
|
7825
|
+
const R = I();
|
|
7826
|
+
R && d.current.onCustomAction({
|
|
7770
7827
|
type: "nextQuestion",
|
|
7771
7828
|
moduleIndex: a.current.currentModuleIndex,
|
|
7772
7829
|
lessonIndex: a.current.currentLessonIndex,
|
|
@@ -7775,109 +7832,109 @@ const yt = Me(({
|
|
|
7775
7832
|
question: R,
|
|
7776
7833
|
score: a.current.score
|
|
7777
7834
|
});
|
|
7778
|
-
const
|
|
7835
|
+
const H = () => {
|
|
7779
7836
|
if (!u.current || !R) return;
|
|
7780
7837
|
if (u.current.setMood("happy"), u.current.setBodyMovement("idle"), e.nextQuestion)
|
|
7781
7838
|
try {
|
|
7782
7839
|
u.current.playAnimation(e.nextQuestion, !0);
|
|
7783
|
-
} catch (
|
|
7784
|
-
console.warn("Failed to play nextQuestion animation:",
|
|
7840
|
+
} catch (J) {
|
|
7841
|
+
console.warn("Failed to play nextQuestion animation:", J);
|
|
7785
7842
|
}
|
|
7786
|
-
const M =
|
|
7843
|
+
const M = C.current || { lipsyncLang: "en" }, ee = y()?.questions?.length || 0, q = a.current.currentQuestionIndex >= ee - 1;
|
|
7787
7844
|
if (R.type === "code_test") {
|
|
7788
|
-
const
|
|
7789
|
-
u.current.speakText(
|
|
7845
|
+
const J = q ? `Great! Here's your final coding challenge: ${R.question}` : `Great! Now let's move on to your next coding challenge: ${R.question}`;
|
|
7846
|
+
u.current.speakText(J, {
|
|
7790
7847
|
lipsyncLang: M.lipsyncLang
|
|
7791
7848
|
});
|
|
7792
7849
|
} else if (R.type === "multiple_choice") {
|
|
7793
|
-
const
|
|
7794
|
-
u.current.speakText(
|
|
7850
|
+
const J = q ? `Alright! Here's your final question: ${R.question}` : `Alright! Here's your next question: ${R.question}`;
|
|
7851
|
+
u.current.speakText(J, {
|
|
7795
7852
|
lipsyncLang: M.lipsyncLang
|
|
7796
7853
|
});
|
|
7797
7854
|
} else if (R.type === "true_false") {
|
|
7798
|
-
const
|
|
7799
|
-
u.current.speakText(
|
|
7855
|
+
const J = q ? `Now let's try this final one: ${R.question}` : `Now let's try this one: ${R.question}`;
|
|
7856
|
+
u.current.speakText(J, {
|
|
7800
7857
|
lipsyncLang: M.lipsyncLang
|
|
7801
7858
|
});
|
|
7802
7859
|
} else {
|
|
7803
|
-
const
|
|
7804
|
-
u.current.speakText(
|
|
7860
|
+
const J = q ? `Here's your final question: ${R.question}` : `Here's the next question: ${R.question}`;
|
|
7861
|
+
u.current.speakText(J, {
|
|
7805
7862
|
lipsyncLang: M.lipsyncLang
|
|
7806
7863
|
});
|
|
7807
7864
|
}
|
|
7808
7865
|
};
|
|
7809
7866
|
if (u.current && u.current.isReady && R)
|
|
7810
|
-
|
|
7867
|
+
H();
|
|
7811
7868
|
else if (R) {
|
|
7812
7869
|
const M = setInterval(() => {
|
|
7813
|
-
u.current && u.current.isReady && (clearInterval(M),
|
|
7870
|
+
u.current && u.current.isReady && (clearInterval(M), H());
|
|
7814
7871
|
}, 100);
|
|
7815
7872
|
setTimeout(() => {
|
|
7816
7873
|
clearInterval(M);
|
|
7817
7874
|
}, 5e3);
|
|
7818
7875
|
}
|
|
7819
7876
|
} else
|
|
7820
|
-
|
|
7877
|
+
d.current.onCustomAction({
|
|
7821
7878
|
type: "allQuestionsComplete",
|
|
7822
7879
|
moduleIndex: a.current.currentModuleIndex,
|
|
7823
7880
|
lessonIndex: a.current.currentLessonIndex,
|
|
7824
7881
|
totalQuestions: a.current.totalQuestions,
|
|
7825
7882
|
score: a.current.score
|
|
7826
7883
|
});
|
|
7827
|
-
}, [e.nextQuestion, y,
|
|
7828
|
-
const v =
|
|
7884
|
+
}, [e.nextQuestion, y, I]), _ = N(() => {
|
|
7885
|
+
const v = P.current || { modules: [] }, R = v.modules[a.current.currentModuleIndex];
|
|
7829
7886
|
if (a.current.currentLessonIndex < (R?.lessons?.length || 0) - 1) {
|
|
7830
7887
|
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;
|
|
7831
|
-
const M = v.modules[a.current.currentModuleIndex],
|
|
7832
|
-
|
|
7888
|
+
const M = v.modules[a.current.currentModuleIndex], G = a.current.currentLessonIndex < (M?.lessons?.length || 0) - 1, ee = a.current.currentModuleIndex < (v.modules?.length || 0) - 1, q = G || ee;
|
|
7889
|
+
d.current.onCustomAction({
|
|
7833
7890
|
type: "lessonStart",
|
|
7834
7891
|
moduleIndex: a.current.currentModuleIndex,
|
|
7835
7892
|
lessonIndex: a.current.currentLessonIndex,
|
|
7836
|
-
hasNextLesson:
|
|
7837
|
-
}),
|
|
7893
|
+
hasNextLesson: q
|
|
7894
|
+
}), d.current.onLessonStart({
|
|
7838
7895
|
moduleIndex: a.current.currentModuleIndex,
|
|
7839
7896
|
lessonIndex: a.current.currentLessonIndex,
|
|
7840
7897
|
lesson: y()
|
|
7841
7898
|
}), u.current && (u.current.setMood("happy"), u.current.setBodyMovement("idle"));
|
|
7842
7899
|
} else if (a.current.currentModuleIndex < (v.modules?.length || 0) - 1) {
|
|
7843
7900
|
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;
|
|
7844
|
-
const
|
|
7845
|
-
|
|
7901
|
+
const G = v.modules[a.current.currentModuleIndex], ee = a.current.currentLessonIndex < (G?.lessons?.length || 0) - 1, q = a.current.currentModuleIndex < (v.modules?.length || 0) - 1, J = ee || q;
|
|
7902
|
+
d.current.onCustomAction({
|
|
7846
7903
|
type: "lessonStart",
|
|
7847
7904
|
moduleIndex: a.current.currentModuleIndex,
|
|
7848
7905
|
lessonIndex: a.current.currentLessonIndex,
|
|
7849
|
-
hasNextLesson:
|
|
7850
|
-
}),
|
|
7906
|
+
hasNextLesson: J
|
|
7907
|
+
}), d.current.onLessonStart({
|
|
7851
7908
|
moduleIndex: a.current.currentModuleIndex,
|
|
7852
7909
|
lessonIndex: a.current.currentLessonIndex,
|
|
7853
7910
|
lesson: y()
|
|
7854
7911
|
}), u.current && (u.current.setMood("happy"), u.current.setBodyMovement("idle"));
|
|
7855
7912
|
} else
|
|
7856
|
-
|
|
7857
|
-
}, []),
|
|
7913
|
+
S.current && S.current();
|
|
7914
|
+
}, []), B = N(() => {
|
|
7858
7915
|
const v = y();
|
|
7859
7916
|
let R = null;
|
|
7860
7917
|
if (v?.avatar_script && v?.body) {
|
|
7861
|
-
const
|
|
7862
|
-
R = `${
|
|
7918
|
+
const H = v.avatar_script.trim(), M = v.body.trim(), G = H.match(/[.!?]$/) ? " " : ". ";
|
|
7919
|
+
R = `${H}${G}${M}`;
|
|
7863
7920
|
} else
|
|
7864
7921
|
R = v?.avatar_script || v?.body || null;
|
|
7865
7922
|
if (u.current && u.current.isReady && R) {
|
|
7866
7923
|
a.current.isTeaching = !0, a.current.isQuestionMode = !1, a.current.score = 0, a.current.totalQuestions = 0, u.current.setMood("happy");
|
|
7867
|
-
let
|
|
7924
|
+
let H = !1;
|
|
7868
7925
|
if (e.teaching)
|
|
7869
7926
|
try {
|
|
7870
|
-
u.current.playAnimation(e.teaching, !0),
|
|
7871
|
-
} catch (
|
|
7872
|
-
console.warn("Failed to play teaching animation:",
|
|
7927
|
+
u.current.playAnimation(e.teaching, !0), H = !0;
|
|
7928
|
+
} catch (G) {
|
|
7929
|
+
console.warn("Failed to play teaching animation:", G);
|
|
7873
7930
|
}
|
|
7874
|
-
|
|
7875
|
-
const M =
|
|
7876
|
-
|
|
7931
|
+
H || u.current.setBodyMovement("gesturing");
|
|
7932
|
+
const M = C.current || { lipsyncLang: "en" };
|
|
7933
|
+
d.current.onLessonStart({
|
|
7877
7934
|
moduleIndex: a.current.currentModuleIndex,
|
|
7878
7935
|
lessonIndex: a.current.currentLessonIndex,
|
|
7879
7936
|
lesson: v
|
|
7880
|
-
}),
|
|
7937
|
+
}), d.current.onCustomAction({
|
|
7881
7938
|
type: "teachingStart",
|
|
7882
7939
|
moduleIndex: a.current.currentModuleIndex,
|
|
7883
7940
|
lessonIndex: a.current.currentLessonIndex,
|
|
@@ -7885,13 +7942,13 @@ const yt = Me(({
|
|
|
7885
7942
|
}), u.current.speakText(R, {
|
|
7886
7943
|
lipsyncLang: M.lipsyncLang,
|
|
7887
7944
|
onSpeechEnd: () => {
|
|
7888
|
-
a.current.isTeaching = !1,
|
|
7945
|
+
a.current.isTeaching = !1, d.current.onCustomAction({
|
|
7889
7946
|
type: "teachingComplete",
|
|
7890
7947
|
moduleIndex: a.current.currentModuleIndex,
|
|
7891
7948
|
lessonIndex: a.current.currentLessonIndex,
|
|
7892
7949
|
lesson: v,
|
|
7893
7950
|
hasQuestions: v.questions && v.questions.length > 0
|
|
7894
|
-
}), v?.code_example &&
|
|
7951
|
+
}), v?.code_example && d.current.onCustomAction({
|
|
7895
7952
|
type: "codeExampleReady",
|
|
7896
7953
|
moduleIndex: a.current.currentModuleIndex,
|
|
7897
7954
|
lessonIndex: a.current.currentLessonIndex,
|
|
@@ -7901,17 +7958,17 @@ const yt = Me(({
|
|
|
7901
7958
|
}
|
|
7902
7959
|
});
|
|
7903
7960
|
}
|
|
7904
|
-
}, [e.teaching, y]),
|
|
7905
|
-
const R =
|
|
7906
|
-
if (
|
|
7961
|
+
}, [e.teaching, y]), $ = N((v) => {
|
|
7962
|
+
const R = I(), H = z(v, R);
|
|
7963
|
+
if (H && (a.current.score += 1), d.current.onQuestionAnswer({
|
|
7907
7964
|
moduleIndex: a.current.currentModuleIndex,
|
|
7908
7965
|
lessonIndex: a.current.currentLessonIndex,
|
|
7909
7966
|
questionIndex: a.current.currentQuestionIndex,
|
|
7910
7967
|
answer: v,
|
|
7911
|
-
isCorrect:
|
|
7968
|
+
isCorrect: H,
|
|
7912
7969
|
question: R
|
|
7913
7970
|
}), u.current)
|
|
7914
|
-
if (
|
|
7971
|
+
if (H) {
|
|
7915
7972
|
if (u.current.setMood("happy"), e.correct)
|
|
7916
7973
|
try {
|
|
7917
7974
|
u.current.playReaction("happy");
|
|
@@ -7919,21 +7976,21 @@ const yt = Me(({
|
|
|
7919
7976
|
u.current.setBodyMovement("happy");
|
|
7920
7977
|
}
|
|
7921
7978
|
u.current.setBodyMovement("gesturing");
|
|
7922
|
-
const
|
|
7923
|
-
a.current.currentQuestionIndex >=
|
|
7924
|
-
const
|
|
7925
|
-
console.log("[CurriculumLearning] Answer feedback - questionIndex:", a.current.currentQuestionIndex, "totalQuestions:",
|
|
7926
|
-
const
|
|
7927
|
-
u.current.speakText(
|
|
7928
|
-
lipsyncLang:
|
|
7979
|
+
const G = y()?.questions?.length || 0;
|
|
7980
|
+
a.current.currentQuestionIndex >= G - 1;
|
|
7981
|
+
const ee = a.current.currentQuestionIndex < G - 1;
|
|
7982
|
+
console.log("[CurriculumLearning] Answer feedback - questionIndex:", a.current.currentQuestionIndex, "totalQuestions:", G, "hasNextQuestion:", ee);
|
|
7983
|
+
const q = R.type === "code_test" ? `Great job! Your code passed all the tests! ${R.explanation || ""}` : `Excellent! That's correct! ${R.explanation || ""}`, J = C.current || { lipsyncLang: "en" };
|
|
7984
|
+
u.current.speakText(q, {
|
|
7985
|
+
lipsyncLang: J.lipsyncLang,
|
|
7929
7986
|
onSpeechEnd: () => {
|
|
7930
|
-
|
|
7987
|
+
d.current.onCustomAction({
|
|
7931
7988
|
type: "answerFeedbackComplete",
|
|
7932
7989
|
moduleIndex: a.current.currentModuleIndex,
|
|
7933
7990
|
lessonIndex: a.current.currentLessonIndex,
|
|
7934
7991
|
questionIndex: a.current.currentQuestionIndex,
|
|
7935
7992
|
isCorrect: !0,
|
|
7936
|
-
hasNextQuestion:
|
|
7993
|
+
hasNextQuestion: ee,
|
|
7937
7994
|
score: a.current.score,
|
|
7938
7995
|
totalQuestions: a.current.totalQuestions
|
|
7939
7996
|
});
|
|
@@ -7947,19 +8004,19 @@ const yt = Me(({
|
|
|
7947
8004
|
u.current.setBodyMovement("idle");
|
|
7948
8005
|
}
|
|
7949
8006
|
u.current.setBodyMovement("gesturing");
|
|
7950
|
-
const
|
|
7951
|
-
console.log("[CurriculumLearning] Answer feedback (incorrect) - questionIndex:", a.current.currentQuestionIndex, "totalQuestions:",
|
|
7952
|
-
const
|
|
7953
|
-
u.current.speakText(
|
|
7954
|
-
lipsyncLang:
|
|
8007
|
+
const G = y()?.questions?.length || 0, ee = a.current.currentQuestionIndex >= G - 1, q = a.current.currentQuestionIndex < G - 1;
|
|
8008
|
+
console.log("[CurriculumLearning] Answer feedback (incorrect) - questionIndex:", a.current.currentQuestionIndex, "totalQuestions:", G, "hasNextQuestion:", q);
|
|
8009
|
+
const J = R.type === "code_test" ? `Your code didn't pass all the tests. ${R.explanation || "Try again!"}` : `Not quite right, but don't worry! ${R.explanation || ""}${ee ? "" : " Let's move on to the next question."}`, Ae = C.current || { lipsyncLang: "en" };
|
|
8010
|
+
u.current.speakText(J, {
|
|
8011
|
+
lipsyncLang: Ae.lipsyncLang,
|
|
7955
8012
|
onSpeechEnd: () => {
|
|
7956
|
-
|
|
8013
|
+
d.current.onCustomAction({
|
|
7957
8014
|
type: "answerFeedbackComplete",
|
|
7958
8015
|
moduleIndex: a.current.currentModuleIndex,
|
|
7959
8016
|
lessonIndex: a.current.currentLessonIndex,
|
|
7960
8017
|
questionIndex: a.current.currentQuestionIndex,
|
|
7961
8018
|
isCorrect: !1,
|
|
7962
|
-
hasNextQuestion:
|
|
8019
|
+
hasNextQuestion: q,
|
|
7963
8020
|
score: a.current.score,
|
|
7964
8021
|
totalQuestions: a.current.totalQuestions
|
|
7965
8022
|
});
|
|
@@ -7967,21 +8024,21 @@ const yt = Me(({
|
|
|
7967
8024
|
});
|
|
7968
8025
|
}
|
|
7969
8026
|
else {
|
|
7970
|
-
const
|
|
7971
|
-
|
|
8027
|
+
const G = y()?.questions?.length || 0;
|
|
8028
|
+
d.current.onCustomAction({
|
|
7972
8029
|
type: "answerFeedbackComplete",
|
|
7973
8030
|
moduleIndex: a.current.currentModuleIndex,
|
|
7974
8031
|
lessonIndex: a.current.currentLessonIndex,
|
|
7975
8032
|
questionIndex: a.current.currentQuestionIndex,
|
|
7976
|
-
isCorrect:
|
|
7977
|
-
hasNextQuestion: a.current.currentQuestionIndex <
|
|
8033
|
+
isCorrect: H,
|
|
8034
|
+
hasNextQuestion: a.current.currentQuestionIndex < G - 1,
|
|
7978
8035
|
score: a.current.score,
|
|
7979
8036
|
totalQuestions: a.current.totalQuestions,
|
|
7980
8037
|
avatarNotReady: !0
|
|
7981
8038
|
});
|
|
7982
8039
|
}
|
|
7983
|
-
}, [e.correct, e.incorrect,
|
|
7984
|
-
const R =
|
|
8040
|
+
}, [e.correct, e.incorrect, I, y, z]), ie = N((v) => {
|
|
8041
|
+
const R = I();
|
|
7985
8042
|
if (!v || typeof v != "object") {
|
|
7986
8043
|
console.error("Invalid code test result format. Expected object with {passed: boolean, ...}");
|
|
7987
8044
|
return;
|
|
@@ -7990,7 +8047,7 @@ const yt = Me(({
|
|
|
7990
8047
|
console.warn("Current question is not a code test. Use handleAnswerSelect for other question types.");
|
|
7991
8048
|
return;
|
|
7992
8049
|
}
|
|
7993
|
-
const
|
|
8050
|
+
const H = {
|
|
7994
8051
|
passed: v.passed === !0,
|
|
7995
8052
|
results: v.results || [],
|
|
7996
8053
|
output: v.output || "",
|
|
@@ -8000,19 +8057,19 @@ const yt = Me(({
|
|
|
8000
8057
|
passedCount: v.passedCount || 0,
|
|
8001
8058
|
failedCount: v.failedCount || 0
|
|
8002
8059
|
};
|
|
8003
|
-
|
|
8060
|
+
d.current.onCustomAction({
|
|
8004
8061
|
type: "codeTestSubmitted",
|
|
8005
8062
|
moduleIndex: a.current.currentModuleIndex,
|
|
8006
8063
|
lessonIndex: a.current.currentLessonIndex,
|
|
8007
8064
|
questionIndex: a.current.currentQuestionIndex,
|
|
8008
|
-
testResult:
|
|
8065
|
+
testResult: H,
|
|
8009
8066
|
question: R
|
|
8010
|
-
}), p.current && p.current(
|
|
8011
|
-
}, [
|
|
8067
|
+
}), p.current && p.current(H);
|
|
8068
|
+
}, [I, z]), oe = N(() => {
|
|
8012
8069
|
if (a.current.currentQuestionIndex > 0) {
|
|
8013
8070
|
a.current.currentQuestionIndex -= 1;
|
|
8014
|
-
const v =
|
|
8015
|
-
v &&
|
|
8071
|
+
const v = I();
|
|
8072
|
+
v && d.current.onCustomAction({
|
|
8016
8073
|
type: "questionStart",
|
|
8017
8074
|
moduleIndex: a.current.currentModuleIndex,
|
|
8018
8075
|
lessonIndex: a.current.currentLessonIndex,
|
|
@@ -8024,82 +8081,82 @@ const yt = Me(({
|
|
|
8024
8081
|
const R = () => {
|
|
8025
8082
|
if (!u.current || !v) return;
|
|
8026
8083
|
u.current.setMood("happy"), u.current.setBodyMovement("idle");
|
|
8027
|
-
const
|
|
8084
|
+
const H = C.current || { lipsyncLang: "en" };
|
|
8028
8085
|
v.type === "code_test" ? u.current.speakText(`Let's go back to this coding challenge: ${v.question}`, {
|
|
8029
|
-
lipsyncLang:
|
|
8086
|
+
lipsyncLang: H.lipsyncLang
|
|
8030
8087
|
}) : u.current.speakText(`Going back to: ${v.question}`, {
|
|
8031
|
-
lipsyncLang:
|
|
8088
|
+
lipsyncLang: H.lipsyncLang
|
|
8032
8089
|
});
|
|
8033
8090
|
};
|
|
8034
8091
|
if (u.current && u.current.isReady && v)
|
|
8035
8092
|
R();
|
|
8036
8093
|
else if (v) {
|
|
8037
|
-
const
|
|
8038
|
-
u.current && u.current.isReady && (clearInterval(
|
|
8094
|
+
const H = setInterval(() => {
|
|
8095
|
+
u.current && u.current.isReady && (clearInterval(H), R());
|
|
8039
8096
|
}, 100);
|
|
8040
8097
|
setTimeout(() => {
|
|
8041
|
-
clearInterval(
|
|
8098
|
+
clearInterval(H);
|
|
8042
8099
|
}, 5e3);
|
|
8043
8100
|
}
|
|
8044
8101
|
}
|
|
8045
|
-
}, [
|
|
8046
|
-
const v =
|
|
8102
|
+
}, [I]), le = N(() => {
|
|
8103
|
+
const v = P.current || { modules: [] };
|
|
8047
8104
|
if (v.modules[a.current.currentModuleIndex], a.current.currentLessonIndex > 0)
|
|
8048
|
-
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,
|
|
8105
|
+
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({
|
|
8049
8106
|
type: "lessonStart",
|
|
8050
8107
|
moduleIndex: a.current.currentModuleIndex,
|
|
8051
8108
|
lessonIndex: a.current.currentLessonIndex
|
|
8052
|
-
}),
|
|
8109
|
+
}), d.current.onLessonStart({
|
|
8053
8110
|
moduleIndex: a.current.currentModuleIndex,
|
|
8054
8111
|
lessonIndex: a.current.currentLessonIndex,
|
|
8055
8112
|
lesson: y()
|
|
8056
8113
|
}), u.current && (u.current.setMood("happy"), u.current.setBodyMovement("idle"));
|
|
8057
8114
|
else if (a.current.currentModuleIndex > 0) {
|
|
8058
8115
|
const M = v.modules[a.current.currentModuleIndex - 1];
|
|
8059
|
-
a.current.currentModuleIndex -= 1, a.current.currentLessonIndex = (M?.lessons?.length || 1) - 1, a.current.currentQuestionIndex = 0, a.current.lessonCompleted = !1, a.current.isQuestionMode = !1, a.current.isTeaching = !1, a.current.score = 0, a.current.totalQuestions = 0,
|
|
8116
|
+
a.current.currentModuleIndex -= 1, a.current.currentLessonIndex = (M?.lessons?.length || 1) - 1, a.current.currentQuestionIndex = 0, a.current.lessonCompleted = !1, a.current.isQuestionMode = !1, a.current.isTeaching = !1, a.current.score = 0, a.current.totalQuestions = 0, d.current.onCustomAction({
|
|
8060
8117
|
type: "lessonStart",
|
|
8061
8118
|
moduleIndex: a.current.currentModuleIndex,
|
|
8062
8119
|
lessonIndex: a.current.currentLessonIndex
|
|
8063
|
-
}),
|
|
8120
|
+
}), d.current.onLessonStart({
|
|
8064
8121
|
moduleIndex: a.current.currentModuleIndex,
|
|
8065
8122
|
lessonIndex: a.current.currentLessonIndex,
|
|
8066
8123
|
lesson: y()
|
|
8067
8124
|
}), u.current && (u.current.setMood("happy"), u.current.setBodyMovement("idle"));
|
|
8068
8125
|
}
|
|
8069
|
-
}, [y]),
|
|
8126
|
+
}, [y]), Z = N(() => {
|
|
8070
8127
|
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;
|
|
8071
|
-
}, []),
|
|
8128
|
+
}, []), ne = N((v) => {
|
|
8072
8129
|
console.log("Avatar is ready!", v);
|
|
8073
|
-
const R = y(),
|
|
8074
|
-
h &&
|
|
8075
|
-
|
|
8130
|
+
const R = y(), H = R?.avatar_script || R?.body;
|
|
8131
|
+
h && H && setTimeout(() => {
|
|
8132
|
+
c.current && c.current();
|
|
8076
8133
|
}, 10);
|
|
8077
8134
|
}, [h, y]);
|
|
8078
8135
|
Xe(() => {
|
|
8079
|
-
|
|
8080
|
-
}),
|
|
8136
|
+
c.current = B, g.current = _, b.current = A, x.current = F, S.current = j, V.current = k, p.current = $;
|
|
8137
|
+
}), Fe(r, () => ({
|
|
8081
8138
|
// Curriculum control methods
|
|
8082
|
-
startTeaching:
|
|
8139
|
+
startTeaching: B,
|
|
8083
8140
|
startQuestions: k,
|
|
8084
|
-
handleAnswerSelect:
|
|
8085
|
-
handleCodeTestResult:
|
|
8086
|
-
nextQuestion:
|
|
8087
|
-
previousQuestion:
|
|
8088
|
-
nextLesson:
|
|
8089
|
-
previousLesson:
|
|
8090
|
-
completeLesson:
|
|
8091
|
-
completeCurriculum:
|
|
8092
|
-
resetCurriculum:
|
|
8141
|
+
handleAnswerSelect: $,
|
|
8142
|
+
handleCodeTestResult: ie,
|
|
8143
|
+
nextQuestion: F,
|
|
8144
|
+
previousQuestion: oe,
|
|
8145
|
+
nextLesson: _,
|
|
8146
|
+
previousLesson: le,
|
|
8147
|
+
completeLesson: A,
|
|
8148
|
+
completeCurriculum: j,
|
|
8149
|
+
resetCurriculum: Z,
|
|
8093
8150
|
getState: () => ({ ...a.current }),
|
|
8094
|
-
getCurrentQuestion: () =>
|
|
8151
|
+
getCurrentQuestion: () => I(),
|
|
8095
8152
|
getCurrentLesson: () => y(),
|
|
8096
8153
|
// Direct access to avatar ref (always returns current value)
|
|
8097
8154
|
getAvatarRef: () => u.current,
|
|
8098
8155
|
// Convenience methods that delegate to avatar (always check current ref)
|
|
8099
8156
|
speakText: async (v, R = {}) => {
|
|
8100
8157
|
await u.current?.resumeAudioContext?.();
|
|
8101
|
-
const
|
|
8102
|
-
u.current?.speakText(v, { ...R, lipsyncLang: R.lipsyncLang ||
|
|
8158
|
+
const H = C.current || { lipsyncLang: "en" };
|
|
8159
|
+
u.current?.speakText(v, { ...R, lipsyncLang: R.lipsyncLang || H.lipsyncLang });
|
|
8103
8160
|
},
|
|
8104
8161
|
resumeAudioContext: async () => {
|
|
8105
8162
|
if (u.current?.resumeAudioContext)
|
|
@@ -8110,8 +8167,8 @@ const yt = Me(({
|
|
|
8110
8167
|
if (R.state === "suspended" || R.state === "interrupted")
|
|
8111
8168
|
try {
|
|
8112
8169
|
await R.resume(), console.log("Audio context resumed via talkingHead");
|
|
8113
|
-
} catch (
|
|
8114
|
-
console.warn("Failed to resume audio context:",
|
|
8170
|
+
} catch (H) {
|
|
8171
|
+
console.warn("Failed to resume audio context:", H);
|
|
8115
8172
|
}
|
|
8116
8173
|
} else
|
|
8117
8174
|
console.warn("Audio context not available yet");
|
|
@@ -8133,7 +8190,7 @@ const yt = Me(({
|
|
|
8133
8190
|
unlockAvatarPosition: () => u.current?.unlockAvatarPosition(),
|
|
8134
8191
|
// Custom action trigger
|
|
8135
8192
|
triggerCustomAction: (v, R) => {
|
|
8136
|
-
|
|
8193
|
+
d.current.onCustomAction({
|
|
8137
8194
|
type: v,
|
|
8138
8195
|
...R,
|
|
8139
8196
|
state: { ...a.current }
|
|
@@ -8143,8 +8200,8 @@ const yt = Me(({
|
|
|
8143
8200
|
handleResize: () => u.current?.handleResize(),
|
|
8144
8201
|
// Avatar readiness check (always returns current value)
|
|
8145
8202
|
isAvatarReady: () => u.current?.isReady || !1
|
|
8146
|
-
}), [
|
|
8147
|
-
const
|
|
8203
|
+
}), [B, k, $, ie, F, _, A, j, Z, I, y]);
|
|
8204
|
+
const O = C.current || {
|
|
8148
8205
|
avatarUrl: "/avatars/brunette.glb",
|
|
8149
8206
|
avatarBody: "F",
|
|
8150
8207
|
mood: "happy",
|
|
@@ -8157,23 +8214,23 @@ const yt = Me(({
|
|
|
8157
8214
|
showFullAvatar: !1,
|
|
8158
8215
|
animations: e
|
|
8159
8216
|
};
|
|
8160
|
-
return /* @__PURE__ */
|
|
8217
|
+
return /* @__PURE__ */ pe("div", { style: { width: "100%", height: "100%" }, children: /* @__PURE__ */ pe(
|
|
8161
8218
|
Ve,
|
|
8162
8219
|
{
|
|
8163
8220
|
ref: u,
|
|
8164
|
-
avatarUrl:
|
|
8165
|
-
avatarBody:
|
|
8166
|
-
mood:
|
|
8167
|
-
ttsLang:
|
|
8168
|
-
ttsService:
|
|
8169
|
-
ttsVoice:
|
|
8170
|
-
ttsApiKey:
|
|
8171
|
-
bodyMovement:
|
|
8172
|
-
movementIntensity:
|
|
8173
|
-
showFullAvatar:
|
|
8221
|
+
avatarUrl: O.avatarUrl,
|
|
8222
|
+
avatarBody: O.avatarBody,
|
|
8223
|
+
mood: O.mood,
|
|
8224
|
+
ttsLang: O.ttsLang,
|
|
8225
|
+
ttsService: O.ttsService,
|
|
8226
|
+
ttsVoice: O.ttsVoice,
|
|
8227
|
+
ttsApiKey: O.ttsApiKey,
|
|
8228
|
+
bodyMovement: O.bodyMovement,
|
|
8229
|
+
movementIntensity: O.movementIntensity,
|
|
8230
|
+
showFullAvatar: O.showFullAvatar,
|
|
8174
8231
|
cameraView: "upper",
|
|
8175
|
-
animations:
|
|
8176
|
-
onReady:
|
|
8232
|
+
animations: O.animations,
|
|
8233
|
+
onReady: ne,
|
|
8177
8234
|
onLoading: () => {
|
|
8178
8235
|
},
|
|
8179
8236
|
onError: (v) => {
|
|
@@ -8286,14 +8343,14 @@ const Ge = {
|
|
|
8286
8343
|
duration: 5e3,
|
|
8287
8344
|
description: "Excited, energetic movement"
|
|
8288
8345
|
}
|
|
8289
|
-
}, wt = (
|
|
8346
|
+
}, wt = (Y) => Ge[Y] || null, zt = (Y) => Ge.hasOwnProperty(Y);
|
|
8290
8347
|
export {
|
|
8291
8348
|
yt as CurriculumLearning,
|
|
8292
8349
|
gt as SimpleTalkingAvatar,
|
|
8293
8350
|
Ve as TalkingHeadAvatar,
|
|
8294
8351
|
pt as TalkingHeadComponent,
|
|
8295
8352
|
Ge as animations,
|
|
8296
|
-
|
|
8353
|
+
Ee as getActiveTTSConfig,
|
|
8297
8354
|
wt as getAnimation,
|
|
8298
8355
|
kt as getVoiceOptions,
|
|
8299
8356
|
zt as hasAnimation
|