@sage-rsc/talking-head-react 1.4.7 → 1.4.8
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 +764 -769
- package/package.json +1 -1
- package/src/lib/talkinghead.mjs +2 -12
package/dist/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { jsxs as Pe, jsx as ye } from "react/jsx-runtime";
|
|
2
|
-
import { forwardRef as Me, useRef as
|
|
2
|
+
import { forwardRef as Me, useRef as W, useState as pe, useEffect as ce, useCallback as O, useImperativeHandle as Fe, useLayoutEffect as Xe } from "react";
|
|
3
3
|
import * as y from "three";
|
|
4
4
|
import { OrbitControls as je } from "three/addons/controls/OrbitControls.js";
|
|
5
5
|
import { GLTFLoader as Ye } from "three/addons/loaders/GLTFLoader.js";
|
|
@@ -8,7 +8,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
10
|
let m, ue, he;
|
|
11
|
-
const
|
|
11
|
+
const C = [0, 0, 0, 0], M = 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();
|
|
@@ -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(M).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(M, re, ae), M.copy(He).applyQuaternion(re).setY(0).normalize(), re.premultiply(Ne.setFromUnitVectors(He, M).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], M.copy(o.vWorld), fe.copy(o.boneParent.matrixWorld), xe.copy(fe).invert(), o.vWorld.setFromMatrixPosition(fe), M.applyMatrix4(xe), M.length() > 0.5 && (console.info("Info: Unrealistic jump of " + M.length().toFixed(2) + " meters."), M.setLength(0.5)), M.applyQuaternion(o.bone.quaternion), C[0] = M.x, C[1] = M.y, C[2] = -M.z, C[3] = M.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, M.set(
|
|
363
|
+
o.vBasis.x + C[0],
|
|
364
|
+
o.vBasis.y + C[1],
|
|
365
|
+
o.vBasis.z + C[2]
|
|
366
|
+
), M.applyMatrix4(fe), M.x += m[0], M.y += m[1], M.z += m[2], M.applyMatrix4(xe), C[0] += M.x - o.vBasis.x, C[1] += M.y - o.vBasis.y, C[2] += M.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(M, re, ae), M.copy(He).applyQuaternion(re).setY(0).normalize(), re.premultiply(Ne.setFromUnitVectors(He, M).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], 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),
|
|
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), M.copy(o.bone.position), !(M.distanceToSquared(ae) >= m.radiusSq) && (he = M.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), M.subVectors(M, Ce).projectOnPlane(ae).normalize().multiplyScalar(ue), ze.subVectors(o.vBasis, Ce).projectOnPlane(ae).normalize(), he = ze.dot(M), he < 0 && (he = Math.sqrt(ue * ue - he * he), ze.multiplyScalar(he), M.add(ze)), M.add(Ce).normalize(), ae.copy(o.bone.position).normalize(), re.setFromUnitVectors(ae, M), o.boneParent.quaternion.premultiply(re), o.boneParent.updateWorldMatrix(!1, !0))));
|
|
375
375
|
}
|
|
376
376
|
this.helpers.isActive && this.updateHelpers();
|
|
377
377
|
}
|
|
@@ -445,14 +445,14 @@ class et {
|
|
|
445
445
|
xe.copy(this.armature.matrixWorld).invert();
|
|
446
446
|
const t = m.object.geometry.getAttribute("position");
|
|
447
447
|
for (let e = 0, n = m.bones.length; e < n; e++)
|
|
448
|
-
fe.multiplyMatrices(xe, m.bones[e].matrixWorld),
|
|
448
|
+
fe.multiplyMatrices(xe, m.bones[e].matrixWorld), M.setFromMatrixPosition(fe), t.setXYZ(e, M.x, M.y, M.z);
|
|
449
449
|
t.needsUpdate = !0, m.object.updateMatrixWorld();
|
|
450
450
|
}
|
|
451
451
|
if (m = this.helpers.lines, m.bones.length) {
|
|
452
452
|
xe.copy(this.armature.matrixWorld).invert();
|
|
453
453
|
const t = m.object.geometry.getAttribute("position");
|
|
454
454
|
for (let e = 0, n = 0, i = m.bones.length; e < i; e++, n += 2)
|
|
455
|
-
fe.multiplyMatrices(xe, m.bones[e].matrixWorld),
|
|
455
|
+
fe.multiplyMatrices(xe, m.bones[e].matrixWorld), M.setFromMatrixPosition(fe), t.setXYZ(n, M.x, M.y, M.z), fe.multiplyMatrices(xe, m.bones[e].parent.matrixWorld), M.setFromMatrixPosition(fe), t.setXYZ(n + 1, M.x, M.y, M.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
|
-
}, $ = new y.Quaternion(),
|
|
2632
|
+
}, $ = new y.Quaternion(), Z = 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) {
|
|
@@ -4436,9 +4436,9 @@ class Be {
|
|
|
4436
4436
|
updatePoseDelta() {
|
|
4437
4437
|
for (const [t, e] of Object.entries(this.poseDelta.props)) {
|
|
4438
4438
|
if (e.x === 0 && e.y === 0 && e.z === 0) continue;
|
|
4439
|
-
|
|
4439
|
+
Z.set(e.x, e.y, e.z);
|
|
4440
4440
|
const n = this.poseAvatar.props[t];
|
|
4441
|
-
n.isQuaternion ? ($.setFromEuler(
|
|
4441
|
+
n.isQuaternion ? ($.setFromEuler(Z), n.multiply($)) : n.isVector3 && n.add(Z);
|
|
4442
4442
|
}
|
|
4443
4443
|
}
|
|
4444
4444
|
/**
|
|
@@ -5145,9 +5145,9 @@ class Be {
|
|
|
5145
5145
|
g.newvalue = c[i];
|
|
5146
5146
|
else {
|
|
5147
5147
|
g.newvalue = c[i + 1];
|
|
5148
|
-
const
|
|
5149
|
-
let
|
|
5150
|
-
|
|
5148
|
+
const x = a.ts[i + 1] - a.ts[i];
|
|
5149
|
+
let f = 1;
|
|
5150
|
+
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;
|
|
5151
5151
|
}
|
|
5152
5152
|
if (l)
|
|
5153
5153
|
switch (d) {
|
|
@@ -5210,7 +5210,7 @@ class Be {
|
|
|
5210
5210
|
}, i.x ? new y.Vector3(i.x, i.y, i.z) : null, !0, i.d);
|
|
5211
5211
|
break;
|
|
5212
5212
|
}
|
|
5213
|
-
if ((h || r) && (
|
|
5213
|
+
if ((h || r) && (Z.setFromQuaternion(this.poseAvatar.props["Head.quaternion"]), Z.x = Math.max(-0.9, Math.min(0.9, 2 * Z.x - 0.5)), Z.y = Math.max(-0.9, Math.min(0.9, -2.5 * Z.y)), h ? (Object.assign(this.mtAvatar.eyesLookDown, { system: Z.x < 0 ? -Z.x : 0, needsUpdate: !0 }), Object.assign(this.mtAvatar.eyesLookUp, { system: Z.x < 0 ? 0 : Z.x, needsUpdate: !0 }), Object.assign(this.mtAvatar.eyeLookInLeft, { system: Z.y < 0 ? -Z.y : 0, needsUpdate: !0 }), Object.assign(this.mtAvatar.eyeLookOutLeft, { system: Z.y < 0 ? 0 : Z.y, needsUpdate: !0 }), Object.assign(this.mtAvatar.eyeLookInRight, { system: Z.y < 0 ? 0 : Z.y, needsUpdate: !0 }), Object.assign(this.mtAvatar.eyeLookOutRight, { system: Z.y < 0 ? -Z.y : 0, needsUpdate: !0 }), r && (n = -this.mtAvatar.bodyRotateY.value, i = this.gaussianRandom(-0.2, 0.2), this.animQueue.push(this.animFactory({
|
|
5214
5214
|
name: "headmove",
|
|
5215
5215
|
dt: [[1e3, 2e3], [1e3, 2e3, 1, 2], [1e3, 2e3], [1e3, 2e3, 1, 2]],
|
|
5216
5216
|
vs: {
|
|
@@ -5300,12 +5300,12 @@ class Be {
|
|
|
5300
5300
|
e = e || {};
|
|
5301
5301
|
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;
|
|
5302
5302
|
let u = "", a = "", d = 0, c = [], g = [];
|
|
5303
|
-
const
|
|
5304
|
-
for (let
|
|
5305
|
-
const
|
|
5306
|
-
let p =
|
|
5307
|
-
const
|
|
5308
|
-
if (p && !
|
|
5303
|
+
const x = Array.from(this.segmenter.segment(t), (f) => f.segment);
|
|
5304
|
+
for (let f = 0; f < x.length; f++) {
|
|
5305
|
+
const k = f === x.length - 1, D = x[f].match(l);
|
|
5306
|
+
let p = x[f].match(s);
|
|
5307
|
+
const B = x[f].match(h), T = x[f].match(o);
|
|
5308
|
+
if (p && !k && !B && x[f + 1].match(s) && (p = !1), n && (u += x[f]), D && (!i || i.every((R) => f < R[0] || f > R[1])) && (a += x[f]), (T || p || k) && (a.length && (a = this.lipsyncPreProcessText(a, r), a.length && c.push({
|
|
5309
5309
|
mark: d,
|
|
5310
5310
|
word: a
|
|
5311
5311
|
})), u.length && (g.push({
|
|
@@ -5316,31 +5316,31 @@ class Be {
|
|
|
5316
5316
|
subtitles: [u]
|
|
5317
5317
|
}
|
|
5318
5318
|
}), u = ""), a.length)) {
|
|
5319
|
-
const
|
|
5320
|
-
if (
|
|
5321
|
-
const
|
|
5322
|
-
for (let
|
|
5319
|
+
const R = this.lipsyncWordsToVisemes(a, r);
|
|
5320
|
+
if (R && R.visemes && R.visemes.length) {
|
|
5321
|
+
const L = R.times[R.visemes.length - 1] + R.durations[R.visemes.length - 1];
|
|
5322
|
+
for (let I = 0; I < R.visemes.length; I++)
|
|
5323
5323
|
g.push({
|
|
5324
5324
|
mark: d,
|
|
5325
5325
|
template: { name: "viseme" },
|
|
5326
|
-
ts: [(
|
|
5326
|
+
ts: [(R.times[I] - 0.6) / L, (R.times[I] + 0.5) / L, (R.times[I] + R.durations[I] + 0.5) / L],
|
|
5327
5327
|
vs: {
|
|
5328
|
-
["viseme_" +
|
|
5328
|
+
["viseme_" + R.visemes[I]]: [null, R.visemes[I] === "PP" || R.visemes[I] === "FF" ? 0.9 : 0.6, 0]
|
|
5329
5329
|
}
|
|
5330
5330
|
});
|
|
5331
5331
|
}
|
|
5332
5332
|
a = "", d++;
|
|
5333
5333
|
}
|
|
5334
|
-
if (p ||
|
|
5335
|
-
if (c.length ||
|
|
5336
|
-
const
|
|
5334
|
+
if (p || k) {
|
|
5335
|
+
if (c.length || k && g.length) {
|
|
5336
|
+
const R = {
|
|
5337
5337
|
anim: g
|
|
5338
5338
|
};
|
|
5339
|
-
n && (
|
|
5339
|
+
n && (R.onSubtitles = n), c.length && !e.avatarMute && (R.text = c, e.avatarMood && (R.mood = e.avatarMood), e.ttsLang && (R.lang = e.ttsLang), e.ttsVoice && (R.voice = e.ttsVoice), e.ttsRate && (R.rate = e.ttsRate), e.ttsVoice && (R.pitch = e.ttsPitch), e.ttsVolume && (R.volume = e.ttsVolume)), this.speechQueue.push(R), c = [], a = "", d = 0, g = [];
|
|
5340
5340
|
}
|
|
5341
|
-
if (
|
|
5342
|
-
let
|
|
5343
|
-
|
|
5341
|
+
if (B) {
|
|
5342
|
+
let R = this.animEmojis[x[f]];
|
|
5343
|
+
R && R.link && (R = this.animEmojis[R.link]), R && this.speechQueue.push({ emoji: R });
|
|
5344
5344
|
}
|
|
5345
5345
|
this.speechQueue.push({ break: 100 });
|
|
5346
5346
|
}
|
|
@@ -5433,15 +5433,15 @@ class Be {
|
|
|
5433
5433
|
const a = this.lipsyncPreProcessText(h, i), d = this.lipsyncWordsToVisemes(a, i);
|
|
5434
5434
|
if (d && d.visemes && d.visemes.length) {
|
|
5435
5435
|
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));
|
|
5436
|
-
let
|
|
5436
|
+
let x = 0.6 + this.convertRange(g, [0, u], [0, 0.4]);
|
|
5437
5437
|
if (u = Math.min(u, d.visemes.length * 200), c > 0)
|
|
5438
|
-
for (let
|
|
5439
|
-
const
|
|
5438
|
+
for (let f = 0; f < d.visemes.length; f++) {
|
|
5439
|
+
const k = r + d.times[f] / c * u, D = d.durations[f] / c * u;
|
|
5440
5440
|
o.push({
|
|
5441
5441
|
template: { name: "viseme" },
|
|
5442
|
-
ts: [
|
|
5442
|
+
ts: [k - Math.min(60, 2 * D / 3), k + Math.min(25, D / 2), k + D + Math.min(60, D / 2)],
|
|
5443
5443
|
vs: {
|
|
5444
|
-
["viseme_" + d.visemes[
|
|
5444
|
+
["viseme_" + d.visemes[f]]: [null, d.visemes[f] === "PP" || d.visemes[f] === "FF" ? 0.9 : x, 0]
|
|
5445
5445
|
}
|
|
5446
5446
|
});
|
|
5447
5447
|
}
|
|
@@ -5521,34 +5521,34 @@ class Be {
|
|
|
5521
5521
|
s.lang = o, s.rate = Math.max(0.1, Math.min(10, l)), s.pitch = Math.max(0, Math.min(2, h)), s.volume = Math.max(0, Math.min(1, r));
|
|
5522
5522
|
const u = speechSynthesis.getVoices(), a = t.voice || this.avatar.ttsVoice || this.opt.ttsVoice;
|
|
5523
5523
|
if (a && u.length > 0) {
|
|
5524
|
-
const p = u.find((
|
|
5524
|
+
const p = u.find((B) => B.name.includes(a) || B.lang === o);
|
|
5525
5525
|
p && (s.voice = p);
|
|
5526
5526
|
}
|
|
5527
|
-
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",
|
|
5527
|
+
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);
|
|
5528
5528
|
console.log("Browser TTS Lip-sync Debug:", {
|
|
5529
5529
|
text: i,
|
|
5530
5530
|
lipsyncLang: g,
|
|
5531
|
-
processedText:
|
|
5532
|
-
lipsyncData:
|
|
5533
|
-
hasVisemes:
|
|
5531
|
+
processedText: x,
|
|
5532
|
+
lipsyncData: f,
|
|
5533
|
+
hasVisemes: f && f.visemes && f.visemes.length > 0,
|
|
5534
5534
|
estimatedDuration: d
|
|
5535
5535
|
});
|
|
5536
|
-
const
|
|
5537
|
-
if (
|
|
5538
|
-
const p =
|
|
5539
|
-
for (let
|
|
5540
|
-
const
|
|
5541
|
-
|
|
5536
|
+
const k = [];
|
|
5537
|
+
if (f && f.visemes && f.visemes.length > 0) {
|
|
5538
|
+
const p = f.times[f.visemes.length - 1] + f.durations[f.visemes.length - 1];
|
|
5539
|
+
for (let B = 0; B < f.visemes.length; B++) {
|
|
5540
|
+
const T = f.visemes[B], R = f.times[B] / p, L = f.durations[B] / p, I = R * d, z = L * d;
|
|
5541
|
+
k.push({
|
|
5542
5542
|
template: { name: "viseme" },
|
|
5543
|
-
ts: [
|
|
5543
|
+
ts: [I - Math.min(60, 2 * z / 3), I + Math.min(25, z / 2), I + z + Math.min(60, z / 2)],
|
|
5544
5544
|
vs: {
|
|
5545
|
-
["viseme_" +
|
|
5545
|
+
["viseme_" + T]: [null, T === "PP" || T === "FF" ? 0.9 : 0.6, 0]
|
|
5546
5546
|
}
|
|
5547
5547
|
});
|
|
5548
5548
|
}
|
|
5549
5549
|
}
|
|
5550
|
-
const
|
|
5551
|
-
this.audioPlaylist.push({ anim:
|
|
5550
|
+
const D = [...t.anim, ...k];
|
|
5551
|
+
this.audioPlaylist.push({ anim: D, audio: c }), this.onSubtitles = t.onSubtitles || null, this.resetLips(), t.mood && this.setMood(t.mood), this.playAudio(), s.onend = () => {
|
|
5552
5552
|
e();
|
|
5553
5553
|
}, s.onerror = (p) => {
|
|
5554
5554
|
console.error("Speech synthesis error:", p.error), n(p.error);
|
|
@@ -5597,10 +5597,10 @@ class Be {
|
|
|
5597
5597
|
hasVisemes: c && c.visemes && c.visemes.length > 0
|
|
5598
5598
|
}), c && c.visemes && c.visemes.length > 0)
|
|
5599
5599
|
r = {
|
|
5600
|
-
visemes: c.visemes.map((g,
|
|
5600
|
+
visemes: c.visemes.map((g, x) => ({
|
|
5601
5601
|
viseme: g,
|
|
5602
|
-
startTime:
|
|
5603
|
-
endTime: (
|
|
5602
|
+
startTime: x * l.duration / c.visemes.length,
|
|
5603
|
+
endTime: (x + 1) * l.duration / c.visemes.length,
|
|
5604
5604
|
duration: l.duration / c.visemes.length,
|
|
5605
5605
|
intensity: 0.7
|
|
5606
5606
|
})),
|
|
@@ -5613,16 +5613,16 @@ class Be {
|
|
|
5613
5613
|
} catch (d) {
|
|
5614
5614
|
console.error("Text-based lip-sync failed, using fallback:", d);
|
|
5615
5615
|
const c = e.toLowerCase().split(/\s+/), g = [];
|
|
5616
|
-
for (const
|
|
5617
|
-
for (const
|
|
5618
|
-
let
|
|
5619
|
-
"aeiou".includes(
|
|
5616
|
+
for (const x of c)
|
|
5617
|
+
for (const f of x) {
|
|
5618
|
+
let k = "aa";
|
|
5619
|
+
"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);
|
|
5620
5620
|
}
|
|
5621
5621
|
r = {
|
|
5622
|
-
visemes: g.map((
|
|
5623
|
-
viseme:
|
|
5624
|
-
startTime:
|
|
5625
|
-
endTime: (
|
|
5622
|
+
visemes: g.map((x, f) => ({
|
|
5623
|
+
viseme: x,
|
|
5624
|
+
startTime: f * l.duration / g.length,
|
|
5625
|
+
endTime: (f + 1) * l.duration / g.length,
|
|
5626
5626
|
duration: l.duration / g.length,
|
|
5627
5627
|
intensity: 0.6
|
|
5628
5628
|
})),
|
|
@@ -5647,12 +5647,12 @@ class Be {
|
|
|
5647
5647
|
if (r.visemes && r.visemes.length > 0) {
|
|
5648
5648
|
console.log("ElevenLabs: Generating lip-sync animation from", r.visemes.length, "visemes");
|
|
5649
5649
|
for (let d = 0; d < r.visemes.length; d++) {
|
|
5650
|
-
const c = r.visemes[d], g = c.startTime * 1e3,
|
|
5650
|
+
const c = r.visemes[d], g = c.startTime * 1e3, x = c.duration * 1e3, f = c.intensity;
|
|
5651
5651
|
u.push({
|
|
5652
5652
|
template: { name: "viseme" },
|
|
5653
|
-
ts: [g - Math.min(60, 2 *
|
|
5653
|
+
ts: [g - Math.min(60, 2 * x / 3), g + Math.min(25, x / 2), g + x + Math.min(60, x / 2)],
|
|
5654
5654
|
vs: {
|
|
5655
|
-
["viseme_" + c.viseme]: [null,
|
|
5655
|
+
["viseme_" + c.viseme]: [null, f, 0]
|
|
5656
5656
|
}
|
|
5657
5657
|
});
|
|
5658
5658
|
}
|
|
@@ -5695,10 +5695,10 @@ class Be {
|
|
|
5695
5695
|
hasVisemes: c && c.visemes && c.visemes.length > 0
|
|
5696
5696
|
}), c && c.visemes && c.visemes.length > 0)
|
|
5697
5697
|
r = {
|
|
5698
|
-
visemes: c.visemes.map((g,
|
|
5698
|
+
visemes: c.visemes.map((g, x) => ({
|
|
5699
5699
|
viseme: g,
|
|
5700
|
-
startTime:
|
|
5701
|
-
endTime: (
|
|
5700
|
+
startTime: x * l.duration / c.visemes.length,
|
|
5701
|
+
endTime: (x + 1) * l.duration / c.visemes.length,
|
|
5702
5702
|
duration: l.duration / c.visemes.length,
|
|
5703
5703
|
intensity: 0.7
|
|
5704
5704
|
})),
|
|
@@ -5711,16 +5711,16 @@ class Be {
|
|
|
5711
5711
|
} catch (d) {
|
|
5712
5712
|
console.error("Text-based lip-sync failed, using fallback:", d);
|
|
5713
5713
|
const c = e.toLowerCase().split(/\s+/), g = [];
|
|
5714
|
-
for (const
|
|
5715
|
-
for (const
|
|
5716
|
-
let
|
|
5717
|
-
"aeiou".includes(
|
|
5714
|
+
for (const x of c)
|
|
5715
|
+
for (const f of x) {
|
|
5716
|
+
let k = "aa";
|
|
5717
|
+
"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);
|
|
5718
5718
|
}
|
|
5719
5719
|
r = {
|
|
5720
|
-
visemes: g.map((
|
|
5721
|
-
viseme:
|
|
5722
|
-
startTime:
|
|
5723
|
-
endTime: (
|
|
5720
|
+
visemes: g.map((x, f) => ({
|
|
5721
|
+
viseme: x,
|
|
5722
|
+
startTime: f * l.duration / g.length,
|
|
5723
|
+
endTime: (f + 1) * l.duration / g.length,
|
|
5724
5724
|
duration: l.duration / g.length,
|
|
5725
5725
|
intensity: 0.6
|
|
5726
5726
|
})),
|
|
@@ -5745,12 +5745,12 @@ class Be {
|
|
|
5745
5745
|
if (r.visemes && r.visemes.length > 0) {
|
|
5746
5746
|
console.log("Deepgram: Generating lip-sync animation from", r.visemes.length, "visemes");
|
|
5747
5747
|
for (let d = 0; d < r.visemes.length; d++) {
|
|
5748
|
-
const c = r.visemes[d], g = c.startTime * 1e3,
|
|
5748
|
+
const c = r.visemes[d], g = c.startTime * 1e3, x = c.duration * 1e3, f = c.intensity;
|
|
5749
5749
|
u.push({
|
|
5750
5750
|
template: { name: "viseme" },
|
|
5751
|
-
ts: [g - Math.min(60, 2 *
|
|
5751
|
+
ts: [g - Math.min(60, 2 * x / 3), g + Math.min(25, x / 2), g + x + Math.min(60, x / 2)],
|
|
5752
5752
|
vs: {
|
|
5753
|
-
["viseme_" + c.viseme]: [null,
|
|
5753
|
+
["viseme_" + c.viseme]: [null, f, 0]
|
|
5754
5754
|
}
|
|
5755
5755
|
});
|
|
5756
5756
|
}
|
|
@@ -5797,12 +5797,12 @@ class Be {
|
|
|
5797
5797
|
});
|
|
5798
5798
|
const r = [];
|
|
5799
5799
|
for (let a = 0; a < h.visemes.length; a++) {
|
|
5800
|
-
const d = h.visemes[a], c = d.startTime * 1e3, g = d.duration * 1e3,
|
|
5800
|
+
const d = h.visemes[a], c = d.startTime * 1e3, g = d.duration * 1e3, x = d.intensity;
|
|
5801
5801
|
r.push({
|
|
5802
5802
|
template: { name: "viseme" },
|
|
5803
5803
|
ts: [c - Math.min(60, 2 * g / 3), c + Math.min(25, g / 2), c + g + Math.min(60, g / 2)],
|
|
5804
5804
|
vs: {
|
|
5805
|
-
["viseme_" + d.viseme]: [null,
|
|
5805
|
+
["viseme_" + d.viseme]: [null, x, 0]
|
|
5806
5806
|
}
|
|
5807
5807
|
});
|
|
5808
5808
|
}
|
|
@@ -6088,10 +6088,10 @@ class Be {
|
|
|
6088
6088
|
let d = 0.6 + this.convertRange(a, [0, o], [0, 0.4]);
|
|
6089
6089
|
if (o = Math.min(o, r.visemes.length * 200), u > 0)
|
|
6090
6090
|
for (let c = 0; c < r.visemes.length; c++) {
|
|
6091
|
-
const g = e + s + r.times[c] / u * o,
|
|
6091
|
+
const g = e + s + r.times[c] / u * o, x = r.durations[c] / u * o;
|
|
6092
6092
|
this.animQueue.push({
|
|
6093
6093
|
template: { name: "viseme" },
|
|
6094
|
-
ts: [g - Math.min(60, 2 *
|
|
6094
|
+
ts: [g - Math.min(60, 2 * x / 3), g + Math.min(25, x / 2), g + x + Math.min(60, x / 2)],
|
|
6095
6095
|
vs: {
|
|
6096
6096
|
["viseme_" + r.visemes[c]]: [null, r.visemes[c] === "PP" || r.visemes[c] === "FF" ? 0.9 : d, 0]
|
|
6097
6097
|
}
|
|
@@ -6199,14 +6199,14 @@ class Be {
|
|
|
6199
6199
|
}
|
|
6200
6200
|
this.objectLeftEye.updateMatrixWorld(!0), this.objectRightEye.updateMatrixWorld(!0), ve.setFromMatrixPosition(this.objectLeftEye.matrixWorld), Re.setFromMatrixPosition(this.objectRightEye.matrixWorld), ve.add(Re).divideScalar(2), $.copy(this.armature.quaternion), $.multiply(this.poseTarget.props["Hips.quaternion"]), $.multiply(this.poseTarget.props["Spine.quaternion"]), $.multiply(this.poseTarget.props["Spine1.quaternion"]), $.multiply(this.poseTarget.props["Spine2.quaternion"]), $.multiply(this.poseTarget.props["Neck.quaternion"]), $.multiply(this.poseTarget.props["Head.quaternion"]);
|
|
6201
6201
|
const n = new y.Vector3().subVectors(e, ve).normalize(), i = Math.atan2(n.x, n.z), s = Math.asin(-n.y);
|
|
6202
|
-
|
|
6203
|
-
const l = new y.Quaternion().setFromEuler(
|
|
6204
|
-
|
|
6205
|
-
let r =
|
|
6202
|
+
Z.set(s, i, 0, "YXZ");
|
|
6203
|
+
const l = new y.Quaternion().setFromEuler(Z), h = new y.Quaternion().copy(l).multiply($.clone().invert());
|
|
6204
|
+
Z.setFromQuaternion(h, "YXZ");
|
|
6205
|
+
let r = Z.x / (40 / 24) + 0.2, u = Z.y / (9 / 4), a = Math.min(0.6, Math.max(-0.3, r)), d = Math.min(0.8, Math.max(-0.8, u)), c = (Math.random() - 0.5) / 4, g = (Math.random() - 0.5) / 4;
|
|
6206
6206
|
if (t) {
|
|
6207
|
-
let
|
|
6208
|
-
|
|
6209
|
-
const
|
|
6207
|
+
let x = this.animQueue.findIndex((k) => k.template.name === "lookat");
|
|
6208
|
+
x !== -1 && this.animQueue.splice(x, 1);
|
|
6209
|
+
const f = {
|
|
6210
6210
|
name: "lookat",
|
|
6211
6211
|
dt: [750, t],
|
|
6212
6212
|
vs: {
|
|
@@ -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(f));
|
|
6225
6225
|
}
|
|
6226
6226
|
}
|
|
6227
6227
|
/**
|
|
@@ -6237,20 +6237,20 @@ class Be {
|
|
|
6237
6237
|
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);
|
|
6238
6238
|
l.project(this.camera);
|
|
6239
6239
|
let h = (l.x + 1) / 2 * i.width + i.left, r = -(l.y - 1) / 2 * i.height + i.top;
|
|
6240
|
-
t === null && (t = h), e === null && (e = r), $.copy(this.armature.quaternion), $.multiply(this.poseTarget.props["Hips.quaternion"]), $.multiply(this.poseTarget.props["Spine.quaternion"]), $.multiply(this.poseTarget.props["Spine1.quaternion"]), $.multiply(this.poseTarget.props["Spine2.quaternion"]), $.multiply(this.poseTarget.props["Neck.quaternion"]), $.multiply(this.poseTarget.props["Head.quaternion"]),
|
|
6241
|
-
let u =
|
|
6242
|
-
|
|
6243
|
-
let
|
|
6240
|
+
t === null && (t = h), e === null && (e = r), $.copy(this.armature.quaternion), $.multiply(this.poseTarget.props["Hips.quaternion"]), $.multiply(this.poseTarget.props["Spine.quaternion"]), $.multiply(this.poseTarget.props["Spine1.quaternion"]), $.multiply(this.poseTarget.props["Spine2.quaternion"]), $.multiply(this.poseTarget.props["Neck.quaternion"]), $.multiply(this.poseTarget.props["Head.quaternion"]), Z.setFromQuaternion($);
|
|
6241
|
+
let u = Z.x / (40 / 24), a = Z.y / (9 / 4), d = Math.min(0.4, Math.max(-0.4, this.camera.rotation.x)), c = Math.min(0.4, Math.max(-0.4, this.camera.rotation.y)), g = Math.max(window.innerWidth - h, h), 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;
|
|
6242
|
+
f = Math.min(0.6, Math.max(-0.3, f)), k = Math.min(0.8, Math.max(-0.8, k));
|
|
6243
|
+
let D = (Math.random() - 0.5) / 4, p = (Math.random() - 0.5) / 4;
|
|
6244
6244
|
if (n) {
|
|
6245
|
-
let
|
|
6246
|
-
|
|
6247
|
-
const
|
|
6245
|
+
let B = this.animQueue.findIndex((R) => R.template.name === "lookat");
|
|
6246
|
+
B !== -1 && this.animQueue.splice(B, 1);
|
|
6247
|
+
const T = {
|
|
6248
6248
|
name: "lookat",
|
|
6249
6249
|
dt: [750, n],
|
|
6250
6250
|
vs: {
|
|
6251
|
-
bodyRotateX: [
|
|
6252
|
-
bodyRotateY: [
|
|
6253
|
-
eyesRotateX: [-3 *
|
|
6251
|
+
bodyRotateX: [f + D],
|
|
6252
|
+
bodyRotateY: [k + p],
|
|
6253
|
+
eyesRotateX: [-3 * D + 0.1],
|
|
6254
6254
|
eyesRotateY: [-5 * p],
|
|
6255
6255
|
browInnerUp: [[0, 0.7]],
|
|
6256
6256
|
mouthLeft: [[0, 0.7]],
|
|
@@ -6259,7 +6259,7 @@ class Be {
|
|
|
6259
6259
|
headMove: [0]
|
|
6260
6260
|
}
|
|
6261
6261
|
};
|
|
6262
|
-
this.animQueue.push(this.animFactory(
|
|
6262
|
+
this.animQueue.push(this.animFactory(T));
|
|
6263
6263
|
}
|
|
6264
6264
|
}
|
|
6265
6265
|
/**
|
|
@@ -6465,13 +6465,13 @@ class Be {
|
|
|
6465
6465
|
suggestion: "Make sure the file is a valid FBX file and the path is correct"
|
|
6466
6466
|
}), 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"));
|
|
6467
6467
|
try {
|
|
6468
|
-
const c = await fetch(t), g = c.headers.get("content-type"),
|
|
6468
|
+
const c = await fetch(t), g = c.headers.get("content-type"), x = await c.text();
|
|
6469
6469
|
console.error("Response details:", {
|
|
6470
6470
|
status: c.status,
|
|
6471
6471
|
contentType: g,
|
|
6472
|
-
firstBytes:
|
|
6473
|
-
isHTML:
|
|
6474
|
-
}), (
|
|
6472
|
+
firstBytes: x.substring(0, 100),
|
|
6473
|
+
isHTML: x.trim().startsWith("<!DOCTYPE") || x.trim().startsWith("<html")
|
|
6474
|
+
}), (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.");
|
|
6475
6475
|
} catch (c) {
|
|
6476
6476
|
console.error("Could not fetch file for debugging:", c);
|
|
6477
6477
|
}
|
|
@@ -6480,39 +6480,39 @@ class Be {
|
|
|
6480
6480
|
if (a && a.animations && a.animations[i]) {
|
|
6481
6481
|
let d = a.animations[i];
|
|
6482
6482
|
const c = /* @__PURE__ */ new Set();
|
|
6483
|
-
this.armature && this.armature.traverse((
|
|
6484
|
-
(
|
|
6483
|
+
this.armature && this.armature.traverse((L) => {
|
|
6484
|
+
(L.isBone || L.type === "Bone") && c.add(L.name);
|
|
6485
6485
|
});
|
|
6486
|
-
const g = /* @__PURE__ */ new Map(),
|
|
6487
|
-
if (c.has(
|
|
6488
|
-
return
|
|
6489
|
-
let
|
|
6490
|
-
if (c.has(
|
|
6491
|
-
return
|
|
6492
|
-
const
|
|
6493
|
-
if (
|
|
6494
|
-
if (
|
|
6486
|
+
const g = /* @__PURE__ */ new Map(), x = (L) => {
|
|
6487
|
+
if (c.has(L))
|
|
6488
|
+
return L;
|
|
6489
|
+
let I = L.replace(/^mixamorig/i, "").replace(/^CC_Base_/i, "").replace(/^RPM_/i, "");
|
|
6490
|
+
if (c.has(I))
|
|
6491
|
+
return I;
|
|
6492
|
+
const z = I.toLowerCase();
|
|
6493
|
+
if (z.includes("left") && z.includes("arm")) {
|
|
6494
|
+
if (z.includes("fore") || z.includes("lower")) {
|
|
6495
6495
|
if (c.has("LeftForeArm")) return "LeftForeArm";
|
|
6496
6496
|
if (c.has("LeftForearm")) return "LeftForearm";
|
|
6497
|
-
} else if (!
|
|
6497
|
+
} else if (!z.includes("fore") && !z.includes("hand") && c.has("LeftArm"))
|
|
6498
6498
|
return "LeftArm";
|
|
6499
6499
|
}
|
|
6500
|
-
if (
|
|
6501
|
-
if (
|
|
6500
|
+
if (z.includes("right") && z.includes("arm")) {
|
|
6501
|
+
if (z.includes("fore") || z.includes("lower")) {
|
|
6502
6502
|
if (c.has("RightForeArm")) return "RightForeArm";
|
|
6503
6503
|
if (c.has("RightForearm")) return "RightForearm";
|
|
6504
|
-
} else if (!
|
|
6504
|
+
} else if (!z.includes("fore") && !z.includes("hand") && c.has("RightArm"))
|
|
6505
6505
|
return "RightArm";
|
|
6506
6506
|
}
|
|
6507
|
-
if (
|
|
6507
|
+
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"))
|
|
6508
6508
|
return "LeftHand";
|
|
6509
|
-
if (
|
|
6509
|
+
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"))
|
|
6510
6510
|
return "RightHand";
|
|
6511
|
-
if (
|
|
6511
|
+
if (z.includes("left") && (z.includes("shoulder") || z.includes("clavicle")) && c.has("LeftShoulder"))
|
|
6512
6512
|
return "LeftShoulder";
|
|
6513
|
-
if (
|
|
6513
|
+
if (z.includes("right") && (z.includes("shoulder") || z.includes("clavicle")) && c.has("RightShoulder"))
|
|
6514
6514
|
return "RightShoulder";
|
|
6515
|
-
const
|
|
6515
|
+
const Y = {
|
|
6516
6516
|
// Arm bones - exact matches
|
|
6517
6517
|
LeftArm: "LeftArm",
|
|
6518
6518
|
leftArm: "LeftArm",
|
|
@@ -6552,70 +6552,65 @@ class Be {
|
|
|
6552
6552
|
Root: "Hips",
|
|
6553
6553
|
root: "Hips"
|
|
6554
6554
|
};
|
|
6555
|
-
if (
|
|
6556
|
-
const
|
|
6557
|
-
if (c.has(
|
|
6558
|
-
return
|
|
6555
|
+
if (Y[I]) {
|
|
6556
|
+
const S = Y[I];
|
|
6557
|
+
if (c.has(S))
|
|
6558
|
+
return S;
|
|
6559
6559
|
}
|
|
6560
|
-
for (const
|
|
6561
|
-
if (
|
|
6562
|
-
return
|
|
6563
|
-
for (const
|
|
6564
|
-
const
|
|
6565
|
-
if ((
|
|
6566
|
-
return
|
|
6560
|
+
for (const S of c)
|
|
6561
|
+
if (S.toLowerCase() === z)
|
|
6562
|
+
return S;
|
|
6563
|
+
for (const S of c) {
|
|
6564
|
+
const E = S.toLowerCase();
|
|
6565
|
+
if ((z.includes("left") && E.includes("left") || z.includes("right") && E.includes("right")) && (z.includes("arm") && E.includes("arm") && !E.includes("fore") || z.includes("forearm") && E.includes("forearm") || z.includes("hand") && E.includes("hand") && !E.includes("index") && !E.includes("thumb") || z.includes("shoulder") && E.includes("shoulder")))
|
|
6566
|
+
return S;
|
|
6567
6567
|
}
|
|
6568
6568
|
return null;
|
|
6569
|
-
},
|
|
6570
|
-
d.tracks.forEach((
|
|
6571
|
-
const
|
|
6572
|
-
|
|
6573
|
-
}), console.log("=== Ready Player Me Animation Bone Analysis ==="), console.log("FBX bone names:", Array.from(
|
|
6574
|
-
const
|
|
6575
|
-
(
|
|
6576
|
-
),
|
|
6577
|
-
(
|
|
6569
|
+
}, f = /* @__PURE__ */ new Set();
|
|
6570
|
+
d.tracks.forEach((L) => {
|
|
6571
|
+
const I = L.name.split(".");
|
|
6572
|
+
f.add(I[0]);
|
|
6573
|
+
}), 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(", "));
|
|
6574
|
+
const k = Array.from(f).filter(
|
|
6575
|
+
(L) => L.toLowerCase().includes("arm") || L.toLowerCase().includes("hand") || L.toLowerCase().includes("shoulder")
|
|
6576
|
+
), D = Array.from(c).filter(
|
|
6577
|
+
(L) => L.includes("Arm") || L.includes("Hand") || L.includes("Shoulder")
|
|
6578
6578
|
);
|
|
6579
|
-
console.log("FBX arm/hand/shoulder bones:",
|
|
6580
|
-
const p = [],
|
|
6581
|
-
|
|
6582
|
-
|
|
6583
|
-
|
|
6584
|
-
|
|
6585
|
-
|
|
6586
|
-
return;
|
|
6587
|
-
}
|
|
6588
|
-
if (B && E) {
|
|
6589
|
-
const Y = `${B}.${E}`, ee = f.clone();
|
|
6590
|
-
ee.name = Y, p.push(ee), L !== B && g.set(L, B);
|
|
6579
|
+
console.log("FBX arm/hand/shoulder bones:", k.sort().join(", ")), console.log("Avatar arm/hand/shoulder bones:", D.sort().join(", "));
|
|
6580
|
+
const p = [], B = /* @__PURE__ */ new Set();
|
|
6581
|
+
if (d.tracks.forEach((L) => {
|
|
6582
|
+
const z = L.name.replaceAll("mixamorig", "").split("."), Y = z[0], S = z[1], E = x(Y);
|
|
6583
|
+
if (E && S) {
|
|
6584
|
+
const j = `${E}.${S}`, X = L.clone();
|
|
6585
|
+
X.name = j, p.push(X), Y !== E && g.set(Y, E);
|
|
6591
6586
|
} else
|
|
6592
|
-
|
|
6593
|
-
}),
|
|
6587
|
+
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`);
|
|
6588
|
+
}), B.size > 0 && console.warn(`⚠️ ${B.size} bone(s) could not be mapped:`, Array.from(B).sort().join(", ")), p.length > 0) {
|
|
6594
6589
|
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(
|
|
6595
6590
|
`✓ Mapped ${g.size} bone(s):`,
|
|
6596
|
-
Array.from(g.entries()).map(([
|
|
6591
|
+
Array.from(g.entries()).map(([I, z]) => `${I}→${z}`).join(", ")
|
|
6597
6592
|
);
|
|
6598
|
-
const
|
|
6599
|
-
(
|
|
6593
|
+
const L = Array.from(g.values()).filter(
|
|
6594
|
+
(I) => I.includes("Arm") || I.includes("Hand") || I.includes("Shoulder")
|
|
6600
6595
|
);
|
|
6601
|
-
|
|
6596
|
+
L.length > 0 ? console.log(`✓ Arm bones mapped: ${L.join(", ")}`) : console.warn("⚠️ No arm bones were mapped! This may cause arm rigging issues.");
|
|
6602
6597
|
} else
|
|
6603
6598
|
console.error("❌ No tracks could be mapped! Animation may not work correctly.");
|
|
6604
|
-
const
|
|
6605
|
-
d.tracks.forEach((
|
|
6606
|
-
|
|
6607
|
-
const
|
|
6608
|
-
if (
|
|
6609
|
-
for (let
|
|
6610
|
-
|
|
6611
|
-
|
|
6612
|
-
} else
|
|
6599
|
+
const T = {};
|
|
6600
|
+
d.tracks.forEach((L) => {
|
|
6601
|
+
L.name = L.name.replaceAll("mixamorig", "");
|
|
6602
|
+
const I = L.name.split(".");
|
|
6603
|
+
if (I[1] === "position") {
|
|
6604
|
+
for (let z = 0; z < L.values.length; z++)
|
|
6605
|
+
L.values[z] = L.values[z] * s;
|
|
6606
|
+
T[L.name] = new y.Vector3(L.values[0], L.values[1], L.values[2]);
|
|
6607
|
+
} else I[1] === "quaternion" ? T[L.name] = new y.Quaternion(L.values[0], L.values[1], L.values[2], L.values[3]) : I[1] === "rotation" && (T[I[0] + ".quaternion"] = new y.Quaternion().setFromEuler(new y.Euler(L.values[0], L.values[1], L.values[2], "XYZ")).normalize());
|
|
6613
6608
|
});
|
|
6614
|
-
const
|
|
6615
|
-
|
|
6609
|
+
const R = { props: T };
|
|
6610
|
+
T["Hips.position"] && (T["Hips.position"].y < 0.5 ? R.lying = !0 : R.standing = !0), this.animClips.push({
|
|
6616
6611
|
url: t + "-" + i,
|
|
6617
6612
|
clip: d,
|
|
6618
|
-
pose:
|
|
6613
|
+
pose: R
|
|
6619
6614
|
}), this.playAnimation(t, e, n, i, s);
|
|
6620
6615
|
} else {
|
|
6621
6616
|
const d = "Animation " + t + " (ndx=" + i + ") not found";
|
|
@@ -6706,9 +6701,9 @@ class Be {
|
|
|
6706
6701
|
const h = l.ts[0], u = l.ts[l.ts.length - 1] - h;
|
|
6707
6702
|
if (e * 1e3 - u > 0) {
|
|
6708
6703
|
const d = [];
|
|
6709
|
-
for (let
|
|
6710
|
-
const c = o.template?.rescale || d.map((
|
|
6711
|
-
l.ts = l.ts.map((
|
|
6704
|
+
for (let x = 1; x < l.ts.length; x++) d.push(l.ts[x] - l.ts[x - 1]);
|
|
6705
|
+
const c = o.template?.rescale || d.map((x) => x / u), g = e * 1e3 - u;
|
|
6706
|
+
l.ts = l.ts.map((x, f, k) => f === 0 ? h : k[f - 1] + d[f - 1] + c[f - 1] * g);
|
|
6712
6707
|
} else {
|
|
6713
6708
|
const d = e * 1e3 / u;
|
|
6714
6709
|
l.ts = l.ts.map((c) => h + d * (c - h));
|
|
@@ -6743,32 +6738,32 @@ class Be {
|
|
|
6743
6738
|
ikSolve(t, e = null, n = !1, i = null) {
|
|
6744
6739
|
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);
|
|
6745
6740
|
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);
|
|
6746
|
-
const g = this.ikMesh.getObjectByName(t.effector),
|
|
6747
|
-
|
|
6748
|
-
|
|
6741
|
+
const g = this.ikMesh.getObjectByName(t.effector), x = t.links;
|
|
6742
|
+
x.forEach((k) => {
|
|
6743
|
+
k.bone = this.ikMesh.getObjectByName(k.link), k.bone.quaternion.copy(this.getPoseTemplateProp(k.link + ".quaternion"));
|
|
6749
6744
|
}), c.updateMatrixWorld(!0);
|
|
6750
|
-
const
|
|
6745
|
+
const f = t.iterations || 10;
|
|
6751
6746
|
if (e)
|
|
6752
|
-
for (let
|
|
6753
|
-
let
|
|
6754
|
-
for (let p = 0,
|
|
6755
|
-
const
|
|
6756
|
-
|
|
6757
|
-
let
|
|
6758
|
-
|
|
6759
|
-
|
|
6760
|
-
|
|
6761
|
-
|
|
6747
|
+
for (let k = 0; k < f; k++) {
|
|
6748
|
+
let D = !1;
|
|
6749
|
+
for (let p = 0, B = x.length; p < B; p++) {
|
|
6750
|
+
const T = x[p].bone;
|
|
6751
|
+
T.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();
|
|
6752
|
+
let R = s.dot(l);
|
|
6753
|
+
R > 1 ? R = 1 : R < -1 && (R = -1), R = Math.acos(R), !(R < 1e-5) && (x[p].minAngle !== void 0 && R < x[p].minAngle && (R = x[p].minAngle), x[p].maxAngle !== void 0 && R > x[p].maxAngle && (R = x[p].maxAngle), a.crossVectors(l, s), a.normalize(), $.setFromAxisAngle(a, R), T.quaternion.multiply($), T.rotation.setFromVector3(d.setFromEuler(T.rotation).clamp(new y.Vector3(
|
|
6754
|
+
x[p].minx !== void 0 ? x[p].minx : -1 / 0,
|
|
6755
|
+
x[p].miny !== void 0 ? x[p].miny : -1 / 0,
|
|
6756
|
+
x[p].minz !== void 0 ? x[p].minz : -1 / 0
|
|
6762
6757
|
), new y.Vector3(
|
|
6763
|
-
|
|
6764
|
-
|
|
6765
|
-
|
|
6766
|
-
))),
|
|
6758
|
+
x[p].maxx !== void 0 ? x[p].maxx : 1 / 0,
|
|
6759
|
+
x[p].maxy !== void 0 ? x[p].maxy : 1 / 0,
|
|
6760
|
+
x[p].maxz !== void 0 ? x[p].maxz : 1 / 0
|
|
6761
|
+
))), T.updateMatrixWorld(!0), D = !0);
|
|
6767
6762
|
}
|
|
6768
|
-
if (!
|
|
6763
|
+
if (!D) break;
|
|
6769
6764
|
}
|
|
6770
|
-
i &&
|
|
6771
|
-
this.poseTarget.props[
|
|
6765
|
+
i && x.forEach((k) => {
|
|
6766
|
+
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;
|
|
6772
6767
|
});
|
|
6773
6768
|
}
|
|
6774
6769
|
/**
|
|
@@ -6828,16 +6823,16 @@ function Ee() {
|
|
|
6828
6823
|
};
|
|
6829
6824
|
}
|
|
6830
6825
|
function wt() {
|
|
6831
|
-
const
|
|
6832
|
-
return Object.entries(
|
|
6826
|
+
const V = Ee(), t = [];
|
|
6827
|
+
return Object.entries(V.voices).forEach(([e, n]) => {
|
|
6833
6828
|
t.push({
|
|
6834
6829
|
value: n,
|
|
6835
|
-
label: `${e.charAt(0).toUpperCase() + e.slice(1)} (${
|
|
6830
|
+
label: `${e.charAt(0).toUpperCase() + e.slice(1)} (${V.service})`
|
|
6836
6831
|
});
|
|
6837
6832
|
}), t;
|
|
6838
6833
|
}
|
|
6839
6834
|
const Ve = Me(({
|
|
6840
|
-
avatarUrl:
|
|
6835
|
+
avatarUrl: V = "/avatars/brunette.glb",
|
|
6841
6836
|
avatarBody: t = "F",
|
|
6842
6837
|
mood: e = "neutral",
|
|
6843
6838
|
ttsLang: n = "en",
|
|
@@ -6855,16 +6850,16 @@ const Ve = Me(({
|
|
|
6855
6850
|
onError: c = () => {
|
|
6856
6851
|
},
|
|
6857
6852
|
className: g = "",
|
|
6858
|
-
style:
|
|
6859
|
-
animations:
|
|
6860
|
-
},
|
|
6861
|
-
const
|
|
6853
|
+
style: x = {},
|
|
6854
|
+
animations: f = {}
|
|
6855
|
+
}, k) => {
|
|
6856
|
+
const D = W(null), p = W(null), B = W(r), T = W(null), R = W(null), L = W(!1), I = W({ remainingText: null, originalText: null, options: null }), z = W([]), Y = W(0), [S, E] = pe(!0), [j, X] = pe(null), [oe, le] = pe(!1), [ge, de] = pe(!1);
|
|
6862
6857
|
ce(() => {
|
|
6863
|
-
|
|
6858
|
+
L.current = ge;
|
|
6864
6859
|
}, [ge]), ce(() => {
|
|
6865
|
-
|
|
6860
|
+
B.current = r;
|
|
6866
6861
|
}, [r]);
|
|
6867
|
-
const
|
|
6862
|
+
const ee = Ee(), be = i || ee.service;
|
|
6868
6863
|
let Q;
|
|
6869
6864
|
be === "browser" ? Q = {
|
|
6870
6865
|
service: "browser",
|
|
@@ -6874,22 +6869,22 @@ const Ve = Me(({
|
|
|
6874
6869
|
} : be === "elevenlabs" ? Q = {
|
|
6875
6870
|
service: "elevenlabs",
|
|
6876
6871
|
endpoint: "https://api.elevenlabs.io/v1/text-to-speech",
|
|
6877
|
-
apiKey: o ||
|
|
6878
|
-
defaultVoice: s ||
|
|
6879
|
-
voices:
|
|
6872
|
+
apiKey: o || ee.apiKey,
|
|
6873
|
+
defaultVoice: s || ee.defaultVoice || Ie.defaultVoice,
|
|
6874
|
+
voices: ee.voices || Ie.voices
|
|
6880
6875
|
} : be === "deepgram" ? Q = {
|
|
6881
6876
|
service: "deepgram",
|
|
6882
6877
|
endpoint: "https://api.deepgram.com/v1/speak",
|
|
6883
|
-
apiKey: o ||
|
|
6884
|
-
defaultVoice: s ||
|
|
6885
|
-
voices:
|
|
6878
|
+
apiKey: o || ee.apiKey,
|
|
6879
|
+
defaultVoice: s || ee.defaultVoice || Te.defaultVoice,
|
|
6880
|
+
voices: ee.voices || Te.voices
|
|
6886
6881
|
} : Q = {
|
|
6887
|
-
...
|
|
6882
|
+
...ee,
|
|
6888
6883
|
// Override API key if provided via props
|
|
6889
|
-
apiKey: o !== null ? o :
|
|
6884
|
+
apiKey: o !== null ? o : ee.apiKey
|
|
6890
6885
|
};
|
|
6891
|
-
const
|
|
6892
|
-
url:
|
|
6886
|
+
const b = {
|
|
6887
|
+
url: V,
|
|
6893
6888
|
body: t,
|
|
6894
6889
|
avatarMood: e,
|
|
6895
6890
|
ttsLang: be === "browser" ? "en-US" : n,
|
|
@@ -6898,25 +6893,25 @@ const Ve = Me(({
|
|
|
6898
6893
|
showFullAvatar: r,
|
|
6899
6894
|
bodyMovement: l,
|
|
6900
6895
|
movementIntensity: h
|
|
6901
|
-
},
|
|
6896
|
+
}, v = {
|
|
6902
6897
|
ttsEndpoint: Q.endpoint,
|
|
6903
6898
|
ttsApikey: Q.apiKey,
|
|
6904
6899
|
ttsService: be,
|
|
6905
6900
|
lipsyncModules: ["en"],
|
|
6906
6901
|
cameraView: u
|
|
6907
|
-
},
|
|
6908
|
-
if (!(!
|
|
6902
|
+
}, F = O(async () => {
|
|
6903
|
+
if (!(!D.current || p.current))
|
|
6909
6904
|
try {
|
|
6910
|
-
if (E(!0),
|
|
6905
|
+
if (E(!0), X(null), p.current = new Be(D.current, v), 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, (K) => {
|
|
6911
6906
|
if (K.lengthComputable) {
|
|
6912
|
-
const
|
|
6913
|
-
d(
|
|
6907
|
+
const ne = Math.min(100, Math.round(K.loaded / K.total * 100));
|
|
6908
|
+
d(ne);
|
|
6914
6909
|
}
|
|
6915
6910
|
}), await new Promise((K) => {
|
|
6916
|
-
const
|
|
6917
|
-
p.current.lipsync && Object.keys(p.current.lipsync).length > 0 ? K() : setTimeout(
|
|
6911
|
+
const ne = () => {
|
|
6912
|
+
p.current.lipsync && Object.keys(p.current.lipsync).length > 0 ? K() : setTimeout(ne, 100);
|
|
6918
6913
|
};
|
|
6919
|
-
|
|
6914
|
+
ne();
|
|
6920
6915
|
}), p.current && p.current.setShowFullAvatar)
|
|
6921
6916
|
try {
|
|
6922
6917
|
p.current.setShowFullAvatar(r);
|
|
@@ -6924,62 +6919,62 @@ const Ve = Me(({
|
|
|
6924
6919
|
console.warn("Error setting full body mode on initialization:", K);
|
|
6925
6920
|
}
|
|
6926
6921
|
p.current && p.current.controls && (p.current.controls.enableRotate = !1, p.current.controls.enableZoom = !1, p.current.controls.enablePan = !1, p.current.controls.enableDamping = !1, p.current.controls.update()), E(!1), le(!0), a(p.current);
|
|
6927
|
-
const
|
|
6922
|
+
const U = () => {
|
|
6928
6923
|
document.visibilityState === "visible" ? p.current?.start() : p.current?.stop();
|
|
6929
6924
|
};
|
|
6930
|
-
return document.addEventListener("visibilitychange",
|
|
6931
|
-
document.removeEventListener("visibilitychange",
|
|
6925
|
+
return document.addEventListener("visibilitychange", U), () => {
|
|
6926
|
+
document.removeEventListener("visibilitychange", U);
|
|
6932
6927
|
};
|
|
6933
|
-
} catch (
|
|
6934
|
-
console.error("Error initializing TalkingHead:",
|
|
6928
|
+
} catch (w) {
|
|
6929
|
+
console.error("Error initializing TalkingHead:", w), X(w.message || "Failed to initialize avatar"), E(!1), c(w);
|
|
6935
6930
|
}
|
|
6936
|
-
}, [
|
|
6937
|
-
ce(() => (
|
|
6931
|
+
}, [V, t, e, n, i, s, o, r, l, h, u]);
|
|
6932
|
+
ce(() => (F(), () => {
|
|
6938
6933
|
p.current && (p.current.stop(), p.current.dispose(), p.current = null);
|
|
6939
|
-
}), [
|
|
6940
|
-
if (!
|
|
6941
|
-
const
|
|
6942
|
-
for (const
|
|
6934
|
+
}), [F]), ce(() => {
|
|
6935
|
+
if (!D.current || !p.current) return;
|
|
6936
|
+
const w = new ResizeObserver((K) => {
|
|
6937
|
+
for (const ne of K)
|
|
6943
6938
|
p.current && p.current.onResize && p.current.onResize();
|
|
6944
6939
|
});
|
|
6945
|
-
|
|
6946
|
-
const
|
|
6940
|
+
w.observe(D.current);
|
|
6941
|
+
const U = () => {
|
|
6947
6942
|
p.current && p.current.onResize && p.current.onResize();
|
|
6948
6943
|
};
|
|
6949
|
-
return window.addEventListener("resize",
|
|
6950
|
-
|
|
6944
|
+
return window.addEventListener("resize", U), () => {
|
|
6945
|
+
w.disconnect(), window.removeEventListener("resize", U);
|
|
6951
6946
|
};
|
|
6952
|
-
}, [
|
|
6953
|
-
const
|
|
6947
|
+
}, [oe]);
|
|
6948
|
+
const P = O(async () => {
|
|
6954
6949
|
if (p.current && p.current.audioCtx)
|
|
6955
6950
|
try {
|
|
6956
6951
|
(p.current.audioCtx.state === "suspended" || p.current.audioCtx.state === "interrupted") && (await p.current.audioCtx.resume(), console.log("Audio context resumed"));
|
|
6957
|
-
} catch (
|
|
6958
|
-
console.warn("Failed to resume audio context:",
|
|
6952
|
+
} catch (w) {
|
|
6953
|
+
console.warn("Failed to resume audio context:", w);
|
|
6959
6954
|
}
|
|
6960
|
-
}, []),
|
|
6961
|
-
if (p.current &&
|
|
6955
|
+
}, []), N = O(async (w, U = {}) => {
|
|
6956
|
+
if (p.current && oe)
|
|
6962
6957
|
try {
|
|
6963
|
-
|
|
6964
|
-
const K = /[!\.\?\n\p{Extended_Pictographic}]/ug,
|
|
6965
|
-
|
|
6958
|
+
R.current && (clearInterval(R.current), R.current = null), T.current = { text: w, options: U }, I.current = { remainingText: null, originalText: null, options: null };
|
|
6959
|
+
const K = /[!\.\?\n\p{Extended_Pictographic}]/ug, ne = w.split(K).map((A) => A.trim()).filter((A) => A.length > 0);
|
|
6960
|
+
z.current = ne, Y.current = 0, de(!1), L.current = !1, await P();
|
|
6966
6961
|
const me = {
|
|
6967
|
-
...
|
|
6968
|
-
lipsyncLang:
|
|
6962
|
+
...U,
|
|
6963
|
+
lipsyncLang: U.lipsyncLang || b.lipsyncLang || "en"
|
|
6969
6964
|
};
|
|
6970
|
-
if (
|
|
6965
|
+
if (U.onSpeechEnd && p.current) {
|
|
6971
6966
|
const A = p.current;
|
|
6972
|
-
let
|
|
6967
|
+
let H = null, G = 0;
|
|
6973
6968
|
const J = 1200;
|
|
6974
|
-
let
|
|
6975
|
-
|
|
6976
|
-
if (
|
|
6969
|
+
let ie = !1;
|
|
6970
|
+
H = setInterval(() => {
|
|
6971
|
+
if (G++, L.current)
|
|
6977
6972
|
return;
|
|
6978
|
-
if (
|
|
6979
|
-
if (
|
|
6980
|
-
|
|
6973
|
+
if (G > J) {
|
|
6974
|
+
if (H && (clearInterval(H), H = null, R.current = null), !ie && !L.current) {
|
|
6975
|
+
ie = !0;
|
|
6981
6976
|
try {
|
|
6982
|
-
|
|
6977
|
+
U.onSpeechEnd();
|
|
6983
6978
|
} catch (Oe) {
|
|
6984
6979
|
console.error("Error in onSpeechEnd callback (timeout):", Oe);
|
|
6985
6980
|
}
|
|
@@ -6987,85 +6982,85 @@ const Ve = Me(({
|
|
|
6987
6982
|
return;
|
|
6988
6983
|
}
|
|
6989
6984
|
const se = !A.speechQueue || A.speechQueue.length === 0, we = !A.audioPlaylist || A.audioPlaylist.length === 0;
|
|
6990
|
-
A && A.isSpeaking === !1 && se && we && A.isAudioPlaying === !1 && !
|
|
6991
|
-
if (A && !
|
|
6992
|
-
|
|
6985
|
+
A && A.isSpeaking === !1 && se && we && A.isAudioPlaying === !1 && !ie && !L.current && setTimeout(() => {
|
|
6986
|
+
if (A && !L.current && A.isSpeaking === !1 && (!A.speechQueue || A.speechQueue.length === 0) && (!A.audioPlaylist || A.audioPlaylist.length === 0) && A.isAudioPlaying === !1 && !ie && !L.current) {
|
|
6987
|
+
ie = !0, H && (clearInterval(H), H = null, R.current = null);
|
|
6993
6988
|
try {
|
|
6994
|
-
|
|
6989
|
+
U.onSpeechEnd();
|
|
6995
6990
|
} catch (Ze) {
|
|
6996
6991
|
console.error("Error in onSpeechEnd callback:", Ze);
|
|
6997
6992
|
}
|
|
6998
6993
|
}
|
|
6999
6994
|
}, 100);
|
|
7000
|
-
}, 100),
|
|
6995
|
+
}, 100), R.current = H;
|
|
7001
6996
|
}
|
|
7002
|
-
p.current.lipsync && Object.keys(p.current.lipsync).length > 0 ? (p.current.setSlowdownRate && p.current.setSlowdownRate(1.05), p.current.speakText(
|
|
7003
|
-
await
|
|
6997
|
+
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 () => {
|
|
6998
|
+
await P(), p.current && p.current.lipsync && (p.current.setSlowdownRate && p.current.setSlowdownRate(1.05), p.current.speakText(w, me));
|
|
7004
6999
|
}, 100);
|
|
7005
7000
|
} catch (K) {
|
|
7006
|
-
console.error("Error speaking text:", K),
|
|
7001
|
+
console.error("Error speaking text:", K), X(K.message || "Failed to speak text");
|
|
7007
7002
|
}
|
|
7008
|
-
}, [
|
|
7009
|
-
p.current && (p.current.stopSpeaking(), p.current.setSlowdownRate && p.current.setSlowdownRate(1),
|
|
7010
|
-
}, []), q =
|
|
7003
|
+
}, [oe, P, b.lipsyncLang]), te = O(() => {
|
|
7004
|
+
p.current && (p.current.stopSpeaking(), p.current.setSlowdownRate && p.current.setSlowdownRate(1), T.current = null, de(!1));
|
|
7005
|
+
}, []), q = O(() => {
|
|
7011
7006
|
if (p.current && p.current.pauseSpeaking) {
|
|
7012
|
-
const
|
|
7013
|
-
if (
|
|
7014
|
-
|
|
7007
|
+
const w = p.current;
|
|
7008
|
+
if (w.isSpeaking || w.audioPlaylist && w.audioPlaylist.length > 0 || w.speechQueue && w.speechQueue.length > 0) {
|
|
7009
|
+
R.current && (clearInterval(R.current), R.current = null);
|
|
7015
7010
|
let K = "";
|
|
7016
|
-
if (
|
|
7017
|
-
const
|
|
7018
|
-
if (
|
|
7019
|
-
const
|
|
7020
|
-
|
|
7011
|
+
if (T.current && z.current.length > 0) {
|
|
7012
|
+
const ne = z.current.length, me = w.speechQueue ? w.speechQueue.filter((J) => J && J.text && Array.isArray(J.text) && J.text.length > 0).length : 0, A = w.audioPlaylist && w.audioPlaylist.length > 0, H = me + (A ? 1 : 0), G = ne - H;
|
|
7013
|
+
if (H > 0 && G < ne && (K = z.current.slice(G).join(". ").trim(), !K && me > 0 && w.speechQueue)) {
|
|
7014
|
+
const ie = w.speechQueue.filter((se) => se && se.text && Array.isArray(se.text) && se.text.length > 0).map((se) => se.text.map((we) => we.word || "").filter((we) => we.length > 0).join(" ")).filter((se) => se.length > 0).join(" ");
|
|
7015
|
+
ie && ie.trim() && (K = ie.trim());
|
|
7021
7016
|
}
|
|
7022
7017
|
}
|
|
7023
|
-
|
|
7018
|
+
T.current && (I.current = {
|
|
7024
7019
|
remainingText: K || null,
|
|
7025
|
-
originalText:
|
|
7026
|
-
options:
|
|
7027
|
-
}),
|
|
7020
|
+
originalText: T.current.text,
|
|
7021
|
+
options: T.current.options
|
|
7022
|
+
}), w.speechQueue && (w.speechQueue.length = 0), p.current.pauseSpeaking(), L.current = !0, de(!0);
|
|
7028
7023
|
}
|
|
7029
7024
|
}
|
|
7030
|
-
}, []), _ =
|
|
7025
|
+
}, []), _ = O(async () => {
|
|
7031
7026
|
if (!p.current || !ge)
|
|
7032
7027
|
return;
|
|
7033
|
-
let
|
|
7034
|
-
if (
|
|
7035
|
-
|
|
7036
|
-
else if (
|
|
7037
|
-
|
|
7028
|
+
let w = "", U = {};
|
|
7029
|
+
if (I.current && I.current.remainingText)
|
|
7030
|
+
w = I.current.remainingText, U = I.current.options || {}, I.current = { remainingText: null, originalText: null, options: null };
|
|
7031
|
+
else if (T.current && T.current.text)
|
|
7032
|
+
w = T.current.text, U = T.current.options || {};
|
|
7038
7033
|
else {
|
|
7039
|
-
console.warn("Resume called but no paused speech found"), de(!1),
|
|
7034
|
+
console.warn("Resume called but no paused speech found"), de(!1), L.current = !1;
|
|
7040
7035
|
return;
|
|
7041
7036
|
}
|
|
7042
|
-
de(!1),
|
|
7037
|
+
de(!1), L.current = !1, await P();
|
|
7043
7038
|
const K = {
|
|
7044
|
-
...
|
|
7045
|
-
lipsyncLang:
|
|
7039
|
+
...U,
|
|
7040
|
+
lipsyncLang: U.lipsyncLang || b.lipsyncLang || "en"
|
|
7046
7041
|
};
|
|
7047
7042
|
try {
|
|
7048
|
-
await
|
|
7049
|
-
} catch (
|
|
7050
|
-
console.error("Error resuming speech:",
|
|
7043
|
+
await N(w, K);
|
|
7044
|
+
} catch (ne) {
|
|
7045
|
+
console.error("Error resuming speech:", ne), de(!1), L.current = !1;
|
|
7051
7046
|
}
|
|
7052
|
-
}, [
|
|
7053
|
-
p.current && p.current.setMood(
|
|
7054
|
-
}, []), Se =
|
|
7055
|
-
p.current && p.current.setSlowdownRate && p.current.setSlowdownRate(
|
|
7056
|
-
}, []), Le =
|
|
7047
|
+
}, [P, ge, N, b]), Ae = O((w) => {
|
|
7048
|
+
p.current && p.current.setMood(w);
|
|
7049
|
+
}, []), Se = O((w) => {
|
|
7050
|
+
p.current && p.current.setSlowdownRate && p.current.setSlowdownRate(w);
|
|
7051
|
+
}, []), Le = O((w, U = !1) => {
|
|
7057
7052
|
if (p.current && p.current.playAnimation) {
|
|
7058
|
-
if (
|
|
7053
|
+
if (f && f[w] && (w = f[w]), p.current.setShowFullAvatar)
|
|
7059
7054
|
try {
|
|
7060
|
-
p.current.setShowFullAvatar(
|
|
7061
|
-
} catch (
|
|
7062
|
-
console.warn("Error setting full body mode:",
|
|
7055
|
+
p.current.setShowFullAvatar(B.current);
|
|
7056
|
+
} catch (ne) {
|
|
7057
|
+
console.warn("Error setting full body mode:", ne);
|
|
7063
7058
|
}
|
|
7064
|
-
if (
|
|
7059
|
+
if (w.includes("."))
|
|
7065
7060
|
try {
|
|
7066
|
-
p.current.playAnimation(
|
|
7067
|
-
} catch (
|
|
7068
|
-
console.warn(`Failed to play ${
|
|
7061
|
+
p.current.playAnimation(w, null, 10, 0, 0.01, U);
|
|
7062
|
+
} catch (ne) {
|
|
7063
|
+
console.warn(`Failed to play ${w}:`, ne);
|
|
7069
7064
|
try {
|
|
7070
7065
|
p.current.setBodyMovement("idle");
|
|
7071
7066
|
} catch (me) {
|
|
@@ -7073,16 +7068,16 @@ const Ve = Me(({
|
|
|
7073
7068
|
}
|
|
7074
7069
|
}
|
|
7075
7070
|
else {
|
|
7076
|
-
const
|
|
7071
|
+
const ne = [".fbx", ".glb", ".gltf"];
|
|
7077
7072
|
let me = !1;
|
|
7078
|
-
for (const A of
|
|
7073
|
+
for (const A of ne)
|
|
7079
7074
|
try {
|
|
7080
|
-
p.current.playAnimation(
|
|
7075
|
+
p.current.playAnimation(w + A, null, 10, 0, 0.01, U), me = !0;
|
|
7081
7076
|
break;
|
|
7082
7077
|
} catch {
|
|
7083
7078
|
}
|
|
7084
7079
|
if (!me) {
|
|
7085
|
-
console.warn("Animation not found:",
|
|
7080
|
+
console.warn("Animation not found:", w);
|
|
7086
7081
|
try {
|
|
7087
7082
|
p.current.setBodyMovement("idle");
|
|
7088
7083
|
} catch (A) {
|
|
@@ -7091,77 +7086,77 @@ const Ve = Me(({
|
|
|
7091
7086
|
}
|
|
7092
7087
|
}
|
|
7093
7088
|
}
|
|
7094
|
-
}, [
|
|
7089
|
+
}, [f]), ke = O(() => {
|
|
7095
7090
|
p.current && p.current.onResize && p.current.onResize();
|
|
7096
7091
|
}, []);
|
|
7097
|
-
return Fe(
|
|
7098
|
-
speakText:
|
|
7099
|
-
stopSpeaking:
|
|
7092
|
+
return Fe(k, () => ({
|
|
7093
|
+
speakText: N,
|
|
7094
|
+
stopSpeaking: te,
|
|
7100
7095
|
pauseSpeaking: q,
|
|
7101
7096
|
resumeSpeaking: _,
|
|
7102
|
-
resumeAudioContext:
|
|
7097
|
+
resumeAudioContext: P,
|
|
7103
7098
|
setMood: Ae,
|
|
7104
7099
|
setTimingAdjustment: Se,
|
|
7105
7100
|
playAnimation: Le,
|
|
7106
|
-
isReady:
|
|
7101
|
+
isReady: oe,
|
|
7107
7102
|
isPaused: ge,
|
|
7108
7103
|
talkingHead: p.current,
|
|
7109
7104
|
handleResize: ke,
|
|
7110
|
-
setBodyMovement: (
|
|
7105
|
+
setBodyMovement: (w) => {
|
|
7111
7106
|
if (p.current && p.current.setShowFullAvatar && p.current.setBodyMovement)
|
|
7112
7107
|
try {
|
|
7113
|
-
p.current.setShowFullAvatar(
|
|
7114
|
-
} catch (
|
|
7115
|
-
console.warn("Error setting body movement:",
|
|
7108
|
+
p.current.setShowFullAvatar(B.current), p.current.setBodyMovement(w);
|
|
7109
|
+
} catch (U) {
|
|
7110
|
+
console.warn("Error setting body movement:", U);
|
|
7116
7111
|
}
|
|
7117
7112
|
},
|
|
7118
|
-
setMovementIntensity: (
|
|
7113
|
+
setMovementIntensity: (w) => p.current?.setMovementIntensity(w),
|
|
7119
7114
|
playRandomDance: () => {
|
|
7120
7115
|
if (p.current && p.current.setShowFullAvatar && p.current.playRandomDance)
|
|
7121
7116
|
try {
|
|
7122
|
-
p.current.setShowFullAvatar(
|
|
7123
|
-
} catch (
|
|
7124
|
-
console.warn("Error playing random dance:",
|
|
7117
|
+
p.current.setShowFullAvatar(B.current), p.current.playRandomDance();
|
|
7118
|
+
} catch (w) {
|
|
7119
|
+
console.warn("Error playing random dance:", w);
|
|
7125
7120
|
}
|
|
7126
7121
|
},
|
|
7127
|
-
playReaction: (
|
|
7122
|
+
playReaction: (w) => {
|
|
7128
7123
|
if (p.current && p.current.setShowFullAvatar && p.current.playReaction)
|
|
7129
7124
|
try {
|
|
7130
|
-
p.current.setShowFullAvatar(
|
|
7131
|
-
} catch (
|
|
7132
|
-
console.warn("Error playing reaction:",
|
|
7125
|
+
p.current.setShowFullAvatar(B.current), p.current.playReaction(w);
|
|
7126
|
+
} catch (U) {
|
|
7127
|
+
console.warn("Error playing reaction:", U);
|
|
7133
7128
|
}
|
|
7134
7129
|
},
|
|
7135
7130
|
playCelebration: () => {
|
|
7136
7131
|
if (p.current && p.current.setShowFullAvatar && p.current.playCelebration)
|
|
7137
7132
|
try {
|
|
7138
|
-
p.current.setShowFullAvatar(
|
|
7139
|
-
} catch (
|
|
7140
|
-
console.warn("Error playing celebration:",
|
|
7133
|
+
p.current.setShowFullAvatar(B.current), p.current.playCelebration();
|
|
7134
|
+
} catch (w) {
|
|
7135
|
+
console.warn("Error playing celebration:", w);
|
|
7141
7136
|
}
|
|
7142
7137
|
},
|
|
7143
|
-
setShowFullAvatar: (
|
|
7138
|
+
setShowFullAvatar: (w) => {
|
|
7144
7139
|
if (p.current && p.current.setShowFullAvatar)
|
|
7145
7140
|
try {
|
|
7146
|
-
|
|
7147
|
-
} catch (
|
|
7148
|
-
console.warn("Error setting showFullAvatar:",
|
|
7141
|
+
B.current = w, p.current.setShowFullAvatar(w);
|
|
7142
|
+
} catch (U) {
|
|
7143
|
+
console.warn("Error setting showFullAvatar:", U);
|
|
7149
7144
|
}
|
|
7150
7145
|
},
|
|
7151
7146
|
lockAvatarPosition: () => {
|
|
7152
7147
|
if (p.current && p.current.lockAvatarPosition)
|
|
7153
7148
|
try {
|
|
7154
7149
|
p.current.lockAvatarPosition();
|
|
7155
|
-
} catch (
|
|
7156
|
-
console.warn("Error locking avatar position:",
|
|
7150
|
+
} catch (w) {
|
|
7151
|
+
console.warn("Error locking avatar position:", w);
|
|
7157
7152
|
}
|
|
7158
7153
|
},
|
|
7159
7154
|
unlockAvatarPosition: () => {
|
|
7160
7155
|
if (p.current && p.current.unlockAvatarPosition)
|
|
7161
7156
|
try {
|
|
7162
7157
|
p.current.unlockAvatarPosition();
|
|
7163
|
-
} catch (
|
|
7164
|
-
console.warn("Error unlocking avatar position:",
|
|
7158
|
+
} catch (w) {
|
|
7159
|
+
console.warn("Error unlocking avatar position:", w);
|
|
7165
7160
|
}
|
|
7166
7161
|
}
|
|
7167
7162
|
})), /* @__PURE__ */ Pe(
|
|
@@ -7172,13 +7167,13 @@ const Ve = Me(({
|
|
|
7172
7167
|
width: "100%",
|
|
7173
7168
|
height: "100%",
|
|
7174
7169
|
position: "relative",
|
|
7175
|
-
...
|
|
7170
|
+
...x
|
|
7176
7171
|
},
|
|
7177
7172
|
children: [
|
|
7178
7173
|
/* @__PURE__ */ ye(
|
|
7179
7174
|
"div",
|
|
7180
7175
|
{
|
|
7181
|
-
ref:
|
|
7176
|
+
ref: D,
|
|
7182
7177
|
className: "talking-head-viewer",
|
|
7183
7178
|
style: {
|
|
7184
7179
|
width: "100%",
|
|
@@ -7187,7 +7182,7 @@ const Ve = Me(({
|
|
|
7187
7182
|
}
|
|
7188
7183
|
}
|
|
7189
7184
|
),
|
|
7190
|
-
|
|
7185
|
+
S && /* @__PURE__ */ ye("div", { className: "loading-overlay", style: {
|
|
7191
7186
|
position: "absolute",
|
|
7192
7187
|
top: "50%",
|
|
7193
7188
|
left: "50%",
|
|
@@ -7196,7 +7191,7 @@ const Ve = Me(({
|
|
|
7196
7191
|
fontSize: "18px",
|
|
7197
7192
|
zIndex: 10
|
|
7198
7193
|
}, children: "Loading avatar..." }),
|
|
7199
|
-
|
|
7194
|
+
j && /* @__PURE__ */ ye("div", { className: "error-overlay", style: {
|
|
7200
7195
|
position: "absolute",
|
|
7201
7196
|
top: "50%",
|
|
7202
7197
|
left: "50%",
|
|
@@ -7207,14 +7202,14 @@ const Ve = Me(({
|
|
|
7207
7202
|
zIndex: 10,
|
|
7208
7203
|
padding: "20px",
|
|
7209
7204
|
borderRadius: "8px"
|
|
7210
|
-
}, children:
|
|
7205
|
+
}, children: j })
|
|
7211
7206
|
]
|
|
7212
7207
|
}
|
|
7213
7208
|
);
|
|
7214
7209
|
});
|
|
7215
7210
|
Ve.displayName = "TalkingHeadAvatar";
|
|
7216
7211
|
const pt = Me(({
|
|
7217
|
-
text:
|
|
7212
|
+
text: V = "Hello! I'm a talking avatar. How are you today?",
|
|
7218
7213
|
onLoading: t = () => {
|
|
7219
7214
|
},
|
|
7220
7215
|
onError: e = () => {
|
|
@@ -7225,23 +7220,23 @@ const pt = Me(({
|
|
|
7225
7220
|
style: s = {},
|
|
7226
7221
|
avatarConfig: o = {}
|
|
7227
7222
|
}, l) => {
|
|
7228
|
-
const h =
|
|
7223
|
+
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, D = k === "browser" ? {
|
|
7229
7224
|
endpoint: "",
|
|
7230
7225
|
apiKey: null,
|
|
7231
7226
|
defaultVoice: "Google US English"
|
|
7232
7227
|
} : {
|
|
7233
|
-
...
|
|
7228
|
+
...f,
|
|
7234
7229
|
// Override API key if provided via avatarConfig
|
|
7235
|
-
apiKey: o.ttsApiKey !== void 0 && o.ttsApiKey !== null ? o.ttsApiKey :
|
|
7230
|
+
apiKey: o.ttsApiKey !== void 0 && o.ttsApiKey !== null ? o.ttsApiKey : f.apiKey,
|
|
7236
7231
|
// Override endpoint for ElevenLabs if service is explicitly set
|
|
7237
|
-
endpoint:
|
|
7232
|
+
endpoint: k === "elevenlabs" && o.ttsApiKey ? "https://api.elevenlabs.io/v1/text-to-speech" : f.endpoint
|
|
7238
7233
|
}, p = {
|
|
7239
7234
|
url: "/avatars/brunette.glb",
|
|
7240
7235
|
// Use brunette avatar (working glTF file)
|
|
7241
7236
|
body: "F",
|
|
7242
7237
|
avatarMood: "neutral",
|
|
7243
|
-
ttsLang:
|
|
7244
|
-
ttsVoice: o.ttsVoice ||
|
|
7238
|
+
ttsLang: k === "browser" ? "en-US" : "en",
|
|
7239
|
+
ttsVoice: o.ttsVoice || D.defaultVoice,
|
|
7245
7240
|
lipsyncLang: "en",
|
|
7246
7241
|
// English lip-sync
|
|
7247
7242
|
showFullAvatar: !0,
|
|
@@ -7249,99 +7244,99 @@ const pt = Me(({
|
|
|
7249
7244
|
bodyMovement: "idle",
|
|
7250
7245
|
movementIntensity: 0.5,
|
|
7251
7246
|
...o
|
|
7252
|
-
},
|
|
7253
|
-
ttsEndpoint:
|
|
7254
|
-
ttsApikey:
|
|
7255
|
-
ttsService:
|
|
7247
|
+
}, B = {
|
|
7248
|
+
ttsEndpoint: D.endpoint,
|
|
7249
|
+
ttsApikey: D.apiKey,
|
|
7250
|
+
ttsService: k,
|
|
7256
7251
|
lipsyncModules: ["en"],
|
|
7257
7252
|
cameraView: "upper"
|
|
7258
|
-
},
|
|
7253
|
+
}, T = O(async () => {
|
|
7259
7254
|
if (!(!h.current || r.current))
|
|
7260
7255
|
try {
|
|
7261
|
-
if (a(!0), c(null), r.current = new Be(h.current,
|
|
7262
|
-
if (
|
|
7263
|
-
const
|
|
7264
|
-
t(
|
|
7256
|
+
if (a(!0), c(null), r.current = new Be(h.current, B), await r.current.showAvatar(p, (j) => {
|
|
7257
|
+
if (j.lengthComputable) {
|
|
7258
|
+
const X = Math.min(100, Math.round(j.loaded / j.total * 100));
|
|
7259
|
+
t(X);
|
|
7265
7260
|
}
|
|
7266
7261
|
}), r.current.morphs && r.current.morphs.length > 0) {
|
|
7267
|
-
const
|
|
7268
|
-
console.log("Available morph targets:", Object.keys(
|
|
7269
|
-
const
|
|
7270
|
-
console.log("Viseme morph targets found:",
|
|
7262
|
+
const j = r.current.morphs[0].morphTargetDictionary;
|
|
7263
|
+
console.log("Available morph targets:", Object.keys(j));
|
|
7264
|
+
const X = Object.keys(j).filter((oe) => oe.startsWith("viseme_"));
|
|
7265
|
+
console.log("Viseme morph targets found:", X), X.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"));
|
|
7271
7266
|
}
|
|
7272
|
-
if (await new Promise((
|
|
7273
|
-
const
|
|
7274
|
-
r.current.lipsync && Object.keys(r.current.lipsync).length > 0 ? (console.log("Lip-sync modules loaded:", Object.keys(r.current.lipsync)),
|
|
7267
|
+
if (await new Promise((j) => {
|
|
7268
|
+
const X = () => {
|
|
7269
|
+
r.current.lipsync && Object.keys(r.current.lipsync).length > 0 ? (console.log("Lip-sync modules loaded:", Object.keys(r.current.lipsync)), j()) : (console.log("Waiting for lip-sync modules to load..."), setTimeout(X, 100));
|
|
7275
7270
|
};
|
|
7276
|
-
|
|
7271
|
+
X();
|
|
7277
7272
|
}), r.current && r.current.setShowFullAvatar)
|
|
7278
7273
|
try {
|
|
7279
7274
|
r.current.setShowFullAvatar(!0), console.log("Avatar initialized in full body mode");
|
|
7280
|
-
} catch (
|
|
7281
|
-
console.warn("Error setting full body mode on initialization:",
|
|
7275
|
+
} catch (j) {
|
|
7276
|
+
console.warn("Error setting full body mode on initialization:", j);
|
|
7282
7277
|
}
|
|
7283
|
-
a(!1),
|
|
7278
|
+
a(!1), x(!0), n(r.current);
|
|
7284
7279
|
const E = () => {
|
|
7285
7280
|
document.visibilityState === "visible" ? r.current?.start() : r.current?.stop();
|
|
7286
7281
|
};
|
|
7287
7282
|
return document.addEventListener("visibilitychange", E), () => {
|
|
7288
7283
|
document.removeEventListener("visibilitychange", E);
|
|
7289
7284
|
};
|
|
7290
|
-
} catch (
|
|
7291
|
-
console.error("Error initializing TalkingHead:",
|
|
7285
|
+
} catch (S) {
|
|
7286
|
+
console.error("Error initializing TalkingHead:", S), c(S.message || "Failed to initialize avatar"), a(!1), e(S);
|
|
7292
7287
|
}
|
|
7293
7288
|
}, []);
|
|
7294
|
-
ce(() => (
|
|
7289
|
+
ce(() => (T(), () => {
|
|
7295
7290
|
r.current && (r.current.stop(), r.current.dispose(), r.current = null);
|
|
7296
|
-
}), [
|
|
7297
|
-
const
|
|
7291
|
+
}), [T]);
|
|
7292
|
+
const R = O((S) => {
|
|
7298
7293
|
if (r.current && g)
|
|
7299
7294
|
try {
|
|
7300
|
-
console.log("Speaking text:",
|
|
7301
|
-
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(
|
|
7295
|
+
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(() => {
|
|
7296
|
+
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");
|
|
7302
7297
|
}, 500));
|
|
7303
7298
|
} catch (E) {
|
|
7304
7299
|
console.error("Error speaking text:", E), c(E.message || "Failed to speak text");
|
|
7305
7300
|
}
|
|
7306
7301
|
else
|
|
7307
7302
|
console.warn("Avatar not ready for speaking. isReady:", g, "talkingHeadRef:", !!r.current);
|
|
7308
|
-
}, [g, p]),
|
|
7303
|
+
}, [g, p]), L = O(() => {
|
|
7309
7304
|
r.current && (r.current.stopSpeaking(), r.current.setSlowdownRate && (r.current.setSlowdownRate(1), console.log("Reset timing to normal")));
|
|
7310
|
-
}, []),
|
|
7311
|
-
r.current && r.current.setMood(
|
|
7312
|
-
}, []),
|
|
7313
|
-
r.current && r.current.setSlowdownRate && (r.current.setSlowdownRate(
|
|
7314
|
-
}, []),
|
|
7305
|
+
}, []), I = O((S) => {
|
|
7306
|
+
r.current && r.current.setMood(S);
|
|
7307
|
+
}, []), z = O((S) => {
|
|
7308
|
+
r.current && r.current.setSlowdownRate && (r.current.setSlowdownRate(S), console.log("Timing adjustment set to:", S));
|
|
7309
|
+
}, []), Y = O((S, E = !1) => {
|
|
7315
7310
|
if (r.current && r.current.playAnimation) {
|
|
7316
7311
|
if (r.current.setShowFullAvatar)
|
|
7317
7312
|
try {
|
|
7318
7313
|
r.current.setShowFullAvatar(!0);
|
|
7319
|
-
} catch (
|
|
7320
|
-
console.warn("Error setting full body mode:",
|
|
7314
|
+
} catch (X) {
|
|
7315
|
+
console.warn("Error setting full body mode:", X);
|
|
7321
7316
|
}
|
|
7322
|
-
if (
|
|
7317
|
+
if (S.includes("."))
|
|
7323
7318
|
try {
|
|
7324
|
-
r.current.playAnimation(
|
|
7325
|
-
} catch (
|
|
7326
|
-
console.log(`Failed to play ${
|
|
7319
|
+
r.current.playAnimation(S, null, 10, 0, 0.01, E), console.log("Playing animation:", S);
|
|
7320
|
+
} catch (X) {
|
|
7321
|
+
console.log(`Failed to play ${S}:`, X);
|
|
7327
7322
|
try {
|
|
7328
7323
|
r.current.setBodyMovement("idle"), console.log("Fallback to idle animation");
|
|
7329
|
-
} catch (
|
|
7330
|
-
console.warn("Fallback animation also failed:",
|
|
7324
|
+
} catch (oe) {
|
|
7325
|
+
console.warn("Fallback animation also failed:", oe);
|
|
7331
7326
|
}
|
|
7332
7327
|
}
|
|
7333
7328
|
else {
|
|
7334
|
-
const
|
|
7335
|
-
let
|
|
7336
|
-
for (const le of
|
|
7329
|
+
const X = [".fbx", ".glb", ".gltf"];
|
|
7330
|
+
let oe = !1;
|
|
7331
|
+
for (const le of X)
|
|
7337
7332
|
try {
|
|
7338
|
-
r.current.playAnimation(
|
|
7333
|
+
r.current.playAnimation(S + le, null, 10, 0, 0.01, E), console.log("Playing animation:", S + le), oe = !0;
|
|
7339
7334
|
break;
|
|
7340
7335
|
} catch {
|
|
7341
|
-
console.log(`Failed to play ${
|
|
7336
|
+
console.log(`Failed to play ${S}${le}, trying next format...`);
|
|
7342
7337
|
}
|
|
7343
|
-
if (!
|
|
7344
|
-
console.warn("Animation system not available or animation not found:",
|
|
7338
|
+
if (!oe) {
|
|
7339
|
+
console.warn("Animation system not available or animation not found:", S);
|
|
7345
7340
|
try {
|
|
7346
7341
|
r.current.setBodyMovement("idle"), console.log("Fallback to idle animation");
|
|
7347
7342
|
} catch (le) {
|
|
@@ -7350,37 +7345,37 @@ const pt = Me(({
|
|
|
7350
7345
|
}
|
|
7351
7346
|
}
|
|
7352
7347
|
} else
|
|
7353
|
-
console.warn("Animation system not available or animation not found:",
|
|
7348
|
+
console.warn("Animation system not available or animation not found:", S);
|
|
7354
7349
|
}, []);
|
|
7355
7350
|
return Fe(l, () => ({
|
|
7356
|
-
speakText:
|
|
7357
|
-
stopSpeaking:
|
|
7358
|
-
setMood:
|
|
7359
|
-
setTimingAdjustment:
|
|
7360
|
-
playAnimation:
|
|
7351
|
+
speakText: R,
|
|
7352
|
+
stopSpeaking: L,
|
|
7353
|
+
setMood: I,
|
|
7354
|
+
setTimingAdjustment: z,
|
|
7355
|
+
playAnimation: Y,
|
|
7361
7356
|
isReady: g,
|
|
7362
7357
|
talkingHead: r.current,
|
|
7363
|
-
setBodyMovement: (
|
|
7358
|
+
setBodyMovement: (S) => {
|
|
7364
7359
|
if (r.current && r.current.setShowFullAvatar && r.current.setBodyMovement)
|
|
7365
7360
|
try {
|
|
7366
|
-
r.current.setShowFullAvatar(!0), r.current.setBodyMovement(
|
|
7361
|
+
r.current.setShowFullAvatar(!0), r.current.setBodyMovement(S), console.log("Body movement set with full body mode:", S);
|
|
7367
7362
|
} catch (E) {
|
|
7368
7363
|
console.warn("Error setting body movement:", E);
|
|
7369
7364
|
}
|
|
7370
7365
|
},
|
|
7371
|
-
setMovementIntensity: (
|
|
7366
|
+
setMovementIntensity: (S) => r.current?.setMovementIntensity(S),
|
|
7372
7367
|
playRandomDance: () => {
|
|
7373
7368
|
if (r.current && r.current.setShowFullAvatar && r.current.playRandomDance)
|
|
7374
7369
|
try {
|
|
7375
7370
|
r.current.setShowFullAvatar(!0), r.current.playRandomDance(), console.log("Random dance played with full body mode");
|
|
7376
|
-
} catch (
|
|
7377
|
-
console.warn("Error playing random dance:",
|
|
7371
|
+
} catch (S) {
|
|
7372
|
+
console.warn("Error playing random dance:", S);
|
|
7378
7373
|
}
|
|
7379
7374
|
},
|
|
7380
|
-
playReaction: (
|
|
7375
|
+
playReaction: (S) => {
|
|
7381
7376
|
if (r.current && r.current.setShowFullAvatar && r.current.playReaction)
|
|
7382
7377
|
try {
|
|
7383
|
-
r.current.setShowFullAvatar(!0), r.current.playReaction(
|
|
7378
|
+
r.current.setShowFullAvatar(!0), r.current.playReaction(S), console.log("Reaction played with full body mode:", S);
|
|
7384
7379
|
} catch (E) {
|
|
7385
7380
|
console.warn("Error playing reaction:", E);
|
|
7386
7381
|
}
|
|
@@ -7389,14 +7384,14 @@ const pt = Me(({
|
|
|
7389
7384
|
if (r.current && r.current.setShowFullAvatar && r.current.playCelebration)
|
|
7390
7385
|
try {
|
|
7391
7386
|
r.current.setShowFullAvatar(!0), r.current.playCelebration(), console.log("Celebration played with full body mode");
|
|
7392
|
-
} catch (
|
|
7393
|
-
console.warn("Error playing celebration:",
|
|
7387
|
+
} catch (S) {
|
|
7388
|
+
console.warn("Error playing celebration:", S);
|
|
7394
7389
|
}
|
|
7395
7390
|
},
|
|
7396
|
-
setShowFullAvatar: (
|
|
7391
|
+
setShowFullAvatar: (S) => {
|
|
7397
7392
|
if (r.current && r.current.setShowFullAvatar)
|
|
7398
7393
|
try {
|
|
7399
|
-
r.current.setShowFullAvatar(
|
|
7394
|
+
r.current.setShowFullAvatar(S), console.log("Show full avatar set to:", S);
|
|
7400
7395
|
} catch (E) {
|
|
7401
7396
|
console.warn("Error setting showFullAvatar:", E);
|
|
7402
7397
|
}
|
|
@@ -7405,16 +7400,16 @@ const pt = Me(({
|
|
|
7405
7400
|
if (r.current && r.current.lockAvatarPosition)
|
|
7406
7401
|
try {
|
|
7407
7402
|
r.current.lockAvatarPosition();
|
|
7408
|
-
} catch (
|
|
7409
|
-
console.warn("Error locking avatar position:",
|
|
7403
|
+
} catch (S) {
|
|
7404
|
+
console.warn("Error locking avatar position:", S);
|
|
7410
7405
|
}
|
|
7411
7406
|
},
|
|
7412
7407
|
unlockAvatarPosition: () => {
|
|
7413
7408
|
if (r.current && r.current.unlockAvatarPosition)
|
|
7414
7409
|
try {
|
|
7415
7410
|
r.current.unlockAvatarPosition();
|
|
7416
|
-
} catch (
|
|
7417
|
-
console.warn("Error unlocking avatar position:",
|
|
7411
|
+
} catch (S) {
|
|
7412
|
+
console.warn("Error unlocking avatar position:", S);
|
|
7418
7413
|
}
|
|
7419
7414
|
}
|
|
7420
7415
|
})), /* @__PURE__ */ Pe("div", { className: `talking-head-container ${i}`, style: s, children: [
|
|
@@ -7454,10 +7449,10 @@ const pt = Me(({
|
|
|
7454
7449
|
] });
|
|
7455
7450
|
});
|
|
7456
7451
|
pt.displayName = "TalkingHeadComponent";
|
|
7457
|
-
async function gt(
|
|
7452
|
+
async function gt(V) {
|
|
7458
7453
|
try {
|
|
7459
|
-
console.log(`📥 Loading animation manifest from: ${
|
|
7460
|
-
const t = await fetch(
|
|
7454
|
+
console.log(`📥 Loading animation manifest from: ${V}`);
|
|
7455
|
+
const t = await fetch(V);
|
|
7461
7456
|
if (!t.ok)
|
|
7462
7457
|
throw new Error(`Failed to fetch manifest: ${t.status} ${t.statusText}`);
|
|
7463
7458
|
const e = await t.json();
|
|
@@ -7473,7 +7468,7 @@ async function gt(Z) {
|
|
|
7473
7468
|
}
|
|
7474
7469
|
}
|
|
7475
7470
|
const yt = Me(({
|
|
7476
|
-
text:
|
|
7471
|
+
text: V = null,
|
|
7477
7472
|
avatarUrl: t = "/avatars/brunette.glb",
|
|
7478
7473
|
avatarBody: e = "F",
|
|
7479
7474
|
mood: n = "neutral",
|
|
@@ -7491,68 +7486,68 @@ const yt = Me(({
|
|
|
7491
7486
|
},
|
|
7492
7487
|
onError: g = () => {
|
|
7493
7488
|
},
|
|
7494
|
-
onSpeechEnd:
|
|
7489
|
+
onSpeechEnd: x = () => {
|
|
7495
7490
|
},
|
|
7496
|
-
className:
|
|
7497
|
-
style:
|
|
7498
|
-
animations:
|
|
7491
|
+
className: f = "",
|
|
7492
|
+
style: k = {},
|
|
7493
|
+
animations: D = {},
|
|
7499
7494
|
autoAnimationGroup: p = null,
|
|
7500
7495
|
// e.g., "talking" - will randomly select from this group when speaking
|
|
7501
|
-
autoIdleGroup:
|
|
7496
|
+
autoIdleGroup: B = null,
|
|
7502
7497
|
// e.g., "idle" - will randomly select from this group when idle
|
|
7503
|
-
autoSpeak:
|
|
7504
|
-
},
|
|
7505
|
-
const
|
|
7498
|
+
autoSpeak: T = !1
|
|
7499
|
+
}, R) => {
|
|
7500
|
+
const L = W(null), I = W(null), z = W(u), Y = W(null), S = W(null), E = W(!1), j = W({ remainingText: null, originalText: null, options: null }), X = W([]), [oe, le] = pe(!0), [ge, de] = pe(null), [ee, be] = pe(!1), [Q, b] = pe(!1), [v, F] = pe(D), P = W(null);
|
|
7506
7501
|
ce(() => {
|
|
7507
7502
|
E.current = Q;
|
|
7508
7503
|
}, [Q]), ce(() => {
|
|
7509
7504
|
(async () => {
|
|
7510
|
-
if (
|
|
7505
|
+
if (D.manifest)
|
|
7511
7506
|
try {
|
|
7512
|
-
console.log("🔄 Loading animations from manifest:",
|
|
7513
|
-
const
|
|
7514
|
-
|
|
7515
|
-
male: Object.keys(
|
|
7516
|
-
female: Object.keys(
|
|
7517
|
-
shared: Object.keys(
|
|
7507
|
+
console.log("🔄 Loading animations from manifest:", D.manifest);
|
|
7508
|
+
const H = await gt(D.manifest);
|
|
7509
|
+
F(H), console.log("✅ Animations loaded and set:", H), H._genderSpecific ? console.log("👥 Gender-specific animations detected:", {
|
|
7510
|
+
male: Object.keys(H._genderSpecific.male || {}),
|
|
7511
|
+
female: Object.keys(H._genderSpecific.female || {}),
|
|
7512
|
+
shared: Object.keys(H._genderSpecific.shared || {})
|
|
7518
7513
|
}) : console.log("⚠️ No gender-specific animations found in manifest");
|
|
7519
|
-
} catch (
|
|
7520
|
-
console.error("❌ Failed to load animation manifest:",
|
|
7514
|
+
} catch (H) {
|
|
7515
|
+
console.error("❌ Failed to load animation manifest:", H), F(D);
|
|
7521
7516
|
}
|
|
7522
7517
|
else
|
|
7523
|
-
console.log("📝 Using animations from props (no manifest):",
|
|
7518
|
+
console.log("📝 Using animations from props (no manifest):", D), F(D);
|
|
7524
7519
|
})();
|
|
7525
|
-
}, [
|
|
7526
|
-
|
|
7520
|
+
}, [D]), ce(() => {
|
|
7521
|
+
z.current = u;
|
|
7527
7522
|
}, [u]);
|
|
7528
|
-
const
|
|
7523
|
+
const N = Ee(), te = s || N.service;
|
|
7529
7524
|
let q;
|
|
7530
|
-
|
|
7525
|
+
te === "browser" ? q = {
|
|
7531
7526
|
service: "browser",
|
|
7532
7527
|
endpoint: "",
|
|
7533
7528
|
apiKey: null,
|
|
7534
7529
|
defaultVoice: "Google US English"
|
|
7535
|
-
} :
|
|
7530
|
+
} : te === "elevenlabs" ? q = {
|
|
7536
7531
|
service: "elevenlabs",
|
|
7537
7532
|
endpoint: "https://api.elevenlabs.io/v1/text-to-speech",
|
|
7538
|
-
apiKey: l ||
|
|
7539
|
-
defaultVoice: o ||
|
|
7540
|
-
voices:
|
|
7541
|
-
} :
|
|
7533
|
+
apiKey: l || N.apiKey,
|
|
7534
|
+
defaultVoice: o || N.defaultVoice || Ie.defaultVoice,
|
|
7535
|
+
voices: N.voices || Ie.voices
|
|
7536
|
+
} : te === "deepgram" ? q = {
|
|
7542
7537
|
service: "deepgram",
|
|
7543
7538
|
endpoint: "https://api.deepgram.com/v1/speak",
|
|
7544
|
-
apiKey: l ||
|
|
7545
|
-
defaultVoice: o ||
|
|
7546
|
-
voices:
|
|
7539
|
+
apiKey: l || N.apiKey,
|
|
7540
|
+
defaultVoice: o || N.defaultVoice || Te.defaultVoice,
|
|
7541
|
+
voices: N.voices || Te.voices
|
|
7547
7542
|
} : q = {
|
|
7548
|
-
...
|
|
7549
|
-
apiKey: l !== null ? l :
|
|
7543
|
+
...N,
|
|
7544
|
+
apiKey: l !== null ? l : N.apiKey
|
|
7550
7545
|
};
|
|
7551
7546
|
const _ = {
|
|
7552
7547
|
url: t,
|
|
7553
7548
|
body: e,
|
|
7554
7549
|
avatarMood: n,
|
|
7555
|
-
ttsLang:
|
|
7550
|
+
ttsLang: te === "browser" ? "en-US" : i,
|
|
7556
7551
|
ttsVoice: o || q.defaultVoice,
|
|
7557
7552
|
lipsyncLang: "en",
|
|
7558
7553
|
showFullAvatar: u,
|
|
@@ -7561,24 +7556,24 @@ const yt = Me(({
|
|
|
7561
7556
|
}, Ae = {
|
|
7562
7557
|
ttsEndpoint: q.endpoint,
|
|
7563
7558
|
ttsApikey: q.apiKey,
|
|
7564
|
-
ttsService:
|
|
7559
|
+
ttsService: te,
|
|
7565
7560
|
lipsyncModules: ["en"],
|
|
7566
7561
|
cameraView: a
|
|
7567
|
-
}, Se =
|
|
7568
|
-
if (!(!
|
|
7562
|
+
}, Se = O(async () => {
|
|
7563
|
+
if (!(!L.current || I.current))
|
|
7569
7564
|
try {
|
|
7570
|
-
le(!0), de(null),
|
|
7565
|
+
le(!0), de(null), I.current = new Be(L.current, Ae), console.log("Avatar config being passed:", {
|
|
7571
7566
|
url: _.url,
|
|
7572
7567
|
body: _.body,
|
|
7573
7568
|
avatarMood: _.avatarMood
|
|
7574
|
-
}), await
|
|
7575
|
-
if (
|
|
7576
|
-
const
|
|
7577
|
-
c(
|
|
7569
|
+
}), await I.current.showAvatar(_, (H) => {
|
|
7570
|
+
if (H.lengthComputable) {
|
|
7571
|
+
const G = Math.min(100, Math.round(H.loaded / H.total * 100));
|
|
7572
|
+
c(G);
|
|
7578
7573
|
}
|
|
7579
|
-
}),
|
|
7574
|
+
}), I.current?.avatar && console.log("Avatar body after initialization:", I.current.avatar.body), le(!1), be(!0), d(I.current);
|
|
7580
7575
|
const A = () => {
|
|
7581
|
-
document.visibilityState === "visible" ?
|
|
7576
|
+
document.visibilityState === "visible" ? I.current?.start() : I.current?.stop();
|
|
7582
7577
|
};
|
|
7583
7578
|
return document.addEventListener("visibilitychange", A), () => {
|
|
7584
7579
|
document.removeEventListener("visibilitychange", A);
|
|
@@ -7588,51 +7583,51 @@ const yt = Me(({
|
|
|
7588
7583
|
}
|
|
7589
7584
|
}, []);
|
|
7590
7585
|
ce(() => (Se(), () => {
|
|
7591
|
-
|
|
7586
|
+
I.current && (I.current.stop(), I.current.dispose(), I.current = null);
|
|
7592
7587
|
}), [Se]);
|
|
7593
|
-
const Le =
|
|
7594
|
-
if (
|
|
7588
|
+
const Le = O(async () => {
|
|
7589
|
+
if (I.current)
|
|
7595
7590
|
try {
|
|
7596
|
-
const A =
|
|
7591
|
+
const A = I.current.audioCtx || I.current.audioContext;
|
|
7597
7592
|
A && (A.state === "suspended" || A.state === "interrupted") && (await A.resume(), console.log("Audio context resumed"));
|
|
7598
7593
|
} catch (A) {
|
|
7599
7594
|
console.warn("Failed to resume audio context:", A);
|
|
7600
7595
|
}
|
|
7601
|
-
}, []), ke =
|
|
7602
|
-
if (!
|
|
7596
|
+
}, []), ke = O((A) => {
|
|
7597
|
+
if (!v)
|
|
7603
7598
|
return console.warn("No animations loaded"), null;
|
|
7604
|
-
let
|
|
7605
|
-
if (
|
|
7606
|
-
const J = (e?.toUpperCase() || "F") === "M" ? "male" : "female",
|
|
7607
|
-
|
|
7599
|
+
let H = null;
|
|
7600
|
+
if (v._genderSpecific) {
|
|
7601
|
+
const J = (e?.toUpperCase() || "F") === "M" ? "male" : "female", ie = v._genderSpecific[J];
|
|
7602
|
+
ie && ie[A] ? (H = ie[A], console.log(`Using ${J} animations for "${A}":`, H)) : v._genderSpecific.shared && v._genderSpecific.shared[A] && (H = v._genderSpecific.shared[A], console.log(`Using shared animations for "${A}":`, H));
|
|
7608
7603
|
}
|
|
7609
|
-
if (!
|
|
7610
|
-
if (console.warn(`Animation group "${A}" not found. Available groups:`, Object.keys(
|
|
7604
|
+
if (!H && v[A] && (H = v[A], console.log(`Using root-level animations for "${A}":`, H)), !H) {
|
|
7605
|
+
if (console.warn(`Animation group "${A}" not found. Available groups:`, Object.keys(v).filter((G) => G !== "_genderSpecific")), v._genderSpecific) {
|
|
7611
7606
|
const J = (e?.toUpperCase() || "F") === "M" ? "male" : "female";
|
|
7612
|
-
console.warn(`Gender-specific groups (${J}):`, Object.keys(
|
|
7607
|
+
console.warn(`Gender-specific groups (${J}):`, Object.keys(v._genderSpecific[J] || {}));
|
|
7613
7608
|
}
|
|
7614
7609
|
return null;
|
|
7615
7610
|
}
|
|
7616
|
-
if (Array.isArray(
|
|
7617
|
-
const
|
|
7618
|
-
return
|
|
7611
|
+
if (Array.isArray(H) && H.length > 0) {
|
|
7612
|
+
const G = Math.floor(Math.random() * H.length);
|
|
7613
|
+
return H[G];
|
|
7619
7614
|
}
|
|
7620
|
-
return typeof
|
|
7621
|
-
}, [
|
|
7622
|
-
if (!
|
|
7615
|
+
return typeof H == "string" ? H : (console.warn(`Animation group "${A}" is not a valid format (expected array or string):`, H), null);
|
|
7616
|
+
}, [v, e]), w = O((A, H = !1) => {
|
|
7617
|
+
if (!I.current)
|
|
7623
7618
|
return console.warn("TalkingHead not initialized yet"), null;
|
|
7624
|
-
const
|
|
7625
|
-
if (
|
|
7619
|
+
const G = ke(A);
|
|
7620
|
+
if (G)
|
|
7626
7621
|
try {
|
|
7627
|
-
return
|
|
7622
|
+
return I.current.playAnimation(G, null, 10, 0, 0.01, H), console.log(`✅ Playing random animation from "${A}" group:`, G), G;
|
|
7628
7623
|
} catch (J) {
|
|
7629
7624
|
return console.error(`❌ Failed to play random animation from "${A}" group:`, J), null;
|
|
7630
7625
|
}
|
|
7631
7626
|
else
|
|
7632
7627
|
console.warn(`⚠️ No animation found for group "${A}"`);
|
|
7633
7628
|
return null;
|
|
7634
|
-
}, [ke]),
|
|
7635
|
-
if (!
|
|
7629
|
+
}, [ke]), U = O(async (A, H = {}) => {
|
|
7630
|
+
if (!I.current || !ee) {
|
|
7636
7631
|
console.warn("Avatar not ready for speaking");
|
|
7637
7632
|
return;
|
|
7638
7633
|
}
|
|
@@ -7641,93 +7636,93 @@ const yt = Me(({
|
|
|
7641
7636
|
return;
|
|
7642
7637
|
}
|
|
7643
7638
|
await Le();
|
|
7644
|
-
const
|
|
7645
|
-
|
|
7639
|
+
const G = H.animationGroup || p;
|
|
7640
|
+
G && !H.skipAnimation ? (console.log(`🎬 Attempting to play animation from group: "${G}"`), console.log(`📊 Current avatarBody: "${e}", loadedAnimations:`, v), w(G)) : console.log(`⏭️ Skipping animation (group: ${G}, skipAnimation: ${H.skipAnimation})`), j.current = { remainingText: null, originalText: null, options: null }, X.current = [], Y.current = { text: A, options: H }, S.current && (clearInterval(S.current), S.current = null), b(!1), E.current = !1;
|
|
7646
7641
|
const J = A.split(/[.!?]+/).filter((se) => se.trim().length > 0);
|
|
7647
|
-
|
|
7648
|
-
const
|
|
7649
|
-
lipsyncLang:
|
|
7642
|
+
X.current = J;
|
|
7643
|
+
const ie = {
|
|
7644
|
+
lipsyncLang: H.lipsyncLang || "en",
|
|
7650
7645
|
onSpeechEnd: () => {
|
|
7651
|
-
|
|
7646
|
+
S.current && (clearInterval(S.current), S.current = null), H.onSpeechEnd && H.onSpeechEnd(), x();
|
|
7652
7647
|
}
|
|
7653
7648
|
};
|
|
7654
7649
|
try {
|
|
7655
|
-
|
|
7650
|
+
I.current.speakText(A, ie);
|
|
7656
7651
|
} catch (se) {
|
|
7657
7652
|
console.error("Error speaking text:", se), de(se.message || "Failed to speak text");
|
|
7658
7653
|
}
|
|
7659
|
-
}, [
|
|
7654
|
+
}, [ee, x, Le, p, w]);
|
|
7660
7655
|
ce(() => {
|
|
7661
|
-
if (!
|
|
7656
|
+
if (!ee || !B || !I.current)
|
|
7662
7657
|
return;
|
|
7663
|
-
|
|
7658
|
+
P.current && clearInterval(P.current);
|
|
7664
7659
|
const A = () => {
|
|
7665
|
-
|
|
7660
|
+
I.current && !E.current && w(B);
|
|
7666
7661
|
};
|
|
7667
|
-
return A(),
|
|
7662
|
+
return A(), P.current = setInterval(() => {
|
|
7668
7663
|
A();
|
|
7669
7664
|
}, 12e3 + Math.random() * 3e3), () => {
|
|
7670
|
-
|
|
7665
|
+
P.current && (clearInterval(P.current), P.current = null);
|
|
7671
7666
|
};
|
|
7672
|
-
}, [
|
|
7673
|
-
|
|
7674
|
-
}, [
|
|
7675
|
-
const K =
|
|
7676
|
-
if (
|
|
7667
|
+
}, [ee, B, w]), ce(() => {
|
|
7668
|
+
ee && V && T && I.current && U(V);
|
|
7669
|
+
}, [ee, V, T, U]);
|
|
7670
|
+
const K = O(() => {
|
|
7671
|
+
if (I.current)
|
|
7677
7672
|
try {
|
|
7678
|
-
const A =
|
|
7679
|
-
if (A ||
|
|
7680
|
-
|
|
7673
|
+
const A = I.current.isSpeaking || !1, H = I.current.audioPlaylist || [], G = I.current.speechQueue || [];
|
|
7674
|
+
if (A || H.length > 0 || G.length > 0) {
|
|
7675
|
+
S.current && (clearInterval(S.current), S.current = null);
|
|
7681
7676
|
let J = "";
|
|
7682
|
-
|
|
7677
|
+
G.length > 0 && (J = G.map((ie) => ie.text && Array.isArray(ie.text) ? ie.text.map((se) => se.word).join(" ") : ie.text || "").join(" ")), j.current = {
|
|
7683
7678
|
remainingText: J || null,
|
|
7684
|
-
originalText:
|
|
7685
|
-
options:
|
|
7686
|
-
},
|
|
7679
|
+
originalText: Y.current?.text || null,
|
|
7680
|
+
options: Y.current?.options || null
|
|
7681
|
+
}, I.current.speechQueue.length = 0, I.current.pauseSpeaking(), b(!0), E.current = !0;
|
|
7687
7682
|
}
|
|
7688
7683
|
} catch (A) {
|
|
7689
7684
|
console.warn("Error pausing speech:", A);
|
|
7690
7685
|
}
|
|
7691
|
-
}, []),
|
|
7692
|
-
if (!(!
|
|
7686
|
+
}, []), ne = O(async () => {
|
|
7687
|
+
if (!(!I.current || !Q))
|
|
7693
7688
|
try {
|
|
7694
|
-
await Le(),
|
|
7695
|
-
const A =
|
|
7696
|
-
J &&
|
|
7689
|
+
await Le(), b(!1), E.current = !1;
|
|
7690
|
+
const A = j.current?.remainingText, H = j.current?.originalText || Y.current?.text, G = j.current?.options || Y.current?.options || {}, J = A || H;
|
|
7691
|
+
J && U(J, G);
|
|
7697
7692
|
} catch (A) {
|
|
7698
|
-
console.warn("Error resuming speech:", A),
|
|
7693
|
+
console.warn("Error resuming speech:", A), b(!1), E.current = !1;
|
|
7699
7694
|
}
|
|
7700
|
-
}, [Q,
|
|
7701
|
-
|
|
7695
|
+
}, [Q, U, Le]), me = O(() => {
|
|
7696
|
+
I.current && (I.current.stopSpeaking(), S.current && (clearInterval(S.current), S.current = null), b(!1), E.current = !1);
|
|
7702
7697
|
}, []);
|
|
7703
|
-
return Fe(
|
|
7704
|
-
speakText:
|
|
7698
|
+
return Fe(R, () => ({
|
|
7699
|
+
speakText: U,
|
|
7705
7700
|
pauseSpeaking: K,
|
|
7706
|
-
resumeSpeaking:
|
|
7701
|
+
resumeSpeaking: ne,
|
|
7707
7702
|
stopSpeaking: me,
|
|
7708
7703
|
resumeAudioContext: Le,
|
|
7709
7704
|
isPaused: () => Q,
|
|
7710
|
-
setMood: (A) =>
|
|
7705
|
+
setMood: (A) => I.current?.setMood(A),
|
|
7711
7706
|
setBodyMovement: (A) => {
|
|
7712
|
-
|
|
7707
|
+
I.current && I.current.setBodyMovement(A);
|
|
7713
7708
|
},
|
|
7714
|
-
playAnimation: (A,
|
|
7715
|
-
|
|
7709
|
+
playAnimation: (A, H = !1) => {
|
|
7710
|
+
I.current && I.current.playAnimation && I.current.playAnimation(A, null, 10, 0, 0.01, H);
|
|
7716
7711
|
},
|
|
7717
|
-
playRandomAnimation: (A,
|
|
7712
|
+
playRandomAnimation: (A, H = !1) => w(A, H),
|
|
7718
7713
|
getRandomAnimation: (A) => ke(A),
|
|
7719
|
-
playReaction: (A) =>
|
|
7720
|
-
playCelebration: () =>
|
|
7714
|
+
playReaction: (A) => I.current?.playReaction(A),
|
|
7715
|
+
playCelebration: () => I.current?.playCelebration(),
|
|
7721
7716
|
setShowFullAvatar: (A) => {
|
|
7722
|
-
|
|
7717
|
+
I.current && (z.current = A, I.current.setShowFullAvatar(A));
|
|
7723
7718
|
},
|
|
7724
|
-
isReady:
|
|
7725
|
-
talkingHead:
|
|
7726
|
-
})), /* @__PURE__ */ Pe("div", { className: `simple-talking-avatar-container ${
|
|
7719
|
+
isReady: ee,
|
|
7720
|
+
talkingHead: I.current
|
|
7721
|
+
})), /* @__PURE__ */ Pe("div", { className: `simple-talking-avatar-container ${f}`, style: k, children: [
|
|
7727
7722
|
/* @__PURE__ */ ye(
|
|
7728
7723
|
"div",
|
|
7729
7724
|
{
|
|
7730
|
-
ref:
|
|
7725
|
+
ref: L,
|
|
7731
7726
|
className: "talking-head-viewer",
|
|
7732
7727
|
style: {
|
|
7733
7728
|
width: "100%",
|
|
@@ -7736,7 +7731,7 @@ const yt = Me(({
|
|
|
7736
7731
|
}
|
|
7737
7732
|
}
|
|
7738
7733
|
),
|
|
7739
|
-
|
|
7734
|
+
oe && /* @__PURE__ */ ye("div", { className: "loading-overlay", style: {
|
|
7740
7735
|
position: "absolute",
|
|
7741
7736
|
top: "50%",
|
|
7742
7737
|
left: "50%",
|
|
@@ -7761,7 +7756,7 @@ const yt = Me(({
|
|
|
7761
7756
|
});
|
|
7762
7757
|
yt.displayName = "SimpleTalkingAvatar";
|
|
7763
7758
|
const ft = Me(({
|
|
7764
|
-
curriculumData:
|
|
7759
|
+
curriculumData: V = null,
|
|
7765
7760
|
avatarConfig: t = {},
|
|
7766
7761
|
animations: e = {},
|
|
7767
7762
|
onLessonStart: n = () => {
|
|
@@ -7776,7 +7771,7 @@ const ft = Me(({
|
|
|
7776
7771
|
},
|
|
7777
7772
|
autoStart: h = !1
|
|
7778
7773
|
}, r) => {
|
|
7779
|
-
const u =
|
|
7774
|
+
const u = W(null), a = W({
|
|
7780
7775
|
currentModuleIndex: 0,
|
|
7781
7776
|
currentLessonIndex: 0,
|
|
7782
7777
|
currentQuestionIndex: 0,
|
|
@@ -7786,18 +7781,18 @@ const ft = Me(({
|
|
|
7786
7781
|
curriculumCompleted: !1,
|
|
7787
7782
|
score: 0,
|
|
7788
7783
|
totalQuestions: 0
|
|
7789
|
-
}), d =
|
|
7784
|
+
}), d = W({
|
|
7790
7785
|
onLessonStart: n,
|
|
7791
7786
|
onLessonComplete: i,
|
|
7792
7787
|
onQuestionAnswer: s,
|
|
7793
7788
|
onCurriculumComplete: o,
|
|
7794
7789
|
onCustomAction: l
|
|
7795
|
-
}), c =
|
|
7790
|
+
}), c = W(null), g = W(null), x = W(null), f = W(null), k = W(null), D = W(null), p = W(null), B = W(V?.curriculum || {
|
|
7796
7791
|
title: "Default Curriculum",
|
|
7797
7792
|
description: "No curriculum data provided",
|
|
7798
7793
|
language: "en",
|
|
7799
7794
|
modules: []
|
|
7800
|
-
}),
|
|
7795
|
+
}), T = W({
|
|
7801
7796
|
avatarUrl: t.avatarUrl || "/avatars/brunette.glb",
|
|
7802
7797
|
avatarBody: t.avatarBody || "F",
|
|
7803
7798
|
mood: t.mood || "happy",
|
|
@@ -7820,12 +7815,12 @@ const ft = Me(({
|
|
|
7820
7815
|
onCustomAction: l
|
|
7821
7816
|
};
|
|
7822
7817
|
}, [n, i, s, o, l]), ce(() => {
|
|
7823
|
-
|
|
7818
|
+
B.current = V?.curriculum || {
|
|
7824
7819
|
title: "Default Curriculum",
|
|
7825
7820
|
description: "No curriculum data provided",
|
|
7826
7821
|
language: "en",
|
|
7827
7822
|
modules: []
|
|
7828
|
-
},
|
|
7823
|
+
}, T.current = {
|
|
7829
7824
|
avatarUrl: t.avatarUrl || "/avatars/brunette.glb",
|
|
7830
7825
|
avatarBody: t.avatarBody || "F",
|
|
7831
7826
|
mood: t.mood || "happy",
|
|
@@ -7839,24 +7834,24 @@ const ft = Me(({
|
|
|
7839
7834
|
animations: e,
|
|
7840
7835
|
lipsyncLang: "en"
|
|
7841
7836
|
};
|
|
7842
|
-
}, [
|
|
7843
|
-
const
|
|
7837
|
+
}, [V, t, e]);
|
|
7838
|
+
const R = O(() => (B.current || { modules: [] }).modules[a.current.currentModuleIndex]?.lessons[a.current.currentLessonIndex], []), L = O(() => R()?.questions[a.current.currentQuestionIndex], [R]), I = O((b, v) => v.type === "multiple_choice" || v.type === "true_false" ? b === v.answer : v.type === "code_test" && typeof b == "object" && b !== null ? b.passed === !0 : !1, []), z = O(() => {
|
|
7844
7839
|
a.current.lessonCompleted = !0, a.current.isQuestionMode = !1;
|
|
7845
|
-
const
|
|
7846
|
-
let
|
|
7847
|
-
if (a.current.totalQuestions > 0 ?
|
|
7840
|
+
const b = a.current.totalQuestions > 0 ? Math.round(a.current.score / a.current.totalQuestions * 100) : 100;
|
|
7841
|
+
let v = "Congratulations! You've completed this lesson";
|
|
7842
|
+
if (a.current.totalQuestions > 0 ? v += ` You got ${a.current.score} correct out of ${a.current.totalQuestions} question${a.current.totalQuestions === 1 ? "" : "s"}, achieving a score of ${b} percent. ` : v += "! ", b >= 80 ? v += "Excellent work! You have a great understanding of this topic." : b >= 60 ? v += "Good job! You understand most of the concepts." : v += "Keep practicing! You're making progress.", d.current.onLessonComplete({
|
|
7848
7843
|
moduleIndex: a.current.currentModuleIndex,
|
|
7849
7844
|
lessonIndex: a.current.currentLessonIndex,
|
|
7850
7845
|
score: a.current.score,
|
|
7851
7846
|
totalQuestions: a.current.totalQuestions,
|
|
7852
|
-
percentage:
|
|
7847
|
+
percentage: b
|
|
7853
7848
|
}), d.current.onCustomAction({
|
|
7854
7849
|
type: "lessonComplete",
|
|
7855
7850
|
moduleIndex: a.current.currentModuleIndex,
|
|
7856
7851
|
lessonIndex: a.current.currentLessonIndex,
|
|
7857
7852
|
score: a.current.score,
|
|
7858
7853
|
totalQuestions: a.current.totalQuestions,
|
|
7859
|
-
percentage:
|
|
7854
|
+
percentage: b
|
|
7860
7855
|
}), u.current) {
|
|
7861
7856
|
if (u.current.setMood("happy"), e.lessonComplete)
|
|
7862
7857
|
try {
|
|
@@ -7864,8 +7859,8 @@ const ft = Me(({
|
|
|
7864
7859
|
} catch {
|
|
7865
7860
|
u.current.playCelebration();
|
|
7866
7861
|
}
|
|
7867
|
-
const
|
|
7868
|
-
u.current.speakText(
|
|
7862
|
+
const F = B.current || { modules: [] }, P = F.modules[a.current.currentModuleIndex], N = a.current.currentLessonIndex < (P?.lessons?.length || 0) - 1, te = a.current.currentModuleIndex < (F.modules?.length || 0) - 1, q = N || te, _ = T.current || { lipsyncLang: "en" };
|
|
7863
|
+
u.current.speakText(v, {
|
|
7869
7864
|
lipsyncLang: _.lipsyncLang,
|
|
7870
7865
|
onSpeechEnd: () => {
|
|
7871
7866
|
d.current.onCustomAction({
|
|
@@ -7874,18 +7869,18 @@ const ft = Me(({
|
|
|
7874
7869
|
lessonIndex: a.current.currentLessonIndex,
|
|
7875
7870
|
score: a.current.score,
|
|
7876
7871
|
totalQuestions: a.current.totalQuestions,
|
|
7877
|
-
percentage:
|
|
7872
|
+
percentage: b,
|
|
7878
7873
|
hasNextLesson: q
|
|
7879
7874
|
});
|
|
7880
7875
|
}
|
|
7881
7876
|
});
|
|
7882
7877
|
}
|
|
7883
|
-
}, [e.lessonComplete]),
|
|
7878
|
+
}, [e.lessonComplete]), Y = O(() => {
|
|
7884
7879
|
a.current.curriculumCompleted = !0;
|
|
7885
|
-
const
|
|
7880
|
+
const b = B.current || { modules: [] };
|
|
7886
7881
|
if (d.current.onCurriculumComplete({
|
|
7887
|
-
modules:
|
|
7888
|
-
totalLessons:
|
|
7882
|
+
modules: b.modules.length,
|
|
7883
|
+
totalLessons: b.modules.reduce((v, F) => v + F.lessons.length, 0)
|
|
7889
7884
|
}), u.current) {
|
|
7890
7885
|
if (u.current.setMood("celebrating"), e.curriculumComplete)
|
|
7891
7886
|
try {
|
|
@@ -7893,99 +7888,99 @@ const ft = Me(({
|
|
|
7893
7888
|
} catch {
|
|
7894
7889
|
u.current.playCelebration();
|
|
7895
7890
|
}
|
|
7896
|
-
const
|
|
7897
|
-
u.current.speakText("Amazing! You've completed the entire curriculum! You're now ready to move on to more advanced topics. Well done!", { lipsyncLang:
|
|
7891
|
+
const v = T.current || { lipsyncLang: "en" };
|
|
7892
|
+
u.current.speakText("Amazing! You've completed the entire curriculum! You're now ready to move on to more advanced topics. Well done!", { lipsyncLang: v.lipsyncLang });
|
|
7898
7893
|
}
|
|
7899
|
-
}, [e.curriculumComplete]),
|
|
7900
|
-
const
|
|
7901
|
-
a.current.isQuestionMode = !0, a.current.currentQuestionIndex = 0, a.current.totalQuestions =
|
|
7902
|
-
const
|
|
7903
|
-
|
|
7894
|
+
}, [e.curriculumComplete]), S = O(() => {
|
|
7895
|
+
const b = R();
|
|
7896
|
+
a.current.isQuestionMode = !0, a.current.currentQuestionIndex = 0, a.current.totalQuestions = b?.questions?.length || 0, a.current.score = 0;
|
|
7897
|
+
const v = L();
|
|
7898
|
+
v && d.current.onCustomAction({
|
|
7904
7899
|
type: "questionStart",
|
|
7905
7900
|
moduleIndex: a.current.currentModuleIndex,
|
|
7906
7901
|
lessonIndex: a.current.currentLessonIndex,
|
|
7907
7902
|
questionIndex: a.current.currentQuestionIndex,
|
|
7908
7903
|
totalQuestions: a.current.totalQuestions,
|
|
7909
|
-
question:
|
|
7904
|
+
question: v,
|
|
7910
7905
|
score: a.current.score
|
|
7911
7906
|
});
|
|
7912
|
-
const
|
|
7913
|
-
if (!u.current || !
|
|
7907
|
+
const F = () => {
|
|
7908
|
+
if (!u.current || !v) return;
|
|
7914
7909
|
if (u.current.setMood("happy"), e.questionStart)
|
|
7915
7910
|
try {
|
|
7916
7911
|
u.current.playAnimation(e.questionStart, !0);
|
|
7917
|
-
} catch (
|
|
7918
|
-
console.warn("Failed to play questionStart animation:",
|
|
7912
|
+
} catch (N) {
|
|
7913
|
+
console.warn("Failed to play questionStart animation:", N);
|
|
7919
7914
|
}
|
|
7920
|
-
const
|
|
7921
|
-
|
|
7915
|
+
const P = T.current || { lipsyncLang: "en" };
|
|
7916
|
+
v.type === "code_test" ? u.current.speakText(`Let's test your coding skills! Here's your first challenge: ${v.question}`, { lipsyncLang: P.lipsyncLang }) : v.type === "multiple_choice" ? u.current.speakText(`Now let me ask you some questions. Here's the first one: ${v.question}`, { lipsyncLang: P.lipsyncLang }) : v.type === "true_false" ? u.current.speakText(`Let's start with some true or false questions. First question: ${v.question}`, { lipsyncLang: P.lipsyncLang }) : u.current.speakText(`Now let me ask you some questions. Here's the first one: ${v.question}`, { lipsyncLang: P.lipsyncLang });
|
|
7922
7917
|
};
|
|
7923
|
-
if (u.current && u.current.isReady &&
|
|
7924
|
-
|
|
7918
|
+
if (u.current && u.current.isReady && v)
|
|
7919
|
+
F();
|
|
7925
7920
|
else if (u.current && u.current.isReady) {
|
|
7926
|
-
const
|
|
7927
|
-
u.current.speakText("Now let me ask you some questions to test your understanding.", { lipsyncLang:
|
|
7921
|
+
const P = T.current || { lipsyncLang: "en" };
|
|
7922
|
+
u.current.speakText("Now let me ask you some questions to test your understanding.", { lipsyncLang: P.lipsyncLang });
|
|
7928
7923
|
} else {
|
|
7929
|
-
const
|
|
7930
|
-
u.current && u.current.isReady && (clearInterval(
|
|
7924
|
+
const P = setInterval(() => {
|
|
7925
|
+
u.current && u.current.isReady && (clearInterval(P), v && F());
|
|
7931
7926
|
}, 100);
|
|
7932
7927
|
setTimeout(() => {
|
|
7933
|
-
clearInterval(
|
|
7928
|
+
clearInterval(P);
|
|
7934
7929
|
}, 5e3);
|
|
7935
7930
|
}
|
|
7936
|
-
}, [e.questionStart,
|
|
7937
|
-
const
|
|
7938
|
-
if (a.current.currentQuestionIndex < (
|
|
7931
|
+
}, [e.questionStart, R, L]), E = O(() => {
|
|
7932
|
+
const b = R();
|
|
7933
|
+
if (a.current.currentQuestionIndex < (b?.questions?.length || 0) - 1) {
|
|
7939
7934
|
u.current && u.current.stopSpeaking && u.current.stopSpeaking(), a.current.currentQuestionIndex += 1;
|
|
7940
|
-
const
|
|
7941
|
-
|
|
7935
|
+
const v = L();
|
|
7936
|
+
v && d.current.onCustomAction({
|
|
7942
7937
|
type: "nextQuestion",
|
|
7943
7938
|
moduleIndex: a.current.currentModuleIndex,
|
|
7944
7939
|
lessonIndex: a.current.currentLessonIndex,
|
|
7945
7940
|
questionIndex: a.current.currentQuestionIndex,
|
|
7946
7941
|
totalQuestions: a.current.totalQuestions,
|
|
7947
|
-
question:
|
|
7942
|
+
question: v,
|
|
7948
7943
|
score: a.current.score
|
|
7949
7944
|
});
|
|
7950
|
-
const
|
|
7951
|
-
if (!u.current || !
|
|
7945
|
+
const F = () => {
|
|
7946
|
+
if (!u.current || !v) return;
|
|
7952
7947
|
if (u.current.setMood("happy"), u.current.setBodyMovement("idle"), e.nextQuestion)
|
|
7953
7948
|
try {
|
|
7954
7949
|
u.current.playAnimation(e.nextQuestion, !0);
|
|
7955
7950
|
} catch (_) {
|
|
7956
7951
|
console.warn("Failed to play nextQuestion animation:", _);
|
|
7957
7952
|
}
|
|
7958
|
-
const
|
|
7959
|
-
if (
|
|
7960
|
-
const _ = q ? `Great! Here's your final coding challenge: ${
|
|
7953
|
+
const P = T.current || { lipsyncLang: "en" }, te = R()?.questions?.length || 0, q = a.current.currentQuestionIndex >= te - 1;
|
|
7954
|
+
if (v.type === "code_test") {
|
|
7955
|
+
const _ = q ? `Great! Here's your final coding challenge: ${v.question}` : `Great! Now let's move on to your next coding challenge: ${v.question}`;
|
|
7961
7956
|
u.current.speakText(_, {
|
|
7962
|
-
lipsyncLang:
|
|
7957
|
+
lipsyncLang: P.lipsyncLang
|
|
7963
7958
|
});
|
|
7964
|
-
} else if (
|
|
7965
|
-
const _ = q ? `Alright! Here's your final question: ${
|
|
7959
|
+
} else if (v.type === "multiple_choice") {
|
|
7960
|
+
const _ = q ? `Alright! Here's your final question: ${v.question}` : `Alright! Here's your next question: ${v.question}`;
|
|
7966
7961
|
u.current.speakText(_, {
|
|
7967
|
-
lipsyncLang:
|
|
7962
|
+
lipsyncLang: P.lipsyncLang
|
|
7968
7963
|
});
|
|
7969
|
-
} else if (
|
|
7970
|
-
const _ = q ? `Now let's try this final one: ${
|
|
7964
|
+
} else if (v.type === "true_false") {
|
|
7965
|
+
const _ = q ? `Now let's try this final one: ${v.question}` : `Now let's try this one: ${v.question}`;
|
|
7971
7966
|
u.current.speakText(_, {
|
|
7972
|
-
lipsyncLang:
|
|
7967
|
+
lipsyncLang: P.lipsyncLang
|
|
7973
7968
|
});
|
|
7974
7969
|
} else {
|
|
7975
|
-
const _ = q ? `Here's your final question: ${
|
|
7970
|
+
const _ = q ? `Here's your final question: ${v.question}` : `Here's the next question: ${v.question}`;
|
|
7976
7971
|
u.current.speakText(_, {
|
|
7977
|
-
lipsyncLang:
|
|
7972
|
+
lipsyncLang: P.lipsyncLang
|
|
7978
7973
|
});
|
|
7979
7974
|
}
|
|
7980
7975
|
};
|
|
7981
|
-
if (u.current && u.current.isReady &&
|
|
7982
|
-
|
|
7983
|
-
else if (
|
|
7984
|
-
const
|
|
7985
|
-
u.current && u.current.isReady && (clearInterval(
|
|
7976
|
+
if (u.current && u.current.isReady && v)
|
|
7977
|
+
F();
|
|
7978
|
+
else if (v) {
|
|
7979
|
+
const P = setInterval(() => {
|
|
7980
|
+
u.current && u.current.isReady && (clearInterval(P), F());
|
|
7986
7981
|
}, 100);
|
|
7987
7982
|
setTimeout(() => {
|
|
7988
|
-
clearInterval(
|
|
7983
|
+
clearInterval(P);
|
|
7989
7984
|
}, 5e3);
|
|
7990
7985
|
}
|
|
7991
7986
|
} else
|
|
@@ -7996,11 +7991,11 @@ const ft = Me(({
|
|
|
7996
7991
|
totalQuestions: a.current.totalQuestions,
|
|
7997
7992
|
score: a.current.score
|
|
7998
7993
|
});
|
|
7999
|
-
}, [e.nextQuestion,
|
|
8000
|
-
const
|
|
8001
|
-
if (a.current.currentLessonIndex < (
|
|
7994
|
+
}, [e.nextQuestion, R, L]), j = O(() => {
|
|
7995
|
+
const b = B.current || { modules: [] }, v = b.modules[a.current.currentModuleIndex];
|
|
7996
|
+
if (a.current.currentLessonIndex < (v?.lessons?.length || 0) - 1) {
|
|
8002
7997
|
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;
|
|
8003
|
-
const
|
|
7998
|
+
const P = b.modules[a.current.currentModuleIndex], N = a.current.currentLessonIndex < (P?.lessons?.length || 0) - 1, te = a.current.currentModuleIndex < (b.modules?.length || 0) - 1, q = N || te;
|
|
8004
7999
|
d.current.onCustomAction({
|
|
8005
8000
|
type: "lessonStart",
|
|
8006
8001
|
moduleIndex: a.current.currentModuleIndex,
|
|
@@ -8009,11 +8004,11 @@ const ft = Me(({
|
|
|
8009
8004
|
}), d.current.onLessonStart({
|
|
8010
8005
|
moduleIndex: a.current.currentModuleIndex,
|
|
8011
8006
|
lessonIndex: a.current.currentLessonIndex,
|
|
8012
|
-
lesson:
|
|
8007
|
+
lesson: R()
|
|
8013
8008
|
}), u.current && (u.current.setMood("happy"), u.current.setBodyMovement("idle"));
|
|
8014
|
-
} else if (a.current.currentModuleIndex < (
|
|
8009
|
+
} else if (a.current.currentModuleIndex < (b.modules?.length || 0) - 1) {
|
|
8015
8010
|
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;
|
|
8016
|
-
const
|
|
8011
|
+
const N = b.modules[a.current.currentModuleIndex], te = a.current.currentLessonIndex < (N?.lessons?.length || 0) - 1, q = a.current.currentModuleIndex < (b.modules?.length || 0) - 1, _ = te || q;
|
|
8017
8012
|
d.current.onCustomAction({
|
|
8018
8013
|
type: "lessonStart",
|
|
8019
8014
|
moduleIndex: a.current.currentModuleIndex,
|
|
@@ -8022,68 +8017,68 @@ const ft = Me(({
|
|
|
8022
8017
|
}), d.current.onLessonStart({
|
|
8023
8018
|
moduleIndex: a.current.currentModuleIndex,
|
|
8024
8019
|
lessonIndex: a.current.currentLessonIndex,
|
|
8025
|
-
lesson:
|
|
8020
|
+
lesson: R()
|
|
8026
8021
|
}), u.current && (u.current.setMood("happy"), u.current.setBodyMovement("idle"));
|
|
8027
8022
|
} else
|
|
8028
|
-
|
|
8029
|
-
}, []),
|
|
8030
|
-
const
|
|
8031
|
-
let
|
|
8032
|
-
if (
|
|
8033
|
-
const
|
|
8034
|
-
|
|
8023
|
+
k.current && k.current();
|
|
8024
|
+
}, []), X = O(() => {
|
|
8025
|
+
const b = R();
|
|
8026
|
+
let v = null;
|
|
8027
|
+
if (b?.avatar_script && b?.body) {
|
|
8028
|
+
const F = b.avatar_script.trim(), P = b.body.trim(), N = F.match(/[.!?]$/) ? " " : ". ";
|
|
8029
|
+
v = `${F}${N}${P}`;
|
|
8035
8030
|
} else
|
|
8036
|
-
|
|
8037
|
-
if (u.current && u.current.isReady &&
|
|
8031
|
+
v = b?.avatar_script || b?.body || null;
|
|
8032
|
+
if (u.current && u.current.isReady && v) {
|
|
8038
8033
|
a.current.isTeaching = !0, a.current.isQuestionMode = !1, a.current.score = 0, a.current.totalQuestions = 0, u.current.setMood("happy");
|
|
8039
|
-
let
|
|
8034
|
+
let F = !1;
|
|
8040
8035
|
if (e.teaching)
|
|
8041
8036
|
try {
|
|
8042
|
-
u.current.playAnimation(e.teaching, !0),
|
|
8043
|
-
} catch (
|
|
8044
|
-
console.warn("Failed to play teaching animation:",
|
|
8037
|
+
u.current.playAnimation(e.teaching, !0), F = !0;
|
|
8038
|
+
} catch (N) {
|
|
8039
|
+
console.warn("Failed to play teaching animation:", N);
|
|
8045
8040
|
}
|
|
8046
|
-
|
|
8047
|
-
const
|
|
8041
|
+
F || u.current.setBodyMovement("gesturing");
|
|
8042
|
+
const P = T.current || { lipsyncLang: "en" };
|
|
8048
8043
|
d.current.onLessonStart({
|
|
8049
8044
|
moduleIndex: a.current.currentModuleIndex,
|
|
8050
8045
|
lessonIndex: a.current.currentLessonIndex,
|
|
8051
|
-
lesson:
|
|
8046
|
+
lesson: b
|
|
8052
8047
|
}), d.current.onCustomAction({
|
|
8053
8048
|
type: "teachingStart",
|
|
8054
8049
|
moduleIndex: a.current.currentModuleIndex,
|
|
8055
8050
|
lessonIndex: a.current.currentLessonIndex,
|
|
8056
|
-
lesson:
|
|
8057
|
-
}), u.current.speakText(
|
|
8058
|
-
lipsyncLang:
|
|
8051
|
+
lesson: b
|
|
8052
|
+
}), u.current.speakText(v, {
|
|
8053
|
+
lipsyncLang: P.lipsyncLang,
|
|
8059
8054
|
onSpeechEnd: () => {
|
|
8060
8055
|
a.current.isTeaching = !1, d.current.onCustomAction({
|
|
8061
8056
|
type: "teachingComplete",
|
|
8062
8057
|
moduleIndex: a.current.currentModuleIndex,
|
|
8063
8058
|
lessonIndex: a.current.currentLessonIndex,
|
|
8064
|
-
lesson:
|
|
8065
|
-
hasQuestions:
|
|
8066
|
-
}),
|
|
8059
|
+
lesson: b,
|
|
8060
|
+
hasQuestions: b.questions && b.questions.length > 0
|
|
8061
|
+
}), b?.code_example && d.current.onCustomAction({
|
|
8067
8062
|
type: "codeExampleReady",
|
|
8068
8063
|
moduleIndex: a.current.currentModuleIndex,
|
|
8069
8064
|
lessonIndex: a.current.currentLessonIndex,
|
|
8070
|
-
lesson:
|
|
8071
|
-
codeExample:
|
|
8065
|
+
lesson: b,
|
|
8066
|
+
codeExample: b.code_example
|
|
8072
8067
|
});
|
|
8073
8068
|
}
|
|
8074
8069
|
});
|
|
8075
8070
|
}
|
|
8076
|
-
}, [e.teaching,
|
|
8077
|
-
const
|
|
8078
|
-
if (
|
|
8071
|
+
}, [e.teaching, R]), oe = O((b) => {
|
|
8072
|
+
const v = L(), F = I(b, v);
|
|
8073
|
+
if (F && (a.current.score += 1), d.current.onQuestionAnswer({
|
|
8079
8074
|
moduleIndex: a.current.currentModuleIndex,
|
|
8080
8075
|
lessonIndex: a.current.currentLessonIndex,
|
|
8081
8076
|
questionIndex: a.current.currentQuestionIndex,
|
|
8082
|
-
answer:
|
|
8083
|
-
isCorrect:
|
|
8084
|
-
question:
|
|
8077
|
+
answer: b,
|
|
8078
|
+
isCorrect: F,
|
|
8079
|
+
question: v
|
|
8085
8080
|
}), u.current)
|
|
8086
|
-
if (
|
|
8081
|
+
if (F) {
|
|
8087
8082
|
if (u.current.setMood("happy"), e.correct)
|
|
8088
8083
|
try {
|
|
8089
8084
|
u.current.playReaction("happy");
|
|
@@ -8091,11 +8086,11 @@ const ft = Me(({
|
|
|
8091
8086
|
u.current.setBodyMovement("happy");
|
|
8092
8087
|
}
|
|
8093
8088
|
u.current.setBodyMovement("gesturing");
|
|
8094
|
-
const
|
|
8095
|
-
a.current.currentQuestionIndex >=
|
|
8096
|
-
const
|
|
8097
|
-
console.log("[CurriculumLearning] Answer feedback - questionIndex:", a.current.currentQuestionIndex, "totalQuestions:",
|
|
8098
|
-
const q =
|
|
8089
|
+
const N = R()?.questions?.length || 0;
|
|
8090
|
+
a.current.currentQuestionIndex >= N - 1;
|
|
8091
|
+
const te = a.current.currentQuestionIndex < N - 1;
|
|
8092
|
+
console.log("[CurriculumLearning] Answer feedback - questionIndex:", a.current.currentQuestionIndex, "totalQuestions:", N, "hasNextQuestion:", te);
|
|
8093
|
+
const q = v.type === "code_test" ? `Great job! Your code passed all the tests! ${v.explanation || ""}` : `Excellent! That's correct! ${v.explanation || ""}`, _ = T.current || { lipsyncLang: "en" };
|
|
8099
8094
|
u.current.speakText(q, {
|
|
8100
8095
|
lipsyncLang: _.lipsyncLang,
|
|
8101
8096
|
onSpeechEnd: () => {
|
|
@@ -8105,7 +8100,7 @@ const ft = Me(({
|
|
|
8105
8100
|
lessonIndex: a.current.currentLessonIndex,
|
|
8106
8101
|
questionIndex: a.current.currentQuestionIndex,
|
|
8107
8102
|
isCorrect: !0,
|
|
8108
|
-
hasNextQuestion:
|
|
8103
|
+
hasNextQuestion: te,
|
|
8109
8104
|
score: a.current.score,
|
|
8110
8105
|
totalQuestions: a.current.totalQuestions
|
|
8111
8106
|
});
|
|
@@ -8119,9 +8114,9 @@ const ft = Me(({
|
|
|
8119
8114
|
u.current.setBodyMovement("idle");
|
|
8120
8115
|
}
|
|
8121
8116
|
u.current.setBodyMovement("gesturing");
|
|
8122
|
-
const
|
|
8123
|
-
console.log("[CurriculumLearning] Answer feedback (incorrect) - questionIndex:", a.current.currentQuestionIndex, "totalQuestions:",
|
|
8124
|
-
const _ =
|
|
8117
|
+
const N = R()?.questions?.length || 0, te = a.current.currentQuestionIndex >= N - 1, q = a.current.currentQuestionIndex < N - 1;
|
|
8118
|
+
console.log("[CurriculumLearning] Answer feedback (incorrect) - questionIndex:", a.current.currentQuestionIndex, "totalQuestions:", N, "hasNextQuestion:", q);
|
|
8119
|
+
const _ = v.type === "code_test" ? `Your code didn't pass all the tests. ${v.explanation || "Try again!"}` : `Not quite right, but don't worry! ${v.explanation || ""}${te ? "" : " Let's move on to the next question."}`, Ae = T.current || { lipsyncLang: "en" };
|
|
8125
8120
|
u.current.speakText(_, {
|
|
8126
8121
|
lipsyncLang: Ae.lipsyncLang,
|
|
8127
8122
|
onSpeechEnd: () => {
|
|
@@ -8139,84 +8134,84 @@ const ft = Me(({
|
|
|
8139
8134
|
});
|
|
8140
8135
|
}
|
|
8141
8136
|
else {
|
|
8142
|
-
const
|
|
8137
|
+
const N = R()?.questions?.length || 0;
|
|
8143
8138
|
d.current.onCustomAction({
|
|
8144
8139
|
type: "answerFeedbackComplete",
|
|
8145
8140
|
moduleIndex: a.current.currentModuleIndex,
|
|
8146
8141
|
lessonIndex: a.current.currentLessonIndex,
|
|
8147
8142
|
questionIndex: a.current.currentQuestionIndex,
|
|
8148
|
-
isCorrect:
|
|
8149
|
-
hasNextQuestion: a.current.currentQuestionIndex <
|
|
8143
|
+
isCorrect: F,
|
|
8144
|
+
hasNextQuestion: a.current.currentQuestionIndex < N - 1,
|
|
8150
8145
|
score: a.current.score,
|
|
8151
8146
|
totalQuestions: a.current.totalQuestions,
|
|
8152
8147
|
avatarNotReady: !0
|
|
8153
8148
|
});
|
|
8154
8149
|
}
|
|
8155
|
-
}, [e.correct, e.incorrect,
|
|
8156
|
-
const
|
|
8157
|
-
if (!
|
|
8150
|
+
}, [e.correct, e.incorrect, L, R, I]), le = O((b) => {
|
|
8151
|
+
const v = L();
|
|
8152
|
+
if (!b || typeof b != "object") {
|
|
8158
8153
|
console.error("Invalid code test result format. Expected object with {passed: boolean, ...}");
|
|
8159
8154
|
return;
|
|
8160
8155
|
}
|
|
8161
|
-
if (
|
|
8156
|
+
if (v?.type !== "code_test") {
|
|
8162
8157
|
console.warn("Current question is not a code test. Use handleAnswerSelect for other question types.");
|
|
8163
8158
|
return;
|
|
8164
8159
|
}
|
|
8165
|
-
const
|
|
8166
|
-
passed:
|
|
8167
|
-
results:
|
|
8168
|
-
output:
|
|
8169
|
-
error:
|
|
8170
|
-
executionTime:
|
|
8171
|
-
testCount:
|
|
8172
|
-
passedCount:
|
|
8173
|
-
failedCount:
|
|
8160
|
+
const F = {
|
|
8161
|
+
passed: b.passed === !0,
|
|
8162
|
+
results: b.results || [],
|
|
8163
|
+
output: b.output || "",
|
|
8164
|
+
error: b.error || null,
|
|
8165
|
+
executionTime: b.executionTime || null,
|
|
8166
|
+
testCount: b.testCount || 0,
|
|
8167
|
+
passedCount: b.passedCount || 0,
|
|
8168
|
+
failedCount: b.failedCount || 0
|
|
8174
8169
|
};
|
|
8175
8170
|
d.current.onCustomAction({
|
|
8176
8171
|
type: "codeTestSubmitted",
|
|
8177
8172
|
moduleIndex: a.current.currentModuleIndex,
|
|
8178
8173
|
lessonIndex: a.current.currentLessonIndex,
|
|
8179
8174
|
questionIndex: a.current.currentQuestionIndex,
|
|
8180
|
-
testResult:
|
|
8181
|
-
question:
|
|
8182
|
-
}), p.current && p.current(
|
|
8183
|
-
}, [
|
|
8175
|
+
testResult: F,
|
|
8176
|
+
question: v
|
|
8177
|
+
}), p.current && p.current(F);
|
|
8178
|
+
}, [L, I]), ge = O(() => {
|
|
8184
8179
|
if (a.current.currentQuestionIndex > 0) {
|
|
8185
8180
|
a.current.currentQuestionIndex -= 1;
|
|
8186
|
-
const
|
|
8187
|
-
|
|
8181
|
+
const b = L();
|
|
8182
|
+
b && d.current.onCustomAction({
|
|
8188
8183
|
type: "questionStart",
|
|
8189
8184
|
moduleIndex: a.current.currentModuleIndex,
|
|
8190
8185
|
lessonIndex: a.current.currentLessonIndex,
|
|
8191
8186
|
questionIndex: a.current.currentQuestionIndex,
|
|
8192
8187
|
totalQuestions: a.current.totalQuestions,
|
|
8193
|
-
question:
|
|
8188
|
+
question: b,
|
|
8194
8189
|
score: a.current.score
|
|
8195
8190
|
});
|
|
8196
|
-
const
|
|
8197
|
-
if (!u.current || !
|
|
8191
|
+
const v = () => {
|
|
8192
|
+
if (!u.current || !b) return;
|
|
8198
8193
|
u.current.setMood("happy"), u.current.setBodyMovement("idle");
|
|
8199
|
-
const
|
|
8200
|
-
|
|
8201
|
-
lipsyncLang:
|
|
8202
|
-
}) : u.current.speakText(`Going back to: ${
|
|
8203
|
-
lipsyncLang:
|
|
8194
|
+
const F = T.current || { lipsyncLang: "en" };
|
|
8195
|
+
b.type === "code_test" ? u.current.speakText(`Let's go back to this coding challenge: ${b.question}`, {
|
|
8196
|
+
lipsyncLang: F.lipsyncLang
|
|
8197
|
+
}) : u.current.speakText(`Going back to: ${b.question}`, {
|
|
8198
|
+
lipsyncLang: F.lipsyncLang
|
|
8204
8199
|
});
|
|
8205
8200
|
};
|
|
8206
|
-
if (u.current && u.current.isReady &&
|
|
8207
|
-
|
|
8208
|
-
else if (
|
|
8209
|
-
const
|
|
8210
|
-
u.current && u.current.isReady && (clearInterval(
|
|
8201
|
+
if (u.current && u.current.isReady && b)
|
|
8202
|
+
v();
|
|
8203
|
+
else if (b) {
|
|
8204
|
+
const F = setInterval(() => {
|
|
8205
|
+
u.current && u.current.isReady && (clearInterval(F), v());
|
|
8211
8206
|
}, 100);
|
|
8212
8207
|
setTimeout(() => {
|
|
8213
|
-
clearInterval(
|
|
8208
|
+
clearInterval(F);
|
|
8214
8209
|
}, 5e3);
|
|
8215
8210
|
}
|
|
8216
8211
|
}
|
|
8217
|
-
}, [
|
|
8218
|
-
const
|
|
8219
|
-
if (
|
|
8212
|
+
}, [L]), de = O(() => {
|
|
8213
|
+
const b = B.current || { modules: [] };
|
|
8214
|
+
if (b.modules[a.current.currentModuleIndex], a.current.currentLessonIndex > 0)
|
|
8220
8215
|
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({
|
|
8221
8216
|
type: "lessonStart",
|
|
8222
8217
|
moduleIndex: a.current.currentModuleIndex,
|
|
@@ -8224,66 +8219,66 @@ const ft = Me(({
|
|
|
8224
8219
|
}), d.current.onLessonStart({
|
|
8225
8220
|
moduleIndex: a.current.currentModuleIndex,
|
|
8226
8221
|
lessonIndex: a.current.currentLessonIndex,
|
|
8227
|
-
lesson:
|
|
8222
|
+
lesson: R()
|
|
8228
8223
|
}), u.current && (u.current.setMood("happy"), u.current.setBodyMovement("idle"));
|
|
8229
8224
|
else if (a.current.currentModuleIndex > 0) {
|
|
8230
|
-
const
|
|
8231
|
-
a.current.currentModuleIndex -= 1, a.current.currentLessonIndex = (
|
|
8225
|
+
const P = b.modules[a.current.currentModuleIndex - 1];
|
|
8226
|
+
a.current.currentModuleIndex -= 1, a.current.currentLessonIndex = (P?.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({
|
|
8232
8227
|
type: "lessonStart",
|
|
8233
8228
|
moduleIndex: a.current.currentModuleIndex,
|
|
8234
8229
|
lessonIndex: a.current.currentLessonIndex
|
|
8235
8230
|
}), d.current.onLessonStart({
|
|
8236
8231
|
moduleIndex: a.current.currentModuleIndex,
|
|
8237
8232
|
lessonIndex: a.current.currentLessonIndex,
|
|
8238
|
-
lesson:
|
|
8233
|
+
lesson: R()
|
|
8239
8234
|
}), u.current && (u.current.setMood("happy"), u.current.setBodyMovement("idle"));
|
|
8240
8235
|
}
|
|
8241
|
-
}, [
|
|
8236
|
+
}, [R]), ee = O(() => {
|
|
8242
8237
|
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;
|
|
8243
|
-
}, []), be =
|
|
8244
|
-
console.log("Avatar is ready!",
|
|
8245
|
-
const
|
|
8246
|
-
h &&
|
|
8238
|
+
}, []), be = O((b) => {
|
|
8239
|
+
console.log("Avatar is ready!", b);
|
|
8240
|
+
const v = R(), F = v?.avatar_script || v?.body;
|
|
8241
|
+
h && F && setTimeout(() => {
|
|
8247
8242
|
c.current && c.current();
|
|
8248
8243
|
}, 10);
|
|
8249
|
-
}, [h,
|
|
8244
|
+
}, [h, R]);
|
|
8250
8245
|
Xe(() => {
|
|
8251
|
-
c.current =
|
|
8246
|
+
c.current = X, g.current = j, x.current = z, f.current = E, k.current = Y, D.current = S, p.current = oe;
|
|
8252
8247
|
}), Fe(r, () => ({
|
|
8253
8248
|
// Curriculum control methods
|
|
8254
|
-
startTeaching:
|
|
8255
|
-
startQuestions:
|
|
8256
|
-
handleAnswerSelect:
|
|
8249
|
+
startTeaching: X,
|
|
8250
|
+
startQuestions: S,
|
|
8251
|
+
handleAnswerSelect: oe,
|
|
8257
8252
|
handleCodeTestResult: le,
|
|
8258
8253
|
nextQuestion: E,
|
|
8259
8254
|
previousQuestion: ge,
|
|
8260
|
-
nextLesson:
|
|
8255
|
+
nextLesson: j,
|
|
8261
8256
|
previousLesson: de,
|
|
8262
|
-
completeLesson:
|
|
8263
|
-
completeCurriculum:
|
|
8264
|
-
resetCurriculum:
|
|
8257
|
+
completeLesson: z,
|
|
8258
|
+
completeCurriculum: Y,
|
|
8259
|
+
resetCurriculum: ee,
|
|
8265
8260
|
getState: () => ({ ...a.current }),
|
|
8266
|
-
getCurrentQuestion: () =>
|
|
8267
|
-
getCurrentLesson: () =>
|
|
8261
|
+
getCurrentQuestion: () => L(),
|
|
8262
|
+
getCurrentLesson: () => R(),
|
|
8268
8263
|
// Direct access to avatar ref (always returns current value)
|
|
8269
8264
|
getAvatarRef: () => u.current,
|
|
8270
8265
|
// Convenience methods that delegate to avatar (always check current ref)
|
|
8271
|
-
speakText: async (
|
|
8266
|
+
speakText: async (b, v = {}) => {
|
|
8272
8267
|
await u.current?.resumeAudioContext?.();
|
|
8273
|
-
const
|
|
8274
|
-
u.current?.speakText(
|
|
8268
|
+
const F = T.current || { lipsyncLang: "en" };
|
|
8269
|
+
u.current?.speakText(b, { ...v, lipsyncLang: v.lipsyncLang || F.lipsyncLang });
|
|
8275
8270
|
},
|
|
8276
8271
|
resumeAudioContext: async () => {
|
|
8277
8272
|
if (u.current?.resumeAudioContext)
|
|
8278
8273
|
return await u.current.resumeAudioContext();
|
|
8279
|
-
const
|
|
8280
|
-
if (
|
|
8281
|
-
const
|
|
8282
|
-
if (
|
|
8274
|
+
const b = u.current?.talkingHead;
|
|
8275
|
+
if (b?.audioCtx) {
|
|
8276
|
+
const v = b.audioCtx;
|
|
8277
|
+
if (v.state === "suspended" || v.state === "interrupted")
|
|
8283
8278
|
try {
|
|
8284
|
-
await
|
|
8285
|
-
} catch (
|
|
8286
|
-
console.warn("Failed to resume audio context:",
|
|
8279
|
+
await v.resume(), console.log("Audio context resumed via talkingHead");
|
|
8280
|
+
} catch (F) {
|
|
8281
|
+
console.warn("Failed to resume audio context:", F);
|
|
8287
8282
|
}
|
|
8288
8283
|
} else
|
|
8289
8284
|
console.warn("Audio context not available yet");
|
|
@@ -8292,22 +8287,22 @@ const ft = Me(({
|
|
|
8292
8287
|
pauseSpeaking: () => u.current?.pauseSpeaking(),
|
|
8293
8288
|
resumeSpeaking: async () => await u.current?.resumeSpeaking(),
|
|
8294
8289
|
isPaused: () => u.current && typeof u.current.isPaused < "u" ? u.current.isPaused : !1,
|
|
8295
|
-
setMood: (
|
|
8296
|
-
playAnimation: (
|
|
8297
|
-
setBodyMovement: (
|
|
8298
|
-
setMovementIntensity: (
|
|
8290
|
+
setMood: (b) => u.current?.setMood(b),
|
|
8291
|
+
playAnimation: (b, v) => u.current?.playAnimation(b, v),
|
|
8292
|
+
setBodyMovement: (b) => u.current?.setBodyMovement(b),
|
|
8293
|
+
setMovementIntensity: (b) => u.current?.setMovementIntensity(b),
|
|
8299
8294
|
playRandomDance: () => u.current?.playRandomDance(),
|
|
8300
|
-
playReaction: (
|
|
8295
|
+
playReaction: (b) => u.current?.playReaction(b),
|
|
8301
8296
|
playCelebration: () => u.current?.playCelebration(),
|
|
8302
|
-
setShowFullAvatar: (
|
|
8303
|
-
setTimingAdjustment: (
|
|
8297
|
+
setShowFullAvatar: (b) => u.current?.setShowFullAvatar(b),
|
|
8298
|
+
setTimingAdjustment: (b) => u.current?.setTimingAdjustment(b),
|
|
8304
8299
|
lockAvatarPosition: () => u.current?.lockAvatarPosition(),
|
|
8305
8300
|
unlockAvatarPosition: () => u.current?.unlockAvatarPosition(),
|
|
8306
8301
|
// Custom action trigger
|
|
8307
|
-
triggerCustomAction: (
|
|
8302
|
+
triggerCustomAction: (b, v) => {
|
|
8308
8303
|
d.current.onCustomAction({
|
|
8309
|
-
type:
|
|
8310
|
-
...
|
|
8304
|
+
type: b,
|
|
8305
|
+
...v,
|
|
8311
8306
|
state: { ...a.current }
|
|
8312
8307
|
});
|
|
8313
8308
|
},
|
|
@@ -8315,8 +8310,8 @@ const ft = Me(({
|
|
|
8315
8310
|
handleResize: () => u.current?.handleResize(),
|
|
8316
8311
|
// Avatar readiness check (always returns current value)
|
|
8317
8312
|
isAvatarReady: () => u.current?.isReady || !1
|
|
8318
|
-
}), [
|
|
8319
|
-
const Q =
|
|
8313
|
+
}), [X, S, oe, le, E, j, z, Y, ee, L, R]);
|
|
8314
|
+
const Q = T.current || {
|
|
8320
8315
|
avatarUrl: "/avatars/brunette.glb",
|
|
8321
8316
|
avatarBody: "F",
|
|
8322
8317
|
mood: "happy",
|
|
@@ -8348,8 +8343,8 @@ const ft = Me(({
|
|
|
8348
8343
|
onReady: be,
|
|
8349
8344
|
onLoading: () => {
|
|
8350
8345
|
},
|
|
8351
|
-
onError: (
|
|
8352
|
-
console.error("Avatar error:",
|
|
8346
|
+
onError: (b) => {
|
|
8347
|
+
console.error("Avatar error:", b);
|
|
8353
8348
|
}
|
|
8354
8349
|
}
|
|
8355
8350
|
) });
|
|
@@ -8458,7 +8453,7 @@ const Ge = {
|
|
|
8458
8453
|
duration: 5e3,
|
|
8459
8454
|
description: "Excited, energetic movement"
|
|
8460
8455
|
}
|
|
8461
|
-
}, zt = (
|
|
8456
|
+
}, zt = (V) => Ge[V] || null, Ct = (V) => Ge.hasOwnProperty(V);
|
|
8462
8457
|
export {
|
|
8463
8458
|
ft as CurriculumLearning,
|
|
8464
8459
|
yt as SimpleTalkingAvatar,
|