@sage-rsc/talking-head-react 1.0.67 → 1.0.68
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 +517 -511
- package/package.json +1 -1
- package/src/components/CurriculumLearning.jsx +18 -0
package/dist/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { jsxs as De, jsx as ge } from "react/jsx-runtime";
|
|
2
|
-
import { forwardRef as ze, useRef as N, useState as be, useEffect as
|
|
2
|
+
import { forwardRef as ze, useRef as N, useState as be, useEffect as Re, useCallback as M, useImperativeHandle as Ce, useLayoutEffect as Xe } from "react";
|
|
3
3
|
import * as f from "three";
|
|
4
4
|
import { OrbitControls as Ye } from "three/addons/controls/OrbitControls.js";
|
|
5
5
|
import { GLTFLoader as je } from "three/addons/loaders/GLTFLoader.js";
|
|
@@ -202,7 +202,7 @@ class et {
|
|
|
202
202
|
deltaLocal: null
|
|
203
203
|
};
|
|
204
204
|
if (s.deltaLocal) {
|
|
205
|
-
if (!Array.isArray(s.deltaLocal) || s.deltaLocal.length !== 3 || s.deltaLocal.some((
|
|
205
|
+
if (!Array.isArray(s.deltaLocal) || s.deltaLocal.length !== 3 || s.deltaLocal.some((r) => Number.isNaN(r))) throw new Error("deltaLocal must be an array of three numbers in #" + o + " exclude.");
|
|
206
206
|
u.deltaLocal = [...s.deltaLocal];
|
|
207
207
|
}
|
|
208
208
|
i.excludes.push(u);
|
|
@@ -310,22 +310,22 @@ class et {
|
|
|
310
310
|
i(s.bone, l + "Bone not specified.");
|
|
311
311
|
const u = s.bone;
|
|
312
312
|
i(typeof u == "string" && u.length > 0, l + "Bone name must be a non-empty string.");
|
|
313
|
-
const
|
|
314
|
-
i(
|
|
313
|
+
const r = this.armature.getObjectByName(u);
|
|
314
|
+
i(r, l + "Bone '" + u + "' not found."), i(r.parent?.isBone, l + "Bone must have a parent bone."), i(this.data.every((a) => a.bone !== r), l + "Bone '" + u + "' already exists."), r.updateMatrixWorld(!0);
|
|
315
315
|
const h = {
|
|
316
316
|
name: u,
|
|
317
317
|
// Bone name
|
|
318
|
-
bone:
|
|
318
|
+
bone: r,
|
|
319
319
|
// Bone object
|
|
320
|
-
boneParent:
|
|
320
|
+
boneParent: r.parent,
|
|
321
321
|
/// Bone's parent object
|
|
322
|
-
vBasis:
|
|
322
|
+
vBasis: r.position.clone(),
|
|
323
323
|
// Original local position
|
|
324
|
-
vWorld:
|
|
324
|
+
vWorld: r.parent.getWorldPosition(k).clone(),
|
|
325
325
|
// World position, parent
|
|
326
|
-
qBasis:
|
|
326
|
+
qBasis: r.parent.quaternion.clone(),
|
|
327
327
|
// Original quaternion, parent
|
|
328
|
-
l:
|
|
328
|
+
l: r.position.length(),
|
|
329
329
|
// Bone length
|
|
330
330
|
p: [0, 0, 0, 0],
|
|
331
331
|
// Relative position [m]
|
|
@@ -341,8 +341,8 @@ class et {
|
|
|
341
341
|
h.boneParent.matrixWorld.decompose(k, K, _), k.copy(ke).applyQuaternion(K).setY(0).normalize(), K.premultiply(Ee.setFromUnitVectors(ke, k).invert()).normalize(), h.qWorldInverseYaw = K.clone().normalize(), this.data.push(h), this.dict[u] = h;
|
|
342
342
|
try {
|
|
343
343
|
this.setValue(u, "type", s.type), this.setValue(u, "stiffness", s.stiffness), this.setValue(u, "damping", s.damping), this.setValue(u, "external", s.external), this.setValue(u, "limits", s.limits), this.setValue(u, "excludes", s.excludes), this.setValue(u, "deltaLocal", s.deltaLocal), this.setValue(u, "deltaWorld", s.deltaWorld), this.setValue(u, "pivot", s.pivot), this.setValue(u, "helper", s.helper);
|
|
344
|
-
} catch (
|
|
345
|
-
i(!1, l +
|
|
344
|
+
} catch (a) {
|
|
345
|
+
i(!1, l + a);
|
|
346
346
|
}
|
|
347
347
|
}), this.sortBones(), this.start();
|
|
348
348
|
}
|
|
@@ -519,8 +519,8 @@ class tt {
|
|
|
519
519
|
phonemeBoundaries: []
|
|
520
520
|
}, i = 1024, s = 512, o = Math.floor((t.length - i) / s) + 1;
|
|
521
521
|
for (let l = 0; l < o; l++) {
|
|
522
|
-
const u = l * s,
|
|
523
|
-
n.energy.push(
|
|
522
|
+
const u = l * s, r = Math.min(u + i, t.length), h = t.slice(u, r), a = this.calculateEnergy(h);
|
|
523
|
+
n.energy.push(a);
|
|
524
524
|
const c = this.calculateSpectralCentroid(h);
|
|
525
525
|
n.spectralCentroid.push(c);
|
|
526
526
|
const d = this.calculateZeroCrossingRate(h);
|
|
@@ -604,12 +604,12 @@ class tt {
|
|
|
604
604
|
for (let i = 2; i <= e; i <<= 1) {
|
|
605
605
|
const s = -2 * Math.PI / i, o = Math.cos(s), l = Math.sin(s);
|
|
606
606
|
for (let u = 0; u < e; u += i) {
|
|
607
|
-
let
|
|
608
|
-
for (let
|
|
609
|
-
const c = n[(u +
|
|
610
|
-
n[(u +
|
|
611
|
-
const x =
|
|
612
|
-
|
|
607
|
+
let r = 1, h = 0;
|
|
608
|
+
for (let a = 0; a < i / 2; a++) {
|
|
609
|
+
const c = n[(u + a) * 2], d = n[(u + a) * 2 + 1], g = n[(u + a + i / 2) * 2] * r - n[(u + a + i / 2) * 2 + 1] * h, y = n[(u + a + i / 2) * 2] * h + n[(u + a + i / 2) * 2 + 1] * r;
|
|
610
|
+
n[(u + a) * 2] = c + g, n[(u + a) * 2 + 1] = d + y, n[(u + a + i / 2) * 2] = c - g, n[(u + a + i / 2) * 2 + 1] = d - y;
|
|
611
|
+
const x = r * o - h * l, I = r * l + h * o;
|
|
612
|
+
r = x, h = I;
|
|
613
613
|
}
|
|
614
614
|
}
|
|
615
615
|
}
|
|
@@ -637,8 +637,8 @@ class tt {
|
|
|
637
637
|
detectPhonemeBoundaries(t) {
|
|
638
638
|
const e = [], { energy: n, spectralCentroid: i, zeroCrossingRate: s } = t;
|
|
639
639
|
for (let o = 1; o < n.length; o++) {
|
|
640
|
-
const l = o * 0.023, u = Math.abs(n[o] - n[o - 1]),
|
|
641
|
-
u +
|
|
640
|
+
const l = o * 0.023, u = Math.abs(n[o] - n[o - 1]), r = Math.abs(i[o] - i[o - 1]), h = Math.abs(s[o] - s[o - 1]);
|
|
641
|
+
u + r * 0.1 + h * 0.5 > 0.2 && e.push(l);
|
|
642
642
|
}
|
|
643
643
|
return e;
|
|
644
644
|
}
|
|
@@ -655,9 +655,9 @@ class tt {
|
|
|
655
655
|
const s = [];
|
|
656
656
|
let o = 0;
|
|
657
657
|
for (let u = 0; u < i.length; u++) {
|
|
658
|
-
const
|
|
658
|
+
const r = i[u], h = this.estimateWordDuration(r, n / i.length);
|
|
659
659
|
s.push({
|
|
660
|
-
word:
|
|
660
|
+
word: r,
|
|
661
661
|
startTime: o,
|
|
662
662
|
endTime: o + h,
|
|
663
663
|
duration: h
|
|
@@ -702,10 +702,10 @@ class tt {
|
|
|
702
702
|
t.onsets;
|
|
703
703
|
const o = this.textToVisemes(e);
|
|
704
704
|
let l = 0, u = 0;
|
|
705
|
-
for (let
|
|
706
|
-
const h = s[
|
|
705
|
+
for (let r = 0; r < s.length && l < o.length; r++) {
|
|
706
|
+
const h = s[r], a = o[l], c = t.energy[Math.floor(h / 0.023)] || 0, d = this.calculateVisemeDuration(a, c);
|
|
707
707
|
i.push({
|
|
708
|
-
viseme:
|
|
708
|
+
viseme: a,
|
|
709
709
|
startTime: u,
|
|
710
710
|
endTime: u + d,
|
|
711
711
|
duration: d,
|
|
@@ -714,9 +714,9 @@ class tt {
|
|
|
714
714
|
}), u += d, l++;
|
|
715
715
|
}
|
|
716
716
|
for (; l < o.length; ) {
|
|
717
|
-
const
|
|
717
|
+
const r = o[l], h = this.calculateVisemeDuration(r, 0.5);
|
|
718
718
|
i.push({
|
|
719
|
-
viseme:
|
|
719
|
+
viseme: r,
|
|
720
720
|
startTime: u,
|
|
721
721
|
endTime: u + h,
|
|
722
722
|
duration: h,
|
|
@@ -776,9 +776,9 @@ class tt {
|
|
|
776
776
|
for (; o < s.length; ) {
|
|
777
777
|
let l = !1;
|
|
778
778
|
for (let u = 3; u >= 2; u--) {
|
|
779
|
-
const
|
|
780
|
-
if (e[
|
|
781
|
-
n.push(e[
|
|
779
|
+
const r = s.substr(o, u);
|
|
780
|
+
if (e[r]) {
|
|
781
|
+
n.push(e[r]), o += u, l = !0;
|
|
782
782
|
break;
|
|
783
783
|
}
|
|
784
784
|
}
|
|
@@ -1206,13 +1206,13 @@ class nt {
|
|
|
1206
1206
|
};
|
|
1207
1207
|
Object.keys(this.rules).forEach((e) => {
|
|
1208
1208
|
this.rules[e] = this.rules[e].map((n) => {
|
|
1209
|
-
const i = n.indexOf("["), s = n.indexOf("]"), o = n.indexOf("="), l = n.substring(0, i), u = n.substring(i + 1, s),
|
|
1209
|
+
const i = n.indexOf("["), s = n.indexOf("]"), o = n.indexOf("="), l = n.substring(0, i), u = n.substring(i + 1, s), r = n.substring(s + 1, o), h = n.substring(o + 1), a = { regex: "", move: 0, visemes: [] };
|
|
1210
1210
|
let c = "";
|
|
1211
1211
|
c += [...l].map((g) => t[g] || g).join("");
|
|
1212
1212
|
const d = [...u];
|
|
1213
|
-
return d[0] = d[0].toLowerCase(), c += d.join(""),
|
|
1214
|
-
|
|
1215
|
-
}),
|
|
1213
|
+
return d[0] = d[0].toLowerCase(), c += d.join(""), a.move = d.length, c += [...r].map((g) => t[g] || g).join(""), a.regex = new RegExp(c), h.length && h.split(" ").forEach((g) => {
|
|
1214
|
+
a.visemes.push(g);
|
|
1215
|
+
}), a;
|
|
1216
1216
|
});
|
|
1217
1217
|
}), this.visemeDurations = {
|
|
1218
1218
|
aa: 0.95,
|
|
@@ -1378,13 +1378,13 @@ class nt {
|
|
|
1378
1378
|
for (let l = 0; l < o.length; l++) {
|
|
1379
1379
|
const u = o[l];
|
|
1380
1380
|
if ((e.words.substring(0, e.i) + s.toLowerCase() + e.words.substring(e.i + 1)).match(u.regex)) {
|
|
1381
|
-
u.visemes.forEach((
|
|
1382
|
-
if (e.visemes.length && e.visemes[e.visemes.length - 1] ===
|
|
1383
|
-
const c = 0.7 * (this.visemeDurations[
|
|
1381
|
+
u.visemes.forEach((a) => {
|
|
1382
|
+
if (e.visemes.length && e.visemes[e.visemes.length - 1] === a) {
|
|
1383
|
+
const c = 0.7 * (this.visemeDurations[a] || 1);
|
|
1384
1384
|
e.durations[e.durations.length - 1] += c, n += c;
|
|
1385
1385
|
} else {
|
|
1386
|
-
const c = this.visemeDurations[
|
|
1387
|
-
e.visemes.push(
|
|
1386
|
+
const c = this.visemeDurations[a] || 1;
|
|
1387
|
+
e.visemes.push(a), e.times.push(n), e.durations.push(c), n += c;
|
|
1388
1388
|
}
|
|
1389
1389
|
}), e.i += u.move;
|
|
1390
1390
|
break;
|
|
@@ -1616,13 +1616,13 @@ class ot {
|
|
|
1616
1616
|
};
|
|
1617
1617
|
Object.keys(this.rules).forEach((e) => {
|
|
1618
1618
|
this.rules[e] = this.rules[e].map((n) => {
|
|
1619
|
-
const i = n.indexOf("["), s = n.indexOf("]"), o = n.indexOf("="), l = n.substring(0, i), u = n.substring(i + 1, s),
|
|
1619
|
+
const i = n.indexOf("["), s = n.indexOf("]"), o = n.indexOf("="), l = n.substring(0, i), u = n.substring(i + 1, s), r = n.substring(s + 1, o), h = n.substring(o + 1), a = { regex: "", move: 0, visemes: [] };
|
|
1620
1620
|
let c = "";
|
|
1621
1621
|
c += [...l].map((g) => t[g] || g).join("");
|
|
1622
1622
|
const d = [...u];
|
|
1623
|
-
return d[0] = d[0].toLowerCase(), c += d.join(""),
|
|
1624
|
-
|
|
1625
|
-
}),
|
|
1623
|
+
return d[0] = d[0].toLowerCase(), c += d.join(""), a.move = d.length, c += [...r].map((g) => t[g] || g).join(""), a.regex = new RegExp(c), h.length && h.split(" ").forEach((g) => {
|
|
1624
|
+
a.visemes.push(g);
|
|
1625
|
+
}), a;
|
|
1626
1626
|
});
|
|
1627
1627
|
}), this.visemeDurations = {
|
|
1628
1628
|
aa: 1,
|
|
@@ -1733,9 +1733,9 @@ class ot {
|
|
|
1733
1733
|
if (o) {
|
|
1734
1734
|
let l = !1;
|
|
1735
1735
|
for (let u = 0; u < o.length; u++) {
|
|
1736
|
-
const
|
|
1737
|
-
if ((e.words.substring(0, e.i) + s.toLowerCase() + e.words.substring(e.i + 1)).match(
|
|
1738
|
-
|
|
1736
|
+
const r = o[u];
|
|
1737
|
+
if ((e.words.substring(0, e.i) + s.toLowerCase() + e.words.substring(e.i + 1)).match(r.regex)) {
|
|
1738
|
+
r.visemes.forEach((c) => {
|
|
1739
1739
|
if (e.visemes.length && e.visemes[e.visemes.length - 1] === c) {
|
|
1740
1740
|
const d = 0.7 * (this.visemeDurations[c] || 1);
|
|
1741
1741
|
e.durations[e.durations.length - 1] += d, n += d;
|
|
@@ -1743,7 +1743,7 @@ class ot {
|
|
|
1743
1743
|
const d = this.visemeDurations[c] || 1;
|
|
1744
1744
|
e.visemes.push(c), e.times.push(n), e.durations.push(d), n += d;
|
|
1745
1745
|
}
|
|
1746
|
-
}), e.i +=
|
|
1746
|
+
}), e.i += r.move, l = !0;
|
|
1747
1747
|
break;
|
|
1748
1748
|
}
|
|
1749
1749
|
}
|
|
@@ -2131,13 +2131,13 @@ class at {
|
|
|
2131
2131
|
};
|
|
2132
2132
|
Object.keys(this.rules).forEach((e) => {
|
|
2133
2133
|
this.rules[e] = this.rules[e].map((n) => {
|
|
2134
|
-
const i = n.indexOf("["), s = n.indexOf("]"), o = n.indexOf("="), l = n.substring(0, i), u = n.substring(i + 1, s),
|
|
2134
|
+
const i = n.indexOf("["), s = n.indexOf("]"), o = n.indexOf("="), l = n.substring(0, i), u = n.substring(i + 1, s), r = n.substring(s + 1, o), h = n.substring(o + 1), a = { regex: "", move: 0, visemes: [] };
|
|
2135
2135
|
let c = "";
|
|
2136
2136
|
c += [...l].map((g) => t[g] || g).join("");
|
|
2137
2137
|
const d = [...u];
|
|
2138
|
-
return d[0] = d[0].toLowerCase(), c += d.join(""),
|
|
2139
|
-
g &&
|
|
2140
|
-
}),
|
|
2138
|
+
return d[0] = d[0].toLowerCase(), c += d.join(""), a.move = d.length, c += [...r].map((g) => t[g] || g).join(""), a.regex = new RegExp(c, "i"), h.length && h.split(" ").forEach((g) => {
|
|
2139
|
+
g && a.visemes.push(g);
|
|
2140
|
+
}), a;
|
|
2141
2141
|
});
|
|
2142
2142
|
}), this.visemeDurations = {
|
|
2143
2143
|
aa: 1,
|
|
@@ -2268,9 +2268,9 @@ class at {
|
|
|
2268
2268
|
if (o) {
|
|
2269
2269
|
let l = !1;
|
|
2270
2270
|
for (let u = 0; u < o.length; u++) {
|
|
2271
|
-
const
|
|
2272
|
-
if ((e.words.substring(0, e.i) + s.toLowerCase() + e.words.substring(e.i + 1)).match(
|
|
2273
|
-
|
|
2271
|
+
const r = o[u];
|
|
2272
|
+
if ((e.words.substring(0, e.i) + s.toLowerCase() + e.words.substring(e.i + 1)).match(r.regex)) {
|
|
2273
|
+
r.visemes.forEach((c) => {
|
|
2274
2274
|
if (e.visemes.length && e.visemes[e.visemes.length - 1] === c) {
|
|
2275
2275
|
const d = 0.7 * (this.visemeDurations[c] || 1);
|
|
2276
2276
|
e.durations[e.durations.length - 1] += d, n += d;
|
|
@@ -2278,7 +2278,7 @@ class at {
|
|
|
2278
2278
|
const d = this.visemeDurations[c] || 1;
|
|
2279
2279
|
e.visemes.push(c), e.times.push(n), e.durations.push(d), n += d;
|
|
2280
2280
|
}
|
|
2281
|
-
}), e.i +=
|
|
2281
|
+
}), e.i += r.move, l = !0;
|
|
2282
2282
|
break;
|
|
2283
2283
|
}
|
|
2284
2284
|
}
|
|
@@ -2381,10 +2381,10 @@ class lt {
|
|
|
2381
2381
|
const e = [];
|
|
2382
2382
|
let n = parseFloat(t);
|
|
2383
2383
|
if (n === void 0) return t;
|
|
2384
|
-
let i = (s, o, l, u,
|
|
2384
|
+
let i = (s, o, l, u, r) => {
|
|
2385
2385
|
if (s < o) return s;
|
|
2386
2386
|
const h = Math.floor(s / o);
|
|
2387
|
-
return e.push(l + (h === 1 ? u : this.numberToFinnishWords(h.toString()) +
|
|
2387
|
+
return e.push(l + (h === 1 ? u : this.numberToFinnishWords(h.toString()) + r)), s - h * o;
|
|
2388
2388
|
};
|
|
2389
2389
|
if (n < 0 && (e.push("miinus "), n = Math.abs(n)), n = i(n, 1e9, " ", "miljardi", " miljardia"), n = i(n, 1e6, " ", "miljoona", " miljoonaa"), n = i(n, 1e3, "", "tuhat", "tuhatta"), n = i(n, 100, " ", "sata", "sataa"), n > 20 && (n = i(n, 10, "", "", "kymmentä")), n >= 1) {
|
|
2390
2390
|
let s = Math.floor(n);
|
|
@@ -2559,10 +2559,10 @@ class ut {
|
|
|
2559
2559
|
const e = [];
|
|
2560
2560
|
let n = parseFloat(t);
|
|
2561
2561
|
if (n === void 0) return t;
|
|
2562
|
-
let i = (s, o, l, u,
|
|
2562
|
+
let i = (s, o, l, u, r) => {
|
|
2563
2563
|
if (s < o) return s;
|
|
2564
2564
|
const h = Math.floor(s / o);
|
|
2565
|
-
return h === 1 ? e.push(this.numbers[1]) : e.push(this.numberToLithuanianWords(h.toString())), h % 10 === 1 ? e.push(l) : h % 10 === 0 || h % 100 > 10 && h % 100 < 20 ? e.push(
|
|
2565
|
+
return h === 1 ? e.push(this.numbers[1]) : e.push(this.numberToLithuanianWords(h.toString())), h % 10 === 1 ? e.push(l) : h % 10 === 0 || h % 100 > 10 && h % 100 < 20 ? e.push(r) : e.push(u), s - h * o;
|
|
2566
2566
|
};
|
|
2567
2567
|
n < 0 && (e.push("minus"), n = Math.abs(n)), n = i(n, 1e9, "milijardas", "milijardai", "milijardų"), n = i(n, 1e6, "milijonas", "milijonai", "milijonų"), n = i(n, 1e3, "tūkstantis", "tūkstančiai", "tūkstančių"), n = i(n, 100, "šimtas", "šimtai", "šimtų");
|
|
2568
2568
|
for (let s = this.tens.length - 1; s >= 1; s--)
|
|
@@ -4078,8 +4078,8 @@ class Oe {
|
|
|
4078
4078
|
RightHandMiddle1: "RightHand"
|
|
4079
4079
|
}, o = [];
|
|
4080
4080
|
Object.entries(s).forEach((l, u) => {
|
|
4081
|
-
const
|
|
4082
|
-
|
|
4081
|
+
const r = new f.Bone();
|
|
4082
|
+
r.name = l[0], l[1] ? this.ikMesh.getObjectByName(l[1]).add(r) : this.ikMesh.add(r), o.push(r);
|
|
4083
4083
|
}), this.ikMesh.bind(new f.Skeleton(o)), this.dynamicbones = new et(), this.isStreaming = !1, this.streamWorkletNode = null, this.streamAudioStartTime = null, this.streamWaitForAudioChunks = !0, this.streamLipsyncLang = null, this.streamLipsyncType = "visemes", this.streamLipsyncQueue = [];
|
|
4084
4084
|
}
|
|
4085
4085
|
/**
|
|
@@ -4126,9 +4126,9 @@ class Oe {
|
|
|
4126
4126
|
let e = 3 * t.length / 4;
|
|
4127
4127
|
t[t.length - 1] === "=" && (e--, t[t.length - 2] === "=" && e--);
|
|
4128
4128
|
const n = new ArrayBuffer(e), i = new Uint8Array(n);
|
|
4129
|
-
let s, o = 0, l, u,
|
|
4129
|
+
let s, o = 0, l, u, r, h;
|
|
4130
4130
|
for (s = 0; s < t.length; s += 4)
|
|
4131
|
-
l = this.b64Lookup[t.charCodeAt(s)], u = this.b64Lookup[t.charCodeAt(s + 1)],
|
|
4131
|
+
l = this.b64Lookup[t.charCodeAt(s)], u = this.b64Lookup[t.charCodeAt(s + 1)], r = this.b64Lookup[t.charCodeAt(s + 2)], h = this.b64Lookup[t.charCodeAt(s + 3)], i[o++] = l << 2 | u >> 4, i[o++] = (u & 15) << 4 | r >> 2, i[o++] = (r & 3) << 6 | h & 63;
|
|
4132
4132
|
return n;
|
|
4133
4133
|
}
|
|
4134
4134
|
/**
|
|
@@ -4199,9 +4199,9 @@ class Oe {
|
|
|
4199
4199
|
if (!i && s.morphTargetDictionary.hasOwnProperty(e)) return;
|
|
4200
4200
|
const o = s.geometry;
|
|
4201
4201
|
let l = null, u = null;
|
|
4202
|
-
for (const [
|
|
4203
|
-
if (s.morphTargetDictionary.hasOwnProperty(
|
|
4204
|
-
const
|
|
4202
|
+
for (const [r, h] of Object.entries(n))
|
|
4203
|
+
if (s.morphTargetDictionary.hasOwnProperty(r)) {
|
|
4204
|
+
const a = s.morphTargetDictionary[r], c = o.morphAttributes.position[a], d = o.morphAttributes.normal?.[a];
|
|
4205
4205
|
l || (l = new f.Float32BufferAttribute(c.count * 3, 3), d && (u = new f.Float32BufferAttribute(c.count * 3, 3)));
|
|
4206
4206
|
for (let g = 0; g < c.count; g++) {
|
|
4207
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;
|
|
@@ -4215,8 +4215,8 @@ class Oe {
|
|
|
4215
4215
|
}
|
|
4216
4216
|
if (l) {
|
|
4217
4217
|
o.morphAttributes.position.push(l), u && o.morphAttributes.normal.push(u);
|
|
4218
|
-
const
|
|
4219
|
-
s.morphTargetInfluences[
|
|
4218
|
+
const r = o.morphAttributes.position.length - 1;
|
|
4219
|
+
s.morphTargetInfluences[r] = 0, s.morphTargetDictionary[e] = r;
|
|
4220
4220
|
}
|
|
4221
4221
|
});
|
|
4222
4222
|
}
|
|
@@ -4230,64 +4230,64 @@ class Oe {
|
|
|
4230
4230
|
throw new Error("Invalid parameter. The avatar must have at least 'url' specified.");
|
|
4231
4231
|
const n = new je();
|
|
4232
4232
|
if (this.dracoEnabled) {
|
|
4233
|
-
const
|
|
4234
|
-
|
|
4233
|
+
const r = new Qe();
|
|
4234
|
+
r.setDecoderPath(this.dracoDecoderPath), n.setDRACOLoader(r);
|
|
4235
4235
|
}
|
|
4236
4236
|
let i = await n.loadAsync(t.url, e);
|
|
4237
4237
|
const s = [this.opt.modelRoot];
|
|
4238
|
-
if (this.posePropNames.forEach((
|
|
4239
|
-
if (!i.scene.getObjectByName(
|
|
4240
|
-
throw new Error("Avatar object " +
|
|
4241
|
-
}), this.stop(), this.avatar = t, this.bodyMovement = t.bodyMovement || "idle", this.movementIntensity = t.movementIntensity || 0.5, this.showFullAvatar = t.showFullAvatar || !1, this.fbxAnimationLoader = null, this.dynamicbones.dispose(), this.mixer = null, this.isAvatarOnly ? this.armature && this.clearThree(this.armature) : this.armature && this.clearThree(this.scene), this.armature = i.scene.getObjectByName(this.opt.modelRoot), this.armature.scale.setScalar(1), this.animations = i.animations, this.userData = i.userData, this.morphs = [], this.armature.traverse((
|
|
4242
|
-
|
|
4238
|
+
if (this.posePropNames.forEach((r) => s.push(r.split(".")[0])), s.forEach((r) => {
|
|
4239
|
+
if (!i.scene.getObjectByName(r))
|
|
4240
|
+
throw new Error("Avatar object " + r + " not found");
|
|
4241
|
+
}), this.stop(), this.avatar = t, this.bodyMovement = t.bodyMovement || "idle", this.movementIntensity = t.movementIntensity || 0.5, this.showFullAvatar = t.showFullAvatar || !1, this.fbxAnimationLoader = null, this.dynamicbones.dispose(), this.mixer = null, this.isAvatarOnly ? this.armature && this.clearThree(this.armature) : this.armature && this.clearThree(this.scene), this.armature = i.scene.getObjectByName(this.opt.modelRoot), this.armature.scale.setScalar(1), this.animations = i.animations, this.userData = i.userData, this.morphs = [], this.armature.traverse((r) => {
|
|
4242
|
+
r.morphTargetInfluences && r.morphTargetInfluences.length && r.morphTargetDictionary && this.morphs.push(r), r.frustumCulled = !1;
|
|
4243
4243
|
}), this.morphs.length === 0)
|
|
4244
4244
|
throw new Error("Blend shapes not found");
|
|
4245
4245
|
const o = new Set(this.mtCustoms);
|
|
4246
|
-
this.morphs.forEach((
|
|
4247
|
-
Object.keys(
|
|
4248
|
-
}), this.mtExtras.forEach((
|
|
4249
|
-
o.has(
|
|
4246
|
+
this.morphs.forEach((r) => {
|
|
4247
|
+
Object.keys(r.morphTargetDictionary).forEach((h) => o.add(h));
|
|
4248
|
+
}), this.mtExtras.forEach((r) => {
|
|
4249
|
+
o.has(r.key) || (this.addMixedMorphTarget(this.morphs, r.key, r.mix), o.add(r.key));
|
|
4250
4250
|
});
|
|
4251
4251
|
const l = {};
|
|
4252
|
-
if (o.forEach((
|
|
4253
|
-
l[
|
|
4252
|
+
if (o.forEach((r) => {
|
|
4253
|
+
l[r] = {
|
|
4254
4254
|
fixed: null,
|
|
4255
4255
|
realtime: null,
|
|
4256
4256
|
system: null,
|
|
4257
4257
|
systemd: null,
|
|
4258
4258
|
newvalue: null,
|
|
4259
4259
|
ref: null,
|
|
4260
|
-
min: this.mtMinExceptions.hasOwnProperty(
|
|
4261
|
-
max: this.mtMaxExceptions.hasOwnProperty(
|
|
4260
|
+
min: this.mtMinExceptions.hasOwnProperty(r) ? this.mtMinExceptions[r] : this.mtMinDefault,
|
|
4261
|
+
max: this.mtMaxExceptions.hasOwnProperty(r) ? this.mtMaxExceptions[r] : this.mtMaxDefault,
|
|
4262
4262
|
easing: this.mtEasingDefault,
|
|
4263
4263
|
base: null,
|
|
4264
4264
|
v: 0,
|
|
4265
4265
|
needsUpdate: !0,
|
|
4266
|
-
acc: (this.mtAccExceptions.hasOwnProperty(
|
|
4267
|
-
maxv: (this.mtMaxVExceptions.hasOwnProperty(
|
|
4268
|
-
limit: this.mtLimits.hasOwnProperty(
|
|
4269
|
-
onchange: this.mtOnchange.hasOwnProperty(
|
|
4270
|
-
baseline: this.avatar.baseline?.hasOwnProperty(
|
|
4266
|
+
acc: (this.mtAccExceptions.hasOwnProperty(r) ? this.mtAccExceptions[r] : this.mtAccDefault) / 1e3,
|
|
4267
|
+
maxv: (this.mtMaxVExceptions.hasOwnProperty(r) ? this.mtMaxVExceptions[r] : this.mtMaxVDefault) / 1e3,
|
|
4268
|
+
limit: this.mtLimits.hasOwnProperty(r) ? this.mtLimits[r] : null,
|
|
4269
|
+
onchange: this.mtOnchange.hasOwnProperty(r) ? this.mtOnchange[r] : null,
|
|
4270
|
+
baseline: this.avatar.baseline?.hasOwnProperty(r) ? this.avatar.baseline[r] : this.mtBaselineExceptions.hasOwnProperty(r) ? this.mtBaselineExceptions[r] : this.mtBaselineDefault,
|
|
4271
4271
|
ms: [],
|
|
4272
4272
|
is: []
|
|
4273
|
-
}, l[
|
|
4274
|
-
const h = this.mtAvatar[
|
|
4275
|
-
h && ["fixed", "system", "systemd", "realtime", "base", "v", "value", "applied"].forEach((
|
|
4276
|
-
l[
|
|
4277
|
-
}), this.morphs.forEach((
|
|
4278
|
-
const c =
|
|
4279
|
-
c !== void 0 && (l[
|
|
4273
|
+
}, l[r].value = l[r].baseline, l[r].applied = l[r].baseline;
|
|
4274
|
+
const h = this.mtAvatar[r];
|
|
4275
|
+
h && ["fixed", "system", "systemd", "realtime", "base", "v", "value", "applied"].forEach((a) => {
|
|
4276
|
+
l[r][a] = h[a];
|
|
4277
|
+
}), this.morphs.forEach((a) => {
|
|
4278
|
+
const c = a.morphTargetDictionary[r];
|
|
4279
|
+
c !== void 0 && (l[r].ms.push(a.morphTargetInfluences), l[r].is.push(c), a.morphTargetInfluences[c] = l[r].applied);
|
|
4280
4280
|
});
|
|
4281
|
-
}), this.mtAvatar = l, this.poseAvatar = { props: {} }, this.posePropNames.forEach((
|
|
4282
|
-
const h =
|
|
4283
|
-
this.poseAvatar.props[
|
|
4284
|
-
}), this.ikMesh.traverse((
|
|
4285
|
-
|
|
4281
|
+
}), this.mtAvatar = l, this.poseAvatar = { props: {} }, this.posePropNames.forEach((r) => {
|
|
4282
|
+
const h = r.split("."), a = this.armature.getObjectByName(h[0]);
|
|
4283
|
+
this.poseAvatar.props[r] = a[h[1]], this.poseBase.props.hasOwnProperty(r) ? this.poseAvatar.props[r].copy(this.poseBase.props[r]) : this.poseBase.props[r] = this.poseAvatar.props[r].clone(), this.poseDelta.props.hasOwnProperty(r) && !this.poseTarget.props.hasOwnProperty(r) && (this.poseTarget.props[r] = this.poseAvatar.props[r].clone()), this.poseTarget.props[r].t = this.animClock, this.poseTarget.props[r].d = 2e3;
|
|
4284
|
+
}), this.ikMesh.traverse((r) => {
|
|
4285
|
+
r.isBone && r.position.copy(this.armature.getObjectByName(r.name).position);
|
|
4286
4286
|
}), this.isAvatarOnly ? this.scene && this.scene.add(this.armature) : (this.scene.add(i.scene), this.scene.add(this.lightAmbient), this.scene.add(this.lightDirect), this.scene.add(this.lightSpot), this.lightSpot.target = this.armature.getObjectByName("Head")), t.hasOwnProperty("modelDynamicBones"))
|
|
4287
4287
|
try {
|
|
4288
4288
|
this.dynamicbones.setup(this.scene, this.armature, t.modelDynamicBones);
|
|
4289
|
-
} catch (
|
|
4290
|
-
console.error("Dynamic bones setup failed: " +
|
|
4289
|
+
} catch (r) {
|
|
4290
|
+
console.error("Dynamic bones setup failed: " + r);
|
|
4291
4291
|
}
|
|
4292
4292
|
this.objectLeftToeBase = this.armature.getObjectByName("LeftToeBase"), this.objectRightToeBase = this.armature.getObjectByName("RightToeBase"), this.objectLeftEye = this.armature.getObjectByName("LeftEye"), this.objectRightEye = this.armature.getObjectByName("RightEye"), this.objectLeftArm = this.armature.getObjectByName("LeftArm"), this.objectRightArm = this.armature.getObjectByName("RightArm"), this.objectHips = this.armature.getObjectByName("Hips"), this.objectHead = this.armature.getObjectByName("Head"), this.objectNeck = this.armature.getObjectByName("Neck");
|
|
4293
4293
|
const u = new f.Vector3();
|
|
@@ -4320,21 +4320,21 @@ class Oe {
|
|
|
4320
4320
|
}
|
|
4321
4321
|
if (this.viewName = t || this.viewName, e = e || {}, this.isAvatarOnly) return;
|
|
4322
4322
|
const n = e.hasOwnProperty("cameraX") ? e.cameraX : this.opt.cameraX, i = e.hasOwnProperty("cameraY") ? e.cameraY : this.opt.cameraY, s = e.hasOwnProperty("cameraDistance") ? e.cameraDistance : this.opt.cameraDistance, o = e.hasOwnProperty("cameraRotateX") ? e.cameraRotateX : this.opt.cameraRotateX, l = e.hasOwnProperty("cameraRotateY") ? e.cameraRotateY : this.opt.cameraRotateY, u = this.camera.fov * (Math.PI / 180);
|
|
4323
|
-
let
|
|
4323
|
+
let r = -n * Math.tan(u / 2), h = (1 - i) * Math.tan(u / 2), a = s;
|
|
4324
4324
|
switch (this.viewName) {
|
|
4325
4325
|
case "head":
|
|
4326
|
-
|
|
4326
|
+
a += 2, h = h * a + 4 * this.avatarHeight / 5;
|
|
4327
4327
|
break;
|
|
4328
4328
|
case "upper":
|
|
4329
|
-
|
|
4329
|
+
a += 4.5, h = h * a + 2 * this.avatarHeight / 3;
|
|
4330
4330
|
break;
|
|
4331
4331
|
case "mid":
|
|
4332
|
-
|
|
4332
|
+
a += 8, h = h * a + this.avatarHeight / 3;
|
|
4333
4333
|
break;
|
|
4334
4334
|
default:
|
|
4335
|
-
|
|
4335
|
+
a += 12, h = h * a;
|
|
4336
4336
|
}
|
|
4337
|
-
|
|
4337
|
+
r = r * a, this.controlsEnd = new f.Vector3(r, h, 0), this.cameraEnd = new f.Vector3(r, h, a).applyEuler(new f.Euler(o, l, 0)), this.cameraClock === null && (this.controls.target.copy(this.controlsEnd), this.camera.position.copy(this.cameraEnd)), this.controlsStart = this.controls.target.clone(), this.cameraStart = this.camera.position.clone(), this.cameraClock = 0;
|
|
4338
4338
|
}
|
|
4339
4339
|
/**
|
|
4340
4340
|
* Change light colors and intensities.
|
|
@@ -4431,16 +4431,16 @@ class Oe {
|
|
|
4431
4431
|
"HandMiddle",
|
|
4432
4432
|
"HandRing",
|
|
4433
4433
|
"HandPinky"
|
|
4434
|
-
].forEach((h,
|
|
4435
|
-
|
|
4434
|
+
].forEach((h, a) => {
|
|
4435
|
+
a === 0 ? (this.poseDelta.props[o + h + "1.quaternion"].x = 0, this.poseDelta.props[o + h + "2.quaternion"].z = (o === "Left" ? -1 : 1) * n.applied, this.poseDelta.props[o + h + "3.quaternion"].z = (o === "Left" ? -1 : 1) * n.applied) : (this.poseDelta.props[o + h + "1.quaternion"].x = n.applied, this.poseDelta.props[o + h + "2.quaternion"].x = 1.5 * n.applied, this.poseDelta.props[o + h + "3.quaternion"].x = 1.5 * n.applied);
|
|
4436
4436
|
});
|
|
4437
4437
|
break;
|
|
4438
4438
|
case "chestInhale":
|
|
4439
|
-
const l = n.applied / 20, u = { x: l, y: l / 2, z: 3 * l },
|
|
4440
|
-
this.poseDelta.props["Spine1.scale"] = u, this.poseDelta.props["Neck.scale"] =
|
|
4439
|
+
const l = n.applied / 20, u = { x: l, y: l / 2, z: 3 * l }, r = { x: 1 / (1 + l) - 1, y: 1 / (1 + l / 2) - 1, z: 1 / (1 + 3 * l) - 1 };
|
|
4440
|
+
this.poseDelta.props["Spine1.scale"] = u, this.poseDelta.props["Neck.scale"] = r, this.poseDelta.props["LeftArm.scale"] = r, this.poseDelta.props["RightArm.scale"] = r;
|
|
4441
4441
|
break;
|
|
4442
4442
|
default:
|
|
4443
|
-
for (let h = 0,
|
|
4443
|
+
for (let h = 0, a = n.ms.length; h < a; h++)
|
|
4444
4444
|
n.ms[h][n.is[h]] = n.applied;
|
|
4445
4445
|
}
|
|
4446
4446
|
}
|
|
@@ -4971,38 +4971,38 @@ class Oe {
|
|
|
4971
4971
|
else if (this.avatar.body && l.hasOwnProperty(this.avatar.body))
|
|
4972
4972
|
l = l[this.avatar.body];
|
|
4973
4973
|
else if (l.hasOwnProperty("alt")) {
|
|
4974
|
-
let
|
|
4974
|
+
let r = l.alt[0];
|
|
4975
4975
|
if (l.alt.length > 1) {
|
|
4976
4976
|
const h = Math.random();
|
|
4977
|
-
let
|
|
4977
|
+
let a = 0;
|
|
4978
4978
|
for (let c = 0; c < l.alt.length; c++) {
|
|
4979
4979
|
let d = this.valueFn(l.alt[c].p);
|
|
4980
|
-
if (
|
|
4981
|
-
|
|
4980
|
+
if (a += d === void 0 ? (1 - a) / (l.alt.length - 1 - c) : d, h < a) {
|
|
4981
|
+
r = l.alt[c];
|
|
4982
4982
|
break;
|
|
4983
4983
|
}
|
|
4984
4984
|
}
|
|
4985
4985
|
}
|
|
4986
|
-
l =
|
|
4986
|
+
l = r;
|
|
4987
4987
|
} else
|
|
4988
4988
|
break;
|
|
4989
4989
|
let u = this.valueFn(l.delay) || 0;
|
|
4990
4990
|
if (Array.isArray(u) && (u = this.gaussianRandom(...u)), l.hasOwnProperty("dt"))
|
|
4991
|
-
l.dt.forEach((
|
|
4992
|
-
let
|
|
4993
|
-
Array.isArray(
|
|
4991
|
+
l.dt.forEach((r, h) => {
|
|
4992
|
+
let a = this.valueFn(r);
|
|
4993
|
+
Array.isArray(a) && (a = this.gaussianRandom(...a)), o.ts[h + 1] = o.ts[h] + a;
|
|
4994
4994
|
});
|
|
4995
4995
|
else {
|
|
4996
|
-
let
|
|
4997
|
-
o.ts = Array(
|
|
4996
|
+
let r = Object.values(l.vs).reduce((h, a) => a.length > h ? a.length : h, 0);
|
|
4997
|
+
o.ts = Array(r + 1).fill(0);
|
|
4998
4998
|
}
|
|
4999
|
-
s ? o.ts = o.ts.map((
|
|
5000
|
-
for (let [
|
|
5001
|
-
const
|
|
5002
|
-
|
|
4999
|
+
s ? o.ts = o.ts.map((r) => u + r * n) : o.ts = o.ts.map((r) => this.animClock + u + r * n);
|
|
5000
|
+
for (let [r, h] of Object.entries(l.vs)) {
|
|
5001
|
+
const a = this.getBaselineValue(r), 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) ? r === "gesture" ? d.slice() : (a === void 0 ? 0 : a) + i * this.gaussianRandom(...d) : typeof d == "boolean" ? d : d instanceof Object && d.constructor === Object ? Object.assign({}, d) : (a === void 0 ? 0 : a) + i * d));
|
|
5002
|
+
r === "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)]) : r === "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[r] = [null, ...c];
|
|
5003
5003
|
}
|
|
5004
|
-
for (let
|
|
5005
|
-
for (; o.vs[
|
|
5004
|
+
for (let r of Object.keys(o.vs))
|
|
5005
|
+
for (; o.vs[r].length <= o.ts.length; ) o.vs[r].push(o.vs[r][o.vs[r].length - 1]);
|
|
5006
5006
|
return t.hasOwnProperty("mood") && (o.mood = this.valueFn(t.mood).slice()), e && (o.loop = e), o;
|
|
5007
5007
|
}
|
|
5008
5008
|
/**
|
|
@@ -5080,13 +5080,13 @@ class Oe {
|
|
|
5080
5080
|
if (this.isSpeaking)
|
|
5081
5081
|
for (l = 0, this.audioAnalyzerNode.getByteFrequencyData(this.volumeFrequencyData), n = 2, s = 10; n < s; n++)
|
|
5082
5082
|
this.volumeFrequencyData[n] > l && (l = this.volumeFrequencyData[n]);
|
|
5083
|
-
let u = null,
|
|
5083
|
+
let u = null, r = null;
|
|
5084
5084
|
const h = [];
|
|
5085
5085
|
for (n = 0, s = this.animQueue.length; n < s; n++) {
|
|
5086
|
-
const
|
|
5087
|
-
if (!(!
|
|
5088
|
-
for (i =
|
|
5089
|
-
for (let [c, d] of Object.entries(
|
|
5086
|
+
const a = this.animQueue[n];
|
|
5087
|
+
if (!(!a || !a.ts || !a.ts.length || this.animClock < a.ts[0])) {
|
|
5088
|
+
for (i = a.ndx || 0, o = a.ts.length; i < o && !(this.animClock < a.ts[i]); i++)
|
|
5089
|
+
for (let [c, d] of Object.entries(a.vs))
|
|
5090
5090
|
if (this.mtAvatar.hasOwnProperty(c)) {
|
|
5091
5091
|
if (d[i + 1] === null) continue;
|
|
5092
5092
|
const g = this.mtAvatar[c];
|
|
@@ -5094,9 +5094,9 @@ class Oe {
|
|
|
5094
5094
|
g.newvalue = d[i];
|
|
5095
5095
|
else {
|
|
5096
5096
|
g.newvalue = d[i + 1];
|
|
5097
|
-
const y =
|
|
5097
|
+
const y = a.ts[i + 1] - a.ts[i];
|
|
5098
5098
|
let x = 1;
|
|
5099
|
-
y > 1e-4 && (x = (this.animClock -
|
|
5099
|
+
y > 1e-4 && (x = (this.animClock - a.ts[i]) / y), x < 1 && (g.easing && (x = g.easing(x)), g.newvalue = (1 - x) * d[i] + x * g.newvalue), g.ref && g.ref !== a.vs && g.ref.hasOwnProperty(c) && delete g.ref[c], g.ref = a.vs;
|
|
5100
5100
|
}
|
|
5101
5101
|
if (l)
|
|
5102
5102
|
switch (c) {
|
|
@@ -5108,12 +5108,12 @@ class Oe {
|
|
|
5108
5108
|
g.newvalue *= 1 + l / 255 - 0.5;
|
|
5109
5109
|
}
|
|
5110
5110
|
g.needsUpdate = !0;
|
|
5111
|
-
} else c === "eyeContact" && d[i] !== null && u !== !1 ? u = !!d[i] : c === "headMove" && d[i] !== null &&
|
|
5112
|
-
i === o ? (
|
|
5111
|
+
} else c === "eyeContact" && d[i] !== null && u !== !1 ? u = !!d[i] : c === "headMove" && d[i] !== null && r !== !1 ? d[i] === 0 ? r = !1 : (Math.random() < d[i] && (r = !0), d[i] = null) : d[i] !== null && (h.push({ mt: c, val: d[i] }), d[i] = null);
|
|
5112
|
+
i === o ? (a.hasOwnProperty("mood") && this.setMood(a.mood), a.loop ? (o = this.isSpeaking && (a.template.name === "head" || a.template.name === "eyes") ? 4 : 1, this.animQueue[n] = this.animFactory(a.template, a.loop > 0 ? a.loop - 1 : a.loop, 1, 1 / o)) : (this.animQueue.splice(n--, 1), s--)) : a.ndx = i - 1;
|
|
5113
5113
|
}
|
|
5114
5114
|
}
|
|
5115
|
-
for (let
|
|
5116
|
-
switch (i = h[
|
|
5115
|
+
for (let a = 0, c = h.length; a < c; a++)
|
|
5116
|
+
switch (i = h[a].val, h[a].mt) {
|
|
5117
5117
|
case "speak":
|
|
5118
5118
|
this.speakText(i);
|
|
5119
5119
|
break;
|
|
@@ -5159,7 +5159,7 @@ class Oe {
|
|
|
5159
5159
|
}, i.x ? new f.Vector3(i.x, i.y, i.z) : null, !0, i.d);
|
|
5160
5160
|
break;
|
|
5161
5161
|
}
|
|
5162
|
-
if ((u ||
|
|
5162
|
+
if ((u || r) && (E.setFromQuaternion(this.poseAvatar.props["Head.quaternion"]), E.x = Math.max(-0.9, Math.min(0.9, 2 * E.x - 0.5)), E.y = Math.max(-0.9, Math.min(0.9, -2.5 * E.y)), u ? (Object.assign(this.mtAvatar.eyesLookDown, { system: E.x < 0 ? -E.x : 0, needsUpdate: !0 }), Object.assign(this.mtAvatar.eyesLookUp, { system: E.x < 0 ? 0 : E.x, needsUpdate: !0 }), Object.assign(this.mtAvatar.eyeLookInLeft, { system: E.y < 0 ? -E.y : 0, needsUpdate: !0 }), Object.assign(this.mtAvatar.eyeLookOutLeft, { system: E.y < 0 ? 0 : E.y, needsUpdate: !0 }), Object.assign(this.mtAvatar.eyeLookInRight, { system: E.y < 0 ? 0 : E.y, needsUpdate: !0 }), Object.assign(this.mtAvatar.eyeLookOutRight, { system: E.y < 0 ? -E.y : 0, needsUpdate: !0 }), r && (n = -this.mtAvatar.bodyRotateY.value, i = this.gaussianRandom(-0.2, 0.2), this.animQueue.push(this.animFactory({
|
|
5163
5163
|
name: "headmove",
|
|
5164
5164
|
dt: [[1e3, 2e3], [1e3, 2e3, 1, 2], [1e3, 2e3], [1e3, 2e3, 1, 2]],
|
|
5165
5165
|
vs: {
|
|
@@ -5185,8 +5185,8 @@ class Oe {
|
|
|
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
|
|
5189
|
-
|
|
5188
|
+
let a = new f.Spherical().setFromVector3(this.cameraStart), c = new f.Spherical().setFromVector3(this.cameraEnd);
|
|
5189
|
+
a.phi += this.easing(this.cameraClock / 1e3) * (c.phi - a.phi), a.theta += this.easing(this.cameraClock / 1e3) * (c.theta - a.theta), a.radius += this.easing(this.cameraClock / 1e3) * (c.radius - a.radius), a.makeSafe(), this.camera.position.setFromSpherical(a), this.controlsStart.x !== this.controlsEnd.x ? this.controls.target.copy(this.controlsStart.lerp(this.controlsEnd, this.easing(this.cameraClock / 1e3))) : (a.setFromVector3(this.controlsStart), c.setFromVector3(this.controlsEnd), a.phi += this.easing(this.cameraClock / 1e3) * (c.phi - a.phi), a.theta += this.easing(this.cameraClock / 1e3) * (c.theta - a.theta), a.radius += this.easing(this.cameraClock / 1e3) * (c.radius - a.radius), a.makeSafe(), this.controls.target.setFromSpherical(a)), this.controls.update();
|
|
5190
5190
|
}
|
|
5191
5191
|
this.controls.autoRotate && this.controls.update(), this.stats && this.stats.end(), this.render();
|
|
5192
5192
|
}
|
|
@@ -5247,16 +5247,16 @@ class Oe {
|
|
|
5247
5247
|
*/
|
|
5248
5248
|
speakText(t, e = null, n = null, i = null) {
|
|
5249
5249
|
e = e || {};
|
|
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,
|
|
5251
|
-
let h = "",
|
|
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, r = e.lipsyncLang || this.avatar.lipsyncLang || this.opt.lipsyncLang;
|
|
5251
|
+
let h = "", a = "", 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
5254
|
const I = x === y.length - 1, B = 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), n && (h += y[x]), B && (!i || i.every((
|
|
5257
|
+
if (p && !I && !H && y[x + 1].match(s) && (p = !1), n && (h += y[x]), B && (!i || i.every((R) => x < R[0] || x > R[1])) && (a += y[x]), (z || p || I) && (a.length && (a = this.lipsyncPreProcessText(a, r), a.length && d.push({
|
|
5258
5258
|
mark: c,
|
|
5259
|
-
word:
|
|
5259
|
+
word: a
|
|
5260
5260
|
})), h.length && (g.push({
|
|
5261
5261
|
mark: c,
|
|
5262
5262
|
template: { name: "subtitles" },
|
|
@@ -5264,32 +5264,32 @@ class Oe {
|
|
|
5264
5264
|
vs: {
|
|
5265
5265
|
subtitles: [h]
|
|
5266
5266
|
}
|
|
5267
|
-
}), h = ""),
|
|
5268
|
-
const
|
|
5269
|
-
if (
|
|
5270
|
-
const T =
|
|
5271
|
-
for (let F = 0; F <
|
|
5267
|
+
}), h = ""), a.length)) {
|
|
5268
|
+
const R = this.lipsyncWordsToVisemes(a, r);
|
|
5269
|
+
if (R && R.visemes && R.visemes.length) {
|
|
5270
|
+
const T = R.times[R.visemes.length - 1] + R.durations[R.visemes.length - 1];
|
|
5271
|
+
for (let F = 0; F < R.visemes.length; F++)
|
|
5272
5272
|
g.push({
|
|
5273
5273
|
mark: c,
|
|
5274
5274
|
template: { name: "viseme" },
|
|
5275
|
-
ts: [(
|
|
5275
|
+
ts: [(R.times[F] - 0.6) / T, (R.times[F] + 0.5) / T, (R.times[F] + R.durations[F] + 0.5) / T],
|
|
5276
5276
|
vs: {
|
|
5277
|
-
["viseme_" +
|
|
5277
|
+
["viseme_" + R.visemes[F]]: [null, R.visemes[F] === "PP" || R.visemes[F] === "FF" ? 0.9 : 0.6, 0]
|
|
5278
5278
|
}
|
|
5279
5279
|
});
|
|
5280
5280
|
}
|
|
5281
|
-
|
|
5281
|
+
a = "", c++;
|
|
5282
5282
|
}
|
|
5283
5283
|
if (p || I) {
|
|
5284
5284
|
if (d.length || I && g.length) {
|
|
5285
|
-
const
|
|
5285
|
+
const R = {
|
|
5286
5286
|
anim: g
|
|
5287
5287
|
};
|
|
5288
|
-
n && (
|
|
5288
|
+
n && (R.onSubtitles = n), d.length && !e.avatarMute && (R.text = d, e.avatarMood && (R.mood = e.avatarMood), e.ttsLang && (R.lang = e.ttsLang), e.ttsVoice && (R.voice = e.ttsVoice), e.ttsRate && (R.rate = e.ttsRate), e.ttsVoice && (R.pitch = e.ttsPitch), e.ttsVolume && (R.volume = e.ttsVolume)), this.speechQueue.push(R), d = [], a = "", c = 0, g = [];
|
|
5289
5289
|
}
|
|
5290
5290
|
if (H) {
|
|
5291
|
-
let
|
|
5292
|
-
|
|
5291
|
+
let R = this.animEmojis[y[x]];
|
|
5292
|
+
R && R.link && (R = this.animEmojis[R.link]), R && this.speechQueue.push({ emoji: R });
|
|
5293
5293
|
}
|
|
5294
5294
|
this.speechQueue.push({ break: 100 });
|
|
5295
5295
|
}
|
|
@@ -5370,22 +5370,22 @@ class Oe {
|
|
|
5370
5370
|
if (t.words) {
|
|
5371
5371
|
let o = [];
|
|
5372
5372
|
for (let l = 0; l < t.words.length; l++) {
|
|
5373
|
-
const u = t.words[l],
|
|
5373
|
+
const u = t.words[l], r = t.wtimes[l];
|
|
5374
5374
|
let h = t.wdurations[l];
|
|
5375
5375
|
if (u.length && (n && o.push({
|
|
5376
5376
|
template: { name: "subtitles" },
|
|
5377
|
-
ts: [
|
|
5377
|
+
ts: [r],
|
|
5378
5378
|
vs: {
|
|
5379
5379
|
subtitles: [" " + u]
|
|
5380
5380
|
}
|
|
5381
5381
|
}), !t.visemes)) {
|
|
5382
|
-
const
|
|
5382
|
+
const a = this.lipsyncPreProcessText(u, i), c = this.lipsyncWordsToVisemes(a, i);
|
|
5383
5383
|
if (c && c.visemes && c.visemes.length) {
|
|
5384
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
5386
|
if (h = Math.min(h, c.visemes.length * 200), d > 0)
|
|
5387
5387
|
for (let x = 0; x < c.visemes.length; x++) {
|
|
5388
|
-
const I =
|
|
5388
|
+
const I = r + c.times[x] / d * h, B = c.durations[x] / d * h;
|
|
5389
5389
|
o.push({
|
|
5390
5390
|
template: { name: "viseme" },
|
|
5391
5391
|
ts: [I - Math.min(60, 2 * B / 3), I + Math.min(25, B / 2), I + B + Math.min(60, B / 2)],
|
|
@@ -5399,10 +5399,10 @@ class Oe {
|
|
|
5399
5399
|
}
|
|
5400
5400
|
if (t.visemes)
|
|
5401
5401
|
for (let l = 0; l < t.visemes.length; l++) {
|
|
5402
|
-
const u = t.visemes[l],
|
|
5402
|
+
const u = t.visemes[l], r = t.vtimes[l], h = t.vdurations[l];
|
|
5403
5403
|
o.push({
|
|
5404
5404
|
template: { name: "viseme" },
|
|
5405
|
-
ts: [
|
|
5405
|
+
ts: [r - 2 * h / 3, r + h / 2, r + h + h / 2],
|
|
5406
5406
|
vs: {
|
|
5407
5407
|
["viseme_" + u]: [null, u === "PP" || u === "FF" ? 0.9 : 0.6, 0]
|
|
5408
5408
|
}
|
|
@@ -5410,10 +5410,10 @@ class Oe {
|
|
|
5410
5410
|
}
|
|
5411
5411
|
if (t.markers)
|
|
5412
5412
|
for (let l = 0; l < t.markers.length; l++) {
|
|
5413
|
-
const u = t.markers[l],
|
|
5413
|
+
const u = t.markers[l], r = t.mtimes[l];
|
|
5414
5414
|
o.push({
|
|
5415
5415
|
template: { name: "markers" },
|
|
5416
|
-
ts: [
|
|
5416
|
+
ts: [r],
|
|
5417
5417
|
vs: { function: [u] }
|
|
5418
5418
|
});
|
|
5419
5419
|
}
|
|
@@ -5466,11 +5466,11 @@ class Oe {
|
|
|
5466
5466
|
*/
|
|
5467
5467
|
async synthesizeWithBrowserTTS(t) {
|
|
5468
5468
|
return new Promise((e, n) => {
|
|
5469
|
-
const i = t.text.map((p) => p.word).join(" "), s = new SpeechSynthesisUtterance(i), o = t.lang || this.avatar.ttsLang || this.opt.ttsLang || "en-US", l = (t.rate || this.avatar.ttsRate || this.opt.ttsRate || 1) + this.mood.speech.deltaRate, u = (t.pitch || this.avatar.ttsPitch || this.opt.ttsPitch || 1) + this.mood.speech.deltaPitch,
|
|
5470
|
-
s.lang = o, s.rate = Math.max(0.1, Math.min(10, l)), s.pitch = Math.max(0, Math.min(2, u)), s.volume = Math.max(0, Math.min(1,
|
|
5471
|
-
const h = speechSynthesis.getVoices(),
|
|
5472
|
-
if (
|
|
5473
|
-
const p = h.find((H) => H.name.includes(
|
|
5469
|
+
const i = t.text.map((p) => p.word).join(" "), s = new SpeechSynthesisUtterance(i), o = t.lang || this.avatar.ttsLang || this.opt.ttsLang || "en-US", l = (t.rate || this.avatar.ttsRate || this.opt.ttsRate || 1) + this.mood.speech.deltaRate, u = (t.pitch || this.avatar.ttsPitch || this.opt.ttsPitch || 1) + this.mood.speech.deltaPitch, r = (t.volume || this.avatar.ttsVolume || this.opt.ttsVolume || 1) + this.mood.speech.deltaVolume;
|
|
5470
|
+
s.lang = o, s.rate = Math.max(0.1, Math.min(10, l)), s.pitch = Math.max(0, Math.min(2, u)), s.volume = Math.max(0, Math.min(1, r));
|
|
5471
|
+
const h = speechSynthesis.getVoices(), a = t.voice || this.avatar.ttsVoice || this.opt.ttsVoice;
|
|
5472
|
+
if (a && h.length > 0) {
|
|
5473
|
+
const p = h.find((H) => H.name.includes(a) || H.lang === o);
|
|
5474
5474
|
p && (s.voice = p);
|
|
5475
5475
|
}
|
|
5476
5476
|
const c = i.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(i, g), x = this.lipsyncWordsToVisemes(y, g);
|
|
@@ -5486,7 +5486,7 @@ class Oe {
|
|
|
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],
|
|
5489
|
+
const z = x.visemes[H], R = x.times[H] / p, T = x.durations[H] / p, F = R * c, J = T * c;
|
|
5490
5490
|
I.push({
|
|
5491
5491
|
template: { name: "viseme" },
|
|
5492
5492
|
ts: [F - Math.min(60, 2 * J / 3), F + Math.min(25, J / 2), F + J + Math.min(60, J / 2)],
|
|
@@ -5532,7 +5532,7 @@ class Oe {
|
|
|
5532
5532
|
const o = await s.arrayBuffer(), l = await this.audioCtx.decodeAudioData(o);
|
|
5533
5533
|
console.log("Using text-based lip-sync for debugging...");
|
|
5534
5534
|
const u = this.avatar.lipsyncLang || this.opt.lipsyncLang || "en";
|
|
5535
|
-
let
|
|
5535
|
+
let r;
|
|
5536
5536
|
try {
|
|
5537
5537
|
console.log("Lip-sync modules available:", {
|
|
5538
5538
|
hasLipsync: !!this.lipsync,
|
|
@@ -5545,7 +5545,7 @@ class Oe {
|
|
|
5545
5545
|
lipsyncData: d,
|
|
5546
5546
|
hasVisemes: d && d.visemes && d.visemes.length > 0
|
|
5547
5547
|
}), d && d.visemes && d.visemes.length > 0)
|
|
5548
|
-
|
|
5548
|
+
r = {
|
|
5549
5549
|
visemes: d.visemes.map((g, y) => ({
|
|
5550
5550
|
viseme: g,
|
|
5551
5551
|
startTime: y * l.duration / d.visemes.length,
|
|
@@ -5567,7 +5567,7 @@ class Oe {
|
|
|
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);
|
|
5569
5569
|
}
|
|
5570
|
-
|
|
5570
|
+
r = {
|
|
5571
5571
|
visemes: g.map((y, x) => ({
|
|
5572
5572
|
viseme: y,
|
|
5573
5573
|
startTime: x * l.duration / g.length,
|
|
@@ -5583,20 +5583,20 @@ class Oe {
|
|
|
5583
5583
|
console.log("ElevenLabs TTS Audio Analysis:", {
|
|
5584
5584
|
text: e,
|
|
5585
5585
|
audioDuration: l.duration,
|
|
5586
|
-
visemeCount:
|
|
5587
|
-
wordCount:
|
|
5586
|
+
visemeCount: r.visemes ? r.visemes.length : 0,
|
|
5587
|
+
wordCount: r.words ? r.words.length : 0,
|
|
5588
5588
|
features: {
|
|
5589
|
-
onsets:
|
|
5590
|
-
boundaries:
|
|
5589
|
+
onsets: r.features && r.features.onsets ? r.features.onsets.length : 0,
|
|
5590
|
+
boundaries: r.features && r.features.phonemeBoundaries ? r.features.phonemeBoundaries.length : 0
|
|
5591
5591
|
},
|
|
5592
|
-
visemes:
|
|
5592
|
+
visemes: r.visemes ? r.visemes.slice(0, 3) : []
|
|
5593
5593
|
// Show first 3 visemes for debugging
|
|
5594
5594
|
});
|
|
5595
5595
|
const h = [];
|
|
5596
|
-
if (
|
|
5597
|
-
console.log("ElevenLabs: Generating lip-sync animation from",
|
|
5598
|
-
for (let c = 0; c <
|
|
5599
|
-
const d =
|
|
5596
|
+
if (r.visemes && r.visemes.length > 0) {
|
|
5597
|
+
console.log("ElevenLabs: Generating lip-sync animation from", r.visemes.length, "visemes");
|
|
5598
|
+
for (let c = 0; c < r.visemes.length; c++) {
|
|
5599
|
+
const d = r.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)],
|
|
@@ -5608,8 +5608,8 @@ class Oe {
|
|
|
5608
5608
|
console.log("ElevenLabs: Generated", h.length, "lip-sync animation frames");
|
|
5609
5609
|
} else
|
|
5610
5610
|
console.warn("ElevenLabs: No visemes available for lip-sync animation");
|
|
5611
|
-
const
|
|
5612
|
-
console.log("ElevenLabs: Combined animation frames:",
|
|
5611
|
+
const a = [...t.anim, ...h];
|
|
5612
|
+
console.log("ElevenLabs: Combined animation frames:", a.length, "(original:", t.anim.length, "+ lipsync:", h.length, ")"), this.audioPlaylist.push({ anim: a, audio: l }), this.onSubtitles = t.onSubtitles || null, this.resetLips(), t.mood && this.setMood(t.mood), this.playAudio();
|
|
5613
5613
|
}
|
|
5614
5614
|
/**
|
|
5615
5615
|
* Synthesize speech using Deepgram Aura-2 TTS
|
|
@@ -5630,7 +5630,7 @@ class Oe {
|
|
|
5630
5630
|
const o = await s.arrayBuffer(), l = await this.audioCtx.decodeAudioData(o);
|
|
5631
5631
|
console.log("Using text-based lip-sync for Deepgram...");
|
|
5632
5632
|
const u = this.avatar.lipsyncLang || this.opt.lipsyncLang || "en";
|
|
5633
|
-
let
|
|
5633
|
+
let r;
|
|
5634
5634
|
try {
|
|
5635
5635
|
console.log("Lip-sync modules available:", {
|
|
5636
5636
|
hasLipsync: !!this.lipsync,
|
|
@@ -5643,7 +5643,7 @@ class Oe {
|
|
|
5643
5643
|
lipsyncData: d,
|
|
5644
5644
|
hasVisemes: d && d.visemes && d.visemes.length > 0
|
|
5645
5645
|
}), d && d.visemes && d.visemes.length > 0)
|
|
5646
|
-
|
|
5646
|
+
r = {
|
|
5647
5647
|
visemes: d.visemes.map((g, y) => ({
|
|
5648
5648
|
viseme: g,
|
|
5649
5649
|
startTime: y * l.duration / d.visemes.length,
|
|
@@ -5665,7 +5665,7 @@ class Oe {
|
|
|
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);
|
|
5667
5667
|
}
|
|
5668
|
-
|
|
5668
|
+
r = {
|
|
5669
5669
|
visemes: g.map((y, x) => ({
|
|
5670
5670
|
viseme: y,
|
|
5671
5671
|
startTime: x * l.duration / g.length,
|
|
@@ -5681,20 +5681,20 @@ class Oe {
|
|
|
5681
5681
|
console.log("Deepgram TTS Audio Analysis:", {
|
|
5682
5682
|
text: e,
|
|
5683
5683
|
audioDuration: l.duration,
|
|
5684
|
-
visemeCount:
|
|
5685
|
-
wordCount:
|
|
5684
|
+
visemeCount: r.visemes ? r.visemes.length : 0,
|
|
5685
|
+
wordCount: r.words ? r.words.length : 0,
|
|
5686
5686
|
features: {
|
|
5687
|
-
onsets:
|
|
5688
|
-
boundaries:
|
|
5687
|
+
onsets: r.features && r.features.onsets ? r.features.onsets.length : 0,
|
|
5688
|
+
boundaries: r.features && r.features.phonemeBoundaries ? r.features.phonemeBoundaries.length : 0
|
|
5689
5689
|
},
|
|
5690
|
-
visemes:
|
|
5690
|
+
visemes: r.visemes ? r.visemes.slice(0, 3) : []
|
|
5691
5691
|
// Show first 3 visemes for debugging
|
|
5692
5692
|
});
|
|
5693
5693
|
const h = [];
|
|
5694
|
-
if (
|
|
5695
|
-
console.log("Deepgram: Generating lip-sync animation from",
|
|
5696
|
-
for (let c = 0; c <
|
|
5697
|
-
const d =
|
|
5694
|
+
if (r.visemes && r.visemes.length > 0) {
|
|
5695
|
+
console.log("Deepgram: Generating lip-sync animation from", r.visemes.length, "visemes");
|
|
5696
|
+
for (let c = 0; c < r.visemes.length; c++) {
|
|
5697
|
+
const d = r.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)],
|
|
@@ -5706,15 +5706,15 @@ class Oe {
|
|
|
5706
5706
|
console.log("Deepgram: Generated", h.length, "lip-sync animation frames");
|
|
5707
5707
|
} else
|
|
5708
5708
|
console.warn("Deepgram: No visemes available for lip-sync animation");
|
|
5709
|
-
const
|
|
5710
|
-
console.log("Deepgram: Combined animation frames:",
|
|
5709
|
+
const a = [...t.anim, ...h];
|
|
5710
|
+
console.log("Deepgram: Combined animation frames:", a.length, "(original:", t.anim.length, "+ lipsync:", h.length, ")"), this.audioPlaylist.push({ anim: a, audio: l }), this.onSubtitles = t.onSubtitles || null, this.resetLips(), t.mood && this.setMood(t.mood), this.playAudio();
|
|
5711
5711
|
}
|
|
5712
5712
|
/**
|
|
5713
5713
|
* Synthesize speech using Azure TTS
|
|
5714
5714
|
* @param {Object} line Speech line object
|
|
5715
5715
|
*/
|
|
5716
5716
|
async synthesizeWithAzureTTS(t) {
|
|
5717
|
-
const e = t.text.map((
|
|
5717
|
+
const e = t.text.map((a) => a.word).join(" "), i = `
|
|
5718
5718
|
<speak version="1.0" xmlns="http://www.w3.org/2001/10/synthesis" xml:lang="en-US">
|
|
5719
5719
|
<voice name="${t.voice || this.avatar.ttsVoice || this.opt.ttsVoice || "en-US-AriaNeural"}">
|
|
5720
5720
|
${e}
|
|
@@ -5744,10 +5744,10 @@ class Oe {
|
|
|
5744
5744
|
boundaries: u.features.phonemeBoundaries.length
|
|
5745
5745
|
}
|
|
5746
5746
|
});
|
|
5747
|
-
const
|
|
5748
|
-
for (let
|
|
5749
|
-
const c = u.visemes[
|
|
5750
|
-
|
|
5747
|
+
const r = [];
|
|
5748
|
+
for (let a = 0; a < u.visemes.length; a++) {
|
|
5749
|
+
const c = u.visemes[a], d = c.startTime * 1e3, g = c.duration * 1e3, y = c.intensity;
|
|
5750
|
+
r.push({
|
|
5751
5751
|
template: { name: "viseme" },
|
|
5752
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: {
|
|
@@ -5755,7 +5755,7 @@ class Oe {
|
|
|
5755
5755
|
}
|
|
5756
5756
|
});
|
|
5757
5757
|
}
|
|
5758
|
-
const h = [...t.anim, ...
|
|
5758
|
+
const h = [...t.anim, ...r];
|
|
5759
5759
|
this.audioPlaylist.push({ anim: h, audio: l }), this.onSubtitles = t.onSubtitles || null, this.resetLips(), t.mood && this.setMood(t.mood), this.playAudio();
|
|
5760
5760
|
}
|
|
5761
5761
|
/**
|
|
@@ -5796,11 +5796,11 @@ class Oe {
|
|
|
5796
5796
|
const o = this.b64ToArrayBuffer(s.audioContent), l = await this.audioCtx.decodeAudioData(o);
|
|
5797
5797
|
this.speakWithHands();
|
|
5798
5798
|
const u = [0];
|
|
5799
|
-
let
|
|
5799
|
+
let r = 0;
|
|
5800
5800
|
t.text.forEach((c, d) => {
|
|
5801
5801
|
if (d > 0) {
|
|
5802
5802
|
let g = u[u.length - 1];
|
|
5803
|
-
s.timepoints[
|
|
5803
|
+
s.timepoints[r] && (g = s.timepoints[r].timeSeconds * 1e3, s.timepoints[r].markName === "" + c.mark && r++), u.push(g);
|
|
5804
5804
|
}
|
|
5805
5805
|
});
|
|
5806
5806
|
const h = [{ mark: 0, time: 0 }];
|
|
@@ -5810,8 +5810,8 @@ class Oe {
|
|
|
5810
5810
|
h[d - 1].duration = g, h.push({ mark: d, time: c });
|
|
5811
5811
|
}
|
|
5812
5812
|
});
|
|
5813
|
-
let
|
|
5814
|
-
|
|
5813
|
+
let a = 1e3 * l.duration;
|
|
5814
|
+
a > this.opt.ttsTrimEnd && (a = a - this.opt.ttsTrimEnd), h[h.length - 1].duration = a - h[h.length - 1].time, t.anim.forEach((c) => {
|
|
5815
5815
|
const d = h[c.mark];
|
|
5816
5816
|
if (d)
|
|
5817
5817
|
for (let g = 0; g < c.ts.length; g++)
|
|
@@ -5896,7 +5896,7 @@ class Oe {
|
|
|
5896
5896
|
if (!this.workletLoaded)
|
|
5897
5897
|
try {
|
|
5898
5898
|
const l = this.audioCtx.audioWorklet.addModule(dt.href), u = new Promise(
|
|
5899
|
-
(
|
|
5899
|
+
(r, h) => setTimeout(() => h(new Error("Worklet loading timed out")), 5e3)
|
|
5900
5900
|
);
|
|
5901
5901
|
await Promise.race([l, u]), this.workletLoaded = !0;
|
|
5902
5902
|
} catch (l) {
|
|
@@ -5932,7 +5932,7 @@ class Oe {
|
|
|
5932
5932
|
} catch {
|
|
5933
5933
|
}
|
|
5934
5934
|
if (this.resetLips(), this.lookAtCamera(500), t.mood && this.setMood(t.mood), this.onSubtitles = i || null, this.audioCtx.state === "suspended" || this.audioCtx.state === "interrupted") {
|
|
5935
|
-
const l = this.audioCtx.resume(), u = new Promise((
|
|
5935
|
+
const l = this.audioCtx.resume(), u = new Promise((r, h) => setTimeout(() => h("p2"), 1e3));
|
|
5936
5936
|
try {
|
|
5937
5937
|
await Promise.race([l, u]);
|
|
5938
5938
|
} catch {
|
|
@@ -6031,18 +6031,18 @@ class Oe {
|
|
|
6031
6031
|
subtitles: [" " + i]
|
|
6032
6032
|
}
|
|
6033
6033
|
}), this.streamLipsyncType == "words")) {
|
|
6034
|
-
const l = this.streamLipsyncLang || this.avatar.lipsyncLang || this.opt.lipsyncLang, u = this.lipsyncPreProcessText(i, l),
|
|
6035
|
-
if (
|
|
6036
|
-
const h =
|
|
6037
|
-
let c = 0.6 + this.convertRange(
|
|
6038
|
-
if (o = Math.min(o,
|
|
6039
|
-
for (let d = 0; d <
|
|
6040
|
-
const g = e + s +
|
|
6034
|
+
const l = this.streamLipsyncLang || this.avatar.lipsyncLang || this.opt.lipsyncLang, u = this.lipsyncPreProcessText(i, l), r = this.lipsyncWordsToVisemes(u, l);
|
|
6035
|
+
if (r && r.visemes && r.visemes.length) {
|
|
6036
|
+
const h = r.times[r.visemes.length - 1] + r.durations[r.visemes.length - 1], a = Math.min(o, Math.max(0, o - r.visemes.length * 150));
|
|
6037
|
+
let c = 0.6 + this.convertRange(a, [0, o], [0, 0.4]);
|
|
6038
|
+
if (o = Math.min(o, r.visemes.length * 200), h > 0)
|
|
6039
|
+
for (let d = 0; d < r.visemes.length; d++) {
|
|
6040
|
+
const g = e + s + r.times[d] / h * o, y = r.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_" +
|
|
6045
|
+
["viseme_" + r.visemes[d]]: [null, r.visemes[d] === "PP" || r.visemes[d] === "FF" ? 0.9 : c, 0]
|
|
6046
6046
|
}
|
|
6047
6047
|
});
|
|
6048
6048
|
}
|
|
@@ -6151,7 +6151,7 @@ class Oe {
|
|
|
6151
6151
|
E.set(s, i, 0, "YXZ");
|
|
6152
6152
|
const l = new f.Quaternion().setFromEuler(E), u = new f.Quaternion().copy(l).multiply(G.clone().invert());
|
|
6153
6153
|
E.setFromQuaternion(u, "YXZ");
|
|
6154
|
-
let
|
|
6154
|
+
let r = E.x / (40 / 24) + 0.2, h = E.y / (9 / 4), a = Math.min(0.6, Math.max(-0.3, r)), 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,7 +6159,7 @@ class Oe {
|
|
|
6159
6159
|
name: "lookat",
|
|
6160
6160
|
dt: [750, t],
|
|
6161
6161
|
vs: {
|
|
6162
|
-
bodyRotateX: [
|
|
6162
|
+
bodyRotateX: [a + d],
|
|
6163
6163
|
bodyRotateY: [c + g],
|
|
6164
6164
|
eyesRotateX: [-3 * d + 0.1],
|
|
6165
6165
|
eyesRotateY: [-5 * g],
|
|
@@ -6185,13 +6185,13 @@ class Oe {
|
|
|
6185
6185
|
this.objectLeftEye.updateMatrixWorld(!0), this.objectRightEye.updateMatrixWorld(!0);
|
|
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
|
-
let u = (l.x + 1) / 2 * i.width + i.left,
|
|
6189
|
-
t === null && (t = u), e === null && (e =
|
|
6190
|
-
let h = E.x / (40 / 24),
|
|
6188
|
+
let u = (l.x + 1) / 2 * i.width + i.left, r = -(l.y - 1) / 2 * i.height + i.top;
|
|
6189
|
+
t === null && (t = u), e === null && (e = r), G.copy(this.armature.quaternion), G.multiply(this.poseTarget.props["Hips.quaternion"]), G.multiply(this.poseTarget.props["Spine.quaternion"]), G.multiply(this.poseTarget.props["Spine1.quaternion"]), G.multiply(this.poseTarget.props["Spine2.quaternion"]), G.multiply(this.poseTarget.props["Neck.quaternion"]), G.multiply(this.poseTarget.props["Head.quaternion"]), E.setFromQuaternion(G);
|
|
6190
|
+
let h = E.x / (40 / 24), a = E.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 - r, r), x = this.convertRange(e, [r - y, r + y], [-0.3, 0.6]) - h + c, I = this.convertRange(t, [u - g, u + g], [-0.8, 0.8]) - a + d;
|
|
6191
6191
|
x = Math.min(0.6, Math.max(-0.3, x)), I = Math.min(0.8, Math.max(-0.8, I));
|
|
6192
6192
|
let B = (Math.random() - 0.5) / 4, p = (Math.random() - 0.5) / 4;
|
|
6193
6193
|
if (n) {
|
|
6194
|
-
let H = this.animQueue.findIndex((
|
|
6194
|
+
let H = this.animQueue.findIndex((R) => R.template.name === "lookat");
|
|
6195
6195
|
H !== -1 && this.animQueue.splice(H, 1);
|
|
6196
6196
|
const z = {
|
|
6197
6197
|
name: "lookat",
|
|
@@ -6226,10 +6226,10 @@ class Oe {
|
|
|
6226
6226
|
s.setFromCamera(i, this.camera);
|
|
6227
6227
|
const o = s.intersectObject(this.armature);
|
|
6228
6228
|
if (o.length > 0) {
|
|
6229
|
-
const l = o[0].point, u = new f.Vector3(),
|
|
6230
|
-
this.objectLeftArm.getWorldPosition(u), this.objectRightArm.getWorldPosition(
|
|
6231
|
-
const h = u.distanceToSquared(l),
|
|
6232
|
-
h <
|
|
6229
|
+
const l = o[0].point, u = new f.Vector3(), r = new f.Vector3();
|
|
6230
|
+
this.objectLeftArm.getWorldPosition(u), this.objectRightArm.getWorldPosition(r);
|
|
6231
|
+
const h = u.distanceToSquared(l), a = r.distanceToSquared(l);
|
|
6232
|
+
h < a ? (this.ikSolve({
|
|
6233
6233
|
iterations: 20,
|
|
6234
6234
|
root: "LeftShoulder",
|
|
6235
6235
|
effector: "LeftHandMiddle1",
|
|
@@ -6372,16 +6372,16 @@ class Oe {
|
|
|
6372
6372
|
this.positionWasLocked = !o, o ? console.log("Position locking disabled for FBX animation:", t) : (this.lockAvatarPosition(), console.log("Position locked immediately before FBX animation:", t));
|
|
6373
6373
|
let l = this.animClips.find((u) => u.url === t + "-" + i);
|
|
6374
6374
|
if (l) {
|
|
6375
|
-
let u = this.animQueue.find((
|
|
6376
|
-
u && (u.ts[0] = 1 / 0), Object.entries(l.pose.props).forEach((
|
|
6377
|
-
this.poseBase.props[
|
|
6375
|
+
let u = this.animQueue.find((a) => a.template.name === "pose");
|
|
6376
|
+
u && (u.ts[0] = 1 / 0), Object.entries(l.pose.props).forEach((a) => {
|
|
6377
|
+
this.poseBase.props[a[0]] = a[1].clone(), this.poseTarget.props[a[0]] = a[1].clone(), this.poseTarget.props[a[0]].t = 0, this.poseTarget.props[a[0]].d = 1e3;
|
|
6378
6378
|
}), this.mixer ? console.log("Using existing mixer for FBX animation, preserving morph targets") : (this.mixer = new f.AnimationMixer(this.armature), console.log("Created new mixer for FBX animation")), this.mixer.addEventListener("finished", this.stopAnimation.bind(this), { once: !0 });
|
|
6379
|
-
const
|
|
6380
|
-
h.setLoop(f.LoopRepeat,
|
|
6379
|
+
const r = Math.ceil(n / l.clip.duration), h = this.mixer.clipAction(l.clip);
|
|
6380
|
+
h.setLoop(f.LoopRepeat, r), h.clampWhenFinished = !0, this.currentFBXAction = h;
|
|
6381
6381
|
try {
|
|
6382
6382
|
h.fadeIn(0.5).play(), console.log("FBX animation started successfully:", t);
|
|
6383
|
-
} catch (
|
|
6384
|
-
console.warn("FBX animation failed to start:",
|
|
6383
|
+
} catch (a) {
|
|
6384
|
+
console.warn("FBX animation failed to start:", a), this.stopAnimation();
|
|
6385
6385
|
return;
|
|
6386
6386
|
}
|
|
6387
6387
|
if (h.getClip().tracks.length === 0) {
|
|
@@ -6393,10 +6393,10 @@ class Oe {
|
|
|
6393
6393
|
console.error(`Invalid file type for FBX animation: ${t}. Expected .fbx file.`);
|
|
6394
6394
|
return;
|
|
6395
6395
|
}
|
|
6396
|
-
let
|
|
6396
|
+
let r = !1;
|
|
6397
6397
|
try {
|
|
6398
6398
|
const c = await fetch(t, { method: "HEAD" });
|
|
6399
|
-
if (
|
|
6399
|
+
if (r = c.ok, !r) {
|
|
6400
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
|
}
|
|
@@ -6404,9 +6404,9 @@ class Oe {
|
|
|
6404
6404
|
console.warn(`Could not verify file existence for ${t}, attempting to load anyway:`, c);
|
|
6405
6405
|
}
|
|
6406
6406
|
const h = new Me();
|
|
6407
|
-
let
|
|
6407
|
+
let a;
|
|
6408
6408
|
try {
|
|
6409
|
-
|
|
6409
|
+
a = await h.loadAsync(t, e);
|
|
6410
6410
|
} catch (c) {
|
|
6411
6411
|
console.error(`Failed to load FBX animation from ${t}:`, c), console.error("Error details:", {
|
|
6412
6412
|
message: c.message,
|
|
@@ -6426,8 +6426,8 @@ class Oe {
|
|
|
6426
6426
|
}
|
|
6427
6427
|
return;
|
|
6428
6428
|
}
|
|
6429
|
-
if (
|
|
6430
|
-
let c =
|
|
6429
|
+
if (a && a.animations && a.animations[i]) {
|
|
6430
|
+
let c = a.animations[i];
|
|
6431
6431
|
const d = {};
|
|
6432
6432
|
c.tracks.forEach((y) => {
|
|
6433
6433
|
y.name = y.name.replaceAll("mixamorig", "");
|
|
@@ -6446,7 +6446,7 @@ class Oe {
|
|
|
6446
6446
|
}), this.playAnimation(t, e, n, i, s);
|
|
6447
6447
|
} else {
|
|
6448
6448
|
const c = "Animation " + t + " (ndx=" + i + ") not found";
|
|
6449
|
-
console.error(c),
|
|
6449
|
+
console.error(c), a && a.animations ? console.error(`FBX file loaded but has ${a.animations.length} animation(s), requested index ${i}`) : console.error(a ? "FBX file loaded but contains no animations" : "FBX file failed to load or is invalid");
|
|
6450
6450
|
}
|
|
6451
6451
|
}
|
|
6452
6452
|
}
|
|
@@ -6482,21 +6482,21 @@ class Oe {
|
|
|
6482
6482
|
} else {
|
|
6483
6483
|
let u = await new Me().loadAsync(t, e);
|
|
6484
6484
|
if (u && u.animations && u.animations[i]) {
|
|
6485
|
-
let
|
|
6485
|
+
let r = u.animations[i];
|
|
6486
6486
|
const h = {};
|
|
6487
|
-
|
|
6487
|
+
r.tracks.forEach((c) => {
|
|
6488
6488
|
c.name = c.name.replaceAll("mixamorig", "");
|
|
6489
6489
|
const d = c.name.split(".");
|
|
6490
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
|
-
const
|
|
6493
|
-
h["Hips.position"] && (h["Hips.position"].y < 0.5 ?
|
|
6492
|
+
const a = { props: h };
|
|
6493
|
+
h["Hips.position"] && (h["Hips.position"].y < 0.5 ? a.lying = !0 : a.standing = !0), this.animPoses.push({
|
|
6494
6494
|
url: t + "-" + i,
|
|
6495
|
-
pose:
|
|
6495
|
+
pose: a
|
|
6496
6496
|
}), this.playPose(t, e, n, i, s);
|
|
6497
6497
|
} else {
|
|
6498
|
-
const
|
|
6499
|
-
console.error(
|
|
6498
|
+
const r = "Pose " + t + " (ndx=" + i + ") not found";
|
|
6499
|
+
console.error(r);
|
|
6500
6500
|
}
|
|
6501
6501
|
}
|
|
6502
6502
|
}
|
|
@@ -6521,8 +6521,8 @@ class Oe {
|
|
|
6521
6521
|
this.gestureTimeout && (clearTimeout(this.gestureTimeout), this.gestureTimeout = null);
|
|
6522
6522
|
let l = this.animQueue.findIndex((u) => u.template.name === "talkinghands");
|
|
6523
6523
|
l !== -1 && (this.animQueue[l].ts = this.animQueue[l].ts.map((u) => 0)), this.gesture = this.propsToThreeObjects(s), n && (this.gesture = this.mirrorPose(this.gesture)), t === "namaste" && this.avatar.body === "M" && (this.gesture["RightArm.quaternion"].rotateTowards(new f.Quaternion(0, 1, 0, 0), -0.25), this.gesture["LeftArm.quaternion"].rotateTowards(new f.Quaternion(0, 1, 0, 0), -0.25));
|
|
6524
|
-
for (let [u,
|
|
6525
|
-
|
|
6524
|
+
for (let [u, r] of Object.entries(this.gesture))
|
|
6525
|
+
r.t = this.animClock, r.d = i, this.poseTarget.props.hasOwnProperty(u) && (this.poseTarget.props[u].copy(r), this.poseTarget.props[u].t = this.animClock, this.poseTarget.props[u].d = i);
|
|
6526
6526
|
e && Number.isFinite(e) && (this.gestureTimeout = setTimeout(this.stopGesture.bind(this, i), 1e3 * e));
|
|
6527
6527
|
}
|
|
6528
6528
|
let o = this.animEmojis[t];
|
|
@@ -6568,7 +6568,7 @@ class Oe {
|
|
|
6568
6568
|
* @param {numeric} [d=null] If set, apply in d milliseconds
|
|
6569
6569
|
*/
|
|
6570
6570
|
ikSolve(t, e = null, n = !1, i = null) {
|
|
6571
|
-
const s = new f.Vector3(), o = new f.Vector3(), l = new f.Vector3(), u = new f.Vector3(),
|
|
6571
|
+
const s = new f.Vector3(), o = new f.Vector3(), l = new f.Vector3(), u = new f.Vector3(), r = new f.Quaternion(), h = new f.Vector3(), a = new f.Vector3(), c = new f.Vector3(), d = this.ikMesh.getObjectByName(t.root);
|
|
6572
6572
|
d.position.setFromMatrixPosition(this.armature.getObjectByName(t.root).matrixWorld), d.quaternion.setFromRotationMatrix(this.armature.getObjectByName(t.root).matrixWorld), e && n && 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) => {
|
|
@@ -6580,9 +6580,9 @@ class Oe {
|
|
|
6580
6580
|
let B = !1;
|
|
6581
6581
|
for (let p = 0, H = y.length; p < H; p++) {
|
|
6582
6582
|
const z = y[p].bone;
|
|
6583
|
-
z.matrixWorld.decompose(u,
|
|
6584
|
-
let
|
|
6585
|
-
|
|
6583
|
+
z.matrixWorld.decompose(u, r, h), r.invert(), o.setFromMatrixPosition(g.matrixWorld), l.subVectors(o, u), l.applyQuaternion(r), l.normalize(), s.subVectors(e, u), s.applyQuaternion(r), s.normalize();
|
|
6584
|
+
let R = s.dot(l);
|
|
6585
|
+
R > 1 ? R = 1 : R < -1 && (R = -1), R = Math.acos(R), !(R < 1e-5) && (y[p].minAngle !== void 0 && R < y[p].minAngle && (R = y[p].minAngle), y[p].maxAngle !== void 0 && R > y[p].maxAngle && (R = y[p].maxAngle), a.crossVectors(l, s), a.normalize(), G.setFromAxisAngle(a, R), z.quaternion.multiply(G), 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
|
|
@@ -6605,7 +6605,7 @@ class Oe {
|
|
|
6605
6605
|
this.isRunning = !1, this.stop(), this.stopSpeaking(), this.streamStop(), this.isAvatarOnly ? this.armature && (this.armature.parent && this.armature.parent.remove(this.armature), this.clearThree(this.armature)) : (this.clearThree(this.scene), this.resizeobserver.disconnect(), this.renderer && (this.renderer.dispose(), this.renderer.domElement && this.renderer.domElement.parentNode && this.renderer.domElement.parentNode.removeChild(this.renderer.domElement), this.renderer = null)), this.clearThree(this.ikMesh), this.dynamicbones.dispose();
|
|
6606
6606
|
}
|
|
6607
6607
|
}
|
|
6608
|
-
const
|
|
6608
|
+
const ve = {
|
|
6609
6609
|
apiKey: "sk_ace57ef3ef65a92b9d3bee2a00183b78ca790bc3e10964f2",
|
|
6610
6610
|
// Replace with your actual API key (should start with sk_)
|
|
6611
6611
|
endpoint: "https://api.elevenlabs.io/v1/text-to-speech",
|
|
@@ -6648,10 +6648,10 @@ const Re = {
|
|
|
6648
6648
|
function He() {
|
|
6649
6649
|
return {
|
|
6650
6650
|
service: "elevenlabs",
|
|
6651
|
-
endpoint:
|
|
6652
|
-
apiKey:
|
|
6653
|
-
defaultVoice:
|
|
6654
|
-
voices:
|
|
6651
|
+
endpoint: ve.endpoint,
|
|
6652
|
+
apiKey: ve.apiKey,
|
|
6653
|
+
defaultVoice: ve.defaultVoice,
|
|
6654
|
+
voices: ve.voices
|
|
6655
6655
|
};
|
|
6656
6656
|
}
|
|
6657
6657
|
function St() {
|
|
@@ -6673,9 +6673,9 @@ const Ne = ze(({
|
|
|
6673
6673
|
ttsApiKey: o = null,
|
|
6674
6674
|
bodyMovement: l = "idle",
|
|
6675
6675
|
movementIntensity: u = 0.5,
|
|
6676
|
-
showFullAvatar:
|
|
6676
|
+
showFullAvatar: r = !0,
|
|
6677
6677
|
cameraView: h = "upper",
|
|
6678
|
-
onReady:
|
|
6678
|
+
onReady: a = () => {
|
|
6679
6679
|
},
|
|
6680
6680
|
onLoading: c = () => {
|
|
6681
6681
|
},
|
|
@@ -6685,12 +6685,12 @@ const Ne = ze(({
|
|
|
6685
6685
|
style: y = {},
|
|
6686
6686
|
animations: x = {}
|
|
6687
6687
|
}, I) => {
|
|
6688
|
-
const B = N(null), p = N(null), H = N(
|
|
6689
|
-
|
|
6688
|
+
const B = N(null), p = N(null), H = N(r), z = N(null), R = N(null), T = N(!1), F = N({ remainingText: null, originalText: null, options: null }), J = N([]), ye = N(0), [S, W] = be(!0), [Y, Z] = be(null), [$, se] = be(!1), [de, me] = be(!1);
|
|
6689
|
+
Re(() => {
|
|
6690
6690
|
T.current = de;
|
|
6691
|
-
}, [de]),
|
|
6692
|
-
H.current =
|
|
6693
|
-
}, [
|
|
6691
|
+
}, [de]), Re(() => {
|
|
6692
|
+
H.current = r;
|
|
6693
|
+
}, [r]);
|
|
6694
6694
|
const ie = He(), fe = i || ie.service;
|
|
6695
6695
|
let X;
|
|
6696
6696
|
fe === "browser" ? X = {
|
|
@@ -6702,8 +6702,8 @@ const Ne = ze(({
|
|
|
6702
6702
|
service: "elevenlabs",
|
|
6703
6703
|
endpoint: "https://api.elevenlabs.io/v1/text-to-speech",
|
|
6704
6704
|
apiKey: o || ie.apiKey,
|
|
6705
|
-
defaultVoice: s || ie.defaultVoice ||
|
|
6706
|
-
voices: ie.voices ||
|
|
6705
|
+
defaultVoice: s || ie.defaultVoice || ve.defaultVoice,
|
|
6706
|
+
voices: ie.voices || ve.voices
|
|
6707
6707
|
} : fe === "deepgram" ? X = {
|
|
6708
6708
|
service: "deepgram",
|
|
6709
6709
|
endpoint: "https://api.deepgram.com/v1/speak",
|
|
@@ -6722,10 +6722,10 @@ const Ne = ze(({
|
|
|
6722
6722
|
ttsLang: fe === "browser" ? "en-US" : n,
|
|
6723
6723
|
ttsVoice: s || X.defaultVoice,
|
|
6724
6724
|
lipsyncLang: "en",
|
|
6725
|
-
showFullAvatar:
|
|
6725
|
+
showFullAvatar: r,
|
|
6726
6726
|
bodyMovement: l,
|
|
6727
6727
|
movementIntensity: u
|
|
6728
|
-
},
|
|
6728
|
+
}, v = {
|
|
6729
6729
|
ttsEndpoint: X.endpoint,
|
|
6730
6730
|
ttsApikey: X.apiKey,
|
|
6731
6731
|
ttsService: fe,
|
|
@@ -6734,7 +6734,7 @@ const Ne = ze(({
|
|
|
6734
6734
|
}, w = M(async () => {
|
|
6735
6735
|
if (!(!B.current || p.current))
|
|
6736
6736
|
try {
|
|
6737
|
-
if (W(!0), Z(null), p.current = new Oe(B.current,
|
|
6737
|
+
if (W(!0), Z(null), p.current = new Oe(B.current, v), p.current.controls && (p.current.controls.enableRotate = !1, p.current.controls.enableZoom = !1, p.current.controls.enablePan = !1, p.current.controls.enableDamping = !1), x && Object.keys(x).length > 0 && (p.current.customAnimations = x), await p.current.showAvatar(b, (V) => {
|
|
6738
6738
|
if (V.lengthComputable) {
|
|
6739
6739
|
const Q = Math.min(100, Math.round(V.loaded / V.total * 100));
|
|
6740
6740
|
c(Q);
|
|
@@ -6746,11 +6746,11 @@ const Ne = ze(({
|
|
|
6746
6746
|
Q();
|
|
6747
6747
|
}), p.current && p.current.setShowFullAvatar)
|
|
6748
6748
|
try {
|
|
6749
|
-
p.current.setShowFullAvatar(
|
|
6749
|
+
p.current.setShowFullAvatar(r);
|
|
6750
6750
|
} catch (V) {
|
|
6751
6751
|
console.warn("Error setting full body mode on initialization:", V);
|
|
6752
6752
|
}
|
|
6753
|
-
p.current && p.current.controls && (p.current.controls.enableRotate = !1, p.current.controls.enableZoom = !1, p.current.controls.enablePan = !1, p.current.controls.enableDamping = !1, p.current.controls.update()), W(!1), se(!0),
|
|
6753
|
+
p.current && p.current.controls && (p.current.controls.enableRotate = !1, p.current.controls.enableZoom = !1, p.current.controls.enablePan = !1, p.current.controls.enableDamping = !1, p.current.controls.update()), W(!1), se(!0), a(p.current);
|
|
6754
6754
|
const P = () => {
|
|
6755
6755
|
document.visibilityState === "visible" ? p.current?.start() : p.current?.stop();
|
|
6756
6756
|
};
|
|
@@ -6760,10 +6760,10 @@ const Ne = ze(({
|
|
|
6760
6760
|
} catch (L) {
|
|
6761
6761
|
console.error("Error initializing TalkingHead:", L), Z(L.message || "Failed to initialize avatar"), W(!1), d(L);
|
|
6762
6762
|
}
|
|
6763
|
-
}, [U, t, e, n, i, s, o,
|
|
6764
|
-
|
|
6763
|
+
}, [U, t, e, n, i, s, o, r, l, u, h]);
|
|
6764
|
+
Re(() => (w(), () => {
|
|
6765
6765
|
p.current && (p.current.stop(), p.current.dispose(), p.current = null);
|
|
6766
|
-
}), [w]),
|
|
6766
|
+
}), [w]), Re(() => {
|
|
6767
6767
|
if (!B.current || !p.current) return;
|
|
6768
6768
|
const L = new ResizeObserver((V) => {
|
|
6769
6769
|
for (const Q of V)
|
|
@@ -6787,7 +6787,7 @@ const Ne = ze(({
|
|
|
6787
6787
|
}, []), D = M(async (L, P = {}) => {
|
|
6788
6788
|
if (p.current && $)
|
|
6789
6789
|
try {
|
|
6790
|
-
|
|
6790
|
+
R.current && (clearInterval(R.current), R.current = null), z.current = { text: L, options: P }, F.current = { remainingText: null, originalText: null, options: null };
|
|
6791
6791
|
const V = /[!\.\?\n\p{Extended_Pictographic}]/ug, Q = L.split(V).map((O) => O.trim()).filter((O) => O.length > 0);
|
|
6792
6792
|
J.current = Q, ye.current = 0, me(!1), T.current = !1, await C();
|
|
6793
6793
|
const ae = {
|
|
@@ -6803,7 +6803,7 @@ const Ne = ze(({
|
|
|
6803
6803
|
if (Ie++, T.current)
|
|
6804
6804
|
return;
|
|
6805
6805
|
if (Ie > xe) {
|
|
6806
|
-
if (oe && (clearInterval(oe), oe = null,
|
|
6806
|
+
if (oe && (clearInterval(oe), oe = null, R.current = null), !ue && !T.current) {
|
|
6807
6807
|
ue = !0;
|
|
6808
6808
|
try {
|
|
6809
6809
|
P.onSpeechEnd();
|
|
@@ -6816,7 +6816,7 @@ const Ne = ze(({
|
|
|
6816
6816
|
const re = !O.speechQueue || O.speechQueue.length === 0, Le = !O.audioPlaylist || O.audioPlaylist.length === 0;
|
|
6817
6817
|
O && O.isSpeaking === !1 && re && Le && O.isAudioPlaying === !1 && !ue && !T.current && setTimeout(() => {
|
|
6818
6818
|
if (O && !T.current && O.isSpeaking === !1 && (!O.speechQueue || O.speechQueue.length === 0) && (!O.audioPlaylist || O.audioPlaylist.length === 0) && O.isAudioPlaying === !1 && !ue && !T.current) {
|
|
6819
|
-
ue = !0, oe && (clearInterval(oe), oe = null,
|
|
6819
|
+
ue = !0, oe && (clearInterval(oe), oe = null, R.current = null);
|
|
6820
6820
|
try {
|
|
6821
6821
|
P.onSpeechEnd();
|
|
6822
6822
|
} catch (Ze) {
|
|
@@ -6824,7 +6824,7 @@ const Ne = ze(({
|
|
|
6824
6824
|
}
|
|
6825
6825
|
}
|
|
6826
6826
|
}, 100);
|
|
6827
|
-
}, 100),
|
|
6827
|
+
}, 100), R.current = oe;
|
|
6828
6828
|
}
|
|
6829
6829
|
p.current.lipsync && Object.keys(p.current.lipsync).length > 0 ? (p.current.setSlowdownRate && p.current.setSlowdownRate(1.05), p.current.speakText(L, ae)) : setTimeout(async () => {
|
|
6830
6830
|
await C(), p.current && p.current.lipsync && (p.current.setSlowdownRate && p.current.setSlowdownRate(1.05), p.current.speakText(L, ae));
|
|
@@ -6838,7 +6838,7 @@ const Ne = ze(({
|
|
|
6838
6838
|
if (p.current && p.current.pauseSpeaking) {
|
|
6839
6839
|
const L = p.current;
|
|
6840
6840
|
if (L.isSpeaking || L.audioPlaylist && L.audioPlaylist.length > 0 || L.speechQueue && L.speechQueue.length > 0) {
|
|
6841
|
-
|
|
6841
|
+
R.current && (clearInterval(R.current), R.current = null);
|
|
6842
6842
|
let V = "";
|
|
6843
6843
|
if (z.current && J.current.length > 0) {
|
|
6844
6844
|
const Q = J.current.length, ae = L.speechQueue ? L.speechQueue.filter((xe) => xe && xe.text && Array.isArray(xe.text) && xe.text.length > 0).length : 0, O = L.audioPlaylist && L.audioPlaylist.length > 0, oe = ae + (O ? 1 : 0), Ie = Q - oe;
|
|
@@ -7052,7 +7052,7 @@ const pt = ze(({
|
|
|
7052
7052
|
style: s = {},
|
|
7053
7053
|
avatarConfig: o = {}
|
|
7054
7054
|
}, l) => {
|
|
7055
|
-
const u = N(null),
|
|
7055
|
+
const u = N(null), r = N(null), [h, a] = be(!0), [c, d] = be(null), [g, y] = be(!1), x = He(), I = o.ttsService || x.service, B = I === "browser" ? {
|
|
7056
7056
|
endpoint: "",
|
|
7057
7057
|
apiKey: null,
|
|
7058
7058
|
defaultVoice: "Google US English"
|
|
@@ -7083,76 +7083,76 @@ const pt = ze(({
|
|
|
7083
7083
|
lipsyncModules: ["en"],
|
|
7084
7084
|
cameraView: "upper"
|
|
7085
7085
|
}, z = M(async () => {
|
|
7086
|
-
if (!(!u.current ||
|
|
7086
|
+
if (!(!u.current || r.current))
|
|
7087
7087
|
try {
|
|
7088
|
-
if (
|
|
7088
|
+
if (a(!0), d(null), r.current = new Oe(u.current, H), await r.current.showAvatar(p, (Y) => {
|
|
7089
7089
|
if (Y.lengthComputable) {
|
|
7090
7090
|
const Z = Math.min(100, Math.round(Y.loaded / Y.total * 100));
|
|
7091
7091
|
t(Z);
|
|
7092
7092
|
}
|
|
7093
|
-
}),
|
|
7094
|
-
const Y =
|
|
7093
|
+
}), r.current.morphs && r.current.morphs.length > 0) {
|
|
7094
|
+
const Y = r.current.morphs[0].morphTargetDictionary;
|
|
7095
7095
|
console.log("Available morph targets:", Object.keys(Y));
|
|
7096
7096
|
const Z = Object.keys(Y).filter(($) => $.startsWith("viseme_"));
|
|
7097
7097
|
console.log("Viseme morph targets found:", Z), Z.length === 0 && (console.warn("No viseme morph targets found! Lip-sync will not work properly."), console.log("Expected viseme targets: viseme_aa, viseme_E, viseme_I, viseme_O, viseme_U, viseme_PP, viseme_SS, viseme_TH, viseme_DD, viseme_FF, viseme_kk, viseme_nn, viseme_RR, viseme_CH, viseme_sil"));
|
|
7098
7098
|
}
|
|
7099
7099
|
if (await new Promise((Y) => {
|
|
7100
7100
|
const Z = () => {
|
|
7101
|
-
|
|
7101
|
+
r.current.lipsync && Object.keys(r.current.lipsync).length > 0 ? (console.log("Lip-sync modules loaded:", Object.keys(r.current.lipsync)), Y()) : (console.log("Waiting for lip-sync modules to load..."), setTimeout(Z, 100));
|
|
7102
7102
|
};
|
|
7103
7103
|
Z();
|
|
7104
|
-
}),
|
|
7104
|
+
}), r.current && r.current.setShowFullAvatar)
|
|
7105
7105
|
try {
|
|
7106
|
-
|
|
7106
|
+
r.current.setShowFullAvatar(!0), console.log("Avatar initialized in full body mode");
|
|
7107
7107
|
} catch (Y) {
|
|
7108
7108
|
console.warn("Error setting full body mode on initialization:", Y);
|
|
7109
7109
|
}
|
|
7110
|
-
|
|
7110
|
+
a(!1), y(!0), n(r.current);
|
|
7111
7111
|
const W = () => {
|
|
7112
|
-
document.visibilityState === "visible" ?
|
|
7112
|
+
document.visibilityState === "visible" ? r.current?.start() : r.current?.stop();
|
|
7113
7113
|
};
|
|
7114
7114
|
return document.addEventListener("visibilitychange", W), () => {
|
|
7115
7115
|
document.removeEventListener("visibilitychange", W);
|
|
7116
7116
|
};
|
|
7117
7117
|
} catch (S) {
|
|
7118
|
-
console.error("Error initializing TalkingHead:", S), d(S.message || "Failed to initialize avatar"),
|
|
7118
|
+
console.error("Error initializing TalkingHead:", S), d(S.message || "Failed to initialize avatar"), a(!1), e(S);
|
|
7119
7119
|
}
|
|
7120
7120
|
}, []);
|
|
7121
|
-
|
|
7122
|
-
|
|
7121
|
+
Re(() => (z(), () => {
|
|
7122
|
+
r.current && (r.current.stop(), r.current.dispose(), r.current = null);
|
|
7123
7123
|
}), [z]);
|
|
7124
|
-
const
|
|
7125
|
-
if (
|
|
7124
|
+
const R = M((S) => {
|
|
7125
|
+
if (r.current && g)
|
|
7126
7126
|
try {
|
|
7127
|
-
console.log("Speaking text:", S), console.log("Avatar config:", p), console.log("TalkingHead instance:",
|
|
7128
|
-
|
|
7127
|
+
console.log("Speaking text:", S), console.log("Avatar config:", p), console.log("TalkingHead instance:", r.current), r.current.lipsync && Object.keys(r.current.lipsync).length > 0 ? (console.log("Lip-sync modules loaded:", Object.keys(r.current.lipsync)), r.current.setSlowdownRate && (r.current.setSlowdownRate(1.05), console.log("Applied timing adjustment for better lip-sync")), r.current.speakText(S)) : (console.warn("Lip-sync modules not ready, waiting..."), setTimeout(() => {
|
|
7128
|
+
r.current && r.current.lipsync ? (console.log("Lip-sync now ready, speaking..."), r.current.setSlowdownRate && (r.current.setSlowdownRate(1.05), console.log("Applied timing adjustment for better lip-sync")), r.current.speakText(S)) : console.error("Lip-sync still not ready after waiting");
|
|
7129
7129
|
}, 500));
|
|
7130
7130
|
} catch (W) {
|
|
7131
7131
|
console.error("Error speaking text:", W), d(W.message || "Failed to speak text");
|
|
7132
7132
|
}
|
|
7133
7133
|
else
|
|
7134
|
-
console.warn("Avatar not ready for speaking. isReady:", g, "talkingHeadRef:", !!
|
|
7134
|
+
console.warn("Avatar not ready for speaking. isReady:", g, "talkingHeadRef:", !!r.current);
|
|
7135
7135
|
}, [g, p]), T = M(() => {
|
|
7136
|
-
|
|
7136
|
+
r.current && (r.current.stopSpeaking(), r.current.setSlowdownRate && (r.current.setSlowdownRate(1), console.log("Reset timing to normal")));
|
|
7137
7137
|
}, []), F = M((S) => {
|
|
7138
|
-
|
|
7138
|
+
r.current && r.current.setMood(S);
|
|
7139
7139
|
}, []), J = M((S) => {
|
|
7140
|
-
|
|
7140
|
+
r.current && r.current.setSlowdownRate && (r.current.setSlowdownRate(S), console.log("Timing adjustment set to:", S));
|
|
7141
7141
|
}, []), ye = M((S, W = !1) => {
|
|
7142
|
-
if (
|
|
7143
|
-
if (
|
|
7142
|
+
if (r.current && r.current.playAnimation) {
|
|
7143
|
+
if (r.current.setShowFullAvatar)
|
|
7144
7144
|
try {
|
|
7145
|
-
|
|
7145
|
+
r.current.setShowFullAvatar(!0);
|
|
7146
7146
|
} catch (Z) {
|
|
7147
7147
|
console.warn("Error setting full body mode:", Z);
|
|
7148
7148
|
}
|
|
7149
7149
|
if (S.includes("."))
|
|
7150
7150
|
try {
|
|
7151
|
-
|
|
7151
|
+
r.current.playAnimation(S, null, 10, 0, 0.01, W), console.log("Playing animation:", S);
|
|
7152
7152
|
} catch (Z) {
|
|
7153
7153
|
console.log(`Failed to play ${S}:`, Z);
|
|
7154
7154
|
try {
|
|
7155
|
-
|
|
7155
|
+
r.current.setBodyMovement("idle"), console.log("Fallback to idle animation");
|
|
7156
7156
|
} catch ($) {
|
|
7157
7157
|
console.warn("Fallback animation also failed:", $);
|
|
7158
7158
|
}
|
|
@@ -7162,7 +7162,7 @@ const pt = ze(({
|
|
|
7162
7162
|
let $ = !1;
|
|
7163
7163
|
for (const se of Z)
|
|
7164
7164
|
try {
|
|
7165
|
-
|
|
7165
|
+
r.current.playAnimation(S + se, null, 10, 0, 0.01, W), console.log("Playing animation:", S + se), $ = !0;
|
|
7166
7166
|
break;
|
|
7167
7167
|
} catch {
|
|
7168
7168
|
console.log(`Failed to play ${S}${se}, trying next format...`);
|
|
@@ -7170,7 +7170,7 @@ const pt = ze(({
|
|
|
7170
7170
|
if (!$) {
|
|
7171
7171
|
console.warn("Animation system not available or animation not found:", S);
|
|
7172
7172
|
try {
|
|
7173
|
-
|
|
7173
|
+
r.current.setBodyMovement("idle"), console.log("Fallback to idle animation");
|
|
7174
7174
|
} catch (se) {
|
|
7175
7175
|
console.warn("Fallback animation also failed:", se);
|
|
7176
7176
|
}
|
|
@@ -7180,66 +7180,66 @@ const pt = ze(({
|
|
|
7180
7180
|
console.warn("Animation system not available or animation not found:", S);
|
|
7181
7181
|
}, []);
|
|
7182
7182
|
return Ce(l, () => ({
|
|
7183
|
-
speakText:
|
|
7183
|
+
speakText: R,
|
|
7184
7184
|
stopSpeaking: T,
|
|
7185
7185
|
setMood: F,
|
|
7186
7186
|
setTimingAdjustment: J,
|
|
7187
7187
|
playAnimation: ye,
|
|
7188
7188
|
isReady: g,
|
|
7189
|
-
talkingHead:
|
|
7189
|
+
talkingHead: r.current,
|
|
7190
7190
|
setBodyMovement: (S) => {
|
|
7191
|
-
if (
|
|
7191
|
+
if (r.current && r.current.setShowFullAvatar && r.current.setBodyMovement)
|
|
7192
7192
|
try {
|
|
7193
|
-
|
|
7193
|
+
r.current.setShowFullAvatar(!0), r.current.setBodyMovement(S), console.log("Body movement set with full body mode:", S);
|
|
7194
7194
|
} catch (W) {
|
|
7195
7195
|
console.warn("Error setting body movement:", W);
|
|
7196
7196
|
}
|
|
7197
7197
|
},
|
|
7198
|
-
setMovementIntensity: (S) =>
|
|
7198
|
+
setMovementIntensity: (S) => r.current?.setMovementIntensity(S),
|
|
7199
7199
|
playRandomDance: () => {
|
|
7200
|
-
if (
|
|
7200
|
+
if (r.current && r.current.setShowFullAvatar && r.current.playRandomDance)
|
|
7201
7201
|
try {
|
|
7202
|
-
|
|
7202
|
+
r.current.setShowFullAvatar(!0), r.current.playRandomDance(), console.log("Random dance played with full body mode");
|
|
7203
7203
|
} catch (S) {
|
|
7204
7204
|
console.warn("Error playing random dance:", S);
|
|
7205
7205
|
}
|
|
7206
7206
|
},
|
|
7207
7207
|
playReaction: (S) => {
|
|
7208
|
-
if (
|
|
7208
|
+
if (r.current && r.current.setShowFullAvatar && r.current.playReaction)
|
|
7209
7209
|
try {
|
|
7210
|
-
|
|
7210
|
+
r.current.setShowFullAvatar(!0), r.current.playReaction(S), console.log("Reaction played with full body mode:", S);
|
|
7211
7211
|
} catch (W) {
|
|
7212
7212
|
console.warn("Error playing reaction:", W);
|
|
7213
7213
|
}
|
|
7214
7214
|
},
|
|
7215
7215
|
playCelebration: () => {
|
|
7216
|
-
if (
|
|
7216
|
+
if (r.current && r.current.setShowFullAvatar && r.current.playCelebration)
|
|
7217
7217
|
try {
|
|
7218
|
-
|
|
7218
|
+
r.current.setShowFullAvatar(!0), r.current.playCelebration(), console.log("Celebration played with full body mode");
|
|
7219
7219
|
} catch (S) {
|
|
7220
7220
|
console.warn("Error playing celebration:", S);
|
|
7221
7221
|
}
|
|
7222
7222
|
},
|
|
7223
7223
|
setShowFullAvatar: (S) => {
|
|
7224
|
-
if (
|
|
7224
|
+
if (r.current && r.current.setShowFullAvatar)
|
|
7225
7225
|
try {
|
|
7226
|
-
|
|
7226
|
+
r.current.setShowFullAvatar(S), console.log("Show full avatar set to:", S);
|
|
7227
7227
|
} catch (W) {
|
|
7228
7228
|
console.warn("Error setting showFullAvatar:", W);
|
|
7229
7229
|
}
|
|
7230
7230
|
},
|
|
7231
7231
|
lockAvatarPosition: () => {
|
|
7232
|
-
if (
|
|
7232
|
+
if (r.current && r.current.lockAvatarPosition)
|
|
7233
7233
|
try {
|
|
7234
|
-
|
|
7234
|
+
r.current.lockAvatarPosition();
|
|
7235
7235
|
} catch (S) {
|
|
7236
7236
|
console.warn("Error locking avatar position:", S);
|
|
7237
7237
|
}
|
|
7238
7238
|
},
|
|
7239
7239
|
unlockAvatarPosition: () => {
|
|
7240
|
-
if (
|
|
7240
|
+
if (r.current && r.current.unlockAvatarPosition)
|
|
7241
7241
|
try {
|
|
7242
|
-
|
|
7242
|
+
r.current.unlockAvatarPosition();
|
|
7243
7243
|
} catch (S) {
|
|
7244
7244
|
console.warn("Error unlocking avatar position:", S);
|
|
7245
7245
|
}
|
|
@@ -7296,8 +7296,8 @@ const gt = ze(({
|
|
|
7296
7296
|
onCustomAction: l = () => {
|
|
7297
7297
|
},
|
|
7298
7298
|
autoStart: u = !1
|
|
7299
|
-
},
|
|
7300
|
-
const h = N(null),
|
|
7299
|
+
}, r) => {
|
|
7300
|
+
const h = N(null), a = N({
|
|
7301
7301
|
currentModuleIndex: 0,
|
|
7302
7302
|
currentLessonIndex: 0,
|
|
7303
7303
|
currentQuestionIndex: 0,
|
|
@@ -7332,7 +7332,7 @@ const gt = ze(({
|
|
|
7332
7332
|
animations: e,
|
|
7333
7333
|
lipsyncLang: "en"
|
|
7334
7334
|
});
|
|
7335
|
-
|
|
7335
|
+
Re(() => {
|
|
7336
7336
|
c.current = {
|
|
7337
7337
|
onLessonStart: n,
|
|
7338
7338
|
onLessonComplete: i,
|
|
@@ -7340,7 +7340,7 @@ const gt = ze(({
|
|
|
7340
7340
|
onCurriculumComplete: o,
|
|
7341
7341
|
onCustomAction: l
|
|
7342
7342
|
};
|
|
7343
|
-
}, [n, i, s, o, l]),
|
|
7343
|
+
}, [n, i, s, o, l]), Re(() => {
|
|
7344
7344
|
H.current = U?.curriculum || {
|
|
7345
7345
|
title: "Default Curriculum",
|
|
7346
7346
|
description: "No curriculum data provided",
|
|
@@ -7361,22 +7361,22 @@ const gt = ze(({
|
|
|
7361
7361
|
lipsyncLang: "en"
|
|
7362
7362
|
};
|
|
7363
7363
|
}, [U, t, e]);
|
|
7364
|
-
const
|
|
7365
|
-
|
|
7366
|
-
const b =
|
|
7367
|
-
let
|
|
7368
|
-
if (
|
|
7369
|
-
moduleIndex:
|
|
7370
|
-
lessonIndex:
|
|
7371
|
-
score:
|
|
7372
|
-
totalQuestions:
|
|
7364
|
+
const R = M(() => (H.current || { modules: [] }).modules[a.current.currentModuleIndex]?.lessons[a.current.currentLessonIndex], []), T = M(() => R()?.questions[a.current.currentQuestionIndex], [R]), F = M((b, v) => v.type === "multiple_choice" || v.type === "true_false" ? b === v.answer : v.type === "code_test" && typeof b == "object" && b !== null ? b.passed === !0 : !1, []), J = M(() => {
|
|
7365
|
+
a.current.lessonCompleted = !0, a.current.isQuestionMode = !1;
|
|
7366
|
+
const b = a.current.totalQuestions > 0 ? Math.round(a.current.score / a.current.totalQuestions * 100) : 100;
|
|
7367
|
+
let v = "Congratulations! You've completed this lesson";
|
|
7368
|
+
if (a.current.totalQuestions > 0 ? v += ` You got ${a.current.score} correct out of ${a.current.totalQuestions} question${a.current.totalQuestions === 1 ? "" : "s"}, achieving a score of ${b} percent. ` : v += "! ", b >= 80 ? v += "Excellent work! You have a great understanding of this topic." : b >= 60 ? v += "Good job! You understand most of the concepts." : v += "Keep practicing! You're making progress.", c.current.onLessonComplete({
|
|
7369
|
+
moduleIndex: a.current.currentModuleIndex,
|
|
7370
|
+
lessonIndex: a.current.currentLessonIndex,
|
|
7371
|
+
score: a.current.score,
|
|
7372
|
+
totalQuestions: a.current.totalQuestions,
|
|
7373
7373
|
percentage: b
|
|
7374
7374
|
}), c.current.onCustomAction({
|
|
7375
7375
|
type: "lessonComplete",
|
|
7376
|
-
moduleIndex:
|
|
7377
|
-
lessonIndex:
|
|
7378
|
-
score:
|
|
7379
|
-
totalQuestions:
|
|
7376
|
+
moduleIndex: a.current.currentModuleIndex,
|
|
7377
|
+
lessonIndex: a.current.currentLessonIndex,
|
|
7378
|
+
score: a.current.score,
|
|
7379
|
+
totalQuestions: a.current.totalQuestions,
|
|
7380
7380
|
percentage: b
|
|
7381
7381
|
}), h.current) {
|
|
7382
7382
|
if (h.current.setMood("happy"), e.lessonComplete)
|
|
@@ -7385,16 +7385,16 @@ const gt = ze(({
|
|
|
7385
7385
|
} catch {
|
|
7386
7386
|
h.current.playCelebration();
|
|
7387
7387
|
}
|
|
7388
|
-
const w = H.current || { modules: [] }, C = w.modules[
|
|
7389
|
-
h.current.speakText(
|
|
7388
|
+
const w = H.current || { modules: [] }, C = w.modules[a.current.currentModuleIndex], D = a.current.currentLessonIndex < (C?.lessons?.length || 0) - 1, te = a.current.currentModuleIndex < (w.modules?.length || 0) - 1, q = D || te, j = z.current || { lipsyncLang: "en" };
|
|
7389
|
+
h.current.speakText(v, {
|
|
7390
7390
|
lipsyncLang: j.lipsyncLang,
|
|
7391
7391
|
onSpeechEnd: () => {
|
|
7392
7392
|
c.current.onCustomAction({
|
|
7393
7393
|
type: "lessonCompleteFeedbackDone",
|
|
7394
|
-
moduleIndex:
|
|
7395
|
-
lessonIndex:
|
|
7396
|
-
score:
|
|
7397
|
-
totalQuestions:
|
|
7394
|
+
moduleIndex: a.current.currentModuleIndex,
|
|
7395
|
+
lessonIndex: a.current.currentLessonIndex,
|
|
7396
|
+
score: a.current.score,
|
|
7397
|
+
totalQuestions: a.current.totalQuestions,
|
|
7398
7398
|
percentage: b,
|
|
7399
7399
|
hasNextLesson: q
|
|
7400
7400
|
});
|
|
@@ -7402,11 +7402,11 @@ const gt = ze(({
|
|
|
7402
7402
|
});
|
|
7403
7403
|
}
|
|
7404
7404
|
}, [e.lessonComplete]), ye = M(() => {
|
|
7405
|
-
|
|
7405
|
+
a.current.curriculumCompleted = !0;
|
|
7406
7406
|
const b = H.current || { modules: [] };
|
|
7407
7407
|
if (c.current.onCurriculumComplete({
|
|
7408
7408
|
modules: b.modules.length,
|
|
7409
|
-
totalLessons: b.modules.reduce((
|
|
7409
|
+
totalLessons: b.modules.reduce((v, w) => v + w.lessons.length, 0)
|
|
7410
7410
|
}), h.current) {
|
|
7411
7411
|
if (h.current.setMood("celebrating"), e.curriculumComplete)
|
|
7412
7412
|
try {
|
|
@@ -7414,24 +7414,24 @@ const gt = ze(({
|
|
|
7414
7414
|
} catch {
|
|
7415
7415
|
h.current.playCelebration();
|
|
7416
7416
|
}
|
|
7417
|
-
const
|
|
7418
|
-
h.current.speakText("Amazing! You've completed the entire curriculum! You're now ready to move on to more advanced topics. Well done!", { lipsyncLang:
|
|
7417
|
+
const v = z.current || { lipsyncLang: "en" };
|
|
7418
|
+
h.current.speakText("Amazing! You've completed the entire curriculum! You're now ready to move on to more advanced topics. Well done!", { lipsyncLang: v.lipsyncLang });
|
|
7419
7419
|
}
|
|
7420
7420
|
}, [e.curriculumComplete]), S = M(() => {
|
|
7421
|
-
const b =
|
|
7422
|
-
|
|
7423
|
-
const
|
|
7424
|
-
|
|
7421
|
+
const b = R();
|
|
7422
|
+
a.current.isQuestionMode = !0, a.current.currentQuestionIndex = 0, a.current.totalQuestions = b?.questions?.length || 0, a.current.score = 0;
|
|
7423
|
+
const v = T();
|
|
7424
|
+
v && c.current.onCustomAction({
|
|
7425
7425
|
type: "questionStart",
|
|
7426
|
-
moduleIndex:
|
|
7427
|
-
lessonIndex:
|
|
7428
|
-
questionIndex:
|
|
7429
|
-
totalQuestions:
|
|
7430
|
-
question:
|
|
7431
|
-
score:
|
|
7426
|
+
moduleIndex: a.current.currentModuleIndex,
|
|
7427
|
+
lessonIndex: a.current.currentLessonIndex,
|
|
7428
|
+
questionIndex: a.current.currentQuestionIndex,
|
|
7429
|
+
totalQuestions: a.current.totalQuestions,
|
|
7430
|
+
question: v,
|
|
7431
|
+
score: a.current.score
|
|
7432
7432
|
});
|
|
7433
7433
|
const w = () => {
|
|
7434
|
-
if (!h.current || !
|
|
7434
|
+
if (!h.current || !v) return;
|
|
7435
7435
|
if (h.current.setMood("happy"), e.questionStart)
|
|
7436
7436
|
try {
|
|
7437
7437
|
h.current.playAnimation(e.questionStart, !0);
|
|
@@ -7439,69 +7439,69 @@ const gt = ze(({
|
|
|
7439
7439
|
console.warn("Failed to play questionStart animation:", D);
|
|
7440
7440
|
}
|
|
7441
7441
|
const C = z.current || { lipsyncLang: "en" };
|
|
7442
|
-
|
|
7442
|
+
v.type === "code_test" ? h.current.speakText(`Let's test your coding skills! Here's your first challenge: ${v.question}`, { lipsyncLang: C.lipsyncLang }) : v.type === "multiple_choice" ? h.current.speakText(`Now let me ask you some questions. Here's the first one: ${v.question}`, { lipsyncLang: C.lipsyncLang }) : v.type === "true_false" ? h.current.speakText(`Let's start with some true or false questions. First question: ${v.question}`, { lipsyncLang: C.lipsyncLang }) : h.current.speakText(`Now let me ask you some questions. Here's the first one: ${v.question}`, { lipsyncLang: C.lipsyncLang });
|
|
7443
7443
|
};
|
|
7444
|
-
if (h.current && h.current.isReady &&
|
|
7444
|
+
if (h.current && h.current.isReady && v)
|
|
7445
7445
|
w();
|
|
7446
7446
|
else if (h.current && h.current.isReady) {
|
|
7447
7447
|
const C = z.current || { lipsyncLang: "en" };
|
|
7448
7448
|
h.current.speakText("Now let me ask you some questions to test your understanding.", { lipsyncLang: C.lipsyncLang });
|
|
7449
7449
|
} else {
|
|
7450
7450
|
const C = setInterval(() => {
|
|
7451
|
-
h.current && h.current.isReady && (clearInterval(C),
|
|
7451
|
+
h.current && h.current.isReady && (clearInterval(C), v && w());
|
|
7452
7452
|
}, 100);
|
|
7453
7453
|
setTimeout(() => {
|
|
7454
7454
|
clearInterval(C);
|
|
7455
7455
|
}, 5e3);
|
|
7456
7456
|
}
|
|
7457
|
-
}, [e.questionStart,
|
|
7458
|
-
const b =
|
|
7459
|
-
if (
|
|
7460
|
-
h.current && h.current.stopSpeaking && h.current.stopSpeaking(),
|
|
7461
|
-
const
|
|
7462
|
-
|
|
7457
|
+
}, [e.questionStart, R, T]), W = M(() => {
|
|
7458
|
+
const b = R();
|
|
7459
|
+
if (a.current.currentQuestionIndex < (b?.questions?.length || 0) - 1) {
|
|
7460
|
+
h.current && h.current.stopSpeaking && h.current.stopSpeaking(), a.current.currentQuestionIndex += 1;
|
|
7461
|
+
const v = T();
|
|
7462
|
+
v && c.current.onCustomAction({
|
|
7463
7463
|
type: "nextQuestion",
|
|
7464
|
-
moduleIndex:
|
|
7465
|
-
lessonIndex:
|
|
7466
|
-
questionIndex:
|
|
7467
|
-
totalQuestions:
|
|
7468
|
-
question:
|
|
7469
|
-
score:
|
|
7464
|
+
moduleIndex: a.current.currentModuleIndex,
|
|
7465
|
+
lessonIndex: a.current.currentLessonIndex,
|
|
7466
|
+
questionIndex: a.current.currentQuestionIndex,
|
|
7467
|
+
totalQuestions: a.current.totalQuestions,
|
|
7468
|
+
question: v,
|
|
7469
|
+
score: a.current.score
|
|
7470
7470
|
});
|
|
7471
7471
|
const w = () => {
|
|
7472
|
-
if (!h.current || !
|
|
7472
|
+
if (!h.current || !v) return;
|
|
7473
7473
|
if (h.current.setMood("happy"), h.current.setBodyMovement("idle"), e.nextQuestion)
|
|
7474
7474
|
try {
|
|
7475
7475
|
h.current.playAnimation(e.nextQuestion, !0);
|
|
7476
7476
|
} catch (j) {
|
|
7477
7477
|
console.warn("Failed to play nextQuestion animation:", j);
|
|
7478
7478
|
}
|
|
7479
|
-
const C = z.current || { lipsyncLang: "en" }, te =
|
|
7480
|
-
if (
|
|
7481
|
-
const j = q ? `Great! Here's your final coding challenge: ${
|
|
7479
|
+
const C = z.current || { lipsyncLang: "en" }, te = R()?.questions?.length || 0, q = a.current.currentQuestionIndex >= te - 1;
|
|
7480
|
+
if (v.type === "code_test") {
|
|
7481
|
+
const j = q ? `Great! Here's your final coding challenge: ${v.question}` : `Great! Now let's move on to your next coding challenge: ${v.question}`;
|
|
7482
7482
|
h.current.speakText(j, {
|
|
7483
7483
|
lipsyncLang: C.lipsyncLang
|
|
7484
7484
|
});
|
|
7485
|
-
} else if (
|
|
7486
|
-
const j = q ? `Alright! Here's your final question: ${
|
|
7485
|
+
} else if (v.type === "multiple_choice") {
|
|
7486
|
+
const j = q ? `Alright! Here's your final question: ${v.question}` : `Alright! Here's your next question: ${v.question}`;
|
|
7487
7487
|
h.current.speakText(j, {
|
|
7488
7488
|
lipsyncLang: C.lipsyncLang
|
|
7489
7489
|
});
|
|
7490
|
-
} else if (
|
|
7491
|
-
const j = q ? `Now let's try this final one: ${
|
|
7490
|
+
} else if (v.type === "true_false") {
|
|
7491
|
+
const j = q ? `Now let's try this final one: ${v.question}` : `Now let's try this one: ${v.question}`;
|
|
7492
7492
|
h.current.speakText(j, {
|
|
7493
7493
|
lipsyncLang: C.lipsyncLang
|
|
7494
7494
|
});
|
|
7495
7495
|
} else {
|
|
7496
|
-
const j = q ? `Here's your final question: ${
|
|
7496
|
+
const j = q ? `Here's your final question: ${v.question}` : `Here's the next question: ${v.question}`;
|
|
7497
7497
|
h.current.speakText(j, {
|
|
7498
7498
|
lipsyncLang: C.lipsyncLang
|
|
7499
7499
|
});
|
|
7500
7500
|
}
|
|
7501
7501
|
};
|
|
7502
|
-
if (h.current && h.current.isReady &&
|
|
7502
|
+
if (h.current && h.current.isReady && v)
|
|
7503
7503
|
w();
|
|
7504
|
-
else if (
|
|
7504
|
+
else if (v) {
|
|
7505
7505
|
const C = setInterval(() => {
|
|
7506
7506
|
h.current && h.current.isReady && (clearInterval(C), w());
|
|
7507
7507
|
}, 100);
|
|
@@ -7512,51 +7512,51 @@ const gt = ze(({
|
|
|
7512
7512
|
} else
|
|
7513
7513
|
c.current.onCustomAction({
|
|
7514
7514
|
type: "allQuestionsComplete",
|
|
7515
|
-
moduleIndex:
|
|
7516
|
-
lessonIndex:
|
|
7517
|
-
totalQuestions:
|
|
7518
|
-
score:
|
|
7515
|
+
moduleIndex: a.current.currentModuleIndex,
|
|
7516
|
+
lessonIndex: a.current.currentLessonIndex,
|
|
7517
|
+
totalQuestions: a.current.totalQuestions,
|
|
7518
|
+
score: a.current.score
|
|
7519
7519
|
});
|
|
7520
|
-
}, [e.nextQuestion,
|
|
7521
|
-
const b = H.current || { modules: [] },
|
|
7522
|
-
if (
|
|
7523
|
-
|
|
7524
|
-
const C = b.modules[
|
|
7520
|
+
}, [e.nextQuestion, R, T]), Y = M(() => {
|
|
7521
|
+
const b = H.current || { modules: [] }, v = b.modules[a.current.currentModuleIndex];
|
|
7522
|
+
if (a.current.currentLessonIndex < (v?.lessons?.length || 0) - 1) {
|
|
7523
|
+
a.current.currentLessonIndex += 1, a.current.currentQuestionIndex = 0, a.current.lessonCompleted = !1, a.current.isQuestionMode = !1, a.current.isTeaching = !1, a.current.score = 0, a.current.totalQuestions = 0;
|
|
7524
|
+
const C = b.modules[a.current.currentModuleIndex], D = a.current.currentLessonIndex < (C?.lessons?.length || 0) - 1, te = a.current.currentModuleIndex < (b.modules?.length || 0) - 1, q = D || te;
|
|
7525
7525
|
c.current.onCustomAction({
|
|
7526
7526
|
type: "lessonStart",
|
|
7527
|
-
moduleIndex:
|
|
7528
|
-
lessonIndex:
|
|
7527
|
+
moduleIndex: a.current.currentModuleIndex,
|
|
7528
|
+
lessonIndex: a.current.currentLessonIndex,
|
|
7529
7529
|
hasNextLesson: q
|
|
7530
7530
|
}), c.current.onLessonStart({
|
|
7531
|
-
moduleIndex:
|
|
7532
|
-
lessonIndex:
|
|
7533
|
-
lesson:
|
|
7531
|
+
moduleIndex: a.current.currentModuleIndex,
|
|
7532
|
+
lessonIndex: a.current.currentLessonIndex,
|
|
7533
|
+
lesson: R()
|
|
7534
7534
|
}), h.current && (h.current.setMood("happy"), h.current.setBodyMovement("idle"));
|
|
7535
|
-
} else if (
|
|
7536
|
-
|
|
7537
|
-
const D = b.modules[
|
|
7535
|
+
} else if (a.current.currentModuleIndex < (b.modules?.length || 0) - 1) {
|
|
7536
|
+
a.current.currentModuleIndex += 1, a.current.currentLessonIndex = 0, a.current.currentQuestionIndex = 0, a.current.lessonCompleted = !1, a.current.isQuestionMode = !1, a.current.isTeaching = !1, a.current.score = 0, a.current.totalQuestions = 0;
|
|
7537
|
+
const D = b.modules[a.current.currentModuleIndex], te = a.current.currentLessonIndex < (D?.lessons?.length || 0) - 1, q = a.current.currentModuleIndex < (b.modules?.length || 0) - 1, j = te || q;
|
|
7538
7538
|
c.current.onCustomAction({
|
|
7539
7539
|
type: "lessonStart",
|
|
7540
|
-
moduleIndex:
|
|
7541
|
-
lessonIndex:
|
|
7540
|
+
moduleIndex: a.current.currentModuleIndex,
|
|
7541
|
+
lessonIndex: a.current.currentLessonIndex,
|
|
7542
7542
|
hasNextLesson: j
|
|
7543
7543
|
}), c.current.onLessonStart({
|
|
7544
|
-
moduleIndex:
|
|
7545
|
-
lessonIndex:
|
|
7546
|
-
lesson:
|
|
7544
|
+
moduleIndex: a.current.currentModuleIndex,
|
|
7545
|
+
lessonIndex: a.current.currentLessonIndex,
|
|
7546
|
+
lesson: R()
|
|
7547
7547
|
}), h.current && (h.current.setMood("happy"), h.current.setBodyMovement("idle"));
|
|
7548
7548
|
} else
|
|
7549
7549
|
I.current && I.current();
|
|
7550
7550
|
}, []), Z = M(() => {
|
|
7551
|
-
const b =
|
|
7552
|
-
let
|
|
7551
|
+
const b = R();
|
|
7552
|
+
let v = null;
|
|
7553
7553
|
if (b?.avatar_script && b?.body) {
|
|
7554
7554
|
const w = b.avatar_script.trim(), C = b.body.trim(), D = w.match(/[.!?]$/) ? " " : ". ";
|
|
7555
|
-
|
|
7555
|
+
v = `${w}${D}${C}`;
|
|
7556
7556
|
} else
|
|
7557
|
-
|
|
7558
|
-
if (h.current && h.current.isReady &&
|
|
7559
|
-
|
|
7557
|
+
v = b?.avatar_script || b?.body || null;
|
|
7558
|
+
if (h.current && h.current.isReady && v) {
|
|
7559
|
+
a.current.isTeaching = !0, a.current.isQuestionMode = !1, a.current.score = 0, a.current.totalQuestions = 0, h.current.setMood("happy");
|
|
7560
7560
|
let w = !1;
|
|
7561
7561
|
if (e.teaching)
|
|
7562
7562
|
try {
|
|
@@ -7567,36 +7567,42 @@ const gt = ze(({
|
|
|
7567
7567
|
w || h.current.setBodyMovement("gesturing");
|
|
7568
7568
|
const C = z.current || { lipsyncLang: "en" };
|
|
7569
7569
|
c.current.onLessonStart({
|
|
7570
|
-
moduleIndex:
|
|
7571
|
-
lessonIndex:
|
|
7570
|
+
moduleIndex: a.current.currentModuleIndex,
|
|
7571
|
+
lessonIndex: a.current.currentLessonIndex,
|
|
7572
7572
|
lesson: b
|
|
7573
7573
|
}), c.current.onCustomAction({
|
|
7574
7574
|
type: "teachingStart",
|
|
7575
|
-
moduleIndex:
|
|
7576
|
-
lessonIndex:
|
|
7575
|
+
moduleIndex: a.current.currentModuleIndex,
|
|
7576
|
+
lessonIndex: a.current.currentLessonIndex,
|
|
7577
7577
|
lesson: b
|
|
7578
|
-
}), h.current.speakText(
|
|
7578
|
+
}), h.current.speakText(v, {
|
|
7579
7579
|
lipsyncLang: C.lipsyncLang,
|
|
7580
7580
|
onSpeechEnd: () => {
|
|
7581
|
-
|
|
7581
|
+
a.current.isTeaching = !1, c.current.onCustomAction({
|
|
7582
7582
|
type: "teachingComplete",
|
|
7583
|
-
moduleIndex:
|
|
7584
|
-
lessonIndex:
|
|
7583
|
+
moduleIndex: a.current.currentModuleIndex,
|
|
7584
|
+
lessonIndex: a.current.currentLessonIndex,
|
|
7585
7585
|
lesson: b,
|
|
7586
7586
|
hasQuestions: b.questions && b.questions.length > 0
|
|
7587
|
+
}), b?.code_example && c.current.onCustomAction({
|
|
7588
|
+
type: "codeExampleReady",
|
|
7589
|
+
moduleIndex: a.current.currentModuleIndex,
|
|
7590
|
+
lessonIndex: a.current.currentLessonIndex,
|
|
7591
|
+
lesson: b,
|
|
7592
|
+
codeExample: b.code_example
|
|
7587
7593
|
});
|
|
7588
7594
|
}
|
|
7589
7595
|
});
|
|
7590
7596
|
}
|
|
7591
|
-
}, [e.teaching,
|
|
7592
|
-
const
|
|
7593
|
-
if (w && (
|
|
7594
|
-
moduleIndex:
|
|
7595
|
-
lessonIndex:
|
|
7596
|
-
questionIndex:
|
|
7597
|
+
}, [e.teaching, R]), $ = M((b) => {
|
|
7598
|
+
const v = T(), w = F(b, v);
|
|
7599
|
+
if (w && (a.current.score += 1), c.current.onQuestionAnswer({
|
|
7600
|
+
moduleIndex: a.current.currentModuleIndex,
|
|
7601
|
+
lessonIndex: a.current.currentLessonIndex,
|
|
7602
|
+
questionIndex: a.current.currentQuestionIndex,
|
|
7597
7603
|
answer: b,
|
|
7598
7604
|
isCorrect: w,
|
|
7599
|
-
question:
|
|
7605
|
+
question: v
|
|
7600
7606
|
}), h.current)
|
|
7601
7607
|
if (w) {
|
|
7602
7608
|
if (h.current.setMood("happy"), e.correct)
|
|
@@ -7606,21 +7612,21 @@ const gt = ze(({
|
|
|
7606
7612
|
h.current.setBodyMovement("happy");
|
|
7607
7613
|
}
|
|
7608
7614
|
h.current.setBodyMovement("gesturing");
|
|
7609
|
-
const D =
|
|
7610
|
-
|
|
7611
|
-
const te =
|
|
7615
|
+
const D = R()?.questions?.length || 0;
|
|
7616
|
+
a.current.currentQuestionIndex >= D - 1;
|
|
7617
|
+
const te = v.type === "code_test" ? `Great job! Your code passed all the tests! ${v.explanation || ""}` : `Excellent! That's correct! ${v.explanation || ""}`, q = z.current || { lipsyncLang: "en" };
|
|
7612
7618
|
h.current.speakText(te, {
|
|
7613
7619
|
lipsyncLang: q.lipsyncLang,
|
|
7614
7620
|
onSpeechEnd: () => {
|
|
7615
7621
|
c.current.onCustomAction({
|
|
7616
7622
|
type: "answerFeedbackComplete",
|
|
7617
|
-
moduleIndex:
|
|
7618
|
-
lessonIndex:
|
|
7619
|
-
questionIndex:
|
|
7623
|
+
moduleIndex: a.current.currentModuleIndex,
|
|
7624
|
+
lessonIndex: a.current.currentLessonIndex,
|
|
7625
|
+
questionIndex: a.current.currentQuestionIndex,
|
|
7620
7626
|
isCorrect: !0,
|
|
7621
|
-
hasNextQuestion:
|
|
7622
|
-
score:
|
|
7623
|
-
totalQuestions:
|
|
7627
|
+
hasNextQuestion: a.current.currentQuestionIndex < D - 1,
|
|
7628
|
+
score: a.current.score,
|
|
7629
|
+
totalQuestions: a.current.totalQuestions
|
|
7624
7630
|
});
|
|
7625
7631
|
}
|
|
7626
7632
|
});
|
|
@@ -7632,44 +7638,44 @@ const gt = ze(({
|
|
|
7632
7638
|
h.current.setBodyMovement("idle");
|
|
7633
7639
|
}
|
|
7634
7640
|
h.current.setBodyMovement("gesturing");
|
|
7635
|
-
const D =
|
|
7641
|
+
const D = R()?.questions?.length || 0, te = a.current.currentQuestionIndex >= D - 1, q = v.type === "code_test" ? `Your code didn't pass all the tests. ${v.explanation || "Try again!"}` : `Not quite right, but don't worry! ${v.explanation || ""}${te ? "" : " Let's move on to the next question."}`, j = z.current || { lipsyncLang: "en" };
|
|
7636
7642
|
h.current.speakText(q, {
|
|
7637
7643
|
lipsyncLang: j.lipsyncLang,
|
|
7638
7644
|
onSpeechEnd: () => {
|
|
7639
7645
|
c.current.onCustomAction({
|
|
7640
7646
|
type: "answerFeedbackComplete",
|
|
7641
|
-
moduleIndex:
|
|
7642
|
-
lessonIndex:
|
|
7643
|
-
questionIndex:
|
|
7647
|
+
moduleIndex: a.current.currentModuleIndex,
|
|
7648
|
+
lessonIndex: a.current.currentLessonIndex,
|
|
7649
|
+
questionIndex: a.current.currentQuestionIndex,
|
|
7644
7650
|
isCorrect: !1,
|
|
7645
|
-
hasNextQuestion:
|
|
7646
|
-
score:
|
|
7647
|
-
totalQuestions:
|
|
7651
|
+
hasNextQuestion: a.current.currentQuestionIndex < D - 1,
|
|
7652
|
+
score: a.current.score,
|
|
7653
|
+
totalQuestions: a.current.totalQuestions
|
|
7648
7654
|
});
|
|
7649
7655
|
}
|
|
7650
7656
|
});
|
|
7651
7657
|
}
|
|
7652
7658
|
else {
|
|
7653
|
-
const D =
|
|
7659
|
+
const D = R()?.questions?.length || 0;
|
|
7654
7660
|
c.current.onCustomAction({
|
|
7655
7661
|
type: "answerFeedbackComplete",
|
|
7656
|
-
moduleIndex:
|
|
7657
|
-
lessonIndex:
|
|
7658
|
-
questionIndex:
|
|
7662
|
+
moduleIndex: a.current.currentModuleIndex,
|
|
7663
|
+
lessonIndex: a.current.currentLessonIndex,
|
|
7664
|
+
questionIndex: a.current.currentQuestionIndex,
|
|
7659
7665
|
isCorrect: w,
|
|
7660
|
-
hasNextQuestion:
|
|
7661
|
-
score:
|
|
7662
|
-
totalQuestions:
|
|
7666
|
+
hasNextQuestion: a.current.currentQuestionIndex < D - 1,
|
|
7667
|
+
score: a.current.score,
|
|
7668
|
+
totalQuestions: a.current.totalQuestions,
|
|
7663
7669
|
avatarNotReady: !0
|
|
7664
7670
|
});
|
|
7665
7671
|
}
|
|
7666
|
-
}, [e.correct, e.incorrect, T,
|
|
7667
|
-
const
|
|
7672
|
+
}, [e.correct, e.incorrect, T, R, F]), se = M((b) => {
|
|
7673
|
+
const v = T();
|
|
7668
7674
|
if (!b || typeof b != "object") {
|
|
7669
7675
|
console.error("Invalid code test result format. Expected object with {passed: boolean, ...}");
|
|
7670
7676
|
return;
|
|
7671
7677
|
}
|
|
7672
|
-
if (
|
|
7678
|
+
if (v?.type !== "code_test") {
|
|
7673
7679
|
console.warn("Current question is not a code test. Use handleAnswerSelect for other question types.");
|
|
7674
7680
|
return;
|
|
7675
7681
|
}
|
|
@@ -7685,26 +7691,26 @@ const gt = ze(({
|
|
|
7685
7691
|
};
|
|
7686
7692
|
c.current.onCustomAction({
|
|
7687
7693
|
type: "codeTestSubmitted",
|
|
7688
|
-
moduleIndex:
|
|
7689
|
-
lessonIndex:
|
|
7690
|
-
questionIndex:
|
|
7694
|
+
moduleIndex: a.current.currentModuleIndex,
|
|
7695
|
+
lessonIndex: a.current.currentLessonIndex,
|
|
7696
|
+
questionIndex: a.current.currentQuestionIndex,
|
|
7691
7697
|
testResult: w,
|
|
7692
|
-
question:
|
|
7698
|
+
question: v
|
|
7693
7699
|
}), p.current && p.current(w);
|
|
7694
7700
|
}, [T, F]), de = M(() => {
|
|
7695
|
-
if (
|
|
7696
|
-
|
|
7701
|
+
if (a.current.currentQuestionIndex > 0) {
|
|
7702
|
+
a.current.currentQuestionIndex -= 1;
|
|
7697
7703
|
const b = T();
|
|
7698
7704
|
b && c.current.onCustomAction({
|
|
7699
7705
|
type: "questionStart",
|
|
7700
|
-
moduleIndex:
|
|
7701
|
-
lessonIndex:
|
|
7702
|
-
questionIndex:
|
|
7703
|
-
totalQuestions:
|
|
7706
|
+
moduleIndex: a.current.currentModuleIndex,
|
|
7707
|
+
lessonIndex: a.current.currentLessonIndex,
|
|
7708
|
+
questionIndex: a.current.currentQuestionIndex,
|
|
7709
|
+
totalQuestions: a.current.totalQuestions,
|
|
7704
7710
|
question: b,
|
|
7705
|
-
score:
|
|
7711
|
+
score: a.current.score
|
|
7706
7712
|
});
|
|
7707
|
-
const
|
|
7713
|
+
const v = () => {
|
|
7708
7714
|
if (!h.current || !b) return;
|
|
7709
7715
|
h.current.setMood("happy"), h.current.setBodyMovement("idle");
|
|
7710
7716
|
const w = z.current || { lipsyncLang: "en" };
|
|
@@ -7715,10 +7721,10 @@ const gt = ze(({
|
|
|
7715
7721
|
});
|
|
7716
7722
|
};
|
|
7717
7723
|
if (h.current && h.current.isReady && b)
|
|
7718
|
-
|
|
7724
|
+
v();
|
|
7719
7725
|
else if (b) {
|
|
7720
7726
|
const w = setInterval(() => {
|
|
7721
|
-
h.current && h.current.isReady && (clearInterval(w),
|
|
7727
|
+
h.current && h.current.isReady && (clearInterval(w), v());
|
|
7722
7728
|
}, 100);
|
|
7723
7729
|
setTimeout(() => {
|
|
7724
7730
|
clearInterval(w);
|
|
@@ -7727,40 +7733,40 @@ const gt = ze(({
|
|
|
7727
7733
|
}
|
|
7728
7734
|
}, [T]), me = M(() => {
|
|
7729
7735
|
const b = H.current || { modules: [] };
|
|
7730
|
-
if (b.modules[
|
|
7731
|
-
|
|
7736
|
+
if (b.modules[a.current.currentModuleIndex], a.current.currentLessonIndex > 0)
|
|
7737
|
+
a.current.currentLessonIndex -= 1, a.current.currentQuestionIndex = 0, a.current.lessonCompleted = !1, a.current.isQuestionMode = !1, a.current.isTeaching = !1, a.current.score = 0, a.current.totalQuestions = 0, c.current.onCustomAction({
|
|
7732
7738
|
type: "lessonStart",
|
|
7733
|
-
moduleIndex:
|
|
7734
|
-
lessonIndex:
|
|
7739
|
+
moduleIndex: a.current.currentModuleIndex,
|
|
7740
|
+
lessonIndex: a.current.currentLessonIndex
|
|
7735
7741
|
}), c.current.onLessonStart({
|
|
7736
|
-
moduleIndex:
|
|
7737
|
-
lessonIndex:
|
|
7738
|
-
lesson:
|
|
7742
|
+
moduleIndex: a.current.currentModuleIndex,
|
|
7743
|
+
lessonIndex: a.current.currentLessonIndex,
|
|
7744
|
+
lesson: R()
|
|
7739
7745
|
}), h.current && (h.current.setMood("happy"), h.current.setBodyMovement("idle"));
|
|
7740
|
-
else if (
|
|
7741
|
-
const C = b.modules[
|
|
7742
|
-
|
|
7746
|
+
else if (a.current.currentModuleIndex > 0) {
|
|
7747
|
+
const C = b.modules[a.current.currentModuleIndex - 1];
|
|
7748
|
+
a.current.currentModuleIndex -= 1, a.current.currentLessonIndex = (C?.lessons?.length || 1) - 1, a.current.currentQuestionIndex = 0, a.current.lessonCompleted = !1, a.current.isQuestionMode = !1, a.current.isTeaching = !1, a.current.score = 0, a.current.totalQuestions = 0, c.current.onCustomAction({
|
|
7743
7749
|
type: "lessonStart",
|
|
7744
|
-
moduleIndex:
|
|
7745
|
-
lessonIndex:
|
|
7750
|
+
moduleIndex: a.current.currentModuleIndex,
|
|
7751
|
+
lessonIndex: a.current.currentLessonIndex
|
|
7746
7752
|
}), c.current.onLessonStart({
|
|
7747
|
-
moduleIndex:
|
|
7748
|
-
lessonIndex:
|
|
7749
|
-
lesson:
|
|
7753
|
+
moduleIndex: a.current.currentModuleIndex,
|
|
7754
|
+
lessonIndex: a.current.currentLessonIndex,
|
|
7755
|
+
lesson: R()
|
|
7750
7756
|
}), h.current && (h.current.setMood("happy"), h.current.setBodyMovement("idle"));
|
|
7751
7757
|
}
|
|
7752
|
-
}, [
|
|
7753
|
-
|
|
7758
|
+
}, [R]), ie = M(() => {
|
|
7759
|
+
a.current.currentModuleIndex = 0, a.current.currentLessonIndex = 0, a.current.currentQuestionIndex = 0, a.current.isTeaching = !1, a.current.isQuestionMode = !1, a.current.lessonCompleted = !1, a.current.curriculumCompleted = !1, a.current.score = 0, a.current.totalQuestions = 0;
|
|
7754
7760
|
}, []), fe = M((b) => {
|
|
7755
7761
|
console.log("Avatar is ready!", b);
|
|
7756
|
-
const
|
|
7762
|
+
const v = R(), w = v?.avatar_script || v?.body;
|
|
7757
7763
|
u && w && setTimeout(() => {
|
|
7758
7764
|
d.current && d.current();
|
|
7759
7765
|
}, 10);
|
|
7760
|
-
}, [u,
|
|
7766
|
+
}, [u, R]);
|
|
7761
7767
|
Xe(() => {
|
|
7762
7768
|
d.current = Z, g.current = Y, y.current = J, x.current = W, I.current = ye, B.current = S, p.current = $;
|
|
7763
|
-
}), Ce(
|
|
7769
|
+
}), Ce(r, () => ({
|
|
7764
7770
|
// Curriculum control methods
|
|
7765
7771
|
startTeaching: Z,
|
|
7766
7772
|
startQuestions: S,
|
|
@@ -7773,26 +7779,26 @@ const gt = ze(({
|
|
|
7773
7779
|
completeLesson: J,
|
|
7774
7780
|
completeCurriculum: ye,
|
|
7775
7781
|
resetCurriculum: ie,
|
|
7776
|
-
getState: () => ({ ...
|
|
7782
|
+
getState: () => ({ ...a.current }),
|
|
7777
7783
|
getCurrentQuestion: () => T(),
|
|
7778
|
-
getCurrentLesson: () =>
|
|
7784
|
+
getCurrentLesson: () => R(),
|
|
7779
7785
|
// Direct access to avatar ref (always returns current value)
|
|
7780
7786
|
getAvatarRef: () => h.current,
|
|
7781
7787
|
// Convenience methods that delegate to avatar (always check current ref)
|
|
7782
|
-
speakText: async (b,
|
|
7788
|
+
speakText: async (b, v = {}) => {
|
|
7783
7789
|
await h.current?.resumeAudioContext?.();
|
|
7784
7790
|
const w = z.current || { lipsyncLang: "en" };
|
|
7785
|
-
h.current?.speakText(b, { ...
|
|
7791
|
+
h.current?.speakText(b, { ...v, lipsyncLang: v.lipsyncLang || w.lipsyncLang });
|
|
7786
7792
|
},
|
|
7787
7793
|
resumeAudioContext: async () => {
|
|
7788
7794
|
if (h.current?.resumeAudioContext)
|
|
7789
7795
|
return await h.current.resumeAudioContext();
|
|
7790
7796
|
const b = h.current?.talkingHead;
|
|
7791
7797
|
if (b?.audioCtx) {
|
|
7792
|
-
const
|
|
7793
|
-
if (
|
|
7798
|
+
const v = b.audioCtx;
|
|
7799
|
+
if (v.state === "suspended" || v.state === "interrupted")
|
|
7794
7800
|
try {
|
|
7795
|
-
await
|
|
7801
|
+
await v.resume(), console.log("Audio context resumed via talkingHead");
|
|
7796
7802
|
} catch (w) {
|
|
7797
7803
|
console.warn("Failed to resume audio context:", w);
|
|
7798
7804
|
}
|
|
@@ -7804,7 +7810,7 @@ const gt = ze(({
|
|
|
7804
7810
|
resumeSpeaking: async () => await h.current?.resumeSpeaking(),
|
|
7805
7811
|
isPaused: () => h.current && typeof h.current.isPaused < "u" ? h.current.isPaused : !1,
|
|
7806
7812
|
setMood: (b) => h.current?.setMood(b),
|
|
7807
|
-
playAnimation: (b,
|
|
7813
|
+
playAnimation: (b, v) => h.current?.playAnimation(b, v),
|
|
7808
7814
|
setBodyMovement: (b) => h.current?.setBodyMovement(b),
|
|
7809
7815
|
setMovementIntensity: (b) => h.current?.setMovementIntensity(b),
|
|
7810
7816
|
playRandomDance: () => h.current?.playRandomDance(),
|
|
@@ -7815,18 +7821,18 @@ const gt = ze(({
|
|
|
7815
7821
|
lockAvatarPosition: () => h.current?.lockAvatarPosition(),
|
|
7816
7822
|
unlockAvatarPosition: () => h.current?.unlockAvatarPosition(),
|
|
7817
7823
|
// Custom action trigger
|
|
7818
|
-
triggerCustomAction: (b,
|
|
7824
|
+
triggerCustomAction: (b, v) => {
|
|
7819
7825
|
c.current.onCustomAction({
|
|
7820
7826
|
type: b,
|
|
7821
|
-
...
|
|
7822
|
-
state: { ...
|
|
7827
|
+
...v,
|
|
7828
|
+
state: { ...a.current }
|
|
7823
7829
|
});
|
|
7824
7830
|
},
|
|
7825
7831
|
// Responsive resize handler
|
|
7826
7832
|
handleResize: () => h.current?.handleResize(),
|
|
7827
7833
|
// Avatar readiness check (always returns current value)
|
|
7828
7834
|
isAvatarReady: () => h.current?.isReady || !1
|
|
7829
|
-
}), [Z, S, $, se, W, Y, J, ye, ie, T,
|
|
7835
|
+
}), [Z, S, $, se, W, Y, J, ye, ie, T, R]);
|
|
7830
7836
|
const X = z.current || {
|
|
7831
7837
|
avatarUrl: "/avatars/brunette.glb",
|
|
7832
7838
|
avatarBody: "F",
|