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