@sage-rsc/talking-head-react 1.1.8 → 1.2.0
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 +836 -773
- package/package.json +1 -1
- package/src/lib/talkinghead.mjs +149 -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 V, 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, le, ue;
|
|
11
|
+
const w = [0, 0, 0, 0], F = 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(F).clone(),
|
|
325
325
|
// World position, parent
|
|
326
326
|
qBasis: r.parent.quaternion.clone(),
|
|
327
327
|
// Original quaternion, parent
|
|
@@ -338,7 +338,7 @@ class et {
|
|
|
338
338
|
ea: [0, 0, 0, 0]
|
|
339
339
|
// External acceleration [m/s^2]
|
|
340
340
|
};
|
|
341
|
-
u.boneParent.matrixWorld.decompose(
|
|
341
|
+
u.boneParent.matrixWorld.decompose(F, re, ae), F.copy(He).applyQuaternion(re).setY(0).normalize(), re.premultiply(Oe.setFromUnitVectors(He, F).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], F.copy(o.vWorld), fe.copy(o.boneParent.matrixWorld), xe.copy(fe).invert(), o.vWorld.setFromMatrixPosition(fe), F.applyMatrix4(xe), F.length() > 0.5 && (console.info("Info: Unrealistic jump of " + F.length().toFixed(2) + " meters."), F.setLength(0.5)), F.applyQuaternion(o.bone.quaternion), w[0] = F.x, w[1] = F.y, w[2] = -F.z, w[3] = F.length() / 3, o.children)
|
|
360
360
|
for (n = 0, s = o.children.length; n < s; n++)
|
|
361
|
-
m = o.children[n],
|
|
362
|
-
if (m = this.opt.sensitivityFactor,
|
|
363
|
-
o.vBasis.x +
|
|
364
|
-
o.vBasis.y +
|
|
365
|
-
o.vBasis.z +
|
|
366
|
-
),
|
|
361
|
+
m = o.children[n], 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, F.set(
|
|
363
|
+
o.vBasis.x + w[0],
|
|
364
|
+
o.vBasis.y + w[1],
|
|
365
|
+
o.vBasis.z + w[2]
|
|
366
|
+
), F.applyMatrix4(fe), F.x += m[0], F.y += m[1], F.z += m[2], F.applyMatrix4(xe), w[0] += F.x - o.vBasis.x, w[1] += F.y - o.vBasis.y, w[2] += F.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(F, re, ae), F.copy(He).applyQuaternion(re).setY(0).normalize(), re.premultiply(Oe.setFromUnitVectors(He, F).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), F.copy(o.bone.position), !(F.distanceToSquared(ae) >= m.radiusSq) && (ue = F.length(), le = ae.length(), !(le > m.radius + ue) && (le < Math.abs(m.radius - ue) || (le = (le * le + ue * ue - m.radiusSq) / (2 * le), ae.normalize(), Ce.copy(ae).multiplyScalar(le), le = Math.sqrt(ue * ue - le * le), F.subVectors(F, Ce).projectOnPlane(ae).normalize().multiplyScalar(le), ze.subVectors(o.vBasis, Ce).projectOnPlane(ae).normalize(), ue = ze.dot(F), ue < 0 && (ue = Math.sqrt(le * le - ue * ue), ze.multiplyScalar(ue), F.add(ze)), F.add(Ce).normalize(), ae.copy(o.bone.position).normalize(), re.setFromUnitVectors(ae, F), 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), F.setFromMatrixPosition(fe), t.setXYZ(e, F.x, F.y, F.z);
|
|
449
449
|
t.needsUpdate = !0, m.object.updateMatrixWorld();
|
|
450
450
|
}
|
|
451
451
|
if (m = this.helpers.lines, m.bones.length) {
|
|
452
452
|
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), F.setFromMatrixPosition(fe), t.setXYZ(n, F.x, F.y, F.z), fe.multiplyMatrices(xe, m.bones[e].parent.matrixWorld), F.setFromMatrixPosition(fe), t.setXYZ(n + 1, F.x, F.y, F.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
|
+
}, J = new f.Quaternion(), Z = 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
|
+
Z.set(e.x, e.y, e.z);
|
|
4402
4402
|
const n = this.poseAvatar.props[t];
|
|
4403
|
-
n.isQuaternion ? (
|
|
4403
|
+
n.isQuaternion ? (J.setFromEuler(Z), n.multiply(J)) : n.isVector3 && n.add(Z);
|
|
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) && (Z.setFromQuaternion(this.poseAvatar.props["Head.quaternion"]), Z.x = Math.max(-0.9, Math.min(0.9, 2 * Z.x - 0.5)), Z.y = Math.max(-0.9, Math.min(0.9, -2.5 * Z.y)), h ? (Object.assign(this.mtAvatar.eyesLookDown, { system: Z.x < 0 ? -Z.x : 0, needsUpdate: !0 }), Object.assign(this.mtAvatar.eyesLookUp, { system: Z.x < 0 ? 0 : Z.x, needsUpdate: !0 }), Object.assign(this.mtAvatar.eyeLookInLeft, { system: Z.y < 0 ? -Z.y : 0, needsUpdate: !0 }), Object.assign(this.mtAvatar.eyeLookOutLeft, { system: Z.y < 0 ? 0 : Z.y, needsUpdate: !0 }), Object.assign(this.mtAvatar.eyeLookInRight, { system: Z.y < 0 ? 0 : Z.y, needsUpdate: !0 }), Object.assign(this.mtAvatar.eyeLookOutRight, { system: Z.y < 0 ? -Z.y : 0, needsUpdate: !0 }), r && (n = -this.mtAvatar.bodyRotateY.value, i = this.gaussianRandom(-0.2, 0.2), this.animQueue.push(this.animFactory({
|
|
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 && (J.setFromAxisAngle(mt, this.volumeHeadCurrent), this.objectNeck.quaternion.multiply(J)), 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, G = 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), H = b[x].match(o);
|
|
5270
|
+
if (p && !S && !P && b[x + 1].match(s) && (p = !1), n && (u += b[x]), G && (!i || i.every((y) => x < y[0] || x > y[1])) && (a += b[x]), (H || 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, G = d.durations[x] / c * u;
|
|
5402
5402
|
o.push({
|
|
5403
5403
|
template: { name: "viseme" },
|
|
5404
|
-
ts: [
|
|
5404
|
+
ts: [S - Math.min(60, 2 * G / 3), S + Math.min(25, G / 2), S + G + Math.min(60, G / 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 H = 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_" + H]: [null, H === "PP" || H === "FF" ? 0.9 : 0.6, 0]
|
|
5508
5508
|
}
|
|
5509
5509
|
});
|
|
5510
5510
|
}
|
|
5511
5511
|
}
|
|
5512
|
-
const
|
|
5513
|
-
this.audioPlaylist.push({ anim:
|
|
5512
|
+
const G = [...t.anim, ...S];
|
|
5513
|
+
this.audioPlaylist.push({ anim: G, 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), J.copy(this.armature.quaternion), J.multiply(this.poseTarget.props["Hips.quaternion"]), J.multiply(this.poseTarget.props["Spine.quaternion"]), J.multiply(this.poseTarget.props["Spine1.quaternion"]), J.multiply(this.poseTarget.props["Spine2.quaternion"]), J.multiply(this.poseTarget.props["Neck.quaternion"]), J.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
|
+
Z.set(s, i, 0, "YXZ");
|
|
6165
|
+
const l = new f.Quaternion().setFromEuler(Z), h = new f.Quaternion().copy(l).multiply(J.clone().invert());
|
|
6166
|
+
Z.setFromQuaternion(h, "YXZ");
|
|
6167
|
+
let r = Z.x / (40 / 24) + 0.2, u = Z.y / (9 / 4), a = Math.min(0.6, Math.max(-0.3, r)), d = Math.min(0.8, Math.max(-0.8, u)), c = (Math.random() - 0.5) / 4, g = (Math.random() - 0.5) / 4;
|
|
6168
6168
|
if (t) {
|
|
6169
|
-
let b = this.animQueue.findIndex((
|
|
6169
|
+
let b = this.animQueue.findIndex((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), J.copy(this.armature.quaternion), J.multiply(this.poseTarget.props["Hips.quaternion"]), J.multiply(this.poseTarget.props["Spine.quaternion"]), J.multiply(this.poseTarget.props["Spine1.quaternion"]), J.multiply(this.poseTarget.props["Spine2.quaternion"]), J.multiply(this.poseTarget.props["Neck.quaternion"]), J.multiply(this.poseTarget.props["Head.quaternion"]), Z.setFromQuaternion(J);
|
|
6203
|
+
let u = Z.x / (40 / 24), a = Z.y / (9 / 4), d = Math.min(0.4, Math.max(-0.4, this.camera.rotation.x)), c = Math.min(0.4, Math.max(-0.4, this.camera.rotation.y)), g = Math.max(window.innerWidth - h, h), b = Math.max(window.innerHeight - r, r), x = this.convertRange(e, [r - b, r + b], [-0.3, 0.6]) - u + d, 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 G = (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 H = {
|
|
6210
6210
|
name: "lookat",
|
|
6211
6211
|
dt: [750, n],
|
|
6212
6212
|
vs: {
|
|
6213
|
-
bodyRotateX: [x +
|
|
6214
|
-
bodyRotateY: [
|
|
6215
|
-
eyesRotateX: [-3 *
|
|
6213
|
+
bodyRotateX: [x + G],
|
|
6214
|
+
bodyRotateY: [S + p],
|
|
6215
|
+
eyesRotateX: [-3 * G + 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(H));
|
|
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 Y = {
|
|
6478
|
+
// Arm bones - exact matches
|
|
6456
6479
|
LeftArm: "LeftArm",
|
|
6457
6480
|
leftArm: "LeftArm",
|
|
6458
6481
|
LEFTARM: "LeftArm",
|
|
@@ -6491,51 +6514,91 @@ class Be {
|
|
|
6491
6514
|
Root: "Hips",
|
|
6492
6515
|
root: "Hips"
|
|
6493
6516
|
};
|
|
6494
|
-
if (
|
|
6495
|
-
const
|
|
6496
|
-
if (
|
|
6497
|
-
return
|
|
6517
|
+
if (Y[z]) {
|
|
6518
|
+
const k = Y[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 C = k.toLowerCase();
|
|
6527
|
+
if ((A.includes("left") && C.includes("left") || A.includes("right") && C.includes("right")) && (A.includes("arm") && C.includes("arm") && !C.includes("fore") || A.includes("forearm") && C.includes("forearm") || A.includes("hand") && C.includes("hand") && !C.includes("index") && !C.includes("thumb") || A.includes("shoulder") && C.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
|
+
), G = 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:", G.sort().join(", "));
|
|
6542
|
+
const p = [], P = /* @__PURE__ */ new Set();
|
|
6543
|
+
if (d.tracks.forEach((I) => {
|
|
6544
|
+
const A = I.name.replaceAll("mixamorig", "").split("."), Y = A[0], k = A[1], C = b(Y);
|
|
6545
|
+
if (C && k) {
|
|
6546
|
+
const _ = `${C}.${k}`, B = I.clone();
|
|
6547
|
+
B.name = _;
|
|
6548
|
+
const ee = C.includes("Arm") || C.includes("Hand") || C.includes("Shoulder");
|
|
6549
|
+
C.includes("Left"), C.includes("Right");
|
|
6550
|
+
const ie = C.includes("ForeArm") || C.includes("Forearm"), oe = C.includes("Hand") && !C.includes("Index") && !C.includes("Thumb") && !C.includes("Middle") && !C.includes("Ring") && !C.includes("Pinky");
|
|
6551
|
+
if (ee && (k === "quaternion" || k === "rotation") && k === "quaternion" && B.values && B.values.length >= 4) {
|
|
6552
|
+
const he = B.times.length;
|
|
6553
|
+
for (let K = 0; K < he; K++) {
|
|
6554
|
+
const Q = K * 4;
|
|
6555
|
+
if (Q + 3 < B.values.length) {
|
|
6556
|
+
let W = B.values[Q], v = B.values[Q + 1], R = B.values[Q + 2], T = B.values[Q + 3];
|
|
6557
|
+
const M = new f.Quaternion(W, v, R, T);
|
|
6558
|
+
if (oe) {
|
|
6559
|
+
const O = new f.Quaternion().setFromAxisAngle(new f.Vector3(0, 1, 0), Math.PI);
|
|
6560
|
+
M.multiply(O);
|
|
6561
|
+
} else if (ie) {
|
|
6562
|
+
const O = new f.Quaternion().setFromAxisAngle(new f.Vector3(0, 0, 1), Math.PI / 2);
|
|
6563
|
+
M.multiply(O);
|
|
6564
|
+
}
|
|
6565
|
+
B.values[Q] = M.x, B.values[Q + 1] = M.y, B.values[Q + 2] = M.z, B.values[Q + 3] = M.w;
|
|
6566
|
+
}
|
|
6567
|
+
}
|
|
6568
|
+
}
|
|
6569
|
+
p.push(B), Y !== C && g.set(Y, C);
|
|
6514
6570
|
} else
|
|
6515
|
-
|
|
6516
|
-
}),
|
|
6517
|
-
|
|
6518
|
-
|
|
6519
|
-
|
|
6520
|
-
|
|
6521
|
-
|
|
6571
|
+
P.add(Y), (Y.toLowerCase().includes("arm") || Y.toLowerCase().includes("hand") || Y.toLowerCase().includes("shoulder")) && console.warn(`⚠️ Arm bone "${Y}" could not be mapped to avatar skeleton`);
|
|
6572
|
+
}), P.size > 0 && console.warn(`⚠️ ${P.size} bone(s) could not be mapped:`, Array.from(P).sort().join(", ")), p.length > 0) {
|
|
6573
|
+
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(
|
|
6574
|
+
`✓ Mapped ${g.size} bone(s):`,
|
|
6575
|
+
Array.from(g.entries()).map(([z, A]) => `${z}→${A}`).join(", ")
|
|
6576
|
+
);
|
|
6577
|
+
const I = Array.from(g.values()).filter(
|
|
6578
|
+
(z) => z.includes("Arm") || z.includes("Hand") || z.includes("Shoulder")
|
|
6579
|
+
);
|
|
6580
|
+
I.length > 0 ? console.log(`✓ Arm bones mapped: ${I.join(", ")}`) : console.warn("⚠️ No arm bones were mapped! This may cause arm rigging issues.");
|
|
6581
|
+
} else
|
|
6582
|
+
console.error("❌ No tracks could be mapped! Animation may not work correctly.");
|
|
6583
|
+
const H = {};
|
|
6584
|
+
d.tracks.forEach((I) => {
|
|
6522
6585
|
I.name = I.name.replaceAll("mixamorig", "");
|
|
6523
|
-
const
|
|
6524
|
-
if (
|
|
6525
|
-
for (let
|
|
6526
|
-
I.values[
|
|
6527
|
-
|
|
6528
|
-
} else
|
|
6586
|
+
const z = I.name.split(".");
|
|
6587
|
+
if (z[1] === "position") {
|
|
6588
|
+
for (let A = 0; A < I.values.length; A++)
|
|
6589
|
+
I.values[A] = I.values[A] * s;
|
|
6590
|
+
H[I.name] = new f.Vector3(I.values[0], I.values[1], I.values[2]);
|
|
6591
|
+
} else z[1] === "quaternion" ? H[I.name] = new f.Quaternion(I.values[0], I.values[1], I.values[2], I.values[3]) : z[1] === "rotation" && (H[z[0] + ".quaternion"] = new f.Quaternion().setFromEuler(new f.Euler(I.values[0], I.values[1], I.values[2], "XYZ")).normalize());
|
|
6529
6592
|
});
|
|
6530
|
-
const
|
|
6531
|
-
|
|
6593
|
+
const y = { props: H };
|
|
6594
|
+
H["Hips.position"] && (H["Hips.position"].y < 0.5 ? y.lying = !0 : y.standing = !0), this.animClips.push({
|
|
6532
6595
|
url: t + "-" + i,
|
|
6533
|
-
clip:
|
|
6534
|
-
pose:
|
|
6596
|
+
clip: d,
|
|
6597
|
+
pose: y
|
|
6535
6598
|
}), this.playAnimation(t, e, n, i, s);
|
|
6536
6599
|
} else {
|
|
6537
|
-
const
|
|
6538
|
-
console.error(
|
|
6600
|
+
const d = "Animation " + t + " (ndx=" + i + ") not found";
|
|
6601
|
+
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
6602
|
}
|
|
6540
6603
|
}
|
|
6541
6604
|
}
|
|
@@ -6573,10 +6636,10 @@ class Be {
|
|
|
6573
6636
|
if (h && h.animations && h.animations[i]) {
|
|
6574
6637
|
let r = h.animations[i];
|
|
6575
6638
|
const u = {};
|
|
6576
|
-
r.tracks.forEach((
|
|
6577
|
-
|
|
6578
|
-
const
|
|
6579
|
-
|
|
6639
|
+
r.tracks.forEach((d) => {
|
|
6640
|
+
d.name = d.name.replaceAll("mixamorig", "");
|
|
6641
|
+
const c = d.name.split(".");
|
|
6642
|
+
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
6643
|
});
|
|
6581
6644
|
const a = { props: u };
|
|
6582
6645
|
u["Hips.position"] && (u["Hips.position"].y < 0.5 ? a.lying = !0 : a.standing = !0), this.animPoses.push({
|
|
@@ -6621,13 +6684,13 @@ class Be {
|
|
|
6621
6684
|
if (l.gesture = !0, e && Number.isFinite(e)) {
|
|
6622
6685
|
const h = l.ts[0], u = l.ts[l.ts.length - 1] - h;
|
|
6623
6686
|
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,
|
|
6687
|
+
const d = [];
|
|
6688
|
+
for (let b = 1; b < l.ts.length; b++) d.push(l.ts[b] - l.ts[b - 1]);
|
|
6689
|
+
const c = o.template?.rescale || d.map((b) => b / u), g = e * 1e3 - u;
|
|
6690
|
+
l.ts = l.ts.map((b, x, S) => x === 0 ? h : S[x - 1] + d[x - 1] + c[x - 1] * g);
|
|
6628
6691
|
} else {
|
|
6629
|
-
const
|
|
6630
|
-
l.ts = l.ts.map((
|
|
6692
|
+
const d = e * 1e3 / u;
|
|
6693
|
+
l.ts = l.ts.map((c) => h + d * (c - h));
|
|
6631
6694
|
}
|
|
6632
6695
|
}
|
|
6633
6696
|
this.animQueue.push(l);
|
|
@@ -6657,21 +6720,21 @@ class Be {
|
|
|
6657
6720
|
* @param {numeric} [d=null] If set, apply in d milliseconds
|
|
6658
6721
|
*/
|
|
6659
6722
|
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
|
-
|
|
6723
|
+
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);
|
|
6724
|
+
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
6725
|
const g = this.ikMesh.getObjectByName(t.effector), b = t.links;
|
|
6663
|
-
b.forEach((
|
|
6664
|
-
|
|
6665
|
-
}),
|
|
6726
|
+
b.forEach((S) => {
|
|
6727
|
+
S.bone = this.ikMesh.getObjectByName(S.link), S.bone.quaternion.copy(this.getPoseTemplateProp(S.link + ".quaternion"));
|
|
6728
|
+
}), c.updateMatrixWorld(!0);
|
|
6666
6729
|
const x = t.iterations || 10;
|
|
6667
6730
|
if (e)
|
|
6668
|
-
for (let
|
|
6669
|
-
let
|
|
6670
|
-
for (let p = 0,
|
|
6671
|
-
const
|
|
6672
|
-
|
|
6731
|
+
for (let S = 0; S < x; S++) {
|
|
6732
|
+
let G = !1;
|
|
6733
|
+
for (let p = 0, P = b.length; p < P; p++) {
|
|
6734
|
+
const H = b[p].bone;
|
|
6735
|
+
H.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
6736
|
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(),
|
|
6737
|
+
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(), J.setFromAxisAngle(a, y), H.quaternion.multiply(J), H.rotation.setFromVector3(d.setFromEuler(H.rotation).clamp(new f.Vector3(
|
|
6675
6738
|
b[p].minx !== void 0 ? b[p].minx : -1 / 0,
|
|
6676
6739
|
b[p].miny !== void 0 ? b[p].miny : -1 / 0,
|
|
6677
6740
|
b[p].minz !== void 0 ? b[p].minz : -1 / 0
|
|
@@ -6679,12 +6742,12 @@ class Be {
|
|
|
6679
6742
|
b[p].maxx !== void 0 ? b[p].maxx : 1 / 0,
|
|
6680
6743
|
b[p].maxy !== void 0 ? b[p].maxy : 1 / 0,
|
|
6681
6744
|
b[p].maxz !== void 0 ? b[p].maxz : 1 / 0
|
|
6682
|
-
))),
|
|
6745
|
+
))), H.updateMatrixWorld(!0), G = !0);
|
|
6683
6746
|
}
|
|
6684
|
-
if (!
|
|
6747
|
+
if (!G) break;
|
|
6685
6748
|
}
|
|
6686
|
-
i && b.forEach((
|
|
6687
|
-
this.poseTarget.props[
|
|
6749
|
+
i && b.forEach((S) => {
|
|
6750
|
+
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
6751
|
});
|
|
6689
6752
|
}
|
|
6690
6753
|
/**
|
|
@@ -6734,7 +6797,7 @@ const Ie = {
|
|
|
6734
6797
|
// Male, English - Powerful
|
|
6735
6798
|
}
|
|
6736
6799
|
};
|
|
6737
|
-
function
|
|
6800
|
+
function Ee() {
|
|
6738
6801
|
return {
|
|
6739
6802
|
service: "elevenlabs",
|
|
6740
6803
|
endpoint: Ie.endpoint,
|
|
@@ -6744,16 +6807,16 @@ function Fe() {
|
|
|
6744
6807
|
};
|
|
6745
6808
|
}
|
|
6746
6809
|
function kt() {
|
|
6747
|
-
const
|
|
6748
|
-
return Object.entries(
|
|
6810
|
+
const X = Ee(), t = [];
|
|
6811
|
+
return Object.entries(X.voices).forEach(([e, n]) => {
|
|
6749
6812
|
t.push({
|
|
6750
6813
|
value: n,
|
|
6751
|
-
label: `${e.charAt(0).toUpperCase() + e.slice(1)} (${
|
|
6814
|
+
label: `${e.charAt(0).toUpperCase() + e.slice(1)} (${X.service})`
|
|
6752
6815
|
});
|
|
6753
6816
|
}), t;
|
|
6754
6817
|
}
|
|
6755
6818
|
const Ve = Me(({
|
|
6756
|
-
avatarUrl:
|
|
6819
|
+
avatarUrl: X = "/avatars/brunette.glb",
|
|
6757
6820
|
avatarBody: t = "F",
|
|
6758
6821
|
mood: e = "neutral",
|
|
6759
6822
|
ttsLang: n = "en",
|
|
@@ -6766,222 +6829,222 @@ const Ve = Me(({
|
|
|
6766
6829
|
cameraView: u = "upper",
|
|
6767
6830
|
onReady: a = () => {
|
|
6768
6831
|
},
|
|
6769
|
-
onLoading:
|
|
6832
|
+
onLoading: d = () => {
|
|
6770
6833
|
},
|
|
6771
|
-
onError:
|
|
6834
|
+
onError: c = () => {
|
|
6772
6835
|
},
|
|
6773
6836
|
className: g = "",
|
|
6774
6837
|
style: b = {},
|
|
6775
6838
|
animations: x = {}
|
|
6776
|
-
},
|
|
6777
|
-
const
|
|
6778
|
-
|
|
6779
|
-
|
|
6780
|
-
}, [
|
|
6781
|
-
|
|
6839
|
+
}, S) => {
|
|
6840
|
+
const G = V(null), p = V(null), P = V(r), H = V(null), y = V(null), I = V(!1), z = V({ remainingText: null, originalText: null, options: null }), A = V([]), Y = V(0), [k, C] = de(!0), [_, B] = de(null), [ee, ie] = de(!1), [oe, he] = de(!1);
|
|
6841
|
+
me(() => {
|
|
6842
|
+
I.current = oe;
|
|
6843
|
+
}, [oe]), me(() => {
|
|
6844
|
+
P.current = r;
|
|
6782
6845
|
}, [r]);
|
|
6783
|
-
const
|
|
6784
|
-
let
|
|
6785
|
-
|
|
6846
|
+
const K = Ee(), Q = i || K.service;
|
|
6847
|
+
let W;
|
|
6848
|
+
Q === "browser" ? W = {
|
|
6786
6849
|
service: "browser",
|
|
6787
6850
|
endpoint: "",
|
|
6788
6851
|
apiKey: null,
|
|
6789
6852
|
defaultVoice: "Google US English"
|
|
6790
|
-
} :
|
|
6853
|
+
} : Q === "elevenlabs" ? W = {
|
|
6791
6854
|
service: "elevenlabs",
|
|
6792
6855
|
endpoint: "https://api.elevenlabs.io/v1/text-to-speech",
|
|
6793
|
-
apiKey: o ||
|
|
6794
|
-
defaultVoice: s ||
|
|
6795
|
-
voices:
|
|
6796
|
-
} :
|
|
6856
|
+
apiKey: o || K.apiKey,
|
|
6857
|
+
defaultVoice: s || K.defaultVoice || Ie.defaultVoice,
|
|
6858
|
+
voices: K.voices || Ie.voices
|
|
6859
|
+
} : Q === "deepgram" ? W = {
|
|
6797
6860
|
service: "deepgram",
|
|
6798
6861
|
endpoint: "https://api.deepgram.com/v1/speak",
|
|
6799
|
-
apiKey: o ||
|
|
6800
|
-
defaultVoice: s ||
|
|
6801
|
-
voices:
|
|
6802
|
-
} :
|
|
6803
|
-
...
|
|
6862
|
+
apiKey: o || K.apiKey,
|
|
6863
|
+
defaultVoice: s || K.defaultVoice || Te.defaultVoice,
|
|
6864
|
+
voices: K.voices || Te.voices
|
|
6865
|
+
} : W = {
|
|
6866
|
+
...K,
|
|
6804
6867
|
// Override API key if provided via props
|
|
6805
|
-
apiKey: o !== null ? o :
|
|
6868
|
+
apiKey: o !== null ? o : K.apiKey
|
|
6806
6869
|
};
|
|
6807
6870
|
const v = {
|
|
6808
|
-
url:
|
|
6871
|
+
url: X,
|
|
6809
6872
|
body: t,
|
|
6810
6873
|
avatarMood: e,
|
|
6811
|
-
ttsLang:
|
|
6812
|
-
ttsVoice: s ||
|
|
6874
|
+
ttsLang: Q === "browser" ? "en-US" : n,
|
|
6875
|
+
ttsVoice: s || W.defaultVoice,
|
|
6813
6876
|
lipsyncLang: "en",
|
|
6814
6877
|
showFullAvatar: r,
|
|
6815
6878
|
bodyMovement: l,
|
|
6816
6879
|
movementIntensity: h
|
|
6817
6880
|
}, R = {
|
|
6818
|
-
ttsEndpoint:
|
|
6819
|
-
ttsApikey:
|
|
6820
|
-
ttsService:
|
|
6881
|
+
ttsEndpoint: W.endpoint,
|
|
6882
|
+
ttsApikey: W.apiKey,
|
|
6883
|
+
ttsService: Q,
|
|
6821
6884
|
lipsyncModules: ["en"],
|
|
6822
6885
|
cameraView: u
|
|
6823
|
-
},
|
|
6824
|
-
if (!(!
|
|
6886
|
+
}, T = N(async () => {
|
|
6887
|
+
if (!(!G.current || p.current))
|
|
6825
6888
|
try {
|
|
6826
|
-
if (
|
|
6827
|
-
if (
|
|
6828
|
-
const
|
|
6829
|
-
|
|
6889
|
+
if (C(!0), B(null), p.current = new Be(G.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) => {
|
|
6890
|
+
if (U.lengthComputable) {
|
|
6891
|
+
const ne = Math.min(100, Math.round(U.loaded / U.total * 100));
|
|
6892
|
+
d(ne);
|
|
6830
6893
|
}
|
|
6831
|
-
}), await new Promise((
|
|
6832
|
-
const
|
|
6833
|
-
p.current.lipsync && Object.keys(p.current.lipsync).length > 0 ?
|
|
6894
|
+
}), await new Promise((U) => {
|
|
6895
|
+
const ne = () => {
|
|
6896
|
+
p.current.lipsync && Object.keys(p.current.lipsync).length > 0 ? U() : setTimeout(ne, 100);
|
|
6834
6897
|
};
|
|
6835
|
-
|
|
6898
|
+
ne();
|
|
6836
6899
|
}), p.current && p.current.setShowFullAvatar)
|
|
6837
6900
|
try {
|
|
6838
6901
|
p.current.setShowFullAvatar(r);
|
|
6839
|
-
} catch (
|
|
6840
|
-
console.warn("Error setting full body mode on initialization:",
|
|
6902
|
+
} catch (U) {
|
|
6903
|
+
console.warn("Error setting full body mode on initialization:", U);
|
|
6841
6904
|
}
|
|
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
|
|
6905
|
+
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()), C(!1), ie(!0), a(p.current);
|
|
6906
|
+
const D = () => {
|
|
6844
6907
|
document.visibilityState === "visible" ? p.current?.start() : p.current?.stop();
|
|
6845
6908
|
};
|
|
6846
|
-
return document.addEventListener("visibilitychange",
|
|
6847
|
-
document.removeEventListener("visibilitychange",
|
|
6909
|
+
return document.addEventListener("visibilitychange", D), () => {
|
|
6910
|
+
document.removeEventListener("visibilitychange", D);
|
|
6848
6911
|
};
|
|
6849
6912
|
} catch (L) {
|
|
6850
|
-
console.error("Error initializing TalkingHead:", L),
|
|
6913
|
+
console.error("Error initializing TalkingHead:", L), B(L.message || "Failed to initialize avatar"), C(!1), c(L);
|
|
6851
6914
|
}
|
|
6852
|
-
}, [
|
|
6853
|
-
|
|
6915
|
+
}, [X, t, e, n, i, s, o, r, l, h, u]);
|
|
6916
|
+
me(() => (T(), () => {
|
|
6854
6917
|
p.current && (p.current.stop(), p.current.dispose(), p.current = null);
|
|
6855
|
-
}), [
|
|
6856
|
-
if (!
|
|
6857
|
-
const L = new ResizeObserver((
|
|
6858
|
-
for (const
|
|
6918
|
+
}), [T]), me(() => {
|
|
6919
|
+
if (!G.current || !p.current) return;
|
|
6920
|
+
const L = new ResizeObserver((U) => {
|
|
6921
|
+
for (const ne of U)
|
|
6859
6922
|
p.current && p.current.onResize && p.current.onResize();
|
|
6860
6923
|
});
|
|
6861
|
-
L.observe(
|
|
6862
|
-
const
|
|
6924
|
+
L.observe(G.current);
|
|
6925
|
+
const D = () => {
|
|
6863
6926
|
p.current && p.current.onResize && p.current.onResize();
|
|
6864
6927
|
};
|
|
6865
|
-
return window.addEventListener("resize",
|
|
6866
|
-
L.disconnect(), window.removeEventListener("resize",
|
|
6928
|
+
return window.addEventListener("resize", D), () => {
|
|
6929
|
+
L.disconnect(), window.removeEventListener("resize", D);
|
|
6867
6930
|
};
|
|
6868
6931
|
}, [ee]);
|
|
6869
|
-
const M =
|
|
6932
|
+
const M = N(async () => {
|
|
6870
6933
|
if (p.current && p.current.audioCtx)
|
|
6871
6934
|
try {
|
|
6872
6935
|
(p.current.audioCtx.state === "suspended" || p.current.audioCtx.state === "interrupted") && (await p.current.audioCtx.resume(), console.log("Audio context resumed"));
|
|
6873
6936
|
} catch (L) {
|
|
6874
6937
|
console.warn("Failed to resume audio context:", L);
|
|
6875
6938
|
}
|
|
6876
|
-
}, []),
|
|
6939
|
+
}, []), O = N(async (L, D = {}) => {
|
|
6877
6940
|
if (p.current && ee)
|
|
6878
6941
|
try {
|
|
6879
|
-
y.current && (clearInterval(y.current), y.current = null),
|
|
6880
|
-
const
|
|
6881
|
-
|
|
6942
|
+
y.current && (clearInterval(y.current), y.current = null), H.current = { text: L, options: D }, z.current = { remainingText: null, originalText: null, options: null };
|
|
6943
|
+
const U = /[!\.\?\n\p{Extended_Pictographic}]/ug, ne = L.split(U).map((j) => j.trim()).filter((j) => j.length > 0);
|
|
6944
|
+
A.current = ne, Y.current = 0, he(!1), I.current = !1, await M();
|
|
6882
6945
|
const ge = {
|
|
6883
|
-
...
|
|
6884
|
-
lipsyncLang:
|
|
6946
|
+
...D,
|
|
6947
|
+
lipsyncLang: D.lipsyncLang || v.lipsyncLang || "en"
|
|
6885
6948
|
};
|
|
6886
|
-
if (
|
|
6887
|
-
const
|
|
6888
|
-
let
|
|
6889
|
-
const
|
|
6949
|
+
if (D.onSpeechEnd && p.current) {
|
|
6950
|
+
const j = p.current;
|
|
6951
|
+
let ce = null, Se = 0;
|
|
6952
|
+
const Le = 1200;
|
|
6890
6953
|
let be = !1;
|
|
6891
|
-
|
|
6892
|
-
if (Se++,
|
|
6954
|
+
ce = setInterval(() => {
|
|
6955
|
+
if (Se++, I.current)
|
|
6893
6956
|
return;
|
|
6894
|
-
if (Se >
|
|
6895
|
-
if (
|
|
6957
|
+
if (Se > Le) {
|
|
6958
|
+
if (ce && (clearInterval(ce), ce = null, y.current = null), !be && !I.current) {
|
|
6896
6959
|
be = !0;
|
|
6897
6960
|
try {
|
|
6898
|
-
|
|
6961
|
+
D.onSpeechEnd();
|
|
6899
6962
|
} catch (Ne) {
|
|
6900
6963
|
console.error("Error in onSpeechEnd callback (timeout):", Ne);
|
|
6901
6964
|
}
|
|
6902
6965
|
}
|
|
6903
6966
|
return;
|
|
6904
6967
|
}
|
|
6905
|
-
const ye = !
|
|
6906
|
-
|
|
6907
|
-
if (
|
|
6908
|
-
be = !0,
|
|
6968
|
+
const ye = !j.speechQueue || j.speechQueue.length === 0, ke = !j.audioPlaylist || j.audioPlaylist.length === 0;
|
|
6969
|
+
j && j.isSpeaking === !1 && ye && ke && j.isAudioPlaying === !1 && !be && !I.current && setTimeout(() => {
|
|
6970
|
+
if (j && !I.current && j.isSpeaking === !1 && (!j.speechQueue || j.speechQueue.length === 0) && (!j.audioPlaylist || j.audioPlaylist.length === 0) && j.isAudioPlaying === !1 && !be && !I.current) {
|
|
6971
|
+
be = !0, ce && (clearInterval(ce), ce = null, y.current = null);
|
|
6909
6972
|
try {
|
|
6910
|
-
|
|
6973
|
+
D.onSpeechEnd();
|
|
6911
6974
|
} catch (Ze) {
|
|
6912
6975
|
console.error("Error in onSpeechEnd callback:", Ze);
|
|
6913
6976
|
}
|
|
6914
6977
|
}
|
|
6915
6978
|
}, 100);
|
|
6916
|
-
}, 100), y.current =
|
|
6979
|
+
}, 100), y.current = ce;
|
|
6917
6980
|
}
|
|
6918
6981
|
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
6982
|
await M(), p.current && p.current.lipsync && (p.current.setSlowdownRate && p.current.setSlowdownRate(1.05), p.current.speakText(L, ge));
|
|
6920
6983
|
}, 100);
|
|
6921
|
-
} catch (
|
|
6922
|
-
console.error("Error speaking text:",
|
|
6984
|
+
} catch (U) {
|
|
6985
|
+
console.error("Error speaking text:", U), B(U.message || "Failed to speak text");
|
|
6923
6986
|
}
|
|
6924
|
-
}, [ee, M, v.lipsyncLang]),
|
|
6925
|
-
p.current && (p.current.stopSpeaking(), p.current.setSlowdownRate && p.current.setSlowdownRate(1),
|
|
6926
|
-
}, []),
|
|
6987
|
+
}, [ee, M, v.lipsyncLang]), te = N(() => {
|
|
6988
|
+
p.current && (p.current.stopSpeaking(), p.current.setSlowdownRate && p.current.setSlowdownRate(1), H.current = null, he(!1));
|
|
6989
|
+
}, []), q = N(() => {
|
|
6927
6990
|
if (p.current && p.current.pauseSpeaking) {
|
|
6928
6991
|
const L = p.current;
|
|
6929
6992
|
if (L.isSpeaking || L.audioPlaylist && L.audioPlaylist.length > 0 || L.speechQueue && L.speechQueue.length > 0) {
|
|
6930
6993
|
y.current && (clearInterval(y.current), y.current = null);
|
|
6931
|
-
let
|
|
6932
|
-
if (
|
|
6933
|
-
const
|
|
6934
|
-
if (
|
|
6994
|
+
let U = "";
|
|
6995
|
+
if (H.current && A.current.length > 0) {
|
|
6996
|
+
const ne = A.current.length, ge = L.speechQueue ? L.speechQueue.filter((Le) => Le && Le.text && Array.isArray(Le.text) && Le.text.length > 0).length : 0, j = L.audioPlaylist && L.audioPlaylist.length > 0, ce = ge + (j ? 1 : 0), Se = ne - ce;
|
|
6997
|
+
if (ce > 0 && Se < ne && (U = A.current.slice(Se).join(". ").trim(), !U && ge > 0 && L.speechQueue)) {
|
|
6935
6998
|
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() && (
|
|
6999
|
+
be && be.trim() && (U = be.trim());
|
|
6937
7000
|
}
|
|
6938
7001
|
}
|
|
6939
|
-
|
|
6940
|
-
remainingText:
|
|
6941
|
-
originalText:
|
|
6942
|
-
options:
|
|
6943
|
-
}), L.speechQueue && (L.speechQueue.length = 0), p.current.pauseSpeaking(),
|
|
7002
|
+
H.current && (z.current = {
|
|
7003
|
+
remainingText: U || null,
|
|
7004
|
+
originalText: H.current.text,
|
|
7005
|
+
options: H.current.options
|
|
7006
|
+
}), L.speechQueue && (L.speechQueue.length = 0), p.current.pauseSpeaking(), I.current = !0, he(!0);
|
|
6944
7007
|
}
|
|
6945
7008
|
}
|
|
6946
|
-
}, []),
|
|
6947
|
-
if (!p.current || !
|
|
7009
|
+
}, []), $ = N(async () => {
|
|
7010
|
+
if (!p.current || !oe)
|
|
6948
7011
|
return;
|
|
6949
|
-
let L = "",
|
|
6950
|
-
if (
|
|
6951
|
-
L =
|
|
6952
|
-
else if (
|
|
6953
|
-
L =
|
|
7012
|
+
let L = "", D = {};
|
|
7013
|
+
if (z.current && z.current.remainingText)
|
|
7014
|
+
L = z.current.remainingText, D = z.current.options || {}, z.current = { remainingText: null, originalText: null, options: null };
|
|
7015
|
+
else if (H.current && H.current.text)
|
|
7016
|
+
L = H.current.text, D = H.current.options || {};
|
|
6954
7017
|
else {
|
|
6955
|
-
console.warn("Resume called but no paused speech found"),
|
|
7018
|
+
console.warn("Resume called but no paused speech found"), he(!1), I.current = !1;
|
|
6956
7019
|
return;
|
|
6957
7020
|
}
|
|
6958
|
-
|
|
6959
|
-
const
|
|
6960
|
-
...
|
|
6961
|
-
lipsyncLang:
|
|
7021
|
+
he(!1), I.current = !1, await M();
|
|
7022
|
+
const U = {
|
|
7023
|
+
...D,
|
|
7024
|
+
lipsyncLang: D.lipsyncLang || v.lipsyncLang || "en"
|
|
6962
7025
|
};
|
|
6963
7026
|
try {
|
|
6964
|
-
await
|
|
6965
|
-
} catch (
|
|
6966
|
-
console.error("Error resuming speech:",
|
|
7027
|
+
await O(L, U);
|
|
7028
|
+
} catch (ne) {
|
|
7029
|
+
console.error("Error resuming speech:", ne), he(!1), I.current = !1;
|
|
6967
7030
|
}
|
|
6968
|
-
}, [M,
|
|
7031
|
+
}, [M, oe, O, v]), Ae = N((L) => {
|
|
6969
7032
|
p.current && p.current.setMood(L);
|
|
6970
|
-
}, []), we =
|
|
7033
|
+
}, []), we = N((L) => {
|
|
6971
7034
|
p.current && p.current.setSlowdownRate && p.current.setSlowdownRate(L);
|
|
6972
|
-
}, []),
|
|
7035
|
+
}, []), E = N((L, D = !1) => {
|
|
6973
7036
|
if (p.current && p.current.playAnimation) {
|
|
6974
7037
|
if (x && x[L] && (L = x[L]), p.current.setShowFullAvatar)
|
|
6975
7038
|
try {
|
|
6976
|
-
p.current.setShowFullAvatar(
|
|
6977
|
-
} catch (
|
|
6978
|
-
console.warn("Error setting full body mode:",
|
|
7039
|
+
p.current.setShowFullAvatar(P.current);
|
|
7040
|
+
} catch (ne) {
|
|
7041
|
+
console.warn("Error setting full body mode:", ne);
|
|
6979
7042
|
}
|
|
6980
7043
|
if (L.includes("."))
|
|
6981
7044
|
try {
|
|
6982
|
-
p.current.playAnimation(L, null, 10, 0, 0.01,
|
|
6983
|
-
} catch (
|
|
6984
|
-
console.warn(`Failed to play ${L}:`,
|
|
7045
|
+
p.current.playAnimation(L, null, 10, 0, 0.01, D);
|
|
7046
|
+
} catch (ne) {
|
|
7047
|
+
console.warn(`Failed to play ${L}:`, ne);
|
|
6985
7048
|
try {
|
|
6986
7049
|
p.current.setBodyMovement("idle");
|
|
6987
7050
|
} catch (ge) {
|
|
@@ -6989,11 +7052,11 @@ const Ve = Me(({
|
|
|
6989
7052
|
}
|
|
6990
7053
|
}
|
|
6991
7054
|
else {
|
|
6992
|
-
const
|
|
7055
|
+
const ne = [".fbx", ".glb", ".gltf"];
|
|
6993
7056
|
let ge = !1;
|
|
6994
|
-
for (const
|
|
7057
|
+
for (const j of ne)
|
|
6995
7058
|
try {
|
|
6996
|
-
p.current.playAnimation(L +
|
|
7059
|
+
p.current.playAnimation(L + j, null, 10, 0, 0.01, D), ge = !0;
|
|
6997
7060
|
break;
|
|
6998
7061
|
} catch {
|
|
6999
7062
|
}
|
|
@@ -7001,41 +7064,41 @@ const Ve = Me(({
|
|
|
7001
7064
|
console.warn("Animation not found:", L);
|
|
7002
7065
|
try {
|
|
7003
7066
|
p.current.setBodyMovement("idle");
|
|
7004
|
-
} catch (
|
|
7005
|
-
console.warn("Fallback animation also failed:",
|
|
7067
|
+
} catch (j) {
|
|
7068
|
+
console.warn("Fallback animation also failed:", j);
|
|
7006
7069
|
}
|
|
7007
7070
|
}
|
|
7008
7071
|
}
|
|
7009
7072
|
}
|
|
7010
|
-
}, [x]),
|
|
7073
|
+
}, [x]), se = N(() => {
|
|
7011
7074
|
p.current && p.current.onResize && p.current.onResize();
|
|
7012
7075
|
}, []);
|
|
7013
|
-
return
|
|
7014
|
-
speakText:
|
|
7015
|
-
stopSpeaking:
|
|
7016
|
-
pauseSpeaking:
|
|
7017
|
-
resumeSpeaking:
|
|
7076
|
+
return Fe(S, () => ({
|
|
7077
|
+
speakText: O,
|
|
7078
|
+
stopSpeaking: te,
|
|
7079
|
+
pauseSpeaking: q,
|
|
7080
|
+
resumeSpeaking: $,
|
|
7018
7081
|
resumeAudioContext: M,
|
|
7019
|
-
setMood:
|
|
7082
|
+
setMood: Ae,
|
|
7020
7083
|
setTimingAdjustment: we,
|
|
7021
|
-
playAnimation:
|
|
7084
|
+
playAnimation: E,
|
|
7022
7085
|
isReady: ee,
|
|
7023
|
-
isPaused:
|
|
7086
|
+
isPaused: oe,
|
|
7024
7087
|
talkingHead: p.current,
|
|
7025
|
-
handleResize:
|
|
7088
|
+
handleResize: se,
|
|
7026
7089
|
setBodyMovement: (L) => {
|
|
7027
7090
|
if (p.current && p.current.setShowFullAvatar && p.current.setBodyMovement)
|
|
7028
7091
|
try {
|
|
7029
|
-
p.current.setShowFullAvatar(
|
|
7030
|
-
} catch (
|
|
7031
|
-
console.warn("Error setting body movement:",
|
|
7092
|
+
p.current.setShowFullAvatar(P.current), p.current.setBodyMovement(L);
|
|
7093
|
+
} catch (D) {
|
|
7094
|
+
console.warn("Error setting body movement:", D);
|
|
7032
7095
|
}
|
|
7033
7096
|
},
|
|
7034
7097
|
setMovementIntensity: (L) => p.current?.setMovementIntensity(L),
|
|
7035
7098
|
playRandomDance: () => {
|
|
7036
7099
|
if (p.current && p.current.setShowFullAvatar && p.current.playRandomDance)
|
|
7037
7100
|
try {
|
|
7038
|
-
p.current.setShowFullAvatar(
|
|
7101
|
+
p.current.setShowFullAvatar(P.current), p.current.playRandomDance();
|
|
7039
7102
|
} catch (L) {
|
|
7040
7103
|
console.warn("Error playing random dance:", L);
|
|
7041
7104
|
}
|
|
@@ -7043,15 +7106,15 @@ const Ve = Me(({
|
|
|
7043
7106
|
playReaction: (L) => {
|
|
7044
7107
|
if (p.current && p.current.setShowFullAvatar && p.current.playReaction)
|
|
7045
7108
|
try {
|
|
7046
|
-
p.current.setShowFullAvatar(
|
|
7047
|
-
} catch (
|
|
7048
|
-
console.warn("Error playing reaction:",
|
|
7109
|
+
p.current.setShowFullAvatar(P.current), p.current.playReaction(L);
|
|
7110
|
+
} catch (D) {
|
|
7111
|
+
console.warn("Error playing reaction:", D);
|
|
7049
7112
|
}
|
|
7050
7113
|
},
|
|
7051
7114
|
playCelebration: () => {
|
|
7052
7115
|
if (p.current && p.current.setShowFullAvatar && p.current.playCelebration)
|
|
7053
7116
|
try {
|
|
7054
|
-
p.current.setShowFullAvatar(
|
|
7117
|
+
p.current.setShowFullAvatar(P.current), p.current.playCelebration();
|
|
7055
7118
|
} catch (L) {
|
|
7056
7119
|
console.warn("Error playing celebration:", L);
|
|
7057
7120
|
}
|
|
@@ -7059,9 +7122,9 @@ const Ve = Me(({
|
|
|
7059
7122
|
setShowFullAvatar: (L) => {
|
|
7060
7123
|
if (p.current && p.current.setShowFullAvatar)
|
|
7061
7124
|
try {
|
|
7062
|
-
|
|
7063
|
-
} catch (
|
|
7064
|
-
console.warn("Error setting showFullAvatar:",
|
|
7125
|
+
P.current = L, p.current.setShowFullAvatar(L);
|
|
7126
|
+
} catch (D) {
|
|
7127
|
+
console.warn("Error setting showFullAvatar:", D);
|
|
7065
7128
|
}
|
|
7066
7129
|
},
|
|
7067
7130
|
lockAvatarPosition: () => {
|
|
@@ -7091,10 +7154,10 @@ const Ve = Me(({
|
|
|
7091
7154
|
...b
|
|
7092
7155
|
},
|
|
7093
7156
|
children: [
|
|
7094
|
-
/* @__PURE__ */
|
|
7157
|
+
/* @__PURE__ */ pe(
|
|
7095
7158
|
"div",
|
|
7096
7159
|
{
|
|
7097
|
-
ref:
|
|
7160
|
+
ref: G,
|
|
7098
7161
|
className: "talking-head-viewer",
|
|
7099
7162
|
style: {
|
|
7100
7163
|
width: "100%",
|
|
@@ -7103,7 +7166,7 @@ const Ve = Me(({
|
|
|
7103
7166
|
}
|
|
7104
7167
|
}
|
|
7105
7168
|
),
|
|
7106
|
-
k && /* @__PURE__ */
|
|
7169
|
+
k && /* @__PURE__ */ pe("div", { className: "loading-overlay", style: {
|
|
7107
7170
|
position: "absolute",
|
|
7108
7171
|
top: "50%",
|
|
7109
7172
|
left: "50%",
|
|
@@ -7112,7 +7175,7 @@ const Ve = Me(({
|
|
|
7112
7175
|
fontSize: "18px",
|
|
7113
7176
|
zIndex: 10
|
|
7114
7177
|
}, children: "Loading avatar..." }),
|
|
7115
|
-
|
|
7178
|
+
_ && /* @__PURE__ */ pe("div", { className: "error-overlay", style: {
|
|
7116
7179
|
position: "absolute",
|
|
7117
7180
|
top: "50%",
|
|
7118
7181
|
left: "50%",
|
|
@@ -7123,14 +7186,14 @@ const Ve = Me(({
|
|
|
7123
7186
|
zIndex: 10,
|
|
7124
7187
|
padding: "20px",
|
|
7125
7188
|
borderRadius: "8px"
|
|
7126
|
-
}, children:
|
|
7189
|
+
}, children: _ })
|
|
7127
7190
|
]
|
|
7128
7191
|
}
|
|
7129
7192
|
);
|
|
7130
7193
|
});
|
|
7131
7194
|
Ve.displayName = "TalkingHeadAvatar";
|
|
7132
7195
|
const pt = Me(({
|
|
7133
|
-
text:
|
|
7196
|
+
text: X = "Hello! I'm a talking avatar. How are you today?",
|
|
7134
7197
|
onLoading: t = () => {
|
|
7135
7198
|
},
|
|
7136
7199
|
onError: e = () => {
|
|
@@ -7141,7 +7204,7 @@ const pt = Me(({
|
|
|
7141
7204
|
style: s = {},
|
|
7142
7205
|
avatarConfig: o = {}
|
|
7143
7206
|
}, l) => {
|
|
7144
|
-
const h =
|
|
7207
|
+
const h = V(null), r = V(null), [u, a] = de(!0), [d, c] = de(null), [g, b] = de(!1), x = Ee(), S = o.ttsService || x.service, G = S === "browser" ? {
|
|
7145
7208
|
endpoint: "",
|
|
7146
7209
|
apiKey: null,
|
|
7147
7210
|
defaultVoice: "Google US English"
|
|
@@ -7150,14 +7213,14 @@ const pt = Me(({
|
|
|
7150
7213
|
// Override API key if provided via avatarConfig
|
|
7151
7214
|
apiKey: o.ttsApiKey !== void 0 && o.ttsApiKey !== null ? o.ttsApiKey : x.apiKey,
|
|
7152
7215
|
// Override endpoint for ElevenLabs if service is explicitly set
|
|
7153
|
-
endpoint:
|
|
7216
|
+
endpoint: S === "elevenlabs" && o.ttsApiKey ? "https://api.elevenlabs.io/v1/text-to-speech" : x.endpoint
|
|
7154
7217
|
}, p = {
|
|
7155
7218
|
url: "/avatars/brunette.glb",
|
|
7156
7219
|
// Use brunette avatar (working glTF file)
|
|
7157
7220
|
body: "F",
|
|
7158
7221
|
avatarMood: "neutral",
|
|
7159
|
-
ttsLang:
|
|
7160
|
-
ttsVoice: o.ttsVoice ||
|
|
7222
|
+
ttsLang: S === "browser" ? "en-US" : "en",
|
|
7223
|
+
ttsVoice: o.ttsVoice || G.defaultVoice,
|
|
7161
7224
|
lipsyncLang: "en",
|
|
7162
7225
|
// English lip-sync
|
|
7163
7226
|
showFullAvatar: !0,
|
|
@@ -7165,81 +7228,81 @@ const pt = Me(({
|
|
|
7165
7228
|
bodyMovement: "idle",
|
|
7166
7229
|
movementIntensity: 0.5,
|
|
7167
7230
|
...o
|
|
7168
|
-
},
|
|
7169
|
-
ttsEndpoint:
|
|
7170
|
-
ttsApikey:
|
|
7171
|
-
ttsService:
|
|
7231
|
+
}, P = {
|
|
7232
|
+
ttsEndpoint: G.endpoint,
|
|
7233
|
+
ttsApikey: G.apiKey,
|
|
7234
|
+
ttsService: S,
|
|
7172
7235
|
lipsyncModules: ["en"],
|
|
7173
7236
|
cameraView: "upper"
|
|
7174
|
-
},
|
|
7237
|
+
}, H = N(async () => {
|
|
7175
7238
|
if (!(!h.current || r.current))
|
|
7176
7239
|
try {
|
|
7177
|
-
if (a(!0),
|
|
7178
|
-
if (
|
|
7179
|
-
const
|
|
7180
|
-
t(
|
|
7240
|
+
if (a(!0), c(null), r.current = new Be(h.current, P), await r.current.showAvatar(p, (_) => {
|
|
7241
|
+
if (_.lengthComputable) {
|
|
7242
|
+
const B = Math.min(100, Math.round(_.loaded / _.total * 100));
|
|
7243
|
+
t(B);
|
|
7181
7244
|
}
|
|
7182
7245
|
}), 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:",
|
|
7246
|
+
const _ = r.current.morphs[0].morphTargetDictionary;
|
|
7247
|
+
console.log("Available morph targets:", Object.keys(_));
|
|
7248
|
+
const B = Object.keys(_).filter((ee) => ee.startsWith("viseme_"));
|
|
7249
|
+
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
7250
|
}
|
|
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)),
|
|
7251
|
+
if (await new Promise((_) => {
|
|
7252
|
+
const B = () => {
|
|
7253
|
+
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
7254
|
};
|
|
7192
|
-
|
|
7255
|
+
B();
|
|
7193
7256
|
}), r.current && r.current.setShowFullAvatar)
|
|
7194
7257
|
try {
|
|
7195
7258
|
r.current.setShowFullAvatar(!0), console.log("Avatar initialized in full body mode");
|
|
7196
|
-
} catch (
|
|
7197
|
-
console.warn("Error setting full body mode on initialization:",
|
|
7259
|
+
} catch (_) {
|
|
7260
|
+
console.warn("Error setting full body mode on initialization:", _);
|
|
7198
7261
|
}
|
|
7199
7262
|
a(!1), b(!0), n(r.current);
|
|
7200
|
-
const
|
|
7263
|
+
const C = () => {
|
|
7201
7264
|
document.visibilityState === "visible" ? r.current?.start() : r.current?.stop();
|
|
7202
7265
|
};
|
|
7203
|
-
return document.addEventListener("visibilitychange",
|
|
7204
|
-
document.removeEventListener("visibilitychange",
|
|
7266
|
+
return document.addEventListener("visibilitychange", C), () => {
|
|
7267
|
+
document.removeEventListener("visibilitychange", C);
|
|
7205
7268
|
};
|
|
7206
7269
|
} catch (k) {
|
|
7207
|
-
console.error("Error initializing TalkingHead:", k),
|
|
7270
|
+
console.error("Error initializing TalkingHead:", k), c(k.message || "Failed to initialize avatar"), a(!1), e(k);
|
|
7208
7271
|
}
|
|
7209
7272
|
}, []);
|
|
7210
|
-
|
|
7273
|
+
me(() => (H(), () => {
|
|
7211
7274
|
r.current && (r.current.stop(), r.current.dispose(), r.current = null);
|
|
7212
|
-
}), [
|
|
7213
|
-
const y =
|
|
7275
|
+
}), [H]);
|
|
7276
|
+
const y = N((k) => {
|
|
7214
7277
|
if (r.current && g)
|
|
7215
7278
|
try {
|
|
7216
7279
|
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
7280
|
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
7281
|
}, 500));
|
|
7219
|
-
} catch (
|
|
7220
|
-
console.error("Error speaking text:",
|
|
7282
|
+
} catch (C) {
|
|
7283
|
+
console.error("Error speaking text:", C), c(C.message || "Failed to speak text");
|
|
7221
7284
|
}
|
|
7222
7285
|
else
|
|
7223
7286
|
console.warn("Avatar not ready for speaking. isReady:", g, "talkingHeadRef:", !!r.current);
|
|
7224
|
-
}, [g, p]),
|
|
7287
|
+
}, [g, p]), I = N(() => {
|
|
7225
7288
|
r.current && (r.current.stopSpeaking(), r.current.setSlowdownRate && (r.current.setSlowdownRate(1), console.log("Reset timing to normal")));
|
|
7226
|
-
}, []),
|
|
7289
|
+
}, []), z = N((k) => {
|
|
7227
7290
|
r.current && r.current.setMood(k);
|
|
7228
|
-
}, []),
|
|
7291
|
+
}, []), A = N((k) => {
|
|
7229
7292
|
r.current && r.current.setSlowdownRate && (r.current.setSlowdownRate(k), console.log("Timing adjustment set to:", k));
|
|
7230
|
-
}, []),
|
|
7293
|
+
}, []), Y = N((k, C = !1) => {
|
|
7231
7294
|
if (r.current && r.current.playAnimation) {
|
|
7232
7295
|
if (r.current.setShowFullAvatar)
|
|
7233
7296
|
try {
|
|
7234
7297
|
r.current.setShowFullAvatar(!0);
|
|
7235
|
-
} catch (
|
|
7236
|
-
console.warn("Error setting full body mode:",
|
|
7298
|
+
} catch (B) {
|
|
7299
|
+
console.warn("Error setting full body mode:", B);
|
|
7237
7300
|
}
|
|
7238
7301
|
if (k.includes("."))
|
|
7239
7302
|
try {
|
|
7240
|
-
r.current.playAnimation(k, null, 10, 0, 0.01,
|
|
7241
|
-
} catch (
|
|
7242
|
-
console.log(`Failed to play ${k}:`,
|
|
7303
|
+
r.current.playAnimation(k, null, 10, 0, 0.01, C), console.log("Playing animation:", k);
|
|
7304
|
+
} catch (B) {
|
|
7305
|
+
console.log(`Failed to play ${k}:`, B);
|
|
7243
7306
|
try {
|
|
7244
7307
|
r.current.setBodyMovement("idle"), console.log("Fallback to idle animation");
|
|
7245
7308
|
} catch (ee) {
|
|
@@ -7247,41 +7310,41 @@ const pt = Me(({
|
|
|
7247
7310
|
}
|
|
7248
7311
|
}
|
|
7249
7312
|
else {
|
|
7250
|
-
const
|
|
7313
|
+
const B = [".fbx", ".glb", ".gltf"];
|
|
7251
7314
|
let ee = !1;
|
|
7252
|
-
for (const
|
|
7315
|
+
for (const ie of B)
|
|
7253
7316
|
try {
|
|
7254
|
-
r.current.playAnimation(k +
|
|
7317
|
+
r.current.playAnimation(k + ie, null, 10, 0, 0.01, C), console.log("Playing animation:", k + ie), ee = !0;
|
|
7255
7318
|
break;
|
|
7256
7319
|
} catch {
|
|
7257
|
-
console.log(`Failed to play ${k}${
|
|
7320
|
+
console.log(`Failed to play ${k}${ie}, trying next format...`);
|
|
7258
7321
|
}
|
|
7259
7322
|
if (!ee) {
|
|
7260
7323
|
console.warn("Animation system not available or animation not found:", k);
|
|
7261
7324
|
try {
|
|
7262
7325
|
r.current.setBodyMovement("idle"), console.log("Fallback to idle animation");
|
|
7263
|
-
} catch (
|
|
7264
|
-
console.warn("Fallback animation also failed:",
|
|
7326
|
+
} catch (ie) {
|
|
7327
|
+
console.warn("Fallback animation also failed:", ie);
|
|
7265
7328
|
}
|
|
7266
7329
|
}
|
|
7267
7330
|
}
|
|
7268
7331
|
} else
|
|
7269
7332
|
console.warn("Animation system not available or animation not found:", k);
|
|
7270
7333
|
}, []);
|
|
7271
|
-
return
|
|
7334
|
+
return Fe(l, () => ({
|
|
7272
7335
|
speakText: y,
|
|
7273
|
-
stopSpeaking:
|
|
7274
|
-
setMood:
|
|
7275
|
-
setTimingAdjustment:
|
|
7276
|
-
playAnimation:
|
|
7336
|
+
stopSpeaking: I,
|
|
7337
|
+
setMood: z,
|
|
7338
|
+
setTimingAdjustment: A,
|
|
7339
|
+
playAnimation: Y,
|
|
7277
7340
|
isReady: g,
|
|
7278
7341
|
talkingHead: r.current,
|
|
7279
7342
|
setBodyMovement: (k) => {
|
|
7280
7343
|
if (r.current && r.current.setShowFullAvatar && r.current.setBodyMovement)
|
|
7281
7344
|
try {
|
|
7282
7345
|
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:",
|
|
7346
|
+
} catch (C) {
|
|
7347
|
+
console.warn("Error setting body movement:", C);
|
|
7285
7348
|
}
|
|
7286
7349
|
},
|
|
7287
7350
|
setMovementIntensity: (k) => r.current?.setMovementIntensity(k),
|
|
@@ -7297,8 +7360,8 @@ const pt = Me(({
|
|
|
7297
7360
|
if (r.current && r.current.setShowFullAvatar && r.current.playReaction)
|
|
7298
7361
|
try {
|
|
7299
7362
|
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:",
|
|
7363
|
+
} catch (C) {
|
|
7364
|
+
console.warn("Error playing reaction:", C);
|
|
7302
7365
|
}
|
|
7303
7366
|
},
|
|
7304
7367
|
playCelebration: () => {
|
|
@@ -7313,8 +7376,8 @@ const pt = Me(({
|
|
|
7313
7376
|
if (r.current && r.current.setShowFullAvatar)
|
|
7314
7377
|
try {
|
|
7315
7378
|
r.current.setShowFullAvatar(k), console.log("Show full avatar set to:", k);
|
|
7316
|
-
} catch (
|
|
7317
|
-
console.warn("Error setting showFullAvatar:",
|
|
7379
|
+
} catch (C) {
|
|
7380
|
+
console.warn("Error setting showFullAvatar:", C);
|
|
7318
7381
|
}
|
|
7319
7382
|
},
|
|
7320
7383
|
lockAvatarPosition: () => {
|
|
@@ -7334,7 +7397,7 @@ const pt = Me(({
|
|
|
7334
7397
|
}
|
|
7335
7398
|
}
|
|
7336
7399
|
})), /* @__PURE__ */ Pe("div", { className: `talking-head-container ${i}`, style: s, children: [
|
|
7337
|
-
/* @__PURE__ */
|
|
7400
|
+
/* @__PURE__ */ pe(
|
|
7338
7401
|
"div",
|
|
7339
7402
|
{
|
|
7340
7403
|
ref: h,
|
|
@@ -7346,7 +7409,7 @@ const pt = Me(({
|
|
|
7346
7409
|
}
|
|
7347
7410
|
}
|
|
7348
7411
|
),
|
|
7349
|
-
u && /* @__PURE__ */
|
|
7412
|
+
u && /* @__PURE__ */ pe("div", { className: "loading-overlay", style: {
|
|
7350
7413
|
position: "absolute",
|
|
7351
7414
|
top: "50%",
|
|
7352
7415
|
left: "50%",
|
|
@@ -7355,7 +7418,7 @@ const pt = Me(({
|
|
|
7355
7418
|
fontSize: "18px",
|
|
7356
7419
|
zIndex: 10
|
|
7357
7420
|
}, children: "Loading avatar..." }),
|
|
7358
|
-
|
|
7421
|
+
d && /* @__PURE__ */ pe("div", { className: "error-overlay", style: {
|
|
7359
7422
|
position: "absolute",
|
|
7360
7423
|
top: "50%",
|
|
7361
7424
|
left: "50%",
|
|
@@ -7366,12 +7429,12 @@ const pt = Me(({
|
|
|
7366
7429
|
zIndex: 10,
|
|
7367
7430
|
padding: "20px",
|
|
7368
7431
|
borderRadius: "8px"
|
|
7369
|
-
}, children:
|
|
7432
|
+
}, children: d })
|
|
7370
7433
|
] });
|
|
7371
7434
|
});
|
|
7372
7435
|
pt.displayName = "TalkingHeadComponent";
|
|
7373
7436
|
const gt = Me(({
|
|
7374
|
-
text:
|
|
7437
|
+
text: X = null,
|
|
7375
7438
|
avatarUrl: t = "/avatars/brunette.glb",
|
|
7376
7439
|
avatarBody: e = "F",
|
|
7377
7440
|
mood: n = "neutral",
|
|
@@ -7383,26 +7446,26 @@ const gt = Me(({
|
|
|
7383
7446
|
movementIntensity: r = 0.5,
|
|
7384
7447
|
showFullAvatar: u = !1,
|
|
7385
7448
|
cameraView: a = "upper",
|
|
7386
|
-
onReady:
|
|
7449
|
+
onReady: d = () => {
|
|
7387
7450
|
},
|
|
7388
|
-
onLoading:
|
|
7451
|
+
onLoading: c = () => {
|
|
7389
7452
|
},
|
|
7390
7453
|
onError: g = () => {
|
|
7391
7454
|
},
|
|
7392
7455
|
onSpeechEnd: b = () => {
|
|
7393
7456
|
},
|
|
7394
7457
|
className: x = "",
|
|
7395
|
-
style:
|
|
7396
|
-
animations:
|
|
7458
|
+
style: S = {},
|
|
7459
|
+
animations: G = {},
|
|
7397
7460
|
autoSpeak: p = !1
|
|
7398
|
-
},
|
|
7399
|
-
const
|
|
7400
|
-
|
|
7401
|
-
|
|
7402
|
-
}, [
|
|
7403
|
-
|
|
7461
|
+
}, P) => {
|
|
7462
|
+
const H = V(null), y = V(null), I = V(u), z = V(null), A = V(null), Y = V(!1), k = V({ remainingText: null, originalText: null, options: null }), C = V([]), [_, B] = de(!0), [ee, ie] = de(null), [oe, he] = de(!1), [K, Q] = de(!1);
|
|
7463
|
+
me(() => {
|
|
7464
|
+
Y.current = K;
|
|
7465
|
+
}, [K]), me(() => {
|
|
7466
|
+
I.current = u;
|
|
7404
7467
|
}, [u]);
|
|
7405
|
-
const
|
|
7468
|
+
const W = Ee(), v = s || W.service;
|
|
7406
7469
|
let R;
|
|
7407
7470
|
v === "browser" ? R = {
|
|
7408
7471
|
service: "browser",
|
|
@@ -7412,20 +7475,20 @@ const gt = Me(({
|
|
|
7412
7475
|
} : v === "elevenlabs" ? R = {
|
|
7413
7476
|
service: "elevenlabs",
|
|
7414
7477
|
endpoint: "https://api.elevenlabs.io/v1/text-to-speech",
|
|
7415
|
-
apiKey: l ||
|
|
7416
|
-
defaultVoice: o ||
|
|
7417
|
-
voices:
|
|
7478
|
+
apiKey: l || W.apiKey,
|
|
7479
|
+
defaultVoice: o || W.defaultVoice || Ie.defaultVoice,
|
|
7480
|
+
voices: W.voices || Ie.voices
|
|
7418
7481
|
} : v === "deepgram" ? R = {
|
|
7419
7482
|
service: "deepgram",
|
|
7420
7483
|
endpoint: "https://api.deepgram.com/v1/speak",
|
|
7421
|
-
apiKey: l ||
|
|
7422
|
-
defaultVoice: o ||
|
|
7423
|
-
voices:
|
|
7484
|
+
apiKey: l || W.apiKey,
|
|
7485
|
+
defaultVoice: o || W.defaultVoice || Te.defaultVoice,
|
|
7486
|
+
voices: W.voices || Te.voices
|
|
7424
7487
|
} : R = {
|
|
7425
|
-
...
|
|
7426
|
-
apiKey: l !== null ? l :
|
|
7488
|
+
...W,
|
|
7489
|
+
apiKey: l !== null ? l : W.apiKey
|
|
7427
7490
|
};
|
|
7428
|
-
const
|
|
7491
|
+
const T = {
|
|
7429
7492
|
url: t,
|
|
7430
7493
|
body: e,
|
|
7431
7494
|
avatarMood: n,
|
|
@@ -7441,121 +7504,121 @@ const gt = Me(({
|
|
|
7441
7504
|
ttsService: v,
|
|
7442
7505
|
lipsyncModules: ["en"],
|
|
7443
7506
|
cameraView: a
|
|
7444
|
-
},
|
|
7445
|
-
if (!(!
|
|
7507
|
+
}, O = N(async () => {
|
|
7508
|
+
if (!(!H.current || y.current))
|
|
7446
7509
|
try {
|
|
7447
|
-
|
|
7448
|
-
url:
|
|
7449
|
-
body:
|
|
7450
|
-
avatarMood:
|
|
7451
|
-
}), await y.current.showAvatar(
|
|
7452
|
-
if (
|
|
7453
|
-
const L = Math.min(100, Math.round(
|
|
7454
|
-
|
|
7510
|
+
B(!0), ie(null), y.current = new Be(H.current, M), console.log("Avatar config being passed:", {
|
|
7511
|
+
url: T.url,
|
|
7512
|
+
body: T.body,
|
|
7513
|
+
avatarMood: T.avatarMood
|
|
7514
|
+
}), await y.current.showAvatar(T, (se) => {
|
|
7515
|
+
if (se.lengthComputable) {
|
|
7516
|
+
const L = Math.min(100, Math.round(se.loaded / se.total * 100));
|
|
7517
|
+
c(L);
|
|
7455
7518
|
}
|
|
7456
|
-
}), y.current?.avatar && console.log("Avatar body after initialization:", y.current.avatar.body),
|
|
7457
|
-
const
|
|
7519
|
+
}), y.current?.avatar && console.log("Avatar body after initialization:", y.current.avatar.body), B(!1), he(!0), d(y.current);
|
|
7520
|
+
const E = () => {
|
|
7458
7521
|
document.visibilityState === "visible" ? y.current?.start() : y.current?.stop();
|
|
7459
7522
|
};
|
|
7460
|
-
return document.addEventListener("visibilitychange",
|
|
7461
|
-
document.removeEventListener("visibilitychange",
|
|
7523
|
+
return document.addEventListener("visibilitychange", E), () => {
|
|
7524
|
+
document.removeEventListener("visibilitychange", E);
|
|
7462
7525
|
};
|
|
7463
|
-
} catch (
|
|
7464
|
-
console.error("Error initializing TalkingHead:",
|
|
7526
|
+
} catch (E) {
|
|
7527
|
+
console.error("Error initializing TalkingHead:", E), ie(E.message || "Failed to initialize avatar"), B(!1), g(E);
|
|
7465
7528
|
}
|
|
7466
7529
|
}, []);
|
|
7467
|
-
|
|
7530
|
+
me(() => (O(), () => {
|
|
7468
7531
|
y.current && (y.current.stop(), y.current.dispose(), y.current = null);
|
|
7469
|
-
}), [
|
|
7470
|
-
const
|
|
7532
|
+
}), [O]);
|
|
7533
|
+
const te = N(async () => {
|
|
7471
7534
|
if (y.current)
|
|
7472
7535
|
try {
|
|
7473
|
-
const
|
|
7474
|
-
|
|
7475
|
-
} catch (
|
|
7476
|
-
console.warn("Failed to resume audio context:",
|
|
7536
|
+
const E = y.current.audioCtx || y.current.audioContext;
|
|
7537
|
+
E && (E.state === "suspended" || E.state === "interrupted") && (await E.resume(), console.log("Audio context resumed"));
|
|
7538
|
+
} catch (E) {
|
|
7539
|
+
console.warn("Failed to resume audio context:", E);
|
|
7477
7540
|
}
|
|
7478
|
-
}, []),
|
|
7479
|
-
if (!y.current || !
|
|
7541
|
+
}, []), q = N(async (E, se = {}) => {
|
|
7542
|
+
if (!y.current || !oe) {
|
|
7480
7543
|
console.warn("Avatar not ready for speaking");
|
|
7481
7544
|
return;
|
|
7482
7545
|
}
|
|
7483
|
-
if (!
|
|
7546
|
+
if (!E || E.trim() === "") {
|
|
7484
7547
|
console.warn("No text provided to speak");
|
|
7485
7548
|
return;
|
|
7486
7549
|
}
|
|
7487
|
-
await
|
|
7488
|
-
const L =
|
|
7489
|
-
|
|
7490
|
-
const
|
|
7491
|
-
lipsyncLang:
|
|
7550
|
+
await te(), k.current = { remainingText: null, originalText: null, options: null }, C.current = [], z.current = { text: E, options: se }, A.current && (clearInterval(A.current), A.current = null), Q(!1), Y.current = !1;
|
|
7551
|
+
const L = E.split(/[.!?]+/).filter((U) => U.trim().length > 0);
|
|
7552
|
+
C.current = L;
|
|
7553
|
+
const D = {
|
|
7554
|
+
lipsyncLang: se.lipsyncLang || "en",
|
|
7492
7555
|
onSpeechEnd: () => {
|
|
7493
|
-
|
|
7556
|
+
A.current && (clearInterval(A.current), A.current = null), se.onSpeechEnd && se.onSpeechEnd(), b();
|
|
7494
7557
|
}
|
|
7495
7558
|
};
|
|
7496
7559
|
try {
|
|
7497
|
-
y.current.speakText(
|
|
7498
|
-
} catch (
|
|
7499
|
-
console.error("Error speaking text:",
|
|
7560
|
+
y.current.speakText(E, D);
|
|
7561
|
+
} catch (U) {
|
|
7562
|
+
console.error("Error speaking text:", U), ie(U.message || "Failed to speak text");
|
|
7500
7563
|
}
|
|
7501
|
-
}, [
|
|
7502
|
-
|
|
7503
|
-
|
|
7504
|
-
}, [
|
|
7505
|
-
const
|
|
7564
|
+
}, [oe, b, te]);
|
|
7565
|
+
me(() => {
|
|
7566
|
+
oe && X && p && y.current && q(X);
|
|
7567
|
+
}, [oe, X, p, q]);
|
|
7568
|
+
const $ = N(() => {
|
|
7506
7569
|
if (y.current)
|
|
7507
7570
|
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(),
|
|
7571
|
+
const E = y.current.isSpeaking || !1, se = y.current.audioPlaylist || [], L = y.current.speechQueue || [];
|
|
7572
|
+
if (E || se.length > 0 || L.length > 0) {
|
|
7573
|
+
A.current && (clearInterval(A.current), A.current = null);
|
|
7574
|
+
let D = "";
|
|
7575
|
+
L.length > 0 && (D = L.map((U) => U.text && Array.isArray(U.text) ? U.text.map((ne) => ne.word).join(" ") : U.text || "").join(" ")), k.current = {
|
|
7576
|
+
remainingText: D || null,
|
|
7577
|
+
originalText: z.current?.text || null,
|
|
7578
|
+
options: z.current?.options || null
|
|
7579
|
+
}, y.current.speechQueue.length = 0, y.current.pauseSpeaking(), Q(!0), Y.current = !0;
|
|
7517
7580
|
}
|
|
7518
|
-
} catch (
|
|
7519
|
-
console.warn("Error pausing speech:",
|
|
7581
|
+
} catch (E) {
|
|
7582
|
+
console.warn("Error pausing speech:", E);
|
|
7520
7583
|
}
|
|
7521
|
-
}, []),
|
|
7522
|
-
if (!(!y.current || !
|
|
7584
|
+
}, []), Ae = N(async () => {
|
|
7585
|
+
if (!(!y.current || !K))
|
|
7523
7586
|
try {
|
|
7524
|
-
await
|
|
7525
|
-
const
|
|
7526
|
-
|
|
7527
|
-
} catch (
|
|
7528
|
-
console.warn("Error resuming speech:",
|
|
7587
|
+
await te(), Q(!1), Y.current = !1;
|
|
7588
|
+
const E = k.current?.remainingText, se = k.current?.originalText || z.current?.text, L = k.current?.options || z.current?.options || {}, D = E || se;
|
|
7589
|
+
D && q(D, L);
|
|
7590
|
+
} catch (E) {
|
|
7591
|
+
console.warn("Error resuming speech:", E), Q(!1), Y.current = !1;
|
|
7529
7592
|
}
|
|
7530
|
-
}, [
|
|
7531
|
-
y.current && (y.current.stopSpeaking(),
|
|
7593
|
+
}, [K, q, te]), we = N(() => {
|
|
7594
|
+
y.current && (y.current.stopSpeaking(), A.current && (clearInterval(A.current), A.current = null), Q(!1), Y.current = !1);
|
|
7532
7595
|
}, []);
|
|
7533
|
-
return
|
|
7534
|
-
speakText:
|
|
7535
|
-
pauseSpeaking:
|
|
7536
|
-
resumeSpeaking:
|
|
7596
|
+
return Fe(P, () => ({
|
|
7597
|
+
speakText: q,
|
|
7598
|
+
pauseSpeaking: $,
|
|
7599
|
+
resumeSpeaking: Ae,
|
|
7537
7600
|
stopSpeaking: we,
|
|
7538
|
-
resumeAudioContext:
|
|
7539
|
-
isPaused: () =>
|
|
7540
|
-
setMood: (
|
|
7541
|
-
setBodyMovement: (
|
|
7542
|
-
y.current && y.current.setBodyMovement(
|
|
7601
|
+
resumeAudioContext: te,
|
|
7602
|
+
isPaused: () => K,
|
|
7603
|
+
setMood: (E) => y.current?.setMood(E),
|
|
7604
|
+
setBodyMovement: (E) => {
|
|
7605
|
+
y.current && y.current.setBodyMovement(E);
|
|
7543
7606
|
},
|
|
7544
|
-
playAnimation: (
|
|
7545
|
-
y.current && y.current.playAnimation && y.current.playAnimation(
|
|
7607
|
+
playAnimation: (E, se = !1) => {
|
|
7608
|
+
y.current && y.current.playAnimation && y.current.playAnimation(E, null, 10, 0, 0.01, se);
|
|
7546
7609
|
},
|
|
7547
|
-
playReaction: (
|
|
7610
|
+
playReaction: (E) => y.current?.playReaction(E),
|
|
7548
7611
|
playCelebration: () => y.current?.playCelebration(),
|
|
7549
|
-
setShowFullAvatar: (
|
|
7550
|
-
y.current && (
|
|
7612
|
+
setShowFullAvatar: (E) => {
|
|
7613
|
+
y.current && (I.current = E, y.current.setShowFullAvatar(E));
|
|
7551
7614
|
},
|
|
7552
|
-
isReady:
|
|
7615
|
+
isReady: oe,
|
|
7553
7616
|
talkingHead: y.current
|
|
7554
|
-
})), /* @__PURE__ */ Pe("div", { className: `simple-talking-avatar-container ${x}`, style:
|
|
7555
|
-
/* @__PURE__ */
|
|
7617
|
+
})), /* @__PURE__ */ Pe("div", { className: `simple-talking-avatar-container ${x}`, style: S, children: [
|
|
7618
|
+
/* @__PURE__ */ pe(
|
|
7556
7619
|
"div",
|
|
7557
7620
|
{
|
|
7558
|
-
ref:
|
|
7621
|
+
ref: H,
|
|
7559
7622
|
className: "talking-head-viewer",
|
|
7560
7623
|
style: {
|
|
7561
7624
|
width: "100%",
|
|
@@ -7564,7 +7627,7 @@ const gt = Me(({
|
|
|
7564
7627
|
}
|
|
7565
7628
|
}
|
|
7566
7629
|
),
|
|
7567
|
-
|
|
7630
|
+
_ && /* @__PURE__ */ pe("div", { className: "loading-overlay", style: {
|
|
7568
7631
|
position: "absolute",
|
|
7569
7632
|
top: "50%",
|
|
7570
7633
|
left: "50%",
|
|
@@ -7573,7 +7636,7 @@ const gt = Me(({
|
|
|
7573
7636
|
fontSize: "18px",
|
|
7574
7637
|
zIndex: 10
|
|
7575
7638
|
}, children: "Loading avatar..." }),
|
|
7576
|
-
ee && /* @__PURE__ */
|
|
7639
|
+
ee && /* @__PURE__ */ pe("div", { className: "error-overlay", style: {
|
|
7577
7640
|
position: "absolute",
|
|
7578
7641
|
top: "50%",
|
|
7579
7642
|
left: "50%",
|
|
@@ -7589,7 +7652,7 @@ const gt = Me(({
|
|
|
7589
7652
|
});
|
|
7590
7653
|
gt.displayName = "SimpleTalkingAvatar";
|
|
7591
7654
|
const yt = Me(({
|
|
7592
|
-
curriculumData:
|
|
7655
|
+
curriculumData: X = null,
|
|
7593
7656
|
avatarConfig: t = {},
|
|
7594
7657
|
animations: e = {},
|
|
7595
7658
|
onLessonStart: n = () => {
|
|
@@ -7604,7 +7667,7 @@ const yt = Me(({
|
|
|
7604
7667
|
},
|
|
7605
7668
|
autoStart: h = !1
|
|
7606
7669
|
}, r) => {
|
|
7607
|
-
const u =
|
|
7670
|
+
const u = V(null), a = V({
|
|
7608
7671
|
currentModuleIndex: 0,
|
|
7609
7672
|
currentLessonIndex: 0,
|
|
7610
7673
|
currentQuestionIndex: 0,
|
|
@@ -7614,18 +7677,18 @@ const yt = Me(({
|
|
|
7614
7677
|
curriculumCompleted: !1,
|
|
7615
7678
|
score: 0,
|
|
7616
7679
|
totalQuestions: 0
|
|
7617
|
-
}),
|
|
7680
|
+
}), d = V({
|
|
7618
7681
|
onLessonStart: n,
|
|
7619
7682
|
onLessonComplete: i,
|
|
7620
7683
|
onQuestionAnswer: s,
|
|
7621
7684
|
onCurriculumComplete: o,
|
|
7622
7685
|
onCustomAction: l
|
|
7623
|
-
}),
|
|
7686
|
+
}), c = V(null), g = V(null), b = V(null), x = V(null), S = V(null), G = V(null), p = V(null), P = V(X?.curriculum || {
|
|
7624
7687
|
title: "Default Curriculum",
|
|
7625
7688
|
description: "No curriculum data provided",
|
|
7626
7689
|
language: "en",
|
|
7627
7690
|
modules: []
|
|
7628
|
-
}),
|
|
7691
|
+
}), H = V({
|
|
7629
7692
|
avatarUrl: t.avatarUrl || "/avatars/brunette.glb",
|
|
7630
7693
|
avatarBody: t.avatarBody || "F",
|
|
7631
7694
|
mood: t.mood || "happy",
|
|
@@ -7639,21 +7702,21 @@ const yt = Me(({
|
|
|
7639
7702
|
animations: e,
|
|
7640
7703
|
lipsyncLang: "en"
|
|
7641
7704
|
});
|
|
7642
|
-
|
|
7643
|
-
|
|
7705
|
+
me(() => {
|
|
7706
|
+
d.current = {
|
|
7644
7707
|
onLessonStart: n,
|
|
7645
7708
|
onLessonComplete: i,
|
|
7646
7709
|
onQuestionAnswer: s,
|
|
7647
7710
|
onCurriculumComplete: o,
|
|
7648
7711
|
onCustomAction: l
|
|
7649
7712
|
};
|
|
7650
|
-
}, [n, i, s, o, l]),
|
|
7651
|
-
|
|
7713
|
+
}, [n, i, s, o, l]), me(() => {
|
|
7714
|
+
P.current = X?.curriculum || {
|
|
7652
7715
|
title: "Default Curriculum",
|
|
7653
7716
|
description: "No curriculum data provided",
|
|
7654
7717
|
language: "en",
|
|
7655
7718
|
modules: []
|
|
7656
|
-
},
|
|
7719
|
+
}, H.current = {
|
|
7657
7720
|
avatarUrl: t.avatarUrl || "/avatars/brunette.glb",
|
|
7658
7721
|
avatarBody: t.avatarBody || "F",
|
|
7659
7722
|
mood: t.mood || "happy",
|
|
@@ -7667,18 +7730,18 @@ const yt = Me(({
|
|
|
7667
7730
|
animations: e,
|
|
7668
7731
|
lipsyncLang: "en"
|
|
7669
7732
|
};
|
|
7670
|
-
}, [
|
|
7671
|
-
const y =
|
|
7733
|
+
}, [X, t, e]);
|
|
7734
|
+
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
7735
|
a.current.lessonCompleted = !0, a.current.isQuestionMode = !1;
|
|
7673
7736
|
const v = a.current.totalQuestions > 0 ? Math.round(a.current.score / a.current.totalQuestions * 100) : 100;
|
|
7674
7737
|
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.",
|
|
7738
|
+
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
7739
|
moduleIndex: a.current.currentModuleIndex,
|
|
7677
7740
|
lessonIndex: a.current.currentLessonIndex,
|
|
7678
7741
|
score: a.current.score,
|
|
7679
7742
|
totalQuestions: a.current.totalQuestions,
|
|
7680
7743
|
percentage: v
|
|
7681
|
-
}),
|
|
7744
|
+
}), d.current.onCustomAction({
|
|
7682
7745
|
type: "lessonComplete",
|
|
7683
7746
|
moduleIndex: a.current.currentModuleIndex,
|
|
7684
7747
|
lessonIndex: a.current.currentLessonIndex,
|
|
@@ -7692,28 +7755,28 @@ const yt = Me(({
|
|
|
7692
7755
|
} catch {
|
|
7693
7756
|
u.current.playCelebration();
|
|
7694
7757
|
}
|
|
7695
|
-
const
|
|
7758
|
+
const T = P.current || { modules: [] }, M = T.modules[a.current.currentModuleIndex], O = a.current.currentLessonIndex < (M?.lessons?.length || 0) - 1, te = a.current.currentModuleIndex < (T.modules?.length || 0) - 1, q = O || te, $ = H.current || { lipsyncLang: "en" };
|
|
7696
7759
|
u.current.speakText(R, {
|
|
7697
|
-
lipsyncLang:
|
|
7760
|
+
lipsyncLang: $.lipsyncLang,
|
|
7698
7761
|
onSpeechEnd: () => {
|
|
7699
|
-
|
|
7762
|
+
d.current.onCustomAction({
|
|
7700
7763
|
type: "lessonCompleteFeedbackDone",
|
|
7701
7764
|
moduleIndex: a.current.currentModuleIndex,
|
|
7702
7765
|
lessonIndex: a.current.currentLessonIndex,
|
|
7703
7766
|
score: a.current.score,
|
|
7704
7767
|
totalQuestions: a.current.totalQuestions,
|
|
7705
7768
|
percentage: v,
|
|
7706
|
-
hasNextLesson:
|
|
7769
|
+
hasNextLesson: q
|
|
7707
7770
|
});
|
|
7708
7771
|
}
|
|
7709
7772
|
});
|
|
7710
7773
|
}
|
|
7711
|
-
}, [e.lessonComplete]),
|
|
7774
|
+
}, [e.lessonComplete]), Y = N(() => {
|
|
7712
7775
|
a.current.curriculumCompleted = !0;
|
|
7713
|
-
const v =
|
|
7714
|
-
if (
|
|
7776
|
+
const v = P.current || { modules: [] };
|
|
7777
|
+
if (d.current.onCurriculumComplete({
|
|
7715
7778
|
modules: v.modules.length,
|
|
7716
|
-
totalLessons: v.modules.reduce((R,
|
|
7779
|
+
totalLessons: v.modules.reduce((R, T) => R + T.lessons.length, 0)
|
|
7717
7780
|
}), u.current) {
|
|
7718
7781
|
if (u.current.setMood("celebrating"), e.curriculumComplete)
|
|
7719
7782
|
try {
|
|
@@ -7721,14 +7784,14 @@ const yt = Me(({
|
|
|
7721
7784
|
} catch {
|
|
7722
7785
|
u.current.playCelebration();
|
|
7723
7786
|
}
|
|
7724
|
-
const R =
|
|
7787
|
+
const R = H.current || { lipsyncLang: "en" };
|
|
7725
7788
|
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
7789
|
}
|
|
7727
|
-
}, [e.curriculumComplete]), k =
|
|
7790
|
+
}, [e.curriculumComplete]), k = N(() => {
|
|
7728
7791
|
const v = y();
|
|
7729
7792
|
a.current.isQuestionMode = !0, a.current.currentQuestionIndex = 0, a.current.totalQuestions = v?.questions?.length || 0, a.current.score = 0;
|
|
7730
|
-
const R =
|
|
7731
|
-
R &&
|
|
7793
|
+
const R = I();
|
|
7794
|
+
R && d.current.onCustomAction({
|
|
7732
7795
|
type: "questionStart",
|
|
7733
7796
|
moduleIndex: a.current.currentModuleIndex,
|
|
7734
7797
|
lessonIndex: a.current.currentLessonIndex,
|
|
@@ -7737,36 +7800,36 @@ const yt = Me(({
|
|
|
7737
7800
|
question: R,
|
|
7738
7801
|
score: a.current.score
|
|
7739
7802
|
});
|
|
7740
|
-
const
|
|
7803
|
+
const T = () => {
|
|
7741
7804
|
if (!u.current || !R) return;
|
|
7742
7805
|
if (u.current.setMood("happy"), e.questionStart)
|
|
7743
7806
|
try {
|
|
7744
7807
|
u.current.playAnimation(e.questionStart, !0);
|
|
7745
|
-
} catch (
|
|
7746
|
-
console.warn("Failed to play questionStart animation:",
|
|
7808
|
+
} catch (O) {
|
|
7809
|
+
console.warn("Failed to play questionStart animation:", O);
|
|
7747
7810
|
}
|
|
7748
|
-
const M =
|
|
7811
|
+
const M = H.current || { lipsyncLang: "en" };
|
|
7749
7812
|
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
7813
|
};
|
|
7751
7814
|
if (u.current && u.current.isReady && R)
|
|
7752
|
-
|
|
7815
|
+
T();
|
|
7753
7816
|
else if (u.current && u.current.isReady) {
|
|
7754
|
-
const M =
|
|
7817
|
+
const M = H.current || { lipsyncLang: "en" };
|
|
7755
7818
|
u.current.speakText("Now let me ask you some questions to test your understanding.", { lipsyncLang: M.lipsyncLang });
|
|
7756
7819
|
} else {
|
|
7757
7820
|
const M = setInterval(() => {
|
|
7758
|
-
u.current && u.current.isReady && (clearInterval(M), R &&
|
|
7821
|
+
u.current && u.current.isReady && (clearInterval(M), R && T());
|
|
7759
7822
|
}, 100);
|
|
7760
7823
|
setTimeout(() => {
|
|
7761
7824
|
clearInterval(M);
|
|
7762
7825
|
}, 5e3);
|
|
7763
7826
|
}
|
|
7764
|
-
}, [e.questionStart, y,
|
|
7827
|
+
}, [e.questionStart, y, I]), C = N(() => {
|
|
7765
7828
|
const v = y();
|
|
7766
7829
|
if (a.current.currentQuestionIndex < (v?.questions?.length || 0) - 1) {
|
|
7767
7830
|
u.current && u.current.stopSpeaking && u.current.stopSpeaking(), a.current.currentQuestionIndex += 1;
|
|
7768
|
-
const R =
|
|
7769
|
-
R &&
|
|
7831
|
+
const R = I();
|
|
7832
|
+
R && d.current.onCustomAction({
|
|
7770
7833
|
type: "nextQuestion",
|
|
7771
7834
|
moduleIndex: a.current.currentModuleIndex,
|
|
7772
7835
|
lessonIndex: a.current.currentLessonIndex,
|
|
@@ -7775,109 +7838,109 @@ const yt = Me(({
|
|
|
7775
7838
|
question: R,
|
|
7776
7839
|
score: a.current.score
|
|
7777
7840
|
});
|
|
7778
|
-
const
|
|
7841
|
+
const T = () => {
|
|
7779
7842
|
if (!u.current || !R) return;
|
|
7780
7843
|
if (u.current.setMood("happy"), u.current.setBodyMovement("idle"), e.nextQuestion)
|
|
7781
7844
|
try {
|
|
7782
7845
|
u.current.playAnimation(e.nextQuestion, !0);
|
|
7783
|
-
} catch (
|
|
7784
|
-
console.warn("Failed to play nextQuestion animation:",
|
|
7846
|
+
} catch ($) {
|
|
7847
|
+
console.warn("Failed to play nextQuestion animation:", $);
|
|
7785
7848
|
}
|
|
7786
|
-
const M =
|
|
7849
|
+
const M = H.current || { lipsyncLang: "en" }, te = y()?.questions?.length || 0, q = a.current.currentQuestionIndex >= te - 1;
|
|
7787
7850
|
if (R.type === "code_test") {
|
|
7788
|
-
const
|
|
7789
|
-
u.current.speakText(
|
|
7851
|
+
const $ = q ? `Great! Here's your final coding challenge: ${R.question}` : `Great! Now let's move on to your next coding challenge: ${R.question}`;
|
|
7852
|
+
u.current.speakText($, {
|
|
7790
7853
|
lipsyncLang: M.lipsyncLang
|
|
7791
7854
|
});
|
|
7792
7855
|
} else if (R.type === "multiple_choice") {
|
|
7793
|
-
const
|
|
7794
|
-
u.current.speakText(
|
|
7856
|
+
const $ = q ? `Alright! Here's your final question: ${R.question}` : `Alright! Here's your next question: ${R.question}`;
|
|
7857
|
+
u.current.speakText($, {
|
|
7795
7858
|
lipsyncLang: M.lipsyncLang
|
|
7796
7859
|
});
|
|
7797
7860
|
} else if (R.type === "true_false") {
|
|
7798
|
-
const
|
|
7799
|
-
u.current.speakText(
|
|
7861
|
+
const $ = q ? `Now let's try this final one: ${R.question}` : `Now let's try this one: ${R.question}`;
|
|
7862
|
+
u.current.speakText($, {
|
|
7800
7863
|
lipsyncLang: M.lipsyncLang
|
|
7801
7864
|
});
|
|
7802
7865
|
} else {
|
|
7803
|
-
const
|
|
7804
|
-
u.current.speakText(
|
|
7866
|
+
const $ = q ? `Here's your final question: ${R.question}` : `Here's the next question: ${R.question}`;
|
|
7867
|
+
u.current.speakText($, {
|
|
7805
7868
|
lipsyncLang: M.lipsyncLang
|
|
7806
7869
|
});
|
|
7807
7870
|
}
|
|
7808
7871
|
};
|
|
7809
7872
|
if (u.current && u.current.isReady && R)
|
|
7810
|
-
|
|
7873
|
+
T();
|
|
7811
7874
|
else if (R) {
|
|
7812
7875
|
const M = setInterval(() => {
|
|
7813
|
-
u.current && u.current.isReady && (clearInterval(M),
|
|
7876
|
+
u.current && u.current.isReady && (clearInterval(M), T());
|
|
7814
7877
|
}, 100);
|
|
7815
7878
|
setTimeout(() => {
|
|
7816
7879
|
clearInterval(M);
|
|
7817
7880
|
}, 5e3);
|
|
7818
7881
|
}
|
|
7819
7882
|
} else
|
|
7820
|
-
|
|
7883
|
+
d.current.onCustomAction({
|
|
7821
7884
|
type: "allQuestionsComplete",
|
|
7822
7885
|
moduleIndex: a.current.currentModuleIndex,
|
|
7823
7886
|
lessonIndex: a.current.currentLessonIndex,
|
|
7824
7887
|
totalQuestions: a.current.totalQuestions,
|
|
7825
7888
|
score: a.current.score
|
|
7826
7889
|
});
|
|
7827
|
-
}, [e.nextQuestion, y,
|
|
7828
|
-
const v =
|
|
7890
|
+
}, [e.nextQuestion, y, I]), _ = N(() => {
|
|
7891
|
+
const v = P.current || { modules: [] }, R = v.modules[a.current.currentModuleIndex];
|
|
7829
7892
|
if (a.current.currentLessonIndex < (R?.lessons?.length || 0) - 1) {
|
|
7830
7893
|
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
|
-
|
|
7894
|
+
const M = v.modules[a.current.currentModuleIndex], O = a.current.currentLessonIndex < (M?.lessons?.length || 0) - 1, te = a.current.currentModuleIndex < (v.modules?.length || 0) - 1, q = O || te;
|
|
7895
|
+
d.current.onCustomAction({
|
|
7833
7896
|
type: "lessonStart",
|
|
7834
7897
|
moduleIndex: a.current.currentModuleIndex,
|
|
7835
7898
|
lessonIndex: a.current.currentLessonIndex,
|
|
7836
|
-
hasNextLesson:
|
|
7837
|
-
}),
|
|
7899
|
+
hasNextLesson: q
|
|
7900
|
+
}), d.current.onLessonStart({
|
|
7838
7901
|
moduleIndex: a.current.currentModuleIndex,
|
|
7839
7902
|
lessonIndex: a.current.currentLessonIndex,
|
|
7840
7903
|
lesson: y()
|
|
7841
7904
|
}), u.current && (u.current.setMood("happy"), u.current.setBodyMovement("idle"));
|
|
7842
7905
|
} else if (a.current.currentModuleIndex < (v.modules?.length || 0) - 1) {
|
|
7843
7906
|
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
|
-
|
|
7907
|
+
const O = v.modules[a.current.currentModuleIndex], te = a.current.currentLessonIndex < (O?.lessons?.length || 0) - 1, q = a.current.currentModuleIndex < (v.modules?.length || 0) - 1, $ = te || q;
|
|
7908
|
+
d.current.onCustomAction({
|
|
7846
7909
|
type: "lessonStart",
|
|
7847
7910
|
moduleIndex: a.current.currentModuleIndex,
|
|
7848
7911
|
lessonIndex: a.current.currentLessonIndex,
|
|
7849
|
-
hasNextLesson:
|
|
7850
|
-
}),
|
|
7912
|
+
hasNextLesson: $
|
|
7913
|
+
}), d.current.onLessonStart({
|
|
7851
7914
|
moduleIndex: a.current.currentModuleIndex,
|
|
7852
7915
|
lessonIndex: a.current.currentLessonIndex,
|
|
7853
7916
|
lesson: y()
|
|
7854
7917
|
}), u.current && (u.current.setMood("happy"), u.current.setBodyMovement("idle"));
|
|
7855
7918
|
} else
|
|
7856
|
-
|
|
7857
|
-
}, []),
|
|
7919
|
+
S.current && S.current();
|
|
7920
|
+
}, []), B = N(() => {
|
|
7858
7921
|
const v = y();
|
|
7859
7922
|
let R = null;
|
|
7860
7923
|
if (v?.avatar_script && v?.body) {
|
|
7861
|
-
const
|
|
7862
|
-
R = `${
|
|
7924
|
+
const T = v.avatar_script.trim(), M = v.body.trim(), O = T.match(/[.!?]$/) ? " " : ". ";
|
|
7925
|
+
R = `${T}${O}${M}`;
|
|
7863
7926
|
} else
|
|
7864
7927
|
R = v?.avatar_script || v?.body || null;
|
|
7865
7928
|
if (u.current && u.current.isReady && R) {
|
|
7866
7929
|
a.current.isTeaching = !0, a.current.isQuestionMode = !1, a.current.score = 0, a.current.totalQuestions = 0, u.current.setMood("happy");
|
|
7867
|
-
let
|
|
7930
|
+
let T = !1;
|
|
7868
7931
|
if (e.teaching)
|
|
7869
7932
|
try {
|
|
7870
|
-
u.current.playAnimation(e.teaching, !0),
|
|
7871
|
-
} catch (
|
|
7872
|
-
console.warn("Failed to play teaching animation:",
|
|
7933
|
+
u.current.playAnimation(e.teaching, !0), T = !0;
|
|
7934
|
+
} catch (O) {
|
|
7935
|
+
console.warn("Failed to play teaching animation:", O);
|
|
7873
7936
|
}
|
|
7874
|
-
|
|
7875
|
-
const M =
|
|
7876
|
-
|
|
7937
|
+
T || u.current.setBodyMovement("gesturing");
|
|
7938
|
+
const M = H.current || { lipsyncLang: "en" };
|
|
7939
|
+
d.current.onLessonStart({
|
|
7877
7940
|
moduleIndex: a.current.currentModuleIndex,
|
|
7878
7941
|
lessonIndex: a.current.currentLessonIndex,
|
|
7879
7942
|
lesson: v
|
|
7880
|
-
}),
|
|
7943
|
+
}), d.current.onCustomAction({
|
|
7881
7944
|
type: "teachingStart",
|
|
7882
7945
|
moduleIndex: a.current.currentModuleIndex,
|
|
7883
7946
|
lessonIndex: a.current.currentLessonIndex,
|
|
@@ -7885,13 +7948,13 @@ const yt = Me(({
|
|
|
7885
7948
|
}), u.current.speakText(R, {
|
|
7886
7949
|
lipsyncLang: M.lipsyncLang,
|
|
7887
7950
|
onSpeechEnd: () => {
|
|
7888
|
-
a.current.isTeaching = !1,
|
|
7951
|
+
a.current.isTeaching = !1, d.current.onCustomAction({
|
|
7889
7952
|
type: "teachingComplete",
|
|
7890
7953
|
moduleIndex: a.current.currentModuleIndex,
|
|
7891
7954
|
lessonIndex: a.current.currentLessonIndex,
|
|
7892
7955
|
lesson: v,
|
|
7893
7956
|
hasQuestions: v.questions && v.questions.length > 0
|
|
7894
|
-
}), v?.code_example &&
|
|
7957
|
+
}), v?.code_example && d.current.onCustomAction({
|
|
7895
7958
|
type: "codeExampleReady",
|
|
7896
7959
|
moduleIndex: a.current.currentModuleIndex,
|
|
7897
7960
|
lessonIndex: a.current.currentLessonIndex,
|
|
@@ -7901,17 +7964,17 @@ const yt = Me(({
|
|
|
7901
7964
|
}
|
|
7902
7965
|
});
|
|
7903
7966
|
}
|
|
7904
|
-
}, [e.teaching, y]), ee =
|
|
7905
|
-
const R =
|
|
7906
|
-
if (
|
|
7967
|
+
}, [e.teaching, y]), ee = N((v) => {
|
|
7968
|
+
const R = I(), T = z(v, R);
|
|
7969
|
+
if (T && (a.current.score += 1), d.current.onQuestionAnswer({
|
|
7907
7970
|
moduleIndex: a.current.currentModuleIndex,
|
|
7908
7971
|
lessonIndex: a.current.currentLessonIndex,
|
|
7909
7972
|
questionIndex: a.current.currentQuestionIndex,
|
|
7910
7973
|
answer: v,
|
|
7911
|
-
isCorrect:
|
|
7974
|
+
isCorrect: T,
|
|
7912
7975
|
question: R
|
|
7913
7976
|
}), u.current)
|
|
7914
|
-
if (
|
|
7977
|
+
if (T) {
|
|
7915
7978
|
if (u.current.setMood("happy"), e.correct)
|
|
7916
7979
|
try {
|
|
7917
7980
|
u.current.playReaction("happy");
|
|
@@ -7919,21 +7982,21 @@ const yt = Me(({
|
|
|
7919
7982
|
u.current.setBodyMovement("happy");
|
|
7920
7983
|
}
|
|
7921
7984
|
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:
|
|
7985
|
+
const O = y()?.questions?.length || 0;
|
|
7986
|
+
a.current.currentQuestionIndex >= O - 1;
|
|
7987
|
+
const te = a.current.currentQuestionIndex < O - 1;
|
|
7988
|
+
console.log("[CurriculumLearning] Answer feedback - questionIndex:", a.current.currentQuestionIndex, "totalQuestions:", O, "hasNextQuestion:", te);
|
|
7989
|
+
const q = R.type === "code_test" ? `Great job! Your code passed all the tests! ${R.explanation || ""}` : `Excellent! That's correct! ${R.explanation || ""}`, $ = H.current || { lipsyncLang: "en" };
|
|
7990
|
+
u.current.speakText(q, {
|
|
7991
|
+
lipsyncLang: $.lipsyncLang,
|
|
7929
7992
|
onSpeechEnd: () => {
|
|
7930
|
-
|
|
7993
|
+
d.current.onCustomAction({
|
|
7931
7994
|
type: "answerFeedbackComplete",
|
|
7932
7995
|
moduleIndex: a.current.currentModuleIndex,
|
|
7933
7996
|
lessonIndex: a.current.currentLessonIndex,
|
|
7934
7997
|
questionIndex: a.current.currentQuestionIndex,
|
|
7935
7998
|
isCorrect: !0,
|
|
7936
|
-
hasNextQuestion:
|
|
7999
|
+
hasNextQuestion: te,
|
|
7937
8000
|
score: a.current.score,
|
|
7938
8001
|
totalQuestions: a.current.totalQuestions
|
|
7939
8002
|
});
|
|
@@ -7947,19 +8010,19 @@ const yt = Me(({
|
|
|
7947
8010
|
u.current.setBodyMovement("idle");
|
|
7948
8011
|
}
|
|
7949
8012
|
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:
|
|
8013
|
+
const O = y()?.questions?.length || 0, te = a.current.currentQuestionIndex >= O - 1, q = a.current.currentQuestionIndex < O - 1;
|
|
8014
|
+
console.log("[CurriculumLearning] Answer feedback (incorrect) - questionIndex:", a.current.currentQuestionIndex, "totalQuestions:", O, "hasNextQuestion:", q);
|
|
8015
|
+
const $ = 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 || ""}${te ? "" : " Let's move on to the next question."}`, Ae = H.current || { lipsyncLang: "en" };
|
|
8016
|
+
u.current.speakText($, {
|
|
8017
|
+
lipsyncLang: Ae.lipsyncLang,
|
|
7955
8018
|
onSpeechEnd: () => {
|
|
7956
|
-
|
|
8019
|
+
d.current.onCustomAction({
|
|
7957
8020
|
type: "answerFeedbackComplete",
|
|
7958
8021
|
moduleIndex: a.current.currentModuleIndex,
|
|
7959
8022
|
lessonIndex: a.current.currentLessonIndex,
|
|
7960
8023
|
questionIndex: a.current.currentQuestionIndex,
|
|
7961
8024
|
isCorrect: !1,
|
|
7962
|
-
hasNextQuestion:
|
|
8025
|
+
hasNextQuestion: q,
|
|
7963
8026
|
score: a.current.score,
|
|
7964
8027
|
totalQuestions: a.current.totalQuestions
|
|
7965
8028
|
});
|
|
@@ -7967,21 +8030,21 @@ const yt = Me(({
|
|
|
7967
8030
|
});
|
|
7968
8031
|
}
|
|
7969
8032
|
else {
|
|
7970
|
-
const
|
|
7971
|
-
|
|
8033
|
+
const O = y()?.questions?.length || 0;
|
|
8034
|
+
d.current.onCustomAction({
|
|
7972
8035
|
type: "answerFeedbackComplete",
|
|
7973
8036
|
moduleIndex: a.current.currentModuleIndex,
|
|
7974
8037
|
lessonIndex: a.current.currentLessonIndex,
|
|
7975
8038
|
questionIndex: a.current.currentQuestionIndex,
|
|
7976
|
-
isCorrect:
|
|
7977
|
-
hasNextQuestion: a.current.currentQuestionIndex <
|
|
8039
|
+
isCorrect: T,
|
|
8040
|
+
hasNextQuestion: a.current.currentQuestionIndex < O - 1,
|
|
7978
8041
|
score: a.current.score,
|
|
7979
8042
|
totalQuestions: a.current.totalQuestions,
|
|
7980
8043
|
avatarNotReady: !0
|
|
7981
8044
|
});
|
|
7982
8045
|
}
|
|
7983
|
-
}, [e.correct, e.incorrect,
|
|
7984
|
-
const R =
|
|
8046
|
+
}, [e.correct, e.incorrect, I, y, z]), ie = N((v) => {
|
|
8047
|
+
const R = I();
|
|
7985
8048
|
if (!v || typeof v != "object") {
|
|
7986
8049
|
console.error("Invalid code test result format. Expected object with {passed: boolean, ...}");
|
|
7987
8050
|
return;
|
|
@@ -7990,7 +8053,7 @@ const yt = Me(({
|
|
|
7990
8053
|
console.warn("Current question is not a code test. Use handleAnswerSelect for other question types.");
|
|
7991
8054
|
return;
|
|
7992
8055
|
}
|
|
7993
|
-
const
|
|
8056
|
+
const T = {
|
|
7994
8057
|
passed: v.passed === !0,
|
|
7995
8058
|
results: v.results || [],
|
|
7996
8059
|
output: v.output || "",
|
|
@@ -8000,19 +8063,19 @@ const yt = Me(({
|
|
|
8000
8063
|
passedCount: v.passedCount || 0,
|
|
8001
8064
|
failedCount: v.failedCount || 0
|
|
8002
8065
|
};
|
|
8003
|
-
|
|
8066
|
+
d.current.onCustomAction({
|
|
8004
8067
|
type: "codeTestSubmitted",
|
|
8005
8068
|
moduleIndex: a.current.currentModuleIndex,
|
|
8006
8069
|
lessonIndex: a.current.currentLessonIndex,
|
|
8007
8070
|
questionIndex: a.current.currentQuestionIndex,
|
|
8008
|
-
testResult:
|
|
8071
|
+
testResult: T,
|
|
8009
8072
|
question: R
|
|
8010
|
-
}), p.current && p.current(
|
|
8011
|
-
}, [
|
|
8073
|
+
}), p.current && p.current(T);
|
|
8074
|
+
}, [I, z]), oe = N(() => {
|
|
8012
8075
|
if (a.current.currentQuestionIndex > 0) {
|
|
8013
8076
|
a.current.currentQuestionIndex -= 1;
|
|
8014
|
-
const v =
|
|
8015
|
-
v &&
|
|
8077
|
+
const v = I();
|
|
8078
|
+
v && d.current.onCustomAction({
|
|
8016
8079
|
type: "questionStart",
|
|
8017
8080
|
moduleIndex: a.current.currentModuleIndex,
|
|
8018
8081
|
lessonIndex: a.current.currentLessonIndex,
|
|
@@ -8024,82 +8087,82 @@ const yt = Me(({
|
|
|
8024
8087
|
const R = () => {
|
|
8025
8088
|
if (!u.current || !v) return;
|
|
8026
8089
|
u.current.setMood("happy"), u.current.setBodyMovement("idle");
|
|
8027
|
-
const
|
|
8090
|
+
const T = H.current || { lipsyncLang: "en" };
|
|
8028
8091
|
v.type === "code_test" ? u.current.speakText(`Let's go back to this coding challenge: ${v.question}`, {
|
|
8029
|
-
lipsyncLang:
|
|
8092
|
+
lipsyncLang: T.lipsyncLang
|
|
8030
8093
|
}) : u.current.speakText(`Going back to: ${v.question}`, {
|
|
8031
|
-
lipsyncLang:
|
|
8094
|
+
lipsyncLang: T.lipsyncLang
|
|
8032
8095
|
});
|
|
8033
8096
|
};
|
|
8034
8097
|
if (u.current && u.current.isReady && v)
|
|
8035
8098
|
R();
|
|
8036
8099
|
else if (v) {
|
|
8037
|
-
const
|
|
8038
|
-
u.current && u.current.isReady && (clearInterval(
|
|
8100
|
+
const T = setInterval(() => {
|
|
8101
|
+
u.current && u.current.isReady && (clearInterval(T), R());
|
|
8039
8102
|
}, 100);
|
|
8040
8103
|
setTimeout(() => {
|
|
8041
|
-
clearInterval(
|
|
8104
|
+
clearInterval(T);
|
|
8042
8105
|
}, 5e3);
|
|
8043
8106
|
}
|
|
8044
8107
|
}
|
|
8045
|
-
}, [
|
|
8046
|
-
const v =
|
|
8108
|
+
}, [I]), he = N(() => {
|
|
8109
|
+
const v = P.current || { modules: [] };
|
|
8047
8110
|
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,
|
|
8111
|
+
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
8112
|
type: "lessonStart",
|
|
8050
8113
|
moduleIndex: a.current.currentModuleIndex,
|
|
8051
8114
|
lessonIndex: a.current.currentLessonIndex
|
|
8052
|
-
}),
|
|
8115
|
+
}), d.current.onLessonStart({
|
|
8053
8116
|
moduleIndex: a.current.currentModuleIndex,
|
|
8054
8117
|
lessonIndex: a.current.currentLessonIndex,
|
|
8055
8118
|
lesson: y()
|
|
8056
8119
|
}), u.current && (u.current.setMood("happy"), u.current.setBodyMovement("idle"));
|
|
8057
8120
|
else if (a.current.currentModuleIndex > 0) {
|
|
8058
8121
|
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,
|
|
8122
|
+
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
8123
|
type: "lessonStart",
|
|
8061
8124
|
moduleIndex: a.current.currentModuleIndex,
|
|
8062
8125
|
lessonIndex: a.current.currentLessonIndex
|
|
8063
|
-
}),
|
|
8126
|
+
}), d.current.onLessonStart({
|
|
8064
8127
|
moduleIndex: a.current.currentModuleIndex,
|
|
8065
8128
|
lessonIndex: a.current.currentLessonIndex,
|
|
8066
8129
|
lesson: y()
|
|
8067
8130
|
}), u.current && (u.current.setMood("happy"), u.current.setBodyMovement("idle"));
|
|
8068
8131
|
}
|
|
8069
|
-
}, [y]),
|
|
8132
|
+
}, [y]), K = N(() => {
|
|
8070
8133
|
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
|
-
}, []),
|
|
8134
|
+
}, []), Q = N((v) => {
|
|
8072
8135
|
console.log("Avatar is ready!", v);
|
|
8073
|
-
const R = y(),
|
|
8074
|
-
h &&
|
|
8075
|
-
|
|
8136
|
+
const R = y(), T = R?.avatar_script || R?.body;
|
|
8137
|
+
h && T && setTimeout(() => {
|
|
8138
|
+
c.current && c.current();
|
|
8076
8139
|
}, 10);
|
|
8077
8140
|
}, [h, y]);
|
|
8078
8141
|
Xe(() => {
|
|
8079
|
-
|
|
8080
|
-
}),
|
|
8142
|
+
c.current = B, g.current = _, b.current = A, x.current = C, S.current = Y, G.current = k, p.current = ee;
|
|
8143
|
+
}), Fe(r, () => ({
|
|
8081
8144
|
// Curriculum control methods
|
|
8082
|
-
startTeaching:
|
|
8145
|
+
startTeaching: B,
|
|
8083
8146
|
startQuestions: k,
|
|
8084
8147
|
handleAnswerSelect: ee,
|
|
8085
|
-
handleCodeTestResult:
|
|
8086
|
-
nextQuestion:
|
|
8087
|
-
previousQuestion:
|
|
8088
|
-
nextLesson:
|
|
8089
|
-
previousLesson:
|
|
8090
|
-
completeLesson:
|
|
8091
|
-
completeCurriculum:
|
|
8092
|
-
resetCurriculum:
|
|
8148
|
+
handleCodeTestResult: ie,
|
|
8149
|
+
nextQuestion: C,
|
|
8150
|
+
previousQuestion: oe,
|
|
8151
|
+
nextLesson: _,
|
|
8152
|
+
previousLesson: he,
|
|
8153
|
+
completeLesson: A,
|
|
8154
|
+
completeCurriculum: Y,
|
|
8155
|
+
resetCurriculum: K,
|
|
8093
8156
|
getState: () => ({ ...a.current }),
|
|
8094
|
-
getCurrentQuestion: () =>
|
|
8157
|
+
getCurrentQuestion: () => I(),
|
|
8095
8158
|
getCurrentLesson: () => y(),
|
|
8096
8159
|
// Direct access to avatar ref (always returns current value)
|
|
8097
8160
|
getAvatarRef: () => u.current,
|
|
8098
8161
|
// Convenience methods that delegate to avatar (always check current ref)
|
|
8099
8162
|
speakText: async (v, R = {}) => {
|
|
8100
8163
|
await u.current?.resumeAudioContext?.();
|
|
8101
|
-
const
|
|
8102
|
-
u.current?.speakText(v, { ...R, lipsyncLang: R.lipsyncLang ||
|
|
8164
|
+
const T = H.current || { lipsyncLang: "en" };
|
|
8165
|
+
u.current?.speakText(v, { ...R, lipsyncLang: R.lipsyncLang || T.lipsyncLang });
|
|
8103
8166
|
},
|
|
8104
8167
|
resumeAudioContext: async () => {
|
|
8105
8168
|
if (u.current?.resumeAudioContext)
|
|
@@ -8110,8 +8173,8 @@ const yt = Me(({
|
|
|
8110
8173
|
if (R.state === "suspended" || R.state === "interrupted")
|
|
8111
8174
|
try {
|
|
8112
8175
|
await R.resume(), console.log("Audio context resumed via talkingHead");
|
|
8113
|
-
} catch (
|
|
8114
|
-
console.warn("Failed to resume audio context:",
|
|
8176
|
+
} catch (T) {
|
|
8177
|
+
console.warn("Failed to resume audio context:", T);
|
|
8115
8178
|
}
|
|
8116
8179
|
} else
|
|
8117
8180
|
console.warn("Audio context not available yet");
|
|
@@ -8133,7 +8196,7 @@ const yt = Me(({
|
|
|
8133
8196
|
unlockAvatarPosition: () => u.current?.unlockAvatarPosition(),
|
|
8134
8197
|
// Custom action trigger
|
|
8135
8198
|
triggerCustomAction: (v, R) => {
|
|
8136
|
-
|
|
8199
|
+
d.current.onCustomAction({
|
|
8137
8200
|
type: v,
|
|
8138
8201
|
...R,
|
|
8139
8202
|
state: { ...a.current }
|
|
@@ -8143,8 +8206,8 @@ const yt = Me(({
|
|
|
8143
8206
|
handleResize: () => u.current?.handleResize(),
|
|
8144
8207
|
// Avatar readiness check (always returns current value)
|
|
8145
8208
|
isAvatarReady: () => u.current?.isReady || !1
|
|
8146
|
-
}), [
|
|
8147
|
-
const
|
|
8209
|
+
}), [B, k, ee, ie, C, _, A, Y, K, I, y]);
|
|
8210
|
+
const W = H.current || {
|
|
8148
8211
|
avatarUrl: "/avatars/brunette.glb",
|
|
8149
8212
|
avatarBody: "F",
|
|
8150
8213
|
mood: "happy",
|
|
@@ -8157,23 +8220,23 @@ const yt = Me(({
|
|
|
8157
8220
|
showFullAvatar: !1,
|
|
8158
8221
|
animations: e
|
|
8159
8222
|
};
|
|
8160
|
-
return /* @__PURE__ */
|
|
8223
|
+
return /* @__PURE__ */ pe("div", { style: { width: "100%", height: "100%" }, children: /* @__PURE__ */ pe(
|
|
8161
8224
|
Ve,
|
|
8162
8225
|
{
|
|
8163
8226
|
ref: u,
|
|
8164
|
-
avatarUrl:
|
|
8165
|
-
avatarBody:
|
|
8166
|
-
mood:
|
|
8167
|
-
ttsLang:
|
|
8168
|
-
ttsService:
|
|
8169
|
-
ttsVoice:
|
|
8170
|
-
ttsApiKey:
|
|
8171
|
-
bodyMovement:
|
|
8172
|
-
movementIntensity:
|
|
8173
|
-
showFullAvatar:
|
|
8227
|
+
avatarUrl: W.avatarUrl,
|
|
8228
|
+
avatarBody: W.avatarBody,
|
|
8229
|
+
mood: W.mood,
|
|
8230
|
+
ttsLang: W.ttsLang,
|
|
8231
|
+
ttsService: W.ttsService,
|
|
8232
|
+
ttsVoice: W.ttsVoice,
|
|
8233
|
+
ttsApiKey: W.ttsApiKey,
|
|
8234
|
+
bodyMovement: W.bodyMovement,
|
|
8235
|
+
movementIntensity: W.movementIntensity,
|
|
8236
|
+
showFullAvatar: W.showFullAvatar,
|
|
8174
8237
|
cameraView: "upper",
|
|
8175
|
-
animations:
|
|
8176
|
-
onReady:
|
|
8238
|
+
animations: W.animations,
|
|
8239
|
+
onReady: Q,
|
|
8177
8240
|
onLoading: () => {
|
|
8178
8241
|
},
|
|
8179
8242
|
onError: (v) => {
|
|
@@ -8286,14 +8349,14 @@ const Ge = {
|
|
|
8286
8349
|
duration: 5e3,
|
|
8287
8350
|
description: "Excited, energetic movement"
|
|
8288
8351
|
}
|
|
8289
|
-
}, wt = (
|
|
8352
|
+
}, wt = (X) => Ge[X] || null, zt = (X) => Ge.hasOwnProperty(X);
|
|
8290
8353
|
export {
|
|
8291
8354
|
yt as CurriculumLearning,
|
|
8292
8355
|
gt as SimpleTalkingAvatar,
|
|
8293
8356
|
Ve as TalkingHeadAvatar,
|
|
8294
8357
|
pt as TalkingHeadComponent,
|
|
8295
8358
|
Ge as animations,
|
|
8296
|
-
|
|
8359
|
+
Ee as getActiveTTSConfig,
|
|
8297
8360
|
wt as getAnimation,
|
|
8298
8361
|
kt as getVoiceOptions,
|
|
8299
8362
|
zt as hasAnimation
|