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