@sage-rsc/talking-head-react 1.2.3 → 1.3.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 +855 -822
- package/package.json +1 -1
- package/src/components/SimpleTalkingAvatar.jsx +62 -3
- package/src/utils/animationLoader.js +94 -0
package/dist/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { jsxs as Pe, jsx as
|
|
2
|
-
import { forwardRef as
|
|
1
|
+
import { jsxs as Pe, jsx as ye } from "react/jsx-runtime";
|
|
2
|
+
import { forwardRef as Me, useRef as W, useState as pe, useEffect as ce, useCallback as N, useImperativeHandle as Fe, useLayoutEffect as Xe } from "react";
|
|
3
3
|
import * as y from "three";
|
|
4
4
|
import { OrbitControls as Ye } from "three/addons/controls/OrbitControls.js";
|
|
5
5
|
import { GLTFLoader as je } from "three/addons/loaders/GLTFLoader.js";
|
|
@@ -7,14 +7,14 @@ import { DRACOLoader as Qe } from "three/addons/loaders/DRACOLoader.js";
|
|
|
7
7
|
import { FBXLoader as De } from "three/addons/loaders/FBXLoader.js";
|
|
8
8
|
import { RoomEnvironment as qe } from "three/addons/environments/RoomEnvironment.js";
|
|
9
9
|
import _e from "three/addons/libs/stats.module.js";
|
|
10
|
-
let m,
|
|
11
|
-
const
|
|
10
|
+
let m, ue, he;
|
|
11
|
+
const C = [0, 0, 0, 0], T = new y.Vector3(), ze = new y.Vector3(), ae = new y.Vector3(), Ce = new y.Vector3();
|
|
12
12
|
new y.Plane();
|
|
13
13
|
new y.Ray();
|
|
14
14
|
new y.Euler();
|
|
15
|
-
const
|
|
15
|
+
const re = new y.Quaternion(), Oe = new y.Quaternion(), fe = new y.Matrix4(), xe = new y.Matrix4();
|
|
16
16
|
new y.Vector3();
|
|
17
|
-
const
|
|
17
|
+
const He = new y.Vector3(0, 0, 1), Ke = new y.Vector3(1, 0, 0), Je = new y.Vector3(0, 1, 0), $e = new y.Vector3(0, 0, 1);
|
|
18
18
|
class et {
|
|
19
19
|
constructor(t = null) {
|
|
20
20
|
this.opt = Object.assign({
|
|
@@ -321,7 +321,7 @@ class et {
|
|
|
321
321
|
/// Bone's parent object
|
|
322
322
|
vBasis: r.position.clone(),
|
|
323
323
|
// Original local position
|
|
324
|
-
vWorld: r.parent.getWorldPosition(
|
|
324
|
+
vWorld: r.parent.getWorldPosition(T).clone(),
|
|
325
325
|
// World position, parent
|
|
326
326
|
qBasis: r.parent.quaternion.clone(),
|
|
327
327
|
// Original quaternion, parent
|
|
@@ -338,7 +338,7 @@ class et {
|
|
|
338
338
|
ea: [0, 0, 0, 0]
|
|
339
339
|
// External acceleration [m/s^2]
|
|
340
340
|
};
|
|
341
|
-
u.boneParent.matrixWorld.decompose(
|
|
341
|
+
u.boneParent.matrixWorld.decompose(T, re, ae), T.copy(He).applyQuaternion(re).setY(0).normalize(), re.premultiply(Oe.setFromUnitVectors(He, T).invert()).normalize(), u.qWorldInverseYaw = re.clone().normalize(), this.data.push(u), this.dict[h] = u;
|
|
342
342
|
try {
|
|
343
343
|
this.setValue(h, "type", s.type), this.setValue(h, "stiffness", s.stiffness), this.setValue(h, "damping", s.damping), this.setValue(h, "external", s.external), this.setValue(h, "limits", s.limits), this.setValue(h, "excludes", s.excludes), this.setValue(h, "deltaLocal", s.deltaLocal), this.setValue(h, "deltaWorld", s.deltaWorld), this.setValue(h, "pivot", s.pivot), this.setValue(h, "helper", s.helper);
|
|
344
344
|
} catch (a) {
|
|
@@ -356,22 +356,22 @@ class et {
|
|
|
356
356
|
for (this.timerMs += t, t > 1e3 && (this.timerMs = 0), t /= 1e3, e = 0, i = this.objectsUpdate.length; e < i; e++)
|
|
357
357
|
o = this.objectsUpdate[e], o.updateMatrix(), o.parent === null ? o.matrixWorld.copy(o.matrix) : o.matrixWorld.multiplyMatrices(o.parent.matrixWorld, o.matrix), o.matrixWorldNeedsUpdate = !1;
|
|
358
358
|
for (e = 0, i = this.data.length; e < i; e++) {
|
|
359
|
-
if (o = this.data[e],
|
|
359
|
+
if (o = this.data[e], T.copy(o.vWorld), fe.copy(o.boneParent.matrixWorld), xe.copy(fe).invert(), o.vWorld.setFromMatrixPosition(fe), T.applyMatrix4(xe), T.length() > 0.5 && (console.info("Info: Unrealistic jump of " + T.length().toFixed(2) + " meters."), T.setLength(0.5)), T.applyQuaternion(o.bone.quaternion), C[0] = T.x, C[1] = T.y, C[2] = -T.z, C[3] = T.length() / 3, o.children)
|
|
360
360
|
for (n = 0, s = o.children.length; n < s; n++)
|
|
361
|
-
m = o.children[n],
|
|
362
|
-
if (m = this.opt.sensitivityFactor,
|
|
363
|
-
o.vBasis.x +
|
|
364
|
-
o.vBasis.y +
|
|
365
|
-
o.vBasis.z +
|
|
366
|
-
),
|
|
361
|
+
m = o.children[n], C[0] -= m.v[0] * t / 3, C[1] -= m.v[1] * t / 3, C[2] += m.v[2] * t / 3, C[3] -= m.v[3] * t / 3;
|
|
362
|
+
if (m = this.opt.sensitivityFactor, C[0] *= o.ext * m, C[1] *= o.ext * m, C[2] *= o.ext * m, C[3] *= o.ext * m, o.isX && (m = C[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 + C[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 = C[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 + C[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 = C[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 + C[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 = C[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 + C[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), C[0] = o.p[0], C[1] = o.p[1], C[2] = o.p[2], C[3] = o.p[3], m = this.opt.movementFactor, C[0] *= m, C[1] *= m, C[2] *= m, C[3] *= m, o.dl && (m = o.dl, C[0] += m[0], C[1] += m[1], C[2] += m[2]), o.dw && (m = o.dw, T.set(
|
|
363
|
+
o.vBasis.x + C[0],
|
|
364
|
+
o.vBasis.y + C[1],
|
|
365
|
+
o.vBasis.z + C[2]
|
|
366
|
+
), T.applyMatrix4(fe), T.x += m[0], T.y += m[1], T.z += m[2], T.applyMatrix4(xe), C[0] += T.x - o.vBasis.x, C[1] += T.y - o.vBasis.y, C[2] += T.z - o.vBasis.z), o.limits && this.opt.isLimits && (m = o.limits, m[0] && (m[0][0] !== null && C[0] < m[0][0] && (C[0] = m[0][0]), m[0][1] !== null && C[0] > m[0][1] && (C[0] = m[0][1])), m[1] && (m[1][0] !== null && C[1] < m[1][0] && (C[1] = m[1][0]), m[1][1] !== null && C[1] > m[1][1] && (C[1] = m[1][1])), m[2] && (m[2][0] !== null && C[2] < m[2][0] && (C[2] = m[2][0]), m[2][1] !== null && C[2] > m[2][1] && (C[2] = m[2][1])), m[3] && (m[3][0] !== null && C[3] < m[3][0] && (C[3] = m[3][0]), m[3][1] !== null && C[3] > m[3][1] && (C[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 + C[0],
|
|
369
|
+
o.vBasis.y + C[1],
|
|
370
|
+
o.vBasis.z - C[2]
|
|
371
371
|
);
|
|
372
|
-
else if (o.boneParent.quaternion.copy(o.qBasis), o.pivot && this.opt.isPivots && (o.boneParent.updateWorldMatrix(!1, !1), o.boneParent.matrixWorld.decompose(
|
|
372
|
+
else if (o.boneParent.quaternion.copy(o.qBasis), o.pivot && this.opt.isPivots && (o.boneParent.updateWorldMatrix(!1, !1), o.boneParent.matrixWorld.decompose(T, re, ae), T.copy(He).applyQuaternion(re).setY(0).normalize(), re.premultiply(Oe.setFromUnitVectors(He, T).invert()).normalize(), o.boneParent.quaternion.multiply(re.invert()), o.boneParent.quaternion.multiply(o.qWorldInverseYaw)), o.isZ && (m = Math.atan(C[0] / o.l), re.setFromAxisAngle($e, -m), o.boneParent.quaternion.multiply(re)), o.isY && (m = o.l / 3, m = m * Math.tanh(C[1] / m), o.bone.position.setLength(o.l + m)), o.isX && (m = Math.atan(C[2] / o.l), re.setFromAxisAngle(Ke, -m), o.boneParent.quaternion.multiply(re)), o.isT && (m = 1.5 * Math.tanh(C[3] * 1.5), re.setFromAxisAngle(Je, -m), o.boneParent.quaternion.multiply(re)), o.boneParent.updateWorldMatrix(!1, !0), o.excludes && this.opt.isExcludes)
|
|
373
373
|
for (n = 0, s = o.excludes.length; n < s; n++)
|
|
374
|
-
m = o.excludes[n],
|
|
374
|
+
m = o.excludes[n], ae.set(0, 0, 0), m.deltaLocal && (ae.x += m.deltaLocal[0], ae.y += m.deltaLocal[1], ae.z += m.deltaLocal[2]), ae.applyMatrix4(m.bone.matrixWorld), xe.copy(o.boneParent.matrixWorld).invert(), ae.applyMatrix4(xe), T.copy(o.bone.position), !(T.distanceToSquared(ae) >= m.radiusSq) && (he = T.length(), ue = ae.length(), !(ue > m.radius + he) && (ue < Math.abs(m.radius - he) || (ue = (ue * ue + he * he - m.radiusSq) / (2 * ue), ae.normalize(), Ce.copy(ae).multiplyScalar(ue), ue = Math.sqrt(he * he - ue * ue), T.subVectors(T, Ce).projectOnPlane(ae).normalize().multiplyScalar(ue), ze.subVectors(o.vBasis, Ce).projectOnPlane(ae).normalize(), he = ze.dot(T), he < 0 && (he = Math.sqrt(ue * ue - he * he), ze.multiplyScalar(he), T.add(ze)), T.add(Ce).normalize(), ae.copy(o.bone.position).normalize(), re.setFromUnitVectors(ae, T), o.boneParent.quaternion.premultiply(re), o.boneParent.updateWorldMatrix(!1, !0))));
|
|
375
375
|
}
|
|
376
376
|
this.helpers.isActive && this.updateHelpers();
|
|
377
377
|
}
|
|
@@ -442,17 +442,17 @@ class et {
|
|
|
442
442
|
*/
|
|
443
443
|
updateHelpers() {
|
|
444
444
|
if (m = this.helpers.points, m.bones.length) {
|
|
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
|
-
|
|
448
|
+
fe.multiplyMatrices(xe, m.bones[e].matrixWorld), T.setFromMatrixPosition(fe), t.setXYZ(e, T.x, T.y, T.z);
|
|
449
449
|
t.needsUpdate = !0, m.object.updateMatrixWorld();
|
|
450
450
|
}
|
|
451
451
|
if (m = this.helpers.lines, m.bones.length) {
|
|
452
|
-
|
|
452
|
+
xe.copy(this.armature.matrixWorld).invert();
|
|
453
453
|
const t = m.object.geometry.getAttribute("position");
|
|
454
454
|
for (let e = 0, n = 0, i = m.bones.length; e < i; e++, n += 2)
|
|
455
|
-
|
|
455
|
+
fe.multiplyMatrices(xe, m.bones[e].matrixWorld), T.setFromMatrixPosition(fe), t.setXYZ(n, T.x, T.y, T.z), fe.multiplyMatrices(xe, m.bones[e].parent.matrixWorld), T.setFromMatrixPosition(fe), t.setXYZ(n + 1, T.x, T.y, T.z);
|
|
456
456
|
t.needsUpdate = !0, m.object.updateMatrixWorld();
|
|
457
457
|
}
|
|
458
458
|
}
|
|
@@ -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 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,
|
|
610
|
-
n[(h + a) * 2] = d + g, n[(h + a) * 2 + 1] = c +
|
|
611
|
-
const
|
|
612
|
-
r =
|
|
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, x = 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 + x, n[(h + a + i / 2) * 2] = d - g, n[(h + a + i / 2) * 2 + 1] = c - x;
|
|
611
|
+
const f = r * o - u * l, k = r * l + u * o;
|
|
612
|
+
r = f, u = k;
|
|
613
613
|
}
|
|
614
614
|
}
|
|
615
615
|
}
|
|
@@ -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 y.Quaternion(), G = new y.Euler(), ve = new y.Vector3(), Re = new y.Vector3(), We = new y.Box3();
|
|
2633
2633
|
new y.Matrix4();
|
|
2634
2634
|
new y.Matrix4();
|
|
2635
2635
|
new y.Vector3();
|
|
@@ -4228,13 +4228,13 @@ class Be {
|
|
|
4228
4228
|
const a = s.morphTargetDictionary[r], d = o.morphAttributes.position[a], c = o.morphAttributes.normal?.[a];
|
|
4229
4229
|
l || (l = new y.Float32BufferAttribute(d.count * 3, 3), c && (h = new y.Float32BufferAttribute(d.count * 3, 3)));
|
|
4230
4230
|
for (let g = 0; g < d.count; g++) {
|
|
4231
|
-
const
|
|
4232
|
-
l.setXYZ(g,
|
|
4231
|
+
const x = l.getX(g) + d.getX(g) * u, f = l.getY(g) + d.getY(g) * u, k = l.getZ(g) + d.getZ(g) * u;
|
|
4232
|
+
l.setXYZ(g, x, f, k);
|
|
4233
4233
|
}
|
|
4234
4234
|
if (c)
|
|
4235
4235
|
for (let g = 0; g < d.count; g++) {
|
|
4236
|
-
const
|
|
4237
|
-
h.setXYZ(g,
|
|
4236
|
+
const x = h.getX(g) + c.getX(g) * u, f = h.getY(g) + c.getY(g) * u, k = h.getZ(g) + c.getZ(g) * u;
|
|
4237
|
+
h.setXYZ(g, x, f, k);
|
|
4238
4238
|
}
|
|
4239
4239
|
}
|
|
4240
4240
|
if (l) {
|
|
@@ -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
|
+
G.set(e.x, e.y, e.z);
|
|
4402
4402
|
const n = this.poseAvatar.props[t];
|
|
4403
|
-
n.isQuaternion ? (
|
|
4403
|
+
n.isQuaternion ? (J.setFromEuler(G), n.multiply(J)) : n.isVector3 && n.add(G);
|
|
4404
4404
|
}
|
|
4405
4405
|
}
|
|
4406
4406
|
/**
|
|
@@ -5107,9 +5107,9 @@ class Be {
|
|
|
5107
5107
|
g.newvalue = c[i];
|
|
5108
5108
|
else {
|
|
5109
5109
|
g.newvalue = c[i + 1];
|
|
5110
|
-
const
|
|
5111
|
-
let
|
|
5112
|
-
|
|
5110
|
+
const x = a.ts[i + 1] - a.ts[i];
|
|
5111
|
+
let f = 1;
|
|
5112
|
+
x > 1e-4 && (f = (this.animClock - a.ts[i]) / x), f < 1 && (g.easing && (f = g.easing(f)), g.newvalue = (1 - f) * c[i] + f * 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
5115
|
switch (d) {
|
|
@@ -5172,7 +5172,7 @@ class Be {
|
|
|
5172
5172
|
}, i.x ? new y.Vector3(i.x, i.y, i.z) : null, !0, i.d);
|
|
5173
5173
|
break;
|
|
5174
5174
|
}
|
|
5175
|
-
if ((h || r) && (
|
|
5175
|
+
if ((h || r) && (G.setFromQuaternion(this.poseAvatar.props["Head.quaternion"]), G.x = Math.max(-0.9, Math.min(0.9, 2 * G.x - 0.5)), G.y = Math.max(-0.9, Math.min(0.9, -2.5 * G.y)), h ? (Object.assign(this.mtAvatar.eyesLookDown, { system: G.x < 0 ? -G.x : 0, needsUpdate: !0 }), Object.assign(this.mtAvatar.eyesLookUp, { system: G.x < 0 ? 0 : G.x, needsUpdate: !0 }), Object.assign(this.mtAvatar.eyeLookInLeft, { system: G.y < 0 ? -G.y : 0, needsUpdate: !0 }), Object.assign(this.mtAvatar.eyeLookOutLeft, { system: G.y < 0 ? 0 : G.y, needsUpdate: !0 }), Object.assign(this.mtAvatar.eyeLookInRight, { system: G.y < 0 ? 0 : G.y, needsUpdate: !0 }), Object.assign(this.mtAvatar.eyeLookOutRight, { system: G.y < 0 ? -G.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,7 +5193,7 @@ 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) {
|
|
@@ -5262,12 +5262,12 @@ class Be {
|
|
|
5262
5262
|
e = e || {};
|
|
5263
5263
|
const s = /[!\.\?\n\p{Extended_Pictographic}]/ug, o = /[ ]/ug, l = /[\p{L}\p{N},\.\p{Quotation_Mark}!€\$\+\p{Dash_Punctuation}%&\?]/ug, h = /[\p{Extended_Pictographic}]/ug, r = e.lipsyncLang || this.avatar.lipsyncLang || this.opt.lipsyncLang;
|
|
5264
5264
|
let u = "", a = "", d = 0, c = [], g = [];
|
|
5265
|
-
const
|
|
5266
|
-
for (let
|
|
5267
|
-
const
|
|
5268
|
-
let p =
|
|
5269
|
-
const B =
|
|
5270
|
-
if (p && !
|
|
5265
|
+
const x = Array.from(this.segmenter.segment(t), (f) => f.segment);
|
|
5266
|
+
for (let f = 0; f < x.length; f++) {
|
|
5267
|
+
const k = f === x.length - 1, O = x[f].match(l);
|
|
5268
|
+
let p = x[f].match(s);
|
|
5269
|
+
const B = x[f].match(h), H = x[f].match(o);
|
|
5270
|
+
if (p && !k && !B && x[f + 1].match(s) && (p = !1), n && (u += x[f]), O && (!i || i.every((v) => f < v[0] || f > v[1])) && (a += x[f]), (H || p || k) && (a.length && (a = this.lipsyncPreProcessText(a, r), a.length && c.push({
|
|
5271
5271
|
mark: d,
|
|
5272
5272
|
word: a
|
|
5273
5273
|
})), u.length && (g.push({
|
|
@@ -5278,31 +5278,31 @@ class Be {
|
|
|
5278
5278
|
subtitles: [u]
|
|
5279
5279
|
}
|
|
5280
5280
|
}), u = ""), a.length)) {
|
|
5281
|
-
const
|
|
5282
|
-
if (
|
|
5283
|
-
const
|
|
5284
|
-
for (let
|
|
5281
|
+
const v = this.lipsyncWordsToVisemes(a, r);
|
|
5282
|
+
if (v && v.visemes && v.visemes.length) {
|
|
5283
|
+
const L = v.times[v.visemes.length - 1] + v.durations[v.visemes.length - 1];
|
|
5284
|
+
for (let I = 0; I < v.visemes.length; I++)
|
|
5285
5285
|
g.push({
|
|
5286
5286
|
mark: d,
|
|
5287
5287
|
template: { name: "viseme" },
|
|
5288
|
-
ts: [(
|
|
5288
|
+
ts: [(v.times[I] - 0.6) / L, (v.times[I] + 0.5) / L, (v.times[I] + v.durations[I] + 0.5) / L],
|
|
5289
5289
|
vs: {
|
|
5290
|
-
["viseme_" +
|
|
5290
|
+
["viseme_" + v.visemes[I]]: [null, v.visemes[I] === "PP" || v.visemes[I] === "FF" ? 0.9 : 0.6, 0]
|
|
5291
5291
|
}
|
|
5292
5292
|
});
|
|
5293
5293
|
}
|
|
5294
5294
|
a = "", d++;
|
|
5295
5295
|
}
|
|
5296
|
-
if (p ||
|
|
5297
|
-
if (c.length ||
|
|
5298
|
-
const
|
|
5296
|
+
if (p || k) {
|
|
5297
|
+
if (c.length || k && g.length) {
|
|
5298
|
+
const v = {
|
|
5299
5299
|
anim: g
|
|
5300
5300
|
};
|
|
5301
|
-
n && (
|
|
5301
|
+
n && (v.onSubtitles = n), c.length && !e.avatarMute && (v.text = c, e.avatarMood && (v.mood = e.avatarMood), e.ttsLang && (v.lang = e.ttsLang), e.ttsVoice && (v.voice = e.ttsVoice), e.ttsRate && (v.rate = e.ttsRate), e.ttsVoice && (v.pitch = e.ttsPitch), e.ttsVolume && (v.volume = e.ttsVolume)), this.speechQueue.push(v), c = [], a = "", d = 0, g = [];
|
|
5302
5302
|
}
|
|
5303
5303
|
if (B) {
|
|
5304
|
-
let
|
|
5305
|
-
|
|
5304
|
+
let v = this.animEmojis[x[f]];
|
|
5305
|
+
v && v.link && (v = this.animEmojis[v.link]), v && this.speechQueue.push({ emoji: v });
|
|
5306
5306
|
}
|
|
5307
5307
|
this.speechQueue.push({ break: 100 });
|
|
5308
5308
|
}
|
|
@@ -5395,15 +5395,15 @@ class Be {
|
|
|
5395
5395
|
const a = this.lipsyncPreProcessText(h, i), d = this.lipsyncWordsToVisemes(a, i);
|
|
5396
5396
|
if (d && d.visemes && d.visemes.length) {
|
|
5397
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
|
-
let
|
|
5398
|
+
let x = 0.6 + this.convertRange(g, [0, u], [0, 0.4]);
|
|
5399
5399
|
if (u = Math.min(u, d.visemes.length * 200), c > 0)
|
|
5400
|
-
for (let
|
|
5401
|
-
const
|
|
5400
|
+
for (let f = 0; f < d.visemes.length; f++) {
|
|
5401
|
+
const k = r + d.times[f] / c * u, O = d.durations[f] / c * u;
|
|
5402
5402
|
o.push({
|
|
5403
5403
|
template: { name: "viseme" },
|
|
5404
|
-
ts: [
|
|
5404
|
+
ts: [k - Math.min(60, 2 * O / 3), k + Math.min(25, O / 2), k + O + Math.min(60, O / 2)],
|
|
5405
5405
|
vs: {
|
|
5406
|
-
["viseme_" + d.visemes[
|
|
5406
|
+
["viseme_" + d.visemes[f]]: [null, d.visemes[f] === "PP" || d.visemes[f] === "FF" ? 0.9 : x, 0]
|
|
5407
5407
|
}
|
|
5408
5408
|
});
|
|
5409
5409
|
}
|
|
@@ -5486,30 +5486,30 @@ class Be {
|
|
|
5486
5486
|
const p = u.find((B) => B.name.includes(a) || B.lang === o);
|
|
5487
5487
|
p && (s.voice = p);
|
|
5488
5488
|
}
|
|
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",
|
|
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", x = this.lipsyncPreProcessText(i, g), f = this.lipsyncWordsToVisemes(x, g);
|
|
5490
5490
|
console.log("Browser TTS Lip-sync Debug:", {
|
|
5491
5491
|
text: i,
|
|
5492
5492
|
lipsyncLang: g,
|
|
5493
|
-
processedText:
|
|
5494
|
-
lipsyncData:
|
|
5495
|
-
hasVisemes:
|
|
5493
|
+
processedText: x,
|
|
5494
|
+
lipsyncData: f,
|
|
5495
|
+
hasVisemes: f && f.visemes && f.visemes.length > 0,
|
|
5496
5496
|
estimatedDuration: d
|
|
5497
5497
|
});
|
|
5498
|
-
const
|
|
5499
|
-
if (
|
|
5500
|
-
const p =
|
|
5501
|
-
for (let B = 0; B <
|
|
5502
|
-
const
|
|
5503
|
-
|
|
5498
|
+
const k = [];
|
|
5499
|
+
if (f && f.visemes && f.visemes.length > 0) {
|
|
5500
|
+
const p = f.times[f.visemes.length - 1] + f.durations[f.visemes.length - 1];
|
|
5501
|
+
for (let B = 0; B < f.visemes.length; B++) {
|
|
5502
|
+
const H = f.visemes[B], v = f.times[B] / p, L = f.durations[B] / p, I = v * d, z = L * d;
|
|
5503
|
+
k.push({
|
|
5504
5504
|
template: { name: "viseme" },
|
|
5505
|
-
ts: [
|
|
5505
|
+
ts: [I - Math.min(60, 2 * z / 3), I + Math.min(25, z / 2), I + z + Math.min(60, z / 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 O = [...t.anim, ...
|
|
5512
|
+
const O = [...t.anim, ...k];
|
|
5513
5513
|
this.audioPlaylist.push({ anim: O, audio: c }), this.onSubtitles = t.onSubtitles || null, this.resetLips(), t.mood && this.setMood(t.mood), this.playAudio(), s.onend = () => {
|
|
5514
5514
|
e();
|
|
5515
5515
|
}, s.onerror = (p) => {
|
|
@@ -5559,10 +5559,10 @@ class Be {
|
|
|
5559
5559
|
hasVisemes: c && c.visemes && c.visemes.length > 0
|
|
5560
5560
|
}), c && c.visemes && c.visemes.length > 0)
|
|
5561
5561
|
r = {
|
|
5562
|
-
visemes: c.visemes.map((g,
|
|
5562
|
+
visemes: c.visemes.map((g, x) => ({
|
|
5563
5563
|
viseme: g,
|
|
5564
|
-
startTime:
|
|
5565
|
-
endTime: (
|
|
5564
|
+
startTime: x * l.duration / c.visemes.length,
|
|
5565
|
+
endTime: (x + 1) * l.duration / c.visemes.length,
|
|
5566
5566
|
duration: l.duration / c.visemes.length,
|
|
5567
5567
|
intensity: 0.7
|
|
5568
5568
|
})),
|
|
@@ -5575,16 +5575,16 @@ class Be {
|
|
|
5575
5575
|
} catch (d) {
|
|
5576
5576
|
console.error("Text-based lip-sync failed, using fallback:", d);
|
|
5577
5577
|
const c = e.toLowerCase().split(/\s+/), g = [];
|
|
5578
|
-
for (const
|
|
5579
|
-
for (const
|
|
5580
|
-
let
|
|
5581
|
-
"aeiou".includes(
|
|
5578
|
+
for (const x of c)
|
|
5579
|
+
for (const f of x) {
|
|
5580
|
+
let k = "aa";
|
|
5581
|
+
"aeiou".includes(f) ? k = "aa" : "bp".includes(f) ? k = "PP" : "fv".includes(f) ? k = "FF" : "st".includes(f) ? k = "SS" : "dln".includes(f) ? k = "DD" : "kg".includes(f) ? k = "kk" : "rw".includes(f) && (k = "RR"), g.push(k);
|
|
5582
5582
|
}
|
|
5583
5583
|
r = {
|
|
5584
|
-
visemes: g.map((
|
|
5585
|
-
viseme:
|
|
5586
|
-
startTime:
|
|
5587
|
-
endTime: (
|
|
5584
|
+
visemes: g.map((x, f) => ({
|
|
5585
|
+
viseme: x,
|
|
5586
|
+
startTime: f * l.duration / g.length,
|
|
5587
|
+
endTime: (f + 1) * l.duration / g.length,
|
|
5588
5588
|
duration: l.duration / g.length,
|
|
5589
5589
|
intensity: 0.6
|
|
5590
5590
|
})),
|
|
@@ -5609,12 +5609,12 @@ class Be {
|
|
|
5609
5609
|
if (r.visemes && r.visemes.length > 0) {
|
|
5610
5610
|
console.log("ElevenLabs: Generating lip-sync animation from", r.visemes.length, "visemes");
|
|
5611
5611
|
for (let d = 0; d < r.visemes.length; d++) {
|
|
5612
|
-
const c = r.visemes[d], g = c.startTime * 1e3,
|
|
5612
|
+
const c = r.visemes[d], g = c.startTime * 1e3, x = c.duration * 1e3, f = c.intensity;
|
|
5613
5613
|
u.push({
|
|
5614
5614
|
template: { name: "viseme" },
|
|
5615
|
-
ts: [g - Math.min(60, 2 *
|
|
5615
|
+
ts: [g - Math.min(60, 2 * x / 3), g + Math.min(25, x / 2), g + x + Math.min(60, x / 2)],
|
|
5616
5616
|
vs: {
|
|
5617
|
-
["viseme_" + c.viseme]: [null,
|
|
5617
|
+
["viseme_" + c.viseme]: [null, f, 0]
|
|
5618
5618
|
}
|
|
5619
5619
|
});
|
|
5620
5620
|
}
|
|
@@ -5657,10 +5657,10 @@ class Be {
|
|
|
5657
5657
|
hasVisemes: c && c.visemes && c.visemes.length > 0
|
|
5658
5658
|
}), c && c.visemes && c.visemes.length > 0)
|
|
5659
5659
|
r = {
|
|
5660
|
-
visemes: c.visemes.map((g,
|
|
5660
|
+
visemes: c.visemes.map((g, x) => ({
|
|
5661
5661
|
viseme: g,
|
|
5662
|
-
startTime:
|
|
5663
|
-
endTime: (
|
|
5662
|
+
startTime: x * l.duration / c.visemes.length,
|
|
5663
|
+
endTime: (x + 1) * l.duration / c.visemes.length,
|
|
5664
5664
|
duration: l.duration / c.visemes.length,
|
|
5665
5665
|
intensity: 0.7
|
|
5666
5666
|
})),
|
|
@@ -5673,16 +5673,16 @@ class Be {
|
|
|
5673
5673
|
} catch (d) {
|
|
5674
5674
|
console.error("Text-based lip-sync failed, using fallback:", d);
|
|
5675
5675
|
const c = e.toLowerCase().split(/\s+/), g = [];
|
|
5676
|
-
for (const
|
|
5677
|
-
for (const
|
|
5678
|
-
let
|
|
5679
|
-
"aeiou".includes(
|
|
5676
|
+
for (const x of c)
|
|
5677
|
+
for (const f of x) {
|
|
5678
|
+
let k = "aa";
|
|
5679
|
+
"aeiou".includes(f) ? k = "aa" : "bp".includes(f) ? k = "PP" : "fv".includes(f) ? k = "FF" : "st".includes(f) ? k = "SS" : "dln".includes(f) ? k = "DD" : "kg".includes(f) ? k = "kk" : "rw".includes(f) && (k = "RR"), g.push(k);
|
|
5680
5680
|
}
|
|
5681
5681
|
r = {
|
|
5682
|
-
visemes: g.map((
|
|
5683
|
-
viseme:
|
|
5684
|
-
startTime:
|
|
5685
|
-
endTime: (
|
|
5682
|
+
visemes: g.map((x, f) => ({
|
|
5683
|
+
viseme: x,
|
|
5684
|
+
startTime: f * l.duration / g.length,
|
|
5685
|
+
endTime: (f + 1) * l.duration / g.length,
|
|
5686
5686
|
duration: l.duration / g.length,
|
|
5687
5687
|
intensity: 0.6
|
|
5688
5688
|
})),
|
|
@@ -5707,12 +5707,12 @@ class Be {
|
|
|
5707
5707
|
if (r.visemes && r.visemes.length > 0) {
|
|
5708
5708
|
console.log("Deepgram: Generating lip-sync animation from", r.visemes.length, "visemes");
|
|
5709
5709
|
for (let d = 0; d < r.visemes.length; d++) {
|
|
5710
|
-
const c = r.visemes[d], g = c.startTime * 1e3,
|
|
5710
|
+
const c = r.visemes[d], g = c.startTime * 1e3, x = c.duration * 1e3, f = c.intensity;
|
|
5711
5711
|
u.push({
|
|
5712
5712
|
template: { name: "viseme" },
|
|
5713
|
-
ts: [g - Math.min(60, 2 *
|
|
5713
|
+
ts: [g - Math.min(60, 2 * x / 3), g + Math.min(25, x / 2), g + x + Math.min(60, x / 2)],
|
|
5714
5714
|
vs: {
|
|
5715
|
-
["viseme_" + c.viseme]: [null,
|
|
5715
|
+
["viseme_" + c.viseme]: [null, f, 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 d = h.visemes[a], c = d.startTime * 1e3, g = d.duration * 1e3,
|
|
5762
|
+
const d = h.visemes[a], c = d.startTime * 1e3, g = d.duration * 1e3, x = d.intensity;
|
|
5763
5763
|
r.push({
|
|
5764
5764
|
template: { name: "viseme" },
|
|
5765
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_" + d.viseme]: [null,
|
|
5767
|
+
["viseme_" + d.viseme]: [null, x, 0]
|
|
5768
5768
|
}
|
|
5769
5769
|
});
|
|
5770
5770
|
}
|
|
@@ -6050,10 +6050,10 @@ class Be {
|
|
|
6050
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
6052
|
for (let c = 0; c < r.visemes.length; c++) {
|
|
6053
|
-
const g = e + s + r.times[c] / u * o,
|
|
6053
|
+
const g = e + s + r.times[c] / u * o, x = r.durations[c] / u * o;
|
|
6054
6054
|
this.animQueue.push({
|
|
6055
6055
|
template: { name: "viseme" },
|
|
6056
|
-
ts: [g - Math.min(60, 2 *
|
|
6056
|
+
ts: [g - Math.min(60, 2 * x / 3), g + Math.min(25, x / 2), g + x + Math.min(60, x / 2)],
|
|
6057
6057
|
vs: {
|
|
6058
6058
|
["viseme_" + r.visemes[c]]: [null, r.visemes[c] === "PP" || r.visemes[c] === "FF" ? 0.9 : d, 0]
|
|
6059
6059
|
}
|
|
@@ -6146,7 +6146,7 @@ class Be {
|
|
|
6146
6146
|
*/
|
|
6147
6147
|
lookAtCamera(t) {
|
|
6148
6148
|
let e;
|
|
6149
|
-
if (this.speakTo && (e = new y.Vector3(), this.speakTo.objectLeftEye?.isObject3D ? (this.speakTo.armature.objectHead, this.speakTo.objectLeftEye.updateMatrixWorld(!0), this.speakTo.objectRightEye.updateMatrixWorld(!0),
|
|
6149
|
+
if (this.speakTo && (e = new y.Vector3(), this.speakTo.objectLeftEye?.isObject3D ? (this.speakTo.armature.objectHead, this.speakTo.objectLeftEye.updateMatrixWorld(!0), this.speakTo.objectRightEye.updateMatrixWorld(!0), ve.setFromMatrixPosition(this.speakTo.objectLeftEye.matrixWorld), Re.setFromMatrixPosition(this.speakTo.objectRightEye.matrixWorld), e.addVectors(ve, Re).divideScalar(2)) : this.speakTo.isObject3D ? this.speakTo.getWorldPosition(e) : this.speakTo.isVector3 ? e.set(this.speakTo) : this.speakTo.x && this.speakTo.y && this.speakTo.z && e.set(this.speakTo.x, this.speakTo.y, this.speakTo.z)), !e) {
|
|
6150
6150
|
if (this.avatar.hasOwnProperty("avatarIgnoreCamera")) {
|
|
6151
6151
|
if (this.avatar.avatarIgnoreCamera) {
|
|
6152
6152
|
this.lookAhead(t);
|
|
@@ -6159,16 +6159,16 @@ class Be {
|
|
|
6159
6159
|
this.lookAt(null, null, t);
|
|
6160
6160
|
return;
|
|
6161
6161
|
}
|
|
6162
|
-
this.objectLeftEye.updateMatrixWorld(!0), this.objectRightEye.updateMatrixWorld(!0),
|
|
6163
|
-
const n = new y.Vector3().subVectors(e,
|
|
6164
|
-
|
|
6165
|
-
const l = new y.Quaternion().setFromEuler(
|
|
6166
|
-
|
|
6167
|
-
let r =
|
|
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
|
+
const n = new y.Vector3().subVectors(e, ve).normalize(), i = Math.atan2(n.x, n.z), s = Math.asin(-n.y);
|
|
6164
|
+
G.set(s, i, 0, "YXZ");
|
|
6165
|
+
const l = new y.Quaternion().setFromEuler(G), h = new y.Quaternion().copy(l).multiply(J.clone().invert());
|
|
6166
|
+
G.setFromQuaternion(h, "YXZ");
|
|
6167
|
+
let r = G.x / (40 / 24) + 0.2, u = G.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
|
|
6170
|
-
|
|
6171
|
-
const
|
|
6169
|
+
let x = this.animQueue.findIndex((k) => k.template.name === "lookat");
|
|
6170
|
+
x !== -1 && this.animQueue.splice(x, 1);
|
|
6171
|
+
const f = {
|
|
6172
6172
|
name: "lookat",
|
|
6173
6173
|
dt: [750, t],
|
|
6174
6174
|
vs: {
|
|
@@ -6183,7 +6183,7 @@ class Be {
|
|
|
6183
6183
|
headMove: [0]
|
|
6184
6184
|
}
|
|
6185
6185
|
};
|
|
6186
|
-
this.animQueue.push(this.animFactory(
|
|
6186
|
+
this.animQueue.push(this.animFactory(f));
|
|
6187
6187
|
}
|
|
6188
6188
|
}
|
|
6189
6189
|
/**
|
|
@@ -6199,19 +6199,19 @@ class Be {
|
|
|
6199
6199
|
const s = new y.Vector3().setFromMatrixPosition(this.objectLeftEye.matrixWorld), o = new y.Vector3().setFromMatrixPosition(this.objectRightEye.matrixWorld), l = new y.Vector3().addVectors(s, o).divideScalar(2);
|
|
6200
6200
|
l.project(this.camera);
|
|
6201
6201
|
let h = (l.x + 1) / 2 * i.width + i.left, r = -(l.y - 1) / 2 * i.height + i.top;
|
|
6202
|
-
t === null && (t = h), e === null && (e = r),
|
|
6203
|
-
let u =
|
|
6204
|
-
|
|
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"]), G.setFromQuaternion(J);
|
|
6203
|
+
let u = G.x / (40 / 24), a = G.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), x = Math.max(window.innerHeight - r, r), f = this.convertRange(e, [r - x, r + x], [-0.3, 0.6]) - u + d, k = this.convertRange(t, [h - g, h + g], [-0.8, 0.8]) - a + c;
|
|
6204
|
+
f = Math.min(0.6, Math.max(-0.3, f)), k = Math.min(0.8, Math.max(-0.8, k));
|
|
6205
6205
|
let O = (Math.random() - 0.5) / 4, p = (Math.random() - 0.5) / 4;
|
|
6206
6206
|
if (n) {
|
|
6207
|
-
let B = this.animQueue.findIndex((
|
|
6207
|
+
let B = this.animQueue.findIndex((v) => v.template.name === "lookat");
|
|
6208
6208
|
B !== -1 && this.animQueue.splice(B, 1);
|
|
6209
|
-
const
|
|
6209
|
+
const H = {
|
|
6210
6210
|
name: "lookat",
|
|
6211
6211
|
dt: [750, n],
|
|
6212
6212
|
vs: {
|
|
6213
|
-
bodyRotateX: [
|
|
6214
|
-
bodyRotateY: [
|
|
6213
|
+
bodyRotateX: [f + O],
|
|
6214
|
+
bodyRotateY: [k + p],
|
|
6215
6215
|
eyesRotateX: [-3 * O + 0.1],
|
|
6216
6216
|
eyesRotateY: [-5 * p],
|
|
6217
6217
|
browInnerUp: [[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
|
/**
|
|
@@ -6427,13 +6427,13 @@ class Be {
|
|
|
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 c = await fetch(t), g = c.headers.get("content-type"),
|
|
6430
|
+
const c = await fetch(t), g = c.headers.get("content-type"), x = await c.text();
|
|
6431
6431
|
console.error("Response details:", {
|
|
6432
6432
|
status: c.status,
|
|
6433
6433
|
contentType: g,
|
|
6434
|
-
firstBytes:
|
|
6435
|
-
isHTML:
|
|
6436
|
-
}), (
|
|
6434
|
+
firstBytes: x.substring(0, 100),
|
|
6435
|
+
isHTML: x.trim().startsWith("<!DOCTYPE") || x.trim().startsWith("<html")
|
|
6436
|
+
}), (x.trim().startsWith("<!DOCTYPE") || x.trim().startsWith("<html")) && console.error("The server returned an HTML page instead of an FBX file. The file path is likely incorrect.");
|
|
6437
6437
|
} catch (c) {
|
|
6438
6438
|
console.error("Could not fetch file for debugging:", c);
|
|
6439
6439
|
}
|
|
@@ -6442,39 +6442,39 @@ class Be {
|
|
|
6442
6442
|
if (a && a.animations && a.animations[i]) {
|
|
6443
6443
|
let d = a.animations[i];
|
|
6444
6444
|
const c = /* @__PURE__ */ new Set();
|
|
6445
|
-
this.armature && this.armature.traverse((
|
|
6446
|
-
(
|
|
6445
|
+
this.armature && this.armature.traverse((L) => {
|
|
6446
|
+
(L.isBone || L.type === "Bone") && c.add(L.name);
|
|
6447
6447
|
});
|
|
6448
|
-
const g = /* @__PURE__ */ new Map(),
|
|
6449
|
-
if (c.has(
|
|
6450
|
-
return
|
|
6451
|
-
let
|
|
6452
|
-
if (c.has(
|
|
6453
|
-
return
|
|
6454
|
-
const
|
|
6455
|
-
if (
|
|
6456
|
-
if (
|
|
6448
|
+
const g = /* @__PURE__ */ new Map(), x = (L) => {
|
|
6449
|
+
if (c.has(L))
|
|
6450
|
+
return L;
|
|
6451
|
+
let I = L.replace(/^mixamorig/i, "").replace(/^CC_Base_/i, "").replace(/^RPM_/i, "");
|
|
6452
|
+
if (c.has(I))
|
|
6453
|
+
return I;
|
|
6454
|
+
const z = I.toLowerCase();
|
|
6455
|
+
if (z.includes("left") && z.includes("arm")) {
|
|
6456
|
+
if (z.includes("fore") || z.includes("lower")) {
|
|
6457
6457
|
if (c.has("LeftForeArm")) return "LeftForeArm";
|
|
6458
6458
|
if (c.has("LeftForearm")) return "LeftForearm";
|
|
6459
|
-
} else if (!
|
|
6459
|
+
} else if (!z.includes("fore") && !z.includes("hand") && c.has("LeftArm"))
|
|
6460
6460
|
return "LeftArm";
|
|
6461
6461
|
}
|
|
6462
|
-
if (
|
|
6463
|
-
if (
|
|
6462
|
+
if (z.includes("right") && z.includes("arm")) {
|
|
6463
|
+
if (z.includes("fore") || z.includes("lower")) {
|
|
6464
6464
|
if (c.has("RightForeArm")) return "RightForeArm";
|
|
6465
6465
|
if (c.has("RightForearm")) return "RightForearm";
|
|
6466
|
-
} else if (!
|
|
6466
|
+
} else if (!z.includes("fore") && !z.includes("hand") && c.has("RightArm"))
|
|
6467
6467
|
return "RightArm";
|
|
6468
6468
|
}
|
|
6469
|
-
if (
|
|
6469
|
+
if (z.includes("left") && z.includes("hand") && !z.includes("index") && !z.includes("thumb") && !z.includes("middle") && !z.includes("ring") && !z.includes("pinky") && c.has("LeftHand"))
|
|
6470
6470
|
return "LeftHand";
|
|
6471
|
-
if (
|
|
6471
|
+
if (z.includes("right") && z.includes("hand") && !z.includes("index") && !z.includes("thumb") && !z.includes("middle") && !z.includes("ring") && !z.includes("pinky") && c.has("RightHand"))
|
|
6472
6472
|
return "RightHand";
|
|
6473
|
-
if (
|
|
6473
|
+
if (z.includes("left") && (z.includes("shoulder") || z.includes("clavicle")) && c.has("LeftShoulder"))
|
|
6474
6474
|
return "LeftShoulder";
|
|
6475
|
-
if (
|
|
6475
|
+
if (z.includes("right") && (z.includes("shoulder") || z.includes("clavicle")) && c.has("RightShoulder"))
|
|
6476
6476
|
return "RightShoulder";
|
|
6477
|
-
const
|
|
6477
|
+
const Y = {
|
|
6478
6478
|
// Arm bones - exact matches
|
|
6479
6479
|
LeftArm: "LeftArm",
|
|
6480
6480
|
leftArm: "LeftArm",
|
|
@@ -6514,65 +6514,65 @@ class Be {
|
|
|
6514
6514
|
Root: "Hips",
|
|
6515
6515
|
root: "Hips"
|
|
6516
6516
|
};
|
|
6517
|
-
if (
|
|
6518
|
-
const
|
|
6519
|
-
if (c.has(
|
|
6520
|
-
return
|
|
6517
|
+
if (Y[I]) {
|
|
6518
|
+
const S = Y[I];
|
|
6519
|
+
if (c.has(S))
|
|
6520
|
+
return S;
|
|
6521
6521
|
}
|
|
6522
|
-
for (const
|
|
6523
|
-
if (
|
|
6524
|
-
return
|
|
6525
|
-
for (const
|
|
6526
|
-
const
|
|
6527
|
-
if ((
|
|
6528
|
-
return
|
|
6522
|
+
for (const S of c)
|
|
6523
|
+
if (S.toLowerCase() === z)
|
|
6524
|
+
return S;
|
|
6525
|
+
for (const S of c) {
|
|
6526
|
+
const F = S.toLowerCase();
|
|
6527
|
+
if ((z.includes("left") && F.includes("left") || z.includes("right") && F.includes("right")) && (z.includes("arm") && F.includes("arm") && !F.includes("fore") || z.includes("forearm") && F.includes("forearm") || z.includes("hand") && F.includes("hand") && !F.includes("index") && !F.includes("thumb") || z.includes("shoulder") && F.includes("shoulder")))
|
|
6528
|
+
return S;
|
|
6529
6529
|
}
|
|
6530
6530
|
return null;
|
|
6531
|
-
},
|
|
6532
|
-
d.tracks.forEach((
|
|
6533
|
-
const
|
|
6534
|
-
|
|
6535
|
-
}), console.log("=== Ready Player Me Animation Bone Analysis ==="), console.log("FBX bone names:", Array.from(
|
|
6536
|
-
const
|
|
6537
|
-
(
|
|
6531
|
+
}, f = /* @__PURE__ */ new Set();
|
|
6532
|
+
d.tracks.forEach((L) => {
|
|
6533
|
+
const I = L.name.split(".");
|
|
6534
|
+
f.add(I[0]);
|
|
6535
|
+
}), console.log("=== Ready Player Me Animation Bone Analysis ==="), console.log("FBX bone names:", Array.from(f).sort().join(", ")), console.log("Avatar skeleton bone names:", Array.from(c).sort().join(", "));
|
|
6536
|
+
const k = Array.from(f).filter(
|
|
6537
|
+
(L) => L.toLowerCase().includes("arm") || L.toLowerCase().includes("hand") || L.toLowerCase().includes("shoulder")
|
|
6538
6538
|
), O = Array.from(c).filter(
|
|
6539
|
-
(
|
|
6539
|
+
(L) => L.includes("Arm") || L.includes("Hand") || L.includes("Shoulder")
|
|
6540
6540
|
);
|
|
6541
|
-
console.log("FBX arm/hand/shoulder bones:",
|
|
6541
|
+
console.log("FBX arm/hand/shoulder bones:", k.sort().join(", ")), console.log("Avatar arm/hand/shoulder bones:", O.sort().join(", "));
|
|
6542
6542
|
const p = [], B = /* @__PURE__ */ new Set();
|
|
6543
|
-
if (d.tracks.forEach((
|
|
6544
|
-
const
|
|
6545
|
-
if (
|
|
6546
|
-
const
|
|
6547
|
-
|
|
6543
|
+
if (d.tracks.forEach((L) => {
|
|
6544
|
+
const z = L.name.replaceAll("mixamorig", "").split("."), Y = z[0], S = z[1], F = x(Y);
|
|
6545
|
+
if (F && S) {
|
|
6546
|
+
const X = `${F}.${S}`, Z = L.clone();
|
|
6547
|
+
Z.name = X, p.push(Z), Y !== F && g.set(Y, F);
|
|
6548
6548
|
} else
|
|
6549
|
-
B.add(
|
|
6549
|
+
B.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`);
|
|
6550
6550
|
}), B.size > 0 && console.warn(`⚠️ ${B.size} bone(s) could not be mapped:`, Array.from(B).sort().join(", ")), p.length > 0) {
|
|
6551
6551
|
d = new y.AnimationClip(d.name, d.duration, p), console.log(`✓ Created animation with ${p.length} mapped tracks (from ${d.tracks.length} original tracks)`), g.size > 0 && console.log(
|
|
6552
6552
|
`✓ Mapped ${g.size} bone(s):`,
|
|
6553
|
-
Array.from(g.entries()).map(([
|
|
6553
|
+
Array.from(g.entries()).map(([I, z]) => `${I}→${z}`).join(", ")
|
|
6554
6554
|
);
|
|
6555
|
-
const
|
|
6556
|
-
(
|
|
6555
|
+
const L = Array.from(g.values()).filter(
|
|
6556
|
+
(I) => I.includes("Arm") || I.includes("Hand") || I.includes("Shoulder")
|
|
6557
6557
|
);
|
|
6558
|
-
|
|
6558
|
+
L.length > 0 ? console.log(`✓ Arm bones mapped: ${L.join(", ")}`) : console.warn("⚠️ No arm bones were mapped! This may cause arm rigging issues.");
|
|
6559
6559
|
} else
|
|
6560
6560
|
console.error("❌ No tracks could be mapped! Animation may not work correctly.");
|
|
6561
|
-
const
|
|
6562
|
-
d.tracks.forEach((
|
|
6563
|
-
|
|
6564
|
-
const
|
|
6565
|
-
if (
|
|
6566
|
-
for (let
|
|
6567
|
-
|
|
6568
|
-
|
|
6569
|
-
} else
|
|
6561
|
+
const H = {};
|
|
6562
|
+
d.tracks.forEach((L) => {
|
|
6563
|
+
L.name = L.name.replaceAll("mixamorig", "");
|
|
6564
|
+
const I = L.name.split(".");
|
|
6565
|
+
if (I[1] === "position") {
|
|
6566
|
+
for (let z = 0; z < L.values.length; z++)
|
|
6567
|
+
L.values[z] = L.values[z] * s;
|
|
6568
|
+
H[L.name] = new y.Vector3(L.values[0], L.values[1], L.values[2]);
|
|
6569
|
+
} else I[1] === "quaternion" ? H[L.name] = new y.Quaternion(L.values[0], L.values[1], L.values[2], L.values[3]) : I[1] === "rotation" && (H[I[0] + ".quaternion"] = new y.Quaternion().setFromEuler(new y.Euler(L.values[0], L.values[1], L.values[2], "XYZ")).normalize());
|
|
6570
6570
|
});
|
|
6571
|
-
const
|
|
6572
|
-
|
|
6571
|
+
const v = { props: H };
|
|
6572
|
+
H["Hips.position"] && (H["Hips.position"].y < 0.5 ? v.lying = !0 : v.standing = !0), this.animClips.push({
|
|
6573
6573
|
url: t + "-" + i,
|
|
6574
6574
|
clip: d,
|
|
6575
|
-
pose:
|
|
6575
|
+
pose: v
|
|
6576
6576
|
}), this.playAnimation(t, e, n, i, s);
|
|
6577
6577
|
} else {
|
|
6578
6578
|
const d = "Animation " + t + " (ndx=" + i + ") not found";
|
|
@@ -6663,9 +6663,9 @@ class Be {
|
|
|
6663
6663
|
const h = l.ts[0], u = l.ts[l.ts.length - 1] - h;
|
|
6664
6664
|
if (e * 1e3 - u > 0) {
|
|
6665
6665
|
const d = [];
|
|
6666
|
-
for (let
|
|
6667
|
-
const c = o.template?.rescale || d.map((
|
|
6668
|
-
l.ts = l.ts.map((
|
|
6666
|
+
for (let x = 1; x < l.ts.length; x++) d.push(l.ts[x] - l.ts[x - 1]);
|
|
6667
|
+
const c = o.template?.rescale || d.map((x) => x / u), g = e * 1e3 - u;
|
|
6668
|
+
l.ts = l.ts.map((x, f, k) => f === 0 ? h : k[f - 1] + d[f - 1] + c[f - 1] * g);
|
|
6669
6669
|
} else {
|
|
6670
6670
|
const d = e * 1e3 / u;
|
|
6671
6671
|
l.ts = l.ts.map((c) => h + d * (c - h));
|
|
@@ -6700,32 +6700,32 @@ class Be {
|
|
|
6700
6700
|
ikSolve(t, e = null, n = !1, i = null) {
|
|
6701
6701
|
const s = new y.Vector3(), o = new y.Vector3(), l = new y.Vector3(), h = new y.Vector3(), r = new y.Quaternion(), u = new y.Vector3(), a = new y.Vector3(), d = new y.Vector3(), c = this.ikMesh.getObjectByName(t.root);
|
|
6702
6702
|
c.position.setFromMatrixPosition(this.armature.getObjectByName(t.root).matrixWorld), c.quaternion.setFromRotationMatrix(this.armature.getObjectByName(t.root).matrixWorld), e && n && e.applyQuaternion(this.armature.quaternion).add(c.position);
|
|
6703
|
-
const g = this.ikMesh.getObjectByName(t.effector),
|
|
6704
|
-
|
|
6705
|
-
|
|
6703
|
+
const g = this.ikMesh.getObjectByName(t.effector), x = t.links;
|
|
6704
|
+
x.forEach((k) => {
|
|
6705
|
+
k.bone = this.ikMesh.getObjectByName(k.link), k.bone.quaternion.copy(this.getPoseTemplateProp(k.link + ".quaternion"));
|
|
6706
6706
|
}), c.updateMatrixWorld(!0);
|
|
6707
|
-
const
|
|
6707
|
+
const f = t.iterations || 10;
|
|
6708
6708
|
if (e)
|
|
6709
|
-
for (let
|
|
6709
|
+
for (let k = 0; k < f; k++) {
|
|
6710
6710
|
let O = !1;
|
|
6711
|
-
for (let p = 0, B =
|
|
6712
|
-
const
|
|
6713
|
-
|
|
6714
|
-
let
|
|
6715
|
-
|
|
6716
|
-
|
|
6717
|
-
|
|
6718
|
-
|
|
6711
|
+
for (let p = 0, B = x.length; p < B; p++) {
|
|
6712
|
+
const H = x[p].bone;
|
|
6713
|
+
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();
|
|
6714
|
+
let v = s.dot(l);
|
|
6715
|
+
v > 1 ? v = 1 : v < -1 && (v = -1), v = Math.acos(v), !(v < 1e-5) && (x[p].minAngle !== void 0 && v < x[p].minAngle && (v = x[p].minAngle), x[p].maxAngle !== void 0 && v > x[p].maxAngle && (v = x[p].maxAngle), a.crossVectors(l, s), a.normalize(), J.setFromAxisAngle(a, v), H.quaternion.multiply(J), H.rotation.setFromVector3(d.setFromEuler(H.rotation).clamp(new y.Vector3(
|
|
6716
|
+
x[p].minx !== void 0 ? x[p].minx : -1 / 0,
|
|
6717
|
+
x[p].miny !== void 0 ? x[p].miny : -1 / 0,
|
|
6718
|
+
x[p].minz !== void 0 ? x[p].minz : -1 / 0
|
|
6719
6719
|
), new y.Vector3(
|
|
6720
|
-
|
|
6721
|
-
|
|
6722
|
-
|
|
6723
|
-
))),
|
|
6720
|
+
x[p].maxx !== void 0 ? x[p].maxx : 1 / 0,
|
|
6721
|
+
x[p].maxy !== void 0 ? x[p].maxy : 1 / 0,
|
|
6722
|
+
x[p].maxz !== void 0 ? x[p].maxz : 1 / 0
|
|
6723
|
+
))), H.updateMatrixWorld(!0), O = !0);
|
|
6724
6724
|
}
|
|
6725
6725
|
if (!O) break;
|
|
6726
6726
|
}
|
|
6727
|
-
i &&
|
|
6728
|
-
this.poseTarget.props[
|
|
6727
|
+
i && x.forEach((k) => {
|
|
6728
|
+
this.poseTarget.props[k.link + ".quaternion"].copy(k.bone.quaternion), this.poseTarget.props[k.link + ".quaternion"].t = this.animClock, this.poseTarget.props[k.link + ".quaternion"].d = i;
|
|
6729
6729
|
});
|
|
6730
6730
|
}
|
|
6731
6731
|
/**
|
|
@@ -6755,7 +6755,7 @@ const Ie = {
|
|
|
6755
6755
|
josh: "VR6AewLTigWG4xSOukaG"
|
|
6756
6756
|
// Male, American
|
|
6757
6757
|
}
|
|
6758
|
-
},
|
|
6758
|
+
}, Te = {
|
|
6759
6759
|
defaultVoice: "aura-2-thalia-en",
|
|
6760
6760
|
// Thalia (Female, English)
|
|
6761
6761
|
voices: {
|
|
@@ -6775,7 +6775,7 @@ const Ie = {
|
|
|
6775
6775
|
// Male, English - Powerful
|
|
6776
6776
|
}
|
|
6777
6777
|
};
|
|
6778
|
-
function
|
|
6778
|
+
function Ee() {
|
|
6779
6779
|
return {
|
|
6780
6780
|
service: "elevenlabs",
|
|
6781
6781
|
endpoint: Ie.endpoint,
|
|
@@ -6784,17 +6784,17 @@ function Me() {
|
|
|
6784
6784
|
voices: Ie.voices
|
|
6785
6785
|
};
|
|
6786
6786
|
}
|
|
6787
|
-
function
|
|
6788
|
-
const
|
|
6789
|
-
return Object.entries(
|
|
6787
|
+
function wt() {
|
|
6788
|
+
const V = Ee(), t = [];
|
|
6789
|
+
return Object.entries(V.voices).forEach(([e, n]) => {
|
|
6790
6790
|
t.push({
|
|
6791
6791
|
value: n,
|
|
6792
|
-
label: `${e.charAt(0).toUpperCase() + e.slice(1)} (${
|
|
6792
|
+
label: `${e.charAt(0).toUpperCase() + e.slice(1)} (${V.service})`
|
|
6793
6793
|
});
|
|
6794
6794
|
}), t;
|
|
6795
6795
|
}
|
|
6796
|
-
const Ve =
|
|
6797
|
-
avatarUrl:
|
|
6796
|
+
const Ve = Me(({
|
|
6797
|
+
avatarUrl: V = "/avatars/brunette.glb",
|
|
6798
6798
|
avatarBody: t = "F",
|
|
6799
6799
|
mood: e = "neutral",
|
|
6800
6800
|
ttsLang: n = "en",
|
|
@@ -6812,264 +6812,264 @@ const Ve = He(({
|
|
|
6812
6812
|
onError: c = () => {
|
|
6813
6813
|
},
|
|
6814
6814
|
className: g = "",
|
|
6815
|
-
style:
|
|
6816
|
-
animations:
|
|
6817
|
-
},
|
|
6818
|
-
const O =
|
|
6819
|
-
|
|
6820
|
-
|
|
6821
|
-
}, [
|
|
6815
|
+
style: x = {},
|
|
6816
|
+
animations: f = {}
|
|
6817
|
+
}, k) => {
|
|
6818
|
+
const O = W(null), p = W(null), B = W(r), H = W(null), v = W(null), L = W(!1), I = W({ remainingText: null, originalText: null, options: null }), z = W([]), Y = W(0), [S, F] = pe(!0), [X, Z] = pe(null), [ne, le] = pe(!1), [ge, de] = pe(!1);
|
|
6819
|
+
ce(() => {
|
|
6820
|
+
L.current = ge;
|
|
6821
|
+
}, [ge]), ce(() => {
|
|
6822
6822
|
B.current = r;
|
|
6823
6823
|
}, [r]);
|
|
6824
|
-
const
|
|
6824
|
+
const $ = Ee(), be = i || $.service;
|
|
6825
6825
|
let j;
|
|
6826
|
-
|
|
6826
|
+
be === "browser" ? j = {
|
|
6827
6827
|
service: "browser",
|
|
6828
6828
|
endpoint: "",
|
|
6829
6829
|
apiKey: null,
|
|
6830
6830
|
defaultVoice: "Google US English"
|
|
6831
|
-
} :
|
|
6831
|
+
} : be === "elevenlabs" ? j = {
|
|
6832
6832
|
service: "elevenlabs",
|
|
6833
6833
|
endpoint: "https://api.elevenlabs.io/v1/text-to-speech",
|
|
6834
|
-
apiKey: o ||
|
|
6835
|
-
defaultVoice: s ||
|
|
6836
|
-
voices:
|
|
6837
|
-
} :
|
|
6834
|
+
apiKey: o || $.apiKey,
|
|
6835
|
+
defaultVoice: s || $.defaultVoice || Ie.defaultVoice,
|
|
6836
|
+
voices: $.voices || Ie.voices
|
|
6837
|
+
} : be === "deepgram" ? j = {
|
|
6838
6838
|
service: "deepgram",
|
|
6839
6839
|
endpoint: "https://api.deepgram.com/v1/speak",
|
|
6840
|
-
apiKey: o ||
|
|
6841
|
-
defaultVoice: s ||
|
|
6842
|
-
voices:
|
|
6840
|
+
apiKey: o || $.apiKey,
|
|
6841
|
+
defaultVoice: s || $.defaultVoice || Te.defaultVoice,
|
|
6842
|
+
voices: $.voices || Te.voices
|
|
6843
6843
|
} : j = {
|
|
6844
|
-
|
|
6844
|
+
...$,
|
|
6845
6845
|
// Override API key if provided via props
|
|
6846
|
-
apiKey: o !== null ? o :
|
|
6846
|
+
apiKey: o !== null ? o : $.apiKey
|
|
6847
6847
|
};
|
|
6848
|
-
const
|
|
6849
|
-
url:
|
|
6848
|
+
const b = {
|
|
6849
|
+
url: V,
|
|
6850
6850
|
body: t,
|
|
6851
6851
|
avatarMood: e,
|
|
6852
|
-
ttsLang:
|
|
6852
|
+
ttsLang: be === "browser" ? "en-US" : n,
|
|
6853
6853
|
ttsVoice: s || j.defaultVoice,
|
|
6854
6854
|
lipsyncLang: "en",
|
|
6855
6855
|
showFullAvatar: r,
|
|
6856
6856
|
bodyMovement: l,
|
|
6857
6857
|
movementIntensity: h
|
|
6858
|
-
},
|
|
6858
|
+
}, R = {
|
|
6859
6859
|
ttsEndpoint: j.endpoint,
|
|
6860
6860
|
ttsApikey: j.apiKey,
|
|
6861
|
-
ttsService:
|
|
6861
|
+
ttsService: be,
|
|
6862
6862
|
lipsyncModules: ["en"],
|
|
6863
6863
|
cameraView: u
|
|
6864
|
-
},
|
|
6864
|
+
}, M = N(async () => {
|
|
6865
6865
|
if (!(!O.current || p.current))
|
|
6866
6866
|
try {
|
|
6867
|
-
if (
|
|
6868
|
-
if (
|
|
6869
|
-
const
|
|
6870
|
-
d(
|
|
6867
|
+
if (F(!0), Z(null), p.current = new Be(O.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), f && Object.keys(f).length > 0 && (p.current.customAnimations = f), await p.current.showAvatar(b, (_) => {
|
|
6868
|
+
if (_.lengthComputable) {
|
|
6869
|
+
const te = Math.min(100, Math.round(_.loaded / _.total * 100));
|
|
6870
|
+
d(te);
|
|
6871
6871
|
}
|
|
6872
|
-
}), await new Promise((
|
|
6873
|
-
const
|
|
6874
|
-
p.current.lipsync && Object.keys(p.current.lipsync).length > 0 ?
|
|
6872
|
+
}), await new Promise((_) => {
|
|
6873
|
+
const te = () => {
|
|
6874
|
+
p.current.lipsync && Object.keys(p.current.lipsync).length > 0 ? _() : setTimeout(te, 100);
|
|
6875
6875
|
};
|
|
6876
|
-
|
|
6876
|
+
te();
|
|
6877
6877
|
}), p.current && p.current.setShowFullAvatar)
|
|
6878
6878
|
try {
|
|
6879
6879
|
p.current.setShowFullAvatar(r);
|
|
6880
|
-
} catch (
|
|
6881
|
-
console.warn("Error setting full body mode on initialization:",
|
|
6880
|
+
} catch (_) {
|
|
6881
|
+
console.warn("Error setting full body mode on initialization:", _);
|
|
6882
6882
|
}
|
|
6883
|
-
p.current && p.current.controls && (p.current.controls.enableRotate = !1, p.current.controls.enableZoom = !1, p.current.controls.enablePan = !1, p.current.controls.enableDamping = !1, p.current.controls.update()),
|
|
6884
|
-
const
|
|
6883
|
+
p.current && p.current.controls && (p.current.controls.enableRotate = !1, p.current.controls.enableZoom = !1, p.current.controls.enablePan = !1, p.current.controls.enableDamping = !1, p.current.controls.update()), F(!1), le(!0), a(p.current);
|
|
6884
|
+
const U = () => {
|
|
6885
6885
|
document.visibilityState === "visible" ? p.current?.start() : p.current?.stop();
|
|
6886
6886
|
};
|
|
6887
|
-
return document.addEventListener("visibilitychange",
|
|
6888
|
-
document.removeEventListener("visibilitychange",
|
|
6887
|
+
return document.addEventListener("visibilitychange", U), () => {
|
|
6888
|
+
document.removeEventListener("visibilitychange", U);
|
|
6889
6889
|
};
|
|
6890
6890
|
} catch (w) {
|
|
6891
|
-
console.error("Error initializing TalkingHead:", w),
|
|
6891
|
+
console.error("Error initializing TalkingHead:", w), Z(w.message || "Failed to initialize avatar"), F(!1), c(w);
|
|
6892
6892
|
}
|
|
6893
|
-
}, [
|
|
6894
|
-
|
|
6893
|
+
}, [V, t, e, n, i, s, o, r, l, h, u]);
|
|
6894
|
+
ce(() => (M(), () => {
|
|
6895
6895
|
p.current && (p.current.stop(), p.current.dispose(), p.current = null);
|
|
6896
|
-
}), [
|
|
6896
|
+
}), [M]), ce(() => {
|
|
6897
6897
|
if (!O.current || !p.current) return;
|
|
6898
|
-
const w = new ResizeObserver((
|
|
6899
|
-
for (const
|
|
6898
|
+
const w = new ResizeObserver((_) => {
|
|
6899
|
+
for (const te of _)
|
|
6900
6900
|
p.current && p.current.onResize && p.current.onResize();
|
|
6901
6901
|
});
|
|
6902
6902
|
w.observe(O.current);
|
|
6903
|
-
const
|
|
6903
|
+
const U = () => {
|
|
6904
6904
|
p.current && p.current.onResize && p.current.onResize();
|
|
6905
6905
|
};
|
|
6906
|
-
return window.addEventListener("resize",
|
|
6907
|
-
w.disconnect(), window.removeEventListener("resize",
|
|
6906
|
+
return window.addEventListener("resize", U), () => {
|
|
6907
|
+
w.disconnect(), window.removeEventListener("resize", U);
|
|
6908
6908
|
};
|
|
6909
|
-
}, [
|
|
6910
|
-
const
|
|
6909
|
+
}, [ne]);
|
|
6910
|
+
const E = N(async () => {
|
|
6911
6911
|
if (p.current && p.current.audioCtx)
|
|
6912
6912
|
try {
|
|
6913
6913
|
(p.current.audioCtx.state === "suspended" || p.current.audioCtx.state === "interrupted") && (await p.current.audioCtx.resume(), console.log("Audio context resumed"));
|
|
6914
6914
|
} catch (w) {
|
|
6915
6915
|
console.warn("Failed to resume audio context:", w);
|
|
6916
6916
|
}
|
|
6917
|
-
}, []),
|
|
6918
|
-
if (p.current &&
|
|
6917
|
+
}, []), D = N(async (w, U = {}) => {
|
|
6918
|
+
if (p.current && ne)
|
|
6919
6919
|
try {
|
|
6920
|
-
|
|
6921
|
-
const
|
|
6922
|
-
|
|
6923
|
-
const
|
|
6924
|
-
...
|
|
6925
|
-
lipsyncLang:
|
|
6920
|
+
v.current && (clearInterval(v.current), v.current = null), H.current = { text: w, options: U }, I.current = { remainingText: null, originalText: null, options: null };
|
|
6921
|
+
const _ = /[!\.\?\n\p{Extended_Pictographic}]/ug, te = w.split(_).map((A) => A.trim()).filter((A) => A.length > 0);
|
|
6922
|
+
z.current = te, Y.current = 0, de(!1), L.current = !1, await E();
|
|
6923
|
+
const me = {
|
|
6924
|
+
...U,
|
|
6925
|
+
lipsyncLang: U.lipsyncLang || b.lipsyncLang || "en"
|
|
6926
6926
|
};
|
|
6927
|
-
if (
|
|
6928
|
-
const
|
|
6929
|
-
let
|
|
6930
|
-
const
|
|
6931
|
-
let
|
|
6932
|
-
|
|
6933
|
-
if (
|
|
6927
|
+
if (U.onSpeechEnd && p.current) {
|
|
6928
|
+
const A = p.current;
|
|
6929
|
+
let P = null, K = 0;
|
|
6930
|
+
const ie = 1200;
|
|
6931
|
+
let se = !1;
|
|
6932
|
+
P = setInterval(() => {
|
|
6933
|
+
if (K++, L.current)
|
|
6934
6934
|
return;
|
|
6935
|
-
if (
|
|
6936
|
-
if (
|
|
6937
|
-
|
|
6935
|
+
if (K > ie) {
|
|
6936
|
+
if (P && (clearInterval(P), P = null, v.current = null), !se && !L.current) {
|
|
6937
|
+
se = !0;
|
|
6938
6938
|
try {
|
|
6939
|
-
|
|
6939
|
+
U.onSpeechEnd();
|
|
6940
6940
|
} catch (Ne) {
|
|
6941
6941
|
console.error("Error in onSpeechEnd callback (timeout):", Ne);
|
|
6942
6942
|
}
|
|
6943
6943
|
}
|
|
6944
6944
|
return;
|
|
6945
6945
|
}
|
|
6946
|
-
const
|
|
6947
|
-
|
|
6948
|
-
if (
|
|
6949
|
-
|
|
6946
|
+
const oe = !A.speechQueue || A.speechQueue.length === 0, we = !A.audioPlaylist || A.audioPlaylist.length === 0;
|
|
6947
|
+
A && A.isSpeaking === !1 && oe && we && A.isAudioPlaying === !1 && !se && !L.current && setTimeout(() => {
|
|
6948
|
+
if (A && !L.current && A.isSpeaking === !1 && (!A.speechQueue || A.speechQueue.length === 0) && (!A.audioPlaylist || A.audioPlaylist.length === 0) && A.isAudioPlaying === !1 && !se && !L.current) {
|
|
6949
|
+
se = !0, P && (clearInterval(P), P = null, v.current = null);
|
|
6950
6950
|
try {
|
|
6951
|
-
|
|
6951
|
+
U.onSpeechEnd();
|
|
6952
6952
|
} catch (Ze) {
|
|
6953
6953
|
console.error("Error in onSpeechEnd callback:", Ze);
|
|
6954
6954
|
}
|
|
6955
6955
|
}
|
|
6956
6956
|
}, 100);
|
|
6957
|
-
}, 100),
|
|
6957
|
+
}, 100), v.current = P;
|
|
6958
6958
|
}
|
|
6959
|
-
p.current.lipsync && Object.keys(p.current.lipsync).length > 0 ? (p.current.setSlowdownRate && p.current.setSlowdownRate(1.05), p.current.speakText(w,
|
|
6960
|
-
await
|
|
6959
|
+
p.current.lipsync && Object.keys(p.current.lipsync).length > 0 ? (p.current.setSlowdownRate && p.current.setSlowdownRate(1.05), p.current.speakText(w, me)) : setTimeout(async () => {
|
|
6960
|
+
await E(), p.current && p.current.lipsync && (p.current.setSlowdownRate && p.current.setSlowdownRate(1.05), p.current.speakText(w, me));
|
|
6961
6961
|
}, 100);
|
|
6962
|
-
} catch (
|
|
6963
|
-
console.error("Error speaking text:",
|
|
6962
|
+
} catch (_) {
|
|
6963
|
+
console.error("Error speaking text:", _), Z(_.message || "Failed to speak text");
|
|
6964
6964
|
}
|
|
6965
|
-
}, [
|
|
6966
|
-
p.current && (p.current.stopSpeaking(), p.current.setSlowdownRate && p.current.setSlowdownRate(1),
|
|
6967
|
-
}, []),
|
|
6965
|
+
}, [ne, E, b.lipsyncLang]), ee = N(() => {
|
|
6966
|
+
p.current && (p.current.stopSpeaking(), p.current.setSlowdownRate && p.current.setSlowdownRate(1), H.current = null, de(!1));
|
|
6967
|
+
}, []), Q = N(() => {
|
|
6968
6968
|
if (p.current && p.current.pauseSpeaking) {
|
|
6969
6969
|
const w = p.current;
|
|
6970
6970
|
if (w.isSpeaking || w.audioPlaylist && w.audioPlaylist.length > 0 || w.speechQueue && w.speechQueue.length > 0) {
|
|
6971
|
-
|
|
6972
|
-
let
|
|
6973
|
-
if (
|
|
6974
|
-
const
|
|
6975
|
-
if (
|
|
6976
|
-
const
|
|
6977
|
-
|
|
6971
|
+
v.current && (clearInterval(v.current), v.current = null);
|
|
6972
|
+
let _ = "";
|
|
6973
|
+
if (H.current && z.current.length > 0) {
|
|
6974
|
+
const te = z.current.length, me = w.speechQueue ? w.speechQueue.filter((ie) => ie && ie.text && Array.isArray(ie.text) && ie.text.length > 0).length : 0, A = w.audioPlaylist && w.audioPlaylist.length > 0, P = me + (A ? 1 : 0), K = te - P;
|
|
6975
|
+
if (P > 0 && K < te && (_ = z.current.slice(K).join(". ").trim(), !_ && me > 0 && w.speechQueue)) {
|
|
6976
|
+
const se = w.speechQueue.filter((oe) => oe && oe.text && Array.isArray(oe.text) && oe.text.length > 0).map((oe) => oe.text.map((we) => we.word || "").filter((we) => we.length > 0).join(" ")).filter((oe) => oe.length > 0).join(" ");
|
|
6977
|
+
se && se.trim() && (_ = se.trim());
|
|
6978
6978
|
}
|
|
6979
6979
|
}
|
|
6980
|
-
|
|
6981
|
-
remainingText:
|
|
6982
|
-
originalText:
|
|
6983
|
-
options:
|
|
6984
|
-
}), w.speechQueue && (w.speechQueue.length = 0), p.current.pauseSpeaking(),
|
|
6980
|
+
H.current && (I.current = {
|
|
6981
|
+
remainingText: _ || null,
|
|
6982
|
+
originalText: H.current.text,
|
|
6983
|
+
options: H.current.options
|
|
6984
|
+
}), w.speechQueue && (w.speechQueue.length = 0), p.current.pauseSpeaking(), L.current = !0, de(!0);
|
|
6985
6985
|
}
|
|
6986
6986
|
}
|
|
6987
|
-
}, []),
|
|
6988
|
-
if (!p.current || !
|
|
6987
|
+
}, []), q = N(async () => {
|
|
6988
|
+
if (!p.current || !ge)
|
|
6989
6989
|
return;
|
|
6990
|
-
let w = "",
|
|
6991
|
-
if (
|
|
6992
|
-
w =
|
|
6993
|
-
else if (
|
|
6994
|
-
w =
|
|
6990
|
+
let w = "", U = {};
|
|
6991
|
+
if (I.current && I.current.remainingText)
|
|
6992
|
+
w = I.current.remainingText, U = I.current.options || {}, I.current = { remainingText: null, originalText: null, options: null };
|
|
6993
|
+
else if (H.current && H.current.text)
|
|
6994
|
+
w = H.current.text, U = H.current.options || {};
|
|
6995
6995
|
else {
|
|
6996
|
-
console.warn("Resume called but no paused speech found"),
|
|
6996
|
+
console.warn("Resume called but no paused speech found"), de(!1), L.current = !1;
|
|
6997
6997
|
return;
|
|
6998
6998
|
}
|
|
6999
|
-
|
|
7000
|
-
const
|
|
7001
|
-
...
|
|
7002
|
-
lipsyncLang:
|
|
6999
|
+
de(!1), L.current = !1, await E();
|
|
7000
|
+
const _ = {
|
|
7001
|
+
...U,
|
|
7002
|
+
lipsyncLang: U.lipsyncLang || b.lipsyncLang || "en"
|
|
7003
7003
|
};
|
|
7004
7004
|
try {
|
|
7005
|
-
await
|
|
7006
|
-
} catch (
|
|
7007
|
-
console.error("Error resuming speech:",
|
|
7005
|
+
await D(w, _);
|
|
7006
|
+
} catch (te) {
|
|
7007
|
+
console.error("Error resuming speech:", te), de(!1), L.current = !1;
|
|
7008
7008
|
}
|
|
7009
|
-
}, [
|
|
7009
|
+
}, [E, ge, D, b]), Ae = N((w) => {
|
|
7010
7010
|
p.current && p.current.setMood(w);
|
|
7011
|
-
}, []),
|
|
7011
|
+
}, []), Se = N((w) => {
|
|
7012
7012
|
p.current && p.current.setSlowdownRate && p.current.setSlowdownRate(w);
|
|
7013
|
-
}, []),
|
|
7013
|
+
}, []), Le = N((w, U = !1) => {
|
|
7014
7014
|
if (p.current && p.current.playAnimation) {
|
|
7015
|
-
if (
|
|
7015
|
+
if (f && f[w] && (w = f[w]), p.current.setShowFullAvatar)
|
|
7016
7016
|
try {
|
|
7017
7017
|
p.current.setShowFullAvatar(B.current);
|
|
7018
|
-
} catch (
|
|
7019
|
-
console.warn("Error setting full body mode:",
|
|
7018
|
+
} catch (te) {
|
|
7019
|
+
console.warn("Error setting full body mode:", te);
|
|
7020
7020
|
}
|
|
7021
7021
|
if (w.includes("."))
|
|
7022
7022
|
try {
|
|
7023
|
-
p.current.playAnimation(w, null, 10, 0, 0.01,
|
|
7024
|
-
} catch (
|
|
7025
|
-
console.warn(`Failed to play ${w}:`,
|
|
7023
|
+
p.current.playAnimation(w, null, 10, 0, 0.01, U);
|
|
7024
|
+
} catch (te) {
|
|
7025
|
+
console.warn(`Failed to play ${w}:`, te);
|
|
7026
7026
|
try {
|
|
7027
7027
|
p.current.setBodyMovement("idle");
|
|
7028
|
-
} catch (
|
|
7029
|
-
console.warn("Fallback animation also failed:",
|
|
7028
|
+
} catch (me) {
|
|
7029
|
+
console.warn("Fallback animation also failed:", me);
|
|
7030
7030
|
}
|
|
7031
7031
|
}
|
|
7032
7032
|
else {
|
|
7033
|
-
const
|
|
7034
|
-
let
|
|
7035
|
-
for (const
|
|
7033
|
+
const te = [".fbx", ".glb", ".gltf"];
|
|
7034
|
+
let me = !1;
|
|
7035
|
+
for (const A of te)
|
|
7036
7036
|
try {
|
|
7037
|
-
p.current.playAnimation(w +
|
|
7037
|
+
p.current.playAnimation(w + A, null, 10, 0, 0.01, U), me = !0;
|
|
7038
7038
|
break;
|
|
7039
7039
|
} catch {
|
|
7040
7040
|
}
|
|
7041
|
-
if (!
|
|
7041
|
+
if (!me) {
|
|
7042
7042
|
console.warn("Animation not found:", w);
|
|
7043
7043
|
try {
|
|
7044
7044
|
p.current.setBodyMovement("idle");
|
|
7045
|
-
} catch (
|
|
7046
|
-
console.warn("Fallback animation also failed:",
|
|
7045
|
+
} catch (A) {
|
|
7046
|
+
console.warn("Fallback animation also failed:", A);
|
|
7047
7047
|
}
|
|
7048
7048
|
}
|
|
7049
7049
|
}
|
|
7050
7050
|
}
|
|
7051
|
-
}, [
|
|
7051
|
+
}, [f]), ke = N(() => {
|
|
7052
7052
|
p.current && p.current.onResize && p.current.onResize();
|
|
7053
7053
|
}, []);
|
|
7054
|
-
return
|
|
7055
|
-
speakText:
|
|
7056
|
-
stopSpeaking:
|
|
7057
|
-
pauseSpeaking:
|
|
7058
|
-
resumeSpeaking:
|
|
7059
|
-
resumeAudioContext:
|
|
7060
|
-
setMood:
|
|
7061
|
-
setTimingAdjustment:
|
|
7062
|
-
playAnimation:
|
|
7063
|
-
isReady:
|
|
7064
|
-
isPaused:
|
|
7054
|
+
return Fe(k, () => ({
|
|
7055
|
+
speakText: D,
|
|
7056
|
+
stopSpeaking: ee,
|
|
7057
|
+
pauseSpeaking: Q,
|
|
7058
|
+
resumeSpeaking: q,
|
|
7059
|
+
resumeAudioContext: E,
|
|
7060
|
+
setMood: Ae,
|
|
7061
|
+
setTimingAdjustment: Se,
|
|
7062
|
+
playAnimation: Le,
|
|
7063
|
+
isReady: ne,
|
|
7064
|
+
isPaused: ge,
|
|
7065
7065
|
talkingHead: p.current,
|
|
7066
|
-
handleResize:
|
|
7066
|
+
handleResize: ke,
|
|
7067
7067
|
setBodyMovement: (w) => {
|
|
7068
7068
|
if (p.current && p.current.setShowFullAvatar && p.current.setBodyMovement)
|
|
7069
7069
|
try {
|
|
7070
7070
|
p.current.setShowFullAvatar(B.current), p.current.setBodyMovement(w);
|
|
7071
|
-
} catch (
|
|
7072
|
-
console.warn("Error setting body movement:",
|
|
7071
|
+
} catch (U) {
|
|
7072
|
+
console.warn("Error setting body movement:", U);
|
|
7073
7073
|
}
|
|
7074
7074
|
},
|
|
7075
7075
|
setMovementIntensity: (w) => p.current?.setMovementIntensity(w),
|
|
@@ -7085,8 +7085,8 @@ const Ve = He(({
|
|
|
7085
7085
|
if (p.current && p.current.setShowFullAvatar && p.current.playReaction)
|
|
7086
7086
|
try {
|
|
7087
7087
|
p.current.setShowFullAvatar(B.current), p.current.playReaction(w);
|
|
7088
|
-
} catch (
|
|
7089
|
-
console.warn("Error playing reaction:",
|
|
7088
|
+
} catch (U) {
|
|
7089
|
+
console.warn("Error playing reaction:", U);
|
|
7090
7090
|
}
|
|
7091
7091
|
},
|
|
7092
7092
|
playCelebration: () => {
|
|
@@ -7101,8 +7101,8 @@ const Ve = He(({
|
|
|
7101
7101
|
if (p.current && p.current.setShowFullAvatar)
|
|
7102
7102
|
try {
|
|
7103
7103
|
B.current = w, p.current.setShowFullAvatar(w);
|
|
7104
|
-
} catch (
|
|
7105
|
-
console.warn("Error setting showFullAvatar:",
|
|
7104
|
+
} catch (U) {
|
|
7105
|
+
console.warn("Error setting showFullAvatar:", U);
|
|
7106
7106
|
}
|
|
7107
7107
|
},
|
|
7108
7108
|
lockAvatarPosition: () => {
|
|
@@ -7129,10 +7129,10 @@ const Ve = He(({
|
|
|
7129
7129
|
width: "100%",
|
|
7130
7130
|
height: "100%",
|
|
7131
7131
|
position: "relative",
|
|
7132
|
-
...
|
|
7132
|
+
...x
|
|
7133
7133
|
},
|
|
7134
7134
|
children: [
|
|
7135
|
-
/* @__PURE__ */
|
|
7135
|
+
/* @__PURE__ */ ye(
|
|
7136
7136
|
"div",
|
|
7137
7137
|
{
|
|
7138
7138
|
ref: O,
|
|
@@ -7144,7 +7144,7 @@ const Ve = He(({
|
|
|
7144
7144
|
}
|
|
7145
7145
|
}
|
|
7146
7146
|
),
|
|
7147
|
-
|
|
7147
|
+
S && /* @__PURE__ */ ye("div", { className: "loading-overlay", style: {
|
|
7148
7148
|
position: "absolute",
|
|
7149
7149
|
top: "50%",
|
|
7150
7150
|
left: "50%",
|
|
@@ -7153,7 +7153,7 @@ const Ve = He(({
|
|
|
7153
7153
|
fontSize: "18px",
|
|
7154
7154
|
zIndex: 10
|
|
7155
7155
|
}, children: "Loading avatar..." }),
|
|
7156
|
-
|
|
7156
|
+
X && /* @__PURE__ */ ye("div", { className: "error-overlay", style: {
|
|
7157
7157
|
position: "absolute",
|
|
7158
7158
|
top: "50%",
|
|
7159
7159
|
left: "50%",
|
|
@@ -7164,14 +7164,14 @@ const Ve = He(({
|
|
|
7164
7164
|
zIndex: 10,
|
|
7165
7165
|
padding: "20px",
|
|
7166
7166
|
borderRadius: "8px"
|
|
7167
|
-
}, children:
|
|
7167
|
+
}, children: X })
|
|
7168
7168
|
]
|
|
7169
7169
|
}
|
|
7170
7170
|
);
|
|
7171
7171
|
});
|
|
7172
7172
|
Ve.displayName = "TalkingHeadAvatar";
|
|
7173
|
-
const pt =
|
|
7174
|
-
text:
|
|
7173
|
+
const pt = Me(({
|
|
7174
|
+
text: V = "Hello! I'm a talking avatar. How are you today?",
|
|
7175
7175
|
onLoading: t = () => {
|
|
7176
7176
|
},
|
|
7177
7177
|
onError: e = () => {
|
|
@@ -7182,22 +7182,22 @@ const pt = He(({
|
|
|
7182
7182
|
style: s = {},
|
|
7183
7183
|
avatarConfig: o = {}
|
|
7184
7184
|
}, l) => {
|
|
7185
|
-
const h =
|
|
7185
|
+
const h = W(null), r = W(null), [u, a] = pe(!0), [d, c] = pe(null), [g, x] = pe(!1), f = Ee(), k = o.ttsService || f.service, O = k === "browser" ? {
|
|
7186
7186
|
endpoint: "",
|
|
7187
7187
|
apiKey: null,
|
|
7188
7188
|
defaultVoice: "Google US English"
|
|
7189
7189
|
} : {
|
|
7190
|
-
...
|
|
7190
|
+
...f,
|
|
7191
7191
|
// Override API key if provided via avatarConfig
|
|
7192
|
-
apiKey: o.ttsApiKey !== void 0 && o.ttsApiKey !== null ? o.ttsApiKey :
|
|
7192
|
+
apiKey: o.ttsApiKey !== void 0 && o.ttsApiKey !== null ? o.ttsApiKey : f.apiKey,
|
|
7193
7193
|
// Override endpoint for ElevenLabs if service is explicitly set
|
|
7194
|
-
endpoint:
|
|
7194
|
+
endpoint: k === "elevenlabs" && o.ttsApiKey ? "https://api.elevenlabs.io/v1/text-to-speech" : f.endpoint
|
|
7195
7195
|
}, p = {
|
|
7196
7196
|
url: "/avatars/brunette.glb",
|
|
7197
7197
|
// Use brunette avatar (working glTF file)
|
|
7198
7198
|
body: "F",
|
|
7199
7199
|
avatarMood: "neutral",
|
|
7200
|
-
ttsLang:
|
|
7200
|
+
ttsLang: k === "browser" ? "en-US" : "en",
|
|
7201
7201
|
ttsVoice: o.ttsVoice || O.defaultVoice,
|
|
7202
7202
|
lipsyncLang: "en",
|
|
7203
7203
|
// English lip-sync
|
|
@@ -7209,173 +7209,173 @@ const pt = He(({
|
|
|
7209
7209
|
}, B = {
|
|
7210
7210
|
ttsEndpoint: O.endpoint,
|
|
7211
7211
|
ttsApikey: O.apiKey,
|
|
7212
|
-
ttsService:
|
|
7212
|
+
ttsService: k,
|
|
7213
7213
|
lipsyncModules: ["en"],
|
|
7214
7214
|
cameraView: "upper"
|
|
7215
|
-
},
|
|
7215
|
+
}, H = N(async () => {
|
|
7216
7216
|
if (!(!h.current || r.current))
|
|
7217
7217
|
try {
|
|
7218
|
-
if (a(!0), c(null), r.current = new Be(h.current, B), await r.current.showAvatar(p, (
|
|
7219
|
-
if (
|
|
7220
|
-
const
|
|
7221
|
-
t(
|
|
7218
|
+
if (a(!0), c(null), r.current = new Be(h.current, B), await r.current.showAvatar(p, (X) => {
|
|
7219
|
+
if (X.lengthComputable) {
|
|
7220
|
+
const Z = Math.min(100, Math.round(X.loaded / X.total * 100));
|
|
7221
|
+
t(Z);
|
|
7222
7222
|
}
|
|
7223
7223
|
}), r.current.morphs && r.current.morphs.length > 0) {
|
|
7224
|
-
const
|
|
7225
|
-
console.log("Available morph targets:", Object.keys(
|
|
7226
|
-
const
|
|
7227
|
-
console.log("Viseme morph targets found:",
|
|
7224
|
+
const X = r.current.morphs[0].morphTargetDictionary;
|
|
7225
|
+
console.log("Available morph targets:", Object.keys(X));
|
|
7226
|
+
const Z = Object.keys(X).filter((ne) => ne.startsWith("viseme_"));
|
|
7227
|
+
console.log("Viseme morph targets found:", Z), Z.length === 0 && (console.warn("No viseme morph targets found! Lip-sync will not work properly."), console.log("Expected viseme targets: viseme_aa, viseme_E, viseme_I, viseme_O, viseme_U, viseme_PP, viseme_SS, viseme_TH, viseme_DD, viseme_FF, viseme_kk, viseme_nn, viseme_RR, viseme_CH, viseme_sil"));
|
|
7228
7228
|
}
|
|
7229
|
-
if (await new Promise((
|
|
7230
|
-
const
|
|
7231
|
-
r.current.lipsync && Object.keys(r.current.lipsync).length > 0 ? (console.log("Lip-sync modules loaded:", Object.keys(r.current.lipsync)),
|
|
7229
|
+
if (await new Promise((X) => {
|
|
7230
|
+
const Z = () => {
|
|
7231
|
+
r.current.lipsync && Object.keys(r.current.lipsync).length > 0 ? (console.log("Lip-sync modules loaded:", Object.keys(r.current.lipsync)), X()) : (console.log("Waiting for lip-sync modules to load..."), setTimeout(Z, 100));
|
|
7232
7232
|
};
|
|
7233
|
-
|
|
7233
|
+
Z();
|
|
7234
7234
|
}), r.current && r.current.setShowFullAvatar)
|
|
7235
7235
|
try {
|
|
7236
7236
|
r.current.setShowFullAvatar(!0), console.log("Avatar initialized in full body mode");
|
|
7237
|
-
} catch (
|
|
7238
|
-
console.warn("Error setting full body mode on initialization:",
|
|
7237
|
+
} catch (X) {
|
|
7238
|
+
console.warn("Error setting full body mode on initialization:", X);
|
|
7239
7239
|
}
|
|
7240
|
-
a(!1),
|
|
7241
|
-
const
|
|
7240
|
+
a(!1), x(!0), n(r.current);
|
|
7241
|
+
const F = () => {
|
|
7242
7242
|
document.visibilityState === "visible" ? r.current?.start() : r.current?.stop();
|
|
7243
7243
|
};
|
|
7244
|
-
return document.addEventListener("visibilitychange",
|
|
7245
|
-
document.removeEventListener("visibilitychange",
|
|
7244
|
+
return document.addEventListener("visibilitychange", F), () => {
|
|
7245
|
+
document.removeEventListener("visibilitychange", F);
|
|
7246
7246
|
};
|
|
7247
|
-
} catch (
|
|
7248
|
-
console.error("Error initializing TalkingHead:",
|
|
7247
|
+
} catch (S) {
|
|
7248
|
+
console.error("Error initializing TalkingHead:", S), c(S.message || "Failed to initialize avatar"), a(!1), e(S);
|
|
7249
7249
|
}
|
|
7250
7250
|
}, []);
|
|
7251
|
-
|
|
7251
|
+
ce(() => (H(), () => {
|
|
7252
7252
|
r.current && (r.current.stop(), r.current.dispose(), r.current = null);
|
|
7253
|
-
}), [
|
|
7254
|
-
const
|
|
7253
|
+
}), [H]);
|
|
7254
|
+
const v = N((S) => {
|
|
7255
7255
|
if (r.current && g)
|
|
7256
7256
|
try {
|
|
7257
|
-
console.log("Speaking text:",
|
|
7258
|
-
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(
|
|
7257
|
+
console.log("Speaking text:", S), console.log("Avatar config:", p), console.log("TalkingHead instance:", r.current), r.current.lipsync && Object.keys(r.current.lipsync).length > 0 ? (console.log("Lip-sync modules loaded:", Object.keys(r.current.lipsync)), r.current.setSlowdownRate && (r.current.setSlowdownRate(1.05), console.log("Applied timing adjustment for better lip-sync")), r.current.speakText(S)) : (console.warn("Lip-sync modules not ready, waiting..."), setTimeout(() => {
|
|
7258
|
+
r.current && r.current.lipsync ? (console.log("Lip-sync now ready, speaking..."), r.current.setSlowdownRate && (r.current.setSlowdownRate(1.05), console.log("Applied timing adjustment for better lip-sync")), r.current.speakText(S)) : console.error("Lip-sync still not ready after waiting");
|
|
7259
7259
|
}, 500));
|
|
7260
|
-
} catch (
|
|
7261
|
-
console.error("Error speaking text:",
|
|
7260
|
+
} catch (F) {
|
|
7261
|
+
console.error("Error speaking text:", F), c(F.message || "Failed to speak text");
|
|
7262
7262
|
}
|
|
7263
7263
|
else
|
|
7264
7264
|
console.warn("Avatar not ready for speaking. isReady:", g, "talkingHeadRef:", !!r.current);
|
|
7265
|
-
}, [g, p]),
|
|
7265
|
+
}, [g, p]), L = N(() => {
|
|
7266
7266
|
r.current && (r.current.stopSpeaking(), r.current.setSlowdownRate && (r.current.setSlowdownRate(1), console.log("Reset timing to normal")));
|
|
7267
|
-
}, []),
|
|
7268
|
-
r.current && r.current.setMood(
|
|
7269
|
-
}, []),
|
|
7270
|
-
r.current && r.current.setSlowdownRate && (r.current.setSlowdownRate(
|
|
7271
|
-
}, []),
|
|
7267
|
+
}, []), I = N((S) => {
|
|
7268
|
+
r.current && r.current.setMood(S);
|
|
7269
|
+
}, []), z = N((S) => {
|
|
7270
|
+
r.current && r.current.setSlowdownRate && (r.current.setSlowdownRate(S), console.log("Timing adjustment set to:", S));
|
|
7271
|
+
}, []), Y = N((S, F = !1) => {
|
|
7272
7272
|
if (r.current && r.current.playAnimation) {
|
|
7273
7273
|
if (r.current.setShowFullAvatar)
|
|
7274
7274
|
try {
|
|
7275
7275
|
r.current.setShowFullAvatar(!0);
|
|
7276
|
-
} catch (
|
|
7277
|
-
console.warn("Error setting full body mode:",
|
|
7276
|
+
} catch (Z) {
|
|
7277
|
+
console.warn("Error setting full body mode:", Z);
|
|
7278
7278
|
}
|
|
7279
|
-
if (
|
|
7279
|
+
if (S.includes("."))
|
|
7280
7280
|
try {
|
|
7281
|
-
r.current.playAnimation(
|
|
7282
|
-
} catch (
|
|
7283
|
-
console.log(`Failed to play ${
|
|
7281
|
+
r.current.playAnimation(S, null, 10, 0, 0.01, F), console.log("Playing animation:", S);
|
|
7282
|
+
} catch (Z) {
|
|
7283
|
+
console.log(`Failed to play ${S}:`, Z);
|
|
7284
7284
|
try {
|
|
7285
7285
|
r.current.setBodyMovement("idle"), console.log("Fallback to idle animation");
|
|
7286
|
-
} catch (
|
|
7287
|
-
console.warn("Fallback animation also failed:",
|
|
7286
|
+
} catch (ne) {
|
|
7287
|
+
console.warn("Fallback animation also failed:", ne);
|
|
7288
7288
|
}
|
|
7289
7289
|
}
|
|
7290
7290
|
else {
|
|
7291
|
-
const
|
|
7292
|
-
let
|
|
7293
|
-
for (const
|
|
7291
|
+
const Z = [".fbx", ".glb", ".gltf"];
|
|
7292
|
+
let ne = !1;
|
|
7293
|
+
for (const le of Z)
|
|
7294
7294
|
try {
|
|
7295
|
-
r.current.playAnimation(
|
|
7295
|
+
r.current.playAnimation(S + le, null, 10, 0, 0.01, F), console.log("Playing animation:", S + le), ne = !0;
|
|
7296
7296
|
break;
|
|
7297
7297
|
} catch {
|
|
7298
|
-
console.log(`Failed to play ${
|
|
7298
|
+
console.log(`Failed to play ${S}${le}, trying next format...`);
|
|
7299
7299
|
}
|
|
7300
|
-
if (
|
|
7301
|
-
console.warn("Animation system not available or animation not found:",
|
|
7300
|
+
if (!ne) {
|
|
7301
|
+
console.warn("Animation system not available or animation not found:", S);
|
|
7302
7302
|
try {
|
|
7303
7303
|
r.current.setBodyMovement("idle"), console.log("Fallback to idle animation");
|
|
7304
|
-
} catch (
|
|
7305
|
-
console.warn("Fallback animation also failed:",
|
|
7304
|
+
} catch (le) {
|
|
7305
|
+
console.warn("Fallback animation also failed:", le);
|
|
7306
7306
|
}
|
|
7307
7307
|
}
|
|
7308
7308
|
}
|
|
7309
7309
|
} else
|
|
7310
|
-
console.warn("Animation system not available or animation not found:",
|
|
7310
|
+
console.warn("Animation system not available or animation not found:", S);
|
|
7311
7311
|
}, []);
|
|
7312
|
-
return
|
|
7313
|
-
speakText:
|
|
7314
|
-
stopSpeaking:
|
|
7315
|
-
setMood:
|
|
7316
|
-
setTimingAdjustment:
|
|
7317
|
-
playAnimation:
|
|
7312
|
+
return Fe(l, () => ({
|
|
7313
|
+
speakText: v,
|
|
7314
|
+
stopSpeaking: L,
|
|
7315
|
+
setMood: I,
|
|
7316
|
+
setTimingAdjustment: z,
|
|
7317
|
+
playAnimation: Y,
|
|
7318
7318
|
isReady: g,
|
|
7319
7319
|
talkingHead: r.current,
|
|
7320
|
-
setBodyMovement: (
|
|
7320
|
+
setBodyMovement: (S) => {
|
|
7321
7321
|
if (r.current && r.current.setShowFullAvatar && r.current.setBodyMovement)
|
|
7322
7322
|
try {
|
|
7323
|
-
r.current.setShowFullAvatar(!0), r.current.setBodyMovement(
|
|
7324
|
-
} catch (
|
|
7325
|
-
console.warn("Error setting body movement:",
|
|
7323
|
+
r.current.setShowFullAvatar(!0), r.current.setBodyMovement(S), console.log("Body movement set with full body mode:", S);
|
|
7324
|
+
} catch (F) {
|
|
7325
|
+
console.warn("Error setting body movement:", F);
|
|
7326
7326
|
}
|
|
7327
7327
|
},
|
|
7328
|
-
setMovementIntensity: (
|
|
7328
|
+
setMovementIntensity: (S) => r.current?.setMovementIntensity(S),
|
|
7329
7329
|
playRandomDance: () => {
|
|
7330
7330
|
if (r.current && r.current.setShowFullAvatar && r.current.playRandomDance)
|
|
7331
7331
|
try {
|
|
7332
7332
|
r.current.setShowFullAvatar(!0), r.current.playRandomDance(), console.log("Random dance played with full body mode");
|
|
7333
|
-
} catch (
|
|
7334
|
-
console.warn("Error playing random dance:",
|
|
7333
|
+
} catch (S) {
|
|
7334
|
+
console.warn("Error playing random dance:", S);
|
|
7335
7335
|
}
|
|
7336
7336
|
},
|
|
7337
|
-
playReaction: (
|
|
7337
|
+
playReaction: (S) => {
|
|
7338
7338
|
if (r.current && r.current.setShowFullAvatar && r.current.playReaction)
|
|
7339
7339
|
try {
|
|
7340
|
-
r.current.setShowFullAvatar(!0), r.current.playReaction(
|
|
7341
|
-
} catch (
|
|
7342
|
-
console.warn("Error playing reaction:",
|
|
7340
|
+
r.current.setShowFullAvatar(!0), r.current.playReaction(S), console.log("Reaction played with full body mode:", S);
|
|
7341
|
+
} catch (F) {
|
|
7342
|
+
console.warn("Error playing reaction:", F);
|
|
7343
7343
|
}
|
|
7344
7344
|
},
|
|
7345
7345
|
playCelebration: () => {
|
|
7346
7346
|
if (r.current && r.current.setShowFullAvatar && r.current.playCelebration)
|
|
7347
7347
|
try {
|
|
7348
7348
|
r.current.setShowFullAvatar(!0), r.current.playCelebration(), console.log("Celebration played with full body mode");
|
|
7349
|
-
} catch (
|
|
7350
|
-
console.warn("Error playing celebration:",
|
|
7349
|
+
} catch (S) {
|
|
7350
|
+
console.warn("Error playing celebration:", S);
|
|
7351
7351
|
}
|
|
7352
7352
|
},
|
|
7353
|
-
setShowFullAvatar: (
|
|
7353
|
+
setShowFullAvatar: (S) => {
|
|
7354
7354
|
if (r.current && r.current.setShowFullAvatar)
|
|
7355
7355
|
try {
|
|
7356
|
-
r.current.setShowFullAvatar(
|
|
7357
|
-
} catch (
|
|
7358
|
-
console.warn("Error setting showFullAvatar:",
|
|
7356
|
+
r.current.setShowFullAvatar(S), console.log("Show full avatar set to:", S);
|
|
7357
|
+
} catch (F) {
|
|
7358
|
+
console.warn("Error setting showFullAvatar:", F);
|
|
7359
7359
|
}
|
|
7360
7360
|
},
|
|
7361
7361
|
lockAvatarPosition: () => {
|
|
7362
7362
|
if (r.current && r.current.lockAvatarPosition)
|
|
7363
7363
|
try {
|
|
7364
7364
|
r.current.lockAvatarPosition();
|
|
7365
|
-
} catch (
|
|
7366
|
-
console.warn("Error locking avatar position:",
|
|
7365
|
+
} catch (S) {
|
|
7366
|
+
console.warn("Error locking avatar position:", S);
|
|
7367
7367
|
}
|
|
7368
7368
|
},
|
|
7369
7369
|
unlockAvatarPosition: () => {
|
|
7370
7370
|
if (r.current && r.current.unlockAvatarPosition)
|
|
7371
7371
|
try {
|
|
7372
7372
|
r.current.unlockAvatarPosition();
|
|
7373
|
-
} catch (
|
|
7374
|
-
console.warn("Error unlocking avatar position:",
|
|
7373
|
+
} catch (S) {
|
|
7374
|
+
console.warn("Error unlocking avatar position:", S);
|
|
7375
7375
|
}
|
|
7376
7376
|
}
|
|
7377
7377
|
})), /* @__PURE__ */ Pe("div", { className: `talking-head-container ${i}`, style: s, children: [
|
|
7378
|
-
/* @__PURE__ */
|
|
7378
|
+
/* @__PURE__ */ ye(
|
|
7379
7379
|
"div",
|
|
7380
7380
|
{
|
|
7381
7381
|
ref: h,
|
|
@@ -7387,7 +7387,7 @@ const pt = He(({
|
|
|
7387
7387
|
}
|
|
7388
7388
|
}
|
|
7389
7389
|
),
|
|
7390
|
-
u && /* @__PURE__ */
|
|
7390
|
+
u && /* @__PURE__ */ ye("div", { className: "loading-overlay", style: {
|
|
7391
7391
|
position: "absolute",
|
|
7392
7392
|
top: "50%",
|
|
7393
7393
|
left: "50%",
|
|
@@ -7396,7 +7396,7 @@ const pt = He(({
|
|
|
7396
7396
|
fontSize: "18px",
|
|
7397
7397
|
zIndex: 10
|
|
7398
7398
|
}, children: "Loading avatar..." }),
|
|
7399
|
-
d && /* @__PURE__ */
|
|
7399
|
+
d && /* @__PURE__ */ ye("div", { className: "error-overlay", style: {
|
|
7400
7400
|
position: "absolute",
|
|
7401
7401
|
top: "50%",
|
|
7402
7402
|
left: "50%",
|
|
@@ -7411,8 +7411,15 @@ const pt = He(({
|
|
|
7411
7411
|
] });
|
|
7412
7412
|
});
|
|
7413
7413
|
pt.displayName = "TalkingHeadComponent";
|
|
7414
|
-
|
|
7415
|
-
|
|
7414
|
+
async function gt(V) {
|
|
7415
|
+
try {
|
|
7416
|
+
return (await (await fetch(V)).json()).animations || {};
|
|
7417
|
+
} catch (t) {
|
|
7418
|
+
return console.error("Failed to load animation manifest:", t), {};
|
|
7419
|
+
}
|
|
7420
|
+
}
|
|
7421
|
+
const yt = Me(({
|
|
7422
|
+
text: V = null,
|
|
7416
7423
|
avatarUrl: t = "/avatars/brunette.glb",
|
|
7417
7424
|
avatarBody: e = "F",
|
|
7418
7425
|
mood: n = "neutral",
|
|
@@ -7430,114 +7437,128 @@ const gt = He(({
|
|
|
7430
7437
|
},
|
|
7431
7438
|
onError: g = () => {
|
|
7432
7439
|
},
|
|
7433
|
-
onSpeechEnd:
|
|
7440
|
+
onSpeechEnd: x = () => {
|
|
7434
7441
|
},
|
|
7435
|
-
className:
|
|
7436
|
-
style:
|
|
7442
|
+
className: f = "",
|
|
7443
|
+
style: k = {},
|
|
7437
7444
|
animations: O = {},
|
|
7438
7445
|
autoAnimationGroup: p = null,
|
|
7439
7446
|
// e.g., "talking" - will randomly select from this group when speaking
|
|
7440
|
-
|
|
7441
|
-
|
|
7442
|
-
|
|
7443
|
-
|
|
7444
|
-
|
|
7445
|
-
|
|
7446
|
-
|
|
7447
|
+
autoIdleGroup: B = null,
|
|
7448
|
+
// e.g., "idle" - will randomly select from this group when idle
|
|
7449
|
+
autoSpeak: H = !1
|
|
7450
|
+
}, v) => {
|
|
7451
|
+
const L = W(null), I = W(null), z = W(u), Y = W(null), S = W(null), F = W(!1), X = W({ remainingText: null, originalText: null, options: null }), Z = W([]), [ne, le] = pe(!0), [ge, de] = pe(null), [$, be] = pe(!1), [j, b] = pe(!1), [R, M] = pe(O), E = W(null);
|
|
7452
|
+
ce(() => {
|
|
7453
|
+
F.current = j;
|
|
7454
|
+
}, [j]), ce(() => {
|
|
7455
|
+
(async () => {
|
|
7456
|
+
if (O.manifest)
|
|
7457
|
+
try {
|
|
7458
|
+
const P = await gt(O.manifest);
|
|
7459
|
+
M(P), console.log("Loaded animations from manifest:", P);
|
|
7460
|
+
} catch (P) {
|
|
7461
|
+
console.error("Failed to load animation manifest:", P), M(O);
|
|
7462
|
+
}
|
|
7463
|
+
else
|
|
7464
|
+
M(O);
|
|
7465
|
+
})();
|
|
7466
|
+
}, [O]), ce(() => {
|
|
7467
|
+
z.current = u;
|
|
7447
7468
|
}, [u]);
|
|
7448
|
-
const
|
|
7449
|
-
let
|
|
7450
|
-
|
|
7469
|
+
const D = Ee(), ee = s || D.service;
|
|
7470
|
+
let Q;
|
|
7471
|
+
ee === "browser" ? Q = {
|
|
7451
7472
|
service: "browser",
|
|
7452
7473
|
endpoint: "",
|
|
7453
7474
|
apiKey: null,
|
|
7454
7475
|
defaultVoice: "Google US English"
|
|
7455
|
-
} :
|
|
7476
|
+
} : ee === "elevenlabs" ? Q = {
|
|
7456
7477
|
service: "elevenlabs",
|
|
7457
7478
|
endpoint: "https://api.elevenlabs.io/v1/text-to-speech",
|
|
7458
|
-
apiKey: l ||
|
|
7459
|
-
defaultVoice: o ||
|
|
7460
|
-
voices:
|
|
7461
|
-
} :
|
|
7479
|
+
apiKey: l || D.apiKey,
|
|
7480
|
+
defaultVoice: o || D.defaultVoice || Ie.defaultVoice,
|
|
7481
|
+
voices: D.voices || Ie.voices
|
|
7482
|
+
} : ee === "deepgram" ? Q = {
|
|
7462
7483
|
service: "deepgram",
|
|
7463
7484
|
endpoint: "https://api.deepgram.com/v1/speak",
|
|
7464
|
-
apiKey: l ||
|
|
7465
|
-
defaultVoice: o ||
|
|
7466
|
-
voices:
|
|
7467
|
-
} :
|
|
7468
|
-
...
|
|
7469
|
-
apiKey: l !== null ? l :
|
|
7485
|
+
apiKey: l || D.apiKey,
|
|
7486
|
+
defaultVoice: o || D.defaultVoice || Te.defaultVoice,
|
|
7487
|
+
voices: D.voices || Te.voices
|
|
7488
|
+
} : Q = {
|
|
7489
|
+
...D,
|
|
7490
|
+
apiKey: l !== null ? l : D.apiKey
|
|
7470
7491
|
};
|
|
7471
|
-
const
|
|
7492
|
+
const q = {
|
|
7472
7493
|
url: t,
|
|
7473
7494
|
body: e,
|
|
7474
7495
|
avatarMood: n,
|
|
7475
|
-
ttsLang:
|
|
7476
|
-
ttsVoice: o ||
|
|
7496
|
+
ttsLang: ee === "browser" ? "en-US" : i,
|
|
7497
|
+
ttsVoice: o || Q.defaultVoice,
|
|
7477
7498
|
lipsyncLang: "en",
|
|
7478
7499
|
showFullAvatar: u,
|
|
7479
7500
|
bodyMovement: h,
|
|
7480
7501
|
movementIntensity: r
|
|
7481
|
-
},
|
|
7482
|
-
ttsEndpoint:
|
|
7483
|
-
ttsApikey:
|
|
7484
|
-
ttsService:
|
|
7502
|
+
}, Ae = {
|
|
7503
|
+
ttsEndpoint: Q.endpoint,
|
|
7504
|
+
ttsApikey: Q.apiKey,
|
|
7505
|
+
ttsService: ee,
|
|
7485
7506
|
lipsyncModules: ["en"],
|
|
7486
7507
|
cameraView: a
|
|
7487
|
-
},
|
|
7488
|
-
if (!(!
|
|
7508
|
+
}, Se = N(async () => {
|
|
7509
|
+
if (!(!L.current || I.current))
|
|
7489
7510
|
try {
|
|
7490
|
-
|
|
7491
|
-
url:
|
|
7492
|
-
body:
|
|
7493
|
-
avatarMood:
|
|
7494
|
-
}), await
|
|
7495
|
-
if (
|
|
7496
|
-
const
|
|
7497
|
-
c(
|
|
7511
|
+
le(!0), de(null), I.current = new Be(L.current, Ae), console.log("Avatar config being passed:", {
|
|
7512
|
+
url: q.url,
|
|
7513
|
+
body: q.body,
|
|
7514
|
+
avatarMood: q.avatarMood
|
|
7515
|
+
}), await I.current.showAvatar(q, (P) => {
|
|
7516
|
+
if (P.lengthComputable) {
|
|
7517
|
+
const K = Math.min(100, Math.round(P.loaded / P.total * 100));
|
|
7518
|
+
c(K);
|
|
7498
7519
|
}
|
|
7499
|
-
}),
|
|
7520
|
+
}), I.current?.avatar && console.log("Avatar body after initialization:", I.current.avatar.body), le(!1), be(!0), d(I.current);
|
|
7500
7521
|
const A = () => {
|
|
7501
|
-
document.visibilityState === "visible" ?
|
|
7522
|
+
document.visibilityState === "visible" ? I.current?.start() : I.current?.stop();
|
|
7502
7523
|
};
|
|
7503
7524
|
return document.addEventListener("visibilitychange", A), () => {
|
|
7504
7525
|
document.removeEventListener("visibilitychange", A);
|
|
7505
7526
|
};
|
|
7506
7527
|
} catch (A) {
|
|
7507
|
-
console.error("Error initializing TalkingHead:", A),
|
|
7528
|
+
console.error("Error initializing TalkingHead:", A), de(A.message || "Failed to initialize avatar"), le(!1), g(A);
|
|
7508
7529
|
}
|
|
7509
7530
|
}, []);
|
|
7510
|
-
|
|
7511
|
-
|
|
7512
|
-
}), [
|
|
7513
|
-
const
|
|
7514
|
-
if (
|
|
7531
|
+
ce(() => (Se(), () => {
|
|
7532
|
+
I.current && (I.current.stop(), I.current.dispose(), I.current = null);
|
|
7533
|
+
}), [Se]);
|
|
7534
|
+
const Le = N(async () => {
|
|
7535
|
+
if (I.current)
|
|
7515
7536
|
try {
|
|
7516
|
-
const A =
|
|
7537
|
+
const A = I.current.audioCtx || I.current.audioContext;
|
|
7517
7538
|
A && (A.state === "suspended" || A.state === "interrupted") && (await A.resume(), console.log("Audio context resumed"));
|
|
7518
7539
|
} catch (A) {
|
|
7519
7540
|
console.warn("Failed to resume audio context:", A);
|
|
7520
7541
|
}
|
|
7521
|
-
}, []),
|
|
7522
|
-
if (!
|
|
7542
|
+
}, []), ke = N((A) => {
|
|
7543
|
+
if (!R || !R[A])
|
|
7523
7544
|
return null;
|
|
7524
|
-
const
|
|
7525
|
-
if (Array.isArray(
|
|
7526
|
-
const
|
|
7527
|
-
return
|
|
7545
|
+
const P = R[A];
|
|
7546
|
+
if (Array.isArray(P) && P.length > 0) {
|
|
7547
|
+
const K = Math.floor(Math.random() * P.length);
|
|
7548
|
+
return P[K];
|
|
7528
7549
|
}
|
|
7529
|
-
return typeof
|
|
7530
|
-
}, [
|
|
7531
|
-
const
|
|
7532
|
-
if (
|
|
7550
|
+
return typeof P == "string" ? P : null;
|
|
7551
|
+
}, [R]), w = N((A, P = !1) => {
|
|
7552
|
+
const K = ke(A);
|
|
7553
|
+
if (K && I.current)
|
|
7533
7554
|
try {
|
|
7534
|
-
return
|
|
7535
|
-
} catch (
|
|
7536
|
-
return console.warn(`Failed to play random animation from "${A}" group:`,
|
|
7555
|
+
return I.current.playAnimation(K, null, 10, 0, 0.01, P), console.log(`Playing random animation from "${A}" group:`, K), K;
|
|
7556
|
+
} catch (ie) {
|
|
7557
|
+
return console.warn(`Failed to play random animation from "${A}" group:`, ie), null;
|
|
7537
7558
|
}
|
|
7538
7559
|
return null;
|
|
7539
|
-
}, [
|
|
7540
|
-
if (!
|
|
7560
|
+
}, [ke]), U = N(async (A, P = {}) => {
|
|
7561
|
+
if (!I.current || !$) {
|
|
7541
7562
|
console.warn("Avatar not ready for speaking");
|
|
7542
7563
|
return;
|
|
7543
7564
|
}
|
|
@@ -7545,82 +7566,94 @@ const gt = He(({
|
|
|
7545
7566
|
console.warn("No text provided to speak");
|
|
7546
7567
|
return;
|
|
7547
7568
|
}
|
|
7548
|
-
await
|
|
7549
|
-
const
|
|
7550
|
-
|
|
7551
|
-
const
|
|
7552
|
-
|
|
7553
|
-
const
|
|
7554
|
-
lipsyncLang:
|
|
7569
|
+
await Le();
|
|
7570
|
+
const K = P.animationGroup || p;
|
|
7571
|
+
K && !P.skipAnimation && w(K), X.current = { remainingText: null, originalText: null, options: null }, Z.current = [], Y.current = { text: A, options: P }, S.current && (clearInterval(S.current), S.current = null), b(!1), F.current = !1;
|
|
7572
|
+
const ie = A.split(/[.!?]+/).filter((oe) => oe.trim().length > 0);
|
|
7573
|
+
Z.current = ie;
|
|
7574
|
+
const se = {
|
|
7575
|
+
lipsyncLang: P.lipsyncLang || "en",
|
|
7555
7576
|
onSpeechEnd: () => {
|
|
7556
|
-
|
|
7577
|
+
S.current && (clearInterval(S.current), S.current = null), P.onSpeechEnd && P.onSpeechEnd(), x();
|
|
7557
7578
|
}
|
|
7558
7579
|
};
|
|
7559
7580
|
try {
|
|
7560
|
-
|
|
7561
|
-
} catch (
|
|
7562
|
-
console.error("Error speaking text:",
|
|
7581
|
+
I.current.speakText(A, se);
|
|
7582
|
+
} catch (oe) {
|
|
7583
|
+
console.error("Error speaking text:", oe), de(oe.message || "Failed to speak text");
|
|
7563
7584
|
}
|
|
7564
|
-
}, [
|
|
7565
|
-
|
|
7566
|
-
|
|
7567
|
-
|
|
7568
|
-
|
|
7569
|
-
|
|
7585
|
+
}, [$, x, Le, p, w]);
|
|
7586
|
+
ce(() => {
|
|
7587
|
+
if (!$ || !B || !I.current)
|
|
7588
|
+
return;
|
|
7589
|
+
E.current && clearInterval(E.current);
|
|
7590
|
+
const A = () => {
|
|
7591
|
+
I.current && !F.current && w(B);
|
|
7592
|
+
};
|
|
7593
|
+
return A(), E.current = setInterval(() => {
|
|
7594
|
+
A();
|
|
7595
|
+
}, 12e3 + Math.random() * 3e3), () => {
|
|
7596
|
+
E.current && (clearInterval(E.current), E.current = null);
|
|
7597
|
+
};
|
|
7598
|
+
}, [$, B, w]), ce(() => {
|
|
7599
|
+
$ && V && H && I.current && U(V);
|
|
7600
|
+
}, [$, V, H, U]);
|
|
7601
|
+
const _ = N(() => {
|
|
7602
|
+
if (I.current)
|
|
7570
7603
|
try {
|
|
7571
|
-
const A =
|
|
7572
|
-
if (A ||
|
|
7573
|
-
|
|
7574
|
-
let
|
|
7575
|
-
|
|
7576
|
-
remainingText:
|
|
7577
|
-
originalText:
|
|
7578
|
-
options:
|
|
7579
|
-
},
|
|
7604
|
+
const A = I.current.isSpeaking || !1, P = I.current.audioPlaylist || [], K = I.current.speechQueue || [];
|
|
7605
|
+
if (A || P.length > 0 || K.length > 0) {
|
|
7606
|
+
S.current && (clearInterval(S.current), S.current = null);
|
|
7607
|
+
let ie = "";
|
|
7608
|
+
K.length > 0 && (ie = K.map((se) => se.text && Array.isArray(se.text) ? se.text.map((oe) => oe.word).join(" ") : se.text || "").join(" ")), X.current = {
|
|
7609
|
+
remainingText: ie || null,
|
|
7610
|
+
originalText: Y.current?.text || null,
|
|
7611
|
+
options: Y.current?.options || null
|
|
7612
|
+
}, I.current.speechQueue.length = 0, I.current.pauseSpeaking(), b(!0), F.current = !0;
|
|
7580
7613
|
}
|
|
7581
7614
|
} catch (A) {
|
|
7582
7615
|
console.warn("Error pausing speech:", A);
|
|
7583
7616
|
}
|
|
7584
|
-
}, []),
|
|
7585
|
-
if (!(!
|
|
7617
|
+
}, []), te = N(async () => {
|
|
7618
|
+
if (!(!I.current || !j))
|
|
7586
7619
|
try {
|
|
7587
|
-
await
|
|
7588
|
-
const A =
|
|
7589
|
-
|
|
7620
|
+
await Le(), b(!1), F.current = !1;
|
|
7621
|
+
const A = X.current?.remainingText, P = X.current?.originalText || Y.current?.text, K = X.current?.options || Y.current?.options || {}, ie = A || P;
|
|
7622
|
+
ie && U(ie, K);
|
|
7590
7623
|
} catch (A) {
|
|
7591
|
-
console.warn("Error resuming speech:", A),
|
|
7624
|
+
console.warn("Error resuming speech:", A), b(!1), F.current = !1;
|
|
7592
7625
|
}
|
|
7593
|
-
}, [
|
|
7594
|
-
|
|
7626
|
+
}, [j, U, Le]), me = N(() => {
|
|
7627
|
+
I.current && (I.current.stopSpeaking(), S.current && (clearInterval(S.current), S.current = null), b(!1), F.current = !1);
|
|
7595
7628
|
}, []);
|
|
7596
|
-
return
|
|
7597
|
-
speakText:
|
|
7598
|
-
pauseSpeaking:
|
|
7599
|
-
resumeSpeaking:
|
|
7600
|
-
stopSpeaking:
|
|
7601
|
-
resumeAudioContext:
|
|
7602
|
-
isPaused: () =>
|
|
7603
|
-
setMood: (A) =>
|
|
7629
|
+
return Fe(v, () => ({
|
|
7630
|
+
speakText: U,
|
|
7631
|
+
pauseSpeaking: _,
|
|
7632
|
+
resumeSpeaking: te,
|
|
7633
|
+
stopSpeaking: me,
|
|
7634
|
+
resumeAudioContext: Le,
|
|
7635
|
+
isPaused: () => j,
|
|
7636
|
+
setMood: (A) => I.current?.setMood(A),
|
|
7604
7637
|
setBodyMovement: (A) => {
|
|
7605
|
-
|
|
7638
|
+
I.current && I.current.setBodyMovement(A);
|
|
7606
7639
|
},
|
|
7607
|
-
playAnimation: (A,
|
|
7608
|
-
|
|
7640
|
+
playAnimation: (A, P = !1) => {
|
|
7641
|
+
I.current && I.current.playAnimation && I.current.playAnimation(A, null, 10, 0, 0.01, P);
|
|
7609
7642
|
},
|
|
7610
|
-
playRandomAnimation: (A,
|
|
7611
|
-
getRandomAnimation: (A) =>
|
|
7612
|
-
playReaction: (A) =>
|
|
7613
|
-
playCelebration: () =>
|
|
7643
|
+
playRandomAnimation: (A, P = !1) => w(A, P),
|
|
7644
|
+
getRandomAnimation: (A) => ke(A),
|
|
7645
|
+
playReaction: (A) => I.current?.playReaction(A),
|
|
7646
|
+
playCelebration: () => I.current?.playCelebration(),
|
|
7614
7647
|
setShowFullAvatar: (A) => {
|
|
7615
|
-
|
|
7648
|
+
I.current && (z.current = A, I.current.setShowFullAvatar(A));
|
|
7616
7649
|
},
|
|
7617
|
-
isReady:
|
|
7618
|
-
talkingHead:
|
|
7619
|
-
})), /* @__PURE__ */ Pe("div", { className: `simple-talking-avatar-container ${
|
|
7620
|
-
/* @__PURE__ */
|
|
7650
|
+
isReady: $,
|
|
7651
|
+
talkingHead: I.current
|
|
7652
|
+
})), /* @__PURE__ */ Pe("div", { className: `simple-talking-avatar-container ${f}`, style: k, children: [
|
|
7653
|
+
/* @__PURE__ */ ye(
|
|
7621
7654
|
"div",
|
|
7622
7655
|
{
|
|
7623
|
-
ref:
|
|
7656
|
+
ref: L,
|
|
7624
7657
|
className: "talking-head-viewer",
|
|
7625
7658
|
style: {
|
|
7626
7659
|
width: "100%",
|
|
@@ -7629,7 +7662,7 @@ const gt = He(({
|
|
|
7629
7662
|
}
|
|
7630
7663
|
}
|
|
7631
7664
|
),
|
|
7632
|
-
|
|
7665
|
+
ne && /* @__PURE__ */ ye("div", { className: "loading-overlay", style: {
|
|
7633
7666
|
position: "absolute",
|
|
7634
7667
|
top: "50%",
|
|
7635
7668
|
left: "50%",
|
|
@@ -7638,7 +7671,7 @@ const gt = He(({
|
|
|
7638
7671
|
fontSize: "18px",
|
|
7639
7672
|
zIndex: 10
|
|
7640
7673
|
}, children: "Loading avatar..." }),
|
|
7641
|
-
|
|
7674
|
+
ge && /* @__PURE__ */ ye("div", { className: "error-overlay", style: {
|
|
7642
7675
|
position: "absolute",
|
|
7643
7676
|
top: "50%",
|
|
7644
7677
|
left: "50%",
|
|
@@ -7649,12 +7682,12 @@ const gt = He(({
|
|
|
7649
7682
|
zIndex: 10,
|
|
7650
7683
|
padding: "20px",
|
|
7651
7684
|
borderRadius: "8px"
|
|
7652
|
-
}, children:
|
|
7685
|
+
}, children: ge })
|
|
7653
7686
|
] });
|
|
7654
7687
|
});
|
|
7655
|
-
|
|
7656
|
-
const
|
|
7657
|
-
curriculumData:
|
|
7688
|
+
yt.displayName = "SimpleTalkingAvatar";
|
|
7689
|
+
const ft = Me(({
|
|
7690
|
+
curriculumData: V = null,
|
|
7658
7691
|
avatarConfig: t = {},
|
|
7659
7692
|
animations: e = {},
|
|
7660
7693
|
onLessonStart: n = () => {
|
|
@@ -7669,7 +7702,7 @@ const yt = He(({
|
|
|
7669
7702
|
},
|
|
7670
7703
|
autoStart: h = !1
|
|
7671
7704
|
}, r) => {
|
|
7672
|
-
const u =
|
|
7705
|
+
const u = W(null), a = W({
|
|
7673
7706
|
currentModuleIndex: 0,
|
|
7674
7707
|
currentLessonIndex: 0,
|
|
7675
7708
|
currentQuestionIndex: 0,
|
|
@@ -7679,18 +7712,18 @@ const yt = He(({
|
|
|
7679
7712
|
curriculumCompleted: !1,
|
|
7680
7713
|
score: 0,
|
|
7681
7714
|
totalQuestions: 0
|
|
7682
|
-
}), d =
|
|
7715
|
+
}), d = W({
|
|
7683
7716
|
onLessonStart: n,
|
|
7684
7717
|
onLessonComplete: i,
|
|
7685
7718
|
onQuestionAnswer: s,
|
|
7686
7719
|
onCurriculumComplete: o,
|
|
7687
7720
|
onCustomAction: l
|
|
7688
|
-
}), c =
|
|
7721
|
+
}), c = W(null), g = W(null), x = W(null), f = W(null), k = W(null), O = W(null), p = W(null), B = W(V?.curriculum || {
|
|
7689
7722
|
title: "Default Curriculum",
|
|
7690
7723
|
description: "No curriculum data provided",
|
|
7691
7724
|
language: "en",
|
|
7692
7725
|
modules: []
|
|
7693
|
-
}),
|
|
7726
|
+
}), H = W({
|
|
7694
7727
|
avatarUrl: t.avatarUrl || "/avatars/brunette.glb",
|
|
7695
7728
|
avatarBody: t.avatarBody || "F",
|
|
7696
7729
|
mood: t.mood || "happy",
|
|
@@ -7704,7 +7737,7 @@ const yt = He(({
|
|
|
7704
7737
|
animations: e,
|
|
7705
7738
|
lipsyncLang: "en"
|
|
7706
7739
|
});
|
|
7707
|
-
|
|
7740
|
+
ce(() => {
|
|
7708
7741
|
d.current = {
|
|
7709
7742
|
onLessonStart: n,
|
|
7710
7743
|
onLessonComplete: i,
|
|
@@ -7712,13 +7745,13 @@ const yt = He(({
|
|
|
7712
7745
|
onCurriculumComplete: o,
|
|
7713
7746
|
onCustomAction: l
|
|
7714
7747
|
};
|
|
7715
|
-
}, [n, i, s, o, l]),
|
|
7716
|
-
B.current =
|
|
7748
|
+
}, [n, i, s, o, l]), ce(() => {
|
|
7749
|
+
B.current = V?.curriculum || {
|
|
7717
7750
|
title: "Default Curriculum",
|
|
7718
7751
|
description: "No curriculum data provided",
|
|
7719
7752
|
language: "en",
|
|
7720
7753
|
modules: []
|
|
7721
|
-
},
|
|
7754
|
+
}, H.current = {
|
|
7722
7755
|
avatarUrl: t.avatarUrl || "/avatars/brunette.glb",
|
|
7723
7756
|
avatarBody: t.avatarBody || "F",
|
|
7724
7757
|
mood: t.mood || "happy",
|
|
@@ -7732,24 +7765,24 @@ const yt = He(({
|
|
|
7732
7765
|
animations: e,
|
|
7733
7766
|
lipsyncLang: "en"
|
|
7734
7767
|
};
|
|
7735
|
-
}, [
|
|
7736
|
-
const
|
|
7768
|
+
}, [V, t, e]);
|
|
7769
|
+
const v = N(() => (B.current || { modules: [] }).modules[a.current.currentModuleIndex]?.lessons[a.current.currentLessonIndex], []), L = N(() => v()?.questions[a.current.currentQuestionIndex], [v]), I = N((b, R) => R.type === "multiple_choice" || R.type === "true_false" ? b === R.answer : R.type === "code_test" && typeof b == "object" && b !== null ? b.passed === !0 : !1, []), z = N(() => {
|
|
7737
7770
|
a.current.lessonCompleted = !0, a.current.isQuestionMode = !1;
|
|
7738
|
-
const
|
|
7739
|
-
let
|
|
7740
|
-
if (a.current.totalQuestions > 0 ?
|
|
7771
|
+
const b = a.current.totalQuestions > 0 ? Math.round(a.current.score / a.current.totalQuestions * 100) : 100;
|
|
7772
|
+
let R = "Congratulations! You've completed this lesson";
|
|
7773
|
+
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 ${b} percent. ` : R += "! ", b >= 80 ? R += "Excellent work! You have a great understanding of this topic." : b >= 60 ? R += "Good job! You understand most of the concepts." : R += "Keep practicing! You're making progress.", d.current.onLessonComplete({
|
|
7741
7774
|
moduleIndex: a.current.currentModuleIndex,
|
|
7742
7775
|
lessonIndex: a.current.currentLessonIndex,
|
|
7743
7776
|
score: a.current.score,
|
|
7744
7777
|
totalQuestions: a.current.totalQuestions,
|
|
7745
|
-
percentage:
|
|
7778
|
+
percentage: b
|
|
7746
7779
|
}), d.current.onCustomAction({
|
|
7747
7780
|
type: "lessonComplete",
|
|
7748
7781
|
moduleIndex: a.current.currentModuleIndex,
|
|
7749
7782
|
lessonIndex: a.current.currentLessonIndex,
|
|
7750
7783
|
score: a.current.score,
|
|
7751
7784
|
totalQuestions: a.current.totalQuestions,
|
|
7752
|
-
percentage:
|
|
7785
|
+
percentage: b
|
|
7753
7786
|
}), u.current) {
|
|
7754
7787
|
if (u.current.setMood("happy"), e.lessonComplete)
|
|
7755
7788
|
try {
|
|
@@ -7757,9 +7790,9 @@ const yt = He(({
|
|
|
7757
7790
|
} catch {
|
|
7758
7791
|
u.current.playCelebration();
|
|
7759
7792
|
}
|
|
7760
|
-
const
|
|
7761
|
-
u.current.speakText(
|
|
7762
|
-
lipsyncLang:
|
|
7793
|
+
const M = B.current || { modules: [] }, E = M.modules[a.current.currentModuleIndex], D = a.current.currentLessonIndex < (E?.lessons?.length || 0) - 1, ee = a.current.currentModuleIndex < (M.modules?.length || 0) - 1, Q = D || ee, q = H.current || { lipsyncLang: "en" };
|
|
7794
|
+
u.current.speakText(R, {
|
|
7795
|
+
lipsyncLang: q.lipsyncLang,
|
|
7763
7796
|
onSpeechEnd: () => {
|
|
7764
7797
|
d.current.onCustomAction({
|
|
7765
7798
|
type: "lessonCompleteFeedbackDone",
|
|
@@ -7767,18 +7800,18 @@ const yt = He(({
|
|
|
7767
7800
|
lessonIndex: a.current.currentLessonIndex,
|
|
7768
7801
|
score: a.current.score,
|
|
7769
7802
|
totalQuestions: a.current.totalQuestions,
|
|
7770
|
-
percentage:
|
|
7771
|
-
hasNextLesson:
|
|
7803
|
+
percentage: b,
|
|
7804
|
+
hasNextLesson: Q
|
|
7772
7805
|
});
|
|
7773
7806
|
}
|
|
7774
7807
|
});
|
|
7775
7808
|
}
|
|
7776
|
-
}, [e.lessonComplete]),
|
|
7809
|
+
}, [e.lessonComplete]), Y = N(() => {
|
|
7777
7810
|
a.current.curriculumCompleted = !0;
|
|
7778
|
-
const
|
|
7811
|
+
const b = B.current || { modules: [] };
|
|
7779
7812
|
if (d.current.onCurriculumComplete({
|
|
7780
|
-
modules:
|
|
7781
|
-
totalLessons:
|
|
7813
|
+
modules: b.modules.length,
|
|
7814
|
+
totalLessons: b.modules.reduce((R, M) => R + M.lessons.length, 0)
|
|
7782
7815
|
}), u.current) {
|
|
7783
7816
|
if (u.current.setMood("celebrating"), e.curriculumComplete)
|
|
7784
7817
|
try {
|
|
@@ -7786,99 +7819,99 @@ const yt = He(({
|
|
|
7786
7819
|
} catch {
|
|
7787
7820
|
u.current.playCelebration();
|
|
7788
7821
|
}
|
|
7789
|
-
const
|
|
7790
|
-
u.current.speakText("Amazing! You've completed the entire curriculum! You're now ready to move on to more advanced topics. Well done!", { lipsyncLang:
|
|
7822
|
+
const R = H.current || { lipsyncLang: "en" };
|
|
7823
|
+
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 });
|
|
7791
7824
|
}
|
|
7792
|
-
}, [e.curriculumComplete]),
|
|
7793
|
-
const
|
|
7794
|
-
a.current.isQuestionMode = !0, a.current.currentQuestionIndex = 0, a.current.totalQuestions =
|
|
7795
|
-
const
|
|
7796
|
-
|
|
7825
|
+
}, [e.curriculumComplete]), S = N(() => {
|
|
7826
|
+
const b = v();
|
|
7827
|
+
a.current.isQuestionMode = !0, a.current.currentQuestionIndex = 0, a.current.totalQuestions = b?.questions?.length || 0, a.current.score = 0;
|
|
7828
|
+
const R = L();
|
|
7829
|
+
R && d.current.onCustomAction({
|
|
7797
7830
|
type: "questionStart",
|
|
7798
7831
|
moduleIndex: a.current.currentModuleIndex,
|
|
7799
7832
|
lessonIndex: a.current.currentLessonIndex,
|
|
7800
7833
|
questionIndex: a.current.currentQuestionIndex,
|
|
7801
7834
|
totalQuestions: a.current.totalQuestions,
|
|
7802
|
-
question:
|
|
7835
|
+
question: R,
|
|
7803
7836
|
score: a.current.score
|
|
7804
7837
|
});
|
|
7805
|
-
const
|
|
7806
|
-
if (!u.current || !
|
|
7838
|
+
const M = () => {
|
|
7839
|
+
if (!u.current || !R) return;
|
|
7807
7840
|
if (u.current.setMood("happy"), e.questionStart)
|
|
7808
7841
|
try {
|
|
7809
7842
|
u.current.playAnimation(e.questionStart, !0);
|
|
7810
|
-
} catch (
|
|
7811
|
-
console.warn("Failed to play questionStart animation:",
|
|
7843
|
+
} catch (D) {
|
|
7844
|
+
console.warn("Failed to play questionStart animation:", D);
|
|
7812
7845
|
}
|
|
7813
|
-
const
|
|
7814
|
-
|
|
7846
|
+
const E = H.current || { lipsyncLang: "en" };
|
|
7847
|
+
R.type === "code_test" ? u.current.speakText(`Let's test your coding skills! Here's your first challenge: ${R.question}`, { lipsyncLang: E.lipsyncLang }) : R.type === "multiple_choice" ? u.current.speakText(`Now let me ask you some questions. Here's the first one: ${R.question}`, { lipsyncLang: E.lipsyncLang }) : R.type === "true_false" ? u.current.speakText(`Let's start with some true or false questions. First question: ${R.question}`, { lipsyncLang: E.lipsyncLang }) : u.current.speakText(`Now let me ask you some questions. Here's the first one: ${R.question}`, { lipsyncLang: E.lipsyncLang });
|
|
7815
7848
|
};
|
|
7816
|
-
if (u.current && u.current.isReady &&
|
|
7817
|
-
|
|
7849
|
+
if (u.current && u.current.isReady && R)
|
|
7850
|
+
M();
|
|
7818
7851
|
else if (u.current && u.current.isReady) {
|
|
7819
|
-
const
|
|
7820
|
-
u.current.speakText("Now let me ask you some questions to test your understanding.", { lipsyncLang:
|
|
7852
|
+
const E = H.current || { lipsyncLang: "en" };
|
|
7853
|
+
u.current.speakText("Now let me ask you some questions to test your understanding.", { lipsyncLang: E.lipsyncLang });
|
|
7821
7854
|
} else {
|
|
7822
|
-
const
|
|
7823
|
-
u.current && u.current.isReady && (clearInterval(
|
|
7855
|
+
const E = setInterval(() => {
|
|
7856
|
+
u.current && u.current.isReady && (clearInterval(E), R && M());
|
|
7824
7857
|
}, 100);
|
|
7825
7858
|
setTimeout(() => {
|
|
7826
|
-
clearInterval(
|
|
7859
|
+
clearInterval(E);
|
|
7827
7860
|
}, 5e3);
|
|
7828
7861
|
}
|
|
7829
|
-
}, [e.questionStart,
|
|
7830
|
-
const
|
|
7831
|
-
if (a.current.currentQuestionIndex < (
|
|
7862
|
+
}, [e.questionStart, v, L]), F = N(() => {
|
|
7863
|
+
const b = v();
|
|
7864
|
+
if (a.current.currentQuestionIndex < (b?.questions?.length || 0) - 1) {
|
|
7832
7865
|
u.current && u.current.stopSpeaking && u.current.stopSpeaking(), a.current.currentQuestionIndex += 1;
|
|
7833
|
-
const
|
|
7834
|
-
|
|
7866
|
+
const R = L();
|
|
7867
|
+
R && d.current.onCustomAction({
|
|
7835
7868
|
type: "nextQuestion",
|
|
7836
7869
|
moduleIndex: a.current.currentModuleIndex,
|
|
7837
7870
|
lessonIndex: a.current.currentLessonIndex,
|
|
7838
7871
|
questionIndex: a.current.currentQuestionIndex,
|
|
7839
7872
|
totalQuestions: a.current.totalQuestions,
|
|
7840
|
-
question:
|
|
7873
|
+
question: R,
|
|
7841
7874
|
score: a.current.score
|
|
7842
7875
|
});
|
|
7843
|
-
const
|
|
7844
|
-
if (!u.current || !
|
|
7876
|
+
const M = () => {
|
|
7877
|
+
if (!u.current || !R) return;
|
|
7845
7878
|
if (u.current.setMood("happy"), u.current.setBodyMovement("idle"), e.nextQuestion)
|
|
7846
7879
|
try {
|
|
7847
7880
|
u.current.playAnimation(e.nextQuestion, !0);
|
|
7848
|
-
} catch (
|
|
7849
|
-
console.warn("Failed to play nextQuestion animation:",
|
|
7881
|
+
} catch (q) {
|
|
7882
|
+
console.warn("Failed to play nextQuestion animation:", q);
|
|
7850
7883
|
}
|
|
7851
|
-
const
|
|
7852
|
-
if (
|
|
7853
|
-
const
|
|
7854
|
-
u.current.speakText(
|
|
7855
|
-
lipsyncLang:
|
|
7884
|
+
const E = H.current || { lipsyncLang: "en" }, ee = v()?.questions?.length || 0, Q = a.current.currentQuestionIndex >= ee - 1;
|
|
7885
|
+
if (R.type === "code_test") {
|
|
7886
|
+
const q = Q ? `Great! Here's your final coding challenge: ${R.question}` : `Great! Now let's move on to your next coding challenge: ${R.question}`;
|
|
7887
|
+
u.current.speakText(q, {
|
|
7888
|
+
lipsyncLang: E.lipsyncLang
|
|
7856
7889
|
});
|
|
7857
|
-
} else if (
|
|
7858
|
-
const
|
|
7859
|
-
u.current.speakText(
|
|
7860
|
-
lipsyncLang:
|
|
7890
|
+
} else if (R.type === "multiple_choice") {
|
|
7891
|
+
const q = Q ? `Alright! Here's your final question: ${R.question}` : `Alright! Here's your next question: ${R.question}`;
|
|
7892
|
+
u.current.speakText(q, {
|
|
7893
|
+
lipsyncLang: E.lipsyncLang
|
|
7861
7894
|
});
|
|
7862
|
-
} else if (
|
|
7863
|
-
const
|
|
7864
|
-
u.current.speakText(
|
|
7865
|
-
lipsyncLang:
|
|
7895
|
+
} else if (R.type === "true_false") {
|
|
7896
|
+
const q = Q ? `Now let's try this final one: ${R.question}` : `Now let's try this one: ${R.question}`;
|
|
7897
|
+
u.current.speakText(q, {
|
|
7898
|
+
lipsyncLang: E.lipsyncLang
|
|
7866
7899
|
});
|
|
7867
7900
|
} else {
|
|
7868
|
-
const
|
|
7869
|
-
u.current.speakText(
|
|
7870
|
-
lipsyncLang:
|
|
7901
|
+
const q = Q ? `Here's your final question: ${R.question}` : `Here's the next question: ${R.question}`;
|
|
7902
|
+
u.current.speakText(q, {
|
|
7903
|
+
lipsyncLang: E.lipsyncLang
|
|
7871
7904
|
});
|
|
7872
7905
|
}
|
|
7873
7906
|
};
|
|
7874
|
-
if (u.current && u.current.isReady &&
|
|
7875
|
-
|
|
7876
|
-
else if (
|
|
7877
|
-
const
|
|
7878
|
-
u.current && u.current.isReady && (clearInterval(
|
|
7907
|
+
if (u.current && u.current.isReady && R)
|
|
7908
|
+
M();
|
|
7909
|
+
else if (R) {
|
|
7910
|
+
const E = setInterval(() => {
|
|
7911
|
+
u.current && u.current.isReady && (clearInterval(E), M());
|
|
7879
7912
|
}, 100);
|
|
7880
7913
|
setTimeout(() => {
|
|
7881
|
-
clearInterval(
|
|
7914
|
+
clearInterval(E);
|
|
7882
7915
|
}, 5e3);
|
|
7883
7916
|
}
|
|
7884
7917
|
} else
|
|
@@ -7889,94 +7922,94 @@ const yt = He(({
|
|
|
7889
7922
|
totalQuestions: a.current.totalQuestions,
|
|
7890
7923
|
score: a.current.score
|
|
7891
7924
|
});
|
|
7892
|
-
}, [e.nextQuestion,
|
|
7893
|
-
const
|
|
7894
|
-
if (a.current.currentLessonIndex < (
|
|
7925
|
+
}, [e.nextQuestion, v, L]), X = N(() => {
|
|
7926
|
+
const b = B.current || { modules: [] }, R = b.modules[a.current.currentModuleIndex];
|
|
7927
|
+
if (a.current.currentLessonIndex < (R?.lessons?.length || 0) - 1) {
|
|
7895
7928
|
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;
|
|
7896
|
-
const
|
|
7929
|
+
const E = b.modules[a.current.currentModuleIndex], D = a.current.currentLessonIndex < (E?.lessons?.length || 0) - 1, ee = a.current.currentModuleIndex < (b.modules?.length || 0) - 1, Q = D || ee;
|
|
7897
7930
|
d.current.onCustomAction({
|
|
7898
7931
|
type: "lessonStart",
|
|
7899
7932
|
moduleIndex: a.current.currentModuleIndex,
|
|
7900
7933
|
lessonIndex: a.current.currentLessonIndex,
|
|
7901
|
-
hasNextLesson:
|
|
7934
|
+
hasNextLesson: Q
|
|
7902
7935
|
}), d.current.onLessonStart({
|
|
7903
7936
|
moduleIndex: a.current.currentModuleIndex,
|
|
7904
7937
|
lessonIndex: a.current.currentLessonIndex,
|
|
7905
|
-
lesson:
|
|
7938
|
+
lesson: v()
|
|
7906
7939
|
}), u.current && (u.current.setMood("happy"), u.current.setBodyMovement("idle"));
|
|
7907
|
-
} else if (a.current.currentModuleIndex < (
|
|
7940
|
+
} else if (a.current.currentModuleIndex < (b.modules?.length || 0) - 1) {
|
|
7908
7941
|
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;
|
|
7909
|
-
const
|
|
7942
|
+
const D = b.modules[a.current.currentModuleIndex], ee = a.current.currentLessonIndex < (D?.lessons?.length || 0) - 1, Q = a.current.currentModuleIndex < (b.modules?.length || 0) - 1, q = ee || Q;
|
|
7910
7943
|
d.current.onCustomAction({
|
|
7911
7944
|
type: "lessonStart",
|
|
7912
7945
|
moduleIndex: a.current.currentModuleIndex,
|
|
7913
7946
|
lessonIndex: a.current.currentLessonIndex,
|
|
7914
|
-
hasNextLesson:
|
|
7947
|
+
hasNextLesson: q
|
|
7915
7948
|
}), d.current.onLessonStart({
|
|
7916
7949
|
moduleIndex: a.current.currentModuleIndex,
|
|
7917
7950
|
lessonIndex: a.current.currentLessonIndex,
|
|
7918
|
-
lesson:
|
|
7951
|
+
lesson: v()
|
|
7919
7952
|
}), u.current && (u.current.setMood("happy"), u.current.setBodyMovement("idle"));
|
|
7920
7953
|
} else
|
|
7921
|
-
|
|
7922
|
-
}, []),
|
|
7923
|
-
const
|
|
7924
|
-
let
|
|
7925
|
-
if (
|
|
7926
|
-
const
|
|
7927
|
-
|
|
7954
|
+
k.current && k.current();
|
|
7955
|
+
}, []), Z = N(() => {
|
|
7956
|
+
const b = v();
|
|
7957
|
+
let R = null;
|
|
7958
|
+
if (b?.avatar_script && b?.body) {
|
|
7959
|
+
const M = b.avatar_script.trim(), E = b.body.trim(), D = M.match(/[.!?]$/) ? " " : ". ";
|
|
7960
|
+
R = `${M}${D}${E}`;
|
|
7928
7961
|
} else
|
|
7929
|
-
|
|
7930
|
-
if (u.current && u.current.isReady &&
|
|
7962
|
+
R = b?.avatar_script || b?.body || null;
|
|
7963
|
+
if (u.current && u.current.isReady && R) {
|
|
7931
7964
|
a.current.isTeaching = !0, a.current.isQuestionMode = !1, a.current.score = 0, a.current.totalQuestions = 0, u.current.setMood("happy");
|
|
7932
|
-
let
|
|
7965
|
+
let M = !1;
|
|
7933
7966
|
if (e.teaching)
|
|
7934
7967
|
try {
|
|
7935
|
-
u.current.playAnimation(e.teaching, !0),
|
|
7936
|
-
} catch (
|
|
7937
|
-
console.warn("Failed to play teaching animation:",
|
|
7968
|
+
u.current.playAnimation(e.teaching, !0), M = !0;
|
|
7969
|
+
} catch (D) {
|
|
7970
|
+
console.warn("Failed to play teaching animation:", D);
|
|
7938
7971
|
}
|
|
7939
|
-
|
|
7940
|
-
const
|
|
7972
|
+
M || u.current.setBodyMovement("gesturing");
|
|
7973
|
+
const E = H.current || { lipsyncLang: "en" };
|
|
7941
7974
|
d.current.onLessonStart({
|
|
7942
7975
|
moduleIndex: a.current.currentModuleIndex,
|
|
7943
7976
|
lessonIndex: a.current.currentLessonIndex,
|
|
7944
|
-
lesson:
|
|
7977
|
+
lesson: b
|
|
7945
7978
|
}), d.current.onCustomAction({
|
|
7946
7979
|
type: "teachingStart",
|
|
7947
7980
|
moduleIndex: a.current.currentModuleIndex,
|
|
7948
7981
|
lessonIndex: a.current.currentLessonIndex,
|
|
7949
|
-
lesson:
|
|
7950
|
-
}), u.current.speakText(
|
|
7951
|
-
lipsyncLang:
|
|
7982
|
+
lesson: b
|
|
7983
|
+
}), u.current.speakText(R, {
|
|
7984
|
+
lipsyncLang: E.lipsyncLang,
|
|
7952
7985
|
onSpeechEnd: () => {
|
|
7953
7986
|
a.current.isTeaching = !1, d.current.onCustomAction({
|
|
7954
7987
|
type: "teachingComplete",
|
|
7955
7988
|
moduleIndex: a.current.currentModuleIndex,
|
|
7956
7989
|
lessonIndex: a.current.currentLessonIndex,
|
|
7957
|
-
lesson:
|
|
7958
|
-
hasQuestions:
|
|
7959
|
-
}),
|
|
7990
|
+
lesson: b,
|
|
7991
|
+
hasQuestions: b.questions && b.questions.length > 0
|
|
7992
|
+
}), b?.code_example && d.current.onCustomAction({
|
|
7960
7993
|
type: "codeExampleReady",
|
|
7961
7994
|
moduleIndex: a.current.currentModuleIndex,
|
|
7962
7995
|
lessonIndex: a.current.currentLessonIndex,
|
|
7963
|
-
lesson:
|
|
7964
|
-
codeExample:
|
|
7996
|
+
lesson: b,
|
|
7997
|
+
codeExample: b.code_example
|
|
7965
7998
|
});
|
|
7966
7999
|
}
|
|
7967
8000
|
});
|
|
7968
8001
|
}
|
|
7969
|
-
}, [e.teaching,
|
|
7970
|
-
const
|
|
7971
|
-
if (
|
|
8002
|
+
}, [e.teaching, v]), ne = N((b) => {
|
|
8003
|
+
const R = L(), M = I(b, R);
|
|
8004
|
+
if (M && (a.current.score += 1), d.current.onQuestionAnswer({
|
|
7972
8005
|
moduleIndex: a.current.currentModuleIndex,
|
|
7973
8006
|
lessonIndex: a.current.currentLessonIndex,
|
|
7974
8007
|
questionIndex: a.current.currentQuestionIndex,
|
|
7975
|
-
answer:
|
|
7976
|
-
isCorrect:
|
|
7977
|
-
question:
|
|
8008
|
+
answer: b,
|
|
8009
|
+
isCorrect: M,
|
|
8010
|
+
question: R
|
|
7978
8011
|
}), u.current)
|
|
7979
|
-
if (
|
|
8012
|
+
if (M) {
|
|
7980
8013
|
if (u.current.setMood("happy"), e.correct)
|
|
7981
8014
|
try {
|
|
7982
8015
|
u.current.playReaction("happy");
|
|
@@ -7984,13 +8017,13 @@ const yt = He(({
|
|
|
7984
8017
|
u.current.setBodyMovement("happy");
|
|
7985
8018
|
}
|
|
7986
8019
|
u.current.setBodyMovement("gesturing");
|
|
7987
|
-
const
|
|
7988
|
-
a.current.currentQuestionIndex >=
|
|
7989
|
-
const
|
|
7990
|
-
console.log("[CurriculumLearning] Answer feedback - questionIndex:", a.current.currentQuestionIndex, "totalQuestions:",
|
|
7991
|
-
const
|
|
7992
|
-
u.current.speakText(
|
|
7993
|
-
lipsyncLang:
|
|
8020
|
+
const D = v()?.questions?.length || 0;
|
|
8021
|
+
a.current.currentQuestionIndex >= D - 1;
|
|
8022
|
+
const ee = a.current.currentQuestionIndex < D - 1;
|
|
8023
|
+
console.log("[CurriculumLearning] Answer feedback - questionIndex:", a.current.currentQuestionIndex, "totalQuestions:", D, "hasNextQuestion:", ee);
|
|
8024
|
+
const Q = R.type === "code_test" ? `Great job! Your code passed all the tests! ${R.explanation || ""}` : `Excellent! That's correct! ${R.explanation || ""}`, q = H.current || { lipsyncLang: "en" };
|
|
8025
|
+
u.current.speakText(Q, {
|
|
8026
|
+
lipsyncLang: q.lipsyncLang,
|
|
7994
8027
|
onSpeechEnd: () => {
|
|
7995
8028
|
d.current.onCustomAction({
|
|
7996
8029
|
type: "answerFeedbackComplete",
|
|
@@ -7998,7 +8031,7 @@ const yt = He(({
|
|
|
7998
8031
|
lessonIndex: a.current.currentLessonIndex,
|
|
7999
8032
|
questionIndex: a.current.currentQuestionIndex,
|
|
8000
8033
|
isCorrect: !0,
|
|
8001
|
-
hasNextQuestion:
|
|
8034
|
+
hasNextQuestion: ee,
|
|
8002
8035
|
score: a.current.score,
|
|
8003
8036
|
totalQuestions: a.current.totalQuestions
|
|
8004
8037
|
});
|
|
@@ -8012,11 +8045,11 @@ const yt = He(({
|
|
|
8012
8045
|
u.current.setBodyMovement("idle");
|
|
8013
8046
|
}
|
|
8014
8047
|
u.current.setBodyMovement("gesturing");
|
|
8015
|
-
const
|
|
8016
|
-
console.log("[CurriculumLearning] Answer feedback (incorrect) - questionIndex:", a.current.currentQuestionIndex, "totalQuestions:",
|
|
8017
|
-
const
|
|
8018
|
-
u.current.speakText(
|
|
8019
|
-
lipsyncLang:
|
|
8048
|
+
const D = v()?.questions?.length || 0, ee = a.current.currentQuestionIndex >= D - 1, Q = a.current.currentQuestionIndex < D - 1;
|
|
8049
|
+
console.log("[CurriculumLearning] Answer feedback (incorrect) - questionIndex:", a.current.currentQuestionIndex, "totalQuestions:", D, "hasNextQuestion:", Q);
|
|
8050
|
+
const q = R.type === "code_test" ? `Your code didn't pass all the tests. ${R.explanation || "Try again!"}` : `Not quite right, but don't worry! ${R.explanation || ""}${ee ? "" : " Let's move on to the next question."}`, Ae = H.current || { lipsyncLang: "en" };
|
|
8051
|
+
u.current.speakText(q, {
|
|
8052
|
+
lipsyncLang: Ae.lipsyncLang,
|
|
8020
8053
|
onSpeechEnd: () => {
|
|
8021
8054
|
d.current.onCustomAction({
|
|
8022
8055
|
type: "answerFeedbackComplete",
|
|
@@ -8024,7 +8057,7 @@ const yt = He(({
|
|
|
8024
8057
|
lessonIndex: a.current.currentLessonIndex,
|
|
8025
8058
|
questionIndex: a.current.currentQuestionIndex,
|
|
8026
8059
|
isCorrect: !1,
|
|
8027
|
-
hasNextQuestion:
|
|
8060
|
+
hasNextQuestion: Q,
|
|
8028
8061
|
score: a.current.score,
|
|
8029
8062
|
totalQuestions: a.current.totalQuestions
|
|
8030
8063
|
});
|
|
@@ -8032,84 +8065,84 @@ const yt = He(({
|
|
|
8032
8065
|
});
|
|
8033
8066
|
}
|
|
8034
8067
|
else {
|
|
8035
|
-
const
|
|
8068
|
+
const D = v()?.questions?.length || 0;
|
|
8036
8069
|
d.current.onCustomAction({
|
|
8037
8070
|
type: "answerFeedbackComplete",
|
|
8038
8071
|
moduleIndex: a.current.currentModuleIndex,
|
|
8039
8072
|
lessonIndex: a.current.currentLessonIndex,
|
|
8040
8073
|
questionIndex: a.current.currentQuestionIndex,
|
|
8041
|
-
isCorrect:
|
|
8042
|
-
hasNextQuestion: a.current.currentQuestionIndex <
|
|
8074
|
+
isCorrect: M,
|
|
8075
|
+
hasNextQuestion: a.current.currentQuestionIndex < D - 1,
|
|
8043
8076
|
score: a.current.score,
|
|
8044
8077
|
totalQuestions: a.current.totalQuestions,
|
|
8045
8078
|
avatarNotReady: !0
|
|
8046
8079
|
});
|
|
8047
8080
|
}
|
|
8048
|
-
}, [e.correct, e.incorrect,
|
|
8049
|
-
const
|
|
8050
|
-
if (!
|
|
8081
|
+
}, [e.correct, e.incorrect, L, v, I]), le = N((b) => {
|
|
8082
|
+
const R = L();
|
|
8083
|
+
if (!b || typeof b != "object") {
|
|
8051
8084
|
console.error("Invalid code test result format. Expected object with {passed: boolean, ...}");
|
|
8052
8085
|
return;
|
|
8053
8086
|
}
|
|
8054
|
-
if (
|
|
8087
|
+
if (R?.type !== "code_test") {
|
|
8055
8088
|
console.warn("Current question is not a code test. Use handleAnswerSelect for other question types.");
|
|
8056
8089
|
return;
|
|
8057
8090
|
}
|
|
8058
|
-
const
|
|
8059
|
-
passed:
|
|
8060
|
-
results:
|
|
8061
|
-
output:
|
|
8062
|
-
error:
|
|
8063
|
-
executionTime:
|
|
8064
|
-
testCount:
|
|
8065
|
-
passedCount:
|
|
8066
|
-
failedCount:
|
|
8091
|
+
const M = {
|
|
8092
|
+
passed: b.passed === !0,
|
|
8093
|
+
results: b.results || [],
|
|
8094
|
+
output: b.output || "",
|
|
8095
|
+
error: b.error || null,
|
|
8096
|
+
executionTime: b.executionTime || null,
|
|
8097
|
+
testCount: b.testCount || 0,
|
|
8098
|
+
passedCount: b.passedCount || 0,
|
|
8099
|
+
failedCount: b.failedCount || 0
|
|
8067
8100
|
};
|
|
8068
8101
|
d.current.onCustomAction({
|
|
8069
8102
|
type: "codeTestSubmitted",
|
|
8070
8103
|
moduleIndex: a.current.currentModuleIndex,
|
|
8071
8104
|
lessonIndex: a.current.currentLessonIndex,
|
|
8072
8105
|
questionIndex: a.current.currentQuestionIndex,
|
|
8073
|
-
testResult:
|
|
8074
|
-
question:
|
|
8075
|
-
}), p.current && p.current(
|
|
8076
|
-
}, [
|
|
8106
|
+
testResult: M,
|
|
8107
|
+
question: R
|
|
8108
|
+
}), p.current && p.current(M);
|
|
8109
|
+
}, [L, I]), ge = N(() => {
|
|
8077
8110
|
if (a.current.currentQuestionIndex > 0) {
|
|
8078
8111
|
a.current.currentQuestionIndex -= 1;
|
|
8079
|
-
const
|
|
8080
|
-
|
|
8112
|
+
const b = L();
|
|
8113
|
+
b && d.current.onCustomAction({
|
|
8081
8114
|
type: "questionStart",
|
|
8082
8115
|
moduleIndex: a.current.currentModuleIndex,
|
|
8083
8116
|
lessonIndex: a.current.currentLessonIndex,
|
|
8084
8117
|
questionIndex: a.current.currentQuestionIndex,
|
|
8085
8118
|
totalQuestions: a.current.totalQuestions,
|
|
8086
|
-
question:
|
|
8119
|
+
question: b,
|
|
8087
8120
|
score: a.current.score
|
|
8088
8121
|
});
|
|
8089
|
-
const
|
|
8090
|
-
if (!u.current || !
|
|
8122
|
+
const R = () => {
|
|
8123
|
+
if (!u.current || !b) return;
|
|
8091
8124
|
u.current.setMood("happy"), u.current.setBodyMovement("idle");
|
|
8092
|
-
const
|
|
8093
|
-
|
|
8094
|
-
lipsyncLang:
|
|
8095
|
-
}) : u.current.speakText(`Going back to: ${
|
|
8096
|
-
lipsyncLang:
|
|
8125
|
+
const M = H.current || { lipsyncLang: "en" };
|
|
8126
|
+
b.type === "code_test" ? u.current.speakText(`Let's go back to this coding challenge: ${b.question}`, {
|
|
8127
|
+
lipsyncLang: M.lipsyncLang
|
|
8128
|
+
}) : u.current.speakText(`Going back to: ${b.question}`, {
|
|
8129
|
+
lipsyncLang: M.lipsyncLang
|
|
8097
8130
|
});
|
|
8098
8131
|
};
|
|
8099
|
-
if (u.current && u.current.isReady &&
|
|
8100
|
-
|
|
8101
|
-
else if (
|
|
8102
|
-
const
|
|
8103
|
-
u.current && u.current.isReady && (clearInterval(
|
|
8132
|
+
if (u.current && u.current.isReady && b)
|
|
8133
|
+
R();
|
|
8134
|
+
else if (b) {
|
|
8135
|
+
const M = setInterval(() => {
|
|
8136
|
+
u.current && u.current.isReady && (clearInterval(M), R());
|
|
8104
8137
|
}, 100);
|
|
8105
8138
|
setTimeout(() => {
|
|
8106
|
-
clearInterval(
|
|
8139
|
+
clearInterval(M);
|
|
8107
8140
|
}, 5e3);
|
|
8108
8141
|
}
|
|
8109
8142
|
}
|
|
8110
|
-
}, [
|
|
8111
|
-
const
|
|
8112
|
-
if (
|
|
8143
|
+
}, [L]), de = N(() => {
|
|
8144
|
+
const b = B.current || { modules: [] };
|
|
8145
|
+
if (b.modules[a.current.currentModuleIndex], a.current.currentLessonIndex > 0)
|
|
8113
8146
|
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({
|
|
8114
8147
|
type: "lessonStart",
|
|
8115
8148
|
moduleIndex: a.current.currentModuleIndex,
|
|
@@ -8117,66 +8150,66 @@ const yt = He(({
|
|
|
8117
8150
|
}), d.current.onLessonStart({
|
|
8118
8151
|
moduleIndex: a.current.currentModuleIndex,
|
|
8119
8152
|
lessonIndex: a.current.currentLessonIndex,
|
|
8120
|
-
lesson:
|
|
8153
|
+
lesson: v()
|
|
8121
8154
|
}), u.current && (u.current.setMood("happy"), u.current.setBodyMovement("idle"));
|
|
8122
8155
|
else if (a.current.currentModuleIndex > 0) {
|
|
8123
|
-
const
|
|
8124
|
-
a.current.currentModuleIndex -= 1, a.current.currentLessonIndex = (
|
|
8156
|
+
const E = b.modules[a.current.currentModuleIndex - 1];
|
|
8157
|
+
a.current.currentModuleIndex -= 1, a.current.currentLessonIndex = (E?.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({
|
|
8125
8158
|
type: "lessonStart",
|
|
8126
8159
|
moduleIndex: a.current.currentModuleIndex,
|
|
8127
8160
|
lessonIndex: a.current.currentLessonIndex
|
|
8128
8161
|
}), d.current.onLessonStart({
|
|
8129
8162
|
moduleIndex: a.current.currentModuleIndex,
|
|
8130
8163
|
lessonIndex: a.current.currentLessonIndex,
|
|
8131
|
-
lesson:
|
|
8164
|
+
lesson: v()
|
|
8132
8165
|
}), u.current && (u.current.setMood("happy"), u.current.setBodyMovement("idle"));
|
|
8133
8166
|
}
|
|
8134
|
-
}, [
|
|
8167
|
+
}, [v]), $ = N(() => {
|
|
8135
8168
|
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;
|
|
8136
|
-
}, []),
|
|
8137
|
-
console.log("Avatar is ready!",
|
|
8138
|
-
const
|
|
8139
|
-
h &&
|
|
8169
|
+
}, []), be = N((b) => {
|
|
8170
|
+
console.log("Avatar is ready!", b);
|
|
8171
|
+
const R = v(), M = R?.avatar_script || R?.body;
|
|
8172
|
+
h && M && setTimeout(() => {
|
|
8140
8173
|
c.current && c.current();
|
|
8141
8174
|
}, 10);
|
|
8142
|
-
}, [h,
|
|
8175
|
+
}, [h, v]);
|
|
8143
8176
|
Xe(() => {
|
|
8144
|
-
c.current =
|
|
8145
|
-
}),
|
|
8177
|
+
c.current = Z, g.current = X, x.current = z, f.current = F, k.current = Y, O.current = S, p.current = ne;
|
|
8178
|
+
}), Fe(r, () => ({
|
|
8146
8179
|
// Curriculum control methods
|
|
8147
|
-
startTeaching:
|
|
8148
|
-
startQuestions:
|
|
8149
|
-
handleAnswerSelect:
|
|
8150
|
-
handleCodeTestResult:
|
|
8151
|
-
nextQuestion:
|
|
8152
|
-
previousQuestion:
|
|
8153
|
-
nextLesson:
|
|
8154
|
-
previousLesson:
|
|
8155
|
-
completeLesson:
|
|
8156
|
-
completeCurriculum:
|
|
8157
|
-
resetCurriculum:
|
|
8180
|
+
startTeaching: Z,
|
|
8181
|
+
startQuestions: S,
|
|
8182
|
+
handleAnswerSelect: ne,
|
|
8183
|
+
handleCodeTestResult: le,
|
|
8184
|
+
nextQuestion: F,
|
|
8185
|
+
previousQuestion: ge,
|
|
8186
|
+
nextLesson: X,
|
|
8187
|
+
previousLesson: de,
|
|
8188
|
+
completeLesson: z,
|
|
8189
|
+
completeCurriculum: Y,
|
|
8190
|
+
resetCurriculum: $,
|
|
8158
8191
|
getState: () => ({ ...a.current }),
|
|
8159
|
-
getCurrentQuestion: () =>
|
|
8160
|
-
getCurrentLesson: () =>
|
|
8192
|
+
getCurrentQuestion: () => L(),
|
|
8193
|
+
getCurrentLesson: () => v(),
|
|
8161
8194
|
// Direct access to avatar ref (always returns current value)
|
|
8162
8195
|
getAvatarRef: () => u.current,
|
|
8163
8196
|
// Convenience methods that delegate to avatar (always check current ref)
|
|
8164
|
-
speakText: async (
|
|
8197
|
+
speakText: async (b, R = {}) => {
|
|
8165
8198
|
await u.current?.resumeAudioContext?.();
|
|
8166
|
-
const
|
|
8167
|
-
u.current?.speakText(
|
|
8199
|
+
const M = H.current || { lipsyncLang: "en" };
|
|
8200
|
+
u.current?.speakText(b, { ...R, lipsyncLang: R.lipsyncLang || M.lipsyncLang });
|
|
8168
8201
|
},
|
|
8169
8202
|
resumeAudioContext: async () => {
|
|
8170
8203
|
if (u.current?.resumeAudioContext)
|
|
8171
8204
|
return await u.current.resumeAudioContext();
|
|
8172
|
-
const
|
|
8173
|
-
if (
|
|
8174
|
-
const
|
|
8175
|
-
if (
|
|
8205
|
+
const b = u.current?.talkingHead;
|
|
8206
|
+
if (b?.audioCtx) {
|
|
8207
|
+
const R = b.audioCtx;
|
|
8208
|
+
if (R.state === "suspended" || R.state === "interrupted")
|
|
8176
8209
|
try {
|
|
8177
|
-
await
|
|
8178
|
-
} catch (
|
|
8179
|
-
console.warn("Failed to resume audio context:",
|
|
8210
|
+
await R.resume(), console.log("Audio context resumed via talkingHead");
|
|
8211
|
+
} catch (M) {
|
|
8212
|
+
console.warn("Failed to resume audio context:", M);
|
|
8180
8213
|
}
|
|
8181
8214
|
} else
|
|
8182
8215
|
console.warn("Audio context not available yet");
|
|
@@ -8185,22 +8218,22 @@ const yt = He(({
|
|
|
8185
8218
|
pauseSpeaking: () => u.current?.pauseSpeaking(),
|
|
8186
8219
|
resumeSpeaking: async () => await u.current?.resumeSpeaking(),
|
|
8187
8220
|
isPaused: () => u.current && typeof u.current.isPaused < "u" ? u.current.isPaused : !1,
|
|
8188
|
-
setMood: (
|
|
8189
|
-
playAnimation: (
|
|
8190
|
-
setBodyMovement: (
|
|
8191
|
-
setMovementIntensity: (
|
|
8221
|
+
setMood: (b) => u.current?.setMood(b),
|
|
8222
|
+
playAnimation: (b, R) => u.current?.playAnimation(b, R),
|
|
8223
|
+
setBodyMovement: (b) => u.current?.setBodyMovement(b),
|
|
8224
|
+
setMovementIntensity: (b) => u.current?.setMovementIntensity(b),
|
|
8192
8225
|
playRandomDance: () => u.current?.playRandomDance(),
|
|
8193
|
-
playReaction: (
|
|
8226
|
+
playReaction: (b) => u.current?.playReaction(b),
|
|
8194
8227
|
playCelebration: () => u.current?.playCelebration(),
|
|
8195
|
-
setShowFullAvatar: (
|
|
8196
|
-
setTimingAdjustment: (
|
|
8228
|
+
setShowFullAvatar: (b) => u.current?.setShowFullAvatar(b),
|
|
8229
|
+
setTimingAdjustment: (b) => u.current?.setTimingAdjustment(b),
|
|
8197
8230
|
lockAvatarPosition: () => u.current?.lockAvatarPosition(),
|
|
8198
8231
|
unlockAvatarPosition: () => u.current?.unlockAvatarPosition(),
|
|
8199
8232
|
// Custom action trigger
|
|
8200
|
-
triggerCustomAction: (
|
|
8233
|
+
triggerCustomAction: (b, R) => {
|
|
8201
8234
|
d.current.onCustomAction({
|
|
8202
|
-
type:
|
|
8203
|
-
...
|
|
8235
|
+
type: b,
|
|
8236
|
+
...R,
|
|
8204
8237
|
state: { ...a.current }
|
|
8205
8238
|
});
|
|
8206
8239
|
},
|
|
@@ -8208,8 +8241,8 @@ const yt = He(({
|
|
|
8208
8241
|
handleResize: () => u.current?.handleResize(),
|
|
8209
8242
|
// Avatar readiness check (always returns current value)
|
|
8210
8243
|
isAvatarReady: () => u.current?.isReady || !1
|
|
8211
|
-
}), [
|
|
8212
|
-
const j =
|
|
8244
|
+
}), [Z, S, ne, le, F, X, z, Y, $, L, v]);
|
|
8245
|
+
const j = H.current || {
|
|
8213
8246
|
avatarUrl: "/avatars/brunette.glb",
|
|
8214
8247
|
avatarBody: "F",
|
|
8215
8248
|
mood: "happy",
|
|
@@ -8222,7 +8255,7 @@ const yt = He(({
|
|
|
8222
8255
|
showFullAvatar: !1,
|
|
8223
8256
|
animations: e
|
|
8224
8257
|
};
|
|
8225
|
-
return /* @__PURE__ */
|
|
8258
|
+
return /* @__PURE__ */ ye("div", { style: { width: "100%", height: "100%" }, children: /* @__PURE__ */ ye(
|
|
8226
8259
|
Ve,
|
|
8227
8260
|
{
|
|
8228
8261
|
ref: u,
|
|
@@ -8238,16 +8271,16 @@ const yt = He(({
|
|
|
8238
8271
|
showFullAvatar: j.showFullAvatar,
|
|
8239
8272
|
cameraView: "upper",
|
|
8240
8273
|
animations: j.animations,
|
|
8241
|
-
onReady:
|
|
8274
|
+
onReady: be,
|
|
8242
8275
|
onLoading: () => {
|
|
8243
8276
|
},
|
|
8244
|
-
onError: (
|
|
8245
|
-
console.error("Avatar error:",
|
|
8277
|
+
onError: (b) => {
|
|
8278
|
+
console.error("Avatar error:", b);
|
|
8246
8279
|
}
|
|
8247
8280
|
}
|
|
8248
8281
|
) });
|
|
8249
8282
|
});
|
|
8250
|
-
|
|
8283
|
+
ft.displayName = "CurriculumLearning";
|
|
8251
8284
|
const Ge = {
|
|
8252
8285
|
// Code-based dance animations (no FBX required)
|
|
8253
8286
|
dance: {
|
|
@@ -8351,15 +8384,15 @@ const Ge = {
|
|
|
8351
8384
|
duration: 5e3,
|
|
8352
8385
|
description: "Excited, energetic movement"
|
|
8353
8386
|
}
|
|
8354
|
-
},
|
|
8387
|
+
}, zt = (V) => Ge[V] || null, Ct = (V) => Ge.hasOwnProperty(V);
|
|
8355
8388
|
export {
|
|
8356
|
-
|
|
8357
|
-
|
|
8389
|
+
ft as CurriculumLearning,
|
|
8390
|
+
yt as SimpleTalkingAvatar,
|
|
8358
8391
|
Ve as TalkingHeadAvatar,
|
|
8359
8392
|
pt as TalkingHeadComponent,
|
|
8360
8393
|
Ge as animations,
|
|
8361
|
-
|
|
8362
|
-
|
|
8363
|
-
|
|
8364
|
-
|
|
8394
|
+
Ee as getActiveTTSConfig,
|
|
8395
|
+
zt as getAnimation,
|
|
8396
|
+
wt as getVoiceOptions,
|
|
8397
|
+
Ct as hasAnimation
|
|
8365
8398
|
};
|