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