@sage-rsc/talking-head-react 1.0.35 → 1.0.37
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 +194 -188
- package/package.json +1 -1
- package/src/components/CurriculumLearning.jsx +34 -17
- package/src/lib/talkinghead.mjs +2 -2
package/dist/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { jsxs as Ae, jsx as se } from "react/jsx-runtime";
|
|
2
|
-
import { forwardRef as ye, useRef as X, useState as re, useCallback as
|
|
2
|
+
import { forwardRef as ye, useRef as X, useState as re, useCallback as M, useEffect as he, useImperativeHandle as fe, useLayoutEffect as Ce } from "react";
|
|
3
3
|
import * as y from "three";
|
|
4
4
|
import { OrbitControls as He } from "three/addons/controls/OrbitControls.js";
|
|
5
5
|
import { GLTFLoader as Te } from "three/addons/loaders/GLTFLoader.js";
|
|
@@ -2629,7 +2629,7 @@ const qe = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
|
|
|
2629
2629
|
fr: Xe,
|
|
2630
2630
|
fi: je,
|
|
2631
2631
|
lt: qe
|
|
2632
|
-
}, N = new y.Quaternion(),
|
|
2632
|
+
}, N = new y.Quaternion(), T = new y.Euler(), ie = new y.Vector3(), oe = new y.Vector3(), Ie = new y.Box3();
|
|
2633
2633
|
new y.Matrix4();
|
|
2634
2634
|
new y.Matrix4();
|
|
2635
2635
|
new y.Vector3();
|
|
@@ -2734,9 +2734,9 @@ class Le {
|
|
|
2734
2734
|
cameraPanEnable: !1,
|
|
2735
2735
|
cameraZoomEnable: !1,
|
|
2736
2736
|
lightAmbientColor: 16777215,
|
|
2737
|
-
lightAmbientIntensity: 2,
|
|
2737
|
+
lightAmbientIntensity: 1.2,
|
|
2738
2738
|
lightDirectColor: 8947882,
|
|
2739
|
-
lightDirectIntensity:
|
|
2739
|
+
lightDirectIntensity: 18,
|
|
2740
2740
|
lightDirectPhi: 1,
|
|
2741
2741
|
lightDirectTheta: 2,
|
|
2742
2742
|
lightSpotIntensity: 0,
|
|
@@ -4374,9 +4374,9 @@ class Le {
|
|
|
4374
4374
|
updatePoseDelta() {
|
|
4375
4375
|
for (const [t, e] of Object.entries(this.poseDelta.props)) {
|
|
4376
4376
|
if (e.x === 0 && e.y === 0 && e.z === 0) continue;
|
|
4377
|
-
|
|
4377
|
+
T.set(e.x, e.y, e.z);
|
|
4378
4378
|
const i = this.poseAvatar.props[t];
|
|
4379
|
-
i.isQuaternion ? (N.setFromEuler(
|
|
4379
|
+
i.isQuaternion ? (N.setFromEuler(T), i.multiply(N)) : i.isVector3 && i.add(T);
|
|
4380
4380
|
}
|
|
4381
4381
|
}
|
|
4382
4382
|
/**
|
|
@@ -5159,7 +5159,7 @@ class Le {
|
|
|
5159
5159
|
}, n.x ? new y.Vector3(n.x, n.y, n.z) : null, !0, n.d);
|
|
5160
5160
|
break;
|
|
5161
5161
|
}
|
|
5162
|
-
if ((h || a) && (
|
|
5162
|
+
if ((h || a) && (T.setFromQuaternion(this.poseAvatar.props["Head.quaternion"]), T.x = Math.max(-0.9, Math.min(0.9, 2 * T.x - 0.5)), T.y = Math.max(-0.9, Math.min(0.9, -2.5 * T.y)), h ? (Object.assign(this.mtAvatar.eyesLookDown, { system: T.x < 0 ? -T.x : 0, needsUpdate: !0 }), Object.assign(this.mtAvatar.eyesLookUp, { system: T.x < 0 ? 0 : T.x, needsUpdate: !0 }), Object.assign(this.mtAvatar.eyeLookInLeft, { system: T.y < 0 ? -T.y : 0, needsUpdate: !0 }), Object.assign(this.mtAvatar.eyeLookOutLeft, { system: T.y < 0 ? 0 : T.y, needsUpdate: !0 }), Object.assign(this.mtAvatar.eyeLookInRight, { system: T.y < 0 ? 0 : T.y, needsUpdate: !0 }), Object.assign(this.mtAvatar.eyeLookOutRight, { system: T.y < 0 ? -T.y : 0, needsUpdate: !0 }), a && (i = -this.mtAvatar.bodyRotateY.value, n = this.gaussianRandom(-0.2, 0.2), this.animQueue.push(this.animFactory({
|
|
5163
5163
|
name: "headmove",
|
|
5164
5164
|
dt: [[1e3, 2e3], [1e3, 2e3, 1, 2], [1e3, 2e3], [1e3, 2e3, 1, 2]],
|
|
5165
5165
|
vs: {
|
|
@@ -5251,10 +5251,10 @@ class Le {
|
|
|
5251
5251
|
let u = "", l = "", c = 0, d = [], g = [];
|
|
5252
5252
|
const f = Array.from(this.segmenter.segment(t), (x) => x.segment);
|
|
5253
5253
|
for (let x = 0; x < f.length; x++) {
|
|
5254
|
-
const I = x === f.length - 1,
|
|
5254
|
+
const I = x === f.length - 1, H = f[x].match(r);
|
|
5255
5255
|
let p = f[x].match(s);
|
|
5256
|
-
const
|
|
5257
|
-
if (p && !I && !
|
|
5256
|
+
const E = f[x].match(h), z = f[x].match(o);
|
|
5257
|
+
if (p && !I && !E && f[x + 1].match(s) && (p = !1), i && (u += f[x]), H && (!n || n.every((v) => x < v[0] || x > v[1])) && (l += f[x]), (z || p || I) && (l.length && (l = this.lipsyncPreProcessText(l, a), l.length && d.push({
|
|
5258
5258
|
mark: c,
|
|
5259
5259
|
word: l
|
|
5260
5260
|
})), u.length && (g.push({
|
|
@@ -5287,7 +5287,7 @@ class Le {
|
|
|
5287
5287
|
};
|
|
5288
5288
|
i && (v.onSubtitles = i), d.length && !e.avatarMute && (v.text = d, e.avatarMood && (v.mood = e.avatarMood), e.ttsLang && (v.lang = e.ttsLang), e.ttsVoice && (v.voice = e.ttsVoice), e.ttsRate && (v.rate = e.ttsRate), e.ttsVoice && (v.pitch = e.ttsPitch), e.ttsVolume && (v.volume = e.ttsVolume)), this.speechQueue.push(v), d = [], l = "", c = 0, g = [];
|
|
5289
5289
|
}
|
|
5290
|
-
if (
|
|
5290
|
+
if (E) {
|
|
5291
5291
|
let v = this.animEmojis[f[x]];
|
|
5292
5292
|
v && v.link && (v = this.animEmojis[v.link]), v && this.speechQueue.push({ emoji: v });
|
|
5293
5293
|
}
|
|
@@ -5385,10 +5385,10 @@ class Le {
|
|
|
5385
5385
|
let f = 0.6 + this.convertRange(g, [0, u], [0, 0.4]);
|
|
5386
5386
|
if (u = Math.min(u, c.visemes.length * 200), d > 0)
|
|
5387
5387
|
for (let x = 0; x < c.visemes.length; x++) {
|
|
5388
|
-
const I = a + c.times[x] / d * u,
|
|
5388
|
+
const I = a + c.times[x] / d * u, H = c.durations[x] / d * u;
|
|
5389
5389
|
o.push({
|
|
5390
5390
|
template: { name: "viseme" },
|
|
5391
|
-
ts: [I - Math.min(60, 2 *
|
|
5391
|
+
ts: [I - Math.min(60, 2 * H / 3), I + Math.min(25, H / 2), I + H + Math.min(60, H / 2)],
|
|
5392
5392
|
vs: {
|
|
5393
5393
|
["viseme_" + c.visemes[x]]: [null, c.visemes[x] === "PP" || c.visemes[x] === "FF" ? 0.9 : f, 0]
|
|
5394
5394
|
}
|
|
@@ -5470,7 +5470,7 @@ class Le {
|
|
|
5470
5470
|
s.lang = o, s.rate = Math.max(0.1, Math.min(10, r)), s.pitch = Math.max(0, Math.min(2, h)), s.volume = Math.max(0, Math.min(1, a));
|
|
5471
5471
|
const u = speechSynthesis.getVoices(), l = t.voice || this.avatar.ttsVoice || this.opt.ttsVoice;
|
|
5472
5472
|
if (l && u.length > 0) {
|
|
5473
|
-
const p = u.find((
|
|
5473
|
+
const p = u.find((E) => E.name.includes(l) || E.lang === o);
|
|
5474
5474
|
p && (s.voice = p);
|
|
5475
5475
|
}
|
|
5476
5476
|
const c = n.length * 100 / s.rate, d = this.audioCtx.createBuffer(1, this.audioCtx.sampleRate * (c / 1e3), this.audioCtx.sampleRate), g = this.avatar.lipsyncLang || this.opt.lipsyncLang || "en", f = this.lipsyncPreProcessText(n, g), x = this.lipsyncWordsToVisemes(f, g);
|
|
@@ -5485,8 +5485,8 @@ class Le {
|
|
|
5485
5485
|
const I = [];
|
|
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
|
-
for (let
|
|
5489
|
-
const z = x.visemes[
|
|
5488
|
+
for (let E = 0; E < x.visemes.length; E++) {
|
|
5489
|
+
const z = x.visemes[E], v = x.times[E] / p, O = x.durations[E] / p, P = v * c, K = O * c;
|
|
5490
5490
|
I.push({
|
|
5491
5491
|
template: { name: "viseme" },
|
|
5492
5492
|
ts: [P - Math.min(60, 2 * K / 3), P + Math.min(25, K / 2), P + K + Math.min(60, K / 2)],
|
|
@@ -5496,8 +5496,8 @@ class Le {
|
|
|
5496
5496
|
});
|
|
5497
5497
|
}
|
|
5498
5498
|
}
|
|
5499
|
-
const
|
|
5500
|
-
this.audioPlaylist.push({ anim:
|
|
5499
|
+
const H = [...t.anim, ...I];
|
|
5500
|
+
this.audioPlaylist.push({ anim: H, audio: d }), this.onSubtitles = t.onSubtitles || null, this.resetLips(), t.mood && this.setMood(t.mood), this.playAudio(), s.onend = () => {
|
|
5501
5501
|
e();
|
|
5502
5502
|
}, s.onerror = (p) => {
|
|
5503
5503
|
console.error("Speech synthesis error:", p.error), i(p.error);
|
|
@@ -6050,10 +6050,10 @@ class Le {
|
|
|
6050
6050
|
}
|
|
6051
6051
|
this.objectLeftEye.updateMatrixWorld(!0), this.objectRightEye.updateMatrixWorld(!0), ie.setFromMatrixPosition(this.objectLeftEye.matrixWorld), oe.setFromMatrixPosition(this.objectRightEye.matrixWorld), ie.add(oe).divideScalar(2), N.copy(this.armature.quaternion), N.multiply(this.poseTarget.props["Hips.quaternion"]), N.multiply(this.poseTarget.props["Spine.quaternion"]), N.multiply(this.poseTarget.props["Spine1.quaternion"]), N.multiply(this.poseTarget.props["Spine2.quaternion"]), N.multiply(this.poseTarget.props["Neck.quaternion"]), N.multiply(this.poseTarget.props["Head.quaternion"]);
|
|
6052
6052
|
const i = new y.Vector3().subVectors(e, ie).normalize(), n = Math.atan2(i.x, i.z), s = Math.asin(-i.y);
|
|
6053
|
-
|
|
6054
|
-
const r = new y.Quaternion().setFromEuler(
|
|
6055
|
-
|
|
6056
|
-
let a =
|
|
6053
|
+
T.set(s, n, 0, "YXZ");
|
|
6054
|
+
const r = new y.Quaternion().setFromEuler(T), h = new y.Quaternion().copy(r).multiply(N.clone().invert());
|
|
6055
|
+
T.setFromQuaternion(h, "YXZ");
|
|
6056
|
+
let a = T.x / (40 / 24) + 0.2, u = T.y / (9 / 4), l = Math.min(0.6, Math.max(-0.3, a)), c = Math.min(0.8, Math.max(-0.8, u)), d = (Math.random() - 0.5) / 4, g = (Math.random() - 0.5) / 4;
|
|
6057
6057
|
if (t) {
|
|
6058
6058
|
let f = this.animQueue.findIndex((I) => I.template.name === "lookat");
|
|
6059
6059
|
f !== -1 && this.animQueue.splice(f, 1);
|
|
@@ -6088,20 +6088,20 @@ class Le {
|
|
|
6088
6088
|
const s = new y.Vector3().setFromMatrixPosition(this.objectLeftEye.matrixWorld), o = new y.Vector3().setFromMatrixPosition(this.objectRightEye.matrixWorld), r = new y.Vector3().addVectors(s, o).divideScalar(2);
|
|
6089
6089
|
r.project(this.camera);
|
|
6090
6090
|
let h = (r.x + 1) / 2 * n.width + n.left, a = -(r.y - 1) / 2 * n.height + n.top;
|
|
6091
|
-
t === null && (t = h), e === null && (e = a), N.copy(this.armature.quaternion), N.multiply(this.poseTarget.props["Hips.quaternion"]), N.multiply(this.poseTarget.props["Spine.quaternion"]), N.multiply(this.poseTarget.props["Spine1.quaternion"]), N.multiply(this.poseTarget.props["Spine2.quaternion"]), N.multiply(this.poseTarget.props["Neck.quaternion"]), N.multiply(this.poseTarget.props["Head.quaternion"]),
|
|
6092
|
-
let u =
|
|
6091
|
+
t === null && (t = h), e === null && (e = a), N.copy(this.armature.quaternion), N.multiply(this.poseTarget.props["Hips.quaternion"]), N.multiply(this.poseTarget.props["Spine.quaternion"]), N.multiply(this.poseTarget.props["Spine1.quaternion"]), N.multiply(this.poseTarget.props["Spine2.quaternion"]), N.multiply(this.poseTarget.props["Neck.quaternion"]), N.multiply(this.poseTarget.props["Head.quaternion"]), T.setFromQuaternion(N);
|
|
6092
|
+
let u = T.x / (40 / 24), l = T.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 - h, h), f = Math.max(window.innerHeight - a, a), x = this.convertRange(e, [a - f, a + f], [-0.3, 0.6]) - u + c, I = this.convertRange(t, [h - g, h + g], [-0.8, 0.8]) - l + d;
|
|
6093
6093
|
x = Math.min(0.6, Math.max(-0.3, x)), I = Math.min(0.8, Math.max(-0.8, I));
|
|
6094
|
-
let
|
|
6094
|
+
let H = (Math.random() - 0.5) / 4, p = (Math.random() - 0.5) / 4;
|
|
6095
6095
|
if (i) {
|
|
6096
|
-
let
|
|
6097
|
-
|
|
6096
|
+
let E = this.animQueue.findIndex((v) => v.template.name === "lookat");
|
|
6097
|
+
E !== -1 && this.animQueue.splice(E, 1);
|
|
6098
6098
|
const z = {
|
|
6099
6099
|
name: "lookat",
|
|
6100
6100
|
dt: [750, i],
|
|
6101
6101
|
vs: {
|
|
6102
|
-
bodyRotateX: [x +
|
|
6102
|
+
bodyRotateX: [x + H],
|
|
6103
6103
|
bodyRotateY: [I + p],
|
|
6104
|
-
eyesRotateX: [-3 *
|
|
6104
|
+
eyesRotateX: [-3 * H + 0.1],
|
|
6105
6105
|
eyesRotateY: [-5 * p],
|
|
6106
6106
|
browInnerUp: [[0, 0.7]],
|
|
6107
6107
|
mouthLeft: [[0, 0.7]],
|
|
@@ -6479,8 +6479,8 @@ class Le {
|
|
|
6479
6479
|
const x = t.iterations || 10;
|
|
6480
6480
|
if (e)
|
|
6481
6481
|
for (let I = 0; I < x; I++) {
|
|
6482
|
-
let
|
|
6483
|
-
for (let p = 0,
|
|
6482
|
+
let H = !1;
|
|
6483
|
+
for (let p = 0, E = f.length; p < E; p++) {
|
|
6484
6484
|
const z = f[p].bone;
|
|
6485
6485
|
z.matrixWorld.decompose(h, a, u), a.invert(), o.setFromMatrixPosition(g.matrixWorld), r.subVectors(o, h), r.applyQuaternion(a), r.normalize(), s.subVectors(e, h), s.applyQuaternion(a), s.normalize();
|
|
6486
6486
|
let v = s.dot(r);
|
|
@@ -6492,9 +6492,9 @@ class Le {
|
|
|
6492
6492
|
f[p].maxx !== void 0 ? f[p].maxx : 1 / 0,
|
|
6493
6493
|
f[p].maxy !== void 0 ? f[p].maxy : 1 / 0,
|
|
6494
6494
|
f[p].maxz !== void 0 ? f[p].maxz : 1 / 0
|
|
6495
|
-
))), z.updateMatrixWorld(!0),
|
|
6495
|
+
))), z.updateMatrixWorld(!0), H = !0);
|
|
6496
6496
|
}
|
|
6497
|
-
if (!
|
|
6497
|
+
if (!H) break;
|
|
6498
6498
|
}
|
|
6499
6499
|
n && f.forEach((I) => {
|
|
6500
6500
|
this.poseTarget.props[I.link + ".quaternion"].copy(I.bone.quaternion), this.poseTarget.props[I.link + ".quaternion"].t = this.animClock, this.poseTarget.props[I.link + ".quaternion"].d = n;
|
|
@@ -6568,7 +6568,7 @@ const Se = ye(({
|
|
|
6568
6568
|
style: f = {},
|
|
6569
6569
|
animations: x = {}
|
|
6570
6570
|
}, I) => {
|
|
6571
|
-
const
|
|
6571
|
+
const H = X(null), p = X(null), [E, z] = re(!0), [v, O] = re(null), [P, K] = re(!1), J = xe(), S = n || J.service;
|
|
6572
6572
|
let F;
|
|
6573
6573
|
S === "browser" ? F = {
|
|
6574
6574
|
service: "browser",
|
|
@@ -6602,10 +6602,10 @@ const Se = ye(({
|
|
|
6602
6602
|
ttsService: S,
|
|
6603
6603
|
lipsyncModules: ["en"],
|
|
6604
6604
|
cameraView: u
|
|
6605
|
-
}, j =
|
|
6606
|
-
if (!(!
|
|
6605
|
+
}, j = M(async () => {
|
|
6606
|
+
if (!(!H.current || p.current))
|
|
6607
6607
|
try {
|
|
6608
|
-
if (z(!0), O(null), p.current = new Le(
|
|
6608
|
+
if (z(!0), O(null), p.current = new Le(H.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), x && Object.keys(x).length > 0 && (p.current.customAnimations = x), await p.current.showAvatar(W, (U) => {
|
|
6609
6609
|
if (U.lengthComputable) {
|
|
6610
6610
|
const D = Math.min(100, Math.round(U.loaded / U.total * 100));
|
|
6611
6611
|
c(D);
|
|
@@ -6622,11 +6622,11 @@ const Se = ye(({
|
|
|
6622
6622
|
console.warn("Error setting full body mode on initialization:", U);
|
|
6623
6623
|
}
|
|
6624
6624
|
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()), z(!1), K(!0), l(p.current);
|
|
6625
|
-
const
|
|
6625
|
+
const C = () => {
|
|
6626
6626
|
document.visibilityState === "visible" ? p.current?.start() : p.current?.stop();
|
|
6627
6627
|
};
|
|
6628
|
-
return document.addEventListener("visibilitychange",
|
|
6629
|
-
document.removeEventListener("visibilitychange",
|
|
6628
|
+
return document.addEventListener("visibilitychange", C), () => {
|
|
6629
|
+
document.removeEventListener("visibilitychange", C);
|
|
6630
6630
|
};
|
|
6631
6631
|
} catch (L) {
|
|
6632
6632
|
console.error("Error initializing TalkingHead:", L), O(L.message || "Failed to initialize avatar"), z(!1), d(L);
|
|
@@ -6635,42 +6635,42 @@ const Se = ye(({
|
|
|
6635
6635
|
he(() => (j(), () => {
|
|
6636
6636
|
p.current && (p.current.stop(), p.current.dispose(), p.current = null);
|
|
6637
6637
|
}), [j]), he(() => {
|
|
6638
|
-
if (!
|
|
6638
|
+
if (!H.current || !p.current) return;
|
|
6639
6639
|
const L = new ResizeObserver((U) => {
|
|
6640
6640
|
for (const D of U)
|
|
6641
6641
|
p.current && p.current.onResize && p.current.onResize();
|
|
6642
6642
|
});
|
|
6643
|
-
L.observe(
|
|
6644
|
-
const
|
|
6643
|
+
L.observe(H.current);
|
|
6644
|
+
const C = () => {
|
|
6645
6645
|
p.current && p.current.onResize && p.current.onResize();
|
|
6646
6646
|
};
|
|
6647
|
-
return window.addEventListener("resize",
|
|
6648
|
-
L.disconnect(), window.removeEventListener("resize",
|
|
6647
|
+
return window.addEventListener("resize", C), () => {
|
|
6648
|
+
L.disconnect(), window.removeEventListener("resize", C);
|
|
6649
6649
|
};
|
|
6650
6650
|
}, [P]);
|
|
6651
|
-
const Q =
|
|
6651
|
+
const Q = M(async () => {
|
|
6652
6652
|
if (p.current && p.current.audioCtx)
|
|
6653
6653
|
try {
|
|
6654
6654
|
(p.current.audioCtx.state === "suspended" || p.current.audioCtx.state === "interrupted") && (await p.current.audioCtx.resume(), console.log("Audio context resumed"));
|
|
6655
6655
|
} catch (L) {
|
|
6656
6656
|
console.warn("Failed to resume audio context:", L);
|
|
6657
6657
|
}
|
|
6658
|
-
}, []), le =
|
|
6658
|
+
}, []), le = M(async (L, C = {}) => {
|
|
6659
6659
|
if (p.current && P)
|
|
6660
6660
|
try {
|
|
6661
6661
|
await Q();
|
|
6662
6662
|
const U = {
|
|
6663
|
-
...
|
|
6664
|
-
lipsyncLang:
|
|
6663
|
+
...C,
|
|
6664
|
+
lipsyncLang: C.lipsyncLang || W.lipsyncLang || "en"
|
|
6665
6665
|
};
|
|
6666
|
-
if (
|
|
6666
|
+
if (C.onSpeechEnd && p.current) {
|
|
6667
6667
|
const D = p.current, ne = D.onAudioEnd;
|
|
6668
6668
|
let $ = null, pe = 0;
|
|
6669
6669
|
const we = 600, ze = () => {
|
|
6670
6670
|
if (pe++, pe > we) {
|
|
6671
6671
|
$ && (clearInterval($), $ = null);
|
|
6672
6672
|
try {
|
|
6673
|
-
|
|
6673
|
+
C.onSpeechEnd();
|
|
6674
6674
|
} catch (ge) {
|
|
6675
6675
|
console.error("Error in onSpeechEnd callback:", ge);
|
|
6676
6676
|
}
|
|
@@ -6678,7 +6678,7 @@ const Se = ye(({
|
|
|
6678
6678
|
}
|
|
6679
6679
|
D && (!D.isSpeaking || D.isSpeaking === !1) && (!D.audioPlaylist || D.audioPlaylist.length === 0) && (!D.isAudioPlaying || D.isAudioPlaying === !1) && ($ && (clearInterval($), $ = null), setTimeout(() => {
|
|
6680
6680
|
try {
|
|
6681
|
-
|
|
6681
|
+
C.onSpeechEnd();
|
|
6682
6682
|
} catch (ge) {
|
|
6683
6683
|
console.error("Error in onSpeechEnd callback:", ge);
|
|
6684
6684
|
}
|
|
@@ -6694,13 +6694,13 @@ const Se = ye(({
|
|
|
6694
6694
|
} catch (U) {
|
|
6695
6695
|
console.error("Error speaking text:", U), O(U.message || "Failed to speak text");
|
|
6696
6696
|
}
|
|
6697
|
-
}, [P, Q, W.lipsyncLang]), me =
|
|
6697
|
+
}, [P, Q, W.lipsyncLang]), me = M(() => {
|
|
6698
6698
|
p.current && (p.current.stopSpeaking(), p.current.setSlowdownRate && p.current.setSlowdownRate(1));
|
|
6699
|
-
}, []), q =
|
|
6699
|
+
}, []), q = M((L) => {
|
|
6700
6700
|
p.current && p.current.setMood(L);
|
|
6701
|
-
}, []),
|
|
6701
|
+
}, []), b = M((L) => {
|
|
6702
6702
|
p.current && p.current.setSlowdownRate && p.current.setSlowdownRate(L);
|
|
6703
|
-
}, []),
|
|
6703
|
+
}, []), R = M((L, C = !1) => {
|
|
6704
6704
|
if (p.current && p.current.playAnimation) {
|
|
6705
6705
|
if (x && x[L] && (L = x[L]), p.current.setShowFullAvatar)
|
|
6706
6706
|
try {
|
|
@@ -6710,7 +6710,7 @@ const Se = ye(({
|
|
|
6710
6710
|
}
|
|
6711
6711
|
if (L.includes("."))
|
|
6712
6712
|
try {
|
|
6713
|
-
p.current.playAnimation(L, null, 10, 0, 0.01,
|
|
6713
|
+
p.current.playAnimation(L, null, 10, 0, 0.01, C);
|
|
6714
6714
|
} catch (D) {
|
|
6715
6715
|
console.warn(`Failed to play ${L}:`, D);
|
|
6716
6716
|
try {
|
|
@@ -6724,7 +6724,7 @@ const Se = ye(({
|
|
|
6724
6724
|
let ne = !1;
|
|
6725
6725
|
for (const $ of D)
|
|
6726
6726
|
try {
|
|
6727
|
-
p.current.playAnimation(L + $, null, 10, 0, 0.01,
|
|
6727
|
+
p.current.playAnimation(L + $, null, 10, 0, 0.01, C), ne = !0;
|
|
6728
6728
|
break;
|
|
6729
6729
|
} catch {
|
|
6730
6730
|
}
|
|
@@ -6738,7 +6738,7 @@ const Se = ye(({
|
|
|
6738
6738
|
}
|
|
6739
6739
|
}
|
|
6740
6740
|
}
|
|
6741
|
-
}, [x]), w =
|
|
6741
|
+
}, [x]), w = M(() => {
|
|
6742
6742
|
p.current && p.current.onResize && p.current.onResize();
|
|
6743
6743
|
}, []);
|
|
6744
6744
|
return fe(I, () => ({
|
|
@@ -6746,8 +6746,8 @@ const Se = ye(({
|
|
|
6746
6746
|
stopSpeaking: me,
|
|
6747
6747
|
resumeAudioContext: Q,
|
|
6748
6748
|
setMood: q,
|
|
6749
|
-
setTimingAdjustment:
|
|
6750
|
-
playAnimation:
|
|
6749
|
+
setTimingAdjustment: b,
|
|
6750
|
+
playAnimation: R,
|
|
6751
6751
|
isReady: P,
|
|
6752
6752
|
talkingHead: p.current,
|
|
6753
6753
|
handleResize: w,
|
|
@@ -6755,8 +6755,8 @@ const Se = ye(({
|
|
|
6755
6755
|
if (p.current && p.current.setShowFullAvatar && p.current.setBodyMovement)
|
|
6756
6756
|
try {
|
|
6757
6757
|
p.current.setShowFullAvatar(!0), p.current.setBodyMovement(L);
|
|
6758
|
-
} catch (
|
|
6759
|
-
console.warn("Error setting body movement:",
|
|
6758
|
+
} catch (C) {
|
|
6759
|
+
console.warn("Error setting body movement:", C);
|
|
6760
6760
|
}
|
|
6761
6761
|
},
|
|
6762
6762
|
setMovementIntensity: (L) => p.current?.setMovementIntensity(L),
|
|
@@ -6772,8 +6772,8 @@ const Se = ye(({
|
|
|
6772
6772
|
if (p.current && p.current.setShowFullAvatar && p.current.playReaction)
|
|
6773
6773
|
try {
|
|
6774
6774
|
p.current.setShowFullAvatar(!0), p.current.playReaction(L);
|
|
6775
|
-
} catch (
|
|
6776
|
-
console.warn("Error playing reaction:",
|
|
6775
|
+
} catch (C) {
|
|
6776
|
+
console.warn("Error playing reaction:", C);
|
|
6777
6777
|
}
|
|
6778
6778
|
},
|
|
6779
6779
|
playCelebration: () => {
|
|
@@ -6788,8 +6788,8 @@ const Se = ye(({
|
|
|
6788
6788
|
if (p.current && p.current.setShowFullAvatar)
|
|
6789
6789
|
try {
|
|
6790
6790
|
p.current.setShowFullAvatar(L);
|
|
6791
|
-
} catch (
|
|
6792
|
-
console.warn("Error setting showFullAvatar:",
|
|
6791
|
+
} catch (C) {
|
|
6792
|
+
console.warn("Error setting showFullAvatar:", C);
|
|
6793
6793
|
}
|
|
6794
6794
|
},
|
|
6795
6795
|
lockAvatarPosition: () => {
|
|
@@ -6822,7 +6822,7 @@ const Se = ye(({
|
|
|
6822
6822
|
/* @__PURE__ */ se(
|
|
6823
6823
|
"div",
|
|
6824
6824
|
{
|
|
6825
|
-
ref:
|
|
6825
|
+
ref: H,
|
|
6826
6826
|
className: "talking-head-viewer",
|
|
6827
6827
|
style: {
|
|
6828
6828
|
width: "100%",
|
|
@@ -6831,7 +6831,7 @@ const Se = ye(({
|
|
|
6831
6831
|
}
|
|
6832
6832
|
}
|
|
6833
6833
|
),
|
|
6834
|
-
|
|
6834
|
+
E && /* @__PURE__ */ se("div", { className: "loading-overlay", style: {
|
|
6835
6835
|
position: "absolute",
|
|
6836
6836
|
top: "50%",
|
|
6837
6837
|
left: "50%",
|
|
@@ -6869,7 +6869,7 @@ const Je = ye(({
|
|
|
6869
6869
|
style: s = {},
|
|
6870
6870
|
avatarConfig: o = {}
|
|
6871
6871
|
}, r) => {
|
|
6872
|
-
const h = X(null), a = X(null), [u, l] = re(!0), [c, d] = re(null), [g, f] = re(!1), x = xe(), I = o.ttsService || x.service,
|
|
6872
|
+
const h = X(null), a = X(null), [u, l] = re(!0), [c, d] = re(null), [g, f] = re(!1), x = xe(), I = o.ttsService || x.service, H = I === "browser" ? {
|
|
6873
6873
|
endpoint: "",
|
|
6874
6874
|
apiKey: null,
|
|
6875
6875
|
defaultVoice: "Google US English"
|
|
@@ -6885,7 +6885,7 @@ const Je = ye(({
|
|
|
6885
6885
|
body: "F",
|
|
6886
6886
|
avatarMood: "neutral",
|
|
6887
6887
|
ttsLang: I === "browser" ? "en-US" : "en",
|
|
6888
|
-
ttsVoice: o.ttsVoice ||
|
|
6888
|
+
ttsVoice: o.ttsVoice || H.defaultVoice,
|
|
6889
6889
|
lipsyncLang: "en",
|
|
6890
6890
|
// English lip-sync
|
|
6891
6891
|
showFullAvatar: !0,
|
|
@@ -6893,16 +6893,16 @@ const Je = ye(({
|
|
|
6893
6893
|
bodyMovement: "idle",
|
|
6894
6894
|
movementIntensity: 0.5,
|
|
6895
6895
|
...o
|
|
6896
|
-
},
|
|
6897
|
-
ttsEndpoint:
|
|
6898
|
-
ttsApikey:
|
|
6896
|
+
}, E = {
|
|
6897
|
+
ttsEndpoint: H.endpoint,
|
|
6898
|
+
ttsApikey: H.apiKey,
|
|
6899
6899
|
ttsService: I,
|
|
6900
6900
|
lipsyncModules: ["en"],
|
|
6901
6901
|
cameraView: "upper"
|
|
6902
|
-
}, z =
|
|
6902
|
+
}, z = M(async () => {
|
|
6903
6903
|
if (!(!h.current || a.current))
|
|
6904
6904
|
try {
|
|
6905
|
-
if (l(!0), d(null), a.current = new Le(h.current,
|
|
6905
|
+
if (l(!0), d(null), a.current = new Le(h.current, E), await a.current.showAvatar(p, (W) => {
|
|
6906
6906
|
if (W.lengthComputable) {
|
|
6907
6907
|
const V = Math.min(100, Math.round(W.loaded / W.total * 100));
|
|
6908
6908
|
t(V);
|
|
@@ -6938,7 +6938,7 @@ const Je = ye(({
|
|
|
6938
6938
|
he(() => (z(), () => {
|
|
6939
6939
|
a.current && (a.current.stop(), a.current.dispose(), a.current = null);
|
|
6940
6940
|
}), [z]);
|
|
6941
|
-
const v =
|
|
6941
|
+
const v = M((S) => {
|
|
6942
6942
|
if (a.current && g)
|
|
6943
6943
|
try {
|
|
6944
6944
|
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(() => {
|
|
@@ -6949,13 +6949,13 @@ const Je = ye(({
|
|
|
6949
6949
|
}
|
|
6950
6950
|
else
|
|
6951
6951
|
console.warn("Avatar not ready for speaking. isReady:", g, "talkingHeadRef:", !!a.current);
|
|
6952
|
-
}, [g, p]), O =
|
|
6952
|
+
}, [g, p]), O = M(() => {
|
|
6953
6953
|
a.current && (a.current.stopSpeaking(), a.current.setSlowdownRate && (a.current.setSlowdownRate(1), console.log("Reset timing to normal")));
|
|
6954
|
-
}, []), P =
|
|
6954
|
+
}, []), P = M((S) => {
|
|
6955
6955
|
a.current && a.current.setMood(S);
|
|
6956
|
-
}, []), K =
|
|
6956
|
+
}, []), K = M((S) => {
|
|
6957
6957
|
a.current && a.current.setSlowdownRate && (a.current.setSlowdownRate(S), console.log("Timing adjustment set to:", S));
|
|
6958
|
-
}, []), J =
|
|
6958
|
+
}, []), J = M((S, F = !1) => {
|
|
6959
6959
|
if (a.current && a.current.playAnimation) {
|
|
6960
6960
|
if (a.current.setShowFullAvatar)
|
|
6961
6961
|
try {
|
|
@@ -7130,7 +7130,7 @@ const $e = ye(({
|
|
|
7130
7130
|
onQuestionAnswer: s,
|
|
7131
7131
|
onCurriculumComplete: o,
|
|
7132
7132
|
onCustomAction: r
|
|
7133
|
-
}), d = X(null), g = X(null), f = X(null), x = X(null), I = X(null),
|
|
7133
|
+
}), d = X(null), g = X(null), f = X(null), x = X(null), I = X(null), H = X(null), p = X(null), E = X(B?.curriculum || {
|
|
7134
7134
|
title: "Default Curriculum",
|
|
7135
7135
|
description: "No curriculum data provided",
|
|
7136
7136
|
language: "en",
|
|
@@ -7158,7 +7158,7 @@ const $e = ye(({
|
|
|
7158
7158
|
onCustomAction: r
|
|
7159
7159
|
};
|
|
7160
7160
|
}, [i, n, s, o, r]), he(() => {
|
|
7161
|
-
|
|
7161
|
+
E.current = B?.curriculum || {
|
|
7162
7162
|
title: "Default Curriculum",
|
|
7163
7163
|
description: "No curriculum data provided",
|
|
7164
7164
|
language: "en",
|
|
@@ -7178,23 +7178,23 @@ const $e = ye(({
|
|
|
7178
7178
|
lipsyncLang: "en"
|
|
7179
7179
|
};
|
|
7180
7180
|
}, [B, t, e]);
|
|
7181
|
-
const v =
|
|
7181
|
+
const v = M(() => (E.current || { modules: [] }).modules[l.current.currentModuleIndex]?.lessons[l.current.currentLessonIndex], []), O = M(() => v()?.questions[l.current.currentQuestionIndex], [v]), P = M((b, R) => R.type === "multiple_choice" || R.type === "true_false" ? b === R.answer : R.type === "code_test" && typeof b == "object" && b !== null ? b.passed === !0 : !1, []), K = M(() => {
|
|
7182
7182
|
l.current.lessonCompleted = !0, l.current.isQuestionMode = !1;
|
|
7183
|
-
const
|
|
7184
|
-
let
|
|
7185
|
-
if (l.current.totalQuestions > 0 ?
|
|
7183
|
+
const b = l.current.totalQuestions > 0 ? Math.round(l.current.score / l.current.totalQuestions * 100) : 100;
|
|
7184
|
+
let R = "Congratulations! You've completed this lesson";
|
|
7185
|
+
if (l.current.totalQuestions > 0 ? R += ` with a score of ${l.current.score} out of ${l.current.totalQuestions} (${b}%). ` : R += "! ", b >= 80 ? R += "Excellent work! You have a great understanding of this topic." : b >= 60 ? R += "Good job! You understand most of the concepts." : R += "Keep practicing! You're making progress.", c.current.onLessonComplete({
|
|
7186
7186
|
moduleIndex: l.current.currentModuleIndex,
|
|
7187
7187
|
lessonIndex: l.current.currentLessonIndex,
|
|
7188
7188
|
score: l.current.score,
|
|
7189
7189
|
totalQuestions: l.current.totalQuestions,
|
|
7190
|
-
percentage:
|
|
7190
|
+
percentage: b
|
|
7191
7191
|
}), c.current.onCustomAction({
|
|
7192
7192
|
type: "lessonComplete",
|
|
7193
7193
|
moduleIndex: l.current.currentModuleIndex,
|
|
7194
7194
|
lessonIndex: l.current.currentLessonIndex,
|
|
7195
7195
|
score: l.current.score,
|
|
7196
7196
|
totalQuestions: l.current.totalQuestions,
|
|
7197
|
-
percentage:
|
|
7197
|
+
percentage: b
|
|
7198
7198
|
}), u.current) {
|
|
7199
7199
|
if (u.current.setMood("happy"), e.lessonComplete)
|
|
7200
7200
|
try {
|
|
@@ -7202,29 +7202,29 @@ const $e = ye(({
|
|
|
7202
7202
|
} catch {
|
|
7203
7203
|
u.current.playCelebration();
|
|
7204
7204
|
}
|
|
7205
|
-
const w =
|
|
7206
|
-
D ? u.current.speakText(
|
|
7205
|
+
const w = E.current || { modules: [] }, L = w.modules[l.current.currentModuleIndex], C = l.current.currentLessonIndex < (L?.lessons?.length || 0) - 1, U = l.current.currentModuleIndex < (w.modules?.length || 0) - 1, D = C || U, ne = z.current || { lipsyncLang: "en" };
|
|
7206
|
+
D ? u.current.speakText(R, {
|
|
7207
7207
|
lipsyncLang: ne.lipsyncLang,
|
|
7208
7208
|
onSpeechEnd: () => {
|
|
7209
7209
|
setTimeout(() => {
|
|
7210
7210
|
g.current && g.current();
|
|
7211
|
-
},
|
|
7211
|
+
}, 300);
|
|
7212
7212
|
}
|
|
7213
|
-
}) : u.current.speakText(
|
|
7213
|
+
}) : u.current.speakText(R, {
|
|
7214
7214
|
lipsyncLang: ne.lipsyncLang,
|
|
7215
7215
|
onSpeechEnd: () => {
|
|
7216
7216
|
setTimeout(() => {
|
|
7217
7217
|
I.current && I.current();
|
|
7218
|
-
},
|
|
7218
|
+
}, 300);
|
|
7219
7219
|
}
|
|
7220
7220
|
});
|
|
7221
7221
|
}
|
|
7222
|
-
}, [e.lessonComplete]), J =
|
|
7222
|
+
}, [e.lessonComplete]), J = M(() => {
|
|
7223
7223
|
l.current.curriculumCompleted = !0;
|
|
7224
|
-
const
|
|
7224
|
+
const b = E.current || { modules: [] };
|
|
7225
7225
|
if (c.current.onCurriculumComplete({
|
|
7226
|
-
modules:
|
|
7227
|
-
totalLessons:
|
|
7226
|
+
modules: b.modules.length,
|
|
7227
|
+
totalLessons: b.modules.reduce((R, w) => R + w.lessons.length, 0)
|
|
7228
7228
|
}), u.current) {
|
|
7229
7229
|
if (u.current.setMood("celebrating"), e.curriculumComplete)
|
|
7230
7230
|
try {
|
|
@@ -7232,21 +7232,21 @@ const $e = ye(({
|
|
|
7232
7232
|
} catch {
|
|
7233
7233
|
u.current.playCelebration();
|
|
7234
7234
|
}
|
|
7235
|
-
const
|
|
7236
|
-
u.current.speakText("Amazing! You've completed the entire curriculum! You're now ready to move on to more advanced topics. Well done!", { lipsyncLang:
|
|
7235
|
+
const R = z.current || { lipsyncLang: "en" };
|
|
7236
|
+
u.current.speakText("Amazing! You've completed the entire curriculum! You're now ready to move on to more advanced topics. Well done!", { lipsyncLang: R.lipsyncLang });
|
|
7237
7237
|
}
|
|
7238
|
-
}, [e.curriculumComplete]), S =
|
|
7239
|
-
const
|
|
7240
|
-
l.current.isQuestionMode = !0, l.current.currentQuestionIndex = 0, l.current.totalQuestions =
|
|
7241
|
-
const
|
|
7242
|
-
if (
|
|
7238
|
+
}, [e.curriculumComplete]), S = M(() => {
|
|
7239
|
+
const b = v();
|
|
7240
|
+
l.current.isQuestionMode = !0, l.current.currentQuestionIndex = 0, l.current.totalQuestions = b?.questions?.length || 0;
|
|
7241
|
+
const R = O();
|
|
7242
|
+
if (R && c.current.onCustomAction({
|
|
7243
7243
|
type: "questionStart",
|
|
7244
7244
|
moduleIndex: l.current.currentModuleIndex,
|
|
7245
7245
|
lessonIndex: l.current.currentLessonIndex,
|
|
7246
7246
|
questionIndex: l.current.currentQuestionIndex,
|
|
7247
7247
|
totalQuestions: l.current.totalQuestions,
|
|
7248
|
-
question:
|
|
7249
|
-
}), u.current &&
|
|
7248
|
+
question: R
|
|
7249
|
+
}), u.current && R) {
|
|
7250
7250
|
if (u.current.setMood("curious"), e.questionStart)
|
|
7251
7251
|
try {
|
|
7252
7252
|
u.current.playAnimation(e.questionStart, !0);
|
|
@@ -7254,24 +7254,24 @@ const $e = ye(({
|
|
|
7254
7254
|
console.warn("Failed to play questionStart animation:", L);
|
|
7255
7255
|
}
|
|
7256
7256
|
const w = z.current || { lipsyncLang: "en" };
|
|
7257
|
-
|
|
7257
|
+
R.type === "code_test" ? u.current.speakText(`Let's test your coding skills! Here's your first challenge: ${R.question}`, { lipsyncLang: w.lipsyncLang }) : R.type === "multiple_choice" ? u.current.speakText(`Now let me ask you some questions. Here's the first one: ${R.question}`, { lipsyncLang: w.lipsyncLang }) : R.type === "true_false" ? u.current.speakText(`Let's start with some true or false questions. First question: ${R.question}`, { lipsyncLang: w.lipsyncLang }) : u.current.speakText(`Now let me ask you some questions. Here's the first one: ${R.question}`, { lipsyncLang: w.lipsyncLang });
|
|
7258
7258
|
} else if (u.current) {
|
|
7259
7259
|
const w = z.current || { lipsyncLang: "en" };
|
|
7260
7260
|
u.current.speakText("Now let me ask you some questions to test your understanding.", { lipsyncLang: w.lipsyncLang });
|
|
7261
7261
|
}
|
|
7262
|
-
}, [e.questionStart, v, O]), F =
|
|
7263
|
-
const
|
|
7264
|
-
if (l.current.currentQuestionIndex < (
|
|
7262
|
+
}, [e.questionStart, v, O]), F = M(() => {
|
|
7263
|
+
const b = v();
|
|
7264
|
+
if (l.current.currentQuestionIndex < (b?.questions?.length || 0) - 1) {
|
|
7265
7265
|
l.current.currentQuestionIndex += 1;
|
|
7266
|
-
const
|
|
7267
|
-
if (
|
|
7266
|
+
const R = O();
|
|
7267
|
+
if (R && c.current.onCustomAction({
|
|
7268
7268
|
type: "nextQuestion",
|
|
7269
7269
|
moduleIndex: l.current.currentModuleIndex,
|
|
7270
7270
|
lessonIndex: l.current.currentLessonIndex,
|
|
7271
7271
|
questionIndex: l.current.currentQuestionIndex,
|
|
7272
7272
|
totalQuestions: l.current.totalQuestions,
|
|
7273
|
-
question:
|
|
7274
|
-
}), u.current &&
|
|
7273
|
+
question: R
|
|
7274
|
+
}), u.current && R) {
|
|
7275
7275
|
if (u.current.setMood("happy"), u.current.setBodyMovement("idle"), e.nextQuestion)
|
|
7276
7276
|
try {
|
|
7277
7277
|
u.current.playAnimation(e.nextQuestion, !0);
|
|
@@ -7279,73 +7279,79 @@ const $e = ye(({
|
|
|
7279
7279
|
console.warn("Failed to play nextQuestion animation:", L);
|
|
7280
7280
|
}
|
|
7281
7281
|
const w = z.current || { lipsyncLang: "en" };
|
|
7282
|
-
|
|
7282
|
+
R.type === "code_test" ? u.current.speakText(`Great! Now let's move on to your next coding challenge: ${R.question}`, {
|
|
7283
7283
|
lipsyncLang: w.lipsyncLang
|
|
7284
|
-
}) :
|
|
7284
|
+
}) : R.type === "multiple_choice" ? u.current.speakText(`Alright! Here's your next question: ${R.question}`, {
|
|
7285
7285
|
lipsyncLang: w.lipsyncLang
|
|
7286
|
-
}) :
|
|
7286
|
+
}) : R.type === "true_false" ? u.current.speakText(`Now let's try this one: ${R.question}`, {
|
|
7287
7287
|
lipsyncLang: w.lipsyncLang
|
|
7288
|
-
}) : u.current.speakText(`Here's the next question: ${
|
|
7288
|
+
}) : u.current.speakText(`Here's the next question: ${R.question}`, {
|
|
7289
7289
|
lipsyncLang: w.lipsyncLang
|
|
7290
7290
|
});
|
|
7291
7291
|
}
|
|
7292
7292
|
} else
|
|
7293
7293
|
f.current && f.current();
|
|
7294
|
-
}, [e.nextQuestion, v, O]), W =
|
|
7295
|
-
const
|
|
7296
|
-
l.current.currentLessonIndex < (
|
|
7294
|
+
}, [e.nextQuestion, v, O]), W = M(() => {
|
|
7295
|
+
const b = E.current || { modules: [] }, R = b.modules[l.current.currentModuleIndex];
|
|
7296
|
+
l.current.currentLessonIndex < (R?.lessons?.length || 0) - 1 ? (l.current.currentLessonIndex += 1, l.current.currentQuestionIndex = 0, l.current.lessonCompleted = !1, l.current.isQuestionMode = !1, l.current.isTeaching = !1, l.current.score = 0, l.current.totalQuestions = 0, c.current.onCustomAction({
|
|
7297
7297
|
type: "lessonStart",
|
|
7298
7298
|
moduleIndex: l.current.currentModuleIndex,
|
|
7299
7299
|
lessonIndex: l.current.currentLessonIndex
|
|
7300
7300
|
}), u.current && (u.current.setMood("happy"), u.current.setBodyMovement("idle"), setTimeout(() => {
|
|
7301
7301
|
d.current && d.current();
|
|
7302
|
-
},
|
|
7302
|
+
}, 300))) : l.current.currentModuleIndex < (b.modules?.length || 0) - 1 ? (l.current.currentModuleIndex += 1, l.current.currentLessonIndex = 0, l.current.currentQuestionIndex = 0, l.current.lessonCompleted = !1, l.current.isQuestionMode = !1, l.current.isTeaching = !1, l.current.score = 0, l.current.totalQuestions = 0, c.current.onCustomAction({
|
|
7303
7303
|
type: "lessonStart",
|
|
7304
7304
|
moduleIndex: l.current.currentModuleIndex,
|
|
7305
7305
|
lessonIndex: l.current.currentLessonIndex
|
|
7306
7306
|
}), u.current && (u.current.setMood("happy"), u.current.setBodyMovement("idle"), setTimeout(() => {
|
|
7307
7307
|
d.current && d.current();
|
|
7308
|
-
},
|
|
7309
|
-
}, []), V =
|
|
7310
|
-
const
|
|
7311
|
-
|
|
7308
|
+
}, 300))) : I.current && I.current();
|
|
7309
|
+
}, []), V = M(() => {
|
|
7310
|
+
const b = v();
|
|
7311
|
+
let R = null;
|
|
7312
|
+
if (b?.avatar_script && b?.body) {
|
|
7313
|
+
const w = b.avatar_script.trim(), L = b.body.trim(), C = w.match(/[.!?]$/) ? " " : ". ";
|
|
7314
|
+
R = `${w}${C}${L}`;
|
|
7315
|
+
} else
|
|
7316
|
+
R = b?.avatar_script || b?.body || null;
|
|
7317
|
+
if (u.current && u.current.isReady && R) {
|
|
7312
7318
|
l.current.isTeaching = !0, l.current.isQuestionMode = !1, u.current.setMood("happy");
|
|
7313
|
-
let
|
|
7319
|
+
let w = !1;
|
|
7314
7320
|
if (e.teaching)
|
|
7315
7321
|
try {
|
|
7316
|
-
u.current.playAnimation(e.teaching, !0),
|
|
7317
|
-
} catch (
|
|
7318
|
-
console.warn("Failed to play teaching animation:",
|
|
7322
|
+
u.current.playAnimation(e.teaching, !0), w = !0;
|
|
7323
|
+
} catch (C) {
|
|
7324
|
+
console.warn("Failed to play teaching animation:", C);
|
|
7319
7325
|
}
|
|
7320
|
-
|
|
7321
|
-
const
|
|
7326
|
+
w || u.current.setBodyMovement("gesturing");
|
|
7327
|
+
const L = z.current || { lipsyncLang: "en" };
|
|
7322
7328
|
c.current.onLessonStart({
|
|
7323
7329
|
moduleIndex: l.current.currentModuleIndex,
|
|
7324
7330
|
lessonIndex: l.current.currentLessonIndex,
|
|
7325
|
-
lesson:
|
|
7331
|
+
lesson: b
|
|
7326
7332
|
}), c.current.onCustomAction({
|
|
7327
7333
|
type: "teachingStart",
|
|
7328
7334
|
moduleIndex: l.current.currentModuleIndex,
|
|
7329
7335
|
lessonIndex: l.current.currentLessonIndex,
|
|
7330
|
-
lesson:
|
|
7331
|
-
}), u.current.speakText(R
|
|
7332
|
-
lipsyncLang:
|
|
7336
|
+
lesson: b
|
|
7337
|
+
}), u.current.speakText(R, {
|
|
7338
|
+
lipsyncLang: L.lipsyncLang,
|
|
7333
7339
|
onSpeechEnd: () => {
|
|
7334
7340
|
l.current.isTeaching = !1, setTimeout(() => {
|
|
7335
|
-
|
|
7336
|
-
},
|
|
7341
|
+
b.questions && b.questions.length > 0 ? H.current && H.current() : f.current && f.current();
|
|
7342
|
+
}, 200);
|
|
7337
7343
|
}
|
|
7338
7344
|
});
|
|
7339
7345
|
}
|
|
7340
|
-
}, [e.teaching, v]), j =
|
|
7341
|
-
const
|
|
7346
|
+
}, [e.teaching, v]), j = M((b) => {
|
|
7347
|
+
const R = O(), w = P(b, R);
|
|
7342
7348
|
if (w && (l.current.score += 1), c.current.onQuestionAnswer({
|
|
7343
7349
|
moduleIndex: l.current.currentModuleIndex,
|
|
7344
7350
|
lessonIndex: l.current.currentLessonIndex,
|
|
7345
7351
|
questionIndex: l.current.currentQuestionIndex,
|
|
7346
|
-
answer:
|
|
7352
|
+
answer: b,
|
|
7347
7353
|
isCorrect: w,
|
|
7348
|
-
question:
|
|
7354
|
+
question: R
|
|
7349
7355
|
}), u.current)
|
|
7350
7356
|
if (w) {
|
|
7351
7357
|
if (u.current.setMood("happy"), e.correct)
|
|
@@ -7355,13 +7361,13 @@ const $e = ye(({
|
|
|
7355
7361
|
u.current.setBodyMovement("happy");
|
|
7356
7362
|
}
|
|
7357
7363
|
u.current.setBodyMovement("gesturing");
|
|
7358
|
-
const L =
|
|
7364
|
+
const L = R.type === "code_test" ? `Great job! Your code passed all the tests! ${R.explanation || ""}` : `Excellent! That's correct! ${R.explanation || ""}`, C = z.current || { lipsyncLang: "en" };
|
|
7359
7365
|
u.current.speakText(L, {
|
|
7360
|
-
lipsyncLang:
|
|
7366
|
+
lipsyncLang: C.lipsyncLang,
|
|
7361
7367
|
onSpeechEnd: () => {
|
|
7362
7368
|
setTimeout(() => {
|
|
7363
7369
|
x.current && x.current();
|
|
7364
|
-
},
|
|
7370
|
+
}, 200);
|
|
7365
7371
|
}
|
|
7366
7372
|
});
|
|
7367
7373
|
} else {
|
|
@@ -7372,37 +7378,37 @@ const $e = ye(({
|
|
|
7372
7378
|
u.current.setBodyMovement("idle");
|
|
7373
7379
|
}
|
|
7374
7380
|
u.current.setBodyMovement("gesturing");
|
|
7375
|
-
const L =
|
|
7381
|
+
const L = R.type === "code_test" ? `Your code didn't pass all the tests. ${R.explanation || "Try again!"}` : `Not quite right, but don't worry! ${R.explanation || ""} Let's move on to the next question.`, C = z.current || { lipsyncLang: "en" };
|
|
7376
7382
|
u.current.speakText(L, {
|
|
7377
|
-
lipsyncLang:
|
|
7383
|
+
lipsyncLang: C.lipsyncLang,
|
|
7378
7384
|
onSpeechEnd: () => {
|
|
7379
7385
|
setTimeout(() => {
|
|
7380
7386
|
x.current && x.current();
|
|
7381
|
-
},
|
|
7387
|
+
}, 200);
|
|
7382
7388
|
}
|
|
7383
7389
|
});
|
|
7384
7390
|
}
|
|
7385
7391
|
else
|
|
7386
7392
|
x.current && x.current();
|
|
7387
|
-
}, [e.correct, e.incorrect, O, P]), Q =
|
|
7388
|
-
const
|
|
7389
|
-
if (!
|
|
7393
|
+
}, [e.correct, e.incorrect, O, P]), Q = M((b) => {
|
|
7394
|
+
const R = O();
|
|
7395
|
+
if (!b || typeof b != "object") {
|
|
7390
7396
|
console.error("Invalid code test result format. Expected object with {passed: boolean, ...}");
|
|
7391
7397
|
return;
|
|
7392
7398
|
}
|
|
7393
|
-
if (
|
|
7399
|
+
if (R?.type !== "code_test") {
|
|
7394
7400
|
console.warn("Current question is not a code test. Use handleAnswerSelect for other question types.");
|
|
7395
7401
|
return;
|
|
7396
7402
|
}
|
|
7397
7403
|
const w = {
|
|
7398
|
-
passed:
|
|
7399
|
-
results:
|
|
7400
|
-
output:
|
|
7401
|
-
error:
|
|
7402
|
-
executionTime:
|
|
7403
|
-
testCount:
|
|
7404
|
-
passedCount:
|
|
7405
|
-
failedCount:
|
|
7404
|
+
passed: b.passed === !0,
|
|
7405
|
+
results: b.results || [],
|
|
7406
|
+
output: b.output || "",
|
|
7407
|
+
error: b.error || null,
|
|
7408
|
+
executionTime: b.executionTime || null,
|
|
7409
|
+
testCount: b.testCount || 0,
|
|
7410
|
+
passedCount: b.passedCount || 0,
|
|
7411
|
+
failedCount: b.failedCount || 0
|
|
7406
7412
|
};
|
|
7407
7413
|
c.current.onCustomAction({
|
|
7408
7414
|
type: "codeTestSubmitted",
|
|
@@ -7410,19 +7416,19 @@ const $e = ye(({
|
|
|
7410
7416
|
lessonIndex: l.current.currentLessonIndex,
|
|
7411
7417
|
questionIndex: l.current.currentQuestionIndex,
|
|
7412
7418
|
testResult: w,
|
|
7413
|
-
question:
|
|
7419
|
+
question: R
|
|
7414
7420
|
}), p.current && p.current(w);
|
|
7415
|
-
}, [O, P]), le =
|
|
7421
|
+
}, [O, P]), le = M(() => {
|
|
7416
7422
|
l.current.currentModuleIndex = 0, l.current.currentLessonIndex = 0, l.current.currentQuestionIndex = 0, l.current.isTeaching = !1, l.current.isQuestionMode = !1, l.current.lessonCompleted = !1, l.current.curriculumCompleted = !1, l.current.score = 0, l.current.totalQuestions = 0;
|
|
7417
|
-
}, []), me =
|
|
7418
|
-
console.log("Avatar is ready!",
|
|
7419
|
-
const
|
|
7420
|
-
h &&
|
|
7423
|
+
}, []), me = M((b) => {
|
|
7424
|
+
console.log("Avatar is ready!", b);
|
|
7425
|
+
const R = v(), w = R?.avatar_script || R?.body;
|
|
7426
|
+
h && w && setTimeout(() => {
|
|
7421
7427
|
d.current && d.current();
|
|
7422
|
-
},
|
|
7428
|
+
}, 500);
|
|
7423
7429
|
}, [h, v]);
|
|
7424
7430
|
Ce(() => {
|
|
7425
|
-
d.current = V, g.current = W, f.current = K, x.current = F, I.current = J,
|
|
7431
|
+
d.current = V, g.current = W, f.current = K, x.current = F, I.current = J, H.current = S, p.current = j;
|
|
7426
7432
|
}), fe(a, () => ({
|
|
7427
7433
|
// Curriculum control methods
|
|
7428
7434
|
startTeaching: V,
|
|
@@ -7440,20 +7446,20 @@ const $e = ye(({
|
|
|
7440
7446
|
// Direct access to avatar ref (always returns current value)
|
|
7441
7447
|
getAvatarRef: () => u.current,
|
|
7442
7448
|
// Convenience methods that delegate to avatar (always check current ref)
|
|
7443
|
-
speakText: async (
|
|
7449
|
+
speakText: async (b, R = {}) => {
|
|
7444
7450
|
await u.current?.resumeAudioContext?.();
|
|
7445
7451
|
const w = z.current || { lipsyncLang: "en" };
|
|
7446
|
-
u.current?.speakText(
|
|
7452
|
+
u.current?.speakText(b, { ...R, lipsyncLang: R.lipsyncLang || w.lipsyncLang });
|
|
7447
7453
|
},
|
|
7448
7454
|
resumeAudioContext: async () => {
|
|
7449
7455
|
if (u.current?.resumeAudioContext)
|
|
7450
7456
|
return await u.current.resumeAudioContext();
|
|
7451
|
-
const
|
|
7452
|
-
if (
|
|
7453
|
-
const
|
|
7454
|
-
if (
|
|
7457
|
+
const b = u.current?.talkingHead;
|
|
7458
|
+
if (b?.audioCtx) {
|
|
7459
|
+
const R = b.audioCtx;
|
|
7460
|
+
if (R.state === "suspended" || R.state === "interrupted")
|
|
7455
7461
|
try {
|
|
7456
|
-
await
|
|
7462
|
+
await R.resume(), console.log("Audio context resumed via talkingHead");
|
|
7457
7463
|
} catch (w) {
|
|
7458
7464
|
console.warn("Failed to resume audio context:", w);
|
|
7459
7465
|
}
|
|
@@ -7461,22 +7467,22 @@ const $e = ye(({
|
|
|
7461
7467
|
console.warn("Audio context not available yet");
|
|
7462
7468
|
},
|
|
7463
7469
|
stopSpeaking: () => u.current?.stopSpeaking(),
|
|
7464
|
-
setMood: (
|
|
7465
|
-
playAnimation: (
|
|
7466
|
-
setBodyMovement: (
|
|
7467
|
-
setMovementIntensity: (
|
|
7470
|
+
setMood: (b) => u.current?.setMood(b),
|
|
7471
|
+
playAnimation: (b, R) => u.current?.playAnimation(b, R),
|
|
7472
|
+
setBodyMovement: (b) => u.current?.setBodyMovement(b),
|
|
7473
|
+
setMovementIntensity: (b) => u.current?.setMovementIntensity(b),
|
|
7468
7474
|
playRandomDance: () => u.current?.playRandomDance(),
|
|
7469
|
-
playReaction: (
|
|
7475
|
+
playReaction: (b) => u.current?.playReaction(b),
|
|
7470
7476
|
playCelebration: () => u.current?.playCelebration(),
|
|
7471
|
-
setShowFullAvatar: (
|
|
7472
|
-
setTimingAdjustment: (
|
|
7477
|
+
setShowFullAvatar: (b) => u.current?.setShowFullAvatar(b),
|
|
7478
|
+
setTimingAdjustment: (b) => u.current?.setTimingAdjustment(b),
|
|
7473
7479
|
lockAvatarPosition: () => u.current?.lockAvatarPosition(),
|
|
7474
7480
|
unlockAvatarPosition: () => u.current?.unlockAvatarPosition(),
|
|
7475
7481
|
// Custom action trigger
|
|
7476
|
-
triggerCustomAction: (
|
|
7482
|
+
triggerCustomAction: (b, R) => {
|
|
7477
7483
|
c.current.onCustomAction({
|
|
7478
|
-
type:
|
|
7479
|
-
...
|
|
7484
|
+
type: b,
|
|
7485
|
+
...R,
|
|
7480
7486
|
state: { ...l.current }
|
|
7481
7487
|
});
|
|
7482
7488
|
},
|
|
@@ -7517,8 +7523,8 @@ const $e = ye(({
|
|
|
7517
7523
|
onReady: me,
|
|
7518
7524
|
onLoading: () => {
|
|
7519
7525
|
},
|
|
7520
|
-
onError: (
|
|
7521
|
-
console.error("Avatar error:",
|
|
7526
|
+
onError: (b) => {
|
|
7527
|
+
console.error("Avatar error:", b);
|
|
7522
7528
|
}
|
|
7523
7529
|
}
|
|
7524
7530
|
) });
|