@sage-rsc/talking-head-react 1.0.57 → 1.0.59
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 +378 -370
- package/package.json +1 -1
- package/src/components/CurriculumLearning.jsx +11 -2
- package/src/components/TalkingHeadAvatar.jsx +24 -9
package/dist/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { jsxs as Te, jsx as he } from "react/jsx-runtime";
|
|
2
|
-
import { forwardRef as ve, useRef as Z, useState as
|
|
2
|
+
import { forwardRef as ve, useRef as Z, useState as ce, useEffect as pe, useCallback as T, useImperativeHandle as Ie, useLayoutEffect as Oe } from "react";
|
|
3
3
|
import * as f from "three";
|
|
4
4
|
import { OrbitControls as Ne } from "three/addons/controls/OrbitControls.js";
|
|
5
5
|
import { GLTFLoader as Ue } from "three/addons/loaders/GLTFLoader.js";
|
|
@@ -521,10 +521,10 @@ class Qe {
|
|
|
521
521
|
for (let l = 0; l < o; l++) {
|
|
522
522
|
const u = l * s, a = Math.min(u + n, t.length), h = t.slice(u, a), r = this.calculateEnergy(h);
|
|
523
523
|
i.energy.push(r);
|
|
524
|
-
const
|
|
525
|
-
i.spectralCentroid.push(
|
|
526
|
-
const
|
|
527
|
-
i.zeroCrossingRate.push(
|
|
524
|
+
const c = this.calculateSpectralCentroid(h);
|
|
525
|
+
i.spectralCentroid.push(c);
|
|
526
|
+
const d = this.calculateZeroCrossingRate(h);
|
|
527
|
+
i.zeroCrossingRate.push(d);
|
|
528
528
|
const g = this.calculateMFCC(h);
|
|
529
529
|
i.mfcc.push(g);
|
|
530
530
|
}
|
|
@@ -606,8 +606,8 @@ class Qe {
|
|
|
606
606
|
for (let u = 0; u < e; u += n) {
|
|
607
607
|
let a = 1, h = 0;
|
|
608
608
|
for (let r = 0; r < n / 2; r++) {
|
|
609
|
-
const
|
|
610
|
-
i[(u + r) * 2] =
|
|
609
|
+
const c = i[(u + r) * 2], d = i[(u + r) * 2 + 1], g = i[(u + r + n / 2) * 2] * a - i[(u + r + n / 2) * 2 + 1] * h, y = i[(u + r + n / 2) * 2] * h + i[(u + r + n / 2) * 2 + 1] * a;
|
|
610
|
+
i[(u + r) * 2] = c + g, i[(u + r) * 2 + 1] = d + y, i[(u + r + n / 2) * 2] = c - g, i[(u + r + n / 2) * 2 + 1] = d - y;
|
|
611
611
|
const x = a * o - h * l, I = a * l + h * o;
|
|
612
612
|
a = x, h = I;
|
|
613
613
|
}
|
|
@@ -703,15 +703,15 @@ class Qe {
|
|
|
703
703
|
const o = this.textToVisemes(e);
|
|
704
704
|
let l = 0, u = 0;
|
|
705
705
|
for (let a = 0; a < s.length && l < o.length; a++) {
|
|
706
|
-
const h = s[a], r = o[l],
|
|
706
|
+
const h = s[a], r = o[l], c = t.energy[Math.floor(h / 0.023)] || 0, d = this.calculateVisemeDuration(r, c);
|
|
707
707
|
n.push({
|
|
708
708
|
viseme: r,
|
|
709
709
|
startTime: u,
|
|
710
|
-
endTime: u +
|
|
711
|
-
duration:
|
|
712
|
-
intensity: Math.min(1,
|
|
710
|
+
endTime: u + d,
|
|
711
|
+
duration: d,
|
|
712
|
+
intensity: Math.min(1, c * 2)
|
|
713
713
|
// Map energy to viseme intensity
|
|
714
|
-
}), u +=
|
|
714
|
+
}), u += d, l++;
|
|
715
715
|
}
|
|
716
716
|
for (; l < o.length; ) {
|
|
717
717
|
const a = o[l], h = this.calculateVisemeDuration(a, 0.5);
|
|
@@ -1207,10 +1207,10 @@ class qe {
|
|
|
1207
1207
|
Object.keys(this.rules).forEach((e) => {
|
|
1208
1208
|
this.rules[e] = this.rules[e].map((i) => {
|
|
1209
1209
|
const n = i.indexOf("["), s = i.indexOf("]"), o = i.indexOf("="), l = i.substring(0, n), u = i.substring(n + 1, s), a = i.substring(s + 1, o), h = i.substring(o + 1), r = { regex: "", move: 0, visemes: [] };
|
|
1210
|
-
let
|
|
1211
|
-
|
|
1212
|
-
const
|
|
1213
|
-
return
|
|
1210
|
+
let c = "";
|
|
1211
|
+
c += [...l].map((g) => t[g] || g).join("");
|
|
1212
|
+
const d = [...u];
|
|
1213
|
+
return d[0] = d[0].toLowerCase(), c += d.join(""), r.move = d.length, c += [...a].map((g) => t[g] || g).join(""), r.regex = new RegExp(c), h.length && h.split(" ").forEach((g) => {
|
|
1214
1214
|
r.visemes.push(g);
|
|
1215
1215
|
}), r;
|
|
1216
1216
|
});
|
|
@@ -1380,11 +1380,11 @@ class qe {
|
|
|
1380
1380
|
if ((e.words.substring(0, e.i) + s.toLowerCase() + e.words.substring(e.i + 1)).match(u.regex)) {
|
|
1381
1381
|
u.visemes.forEach((r) => {
|
|
1382
1382
|
if (e.visemes.length && e.visemes[e.visemes.length - 1] === r) {
|
|
1383
|
-
const
|
|
1384
|
-
e.durations[e.durations.length - 1] +=
|
|
1383
|
+
const c = 0.7 * (this.visemeDurations[r] || 1);
|
|
1384
|
+
e.durations[e.durations.length - 1] += c, i += c;
|
|
1385
1385
|
} else {
|
|
1386
|
-
const
|
|
1387
|
-
e.visemes.push(r), e.times.push(i), e.durations.push(
|
|
1386
|
+
const c = this.visemeDurations[r] || 1;
|
|
1387
|
+
e.visemes.push(r), e.times.push(i), e.durations.push(c), i += c;
|
|
1388
1388
|
}
|
|
1389
1389
|
}), e.i += u.move;
|
|
1390
1390
|
break;
|
|
@@ -1617,10 +1617,10 @@ class Ke {
|
|
|
1617
1617
|
Object.keys(this.rules).forEach((e) => {
|
|
1618
1618
|
this.rules[e] = this.rules[e].map((i) => {
|
|
1619
1619
|
const n = i.indexOf("["), s = i.indexOf("]"), o = i.indexOf("="), l = i.substring(0, n), u = i.substring(n + 1, s), a = i.substring(s + 1, o), h = i.substring(o + 1), r = { regex: "", move: 0, visemes: [] };
|
|
1620
|
-
let
|
|
1621
|
-
|
|
1622
|
-
const
|
|
1623
|
-
return
|
|
1620
|
+
let c = "";
|
|
1621
|
+
c += [...l].map((g) => t[g] || g).join("");
|
|
1622
|
+
const d = [...u];
|
|
1623
|
+
return d[0] = d[0].toLowerCase(), c += d.join(""), r.move = d.length, c += [...a].map((g) => t[g] || g).join(""), r.regex = new RegExp(c), h.length && h.split(" ").forEach((g) => {
|
|
1624
1624
|
r.visemes.push(g);
|
|
1625
1625
|
}), r;
|
|
1626
1626
|
});
|
|
@@ -1735,13 +1735,13 @@ class Ke {
|
|
|
1735
1735
|
for (let u = 0; u < o.length; u++) {
|
|
1736
1736
|
const a = o[u];
|
|
1737
1737
|
if ((e.words.substring(0, e.i) + s.toLowerCase() + e.words.substring(e.i + 1)).match(a.regex)) {
|
|
1738
|
-
a.visemes.forEach((
|
|
1739
|
-
if (e.visemes.length && e.visemes[e.visemes.length - 1] ===
|
|
1740
|
-
const
|
|
1741
|
-
e.durations[e.durations.length - 1] +=
|
|
1738
|
+
a.visemes.forEach((c) => {
|
|
1739
|
+
if (e.visemes.length && e.visemes[e.visemes.length - 1] === c) {
|
|
1740
|
+
const d = 0.7 * (this.visemeDurations[c] || 1);
|
|
1741
|
+
e.durations[e.durations.length - 1] += d, i += d;
|
|
1742
1742
|
} else {
|
|
1743
|
-
const
|
|
1744
|
-
e.visemes.push(
|
|
1743
|
+
const d = this.visemeDurations[c] || 1;
|
|
1744
|
+
e.visemes.push(c), e.times.push(i), e.durations.push(d), i += d;
|
|
1745
1745
|
}
|
|
1746
1746
|
}), e.i += a.move, l = !0;
|
|
1747
1747
|
break;
|
|
@@ -2132,10 +2132,10 @@ class $e {
|
|
|
2132
2132
|
Object.keys(this.rules).forEach((e) => {
|
|
2133
2133
|
this.rules[e] = this.rules[e].map((i) => {
|
|
2134
2134
|
const n = i.indexOf("["), s = i.indexOf("]"), o = i.indexOf("="), l = i.substring(0, n), u = i.substring(n + 1, s), a = i.substring(s + 1, o), h = i.substring(o + 1), r = { regex: "", move: 0, visemes: [] };
|
|
2135
|
-
let
|
|
2136
|
-
|
|
2137
|
-
const
|
|
2138
|
-
return
|
|
2135
|
+
let c = "";
|
|
2136
|
+
c += [...l].map((g) => t[g] || g).join("");
|
|
2137
|
+
const d = [...u];
|
|
2138
|
+
return d[0] = d[0].toLowerCase(), c += d.join(""), r.move = d.length, c += [...a].map((g) => t[g] || g).join(""), r.regex = new RegExp(c, "i"), h.length && h.split(" ").forEach((g) => {
|
|
2139
2139
|
g && r.visemes.push(g);
|
|
2140
2140
|
}), r;
|
|
2141
2141
|
});
|
|
@@ -2270,13 +2270,13 @@ class $e {
|
|
|
2270
2270
|
for (let u = 0; u < o.length; u++) {
|
|
2271
2271
|
const a = o[u];
|
|
2272
2272
|
if ((e.words.substring(0, e.i) + s.toLowerCase() + e.words.substring(e.i + 1)).match(a.regex)) {
|
|
2273
|
-
a.visemes.forEach((
|
|
2274
|
-
if (e.visemes.length && e.visemes[e.visemes.length - 1] ===
|
|
2275
|
-
const
|
|
2276
|
-
e.durations[e.durations.length - 1] +=
|
|
2273
|
+
a.visemes.forEach((c) => {
|
|
2274
|
+
if (e.visemes.length && e.visemes[e.visemes.length - 1] === c) {
|
|
2275
|
+
const d = 0.7 * (this.visemeDurations[c] || 1);
|
|
2276
|
+
e.durations[e.durations.length - 1] += d, i += d;
|
|
2277
2277
|
} else {
|
|
2278
|
-
const
|
|
2279
|
-
e.visemes.push(
|
|
2278
|
+
const d = this.visemeDurations[c] || 1;
|
|
2279
|
+
e.visemes.push(c), e.times.push(i), e.durations.push(d), i += d;
|
|
2280
2280
|
}
|
|
2281
2281
|
}), e.i += a.move, l = !0;
|
|
2282
2282
|
break;
|
|
@@ -2629,7 +2629,7 @@ const ot = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
|
|
|
2629
2629
|
fr: et,
|
|
2630
2630
|
fi: it,
|
|
2631
2631
|
lt: ot
|
|
2632
|
-
},
|
|
2632
|
+
}, V = new f.Quaternion(), M = new f.Euler(), ae = new f.Vector3(), le = new f.Vector3(), Ce = new f.Box3();
|
|
2633
2633
|
new f.Matrix4();
|
|
2634
2634
|
new f.Matrix4();
|
|
2635
2635
|
new f.Vector3();
|
|
@@ -4201,15 +4201,15 @@ class Me {
|
|
|
4201
4201
|
let l = null, u = null;
|
|
4202
4202
|
for (const [a, h] of Object.entries(i))
|
|
4203
4203
|
if (s.morphTargetDictionary.hasOwnProperty(a)) {
|
|
4204
|
-
const r = s.morphTargetDictionary[a],
|
|
4205
|
-
l || (l = new f.Float32BufferAttribute(
|
|
4206
|
-
for (let g = 0; g <
|
|
4207
|
-
const y = l.getX(g) +
|
|
4204
|
+
const r = s.morphTargetDictionary[a], c = o.morphAttributes.position[r], d = o.morphAttributes.normal?.[r];
|
|
4205
|
+
l || (l = new f.Float32BufferAttribute(c.count * 3, 3), d && (u = new f.Float32BufferAttribute(c.count * 3, 3)));
|
|
4206
|
+
for (let g = 0; g < c.count; g++) {
|
|
4207
|
+
const y = l.getX(g) + c.getX(g) * h, x = l.getY(g) + c.getY(g) * h, I = l.getZ(g) + c.getZ(g) * h;
|
|
4208
4208
|
l.setXYZ(g, y, x, I);
|
|
4209
4209
|
}
|
|
4210
|
-
if (
|
|
4211
|
-
for (let g = 0; g <
|
|
4212
|
-
const y = u.getX(g) +
|
|
4210
|
+
if (d)
|
|
4211
|
+
for (let g = 0; g < c.count; g++) {
|
|
4212
|
+
const y = u.getX(g) + d.getX(g) * h, x = u.getY(g) + d.getY(g) * h, I = u.getZ(g) + d.getZ(g) * h;
|
|
4213
4213
|
u.setXYZ(g, y, x, I);
|
|
4214
4214
|
}
|
|
4215
4215
|
}
|
|
@@ -4275,8 +4275,8 @@ class Me {
|
|
|
4275
4275
|
h && ["fixed", "system", "systemd", "realtime", "base", "v", "value", "applied"].forEach((r) => {
|
|
4276
4276
|
l[a][r] = h[r];
|
|
4277
4277
|
}), this.morphs.forEach((r) => {
|
|
4278
|
-
const
|
|
4279
|
-
|
|
4278
|
+
const c = r.morphTargetDictionary[a];
|
|
4279
|
+
c !== void 0 && (l[a].ms.push(r.morphTargetInfluences), l[a].is.push(c), r.morphTargetInfluences[c] = l[a].applied);
|
|
4280
4280
|
});
|
|
4281
4281
|
}), this.mtAvatar = l, this.poseAvatar = { props: {} }, this.posePropNames.forEach((a) => {
|
|
4282
4282
|
const h = a.split("."), r = this.armature.getObjectByName(h[0]);
|
|
@@ -4376,7 +4376,7 @@ class Me {
|
|
|
4376
4376
|
if (e.x === 0 && e.y === 0 && e.z === 0) continue;
|
|
4377
4377
|
M.set(e.x, e.y, e.z);
|
|
4378
4378
|
const i = this.poseAvatar.props[t];
|
|
4379
|
-
i.isQuaternion ? (
|
|
4379
|
+
i.isQuaternion ? (V.setFromEuler(M), i.multiply(V)) : i.isVector3 && i.add(M);
|
|
4380
4380
|
}
|
|
4381
4381
|
}
|
|
4382
4382
|
/**
|
|
@@ -4975,10 +4975,10 @@ class Me {
|
|
|
4975
4975
|
if (l.alt.length > 1) {
|
|
4976
4976
|
const h = Math.random();
|
|
4977
4977
|
let r = 0;
|
|
4978
|
-
for (let
|
|
4979
|
-
let
|
|
4980
|
-
if (r +=
|
|
4981
|
-
a = l.alt[
|
|
4978
|
+
for (let c = 0; c < l.alt.length; c++) {
|
|
4979
|
+
let d = this.valueFn(l.alt[c].p);
|
|
4980
|
+
if (r += d === void 0 ? (1 - r) / (l.alt.length - 1 - c) : d, h < r) {
|
|
4981
|
+
a = l.alt[c];
|
|
4982
4982
|
break;
|
|
4983
4983
|
}
|
|
4984
4984
|
}
|
|
@@ -4998,8 +4998,8 @@ class Me {
|
|
|
4998
4998
|
}
|
|
4999
4999
|
s ? o.ts = o.ts.map((a) => u + a * i) : o.ts = o.ts.map((a) => this.animClock + u + a * i);
|
|
5000
5000
|
for (let [a, h] of Object.entries(l.vs)) {
|
|
5001
|
-
const r = this.getBaselineValue(a),
|
|
5002
|
-
a === "eyesRotateY" ? (o.vs.eyeLookOutLeft = [null, ...
|
|
5001
|
+
const r = this.getBaselineValue(a), c = h.map((d) => (d = this.valueFn(d), d === null ? null : typeof d == "function" ? d : typeof d == "string" || d instanceof String ? d.slice() : Array.isArray(d) ? a === "gesture" ? d.slice() : (r === void 0 ? 0 : r) + n * this.gaussianRandom(...d) : typeof d == "boolean" ? d : d instanceof Object && d.constructor === Object ? Object.assign({}, d) : (r === void 0 ? 0 : r) + n * d));
|
|
5002
|
+
a === "eyesRotateY" ? (o.vs.eyeLookOutLeft = [null, ...c.map((d) => d > 0 ? d : 0)], o.vs.eyeLookInLeft = [null, ...c.map((d) => d > 0 ? 0 : -d)], o.vs.eyeLookOutRight = [null, ...c.map((d) => d > 0 ? 0 : -d)], o.vs.eyeLookInRight = [null, ...c.map((d) => d > 0 ? d : 0)]) : a === "eyesRotateX" ? (o.vs.eyesLookDown = [null, ...c.map((d) => d > 0 ? d : 0)], o.vs.eyesLookUp = [null, ...c.map((d) => d > 0 ? 0 : -d)]) : o.vs[a] = [null, ...c];
|
|
5003
5003
|
}
|
|
5004
5004
|
for (let a of Object.keys(o.vs))
|
|
5005
5005
|
for (; o.vs[a].length <= o.ts.length; ) o.vs[a].push(o.vs[a][o.vs[a].length - 1]);
|
|
@@ -5086,20 +5086,20 @@ class Me {
|
|
|
5086
5086
|
const r = this.animQueue[i];
|
|
5087
5087
|
if (!(!r || !r.ts || !r.ts.length || this.animClock < r.ts[0])) {
|
|
5088
5088
|
for (n = r.ndx || 0, o = r.ts.length; n < o && !(this.animClock < r.ts[n]); n++)
|
|
5089
|
-
for (let [
|
|
5090
|
-
if (this.mtAvatar.hasOwnProperty(
|
|
5091
|
-
if (
|
|
5092
|
-
const g = this.mtAvatar[
|
|
5093
|
-
if (
|
|
5094
|
-
g.newvalue =
|
|
5089
|
+
for (let [c, d] of Object.entries(r.vs))
|
|
5090
|
+
if (this.mtAvatar.hasOwnProperty(c)) {
|
|
5091
|
+
if (d[n + 1] === null) continue;
|
|
5092
|
+
const g = this.mtAvatar[c];
|
|
5093
|
+
if (d[n] === null && (d[n] = g.value), n === o - 1)
|
|
5094
|
+
g.newvalue = d[n];
|
|
5095
5095
|
else {
|
|
5096
|
-
g.newvalue =
|
|
5096
|
+
g.newvalue = d[n + 1];
|
|
5097
5097
|
const y = r.ts[n + 1] - r.ts[n];
|
|
5098
5098
|
let x = 1;
|
|
5099
|
-
y > 1e-4 && (x = (this.animClock - r.ts[n]) / y), x < 1 && (g.easing && (x = g.easing(x)), g.newvalue = (1 - x) *
|
|
5099
|
+
y > 1e-4 && (x = (this.animClock - r.ts[n]) / y), x < 1 && (g.easing && (x = g.easing(x)), g.newvalue = (1 - x) * d[n] + x * g.newvalue), g.ref && g.ref !== r.vs && g.ref.hasOwnProperty(c) && delete g.ref[c], g.ref = r.vs;
|
|
5100
5100
|
}
|
|
5101
5101
|
if (l)
|
|
5102
|
-
switch (
|
|
5102
|
+
switch (c) {
|
|
5103
5103
|
case "viseme_aa":
|
|
5104
5104
|
case "viseme_E":
|
|
5105
5105
|
case "viseme_I":
|
|
@@ -5108,11 +5108,11 @@ class Me {
|
|
|
5108
5108
|
g.newvalue *= 1 + l / 255 - 0.5;
|
|
5109
5109
|
}
|
|
5110
5110
|
g.needsUpdate = !0;
|
|
5111
|
-
} else
|
|
5111
|
+
} else c === "eyeContact" && d[n] !== null && u !== !1 ? u = !!d[n] : c === "headMove" && d[n] !== null && a !== !1 ? d[n] === 0 ? a = !1 : (Math.random() < d[n] && (a = !0), d[n] = null) : d[n] !== null && (h.push({ mt: c, val: d[n] }), d[n] = null);
|
|
5112
5112
|
n === o ? (r.hasOwnProperty("mood") && this.setMood(r.mood), r.loop ? (o = this.isSpeaking && (r.template.name === "head" || r.template.name === "eyes") ? 4 : 1, this.animQueue[i] = this.animFactory(r.template, r.loop > 0 ? r.loop - 1 : r.loop, 1, 1 / o)) : (this.animQueue.splice(i--, 1), s--)) : r.ndx = n - 1;
|
|
5113
5113
|
}
|
|
5114
5114
|
}
|
|
5115
|
-
for (let r = 0,
|
|
5115
|
+
for (let r = 0, c = h.length; r < c; r++)
|
|
5116
5116
|
switch (n = h[r].val, h[r].mt) {
|
|
5117
5117
|
case "speak":
|
|
5118
5118
|
this.speakText(n);
|
|
@@ -5130,8 +5130,8 @@ class Me {
|
|
|
5130
5130
|
n && typeof n == "function" && n();
|
|
5131
5131
|
break;
|
|
5132
5132
|
case "moveto":
|
|
5133
|
-
Object.entries(n.props).forEach((
|
|
5134
|
-
|
|
5133
|
+
Object.entries(n.props).forEach((d) => {
|
|
5134
|
+
d[1] ? this.poseTarget.props[d[0]].copy(d[1]) : this.poseTarget.props[d[0]].copy(this.getPoseTemplateProp(d[0])), this.poseTarget.props[d[0]].t = this.animClock, this.poseTarget.props[d[0]].d = d[1] && d[1].d ? d[1].d : d.duration || 2e3;
|
|
5135
5135
|
});
|
|
5136
5136
|
break;
|
|
5137
5137
|
case "handLeft":
|
|
@@ -5180,13 +5180,13 @@ class Me {
|
|
|
5180
5180
|
eyeLookOutRight: [null, 0],
|
|
5181
5181
|
eyeContact: [0]
|
|
5182
5182
|
}
|
|
5183
|
-
})))), e > 2 * this.animFrameDur && (e = 2 * this.animFrameDur), (this.viewName !== "full" || this.isAvatarOnly) && (i = this.mtRandomized[Math.floor(Math.random() * this.mtRandomized.length)], n = this.mtAvatar[i], n.needsUpdate || Object.assign(n, { base: (this.mood.baseline[i] || 0) + (1 + l / 255) * Math.random() / 5, needsUpdate: !0 })), this.updatePoseBase(this.animClock), this.mixer && this.mixer.update(e / 1e3 * this.mixer.timeScale), this.updatePoseDelta(), (this.isSpeaking || this.isListening) && u ? l > this.volumeMax ? (this.volumeHeadBase = 0.05, Math.random() > 0.6 && (this.volumeHeadTarget = -0.05 - Math.random() / 15), this.volumeMax = l) : (this.volumeMax *= 0.92, this.volumeHeadTarget = this.volumeHeadBase - 0.9 * (this.volumeHeadBase - this.volumeHeadTarget)) : (this.volumeHeadTarget = 0, this.volumeMax = 0), i = this.volumeHeadTarget - this.volumeHeadCurrent, n = Math.abs(i), n > 1e-4 && (o = n * (this.volumeHeadEasing(Math.min(1, this.volumeHeadVelocity * e / 1e3 / n) / 2 + 0.5) - 0.5), this.volumeHeadCurrent += Math.sign(i) * Math.min(n, o)), Math.abs(this.volumeHeadCurrent) > 1e-4 && (
|
|
5183
|
+
})))), e > 2 * this.animFrameDur && (e = 2 * this.animFrameDur), (this.viewName !== "full" || this.isAvatarOnly) && (i = this.mtRandomized[Math.floor(Math.random() * this.mtRandomized.length)], n = this.mtAvatar[i], n.needsUpdate || Object.assign(n, { base: (this.mood.baseline[i] || 0) + (1 + l / 255) * Math.random() / 5, needsUpdate: !0 })), this.updatePoseBase(this.animClock), this.mixer && this.mixer.update(e / 1e3 * this.mixer.timeScale), this.updatePoseDelta(), (this.isSpeaking || this.isListening) && u ? l > this.volumeMax ? (this.volumeHeadBase = 0.05, Math.random() > 0.6 && (this.volumeHeadTarget = -0.05 - Math.random() / 15), this.volumeMax = l) : (this.volumeMax *= 0.92, this.volumeHeadTarget = this.volumeHeadBase - 0.9 * (this.volumeHeadBase - this.volumeHeadTarget)) : (this.volumeHeadTarget = 0, this.volumeMax = 0), i = this.volumeHeadTarget - this.volumeHeadCurrent, n = Math.abs(i), n > 1e-4 && (o = n * (this.volumeHeadEasing(Math.min(1, this.volumeHeadVelocity * e / 1e3 / n) / 2 + 0.5) - 0.5), this.volumeHeadCurrent += Math.sign(i) * Math.min(n, o)), Math.abs(this.volumeHeadCurrent) > 1e-4 && (V.setFromAxisAngle(at, this.volumeHeadCurrent), this.objectNeck.quaternion.multiply(V)), Ce.setFromObject(this.armature), this.objectLeftToeBase.getWorldPosition(ae), ae.sub(this.armature.position), this.objectRightToeBase.getWorldPosition(le), le.sub(this.armature.position), this.objectHips.position.y -= Ce.min.y / 2, this.objectHips.position.x -= (ae.x + le.x) / 4, this.objectHips.position.z -= (ae.z + le.z) / 2, this.dynamicbones.update(e), this.fbxAnimationLoader && this.fbxAnimationLoader.update(), this.opt.update && this.opt.update(e), this.updateMorphTargets(e), this.isAvatarOnly)
|
|
5184
5184
|
this.stats && this.stats.end();
|
|
5185
5185
|
else {
|
|
5186
5186
|
if (this.cameraClock !== null && this.cameraClock < 1e3) {
|
|
5187
5187
|
this.cameraClock += e, this.cameraClock > 1e3 && (this.cameraClock = 1e3);
|
|
5188
|
-
let r = new f.Spherical().setFromVector3(this.cameraStart),
|
|
5189
|
-
r.phi += this.easing(this.cameraClock / 1e3) * (
|
|
5188
|
+
let r = new f.Spherical().setFromVector3(this.cameraStart), c = new f.Spherical().setFromVector3(this.cameraEnd);
|
|
5189
|
+
r.phi += this.easing(this.cameraClock / 1e3) * (c.phi - r.phi), r.theta += this.easing(this.cameraClock / 1e3) * (c.theta - r.theta), r.radius += this.easing(this.cameraClock / 1e3) * (c.radius - r.radius), r.makeSafe(), this.camera.position.setFromSpherical(r), this.controlsStart.x !== this.controlsEnd.x ? this.controls.target.copy(this.controlsStart.lerp(this.controlsEnd, this.easing(this.cameraClock / 1e3))) : (r.setFromVector3(this.controlsStart), c.setFromVector3(this.controlsEnd), r.phi += this.easing(this.cameraClock / 1e3) * (c.phi - r.phi), r.theta += this.easing(this.cameraClock / 1e3) * (c.theta - r.theta), r.radius += this.easing(this.cameraClock / 1e3) * (c.radius - r.radius), r.makeSafe(), this.controls.target.setFromSpherical(r)), this.controls.update();
|
|
5190
5190
|
}
|
|
5191
5191
|
this.controls.autoRotate && this.controls.update(), this.stats && this.stats.end(), this.render();
|
|
5192
5192
|
}
|
|
@@ -5248,17 +5248,17 @@ class Me {
|
|
|
5248
5248
|
speakText(t, e = null, i = null, n = null) {
|
|
5249
5249
|
e = e || {};
|
|
5250
5250
|
const s = /[!\.\?\n\p{Extended_Pictographic}]/ug, o = /[ ]/ug, l = /[\p{L}\p{N},\.\p{Quotation_Mark}!€\$\+\p{Dash_Punctuation}%&\?]/ug, u = /[\p{Extended_Pictographic}]/ug, a = e.lipsyncLang || this.avatar.lipsyncLang || this.opt.lipsyncLang;
|
|
5251
|
-
let h = "", r = "",
|
|
5251
|
+
let h = "", r = "", 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 I = x === y.length - 1,
|
|
5254
|
+
const I = x === y.length - 1, P = y[x].match(l);
|
|
5255
5255
|
let p = y[x].match(s);
|
|
5256
5256
|
const H = y[x].match(u), z = y[x].match(o);
|
|
5257
|
-
if (p && !I && !H && y[x + 1].match(s) && (p = !1), i && (h += y[x]),
|
|
5258
|
-
mark:
|
|
5257
|
+
if (p && !I && !H && y[x + 1].match(s) && (p = !1), i && (h += y[x]), P && (!n || n.every((v) => x < v[0] || x > v[1])) && (r += y[x]), (z || p || I) && (r.length && (r = this.lipsyncPreProcessText(r, a), r.length && d.push({
|
|
5258
|
+
mark: c,
|
|
5259
5259
|
word: r
|
|
5260
5260
|
})), h.length && (g.push({
|
|
5261
|
-
mark:
|
|
5261
|
+
mark: c,
|
|
5262
5262
|
template: { name: "subtitles" },
|
|
5263
5263
|
ts: [0],
|
|
5264
5264
|
vs: {
|
|
@@ -5267,25 +5267,25 @@ class Me {
|
|
|
5267
5267
|
}), h = ""), r.length)) {
|
|
5268
5268
|
const v = this.lipsyncWordsToVisemes(r, a);
|
|
5269
5269
|
if (v && v.visemes && v.visemes.length) {
|
|
5270
|
-
const
|
|
5271
|
-
for (let
|
|
5270
|
+
const D = v.times[v.visemes.length - 1] + v.durations[v.visemes.length - 1];
|
|
5271
|
+
for (let U = 0; U < v.visemes.length; U++)
|
|
5272
5272
|
g.push({
|
|
5273
|
-
mark:
|
|
5273
|
+
mark: c,
|
|
5274
5274
|
template: { name: "viseme" },
|
|
5275
|
-
ts: [(v.times[
|
|
5275
|
+
ts: [(v.times[U] - 0.6) / D, (v.times[U] + 0.5) / D, (v.times[U] + v.durations[U] + 0.5) / D],
|
|
5276
5276
|
vs: {
|
|
5277
|
-
["viseme_" + v.visemes[
|
|
5277
|
+
["viseme_" + v.visemes[U]]: [null, v.visemes[U] === "PP" || v.visemes[U] === "FF" ? 0.9 : 0.6, 0]
|
|
5278
5278
|
}
|
|
5279
5279
|
});
|
|
5280
5280
|
}
|
|
5281
|
-
r = "",
|
|
5281
|
+
r = "", c++;
|
|
5282
5282
|
}
|
|
5283
5283
|
if (p || I) {
|
|
5284
|
-
if (
|
|
5284
|
+
if (d.length || I && g.length) {
|
|
5285
5285
|
const v = {
|
|
5286
5286
|
anim: g
|
|
5287
5287
|
};
|
|
5288
|
-
i && (v.onSubtitles = i),
|
|
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 = [], r = "", c = 0, g = [];
|
|
5289
5289
|
}
|
|
5290
5290
|
if (H) {
|
|
5291
5291
|
let v = this.animEmojis[y[x]];
|
|
@@ -5379,18 +5379,18 @@ class Me {
|
|
|
5379
5379
|
subtitles: [" " + u]
|
|
5380
5380
|
}
|
|
5381
5381
|
}), !t.visemes)) {
|
|
5382
|
-
const r = this.lipsyncPreProcessText(u, n),
|
|
5383
|
-
if (
|
|
5384
|
-
const
|
|
5382
|
+
const r = this.lipsyncPreProcessText(u, n), c = this.lipsyncWordsToVisemes(r, n);
|
|
5383
|
+
if (c && c.visemes && c.visemes.length) {
|
|
5384
|
+
const d = c.times[c.visemes.length - 1] + c.durations[c.visemes.length - 1], g = Math.min(h, Math.max(0, h - c.visemes.length * 150));
|
|
5385
5385
|
let y = 0.6 + this.convertRange(g, [0, h], [0, 0.4]);
|
|
5386
|
-
if (h = Math.min(h,
|
|
5387
|
-
for (let x = 0; x <
|
|
5388
|
-
const I = a +
|
|
5386
|
+
if (h = Math.min(h, c.visemes.length * 200), d > 0)
|
|
5387
|
+
for (let x = 0; x < c.visemes.length; x++) {
|
|
5388
|
+
const I = a + c.times[x] / d * h, P = c.durations[x] / d * h;
|
|
5389
5389
|
o.push({
|
|
5390
5390
|
template: { name: "viseme" },
|
|
5391
|
-
ts: [I - Math.min(60, 2 *
|
|
5391
|
+
ts: [I - Math.min(60, 2 * P / 3), I + Math.min(25, P / 2), I + P + Math.min(60, P / 2)],
|
|
5392
5392
|
vs: {
|
|
5393
|
-
["viseme_" +
|
|
5393
|
+
["viseme_" + c.visemes[x]]: [null, c.visemes[x] === "PP" || c.visemes[x] === "FF" ? 0.9 : y, 0]
|
|
5394
5394
|
}
|
|
5395
5395
|
});
|
|
5396
5396
|
}
|
|
@@ -5473,31 +5473,31 @@ class Me {
|
|
|
5473
5473
|
const p = h.find((H) => H.name.includes(r) || H.lang === o);
|
|
5474
5474
|
p && (s.voice = p);
|
|
5475
5475
|
}
|
|
5476
|
-
const
|
|
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", y = this.lipsyncPreProcessText(n, g), x = this.lipsyncWordsToVisemes(y, g);
|
|
5477
5477
|
console.log("Browser TTS Lip-sync Debug:", {
|
|
5478
5478
|
text: n,
|
|
5479
5479
|
lipsyncLang: g,
|
|
5480
5480
|
processedText: y,
|
|
5481
5481
|
lipsyncData: x,
|
|
5482
5482
|
hasVisemes: x && x.visemes && x.visemes.length > 0,
|
|
5483
|
-
estimatedDuration:
|
|
5483
|
+
estimatedDuration: c
|
|
5484
5484
|
});
|
|
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
5488
|
for (let H = 0; H < x.visemes.length; H++) {
|
|
5489
|
-
const z = x.visemes[H], v = x.times[H] / p,
|
|
5489
|
+
const z = x.visemes[H], v = x.times[H] / p, D = x.durations[H] / p, U = v * c, _ = D * c;
|
|
5490
5490
|
I.push({
|
|
5491
5491
|
template: { name: "viseme" },
|
|
5492
|
-
ts: [
|
|
5492
|
+
ts: [U - Math.min(60, 2 * _ / 3), U + Math.min(25, _ / 2), U + _ + Math.min(60, _ / 2)],
|
|
5493
5493
|
vs: {
|
|
5494
5494
|
["viseme_" + z]: [null, z === "PP" || z === "FF" ? 0.9 : 0.6, 0]
|
|
5495
5495
|
}
|
|
5496
5496
|
});
|
|
5497
5497
|
}
|
|
5498
5498
|
}
|
|
5499
|
-
const
|
|
5500
|
-
this.audioPlaylist.push({ anim:
|
|
5499
|
+
const P = [...t.anim, ...I];
|
|
5500
|
+
this.audioPlaylist.push({ anim: P, 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);
|
|
@@ -5509,7 +5509,7 @@ class Me {
|
|
|
5509
5509
|
* @param {Object} line Speech line object
|
|
5510
5510
|
*/
|
|
5511
5511
|
async synthesizeWithElevenLabsTTS(t) {
|
|
5512
|
-
const e = t.text.map((
|
|
5512
|
+
const e = t.text.map((c) => c.word).join(" "), i = t.voice || this.avatar.ttsVoice || this.opt.ttsVoice || "21m00Tcm4TlvDq8ikWAM", n = {
|
|
5513
5513
|
text: e,
|
|
5514
5514
|
model_id: "eleven_monolingual_v1",
|
|
5515
5515
|
voice_settings: {
|
|
@@ -5539,18 +5539,18 @@ class Me {
|
|
|
5539
5539
|
lipsyncKeys: this.lipsync ? Object.keys(this.lipsync) : [],
|
|
5540
5540
|
lipsyncLang: u
|
|
5541
5541
|
});
|
|
5542
|
-
const
|
|
5542
|
+
const c = this.lipsyncPreProcessText(e, u), d = this.lipsyncWordsToVisemes(c, u);
|
|
5543
5543
|
if (console.log("Lip-sync data:", {
|
|
5544
|
-
processedText:
|
|
5545
|
-
lipsyncData:
|
|
5546
|
-
hasVisemes:
|
|
5547
|
-
}),
|
|
5544
|
+
processedText: c,
|
|
5545
|
+
lipsyncData: d,
|
|
5546
|
+
hasVisemes: d && d.visemes && d.visemes.length > 0
|
|
5547
|
+
}), d && d.visemes && d.visemes.length > 0)
|
|
5548
5548
|
a = {
|
|
5549
|
-
visemes:
|
|
5549
|
+
visemes: d.visemes.map((g, y) => ({
|
|
5550
5550
|
viseme: g,
|
|
5551
|
-
startTime: y * l.duration /
|
|
5552
|
-
endTime: (y + 1) * l.duration /
|
|
5553
|
-
duration: l.duration /
|
|
5551
|
+
startTime: y * l.duration / d.visemes.length,
|
|
5552
|
+
endTime: (y + 1) * l.duration / d.visemes.length,
|
|
5553
|
+
duration: l.duration / d.visemes.length,
|
|
5554
5554
|
intensity: 0.7
|
|
5555
5555
|
})),
|
|
5556
5556
|
words: [],
|
|
@@ -5559,10 +5559,10 @@ class Me {
|
|
|
5559
5559
|
};
|
|
5560
5560
|
else
|
|
5561
5561
|
throw new Error("No visemes generated from text");
|
|
5562
|
-
} catch (
|
|
5563
|
-
console.error("Text-based lip-sync failed, using fallback:",
|
|
5564
|
-
const
|
|
5565
|
-
for (const y of
|
|
5562
|
+
} catch (c) {
|
|
5563
|
+
console.error("Text-based lip-sync failed, using fallback:", c);
|
|
5564
|
+
const d = e.toLowerCase().split(/\s+/), g = [];
|
|
5565
|
+
for (const y of d)
|
|
5566
5566
|
for (const x of y) {
|
|
5567
5567
|
let I = "aa";
|
|
5568
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);
|
|
@@ -5595,13 +5595,13 @@ class Me {
|
|
|
5595
5595
|
const h = [];
|
|
5596
5596
|
if (a.visemes && a.visemes.length > 0) {
|
|
5597
5597
|
console.log("ElevenLabs: Generating lip-sync animation from", a.visemes.length, "visemes");
|
|
5598
|
-
for (let
|
|
5599
|
-
const
|
|
5598
|
+
for (let c = 0; c < a.visemes.length; c++) {
|
|
5599
|
+
const d = a.visemes[c], g = d.startTime * 1e3, y = d.duration * 1e3, x = d.intensity;
|
|
5600
5600
|
h.push({
|
|
5601
5601
|
template: { name: "viseme" },
|
|
5602
5602
|
ts: [g - Math.min(60, 2 * y / 3), g + Math.min(25, y / 2), g + y + Math.min(60, y / 2)],
|
|
5603
5603
|
vs: {
|
|
5604
|
-
["viseme_" +
|
|
5604
|
+
["viseme_" + d.viseme]: [null, x, 0]
|
|
5605
5605
|
}
|
|
5606
5606
|
});
|
|
5607
5607
|
}
|
|
@@ -5616,7 +5616,7 @@ class Me {
|
|
|
5616
5616
|
* @param {Object} line Speech line object
|
|
5617
5617
|
*/
|
|
5618
5618
|
async synthesizeWithDeepgramTTS(t) {
|
|
5619
|
-
const e = t.text.map((
|
|
5619
|
+
const e = t.text.map((c) => c.word).join(" "), i = t.voice || this.avatar.ttsVoice || this.opt.ttsVoice || "aura-2-thalia-en", n = `${this.opt.ttsEndpoint}?model=${i}`, s = await fetch(n, {
|
|
5620
5620
|
method: "POST",
|
|
5621
5621
|
headers: {
|
|
5622
5622
|
Authorization: `Token ${this.opt.ttsApikey}`,
|
|
@@ -5637,18 +5637,18 @@ class Me {
|
|
|
5637
5637
|
lipsyncKeys: this.lipsync ? Object.keys(this.lipsync) : [],
|
|
5638
5638
|
lipsyncLang: u
|
|
5639
5639
|
});
|
|
5640
|
-
const
|
|
5640
|
+
const c = this.lipsyncPreProcessText(e, u), d = this.lipsyncWordsToVisemes(c, u);
|
|
5641
5641
|
if (console.log("Lip-sync data:", {
|
|
5642
|
-
processedText:
|
|
5643
|
-
lipsyncData:
|
|
5644
|
-
hasVisemes:
|
|
5645
|
-
}),
|
|
5642
|
+
processedText: c,
|
|
5643
|
+
lipsyncData: d,
|
|
5644
|
+
hasVisemes: d && d.visemes && d.visemes.length > 0
|
|
5645
|
+
}), d && d.visemes && d.visemes.length > 0)
|
|
5646
5646
|
a = {
|
|
5647
|
-
visemes:
|
|
5647
|
+
visemes: d.visemes.map((g, y) => ({
|
|
5648
5648
|
viseme: g,
|
|
5649
|
-
startTime: y * l.duration /
|
|
5650
|
-
endTime: (y + 1) * l.duration /
|
|
5651
|
-
duration: l.duration /
|
|
5649
|
+
startTime: y * l.duration / d.visemes.length,
|
|
5650
|
+
endTime: (y + 1) * l.duration / d.visemes.length,
|
|
5651
|
+
duration: l.duration / d.visemes.length,
|
|
5652
5652
|
intensity: 0.7
|
|
5653
5653
|
})),
|
|
5654
5654
|
words: [],
|
|
@@ -5657,10 +5657,10 @@ class Me {
|
|
|
5657
5657
|
};
|
|
5658
5658
|
else
|
|
5659
5659
|
throw new Error("No visemes generated from text");
|
|
5660
|
-
} catch (
|
|
5661
|
-
console.error("Text-based lip-sync failed, using fallback:",
|
|
5662
|
-
const
|
|
5663
|
-
for (const y of
|
|
5660
|
+
} catch (c) {
|
|
5661
|
+
console.error("Text-based lip-sync failed, using fallback:", c);
|
|
5662
|
+
const d = e.toLowerCase().split(/\s+/), g = [];
|
|
5663
|
+
for (const y of d)
|
|
5664
5664
|
for (const x of y) {
|
|
5665
5665
|
let I = "aa";
|
|
5666
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);
|
|
@@ -5693,13 +5693,13 @@ class Me {
|
|
|
5693
5693
|
const h = [];
|
|
5694
5694
|
if (a.visemes && a.visemes.length > 0) {
|
|
5695
5695
|
console.log("Deepgram: Generating lip-sync animation from", a.visemes.length, "visemes");
|
|
5696
|
-
for (let
|
|
5697
|
-
const
|
|
5696
|
+
for (let c = 0; c < a.visemes.length; c++) {
|
|
5697
|
+
const d = a.visemes[c], g = d.startTime * 1e3, y = d.duration * 1e3, x = d.intensity;
|
|
5698
5698
|
h.push({
|
|
5699
5699
|
template: { name: "viseme" },
|
|
5700
5700
|
ts: [g - Math.min(60, 2 * y / 3), g + Math.min(25, y / 2), g + y + Math.min(60, y / 2)],
|
|
5701
5701
|
vs: {
|
|
5702
|
-
["viseme_" +
|
|
5702
|
+
["viseme_" + d.viseme]: [null, x, 0]
|
|
5703
5703
|
}
|
|
5704
5704
|
});
|
|
5705
5705
|
}
|
|
@@ -5746,12 +5746,12 @@ class Me {
|
|
|
5746
5746
|
});
|
|
5747
5747
|
const a = [];
|
|
5748
5748
|
for (let r = 0; r < u.visemes.length; r++) {
|
|
5749
|
-
const
|
|
5749
|
+
const c = u.visemes[r], d = c.startTime * 1e3, g = c.duration * 1e3, y = c.intensity;
|
|
5750
5750
|
a.push({
|
|
5751
5751
|
template: { name: "viseme" },
|
|
5752
|
-
ts: [
|
|
5752
|
+
ts: [d - Math.min(60, 2 * g / 3), d + Math.min(25, g / 2), d + g + Math.min(60, g / 2)],
|
|
5753
5753
|
vs: {
|
|
5754
|
-
["viseme_" +
|
|
5754
|
+
["viseme_" + c.viseme]: [null, y, 0]
|
|
5755
5755
|
}
|
|
5756
5756
|
});
|
|
5757
5757
|
}
|
|
@@ -5797,25 +5797,25 @@ class Me {
|
|
|
5797
5797
|
this.speakWithHands();
|
|
5798
5798
|
const u = [0];
|
|
5799
5799
|
let a = 0;
|
|
5800
|
-
t.text.forEach((
|
|
5801
|
-
if (
|
|
5800
|
+
t.text.forEach((c, d) => {
|
|
5801
|
+
if (d > 0) {
|
|
5802
5802
|
let g = u[u.length - 1];
|
|
5803
|
-
s.timepoints[a] && (g = s.timepoints[a].timeSeconds * 1e3, s.timepoints[a].markName === "" +
|
|
5803
|
+
s.timepoints[a] && (g = s.timepoints[a].timeSeconds * 1e3, s.timepoints[a].markName === "" + c.mark && a++), u.push(g);
|
|
5804
5804
|
}
|
|
5805
5805
|
});
|
|
5806
5806
|
const h = [{ mark: 0, time: 0 }];
|
|
5807
|
-
u.forEach((
|
|
5808
|
-
if (
|
|
5809
|
-
let g =
|
|
5810
|
-
h[
|
|
5807
|
+
u.forEach((c, d) => {
|
|
5808
|
+
if (d > 0) {
|
|
5809
|
+
let g = c - u[d - 1];
|
|
5810
|
+
h[d - 1].duration = g, h.push({ mark: d, time: c });
|
|
5811
5811
|
}
|
|
5812
5812
|
});
|
|
5813
5813
|
let r = 1e3 * l.duration;
|
|
5814
|
-
r > this.opt.ttsTrimEnd && (r = r - this.opt.ttsTrimEnd), h[h.length - 1].duration = r - h[h.length - 1].time, t.anim.forEach((
|
|
5815
|
-
const
|
|
5816
|
-
if (
|
|
5817
|
-
for (let g = 0; g <
|
|
5818
|
-
|
|
5814
|
+
r > this.opt.ttsTrimEnd && (r = r - this.opt.ttsTrimEnd), h[h.length - 1].duration = r - h[h.length - 1].time, t.anim.forEach((c) => {
|
|
5815
|
+
const d = h[c.mark];
|
|
5816
|
+
if (d)
|
|
5817
|
+
for (let g = 0; g < c.ts.length; g++)
|
|
5818
|
+
c.ts[g] = d.time + c.ts[g] * d.duration + this.opt.ttsTrimStart;
|
|
5819
5819
|
}), this.audioPlaylist.push({ anim: t.anim, audio: l }), this.onSubtitles = t.onSubtitles || null, this.resetLips(), t.mood && this.setMood(t.mood), this.playAudio();
|
|
5820
5820
|
} else
|
|
5821
5821
|
this.startSpeaking(!0);
|
|
@@ -6034,15 +6034,15 @@ class Me {
|
|
|
6034
6034
|
const l = this.streamLipsyncLang || this.avatar.lipsyncLang || this.opt.lipsyncLang, u = this.lipsyncPreProcessText(n, l), a = this.lipsyncWordsToVisemes(u, l);
|
|
6035
6035
|
if (a && a.visemes && a.visemes.length) {
|
|
6036
6036
|
const h = a.times[a.visemes.length - 1] + a.durations[a.visemes.length - 1], r = Math.min(o, Math.max(0, o - a.visemes.length * 150));
|
|
6037
|
-
let
|
|
6037
|
+
let c = 0.6 + this.convertRange(r, [0, o], [0, 0.4]);
|
|
6038
6038
|
if (o = Math.min(o, a.visemes.length * 200), h > 0)
|
|
6039
|
-
for (let
|
|
6040
|
-
const g = e + s + a.times[
|
|
6039
|
+
for (let d = 0; d < a.visemes.length; d++) {
|
|
6040
|
+
const g = e + s + a.times[d] / h * o, y = a.durations[d] / h * o;
|
|
6041
6041
|
this.animQueue.push({
|
|
6042
6042
|
template: { name: "viseme" },
|
|
6043
6043
|
ts: [g - Math.min(60, 2 * y / 3), g + Math.min(25, y / 2), g + y + Math.min(60, y / 2)],
|
|
6044
6044
|
vs: {
|
|
6045
|
-
["viseme_" + a.visemes[
|
|
6045
|
+
["viseme_" + a.visemes[d]]: [null, a.visemes[d] === "PP" || a.visemes[d] === "FF" ? 0.9 : c, 0]
|
|
6046
6046
|
}
|
|
6047
6047
|
});
|
|
6048
6048
|
}
|
|
@@ -6146,12 +6146,12 @@ class Me {
|
|
|
6146
6146
|
this.lookAt(null, null, t);
|
|
6147
6147
|
return;
|
|
6148
6148
|
}
|
|
6149
|
-
this.objectLeftEye.updateMatrixWorld(!0), this.objectRightEye.updateMatrixWorld(!0), ae.setFromMatrixPosition(this.objectLeftEye.matrixWorld), le.setFromMatrixPosition(this.objectRightEye.matrixWorld), ae.add(le).divideScalar(2),
|
|
6149
|
+
this.objectLeftEye.updateMatrixWorld(!0), this.objectRightEye.updateMatrixWorld(!0), ae.setFromMatrixPosition(this.objectLeftEye.matrixWorld), le.setFromMatrixPosition(this.objectRightEye.matrixWorld), ae.add(le).divideScalar(2), V.copy(this.armature.quaternion), V.multiply(this.poseTarget.props["Hips.quaternion"]), V.multiply(this.poseTarget.props["Spine.quaternion"]), V.multiply(this.poseTarget.props["Spine1.quaternion"]), V.multiply(this.poseTarget.props["Spine2.quaternion"]), V.multiply(this.poseTarget.props["Neck.quaternion"]), V.multiply(this.poseTarget.props["Head.quaternion"]);
|
|
6150
6150
|
const i = new f.Vector3().subVectors(e, ae).normalize(), n = Math.atan2(i.x, i.z), s = Math.asin(-i.y);
|
|
6151
6151
|
M.set(s, n, 0, "YXZ");
|
|
6152
|
-
const l = new f.Quaternion().setFromEuler(M), u = new f.Quaternion().copy(l).multiply(
|
|
6152
|
+
const l = new f.Quaternion().setFromEuler(M), u = new f.Quaternion().copy(l).multiply(V.clone().invert());
|
|
6153
6153
|
M.setFromQuaternion(u, "YXZ");
|
|
6154
|
-
let a = M.x / (40 / 24) + 0.2, h = M.y / (9 / 4), r = Math.min(0.6, Math.max(-0.3, a)),
|
|
6154
|
+
let a = M.x / (40 / 24) + 0.2, h = M.y / (9 / 4), r = Math.min(0.6, Math.max(-0.3, a)), c = Math.min(0.8, Math.max(-0.8, h)), d = (Math.random() - 0.5) / 4, g = (Math.random() - 0.5) / 4;
|
|
6155
6155
|
if (t) {
|
|
6156
6156
|
let y = this.animQueue.findIndex((I) => I.template.name === "lookat");
|
|
6157
6157
|
y !== -1 && this.animQueue.splice(y, 1);
|
|
@@ -6159,9 +6159,9 @@ class Me {
|
|
|
6159
6159
|
name: "lookat",
|
|
6160
6160
|
dt: [750, t],
|
|
6161
6161
|
vs: {
|
|
6162
|
-
bodyRotateX: [r +
|
|
6163
|
-
bodyRotateY: [
|
|
6164
|
-
eyesRotateX: [-3 *
|
|
6162
|
+
bodyRotateX: [r + d],
|
|
6163
|
+
bodyRotateY: [c + g],
|
|
6164
|
+
eyesRotateX: [-3 * d + 0.1],
|
|
6165
6165
|
eyesRotateY: [-5 * g],
|
|
6166
6166
|
browInnerUp: [[0, 0.7]],
|
|
6167
6167
|
mouthLeft: [[0, 0.7]],
|
|
@@ -6186,10 +6186,10 @@ class Me {
|
|
|
6186
6186
|
const s = new f.Vector3().setFromMatrixPosition(this.objectLeftEye.matrixWorld), o = new f.Vector3().setFromMatrixPosition(this.objectRightEye.matrixWorld), l = new f.Vector3().addVectors(s, o).divideScalar(2);
|
|
6187
6187
|
l.project(this.camera);
|
|
6188
6188
|
let u = (l.x + 1) / 2 * n.width + n.left, a = -(l.y - 1) / 2 * n.height + n.top;
|
|
6189
|
-
t === null && (t = u), e === null && (e = a),
|
|
6190
|
-
let h = M.x / (40 / 24), r = M.y / (9 / 4),
|
|
6189
|
+
t === null && (t = u), e === null && (e = a), V.copy(this.armature.quaternion), V.multiply(this.poseTarget.props["Hips.quaternion"]), V.multiply(this.poseTarget.props["Spine.quaternion"]), V.multiply(this.poseTarget.props["Spine1.quaternion"]), V.multiply(this.poseTarget.props["Spine2.quaternion"]), V.multiply(this.poseTarget.props["Neck.quaternion"]), V.multiply(this.poseTarget.props["Head.quaternion"]), M.setFromQuaternion(V);
|
|
6190
|
+
let h = M.x / (40 / 24), r = 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 - u, u), y = Math.max(window.innerHeight - a, a), x = this.convertRange(e, [a - y, a + y], [-0.3, 0.6]) - h + c, I = this.convertRange(t, [u - g, u + g], [-0.8, 0.8]) - r + d;
|
|
6191
6191
|
x = Math.min(0.6, Math.max(-0.3, x)), I = Math.min(0.8, Math.max(-0.8, I));
|
|
6192
|
-
let
|
|
6192
|
+
let P = (Math.random() - 0.5) / 4, p = (Math.random() - 0.5) / 4;
|
|
6193
6193
|
if (i) {
|
|
6194
6194
|
let H = this.animQueue.findIndex((v) => v.template.name === "lookat");
|
|
6195
6195
|
H !== -1 && this.animQueue.splice(H, 1);
|
|
@@ -6197,9 +6197,9 @@ class Me {
|
|
|
6197
6197
|
name: "lookat",
|
|
6198
6198
|
dt: [750, i],
|
|
6199
6199
|
vs: {
|
|
6200
|
-
bodyRotateX: [x +
|
|
6200
|
+
bodyRotateX: [x + P],
|
|
6201
6201
|
bodyRotateY: [I + p],
|
|
6202
|
-
eyesRotateX: [-3 *
|
|
6202
|
+
eyesRotateX: [-3 * P + 0.1],
|
|
6203
6203
|
eyesRotateY: [-5 * p],
|
|
6204
6204
|
browInnerUp: [[0, 0.7]],
|
|
6205
6205
|
mouthLeft: [[0, 0.7]],
|
|
@@ -6395,58 +6395,58 @@ class Me {
|
|
|
6395
6395
|
}
|
|
6396
6396
|
let a = !1;
|
|
6397
6397
|
try {
|
|
6398
|
-
const
|
|
6399
|
-
if (a =
|
|
6400
|
-
console.error(`FBX file not found at ${t}. Status: ${
|
|
6398
|
+
const c = await fetch(t, { method: "HEAD" });
|
|
6399
|
+
if (a = c.ok, !a) {
|
|
6400
|
+
console.error(`FBX file not found at ${t}. Status: ${c.status}`), console.error("Please check:"), console.error("1. File path is correct (note: path is case-sensitive)"), console.error("2. File exists in your public folder"), console.error("3. File is accessible (not blocked by server)");
|
|
6401
6401
|
return;
|
|
6402
6402
|
}
|
|
6403
|
-
} catch (
|
|
6404
|
-
console.warn(`Could not verify file existence for ${t}, attempting to load anyway:`,
|
|
6403
|
+
} catch (c) {
|
|
6404
|
+
console.warn(`Could not verify file existence for ${t}, attempting to load anyway:`, c);
|
|
6405
6405
|
}
|
|
6406
6406
|
const h = new ke();
|
|
6407
6407
|
let r;
|
|
6408
6408
|
try {
|
|
6409
6409
|
r = await h.loadAsync(t, e);
|
|
6410
|
-
} catch (
|
|
6411
|
-
console.error(`Failed to load FBX animation from ${t}:`,
|
|
6412
|
-
message:
|
|
6410
|
+
} catch (c) {
|
|
6411
|
+
console.error(`Failed to load FBX animation from ${t}:`, c), console.error("Error details:", {
|
|
6412
|
+
message: c.message,
|
|
6413
6413
|
url: t,
|
|
6414
6414
|
suggestion: "Make sure the file is a valid FBX file and the path is correct"
|
|
6415
|
-
}),
|
|
6415
|
+
}), c.message && c.message.includes("version number") && (console.error("FBX Loader Error: Cannot find version number"), console.error("This error usually means:"), console.error("1. The file is not a valid FBX file (might be GLB, corrupted, or wrong format)"), console.error("2. The file might be corrupted"), console.error("3. The file path might be incorrect"), console.error("4. The server returned an HTML error page instead of the FBX file"), console.error("5. The file might not exist at that path"), console.error(""), console.error("Solution: Please verify:"), console.error(` - File exists at: ${t}`), console.error(" - File is a valid FBX binary file"), console.error(" - File path matches your public folder structure"), console.error(" - File is not corrupted"));
|
|
6416
6416
|
try {
|
|
6417
|
-
const
|
|
6417
|
+
const d = await fetch(t), g = d.headers.get("content-type"), y = await d.text();
|
|
6418
6418
|
console.error("Response details:", {
|
|
6419
|
-
status:
|
|
6419
|
+
status: d.status,
|
|
6420
6420
|
contentType: g,
|
|
6421
6421
|
firstBytes: y.substring(0, 100),
|
|
6422
6422
|
isHTML: y.trim().startsWith("<!DOCTYPE") || y.trim().startsWith("<html")
|
|
6423
6423
|
}), (y.trim().startsWith("<!DOCTYPE") || y.trim().startsWith("<html")) && console.error("The server returned an HTML page instead of an FBX file. The file path is likely incorrect.");
|
|
6424
|
-
} catch (
|
|
6425
|
-
console.error("Could not fetch file for debugging:",
|
|
6424
|
+
} catch (d) {
|
|
6425
|
+
console.error("Could not fetch file for debugging:", d);
|
|
6426
6426
|
}
|
|
6427
6427
|
return;
|
|
6428
6428
|
}
|
|
6429
6429
|
if (r && r.animations && r.animations[n]) {
|
|
6430
|
-
let
|
|
6431
|
-
const
|
|
6432
|
-
|
|
6430
|
+
let c = r.animations[n];
|
|
6431
|
+
const d = {};
|
|
6432
|
+
c.tracks.forEach((y) => {
|
|
6433
6433
|
y.name = y.name.replaceAll("mixamorig", "");
|
|
6434
6434
|
const x = y.name.split(".");
|
|
6435
6435
|
if (x[1] === "position") {
|
|
6436
6436
|
for (let I = 0; I < y.values.length; I++)
|
|
6437
6437
|
y.values[I] = y.values[I] * s;
|
|
6438
|
-
|
|
6439
|
-
} else x[1] === "quaternion" ?
|
|
6438
|
+
d[y.name] = new f.Vector3(y.values[0], y.values[1], y.values[2]);
|
|
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
|
});
|
|
6441
|
-
const g = { props:
|
|
6442
|
-
|
|
6441
|
+
const g = { props: d };
|
|
6442
|
+
d["Hips.position"] && (d["Hips.position"].y < 0.5 ? g.lying = !0 : g.standing = !0), this.animClips.push({
|
|
6443
6443
|
url: t + "-" + n,
|
|
6444
|
-
clip:
|
|
6444
|
+
clip: c,
|
|
6445
6445
|
pose: g
|
|
6446
6446
|
}), this.playAnimation(t, e, i, n, s);
|
|
6447
6447
|
} else {
|
|
6448
|
-
const
|
|
6449
|
-
console.error(
|
|
6448
|
+
const c = "Animation " + t + " (ndx=" + n + ") not found";
|
|
6449
|
+
console.error(c), r && r.animations ? console.error(`FBX file loaded but has ${r.animations.length} animation(s), requested index ${n}`) : console.error(r ? "FBX file loaded but contains no animations" : "FBX file failed to load or is invalid");
|
|
6450
6450
|
}
|
|
6451
6451
|
}
|
|
6452
6452
|
}
|
|
@@ -6484,10 +6484,10 @@ class Me {
|
|
|
6484
6484
|
if (u && u.animations && u.animations[n]) {
|
|
6485
6485
|
let a = u.animations[n];
|
|
6486
6486
|
const h = {};
|
|
6487
|
-
a.tracks.forEach((
|
|
6488
|
-
|
|
6489
|
-
const
|
|
6490
|
-
|
|
6487
|
+
a.tracks.forEach((c) => {
|
|
6488
|
+
c.name = c.name.replaceAll("mixamorig", "");
|
|
6489
|
+
const d = c.name.split(".");
|
|
6490
|
+
d[1] === "position" ? h[c.name] = new f.Vector3(c.values[0] * s, c.values[1] * s, c.values[2] * s) : d[1] === "quaternion" ? h[c.name] = new f.Quaternion(c.values[0], c.values[1], c.values[2], c.values[3]) : d[1] === "rotation" && (h[d[0] + ".quaternion"] = new f.Quaternion().setFromEuler(new f.Euler(c.values[0], c.values[1], c.values[2], "XYZ")).normalize());
|
|
6491
6491
|
});
|
|
6492
6492
|
const r = { props: h };
|
|
6493
6493
|
h["Hips.position"] && (h["Hips.position"].y < 0.5 ? r.lying = !0 : r.standing = !0), this.animPoses.push({
|
|
@@ -6532,13 +6532,13 @@ class Me {
|
|
|
6532
6532
|
if (l.gesture = !0, e && Number.isFinite(e)) {
|
|
6533
6533
|
const u = l.ts[0], h = l.ts[l.ts.length - 1] - u;
|
|
6534
6534
|
if (e * 1e3 - h > 0) {
|
|
6535
|
-
const
|
|
6536
|
-
for (let y = 1; y < l.ts.length; y++)
|
|
6537
|
-
const
|
|
6538
|
-
l.ts = l.ts.map((y, x, I) => x === 0 ? u : I[x - 1] +
|
|
6535
|
+
const c = [];
|
|
6536
|
+
for (let y = 1; y < l.ts.length; y++) c.push(l.ts[y] - l.ts[y - 1]);
|
|
6537
|
+
const d = o.template?.rescale || c.map((y) => y / h), g = e * 1e3 - h;
|
|
6538
|
+
l.ts = l.ts.map((y, x, I) => x === 0 ? u : I[x - 1] + c[x - 1] + d[x - 1] * g);
|
|
6539
6539
|
} else {
|
|
6540
|
-
const
|
|
6541
|
-
l.ts = l.ts.map((
|
|
6540
|
+
const c = e * 1e3 / h;
|
|
6541
|
+
l.ts = l.ts.map((d) => u + c * (d - u));
|
|
6542
6542
|
}
|
|
6543
6543
|
}
|
|
6544
6544
|
this.animQueue.push(l);
|
|
@@ -6568,21 +6568,21 @@ class Me {
|
|
|
6568
6568
|
* @param {numeric} [d=null] If set, apply in d milliseconds
|
|
6569
6569
|
*/
|
|
6570
6570
|
ikSolve(t, e = null, i = !1, n = null) {
|
|
6571
|
-
const s = new f.Vector3(), o = new f.Vector3(), l = new f.Vector3(), u = new f.Vector3(), a = new f.Quaternion(), h = new f.Vector3(), r = new f.Vector3(),
|
|
6572
|
-
|
|
6571
|
+
const s = new f.Vector3(), o = new f.Vector3(), l = new f.Vector3(), u = new f.Vector3(), a = new f.Quaternion(), h = new f.Vector3(), r = new f.Vector3(), c = new f.Vector3(), d = this.ikMesh.getObjectByName(t.root);
|
|
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
6574
|
y.forEach((I) => {
|
|
6575
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
6579
|
for (let I = 0; I < x; I++) {
|
|
6580
|
-
let
|
|
6580
|
+
let P = !1;
|
|
6581
6581
|
for (let p = 0, H = y.length; p < H; p++) {
|
|
6582
6582
|
const z = y[p].bone;
|
|
6583
6583
|
z.matrixWorld.decompose(u, a, h), a.invert(), o.setFromMatrixPosition(g.matrixWorld), l.subVectors(o, u), l.applyQuaternion(a), l.normalize(), s.subVectors(e, u), s.applyQuaternion(a), s.normalize();
|
|
6584
6584
|
let v = s.dot(l);
|
|
6585
|
-
v > 1 ? v = 1 : v < -1 && (v = -1), v = Math.acos(v), !(v < 1e-5) && (y[p].minAngle !== void 0 && v < y[p].minAngle && (v = y[p].minAngle), y[p].maxAngle !== void 0 && v > y[p].maxAngle && (v = y[p].maxAngle), r.crossVectors(l, s), r.normalize(),
|
|
6585
|
+
v > 1 ? v = 1 : v < -1 && (v = -1), v = Math.acos(v), !(v < 1e-5) && (y[p].minAngle !== void 0 && v < y[p].minAngle && (v = y[p].minAngle), y[p].maxAngle !== void 0 && v > y[p].maxAngle && (v = y[p].maxAngle), r.crossVectors(l, s), r.normalize(), V.setFromAxisAngle(r, v), z.quaternion.multiply(V), z.rotation.setFromVector3(c.setFromEuler(z.rotation).clamp(new f.Vector3(
|
|
6586
6586
|
y[p].minx !== void 0 ? y[p].minx : -1 / 0,
|
|
6587
6587
|
y[p].miny !== void 0 ? y[p].miny : -1 / 0,
|
|
6588
6588
|
y[p].minz !== void 0 ? y[p].minz : -1 / 0
|
|
@@ -6590,9 +6590,9 @@ class Me {
|
|
|
6590
6590
|
y[p].maxx !== void 0 ? y[p].maxx : 1 / 0,
|
|
6591
6591
|
y[p].maxy !== void 0 ? y[p].maxy : 1 / 0,
|
|
6592
6592
|
y[p].maxz !== void 0 ? y[p].maxz : 1 / 0
|
|
6593
|
-
))), z.updateMatrixWorld(!0),
|
|
6593
|
+
))), z.updateMatrixWorld(!0), P = !0);
|
|
6594
6594
|
}
|
|
6595
|
-
if (!
|
|
6595
|
+
if (!P) break;
|
|
6596
6596
|
}
|
|
6597
6597
|
n && y.forEach((I) => {
|
|
6598
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;
|
|
@@ -6655,16 +6655,16 @@ function Le() {
|
|
|
6655
6655
|
};
|
|
6656
6656
|
}
|
|
6657
6657
|
function xt() {
|
|
6658
|
-
const
|
|
6659
|
-
return Object.entries(
|
|
6658
|
+
const N = Le(), t = [];
|
|
6659
|
+
return Object.entries(N.voices).forEach(([e, i]) => {
|
|
6660
6660
|
t.push({
|
|
6661
6661
|
value: i,
|
|
6662
|
-
label: `${e.charAt(0).toUpperCase() + e.slice(1)} (${
|
|
6662
|
+
label: `${e.charAt(0).toUpperCase() + e.slice(1)} (${N.service})`
|
|
6663
6663
|
});
|
|
6664
6664
|
}), t;
|
|
6665
6665
|
}
|
|
6666
6666
|
const Ee = ve(({
|
|
6667
|
-
avatarUrl:
|
|
6667
|
+
avatarUrl: N = "/avatars/brunette.glb",
|
|
6668
6668
|
avatarBody: t = "F",
|
|
6669
6669
|
mood: e = "neutral",
|
|
6670
6670
|
ttsLang: i = "en",
|
|
@@ -6677,15 +6677,15 @@ const Ee = ve(({
|
|
|
6677
6677
|
cameraView: h = "upper",
|
|
6678
6678
|
onReady: r = () => {
|
|
6679
6679
|
},
|
|
6680
|
-
onLoading:
|
|
6680
|
+
onLoading: c = () => {
|
|
6681
6681
|
},
|
|
6682
|
-
onError:
|
|
6682
|
+
onError: d = () => {
|
|
6683
6683
|
},
|
|
6684
6684
|
className: g = "",
|
|
6685
6685
|
style: y = {},
|
|
6686
6686
|
animations: x = {}
|
|
6687
6687
|
}, I) => {
|
|
6688
|
-
const
|
|
6688
|
+
const P = Z(null), p = Z(null), H = Z(a), z = Z(null), [v, D] = ce(!0), [U, _] = ce(null), [ne, S] = ce(!1), [W, G] = ce(!1);
|
|
6689
6689
|
pe(() => {
|
|
6690
6690
|
H.current = a;
|
|
6691
6691
|
}, [a]);
|
|
@@ -6714,7 +6714,7 @@ const Ee = ve(({
|
|
|
6714
6714
|
apiKey: o !== null ? o : E.apiKey
|
|
6715
6715
|
};
|
|
6716
6716
|
const ue = {
|
|
6717
|
-
url:
|
|
6717
|
+
url: N,
|
|
6718
6718
|
body: t,
|
|
6719
6719
|
avatarMood: e,
|
|
6720
6720
|
ttsLang: X === "browser" ? "en-US" : i,
|
|
@@ -6730,49 +6730,49 @@ const Ee = ve(({
|
|
|
6730
6730
|
lipsyncModules: ["en"],
|
|
6731
6731
|
cameraView: h
|
|
6732
6732
|
}, ge = T(async () => {
|
|
6733
|
-
if (!(!
|
|
6733
|
+
if (!(!P.current || p.current))
|
|
6734
6734
|
try {
|
|
6735
|
-
if (
|
|
6735
|
+
if (D(!0), _(null), p.current = new Me(P.current, Re), 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(ue, (j) => {
|
|
6736
6736
|
if (j.lengthComputable) {
|
|
6737
|
-
const
|
|
6738
|
-
|
|
6737
|
+
const B = Math.min(100, Math.round(j.loaded / j.total * 100));
|
|
6738
|
+
c(B);
|
|
6739
6739
|
}
|
|
6740
6740
|
}), await new Promise((j) => {
|
|
6741
|
-
const
|
|
6742
|
-
p.current.lipsync && Object.keys(p.current.lipsync).length > 0 ? j() : setTimeout(
|
|
6741
|
+
const B = () => {
|
|
6742
|
+
p.current.lipsync && Object.keys(p.current.lipsync).length > 0 ? j() : setTimeout(B, 100);
|
|
6743
6743
|
};
|
|
6744
|
-
|
|
6744
|
+
B();
|
|
6745
6745
|
}), p.current && p.current.setShowFullAvatar)
|
|
6746
6746
|
try {
|
|
6747
6747
|
p.current.setShowFullAvatar(a);
|
|
6748
6748
|
} catch (j) {
|
|
6749
6749
|
console.warn("Error setting full body mode on initialization:", j);
|
|
6750
6750
|
}
|
|
6751
|
-
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()),
|
|
6752
|
-
const
|
|
6751
|
+
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()), D(!1), S(!0), r(p.current);
|
|
6752
|
+
const F = () => {
|
|
6753
6753
|
document.visibilityState === "visible" ? p.current?.start() : p.current?.stop();
|
|
6754
6754
|
};
|
|
6755
|
-
return document.addEventListener("visibilitychange",
|
|
6756
|
-
document.removeEventListener("visibilitychange",
|
|
6755
|
+
return document.addEventListener("visibilitychange", F), () => {
|
|
6756
|
+
document.removeEventListener("visibilitychange", F);
|
|
6757
6757
|
};
|
|
6758
6758
|
} catch (A) {
|
|
6759
|
-
console.error("Error initializing TalkingHead:", A), _(A.message || "Failed to initialize avatar"),
|
|
6759
|
+
console.error("Error initializing TalkingHead:", A), _(A.message || "Failed to initialize avatar"), D(!1), d(A);
|
|
6760
6760
|
}
|
|
6761
|
-
}, [
|
|
6761
|
+
}, [N, t, e, i, n, s, o, a, l, u, h]);
|
|
6762
6762
|
pe(() => (ge(), () => {
|
|
6763
6763
|
p.current && (p.current.stop(), p.current.dispose(), p.current = null);
|
|
6764
6764
|
}), [ge]), pe(() => {
|
|
6765
|
-
if (!
|
|
6765
|
+
if (!P.current || !p.current) return;
|
|
6766
6766
|
const A = new ResizeObserver((j) => {
|
|
6767
|
-
for (const
|
|
6767
|
+
for (const B of j)
|
|
6768
6768
|
p.current && p.current.onResize && p.current.onResize();
|
|
6769
6769
|
});
|
|
6770
|
-
A.observe(
|
|
6771
|
-
const
|
|
6770
|
+
A.observe(P.current);
|
|
6771
|
+
const F = () => {
|
|
6772
6772
|
p.current && p.current.onResize && p.current.onResize();
|
|
6773
6773
|
};
|
|
6774
|
-
return window.addEventListener("resize",
|
|
6775
|
-
A.disconnect(), window.removeEventListener("resize",
|
|
6774
|
+
return window.addEventListener("resize", F), () => {
|
|
6775
|
+
A.disconnect(), window.removeEventListener("resize", F);
|
|
6776
6776
|
};
|
|
6777
6777
|
}, [ne]);
|
|
6778
6778
|
const re = T(async () => {
|
|
@@ -6782,37 +6782,37 @@ const Ee = ve(({
|
|
|
6782
6782
|
} catch (A) {
|
|
6783
6783
|
console.warn("Failed to resume audio context:", A);
|
|
6784
6784
|
}
|
|
6785
|
-
}, []), J = T(async (A,
|
|
6785
|
+
}, []), J = T(async (A, F = {}) => {
|
|
6786
6786
|
if (p.current && ne)
|
|
6787
6787
|
try {
|
|
6788
|
-
z.current = { text: A, options:
|
|
6788
|
+
z.current = { text: A, options: F }, G(!1), await re();
|
|
6789
6789
|
const j = {
|
|
6790
|
-
...
|
|
6791
|
-
lipsyncLang:
|
|
6790
|
+
...F,
|
|
6791
|
+
lipsyncLang: F.lipsyncLang || ue.lipsyncLang || "en"
|
|
6792
6792
|
};
|
|
6793
|
-
if (
|
|
6794
|
-
const
|
|
6795
|
-
let ee = null,
|
|
6793
|
+
if (F.onSpeechEnd && p.current) {
|
|
6794
|
+
const B = p.current;
|
|
6795
|
+
let ee = null, de = 0;
|
|
6796
6796
|
const Ae = 1200;
|
|
6797
6797
|
let ye = !1;
|
|
6798
6798
|
ee = setInterval(() => {
|
|
6799
|
-
if (
|
|
6799
|
+
if (de++, de > Ae) {
|
|
6800
6800
|
if (ee && (clearInterval(ee), ee = null), !ye) {
|
|
6801
6801
|
ye = !0;
|
|
6802
6802
|
try {
|
|
6803
|
-
|
|
6803
|
+
F.onSpeechEnd();
|
|
6804
6804
|
} catch (Se) {
|
|
6805
6805
|
console.error("Error in onSpeechEnd callback (timeout):", Se);
|
|
6806
6806
|
}
|
|
6807
6807
|
}
|
|
6808
6808
|
return;
|
|
6809
6809
|
}
|
|
6810
|
-
const Pe = !
|
|
6811
|
-
|
|
6812
|
-
if (
|
|
6810
|
+
const Pe = !B.speechQueue || B.speechQueue.length === 0, Be = !B.audioPlaylist || B.audioPlaylist.length === 0;
|
|
6811
|
+
B && B.isSpeaking === !1 && Pe && Be && B.isAudioPlaying === !1 && !ye && setTimeout(() => {
|
|
6812
|
+
if (B && B.isSpeaking === !1 && (!B.speechQueue || B.speechQueue.length === 0) && (!B.audioPlaylist || B.audioPlaylist.length === 0) && B.isAudioPlaying === !1 && !ye) {
|
|
6813
6813
|
ye = !0, ee && (clearInterval(ee), ee = null);
|
|
6814
6814
|
try {
|
|
6815
|
-
|
|
6815
|
+
F.onSpeechEnd();
|
|
6816
6816
|
} catch (De) {
|
|
6817
6817
|
console.error("Error in onSpeechEnd callback:", De);
|
|
6818
6818
|
}
|
|
@@ -6829,36 +6829,39 @@ const Ee = ve(({
|
|
|
6829
6829
|
}, [ne, re, ue.lipsyncLang]), b = T(() => {
|
|
6830
6830
|
p.current && (p.current.stopSpeaking(), p.current.setSlowdownRate && p.current.setSlowdownRate(1), z.current = null, G(!1));
|
|
6831
6831
|
}, []), R = T(() => {
|
|
6832
|
-
|
|
6832
|
+
if (p.current && p.current.pauseSpeaking) {
|
|
6833
|
+
const A = p.current, F = A.isSpeaking || A.audioPlaylist && A.audioPlaylist.length > 0 || A.speechQueue && A.speechQueue.length > 0;
|
|
6834
|
+
(F && z.current && z.current.text || F) && (p.current.pauseSpeaking(), G(!0));
|
|
6835
|
+
}
|
|
6833
6836
|
}, []), w = T(async () => {
|
|
6834
|
-
if (p.current &&
|
|
6835
|
-
G(!1)
|
|
6836
|
-
|
|
6837
|
-
|
|
6838
|
-
const
|
|
6837
|
+
if (p.current && W)
|
|
6838
|
+
if (G(!1), await re(), z.current && z.current.text) {
|
|
6839
|
+
const A = z.current;
|
|
6840
|
+
z.current = null;
|
|
6841
|
+
const F = {
|
|
6839
6842
|
...A.options,
|
|
6840
6843
|
lipsyncLang: A.options.lipsyncLang || ue.lipsyncLang || "en"
|
|
6841
6844
|
};
|
|
6842
|
-
p.current.lipsync && Object.keys(p.current.lipsync).length > 0 && (p.current.setSlowdownRate && p.current.setSlowdownRate(1.05), p.current.speakText(A.text,
|
|
6843
|
-
}
|
|
6844
|
-
|
|
6845
|
-
}, [re]), C = T((A) => {
|
|
6845
|
+
p.current.lipsync && Object.keys(p.current.lipsync).length > 0 && (p.current.setSlowdownRate && p.current.setSlowdownRate(1.05), p.current.speakText(A.text, F));
|
|
6846
|
+
} else
|
|
6847
|
+
z.current = null;
|
|
6848
|
+
}, [re, W]), C = T((A) => {
|
|
6846
6849
|
p.current && p.current.setMood(A);
|
|
6847
|
-
}, []),
|
|
6850
|
+
}, []), O = T((A) => {
|
|
6848
6851
|
p.current && p.current.setSlowdownRate && p.current.setSlowdownRate(A);
|
|
6849
|
-
}, []), te = T((A,
|
|
6852
|
+
}, []), te = T((A, F = !1) => {
|
|
6850
6853
|
if (p.current && p.current.playAnimation) {
|
|
6851
6854
|
if (x && x[A] && (A = x[A]), p.current.setShowFullAvatar)
|
|
6852
6855
|
try {
|
|
6853
6856
|
p.current.setShowFullAvatar(H.current);
|
|
6854
|
-
} catch (
|
|
6855
|
-
console.warn("Error setting full body mode:",
|
|
6857
|
+
} catch (B) {
|
|
6858
|
+
console.warn("Error setting full body mode:", B);
|
|
6856
6859
|
}
|
|
6857
6860
|
if (A.includes("."))
|
|
6858
6861
|
try {
|
|
6859
|
-
p.current.playAnimation(A, null, 10, 0, 0.01,
|
|
6860
|
-
} catch (
|
|
6861
|
-
console.warn(`Failed to play ${A}:`,
|
|
6862
|
+
p.current.playAnimation(A, null, 10, 0, 0.01, F);
|
|
6863
|
+
} catch (B) {
|
|
6864
|
+
console.warn(`Failed to play ${A}:`, B);
|
|
6862
6865
|
try {
|
|
6863
6866
|
p.current.setBodyMovement("idle");
|
|
6864
6867
|
} catch (ee) {
|
|
@@ -6866,11 +6869,11 @@ const Ee = ve(({
|
|
|
6866
6869
|
}
|
|
6867
6870
|
}
|
|
6868
6871
|
else {
|
|
6869
|
-
const
|
|
6872
|
+
const B = [".fbx", ".glb", ".gltf"];
|
|
6870
6873
|
let ee = !1;
|
|
6871
|
-
for (const
|
|
6874
|
+
for (const de of B)
|
|
6872
6875
|
try {
|
|
6873
|
-
p.current.playAnimation(A +
|
|
6876
|
+
p.current.playAnimation(A + de, null, 10, 0, 0.01, F), ee = !0;
|
|
6874
6877
|
break;
|
|
6875
6878
|
} catch {
|
|
6876
6879
|
}
|
|
@@ -6878,8 +6881,8 @@ const Ee = ve(({
|
|
|
6878
6881
|
console.warn("Animation not found:", A);
|
|
6879
6882
|
try {
|
|
6880
6883
|
p.current.setBodyMovement("idle");
|
|
6881
|
-
} catch (
|
|
6882
|
-
console.warn("Fallback animation also failed:",
|
|
6884
|
+
} catch (de) {
|
|
6885
|
+
console.warn("Fallback animation also failed:", de);
|
|
6883
6886
|
}
|
|
6884
6887
|
}
|
|
6885
6888
|
}
|
|
@@ -6894,18 +6897,18 @@ const Ee = ve(({
|
|
|
6894
6897
|
resumeSpeaking: w,
|
|
6895
6898
|
resumeAudioContext: re,
|
|
6896
6899
|
setMood: C,
|
|
6897
|
-
setTimingAdjustment:
|
|
6900
|
+
setTimingAdjustment: O,
|
|
6898
6901
|
playAnimation: te,
|
|
6899
6902
|
isReady: ne,
|
|
6900
|
-
isPaused:
|
|
6903
|
+
isPaused: W,
|
|
6901
6904
|
talkingHead: p.current,
|
|
6902
6905
|
handleResize: ie,
|
|
6903
6906
|
setBodyMovement: (A) => {
|
|
6904
6907
|
if (p.current && p.current.setShowFullAvatar && p.current.setBodyMovement)
|
|
6905
6908
|
try {
|
|
6906
6909
|
p.current.setShowFullAvatar(H.current), p.current.setBodyMovement(A);
|
|
6907
|
-
} catch (
|
|
6908
|
-
console.warn("Error setting body movement:",
|
|
6910
|
+
} catch (F) {
|
|
6911
|
+
console.warn("Error setting body movement:", F);
|
|
6909
6912
|
}
|
|
6910
6913
|
},
|
|
6911
6914
|
setMovementIntensity: (A) => p.current?.setMovementIntensity(A),
|
|
@@ -6921,8 +6924,8 @@ const Ee = ve(({
|
|
|
6921
6924
|
if (p.current && p.current.setShowFullAvatar && p.current.playReaction)
|
|
6922
6925
|
try {
|
|
6923
6926
|
p.current.setShowFullAvatar(H.current), p.current.playReaction(A);
|
|
6924
|
-
} catch (
|
|
6925
|
-
console.warn("Error playing reaction:",
|
|
6927
|
+
} catch (F) {
|
|
6928
|
+
console.warn("Error playing reaction:", F);
|
|
6926
6929
|
}
|
|
6927
6930
|
},
|
|
6928
6931
|
playCelebration: () => {
|
|
@@ -6937,8 +6940,8 @@ const Ee = ve(({
|
|
|
6937
6940
|
if (p.current && p.current.setShowFullAvatar)
|
|
6938
6941
|
try {
|
|
6939
6942
|
H.current = A, p.current.setShowFullAvatar(A);
|
|
6940
|
-
} catch (
|
|
6941
|
-
console.warn("Error setting showFullAvatar:",
|
|
6943
|
+
} catch (F) {
|
|
6944
|
+
console.warn("Error setting showFullAvatar:", F);
|
|
6942
6945
|
}
|
|
6943
6946
|
},
|
|
6944
6947
|
lockAvatarPosition: () => {
|
|
@@ -6971,7 +6974,7 @@ const Ee = ve(({
|
|
|
6971
6974
|
/* @__PURE__ */ he(
|
|
6972
6975
|
"div",
|
|
6973
6976
|
{
|
|
6974
|
-
ref:
|
|
6977
|
+
ref: P,
|
|
6975
6978
|
className: "talking-head-viewer",
|
|
6976
6979
|
style: {
|
|
6977
6980
|
width: "100%",
|
|
@@ -6989,7 +6992,7 @@ const Ee = ve(({
|
|
|
6989
6992
|
fontSize: "18px",
|
|
6990
6993
|
zIndex: 10
|
|
6991
6994
|
}, children: "Loading avatar..." }),
|
|
6992
|
-
|
|
6995
|
+
U && /* @__PURE__ */ he("div", { className: "error-overlay", style: {
|
|
6993
6996
|
position: "absolute",
|
|
6994
6997
|
top: "50%",
|
|
6995
6998
|
left: "50%",
|
|
@@ -7000,14 +7003,14 @@ const Ee = ve(({
|
|
|
7000
7003
|
zIndex: 10,
|
|
7001
7004
|
padding: "20px",
|
|
7002
7005
|
borderRadius: "8px"
|
|
7003
|
-
}, children:
|
|
7006
|
+
}, children: U })
|
|
7004
7007
|
]
|
|
7005
7008
|
}
|
|
7006
7009
|
);
|
|
7007
7010
|
});
|
|
7008
7011
|
Ee.displayName = "TalkingHeadAvatar";
|
|
7009
7012
|
const rt = ve(({
|
|
7010
|
-
text:
|
|
7013
|
+
text: N = "Hello! I'm a talking avatar. How are you today?",
|
|
7011
7014
|
onLoading: t = () => {
|
|
7012
7015
|
},
|
|
7013
7016
|
onError: e = () => {
|
|
@@ -7018,7 +7021,7 @@ const rt = ve(({
|
|
|
7018
7021
|
style: s = {},
|
|
7019
7022
|
avatarConfig: o = {}
|
|
7020
7023
|
}, l) => {
|
|
7021
|
-
const u = Z(null), a = Z(null), [h, r] =
|
|
7024
|
+
const u = Z(null), a = Z(null), [h, r] = ce(!0), [c, d] = ce(null), [g, y] = ce(!1), x = Le(), I = o.ttsService || x.service, P = I === "browser" ? {
|
|
7022
7025
|
endpoint: "",
|
|
7023
7026
|
apiKey: null,
|
|
7024
7027
|
defaultVoice: "Google US English"
|
|
@@ -7034,7 +7037,7 @@ const rt = ve(({
|
|
|
7034
7037
|
body: "F",
|
|
7035
7038
|
avatarMood: "neutral",
|
|
7036
7039
|
ttsLang: I === "browser" ? "en-US" : "en",
|
|
7037
|
-
ttsVoice: o.ttsVoice ||
|
|
7040
|
+
ttsVoice: o.ttsVoice || P.defaultVoice,
|
|
7038
7041
|
lipsyncLang: "en",
|
|
7039
7042
|
// English lip-sync
|
|
7040
7043
|
showFullAvatar: !0,
|
|
@@ -7043,15 +7046,15 @@ const rt = ve(({
|
|
|
7043
7046
|
movementIntensity: 0.5,
|
|
7044
7047
|
...o
|
|
7045
7048
|
}, H = {
|
|
7046
|
-
ttsEndpoint:
|
|
7047
|
-
ttsApikey:
|
|
7049
|
+
ttsEndpoint: P.endpoint,
|
|
7050
|
+
ttsApikey: P.apiKey,
|
|
7048
7051
|
ttsService: I,
|
|
7049
7052
|
lipsyncModules: ["en"],
|
|
7050
7053
|
cameraView: "upper"
|
|
7051
7054
|
}, z = T(async () => {
|
|
7052
7055
|
if (!(!u.current || a.current))
|
|
7053
7056
|
try {
|
|
7054
|
-
if (r(!0),
|
|
7057
|
+
if (r(!0), d(null), a.current = new Me(u.current, H), await a.current.showAvatar(p, (G) => {
|
|
7055
7058
|
if (G.lengthComputable) {
|
|
7056
7059
|
const E = Math.min(100, Math.round(G.loaded / G.total * 100));
|
|
7057
7060
|
t(E);
|
|
@@ -7074,14 +7077,14 @@ const rt = ve(({
|
|
|
7074
7077
|
console.warn("Error setting full body mode on initialization:", G);
|
|
7075
7078
|
}
|
|
7076
7079
|
r(!1), y(!0), i(a.current);
|
|
7077
|
-
const
|
|
7080
|
+
const W = () => {
|
|
7078
7081
|
document.visibilityState === "visible" ? a.current?.start() : a.current?.stop();
|
|
7079
7082
|
};
|
|
7080
|
-
return document.addEventListener("visibilitychange",
|
|
7081
|
-
document.removeEventListener("visibilitychange",
|
|
7083
|
+
return document.addEventListener("visibilitychange", W), () => {
|
|
7084
|
+
document.removeEventListener("visibilitychange", W);
|
|
7082
7085
|
};
|
|
7083
7086
|
} catch (S) {
|
|
7084
|
-
console.error("Error initializing TalkingHead:", S),
|
|
7087
|
+
console.error("Error initializing TalkingHead:", S), d(S.message || "Failed to initialize avatar"), r(!1), e(S);
|
|
7085
7088
|
}
|
|
7086
7089
|
}, []);
|
|
7087
7090
|
pe(() => (z(), () => {
|
|
@@ -7093,18 +7096,18 @@ const rt = ve(({
|
|
|
7093
7096
|
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(() => {
|
|
7094
7097
|
a.current && a.current.lipsync ? (console.log("Lip-sync now ready, speaking..."), a.current.setSlowdownRate && (a.current.setSlowdownRate(1.05), console.log("Applied timing adjustment for better lip-sync")), a.current.speakText(S)) : console.error("Lip-sync still not ready after waiting");
|
|
7095
7098
|
}, 500));
|
|
7096
|
-
} catch (
|
|
7097
|
-
console.error("Error speaking text:",
|
|
7099
|
+
} catch (W) {
|
|
7100
|
+
console.error("Error speaking text:", W), d(W.message || "Failed to speak text");
|
|
7098
7101
|
}
|
|
7099
7102
|
else
|
|
7100
7103
|
console.warn("Avatar not ready for speaking. isReady:", g, "talkingHeadRef:", !!a.current);
|
|
7101
|
-
}, [g, p]),
|
|
7104
|
+
}, [g, p]), D = T(() => {
|
|
7102
7105
|
a.current && (a.current.stopSpeaking(), a.current.setSlowdownRate && (a.current.setSlowdownRate(1), console.log("Reset timing to normal")));
|
|
7103
|
-
}, []),
|
|
7106
|
+
}, []), U = T((S) => {
|
|
7104
7107
|
a.current && a.current.setMood(S);
|
|
7105
7108
|
}, []), _ = T((S) => {
|
|
7106
7109
|
a.current && a.current.setSlowdownRate && (a.current.setSlowdownRate(S), console.log("Timing adjustment set to:", S));
|
|
7107
|
-
}, []), ne = T((S,
|
|
7110
|
+
}, []), ne = T((S, W = !1) => {
|
|
7108
7111
|
if (a.current && a.current.playAnimation) {
|
|
7109
7112
|
if (a.current.setShowFullAvatar)
|
|
7110
7113
|
try {
|
|
@@ -7114,7 +7117,7 @@ const rt = ve(({
|
|
|
7114
7117
|
}
|
|
7115
7118
|
if (S.includes("."))
|
|
7116
7119
|
try {
|
|
7117
|
-
a.current.playAnimation(S, null, 10, 0, 0.01,
|
|
7120
|
+
a.current.playAnimation(S, null, 10, 0, 0.01, W), console.log("Playing animation:", S);
|
|
7118
7121
|
} catch (E) {
|
|
7119
7122
|
console.log(`Failed to play ${S}:`, E);
|
|
7120
7123
|
try {
|
|
@@ -7128,7 +7131,7 @@ const rt = ve(({
|
|
|
7128
7131
|
let X = !1;
|
|
7129
7132
|
for (const Y of E)
|
|
7130
7133
|
try {
|
|
7131
|
-
a.current.playAnimation(S + Y, null, 10, 0, 0.01,
|
|
7134
|
+
a.current.playAnimation(S + Y, null, 10, 0, 0.01, W), console.log("Playing animation:", S + Y), X = !0;
|
|
7132
7135
|
break;
|
|
7133
7136
|
} catch {
|
|
7134
7137
|
console.log(`Failed to play ${S}${Y}, trying next format...`);
|
|
@@ -7147,8 +7150,8 @@ const rt = ve(({
|
|
|
7147
7150
|
}, []);
|
|
7148
7151
|
return Ie(l, () => ({
|
|
7149
7152
|
speakText: v,
|
|
7150
|
-
stopSpeaking:
|
|
7151
|
-
setMood:
|
|
7153
|
+
stopSpeaking: D,
|
|
7154
|
+
setMood: U,
|
|
7152
7155
|
setTimingAdjustment: _,
|
|
7153
7156
|
playAnimation: ne,
|
|
7154
7157
|
isReady: g,
|
|
@@ -7157,8 +7160,8 @@ const rt = ve(({
|
|
|
7157
7160
|
if (a.current && a.current.setShowFullAvatar && a.current.setBodyMovement)
|
|
7158
7161
|
try {
|
|
7159
7162
|
a.current.setShowFullAvatar(!0), a.current.setBodyMovement(S), console.log("Body movement set with full body mode:", S);
|
|
7160
|
-
} catch (
|
|
7161
|
-
console.warn("Error setting body movement:",
|
|
7163
|
+
} catch (W) {
|
|
7164
|
+
console.warn("Error setting body movement:", W);
|
|
7162
7165
|
}
|
|
7163
7166
|
},
|
|
7164
7167
|
setMovementIntensity: (S) => a.current?.setMovementIntensity(S),
|
|
@@ -7174,8 +7177,8 @@ const rt = ve(({
|
|
|
7174
7177
|
if (a.current && a.current.setShowFullAvatar && a.current.playReaction)
|
|
7175
7178
|
try {
|
|
7176
7179
|
a.current.setShowFullAvatar(!0), a.current.playReaction(S), console.log("Reaction played with full body mode:", S);
|
|
7177
|
-
} catch (
|
|
7178
|
-
console.warn("Error playing reaction:",
|
|
7180
|
+
} catch (W) {
|
|
7181
|
+
console.warn("Error playing reaction:", W);
|
|
7179
7182
|
}
|
|
7180
7183
|
},
|
|
7181
7184
|
playCelebration: () => {
|
|
@@ -7190,8 +7193,8 @@ const rt = ve(({
|
|
|
7190
7193
|
if (a.current && a.current.setShowFullAvatar)
|
|
7191
7194
|
try {
|
|
7192
7195
|
a.current.setShowFullAvatar(S), console.log("Show full avatar set to:", S);
|
|
7193
|
-
} catch (
|
|
7194
|
-
console.warn("Error setting showFullAvatar:",
|
|
7196
|
+
} catch (W) {
|
|
7197
|
+
console.warn("Error setting showFullAvatar:", W);
|
|
7195
7198
|
}
|
|
7196
7199
|
},
|
|
7197
7200
|
lockAvatarPosition: () => {
|
|
@@ -7232,7 +7235,7 @@ const rt = ve(({
|
|
|
7232
7235
|
fontSize: "18px",
|
|
7233
7236
|
zIndex: 10
|
|
7234
7237
|
}, children: "Loading avatar..." }),
|
|
7235
|
-
|
|
7238
|
+
c && /* @__PURE__ */ he("div", { className: "error-overlay", style: {
|
|
7236
7239
|
position: "absolute",
|
|
7237
7240
|
top: "50%",
|
|
7238
7241
|
left: "50%",
|
|
@@ -7243,12 +7246,12 @@ const rt = ve(({
|
|
|
7243
7246
|
zIndex: 10,
|
|
7244
7247
|
padding: "20px",
|
|
7245
7248
|
borderRadius: "8px"
|
|
7246
|
-
}, children:
|
|
7249
|
+
}, children: c })
|
|
7247
7250
|
] });
|
|
7248
7251
|
});
|
|
7249
7252
|
rt.displayName = "TalkingHeadComponent";
|
|
7250
7253
|
const lt = ve(({
|
|
7251
|
-
curriculumData:
|
|
7254
|
+
curriculumData: N = null,
|
|
7252
7255
|
avatarConfig: t = {},
|
|
7253
7256
|
animations: e = {},
|
|
7254
7257
|
onLessonStart: i = () => {
|
|
@@ -7273,13 +7276,13 @@ const lt = ve(({
|
|
|
7273
7276
|
curriculumCompleted: !1,
|
|
7274
7277
|
score: 0,
|
|
7275
7278
|
totalQuestions: 0
|
|
7276
|
-
}),
|
|
7279
|
+
}), c = Z({
|
|
7277
7280
|
onLessonStart: i,
|
|
7278
7281
|
onLessonComplete: n,
|
|
7279
7282
|
onQuestionAnswer: s,
|
|
7280
7283
|
onCurriculumComplete: o,
|
|
7281
7284
|
onCustomAction: l
|
|
7282
|
-
}),
|
|
7285
|
+
}), d = Z(null), g = Z(null), y = Z(null), x = Z(null), I = Z(null), P = Z(null), p = Z(null), H = Z(N?.curriculum || {
|
|
7283
7286
|
title: "Default Curriculum",
|
|
7284
7287
|
description: "No curriculum data provided",
|
|
7285
7288
|
language: "en",
|
|
@@ -7299,7 +7302,7 @@ const lt = ve(({
|
|
|
7299
7302
|
lipsyncLang: "en"
|
|
7300
7303
|
});
|
|
7301
7304
|
pe(() => {
|
|
7302
|
-
|
|
7305
|
+
c.current = {
|
|
7303
7306
|
onLessonStart: i,
|
|
7304
7307
|
onLessonComplete: n,
|
|
7305
7308
|
onQuestionAnswer: s,
|
|
@@ -7307,7 +7310,7 @@ const lt = ve(({
|
|
|
7307
7310
|
onCustomAction: l
|
|
7308
7311
|
};
|
|
7309
7312
|
}, [i, n, s, o, l]), pe(() => {
|
|
7310
|
-
H.current =
|
|
7313
|
+
H.current = N?.curriculum || {
|
|
7311
7314
|
title: "Default Curriculum",
|
|
7312
7315
|
description: "No curriculum data provided",
|
|
7313
7316
|
language: "en",
|
|
@@ -7326,18 +7329,23 @@ const lt = ve(({
|
|
|
7326
7329
|
animations: e,
|
|
7327
7330
|
lipsyncLang: "en"
|
|
7328
7331
|
};
|
|
7329
|
-
}, [
|
|
7330
|
-
const v = T(() => (H.current || { modules: [] }).modules[r.current.currentModuleIndex]?.lessons[r.current.currentLessonIndex], []),
|
|
7332
|
+
}, [N, t, e]);
|
|
7333
|
+
const v = T(() => (H.current || { modules: [] }).modules[r.current.currentModuleIndex]?.lessons[r.current.currentLessonIndex], []), D = T(() => v()?.questions[r.current.currentQuestionIndex], [v]), U = T((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, []), _ = T(() => {
|
|
7331
7334
|
r.current.lessonCompleted = !0, r.current.isQuestionMode = !1;
|
|
7332
7335
|
const b = r.current.totalQuestions > 0 ? Math.round(r.current.score / r.current.totalQuestions * 100) : 100;
|
|
7333
7336
|
let R = "Congratulations! You've completed this lesson";
|
|
7334
|
-
if (r.current.totalQuestions > 0
|
|
7337
|
+
if (r.current.totalQuestions > 0) {
|
|
7338
|
+
const w = r.current.score === 1 ? "one" : r.current.score, C = r.current.totalQuestions === 1 ? "one" : r.current.totalQuestions, O = b === 50 ? "fifty" : `${b}`;
|
|
7339
|
+
R += ` You got ${w} correct out of ${C} question${r.current.totalQuestions === 1 ? "" : "s"}, which is ${O} percent. `;
|
|
7340
|
+
} else
|
|
7341
|
+
R += "! ";
|
|
7342
|
+
if (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({
|
|
7335
7343
|
moduleIndex: r.current.currentModuleIndex,
|
|
7336
7344
|
lessonIndex: r.current.currentLessonIndex,
|
|
7337
7345
|
score: r.current.score,
|
|
7338
7346
|
totalQuestions: r.current.totalQuestions,
|
|
7339
7347
|
percentage: b
|
|
7340
|
-
}),
|
|
7348
|
+
}), c.current.onCustomAction({
|
|
7341
7349
|
type: "lessonComplete",
|
|
7342
7350
|
moduleIndex: r.current.currentModuleIndex,
|
|
7343
7351
|
lessonIndex: r.current.currentLessonIndex,
|
|
@@ -7351,11 +7359,11 @@ const lt = ve(({
|
|
|
7351
7359
|
} catch {
|
|
7352
7360
|
h.current.playCelebration();
|
|
7353
7361
|
}
|
|
7354
|
-
const w = H.current || { modules: [] }, C = w.modules[r.current.currentModuleIndex],
|
|
7362
|
+
const w = H.current || { modules: [] }, C = w.modules[r.current.currentModuleIndex], O = r.current.currentLessonIndex < (C?.lessons?.length || 0) - 1, te = r.current.currentModuleIndex < (w.modules?.length || 0) - 1, ie = O || te, A = z.current || { lipsyncLang: "en" };
|
|
7355
7363
|
h.current.speakText(R, {
|
|
7356
7364
|
lipsyncLang: A.lipsyncLang,
|
|
7357
7365
|
onSpeechEnd: () => {
|
|
7358
|
-
|
|
7366
|
+
c.current.onCustomAction({
|
|
7359
7367
|
type: "lessonCompleteFeedbackDone",
|
|
7360
7368
|
moduleIndex: r.current.currentModuleIndex,
|
|
7361
7369
|
lessonIndex: r.current.currentLessonIndex,
|
|
@@ -7370,7 +7378,7 @@ const lt = ve(({
|
|
|
7370
7378
|
}, [e.lessonComplete]), ne = T(() => {
|
|
7371
7379
|
r.current.curriculumCompleted = !0;
|
|
7372
7380
|
const b = H.current || { modules: [] };
|
|
7373
|
-
if (
|
|
7381
|
+
if (c.current.onCurriculumComplete({
|
|
7374
7382
|
modules: b.modules.length,
|
|
7375
7383
|
totalLessons: b.modules.reduce((R, w) => R + w.lessons.length, 0)
|
|
7376
7384
|
}), h.current) {
|
|
@@ -7386,8 +7394,8 @@ const lt = ve(({
|
|
|
7386
7394
|
}, [e.curriculumComplete]), S = T(() => {
|
|
7387
7395
|
const b = v();
|
|
7388
7396
|
r.current.isQuestionMode = !0, r.current.currentQuestionIndex = 0, r.current.totalQuestions = b?.questions?.length || 0, r.current.score = 0;
|
|
7389
|
-
const R =
|
|
7390
|
-
R &&
|
|
7397
|
+
const R = D();
|
|
7398
|
+
R && c.current.onCustomAction({
|
|
7391
7399
|
type: "questionStart",
|
|
7392
7400
|
moduleIndex: r.current.currentModuleIndex,
|
|
7393
7401
|
lessonIndex: r.current.currentLessonIndex,
|
|
@@ -7401,8 +7409,8 @@ const lt = ve(({
|
|
|
7401
7409
|
if (h.current.setMood("happy"), e.questionStart)
|
|
7402
7410
|
try {
|
|
7403
7411
|
h.current.playAnimation(e.questionStart, !0);
|
|
7404
|
-
} catch (
|
|
7405
|
-
console.warn("Failed to play questionStart animation:",
|
|
7412
|
+
} catch (O) {
|
|
7413
|
+
console.warn("Failed to play questionStart animation:", O);
|
|
7406
7414
|
}
|
|
7407
7415
|
const C = z.current || { lipsyncLang: "en" };
|
|
7408
7416
|
R.type === "code_test" ? h.current.speakText(`Let's test your coding skills! Here's your first challenge: ${R.question}`, { lipsyncLang: C.lipsyncLang }) : R.type === "multiple_choice" ? h.current.speakText(`Now let me ask you some questions. Here's the first one: ${R.question}`, { lipsyncLang: C.lipsyncLang }) : R.type === "true_false" ? h.current.speakText(`Let's start with some true or false questions. First question: ${R.question}`, { lipsyncLang: C.lipsyncLang }) : h.current.speakText(`Now let me ask you some questions. Here's the first one: ${R.question}`, { lipsyncLang: C.lipsyncLang });
|
|
@@ -7420,12 +7428,12 @@ const lt = ve(({
|
|
|
7420
7428
|
clearInterval(C);
|
|
7421
7429
|
}, 5e3);
|
|
7422
7430
|
}
|
|
7423
|
-
}, [e.questionStart, v,
|
|
7431
|
+
}, [e.questionStart, v, D]), W = T(() => {
|
|
7424
7432
|
const b = v();
|
|
7425
7433
|
if (r.current.currentQuestionIndex < (b?.questions?.length || 0) - 1) {
|
|
7426
7434
|
h.current && h.current.stopSpeaking && h.current.stopSpeaking(), r.current.currentQuestionIndex += 1;
|
|
7427
|
-
const R =
|
|
7428
|
-
R &&
|
|
7435
|
+
const R = D();
|
|
7436
|
+
R && c.current.onCustomAction({
|
|
7429
7437
|
type: "nextQuestion",
|
|
7430
7438
|
moduleIndex: r.current.currentModuleIndex,
|
|
7431
7439
|
lessonIndex: r.current.currentLessonIndex,
|
|
@@ -7439,8 +7447,8 @@ const lt = ve(({
|
|
|
7439
7447
|
if (h.current.setMood("happy"), h.current.setBodyMovement("idle"), e.nextQuestion)
|
|
7440
7448
|
try {
|
|
7441
7449
|
h.current.playAnimation(e.nextQuestion, !0);
|
|
7442
|
-
} catch (
|
|
7443
|
-
console.warn("Failed to play nextQuestion animation:",
|
|
7450
|
+
} catch (O) {
|
|
7451
|
+
console.warn("Failed to play nextQuestion animation:", O);
|
|
7444
7452
|
}
|
|
7445
7453
|
const C = z.current || { lipsyncLang: "en" };
|
|
7446
7454
|
R.type === "code_test" ? h.current.speakText(`Great! Now let's move on to your next coding challenge: ${R.question}`, {
|
|
@@ -7464,37 +7472,37 @@ const lt = ve(({
|
|
|
7464
7472
|
}, 5e3);
|
|
7465
7473
|
}
|
|
7466
7474
|
} else
|
|
7467
|
-
|
|
7475
|
+
c.current.onCustomAction({
|
|
7468
7476
|
type: "allQuestionsComplete",
|
|
7469
7477
|
moduleIndex: r.current.currentModuleIndex,
|
|
7470
7478
|
lessonIndex: r.current.currentLessonIndex,
|
|
7471
7479
|
totalQuestions: r.current.totalQuestions,
|
|
7472
7480
|
score: r.current.score
|
|
7473
7481
|
});
|
|
7474
|
-
}, [e.nextQuestion, v,
|
|
7482
|
+
}, [e.nextQuestion, v, D]), G = T(() => {
|
|
7475
7483
|
const b = H.current || { modules: [] }, R = b.modules[r.current.currentModuleIndex];
|
|
7476
7484
|
if (r.current.currentLessonIndex < (R?.lessons?.length || 0) - 1) {
|
|
7477
7485
|
r.current.currentLessonIndex += 1, r.current.currentQuestionIndex = 0, r.current.lessonCompleted = !1, r.current.isQuestionMode = !1, r.current.isTeaching = !1, r.current.score = 0, r.current.totalQuestions = 0;
|
|
7478
|
-
const C = b.modules[r.current.currentModuleIndex],
|
|
7479
|
-
|
|
7486
|
+
const C = b.modules[r.current.currentModuleIndex], O = r.current.currentLessonIndex < (C?.lessons?.length || 0) - 1, te = r.current.currentModuleIndex < (b.modules?.length || 0) - 1, ie = O || te;
|
|
7487
|
+
c.current.onCustomAction({
|
|
7480
7488
|
type: "lessonStart",
|
|
7481
7489
|
moduleIndex: r.current.currentModuleIndex,
|
|
7482
7490
|
lessonIndex: r.current.currentLessonIndex,
|
|
7483
7491
|
hasNextLesson: ie
|
|
7484
|
-
}),
|
|
7492
|
+
}), c.current.onLessonStart({
|
|
7485
7493
|
moduleIndex: r.current.currentModuleIndex,
|
|
7486
7494
|
lessonIndex: r.current.currentLessonIndex,
|
|
7487
7495
|
lesson: v()
|
|
7488
7496
|
}), h.current && (h.current.setMood("happy"), h.current.setBodyMovement("idle"));
|
|
7489
7497
|
} else if (r.current.currentModuleIndex < (b.modules?.length || 0) - 1) {
|
|
7490
7498
|
r.current.currentModuleIndex += 1, r.current.currentLessonIndex = 0, r.current.currentQuestionIndex = 0, r.current.lessonCompleted = !1, r.current.isQuestionMode = !1, r.current.isTeaching = !1, r.current.score = 0, r.current.totalQuestions = 0;
|
|
7491
|
-
const
|
|
7492
|
-
|
|
7499
|
+
const O = b.modules[r.current.currentModuleIndex], te = r.current.currentLessonIndex < (O?.lessons?.length || 0) - 1, ie = r.current.currentModuleIndex < (b.modules?.length || 0) - 1, A = te || ie;
|
|
7500
|
+
c.current.onCustomAction({
|
|
7493
7501
|
type: "lessonStart",
|
|
7494
7502
|
moduleIndex: r.current.currentModuleIndex,
|
|
7495
7503
|
lessonIndex: r.current.currentLessonIndex,
|
|
7496
7504
|
hasNextLesson: A
|
|
7497
|
-
}),
|
|
7505
|
+
}), c.current.onLessonStart({
|
|
7498
7506
|
moduleIndex: r.current.currentModuleIndex,
|
|
7499
7507
|
lessonIndex: r.current.currentLessonIndex,
|
|
7500
7508
|
lesson: v()
|
|
@@ -7505,8 +7513,8 @@ const lt = ve(({
|
|
|
7505
7513
|
const b = v();
|
|
7506
7514
|
let R = null;
|
|
7507
7515
|
if (b?.avatar_script && b?.body) {
|
|
7508
|
-
const w = b.avatar_script.trim(), C = b.body.trim(),
|
|
7509
|
-
R = `${w}${
|
|
7516
|
+
const w = b.avatar_script.trim(), C = b.body.trim(), O = w.match(/[.!?]$/) ? " " : ". ";
|
|
7517
|
+
R = `${w}${O}${C}`;
|
|
7510
7518
|
} else
|
|
7511
7519
|
R = b?.avatar_script || b?.body || null;
|
|
7512
7520
|
if (h.current && h.current.isReady && R) {
|
|
@@ -7515,16 +7523,16 @@ const lt = ve(({
|
|
|
7515
7523
|
if (e.teaching)
|
|
7516
7524
|
try {
|
|
7517
7525
|
h.current.playAnimation(e.teaching, !0), w = !0;
|
|
7518
|
-
} catch (
|
|
7519
|
-
console.warn("Failed to play teaching animation:",
|
|
7526
|
+
} catch (O) {
|
|
7527
|
+
console.warn("Failed to play teaching animation:", O);
|
|
7520
7528
|
}
|
|
7521
7529
|
w || h.current.setBodyMovement("gesturing");
|
|
7522
7530
|
const C = z.current || { lipsyncLang: "en" };
|
|
7523
|
-
|
|
7531
|
+
c.current.onLessonStart({
|
|
7524
7532
|
moduleIndex: r.current.currentModuleIndex,
|
|
7525
7533
|
lessonIndex: r.current.currentLessonIndex,
|
|
7526
7534
|
lesson: b
|
|
7527
|
-
}),
|
|
7535
|
+
}), c.current.onCustomAction({
|
|
7528
7536
|
type: "teachingStart",
|
|
7529
7537
|
moduleIndex: r.current.currentModuleIndex,
|
|
7530
7538
|
lessonIndex: r.current.currentLessonIndex,
|
|
@@ -7532,7 +7540,7 @@ const lt = ve(({
|
|
|
7532
7540
|
}), h.current.speakText(R, {
|
|
7533
7541
|
lipsyncLang: C.lipsyncLang,
|
|
7534
7542
|
onSpeechEnd: () => {
|
|
7535
|
-
r.current.isTeaching = !1,
|
|
7543
|
+
r.current.isTeaching = !1, c.current.onCustomAction({
|
|
7536
7544
|
type: "teachingComplete",
|
|
7537
7545
|
moduleIndex: r.current.currentModuleIndex,
|
|
7538
7546
|
lessonIndex: r.current.currentLessonIndex,
|
|
@@ -7543,8 +7551,8 @@ const lt = ve(({
|
|
|
7543
7551
|
});
|
|
7544
7552
|
}
|
|
7545
7553
|
}, [e.teaching, v]), X = T((b) => {
|
|
7546
|
-
const R =
|
|
7547
|
-
if (w && (r.current.score += 1),
|
|
7554
|
+
const R = D(), w = U(b, R);
|
|
7555
|
+
if (w && (r.current.score += 1), c.current.onQuestionAnswer({
|
|
7548
7556
|
moduleIndex: r.current.currentModuleIndex,
|
|
7549
7557
|
lessonIndex: r.current.currentLessonIndex,
|
|
7550
7558
|
questionIndex: r.current.currentQuestionIndex,
|
|
@@ -7560,12 +7568,12 @@ const lt = ve(({
|
|
|
7560
7568
|
h.current.setBodyMovement("happy");
|
|
7561
7569
|
}
|
|
7562
7570
|
h.current.setBodyMovement("gesturing");
|
|
7563
|
-
const C = R.type === "code_test" ? `Great job! Your code passed all the tests! ${R.explanation || ""}` : `Excellent! That's correct! ${R.explanation || ""}`,
|
|
7571
|
+
const C = R.type === "code_test" ? `Great job! Your code passed all the tests! ${R.explanation || ""}` : `Excellent! That's correct! ${R.explanation || ""}`, O = z.current || { lipsyncLang: "en" };
|
|
7564
7572
|
h.current.speakText(C, {
|
|
7565
|
-
lipsyncLang:
|
|
7573
|
+
lipsyncLang: O.lipsyncLang,
|
|
7566
7574
|
onSpeechEnd: () => {
|
|
7567
7575
|
const ie = v()?.questions?.length || 0;
|
|
7568
|
-
|
|
7576
|
+
c.current.onCustomAction({
|
|
7569
7577
|
type: "answerFeedbackComplete",
|
|
7570
7578
|
moduleIndex: r.current.currentModuleIndex,
|
|
7571
7579
|
lessonIndex: r.current.currentLessonIndex,
|
|
@@ -7585,12 +7593,12 @@ const lt = ve(({
|
|
|
7585
7593
|
h.current.setBodyMovement("idle");
|
|
7586
7594
|
}
|
|
7587
7595
|
h.current.setBodyMovement("gesturing");
|
|
7588
|
-
const C = 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.`,
|
|
7596
|
+
const C = 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.`, O = z.current || { lipsyncLang: "en" };
|
|
7589
7597
|
h.current.speakText(C, {
|
|
7590
|
-
lipsyncLang:
|
|
7598
|
+
lipsyncLang: O.lipsyncLang,
|
|
7591
7599
|
onSpeechEnd: () => {
|
|
7592
7600
|
const ie = v()?.questions?.length || 0;
|
|
7593
|
-
|
|
7601
|
+
c.current.onCustomAction({
|
|
7594
7602
|
type: "answerFeedbackComplete",
|
|
7595
7603
|
moduleIndex: r.current.currentModuleIndex,
|
|
7596
7604
|
lessonIndex: r.current.currentLessonIndex,
|
|
@@ -7604,21 +7612,21 @@ const lt = ve(({
|
|
|
7604
7612
|
});
|
|
7605
7613
|
}
|
|
7606
7614
|
else {
|
|
7607
|
-
const
|
|
7608
|
-
|
|
7615
|
+
const O = v()?.questions?.length || 0;
|
|
7616
|
+
c.current.onCustomAction({
|
|
7609
7617
|
type: "answerFeedbackComplete",
|
|
7610
7618
|
moduleIndex: r.current.currentModuleIndex,
|
|
7611
7619
|
lessonIndex: r.current.currentLessonIndex,
|
|
7612
7620
|
questionIndex: r.current.currentQuestionIndex,
|
|
7613
7621
|
isCorrect: w,
|
|
7614
|
-
hasNextQuestion: r.current.currentQuestionIndex <
|
|
7622
|
+
hasNextQuestion: r.current.currentQuestionIndex < O - 1,
|
|
7615
7623
|
score: r.current.score,
|
|
7616
7624
|
totalQuestions: r.current.totalQuestions,
|
|
7617
7625
|
avatarNotReady: !0
|
|
7618
7626
|
});
|
|
7619
7627
|
}
|
|
7620
|
-
}, [e.correct, e.incorrect,
|
|
7621
|
-
const R =
|
|
7628
|
+
}, [e.correct, e.incorrect, D, v, U]), Y = T((b) => {
|
|
7629
|
+
const R = D();
|
|
7622
7630
|
if (!b || typeof b != "object") {
|
|
7623
7631
|
console.error("Invalid code test result format. Expected object with {passed: boolean, ...}");
|
|
7624
7632
|
return;
|
|
@@ -7637,7 +7645,7 @@ const lt = ve(({
|
|
|
7637
7645
|
passedCount: b.passedCount || 0,
|
|
7638
7646
|
failedCount: b.failedCount || 0
|
|
7639
7647
|
};
|
|
7640
|
-
|
|
7648
|
+
c.current.onCustomAction({
|
|
7641
7649
|
type: "codeTestSubmitted",
|
|
7642
7650
|
moduleIndex: r.current.currentModuleIndex,
|
|
7643
7651
|
lessonIndex: r.current.currentLessonIndex,
|
|
@@ -7645,11 +7653,11 @@ const lt = ve(({
|
|
|
7645
7653
|
testResult: w,
|
|
7646
7654
|
question: R
|
|
7647
7655
|
}), p.current && p.current(w);
|
|
7648
|
-
}, [
|
|
7656
|
+
}, [D, U]), ue = T(() => {
|
|
7649
7657
|
if (r.current.currentQuestionIndex > 0) {
|
|
7650
7658
|
r.current.currentQuestionIndex -= 1;
|
|
7651
|
-
const b =
|
|
7652
|
-
b &&
|
|
7659
|
+
const b = D();
|
|
7660
|
+
b && c.current.onCustomAction({
|
|
7653
7661
|
type: "questionStart",
|
|
7654
7662
|
moduleIndex: r.current.currentModuleIndex,
|
|
7655
7663
|
lessonIndex: r.current.currentLessonIndex,
|
|
@@ -7679,25 +7687,25 @@ const lt = ve(({
|
|
|
7679
7687
|
}, 5e3);
|
|
7680
7688
|
}
|
|
7681
7689
|
}
|
|
7682
|
-
}, [
|
|
7690
|
+
}, [D]), Re = T(() => {
|
|
7683
7691
|
const b = H.current || { modules: [] };
|
|
7684
7692
|
if (b.modules[r.current.currentModuleIndex], r.current.currentLessonIndex > 0)
|
|
7685
|
-
r.current.currentLessonIndex -= 1, r.current.currentQuestionIndex = 0, r.current.lessonCompleted = !1, r.current.isQuestionMode = !1, r.current.isTeaching = !1, r.current.score = 0, r.current.totalQuestions = 0,
|
|
7693
|
+
r.current.currentLessonIndex -= 1, r.current.currentQuestionIndex = 0, r.current.lessonCompleted = !1, r.current.isQuestionMode = !1, r.current.isTeaching = !1, r.current.score = 0, r.current.totalQuestions = 0, c.current.onCustomAction({
|
|
7686
7694
|
type: "lessonStart",
|
|
7687
7695
|
moduleIndex: r.current.currentModuleIndex,
|
|
7688
7696
|
lessonIndex: r.current.currentLessonIndex
|
|
7689
|
-
}),
|
|
7697
|
+
}), c.current.onLessonStart({
|
|
7690
7698
|
moduleIndex: r.current.currentModuleIndex,
|
|
7691
7699
|
lessonIndex: r.current.currentLessonIndex,
|
|
7692
7700
|
lesson: v()
|
|
7693
7701
|
}), h.current && (h.current.setMood("happy"), h.current.setBodyMovement("idle"));
|
|
7694
7702
|
else if (r.current.currentModuleIndex > 0) {
|
|
7695
7703
|
const C = b.modules[r.current.currentModuleIndex - 1];
|
|
7696
|
-
r.current.currentModuleIndex -= 1, r.current.currentLessonIndex = (C?.lessons?.length || 1) - 1, r.current.currentQuestionIndex = 0, r.current.lessonCompleted = !1, r.current.isQuestionMode = !1, r.current.isTeaching = !1, r.current.score = 0, r.current.totalQuestions = 0,
|
|
7704
|
+
r.current.currentModuleIndex -= 1, r.current.currentLessonIndex = (C?.lessons?.length || 1) - 1, r.current.currentQuestionIndex = 0, r.current.lessonCompleted = !1, r.current.isQuestionMode = !1, r.current.isTeaching = !1, r.current.score = 0, r.current.totalQuestions = 0, c.current.onCustomAction({
|
|
7697
7705
|
type: "lessonStart",
|
|
7698
7706
|
moduleIndex: r.current.currentModuleIndex,
|
|
7699
7707
|
lessonIndex: r.current.currentLessonIndex
|
|
7700
|
-
}),
|
|
7708
|
+
}), c.current.onLessonStart({
|
|
7701
7709
|
moduleIndex: r.current.currentModuleIndex,
|
|
7702
7710
|
lessonIndex: r.current.currentLessonIndex,
|
|
7703
7711
|
lesson: v()
|
|
@@ -7709,18 +7717,18 @@ const lt = ve(({
|
|
|
7709
7717
|
console.log("Avatar is ready!", b);
|
|
7710
7718
|
const R = v(), w = R?.avatar_script || R?.body;
|
|
7711
7719
|
u && w && setTimeout(() => {
|
|
7712
|
-
|
|
7720
|
+
d.current && d.current();
|
|
7713
7721
|
}, 10);
|
|
7714
7722
|
}, [u, v]);
|
|
7715
7723
|
Oe(() => {
|
|
7716
|
-
|
|
7724
|
+
d.current = E, g.current = G, y.current = _, x.current = W, I.current = ne, P.current = S, p.current = X;
|
|
7717
7725
|
}), Ie(a, () => ({
|
|
7718
7726
|
// Curriculum control methods
|
|
7719
7727
|
startTeaching: E,
|
|
7720
7728
|
startQuestions: S,
|
|
7721
7729
|
handleAnswerSelect: X,
|
|
7722
7730
|
handleCodeTestResult: Y,
|
|
7723
|
-
nextQuestion:
|
|
7731
|
+
nextQuestion: W,
|
|
7724
7732
|
previousQuestion: ue,
|
|
7725
7733
|
nextLesson: G,
|
|
7726
7734
|
previousLesson: Re,
|
|
@@ -7728,7 +7736,7 @@ const lt = ve(({
|
|
|
7728
7736
|
completeCurriculum: ne,
|
|
7729
7737
|
resetCurriculum: ge,
|
|
7730
7738
|
getState: () => ({ ...r.current }),
|
|
7731
|
-
getCurrentQuestion: () =>
|
|
7739
|
+
getCurrentQuestion: () => D(),
|
|
7732
7740
|
getCurrentLesson: () => v(),
|
|
7733
7741
|
// Direct access to avatar ref (always returns current value)
|
|
7734
7742
|
getAvatarRef: () => h.current,
|
|
@@ -7756,7 +7764,7 @@ const lt = ve(({
|
|
|
7756
7764
|
stopSpeaking: () => h.current?.stopSpeaking(),
|
|
7757
7765
|
pauseSpeaking: () => h.current?.pauseSpeaking(),
|
|
7758
7766
|
resumeSpeaking: async () => await h.current?.resumeSpeaking(),
|
|
7759
|
-
isPaused: () => h.current
|
|
7767
|
+
isPaused: () => h.current && typeof h.current.isPaused < "u" ? h.current.isPaused : !1,
|
|
7760
7768
|
setMood: (b) => h.current?.setMood(b),
|
|
7761
7769
|
playAnimation: (b, R) => h.current?.playAnimation(b, R),
|
|
7762
7770
|
setBodyMovement: (b) => h.current?.setBodyMovement(b),
|
|
@@ -7770,7 +7778,7 @@ const lt = ve(({
|
|
|
7770
7778
|
unlockAvatarPosition: () => h.current?.unlockAvatarPosition(),
|
|
7771
7779
|
// Custom action trigger
|
|
7772
7780
|
triggerCustomAction: (b, R) => {
|
|
7773
|
-
|
|
7781
|
+
c.current.onCustomAction({
|
|
7774
7782
|
type: b,
|
|
7775
7783
|
...R,
|
|
7776
7784
|
state: { ...r.current }
|
|
@@ -7780,7 +7788,7 @@ const lt = ve(({
|
|
|
7780
7788
|
handleResize: () => h.current?.handleResize(),
|
|
7781
7789
|
// Avatar readiness check (always returns current value)
|
|
7782
7790
|
isAvatarReady: () => h.current?.isReady || !1
|
|
7783
|
-
}), [E, S, X, Y,
|
|
7791
|
+
}), [E, S, X, Y, W, G, _, ne, ge, D, v]);
|
|
7784
7792
|
const J = z.current || {
|
|
7785
7793
|
avatarUrl: "/avatars/brunette.glb",
|
|
7786
7794
|
avatarBody: "F",
|
|
@@ -7923,7 +7931,7 @@ const Fe = {
|
|
|
7923
7931
|
duration: 5e3,
|
|
7924
7932
|
description: "Excited, energetic movement"
|
|
7925
7933
|
}
|
|
7926
|
-
}, bt = (
|
|
7934
|
+
}, bt = (N) => Fe[N] || null, Rt = (N) => Fe.hasOwnProperty(N);
|
|
7927
7935
|
export {
|
|
7928
7936
|
lt as CurriculumLearning,
|
|
7929
7937
|
Ee as TalkingHeadAvatar,
|