@sage-rsc/talking-head-react 1.0.46 → 1.0.48
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 +207 -162
- package/package.json +1 -1
- package/src/components/CurriculumLearning.jsx +122 -81
package/dist/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { jsxs as Ce, jsx as oe } from "react/jsx-runtime";
|
|
2
|
-
import { forwardRef as be, useRef as
|
|
2
|
+
import { forwardRef as be, useRef as X, useState as re, useCallback as E, useEffect as he, useImperativeHandle as Re, useLayoutEffect as Pe } from "react";
|
|
3
3
|
import * as f from "three";
|
|
4
4
|
import { OrbitControls as Be } from "three/addons/controls/OrbitControls.js";
|
|
5
5
|
import { GLTFLoader as De } from "three/addons/loaders/GLTFLoader.js";
|
|
@@ -8,11 +8,11 @@ import { FBXLoader as Le } from "three/addons/loaders/FBXLoader.js";
|
|
|
8
8
|
import { RoomEnvironment as Ne } from "three/addons/environments/RoomEnvironment.js";
|
|
9
9
|
import Ue from "three/addons/libs/stats.module.js";
|
|
10
10
|
let m, Q, J;
|
|
11
|
-
const A = [0, 0, 0, 0], k = new f.Vector3(), me = new f.Vector3(),
|
|
11
|
+
const A = [0, 0, 0, 0], k = new f.Vector3(), me = new f.Vector3(), G = new f.Vector3(), pe = new f.Vector3();
|
|
12
12
|
new f.Plane();
|
|
13
13
|
new f.Ray();
|
|
14
14
|
new f.Euler();
|
|
15
|
-
const
|
|
15
|
+
const Z = new f.Quaternion(), Se = new f.Quaternion(), ee = new f.Matrix4(), te = new f.Matrix4();
|
|
16
16
|
new f.Vector3();
|
|
17
17
|
const ge = new f.Vector3(0, 0, 1), We = new f.Vector3(1, 0, 0), Ve = new f.Vector3(0, 1, 0), Ge = new f.Vector3(0, 0, 1);
|
|
18
18
|
class Ze {
|
|
@@ -338,7 +338,7 @@ class Ze {
|
|
|
338
338
|
ea: [0, 0, 0, 0]
|
|
339
339
|
// External acceleration [m/s^2]
|
|
340
340
|
};
|
|
341
|
-
u.boneParent.matrixWorld.decompose(k,
|
|
341
|
+
u.boneParent.matrixWorld.decompose(k, Z, G), k.copy(ge).applyQuaternion(Z).setY(0).normalize(), Z.premultiply(Se.setFromUnitVectors(ge, k).invert()).normalize(), u.qWorldInverseYaw = Z.clone().normalize(), this.data.push(u), this.dict[h] = u;
|
|
342
342
|
try {
|
|
343
343
|
this.setValue(h, "type", s.type), this.setValue(h, "stiffness", s.stiffness), this.setValue(h, "damping", s.damping), this.setValue(h, "external", s.external), this.setValue(h, "limits", s.limits), this.setValue(h, "excludes", s.excludes), this.setValue(h, "deltaLocal", s.deltaLocal), this.setValue(h, "deltaWorld", s.deltaWorld), this.setValue(h, "pivot", s.pivot), this.setValue(h, "helper", s.helper);
|
|
344
344
|
} catch (l) {
|
|
@@ -369,9 +369,9 @@ class Ze {
|
|
|
369
369
|
o.vBasis.y + A[1],
|
|
370
370
|
o.vBasis.z - A[2]
|
|
371
371
|
);
|
|
372
|
-
else if (o.boneParent.quaternion.copy(o.qBasis), o.pivot && this.opt.isPivots && (o.boneParent.updateWorldMatrix(!1, !1), o.boneParent.matrixWorld.decompose(k,
|
|
372
|
+
else if (o.boneParent.quaternion.copy(o.qBasis), o.pivot && this.opt.isPivots && (o.boneParent.updateWorldMatrix(!1, !1), o.boneParent.matrixWorld.decompose(k, Z, G), k.copy(ge).applyQuaternion(Z).setY(0).normalize(), Z.premultiply(Se.setFromUnitVectors(ge, k).invert()).normalize(), o.boneParent.quaternion.multiply(Z.invert()), o.boneParent.quaternion.multiply(o.qWorldInverseYaw)), o.isZ && (m = Math.atan(A[0] / o.l), Z.setFromAxisAngle(Ge, -m), o.boneParent.quaternion.multiply(Z)), 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), Z.setFromAxisAngle(We, -m), o.boneParent.quaternion.multiply(Z)), o.isT && (m = 1.5 * Math.tanh(A[3] * 1.5), Z.setFromAxisAngle(Ve, -m), o.boneParent.quaternion.multiply(Z)), o.boneParent.updateWorldMatrix(!1, !0), o.excludes && this.opt.isExcludes)
|
|
373
373
|
for (i = 0, s = o.excludes.length; i < s; i++)
|
|
374
|
-
m = o.excludes[i],
|
|
374
|
+
m = o.excludes[i], G.set(0, 0, 0), m.deltaLocal && (G.x += m.deltaLocal[0], G.y += m.deltaLocal[1], G.z += m.deltaLocal[2]), G.applyMatrix4(m.bone.matrixWorld), te.copy(o.boneParent.matrixWorld).invert(), G.applyMatrix4(te), k.copy(o.bone.position), !(k.distanceToSquared(G) >= m.radiusSq) && (J = k.length(), Q = G.length(), !(Q > m.radius + J) && (Q < Math.abs(m.radius - J) || (Q = (Q * Q + J * J - m.radiusSq) / (2 * Q), G.normalize(), pe.copy(G).multiplyScalar(Q), Q = Math.sqrt(J * J - Q * Q), k.subVectors(k, pe).projectOnPlane(G).normalize().multiplyScalar(Q), me.subVectors(o.vBasis, pe).projectOnPlane(G).normalize(), J = me.dot(k), J < 0 && (J = Math.sqrt(Q * Q - J * J), me.multiplyScalar(J), k.add(me)), k.add(pe).normalize(), G.copy(o.bone.position).normalize(), Z.setFromUnitVectors(G, k), o.boneParent.quaternion.premultiply(Z), o.boneParent.updateWorldMatrix(!1, !0))));
|
|
375
375
|
}
|
|
376
376
|
this.helpers.isActive && this.updateHelpers();
|
|
377
377
|
}
|
|
@@ -608,8 +608,8 @@ class Xe {
|
|
|
608
608
|
for (let l = 0; l < n / 2; l++) {
|
|
609
609
|
const c = i[(h + l) * 2], d = i[(h + l) * 2 + 1], g = i[(h + l + n / 2) * 2] * a - i[(h + l + n / 2) * 2 + 1] * u, y = i[(h + l + n / 2) * 2] * u + i[(h + l + n / 2) * 2 + 1] * a;
|
|
610
610
|
i[(h + l) * 2] = c + g, i[(h + l) * 2 + 1] = d + y, i[(h + l + n / 2) * 2] = c - g, i[(h + l + n / 2) * 2 + 1] = d - y;
|
|
611
|
-
const x = a * o - u * r,
|
|
612
|
-
a = x, u =
|
|
611
|
+
const x = a * o - u * r, I = a * r + u * o;
|
|
612
|
+
a = x, u = I;
|
|
613
613
|
}
|
|
614
614
|
}
|
|
615
615
|
}
|
|
@@ -4204,13 +4204,13 @@ class He {
|
|
|
4204
4204
|
const l = s.morphTargetDictionary[a], c = o.morphAttributes.position[l], d = o.morphAttributes.normal?.[l];
|
|
4205
4205
|
r || (r = new f.Float32BufferAttribute(c.count * 3, 3), d && (h = new f.Float32BufferAttribute(c.count * 3, 3)));
|
|
4206
4206
|
for (let g = 0; g < c.count; g++) {
|
|
4207
|
-
const y = r.getX(g) + c.getX(g) * u, x = r.getY(g) + c.getY(g) * u,
|
|
4208
|
-
r.setXYZ(g, y, x,
|
|
4207
|
+
const y = r.getX(g) + c.getX(g) * u, x = r.getY(g) + c.getY(g) * u, I = r.getZ(g) + c.getZ(g) * u;
|
|
4208
|
+
r.setXYZ(g, y, x, I);
|
|
4209
4209
|
}
|
|
4210
4210
|
if (d)
|
|
4211
4211
|
for (let g = 0; g < c.count; g++) {
|
|
4212
|
-
const y = h.getX(g) + d.getX(g) * u, x = h.getY(g) + d.getY(g) * u,
|
|
4213
|
-
h.setXYZ(g, y, x,
|
|
4212
|
+
const y = h.getX(g) + d.getX(g) * u, x = h.getY(g) + d.getY(g) * u, I = h.getZ(g) + d.getZ(g) * u;
|
|
4213
|
+
h.setXYZ(g, y, x, I);
|
|
4214
4214
|
}
|
|
4215
4215
|
}
|
|
4216
4216
|
if (r) {
|
|
@@ -5251,10 +5251,10 @@ class He {
|
|
|
5251
5251
|
let u = "", l = "", c = 0, d = [], g = [];
|
|
5252
5252
|
const y = Array.from(this.segmenter.segment(t), (x) => x.segment);
|
|
5253
5253
|
for (let x = 0; x < y.length; x++) {
|
|
5254
|
-
const
|
|
5254
|
+
const I = x === y.length - 1, T = y[x].match(r);
|
|
5255
5255
|
let p = y[x].match(s);
|
|
5256
5256
|
const F = y[x].match(h), C = y[x].match(o);
|
|
5257
|
-
if (p && !
|
|
5257
|
+
if (p && !I && !F && y[x + 1].match(s) && (p = !1), i && (u += y[x]), T && (!n || n.every((R) => x < R[0] || x > R[1])) && (l += y[x]), (C || 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({
|
|
@@ -5265,31 +5265,31 @@ class He {
|
|
|
5265
5265
|
subtitles: [u]
|
|
5266
5266
|
}
|
|
5267
5267
|
}), u = ""), l.length)) {
|
|
5268
|
-
const
|
|
5269
|
-
if (
|
|
5270
|
-
const O =
|
|
5271
|
-
for (let B = 0; B <
|
|
5268
|
+
const R = this.lipsyncWordsToVisemes(l, a);
|
|
5269
|
+
if (R && R.visemes && R.visemes.length) {
|
|
5270
|
+
const O = R.times[R.visemes.length - 1] + R.durations[R.visemes.length - 1];
|
|
5271
|
+
for (let B = 0; B < R.visemes.length; B++)
|
|
5272
5272
|
g.push({
|
|
5273
5273
|
mark: c,
|
|
5274
5274
|
template: { name: "viseme" },
|
|
5275
|
-
ts: [(
|
|
5275
|
+
ts: [(R.times[B] - 0.6) / O, (R.times[B] + 0.5) / O, (R.times[B] + R.durations[B] + 0.5) / O],
|
|
5276
5276
|
vs: {
|
|
5277
|
-
["viseme_" +
|
|
5277
|
+
["viseme_" + R.visemes[B]]: [null, R.visemes[B] === "PP" || R.visemes[B] === "FF" ? 0.9 : 0.6, 0]
|
|
5278
5278
|
}
|
|
5279
5279
|
});
|
|
5280
5280
|
}
|
|
5281
5281
|
l = "", c++;
|
|
5282
5282
|
}
|
|
5283
|
-
if (p ||
|
|
5284
|
-
if (d.length ||
|
|
5285
|
-
const
|
|
5283
|
+
if (p || I) {
|
|
5284
|
+
if (d.length || I && g.length) {
|
|
5285
|
+
const R = {
|
|
5286
5286
|
anim: g
|
|
5287
5287
|
};
|
|
5288
|
-
i && (
|
|
5288
|
+
i && (R.onSubtitles = i), d.length && !e.avatarMute && (R.text = d, e.avatarMood && (R.mood = e.avatarMood), e.ttsLang && (R.lang = e.ttsLang), e.ttsVoice && (R.voice = e.ttsVoice), e.ttsRate && (R.rate = e.ttsRate), e.ttsVoice && (R.pitch = e.ttsPitch), e.ttsVolume && (R.volume = e.ttsVolume)), this.speechQueue.push(R), d = [], l = "", c = 0, g = [];
|
|
5289
5289
|
}
|
|
5290
5290
|
if (F) {
|
|
5291
|
-
let
|
|
5292
|
-
|
|
5291
|
+
let R = this.animEmojis[y[x]];
|
|
5292
|
+
R && R.link && (R = this.animEmojis[R.link]), R && this.speechQueue.push({ emoji: R });
|
|
5293
5293
|
}
|
|
5294
5294
|
this.speechQueue.push({ break: 100 });
|
|
5295
5295
|
}
|
|
@@ -5385,10 +5385,10 @@ class He {
|
|
|
5385
5385
|
let y = 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
|
|
5388
|
+
const I = a + c.times[x] / d * u, T = c.durations[x] / d * u;
|
|
5389
5389
|
o.push({
|
|
5390
5390
|
template: { name: "viseme" },
|
|
5391
|
-
ts: [
|
|
5391
|
+
ts: [I - Math.min(60, 2 * T / 3), I + Math.min(25, T / 2), I + T + Math.min(60, T / 2)],
|
|
5392
5392
|
vs: {
|
|
5393
5393
|
["viseme_" + c.visemes[x]]: [null, c.visemes[x] === "PP" || c.visemes[x] === "FF" ? 0.9 : y, 0]
|
|
5394
5394
|
}
|
|
@@ -5482,12 +5482,12 @@ class He {
|
|
|
5482
5482
|
hasVisemes: x && x.visemes && x.visemes.length > 0,
|
|
5483
5483
|
estimatedDuration: c
|
|
5484
5484
|
});
|
|
5485
|
-
const
|
|
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
5488
|
for (let F = 0; F < x.visemes.length; F++) {
|
|
5489
|
-
const C = x.visemes[F],
|
|
5490
|
-
|
|
5489
|
+
const C = x.visemes[F], R = x.times[F] / p, O = x.durations[F] / p, B = R * c, $ = O * c;
|
|
5490
|
+
I.push({
|
|
5491
5491
|
template: { name: "viseme" },
|
|
5492
5492
|
ts: [B - Math.min(60, 2 * $ / 3), B + Math.min(25, $ / 2), B + $ + Math.min(60, $ / 2)],
|
|
5493
5493
|
vs: {
|
|
@@ -5496,7 +5496,7 @@ class He {
|
|
|
5496
5496
|
});
|
|
5497
5497
|
}
|
|
5498
5498
|
}
|
|
5499
|
-
const T = [...t.anim, ...
|
|
5499
|
+
const T = [...t.anim, ...I];
|
|
5500
5500
|
this.audioPlaylist.push({ anim: T, 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) => {
|
|
@@ -5564,8 +5564,8 @@ class He {
|
|
|
5564
5564
|
const d = e.toLowerCase().split(/\s+/), g = [];
|
|
5565
5565
|
for (const y of d)
|
|
5566
5566
|
for (const x of y) {
|
|
5567
|
-
let
|
|
5568
|
-
"aeiou".includes(x) ?
|
|
5567
|
+
let I = "aa";
|
|
5568
|
+
"aeiou".includes(x) ? I = "aa" : "bp".includes(x) ? I = "PP" : "fv".includes(x) ? I = "FF" : "st".includes(x) ? I = "SS" : "dln".includes(x) ? I = "DD" : "kg".includes(x) ? I = "kk" : "rw".includes(x) && (I = "RR"), g.push(I);
|
|
5569
5569
|
}
|
|
5570
5570
|
a = {
|
|
5571
5571
|
visemes: g.map((y, x) => ({
|
|
@@ -5662,8 +5662,8 @@ class He {
|
|
|
5662
5662
|
const d = e.toLowerCase().split(/\s+/), g = [];
|
|
5663
5663
|
for (const y of d)
|
|
5664
5664
|
for (const x of y) {
|
|
5665
|
-
let
|
|
5666
|
-
"aeiou".includes(x) ?
|
|
5665
|
+
let I = "aa";
|
|
5666
|
+
"aeiou".includes(x) ? I = "aa" : "bp".includes(x) ? I = "PP" : "fv".includes(x) ? I = "FF" : "st".includes(x) ? I = "SS" : "dln".includes(x) ? I = "DD" : "kg".includes(x) ? I = "kk" : "rw".includes(x) && (I = "RR"), g.push(I);
|
|
5667
5667
|
}
|
|
5668
5668
|
a = {
|
|
5669
5669
|
visemes: g.map((y, x) => ({
|
|
@@ -6153,7 +6153,7 @@ class He {
|
|
|
6153
6153
|
M.setFromQuaternion(h, "YXZ");
|
|
6154
6154
|
let a = M.x / (40 / 24) + 0.2, u = M.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;
|
|
6155
6155
|
if (t) {
|
|
6156
|
-
let y = this.animQueue.findIndex((
|
|
6156
|
+
let y = this.animQueue.findIndex((I) => I.template.name === "lookat");
|
|
6157
6157
|
y !== -1 && this.animQueue.splice(y, 1);
|
|
6158
6158
|
const x = {
|
|
6159
6159
|
name: "lookat",
|
|
@@ -6187,18 +6187,18 @@ class He {
|
|
|
6187
6187
|
r.project(this.camera);
|
|
6188
6188
|
let h = (r.x + 1) / 2 * n.width + n.left, a = -(r.y - 1) / 2 * n.height + n.top;
|
|
6189
6189
|
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"]), M.setFromQuaternion(N);
|
|
6190
|
-
let u = M.x / (40 / 24), l = M.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), y = Math.max(window.innerHeight - a, a), x = this.convertRange(e, [a - y, a + y], [-0.3, 0.6]) - u + c,
|
|
6191
|
-
x = Math.min(0.6, Math.max(-0.3, x)),
|
|
6190
|
+
let u = M.x / (40 / 24), l = M.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), y = Math.max(window.innerHeight - a, a), x = this.convertRange(e, [a - y, a + y], [-0.3, 0.6]) - u + c, I = this.convertRange(t, [h - g, h + g], [-0.8, 0.8]) - l + d;
|
|
6191
|
+
x = Math.min(0.6, Math.max(-0.3, x)), I = Math.min(0.8, Math.max(-0.8, I));
|
|
6192
6192
|
let T = (Math.random() - 0.5) / 4, p = (Math.random() - 0.5) / 4;
|
|
6193
6193
|
if (i) {
|
|
6194
|
-
let F = this.animQueue.findIndex((
|
|
6194
|
+
let F = this.animQueue.findIndex((R) => R.template.name === "lookat");
|
|
6195
6195
|
F !== -1 && this.animQueue.splice(F, 1);
|
|
6196
6196
|
const C = {
|
|
6197
6197
|
name: "lookat",
|
|
6198
6198
|
dt: [750, i],
|
|
6199
6199
|
vs: {
|
|
6200
6200
|
bodyRotateX: [x + T],
|
|
6201
|
-
bodyRotateY: [
|
|
6201
|
+
bodyRotateY: [I + p],
|
|
6202
6202
|
eyesRotateX: [-3 * T + 0.1],
|
|
6203
6203
|
eyesRotateY: [-5 * p],
|
|
6204
6204
|
browInnerUp: [[0, 0.7]],
|
|
@@ -6433,8 +6433,8 @@ class He {
|
|
|
6433
6433
|
y.name = y.name.replaceAll("mixamorig", "");
|
|
6434
6434
|
const x = y.name.split(".");
|
|
6435
6435
|
if (x[1] === "position") {
|
|
6436
|
-
for (let
|
|
6437
|
-
y.values[
|
|
6436
|
+
for (let I = 0; I < y.values.length; I++)
|
|
6437
|
+
y.values[I] = y.values[I] * s;
|
|
6438
6438
|
d[y.name] = new f.Vector3(y.values[0], y.values[1], y.values[2]);
|
|
6439
6439
|
} else x[1] === "quaternion" ? d[y.name] = new f.Quaternion(y.values[0], y.values[1], y.values[2], y.values[3]) : x[1] === "rotation" && (d[x[0] + ".quaternion"] = new f.Quaternion().setFromEuler(new f.Euler(y.values[0], y.values[1], y.values[2], "XYZ")).normalize());
|
|
6440
6440
|
});
|
|
@@ -6535,7 +6535,7 @@ class He {
|
|
|
6535
6535
|
const c = [];
|
|
6536
6536
|
for (let y = 1; y < r.ts.length; y++) c.push(r.ts[y] - r.ts[y - 1]);
|
|
6537
6537
|
const d = o.template?.rescale || c.map((y) => y / u), g = e * 1e3 - u;
|
|
6538
|
-
r.ts = r.ts.map((y, x,
|
|
6538
|
+
r.ts = r.ts.map((y, x, I) => x === 0 ? h : I[x - 1] + c[x - 1] + d[x - 1] * g);
|
|
6539
6539
|
} else {
|
|
6540
6540
|
const c = e * 1e3 / u;
|
|
6541
6541
|
r.ts = r.ts.map((d) => h + c * (d - h));
|
|
@@ -6571,18 +6571,18 @@ class He {
|
|
|
6571
6571
|
const s = new f.Vector3(), o = new f.Vector3(), r = new f.Vector3(), h = new f.Vector3(), a = new f.Quaternion(), u = new f.Vector3(), l = new f.Vector3(), c = new f.Vector3(), d = this.ikMesh.getObjectByName(t.root);
|
|
6572
6572
|
d.position.setFromMatrixPosition(this.armature.getObjectByName(t.root).matrixWorld), d.quaternion.setFromRotationMatrix(this.armature.getObjectByName(t.root).matrixWorld), e && i && e.applyQuaternion(this.armature.quaternion).add(d.position);
|
|
6573
6573
|
const g = this.ikMesh.getObjectByName(t.effector), y = t.links;
|
|
6574
|
-
y.forEach((
|
|
6575
|
-
|
|
6574
|
+
y.forEach((I) => {
|
|
6575
|
+
I.bone = this.ikMesh.getObjectByName(I.link), I.bone.quaternion.copy(this.getPoseTemplateProp(I.link + ".quaternion"));
|
|
6576
6576
|
}), d.updateMatrixWorld(!0);
|
|
6577
6577
|
const x = t.iterations || 10;
|
|
6578
6578
|
if (e)
|
|
6579
|
-
for (let
|
|
6579
|
+
for (let I = 0; I < x; I++) {
|
|
6580
6580
|
let T = !1;
|
|
6581
6581
|
for (let p = 0, F = y.length; p < F; p++) {
|
|
6582
6582
|
const C = y[p].bone;
|
|
6583
6583
|
C.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();
|
|
6584
|
-
let
|
|
6585
|
-
|
|
6584
|
+
let R = s.dot(r);
|
|
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), l.crossVectors(r, s), l.normalize(), N.setFromAxisAngle(l, R), C.quaternion.multiply(N), C.rotation.setFromVector3(c.setFromEuler(C.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
|
|
@@ -6594,8 +6594,8 @@ class He {
|
|
|
6594
6594
|
}
|
|
6595
6595
|
if (!T) break;
|
|
6596
6596
|
}
|
|
6597
|
-
n && y.forEach((
|
|
6598
|
-
this.poseTarget.props[
|
|
6597
|
+
n && y.forEach((I) => {
|
|
6598
|
+
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;
|
|
6599
6599
|
});
|
|
6600
6600
|
}
|
|
6601
6601
|
/**
|
|
@@ -6684,8 +6684,8 @@ const Te = be(({
|
|
|
6684
6684
|
className: g = "",
|
|
6685
6685
|
style: y = {},
|
|
6686
6686
|
animations: x = {}
|
|
6687
|
-
},
|
|
6688
|
-
const T =
|
|
6687
|
+
}, I) => {
|
|
6688
|
+
const T = X(null), p = X(null), [F, C] = re(!0), [R, O] = re(null), [B, $] = re(!1), Y = ve(), S = n || Y.service;
|
|
6689
6689
|
let P;
|
|
6690
6690
|
S === "browser" ? P = {
|
|
6691
6691
|
service: "browser",
|
|
@@ -6695,19 +6695,19 @@ const Te = be(({
|
|
|
6695
6695
|
} : S === "elevenlabs" ? P = {
|
|
6696
6696
|
service: "elevenlabs",
|
|
6697
6697
|
endpoint: "https://api.elevenlabs.io/v1/text-to-speech",
|
|
6698
|
-
apiKey: o ||
|
|
6699
|
-
defaultVoice: s ||
|
|
6700
|
-
voices:
|
|
6698
|
+
apiKey: o || Y.apiKey,
|
|
6699
|
+
defaultVoice: s || Y.defaultVoice || ae.defaultVoice,
|
|
6700
|
+
voices: Y.voices || ae.voices
|
|
6701
6701
|
} : S === "deepgram" ? P = {
|
|
6702
6702
|
service: "deepgram",
|
|
6703
6703
|
endpoint: "https://api.deepgram.com/v1/speak",
|
|
6704
|
-
apiKey: o ||
|
|
6705
|
-
defaultVoice: s ||
|
|
6706
|
-
voices:
|
|
6704
|
+
apiKey: o || Y.apiKey,
|
|
6705
|
+
defaultVoice: s || Y.defaultVoice || ze.defaultVoice,
|
|
6706
|
+
voices: Y.voices || ze.voices
|
|
6707
6707
|
} : P = {
|
|
6708
|
-
...
|
|
6708
|
+
...Y,
|
|
6709
6709
|
// Override API key if provided via props
|
|
6710
|
-
apiKey: o !== null ? o :
|
|
6710
|
+
apiKey: o !== null ? o : Y.apiKey
|
|
6711
6711
|
};
|
|
6712
6712
|
const W = {
|
|
6713
6713
|
url: D,
|
|
@@ -6788,11 +6788,11 @@ const Te = be(({
|
|
|
6788
6788
|
};
|
|
6789
6789
|
if (H.onSpeechEnd && p.current) {
|
|
6790
6790
|
const w = p.current;
|
|
6791
|
-
let
|
|
6791
|
+
let j = null, se = 0, ue = !1;
|
|
6792
6792
|
const Ee = 1200, Fe = 1e4;
|
|
6793
6793
|
let Ie = 0;
|
|
6794
6794
|
const fe = setInterval(() => {
|
|
6795
|
-
Ie++, w && w.isSpeaking && (w.audioPlaylist && w.audioPlaylist.length > 0 || w.isAudioPlaying === !0) && (ue = !0, clearInterval(fe),
|
|
6795
|
+
Ie++, w && w.isSpeaking && (w.audioPlaylist && w.audioPlaylist.length > 0 || w.isAudioPlaying === !0) && (ue = !0, clearInterval(fe), j = setInterval(Ae, 50));
|
|
6796
6796
|
const de = !w.speechQueue || w.speechQueue.length === 0;
|
|
6797
6797
|
if (w && !w.isSpeaking && de && (!w.audioPlaylist || w.audioPlaylist.length === 0) && (!w.isAudioPlaying || w.isAudioPlaying === !1)) {
|
|
6798
6798
|
clearInterval(fe);
|
|
@@ -6805,7 +6805,7 @@ const Te = be(({
|
|
|
6805
6805
|
}
|
|
6806
6806
|
if (Ie * 50 > Fe) {
|
|
6807
6807
|
if (clearInterval(fe), w && w.isSpeaking)
|
|
6808
|
-
ue = !0,
|
|
6808
|
+
ue = !0, j = setInterval(Ae, 50);
|
|
6809
6809
|
else if (w && !w.isSpeaking && de && (!w.audioPlaylist || w.audioPlaylist.length === 0) && (!w.isAudioPlaying || w.isAudioPlaying === !1))
|
|
6810
6810
|
try {
|
|
6811
6811
|
H.onSpeechEnd();
|
|
@@ -6815,7 +6815,7 @@ const Te = be(({
|
|
|
6815
6815
|
}
|
|
6816
6816
|
}, 50), Ae = () => {
|
|
6817
6817
|
if (se++, se > Ee) {
|
|
6818
|
-
|
|
6818
|
+
j && (clearInterval(j), j = null);
|
|
6819
6819
|
try {
|
|
6820
6820
|
H.onSpeechEnd();
|
|
6821
6821
|
} catch (xe) {
|
|
@@ -6826,7 +6826,7 @@ const Te = be(({
|
|
|
6826
6826
|
if (!ue)
|
|
6827
6827
|
return;
|
|
6828
6828
|
const de = !w.speechQueue || w.speechQueue.length === 0;
|
|
6829
|
-
w && (!w.isSpeaking || w.isSpeaking === !1) && (!w.audioPlaylist || w.audioPlaylist.length === 0) && (!w.isAudioPlaying || w.isAudioPlaying === !1) && de && (
|
|
6829
|
+
w && (!w.isSpeaking || w.isSpeaking === !1) && (!w.audioPlaylist || w.audioPlaylist.length === 0) && (!w.isAudioPlaying || w.isAudioPlaying === !1) && de && (j && (clearInterval(j), j = null), setTimeout(() => {
|
|
6830
6830
|
try {
|
|
6831
6831
|
H.onSpeechEnd();
|
|
6832
6832
|
} catch (xe) {
|
|
@@ -6847,7 +6847,7 @@ const Te = be(({
|
|
|
6847
6847
|
p.current && p.current.setMood(L);
|
|
6848
6848
|
}, []), b = E((L) => {
|
|
6849
6849
|
p.current && p.current.setSlowdownRate && p.current.setSlowdownRate(L);
|
|
6850
|
-
}, []),
|
|
6850
|
+
}, []), v = E((L, H = !1) => {
|
|
6851
6851
|
if (p.current && p.current.playAnimation) {
|
|
6852
6852
|
if (x && x[L] && (L = x[L]), p.current.setShowFullAvatar)
|
|
6853
6853
|
try {
|
|
@@ -6862,20 +6862,20 @@ const Te = be(({
|
|
|
6862
6862
|
console.warn(`Failed to play ${L}:`, w);
|
|
6863
6863
|
try {
|
|
6864
6864
|
p.current.setBodyMovement("idle");
|
|
6865
|
-
} catch (
|
|
6866
|
-
console.warn("Fallback animation also failed:",
|
|
6865
|
+
} catch (j) {
|
|
6866
|
+
console.warn("Fallback animation also failed:", j);
|
|
6867
6867
|
}
|
|
6868
6868
|
}
|
|
6869
6869
|
else {
|
|
6870
6870
|
const w = [".fbx", ".glb", ".gltf"];
|
|
6871
|
-
let
|
|
6871
|
+
let j = !1;
|
|
6872
6872
|
for (const se of w)
|
|
6873
6873
|
try {
|
|
6874
|
-
p.current.playAnimation(L + se, null, 10, 0, 0.01, H),
|
|
6874
|
+
p.current.playAnimation(L + se, null, 10, 0, 0.01, H), j = !0;
|
|
6875
6875
|
break;
|
|
6876
6876
|
} catch {
|
|
6877
6877
|
}
|
|
6878
|
-
if (!
|
|
6878
|
+
if (!j) {
|
|
6879
6879
|
console.warn("Animation not found:", L);
|
|
6880
6880
|
try {
|
|
6881
6881
|
p.current.setBodyMovement("idle");
|
|
@@ -6888,13 +6888,13 @@ const Te = be(({
|
|
|
6888
6888
|
}, [x]), z = E(() => {
|
|
6889
6889
|
p.current && p.current.onResize && p.current.onResize();
|
|
6890
6890
|
}, []);
|
|
6891
|
-
return Re(
|
|
6891
|
+
return Re(I, () => ({
|
|
6892
6892
|
speakText: le,
|
|
6893
6893
|
stopSpeaking: ye,
|
|
6894
6894
|
resumeAudioContext: _,
|
|
6895
6895
|
setMood: K,
|
|
6896
6896
|
setTimingAdjustment: b,
|
|
6897
|
-
playAnimation:
|
|
6897
|
+
playAnimation: v,
|
|
6898
6898
|
isReady: B,
|
|
6899
6899
|
talkingHead: p.current,
|
|
6900
6900
|
handleResize: z,
|
|
@@ -6987,7 +6987,7 @@ const Te = be(({
|
|
|
6987
6987
|
fontSize: "18px",
|
|
6988
6988
|
zIndex: 10
|
|
6989
6989
|
}, children: "Loading avatar..." }),
|
|
6990
|
-
|
|
6990
|
+
R && /* @__PURE__ */ oe("div", { className: "error-overlay", style: {
|
|
6991
6991
|
position: "absolute",
|
|
6992
6992
|
top: "50%",
|
|
6993
6993
|
left: "50%",
|
|
@@ -6998,7 +6998,7 @@ const Te = be(({
|
|
|
6998
6998
|
zIndex: 10,
|
|
6999
6999
|
padding: "20px",
|
|
7000
7000
|
borderRadius: "8px"
|
|
7001
|
-
}, children:
|
|
7001
|
+
}, children: R })
|
|
7002
7002
|
]
|
|
7003
7003
|
}
|
|
7004
7004
|
);
|
|
@@ -7016,7 +7016,7 @@ const ot = be(({
|
|
|
7016
7016
|
style: s = {},
|
|
7017
7017
|
avatarConfig: o = {}
|
|
7018
7018
|
}, r) => {
|
|
7019
|
-
const h =
|
|
7019
|
+
const h = X(null), a = X(null), [u, l] = re(!0), [c, d] = re(null), [g, y] = re(!1), x = ve(), I = o.ttsService || x.service, T = I === "browser" ? {
|
|
7020
7020
|
endpoint: "",
|
|
7021
7021
|
apiKey: null,
|
|
7022
7022
|
defaultVoice: "Google US English"
|
|
@@ -7025,13 +7025,13 @@ const ot = be(({
|
|
|
7025
7025
|
// Override API key if provided via avatarConfig
|
|
7026
7026
|
apiKey: o.ttsApiKey !== void 0 && o.ttsApiKey !== null ? o.ttsApiKey : x.apiKey,
|
|
7027
7027
|
// Override endpoint for ElevenLabs if service is explicitly set
|
|
7028
|
-
endpoint:
|
|
7028
|
+
endpoint: I === "elevenlabs" && o.ttsApiKey ? "https://api.elevenlabs.io/v1/text-to-speech" : x.endpoint
|
|
7029
7029
|
}, p = {
|
|
7030
7030
|
url: "/avatars/brunette.glb",
|
|
7031
7031
|
// Use brunette avatar (working glTF file)
|
|
7032
7032
|
body: "F",
|
|
7033
7033
|
avatarMood: "neutral",
|
|
7034
|
-
ttsLang:
|
|
7034
|
+
ttsLang: I === "browser" ? "en-US" : "en",
|
|
7035
7035
|
ttsVoice: o.ttsVoice || T.defaultVoice,
|
|
7036
7036
|
lipsyncLang: "en",
|
|
7037
7037
|
// English lip-sync
|
|
@@ -7043,7 +7043,7 @@ const ot = be(({
|
|
|
7043
7043
|
}, F = {
|
|
7044
7044
|
ttsEndpoint: T.endpoint,
|
|
7045
7045
|
ttsApikey: T.apiKey,
|
|
7046
|
-
ttsService:
|
|
7046
|
+
ttsService: I,
|
|
7047
7047
|
lipsyncModules: ["en"],
|
|
7048
7048
|
cameraView: "upper"
|
|
7049
7049
|
}, C = E(async () => {
|
|
@@ -7085,7 +7085,7 @@ const ot = be(({
|
|
|
7085
7085
|
he(() => (C(), () => {
|
|
7086
7086
|
a.current && (a.current.stop(), a.current.dispose(), a.current = null);
|
|
7087
7087
|
}), [C]);
|
|
7088
|
-
const
|
|
7088
|
+
const R = E((S) => {
|
|
7089
7089
|
if (a.current && g)
|
|
7090
7090
|
try {
|
|
7091
7091
|
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(() => {
|
|
@@ -7102,7 +7102,7 @@ const ot = be(({
|
|
|
7102
7102
|
a.current && a.current.setMood(S);
|
|
7103
7103
|
}, []), $ = E((S) => {
|
|
7104
7104
|
a.current && a.current.setSlowdownRate && (a.current.setSlowdownRate(S), console.log("Timing adjustment set to:", S));
|
|
7105
|
-
}, []),
|
|
7105
|
+
}, []), Y = E((S, P = !1) => {
|
|
7106
7106
|
if (a.current && a.current.playAnimation) {
|
|
7107
7107
|
if (a.current.setShowFullAvatar)
|
|
7108
7108
|
try {
|
|
@@ -7144,11 +7144,11 @@ const ot = be(({
|
|
|
7144
7144
|
console.warn("Animation system not available or animation not found:", S);
|
|
7145
7145
|
}, []);
|
|
7146
7146
|
return Re(r, () => ({
|
|
7147
|
-
speakText:
|
|
7147
|
+
speakText: R,
|
|
7148
7148
|
stopSpeaking: O,
|
|
7149
7149
|
setMood: B,
|
|
7150
7150
|
setTimingAdjustment: $,
|
|
7151
|
-
playAnimation:
|
|
7151
|
+
playAnimation: Y,
|
|
7152
7152
|
isReady: g,
|
|
7153
7153
|
talkingHead: a.current,
|
|
7154
7154
|
setBodyMovement: (S) => {
|
|
@@ -7261,7 +7261,7 @@ const st = be(({
|
|
|
7261
7261
|
},
|
|
7262
7262
|
autoStart: h = !1
|
|
7263
7263
|
}, a) => {
|
|
7264
|
-
const u =
|
|
7264
|
+
const u = X(null), l = X({
|
|
7265
7265
|
currentModuleIndex: 0,
|
|
7266
7266
|
currentLessonIndex: 0,
|
|
7267
7267
|
currentQuestionIndex: 0,
|
|
@@ -7271,18 +7271,18 @@ const st = be(({
|
|
|
7271
7271
|
curriculumCompleted: !1,
|
|
7272
7272
|
score: 0,
|
|
7273
7273
|
totalQuestions: 0
|
|
7274
|
-
}), c =
|
|
7274
|
+
}), c = X({
|
|
7275
7275
|
onLessonStart: i,
|
|
7276
7276
|
onLessonComplete: n,
|
|
7277
7277
|
onQuestionAnswer: s,
|
|
7278
7278
|
onCurriculumComplete: o,
|
|
7279
7279
|
onCustomAction: r
|
|
7280
|
-
}), d =
|
|
7280
|
+
}), d = X(null), g = X(null), y = X(null), x = X(null), I = X(null), T = X(null), p = X(null), F = X(D?.curriculum || {
|
|
7281
7281
|
title: "Default Curriculum",
|
|
7282
7282
|
description: "No curriculum data provided",
|
|
7283
7283
|
language: "en",
|
|
7284
7284
|
modules: []
|
|
7285
|
-
}), C =
|
|
7285
|
+
}), C = X({
|
|
7286
7286
|
avatarUrl: t.avatarUrl || "/avatars/brunette.glb",
|
|
7287
7287
|
avatarBody: t.avatarBody || "F",
|
|
7288
7288
|
mood: t.mood || "happy",
|
|
@@ -7292,7 +7292,7 @@ const st = be(({
|
|
|
7292
7292
|
ttsApiKey: t.ttsApiKey || null,
|
|
7293
7293
|
bodyMovement: t.bodyMovement || "gesturing",
|
|
7294
7294
|
movementIntensity: t.movementIntensity || 0.7,
|
|
7295
|
-
showFullAvatar: t.showFullAvatar !== void 0 ? t.showFullAvatar : !
|
|
7295
|
+
showFullAvatar: t.showFullAvatar !== void 0 ? t.showFullAvatar : !1,
|
|
7296
7296
|
animations: e,
|
|
7297
7297
|
lipsyncLang: "en"
|
|
7298
7298
|
});
|
|
@@ -7320,16 +7320,16 @@ const st = be(({
|
|
|
7320
7320
|
ttsApiKey: t.ttsApiKey || null,
|
|
7321
7321
|
bodyMovement: t.bodyMovement || "gesturing",
|
|
7322
7322
|
movementIntensity: t.movementIntensity || 0.7,
|
|
7323
|
-
showFullAvatar: t.showFullAvatar !== void 0 ? t.showFullAvatar : !
|
|
7323
|
+
showFullAvatar: t.showFullAvatar !== void 0 ? t.showFullAvatar : !1,
|
|
7324
7324
|
animations: e,
|
|
7325
7325
|
lipsyncLang: "en"
|
|
7326
7326
|
};
|
|
7327
7327
|
}, [D, t, e]);
|
|
7328
|
-
const
|
|
7328
|
+
const R = E(() => (F.current || { modules: [] }).modules[l.current.currentModuleIndex]?.lessons[l.current.currentLessonIndex], []), O = E(() => R()?.questions[l.current.currentQuestionIndex], [R]), B = 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, []), $ = E(() => {
|
|
7329
7329
|
l.current.lessonCompleted = !0, l.current.isQuestionMode = !1;
|
|
7330
7330
|
const b = l.current.totalQuestions > 0 ? Math.round(l.current.score / l.current.totalQuestions * 100) : 100;
|
|
7331
|
-
let
|
|
7332
|
-
if (l.current.totalQuestions > 0 ?
|
|
7331
|
+
let v = "Congratulations! You've completed this lesson";
|
|
7332
|
+
if (l.current.totalQuestions > 0 ? v += ` with a score of ${l.current.score} out of ${l.current.totalQuestions} (${b}%). ` : v += "! ", b >= 80 ? v += "Excellent work! You have a great understanding of this topic." : b >= 60 ? v += "Good job! You understand most of the concepts." : v += "Keep practicing! You're making progress.", c.current.onLessonComplete({
|
|
7333
7333
|
moduleIndex: l.current.currentModuleIndex,
|
|
7334
7334
|
lessonIndex: l.current.currentLessonIndex,
|
|
7335
7335
|
score: l.current.score,
|
|
@@ -7349,25 +7349,28 @@ const st = be(({
|
|
|
7349
7349
|
} catch {
|
|
7350
7350
|
u.current.playCelebration();
|
|
7351
7351
|
}
|
|
7352
|
-
const z = F.current || { modules: [] }, L = z.modules[l.current.currentModuleIndex], H = l.current.currentLessonIndex < (L?.lessons?.length || 0) - 1, U = l.current.currentModuleIndex < (z.modules?.length || 0) - 1, w = H || U,
|
|
7353
|
-
|
|
7354
|
-
lipsyncLang:
|
|
7352
|
+
const z = F.current || { modules: [] }, L = z.modules[l.current.currentModuleIndex], H = l.current.currentLessonIndex < (L?.lessons?.length || 0) - 1, U = l.current.currentModuleIndex < (z.modules?.length || 0) - 1, w = H || U, j = C.current || { lipsyncLang: "en" };
|
|
7353
|
+
u.current.speakText(v, {
|
|
7354
|
+
lipsyncLang: j.lipsyncLang,
|
|
7355
7355
|
onSpeechEnd: () => {
|
|
7356
|
-
|
|
7357
|
-
|
|
7358
|
-
|
|
7359
|
-
|
|
7360
|
-
|
|
7361
|
-
|
|
7356
|
+
c.current.onCustomAction({
|
|
7357
|
+
type: "lessonCompleteFeedbackDone",
|
|
7358
|
+
moduleIndex: l.current.currentModuleIndex,
|
|
7359
|
+
lessonIndex: l.current.currentLessonIndex,
|
|
7360
|
+
score: l.current.score,
|
|
7361
|
+
totalQuestions: l.current.totalQuestions,
|
|
7362
|
+
percentage: b,
|
|
7363
|
+
hasNextLesson: w
|
|
7364
|
+
});
|
|
7362
7365
|
}
|
|
7363
7366
|
});
|
|
7364
7367
|
}
|
|
7365
|
-
}, [e.lessonComplete]),
|
|
7368
|
+
}, [e.lessonComplete]), Y = E(() => {
|
|
7366
7369
|
l.current.curriculumCompleted = !0;
|
|
7367
7370
|
const b = F.current || { modules: [] };
|
|
7368
7371
|
if (c.current.onCurriculumComplete({
|
|
7369
7372
|
modules: b.modules.length,
|
|
7370
|
-
totalLessons: b.modules.reduce((
|
|
7373
|
+
totalLessons: b.modules.reduce((v, z) => v + z.lessons.length, 0)
|
|
7371
7374
|
}), u.current) {
|
|
7372
7375
|
if (u.current.setMood("celebrating"), e.curriculumComplete)
|
|
7373
7376
|
try {
|
|
@@ -7375,21 +7378,21 @@ const st = be(({
|
|
|
7375
7378
|
} catch {
|
|
7376
7379
|
u.current.playCelebration();
|
|
7377
7380
|
}
|
|
7378
|
-
const
|
|
7379
|
-
u.current.speakText("Amazing! You've completed the entire curriculum! You're now ready to move on to more advanced topics. Well done!", { lipsyncLang:
|
|
7381
|
+
const v = C.current || { lipsyncLang: "en" };
|
|
7382
|
+
u.current.speakText("Amazing! You've completed the entire curriculum! You're now ready to move on to more advanced topics. Well done!", { lipsyncLang: v.lipsyncLang });
|
|
7380
7383
|
}
|
|
7381
7384
|
}, [e.curriculumComplete]), S = E(() => {
|
|
7382
|
-
const b =
|
|
7385
|
+
const b = R();
|
|
7383
7386
|
l.current.isQuestionMode = !0, l.current.currentQuestionIndex = 0, l.current.totalQuestions = b?.questions?.length || 0;
|
|
7384
|
-
const
|
|
7385
|
-
if (
|
|
7387
|
+
const v = O();
|
|
7388
|
+
if (v && c.current.onCustomAction({
|
|
7386
7389
|
type: "questionStart",
|
|
7387
7390
|
moduleIndex: l.current.currentModuleIndex,
|
|
7388
7391
|
lessonIndex: l.current.currentLessonIndex,
|
|
7389
7392
|
questionIndex: l.current.currentQuestionIndex,
|
|
7390
7393
|
totalQuestions: l.current.totalQuestions,
|
|
7391
|
-
question:
|
|
7392
|
-
}), u.current && u.current.isReady &&
|
|
7394
|
+
question: v
|
|
7395
|
+
}), u.current && u.current.isReady && v) {
|
|
7393
7396
|
if (u.current.setMood("curious"), e.questionStart)
|
|
7394
7397
|
try {
|
|
7395
7398
|
u.current.playAnimation(e.questionStart, !0);
|
|
@@ -7397,7 +7400,7 @@ const st = be(({
|
|
|
7397
7400
|
console.warn("Failed to play questionStart animation:", L);
|
|
7398
7401
|
}
|
|
7399
7402
|
const z = C.current || { lipsyncLang: "en" };
|
|
7400
|
-
|
|
7403
|
+
v.type === "code_test" ? u.current.speakText(`Let's test your coding skills! Here's your first challenge: ${v.question}`, { lipsyncLang: z.lipsyncLang }) : v.type === "multiple_choice" ? u.current.speakText(`Now let me ask you some questions. Here's the first one: ${v.question}`, { lipsyncLang: z.lipsyncLang }) : v.type === "true_false" ? u.current.speakText(`Let's start with some true or false questions. First question: ${v.question}`, { lipsyncLang: z.lipsyncLang }) : u.current.speakText(`Now let me ask you some questions. Here's the first one: ${v.question}`, { lipsyncLang: z.lipsyncLang });
|
|
7401
7404
|
} else if (u.current && u.current.isReady) {
|
|
7402
7405
|
const z = C.current || { lipsyncLang: "en" };
|
|
7403
7406
|
u.current.speakText("Now let me ask you some questions to test your understanding.", { lipsyncLang: z.lipsyncLang });
|
|
@@ -7405,19 +7408,19 @@ const st = be(({
|
|
|
7405
7408
|
setTimeout(() => {
|
|
7406
7409
|
T.current && T.current();
|
|
7407
7410
|
}, 100);
|
|
7408
|
-
}, [e.questionStart,
|
|
7409
|
-
const b =
|
|
7411
|
+
}, [e.questionStart, R, O]), P = E(() => {
|
|
7412
|
+
const b = R();
|
|
7410
7413
|
if (l.current.currentQuestionIndex < (b?.questions?.length || 0) - 1) {
|
|
7411
7414
|
l.current.currentQuestionIndex += 1;
|
|
7412
|
-
const
|
|
7413
|
-
if (
|
|
7415
|
+
const v = O();
|
|
7416
|
+
if (v && c.current.onCustomAction({
|
|
7414
7417
|
type: "nextQuestion",
|
|
7415
7418
|
moduleIndex: l.current.currentModuleIndex,
|
|
7416
7419
|
lessonIndex: l.current.currentLessonIndex,
|
|
7417
7420
|
questionIndex: l.current.currentQuestionIndex,
|
|
7418
7421
|
totalQuestions: l.current.totalQuestions,
|
|
7419
|
-
question:
|
|
7420
|
-
}), u.current &&
|
|
7422
|
+
question: v
|
|
7423
|
+
}), u.current && v) {
|
|
7421
7424
|
if (u.current.setMood("happy"), u.current.setBodyMovement("idle"), e.nextQuestion)
|
|
7422
7425
|
try {
|
|
7423
7426
|
u.current.playAnimation(e.nextQuestion, !0);
|
|
@@ -7425,38 +7428,52 @@ const st = be(({
|
|
|
7425
7428
|
console.warn("Failed to play nextQuestion animation:", L);
|
|
7426
7429
|
}
|
|
7427
7430
|
const z = C.current || { lipsyncLang: "en" };
|
|
7428
|
-
|
|
7431
|
+
v.type === "code_test" ? u.current.speakText(`Great! Now let's move on to your next coding challenge: ${v.question}`, {
|
|
7429
7432
|
lipsyncLang: z.lipsyncLang
|
|
7430
|
-
}) :
|
|
7433
|
+
}) : v.type === "multiple_choice" ? u.current.speakText(`Alright! Here's your next question: ${v.question}`, {
|
|
7431
7434
|
lipsyncLang: z.lipsyncLang
|
|
7432
|
-
}) :
|
|
7435
|
+
}) : v.type === "true_false" ? u.current.speakText(`Now let's try this one: ${v.question}`, {
|
|
7433
7436
|
lipsyncLang: z.lipsyncLang
|
|
7434
|
-
}) : u.current.speakText(`Here's the next question: ${
|
|
7437
|
+
}) : u.current.speakText(`Here's the next question: ${v.question}`, {
|
|
7435
7438
|
lipsyncLang: z.lipsyncLang
|
|
7436
7439
|
});
|
|
7437
7440
|
}
|
|
7438
7441
|
} else
|
|
7439
|
-
|
|
7440
|
-
|
|
7441
|
-
|
|
7442
|
-
|
|
7442
|
+
c.current.onCustomAction({
|
|
7443
|
+
type: "allQuestionsComplete",
|
|
7444
|
+
moduleIndex: l.current.currentModuleIndex,
|
|
7445
|
+
lessonIndex: l.current.currentLessonIndex,
|
|
7446
|
+
totalQuestions: l.current.totalQuestions,
|
|
7447
|
+
score: l.current.score
|
|
7448
|
+
});
|
|
7449
|
+
}, [e.nextQuestion, R, O]), W = E(() => {
|
|
7450
|
+
const b = F.current || { modules: [] }, v = b.modules[l.current.currentModuleIndex];
|
|
7451
|
+
l.current.currentLessonIndex < (v?.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({
|
|
7443
7452
|
type: "lessonStart",
|
|
7444
7453
|
moduleIndex: l.current.currentModuleIndex,
|
|
7445
7454
|
lessonIndex: l.current.currentLessonIndex
|
|
7446
|
-
}),
|
|
7455
|
+
}), c.current.onLessonStart({
|
|
7456
|
+
moduleIndex: l.current.currentModuleIndex,
|
|
7457
|
+
lessonIndex: l.current.currentLessonIndex,
|
|
7458
|
+
lesson: R()
|
|
7459
|
+
}), u.current && (u.current.setMood("happy"), u.current.setBodyMovement("idle"))) : 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({
|
|
7447
7460
|
type: "lessonStart",
|
|
7448
7461
|
moduleIndex: l.current.currentModuleIndex,
|
|
7449
7462
|
lessonIndex: l.current.currentLessonIndex
|
|
7450
|
-
}),
|
|
7463
|
+
}), c.current.onLessonStart({
|
|
7464
|
+
moduleIndex: l.current.currentModuleIndex,
|
|
7465
|
+
lessonIndex: l.current.currentLessonIndex,
|
|
7466
|
+
lesson: R()
|
|
7467
|
+
}), u.current && (u.current.setMood("happy"), u.current.setBodyMovement("idle"))) : I.current && I.current();
|
|
7451
7468
|
}, []), V = E(() => {
|
|
7452
|
-
const b =
|
|
7453
|
-
let
|
|
7469
|
+
const b = R();
|
|
7470
|
+
let v = null;
|
|
7454
7471
|
if (b?.avatar_script && b?.body) {
|
|
7455
7472
|
const z = b.avatar_script.trim(), L = b.body.trim(), H = z.match(/[.!?]$/) ? " " : ". ";
|
|
7456
|
-
|
|
7473
|
+
v = `${z}${H}${L}`;
|
|
7457
7474
|
} else
|
|
7458
|
-
|
|
7459
|
-
if (u.current && u.current.isReady &&
|
|
7475
|
+
v = b?.avatar_script || b?.body || null;
|
|
7476
|
+
if (u.current && u.current.isReady && v) {
|
|
7460
7477
|
l.current.isTeaching = !0, l.current.isQuestionMode = !1, u.current.setMood("happy");
|
|
7461
7478
|
let z = !1;
|
|
7462
7479
|
if (e.teaching)
|
|
@@ -7476,22 +7493,28 @@ const st = be(({
|
|
|
7476
7493
|
moduleIndex: l.current.currentModuleIndex,
|
|
7477
7494
|
lessonIndex: l.current.currentLessonIndex,
|
|
7478
7495
|
lesson: b
|
|
7479
|
-
}), u.current.speakText(
|
|
7496
|
+
}), u.current.speakText(v, {
|
|
7480
7497
|
lipsyncLang: L.lipsyncLang,
|
|
7481
7498
|
onSpeechEnd: () => {
|
|
7482
|
-
l.current.isTeaching = !1,
|
|
7499
|
+
l.current.isTeaching = !1, c.current.onCustomAction({
|
|
7500
|
+
type: "teachingComplete",
|
|
7501
|
+
moduleIndex: l.current.currentModuleIndex,
|
|
7502
|
+
lessonIndex: l.current.currentLessonIndex,
|
|
7503
|
+
lesson: b,
|
|
7504
|
+
hasQuestions: b.questions && b.questions.length > 0
|
|
7505
|
+
});
|
|
7483
7506
|
}
|
|
7484
7507
|
});
|
|
7485
7508
|
}
|
|
7486
|
-
}, [e.teaching,
|
|
7487
|
-
const
|
|
7509
|
+
}, [e.teaching, R]), q = E((b) => {
|
|
7510
|
+
const v = O(), z = B(b, v);
|
|
7488
7511
|
if (z && (l.current.score += 1), c.current.onQuestionAnswer({
|
|
7489
7512
|
moduleIndex: l.current.currentModuleIndex,
|
|
7490
7513
|
lessonIndex: l.current.currentLessonIndex,
|
|
7491
7514
|
questionIndex: l.current.currentQuestionIndex,
|
|
7492
7515
|
answer: b,
|
|
7493
7516
|
isCorrect: z,
|
|
7494
|
-
question:
|
|
7517
|
+
question: v
|
|
7495
7518
|
}), u.current)
|
|
7496
7519
|
if (z) {
|
|
7497
7520
|
if (u.current.setMood("happy"), e.correct)
|
|
@@ -7501,11 +7524,18 @@ const st = be(({
|
|
|
7501
7524
|
u.current.setBodyMovement("happy");
|
|
7502
7525
|
}
|
|
7503
7526
|
u.current.setBodyMovement("gesturing");
|
|
7504
|
-
const L =
|
|
7527
|
+
const L = v.type === "code_test" ? `Great job! Your code passed all the tests! ${v.explanation || ""}` : `Excellent! That's correct! ${v.explanation || ""}`, H = C.current || { lipsyncLang: "en" };
|
|
7505
7528
|
u.current.speakText(L, {
|
|
7506
7529
|
lipsyncLang: H.lipsyncLang,
|
|
7507
7530
|
onSpeechEnd: () => {
|
|
7508
|
-
|
|
7531
|
+
c.current.onCustomAction({
|
|
7532
|
+
type: "answerFeedbackComplete",
|
|
7533
|
+
moduleIndex: l.current.currentModuleIndex,
|
|
7534
|
+
lessonIndex: l.current.currentLessonIndex,
|
|
7535
|
+
questionIndex: l.current.currentQuestionIndex,
|
|
7536
|
+
isCorrect: !0,
|
|
7537
|
+
hasNextQuestion: l.current.currentQuestionIndex < (R()?.questions?.length || 0) - 1
|
|
7538
|
+
});
|
|
7509
7539
|
}
|
|
7510
7540
|
});
|
|
7511
7541
|
} else {
|
|
@@ -7516,23 +7546,38 @@ const st = be(({
|
|
|
7516
7546
|
u.current.setBodyMovement("idle");
|
|
7517
7547
|
}
|
|
7518
7548
|
u.current.setBodyMovement("gesturing");
|
|
7519
|
-
const L =
|
|
7549
|
+
const L = 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.`, H = C.current || { lipsyncLang: "en" };
|
|
7520
7550
|
u.current.speakText(L, {
|
|
7521
7551
|
lipsyncLang: H.lipsyncLang,
|
|
7522
7552
|
onSpeechEnd: () => {
|
|
7523
|
-
|
|
7553
|
+
c.current.onCustomAction({
|
|
7554
|
+
type: "answerFeedbackComplete",
|
|
7555
|
+
moduleIndex: l.current.currentModuleIndex,
|
|
7556
|
+
lessonIndex: l.current.currentLessonIndex,
|
|
7557
|
+
questionIndex: l.current.currentQuestionIndex,
|
|
7558
|
+
isCorrect: !1,
|
|
7559
|
+
hasNextQuestion: l.current.currentQuestionIndex < (R()?.questions?.length || 0) - 1
|
|
7560
|
+
});
|
|
7524
7561
|
}
|
|
7525
7562
|
});
|
|
7526
7563
|
}
|
|
7527
7564
|
else
|
|
7528
|
-
|
|
7529
|
-
|
|
7530
|
-
|
|
7565
|
+
c.current.onCustomAction({
|
|
7566
|
+
type: "answerFeedbackComplete",
|
|
7567
|
+
moduleIndex: l.current.currentModuleIndex,
|
|
7568
|
+
lessonIndex: l.current.currentLessonIndex,
|
|
7569
|
+
questionIndex: l.current.currentQuestionIndex,
|
|
7570
|
+
isCorrect: z,
|
|
7571
|
+
hasNextQuestion: l.current.currentQuestionIndex < (R()?.questions?.length || 0) - 1,
|
|
7572
|
+
avatarNotReady: !0
|
|
7573
|
+
});
|
|
7574
|
+
}, [e.correct, e.incorrect, O, R, B]), _ = E((b) => {
|
|
7575
|
+
const v = O();
|
|
7531
7576
|
if (!b || typeof b != "object") {
|
|
7532
7577
|
console.error("Invalid code test result format. Expected object with {passed: boolean, ...}");
|
|
7533
7578
|
return;
|
|
7534
7579
|
}
|
|
7535
|
-
if (
|
|
7580
|
+
if (v?.type !== "code_test") {
|
|
7536
7581
|
console.warn("Current question is not a code test. Use handleAnswerSelect for other question types.");
|
|
7537
7582
|
return;
|
|
7538
7583
|
}
|
|
@@ -7552,19 +7597,19 @@ const st = be(({
|
|
|
7552
7597
|
lessonIndex: l.current.currentLessonIndex,
|
|
7553
7598
|
questionIndex: l.current.currentQuestionIndex,
|
|
7554
7599
|
testResult: z,
|
|
7555
|
-
question:
|
|
7600
|
+
question: v
|
|
7556
7601
|
}), p.current && p.current(z);
|
|
7557
7602
|
}, [O, B]), le = E(() => {
|
|
7558
7603
|
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;
|
|
7559
7604
|
}, []), ye = E((b) => {
|
|
7560
7605
|
console.log("Avatar is ready!", b);
|
|
7561
|
-
const
|
|
7606
|
+
const v = R(), z = v?.avatar_script || v?.body;
|
|
7562
7607
|
h && z && setTimeout(() => {
|
|
7563
7608
|
d.current && d.current();
|
|
7564
7609
|
}, 10);
|
|
7565
|
-
}, [h,
|
|
7610
|
+
}, [h, R]);
|
|
7566
7611
|
Pe(() => {
|
|
7567
|
-
d.current = V, g.current = W, y.current = $, x.current = P,
|
|
7612
|
+
d.current = V, g.current = W, y.current = $, x.current = P, I.current = Y, T.current = S, p.current = q;
|
|
7568
7613
|
}), Re(a, () => ({
|
|
7569
7614
|
// Curriculum control methods
|
|
7570
7615
|
startTeaching: V,
|
|
@@ -7574,28 +7619,28 @@ const st = be(({
|
|
|
7574
7619
|
nextQuestion: P,
|
|
7575
7620
|
nextLesson: W,
|
|
7576
7621
|
completeLesson: $,
|
|
7577
|
-
completeCurriculum:
|
|
7622
|
+
completeCurriculum: Y,
|
|
7578
7623
|
resetCurriculum: le,
|
|
7579
7624
|
getState: () => ({ ...l.current }),
|
|
7580
7625
|
getCurrentQuestion: () => O(),
|
|
7581
|
-
getCurrentLesson: () =>
|
|
7626
|
+
getCurrentLesson: () => R(),
|
|
7582
7627
|
// Direct access to avatar ref (always returns current value)
|
|
7583
7628
|
getAvatarRef: () => u.current,
|
|
7584
7629
|
// Convenience methods that delegate to avatar (always check current ref)
|
|
7585
|
-
speakText: async (b,
|
|
7630
|
+
speakText: async (b, v = {}) => {
|
|
7586
7631
|
await u.current?.resumeAudioContext?.();
|
|
7587
7632
|
const z = C.current || { lipsyncLang: "en" };
|
|
7588
|
-
u.current?.speakText(b, { ...
|
|
7633
|
+
u.current?.speakText(b, { ...v, lipsyncLang: v.lipsyncLang || z.lipsyncLang });
|
|
7589
7634
|
},
|
|
7590
7635
|
resumeAudioContext: async () => {
|
|
7591
7636
|
if (u.current?.resumeAudioContext)
|
|
7592
7637
|
return await u.current.resumeAudioContext();
|
|
7593
7638
|
const b = u.current?.talkingHead;
|
|
7594
7639
|
if (b?.audioCtx) {
|
|
7595
|
-
const
|
|
7596
|
-
if (
|
|
7640
|
+
const v = b.audioCtx;
|
|
7641
|
+
if (v.state === "suspended" || v.state === "interrupted")
|
|
7597
7642
|
try {
|
|
7598
|
-
await
|
|
7643
|
+
await v.resume(), console.log("Audio context resumed via talkingHead");
|
|
7599
7644
|
} catch (z) {
|
|
7600
7645
|
console.warn("Failed to resume audio context:", z);
|
|
7601
7646
|
}
|
|
@@ -7604,7 +7649,7 @@ const st = be(({
|
|
|
7604
7649
|
},
|
|
7605
7650
|
stopSpeaking: () => u.current?.stopSpeaking(),
|
|
7606
7651
|
setMood: (b) => u.current?.setMood(b),
|
|
7607
|
-
playAnimation: (b,
|
|
7652
|
+
playAnimation: (b, v) => u.current?.playAnimation(b, v),
|
|
7608
7653
|
setBodyMovement: (b) => u.current?.setBodyMovement(b),
|
|
7609
7654
|
setMovementIntensity: (b) => u.current?.setMovementIntensity(b),
|
|
7610
7655
|
playRandomDance: () => u.current?.playRandomDance(),
|
|
@@ -7615,10 +7660,10 @@ const st = be(({
|
|
|
7615
7660
|
lockAvatarPosition: () => u.current?.lockAvatarPosition(),
|
|
7616
7661
|
unlockAvatarPosition: () => u.current?.unlockAvatarPosition(),
|
|
7617
7662
|
// Custom action trigger
|
|
7618
|
-
triggerCustomAction: (b,
|
|
7663
|
+
triggerCustomAction: (b, v) => {
|
|
7619
7664
|
c.current.onCustomAction({
|
|
7620
7665
|
type: b,
|
|
7621
|
-
...
|
|
7666
|
+
...v,
|
|
7622
7667
|
state: { ...l.current }
|
|
7623
7668
|
});
|
|
7624
7669
|
},
|
|
@@ -7626,7 +7671,7 @@ const st = be(({
|
|
|
7626
7671
|
handleResize: () => u.current?.handleResize(),
|
|
7627
7672
|
// Avatar readiness check (always returns current value)
|
|
7628
7673
|
isAvatarReady: () => u.current?.isReady || !1
|
|
7629
|
-
}), [V, S, q, _, P, W, $,
|
|
7674
|
+
}), [V, S, q, _, P, W, $, Y, le, O, R]);
|
|
7630
7675
|
const K = C.current || {
|
|
7631
7676
|
avatarUrl: "/avatars/brunette.glb",
|
|
7632
7677
|
avatarBody: "F",
|
|
@@ -7637,7 +7682,7 @@ const st = be(({
|
|
|
7637
7682
|
ttsApiKey: null,
|
|
7638
7683
|
bodyMovement: "gesturing",
|
|
7639
7684
|
movementIntensity: 0.7,
|
|
7640
|
-
showFullAvatar: !
|
|
7685
|
+
showFullAvatar: !1,
|
|
7641
7686
|
animations: e
|
|
7642
7687
|
};
|
|
7643
7688
|
return /* @__PURE__ */ oe("div", { style: { width: "100%", height: "100%" }, children: /* @__PURE__ */ oe(
|