@sage-rsc/talking-head-react 1.3.2 → 1.3.4
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 +318 -311
- package/package.json +1 -1
- package/scripts/generate-animation-manifest.js +96 -19
- package/src/components/SimpleTalkingAvatar.jsx +27 -3
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 W, useState as pe, useEffect as ce, useCallback as
|
|
2
|
+
import { forwardRef as Me, useRef as W, useState as pe, useEffect as ce, useCallback as O, useImperativeHandle as Fe, useLayoutEffect as Xe } from "react";
|
|
3
3
|
import * as y from "three";
|
|
4
4
|
import { OrbitControls as Ye } from "three/addons/controls/OrbitControls.js";
|
|
5
5
|
import { GLTFLoader as je } from "three/addons/loaders/GLTFLoader.js";
|
|
@@ -8,11 +8,11 @@ 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 C = [0, 0, 0, 0],
|
|
11
|
+
const C = [0, 0, 0, 0], M = new y.Vector3(), ze = new y.Vector3(), ae = new y.Vector3(), Ce = new y.Vector3();
|
|
12
12
|
new y.Plane();
|
|
13
13
|
new y.Ray();
|
|
14
14
|
new y.Euler();
|
|
15
|
-
const re = new y.Quaternion(),
|
|
15
|
+
const re = new y.Quaternion(), Ne = new y.Quaternion(), fe = new y.Matrix4(), xe = new y.Matrix4();
|
|
16
16
|
new y.Vector3();
|
|
17
17
|
const He = new y.Vector3(0, 0, 1), Ke = new y.Vector3(1, 0, 0), Je = new y.Vector3(0, 1, 0), $e = new y.Vector3(0, 0, 1);
|
|
18
18
|
class et {
|
|
@@ -321,7 +321,7 @@ class et {
|
|
|
321
321
|
/// Bone's parent object
|
|
322
322
|
vBasis: r.position.clone(),
|
|
323
323
|
// Original local position
|
|
324
|
-
vWorld: r.parent.getWorldPosition(
|
|
324
|
+
vWorld: r.parent.getWorldPosition(M).clone(),
|
|
325
325
|
// World position, parent
|
|
326
326
|
qBasis: r.parent.quaternion.clone(),
|
|
327
327
|
// Original quaternion, parent
|
|
@@ -338,7 +338,7 @@ class et {
|
|
|
338
338
|
ea: [0, 0, 0, 0]
|
|
339
339
|
// External acceleration [m/s^2]
|
|
340
340
|
};
|
|
341
|
-
u.boneParent.matrixWorld.decompose(
|
|
341
|
+
u.boneParent.matrixWorld.decompose(M, re, ae), M.copy(He).applyQuaternion(re).setY(0).normalize(), re.premultiply(Ne.setFromUnitVectors(He, M).invert()).normalize(), u.qWorldInverseYaw = re.clone().normalize(), this.data.push(u), this.dict[h] = u;
|
|
342
342
|
try {
|
|
343
343
|
this.setValue(h, "type", s.type), this.setValue(h, "stiffness", s.stiffness), this.setValue(h, "damping", s.damping), this.setValue(h, "external", s.external), this.setValue(h, "limits", s.limits), this.setValue(h, "excludes", s.excludes), this.setValue(h, "deltaLocal", s.deltaLocal), this.setValue(h, "deltaWorld", s.deltaWorld), this.setValue(h, "pivot", s.pivot), this.setValue(h, "helper", s.helper);
|
|
344
344
|
} catch (a) {
|
|
@@ -356,22 +356,22 @@ class et {
|
|
|
356
356
|
for (this.timerMs += t, t > 1e3 && (this.timerMs = 0), t /= 1e3, e = 0, i = this.objectsUpdate.length; e < i; e++)
|
|
357
357
|
o = this.objectsUpdate[e], o.updateMatrix(), o.parent === null ? o.matrixWorld.copy(o.matrix) : o.matrixWorld.multiplyMatrices(o.parent.matrixWorld, o.matrix), o.matrixWorldNeedsUpdate = !1;
|
|
358
358
|
for (e = 0, i = this.data.length; e < i; e++) {
|
|
359
|
-
if (o = this.data[e],
|
|
359
|
+
if (o = this.data[e], M.copy(o.vWorld), fe.copy(o.boneParent.matrixWorld), xe.copy(fe).invert(), o.vWorld.setFromMatrixPosition(fe), M.applyMatrix4(xe), M.length() > 0.5 && (console.info("Info: Unrealistic jump of " + M.length().toFixed(2) + " meters."), M.setLength(0.5)), M.applyQuaternion(o.bone.quaternion), C[0] = M.x, C[1] = M.y, C[2] = -M.z, C[3] = M.length() / 3, o.children)
|
|
360
360
|
for (n = 0, s = o.children.length; n < s; n++)
|
|
361
361
|
m = o.children[n], C[0] -= m.v[0] * t / 3, C[1] -= m.v[1] * t / 3, C[2] += m.v[2] * t / 3, C[3] -= m.v[3] * t / 3;
|
|
362
|
-
if (m = this.opt.sensitivityFactor, C[0] *= o.ext * m, C[1] *= o.ext * m, C[2] *= o.ext * m, C[3] *= o.ext * m, o.isX && (m = C[0] / t, o.ea[0] = (m - o.ev[0]) / t, o.ev[0] = m, o.a[0] = -o.k[0] * o.p[0] - o.c[0] * o.v[0] - o.ea[0], o.p[0] += o.v[0] * t + o.a[0] * t * t / 2 + C[0], m = o.v[0] + o.a[0] * t / 2, m = -o.k[0] * o.p[0] - o.c[0] * m - o.ea[0], o.v[0] = o.v[0] + (m + o.a[0]) * t / 2), o.isY && (m = C[1] / t, o.ea[1] = (m - o.ev[1]) / t, o.ev[1] = m, o.a[1] = -o.k[1] * o.p[1] - o.c[1] * o.v[1] - o.ea[1], o.p[1] += o.v[1] * t + o.a[1] * t * t / 2 + C[1], m = o.v[1] + o.a[1] * t / 2, m = -o.k[1] * o.p[1] - o.c[1] * m - o.ea[1], o.v[1] = o.v[1] + (m + o.a[1]) * t / 2), o.isZ && (m = C[2] / t, o.ea[2] = (m - o.ev[2]) / t, o.ev[2] = m, o.a[2] = -o.k[2] * o.p[2] - o.c[2] * o.v[2] - o.ea[2], o.p[2] += o.v[2] * t + o.a[2] * t * t / 2 + C[2], m = o.v[2] + o.a[2] * t / 2, m = -o.k[2] * o.p[2] - o.c[2] * m - o.ea[2], o.v[2] = o.v[2] + (m + o.a[2]) * t / 2), o.isT && (m = C[3] / t, o.ea[3] = (m - o.ev[3]) / t, o.ev[3] = m, o.a[3] = -o.k[3] * o.p[3] - o.c[3] * o.v[3] - o.ea[3], o.p[3] += o.v[3] * t + o.a[3] * t * t / 2 + C[3], m = o.v[3] + o.a[3] * t / 2, m = -o.k[3] * o.p[3] - o.c[3] * m - o.ea[3], o.v[3] = o.v[3] + (m + o.a[3]) * t / 2), this.timerMs < this.opt.warmupMs && (o.v[0] *= 1e-4, o.p[0] *= 1e-4, o.v[1] *= 1e-4, o.p[1] *= 1e-4, o.v[2] *= 1e-4, o.p[2] *= 1e-4, o.v[3] *= 1e-4, o.p[3] *= 1e-4), C[0] = o.p[0], C[1] = o.p[1], C[2] = o.p[2], C[3] = o.p[3], m = this.opt.movementFactor, C[0] *= m, C[1] *= m, C[2] *= m, C[3] *= m, o.dl && (m = o.dl, C[0] += m[0], C[1] += m[1], C[2] += m[2]), o.dw && (m = o.dw,
|
|
362
|
+
if (m = this.opt.sensitivityFactor, C[0] *= o.ext * m, C[1] *= o.ext * m, C[2] *= o.ext * m, C[3] *= o.ext * m, o.isX && (m = C[0] / t, o.ea[0] = (m - o.ev[0]) / t, o.ev[0] = m, o.a[0] = -o.k[0] * o.p[0] - o.c[0] * o.v[0] - o.ea[0], o.p[0] += o.v[0] * t + o.a[0] * t * t / 2 + C[0], m = o.v[0] + o.a[0] * t / 2, m = -o.k[0] * o.p[0] - o.c[0] * m - o.ea[0], o.v[0] = o.v[0] + (m + o.a[0]) * t / 2), o.isY && (m = C[1] / t, o.ea[1] = (m - o.ev[1]) / t, o.ev[1] = m, o.a[1] = -o.k[1] * o.p[1] - o.c[1] * o.v[1] - o.ea[1], o.p[1] += o.v[1] * t + o.a[1] * t * t / 2 + C[1], m = o.v[1] + o.a[1] * t / 2, m = -o.k[1] * o.p[1] - o.c[1] * m - o.ea[1], o.v[1] = o.v[1] + (m + o.a[1]) * t / 2), o.isZ && (m = C[2] / t, o.ea[2] = (m - o.ev[2]) / t, o.ev[2] = m, o.a[2] = -o.k[2] * o.p[2] - o.c[2] * o.v[2] - o.ea[2], o.p[2] += o.v[2] * t + o.a[2] * t * t / 2 + C[2], m = o.v[2] + o.a[2] * t / 2, m = -o.k[2] * o.p[2] - o.c[2] * m - o.ea[2], o.v[2] = o.v[2] + (m + o.a[2]) * t / 2), o.isT && (m = C[3] / t, o.ea[3] = (m - o.ev[3]) / t, o.ev[3] = m, o.a[3] = -o.k[3] * o.p[3] - o.c[3] * o.v[3] - o.ea[3], o.p[3] += o.v[3] * t + o.a[3] * t * t / 2 + C[3], m = o.v[3] + o.a[3] * t / 2, m = -o.k[3] * o.p[3] - o.c[3] * m - o.ea[3], o.v[3] = o.v[3] + (m + o.a[3]) * t / 2), this.timerMs < this.opt.warmupMs && (o.v[0] *= 1e-4, o.p[0] *= 1e-4, o.v[1] *= 1e-4, o.p[1] *= 1e-4, o.v[2] *= 1e-4, o.p[2] *= 1e-4, o.v[3] *= 1e-4, o.p[3] *= 1e-4), C[0] = o.p[0], C[1] = o.p[1], C[2] = o.p[2], C[3] = o.p[3], m = this.opt.movementFactor, C[0] *= m, C[1] *= m, C[2] *= m, C[3] *= m, o.dl && (m = o.dl, C[0] += m[0], C[1] += m[1], C[2] += m[2]), o.dw && (m = o.dw, M.set(
|
|
363
363
|
o.vBasis.x + C[0],
|
|
364
364
|
o.vBasis.y + C[1],
|
|
365
365
|
o.vBasis.z + C[2]
|
|
366
|
-
),
|
|
366
|
+
), M.applyMatrix4(fe), M.x += m[0], M.y += m[1], M.z += m[2], M.applyMatrix4(xe), C[0] += M.x - o.vBasis.x, C[1] += M.y - o.vBasis.y, C[2] += M.z - o.vBasis.z), o.limits && this.opt.isLimits && (m = o.limits, m[0] && (m[0][0] !== null && C[0] < m[0][0] && (C[0] = m[0][0]), m[0][1] !== null && C[0] > m[0][1] && (C[0] = m[0][1])), m[1] && (m[1][0] !== null && C[1] < m[1][0] && (C[1] = m[1][0]), m[1][1] !== null && C[1] > m[1][1] && (C[1] = m[1][1])), m[2] && (m[2][0] !== null && C[2] < m[2][0] && (C[2] = m[2][0]), m[2][1] !== null && C[2] > m[2][1] && (C[2] = m[2][1])), m[3] && (m[3][0] !== null && C[3] < m[3][0] && (C[3] = m[3][0]), m[3][1] !== null && C[3] > m[3][1] && (C[3] = m[3][1]))), o.isPoint)
|
|
367
367
|
o.bone.position.set(
|
|
368
368
|
o.vBasis.x + C[0],
|
|
369
369
|
o.vBasis.y + C[1],
|
|
370
370
|
o.vBasis.z - C[2]
|
|
371
371
|
);
|
|
372
|
-
else if (o.boneParent.quaternion.copy(o.qBasis), o.pivot && this.opt.isPivots && (o.boneParent.updateWorldMatrix(!1, !1), o.boneParent.matrixWorld.decompose(
|
|
372
|
+
else if (o.boneParent.quaternion.copy(o.qBasis), o.pivot && this.opt.isPivots && (o.boneParent.updateWorldMatrix(!1, !1), o.boneParent.matrixWorld.decompose(M, re, ae), M.copy(He).applyQuaternion(re).setY(0).normalize(), re.premultiply(Ne.setFromUnitVectors(He, M).invert()).normalize(), o.boneParent.quaternion.multiply(re.invert()), o.boneParent.quaternion.multiply(o.qWorldInverseYaw)), o.isZ && (m = Math.atan(C[0] / o.l), re.setFromAxisAngle($e, -m), o.boneParent.quaternion.multiply(re)), o.isY && (m = o.l / 3, m = m * Math.tanh(C[1] / m), o.bone.position.setLength(o.l + m)), o.isX && (m = Math.atan(C[2] / o.l), re.setFromAxisAngle(Ke, -m), o.boneParent.quaternion.multiply(re)), o.isT && (m = 1.5 * Math.tanh(C[3] * 1.5), re.setFromAxisAngle(Je, -m), o.boneParent.quaternion.multiply(re)), o.boneParent.updateWorldMatrix(!1, !0), o.excludes && this.opt.isExcludes)
|
|
373
373
|
for (n = 0, s = o.excludes.length; n < s; n++)
|
|
374
|
-
m = o.excludes[n], ae.set(0, 0, 0), m.deltaLocal && (ae.x += m.deltaLocal[0], ae.y += m.deltaLocal[1], ae.z += m.deltaLocal[2]), ae.applyMatrix4(m.bone.matrixWorld), xe.copy(o.boneParent.matrixWorld).invert(), ae.applyMatrix4(xe),
|
|
374
|
+
m = o.excludes[n], ae.set(0, 0, 0), m.deltaLocal && (ae.x += m.deltaLocal[0], ae.y += m.deltaLocal[1], ae.z += m.deltaLocal[2]), ae.applyMatrix4(m.bone.matrixWorld), xe.copy(o.boneParent.matrixWorld).invert(), ae.applyMatrix4(xe), M.copy(o.bone.position), !(M.distanceToSquared(ae) >= m.radiusSq) && (he = M.length(), ue = ae.length(), !(ue > m.radius + he) && (ue < Math.abs(m.radius - he) || (ue = (ue * ue + he * he - m.radiusSq) / (2 * ue), ae.normalize(), Ce.copy(ae).multiplyScalar(ue), ue = Math.sqrt(he * he - ue * ue), M.subVectors(M, Ce).projectOnPlane(ae).normalize().multiplyScalar(ue), ze.subVectors(o.vBasis, Ce).projectOnPlane(ae).normalize(), he = ze.dot(M), he < 0 && (he = Math.sqrt(ue * ue - he * he), ze.multiplyScalar(he), M.add(ze)), M.add(Ce).normalize(), ae.copy(o.bone.position).normalize(), re.setFromUnitVectors(ae, M), o.boneParent.quaternion.premultiply(re), o.boneParent.updateWorldMatrix(!1, !0))));
|
|
375
375
|
}
|
|
376
376
|
this.helpers.isActive && this.updateHelpers();
|
|
377
377
|
}
|
|
@@ -445,14 +445,14 @@ class et {
|
|
|
445
445
|
xe.copy(this.armature.matrixWorld).invert();
|
|
446
446
|
const t = m.object.geometry.getAttribute("position");
|
|
447
447
|
for (let e = 0, n = m.bones.length; e < n; e++)
|
|
448
|
-
fe.multiplyMatrices(xe, m.bones[e].matrixWorld),
|
|
448
|
+
fe.multiplyMatrices(xe, m.bones[e].matrixWorld), M.setFromMatrixPosition(fe), t.setXYZ(e, M.x, M.y, M.z);
|
|
449
449
|
t.needsUpdate = !0, m.object.updateMatrixWorld();
|
|
450
450
|
}
|
|
451
451
|
if (m = this.helpers.lines, m.bones.length) {
|
|
452
452
|
xe.copy(this.armature.matrixWorld).invert();
|
|
453
453
|
const t = m.object.geometry.getAttribute("position");
|
|
454
454
|
for (let e = 0, n = 0, i = m.bones.length; e < i; e++, n += 2)
|
|
455
|
-
fe.multiplyMatrices(xe, m.bones[e].matrixWorld),
|
|
455
|
+
fe.multiplyMatrices(xe, m.bones[e].matrixWorld), M.setFromMatrixPosition(fe), t.setXYZ(n, M.x, M.y, M.z), fe.multiplyMatrices(xe, m.bones[e].parent.matrixWorld), M.setFromMatrixPosition(fe), t.setXYZ(n + 1, M.x, M.y, M.z);
|
|
456
456
|
t.needsUpdate = !0, m.object.updateMatrixWorld();
|
|
457
457
|
}
|
|
458
458
|
}
|
|
@@ -5264,10 +5264,10 @@ class Be {
|
|
|
5264
5264
|
let u = "", a = "", d = 0, c = [], g = [];
|
|
5265
5265
|
const x = Array.from(this.segmenter.segment(t), (f) => f.segment);
|
|
5266
5266
|
for (let f = 0; f < x.length; f++) {
|
|
5267
|
-
const k = f === x.length - 1,
|
|
5267
|
+
const k = f === x.length - 1, N = x[f].match(l);
|
|
5268
5268
|
let p = x[f].match(s);
|
|
5269
5269
|
const B = x[f].match(h), H = x[f].match(o);
|
|
5270
|
-
if (p && !k && !B && x[f + 1].match(s) && (p = !1), n && (u += x[f]),
|
|
5270
|
+
if (p && !k && !B && x[f + 1].match(s) && (p = !1), n && (u += x[f]), N && (!i || i.every((R) => f < R[0] || f > R[1])) && (a += x[f]), (H || p || k) && (a.length && (a = this.lipsyncPreProcessText(a, r), a.length && c.push({
|
|
5271
5271
|
mark: d,
|
|
5272
5272
|
word: a
|
|
5273
5273
|
})), u.length && (g.push({
|
|
@@ -5278,16 +5278,16 @@ class Be {
|
|
|
5278
5278
|
subtitles: [u]
|
|
5279
5279
|
}
|
|
5280
5280
|
}), u = ""), a.length)) {
|
|
5281
|
-
const
|
|
5282
|
-
if (
|
|
5283
|
-
const L =
|
|
5284
|
-
for (let I = 0; I <
|
|
5281
|
+
const R = this.lipsyncWordsToVisemes(a, r);
|
|
5282
|
+
if (R && R.visemes && R.visemes.length) {
|
|
5283
|
+
const L = R.times[R.visemes.length - 1] + R.durations[R.visemes.length - 1];
|
|
5284
|
+
for (let I = 0; I < R.visemes.length; I++)
|
|
5285
5285
|
g.push({
|
|
5286
5286
|
mark: d,
|
|
5287
5287
|
template: { name: "viseme" },
|
|
5288
|
-
ts: [(
|
|
5288
|
+
ts: [(R.times[I] - 0.6) / L, (R.times[I] + 0.5) / L, (R.times[I] + R.durations[I] + 0.5) / L],
|
|
5289
5289
|
vs: {
|
|
5290
|
-
["viseme_" +
|
|
5290
|
+
["viseme_" + R.visemes[I]]: [null, R.visemes[I] === "PP" || R.visemes[I] === "FF" ? 0.9 : 0.6, 0]
|
|
5291
5291
|
}
|
|
5292
5292
|
});
|
|
5293
5293
|
}
|
|
@@ -5295,14 +5295,14 @@ class Be {
|
|
|
5295
5295
|
}
|
|
5296
5296
|
if (p || k) {
|
|
5297
5297
|
if (c.length || k && g.length) {
|
|
5298
|
-
const
|
|
5298
|
+
const R = {
|
|
5299
5299
|
anim: g
|
|
5300
5300
|
};
|
|
5301
|
-
n && (
|
|
5301
|
+
n && (R.onSubtitles = n), c.length && !e.avatarMute && (R.text = c, e.avatarMood && (R.mood = e.avatarMood), e.ttsLang && (R.lang = e.ttsLang), e.ttsVoice && (R.voice = e.ttsVoice), e.ttsRate && (R.rate = e.ttsRate), e.ttsVoice && (R.pitch = e.ttsPitch), e.ttsVolume && (R.volume = e.ttsVolume)), this.speechQueue.push(R), c = [], a = "", d = 0, g = [];
|
|
5302
5302
|
}
|
|
5303
5303
|
if (B) {
|
|
5304
|
-
let
|
|
5305
|
-
|
|
5304
|
+
let R = this.animEmojis[x[f]];
|
|
5305
|
+
R && R.link && (R = this.animEmojis[R.link]), R && this.speechQueue.push({ emoji: R });
|
|
5306
5306
|
}
|
|
5307
5307
|
this.speechQueue.push({ break: 100 });
|
|
5308
5308
|
}
|
|
@@ -5398,10 +5398,10 @@ class Be {
|
|
|
5398
5398
|
let x = 0.6 + this.convertRange(g, [0, u], [0, 0.4]);
|
|
5399
5399
|
if (u = Math.min(u, d.visemes.length * 200), c > 0)
|
|
5400
5400
|
for (let f = 0; f < d.visemes.length; f++) {
|
|
5401
|
-
const k = r + d.times[f] / c * u,
|
|
5401
|
+
const k = r + d.times[f] / c * u, N = d.durations[f] / c * u;
|
|
5402
5402
|
o.push({
|
|
5403
5403
|
template: { name: "viseme" },
|
|
5404
|
-
ts: [k - Math.min(60, 2 *
|
|
5404
|
+
ts: [k - Math.min(60, 2 * N / 3), k + Math.min(25, N / 2), k + N + Math.min(60, N / 2)],
|
|
5405
5405
|
vs: {
|
|
5406
5406
|
["viseme_" + d.visemes[f]]: [null, d.visemes[f] === "PP" || d.visemes[f] === "FF" ? 0.9 : x, 0]
|
|
5407
5407
|
}
|
|
@@ -5499,7 +5499,7 @@ class Be {
|
|
|
5499
5499
|
if (f && f.visemes && f.visemes.length > 0) {
|
|
5500
5500
|
const p = f.times[f.visemes.length - 1] + f.durations[f.visemes.length - 1];
|
|
5501
5501
|
for (let B = 0; B < f.visemes.length; B++) {
|
|
5502
|
-
const H = f.visemes[B],
|
|
5502
|
+
const H = f.visemes[B], R = f.times[B] / p, L = f.durations[B] / p, I = R * d, z = L * d;
|
|
5503
5503
|
k.push({
|
|
5504
5504
|
template: { name: "viseme" },
|
|
5505
5505
|
ts: [I - Math.min(60, 2 * z / 3), I + Math.min(25, z / 2), I + z + Math.min(60, z / 2)],
|
|
@@ -5509,8 +5509,8 @@ class Be {
|
|
|
5509
5509
|
});
|
|
5510
5510
|
}
|
|
5511
5511
|
}
|
|
5512
|
-
const
|
|
5513
|
-
this.audioPlaylist.push({ anim:
|
|
5512
|
+
const N = [...t.anim, ...k];
|
|
5513
|
+
this.audioPlaylist.push({ anim: N, audio: c }), this.onSubtitles = t.onSubtitles || null, this.resetLips(), t.mood && this.setMood(t.mood), this.playAudio(), s.onend = () => {
|
|
5514
5514
|
e();
|
|
5515
5515
|
}, s.onerror = (p) => {
|
|
5516
5516
|
console.error("Speech synthesis error:", p.error), n(p.error);
|
|
@@ -6202,17 +6202,17 @@ class Be {
|
|
|
6202
6202
|
t === null && (t = h), e === null && (e = r), J.copy(this.armature.quaternion), J.multiply(this.poseTarget.props["Hips.quaternion"]), J.multiply(this.poseTarget.props["Spine.quaternion"]), J.multiply(this.poseTarget.props["Spine1.quaternion"]), J.multiply(this.poseTarget.props["Spine2.quaternion"]), J.multiply(this.poseTarget.props["Neck.quaternion"]), J.multiply(this.poseTarget.props["Head.quaternion"]), G.setFromQuaternion(J);
|
|
6203
6203
|
let u = G.x / (40 / 24), a = G.y / (9 / 4), d = Math.min(0.4, Math.max(-0.4, this.camera.rotation.x)), c = Math.min(0.4, Math.max(-0.4, this.camera.rotation.y)), g = Math.max(window.innerWidth - h, h), x = Math.max(window.innerHeight - r, r), f = this.convertRange(e, [r - x, r + x], [-0.3, 0.6]) - u + d, k = this.convertRange(t, [h - g, h + g], [-0.8, 0.8]) - a + c;
|
|
6204
6204
|
f = Math.min(0.6, Math.max(-0.3, f)), k = Math.min(0.8, Math.max(-0.8, k));
|
|
6205
|
-
let
|
|
6205
|
+
let N = (Math.random() - 0.5) / 4, p = (Math.random() - 0.5) / 4;
|
|
6206
6206
|
if (n) {
|
|
6207
|
-
let B = this.animQueue.findIndex((
|
|
6207
|
+
let B = this.animQueue.findIndex((R) => R.template.name === "lookat");
|
|
6208
6208
|
B !== -1 && this.animQueue.splice(B, 1);
|
|
6209
6209
|
const H = {
|
|
6210
6210
|
name: "lookat",
|
|
6211
6211
|
dt: [750, n],
|
|
6212
6212
|
vs: {
|
|
6213
|
-
bodyRotateX: [f +
|
|
6213
|
+
bodyRotateX: [f + N],
|
|
6214
6214
|
bodyRotateY: [k + p],
|
|
6215
|
-
eyesRotateX: [-3 *
|
|
6215
|
+
eyesRotateX: [-3 * N + 0.1],
|
|
6216
6216
|
eyesRotateY: [-5 * p],
|
|
6217
6217
|
browInnerUp: [[0, 0.7]],
|
|
6218
6218
|
mouthLeft: [[0, 0.7]],
|
|
@@ -6523,8 +6523,8 @@ class Be {
|
|
|
6523
6523
|
if (S.toLowerCase() === z)
|
|
6524
6524
|
return S;
|
|
6525
6525
|
for (const S of c) {
|
|
6526
|
-
const
|
|
6527
|
-
if ((z.includes("left") &&
|
|
6526
|
+
const E = S.toLowerCase();
|
|
6527
|
+
if ((z.includes("left") && E.includes("left") || z.includes("right") && E.includes("right")) && (z.includes("arm") && E.includes("arm") && !E.includes("fore") || z.includes("forearm") && E.includes("forearm") || z.includes("hand") && E.includes("hand") && !E.includes("index") && !E.includes("thumb") || z.includes("shoulder") && E.includes("shoulder")))
|
|
6528
6528
|
return S;
|
|
6529
6529
|
}
|
|
6530
6530
|
return null;
|
|
@@ -6535,16 +6535,16 @@ class Be {
|
|
|
6535
6535
|
}), console.log("=== Ready Player Me Animation Bone Analysis ==="), console.log("FBX bone names:", Array.from(f).sort().join(", ")), console.log("Avatar skeleton bone names:", Array.from(c).sort().join(", "));
|
|
6536
6536
|
const k = Array.from(f).filter(
|
|
6537
6537
|
(L) => L.toLowerCase().includes("arm") || L.toLowerCase().includes("hand") || L.toLowerCase().includes("shoulder")
|
|
6538
|
-
),
|
|
6538
|
+
), N = Array.from(c).filter(
|
|
6539
6539
|
(L) => L.includes("Arm") || L.includes("Hand") || L.includes("Shoulder")
|
|
6540
6540
|
);
|
|
6541
|
-
console.log("FBX arm/hand/shoulder bones:", k.sort().join(", ")), console.log("Avatar arm/hand/shoulder bones:",
|
|
6541
|
+
console.log("FBX arm/hand/shoulder bones:", k.sort().join(", ")), console.log("Avatar arm/hand/shoulder bones:", N.sort().join(", "));
|
|
6542
6542
|
const p = [], B = /* @__PURE__ */ new Set();
|
|
6543
6543
|
if (d.tracks.forEach((L) => {
|
|
6544
|
-
const z = L.name.replaceAll("mixamorig", "").split("."), Y = z[0], S = z[1],
|
|
6545
|
-
if (
|
|
6546
|
-
const X = `${
|
|
6547
|
-
Z.name = X, p.push(Z), Y !==
|
|
6544
|
+
const z = L.name.replaceAll("mixamorig", "").split("."), Y = z[0], S = z[1], E = x(Y);
|
|
6545
|
+
if (E && S) {
|
|
6546
|
+
const X = `${E}.${S}`, Z = L.clone();
|
|
6547
|
+
Z.name = X, p.push(Z), Y !== E && g.set(Y, E);
|
|
6548
6548
|
} else
|
|
6549
6549
|
B.add(Y), (Y.toLowerCase().includes("arm") || Y.toLowerCase().includes("hand") || Y.toLowerCase().includes("shoulder")) && console.warn(`⚠️ Arm bone "${Y}" could not be mapped to avatar skeleton`);
|
|
6550
6550
|
}), B.size > 0 && console.warn(`⚠️ ${B.size} bone(s) could not be mapped:`, Array.from(B).sort().join(", ")), p.length > 0) {
|
|
@@ -6568,11 +6568,11 @@ class Be {
|
|
|
6568
6568
|
H[L.name] = new y.Vector3(L.values[0], L.values[1], L.values[2]);
|
|
6569
6569
|
} else I[1] === "quaternion" ? H[L.name] = new y.Quaternion(L.values[0], L.values[1], L.values[2], L.values[3]) : I[1] === "rotation" && (H[I[0] + ".quaternion"] = new y.Quaternion().setFromEuler(new y.Euler(L.values[0], L.values[1], L.values[2], "XYZ")).normalize());
|
|
6570
6570
|
});
|
|
6571
|
-
const
|
|
6572
|
-
H["Hips.position"] && (H["Hips.position"].y < 0.5 ?
|
|
6571
|
+
const R = { props: H };
|
|
6572
|
+
H["Hips.position"] && (H["Hips.position"].y < 0.5 ? R.lying = !0 : R.standing = !0), this.animClips.push({
|
|
6573
6573
|
url: t + "-" + i,
|
|
6574
6574
|
clip: d,
|
|
6575
|
-
pose:
|
|
6575
|
+
pose: R
|
|
6576
6576
|
}), this.playAnimation(t, e, n, i, s);
|
|
6577
6577
|
} else {
|
|
6578
6578
|
const d = "Animation " + t + " (ndx=" + i + ") not found";
|
|
@@ -6707,12 +6707,12 @@ class Be {
|
|
|
6707
6707
|
const f = t.iterations || 10;
|
|
6708
6708
|
if (e)
|
|
6709
6709
|
for (let k = 0; k < f; k++) {
|
|
6710
|
-
let
|
|
6710
|
+
let N = !1;
|
|
6711
6711
|
for (let p = 0, B = x.length; p < B; p++) {
|
|
6712
6712
|
const H = x[p].bone;
|
|
6713
6713
|
H.matrixWorld.decompose(h, r, u), r.invert(), o.setFromMatrixPosition(g.matrixWorld), l.subVectors(o, h), l.applyQuaternion(r), l.normalize(), s.subVectors(e, h), s.applyQuaternion(r), s.normalize();
|
|
6714
|
-
let
|
|
6715
|
-
|
|
6714
|
+
let R = s.dot(l);
|
|
6715
|
+
R > 1 ? R = 1 : R < -1 && (R = -1), R = Math.acos(R), !(R < 1e-5) && (x[p].minAngle !== void 0 && R < x[p].minAngle && (R = x[p].minAngle), x[p].maxAngle !== void 0 && R > x[p].maxAngle && (R = x[p].maxAngle), a.crossVectors(l, s), a.normalize(), J.setFromAxisAngle(a, R), H.quaternion.multiply(J), H.rotation.setFromVector3(d.setFromEuler(H.rotation).clamp(new y.Vector3(
|
|
6716
6716
|
x[p].minx !== void 0 ? x[p].minx : -1 / 0,
|
|
6717
6717
|
x[p].miny !== void 0 ? x[p].miny : -1 / 0,
|
|
6718
6718
|
x[p].minz !== void 0 ? x[p].minz : -1 / 0
|
|
@@ -6720,9 +6720,9 @@ class Be {
|
|
|
6720
6720
|
x[p].maxx !== void 0 ? x[p].maxx : 1 / 0,
|
|
6721
6721
|
x[p].maxy !== void 0 ? x[p].maxy : 1 / 0,
|
|
6722
6722
|
x[p].maxz !== void 0 ? x[p].maxz : 1 / 0
|
|
6723
|
-
))), H.updateMatrixWorld(!0),
|
|
6723
|
+
))), H.updateMatrixWorld(!0), N = !0);
|
|
6724
6724
|
}
|
|
6725
|
-
if (!
|
|
6725
|
+
if (!N) break;
|
|
6726
6726
|
}
|
|
6727
6727
|
i && x.forEach((k) => {
|
|
6728
6728
|
this.poseTarget.props[k.link + ".quaternion"].copy(k.bone.quaternion), this.poseTarget.props[k.link + ".quaternion"].t = this.animClock, this.poseTarget.props[k.link + ".quaternion"].d = i;
|
|
@@ -6815,7 +6815,7 @@ const Ve = Me(({
|
|
|
6815
6815
|
style: x = {},
|
|
6816
6816
|
animations: f = {}
|
|
6817
6817
|
}, k) => {
|
|
6818
|
-
const
|
|
6818
|
+
const N = W(null), p = W(null), B = W(r), H = W(null), R = W(null), L = W(!1), I = W({ remainingText: null, originalText: null, options: null }), z = W([]), Y = W(0), [S, E] = pe(!0), [X, Z] = pe(null), [oe, le] = pe(!1), [ge, de] = pe(!1);
|
|
6819
6819
|
ce(() => {
|
|
6820
6820
|
L.current = ge;
|
|
6821
6821
|
}, [ge]), ce(() => {
|
|
@@ -6855,16 +6855,16 @@ const Ve = Me(({
|
|
|
6855
6855
|
showFullAvatar: r,
|
|
6856
6856
|
bodyMovement: l,
|
|
6857
6857
|
movementIntensity: h
|
|
6858
|
-
},
|
|
6858
|
+
}, v = {
|
|
6859
6859
|
ttsEndpoint: j.endpoint,
|
|
6860
6860
|
ttsApikey: j.apiKey,
|
|
6861
6861
|
ttsService: be,
|
|
6862
6862
|
lipsyncModules: ["en"],
|
|
6863
6863
|
cameraView: u
|
|
6864
|
-
},
|
|
6865
|
-
if (!(!
|
|
6864
|
+
}, F = O(async () => {
|
|
6865
|
+
if (!(!N.current || p.current))
|
|
6866
6866
|
try {
|
|
6867
|
-
if (
|
|
6867
|
+
if (E(!0), Z(null), p.current = new Be(N.current, v), p.current.controls && (p.current.controls.enableRotate = !1, p.current.controls.enableZoom = !1, p.current.controls.enablePan = !1, p.current.controls.enableDamping = !1), f && Object.keys(f).length > 0 && (p.current.customAnimations = f), await p.current.showAvatar(b, (_) => {
|
|
6868
6868
|
if (_.lengthComputable) {
|
|
6869
6869
|
const te = Math.min(100, Math.round(_.loaded / _.total * 100));
|
|
6870
6870
|
d(te);
|
|
@@ -6880,7 +6880,7 @@ const Ve = Me(({
|
|
|
6880
6880
|
} catch (_) {
|
|
6881
6881
|
console.warn("Error setting full body mode on initialization:", _);
|
|
6882
6882
|
}
|
|
6883
|
-
p.current && p.current.controls && (p.current.controls.enableRotate = !1, p.current.controls.enableZoom = !1, p.current.controls.enablePan = !1, p.current.controls.enableDamping = !1, p.current.controls.update()),
|
|
6883
|
+
p.current && p.current.controls && (p.current.controls.enableRotate = !1, p.current.controls.enableZoom = !1, p.current.controls.enablePan = !1, p.current.controls.enableDamping = !1, p.current.controls.update()), E(!1), le(!0), a(p.current);
|
|
6884
6884
|
const U = () => {
|
|
6885
6885
|
document.visibilityState === "visible" ? p.current?.start() : p.current?.stop();
|
|
6886
6886
|
};
|
|
@@ -6888,65 +6888,65 @@ const Ve = Me(({
|
|
|
6888
6888
|
document.removeEventListener("visibilitychange", U);
|
|
6889
6889
|
};
|
|
6890
6890
|
} catch (w) {
|
|
6891
|
-
console.error("Error initializing TalkingHead:", w), Z(w.message || "Failed to initialize avatar"),
|
|
6891
|
+
console.error("Error initializing TalkingHead:", w), Z(w.message || "Failed to initialize avatar"), E(!1), c(w);
|
|
6892
6892
|
}
|
|
6893
6893
|
}, [V, t, e, n, i, s, o, r, l, h, u]);
|
|
6894
|
-
ce(() => (
|
|
6894
|
+
ce(() => (F(), () => {
|
|
6895
6895
|
p.current && (p.current.stop(), p.current.dispose(), p.current = null);
|
|
6896
|
-
}), [
|
|
6897
|
-
if (!
|
|
6896
|
+
}), [F]), ce(() => {
|
|
6897
|
+
if (!N.current || !p.current) return;
|
|
6898
6898
|
const w = new ResizeObserver((_) => {
|
|
6899
6899
|
for (const te of _)
|
|
6900
6900
|
p.current && p.current.onResize && p.current.onResize();
|
|
6901
6901
|
});
|
|
6902
|
-
w.observe(
|
|
6902
|
+
w.observe(N.current);
|
|
6903
6903
|
const U = () => {
|
|
6904
6904
|
p.current && p.current.onResize && p.current.onResize();
|
|
6905
6905
|
};
|
|
6906
6906
|
return window.addEventListener("resize", U), () => {
|
|
6907
6907
|
w.disconnect(), window.removeEventListener("resize", U);
|
|
6908
6908
|
};
|
|
6909
|
-
}, [
|
|
6910
|
-
const
|
|
6909
|
+
}, [oe]);
|
|
6910
|
+
const P = O(async () => {
|
|
6911
6911
|
if (p.current && p.current.audioCtx)
|
|
6912
6912
|
try {
|
|
6913
6913
|
(p.current.audioCtx.state === "suspended" || p.current.audioCtx.state === "interrupted") && (await p.current.audioCtx.resume(), console.log("Audio context resumed"));
|
|
6914
6914
|
} catch (w) {
|
|
6915
6915
|
console.warn("Failed to resume audio context:", w);
|
|
6916
6916
|
}
|
|
6917
|
-
}, []), D =
|
|
6918
|
-
if (p.current &&
|
|
6917
|
+
}, []), D = O(async (w, U = {}) => {
|
|
6918
|
+
if (p.current && oe)
|
|
6919
6919
|
try {
|
|
6920
|
-
|
|
6920
|
+
R.current && (clearInterval(R.current), R.current = null), H.current = { text: w, options: U }, I.current = { remainingText: null, originalText: null, options: null };
|
|
6921
6921
|
const _ = /[!\.\?\n\p{Extended_Pictographic}]/ug, te = w.split(_).map((A) => A.trim()).filter((A) => A.length > 0);
|
|
6922
|
-
z.current = te, Y.current = 0, de(!1), L.current = !1, await
|
|
6922
|
+
z.current = te, Y.current = 0, de(!1), L.current = !1, await P();
|
|
6923
6923
|
const me = {
|
|
6924
6924
|
...U,
|
|
6925
6925
|
lipsyncLang: U.lipsyncLang || b.lipsyncLang || "en"
|
|
6926
6926
|
};
|
|
6927
6927
|
if (U.onSpeechEnd && p.current) {
|
|
6928
6928
|
const A = p.current;
|
|
6929
|
-
let
|
|
6930
|
-
const
|
|
6931
|
-
let
|
|
6932
|
-
|
|
6929
|
+
let T = null, K = 0;
|
|
6930
|
+
const ne = 1200;
|
|
6931
|
+
let ie = !1;
|
|
6932
|
+
T = setInterval(() => {
|
|
6933
6933
|
if (K++, L.current)
|
|
6934
6934
|
return;
|
|
6935
|
-
if (K >
|
|
6936
|
-
if (
|
|
6937
|
-
|
|
6935
|
+
if (K > ne) {
|
|
6936
|
+
if (T && (clearInterval(T), T = null, R.current = null), !ie && !L.current) {
|
|
6937
|
+
ie = !0;
|
|
6938
6938
|
try {
|
|
6939
6939
|
U.onSpeechEnd();
|
|
6940
|
-
} catch (
|
|
6941
|
-
console.error("Error in onSpeechEnd callback (timeout):",
|
|
6940
|
+
} catch (Oe) {
|
|
6941
|
+
console.error("Error in onSpeechEnd callback (timeout):", Oe);
|
|
6942
6942
|
}
|
|
6943
6943
|
}
|
|
6944
6944
|
return;
|
|
6945
6945
|
}
|
|
6946
|
-
const
|
|
6947
|
-
A && A.isSpeaking === !1 &&
|
|
6948
|
-
if (A && !L.current && A.isSpeaking === !1 && (!A.speechQueue || A.speechQueue.length === 0) && (!A.audioPlaylist || A.audioPlaylist.length === 0) && A.isAudioPlaying === !1 && !
|
|
6949
|
-
|
|
6946
|
+
const se = !A.speechQueue || A.speechQueue.length === 0, we = !A.audioPlaylist || A.audioPlaylist.length === 0;
|
|
6947
|
+
A && A.isSpeaking === !1 && se && we && A.isAudioPlaying === !1 && !ie && !L.current && setTimeout(() => {
|
|
6948
|
+
if (A && !L.current && A.isSpeaking === !1 && (!A.speechQueue || A.speechQueue.length === 0) && (!A.audioPlaylist || A.audioPlaylist.length === 0) && A.isAudioPlaying === !1 && !ie && !L.current) {
|
|
6949
|
+
ie = !0, T && (clearInterval(T), T = null, R.current = null);
|
|
6950
6950
|
try {
|
|
6951
6951
|
U.onSpeechEnd();
|
|
6952
6952
|
} catch (Ze) {
|
|
@@ -6954,27 +6954,27 @@ const Ve = Me(({
|
|
|
6954
6954
|
}
|
|
6955
6955
|
}
|
|
6956
6956
|
}, 100);
|
|
6957
|
-
}, 100),
|
|
6957
|
+
}, 100), R.current = T;
|
|
6958
6958
|
}
|
|
6959
6959
|
p.current.lipsync && Object.keys(p.current.lipsync).length > 0 ? (p.current.setSlowdownRate && p.current.setSlowdownRate(1.05), p.current.speakText(w, me)) : setTimeout(async () => {
|
|
6960
|
-
await
|
|
6960
|
+
await P(), p.current && p.current.lipsync && (p.current.setSlowdownRate && p.current.setSlowdownRate(1.05), p.current.speakText(w, me));
|
|
6961
6961
|
}, 100);
|
|
6962
6962
|
} catch (_) {
|
|
6963
6963
|
console.error("Error speaking text:", _), Z(_.message || "Failed to speak text");
|
|
6964
6964
|
}
|
|
6965
|
-
}, [
|
|
6965
|
+
}, [oe, P, b.lipsyncLang]), ee = O(() => {
|
|
6966
6966
|
p.current && (p.current.stopSpeaking(), p.current.setSlowdownRate && p.current.setSlowdownRate(1), H.current = null, de(!1));
|
|
6967
|
-
}, []), Q =
|
|
6967
|
+
}, []), Q = O(() => {
|
|
6968
6968
|
if (p.current && p.current.pauseSpeaking) {
|
|
6969
6969
|
const w = p.current;
|
|
6970
6970
|
if (w.isSpeaking || w.audioPlaylist && w.audioPlaylist.length > 0 || w.speechQueue && w.speechQueue.length > 0) {
|
|
6971
|
-
|
|
6971
|
+
R.current && (clearInterval(R.current), R.current = null);
|
|
6972
6972
|
let _ = "";
|
|
6973
6973
|
if (H.current && z.current.length > 0) {
|
|
6974
|
-
const te = z.current.length, me = w.speechQueue ? w.speechQueue.filter((
|
|
6975
|
-
if (
|
|
6976
|
-
const
|
|
6977
|
-
|
|
6974
|
+
const te = z.current.length, me = w.speechQueue ? w.speechQueue.filter((ne) => ne && ne.text && Array.isArray(ne.text) && ne.text.length > 0).length : 0, A = w.audioPlaylist && w.audioPlaylist.length > 0, T = me + (A ? 1 : 0), K = te - T;
|
|
6975
|
+
if (T > 0 && K < te && (_ = z.current.slice(K).join(". ").trim(), !_ && me > 0 && w.speechQueue)) {
|
|
6976
|
+
const ie = w.speechQueue.filter((se) => se && se.text && Array.isArray(se.text) && se.text.length > 0).map((se) => se.text.map((we) => we.word || "").filter((we) => we.length > 0).join(" ")).filter((se) => se.length > 0).join(" ");
|
|
6977
|
+
ie && ie.trim() && (_ = ie.trim());
|
|
6978
6978
|
}
|
|
6979
6979
|
}
|
|
6980
6980
|
H.current && (I.current = {
|
|
@@ -6984,7 +6984,7 @@ const Ve = Me(({
|
|
|
6984
6984
|
}), w.speechQueue && (w.speechQueue.length = 0), p.current.pauseSpeaking(), L.current = !0, de(!0);
|
|
6985
6985
|
}
|
|
6986
6986
|
}
|
|
6987
|
-
}, []), q =
|
|
6987
|
+
}, []), q = O(async () => {
|
|
6988
6988
|
if (!p.current || !ge)
|
|
6989
6989
|
return;
|
|
6990
6990
|
let w = "", U = {};
|
|
@@ -6996,7 +6996,7 @@ const Ve = Me(({
|
|
|
6996
6996
|
console.warn("Resume called but no paused speech found"), de(!1), L.current = !1;
|
|
6997
6997
|
return;
|
|
6998
6998
|
}
|
|
6999
|
-
de(!1), L.current = !1, await
|
|
6999
|
+
de(!1), L.current = !1, await P();
|
|
7000
7000
|
const _ = {
|
|
7001
7001
|
...U,
|
|
7002
7002
|
lipsyncLang: U.lipsyncLang || b.lipsyncLang || "en"
|
|
@@ -7006,11 +7006,11 @@ const Ve = Me(({
|
|
|
7006
7006
|
} catch (te) {
|
|
7007
7007
|
console.error("Error resuming speech:", te), de(!1), L.current = !1;
|
|
7008
7008
|
}
|
|
7009
|
-
}, [
|
|
7009
|
+
}, [P, ge, D, b]), Ae = O((w) => {
|
|
7010
7010
|
p.current && p.current.setMood(w);
|
|
7011
|
-
}, []), Se =
|
|
7011
|
+
}, []), Se = O((w) => {
|
|
7012
7012
|
p.current && p.current.setSlowdownRate && p.current.setSlowdownRate(w);
|
|
7013
|
-
}, []), Le =
|
|
7013
|
+
}, []), Le = O((w, U = !1) => {
|
|
7014
7014
|
if (p.current && p.current.playAnimation) {
|
|
7015
7015
|
if (f && f[w] && (w = f[w]), p.current.setShowFullAvatar)
|
|
7016
7016
|
try {
|
|
@@ -7048,7 +7048,7 @@ const Ve = Me(({
|
|
|
7048
7048
|
}
|
|
7049
7049
|
}
|
|
7050
7050
|
}
|
|
7051
|
-
}, [f]), ke =
|
|
7051
|
+
}, [f]), ke = O(() => {
|
|
7052
7052
|
p.current && p.current.onResize && p.current.onResize();
|
|
7053
7053
|
}, []);
|
|
7054
7054
|
return Fe(k, () => ({
|
|
@@ -7056,11 +7056,11 @@ const Ve = Me(({
|
|
|
7056
7056
|
stopSpeaking: ee,
|
|
7057
7057
|
pauseSpeaking: Q,
|
|
7058
7058
|
resumeSpeaking: q,
|
|
7059
|
-
resumeAudioContext:
|
|
7059
|
+
resumeAudioContext: P,
|
|
7060
7060
|
setMood: Ae,
|
|
7061
7061
|
setTimingAdjustment: Se,
|
|
7062
7062
|
playAnimation: Le,
|
|
7063
|
-
isReady:
|
|
7063
|
+
isReady: oe,
|
|
7064
7064
|
isPaused: ge,
|
|
7065
7065
|
talkingHead: p.current,
|
|
7066
7066
|
handleResize: ke,
|
|
@@ -7135,7 +7135,7 @@ const Ve = Me(({
|
|
|
7135
7135
|
/* @__PURE__ */ ye(
|
|
7136
7136
|
"div",
|
|
7137
7137
|
{
|
|
7138
|
-
ref:
|
|
7138
|
+
ref: N,
|
|
7139
7139
|
className: "talking-head-viewer",
|
|
7140
7140
|
style: {
|
|
7141
7141
|
width: "100%",
|
|
@@ -7182,7 +7182,7 @@ const pt = Me(({
|
|
|
7182
7182
|
style: s = {},
|
|
7183
7183
|
avatarConfig: o = {}
|
|
7184
7184
|
}, l) => {
|
|
7185
|
-
const h = W(null), r = W(null), [u, a] = pe(!0), [d, c] = pe(null), [g, x] = pe(!1), f = Ee(), k = o.ttsService || f.service,
|
|
7185
|
+
const h = W(null), r = W(null), [u, a] = pe(!0), [d, c] = pe(null), [g, x] = pe(!1), f = Ee(), k = o.ttsService || f.service, N = k === "browser" ? {
|
|
7186
7186
|
endpoint: "",
|
|
7187
7187
|
apiKey: null,
|
|
7188
7188
|
defaultVoice: "Google US English"
|
|
@@ -7198,7 +7198,7 @@ const pt = Me(({
|
|
|
7198
7198
|
body: "F",
|
|
7199
7199
|
avatarMood: "neutral",
|
|
7200
7200
|
ttsLang: k === "browser" ? "en-US" : "en",
|
|
7201
|
-
ttsVoice: o.ttsVoice ||
|
|
7201
|
+
ttsVoice: o.ttsVoice || N.defaultVoice,
|
|
7202
7202
|
lipsyncLang: "en",
|
|
7203
7203
|
// English lip-sync
|
|
7204
7204
|
showFullAvatar: !0,
|
|
@@ -7207,12 +7207,12 @@ const pt = Me(({
|
|
|
7207
7207
|
movementIntensity: 0.5,
|
|
7208
7208
|
...o
|
|
7209
7209
|
}, B = {
|
|
7210
|
-
ttsEndpoint:
|
|
7211
|
-
ttsApikey:
|
|
7210
|
+
ttsEndpoint: N.endpoint,
|
|
7211
|
+
ttsApikey: N.apiKey,
|
|
7212
7212
|
ttsService: k,
|
|
7213
7213
|
lipsyncModules: ["en"],
|
|
7214
7214
|
cameraView: "upper"
|
|
7215
|
-
}, H =
|
|
7215
|
+
}, H = O(async () => {
|
|
7216
7216
|
if (!(!h.current || r.current))
|
|
7217
7217
|
try {
|
|
7218
7218
|
if (a(!0), c(null), r.current = new Be(h.current, B), await r.current.showAvatar(p, (X) => {
|
|
@@ -7223,7 +7223,7 @@ const pt = Me(({
|
|
|
7223
7223
|
}), r.current.morphs && r.current.morphs.length > 0) {
|
|
7224
7224
|
const X = r.current.morphs[0].morphTargetDictionary;
|
|
7225
7225
|
console.log("Available morph targets:", Object.keys(X));
|
|
7226
|
-
const Z = Object.keys(X).filter((
|
|
7226
|
+
const Z = Object.keys(X).filter((oe) => oe.startsWith("viseme_"));
|
|
7227
7227
|
console.log("Viseme morph targets found:", Z), Z.length === 0 && (console.warn("No viseme morph targets found! Lip-sync will not work properly."), console.log("Expected viseme targets: viseme_aa, viseme_E, viseme_I, viseme_O, viseme_U, viseme_PP, viseme_SS, viseme_TH, viseme_DD, viseme_FF, viseme_kk, viseme_nn, viseme_RR, viseme_CH, viseme_sil"));
|
|
7228
7228
|
}
|
|
7229
7229
|
if (await new Promise((X) => {
|
|
@@ -7238,11 +7238,11 @@ const pt = Me(({
|
|
|
7238
7238
|
console.warn("Error setting full body mode on initialization:", X);
|
|
7239
7239
|
}
|
|
7240
7240
|
a(!1), x(!0), n(r.current);
|
|
7241
|
-
const
|
|
7241
|
+
const E = () => {
|
|
7242
7242
|
document.visibilityState === "visible" ? r.current?.start() : r.current?.stop();
|
|
7243
7243
|
};
|
|
7244
|
-
return document.addEventListener("visibilitychange",
|
|
7245
|
-
document.removeEventListener("visibilitychange",
|
|
7244
|
+
return document.addEventListener("visibilitychange", E), () => {
|
|
7245
|
+
document.removeEventListener("visibilitychange", E);
|
|
7246
7246
|
};
|
|
7247
7247
|
} catch (S) {
|
|
7248
7248
|
console.error("Error initializing TalkingHead:", S), c(S.message || "Failed to initialize avatar"), a(!1), e(S);
|
|
@@ -7251,24 +7251,24 @@ const pt = Me(({
|
|
|
7251
7251
|
ce(() => (H(), () => {
|
|
7252
7252
|
r.current && (r.current.stop(), r.current.dispose(), r.current = null);
|
|
7253
7253
|
}), [H]);
|
|
7254
|
-
const
|
|
7254
|
+
const R = O((S) => {
|
|
7255
7255
|
if (r.current && g)
|
|
7256
7256
|
try {
|
|
7257
7257
|
console.log("Speaking text:", S), console.log("Avatar config:", p), console.log("TalkingHead instance:", r.current), r.current.lipsync && Object.keys(r.current.lipsync).length > 0 ? (console.log("Lip-sync modules loaded:", Object.keys(r.current.lipsync)), r.current.setSlowdownRate && (r.current.setSlowdownRate(1.05), console.log("Applied timing adjustment for better lip-sync")), r.current.speakText(S)) : (console.warn("Lip-sync modules not ready, waiting..."), setTimeout(() => {
|
|
7258
7258
|
r.current && r.current.lipsync ? (console.log("Lip-sync now ready, speaking..."), r.current.setSlowdownRate && (r.current.setSlowdownRate(1.05), console.log("Applied timing adjustment for better lip-sync")), r.current.speakText(S)) : console.error("Lip-sync still not ready after waiting");
|
|
7259
7259
|
}, 500));
|
|
7260
|
-
} catch (
|
|
7261
|
-
console.error("Error speaking text:",
|
|
7260
|
+
} catch (E) {
|
|
7261
|
+
console.error("Error speaking text:", E), c(E.message || "Failed to speak text");
|
|
7262
7262
|
}
|
|
7263
7263
|
else
|
|
7264
7264
|
console.warn("Avatar not ready for speaking. isReady:", g, "talkingHeadRef:", !!r.current);
|
|
7265
|
-
}, [g, p]), L =
|
|
7265
|
+
}, [g, p]), L = O(() => {
|
|
7266
7266
|
r.current && (r.current.stopSpeaking(), r.current.setSlowdownRate && (r.current.setSlowdownRate(1), console.log("Reset timing to normal")));
|
|
7267
|
-
}, []), I =
|
|
7267
|
+
}, []), I = O((S) => {
|
|
7268
7268
|
r.current && r.current.setMood(S);
|
|
7269
|
-
}, []), z =
|
|
7269
|
+
}, []), z = O((S) => {
|
|
7270
7270
|
r.current && r.current.setSlowdownRate && (r.current.setSlowdownRate(S), console.log("Timing adjustment set to:", S));
|
|
7271
|
-
}, []), Y =
|
|
7271
|
+
}, []), Y = O((S, E = !1) => {
|
|
7272
7272
|
if (r.current && r.current.playAnimation) {
|
|
7273
7273
|
if (r.current.setShowFullAvatar)
|
|
7274
7274
|
try {
|
|
@@ -7278,26 +7278,26 @@ const pt = Me(({
|
|
|
7278
7278
|
}
|
|
7279
7279
|
if (S.includes("."))
|
|
7280
7280
|
try {
|
|
7281
|
-
r.current.playAnimation(S, null, 10, 0, 0.01,
|
|
7281
|
+
r.current.playAnimation(S, null, 10, 0, 0.01, E), console.log("Playing animation:", S);
|
|
7282
7282
|
} catch (Z) {
|
|
7283
7283
|
console.log(`Failed to play ${S}:`, Z);
|
|
7284
7284
|
try {
|
|
7285
7285
|
r.current.setBodyMovement("idle"), console.log("Fallback to idle animation");
|
|
7286
|
-
} catch (
|
|
7287
|
-
console.warn("Fallback animation also failed:",
|
|
7286
|
+
} catch (oe) {
|
|
7287
|
+
console.warn("Fallback animation also failed:", oe);
|
|
7288
7288
|
}
|
|
7289
7289
|
}
|
|
7290
7290
|
else {
|
|
7291
7291
|
const Z = [".fbx", ".glb", ".gltf"];
|
|
7292
|
-
let
|
|
7292
|
+
let oe = !1;
|
|
7293
7293
|
for (const le of Z)
|
|
7294
7294
|
try {
|
|
7295
|
-
r.current.playAnimation(S + le, null, 10, 0, 0.01,
|
|
7295
|
+
r.current.playAnimation(S + le, null, 10, 0, 0.01, E), console.log("Playing animation:", S + le), oe = !0;
|
|
7296
7296
|
break;
|
|
7297
7297
|
} catch {
|
|
7298
7298
|
console.log(`Failed to play ${S}${le}, trying next format...`);
|
|
7299
7299
|
}
|
|
7300
|
-
if (!
|
|
7300
|
+
if (!oe) {
|
|
7301
7301
|
console.warn("Animation system not available or animation not found:", S);
|
|
7302
7302
|
try {
|
|
7303
7303
|
r.current.setBodyMovement("idle"), console.log("Fallback to idle animation");
|
|
@@ -7310,7 +7310,7 @@ const pt = Me(({
|
|
|
7310
7310
|
console.warn("Animation system not available or animation not found:", S);
|
|
7311
7311
|
}, []);
|
|
7312
7312
|
return Fe(l, () => ({
|
|
7313
|
-
speakText:
|
|
7313
|
+
speakText: R,
|
|
7314
7314
|
stopSpeaking: L,
|
|
7315
7315
|
setMood: I,
|
|
7316
7316
|
setTimingAdjustment: z,
|
|
@@ -7321,8 +7321,8 @@ const pt = Me(({
|
|
|
7321
7321
|
if (r.current && r.current.setShowFullAvatar && r.current.setBodyMovement)
|
|
7322
7322
|
try {
|
|
7323
7323
|
r.current.setShowFullAvatar(!0), r.current.setBodyMovement(S), console.log("Body movement set with full body mode:", S);
|
|
7324
|
-
} catch (
|
|
7325
|
-
console.warn("Error setting body movement:",
|
|
7324
|
+
} catch (E) {
|
|
7325
|
+
console.warn("Error setting body movement:", E);
|
|
7326
7326
|
}
|
|
7327
7327
|
},
|
|
7328
7328
|
setMovementIntensity: (S) => r.current?.setMovementIntensity(S),
|
|
@@ -7338,8 +7338,8 @@ const pt = Me(({
|
|
|
7338
7338
|
if (r.current && r.current.setShowFullAvatar && r.current.playReaction)
|
|
7339
7339
|
try {
|
|
7340
7340
|
r.current.setShowFullAvatar(!0), r.current.playReaction(S), console.log("Reaction played with full body mode:", S);
|
|
7341
|
-
} catch (
|
|
7342
|
-
console.warn("Error playing reaction:",
|
|
7341
|
+
} catch (E) {
|
|
7342
|
+
console.warn("Error playing reaction:", E);
|
|
7343
7343
|
}
|
|
7344
7344
|
},
|
|
7345
7345
|
playCelebration: () => {
|
|
@@ -7354,8 +7354,8 @@ const pt = Me(({
|
|
|
7354
7354
|
if (r.current && r.current.setShowFullAvatar)
|
|
7355
7355
|
try {
|
|
7356
7356
|
r.current.setShowFullAvatar(S), console.log("Show full avatar set to:", S);
|
|
7357
|
-
} catch (
|
|
7358
|
-
console.warn("Error setting showFullAvatar:",
|
|
7357
|
+
} catch (E) {
|
|
7358
|
+
console.warn("Error setting showFullAvatar:", E);
|
|
7359
7359
|
}
|
|
7360
7360
|
},
|
|
7361
7361
|
lockAvatarPosition: () => {
|
|
@@ -7441,29 +7441,32 @@ const yt = Me(({
|
|
|
7441
7441
|
},
|
|
7442
7442
|
className: f = "",
|
|
7443
7443
|
style: k = {},
|
|
7444
|
-
animations:
|
|
7444
|
+
animations: N = {},
|
|
7445
7445
|
autoAnimationGroup: p = null,
|
|
7446
7446
|
// e.g., "talking" - will randomly select from this group when speaking
|
|
7447
7447
|
autoIdleGroup: B = null,
|
|
7448
7448
|
// e.g., "idle" - will randomly select from this group when idle
|
|
7449
7449
|
autoSpeak: H = !1
|
|
7450
|
-
},
|
|
7451
|
-
const L = W(null), I = W(null), z = W(u), Y = W(null), S = W(null),
|
|
7450
|
+
}, R) => {
|
|
7451
|
+
const L = W(null), I = W(null), z = W(u), Y = W(null), S = W(null), E = W(!1), X = W({ remainingText: null, originalText: null, options: null }), Z = W([]), [oe, le] = pe(!0), [ge, de] = pe(null), [$, be] = pe(!1), [j, b] = pe(!1), [v, F] = pe(N), P = W(null);
|
|
7452
7452
|
ce(() => {
|
|
7453
|
-
|
|
7453
|
+
E.current = j;
|
|
7454
7454
|
}, [j]), ce(() => {
|
|
7455
7455
|
(async () => {
|
|
7456
|
-
if (
|
|
7456
|
+
if (N.manifest)
|
|
7457
7457
|
try {
|
|
7458
|
-
const
|
|
7459
|
-
|
|
7460
|
-
|
|
7461
|
-
|
|
7458
|
+
const T = await gt(N.manifest);
|
|
7459
|
+
F(T), console.log("Loaded animations from manifest:", T), T._genderSpecific && console.log("Gender-specific animations detected:", {
|
|
7460
|
+
male: Object.keys(T._genderSpecific.male || {}),
|
|
7461
|
+
female: Object.keys(T._genderSpecific.female || {})
|
|
7462
|
+
});
|
|
7463
|
+
} catch (T) {
|
|
7464
|
+
console.error("Failed to load animation manifest:", T), F(N);
|
|
7462
7465
|
}
|
|
7463
7466
|
else
|
|
7464
|
-
|
|
7467
|
+
F(N);
|
|
7465
7468
|
})();
|
|
7466
|
-
}, [
|
|
7469
|
+
}, [N]), ce(() => {
|
|
7467
7470
|
z.current = u;
|
|
7468
7471
|
}, [u]);
|
|
7469
7472
|
const D = Ee(), ee = s || D.service;
|
|
@@ -7505,16 +7508,16 @@ const yt = Me(({
|
|
|
7505
7508
|
ttsService: ee,
|
|
7506
7509
|
lipsyncModules: ["en"],
|
|
7507
7510
|
cameraView: a
|
|
7508
|
-
}, Se =
|
|
7511
|
+
}, Se = O(async () => {
|
|
7509
7512
|
if (!(!L.current || I.current))
|
|
7510
7513
|
try {
|
|
7511
7514
|
le(!0), de(null), I.current = new Be(L.current, Ae), console.log("Avatar config being passed:", {
|
|
7512
7515
|
url: q.url,
|
|
7513
7516
|
body: q.body,
|
|
7514
7517
|
avatarMood: q.avatarMood
|
|
7515
|
-
}), await I.current.showAvatar(q, (
|
|
7516
|
-
if (
|
|
7517
|
-
const K = Math.min(100, Math.round(
|
|
7518
|
+
}), await I.current.showAvatar(q, (T) => {
|
|
7519
|
+
if (T.lengthComputable) {
|
|
7520
|
+
const K = Math.min(100, Math.round(T.loaded / T.total * 100));
|
|
7518
7521
|
c(K);
|
|
7519
7522
|
}
|
|
7520
7523
|
}), I.current?.avatar && console.log("Avatar body after initialization:", I.current.avatar.body), le(!1), be(!0), d(I.current);
|
|
@@ -7531,7 +7534,7 @@ const yt = Me(({
|
|
|
7531
7534
|
ce(() => (Se(), () => {
|
|
7532
7535
|
I.current && (I.current.stop(), I.current.dispose(), I.current = null);
|
|
7533
7536
|
}), [Se]);
|
|
7534
|
-
const Le =
|
|
7537
|
+
const Le = O(async () => {
|
|
7535
7538
|
if (I.current)
|
|
7536
7539
|
try {
|
|
7537
7540
|
const A = I.current.audioCtx || I.current.audioContext;
|
|
@@ -7539,25 +7542,29 @@ const yt = Me(({
|
|
|
7539
7542
|
} catch (A) {
|
|
7540
7543
|
console.warn("Failed to resume audio context:", A);
|
|
7541
7544
|
}
|
|
7542
|
-
}, []), ke =
|
|
7543
|
-
if (!
|
|
7545
|
+
}, []), ke = O((A) => {
|
|
7546
|
+
if (!v || !v[A])
|
|
7544
7547
|
return null;
|
|
7545
|
-
|
|
7546
|
-
if (
|
|
7547
|
-
const
|
|
7548
|
-
|
|
7548
|
+
let T = v[A];
|
|
7549
|
+
if (v._genderSpecific) {
|
|
7550
|
+
const ne = (e?.toUpperCase() || "F") === "M" ? "male" : "female", ie = v._genderSpecific[ne];
|
|
7551
|
+
ie && ie[A] ? (T = ie[A], console.log(`Using ${ne} animations for "${A}"`)) : v._genderSpecific.shared && v._genderSpecific.shared[A] && (T = v._genderSpecific.shared[A], console.log(`Using shared animations for "${A}"`));
|
|
7552
|
+
}
|
|
7553
|
+
if (Array.isArray(T) && T.length > 0) {
|
|
7554
|
+
const K = Math.floor(Math.random() * T.length);
|
|
7555
|
+
return T[K];
|
|
7549
7556
|
}
|
|
7550
|
-
return typeof
|
|
7551
|
-
}, [
|
|
7557
|
+
return typeof T == "string" ? T : null;
|
|
7558
|
+
}, [v, e]), w = O((A, T = !1) => {
|
|
7552
7559
|
const K = ke(A);
|
|
7553
7560
|
if (K && I.current)
|
|
7554
7561
|
try {
|
|
7555
|
-
return I.current.playAnimation(K, null, 10, 0, 0.01,
|
|
7556
|
-
} catch (
|
|
7557
|
-
return console.warn(`Failed to play random animation from "${A}" group:`,
|
|
7562
|
+
return I.current.playAnimation(K, null, 10, 0, 0.01, T), console.log(`Playing random animation from "${A}" group:`, K), K;
|
|
7563
|
+
} catch (ne) {
|
|
7564
|
+
return console.warn(`Failed to play random animation from "${A}" group:`, ne), null;
|
|
7558
7565
|
}
|
|
7559
7566
|
return null;
|
|
7560
|
-
}, [ke]), U =
|
|
7567
|
+
}, [ke]), U = O(async (A, T = {}) => {
|
|
7561
7568
|
if (!I.current || !$) {
|
|
7562
7569
|
console.warn("Avatar not ready for speaking");
|
|
7563
7570
|
return;
|
|
@@ -7567,66 +7574,66 @@ const yt = Me(({
|
|
|
7567
7574
|
return;
|
|
7568
7575
|
}
|
|
7569
7576
|
await Le();
|
|
7570
|
-
const K =
|
|
7571
|
-
K && !
|
|
7572
|
-
const
|
|
7573
|
-
Z.current =
|
|
7574
|
-
const
|
|
7575
|
-
lipsyncLang:
|
|
7577
|
+
const K = T.animationGroup || p;
|
|
7578
|
+
K && !T.skipAnimation && w(K), X.current = { remainingText: null, originalText: null, options: null }, Z.current = [], Y.current = { text: A, options: T }, S.current && (clearInterval(S.current), S.current = null), b(!1), E.current = !1;
|
|
7579
|
+
const ne = A.split(/[.!?]+/).filter((se) => se.trim().length > 0);
|
|
7580
|
+
Z.current = ne;
|
|
7581
|
+
const ie = {
|
|
7582
|
+
lipsyncLang: T.lipsyncLang || "en",
|
|
7576
7583
|
onSpeechEnd: () => {
|
|
7577
|
-
S.current && (clearInterval(S.current), S.current = null),
|
|
7584
|
+
S.current && (clearInterval(S.current), S.current = null), T.onSpeechEnd && T.onSpeechEnd(), x();
|
|
7578
7585
|
}
|
|
7579
7586
|
};
|
|
7580
7587
|
try {
|
|
7581
|
-
I.current.speakText(A,
|
|
7582
|
-
} catch (
|
|
7583
|
-
console.error("Error speaking text:",
|
|
7588
|
+
I.current.speakText(A, ie);
|
|
7589
|
+
} catch (se) {
|
|
7590
|
+
console.error("Error speaking text:", se), de(se.message || "Failed to speak text");
|
|
7584
7591
|
}
|
|
7585
7592
|
}, [$, x, Le, p, w]);
|
|
7586
7593
|
ce(() => {
|
|
7587
7594
|
if (!$ || !B || !I.current)
|
|
7588
7595
|
return;
|
|
7589
|
-
|
|
7596
|
+
P.current && clearInterval(P.current);
|
|
7590
7597
|
const A = () => {
|
|
7591
|
-
I.current && !
|
|
7598
|
+
I.current && !E.current && w(B);
|
|
7592
7599
|
};
|
|
7593
|
-
return A(),
|
|
7600
|
+
return A(), P.current = setInterval(() => {
|
|
7594
7601
|
A();
|
|
7595
7602
|
}, 12e3 + Math.random() * 3e3), () => {
|
|
7596
|
-
|
|
7603
|
+
P.current && (clearInterval(P.current), P.current = null);
|
|
7597
7604
|
};
|
|
7598
7605
|
}, [$, B, w]), ce(() => {
|
|
7599
7606
|
$ && V && H && I.current && U(V);
|
|
7600
7607
|
}, [$, V, H, U]);
|
|
7601
|
-
const _ =
|
|
7608
|
+
const _ = O(() => {
|
|
7602
7609
|
if (I.current)
|
|
7603
7610
|
try {
|
|
7604
|
-
const A = I.current.isSpeaking || !1,
|
|
7605
|
-
if (A ||
|
|
7611
|
+
const A = I.current.isSpeaking || !1, T = I.current.audioPlaylist || [], K = I.current.speechQueue || [];
|
|
7612
|
+
if (A || T.length > 0 || K.length > 0) {
|
|
7606
7613
|
S.current && (clearInterval(S.current), S.current = null);
|
|
7607
|
-
let
|
|
7608
|
-
K.length > 0 && (
|
|
7609
|
-
remainingText:
|
|
7614
|
+
let ne = "";
|
|
7615
|
+
K.length > 0 && (ne = K.map((ie) => ie.text && Array.isArray(ie.text) ? ie.text.map((se) => se.word).join(" ") : ie.text || "").join(" ")), X.current = {
|
|
7616
|
+
remainingText: ne || null,
|
|
7610
7617
|
originalText: Y.current?.text || null,
|
|
7611
7618
|
options: Y.current?.options || null
|
|
7612
|
-
}, I.current.speechQueue.length = 0, I.current.pauseSpeaking(), b(!0),
|
|
7619
|
+
}, I.current.speechQueue.length = 0, I.current.pauseSpeaking(), b(!0), E.current = !0;
|
|
7613
7620
|
}
|
|
7614
7621
|
} catch (A) {
|
|
7615
7622
|
console.warn("Error pausing speech:", A);
|
|
7616
7623
|
}
|
|
7617
|
-
}, []), te =
|
|
7624
|
+
}, []), te = O(async () => {
|
|
7618
7625
|
if (!(!I.current || !j))
|
|
7619
7626
|
try {
|
|
7620
|
-
await Le(), b(!1),
|
|
7621
|
-
const A = X.current?.remainingText,
|
|
7622
|
-
|
|
7627
|
+
await Le(), b(!1), E.current = !1;
|
|
7628
|
+
const A = X.current?.remainingText, T = X.current?.originalText || Y.current?.text, K = X.current?.options || Y.current?.options || {}, ne = A || T;
|
|
7629
|
+
ne && U(ne, K);
|
|
7623
7630
|
} catch (A) {
|
|
7624
|
-
console.warn("Error resuming speech:", A), b(!1),
|
|
7631
|
+
console.warn("Error resuming speech:", A), b(!1), E.current = !1;
|
|
7625
7632
|
}
|
|
7626
|
-
}, [j, U, Le]), me =
|
|
7627
|
-
I.current && (I.current.stopSpeaking(), S.current && (clearInterval(S.current), S.current = null), b(!1),
|
|
7633
|
+
}, [j, U, Le]), me = O(() => {
|
|
7634
|
+
I.current && (I.current.stopSpeaking(), S.current && (clearInterval(S.current), S.current = null), b(!1), E.current = !1);
|
|
7628
7635
|
}, []);
|
|
7629
|
-
return Fe(
|
|
7636
|
+
return Fe(R, () => ({
|
|
7630
7637
|
speakText: U,
|
|
7631
7638
|
pauseSpeaking: _,
|
|
7632
7639
|
resumeSpeaking: te,
|
|
@@ -7637,10 +7644,10 @@ const yt = Me(({
|
|
|
7637
7644
|
setBodyMovement: (A) => {
|
|
7638
7645
|
I.current && I.current.setBodyMovement(A);
|
|
7639
7646
|
},
|
|
7640
|
-
playAnimation: (A,
|
|
7641
|
-
I.current && I.current.playAnimation && I.current.playAnimation(A, null, 10, 0, 0.01,
|
|
7647
|
+
playAnimation: (A, T = !1) => {
|
|
7648
|
+
I.current && I.current.playAnimation && I.current.playAnimation(A, null, 10, 0, 0.01, T);
|
|
7642
7649
|
},
|
|
7643
|
-
playRandomAnimation: (A,
|
|
7650
|
+
playRandomAnimation: (A, T = !1) => w(A, T),
|
|
7644
7651
|
getRandomAnimation: (A) => ke(A),
|
|
7645
7652
|
playReaction: (A) => I.current?.playReaction(A),
|
|
7646
7653
|
playCelebration: () => I.current?.playCelebration(),
|
|
@@ -7662,7 +7669,7 @@ const yt = Me(({
|
|
|
7662
7669
|
}
|
|
7663
7670
|
}
|
|
7664
7671
|
),
|
|
7665
|
-
|
|
7672
|
+
oe && /* @__PURE__ */ ye("div", { className: "loading-overlay", style: {
|
|
7666
7673
|
position: "absolute",
|
|
7667
7674
|
top: "50%",
|
|
7668
7675
|
left: "50%",
|
|
@@ -7718,7 +7725,7 @@ const ft = Me(({
|
|
|
7718
7725
|
onQuestionAnswer: s,
|
|
7719
7726
|
onCurriculumComplete: o,
|
|
7720
7727
|
onCustomAction: l
|
|
7721
|
-
}), c = W(null), g = W(null), x = W(null), f = W(null), k = W(null),
|
|
7728
|
+
}), c = W(null), g = W(null), x = W(null), f = W(null), k = W(null), N = W(null), p = W(null), B = W(V?.curriculum || {
|
|
7722
7729
|
title: "Default Curriculum",
|
|
7723
7730
|
description: "No curriculum data provided",
|
|
7724
7731
|
language: "en",
|
|
@@ -7766,11 +7773,11 @@ const ft = Me(({
|
|
|
7766
7773
|
lipsyncLang: "en"
|
|
7767
7774
|
};
|
|
7768
7775
|
}, [V, t, e]);
|
|
7769
|
-
const
|
|
7776
|
+
const R = O(() => (B.current || { modules: [] }).modules[a.current.currentModuleIndex]?.lessons[a.current.currentLessonIndex], []), L = O(() => R()?.questions[a.current.currentQuestionIndex], [R]), I = O((b, v) => v.type === "multiple_choice" || v.type === "true_false" ? b === v.answer : v.type === "code_test" && typeof b == "object" && b !== null ? b.passed === !0 : !1, []), z = O(() => {
|
|
7770
7777
|
a.current.lessonCompleted = !0, a.current.isQuestionMode = !1;
|
|
7771
7778
|
const b = a.current.totalQuestions > 0 ? Math.round(a.current.score / a.current.totalQuestions * 100) : 100;
|
|
7772
|
-
let
|
|
7773
|
-
if (a.current.totalQuestions > 0 ?
|
|
7779
|
+
let v = "Congratulations! You've completed this lesson";
|
|
7780
|
+
if (a.current.totalQuestions > 0 ? v += ` You got ${a.current.score} correct out of ${a.current.totalQuestions} question${a.current.totalQuestions === 1 ? "" : "s"}, achieving a score of ${b} percent. ` : v += "! ", b >= 80 ? v += "Excellent work! You have a great understanding of this topic." : b >= 60 ? v += "Good job! You understand most of the concepts." : v += "Keep practicing! You're making progress.", d.current.onLessonComplete({
|
|
7774
7781
|
moduleIndex: a.current.currentModuleIndex,
|
|
7775
7782
|
lessonIndex: a.current.currentLessonIndex,
|
|
7776
7783
|
score: a.current.score,
|
|
@@ -7790,8 +7797,8 @@ const ft = Me(({
|
|
|
7790
7797
|
} catch {
|
|
7791
7798
|
u.current.playCelebration();
|
|
7792
7799
|
}
|
|
7793
|
-
const
|
|
7794
|
-
u.current.speakText(
|
|
7800
|
+
const F = B.current || { modules: [] }, P = F.modules[a.current.currentModuleIndex], D = a.current.currentLessonIndex < (P?.lessons?.length || 0) - 1, ee = a.current.currentModuleIndex < (F.modules?.length || 0) - 1, Q = D || ee, q = H.current || { lipsyncLang: "en" };
|
|
7801
|
+
u.current.speakText(v, {
|
|
7795
7802
|
lipsyncLang: q.lipsyncLang,
|
|
7796
7803
|
onSpeechEnd: () => {
|
|
7797
7804
|
d.current.onCustomAction({
|
|
@@ -7806,12 +7813,12 @@ const ft = Me(({
|
|
|
7806
7813
|
}
|
|
7807
7814
|
});
|
|
7808
7815
|
}
|
|
7809
|
-
}, [e.lessonComplete]), Y =
|
|
7816
|
+
}, [e.lessonComplete]), Y = O(() => {
|
|
7810
7817
|
a.current.curriculumCompleted = !0;
|
|
7811
7818
|
const b = B.current || { modules: [] };
|
|
7812
7819
|
if (d.current.onCurriculumComplete({
|
|
7813
7820
|
modules: b.modules.length,
|
|
7814
|
-
totalLessons: b.modules.reduce((
|
|
7821
|
+
totalLessons: b.modules.reduce((v, F) => v + F.lessons.length, 0)
|
|
7815
7822
|
}), u.current) {
|
|
7816
7823
|
if (u.current.setMood("celebrating"), e.curriculumComplete)
|
|
7817
7824
|
try {
|
|
@@ -7819,99 +7826,99 @@ const ft = Me(({
|
|
|
7819
7826
|
} catch {
|
|
7820
7827
|
u.current.playCelebration();
|
|
7821
7828
|
}
|
|
7822
|
-
const
|
|
7823
|
-
u.current.speakText("Amazing! You've completed the entire curriculum! You're now ready to move on to more advanced topics. Well done!", { lipsyncLang:
|
|
7829
|
+
const v = H.current || { lipsyncLang: "en" };
|
|
7830
|
+
u.current.speakText("Amazing! You've completed the entire curriculum! You're now ready to move on to more advanced topics. Well done!", { lipsyncLang: v.lipsyncLang });
|
|
7824
7831
|
}
|
|
7825
|
-
}, [e.curriculumComplete]), S =
|
|
7826
|
-
const b =
|
|
7832
|
+
}, [e.curriculumComplete]), S = O(() => {
|
|
7833
|
+
const b = R();
|
|
7827
7834
|
a.current.isQuestionMode = !0, a.current.currentQuestionIndex = 0, a.current.totalQuestions = b?.questions?.length || 0, a.current.score = 0;
|
|
7828
|
-
const
|
|
7829
|
-
|
|
7835
|
+
const v = L();
|
|
7836
|
+
v && d.current.onCustomAction({
|
|
7830
7837
|
type: "questionStart",
|
|
7831
7838
|
moduleIndex: a.current.currentModuleIndex,
|
|
7832
7839
|
lessonIndex: a.current.currentLessonIndex,
|
|
7833
7840
|
questionIndex: a.current.currentQuestionIndex,
|
|
7834
7841
|
totalQuestions: a.current.totalQuestions,
|
|
7835
|
-
question:
|
|
7842
|
+
question: v,
|
|
7836
7843
|
score: a.current.score
|
|
7837
7844
|
});
|
|
7838
|
-
const
|
|
7839
|
-
if (!u.current || !
|
|
7845
|
+
const F = () => {
|
|
7846
|
+
if (!u.current || !v) return;
|
|
7840
7847
|
if (u.current.setMood("happy"), e.questionStart)
|
|
7841
7848
|
try {
|
|
7842
7849
|
u.current.playAnimation(e.questionStart, !0);
|
|
7843
7850
|
} catch (D) {
|
|
7844
7851
|
console.warn("Failed to play questionStart animation:", D);
|
|
7845
7852
|
}
|
|
7846
|
-
const
|
|
7847
|
-
|
|
7853
|
+
const P = H.current || { lipsyncLang: "en" };
|
|
7854
|
+
v.type === "code_test" ? u.current.speakText(`Let's test your coding skills! Here's your first challenge: ${v.question}`, { lipsyncLang: P.lipsyncLang }) : v.type === "multiple_choice" ? u.current.speakText(`Now let me ask you some questions. Here's the first one: ${v.question}`, { lipsyncLang: P.lipsyncLang }) : v.type === "true_false" ? u.current.speakText(`Let's start with some true or false questions. First question: ${v.question}`, { lipsyncLang: P.lipsyncLang }) : u.current.speakText(`Now let me ask you some questions. Here's the first one: ${v.question}`, { lipsyncLang: P.lipsyncLang });
|
|
7848
7855
|
};
|
|
7849
|
-
if (u.current && u.current.isReady &&
|
|
7850
|
-
|
|
7856
|
+
if (u.current && u.current.isReady && v)
|
|
7857
|
+
F();
|
|
7851
7858
|
else if (u.current && u.current.isReady) {
|
|
7852
|
-
const
|
|
7853
|
-
u.current.speakText("Now let me ask you some questions to test your understanding.", { lipsyncLang:
|
|
7859
|
+
const P = H.current || { lipsyncLang: "en" };
|
|
7860
|
+
u.current.speakText("Now let me ask you some questions to test your understanding.", { lipsyncLang: P.lipsyncLang });
|
|
7854
7861
|
} else {
|
|
7855
|
-
const
|
|
7856
|
-
u.current && u.current.isReady && (clearInterval(
|
|
7862
|
+
const P = setInterval(() => {
|
|
7863
|
+
u.current && u.current.isReady && (clearInterval(P), v && F());
|
|
7857
7864
|
}, 100);
|
|
7858
7865
|
setTimeout(() => {
|
|
7859
|
-
clearInterval(
|
|
7866
|
+
clearInterval(P);
|
|
7860
7867
|
}, 5e3);
|
|
7861
7868
|
}
|
|
7862
|
-
}, [e.questionStart,
|
|
7863
|
-
const b =
|
|
7869
|
+
}, [e.questionStart, R, L]), E = O(() => {
|
|
7870
|
+
const b = R();
|
|
7864
7871
|
if (a.current.currentQuestionIndex < (b?.questions?.length || 0) - 1) {
|
|
7865
7872
|
u.current && u.current.stopSpeaking && u.current.stopSpeaking(), a.current.currentQuestionIndex += 1;
|
|
7866
|
-
const
|
|
7867
|
-
|
|
7873
|
+
const v = L();
|
|
7874
|
+
v && d.current.onCustomAction({
|
|
7868
7875
|
type: "nextQuestion",
|
|
7869
7876
|
moduleIndex: a.current.currentModuleIndex,
|
|
7870
7877
|
lessonIndex: a.current.currentLessonIndex,
|
|
7871
7878
|
questionIndex: a.current.currentQuestionIndex,
|
|
7872
7879
|
totalQuestions: a.current.totalQuestions,
|
|
7873
|
-
question:
|
|
7880
|
+
question: v,
|
|
7874
7881
|
score: a.current.score
|
|
7875
7882
|
});
|
|
7876
|
-
const
|
|
7877
|
-
if (!u.current || !
|
|
7883
|
+
const F = () => {
|
|
7884
|
+
if (!u.current || !v) return;
|
|
7878
7885
|
if (u.current.setMood("happy"), u.current.setBodyMovement("idle"), e.nextQuestion)
|
|
7879
7886
|
try {
|
|
7880
7887
|
u.current.playAnimation(e.nextQuestion, !0);
|
|
7881
7888
|
} catch (q) {
|
|
7882
7889
|
console.warn("Failed to play nextQuestion animation:", q);
|
|
7883
7890
|
}
|
|
7884
|
-
const
|
|
7885
|
-
if (
|
|
7886
|
-
const q = Q ? `Great! Here's your final coding challenge: ${
|
|
7891
|
+
const P = H.current || { lipsyncLang: "en" }, ee = R()?.questions?.length || 0, Q = a.current.currentQuestionIndex >= ee - 1;
|
|
7892
|
+
if (v.type === "code_test") {
|
|
7893
|
+
const q = Q ? `Great! Here's your final coding challenge: ${v.question}` : `Great! Now let's move on to your next coding challenge: ${v.question}`;
|
|
7887
7894
|
u.current.speakText(q, {
|
|
7888
|
-
lipsyncLang:
|
|
7895
|
+
lipsyncLang: P.lipsyncLang
|
|
7889
7896
|
});
|
|
7890
|
-
} else if (
|
|
7891
|
-
const q = Q ? `Alright! Here's your final question: ${
|
|
7897
|
+
} else if (v.type === "multiple_choice") {
|
|
7898
|
+
const q = Q ? `Alright! Here's your final question: ${v.question}` : `Alright! Here's your next question: ${v.question}`;
|
|
7892
7899
|
u.current.speakText(q, {
|
|
7893
|
-
lipsyncLang:
|
|
7900
|
+
lipsyncLang: P.lipsyncLang
|
|
7894
7901
|
});
|
|
7895
|
-
} else if (
|
|
7896
|
-
const q = Q ? `Now let's try this final one: ${
|
|
7902
|
+
} else if (v.type === "true_false") {
|
|
7903
|
+
const q = Q ? `Now let's try this final one: ${v.question}` : `Now let's try this one: ${v.question}`;
|
|
7897
7904
|
u.current.speakText(q, {
|
|
7898
|
-
lipsyncLang:
|
|
7905
|
+
lipsyncLang: P.lipsyncLang
|
|
7899
7906
|
});
|
|
7900
7907
|
} else {
|
|
7901
|
-
const q = Q ? `Here's your final question: ${
|
|
7908
|
+
const q = Q ? `Here's your final question: ${v.question}` : `Here's the next question: ${v.question}`;
|
|
7902
7909
|
u.current.speakText(q, {
|
|
7903
|
-
lipsyncLang:
|
|
7910
|
+
lipsyncLang: P.lipsyncLang
|
|
7904
7911
|
});
|
|
7905
7912
|
}
|
|
7906
7913
|
};
|
|
7907
|
-
if (u.current && u.current.isReady &&
|
|
7908
|
-
|
|
7909
|
-
else if (
|
|
7910
|
-
const
|
|
7911
|
-
u.current && u.current.isReady && (clearInterval(
|
|
7914
|
+
if (u.current && u.current.isReady && v)
|
|
7915
|
+
F();
|
|
7916
|
+
else if (v) {
|
|
7917
|
+
const P = setInterval(() => {
|
|
7918
|
+
u.current && u.current.isReady && (clearInterval(P), F());
|
|
7912
7919
|
}, 100);
|
|
7913
7920
|
setTimeout(() => {
|
|
7914
|
-
clearInterval(
|
|
7921
|
+
clearInterval(P);
|
|
7915
7922
|
}, 5e3);
|
|
7916
7923
|
}
|
|
7917
7924
|
} else
|
|
@@ -7922,11 +7929,11 @@ const ft = Me(({
|
|
|
7922
7929
|
totalQuestions: a.current.totalQuestions,
|
|
7923
7930
|
score: a.current.score
|
|
7924
7931
|
});
|
|
7925
|
-
}, [e.nextQuestion,
|
|
7926
|
-
const b = B.current || { modules: [] },
|
|
7927
|
-
if (a.current.currentLessonIndex < (
|
|
7932
|
+
}, [e.nextQuestion, R, L]), X = O(() => {
|
|
7933
|
+
const b = B.current || { modules: [] }, v = b.modules[a.current.currentModuleIndex];
|
|
7934
|
+
if (a.current.currentLessonIndex < (v?.lessons?.length || 0) - 1) {
|
|
7928
7935
|
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;
|
|
7929
|
-
const
|
|
7936
|
+
const P = b.modules[a.current.currentModuleIndex], D = a.current.currentLessonIndex < (P?.lessons?.length || 0) - 1, ee = a.current.currentModuleIndex < (b.modules?.length || 0) - 1, Q = D || ee;
|
|
7930
7937
|
d.current.onCustomAction({
|
|
7931
7938
|
type: "lessonStart",
|
|
7932
7939
|
moduleIndex: a.current.currentModuleIndex,
|
|
@@ -7935,7 +7942,7 @@ const ft = Me(({
|
|
|
7935
7942
|
}), d.current.onLessonStart({
|
|
7936
7943
|
moduleIndex: a.current.currentModuleIndex,
|
|
7937
7944
|
lessonIndex: a.current.currentLessonIndex,
|
|
7938
|
-
lesson:
|
|
7945
|
+
lesson: R()
|
|
7939
7946
|
}), u.current && (u.current.setMood("happy"), u.current.setBodyMovement("idle"));
|
|
7940
7947
|
} else if (a.current.currentModuleIndex < (b.modules?.length || 0) - 1) {
|
|
7941
7948
|
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;
|
|
@@ -7948,29 +7955,29 @@ const ft = Me(({
|
|
|
7948
7955
|
}), d.current.onLessonStart({
|
|
7949
7956
|
moduleIndex: a.current.currentModuleIndex,
|
|
7950
7957
|
lessonIndex: a.current.currentLessonIndex,
|
|
7951
|
-
lesson:
|
|
7958
|
+
lesson: R()
|
|
7952
7959
|
}), u.current && (u.current.setMood("happy"), u.current.setBodyMovement("idle"));
|
|
7953
7960
|
} else
|
|
7954
7961
|
k.current && k.current();
|
|
7955
|
-
}, []), Z =
|
|
7956
|
-
const b =
|
|
7957
|
-
let
|
|
7962
|
+
}, []), Z = O(() => {
|
|
7963
|
+
const b = R();
|
|
7964
|
+
let v = null;
|
|
7958
7965
|
if (b?.avatar_script && b?.body) {
|
|
7959
|
-
const
|
|
7960
|
-
|
|
7966
|
+
const F = b.avatar_script.trim(), P = b.body.trim(), D = F.match(/[.!?]$/) ? " " : ". ";
|
|
7967
|
+
v = `${F}${D}${P}`;
|
|
7961
7968
|
} else
|
|
7962
|
-
|
|
7963
|
-
if (u.current && u.current.isReady &&
|
|
7969
|
+
v = b?.avatar_script || b?.body || null;
|
|
7970
|
+
if (u.current && u.current.isReady && v) {
|
|
7964
7971
|
a.current.isTeaching = !0, a.current.isQuestionMode = !1, a.current.score = 0, a.current.totalQuestions = 0, u.current.setMood("happy");
|
|
7965
|
-
let
|
|
7972
|
+
let F = !1;
|
|
7966
7973
|
if (e.teaching)
|
|
7967
7974
|
try {
|
|
7968
|
-
u.current.playAnimation(e.teaching, !0),
|
|
7975
|
+
u.current.playAnimation(e.teaching, !0), F = !0;
|
|
7969
7976
|
} catch (D) {
|
|
7970
7977
|
console.warn("Failed to play teaching animation:", D);
|
|
7971
7978
|
}
|
|
7972
|
-
|
|
7973
|
-
const
|
|
7979
|
+
F || u.current.setBodyMovement("gesturing");
|
|
7980
|
+
const P = H.current || { lipsyncLang: "en" };
|
|
7974
7981
|
d.current.onLessonStart({
|
|
7975
7982
|
moduleIndex: a.current.currentModuleIndex,
|
|
7976
7983
|
lessonIndex: a.current.currentLessonIndex,
|
|
@@ -7980,8 +7987,8 @@ const ft = Me(({
|
|
|
7980
7987
|
moduleIndex: a.current.currentModuleIndex,
|
|
7981
7988
|
lessonIndex: a.current.currentLessonIndex,
|
|
7982
7989
|
lesson: b
|
|
7983
|
-
}), u.current.speakText(
|
|
7984
|
-
lipsyncLang:
|
|
7990
|
+
}), u.current.speakText(v, {
|
|
7991
|
+
lipsyncLang: P.lipsyncLang,
|
|
7985
7992
|
onSpeechEnd: () => {
|
|
7986
7993
|
a.current.isTeaching = !1, d.current.onCustomAction({
|
|
7987
7994
|
type: "teachingComplete",
|
|
@@ -7999,17 +8006,17 @@ const ft = Me(({
|
|
|
7999
8006
|
}
|
|
8000
8007
|
});
|
|
8001
8008
|
}
|
|
8002
|
-
}, [e.teaching,
|
|
8003
|
-
const
|
|
8004
|
-
if (
|
|
8009
|
+
}, [e.teaching, R]), oe = O((b) => {
|
|
8010
|
+
const v = L(), F = I(b, v);
|
|
8011
|
+
if (F && (a.current.score += 1), d.current.onQuestionAnswer({
|
|
8005
8012
|
moduleIndex: a.current.currentModuleIndex,
|
|
8006
8013
|
lessonIndex: a.current.currentLessonIndex,
|
|
8007
8014
|
questionIndex: a.current.currentQuestionIndex,
|
|
8008
8015
|
answer: b,
|
|
8009
|
-
isCorrect:
|
|
8010
|
-
question:
|
|
8016
|
+
isCorrect: F,
|
|
8017
|
+
question: v
|
|
8011
8018
|
}), u.current)
|
|
8012
|
-
if (
|
|
8019
|
+
if (F) {
|
|
8013
8020
|
if (u.current.setMood("happy"), e.correct)
|
|
8014
8021
|
try {
|
|
8015
8022
|
u.current.playReaction("happy");
|
|
@@ -8017,11 +8024,11 @@ const ft = Me(({
|
|
|
8017
8024
|
u.current.setBodyMovement("happy");
|
|
8018
8025
|
}
|
|
8019
8026
|
u.current.setBodyMovement("gesturing");
|
|
8020
|
-
const D =
|
|
8027
|
+
const D = R()?.questions?.length || 0;
|
|
8021
8028
|
a.current.currentQuestionIndex >= D - 1;
|
|
8022
8029
|
const ee = a.current.currentQuestionIndex < D - 1;
|
|
8023
8030
|
console.log("[CurriculumLearning] Answer feedback - questionIndex:", a.current.currentQuestionIndex, "totalQuestions:", D, "hasNextQuestion:", ee);
|
|
8024
|
-
const Q =
|
|
8031
|
+
const Q = v.type === "code_test" ? `Great job! Your code passed all the tests! ${v.explanation || ""}` : `Excellent! That's correct! ${v.explanation || ""}`, q = H.current || { lipsyncLang: "en" };
|
|
8025
8032
|
u.current.speakText(Q, {
|
|
8026
8033
|
lipsyncLang: q.lipsyncLang,
|
|
8027
8034
|
onSpeechEnd: () => {
|
|
@@ -8045,9 +8052,9 @@ const ft = Me(({
|
|
|
8045
8052
|
u.current.setBodyMovement("idle");
|
|
8046
8053
|
}
|
|
8047
8054
|
u.current.setBodyMovement("gesturing");
|
|
8048
|
-
const D =
|
|
8055
|
+
const D = R()?.questions?.length || 0, ee = a.current.currentQuestionIndex >= D - 1, Q = a.current.currentQuestionIndex < D - 1;
|
|
8049
8056
|
console.log("[CurriculumLearning] Answer feedback (incorrect) - questionIndex:", a.current.currentQuestionIndex, "totalQuestions:", D, "hasNextQuestion:", Q);
|
|
8050
|
-
const q =
|
|
8057
|
+
const q = v.type === "code_test" ? `Your code didn't pass all the tests. ${v.explanation || "Try again!"}` : `Not quite right, but don't worry! ${v.explanation || ""}${ee ? "" : " Let's move on to the next question."}`, Ae = H.current || { lipsyncLang: "en" };
|
|
8051
8058
|
u.current.speakText(q, {
|
|
8052
8059
|
lipsyncLang: Ae.lipsyncLang,
|
|
8053
8060
|
onSpeechEnd: () => {
|
|
@@ -8065,30 +8072,30 @@ const ft = Me(({
|
|
|
8065
8072
|
});
|
|
8066
8073
|
}
|
|
8067
8074
|
else {
|
|
8068
|
-
const D =
|
|
8075
|
+
const D = R()?.questions?.length || 0;
|
|
8069
8076
|
d.current.onCustomAction({
|
|
8070
8077
|
type: "answerFeedbackComplete",
|
|
8071
8078
|
moduleIndex: a.current.currentModuleIndex,
|
|
8072
8079
|
lessonIndex: a.current.currentLessonIndex,
|
|
8073
8080
|
questionIndex: a.current.currentQuestionIndex,
|
|
8074
|
-
isCorrect:
|
|
8081
|
+
isCorrect: F,
|
|
8075
8082
|
hasNextQuestion: a.current.currentQuestionIndex < D - 1,
|
|
8076
8083
|
score: a.current.score,
|
|
8077
8084
|
totalQuestions: a.current.totalQuestions,
|
|
8078
8085
|
avatarNotReady: !0
|
|
8079
8086
|
});
|
|
8080
8087
|
}
|
|
8081
|
-
}, [e.correct, e.incorrect, L,
|
|
8082
|
-
const
|
|
8088
|
+
}, [e.correct, e.incorrect, L, R, I]), le = O((b) => {
|
|
8089
|
+
const v = L();
|
|
8083
8090
|
if (!b || typeof b != "object") {
|
|
8084
8091
|
console.error("Invalid code test result format. Expected object with {passed: boolean, ...}");
|
|
8085
8092
|
return;
|
|
8086
8093
|
}
|
|
8087
|
-
if (
|
|
8094
|
+
if (v?.type !== "code_test") {
|
|
8088
8095
|
console.warn("Current question is not a code test. Use handleAnswerSelect for other question types.");
|
|
8089
8096
|
return;
|
|
8090
8097
|
}
|
|
8091
|
-
const
|
|
8098
|
+
const F = {
|
|
8092
8099
|
passed: b.passed === !0,
|
|
8093
8100
|
results: b.results || [],
|
|
8094
8101
|
output: b.output || "",
|
|
@@ -8103,10 +8110,10 @@ const ft = Me(({
|
|
|
8103
8110
|
moduleIndex: a.current.currentModuleIndex,
|
|
8104
8111
|
lessonIndex: a.current.currentLessonIndex,
|
|
8105
8112
|
questionIndex: a.current.currentQuestionIndex,
|
|
8106
|
-
testResult:
|
|
8107
|
-
question:
|
|
8108
|
-
}), p.current && p.current(
|
|
8109
|
-
}, [L, I]), ge =
|
|
8113
|
+
testResult: F,
|
|
8114
|
+
question: v
|
|
8115
|
+
}), p.current && p.current(F);
|
|
8116
|
+
}, [L, I]), ge = O(() => {
|
|
8110
8117
|
if (a.current.currentQuestionIndex > 0) {
|
|
8111
8118
|
a.current.currentQuestionIndex -= 1;
|
|
8112
8119
|
const b = L();
|
|
@@ -8119,28 +8126,28 @@ const ft = Me(({
|
|
|
8119
8126
|
question: b,
|
|
8120
8127
|
score: a.current.score
|
|
8121
8128
|
});
|
|
8122
|
-
const
|
|
8129
|
+
const v = () => {
|
|
8123
8130
|
if (!u.current || !b) return;
|
|
8124
8131
|
u.current.setMood("happy"), u.current.setBodyMovement("idle");
|
|
8125
|
-
const
|
|
8132
|
+
const F = H.current || { lipsyncLang: "en" };
|
|
8126
8133
|
b.type === "code_test" ? u.current.speakText(`Let's go back to this coding challenge: ${b.question}`, {
|
|
8127
|
-
lipsyncLang:
|
|
8134
|
+
lipsyncLang: F.lipsyncLang
|
|
8128
8135
|
}) : u.current.speakText(`Going back to: ${b.question}`, {
|
|
8129
|
-
lipsyncLang:
|
|
8136
|
+
lipsyncLang: F.lipsyncLang
|
|
8130
8137
|
});
|
|
8131
8138
|
};
|
|
8132
8139
|
if (u.current && u.current.isReady && b)
|
|
8133
|
-
|
|
8140
|
+
v();
|
|
8134
8141
|
else if (b) {
|
|
8135
|
-
const
|
|
8136
|
-
u.current && u.current.isReady && (clearInterval(
|
|
8142
|
+
const F = setInterval(() => {
|
|
8143
|
+
u.current && u.current.isReady && (clearInterval(F), v());
|
|
8137
8144
|
}, 100);
|
|
8138
8145
|
setTimeout(() => {
|
|
8139
|
-
clearInterval(
|
|
8146
|
+
clearInterval(F);
|
|
8140
8147
|
}, 5e3);
|
|
8141
8148
|
}
|
|
8142
8149
|
}
|
|
8143
|
-
}, [L]), de =
|
|
8150
|
+
}, [L]), de = O(() => {
|
|
8144
8151
|
const b = B.current || { modules: [] };
|
|
8145
8152
|
if (b.modules[a.current.currentModuleIndex], a.current.currentLessonIndex > 0)
|
|
8146
8153
|
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({
|
|
@@ -8150,38 +8157,38 @@ const ft = Me(({
|
|
|
8150
8157
|
}), d.current.onLessonStart({
|
|
8151
8158
|
moduleIndex: a.current.currentModuleIndex,
|
|
8152
8159
|
lessonIndex: a.current.currentLessonIndex,
|
|
8153
|
-
lesson:
|
|
8160
|
+
lesson: R()
|
|
8154
8161
|
}), u.current && (u.current.setMood("happy"), u.current.setBodyMovement("idle"));
|
|
8155
8162
|
else if (a.current.currentModuleIndex > 0) {
|
|
8156
|
-
const
|
|
8157
|
-
a.current.currentModuleIndex -= 1, a.current.currentLessonIndex = (
|
|
8163
|
+
const P = b.modules[a.current.currentModuleIndex - 1];
|
|
8164
|
+
a.current.currentModuleIndex -= 1, a.current.currentLessonIndex = (P?.lessons?.length || 1) - 1, a.current.currentQuestionIndex = 0, a.current.lessonCompleted = !1, a.current.isQuestionMode = !1, a.current.isTeaching = !1, a.current.score = 0, a.current.totalQuestions = 0, d.current.onCustomAction({
|
|
8158
8165
|
type: "lessonStart",
|
|
8159
8166
|
moduleIndex: a.current.currentModuleIndex,
|
|
8160
8167
|
lessonIndex: a.current.currentLessonIndex
|
|
8161
8168
|
}), d.current.onLessonStart({
|
|
8162
8169
|
moduleIndex: a.current.currentModuleIndex,
|
|
8163
8170
|
lessonIndex: a.current.currentLessonIndex,
|
|
8164
|
-
lesson:
|
|
8171
|
+
lesson: R()
|
|
8165
8172
|
}), u.current && (u.current.setMood("happy"), u.current.setBodyMovement("idle"));
|
|
8166
8173
|
}
|
|
8167
|
-
}, [
|
|
8174
|
+
}, [R]), $ = O(() => {
|
|
8168
8175
|
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;
|
|
8169
|
-
}, []), be =
|
|
8176
|
+
}, []), be = O((b) => {
|
|
8170
8177
|
console.log("Avatar is ready!", b);
|
|
8171
|
-
const
|
|
8172
|
-
h &&
|
|
8178
|
+
const v = R(), F = v?.avatar_script || v?.body;
|
|
8179
|
+
h && F && setTimeout(() => {
|
|
8173
8180
|
c.current && c.current();
|
|
8174
8181
|
}, 10);
|
|
8175
|
-
}, [h,
|
|
8182
|
+
}, [h, R]);
|
|
8176
8183
|
Xe(() => {
|
|
8177
|
-
c.current = Z, g.current = X, x.current = z, f.current =
|
|
8184
|
+
c.current = Z, g.current = X, x.current = z, f.current = E, k.current = Y, N.current = S, p.current = oe;
|
|
8178
8185
|
}), Fe(r, () => ({
|
|
8179
8186
|
// Curriculum control methods
|
|
8180
8187
|
startTeaching: Z,
|
|
8181
8188
|
startQuestions: S,
|
|
8182
|
-
handleAnswerSelect:
|
|
8189
|
+
handleAnswerSelect: oe,
|
|
8183
8190
|
handleCodeTestResult: le,
|
|
8184
|
-
nextQuestion:
|
|
8191
|
+
nextQuestion: E,
|
|
8185
8192
|
previousQuestion: ge,
|
|
8186
8193
|
nextLesson: X,
|
|
8187
8194
|
previousLesson: de,
|
|
@@ -8190,26 +8197,26 @@ const ft = Me(({
|
|
|
8190
8197
|
resetCurriculum: $,
|
|
8191
8198
|
getState: () => ({ ...a.current }),
|
|
8192
8199
|
getCurrentQuestion: () => L(),
|
|
8193
|
-
getCurrentLesson: () =>
|
|
8200
|
+
getCurrentLesson: () => R(),
|
|
8194
8201
|
// Direct access to avatar ref (always returns current value)
|
|
8195
8202
|
getAvatarRef: () => u.current,
|
|
8196
8203
|
// Convenience methods that delegate to avatar (always check current ref)
|
|
8197
|
-
speakText: async (b,
|
|
8204
|
+
speakText: async (b, v = {}) => {
|
|
8198
8205
|
await u.current?.resumeAudioContext?.();
|
|
8199
|
-
const
|
|
8200
|
-
u.current?.speakText(b, { ...
|
|
8206
|
+
const F = H.current || { lipsyncLang: "en" };
|
|
8207
|
+
u.current?.speakText(b, { ...v, lipsyncLang: v.lipsyncLang || F.lipsyncLang });
|
|
8201
8208
|
},
|
|
8202
8209
|
resumeAudioContext: async () => {
|
|
8203
8210
|
if (u.current?.resumeAudioContext)
|
|
8204
8211
|
return await u.current.resumeAudioContext();
|
|
8205
8212
|
const b = u.current?.talkingHead;
|
|
8206
8213
|
if (b?.audioCtx) {
|
|
8207
|
-
const
|
|
8208
|
-
if (
|
|
8214
|
+
const v = b.audioCtx;
|
|
8215
|
+
if (v.state === "suspended" || v.state === "interrupted")
|
|
8209
8216
|
try {
|
|
8210
|
-
await
|
|
8211
|
-
} catch (
|
|
8212
|
-
console.warn("Failed to resume audio context:",
|
|
8217
|
+
await v.resume(), console.log("Audio context resumed via talkingHead");
|
|
8218
|
+
} catch (F) {
|
|
8219
|
+
console.warn("Failed to resume audio context:", F);
|
|
8213
8220
|
}
|
|
8214
8221
|
} else
|
|
8215
8222
|
console.warn("Audio context not available yet");
|
|
@@ -8219,7 +8226,7 @@ const ft = Me(({
|
|
|
8219
8226
|
resumeSpeaking: async () => await u.current?.resumeSpeaking(),
|
|
8220
8227
|
isPaused: () => u.current && typeof u.current.isPaused < "u" ? u.current.isPaused : !1,
|
|
8221
8228
|
setMood: (b) => u.current?.setMood(b),
|
|
8222
|
-
playAnimation: (b,
|
|
8229
|
+
playAnimation: (b, v) => u.current?.playAnimation(b, v),
|
|
8223
8230
|
setBodyMovement: (b) => u.current?.setBodyMovement(b),
|
|
8224
8231
|
setMovementIntensity: (b) => u.current?.setMovementIntensity(b),
|
|
8225
8232
|
playRandomDance: () => u.current?.playRandomDance(),
|
|
@@ -8230,10 +8237,10 @@ const ft = Me(({
|
|
|
8230
8237
|
lockAvatarPosition: () => u.current?.lockAvatarPosition(),
|
|
8231
8238
|
unlockAvatarPosition: () => u.current?.unlockAvatarPosition(),
|
|
8232
8239
|
// Custom action trigger
|
|
8233
|
-
triggerCustomAction: (b,
|
|
8240
|
+
triggerCustomAction: (b, v) => {
|
|
8234
8241
|
d.current.onCustomAction({
|
|
8235
8242
|
type: b,
|
|
8236
|
-
...
|
|
8243
|
+
...v,
|
|
8237
8244
|
state: { ...a.current }
|
|
8238
8245
|
});
|
|
8239
8246
|
},
|
|
@@ -8241,7 +8248,7 @@ const ft = Me(({
|
|
|
8241
8248
|
handleResize: () => u.current?.handleResize(),
|
|
8242
8249
|
// Avatar readiness check (always returns current value)
|
|
8243
8250
|
isAvatarReady: () => u.current?.isReady || !1
|
|
8244
|
-
}), [Z, S,
|
|
8251
|
+
}), [Z, S, oe, le, E, X, z, Y, $, L, R]);
|
|
8245
8252
|
const j = H.current || {
|
|
8246
8253
|
avatarUrl: "/avatars/brunette.glb",
|
|
8247
8254
|
avatarBody: "F",
|