@sage-rsc/talking-head-react 1.0.63 → 1.0.64
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 +144 -138
- package/package.json +1 -1
- package/src/components/TalkingHeadAvatar.jsx +52 -46
package/dist/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { jsxs as Ee, jsx as ue } from "react/jsx-runtime";
|
|
2
|
-
import { forwardRef as Ie, useRef as G, useState as
|
|
2
|
+
import { forwardRef as Ie, useRef as G, useState as me, useEffect as pe, useCallback as E, useImperativeHandle as Le, useLayoutEffect as We } from "react";
|
|
3
3
|
import * as f from "three";
|
|
4
4
|
import { OrbitControls as Ve } from "three/addons/controls/OrbitControls.js";
|
|
5
5
|
import { GLTFLoader as Ge } from "three/addons/loaders/GLTFLoader.js";
|
|
@@ -7,7 +7,7 @@ import { DRACOLoader as Ze } from "three/addons/loaders/DRACOLoader.js";
|
|
|
7
7
|
import { FBXLoader as ze } from "three/addons/loaders/FBXLoader.js";
|
|
8
8
|
import { RoomEnvironment as Xe } from "three/addons/environments/RoomEnvironment.js";
|
|
9
9
|
import Ye from "three/addons/libs/stats.module.js";
|
|
10
|
-
let m,
|
|
10
|
+
let m, K, $;
|
|
11
11
|
const A = [0, 0, 0, 0], k = new f.Vector3(), be = new f.Vector3(), Q = new f.Vector3(), ve = new f.Vector3();
|
|
12
12
|
new f.Plane();
|
|
13
13
|
new f.Ray();
|
|
@@ -371,7 +371,7 @@ class _e {
|
|
|
371
371
|
);
|
|
372
372
|
else if (o.boneParent.quaternion.copy(o.qBasis), o.pivot && this.opt.isPivots && (o.boneParent.updateWorldMatrix(!1, !1), o.boneParent.matrixWorld.decompose(k, q, Q), k.copy(Re).applyQuaternion(q).setY(0).normalize(), q.premultiply(Ce.setFromUnitVectors(Re, k).invert()).normalize(), o.boneParent.quaternion.multiply(q.invert()), o.boneParent.quaternion.multiply(o.qWorldInverseYaw)), o.isZ && (m = Math.atan(A[0] / o.l), q.setFromAxisAngle(qe, -m), o.boneParent.quaternion.multiply(q)), o.isY && (m = o.l / 3, m = m * Math.tanh(A[1] / m), o.bone.position.setLength(o.l + m)), o.isX && (m = Math.atan(A[2] / o.l), q.setFromAxisAngle(je, -m), o.boneParent.quaternion.multiply(q)), o.isT && (m = 1.5 * Math.tanh(A[3] * 1.5), q.setFromAxisAngle(Qe, -m), o.boneParent.quaternion.multiply(q)), 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], Q.set(0, 0, 0), m.deltaLocal && (Q.x += m.deltaLocal[0], Q.y += m.deltaLocal[1], Q.z += m.deltaLocal[2]), Q.applyMatrix4(m.bone.matrixWorld), ae.copy(o.boneParent.matrixWorld).invert(), Q.applyMatrix4(ae), k.copy(o.bone.position), !(k.distanceToSquared(Q) >= m.radiusSq) && ($ = k.length(),
|
|
374
|
+
m = o.excludes[n], Q.set(0, 0, 0), m.deltaLocal && (Q.x += m.deltaLocal[0], Q.y += m.deltaLocal[1], Q.z += m.deltaLocal[2]), Q.applyMatrix4(m.bone.matrixWorld), ae.copy(o.boneParent.matrixWorld).invert(), Q.applyMatrix4(ae), k.copy(o.bone.position), !(k.distanceToSquared(Q) >= m.radiusSq) && ($ = k.length(), K = Q.length(), !(K > m.radius + $) && (K < Math.abs(m.radius - $) || (K = (K * K + $ * $ - m.radiusSq) / (2 * K), Q.normalize(), ve.copy(Q).multiplyScalar(K), K = Math.sqrt($ * $ - K * K), k.subVectors(k, ve).projectOnPlane(Q).normalize().multiplyScalar(K), be.subVectors(o.vBasis, ve).projectOnPlane(Q).normalize(), $ = be.dot(k), $ < 0 && ($ = Math.sqrt(K * K - $ * $), be.multiplyScalar($), k.add(be)), k.add(ve).normalize(), Q.copy(o.bone.position).normalize(), q.setFromUnitVectors(Q, k), o.boneParent.quaternion.premultiply(q), o.boneParent.updateWorldMatrix(!1, !0))));
|
|
375
375
|
}
|
|
376
376
|
this.helpers.isActive && this.updateHelpers();
|
|
377
377
|
}
|
|
@@ -2629,7 +2629,7 @@ const rt = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
|
|
|
2629
2629
|
fr: it,
|
|
2630
2630
|
fi: st,
|
|
2631
2631
|
lt: rt
|
|
2632
|
-
},
|
|
2632
|
+
}, U = new f.Quaternion(), F = new f.Euler(), le = new f.Vector3(), he = new f.Vector3(), Te = new f.Box3();
|
|
2633
2633
|
new f.Matrix4();
|
|
2634
2634
|
new f.Matrix4();
|
|
2635
2635
|
new f.Vector3();
|
|
@@ -4376,7 +4376,7 @@ class Fe {
|
|
|
4376
4376
|
if (e.x === 0 && e.y === 0 && e.z === 0) continue;
|
|
4377
4377
|
F.set(e.x, e.y, e.z);
|
|
4378
4378
|
const n = this.poseAvatar.props[t];
|
|
4379
|
-
n.isQuaternion ? (
|
|
4379
|
+
n.isQuaternion ? (U.setFromEuler(F), n.multiply(U)) : n.isVector3 && n.add(F);
|
|
4380
4380
|
}
|
|
4381
4381
|
}
|
|
4382
4382
|
/**
|
|
@@ -5180,7 +5180,7 @@ class Fe {
|
|
|
5180
5180
|
eyeLookOutRight: [null, 0],
|
|
5181
5181
|
eyeContact: [0]
|
|
5182
5182
|
}
|
|
5183
|
-
})))), e > 2 * this.animFrameDur && (e = 2 * this.animFrameDur), (this.viewName !== "full" || this.isAvatarOnly) && (n = this.mtRandomized[Math.floor(Math.random() * this.mtRandomized.length)], i = this.mtAvatar[n], i.needsUpdate || Object.assign(i, { base: (this.mood.baseline[n] || 0) + (1 + l / 255) * Math.random() / 5, needsUpdate: !0 })), this.updatePoseBase(this.animClock), this.mixer && this.mixer.update(e / 1e3 * this.mixer.timeScale), this.updatePoseDelta(), (this.isSpeaking || this.isListening) && u ? l > this.volumeMax ? (this.volumeHeadBase = 0.05, Math.random() > 0.6 && (this.volumeHeadTarget = -0.05 - Math.random() / 15), this.volumeMax = l) : (this.volumeMax *= 0.92, this.volumeHeadTarget = this.volumeHeadBase - 0.9 * (this.volumeHeadBase - this.volumeHeadTarget)) : (this.volumeHeadTarget = 0, this.volumeMax = 0), n = this.volumeHeadTarget - this.volumeHeadCurrent, i = Math.abs(n), i > 1e-4 && (o = i * (this.volumeHeadEasing(Math.min(1, this.volumeHeadVelocity * e / 1e3 / i) / 2 + 0.5) - 0.5), this.volumeHeadCurrent += Math.sign(n) * Math.min(i, o)), Math.abs(this.volumeHeadCurrent) > 1e-4 && (
|
|
5183
|
+
})))), e > 2 * this.animFrameDur && (e = 2 * this.animFrameDur), (this.viewName !== "full" || this.isAvatarOnly) && (n = this.mtRandomized[Math.floor(Math.random() * this.mtRandomized.length)], i = this.mtAvatar[n], i.needsUpdate || Object.assign(i, { base: (this.mood.baseline[n] || 0) + (1 + l / 255) * Math.random() / 5, needsUpdate: !0 })), this.updatePoseBase(this.animClock), this.mixer && this.mixer.update(e / 1e3 * this.mixer.timeScale), this.updatePoseDelta(), (this.isSpeaking || this.isListening) && u ? l > this.volumeMax ? (this.volumeHeadBase = 0.05, Math.random() > 0.6 && (this.volumeHeadTarget = -0.05 - Math.random() / 15), this.volumeMax = l) : (this.volumeMax *= 0.92, this.volumeHeadTarget = this.volumeHeadBase - 0.9 * (this.volumeHeadBase - this.volumeHeadTarget)) : (this.volumeHeadTarget = 0, this.volumeMax = 0), n = this.volumeHeadTarget - this.volumeHeadCurrent, i = Math.abs(n), i > 1e-4 && (o = i * (this.volumeHeadEasing(Math.min(1, this.volumeHeadVelocity * e / 1e3 / i) / 2 + 0.5) - 0.5), this.volumeHeadCurrent += Math.sign(n) * Math.min(i, o)), Math.abs(this.volumeHeadCurrent) > 1e-4 && (U.setFromAxisAngle(ht, this.volumeHeadCurrent), this.objectNeck.quaternion.multiply(U)), Te.setFromObject(this.armature), this.objectLeftToeBase.getWorldPosition(le), le.sub(this.armature.position), this.objectRightToeBase.getWorldPosition(he), he.sub(this.armature.position), this.objectHips.position.y -= Te.min.y / 2, this.objectHips.position.x -= (le.x + he.x) / 4, this.objectHips.position.z -= (le.z + he.z) / 2, this.dynamicbones.update(e), this.fbxAnimationLoader && this.fbxAnimationLoader.update(), this.opt.update && this.opt.update(e), this.updateMorphTargets(e), this.isAvatarOnly)
|
|
5184
5184
|
this.stats && this.stats.end();
|
|
5185
5185
|
else {
|
|
5186
5186
|
if (this.cameraClock !== null && this.cameraClock < 1e3) {
|
|
@@ -5267,12 +5267,12 @@ class Fe {
|
|
|
5267
5267
|
}), h = ""), r.length)) {
|
|
5268
5268
|
const R = this.lipsyncWordsToVisemes(r, a);
|
|
5269
5269
|
if (R && R.visemes && R.visemes.length) {
|
|
5270
|
-
const
|
|
5270
|
+
const T = R.times[R.visemes.length - 1] + R.durations[R.visemes.length - 1];
|
|
5271
5271
|
for (let P = 0; P < R.visemes.length; P++)
|
|
5272
5272
|
g.push({
|
|
5273
5273
|
mark: c,
|
|
5274
5274
|
template: { name: "viseme" },
|
|
5275
|
-
ts: [(R.times[P] - 0.6) /
|
|
5275
|
+
ts: [(R.times[P] - 0.6) / T, (R.times[P] + 0.5) / T, (R.times[P] + R.durations[P] + 0.5) / T],
|
|
5276
5276
|
vs: {
|
|
5277
5277
|
["viseme_" + R.visemes[P]]: [null, R.visemes[P] === "PP" || R.visemes[P] === "FF" ? 0.9 : 0.6, 0]
|
|
5278
5278
|
}
|
|
@@ -5486,7 +5486,7 @@ class Fe {
|
|
|
5486
5486
|
if (x && x.visemes && x.visemes.length > 0) {
|
|
5487
5487
|
const p = x.times[x.visemes.length - 1] + x.durations[x.visemes.length - 1];
|
|
5488
5488
|
for (let H = 0; H < x.visemes.length; H++) {
|
|
5489
|
-
const z = x.visemes[H], R = x.times[H] / p,
|
|
5489
|
+
const z = x.visemes[H], R = x.times[H] / p, T = x.durations[H] / p, P = R * c, ee = T * c;
|
|
5490
5490
|
I.push({
|
|
5491
5491
|
template: { name: "viseme" },
|
|
5492
5492
|
ts: [P - Math.min(60, 2 * ee / 3), P + Math.min(25, ee / 2), P + ee + Math.min(60, ee / 2)],
|
|
@@ -6146,10 +6146,10 @@ class Fe {
|
|
|
6146
6146
|
this.lookAt(null, null, t);
|
|
6147
6147
|
return;
|
|
6148
6148
|
}
|
|
6149
|
-
this.objectLeftEye.updateMatrixWorld(!0), this.objectRightEye.updateMatrixWorld(!0), le.setFromMatrixPosition(this.objectLeftEye.matrixWorld), he.setFromMatrixPosition(this.objectRightEye.matrixWorld), le.add(he).divideScalar(2),
|
|
6149
|
+
this.objectLeftEye.updateMatrixWorld(!0), this.objectRightEye.updateMatrixWorld(!0), le.setFromMatrixPosition(this.objectLeftEye.matrixWorld), he.setFromMatrixPosition(this.objectRightEye.matrixWorld), le.add(he).divideScalar(2), U.copy(this.armature.quaternion), U.multiply(this.poseTarget.props["Hips.quaternion"]), U.multiply(this.poseTarget.props["Spine.quaternion"]), U.multiply(this.poseTarget.props["Spine1.quaternion"]), U.multiply(this.poseTarget.props["Spine2.quaternion"]), U.multiply(this.poseTarget.props["Neck.quaternion"]), U.multiply(this.poseTarget.props["Head.quaternion"]);
|
|
6150
6150
|
const n = new f.Vector3().subVectors(e, le).normalize(), i = Math.atan2(n.x, n.z), s = Math.asin(-n.y);
|
|
6151
6151
|
F.set(s, i, 0, "YXZ");
|
|
6152
|
-
const l = new f.Quaternion().setFromEuler(F), u = new f.Quaternion().copy(l).multiply(
|
|
6152
|
+
const l = new f.Quaternion().setFromEuler(F), u = new f.Quaternion().copy(l).multiply(U.clone().invert());
|
|
6153
6153
|
F.setFromQuaternion(u, "YXZ");
|
|
6154
6154
|
let a = F.x / (40 / 24) + 0.2, h = F.y / (9 / 4), r = Math.min(0.6, Math.max(-0.3, a)), c = Math.min(0.8, Math.max(-0.8, h)), d = (Math.random() - 0.5) / 4, g = (Math.random() - 0.5) / 4;
|
|
6155
6155
|
if (t) {
|
|
@@ -6186,7 +6186,7 @@ class Fe {
|
|
|
6186
6186
|
const s = new f.Vector3().setFromMatrixPosition(this.objectLeftEye.matrixWorld), o = new f.Vector3().setFromMatrixPosition(this.objectRightEye.matrixWorld), l = new f.Vector3().addVectors(s, o).divideScalar(2);
|
|
6187
6187
|
l.project(this.camera);
|
|
6188
6188
|
let u = (l.x + 1) / 2 * i.width + i.left, a = -(l.y - 1) / 2 * i.height + i.top;
|
|
6189
|
-
t === null && (t = u), e === null && (e = a),
|
|
6189
|
+
t === null && (t = u), e === null && (e = a), U.copy(this.armature.quaternion), U.multiply(this.poseTarget.props["Hips.quaternion"]), U.multiply(this.poseTarget.props["Spine.quaternion"]), U.multiply(this.poseTarget.props["Spine1.quaternion"]), U.multiply(this.poseTarget.props["Spine2.quaternion"]), U.multiply(this.poseTarget.props["Neck.quaternion"]), U.multiply(this.poseTarget.props["Head.quaternion"]), F.setFromQuaternion(U);
|
|
6190
6190
|
let h = F.x / (40 / 24), r = F.y / (9 / 4), c = Math.min(0.4, Math.max(-0.4, this.camera.rotation.x)), d = Math.min(0.4, Math.max(-0.4, this.camera.rotation.y)), g = Math.max(window.innerWidth - u, u), y = Math.max(window.innerHeight - a, a), x = this.convertRange(e, [a - y, a + y], [-0.3, 0.6]) - h + c, I = this.convertRange(t, [u - g, u + g], [-0.8, 0.8]) - r + d;
|
|
6191
6191
|
x = Math.min(0.6, Math.max(-0.3, x)), I = Math.min(0.8, Math.max(-0.8, I));
|
|
6192
6192
|
let D = (Math.random() - 0.5) / 4, p = (Math.random() - 0.5) / 4;
|
|
@@ -6582,7 +6582,7 @@ class Fe {
|
|
|
6582
6582
|
const z = y[p].bone;
|
|
6583
6583
|
z.matrixWorld.decompose(u, a, h), a.invert(), o.setFromMatrixPosition(g.matrixWorld), l.subVectors(o, u), l.applyQuaternion(a), l.normalize(), s.subVectors(e, u), s.applyQuaternion(a), s.normalize();
|
|
6584
6584
|
let R = s.dot(l);
|
|
6585
|
-
R > 1 ? R = 1 : R < -1 && (R = -1), R = Math.acos(R), !(R < 1e-5) && (y[p].minAngle !== void 0 && R < y[p].minAngle && (R = y[p].minAngle), y[p].maxAngle !== void 0 && R > y[p].maxAngle && (R = y[p].maxAngle), r.crossVectors(l, s), r.normalize(),
|
|
6585
|
+
R > 1 ? R = 1 : R < -1 && (R = -1), R = Math.acos(R), !(R < 1e-5) && (y[p].minAngle !== void 0 && R < y[p].minAngle && (R = y[p].minAngle), y[p].maxAngle !== void 0 && R > y[p].maxAngle && (R = y[p].maxAngle), r.crossVectors(l, s), r.normalize(), U.setFromAxisAngle(r, R), z.quaternion.multiply(U), z.rotation.setFromVector3(c.setFromEuler(z.rotation).clamp(new f.Vector3(
|
|
6586
6586
|
y[p].minx !== void 0 ? y[p].minx : -1 / 0,
|
|
6587
6587
|
y[p].miny !== void 0 ? y[p].miny : -1 / 0,
|
|
6588
6588
|
y[p].minz !== void 0 ? y[p].minz : -1 / 0
|
|
@@ -6685,10 +6685,10 @@ const Pe = Ie(({
|
|
|
6685
6685
|
style: y = {},
|
|
6686
6686
|
animations: x = {}
|
|
6687
6687
|
}, I) => {
|
|
6688
|
-
const D = G(null), p = G(null), H = G(a), z = G(null), R = G(null),
|
|
6689
|
-
|
|
6690
|
-
|
|
6691
|
-
}, [j]),
|
|
6688
|
+
const D = G(null), p = G(null), H = G(a), z = G(null), R = G(null), T = G(!1), P = G({ remainingText: null, originalText: null, options: null }), [ee, re] = me(!0), [S, N] = me(null), [Z, X] = me(!1), [j, _] = me(!1);
|
|
6689
|
+
pe(() => {
|
|
6690
|
+
T.current = j;
|
|
6691
|
+
}, [j]), pe(() => {
|
|
6692
6692
|
H.current = a;
|
|
6693
6693
|
}, [a]);
|
|
6694
6694
|
const te = Ae(), ce = i || te.service;
|
|
@@ -6715,7 +6715,7 @@ const Pe = Ie(({
|
|
|
6715
6715
|
// Override API key if provided via props
|
|
6716
6716
|
apiKey: o !== null ? o : te.apiKey
|
|
6717
6717
|
};
|
|
6718
|
-
const
|
|
6718
|
+
const de = {
|
|
6719
6719
|
url: O,
|
|
6720
6720
|
body: t,
|
|
6721
6721
|
avatarMood: e,
|
|
@@ -6731,24 +6731,24 @@ const Pe = Ie(({
|
|
|
6731
6731
|
ttsService: ce,
|
|
6732
6732
|
lipsyncModules: ["en"],
|
|
6733
6733
|
cameraView: h
|
|
6734
|
-
}, b =
|
|
6734
|
+
}, b = E(async () => {
|
|
6735
6735
|
if (!(!D.current || p.current))
|
|
6736
6736
|
try {
|
|
6737
|
-
if (re(!0), N(null), p.current = new Fe(D.current, J), 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(
|
|
6738
|
-
if (
|
|
6739
|
-
const
|
|
6740
|
-
c(
|
|
6737
|
+
if (re(!0), N(null), p.current = new Fe(D.current, J), 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(de, (V) => {
|
|
6738
|
+
if (V.lengthComputable) {
|
|
6739
|
+
const M = Math.min(100, Math.round(V.loaded / V.total * 100));
|
|
6740
|
+
c(M);
|
|
6741
6741
|
}
|
|
6742
|
-
}), await new Promise((
|
|
6743
|
-
const
|
|
6744
|
-
p.current.lipsync && Object.keys(p.current.lipsync).length > 0 ?
|
|
6742
|
+
}), await new Promise((V) => {
|
|
6743
|
+
const M = () => {
|
|
6744
|
+
p.current.lipsync && Object.keys(p.current.lipsync).length > 0 ? V() : setTimeout(M, 100);
|
|
6745
6745
|
};
|
|
6746
|
-
|
|
6746
|
+
M();
|
|
6747
6747
|
}), p.current && p.current.setShowFullAvatar)
|
|
6748
6748
|
try {
|
|
6749
6749
|
p.current.setShowFullAvatar(a);
|
|
6750
|
-
} catch (
|
|
6751
|
-
console.warn("Error setting full body mode on initialization:",
|
|
6750
|
+
} catch (V) {
|
|
6751
|
+
console.warn("Error setting full body mode on initialization:", V);
|
|
6752
6752
|
}
|
|
6753
6753
|
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()), re(!1), X(!0), r(p.current);
|
|
6754
6754
|
const B = () => {
|
|
@@ -6761,12 +6761,12 @@ const Pe = Ie(({
|
|
|
6761
6761
|
console.error("Error initializing TalkingHead:", L), N(L.message || "Failed to initialize avatar"), re(!1), d(L);
|
|
6762
6762
|
}
|
|
6763
6763
|
}, [O, t, e, n, i, s, o, a, l, u, h]);
|
|
6764
|
-
|
|
6764
|
+
pe(() => (b(), () => {
|
|
6765
6765
|
p.current && (p.current.stop(), p.current.dispose(), p.current = null);
|
|
6766
|
-
}), [b]),
|
|
6766
|
+
}), [b]), pe(() => {
|
|
6767
6767
|
if (!D.current || !p.current) return;
|
|
6768
|
-
const L = new ResizeObserver((
|
|
6769
|
-
for (const
|
|
6768
|
+
const L = new ResizeObserver((V) => {
|
|
6769
|
+
for (const M of V)
|
|
6770
6770
|
p.current && p.current.onResize && p.current.onResize();
|
|
6771
6771
|
});
|
|
6772
6772
|
L.observe(D.current);
|
|
@@ -6777,31 +6777,31 @@ const Pe = Ie(({
|
|
|
6777
6777
|
L.disconnect(), window.removeEventListener("resize", B);
|
|
6778
6778
|
};
|
|
6779
6779
|
}, [Z]);
|
|
6780
|
-
const v =
|
|
6780
|
+
const v = E(async () => {
|
|
6781
6781
|
if (p.current && p.current.audioCtx)
|
|
6782
6782
|
try {
|
|
6783
6783
|
(p.current.audioCtx.state === "suspended" || p.current.audioCtx.state === "interrupted") && (await p.current.audioCtx.resume(), console.log("Audio context resumed"));
|
|
6784
6784
|
} catch (L) {
|
|
6785
6785
|
console.warn("Failed to resume audio context:", L);
|
|
6786
6786
|
}
|
|
6787
|
-
}, []), w =
|
|
6787
|
+
}, []), w = E(async (L, B = {}) => {
|
|
6788
6788
|
if (p.current && Z)
|
|
6789
6789
|
try {
|
|
6790
|
-
R.current && (clearInterval(R.current), R.current = null), z.current = { text: L, options: B }, P.current = { remainingText: null, originalText: null, options: null },
|
|
6791
|
-
const
|
|
6790
|
+
R.current && (clearInterval(R.current), R.current = null), z.current = { text: L, options: B }, P.current = { remainingText: null, originalText: null, options: null }, _(!1), T.current = !1, await v();
|
|
6791
|
+
const V = {
|
|
6792
6792
|
...B,
|
|
6793
|
-
lipsyncLang: B.lipsyncLang ||
|
|
6793
|
+
lipsyncLang: B.lipsyncLang || de.lipsyncLang || "en"
|
|
6794
6794
|
};
|
|
6795
6795
|
if (B.onSpeechEnd && p.current) {
|
|
6796
|
-
const
|
|
6796
|
+
const M = p.current;
|
|
6797
6797
|
let Y = null, ge = 0;
|
|
6798
6798
|
const ke = 1200;
|
|
6799
6799
|
let xe = !1;
|
|
6800
6800
|
Y = setInterval(() => {
|
|
6801
|
-
if (ge++,
|
|
6801
|
+
if (ge++, T.current)
|
|
6802
6802
|
return;
|
|
6803
6803
|
if (ge > ke) {
|
|
6804
|
-
if (Y && (clearInterval(Y), Y = null, R.current = null), !xe && !
|
|
6804
|
+
if (Y && (clearInterval(Y), Y = null, R.current = null), !xe && !T.current) {
|
|
6805
6805
|
xe = !0;
|
|
6806
6806
|
try {
|
|
6807
6807
|
B.onSpeechEnd();
|
|
@@ -6811,9 +6811,9 @@ const Pe = Ie(({
|
|
|
6811
6811
|
}
|
|
6812
6812
|
return;
|
|
6813
6813
|
}
|
|
6814
|
-
const Oe = !
|
|
6815
|
-
|
|
6816
|
-
if (
|
|
6814
|
+
const Oe = !M.speechQueue || M.speechQueue.length === 0, Ne = !M.audioPlaylist || M.audioPlaylist.length === 0;
|
|
6815
|
+
M && M.isSpeaking === !1 && Oe && Ne && M.isAudioPlaying === !1 && !xe && !T.current && setTimeout(() => {
|
|
6816
|
+
if (M && !T.current && M.isSpeaking === !1 && (!M.speechQueue || M.speechQueue.length === 0) && (!M.audioPlaylist || M.audioPlaylist.length === 0) && M.isAudioPlaying === !1 && !xe && !T.current) {
|
|
6817
6817
|
xe = !0, Y && (clearInterval(Y), Y = null, R.current = null);
|
|
6818
6818
|
try {
|
|
6819
6819
|
B.onSpeechEnd();
|
|
@@ -6824,64 +6824,70 @@ const Pe = Ie(({
|
|
|
6824
6824
|
}, 100);
|
|
6825
6825
|
}, 100), R.current = Y;
|
|
6826
6826
|
}
|
|
6827
|
-
p.current.lipsync && Object.keys(p.current.lipsync).length > 0 ? (p.current.setSlowdownRate && p.current.setSlowdownRate(1.05), p.current.speakText(L,
|
|
6828
|
-
await v(), p.current && p.current.lipsync && (p.current.setSlowdownRate && p.current.setSlowdownRate(1.05), p.current.speakText(L,
|
|
6827
|
+
p.current.lipsync && Object.keys(p.current.lipsync).length > 0 ? (p.current.setSlowdownRate && p.current.setSlowdownRate(1.05), p.current.speakText(L, V)) : setTimeout(async () => {
|
|
6828
|
+
await v(), p.current && p.current.lipsync && (p.current.setSlowdownRate && p.current.setSlowdownRate(1.05), p.current.speakText(L, V));
|
|
6829
6829
|
}, 100);
|
|
6830
|
-
} catch (
|
|
6831
|
-
console.error("Error speaking text:",
|
|
6830
|
+
} catch (V) {
|
|
6831
|
+
console.error("Error speaking text:", V), N(V.message || "Failed to speak text");
|
|
6832
6832
|
}
|
|
6833
|
-
}, [Z, v,
|
|
6834
|
-
p.current && (p.current.stopSpeaking(), p.current.setSlowdownRate && p.current.setSlowdownRate(1), z.current = null,
|
|
6835
|
-
}, []),
|
|
6833
|
+
}, [Z, v, de.lipsyncLang]), C = E(() => {
|
|
6834
|
+
p.current && (p.current.stopSpeaking(), p.current.setSlowdownRate && p.current.setSlowdownRate(1), z.current = null, _(!1));
|
|
6835
|
+
}, []), W = E(() => {
|
|
6836
6836
|
if (p.current && p.current.pauseSpeaking) {
|
|
6837
6837
|
const L = p.current;
|
|
6838
6838
|
if (L.isSpeaking || L.audioPlaylist && L.audioPlaylist.length > 0 || L.speechQueue && L.speechQueue.length > 0) {
|
|
6839
6839
|
R.current && (clearInterval(R.current), R.current = null);
|
|
6840
|
-
let
|
|
6841
|
-
if (L.speechQueue && L.speechQueue.length > 0) {
|
|
6842
|
-
const
|
|
6843
|
-
|
|
6840
|
+
let V = "";
|
|
6841
|
+
if (L.speechQueue && L.speechQueue.length > 0 && z.current) {
|
|
6842
|
+
const M = L.speechQueue.filter((Y) => Y && Y.text).map((Y) => Y.text).join(" ");
|
|
6843
|
+
M && M.trim() && (V = M.trim());
|
|
6844
6844
|
}
|
|
6845
|
-
|
|
6846
|
-
remainingText:
|
|
6845
|
+
z.current && (P.current = {
|
|
6846
|
+
remainingText: V || null,
|
|
6847
6847
|
originalText: z.current.text,
|
|
6848
6848
|
options: z.current.options
|
|
6849
|
-
}), L.speechQueue && (L.speechQueue.length = 0), p.current.pauseSpeaking(),
|
|
6849
|
+
}), L.speechQueue && (L.speechQueue.length = 0), p.current.pauseSpeaking(), T.current = !0, _(!0);
|
|
6850
6850
|
}
|
|
6851
6851
|
}
|
|
6852
|
-
}, []), ne =
|
|
6853
|
-
if (p.current
|
|
6854
|
-
|
|
6855
|
-
|
|
6856
|
-
|
|
6857
|
-
|
|
6858
|
-
|
|
6859
|
-
|
|
6860
|
-
|
|
6861
|
-
|
|
6862
|
-
|
|
6863
|
-
...B,
|
|
6864
|
-
lipsyncLang: B.lipsyncLang || pe.lipsyncLang || "en"
|
|
6865
|
-
};
|
|
6866
|
-
p.current.lipsync && Object.keys(p.current.lipsync).length > 0 && (p.current.setSlowdownRate && p.current.setSlowdownRate(1.05), await w(L, U));
|
|
6852
|
+
}, []), ne = E(async () => {
|
|
6853
|
+
if (!p.current || !j)
|
|
6854
|
+
return;
|
|
6855
|
+
let L = "", B = {};
|
|
6856
|
+
if (P.current && P.current.remainingText)
|
|
6857
|
+
L = P.current.remainingText, B = P.current.options || {}, P.current = { remainingText: null, originalText: null, options: null };
|
|
6858
|
+
else if (z.current && z.current.text)
|
|
6859
|
+
L = z.current.text, B = z.current.options || {};
|
|
6860
|
+
else {
|
|
6861
|
+
console.warn("Resume called but no paused speech found"), _(!1), T.current = !1;
|
|
6862
|
+
return;
|
|
6867
6863
|
}
|
|
6868
|
-
|
|
6864
|
+
_(!1), T.current = !1, await v();
|
|
6865
|
+
const V = {
|
|
6866
|
+
...B,
|
|
6867
|
+
lipsyncLang: B.lipsyncLang || de.lipsyncLang || "en"
|
|
6868
|
+
};
|
|
6869
|
+
try {
|
|
6870
|
+
await w(L, V);
|
|
6871
|
+
} catch (M) {
|
|
6872
|
+
console.error("Error resuming speech:", M), _(!1), T.current = !1;
|
|
6873
|
+
}
|
|
6874
|
+
}, [v, j, w, de]), ie = E((L) => {
|
|
6869
6875
|
p.current && p.current.setMood(L);
|
|
6870
|
-
}, []), fe =
|
|
6876
|
+
}, []), fe = E((L) => {
|
|
6871
6877
|
p.current && p.current.setSlowdownRate && p.current.setSlowdownRate(L);
|
|
6872
|
-
}, []), Se =
|
|
6878
|
+
}, []), Se = E((L, B = !1) => {
|
|
6873
6879
|
if (p.current && p.current.playAnimation) {
|
|
6874
6880
|
if (x && x[L] && (L = x[L]), p.current.setShowFullAvatar)
|
|
6875
6881
|
try {
|
|
6876
6882
|
p.current.setShowFullAvatar(H.current);
|
|
6877
|
-
} catch (
|
|
6878
|
-
console.warn("Error setting full body mode:",
|
|
6883
|
+
} catch (M) {
|
|
6884
|
+
console.warn("Error setting full body mode:", M);
|
|
6879
6885
|
}
|
|
6880
6886
|
if (L.includes("."))
|
|
6881
6887
|
try {
|
|
6882
6888
|
p.current.playAnimation(L, null, 10, 0, 0.01, B);
|
|
6883
|
-
} catch (
|
|
6884
|
-
console.warn(`Failed to play ${L}:`,
|
|
6889
|
+
} catch (M) {
|
|
6890
|
+
console.warn(`Failed to play ${L}:`, M);
|
|
6885
6891
|
try {
|
|
6886
6892
|
p.current.setBodyMovement("idle");
|
|
6887
6893
|
} catch (Y) {
|
|
@@ -6889,9 +6895,9 @@ const Pe = Ie(({
|
|
|
6889
6895
|
}
|
|
6890
6896
|
}
|
|
6891
6897
|
else {
|
|
6892
|
-
const
|
|
6898
|
+
const M = [".fbx", ".glb", ".gltf"];
|
|
6893
6899
|
let Y = !1;
|
|
6894
|
-
for (const ge of
|
|
6900
|
+
for (const ge of M)
|
|
6895
6901
|
try {
|
|
6896
6902
|
p.current.playAnimation(L + ge, null, 10, 0, 0.01, B), Y = !0;
|
|
6897
6903
|
break;
|
|
@@ -6907,13 +6913,13 @@ const Pe = Ie(({
|
|
|
6907
6913
|
}
|
|
6908
6914
|
}
|
|
6909
6915
|
}
|
|
6910
|
-
}, [x]), De =
|
|
6916
|
+
}, [x]), De = E(() => {
|
|
6911
6917
|
p.current && p.current.onResize && p.current.onResize();
|
|
6912
6918
|
}, []);
|
|
6913
6919
|
return Le(I, () => ({
|
|
6914
6920
|
speakText: w,
|
|
6915
6921
|
stopSpeaking: C,
|
|
6916
|
-
pauseSpeaking:
|
|
6922
|
+
pauseSpeaking: W,
|
|
6917
6923
|
resumeSpeaking: ne,
|
|
6918
6924
|
resumeAudioContext: v,
|
|
6919
6925
|
setMood: ie,
|
|
@@ -7041,7 +7047,7 @@ const ut = Ie(({
|
|
|
7041
7047
|
style: s = {},
|
|
7042
7048
|
avatarConfig: o = {}
|
|
7043
7049
|
}, l) => {
|
|
7044
|
-
const u = G(null), a = G(null), [h, r] =
|
|
7050
|
+
const u = G(null), a = G(null), [h, r] = me(!0), [c, d] = me(null), [g, y] = me(!1), x = Ae(), I = o.ttsService || x.service, D = I === "browser" ? {
|
|
7045
7051
|
endpoint: "",
|
|
7046
7052
|
apiKey: null,
|
|
7047
7053
|
defaultVoice: "Google US English"
|
|
@@ -7071,7 +7077,7 @@ const ut = Ie(({
|
|
|
7071
7077
|
ttsService: I,
|
|
7072
7078
|
lipsyncModules: ["en"],
|
|
7073
7079
|
cameraView: "upper"
|
|
7074
|
-
}, z =
|
|
7080
|
+
}, z = E(async () => {
|
|
7075
7081
|
if (!(!u.current || a.current))
|
|
7076
7082
|
try {
|
|
7077
7083
|
if (r(!0), d(null), a.current = new Fe(u.current, H), await a.current.showAvatar(p, (Z) => {
|
|
@@ -7107,10 +7113,10 @@ const ut = Ie(({
|
|
|
7107
7113
|
console.error("Error initializing TalkingHead:", S), d(S.message || "Failed to initialize avatar"), r(!1), e(S);
|
|
7108
7114
|
}
|
|
7109
7115
|
}, []);
|
|
7110
|
-
|
|
7116
|
+
pe(() => (z(), () => {
|
|
7111
7117
|
a.current && (a.current.stop(), a.current.dispose(), a.current = null);
|
|
7112
7118
|
}), [z]);
|
|
7113
|
-
const R =
|
|
7119
|
+
const R = E((S) => {
|
|
7114
7120
|
if (a.current && g)
|
|
7115
7121
|
try {
|
|
7116
7122
|
console.log("Speaking text:", S), console.log("Avatar config:", p), console.log("TalkingHead instance:", a.current), a.current.lipsync && Object.keys(a.current.lipsync).length > 0 ? (console.log("Lip-sync modules loaded:", Object.keys(a.current.lipsync)), a.current.setSlowdownRate && (a.current.setSlowdownRate(1.05), console.log("Applied timing adjustment for better lip-sync")), a.current.speakText(S)) : (console.warn("Lip-sync modules not ready, waiting..."), setTimeout(() => {
|
|
@@ -7121,13 +7127,13 @@ const ut = Ie(({
|
|
|
7121
7127
|
}
|
|
7122
7128
|
else
|
|
7123
7129
|
console.warn("Avatar not ready for speaking. isReady:", g, "talkingHeadRef:", !!a.current);
|
|
7124
|
-
}, [g, p]),
|
|
7130
|
+
}, [g, p]), T = E(() => {
|
|
7125
7131
|
a.current && (a.current.stopSpeaking(), a.current.setSlowdownRate && (a.current.setSlowdownRate(1), console.log("Reset timing to normal")));
|
|
7126
|
-
}, []), P =
|
|
7132
|
+
}, []), P = E((S) => {
|
|
7127
7133
|
a.current && a.current.setMood(S);
|
|
7128
|
-
}, []), ee =
|
|
7134
|
+
}, []), ee = E((S) => {
|
|
7129
7135
|
a.current && a.current.setSlowdownRate && (a.current.setSlowdownRate(S), console.log("Timing adjustment set to:", S));
|
|
7130
|
-
}, []), re =
|
|
7136
|
+
}, []), re = E((S, N = !1) => {
|
|
7131
7137
|
if (a.current && a.current.playAnimation) {
|
|
7132
7138
|
if (a.current.setShowFullAvatar)
|
|
7133
7139
|
try {
|
|
@@ -7149,19 +7155,19 @@ const ut = Ie(({
|
|
|
7149
7155
|
else {
|
|
7150
7156
|
const X = [".fbx", ".glb", ".gltf"];
|
|
7151
7157
|
let j = !1;
|
|
7152
|
-
for (const
|
|
7158
|
+
for (const _ of X)
|
|
7153
7159
|
try {
|
|
7154
|
-
a.current.playAnimation(S +
|
|
7160
|
+
a.current.playAnimation(S + _, null, 10, 0, 0.01, N), console.log("Playing animation:", S + _), j = !0;
|
|
7155
7161
|
break;
|
|
7156
7162
|
} catch {
|
|
7157
|
-
console.log(`Failed to play ${S}${
|
|
7163
|
+
console.log(`Failed to play ${S}${_}, trying next format...`);
|
|
7158
7164
|
}
|
|
7159
7165
|
if (!j) {
|
|
7160
7166
|
console.warn("Animation system not available or animation not found:", S);
|
|
7161
7167
|
try {
|
|
7162
7168
|
a.current.setBodyMovement("idle"), console.log("Fallback to idle animation");
|
|
7163
|
-
} catch (
|
|
7164
|
-
console.warn("Fallback animation also failed:",
|
|
7169
|
+
} catch (_) {
|
|
7170
|
+
console.warn("Fallback animation also failed:", _);
|
|
7165
7171
|
}
|
|
7166
7172
|
}
|
|
7167
7173
|
}
|
|
@@ -7170,7 +7176,7 @@ const ut = Ie(({
|
|
|
7170
7176
|
}, []);
|
|
7171
7177
|
return Le(l, () => ({
|
|
7172
7178
|
speakText: R,
|
|
7173
|
-
stopSpeaking:
|
|
7179
|
+
stopSpeaking: T,
|
|
7174
7180
|
setMood: P,
|
|
7175
7181
|
setTimingAdjustment: ee,
|
|
7176
7182
|
playAnimation: re,
|
|
@@ -7321,7 +7327,7 @@ const ct = Ie(({
|
|
|
7321
7327
|
animations: e,
|
|
7322
7328
|
lipsyncLang: "en"
|
|
7323
7329
|
});
|
|
7324
|
-
|
|
7330
|
+
pe(() => {
|
|
7325
7331
|
c.current = {
|
|
7326
7332
|
onLessonStart: n,
|
|
7327
7333
|
onLessonComplete: i,
|
|
@@ -7329,7 +7335,7 @@ const ct = Ie(({
|
|
|
7329
7335
|
onCurriculumComplete: o,
|
|
7330
7336
|
onCustomAction: l
|
|
7331
7337
|
};
|
|
7332
|
-
}, [n, i, s, o, l]),
|
|
7338
|
+
}, [n, i, s, o, l]), pe(() => {
|
|
7333
7339
|
H.current = O?.curriculum || {
|
|
7334
7340
|
title: "Default Curriculum",
|
|
7335
7341
|
description: "No curriculum data provided",
|
|
@@ -7350,7 +7356,7 @@ const ct = Ie(({
|
|
|
7350
7356
|
lipsyncLang: "en"
|
|
7351
7357
|
};
|
|
7352
7358
|
}, [O, t, e]);
|
|
7353
|
-
const R =
|
|
7359
|
+
const R = E(() => (H.current || { modules: [] }).modules[r.current.currentModuleIndex]?.lessons[r.current.currentLessonIndex], []), T = E(() => R()?.questions[r.current.currentQuestionIndex], [R]), P = E((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, []), ee = E(() => {
|
|
7354
7360
|
r.current.lessonCompleted = !0, r.current.isQuestionMode = !1;
|
|
7355
7361
|
const b = r.current.totalQuestions > 0 ? Math.round(r.current.score / r.current.totalQuestions * 100) : 100;
|
|
7356
7362
|
let v = "Congratulations! You've completed this lesson";
|
|
@@ -7374,7 +7380,7 @@ const ct = Ie(({
|
|
|
7374
7380
|
} catch {
|
|
7375
7381
|
h.current.playCelebration();
|
|
7376
7382
|
}
|
|
7377
|
-
const w = H.current || { modules: [] }, C = w.modules[r.current.currentModuleIndex],
|
|
7383
|
+
const w = H.current || { modules: [] }, C = w.modules[r.current.currentModuleIndex], W = r.current.currentLessonIndex < (C?.lessons?.length || 0) - 1, ne = r.current.currentModuleIndex < (w.modules?.length || 0) - 1, ie = W || ne, fe = z.current || { lipsyncLang: "en" };
|
|
7378
7384
|
h.current.speakText(v, {
|
|
7379
7385
|
lipsyncLang: fe.lipsyncLang,
|
|
7380
7386
|
onSpeechEnd: () => {
|
|
@@ -7390,7 +7396,7 @@ const ct = Ie(({
|
|
|
7390
7396
|
}
|
|
7391
7397
|
});
|
|
7392
7398
|
}
|
|
7393
|
-
}, [e.lessonComplete]), re =
|
|
7399
|
+
}, [e.lessonComplete]), re = E(() => {
|
|
7394
7400
|
r.current.curriculumCompleted = !0;
|
|
7395
7401
|
const b = H.current || { modules: [] };
|
|
7396
7402
|
if (c.current.onCurriculumComplete({
|
|
@@ -7406,10 +7412,10 @@ const ct = Ie(({
|
|
|
7406
7412
|
const v = z.current || { lipsyncLang: "en" };
|
|
7407
7413
|
h.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 });
|
|
7408
7414
|
}
|
|
7409
|
-
}, [e.curriculumComplete]), S =
|
|
7415
|
+
}, [e.curriculumComplete]), S = E(() => {
|
|
7410
7416
|
const b = R();
|
|
7411
7417
|
r.current.isQuestionMode = !0, r.current.currentQuestionIndex = 0, r.current.totalQuestions = b?.questions?.length || 0, r.current.score = 0;
|
|
7412
|
-
const v =
|
|
7418
|
+
const v = T();
|
|
7413
7419
|
v && c.current.onCustomAction({
|
|
7414
7420
|
type: "questionStart",
|
|
7415
7421
|
moduleIndex: r.current.currentModuleIndex,
|
|
@@ -7424,8 +7430,8 @@ const ct = Ie(({
|
|
|
7424
7430
|
if (h.current.setMood("happy"), e.questionStart)
|
|
7425
7431
|
try {
|
|
7426
7432
|
h.current.playAnimation(e.questionStart, !0);
|
|
7427
|
-
} catch (
|
|
7428
|
-
console.warn("Failed to play questionStart animation:",
|
|
7433
|
+
} catch (W) {
|
|
7434
|
+
console.warn("Failed to play questionStart animation:", W);
|
|
7429
7435
|
}
|
|
7430
7436
|
const C = z.current || { lipsyncLang: "en" };
|
|
7431
7437
|
v.type === "code_test" ? h.current.speakText(`Let's test your coding skills! Here's your first challenge: ${v.question}`, { lipsyncLang: C.lipsyncLang }) : v.type === "multiple_choice" ? h.current.speakText(`Now let me ask you some questions. Here's the first one: ${v.question}`, { lipsyncLang: C.lipsyncLang }) : v.type === "true_false" ? h.current.speakText(`Let's start with some true or false questions. First question: ${v.question}`, { lipsyncLang: C.lipsyncLang }) : h.current.speakText(`Now let me ask you some questions. Here's the first one: ${v.question}`, { lipsyncLang: C.lipsyncLang });
|
|
@@ -7443,11 +7449,11 @@ const ct = Ie(({
|
|
|
7443
7449
|
clearInterval(C);
|
|
7444
7450
|
}, 5e3);
|
|
7445
7451
|
}
|
|
7446
|
-
}, [e.questionStart, R,
|
|
7452
|
+
}, [e.questionStart, R, T]), N = E(() => {
|
|
7447
7453
|
const b = R();
|
|
7448
7454
|
if (r.current.currentQuestionIndex < (b?.questions?.length || 0) - 1) {
|
|
7449
7455
|
h.current && h.current.stopSpeaking && h.current.stopSpeaking(), r.current.currentQuestionIndex += 1;
|
|
7450
|
-
const v =
|
|
7456
|
+
const v = T();
|
|
7451
7457
|
v && c.current.onCustomAction({
|
|
7452
7458
|
type: "nextQuestion",
|
|
7453
7459
|
moduleIndex: r.current.currentModuleIndex,
|
|
@@ -7462,8 +7468,8 @@ const ct = Ie(({
|
|
|
7462
7468
|
if (h.current.setMood("happy"), h.current.setBodyMovement("idle"), e.nextQuestion)
|
|
7463
7469
|
try {
|
|
7464
7470
|
h.current.playAnimation(e.nextQuestion, !0);
|
|
7465
|
-
} catch (
|
|
7466
|
-
console.warn("Failed to play nextQuestion animation:",
|
|
7471
|
+
} catch (W) {
|
|
7472
|
+
console.warn("Failed to play nextQuestion animation:", W);
|
|
7467
7473
|
}
|
|
7468
7474
|
const C = z.current || { lipsyncLang: "en" };
|
|
7469
7475
|
v.type === "code_test" ? h.current.speakText(`Great! Now let's move on to your next coding challenge: ${v.question}`, {
|
|
@@ -7494,11 +7500,11 @@ const ct = Ie(({
|
|
|
7494
7500
|
totalQuestions: r.current.totalQuestions,
|
|
7495
7501
|
score: r.current.score
|
|
7496
7502
|
});
|
|
7497
|
-
}, [e.nextQuestion, R,
|
|
7503
|
+
}, [e.nextQuestion, R, T]), Z = E(() => {
|
|
7498
7504
|
const b = H.current || { modules: [] }, v = b.modules[r.current.currentModuleIndex];
|
|
7499
7505
|
if (r.current.currentLessonIndex < (v?.lessons?.length || 0) - 1) {
|
|
7500
7506
|
r.current.currentLessonIndex += 1, r.current.currentQuestionIndex = 0, r.current.lessonCompleted = !1, r.current.isQuestionMode = !1, r.current.isTeaching = !1, r.current.score = 0, r.current.totalQuestions = 0;
|
|
7501
|
-
const C = b.modules[r.current.currentModuleIndex],
|
|
7507
|
+
const C = b.modules[r.current.currentModuleIndex], W = r.current.currentLessonIndex < (C?.lessons?.length || 0) - 1, ne = r.current.currentModuleIndex < (b.modules?.length || 0) - 1, ie = W || ne;
|
|
7502
7508
|
c.current.onCustomAction({
|
|
7503
7509
|
type: "lessonStart",
|
|
7504
7510
|
moduleIndex: r.current.currentModuleIndex,
|
|
@@ -7511,7 +7517,7 @@ const ct = Ie(({
|
|
|
7511
7517
|
}), h.current && (h.current.setMood("happy"), h.current.setBodyMovement("idle"));
|
|
7512
7518
|
} else if (r.current.currentModuleIndex < (b.modules?.length || 0) - 1) {
|
|
7513
7519
|
r.current.currentModuleIndex += 1, r.current.currentLessonIndex = 0, r.current.currentQuestionIndex = 0, r.current.lessonCompleted = !1, r.current.isQuestionMode = !1, r.current.isTeaching = !1, r.current.score = 0, r.current.totalQuestions = 0;
|
|
7514
|
-
const
|
|
7520
|
+
const W = b.modules[r.current.currentModuleIndex], ne = r.current.currentLessonIndex < (W?.lessons?.length || 0) - 1, ie = r.current.currentModuleIndex < (b.modules?.length || 0) - 1, fe = ne || ie;
|
|
7515
7521
|
c.current.onCustomAction({
|
|
7516
7522
|
type: "lessonStart",
|
|
7517
7523
|
moduleIndex: r.current.currentModuleIndex,
|
|
@@ -7524,12 +7530,12 @@ const ct = Ie(({
|
|
|
7524
7530
|
}), h.current && (h.current.setMood("happy"), h.current.setBodyMovement("idle"));
|
|
7525
7531
|
} else
|
|
7526
7532
|
I.current && I.current();
|
|
7527
|
-
}, []), X =
|
|
7533
|
+
}, []), X = E(() => {
|
|
7528
7534
|
const b = R();
|
|
7529
7535
|
let v = null;
|
|
7530
7536
|
if (b?.avatar_script && b?.body) {
|
|
7531
|
-
const w = b.avatar_script.trim(), C = b.body.trim(),
|
|
7532
|
-
v = `${w}${
|
|
7537
|
+
const w = b.avatar_script.trim(), C = b.body.trim(), W = w.match(/[.!?]$/) ? " " : ". ";
|
|
7538
|
+
v = `${w}${W}${C}`;
|
|
7533
7539
|
} else
|
|
7534
7540
|
v = b?.avatar_script || b?.body || null;
|
|
7535
7541
|
if (h.current && h.current.isReady && v) {
|
|
@@ -7538,8 +7544,8 @@ const ct = Ie(({
|
|
|
7538
7544
|
if (e.teaching)
|
|
7539
7545
|
try {
|
|
7540
7546
|
h.current.playAnimation(e.teaching, !0), w = !0;
|
|
7541
|
-
} catch (
|
|
7542
|
-
console.warn("Failed to play teaching animation:",
|
|
7547
|
+
} catch (W) {
|
|
7548
|
+
console.warn("Failed to play teaching animation:", W);
|
|
7543
7549
|
}
|
|
7544
7550
|
w || h.current.setBodyMovement("gesturing");
|
|
7545
7551
|
const C = z.current || { lipsyncLang: "en" };
|
|
@@ -7565,8 +7571,8 @@ const ct = Ie(({
|
|
|
7565
7571
|
}
|
|
7566
7572
|
});
|
|
7567
7573
|
}
|
|
7568
|
-
}, [e.teaching, R]), j =
|
|
7569
|
-
const v =
|
|
7574
|
+
}, [e.teaching, R]), j = E((b) => {
|
|
7575
|
+
const v = T(), w = P(b, v);
|
|
7570
7576
|
if (w && (r.current.score += 1), c.current.onQuestionAnswer({
|
|
7571
7577
|
moduleIndex: r.current.currentModuleIndex,
|
|
7572
7578
|
lessonIndex: r.current.currentLessonIndex,
|
|
@@ -7583,9 +7589,9 @@ const ct = Ie(({
|
|
|
7583
7589
|
h.current.setBodyMovement("happy");
|
|
7584
7590
|
}
|
|
7585
7591
|
h.current.setBodyMovement("gesturing");
|
|
7586
|
-
const C = v.type === "code_test" ? `Great job! Your code passed all the tests! ${v.explanation || ""}` : `Excellent! That's correct! ${v.explanation || ""}`,
|
|
7592
|
+
const C = v.type === "code_test" ? `Great job! Your code passed all the tests! ${v.explanation || ""}` : `Excellent! That's correct! ${v.explanation || ""}`, W = z.current || { lipsyncLang: "en" };
|
|
7587
7593
|
h.current.speakText(C, {
|
|
7588
|
-
lipsyncLang:
|
|
7594
|
+
lipsyncLang: W.lipsyncLang,
|
|
7589
7595
|
onSpeechEnd: () => {
|
|
7590
7596
|
const ie = R()?.questions?.length || 0;
|
|
7591
7597
|
c.current.onCustomAction({
|
|
@@ -7608,9 +7614,9 @@ const ct = Ie(({
|
|
|
7608
7614
|
h.current.setBodyMovement("idle");
|
|
7609
7615
|
}
|
|
7610
7616
|
h.current.setBodyMovement("gesturing");
|
|
7611
|
-
const C = 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 || ""} Let's move on to the next question.`,
|
|
7617
|
+
const C = 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 || ""} Let's move on to the next question.`, W = z.current || { lipsyncLang: "en" };
|
|
7612
7618
|
h.current.speakText(C, {
|
|
7613
|
-
lipsyncLang:
|
|
7619
|
+
lipsyncLang: W.lipsyncLang,
|
|
7614
7620
|
onSpeechEnd: () => {
|
|
7615
7621
|
const ie = R()?.questions?.length || 0;
|
|
7616
7622
|
c.current.onCustomAction({
|
|
@@ -7627,21 +7633,21 @@ const ct = Ie(({
|
|
|
7627
7633
|
});
|
|
7628
7634
|
}
|
|
7629
7635
|
else {
|
|
7630
|
-
const
|
|
7636
|
+
const W = R()?.questions?.length || 0;
|
|
7631
7637
|
c.current.onCustomAction({
|
|
7632
7638
|
type: "answerFeedbackComplete",
|
|
7633
7639
|
moduleIndex: r.current.currentModuleIndex,
|
|
7634
7640
|
lessonIndex: r.current.currentLessonIndex,
|
|
7635
7641
|
questionIndex: r.current.currentQuestionIndex,
|
|
7636
7642
|
isCorrect: w,
|
|
7637
|
-
hasNextQuestion: r.current.currentQuestionIndex <
|
|
7643
|
+
hasNextQuestion: r.current.currentQuestionIndex < W - 1,
|
|
7638
7644
|
score: r.current.score,
|
|
7639
7645
|
totalQuestions: r.current.totalQuestions,
|
|
7640
7646
|
avatarNotReady: !0
|
|
7641
7647
|
});
|
|
7642
7648
|
}
|
|
7643
|
-
}, [e.correct, e.incorrect,
|
|
7644
|
-
const v =
|
|
7649
|
+
}, [e.correct, e.incorrect, T, R, P]), _ = E((b) => {
|
|
7650
|
+
const v = T();
|
|
7645
7651
|
if (!b || typeof b != "object") {
|
|
7646
7652
|
console.error("Invalid code test result format. Expected object with {passed: boolean, ...}");
|
|
7647
7653
|
return;
|
|
@@ -7668,10 +7674,10 @@ const ct = Ie(({
|
|
|
7668
7674
|
testResult: w,
|
|
7669
7675
|
question: v
|
|
7670
7676
|
}), p.current && p.current(w);
|
|
7671
|
-
}, [
|
|
7677
|
+
}, [T, P]), te = E(() => {
|
|
7672
7678
|
if (r.current.currentQuestionIndex > 0) {
|
|
7673
7679
|
r.current.currentQuestionIndex -= 1;
|
|
7674
|
-
const b =
|
|
7680
|
+
const b = T();
|
|
7675
7681
|
b && c.current.onCustomAction({
|
|
7676
7682
|
type: "questionStart",
|
|
7677
7683
|
moduleIndex: r.current.currentModuleIndex,
|
|
@@ -7702,7 +7708,7 @@ const ct = Ie(({
|
|
|
7702
7708
|
}, 5e3);
|
|
7703
7709
|
}
|
|
7704
7710
|
}
|
|
7705
|
-
}, [
|
|
7711
|
+
}, [T]), ce = E(() => {
|
|
7706
7712
|
const b = H.current || { modules: [] };
|
|
7707
7713
|
if (b.modules[r.current.currentModuleIndex], r.current.currentLessonIndex > 0)
|
|
7708
7714
|
r.current.currentLessonIndex -= 1, r.current.currentQuestionIndex = 0, r.current.lessonCompleted = !1, r.current.isQuestionMode = !1, r.current.isTeaching = !1, r.current.score = 0, r.current.totalQuestions = 0, c.current.onCustomAction({
|
|
@@ -7726,9 +7732,9 @@ const ct = Ie(({
|
|
|
7726
7732
|
lesson: R()
|
|
7727
7733
|
}), h.current && (h.current.setMood("happy"), h.current.setBodyMovement("idle"));
|
|
7728
7734
|
}
|
|
7729
|
-
}, [R]), oe =
|
|
7735
|
+
}, [R]), oe = E(() => {
|
|
7730
7736
|
r.current.currentModuleIndex = 0, r.current.currentLessonIndex = 0, r.current.currentQuestionIndex = 0, r.current.isTeaching = !1, r.current.isQuestionMode = !1, r.current.lessonCompleted = !1, r.current.curriculumCompleted = !1, r.current.score = 0, r.current.totalQuestions = 0;
|
|
7731
|
-
}, []),
|
|
7737
|
+
}, []), de = E((b) => {
|
|
7732
7738
|
console.log("Avatar is ready!", b);
|
|
7733
7739
|
const v = R(), w = v?.avatar_script || v?.body;
|
|
7734
7740
|
u && w && setTimeout(() => {
|
|
@@ -7742,7 +7748,7 @@ const ct = Ie(({
|
|
|
7742
7748
|
startTeaching: X,
|
|
7743
7749
|
startQuestions: S,
|
|
7744
7750
|
handleAnswerSelect: j,
|
|
7745
|
-
handleCodeTestResult:
|
|
7751
|
+
handleCodeTestResult: _,
|
|
7746
7752
|
nextQuestion: N,
|
|
7747
7753
|
previousQuestion: te,
|
|
7748
7754
|
nextLesson: Z,
|
|
@@ -7751,7 +7757,7 @@ const ct = Ie(({
|
|
|
7751
7757
|
completeCurriculum: re,
|
|
7752
7758
|
resetCurriculum: oe,
|
|
7753
7759
|
getState: () => ({ ...r.current }),
|
|
7754
|
-
getCurrentQuestion: () =>
|
|
7760
|
+
getCurrentQuestion: () => T(),
|
|
7755
7761
|
getCurrentLesson: () => R(),
|
|
7756
7762
|
// Direct access to avatar ref (always returns current value)
|
|
7757
7763
|
getAvatarRef: () => h.current,
|
|
@@ -7803,7 +7809,7 @@ const ct = Ie(({
|
|
|
7803
7809
|
handleResize: () => h.current?.handleResize(),
|
|
7804
7810
|
// Avatar readiness check (always returns current value)
|
|
7805
7811
|
isAvatarReady: () => h.current?.isReady || !1
|
|
7806
|
-
}), [X, S, j,
|
|
7812
|
+
}), [X, S, j, _, N, Z, ee, re, oe, T, R]);
|
|
7807
7813
|
const J = z.current || {
|
|
7808
7814
|
avatarUrl: "/avatars/brunette.glb",
|
|
7809
7815
|
avatarBody: "F",
|
|
@@ -7833,7 +7839,7 @@ const ct = Ie(({
|
|
|
7833
7839
|
showFullAvatar: J.showFullAvatar,
|
|
7834
7840
|
cameraView: "upper",
|
|
7835
7841
|
animations: J.animations,
|
|
7836
|
-
onReady:
|
|
7842
|
+
onReady: de,
|
|
7837
7843
|
onLoading: () => {
|
|
7838
7844
|
},
|
|
7839
7845
|
onError: (b) => {
|