@sage-rsc/talking-head-react 1.1.1 → 1.1.3
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 +707 -552
- package/package.json +1 -1
- package/src/lib/talkinghead.mjs +278 -14
package/dist/index.js
CHANGED
|
@@ -1,20 +1,20 @@
|
|
|
1
1
|
import { jsxs as Pe, jsx as me } from "react/jsx-runtime";
|
|
2
|
-
import { forwardRef as Me, useRef as
|
|
2
|
+
import { forwardRef as Me, useRef as N, useState as ce, useEffect as de, useCallback as T, useImperativeHandle as Ee, 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";
|
|
6
6
|
import { DRACOLoader as Qe } from "three/addons/loaders/DRACOLoader.js";
|
|
7
|
-
import { FBXLoader as
|
|
7
|
+
import { FBXLoader as Ne } from "three/addons/loaders/FBXLoader.js";
|
|
8
8
|
import { RoomEnvironment as qe } from "three/addons/environments/RoomEnvironment.js";
|
|
9
|
-
import
|
|
10
|
-
let m, re,
|
|
9
|
+
import _e from "three/addons/libs/stats.module.js";
|
|
10
|
+
let m, re, he;
|
|
11
11
|
const A = [0, 0, 0, 0], w = new f.Vector3(), ze = new f.Vector3(), ne = new f.Vector3(), Ce = new f.Vector3();
|
|
12
12
|
new f.Plane();
|
|
13
13
|
new f.Ray();
|
|
14
14
|
new f.Euler();
|
|
15
15
|
const ie = new f.Quaternion(), Oe = new f.Quaternion(), fe = new f.Matrix4(), xe = new f.Matrix4();
|
|
16
16
|
new f.Vector3();
|
|
17
|
-
const He = new f.Vector3(0, 0, 1),
|
|
17
|
+
const He = new f.Vector3(0, 0, 1), Ke = new f.Vector3(1, 0, 0), Je = new f.Vector3(0, 1, 0), $e = new f.Vector3(0, 0, 1);
|
|
18
18
|
class et {
|
|
19
19
|
constructor(t = null) {
|
|
20
20
|
this.opt = Object.assign({
|
|
@@ -192,7 +192,7 @@ class et {
|
|
|
192
192
|
const l = this.armature.getObjectByName(s.bone);
|
|
193
193
|
if (!l) throw new Error("Bone '" + s.bone + "' not found in #" + o + " exclude.");
|
|
194
194
|
if (Number.isNaN(s.radius) && s.radius >= 0) throw new Error("Radius must be a non-negative number in #" + o + " exclude.");
|
|
195
|
-
const
|
|
195
|
+
const u = {
|
|
196
196
|
bone: l,
|
|
197
197
|
// Bone object
|
|
198
198
|
radius: s.radius,
|
|
@@ -203,9 +203,9 @@ class et {
|
|
|
203
203
|
};
|
|
204
204
|
if (s.deltaLocal) {
|
|
205
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
|
-
i.excludes.push(
|
|
208
|
+
i.excludes.push(u);
|
|
209
209
|
});
|
|
210
210
|
}
|
|
211
211
|
this.showHelpers();
|
|
@@ -282,8 +282,8 @@ class et {
|
|
|
282
282
|
m = this.dict[o.boneParent.name], m && (m.children || (m.children = []), m.children.push(o));
|
|
283
283
|
}), this.objectsUpdate = [];
|
|
284
284
|
const n = /* @__PURE__ */ new WeakSet(), i = (o) => o.parent?.isBone ? [o, ...i(o.parent)] : [o], s = (o) => {
|
|
285
|
-
i(o).forEach((
|
|
286
|
-
n.has(
|
|
285
|
+
i(o).forEach((u) => {
|
|
286
|
+
n.has(u) || (this.objectsUpdate.push(u), n.add(u));
|
|
287
287
|
});
|
|
288
288
|
};
|
|
289
289
|
this.data.forEach((o) => {
|
|
@@ -308,12 +308,12 @@ class et {
|
|
|
308
308
|
i(t?.isScene, "First parameter must be Scene."), this.scene = t, i(e?.isObject3D, "Second parameter must be the armature Object3D."), this.armature = e, i(Array.isArray(n), "Third parameter must be an array of bone configs."), this.config = n, this.config.forEach((s, o) => {
|
|
309
309
|
const l = "Config item #" + o + ": ";
|
|
310
310
|
i(s.bone, l + "Bone not specified.");
|
|
311
|
-
const
|
|
312
|
-
i(typeof
|
|
313
|
-
const r = this.armature.getObjectByName(
|
|
314
|
-
i(r, l + "Bone '" +
|
|
315
|
-
const
|
|
316
|
-
name:
|
|
311
|
+
const u = s.bone;
|
|
312
|
+
i(typeof u == "string" && u.length > 0, l + "Bone name must be a non-empty string.");
|
|
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
|
+
const h = {
|
|
316
|
+
name: u,
|
|
317
317
|
// Bone name
|
|
318
318
|
bone: r,
|
|
319
319
|
// Bone object
|
|
@@ -338,9 +338,9 @@ class et {
|
|
|
338
338
|
ea: [0, 0, 0, 0]
|
|
339
339
|
// External acceleration [m/s^2]
|
|
340
340
|
};
|
|
341
|
-
|
|
341
|
+
h.boneParent.matrixWorld.decompose(w, ie, ne), w.copy(He).applyQuaternion(ie).setY(0).normalize(), ie.premultiply(Oe.setFromUnitVectors(He, w).invert()).normalize(), h.qWorldInverseYaw = ie.clone().normalize(), this.data.push(h), this.dict[u] = h;
|
|
342
342
|
try {
|
|
343
|
-
this.setValue(
|
|
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
344
|
} catch (a) {
|
|
345
345
|
i(!1, l + a);
|
|
346
346
|
}
|
|
@@ -369,9 +369,9 @@ class et {
|
|
|
369
369
|
o.vBasis.y + A[1],
|
|
370
370
|
o.vBasis.z - A[2]
|
|
371
371
|
);
|
|
372
|
-
else if (o.boneParent.quaternion.copy(o.qBasis), o.pivot && this.opt.isPivots && (o.boneParent.updateWorldMatrix(!1, !1), o.boneParent.matrixWorld.decompose(w, ie, ne), w.copy(He).applyQuaternion(ie).setY(0).normalize(), ie.premultiply(Oe.setFromUnitVectors(He, w).invert()).normalize(), o.boneParent.quaternion.multiply(ie.invert()), o.boneParent.quaternion.multiply(o.qWorldInverseYaw)), o.isZ && (m = Math.atan(A[0] / o.l), ie.setFromAxisAngle($e, -m), o.boneParent.quaternion.multiply(ie)), o.isY && (m = o.l / 3, m = m * Math.tanh(A[1] / m), o.bone.position.setLength(o.l + m)), o.isX && (m = Math.atan(A[2] / o.l), ie.setFromAxisAngle(
|
|
372
|
+
else if (o.boneParent.quaternion.copy(o.qBasis), o.pivot && this.opt.isPivots && (o.boneParent.updateWorldMatrix(!1, !1), o.boneParent.matrixWorld.decompose(w, ie, ne), w.copy(He).applyQuaternion(ie).setY(0).normalize(), ie.premultiply(Oe.setFromUnitVectors(He, w).invert()).normalize(), o.boneParent.quaternion.multiply(ie.invert()), o.boneParent.quaternion.multiply(o.qWorldInverseYaw)), o.isZ && (m = Math.atan(A[0] / o.l), ie.setFromAxisAngle($e, -m), o.boneParent.quaternion.multiply(ie)), o.isY && (m = o.l / 3, m = m * Math.tanh(A[1] / m), o.bone.position.setLength(o.l + m)), o.isX && (m = Math.atan(A[2] / o.l), ie.setFromAxisAngle(Ke, -m), o.boneParent.quaternion.multiply(ie)), o.isT && (m = 1.5 * Math.tanh(A[3] * 1.5), ie.setFromAxisAngle(Je, -m), o.boneParent.quaternion.multiply(ie)), o.boneParent.updateWorldMatrix(!1, !0), o.excludes && this.opt.isExcludes)
|
|
373
373
|
for (n = 0, s = o.excludes.length; n < s; n++)
|
|
374
|
-
m = o.excludes[n], ne.set(0, 0, 0), m.deltaLocal && (ne.x += m.deltaLocal[0], ne.y += m.deltaLocal[1], ne.z += m.deltaLocal[2]), ne.applyMatrix4(m.bone.matrixWorld), xe.copy(o.boneParent.matrixWorld).invert(), ne.applyMatrix4(xe), w.copy(o.bone.position), !(w.distanceToSquared(ne) >= m.radiusSq) && (
|
|
374
|
+
m = o.excludes[n], ne.set(0, 0, 0), m.deltaLocal && (ne.x += m.deltaLocal[0], ne.y += m.deltaLocal[1], ne.z += m.deltaLocal[2]), ne.applyMatrix4(m.bone.matrixWorld), xe.copy(o.boneParent.matrixWorld).invert(), ne.applyMatrix4(xe), w.copy(o.bone.position), !(w.distanceToSquared(ne) >= m.radiusSq) && (he = w.length(), re = ne.length(), !(re > m.radius + he) && (re < Math.abs(m.radius - he) || (re = (re * re + he * he - m.radiusSq) / (2 * re), ne.normalize(), Ce.copy(ne).multiplyScalar(re), re = Math.sqrt(he * he - re * re), w.subVectors(w, Ce).projectOnPlane(ne).normalize().multiplyScalar(re), ze.subVectors(o.vBasis, Ce).projectOnPlane(ne).normalize(), he = ze.dot(w), he < 0 && (he = Math.sqrt(re * re - he * he), ze.multiplyScalar(he), w.add(ze)), w.add(Ce).normalize(), ne.copy(o.bone.position).normalize(), ie.setFromUnitVectors(ne, w), o.boneParent.quaternion.premultiply(ie), o.boneParent.updateWorldMatrix(!1, !0))));
|
|
375
375
|
}
|
|
376
376
|
this.helpers.isActive && this.updateHelpers();
|
|
377
377
|
}
|
|
@@ -408,9 +408,9 @@ class et {
|
|
|
408
408
|
);
|
|
409
409
|
}), m = this.helpers.points, m.bones.length) {
|
|
410
410
|
this.helpers.isActive = !0;
|
|
411
|
-
const e = new f.BufferGeometry(), n = m.bones.map((
|
|
411
|
+
const e = new f.BufferGeometry(), n = m.bones.map((u) => [0, 0, 0]).flat();
|
|
412
412
|
e.setAttribute("position", new f.Float32BufferAttribute(n, 3));
|
|
413
|
-
const i = new f.Color(this.opt.helperBoneColor1), s = new f.Color(this.opt.helperBoneColor2), o = m.pivots.map((
|
|
413
|
+
const i = new f.Color(this.opt.helperBoneColor1), s = new f.Color(this.opt.helperBoneColor2), o = m.pivots.map((u) => u && this.opt.isPivots ? [s.r, s.g, s.b] : [i.r, i.g, i.b]).flat();
|
|
414
414
|
e.setAttribute("color", new f.Float32BufferAttribute(o, 3));
|
|
415
415
|
const l = new f.PointsMaterial({
|
|
416
416
|
depthTest: !1,
|
|
@@ -423,9 +423,9 @@ class et {
|
|
|
423
423
|
m.object = new f.Points(e, l), m.object.renderOrder = 998, m.object.matrix = this.armature.matrixWorld, m.object.matrixAutoUpdate = !1, this.scene.add(m.object);
|
|
424
424
|
}
|
|
425
425
|
if (m = this.helpers.lines, m.bones.length) {
|
|
426
|
-
const e = new f.BufferGeometry(), n = m.bones.map((
|
|
426
|
+
const e = new f.BufferGeometry(), n = m.bones.map((u) => [0, 0, 0, 0, 0, 0]).flat();
|
|
427
427
|
e.setAttribute("position", new f.Float32BufferAttribute(n, 3));
|
|
428
|
-
const i = new f.Color(this.opt.helperLinkColor1), s = new f.Color(this.opt.helperLinkColor2), o = m.bones.map((
|
|
428
|
+
const i = new f.Color(this.opt.helperLinkColor1), s = new f.Color(this.opt.helperLinkColor2), o = m.bones.map((u) => [i.r, i.g, i.b, s.r, s.g, s.b]).flat();
|
|
429
429
|
e.setAttribute("color", new f.Float32BufferAttribute(o, 3));
|
|
430
430
|
const l = new f.LineBasicMaterial({
|
|
431
431
|
vertexColors: !0,
|
|
@@ -519,13 +519,13 @@ 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
|
|
522
|
+
const u = l * s, r = Math.min(u + i, t.length), h = t.slice(u, r), a = this.calculateEnergy(h);
|
|
523
523
|
n.energy.push(a);
|
|
524
|
-
const c = this.calculateSpectralCentroid(
|
|
524
|
+
const c = this.calculateSpectralCentroid(h);
|
|
525
525
|
n.spectralCentroid.push(c);
|
|
526
|
-
const d = this.calculateZeroCrossingRate(
|
|
526
|
+
const d = this.calculateZeroCrossingRate(h);
|
|
527
527
|
n.zeroCrossingRate.push(d);
|
|
528
|
-
const g = this.calculateMFCC(
|
|
528
|
+
const g = this.calculateMFCC(h);
|
|
529
529
|
n.mfcc.push(g);
|
|
530
530
|
}
|
|
531
531
|
return n.onsets = this.detectOnsets(n.energy), n.phonemeBoundaries = this.detectPhonemeBoundaries(n), n;
|
|
@@ -597,19 +597,19 @@ class tt {
|
|
|
597
597
|
for (; s & o; )
|
|
598
598
|
s ^= o, o >>= 1;
|
|
599
599
|
if (s ^= o, i < s) {
|
|
600
|
-
const l = n[i * 2],
|
|
601
|
-
n[i * 2] = n[s * 2], n[i * 2 + 1] = n[s * 2 + 1], n[s * 2] = l, n[s * 2 + 1] =
|
|
600
|
+
const l = n[i * 2], u = n[i * 2 + 1];
|
|
601
|
+
n[i * 2] = n[s * 2], n[i * 2 + 1] = n[s * 2 + 1], n[s * 2] = l, n[s * 2 + 1] = u;
|
|
602
602
|
}
|
|
603
603
|
}
|
|
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
|
-
for (let
|
|
607
|
-
let r = 1,
|
|
606
|
+
for (let u = 0; u < e; u += i) {
|
|
607
|
+
let r = 1, h = 0;
|
|
608
608
|
for (let a = 0; a < i / 2; a++) {
|
|
609
|
-
const c = n[(
|
|
610
|
-
n[(
|
|
611
|
-
const b = r * o -
|
|
612
|
-
r = b,
|
|
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, x = 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 + x, n[(u + a + i / 2) * 2] = c - g, n[(u + a + i / 2) * 2 + 1] = d - x;
|
|
611
|
+
const b = r * o - h * l, I = r * l + h * o;
|
|
612
|
+
r = b, h = I;
|
|
613
613
|
}
|
|
614
614
|
}
|
|
615
615
|
}
|
|
@@ -624,8 +624,8 @@ class tt {
|
|
|
624
624
|
const e = [];
|
|
625
625
|
let s = -0.1;
|
|
626
626
|
for (let o = 1; o < t.length; o++) {
|
|
627
|
-
const l = t[o] - t[o - 1],
|
|
628
|
-
l > 0.1 &&
|
|
627
|
+
const l = t[o] - t[o - 1], u = o * 0.023;
|
|
628
|
+
l > 0.1 && u - s > 0.1 && (e.push(u), s = u);
|
|
629
629
|
}
|
|
630
630
|
return e;
|
|
631
631
|
}
|
|
@@ -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,
|
|
641
|
-
|
|
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
|
}
|
|
@@ -654,14 +654,14 @@ class tt {
|
|
|
654
654
|
t.phonemeBoundaries, t.onsets;
|
|
655
655
|
const s = [];
|
|
656
656
|
let o = 0;
|
|
657
|
-
for (let
|
|
658
|
-
const r = i[
|
|
657
|
+
for (let u = 0; u < i.length; u++) {
|
|
658
|
+
const r = i[u], h = this.estimateWordDuration(r, n / i.length);
|
|
659
659
|
s.push({
|
|
660
660
|
word: r,
|
|
661
661
|
startTime: o,
|
|
662
|
-
endTime: o +
|
|
663
|
-
duration:
|
|
664
|
-
}), o +=
|
|
662
|
+
endTime: o + h,
|
|
663
|
+
duration: h
|
|
664
|
+
}), o += h;
|
|
665
665
|
}
|
|
666
666
|
const l = this.generateVisemeTimings(t, e, n);
|
|
667
667
|
return {
|
|
@@ -701,27 +701,27 @@ class tt {
|
|
|
701
701
|
const i = [], s = t.phonemeBoundaries;
|
|
702
702
|
t.onsets;
|
|
703
703
|
const o = this.textToVisemes(e);
|
|
704
|
-
let l = 0,
|
|
704
|
+
let l = 0, u = 0;
|
|
705
705
|
for (let r = 0; r < s.length && l < o.length; r++) {
|
|
706
|
-
const
|
|
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
708
|
viseme: a,
|
|
709
|
-
startTime:
|
|
710
|
-
endTime:
|
|
709
|
+
startTime: u,
|
|
710
|
+
endTime: u + d,
|
|
711
711
|
duration: d,
|
|
712
712
|
intensity: Math.min(1, c * 2)
|
|
713
713
|
// Map energy to viseme intensity
|
|
714
|
-
}),
|
|
714
|
+
}), u += d, l++;
|
|
715
715
|
}
|
|
716
716
|
for (; l < o.length; ) {
|
|
717
|
-
const r = o[l],
|
|
717
|
+
const r = o[l], h = this.calculateVisemeDuration(r, 0.5);
|
|
718
718
|
i.push({
|
|
719
719
|
viseme: r,
|
|
720
|
-
startTime:
|
|
721
|
-
endTime:
|
|
722
|
-
duration:
|
|
720
|
+
startTime: u,
|
|
721
|
+
endTime: u + h,
|
|
722
|
+
duration: h,
|
|
723
723
|
intensity: 0.6
|
|
724
|
-
}),
|
|
724
|
+
}), u += h, l++;
|
|
725
725
|
}
|
|
726
726
|
return i;
|
|
727
727
|
}
|
|
@@ -775,16 +775,16 @@ class tt {
|
|
|
775
775
|
let o = 0;
|
|
776
776
|
for (; o < s.length; ) {
|
|
777
777
|
let l = !1;
|
|
778
|
-
for (let
|
|
779
|
-
const r = s.substr(o,
|
|
778
|
+
for (let u = 3; u >= 2; u--) {
|
|
779
|
+
const r = s.substr(o, u);
|
|
780
780
|
if (e[r]) {
|
|
781
|
-
n.push(e[r]), o +=
|
|
781
|
+
n.push(e[r]), o += u, l = !0;
|
|
782
782
|
break;
|
|
783
783
|
}
|
|
784
784
|
}
|
|
785
785
|
if (!l) {
|
|
786
|
-
const
|
|
787
|
-
e[
|
|
786
|
+
const u = s[o];
|
|
787
|
+
e[u] && n.push(e[u]), o++;
|
|
788
788
|
}
|
|
789
789
|
}
|
|
790
790
|
}
|
|
@@ -1206,11 +1206,11 @@ 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),
|
|
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
|
-
const d = [...
|
|
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),
|
|
1212
|
+
const d = [...u];
|
|
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
1214
|
a.visemes.push(g);
|
|
1215
1215
|
}), a;
|
|
1216
1216
|
});
|
|
@@ -1324,8 +1324,8 @@ class nt {
|
|
|
1324
1324
|
*/
|
|
1325
1325
|
convertDecade(t) {
|
|
1326
1326
|
const e = parseInt(t), n = !isNaN(e) && t.length === 2, i = !isNaN(e) && t.length > 2 && e > 0 && e <= 3e3, s = i && e % 1e3 === 0 ? Math.floor(e / 1e3) : null, o = i && !s ? Math.floor(e / 100) : null, l = n || i ? Math.floor(e % 100 / 10) * 10 : null;
|
|
1327
|
-
let
|
|
1328
|
-
return s ?
|
|
1327
|
+
let u = [];
|
|
1328
|
+
return s ? u.push(this.convertNumberToWords(s).trim(), "thousands") : (o && u.push(this.convertNumberToWords(o).trim()), l ? u.push(this.decades[l] || this.convertNumberToWords(l).trim() + "s") : o ? u.push("hundreds") : u.push(t)), u.join(" ");
|
|
1329
1329
|
}
|
|
1330
1330
|
/**
|
|
1331
1331
|
* Convert ordinal number to text.
|
|
@@ -1376,9 +1376,9 @@ class nt {
|
|
|
1376
1376
|
const s = i[e.i], o = this.rules[s];
|
|
1377
1377
|
if (o)
|
|
1378
1378
|
for (let l = 0; l < o.length; l++) {
|
|
1379
|
-
const
|
|
1380
|
-
if ((e.words.substring(0, e.i) + s.toLowerCase() + e.words.substring(e.i + 1)).match(
|
|
1381
|
-
|
|
1379
|
+
const u = o[l];
|
|
1380
|
+
if ((e.words.substring(0, e.i) + s.toLowerCase() + e.words.substring(e.i + 1)).match(u.regex)) {
|
|
1381
|
+
u.visemes.forEach((a) => {
|
|
1382
1382
|
if (e.visemes.length && e.visemes[e.visemes.length - 1] === a) {
|
|
1383
1383
|
const c = 0.7 * (this.visemeDurations[a] || 1);
|
|
1384
1384
|
e.durations[e.durations.length - 1] += c, n += c;
|
|
@@ -1386,7 +1386,7 @@ class nt {
|
|
|
1386
1386
|
const c = this.visemeDurations[a] || 1;
|
|
1387
1387
|
e.visemes.push(a), e.times.push(n), e.durations.push(c), n += c;
|
|
1388
1388
|
}
|
|
1389
|
-
}), e.i +=
|
|
1389
|
+
}), e.i += u.move;
|
|
1390
1390
|
break;
|
|
1391
1391
|
}
|
|
1392
1392
|
}
|
|
@@ -1616,11 +1616,11 @@ 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),
|
|
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
|
-
const d = [...
|
|
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),
|
|
1622
|
+
const d = [...u];
|
|
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
1624
|
a.visemes.push(g);
|
|
1625
1625
|
}), a;
|
|
1626
1626
|
});
|
|
@@ -1732,8 +1732,8 @@ class ot {
|
|
|
1732
1732
|
const s = i[e.i], o = this.rules[s];
|
|
1733
1733
|
if (o) {
|
|
1734
1734
|
let l = !1;
|
|
1735
|
-
for (let
|
|
1736
|
-
const r = o[
|
|
1735
|
+
for (let u = 0; u < o.length; u++) {
|
|
1736
|
+
const r = o[u];
|
|
1737
1737
|
if ((e.words.substring(0, e.i) + s.toLowerCase() + e.words.substring(e.i + 1)).match(r.regex)) {
|
|
1738
1738
|
r.visemes.forEach((c) => {
|
|
1739
1739
|
if (e.visemes.length && e.visemes[e.visemes.length - 1] === c) {
|
|
@@ -2131,11 +2131,11 @@ 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),
|
|
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
|
-
const d = [...
|
|
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"),
|
|
2137
|
+
const d = [...u];
|
|
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
2139
|
g && a.visemes.push(g);
|
|
2140
2140
|
}), a;
|
|
2141
2141
|
});
|
|
@@ -2267,8 +2267,8 @@ class at {
|
|
|
2267
2267
|
const s = i[e.i], o = this.rules[s];
|
|
2268
2268
|
if (o) {
|
|
2269
2269
|
let l = !1;
|
|
2270
|
-
for (let
|
|
2271
|
-
const r = o[
|
|
2270
|
+
for (let u = 0; u < o.length; u++) {
|
|
2271
|
+
const r = o[u];
|
|
2272
2272
|
if ((e.words.substring(0, e.i) + s.toLowerCase() + e.words.substring(e.i + 1)).match(r.regex)) {
|
|
2273
2273
|
r.visemes.forEach((c) => {
|
|
2274
2274
|
if (e.visemes.length && e.visemes[e.visemes.length - 1] === c) {
|
|
@@ -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,
|
|
2384
|
+
let i = (s, o, l, u, r) => {
|
|
2385
2385
|
if (s < o) return s;
|
|
2386
|
-
const
|
|
2387
|
-
return e.push(l + (
|
|
2386
|
+
const h = Math.floor(s / o);
|
|
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);
|
|
@@ -2436,11 +2436,11 @@ class lt {
|
|
|
2436
2436
|
return e;
|
|
2437
2437
|
}
|
|
2438
2438
|
}
|
|
2439
|
-
const
|
|
2439
|
+
const ht = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
|
|
2440
2440
|
__proto__: null,
|
|
2441
2441
|
LipsyncFi: lt
|
|
2442
2442
|
}, Symbol.toStringTag, { value: "Module" }));
|
|
2443
|
-
class
|
|
2443
|
+
class ut {
|
|
2444
2444
|
/**
|
|
2445
2445
|
* @constructor
|
|
2446
2446
|
*/
|
|
@@ -2559,10 +2559,10 @@ class ht {
|
|
|
2559
2559
|
const e = [];
|
|
2560
2560
|
let n = parseFloat(t);
|
|
2561
2561
|
if (n === void 0) return t;
|
|
2562
|
-
let i = (s, o, l,
|
|
2562
|
+
let i = (s, o, l, u, r) => {
|
|
2563
2563
|
if (s < o) return s;
|
|
2564
|
-
const
|
|
2565
|
-
return
|
|
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(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--)
|
|
@@ -2608,11 +2608,11 @@ class ht {
|
|
|
2608
2608
|
const o = i[s].toLowerCase(), l = this.visemes[o];
|
|
2609
2609
|
if (l)
|
|
2610
2610
|
if (e.visemes.length && e.visemes[e.visemes.length - 1] === l) {
|
|
2611
|
-
const
|
|
2612
|
-
e.durations[e.durations.length - 1] +=
|
|
2611
|
+
const u = 0.7 * (this.durations[o] || 1);
|
|
2612
|
+
e.durations[e.durations.length - 1] += u, n += u;
|
|
2613
2613
|
} else {
|
|
2614
|
-
const
|
|
2615
|
-
e.visemes.push(l), e.times.push(n), e.durations.push(
|
|
2614
|
+
const u = this.durations[o] || 1;
|
|
2615
|
+
e.visemes.push(l), e.times.push(n), e.durations.push(u), n += u;
|
|
2616
2616
|
}
|
|
2617
2617
|
else
|
|
2618
2618
|
n += this.pauses[i[s]] || 0;
|
|
@@ -2622,14 +2622,14 @@ class ht {
|
|
|
2622
2622
|
}
|
|
2623
2623
|
const ct = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
|
|
2624
2624
|
__proto__: null,
|
|
2625
|
-
LipsyncLt:
|
|
2625
|
+
LipsyncLt: ut
|
|
2626
2626
|
}, Symbol.toStringTag, { value: "Module" })), dt = new URL("data:text/javascript;base64,Y2xhc3MgUGxheWJhY2tXb3JrbGV0IGV4dGVuZHMgQXVkaW9Xb3JrbGV0UHJvY2Vzc29yIHsKICBzdGF0aWMgRlNNID0gewogICAgSURMRTogMCwKICAgIFBMQVlJTkc6IDEsCiAgfTsKCiAgY29uc3RydWN0b3Iob3B0aW9ucykgewogICAgc3VwZXIoKTsKICAgIHRoaXMucG9ydC5vbm1lc3NhZ2UgPSB0aGlzLmhhbmRsZU1lc3NhZ2UuYmluZCh0aGlzKTsKCiAgICB0aGlzLl9zYW1wbGVSYXRlID0gb3B0aW9ucz8ucHJvY2Vzc29yT3B0aW9ucz8uc2FtcGxlUmF0ZSB8fCBzYW1wbGVSYXRlOwogICAgdGhpcy5fc2NhbGUgPSAxIC8gMzI3Njg7IC8vIFBDTTE2IC0+IGZsb2F0CgogICAgLy8gU2lsZW5jZSBkZXRlY3Rpb24gdGhyZXNob2xkICgxIHNlY29uZCkgYXMgYSBmYWxsYmFjayBzYWZldHkgbmV0CiAgICBjb25zdCBzaWxlbmNlRHVyYXRpb25TZWNvbmRzID0gMS4wOwogICAgdGhpcy5fc2lsZW5jZVRocmVzaG9sZEJsb2NrcyA9IE1hdGguY2VpbCgodGhpcy5fc2FtcGxlUmF0ZSAqIHNpbGVuY2VEdXJhdGlvblNlY29uZHMpIC8gMTI4KTsKCiAgICAvLyBNZXRyaWNzIGNvbmZpZ3VyYXRpb24gdmlhIG9wdGlvbnMKICAgIGNvbnN0IG1ldHJpY3NDZmcgPSBvcHRpb25zPy5wcm9jZXNzb3JPcHRpb25zPy5tZXRyaWNzIHx8IHt9OwogICAgdGhpcy5fbWV0cmljc0VuYWJsZWQgPSBtZXRyaWNzQ2ZnLmVuYWJsZWQgIT09IGZhbHNlOwogICAgY29uc3QgaW50ZXJ2YWxIeiA9ICh0eXBlb2YgbWV0cmljc0NmZy5pbnRlcnZhbEh6ID09PSAibnVtYmVyIiAmJiBtZXRyaWNzQ2ZnLmludGVydmFsSHogPiAwKQogICAgICA/IG1ldHJpY3NDZmcuaW50ZXJ2YWxIeiA6IDI7CiAgICAvLyBNZXRyaWNzIHN0YXRlIChsb3ctb3ZlcmhlYWQpCiAgICB0aGlzLl9mcmFtZXNQcm9jZXNzZWQgPSAwOwogICAgdGhpcy5fdW5kZXJydW5CbG9ja3MgPSAwOwogICAgdGhpcy5fbWF4UXVldWVTYW1wbGVzID0gMDsKICAgIHRoaXMuX2xhc3RNZXRyaWNzU2VudEF0RnJhbWUgPSAwOwogICAgLy8gQ29udmVydCB0byBmcmFtZXMgYmV0d2VlbiByZXBvcnRzCiAgICB0aGlzLl9tZXRyaWNzSW50ZXJ2YWxGcmFtZXMgPSBNYXRoLm1heCgxMjgsIE1hdGgucm91bmQodGhpcy5fc2FtcGxlUmF0ZSAvIGludGVydmFsSHopKTsKCiAgICB0aGlzLnJlc2V0KCk7CiAgfQoKICAvKioKICAgKiBSZXNldHMgdGhlIHdvcmtsZXQgdG8gaXRzIGluaXRpYWwgSURMRSBzdGF0ZS4KICAgKi8KICByZXNldCgpIHsKICAgIHRoaXMuX2J1ZmZlclF1ZXVlID0gW107CiAgICB0aGlzLl9jdXJyZW50Q2h1bmsgPSBudWxsOwogICAgdGhpcy5fY3VycmVudENodW5rT2Zmc2V0ID0gMDsKICAgIHRoaXMuX3N0YXRlID0gUGxheWJhY2tXb3JrbGV0LkZTTS5JRExFOwoKICAgIHRoaXMuX25vTW9yZURhdGFSZWNlaXZlZCA9IGZhbHNlOwogICAgdGhpcy5fc2lsZW5jZUZyYW1lc0NvdW50ID0gMDsKICAgIHRoaXMuX2hhc1NlbnRFbmRlZCA9IGZhbHNlOwogICAgLy8gUmVzZXQgbWF4IHF1ZXVlIHRyYWNrZXIgb25seSB3aGVuIGdvaW5nIGlkbGUKICAgIHRoaXMuX21heFF1ZXVlU2FtcGxlcyA9IDA7CiAgfQoKICBoYW5kbGVNZXNzYWdlKGV2ZW50KSB7CiAgICBjb25zdCB7IHR5cGUsIGRhdGEgfSA9IGV2ZW50LmRhdGE7CgogICAgLy8gSU5URVJSVVBUOiBUaGUgbWFpbiB0aHJlYWQgd2FudHMgdG8gc3RvcCBpbW1lZGlhdGVseS4KICAgIGlmICh0eXBlID09PSAic3RvcCIpIHsKICAgICAgdGhpcy5yZXNldCgpOwogICAgICAvLyBTZW5kIGZpbmFsIG1ldHJpY3Mgc2hvd2luZyBjbGVhcmVkIHN0YXRlCiAgICAgIGlmICh0aGlzLl9tZXRyaWNzRW5hYmxlZCkgewogICAgICAgIHRyeSB7CiAgICAgICAgICB0aGlzLnBvcnQucG9zdE1lc3NhZ2UoewogICAgICAgICAgICB0eXBlOiAibWV0cmljcyIsCiAgICAgICAgICAgIGRhdGE6IHsKICAgICAgICAgICAgICBzdGF0ZTogUGxheWJhY2tXb3JrbGV0LkZTTS5JRExFLAogICAgICAgICAgICAgIHF1ZXVlZFNhbXBsZXM6IDAsCiAgICAgICAgICAgICAgcXVldWVkTXM6IDAsCiAgICAgICAgICAgICAgbWF4UXVldWVkTXM6IE1hdGgucm91bmQoKHRoaXMuX21heFF1ZXVlU2FtcGxlcyAvIHRoaXMuX3NhbXBsZVJhdGUpICogMTAwMCksCiAgICAgICAgICAgICAgdW5kZXJydW5CbG9ja3M6IHRoaXMuX3VuZGVycnVuQmxvY2tzLAogICAgICAgICAgICAgIGZyYW1lc1Byb2Nlc3NlZDogdGhpcy5fZnJhbWVzUHJvY2Vzc2VkCiAgICAgICAgICAgIH0KICAgICAgICAgIH0pOwogICAgICAgIH0gY2F0Y2ggKF8pIHsgfQogICAgICB9CiAgICAgIHJldHVybjsKICAgIH0KCiAgICAvLyBNYWluIHRocmVhZCBoYXMgc2lnbmFsZWQgdGhhdCBubyBtb3JlIGF1ZGlvIGNodW5rcyB3aWxsIGJlIHNlbnQgZm9yIHRoaXMgdXR0ZXJhbmNlLgogICAgaWYgKHR5cGUgPT09ICJuby1tb3JlLWRhdGEiKSB7CiAgICAgIHRoaXMuX25vTW9yZURhdGFSZWNlaXZlZCA9IHRydWU7CiAgICAgIHJldHVybjsKICAgIH0KCiAgICAvLyBVcGRhdGUgbWV0cmljcyBjb25maWd1cmF0aW9uIGF0IHJ1bnRpbWUKICAgIGlmICh0eXBlID09PSAiY29uZmlnLW1ldHJpY3MiICYmIGRhdGEgJiYgdHlwZW9mIGRhdGEgPT09ICJvYmplY3QiKSB7CiAgICAgIGlmICgiZW5hYmxlZCIgaW4gZGF0YSkgdGhpcy5fbWV0cmljc0VuYWJsZWQgPSAhIWRhdGEuZW5hYmxlZDsKICAgICAgaWYgKHR5cGVvZiBkYXRhLmludGVydmFsSHogPT09ICJudW1iZXIiICYmIGRhdGEuaW50ZXJ2YWxIeiA+IDApIHsKICAgICAgICBjb25zdCBpbnRlcnZhbEh6ID0gZGF0YS5pbnRlcnZhbEh6OwogICAgICAgIHRoaXMuX21ldHJpY3NJbnRlcnZhbEZyYW1lcyA9IE1hdGgubWF4KDEyOCwgTWF0aC5yb3VuZCh0aGlzLl9zYW1wbGVSYXRlIC8gaW50ZXJ2YWxIeikpOwogICAgICB9CiAgICAgIC8vIFJlc2V0IHBhY2luZyBzbyB0aGUgbmV4dCByZXBvcnQgYWxpZ25zIHdpdGggbmV3IGludGVydmFsCiAgICAgIHRoaXMuX2xhc3RNZXRyaWNzU2VudEF0RnJhbWUgPSB0aGlzLl9mcmFtZXNQcm9jZXNzZWQ7CiAgICAgIHJldHVybjsKICAgIH0KCiAgICAvLyBOZXcgYXVkaW8gZGF0YSBoYXMgYXJyaXZlZC4KICAgIGlmICh0eXBlID09PSAiYXVkaW9EYXRhIiAmJiBkYXRhIGluc3RhbmNlb2YgQXJyYXlCdWZmZXIpIHsKICAgICAgdGhpcy5fbm9Nb3JlRGF0YVJlY2VpdmVkID0gZmFsc2U7CiAgICAgIC8vIElmIHdlIHdlcmUgaWRsZSwgdGhpcyBuZXcgZGF0YSBraWNrcyBvZmYgdGhlIHBsYXliYWNrLgogICAgICBpZiAodGhpcy5fc3RhdGUgPT09IFBsYXliYWNrV29ya2xldC5GU00uSURMRSkgewogICAgICAgIHRoaXMuX3N0YXRlID0gUGxheWJhY2tXb3JrbGV0LkZTTS5QTEFZSU5HOwogICAgICAgIHRoaXMucG9ydC5wb3N0TWVzc2FnZSh7IHR5cGU6ICJwbGF5YmFjay1zdGFydGVkIiB9KTsKICAgICAgfQoKICAgICAgLy8gV2Ugb25seSBxdWV1ZSBkYXRhIGlmIHdlIGFyZSBpbiB0aGUgUExBWUlORyBzdGF0ZS4gVGhpcyBwcmV2ZW50cwogICAgICAvLyBkYXRhIGZyb20gYSBwcmV2aW91cywgaW50ZXJydXB0ZWQgc3RyZWFtIGZyb20gbGluZ2VyaW5nLgogICAgICBpZiAodGhpcy5fc3RhdGUgPT09IFBsYXliYWNrV29ya2xldC5GU00uUExBWUlORykgewogICAgICAgIC8vIFN0b3JlIGFzIEludDE2QXJyYXkgdmlldyB0byBhdm9pZCBjb25zdHJ1Y3RpbmcgaXQgaW4gcHJvY2VzcygpCiAgICAgICAgdGhpcy5fYnVmZmVyUXVldWUucHVzaChuZXcgSW50MTZBcnJheShkYXRhKSk7CiAgICAgICAgdGhpcy5fc2lsZW5jZUZyYW1lc0NvdW50ID0gMDsgLy8gUmVzZXQgc2lsZW5jZSBjb3VudGVyIG9uIG5ldyBkYXRhCiAgICAgIH0KICAgIH0KICB9CgogIHByb2Nlc3MoaW5wdXRzLCBvdXRwdXRzLCBwYXJhbWV0ZXJzKSB7CiAgICBjb25zdCBvdXRwdXRDaGFubmVsID0gb3V0cHV0c1swXT8uWzBdOwogICAgaWYgKCFvdXRwdXRDaGFubmVsKSB7CiAgICAgIHJldHVybiB0cnVlOyAvLyBLZWVwIGFsaXZlIGV2ZW4gaWYgb3V0cHV0IGlzIHRlbXBvcmFyaWx5IGRpc2Nvbm5lY3RlZAogICAgfQoKICAgIC8vIElmIHdlIGFyZSBub3QgcGxheWluZywganVzdCBvdXRwdXQgc2lsZW5jZSBhbmQgd2FpdC4KICAgIGlmICh0aGlzLl9zdGF0ZSAhPT0gUGxheWJhY2tXb3JrbGV0LkZTTS5QTEFZSU5HKSB7CiAgICAgIG91dHB1dENoYW5uZWwuZmlsbCgwKTsKICAgICAgcmV0dXJuIHRydWU7IC8vIEFsd2F5cyByZXR1cm4gdHJ1ZSB0byBrZWVwIHRoZSBwcm9jZXNzb3IgYWxpdmUKICAgIH0KCiAgICAvLyBDb3JlIFBMQVlJTkcgTG9naWMKICAgIGNvbnN0IGJsb2NrU2l6ZSA9IG91dHB1dENoYW5uZWwubGVuZ3RoOwogICAgbGV0IHNhbXBsZXNDb3BpZWQgPSAwOwoKICAgIHdoaWxlIChzYW1wbGVzQ29waWVkIDwgYmxvY2tTaXplKSB7CiAgICAgIGlmICghdGhpcy5fY3VycmVudENodW5rIHx8IHRoaXMuX2N1cnJlbnRDaHVua09mZnNldCA+PSB0aGlzLl9jdXJyZW50Q2h1bmsubGVuZ3RoKSB7CiAgICAgICAgaWYgKHRoaXMuX2J1ZmZlclF1ZXVlLmxlbmd0aCA+IDApIHsKICAgICAgICAgIHRoaXMuX2N1cnJlbnRDaHVuayA9IHRoaXMuX2J1ZmZlclF1ZXVlLnNoaWZ0KCk7CiAgICAgICAgICB0aGlzLl9jdXJyZW50Q2h1bmtPZmZzZXQgPSAwOwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAvLyBCdWZmZXIgaXMgZW1wdHkuIENoZWNrIGZvciBlbmQgY29uZGl0aW9ucy4KICAgICAgICAgIGNvbnN0IGlzVGltZWRPdXQgPSB0aGlzLl9zaWxlbmNlRnJhbWVzQ291bnQgPiB0aGlzLl9zaWxlbmNlVGhyZXNob2xkQmxvY2tzOwoKICAgICAgICAgIGlmICh0aGlzLl9ub01vcmVEYXRhUmVjZWl2ZWQgfHwgaXNUaW1lZE91dCkgewogICAgICAgICAgICAvLyBFTkQgT0YgUExBWUJBQ0s6IEVpdGhlciBleHBsaWNpdGx5IHNpZ25hbGVkIG9yIHRpbWVkIG91dC4KICAgICAgICAgICAgaWYgKCF0aGlzLl9oYXNTZW50RW5kZWQpIHsKICAgICAgICAgICAgICB0aGlzLnBvcnQucG9zdE1lc3NhZ2UoeyB0eXBlOiAicGxheWJhY2stZW5kZWQiIH0pOwogICAgICAgICAgICAgIHRoaXMuX2hhc1NlbnRFbmRlZCA9IHRydWU7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgLy8gU2VuZCBmaW5hbCBtZXRyaWNzIHNob3dpbmcgY2xlYXJlZCBzdGF0ZQogICAgICAgICAgICBpZiAodGhpcy5fbWV0cmljc0VuYWJsZWQpIHsKICAgICAgICAgICAgICB0cnkgewogICAgICAgICAgICAgICAgdGhpcy5wb3J0LnBvc3RNZXNzYWdlKHsKICAgICAgICAgICAgICAgICAgdHlwZTogIm1ldHJpY3MiLAogICAgICAgICAgICAgICAgICBkYXRhOiB7CiAgICAgICAgICAgICAgICAgICAgc3RhdGU6IFBsYXliYWNrV29ya2xldC5GU00uSURMRSwKICAgICAgICAgICAgICAgICAgICBxdWV1ZWRTYW1wbGVzOiAwLAogICAgICAgICAgICAgICAgICAgIHF1ZXVlZE1zOiAwLAogICAgICAgICAgICAgICAgICAgIG1heFF1ZXVlZE1zOiBNYXRoLnJvdW5kKCh0aGlzLl9tYXhRdWV1ZVNhbXBsZXMgLyB0aGlzLl9zYW1wbGVSYXRlKSAqIDEwMDApLAogICAgICAgICAgICAgICAgICAgIHVuZGVycnVuQmxvY2tzOiB0aGlzLl91bmRlcnJ1bkJsb2NrcywKICAgICAgICAgICAgICAgICAgICBmcmFtZXNQcm9jZXNzZWQ6IHRoaXMuX2ZyYW1lc1Byb2Nlc3NlZAogICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICB9KTsKICAgICAgICAgICAgICB9IGNhdGNoIChfKSB7IH0KICAgICAgICAgICAgfQogICAgICAgICAgICB0aGlzLnJlc2V0KCk7IC8vIFJlc2V0IHRvIElETEUgc3RhdGUgZm9yIHJldXNlCiAgICAgICAgICAgIGJyZWFrOyAvLyBFeGl0IHdoaWxlIGxvb3AKICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgIC8vIEJVRkZFUiBVTkRFUlJVTiAoTEFHKTogUGxheSBzaWxlbmNlIGFuZCB3YWl0IGZvciBtb3JlIGRhdGEuCiAgICAgICAgICAgIHRoaXMuX3NpbGVuY2VGcmFtZXNDb3VudCsrOwogICAgICAgICAgICBpZiAodGhpcy5fbWV0cmljc0VuYWJsZWQpIHRoaXMuX3VuZGVycnVuQmxvY2tzKys7CiAgICAgICAgICAgIGJyZWFrOyAvLyBFeGl0IHdoaWxlIGxvb3AKICAgICAgICAgIH0KICAgICAgICB9CiAgICAgIH0KCiAgICAgIC8vIElmIHdlIGhhdmUgYSBjaHVuayAoY291bGQgYmUgYSBuZXcgb25lIGZyb20gdGhlIGxvZ2ljIGFib3ZlKSwgcHJvY2VzcyBpdC4KICAgICAgaWYgKHRoaXMuX2N1cnJlbnRDaHVuaykgewogICAgICAgIGNvbnN0IHNhbXBsZXNUb0NvcHkgPSBNYXRoLm1pbigKICAgICAgICAgIGJsb2NrU2l6ZSAtIHNhbXBsZXNDb3BpZWQsCiAgICAgICAgICB0aGlzLl9jdXJyZW50Q2h1bmsubGVuZ3RoIC0gdGhpcy5fY3VycmVudENodW5rT2Zmc2V0CiAgICAgICAgKTsKICAgICAgICAvLyBEaXJlY3RseSB3cml0ZSB0byBvdXRwdXRDaGFubmVsIHRvIGF2b2lkIGV4dHJhIGNvcHkKICAgICAgICBjb25zdCBzcmMgPSB0aGlzLl9jdXJyZW50Q2h1bms7CiAgICAgICAgY29uc3QgYmFzZVNyYyA9IHRoaXMuX2N1cnJlbnRDaHVua09mZnNldDsKICAgICAgICBjb25zdCBiYXNlRHN0ID0gc2FtcGxlc0NvcGllZDsKICAgICAgICBjb25zdCBzY2FsZSA9IHRoaXMuX3NjYWxlOwogICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgc2FtcGxlc1RvQ29weTsgaSsrKSB7CiAgICAgICAgICBvdXRwdXRDaGFubmVsW2Jhc2VEc3QgKyBpXSA9IHNyY1tiYXNlU3JjICsgaV0gKiBzY2FsZTsKICAgICAgICB9CgogICAgICAgIHRoaXMuX2N1cnJlbnRDaHVua09mZnNldCArPSBzYW1wbGVzVG9Db3B5OwogICAgICAgIHNhbXBsZXNDb3BpZWQgKz0gc2FtcGxlc1RvQ29weTsKICAgICAgfQogICAgfQoKICAgIC8vIFplcm8tZmlsbCB0aGUgcmVtYWluZGVyLCBpZiBhbnksIG9uY2UgcGVyIGJsb2NrCiAgICBpZiAoc2FtcGxlc0NvcGllZCA8IGJsb2NrU2l6ZSkgewogICAgICBvdXRwdXRDaGFubmVsLmZpbGwoMCwgc2FtcGxlc0NvcGllZCk7CiAgICB9CgogICAgLy8gVXBkYXRlIG1ldHJpY3MgKG9wdGlvbmFsKQogICAgaWYgKHRoaXMuX21ldHJpY3NFbmFibGVkKSB7CiAgICAgIHRoaXMuX2ZyYW1lc1Byb2Nlc3NlZCArPSBibG9ja1NpemU7CgogICAgICAvLyBUcmFjayBxdWV1ZSBkZXB0aCBpbiBzYW1wbGVzIChhcHByb3hpbWF0ZSkKICAgICAgbGV0IHF1ZXVlZFNhbXBsZXMgPSAwOwogICAgICBpZiAodGhpcy5fY3VycmVudENodW5rKSBxdWV1ZWRTYW1wbGVzICs9IE1hdGgubWF4KDAsIHRoaXMuX2N1cnJlbnRDaHVuay5sZW5ndGggLSB0aGlzLl9jdXJyZW50Q2h1bmtPZmZzZXQpOwogICAgICBmb3IgKGxldCBpID0gMDsgaSA8IHRoaXMuX2J1ZmZlclF1ZXVlLmxlbmd0aDsgaSsrKSBxdWV1ZWRTYW1wbGVzICs9IHRoaXMuX2J1ZmZlclF1ZXVlW2ldLmxlbmd0aDsKICAgICAgaWYgKHF1ZXVlZFNhbXBsZXMgPiB0aGlzLl9tYXhRdWV1ZVNhbXBsZXMpIHRoaXMuX21heFF1ZXVlU2FtcGxlcyA9IHF1ZXVlZFNhbXBsZXM7CgogICAgICAvLyBQZXJpb2RpY2FsbHkgc2VuZCBtZXRyaWNzIHRvIG1haW4gdGhyZWFkCiAgICAgIGlmICh0aGlzLl9mcmFtZXNQcm9jZXNzZWQgLSB0aGlzLl9sYXN0TWV0cmljc1NlbnRBdEZyYW1lID49IHRoaXMuX21ldHJpY3NJbnRlcnZhbEZyYW1lcykgewogICAgICAgIHRoaXMuX2xhc3RNZXRyaWNzU2VudEF0RnJhbWUgPSB0aGlzLl9mcmFtZXNQcm9jZXNzZWQ7CiAgICAgICAgdHJ5IHsKICAgICAgICAgIHRoaXMucG9ydC5wb3N0TWVzc2FnZSh7CiAgICAgICAgICAgIHR5cGU6ICJtZXRyaWNzIiwKICAgICAgICAgICAgZGF0YTogewogICAgICAgICAgICAgIHN0YXRlOiB0aGlzLl9zdGF0ZSwKICAgICAgICAgICAgICBxdWV1ZWRTYW1wbGVzLAogICAgICAgICAgICAgIHF1ZXVlZE1zOiBNYXRoLnJvdW5kKChxdWV1ZWRTYW1wbGVzIC8gdGhpcy5fc2FtcGxlUmF0ZSkgKiAxMDAwKSwKICAgICAgICAgICAgICBtYXhRdWV1ZWRNczogTWF0aC5yb3VuZCgodGhpcy5fbWF4UXVldWVTYW1wbGVzIC8gdGhpcy5fc2FtcGxlUmF0ZSkgKiAxMDAwKSwKICAgICAgICAgICAgICB1bmRlcnJ1bkJsb2NrczogdGhpcy5fdW5kZXJydW5CbG9ja3MsCiAgICAgICAgICAgICAgZnJhbWVzUHJvY2Vzc2VkOiB0aGlzLl9mcmFtZXNQcm9jZXNzZWQKICAgICAgICAgICAgfQogICAgICAgICAgfSk7CiAgICAgICAgfSBjYXRjaCAoXykgeyB9CiAgICAgICAgLy8gRG9uJ3QgcmVzZXQgbWF4IHRyYWNrZXIgLSBrZWVwIHNlc3Npb24gcGVhayB1bnRpbCBpZGxlCiAgICAgIH0KICAgIH0KCiAgICAvLyBBTFdBWVMgcmV0dXJuIHRydWUgdG8ga2VlcCB0aGUgcHJvY2Vzc29yIGFsaXZlIGZvciByZXVzZS4KICAgIHJldHVybiB0cnVlOwogIH0KfQoKcmVnaXN0ZXJQcm9jZXNzb3IoInBsYXliYWNrLXdvcmtsZXQiLCBQbGF5YmFja1dvcmtsZXQpOwo=", import.meta.url), Ue = {
|
|
2627
2627
|
en: it,
|
|
2628
2628
|
de: st,
|
|
2629
2629
|
fr: rt,
|
|
2630
|
-
fi:
|
|
2630
|
+
fi: ht,
|
|
2631
2631
|
lt: ct
|
|
2632
|
-
}, Q = new f.Quaternion(), V = new f.Euler(), ve = new f.Vector3(),
|
|
2632
|
+
}, Q = new f.Quaternion(), V = new f.Euler(), ve = new f.Vector3(), Re = new f.Vector3(), We = new f.Box3();
|
|
2633
2633
|
new f.Matrix4();
|
|
2634
2634
|
new f.Matrix4();
|
|
2635
2635
|
new f.Vector3();
|
|
@@ -2637,7 +2637,7 @@ new f.Vector3(0, 0, 1);
|
|
|
2637
2637
|
const mt = new f.Vector3(1, 0, 0);
|
|
2638
2638
|
new f.Vector3(0, 1, 0);
|
|
2639
2639
|
new f.Vector3(0, 0, 1);
|
|
2640
|
-
class
|
|
2640
|
+
class De {
|
|
2641
2641
|
/**
|
|
2642
2642
|
* Avatar.
|
|
2643
2643
|
* @typedef {Object} Avatar
|
|
@@ -2763,7 +2763,7 @@ class Be {
|
|
|
2763
2763
|
avatarOnlyCamera: null,
|
|
2764
2764
|
statsNode: null,
|
|
2765
2765
|
statsStyle: null
|
|
2766
|
-
}, Object.assign(this.opt, e || {}), this.opt.statsNode && (this.stats = new
|
|
2766
|
+
}, Object.assign(this.opt, e || {}), this.opt.statsNode && (this.stats = new _e(), this.opt.statsStyle && (this.stats.dom.style.cssText = this.opt.statsStyle), this.opt.statsNode.appendChild(this.stats.dom)), this.poseTemplates = {
|
|
2767
2767
|
side: {
|
|
2768
2768
|
standing: !0,
|
|
2769
2769
|
props: {
|
|
@@ -3569,15 +3569,15 @@ class Be {
|
|
|
3569
3569
|
"RightArm.scale": { x: 0, y: 0, z: 0 }
|
|
3570
3570
|
}
|
|
3571
3571
|
}, ["Left", "Right"].forEach((l) => {
|
|
3572
|
-
["Leg", "UpLeg", "Arm", "ForeArm", "Hand"].forEach((
|
|
3573
|
-
this.poseDelta.props[l +
|
|
3574
|
-
}), ["HandThumb", "HandIndex", "HandMiddle", "HandRing", "HandPinky"].forEach((
|
|
3575
|
-
this.poseDelta.props[l +
|
|
3572
|
+
["Leg", "UpLeg", "Arm", "ForeArm", "Hand"].forEach((u) => {
|
|
3573
|
+
this.poseDelta.props[l + u + ".quaternion"] = { x: 0, y: 0, z: 0 };
|
|
3574
|
+
}), ["HandThumb", "HandIndex", "HandMiddle", "HandRing", "HandPinky"].forEach((u) => {
|
|
3575
|
+
this.poseDelta.props[l + u + "1.quaternion"] = { x: 0, y: 0, z: 0 }, this.poseDelta.props[l + u + "2.quaternion"] = { x: 0, y: 0, z: 0 }, this.poseDelta.props[l + u + "3.quaternion"] = { x: 0, y: 0, z: 0 };
|
|
3576
3576
|
});
|
|
3577
3577
|
});
|
|
3578
3578
|
const n = /* @__PURE__ */ new Set();
|
|
3579
3579
|
Object.values(this.poseTemplates).forEach((l) => {
|
|
3580
|
-
Object.keys(this.propsToThreeObjects(l.props)).forEach((
|
|
3580
|
+
Object.keys(this.propsToThreeObjects(l.props)).forEach((u) => n.add(u));
|
|
3581
3581
|
}), Object.keys(this.poseDelta.props).forEach((l) => {
|
|
3582
3582
|
n.add(l);
|
|
3583
3583
|
}), this.posePropNames = [...n], this.poseName = "side", this.poseWeightOnLeft = !0, this.gesture = null, this.poseCurrentTemplate = this.poseTemplates[this.poseName], this.poseStraight = this.propsToThreeObjects(this.poseTemplates.straight.props), this.poseBase = this.poseFactory(this.poseCurrentTemplate), this.poseTarget = this.poseFactory(this.poseCurrentTemplate), this.poseAvatar = null, this.avatarHeight = 1.7, this.animTemplateEyes = {
|
|
@@ -4101,7 +4101,7 @@ class Be {
|
|
|
4101
4101
|
RightHand: "RightForeArm",
|
|
4102
4102
|
RightHandMiddle1: "RightHand"
|
|
4103
4103
|
}, o = [];
|
|
4104
|
-
Object.entries(s).forEach((l,
|
|
4104
|
+
Object.entries(s).forEach((l, u) => {
|
|
4105
4105
|
const r = new f.Bone();
|
|
4106
4106
|
r.name = l[0], l[1] ? this.ikMesh.getObjectByName(l[1]).add(r) : this.ikMesh.add(r), o.push(r);
|
|
4107
4107
|
}), 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 = [];
|
|
@@ -4150,9 +4150,9 @@ class Be {
|
|
|
4150
4150
|
let e = 3 * t.length / 4;
|
|
4151
4151
|
t[t.length - 1] === "=" && (e--, t[t.length - 2] === "=" && e--);
|
|
4152
4152
|
const n = new ArrayBuffer(e), i = new Uint8Array(n);
|
|
4153
|
-
let s, o = 0, l,
|
|
4153
|
+
let s, o = 0, l, u, r, h;
|
|
4154
4154
|
for (s = 0; s < t.length; s += 4)
|
|
4155
|
-
l = this.b64Lookup[t.charCodeAt(s)],
|
|
4155
|
+
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;
|
|
4156
4156
|
return n;
|
|
4157
4157
|
}
|
|
4158
4158
|
/**
|
|
@@ -4193,8 +4193,8 @@ class Be {
|
|
|
4193
4193
|
const e = {};
|
|
4194
4194
|
for (let [n, i] of Object.entries(t)) {
|
|
4195
4195
|
const s = n.split(".");
|
|
4196
|
-
let o = Array.isArray(i.x) ? this.gaussianRandom(...i.x) : i.x, l = Array.isArray(i.y) ? this.gaussianRandom(...i.y) : i.y,
|
|
4197
|
-
s[1] === "position" || s[1] === "scale" ? e[n] = new f.Vector3(o, l,
|
|
4196
|
+
let o = Array.isArray(i.x) ? this.gaussianRandom(...i.x) : i.x, l = Array.isArray(i.y) ? this.gaussianRandom(...i.y) : i.y, u = Array.isArray(i.z) ? this.gaussianRandom(...i.z) : i.z;
|
|
4197
|
+
s[1] === "position" || s[1] === "scale" ? e[n] = new f.Vector3(o, l, u) : s[1] === "rotation" ? (n = s[0] + ".quaternion", e[n] = new f.Quaternion().setFromEuler(new f.Euler(o, l, u, "XYZ")).normalize()) : s[1] === "quaternion" && (e[n] = new f.Quaternion(o, l, u, i.w).normalize());
|
|
4198
4198
|
}
|
|
4199
4199
|
return e;
|
|
4200
4200
|
}
|
|
@@ -4222,23 +4222,23 @@ class Be {
|
|
|
4222
4222
|
t.forEach((s) => {
|
|
4223
4223
|
if (!i && s.morphTargetDictionary.hasOwnProperty(e)) return;
|
|
4224
4224
|
const o = s.geometry;
|
|
4225
|
-
let l = null,
|
|
4226
|
-
for (const [r,
|
|
4225
|
+
let l = null, u = null;
|
|
4226
|
+
for (const [r, h] of Object.entries(n))
|
|
4227
4227
|
if (s.morphTargetDictionary.hasOwnProperty(r)) {
|
|
4228
4228
|
const a = s.morphTargetDictionary[r], c = o.morphAttributes.position[a], d = o.morphAttributes.normal?.[a];
|
|
4229
|
-
l || (l = new f.Float32BufferAttribute(c.count * 3, 3), d && (
|
|
4229
|
+
l || (l = new f.Float32BufferAttribute(c.count * 3, 3), d && (u = new f.Float32BufferAttribute(c.count * 3, 3)));
|
|
4230
4230
|
for (let g = 0; g < c.count; g++) {
|
|
4231
|
-
const x = l.getX(g) + c.getX(g) *
|
|
4232
|
-
l.setXYZ(g, x, b,
|
|
4231
|
+
const x = l.getX(g) + c.getX(g) * h, b = l.getY(g) + c.getY(g) * h, I = l.getZ(g) + c.getZ(g) * h;
|
|
4232
|
+
l.setXYZ(g, x, b, I);
|
|
4233
4233
|
}
|
|
4234
4234
|
if (d)
|
|
4235
4235
|
for (let g = 0; g < c.count; g++) {
|
|
4236
|
-
const x =
|
|
4237
|
-
|
|
4236
|
+
const x = u.getX(g) + d.getX(g) * h, b = u.getY(g) + d.getY(g) * h, I = u.getZ(g) + d.getZ(g) * h;
|
|
4237
|
+
u.setXYZ(g, x, b, I);
|
|
4238
4238
|
}
|
|
4239
4239
|
}
|
|
4240
4240
|
if (l) {
|
|
4241
|
-
o.morphAttributes.position.push(l),
|
|
4241
|
+
o.morphAttributes.position.push(l), u && o.morphAttributes.normal.push(u);
|
|
4242
4242
|
const r = o.morphAttributes.position.length - 1;
|
|
4243
4243
|
s.morphTargetInfluences[r] = 0, s.morphTargetDictionary[e] = r;
|
|
4244
4244
|
}
|
|
@@ -4268,7 +4268,7 @@ class Be {
|
|
|
4268
4268
|
throw new Error("Blend shapes not found");
|
|
4269
4269
|
const o = new Set(this.mtCustoms);
|
|
4270
4270
|
this.morphs.forEach((r) => {
|
|
4271
|
-
Object.keys(r.morphTargetDictionary).forEach((
|
|
4271
|
+
Object.keys(r.morphTargetDictionary).forEach((h) => o.add(h));
|
|
4272
4272
|
}), this.mtExtras.forEach((r) => {
|
|
4273
4273
|
o.has(r.key) || (this.addMixedMorphTarget(this.morphs, r.key, r.mix), o.add(r.key));
|
|
4274
4274
|
});
|
|
@@ -4295,16 +4295,16 @@ class Be {
|
|
|
4295
4295
|
ms: [],
|
|
4296
4296
|
is: []
|
|
4297
4297
|
}, l[r].value = l[r].baseline, l[r].applied = l[r].baseline;
|
|
4298
|
-
const
|
|
4299
|
-
|
|
4300
|
-
l[r][a] =
|
|
4298
|
+
const h = this.mtAvatar[r];
|
|
4299
|
+
h && ["fixed", "system", "systemd", "realtime", "base", "v", "value", "applied"].forEach((a) => {
|
|
4300
|
+
l[r][a] = h[a];
|
|
4301
4301
|
}), this.morphs.forEach((a) => {
|
|
4302
4302
|
const c = a.morphTargetDictionary[r];
|
|
4303
4303
|
c !== void 0 && (l[r].ms.push(a.morphTargetInfluences), l[r].is.push(c), a.morphTargetInfluences[c] = l[r].applied);
|
|
4304
4304
|
});
|
|
4305
4305
|
}), this.mtAvatar = l, this.poseAvatar = { props: {} }, this.posePropNames.forEach((r) => {
|
|
4306
|
-
const
|
|
4307
|
-
this.poseAvatar.props[r] = a[
|
|
4306
|
+
const h = r.split("."), a = this.armature.getObjectByName(h[0]);
|
|
4307
|
+
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;
|
|
4308
4308
|
}), this.ikMesh.traverse((r) => {
|
|
4309
4309
|
r.isBone && r.position.copy(this.armature.getObjectByName(r.name).position);
|
|
4310
4310
|
}), 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"))
|
|
@@ -4314,8 +4314,8 @@ class Be {
|
|
|
4314
4314
|
console.error("Dynamic bones setup failed: " + r);
|
|
4315
4315
|
}
|
|
4316
4316
|
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");
|
|
4317
|
-
const
|
|
4318
|
-
this.objectLeftEye.getWorldPosition(
|
|
4317
|
+
const u = new f.Vector3();
|
|
4318
|
+
this.objectLeftEye.getWorldPosition(u), this.avatarHeight = u.y + 0.2, this.viewName || this.setView(this.opt.cameraView), this.setMood(this.avatar.avatarMood || this.moodName || this.opt.avatarMood), this.avatar.body === "M" && this.poseTemplates.wide && (this.poseName = "wide", this.setPoseFromTemplate(this.poseTemplates.wide, 0), console.log("Set initial male-appropriate pose: wide")), this.initializeFBXAnimationLoader(), this.bodyMovement && this.bodyMovement !== "idle" && this.applyBodyMovementAnimation(), this.start();
|
|
4319
4319
|
}
|
|
4320
4320
|
/**
|
|
4321
4321
|
* Get view names.
|
|
@@ -4343,22 +4343,22 @@ class Be {
|
|
|
4343
4343
|
return;
|
|
4344
4344
|
}
|
|
4345
4345
|
if (this.viewName = t || this.viewName, e = e || {}, this.isAvatarOnly) return;
|
|
4346
|
-
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,
|
|
4347
|
-
let r = -n * Math.tan(
|
|
4346
|
+
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);
|
|
4347
|
+
let r = -n * Math.tan(u / 2), h = (1 - i) * Math.tan(u / 2), a = s;
|
|
4348
4348
|
switch (this.viewName) {
|
|
4349
4349
|
case "head":
|
|
4350
|
-
a += 2,
|
|
4350
|
+
a += 2, h = h * a + 4 * this.avatarHeight / 5;
|
|
4351
4351
|
break;
|
|
4352
4352
|
case "upper":
|
|
4353
|
-
a += 4.5,
|
|
4353
|
+
a += 4.5, h = h * a + 2 * this.avatarHeight / 3;
|
|
4354
4354
|
break;
|
|
4355
4355
|
case "mid":
|
|
4356
|
-
a += 8,
|
|
4356
|
+
a += 8, h = h * a + this.avatarHeight / 3;
|
|
4357
4357
|
break;
|
|
4358
4358
|
default:
|
|
4359
|
-
a += 12,
|
|
4359
|
+
a += 12, h = h * a;
|
|
4360
4360
|
}
|
|
4361
|
-
r = r * a, this.controlsEnd = new f.Vector3(r,
|
|
4361
|
+
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;
|
|
4362
4362
|
}
|
|
4363
4363
|
/**
|
|
4364
4364
|
* Change light colors and intensities.
|
|
@@ -4455,17 +4455,17 @@ class Be {
|
|
|
4455
4455
|
"HandMiddle",
|
|
4456
4456
|
"HandRing",
|
|
4457
4457
|
"HandPinky"
|
|
4458
|
-
].forEach((
|
|
4459
|
-
a === 0 ? (this.poseDelta.props[o +
|
|
4458
|
+
].forEach((h, a) => {
|
|
4459
|
+
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);
|
|
4460
4460
|
});
|
|
4461
4461
|
break;
|
|
4462
4462
|
case "chestInhale":
|
|
4463
|
-
const l = n.applied / 20,
|
|
4464
|
-
this.poseDelta.props["Spine1.scale"] =
|
|
4463
|
+
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 };
|
|
4464
|
+
this.poseDelta.props["Spine1.scale"] = u, this.poseDelta.props["Neck.scale"] = r, this.poseDelta.props["LeftArm.scale"] = r, this.poseDelta.props["RightArm.scale"] = r;
|
|
4465
4465
|
break;
|
|
4466
4466
|
default:
|
|
4467
|
-
for (let
|
|
4468
|
-
n.ms[
|
|
4467
|
+
for (let h = 0, a = n.ms.length; h < a; h++)
|
|
4468
|
+
n.ms[h][n.is[h]] = n.applied;
|
|
4469
4469
|
}
|
|
4470
4470
|
}
|
|
4471
4471
|
}
|
|
@@ -4480,8 +4480,8 @@ class Be {
|
|
|
4480
4480
|
return Object.entries(t).forEach((i, s) => {
|
|
4481
4481
|
const o = i[0].split(".");
|
|
4482
4482
|
if (o[1] === "position" || o[1] === "rotation" || o[1] === "quaternion") {
|
|
4483
|
-
const l = o[1] === "quaternion" ? o[0] + ".rotation" : i[0],
|
|
4484
|
-
n += (s ? ", " : "") + "'" + l + "':{", n += "x:" + Math.round(
|
|
4483
|
+
const l = o[1] === "quaternion" ? o[0] + ".rotation" : i[0], u = i[1].isQuaternion ? new f.Euler().setFromQuaternion(i[1]) : i[1];
|
|
4484
|
+
n += (s ? ", " : "") + "'" + l + "':{", n += "x:" + Math.round(u.x * e) / e, n += ", y:" + Math.round(u.y * e) / e, n += ", z:" + Math.round(u.z * e) / e, n += "}";
|
|
4485
4485
|
}
|
|
4486
4486
|
}), n += "}", n;
|
|
4487
4487
|
}
|
|
@@ -4551,8 +4551,8 @@ class Be {
|
|
|
4551
4551
|
if (n ? (this.poseCurrentTemplate = this.poseTemplates.oneknee, setTimeout(() => {
|
|
4552
4552
|
this.setPoseFromTemplate(t, e);
|
|
4553
4553
|
}, o)) : this.poseCurrentTemplate = t || this.poseCurrentTemplate, this.poseTarget = this.poseFactory(this.poseCurrentTemplate, o), this.poseWeightOnLeft = !0, (!i && !s || i && s) && (this.poseTarget.props = this.mirrorPose(this.poseTarget.props), this.poseWeightOnLeft = !this.poseWeightOnLeft), this.gesture)
|
|
4554
|
-
for (let [l,
|
|
4555
|
-
this.poseTarget.props.hasOwnProperty(l) && (this.poseTarget.props[l].copy(
|
|
4554
|
+
for (let [l, u] of Object.entries(this.gesture))
|
|
4555
|
+
this.poseTarget.props.hasOwnProperty(l) && (this.poseTarget.props[l].copy(u), this.poseTarget.props[l].t = u.t, this.poseTarget.props[l].d = u.d);
|
|
4556
4556
|
Object.keys(this.poseDelta.props).forEach((l) => {
|
|
4557
4557
|
this.poseTarget.props.hasOwnProperty(l) || (this.poseTarget.props[l] = this.poseBase.props[l].clone(), this.poseTarget.props[l].t = this.animClock, this.poseTarget.props[l].d = o);
|
|
4558
4558
|
});
|
|
@@ -4985,11 +4985,11 @@ class Be {
|
|
|
4985
4985
|
else if (l.hasOwnProperty("alt")) {
|
|
4986
4986
|
let r = l.alt[0];
|
|
4987
4987
|
if (l.alt.length > 1) {
|
|
4988
|
-
const
|
|
4988
|
+
const h = Math.random();
|
|
4989
4989
|
let a = 0;
|
|
4990
4990
|
for (let c = 0; c < l.alt.length; c++) {
|
|
4991
4991
|
let d = this.valueFn(l.alt[c].p);
|
|
4992
|
-
if (a += d === void 0 ? (1 - a) / (l.alt.length - 1 - c) : d,
|
|
4992
|
+
if (a += d === void 0 ? (1 - a) / (l.alt.length - 1 - c) : d, h < a) {
|
|
4993
4993
|
r = l.alt[c];
|
|
4994
4994
|
break;
|
|
4995
4995
|
}
|
|
@@ -4999,19 +4999,19 @@ class Be {
|
|
|
4999
4999
|
continue;
|
|
5000
5000
|
} else
|
|
5001
5001
|
break;
|
|
5002
|
-
let
|
|
5003
|
-
if (Array.isArray(
|
|
5004
|
-
l.dt.forEach((r,
|
|
5002
|
+
let u = this.valueFn(l.delay) || 0;
|
|
5003
|
+
if (Array.isArray(u) && (u = this.gaussianRandom(...u)), l.hasOwnProperty("dt"))
|
|
5004
|
+
l.dt.forEach((r, h) => {
|
|
5005
5005
|
let a = this.valueFn(r);
|
|
5006
|
-
Array.isArray(a) && (a = this.gaussianRandom(...a)), o.ts[
|
|
5006
|
+
Array.isArray(a) && (a = this.gaussianRandom(...a)), o.ts[h + 1] = o.ts[h] + a;
|
|
5007
5007
|
});
|
|
5008
5008
|
else {
|
|
5009
|
-
let r = Object.values(l.vs).reduce((
|
|
5009
|
+
let r = Object.values(l.vs).reduce((h, a) => a.length > h ? a.length : h, 0);
|
|
5010
5010
|
o.ts = Array(r + 1).fill(0);
|
|
5011
5011
|
}
|
|
5012
|
-
s ? o.ts = o.ts.map((r) =>
|
|
5013
|
-
for (let [r,
|
|
5014
|
-
const a = this.getBaselineValue(r), c =
|
|
5012
|
+
s ? o.ts = o.ts.map((r) => u + r * n) : o.ts = o.ts.map((r) => this.animClock + u + r * n), l.vs && l.vs.pose && console.log("Pose being selected from vs.pose:", l.vs.pose, "for avatar body:", this.avatar?.body);
|
|
5013
|
+
for (let [r, h] of Object.entries(l.vs)) {
|
|
5014
|
+
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 ? r === "pose" && this.avatar && this.avatar.body === "M" && (d === "hip" || d === "side") ? (console.log("Intercepting pose", d, "in animation factory, overriding to wide for male avatar"), "wide") : 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));
|
|
5015
5015
|
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];
|
|
5016
5016
|
}
|
|
5017
5017
|
for (let r of Object.keys(o.vs))
|
|
@@ -5093,8 +5093,8 @@ class Be {
|
|
|
5093
5093
|
if (this.isSpeaking)
|
|
5094
5094
|
for (l = 0, this.audioAnalyzerNode.getByteFrequencyData(this.volumeFrequencyData), n = 2, s = 10; n < s; n++)
|
|
5095
5095
|
this.volumeFrequencyData[n] > l && (l = this.volumeFrequencyData[n]);
|
|
5096
|
-
let
|
|
5097
|
-
const
|
|
5096
|
+
let u = null, r = null;
|
|
5097
|
+
const h = [];
|
|
5098
5098
|
for (n = 0, s = this.animQueue.length; n < s; n++) {
|
|
5099
5099
|
const a = this.animQueue[n];
|
|
5100
5100
|
if (!(!a || !a.ts || !a.ts.length || this.animClock < a.ts[0])) {
|
|
@@ -5121,12 +5121,12 @@ class Be {
|
|
|
5121
5121
|
g.newvalue *= 1 + l / 255 - 0.5;
|
|
5122
5122
|
}
|
|
5123
5123
|
g.needsUpdate = !0;
|
|
5124
|
-
} else c === "eyeContact" && d[i] !== null &&
|
|
5124
|
+
} 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);
|
|
5125
5125
|
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;
|
|
5126
5126
|
}
|
|
5127
5127
|
}
|
|
5128
|
-
for (let a = 0, c =
|
|
5129
|
-
switch (i =
|
|
5128
|
+
for (let a = 0, c = h.length; a < c; a++)
|
|
5129
|
+
switch (i = h[a].val, h[a].mt) {
|
|
5130
5130
|
case "speak":
|
|
5131
5131
|
this.speakText(i);
|
|
5132
5132
|
break;
|
|
@@ -5172,7 +5172,7 @@ class Be {
|
|
|
5172
5172
|
}, i.x ? new f.Vector3(i.x, i.y, i.z) : null, !0, i.d);
|
|
5173
5173
|
break;
|
|
5174
5174
|
}
|
|
5175
|
-
if ((
|
|
5175
|
+
if ((u || r) && (V.setFromQuaternion(this.poseAvatar.props["Head.quaternion"]), V.x = Math.max(-0.9, Math.min(0.9, 2 * V.x - 0.5)), V.y = Math.max(-0.9, Math.min(0.9, -2.5 * V.y)), u ? (Object.assign(this.mtAvatar.eyesLookDown, { system: V.x < 0 ? -V.x : 0, needsUpdate: !0 }), Object.assign(this.mtAvatar.eyesLookUp, { system: V.x < 0 ? 0 : V.x, needsUpdate: !0 }), Object.assign(this.mtAvatar.eyeLookInLeft, { system: V.y < 0 ? -V.y : 0, needsUpdate: !0 }), Object.assign(this.mtAvatar.eyeLookOutLeft, { system: V.y < 0 ? 0 : V.y, needsUpdate: !0 }), Object.assign(this.mtAvatar.eyeLookInRight, { system: V.y < 0 ? 0 : V.y, needsUpdate: !0 }), Object.assign(this.mtAvatar.eyeLookOutRight, { system: V.y < 0 ? -V.y : 0, needsUpdate: !0 }), r && (n = -this.mtAvatar.bodyRotateY.value, i = this.gaussianRandom(-0.2, 0.2), this.animQueue.push(this.animFactory({
|
|
5176
5176
|
name: "headmove",
|
|
5177
5177
|
dt: [[1e3, 2e3], [1e3, 2e3, 1, 2], [1e3, 2e3], [1e3, 2e3, 1, 2]],
|
|
5178
5178
|
vs: {
|
|
@@ -5193,7 +5193,7 @@ class Be {
|
|
|
5193
5193
|
eyeLookOutRight: [null, 0],
|
|
5194
5194
|
eyeContact: [0]
|
|
5195
5195
|
}
|
|
5196
|
-
})))), e > 2 * this.animFrameDur && (e = 2 * this.animFrameDur), (this.viewName !== "full" || this.isAvatarOnly) && (n = this.mtRandomized[Math.floor(Math.random() * this.mtRandomized.length)], i = this.mtAvatar[n], i.needsUpdate || Object.assign(i, { base: (this.mood.baseline[n] || 0) + (1 + l / 255) * Math.random() / 5, needsUpdate: !0 })), this.updatePoseBase(this.animClock), this.mixer && this.mixer.update(e / 1e3 * this.mixer.timeScale), this.updatePoseDelta(), (this.isSpeaking || this.isListening) &&
|
|
5196
|
+
})))), e > 2 * this.animFrameDur && (e = 2 * this.animFrameDur), (this.viewName !== "full" || this.isAvatarOnly) && (n = this.mtRandomized[Math.floor(Math.random() * this.mtRandomized.length)], i = this.mtAvatar[n], i.needsUpdate || Object.assign(i, { base: (this.mood.baseline[n] || 0) + (1 + l / 255) * Math.random() / 5, needsUpdate: !0 })), this.updatePoseBase(this.animClock), this.mixer && this.mixer.update(e / 1e3 * this.mixer.timeScale), this.updatePoseDelta(), (this.isSpeaking || this.isListening) && u ? l > this.volumeMax ? (this.volumeHeadBase = 0.05, Math.random() > 0.6 && (this.volumeHeadTarget = -0.05 - Math.random() / 15), this.volumeMax = l) : (this.volumeMax *= 0.92, this.volumeHeadTarget = this.volumeHeadBase - 0.9 * (this.volumeHeadBase - this.volumeHeadTarget)) : (this.volumeHeadTarget = 0, this.volumeMax = 0), n = this.volumeHeadTarget - this.volumeHeadCurrent, i = Math.abs(n), i > 1e-4 && (o = i * (this.volumeHeadEasing(Math.min(1, this.volumeHeadVelocity * e / 1e3 / i) / 2 + 0.5) - 0.5), this.volumeHeadCurrent += Math.sign(n) * Math.min(i, o)), Math.abs(this.volumeHeadCurrent) > 1e-4 && (Q.setFromAxisAngle(mt, this.volumeHeadCurrent), this.objectNeck.quaternion.multiply(Q)), We.setFromObject(this.armature), this.objectLeftToeBase.getWorldPosition(ve), ve.sub(this.armature.position), this.objectRightToeBase.getWorldPosition(Re), Re.sub(this.armature.position), this.objectHips.position.y -= We.min.y / 2, this.objectHips.position.x -= (ve.x + Re.x) / 4, this.objectHips.position.z -= (ve.z + Re.z) / 2, this.dynamicbones.update(e), this.fbxAnimationLoader && this.fbxAnimationLoader.update(), this.opt.update && this.opt.update(e), this.updateMorphTargets(e), this.isAvatarOnly)
|
|
5197
5197
|
this.stats && this.stats.end();
|
|
5198
5198
|
else {
|
|
5199
5199
|
if (this.cameraClock !== null && this.cameraClock < 1e3) {
|
|
@@ -5260,24 +5260,24 @@ class Be {
|
|
|
5260
5260
|
*/
|
|
5261
5261
|
speakText(t, e = null, n = null, i = null) {
|
|
5262
5262
|
e = e || {};
|
|
5263
|
-
const s = /[!\.\?\n\p{Extended_Pictographic}]/ug, o = /[ ]/ug, l = /[\p{L}\p{N},\.\p{Quotation_Mark}!€\$\+\p{Dash_Punctuation}%&\?]/ug,
|
|
5264
|
-
let
|
|
5263
|
+
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;
|
|
5264
|
+
let h = "", a = "", c = 0, d = [], g = [];
|
|
5265
5265
|
const x = Array.from(this.segmenter.segment(t), (b) => b.segment);
|
|
5266
5266
|
for (let b = 0; b < x.length; b++) {
|
|
5267
|
-
const
|
|
5267
|
+
const I = b === x.length - 1, D = x[b].match(l);
|
|
5268
5268
|
let p = x[b].match(s);
|
|
5269
|
-
const M = x[b].match(
|
|
5270
|
-
if (p && !
|
|
5269
|
+
const M = x[b].match(u), z = x[b].match(o);
|
|
5270
|
+
if (p && !I && !M && x[b + 1].match(s) && (p = !1), n && (h += x[b]), D && (!i || i.every((y) => b < y[0] || b > y[1])) && (a += x[b]), (z || p || I) && (a.length && (a = this.lipsyncPreProcessText(a, r), a.length && d.push({
|
|
5271
5271
|
mark: c,
|
|
5272
5272
|
word: a
|
|
5273
|
-
})),
|
|
5273
|
+
})), h.length && (g.push({
|
|
5274
5274
|
mark: c,
|
|
5275
5275
|
template: { name: "subtitles" },
|
|
5276
5276
|
ts: [0],
|
|
5277
5277
|
vs: {
|
|
5278
|
-
subtitles: [
|
|
5278
|
+
subtitles: [h]
|
|
5279
5279
|
}
|
|
5280
|
-
}),
|
|
5280
|
+
}), h = ""), a.length)) {
|
|
5281
5281
|
const y = this.lipsyncWordsToVisemes(a, r);
|
|
5282
5282
|
if (y && y.visemes && y.visemes.length) {
|
|
5283
5283
|
const E = y.times[y.visemes.length - 1] + y.durations[y.visemes.length - 1];
|
|
@@ -5293,8 +5293,8 @@ class Be {
|
|
|
5293
5293
|
}
|
|
5294
5294
|
a = "", c++;
|
|
5295
5295
|
}
|
|
5296
|
-
if (p ||
|
|
5297
|
-
if (d.length ||
|
|
5296
|
+
if (p || I) {
|
|
5297
|
+
if (d.length || I && g.length) {
|
|
5298
5298
|
const y = {
|
|
5299
5299
|
anim: g
|
|
5300
5300
|
};
|
|
@@ -5383,25 +5383,25 @@ class Be {
|
|
|
5383
5383
|
if (t.words) {
|
|
5384
5384
|
let o = [];
|
|
5385
5385
|
for (let l = 0; l < t.words.length; l++) {
|
|
5386
|
-
const
|
|
5387
|
-
let
|
|
5388
|
-
if (
|
|
5386
|
+
const u = t.words[l], r = t.wtimes[l];
|
|
5387
|
+
let h = t.wdurations[l];
|
|
5388
|
+
if (u.length && (n && o.push({
|
|
5389
5389
|
template: { name: "subtitles" },
|
|
5390
5390
|
ts: [r],
|
|
5391
5391
|
vs: {
|
|
5392
|
-
subtitles: [" " +
|
|
5392
|
+
subtitles: [" " + u]
|
|
5393
5393
|
}
|
|
5394
5394
|
}), !t.visemes)) {
|
|
5395
|
-
const a = this.lipsyncPreProcessText(
|
|
5395
|
+
const a = this.lipsyncPreProcessText(u, i), c = this.lipsyncWordsToVisemes(a, i);
|
|
5396
5396
|
if (c && c.visemes && c.visemes.length) {
|
|
5397
|
-
const d = c.times[c.visemes.length - 1] + c.durations[c.visemes.length - 1], g = Math.min(
|
|
5398
|
-
let x = 0.6 + this.convertRange(g, [0,
|
|
5399
|
-
if (
|
|
5397
|
+
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));
|
|
5398
|
+
let x = 0.6 + this.convertRange(g, [0, h], [0, 0.4]);
|
|
5399
|
+
if (h = Math.min(h, c.visemes.length * 200), d > 0)
|
|
5400
5400
|
for (let b = 0; b < c.visemes.length; b++) {
|
|
5401
|
-
const
|
|
5401
|
+
const I = r + c.times[b] / d * h, D = c.durations[b] / d * h;
|
|
5402
5402
|
o.push({
|
|
5403
5403
|
template: { name: "viseme" },
|
|
5404
|
-
ts: [
|
|
5404
|
+
ts: [I - Math.min(60, 2 * D / 3), I + Math.min(25, D / 2), I + D + Math.min(60, D / 2)],
|
|
5405
5405
|
vs: {
|
|
5406
5406
|
["viseme_" + c.visemes[b]]: [null, c.visemes[b] === "PP" || c.visemes[b] === "FF" ? 0.9 : x, 0]
|
|
5407
5407
|
}
|
|
@@ -5412,22 +5412,22 @@ class Be {
|
|
|
5412
5412
|
}
|
|
5413
5413
|
if (t.visemes)
|
|
5414
5414
|
for (let l = 0; l < t.visemes.length; l++) {
|
|
5415
|
-
const
|
|
5415
|
+
const u = t.visemes[l], r = t.vtimes[l], h = t.vdurations[l];
|
|
5416
5416
|
o.push({
|
|
5417
5417
|
template: { name: "viseme" },
|
|
5418
|
-
ts: [r - 2 *
|
|
5418
|
+
ts: [r - 2 * h / 3, r + h / 2, r + h + h / 2],
|
|
5419
5419
|
vs: {
|
|
5420
|
-
["viseme_" +
|
|
5420
|
+
["viseme_" + u]: [null, u === "PP" || u === "FF" ? 0.9 : 0.6, 0]
|
|
5421
5421
|
}
|
|
5422
5422
|
});
|
|
5423
5423
|
}
|
|
5424
5424
|
if (t.markers)
|
|
5425
5425
|
for (let l = 0; l < t.markers.length; l++) {
|
|
5426
|
-
const
|
|
5426
|
+
const u = t.markers[l], r = t.mtimes[l];
|
|
5427
5427
|
o.push({
|
|
5428
5428
|
template: { name: "markers" },
|
|
5429
5429
|
ts: [r],
|
|
5430
|
-
vs: { function: [
|
|
5430
|
+
vs: { function: [u] }
|
|
5431
5431
|
});
|
|
5432
5432
|
}
|
|
5433
5433
|
o.length && (s.anim = o);
|
|
@@ -5447,7 +5447,7 @@ class Be {
|
|
|
5447
5447
|
if (this.isAudioPlaying = !0, this.audioPlaylist.length) {
|
|
5448
5448
|
const e = this.audioPlaylist.shift();
|
|
5449
5449
|
if (this.audioCtx.state === "suspended" || this.audioCtx.state === "interrupted") {
|
|
5450
|
-
const s = this.audioCtx.resume(), o = new Promise((l,
|
|
5450
|
+
const s = this.audioCtx.resume(), o = new Promise((l, u) => setTimeout(() => u("p2"), 1e3));
|
|
5451
5451
|
try {
|
|
5452
5452
|
await Promise.race([s, o]);
|
|
5453
5453
|
} catch {
|
|
@@ -5479,11 +5479,11 @@ class Be {
|
|
|
5479
5479
|
*/
|
|
5480
5480
|
async synthesizeWithBrowserTTS(t) {
|
|
5481
5481
|
return new Promise((e, n) => {
|
|
5482
|
-
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,
|
|
5483
|
-
s.lang = o, s.rate = Math.max(0.1, Math.min(10, l)), s.pitch = Math.max(0, Math.min(2,
|
|
5484
|
-
const
|
|
5485
|
-
if (a &&
|
|
5486
|
-
const p =
|
|
5482
|
+
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;
|
|
5483
|
+
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));
|
|
5484
|
+
const h = speechSynthesis.getVoices(), a = t.voice || this.avatar.ttsVoice || this.opt.ttsVoice;
|
|
5485
|
+
if (a && h.length > 0) {
|
|
5486
|
+
const p = h.find((M) => M.name.includes(a) || M.lang === o);
|
|
5487
5487
|
p && (s.voice = p);
|
|
5488
5488
|
}
|
|
5489
5489
|
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", x = this.lipsyncPreProcessText(i, g), b = this.lipsyncWordsToVisemes(x, g);
|
|
@@ -5495,12 +5495,12 @@ class Be {
|
|
|
5495
5495
|
hasVisemes: b && b.visemes && b.visemes.length > 0,
|
|
5496
5496
|
estimatedDuration: c
|
|
5497
5497
|
});
|
|
5498
|
-
const
|
|
5498
|
+
const I = [];
|
|
5499
5499
|
if (b && b.visemes && b.visemes.length > 0) {
|
|
5500
5500
|
const p = b.times[b.visemes.length - 1] + b.durations[b.visemes.length - 1];
|
|
5501
5501
|
for (let M = 0; M < b.visemes.length; M++) {
|
|
5502
5502
|
const z = b.visemes[M], y = b.times[M] / p, E = b.durations[M] / p, P = y * c, W = E * c;
|
|
5503
|
-
|
|
5503
|
+
I.push({
|
|
5504
5504
|
template: { name: "viseme" },
|
|
5505
5505
|
ts: [P - Math.min(60, 2 * W / 3), P + Math.min(25, W / 2), P + W + Math.min(60, W / 2)],
|
|
5506
5506
|
vs: {
|
|
@@ -5509,8 +5509,8 @@ class Be {
|
|
|
5509
5509
|
});
|
|
5510
5510
|
}
|
|
5511
5511
|
}
|
|
5512
|
-
const
|
|
5513
|
-
this.audioPlaylist.push({ anim:
|
|
5512
|
+
const D = [...t.anim, ...I];
|
|
5513
|
+
this.audioPlaylist.push({ anim: D, audio: d }), this.onSubtitles = t.onSubtitles || null, this.resetLips(), t.mood && this.setMood(t.mood), this.playAudio(), s.onend = () => {
|
|
5514
5514
|
e();
|
|
5515
5515
|
}, s.onerror = (p) => {
|
|
5516
5516
|
console.error("Speech synthesis error:", p.error), n(p.error);
|
|
@@ -5544,15 +5544,15 @@ class Be {
|
|
|
5544
5544
|
throw new Error(`ElevenLabs TTS error: ${s.status} ${s.statusText}`);
|
|
5545
5545
|
const o = await s.arrayBuffer(), l = await this.audioCtx.decodeAudioData(o);
|
|
5546
5546
|
console.log("Using text-based lip-sync for debugging...");
|
|
5547
|
-
const
|
|
5547
|
+
const u = this.avatar.lipsyncLang || this.opt.lipsyncLang || "en";
|
|
5548
5548
|
let r;
|
|
5549
5549
|
try {
|
|
5550
5550
|
console.log("Lip-sync modules available:", {
|
|
5551
5551
|
hasLipsync: !!this.lipsync,
|
|
5552
5552
|
lipsyncKeys: this.lipsync ? Object.keys(this.lipsync) : [],
|
|
5553
|
-
lipsyncLang:
|
|
5553
|
+
lipsyncLang: u
|
|
5554
5554
|
});
|
|
5555
|
-
const c = this.lipsyncPreProcessText(e,
|
|
5555
|
+
const c = this.lipsyncPreProcessText(e, u), d = this.lipsyncWordsToVisemes(c, u);
|
|
5556
5556
|
if (console.log("Lip-sync data:", {
|
|
5557
5557
|
processedText: c,
|
|
5558
5558
|
lipsyncData: d,
|
|
@@ -5577,8 +5577,8 @@ class Be {
|
|
|
5577
5577
|
const d = e.toLowerCase().split(/\s+/), g = [];
|
|
5578
5578
|
for (const x of d)
|
|
5579
5579
|
for (const b of x) {
|
|
5580
|
-
let
|
|
5581
|
-
"aeiou".includes(b) ?
|
|
5580
|
+
let I = "aa";
|
|
5581
|
+
"aeiou".includes(b) ? I = "aa" : "bp".includes(b) ? I = "PP" : "fv".includes(b) ? I = "FF" : "st".includes(b) ? I = "SS" : "dln".includes(b) ? I = "DD" : "kg".includes(b) ? I = "kk" : "rw".includes(b) && (I = "RR"), g.push(I);
|
|
5582
5582
|
}
|
|
5583
5583
|
r = {
|
|
5584
5584
|
visemes: g.map((x, b) => ({
|
|
@@ -5605,12 +5605,12 @@ class Be {
|
|
|
5605
5605
|
visemes: r.visemes ? r.visemes.slice(0, 3) : []
|
|
5606
5606
|
// Show first 3 visemes for debugging
|
|
5607
5607
|
});
|
|
5608
|
-
const
|
|
5608
|
+
const h = [];
|
|
5609
5609
|
if (r.visemes && r.visemes.length > 0) {
|
|
5610
5610
|
console.log("ElevenLabs: Generating lip-sync animation from", r.visemes.length, "visemes");
|
|
5611
5611
|
for (let c = 0; c < r.visemes.length; c++) {
|
|
5612
5612
|
const d = r.visemes[c], g = d.startTime * 1e3, x = d.duration * 1e3, b = d.intensity;
|
|
5613
|
-
|
|
5613
|
+
h.push({
|
|
5614
5614
|
template: { name: "viseme" },
|
|
5615
5615
|
ts: [g - Math.min(60, 2 * x / 3), g + Math.min(25, x / 2), g + x + Math.min(60, x / 2)],
|
|
5616
5616
|
vs: {
|
|
@@ -5618,11 +5618,11 @@ class Be {
|
|
|
5618
5618
|
}
|
|
5619
5619
|
});
|
|
5620
5620
|
}
|
|
5621
|
-
console.log("ElevenLabs: Generated",
|
|
5621
|
+
console.log("ElevenLabs: Generated", h.length, "lip-sync animation frames");
|
|
5622
5622
|
} else
|
|
5623
5623
|
console.warn("ElevenLabs: No visemes available for lip-sync animation");
|
|
5624
|
-
const a = [...t.anim, ...
|
|
5625
|
-
console.log("ElevenLabs: Combined animation frames:", a.length, "(original:", t.anim.length, "+ lipsync:",
|
|
5624
|
+
const a = [...t.anim, ...h];
|
|
5625
|
+
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();
|
|
5626
5626
|
}
|
|
5627
5627
|
/**
|
|
5628
5628
|
* Synthesize speech using Deepgram Aura-2 TTS
|
|
@@ -5642,15 +5642,15 @@ class Be {
|
|
|
5642
5642
|
throw new Error(`Deepgram TTS error: ${s.status} ${s.statusText}`);
|
|
5643
5643
|
const o = await s.arrayBuffer(), l = await this.audioCtx.decodeAudioData(o);
|
|
5644
5644
|
console.log("Using text-based lip-sync for Deepgram...");
|
|
5645
|
-
const
|
|
5645
|
+
const u = this.avatar.lipsyncLang || this.opt.lipsyncLang || "en";
|
|
5646
5646
|
let r;
|
|
5647
5647
|
try {
|
|
5648
5648
|
console.log("Lip-sync modules available:", {
|
|
5649
5649
|
hasLipsync: !!this.lipsync,
|
|
5650
5650
|
lipsyncKeys: this.lipsync ? Object.keys(this.lipsync) : [],
|
|
5651
|
-
lipsyncLang:
|
|
5651
|
+
lipsyncLang: u
|
|
5652
5652
|
});
|
|
5653
|
-
const c = this.lipsyncPreProcessText(e,
|
|
5653
|
+
const c = this.lipsyncPreProcessText(e, u), d = this.lipsyncWordsToVisemes(c, u);
|
|
5654
5654
|
if (console.log("Lip-sync data:", {
|
|
5655
5655
|
processedText: c,
|
|
5656
5656
|
lipsyncData: d,
|
|
@@ -5675,8 +5675,8 @@ class Be {
|
|
|
5675
5675
|
const d = e.toLowerCase().split(/\s+/), g = [];
|
|
5676
5676
|
for (const x of d)
|
|
5677
5677
|
for (const b of x) {
|
|
5678
|
-
let
|
|
5679
|
-
"aeiou".includes(b) ?
|
|
5678
|
+
let I = "aa";
|
|
5679
|
+
"aeiou".includes(b) ? I = "aa" : "bp".includes(b) ? I = "PP" : "fv".includes(b) ? I = "FF" : "st".includes(b) ? I = "SS" : "dln".includes(b) ? I = "DD" : "kg".includes(b) ? I = "kk" : "rw".includes(b) && (I = "RR"), g.push(I);
|
|
5680
5680
|
}
|
|
5681
5681
|
r = {
|
|
5682
5682
|
visemes: g.map((x, b) => ({
|
|
@@ -5703,12 +5703,12 @@ class Be {
|
|
|
5703
5703
|
visemes: r.visemes ? r.visemes.slice(0, 3) : []
|
|
5704
5704
|
// Show first 3 visemes for debugging
|
|
5705
5705
|
});
|
|
5706
|
-
const
|
|
5706
|
+
const h = [];
|
|
5707
5707
|
if (r.visemes && r.visemes.length > 0) {
|
|
5708
5708
|
console.log("Deepgram: Generating lip-sync animation from", r.visemes.length, "visemes");
|
|
5709
5709
|
for (let c = 0; c < r.visemes.length; c++) {
|
|
5710
5710
|
const d = r.visemes[c], g = d.startTime * 1e3, x = d.duration * 1e3, b = d.intensity;
|
|
5711
|
-
|
|
5711
|
+
h.push({
|
|
5712
5712
|
template: { name: "viseme" },
|
|
5713
5713
|
ts: [g - Math.min(60, 2 * x / 3), g + Math.min(25, x / 2), g + x + Math.min(60, x / 2)],
|
|
5714
5714
|
vs: {
|
|
@@ -5716,11 +5716,11 @@ class Be {
|
|
|
5716
5716
|
}
|
|
5717
5717
|
});
|
|
5718
5718
|
}
|
|
5719
|
-
console.log("Deepgram: Generated",
|
|
5719
|
+
console.log("Deepgram: Generated", h.length, "lip-sync animation frames");
|
|
5720
5720
|
} else
|
|
5721
5721
|
console.warn("Deepgram: No visemes available for lip-sync animation");
|
|
5722
|
-
const a = [...t.anim, ...
|
|
5723
|
-
console.log("Deepgram: Combined animation frames:", a.length, "(original:", t.anim.length, "+ lipsync:",
|
|
5722
|
+
const a = [...t.anim, ...h];
|
|
5723
|
+
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();
|
|
5724
5724
|
}
|
|
5725
5725
|
/**
|
|
5726
5726
|
* Synthesize speech using Azure TTS
|
|
@@ -5746,20 +5746,20 @@ class Be {
|
|
|
5746
5746
|
throw new Error(`Azure TTS error: ${s.status} ${s.statusText}`);
|
|
5747
5747
|
const o = await s.arrayBuffer(), l = await this.audioCtx.decodeAudioData(o);
|
|
5748
5748
|
console.log("Analyzing audio for precise lip-sync...");
|
|
5749
|
-
const
|
|
5749
|
+
const u = await this.audioAnalyzer.analyzeAudio(l, e);
|
|
5750
5750
|
console.log("Azure TTS Audio Analysis:", {
|
|
5751
5751
|
text: e,
|
|
5752
5752
|
audioDuration: l.duration,
|
|
5753
|
-
visemeCount:
|
|
5754
|
-
wordCount:
|
|
5753
|
+
visemeCount: u.visemes.length,
|
|
5754
|
+
wordCount: u.words.length,
|
|
5755
5755
|
features: {
|
|
5756
|
-
onsets:
|
|
5757
|
-
boundaries:
|
|
5756
|
+
onsets: u.features.onsets.length,
|
|
5757
|
+
boundaries: u.features.phonemeBoundaries.length
|
|
5758
5758
|
}
|
|
5759
5759
|
});
|
|
5760
5760
|
const r = [];
|
|
5761
|
-
for (let a = 0; a <
|
|
5762
|
-
const c =
|
|
5761
|
+
for (let a = 0; a < u.visemes.length; a++) {
|
|
5762
|
+
const c = u.visemes[a], d = c.startTime * 1e3, g = c.duration * 1e3, x = c.intensity;
|
|
5763
5763
|
r.push({
|
|
5764
5764
|
template: { name: "viseme" },
|
|
5765
5765
|
ts: [d - Math.min(60, 2 * g / 3), d + Math.min(25, g / 2), d + g + Math.min(60, g / 2)],
|
|
@@ -5768,8 +5768,8 @@ class Be {
|
|
|
5768
5768
|
}
|
|
5769
5769
|
});
|
|
5770
5770
|
}
|
|
5771
|
-
const
|
|
5772
|
-
this.audioPlaylist.push({ anim:
|
|
5771
|
+
const h = [...t.anim, ...r];
|
|
5772
|
+
this.audioPlaylist.push({ anim: h, audio: l }), this.onSubtitles = t.onSubtitles || null, this.resetLips(), t.mood && this.setMood(t.mood), this.playAudio();
|
|
5773
5773
|
}
|
|
5774
5774
|
/**
|
|
5775
5775
|
* Synthesize speech using external TTS service (Google Cloud, etc.)
|
|
@@ -5808,24 +5808,24 @@ class Be {
|
|
|
5808
5808
|
if (i.status === 200 && s && s.audioContent) {
|
|
5809
5809
|
const o = this.b64ToArrayBuffer(s.audioContent), l = await this.audioCtx.decodeAudioData(o);
|
|
5810
5810
|
this.speakWithHands();
|
|
5811
|
-
const
|
|
5811
|
+
const u = [0];
|
|
5812
5812
|
let r = 0;
|
|
5813
5813
|
t.text.forEach((c, d) => {
|
|
5814
5814
|
if (d > 0) {
|
|
5815
|
-
let g =
|
|
5816
|
-
s.timepoints[r] && (g = s.timepoints[r].timeSeconds * 1e3, s.timepoints[r].markName === "" + c.mark && r++),
|
|
5815
|
+
let g = u[u.length - 1];
|
|
5816
|
+
s.timepoints[r] && (g = s.timepoints[r].timeSeconds * 1e3, s.timepoints[r].markName === "" + c.mark && r++), u.push(g);
|
|
5817
5817
|
}
|
|
5818
5818
|
});
|
|
5819
|
-
const
|
|
5820
|
-
|
|
5819
|
+
const h = [{ mark: 0, time: 0 }];
|
|
5820
|
+
u.forEach((c, d) => {
|
|
5821
5821
|
if (d > 0) {
|
|
5822
|
-
let g = c -
|
|
5823
|
-
|
|
5822
|
+
let g = c - u[d - 1];
|
|
5823
|
+
h[d - 1].duration = g, h.push({ mark: d, time: c });
|
|
5824
5824
|
}
|
|
5825
5825
|
});
|
|
5826
5826
|
let a = 1e3 * l.duration;
|
|
5827
|
-
a > this.opt.ttsTrimEnd && (a = a - this.opt.ttsTrimEnd),
|
|
5828
|
-
const d =
|
|
5827
|
+
a > this.opt.ttsTrimEnd && (a = a - this.opt.ttsTrimEnd), h[h.length - 1].duration = a - h[h.length - 1].time, t.anim.forEach((c) => {
|
|
5828
|
+
const d = h[c.mark];
|
|
5829
5829
|
if (d)
|
|
5830
5830
|
for (let g = 0; g < c.ts.length; g++)
|
|
5831
5831
|
c.ts[g] = d.time + c.ts[g] * d.duration + this.opt.ttsTrimStart;
|
|
@@ -5908,10 +5908,10 @@ class Be {
|
|
|
5908
5908
|
}
|
|
5909
5909
|
if (!this.workletLoaded)
|
|
5910
5910
|
try {
|
|
5911
|
-
const l = this.audioCtx.audioWorklet.addModule(dt.href),
|
|
5912
|
-
(r,
|
|
5911
|
+
const l = this.audioCtx.audioWorklet.addModule(dt.href), u = new Promise(
|
|
5912
|
+
(r, h) => setTimeout(() => h(new Error("Worklet loading timed out")), 5e3)
|
|
5913
5913
|
);
|
|
5914
|
-
await Promise.race([l,
|
|
5914
|
+
await Promise.race([l, u]), this.workletLoaded = !0;
|
|
5915
5915
|
} catch (l) {
|
|
5916
5916
|
throw console.error("Failed to load audio worklet:", l), new Error("Failed to initialize streaming speech");
|
|
5917
5917
|
}
|
|
@@ -5924,8 +5924,8 @@ class Be {
|
|
|
5924
5924
|
if (l.data.type === "playback-started" && (this.isSpeaking = !0, this.stateName = "speaking", this.streamWaitForAudioChunks && (this.streamAudioStartTime = this.animClock), this._processStreamLipsyncQueue(), this.speakWithHands(), this.onAudioStart))
|
|
5925
5925
|
try {
|
|
5926
5926
|
this.onAudioStart?.();
|
|
5927
|
-
} catch (
|
|
5928
|
-
console.error(
|
|
5927
|
+
} catch (u) {
|
|
5928
|
+
console.error(u);
|
|
5929
5929
|
}
|
|
5930
5930
|
if (l.data.type === "playback-ended" && (this._streamPause(), this.onAudioEnd))
|
|
5931
5931
|
try {
|
|
@@ -5945,9 +5945,9 @@ class Be {
|
|
|
5945
5945
|
} catch {
|
|
5946
5946
|
}
|
|
5947
5947
|
if (this.resetLips(), this.lookAtCamera(500), t.mood && this.setMood(t.mood), this.onSubtitles = i || null, this.audioCtx.state === "suspended" || this.audioCtx.state === "interrupted") {
|
|
5948
|
-
const l = this.audioCtx.resume(),
|
|
5948
|
+
const l = this.audioCtx.resume(), u = new Promise((r, h) => setTimeout(() => h("p2"), 1e3));
|
|
5949
5949
|
try {
|
|
5950
|
-
await Promise.race([l,
|
|
5950
|
+
await Promise.race([l, u]);
|
|
5951
5951
|
} catch {
|
|
5952
5952
|
console.warn("Can't play audio. Web Audio API suspended. This is often due to calling some speak method before the first user action, which is typically prevented by the browser.");
|
|
5953
5953
|
return;
|
|
@@ -6044,13 +6044,13 @@ class Be {
|
|
|
6044
6044
|
subtitles: [" " + i]
|
|
6045
6045
|
}
|
|
6046
6046
|
}), this.streamLipsyncType == "words")) {
|
|
6047
|
-
const l = this.streamLipsyncLang || this.avatar.lipsyncLang || this.opt.lipsyncLang,
|
|
6047
|
+
const l = this.streamLipsyncLang || this.avatar.lipsyncLang || this.opt.lipsyncLang, u = this.lipsyncPreProcessText(i, l), r = this.lipsyncWordsToVisemes(u, l);
|
|
6048
6048
|
if (r && r.visemes && r.visemes.length) {
|
|
6049
|
-
const
|
|
6049
|
+
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));
|
|
6050
6050
|
let c = 0.6 + this.convertRange(a, [0, o], [0, 0.4]);
|
|
6051
|
-
if (o = Math.min(o, r.visemes.length * 200),
|
|
6051
|
+
if (o = Math.min(o, r.visemes.length * 200), h > 0)
|
|
6052
6052
|
for (let d = 0; d < r.visemes.length; d++) {
|
|
6053
|
-
const g = e + s + r.times[d] /
|
|
6053
|
+
const g = e + s + r.times[d] / h * o, x = r.durations[d] / h * o;
|
|
6054
6054
|
this.animQueue.push({
|
|
6055
6055
|
template: { name: "viseme" },
|
|
6056
6056
|
ts: [g - Math.min(60, 2 * x / 3), g + Math.min(25, x / 2), g + x + Math.min(60, x / 2)],
|
|
@@ -6146,7 +6146,7 @@ class Be {
|
|
|
6146
6146
|
*/
|
|
6147
6147
|
lookAtCamera(t) {
|
|
6148
6148
|
let e;
|
|
6149
|
-
if (this.speakTo && (e = new f.Vector3(), this.speakTo.objectLeftEye?.isObject3D ? (this.speakTo.armature.objectHead, this.speakTo.objectLeftEye.updateMatrixWorld(!0), this.speakTo.objectRightEye.updateMatrixWorld(!0), ve.setFromMatrixPosition(this.speakTo.objectLeftEye.matrixWorld),
|
|
6149
|
+
if (this.speakTo && (e = new f.Vector3(), this.speakTo.objectLeftEye?.isObject3D ? (this.speakTo.armature.objectHead, this.speakTo.objectLeftEye.updateMatrixWorld(!0), this.speakTo.objectRightEye.updateMatrixWorld(!0), ve.setFromMatrixPosition(this.speakTo.objectLeftEye.matrixWorld), Re.setFromMatrixPosition(this.speakTo.objectRightEye.matrixWorld), e.addVectors(ve, Re).divideScalar(2)) : this.speakTo.isObject3D ? this.speakTo.getWorldPosition(e) : this.speakTo.isVector3 ? e.set(this.speakTo) : this.speakTo.x && this.speakTo.y && this.speakTo.z && e.set(this.speakTo.x, this.speakTo.y, this.speakTo.z)), !e) {
|
|
6150
6150
|
if (this.avatar.hasOwnProperty("avatarIgnoreCamera")) {
|
|
6151
6151
|
if (this.avatar.avatarIgnoreCamera) {
|
|
6152
6152
|
this.lookAhead(t);
|
|
@@ -6159,14 +6159,14 @@ class Be {
|
|
|
6159
6159
|
this.lookAt(null, null, t);
|
|
6160
6160
|
return;
|
|
6161
6161
|
}
|
|
6162
|
-
this.objectLeftEye.updateMatrixWorld(!0), this.objectRightEye.updateMatrixWorld(!0), ve.setFromMatrixPosition(this.objectLeftEye.matrixWorld),
|
|
6162
|
+
this.objectLeftEye.updateMatrixWorld(!0), this.objectRightEye.updateMatrixWorld(!0), ve.setFromMatrixPosition(this.objectLeftEye.matrixWorld), Re.setFromMatrixPosition(this.objectRightEye.matrixWorld), ve.add(Re).divideScalar(2), Q.copy(this.armature.quaternion), Q.multiply(this.poseTarget.props["Hips.quaternion"]), Q.multiply(this.poseTarget.props["Spine.quaternion"]), Q.multiply(this.poseTarget.props["Spine1.quaternion"]), Q.multiply(this.poseTarget.props["Spine2.quaternion"]), Q.multiply(this.poseTarget.props["Neck.quaternion"]), Q.multiply(this.poseTarget.props["Head.quaternion"]);
|
|
6163
6163
|
const n = new f.Vector3().subVectors(e, ve).normalize(), i = Math.atan2(n.x, n.z), s = Math.asin(-n.y);
|
|
6164
6164
|
V.set(s, i, 0, "YXZ");
|
|
6165
|
-
const l = new f.Quaternion().setFromEuler(V),
|
|
6166
|
-
V.setFromQuaternion(
|
|
6167
|
-
let r = V.x / (40 / 24) + 0.2,
|
|
6165
|
+
const l = new f.Quaternion().setFromEuler(V), u = new f.Quaternion().copy(l).multiply(Q.clone().invert());
|
|
6166
|
+
V.setFromQuaternion(u, "YXZ");
|
|
6167
|
+
let r = V.x / (40 / 24) + 0.2, h = V.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;
|
|
6168
6168
|
if (t) {
|
|
6169
|
-
let x = this.animQueue.findIndex((
|
|
6169
|
+
let x = this.animQueue.findIndex((I) => I.template.name === "lookat");
|
|
6170
6170
|
x !== -1 && this.animQueue.splice(x, 1);
|
|
6171
6171
|
const b = {
|
|
6172
6172
|
name: "lookat",
|
|
@@ -6198,11 +6198,11 @@ class Be {
|
|
|
6198
6198
|
this.objectLeftEye.updateMatrixWorld(!0), this.objectRightEye.updateMatrixWorld(!0);
|
|
6199
6199
|
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);
|
|
6200
6200
|
l.project(this.camera);
|
|
6201
|
-
let
|
|
6202
|
-
t === null && (t =
|
|
6203
|
-
let
|
|
6204
|
-
b = Math.min(0.6, Math.max(-0.3, b)),
|
|
6205
|
-
let
|
|
6201
|
+
let u = (l.x + 1) / 2 * i.width + i.left, r = -(l.y - 1) / 2 * i.height + i.top;
|
|
6202
|
+
t === null && (t = u), e === null && (e = r), Q.copy(this.armature.quaternion), Q.multiply(this.poseTarget.props["Hips.quaternion"]), Q.multiply(this.poseTarget.props["Spine.quaternion"]), Q.multiply(this.poseTarget.props["Spine1.quaternion"]), Q.multiply(this.poseTarget.props["Spine2.quaternion"]), Q.multiply(this.poseTarget.props["Neck.quaternion"]), Q.multiply(this.poseTarget.props["Head.quaternion"]), V.setFromQuaternion(Q);
|
|
6203
|
+
let h = V.x / (40 / 24), a = V.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), x = Math.max(window.innerHeight - r, r), b = this.convertRange(e, [r - x, r + x], [-0.3, 0.6]) - h + c, I = this.convertRange(t, [u - g, u + g], [-0.8, 0.8]) - a + d;
|
|
6204
|
+
b = Math.min(0.6, Math.max(-0.3, b)), I = Math.min(0.8, Math.max(-0.8, I));
|
|
6205
|
+
let D = (Math.random() - 0.5) / 4, p = (Math.random() - 0.5) / 4;
|
|
6206
6206
|
if (n) {
|
|
6207
6207
|
let M = this.animQueue.findIndex((y) => y.template.name === "lookat");
|
|
6208
6208
|
M !== -1 && this.animQueue.splice(M, 1);
|
|
@@ -6210,9 +6210,9 @@ class Be {
|
|
|
6210
6210
|
name: "lookat",
|
|
6211
6211
|
dt: [750, n],
|
|
6212
6212
|
vs: {
|
|
6213
|
-
bodyRotateX: [b +
|
|
6214
|
-
bodyRotateY: [
|
|
6215
|
-
eyesRotateX: [-3 *
|
|
6213
|
+
bodyRotateX: [b + D],
|
|
6214
|
+
bodyRotateY: [I + p],
|
|
6215
|
+
eyesRotateX: [-3 * D + 0.1],
|
|
6216
6216
|
eyesRotateY: [-5 * p],
|
|
6217
6217
|
browInnerUp: [[0, 0.7]],
|
|
6218
6218
|
mouthLeft: [[0, 0.7]],
|
|
@@ -6239,10 +6239,10 @@ class Be {
|
|
|
6239
6239
|
s.setFromCamera(i, this.camera);
|
|
6240
6240
|
const o = s.intersectObject(this.armature);
|
|
6241
6241
|
if (o.length > 0) {
|
|
6242
|
-
const l = o[0].point,
|
|
6243
|
-
this.objectLeftArm.getWorldPosition(
|
|
6244
|
-
const
|
|
6245
|
-
|
|
6242
|
+
const l = o[0].point, u = new f.Vector3(), r = new f.Vector3();
|
|
6243
|
+
this.objectLeftArm.getWorldPosition(u), this.objectRightArm.getWorldPosition(r);
|
|
6244
|
+
const h = u.distanceToSquared(l), a = r.distanceToSquared(l);
|
|
6245
|
+
h < a ? (this.ikSolve({
|
|
6246
6246
|
iterations: 20,
|
|
6247
6247
|
root: "LeftShoulder",
|
|
6248
6248
|
effector: "LeftHandMiddle1",
|
|
@@ -6263,8 +6263,8 @@ class Be {
|
|
|
6263
6263
|
}, l, !1, 1e3), this.setValue("handFistRight", 0));
|
|
6264
6264
|
} else
|
|
6265
6265
|
["LeftArm", "LeftForeArm", "LeftHand", "RightArm", "RightForeArm", "RightHand"].forEach((l) => {
|
|
6266
|
-
let
|
|
6267
|
-
this.poseTarget.props[
|
|
6266
|
+
let u = l + ".quaternion";
|
|
6267
|
+
this.poseTarget.props[u].copy(this.getPoseTemplateProp(u)), this.poseTarget.props[u].t = this.animClock, this.poseTarget.props[u].d = 1e3;
|
|
6268
6268
|
});
|
|
6269
6269
|
return o.length > 0;
|
|
6270
6270
|
}
|
|
@@ -6390,37 +6390,192 @@ class Be {
|
|
|
6390
6390
|
(e.isBone || e.type === "Bone") && t.add(e.name);
|
|
6391
6391
|
}), t;
|
|
6392
6392
|
}
|
|
6393
|
+
/**
|
|
6394
|
+
* Map bone names from different naming conventions to avatar bone names
|
|
6395
|
+
* @param {string} fbxBoneName - Bone name from FBX animation
|
|
6396
|
+
* @param {Set<string>} availableBones - Set of available bone names in avatar
|
|
6397
|
+
* @returns {string|null} Mapped bone name or null if no match found
|
|
6398
|
+
*/
|
|
6399
|
+
mapBoneName(t, e) {
|
|
6400
|
+
if (e.has(t))
|
|
6401
|
+
return t;
|
|
6402
|
+
let n = t;
|
|
6403
|
+
if (n.startsWith("CC_Base_") && (n = n.replace("CC_Base_", "")), n = n.replace(/^mixamorig/i, ""), e.has(n))
|
|
6404
|
+
return n;
|
|
6405
|
+
if (this._mappingDebugLog || (this._mappingDebugLog = /* @__PURE__ */ new Set()), this._mappingDebugLog.size < 5 && !this._mappingDebugLog.has(t) && (this._mappingDebugLog.add(t), console.debug(`Mapping attempt: "${t}" -> "${n}" (not found in available bones)`)), n.match(/^Spine\d+$/)) {
|
|
6406
|
+
const a = n.match(/\d+/)?.[0];
|
|
6407
|
+
if (a) {
|
|
6408
|
+
const c = `Spine${parseInt(a)}`;
|
|
6409
|
+
if (e.has(c))
|
|
6410
|
+
return c;
|
|
6411
|
+
if (a === "01" && e.has("Spine1"))
|
|
6412
|
+
return "Spine1";
|
|
6413
|
+
if (parseInt(a) >= 2 && e.has("Spine2"))
|
|
6414
|
+
return "Spine2";
|
|
6415
|
+
}
|
|
6416
|
+
}
|
|
6417
|
+
if (n.includes("Twist"))
|
|
6418
|
+
return null;
|
|
6419
|
+
const i = {
|
|
6420
|
+
// Spine mapping
|
|
6421
|
+
Spine01: "Spine1",
|
|
6422
|
+
Spine02: "Spine2",
|
|
6423
|
+
Spine03: "Spine2",
|
|
6424
|
+
// Left arm mapping
|
|
6425
|
+
L_Upperarm: "LeftArm",
|
|
6426
|
+
L_Forearm: "LeftForeArm",
|
|
6427
|
+
L_Hand: "LeftHand",
|
|
6428
|
+
L_Shoulder: "LeftShoulder",
|
|
6429
|
+
L_Index1: "LeftHandIndex1",
|
|
6430
|
+
L_Index2: "LeftHandIndex2",
|
|
6431
|
+
L_Index3: "LeftHandIndex3",
|
|
6432
|
+
L_Middle1: "LeftHandMiddle1",
|
|
6433
|
+
L_Middle2: "LeftHandMiddle2",
|
|
6434
|
+
L_Middle3: "LeftHandMiddle3",
|
|
6435
|
+
L_Ring1: "LeftHandRing1",
|
|
6436
|
+
L_Ring2: "LeftHandRing2",
|
|
6437
|
+
L_Ring3: "LeftHandRing3",
|
|
6438
|
+
L_Pinky1: "LeftHandPinky1",
|
|
6439
|
+
L_Pinky2: "LeftHandPinky2",
|
|
6440
|
+
L_Pinky3: "LeftHandPinky3",
|
|
6441
|
+
L_Thumb1: "LeftHandThumb1",
|
|
6442
|
+
L_Thumb2: "LeftHandThumb2",
|
|
6443
|
+
L_Thumb3: "LeftHandThumb3",
|
|
6444
|
+
// Right arm mapping
|
|
6445
|
+
R_Upperarm: "RightArm",
|
|
6446
|
+
R_Forearm: "RightForeArm",
|
|
6447
|
+
R_Hand: "RightHand",
|
|
6448
|
+
R_Shoulder: "RightShoulder",
|
|
6449
|
+
R_Index1: "RightHandIndex1",
|
|
6450
|
+
R_Index2: "RightHandIndex2",
|
|
6451
|
+
R_Index3: "RightHandIndex3",
|
|
6452
|
+
R_Middle1: "RightHandMiddle1",
|
|
6453
|
+
R_Middle2: "RightHandMiddle2",
|
|
6454
|
+
R_Middle3: "RightHandMiddle3",
|
|
6455
|
+
R_Ring1: "RightHandRing1",
|
|
6456
|
+
R_Ring2: "RightHandRing2",
|
|
6457
|
+
R_Ring3: "RightHandRing3",
|
|
6458
|
+
R_Pinky1: "RightHandPinky1",
|
|
6459
|
+
R_Pinky2: "RightHandPinky2",
|
|
6460
|
+
R_Pinky3: "RightHandPinky3",
|
|
6461
|
+
R_Thumb1: "RightHandThumb1",
|
|
6462
|
+
R_Thumb2: "RightHandThumb2",
|
|
6463
|
+
R_Thumb3: "RightHandThumb3",
|
|
6464
|
+
// Leg mapping
|
|
6465
|
+
L_Thigh: "LeftUpLeg",
|
|
6466
|
+
L_Calf: "LeftLeg",
|
|
6467
|
+
L_Foot: "LeftFoot",
|
|
6468
|
+
R_Thigh: "RightUpLeg",
|
|
6469
|
+
R_Calf: "RightLeg",
|
|
6470
|
+
R_Foot: "RightFoot"
|
|
6471
|
+
};
|
|
6472
|
+
if (i[n]) {
|
|
6473
|
+
const a = i[n];
|
|
6474
|
+
if (e.has(a))
|
|
6475
|
+
return a;
|
|
6476
|
+
}
|
|
6477
|
+
const s = n.toLowerCase();
|
|
6478
|
+
n.charAt(0).toUpperCase() + n.slice(1).toLowerCase();
|
|
6479
|
+
const o = s.match(/^[rl]_index(\d+)$/);
|
|
6480
|
+
if (o) {
|
|
6481
|
+
const a = o[1], d = `${s.startsWith("r") ? "Right" : "Left"}HandIndex${a}`;
|
|
6482
|
+
if (e.has(d))
|
|
6483
|
+
return d;
|
|
6484
|
+
}
|
|
6485
|
+
const l = s.match(/^[rl]_pinky(\d+)$/);
|
|
6486
|
+
if (l) {
|
|
6487
|
+
const a = l[1], d = `${s.startsWith("r") ? "Right" : "Left"}HandPinky${a}`;
|
|
6488
|
+
if (e.has(d))
|
|
6489
|
+
return d;
|
|
6490
|
+
}
|
|
6491
|
+
const u = s.match(/^[rl]_ring(\d+)$/);
|
|
6492
|
+
if (u) {
|
|
6493
|
+
const a = u[1], d = `${s.startsWith("r") ? "Right" : "Left"}HandRing${a}`;
|
|
6494
|
+
if (e.has(d))
|
|
6495
|
+
return d;
|
|
6496
|
+
}
|
|
6497
|
+
const r = s.match(/^[rl]_middle(\d+)$/);
|
|
6498
|
+
if (r) {
|
|
6499
|
+
const a = r[1], d = `${s.startsWith("r") ? "Right" : "Left"}HandMiddle${a}`;
|
|
6500
|
+
if (e.has(d))
|
|
6501
|
+
return d;
|
|
6502
|
+
}
|
|
6503
|
+
const h = s.match(/^[rl]_thumb(\d+)$/);
|
|
6504
|
+
if (h) {
|
|
6505
|
+
const a = h[1], d = `${s.startsWith("r") ? "Right" : "Left"}HandThumb${a}`;
|
|
6506
|
+
if (e.has(d))
|
|
6507
|
+
return d;
|
|
6508
|
+
}
|
|
6509
|
+
if (s.match(/^[rl]_upperarm/)) {
|
|
6510
|
+
const c = `${s.startsWith("r") ? "Right" : "Left"}Arm`;
|
|
6511
|
+
if (e.has(c))
|
|
6512
|
+
return c;
|
|
6513
|
+
}
|
|
6514
|
+
if (s.includes("upperarmtwist") || s.includes("forearmtwist"))
|
|
6515
|
+
return null;
|
|
6516
|
+
if (s.match(/^[rl]_forearm/)) {
|
|
6517
|
+
const c = `${s.startsWith("r") ? "Right" : "Left"}ForeArm`;
|
|
6518
|
+
if (e.has(c))
|
|
6519
|
+
return c;
|
|
6520
|
+
}
|
|
6521
|
+
if (s.match(/^[rl]_hand$/)) {
|
|
6522
|
+
const c = `${s.startsWith("r") ? "Right" : "Left"}Hand`;
|
|
6523
|
+
if (e.has(c))
|
|
6524
|
+
return c;
|
|
6525
|
+
}
|
|
6526
|
+
for (const a of e)
|
|
6527
|
+
if (a.toLowerCase() === s)
|
|
6528
|
+
return a;
|
|
6529
|
+
return null;
|
|
6530
|
+
}
|
|
6393
6531
|
/**
|
|
6394
6532
|
* Filter animation tracks to only include bones that exist in the avatar
|
|
6533
|
+
* Maps bone names from different naming conventions to avatar bone names
|
|
6395
6534
|
* @param {THREE.AnimationClip} clip - Animation clip to filter
|
|
6396
6535
|
* @param {Set<string>} availableBones - Set of available bone names
|
|
6397
|
-
* @returns {THREE.AnimationClip} Filtered animation clip
|
|
6536
|
+
* @returns {THREE.AnimationClip} Filtered animation clip with mapped bone names
|
|
6398
6537
|
*/
|
|
6399
6538
|
filterAnimationTracks(t, e) {
|
|
6400
|
-
const n = [], i = /* @__PURE__ */ new Set();
|
|
6401
|
-
return
|
|
6402
|
-
|
|
6403
|
-
e.
|
|
6404
|
-
|
|
6539
|
+
const n = [], i = /* @__PURE__ */ new Set(), s = /* @__PURE__ */ new Map();
|
|
6540
|
+
return this._loggedAvailableBones || (console.log(
|
|
6541
|
+
"Available avatar bones:",
|
|
6542
|
+
Array.from(e).sort().slice(0, 50).join(", "),
|
|
6543
|
+
e.size > 50 ? `... (${e.size} total)` : ""
|
|
6544
|
+
), this._loggedAvailableBones = !0), t.tracks.forEach((o) => {
|
|
6545
|
+
const l = o.name.split("."), u = l[0], r = l[1], h = this.mapBoneName(u, e);
|
|
6546
|
+
if (h) {
|
|
6547
|
+
const a = `${h}.${r}`, c = o.clone();
|
|
6548
|
+
c.name = a, n.push(c), u !== h && s.set(u, h);
|
|
6549
|
+
} else
|
|
6550
|
+
i.add(u);
|
|
6551
|
+
}), s.size > 0 && console.info(
|
|
6552
|
+
`FBX animation "${t.name}": Mapped ${s.size} bone(s) to avatar skeleton:`,
|
|
6553
|
+
Array.from(s.entries()).slice(0, 5).map(([o, l]) => `${o} → ${l}`).join(", "),
|
|
6554
|
+
s.size > 5 ? "..." : ""
|
|
6555
|
+
), i.size > 0 && console.warn(
|
|
6556
|
+
`FBX animation "${t.name}" contains tracks for ${i.size} bone(s) that couldn't be mapped:`,
|
|
6557
|
+
Array.from(i).slice(0, 10).join(", "),
|
|
6558
|
+
i.size > 10 ? "..." : ""
|
|
6559
|
+
), n.length > 0 ? console.info(`Filtered ${t.tracks.length} tracks down to ${n.length} valid tracks (${s.size} mapped)`) : console.error(`No valid tracks found for animation "${t.name}". All bones are missing or couldn't be mapped.`), n.length === 0 ? null : new f.AnimationClip(t.name, t.duration, n);
|
|
6405
6560
|
}
|
|
6406
6561
|
async playAnimation(t, e = null, n = 10, i = 0, s = 0.01, o = !1) {
|
|
6407
6562
|
if (!this.armature) return;
|
|
6408
6563
|
this.positionWasLocked = !o, o ? console.log("Position locking disabled for FBX animation:", t) : (this.lockAvatarPosition(), console.log("Position locked immediately before FBX animation:", t));
|
|
6409
|
-
let l = this.animClips.find((
|
|
6564
|
+
let l = this.animClips.find((u) => u.url === t + "-" + i);
|
|
6410
6565
|
if (l) {
|
|
6411
|
-
let
|
|
6412
|
-
|
|
6566
|
+
let u = this.animQueue.find((a) => a.template.name === "pose");
|
|
6567
|
+
u && (u.ts[0] = 1 / 0), Object.entries(l.pose.props).forEach((a) => {
|
|
6413
6568
|
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;
|
|
6414
6569
|
}), 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 });
|
|
6415
|
-
const r = Math.ceil(n / l.clip.duration),
|
|
6416
|
-
|
|
6570
|
+
const r = Math.ceil(n / l.clip.duration), h = this.mixer.clipAction(l.clip);
|
|
6571
|
+
h.setLoop(f.LoopRepeat, r), h.clampWhenFinished = !0, this.currentFBXAction = h;
|
|
6417
6572
|
try {
|
|
6418
|
-
|
|
6573
|
+
h.fadeIn(0.5).play(), console.log("FBX animation started successfully:", t);
|
|
6419
6574
|
} catch (a) {
|
|
6420
6575
|
console.warn("FBX animation failed to start:", a), this.stopAnimation();
|
|
6421
6576
|
return;
|
|
6422
6577
|
}
|
|
6423
|
-
if (
|
|
6578
|
+
if (h.getClip().tracks.length === 0) {
|
|
6424
6579
|
console.warn("FBX animation has no valid tracks, stopping"), this.stopAnimation();
|
|
6425
6580
|
return;
|
|
6426
6581
|
}
|
|
@@ -6439,10 +6594,10 @@ class Be {
|
|
|
6439
6594
|
} catch (c) {
|
|
6440
6595
|
console.warn(`Could not verify file existence for ${t}, attempting to load anyway:`, c);
|
|
6441
6596
|
}
|
|
6442
|
-
const
|
|
6597
|
+
const h = new Ne();
|
|
6443
6598
|
let a;
|
|
6444
6599
|
try {
|
|
6445
|
-
a = await
|
|
6600
|
+
a = await h.loadAsync(t, e);
|
|
6446
6601
|
} catch (c) {
|
|
6447
6602
|
console.error(`Failed to load FBX animation from ${t}:`, c), console.error("Error details:", {
|
|
6448
6603
|
message: c.message,
|
|
@@ -6471,14 +6626,14 @@ class Be {
|
|
|
6471
6626
|
}
|
|
6472
6627
|
c = g;
|
|
6473
6628
|
const x = {};
|
|
6474
|
-
c.tracks.forEach((
|
|
6475
|
-
|
|
6476
|
-
const
|
|
6477
|
-
if (
|
|
6478
|
-
for (let p = 0; p <
|
|
6479
|
-
|
|
6480
|
-
x[
|
|
6481
|
-
} else
|
|
6629
|
+
c.tracks.forEach((I) => {
|
|
6630
|
+
I.name = I.name.replaceAll("mixamorig", "");
|
|
6631
|
+
const D = I.name.split(".");
|
|
6632
|
+
if (D[1] === "position") {
|
|
6633
|
+
for (let p = 0; p < I.values.length; p++)
|
|
6634
|
+
I.values[p] = I.values[p] * s;
|
|
6635
|
+
x[I.name] = new f.Vector3(I.values[0], I.values[1], I.values[2]);
|
|
6636
|
+
} else D[1] === "quaternion" ? x[I.name] = new f.Quaternion(I.values[0], I.values[1], I.values[2], I.values[3]) : D[1] === "rotation" && (x[D[0] + ".quaternion"] = new f.Quaternion().setFromEuler(new f.Euler(I.values[0], I.values[1], I.values[2], "XYZ")).normalize());
|
|
6482
6637
|
});
|
|
6483
6638
|
const b = { props: x };
|
|
6484
6639
|
x["Hips.position"] && (x["Hips.position"].y < 0.5 ? b.lying = !0 : b.standing = !0), this.animClips.push({
|
|
@@ -6514,25 +6669,25 @@ class Be {
|
|
|
6514
6669
|
if (!this.armature) return;
|
|
6515
6670
|
let o = this.poseTemplates[t];
|
|
6516
6671
|
if (!o) {
|
|
6517
|
-
const l = this.animPoses.find((
|
|
6672
|
+
const l = this.animPoses.find((u) => u.url === t + "-" + i);
|
|
6518
6673
|
l && (o = l.pose);
|
|
6519
6674
|
}
|
|
6520
6675
|
if (o) {
|
|
6521
6676
|
this.poseName = t, this.mixer = null;
|
|
6522
|
-
let l = this.animQueue.find((
|
|
6677
|
+
let l = this.animQueue.find((u) => u.template.name === "pose");
|
|
6523
6678
|
l && (l.ts[0] = this.animClock + n * 1e3 + 2e3), this.setPoseFromTemplate(o);
|
|
6524
6679
|
} else {
|
|
6525
|
-
let
|
|
6526
|
-
if (
|
|
6527
|
-
let r =
|
|
6528
|
-
const
|
|
6680
|
+
let u = await new Ne().loadAsync(t, e);
|
|
6681
|
+
if (u && u.animations && u.animations[i]) {
|
|
6682
|
+
let r = u.animations[i];
|
|
6683
|
+
const h = {};
|
|
6529
6684
|
r.tracks.forEach((c) => {
|
|
6530
6685
|
c.name = c.name.replaceAll("mixamorig", "");
|
|
6531
6686
|
const d = c.name.split(".");
|
|
6532
|
-
d[1] === "position" ?
|
|
6687
|
+
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());
|
|
6533
6688
|
});
|
|
6534
|
-
const a = { props:
|
|
6535
|
-
|
|
6689
|
+
const a = { props: h };
|
|
6690
|
+
h["Hips.position"] && (h["Hips.position"].y < 0.5 ? a.lying = !0 : a.standing = !0), this.animPoses.push({
|
|
6536
6691
|
url: t + "-" + i,
|
|
6537
6692
|
pose: a
|
|
6538
6693
|
}), this.playPose(t, e, n, i, s);
|
|
@@ -6561,10 +6716,10 @@ class Be {
|
|
|
6561
6716
|
let s = this.gestureTemplates[t];
|
|
6562
6717
|
if (s) {
|
|
6563
6718
|
this.gestureTimeout && (clearTimeout(this.gestureTimeout), this.gestureTimeout = null);
|
|
6564
|
-
let l = this.animQueue.findIndex((
|
|
6565
|
-
l !== -1 && (this.animQueue[l].ts = this.animQueue[l].ts.map((
|
|
6566
|
-
for (let [
|
|
6567
|
-
r.t = this.animClock, r.d = i, this.poseTarget.props.hasOwnProperty(
|
|
6719
|
+
let l = this.animQueue.findIndex((u) => u.template.name === "talkinghands");
|
|
6720
|
+
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));
|
|
6721
|
+
for (let [u, r] of Object.entries(this.gesture))
|
|
6722
|
+
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);
|
|
6568
6723
|
e && Number.isFinite(e) && (this.gestureTimeout = setTimeout(this.stopGesture.bind(this, i), 1e3 * e));
|
|
6569
6724
|
}
|
|
6570
6725
|
let o = this.animEmojis[t];
|
|
@@ -6572,15 +6727,15 @@ class Be {
|
|
|
6572
6727
|
this.lookAtCamera(500);
|
|
6573
6728
|
const l = this.animFactory(o);
|
|
6574
6729
|
if (l.gesture = !0, e && Number.isFinite(e)) {
|
|
6575
|
-
const
|
|
6576
|
-
if (e * 1e3 -
|
|
6730
|
+
const u = l.ts[0], h = l.ts[l.ts.length - 1] - u;
|
|
6731
|
+
if (e * 1e3 - h > 0) {
|
|
6577
6732
|
const c = [];
|
|
6578
6733
|
for (let x = 1; x < l.ts.length; x++) c.push(l.ts[x] - l.ts[x - 1]);
|
|
6579
|
-
const d = o.template?.rescale || c.map((x) => x /
|
|
6580
|
-
l.ts = l.ts.map((x, b,
|
|
6734
|
+
const d = o.template?.rescale || c.map((x) => x / h), g = e * 1e3 - h;
|
|
6735
|
+
l.ts = l.ts.map((x, b, I) => b === 0 ? u : I[b - 1] + c[b - 1] + d[b - 1] * g);
|
|
6581
6736
|
} else {
|
|
6582
|
-
const c = e * 1e3 /
|
|
6583
|
-
l.ts = l.ts.map((d) =>
|
|
6737
|
+
const c = e * 1e3 / h;
|
|
6738
|
+
l.ts = l.ts.map((d) => u + c * (d - u));
|
|
6584
6739
|
}
|
|
6585
6740
|
}
|
|
6586
6741
|
this.animQueue.push(l);
|
|
@@ -6610,19 +6765,19 @@ class Be {
|
|
|
6610
6765
|
* @param {numeric} [d=null] If set, apply in d milliseconds
|
|
6611
6766
|
*/
|
|
6612
6767
|
ikSolve(t, e = null, n = !1, i = null) {
|
|
6613
|
-
const s = new f.Vector3(), o = new f.Vector3(), l = new f.Vector3(),
|
|
6768
|
+
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);
|
|
6614
6769
|
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);
|
|
6615
6770
|
const g = this.ikMesh.getObjectByName(t.effector), x = t.links;
|
|
6616
|
-
x.forEach((
|
|
6617
|
-
|
|
6771
|
+
x.forEach((I) => {
|
|
6772
|
+
I.bone = this.ikMesh.getObjectByName(I.link), I.bone.quaternion.copy(this.getPoseTemplateProp(I.link + ".quaternion"));
|
|
6618
6773
|
}), d.updateMatrixWorld(!0);
|
|
6619
6774
|
const b = t.iterations || 10;
|
|
6620
6775
|
if (e)
|
|
6621
|
-
for (let
|
|
6622
|
-
let
|
|
6776
|
+
for (let I = 0; I < b; I++) {
|
|
6777
|
+
let D = !1;
|
|
6623
6778
|
for (let p = 0, M = x.length; p < M; p++) {
|
|
6624
6779
|
const z = x[p].bone;
|
|
6625
|
-
z.matrixWorld.decompose(
|
|
6780
|
+
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();
|
|
6626
6781
|
let y = s.dot(l);
|
|
6627
6782
|
y > 1 ? y = 1 : y < -1 && (y = -1), y = Math.acos(y), !(y < 1e-5) && (x[p].minAngle !== void 0 && y < x[p].minAngle && (y = x[p].minAngle), x[p].maxAngle !== void 0 && y > x[p].maxAngle && (y = x[p].maxAngle), a.crossVectors(l, s), a.normalize(), Q.setFromAxisAngle(a, y), z.quaternion.multiply(Q), z.rotation.setFromVector3(c.setFromEuler(z.rotation).clamp(new f.Vector3(
|
|
6628
6783
|
x[p].minx !== void 0 ? x[p].minx : -1 / 0,
|
|
@@ -6632,12 +6787,12 @@ class Be {
|
|
|
6632
6787
|
x[p].maxx !== void 0 ? x[p].maxx : 1 / 0,
|
|
6633
6788
|
x[p].maxy !== void 0 ? x[p].maxy : 1 / 0,
|
|
6634
6789
|
x[p].maxz !== void 0 ? x[p].maxz : 1 / 0
|
|
6635
|
-
))), z.updateMatrixWorld(!0),
|
|
6790
|
+
))), z.updateMatrixWorld(!0), D = !0);
|
|
6636
6791
|
}
|
|
6637
|
-
if (!
|
|
6792
|
+
if (!D) break;
|
|
6638
6793
|
}
|
|
6639
|
-
i && x.forEach((
|
|
6640
|
-
this.poseTarget.props[
|
|
6794
|
+
i && x.forEach((I) => {
|
|
6795
|
+
this.poseTarget.props[I.link + ".quaternion"].copy(I.bone.quaternion), this.poseTarget.props[I.link + ".quaternion"].t = this.animClock, this.poseTarget.props[I.link + ".quaternion"].d = i;
|
|
6641
6796
|
});
|
|
6642
6797
|
}
|
|
6643
6798
|
/**
|
|
@@ -6647,7 +6802,7 @@ class Be {
|
|
|
6647
6802
|
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();
|
|
6648
6803
|
}
|
|
6649
6804
|
}
|
|
6650
|
-
const
|
|
6805
|
+
const Ie = {
|
|
6651
6806
|
apiKey: "sk_ace57ef3ef65a92b9d3bee2a00183b78ca790bc3e10964f2",
|
|
6652
6807
|
// Replace with your actual API key (should start with sk_)
|
|
6653
6808
|
endpoint: "https://api.elevenlabs.io/v1/text-to-speech",
|
|
@@ -6690,10 +6845,10 @@ const Re = {
|
|
|
6690
6845
|
function Fe() {
|
|
6691
6846
|
return {
|
|
6692
6847
|
service: "elevenlabs",
|
|
6693
|
-
endpoint:
|
|
6694
|
-
apiKey:
|
|
6695
|
-
defaultVoice:
|
|
6696
|
-
voices:
|
|
6848
|
+
endpoint: Ie.endpoint,
|
|
6849
|
+
apiKey: Ie.apiKey,
|
|
6850
|
+
defaultVoice: Ie.defaultVoice,
|
|
6851
|
+
voices: Ie.voices
|
|
6697
6852
|
};
|
|
6698
6853
|
}
|
|
6699
6854
|
function kt() {
|
|
@@ -6714,9 +6869,9 @@ const Ve = Me(({
|
|
|
6714
6869
|
ttsVoice: s = null,
|
|
6715
6870
|
ttsApiKey: o = null,
|
|
6716
6871
|
bodyMovement: l = "idle",
|
|
6717
|
-
movementIntensity:
|
|
6872
|
+
movementIntensity: u = 0.5,
|
|
6718
6873
|
showFullAvatar: r = !0,
|
|
6719
|
-
cameraView:
|
|
6874
|
+
cameraView: h = "upper",
|
|
6720
6875
|
onReady: a = () => {
|
|
6721
6876
|
},
|
|
6722
6877
|
onLoading: c = () => {
|
|
@@ -6726,8 +6881,8 @@ const Ve = Me(({
|
|
|
6726
6881
|
className: g = "",
|
|
6727
6882
|
style: x = {},
|
|
6728
6883
|
animations: b = {}
|
|
6729
|
-
},
|
|
6730
|
-
const
|
|
6884
|
+
}, I) => {
|
|
6885
|
+
const D = N(null), p = N(null), M = N(r), z = N(null), y = N(null), E = N(!1), P = N({ remainingText: null, originalText: null, options: null }), W = N([]), oe = N(0), [S, Z] = ce(!0), [_, X] = ce(null), [$, se] = ce(!1), [ae, pe] = ce(!1);
|
|
6731
6886
|
de(() => {
|
|
6732
6887
|
E.current = ae;
|
|
6733
6888
|
}, [ae]), de(() => {
|
|
@@ -6744,8 +6899,8 @@ const Ve = Me(({
|
|
|
6744
6899
|
service: "elevenlabs",
|
|
6745
6900
|
endpoint: "https://api.elevenlabs.io/v1/text-to-speech",
|
|
6746
6901
|
apiKey: o || ee.apiKey,
|
|
6747
|
-
defaultVoice: s || ee.defaultVoice ||
|
|
6748
|
-
voices: ee.voices ||
|
|
6902
|
+
defaultVoice: s || ee.defaultVoice || Ie.defaultVoice,
|
|
6903
|
+
voices: ee.voices || Ie.voices
|
|
6749
6904
|
} : le === "deepgram" ? O = {
|
|
6750
6905
|
service: "deepgram",
|
|
6751
6906
|
endpoint: "https://api.deepgram.com/v1/speak",
|
|
@@ -6766,31 +6921,31 @@ const Ve = Me(({
|
|
|
6766
6921
|
lipsyncLang: "en",
|
|
6767
6922
|
showFullAvatar: r,
|
|
6768
6923
|
bodyMovement: l,
|
|
6769
|
-
movementIntensity:
|
|
6770
|
-
},
|
|
6924
|
+
movementIntensity: u
|
|
6925
|
+
}, R = {
|
|
6771
6926
|
ttsEndpoint: O.endpoint,
|
|
6772
6927
|
ttsApikey: O.apiKey,
|
|
6773
6928
|
ttsService: le,
|
|
6774
6929
|
lipsyncModules: ["en"],
|
|
6775
|
-
cameraView:
|
|
6930
|
+
cameraView: h
|
|
6776
6931
|
}, k = T(async () => {
|
|
6777
|
-
if (!(!
|
|
6932
|
+
if (!(!D.current || p.current))
|
|
6778
6933
|
try {
|
|
6779
|
-
if (Z(!0), X(null), p.current = new
|
|
6780
|
-
if (
|
|
6781
|
-
const J = Math.min(100, Math.round(
|
|
6934
|
+
if (Z(!0), X(null), p.current = new De(D.current, R), p.current.controls && (p.current.controls.enableRotate = !1, p.current.controls.enableZoom = !1, p.current.controls.enablePan = !1, p.current.controls.enableDamping = !1), b && Object.keys(b).length > 0 && (p.current.customAnimations = b), await p.current.showAvatar(v, (B) => {
|
|
6935
|
+
if (B.lengthComputable) {
|
|
6936
|
+
const J = Math.min(100, Math.round(B.loaded / B.total * 100));
|
|
6782
6937
|
c(J);
|
|
6783
6938
|
}
|
|
6784
|
-
}), await new Promise((
|
|
6939
|
+
}), await new Promise((B) => {
|
|
6785
6940
|
const J = () => {
|
|
6786
|
-
p.current.lipsync && Object.keys(p.current.lipsync).length > 0 ?
|
|
6941
|
+
p.current.lipsync && Object.keys(p.current.lipsync).length > 0 ? B() : setTimeout(J, 100);
|
|
6787
6942
|
};
|
|
6788
6943
|
J();
|
|
6789
6944
|
}), p.current && p.current.setShowFullAvatar)
|
|
6790
6945
|
try {
|
|
6791
6946
|
p.current.setShowFullAvatar(r);
|
|
6792
|
-
} catch (
|
|
6793
|
-
console.warn("Error setting full body mode on initialization:",
|
|
6947
|
+
} catch (B) {
|
|
6948
|
+
console.warn("Error setting full body mode on initialization:", B);
|
|
6794
6949
|
}
|
|
6795
6950
|
p.current && p.current.controls && (p.current.controls.enableRotate = !1, p.current.controls.enableZoom = !1, p.current.controls.enablePan = !1, p.current.controls.enableDamping = !1, p.current.controls.update()), Z(!1), se(!0), a(p.current);
|
|
6796
6951
|
const F = () => {
|
|
@@ -6802,16 +6957,16 @@ const Ve = Me(({
|
|
|
6802
6957
|
} catch (L) {
|
|
6803
6958
|
console.error("Error initializing TalkingHead:", L), X(L.message || "Failed to initialize avatar"), Z(!1), d(L);
|
|
6804
6959
|
}
|
|
6805
|
-
}, [G, t, e, n, i, s, o, r, l,
|
|
6960
|
+
}, [G, t, e, n, i, s, o, r, l, u, h]);
|
|
6806
6961
|
de(() => (k(), () => {
|
|
6807
6962
|
p.current && (p.current.stop(), p.current.dispose(), p.current = null);
|
|
6808
6963
|
}), [k]), de(() => {
|
|
6809
|
-
if (!
|
|
6810
|
-
const L = new ResizeObserver((
|
|
6811
|
-
for (const J of
|
|
6964
|
+
if (!D.current || !p.current) return;
|
|
6965
|
+
const L = new ResizeObserver((B) => {
|
|
6966
|
+
for (const J of B)
|
|
6812
6967
|
p.current && p.current.onResize && p.current.onResize();
|
|
6813
6968
|
});
|
|
6814
|
-
L.observe(
|
|
6969
|
+
L.observe(D.current);
|
|
6815
6970
|
const F = () => {
|
|
6816
6971
|
p.current && p.current.onResize && p.current.onResize();
|
|
6817
6972
|
};
|
|
@@ -6830,7 +6985,7 @@ const Ve = Me(({
|
|
|
6830
6985
|
if (p.current && $)
|
|
6831
6986
|
try {
|
|
6832
6987
|
y.current && (clearInterval(y.current), y.current = null), z.current = { text: L, options: F }, P.current = { remainingText: null, originalText: null, options: null };
|
|
6833
|
-
const
|
|
6988
|
+
const B = /[!\.\?\n\p{Extended_Pictographic}]/ug, J = L.split(B).map((Y) => Y.trim()).filter((Y) => Y.length > 0);
|
|
6834
6989
|
W.current = J, oe.current = 0, pe(!1), E.current = !1, await H();
|
|
6835
6990
|
const ge = {
|
|
6836
6991
|
...F,
|
|
@@ -6838,19 +6993,19 @@ const Ve = Me(({
|
|
|
6838
6993
|
};
|
|
6839
6994
|
if (F.onSpeechEnd && p.current) {
|
|
6840
6995
|
const Y = p.current;
|
|
6841
|
-
let
|
|
6996
|
+
let ue = null, Se = 0;
|
|
6842
6997
|
const Ae = 1200;
|
|
6843
6998
|
let be = !1;
|
|
6844
|
-
|
|
6999
|
+
ue = setInterval(() => {
|
|
6845
7000
|
if (Se++, E.current)
|
|
6846
7001
|
return;
|
|
6847
7002
|
if (Se > Ae) {
|
|
6848
|
-
if (
|
|
7003
|
+
if (ue && (clearInterval(ue), ue = null, y.current = null), !be && !E.current) {
|
|
6849
7004
|
be = !0;
|
|
6850
7005
|
try {
|
|
6851
7006
|
F.onSpeechEnd();
|
|
6852
|
-
} catch (
|
|
6853
|
-
console.error("Error in onSpeechEnd callback (timeout):",
|
|
7007
|
+
} catch (Be) {
|
|
7008
|
+
console.error("Error in onSpeechEnd callback (timeout):", Be);
|
|
6854
7009
|
}
|
|
6855
7010
|
}
|
|
6856
7011
|
return;
|
|
@@ -6858,7 +7013,7 @@ const Ve = Me(({
|
|
|
6858
7013
|
const ye = !Y.speechQueue || Y.speechQueue.length === 0, ke = !Y.audioPlaylist || Y.audioPlaylist.length === 0;
|
|
6859
7014
|
Y && Y.isSpeaking === !1 && ye && ke && Y.isAudioPlaying === !1 && !be && !E.current && setTimeout(() => {
|
|
6860
7015
|
if (Y && !E.current && Y.isSpeaking === !1 && (!Y.speechQueue || Y.speechQueue.length === 0) && (!Y.audioPlaylist || Y.audioPlaylist.length === 0) && Y.isAudioPlaying === !1 && !be && !E.current) {
|
|
6861
|
-
be = !0,
|
|
7016
|
+
be = !0, ue && (clearInterval(ue), ue = null, y.current = null);
|
|
6862
7017
|
try {
|
|
6863
7018
|
F.onSpeechEnd();
|
|
6864
7019
|
} catch (Ze) {
|
|
@@ -6866,31 +7021,31 @@ const Ve = Me(({
|
|
|
6866
7021
|
}
|
|
6867
7022
|
}
|
|
6868
7023
|
}, 100);
|
|
6869
|
-
}, 100), y.current =
|
|
7024
|
+
}, 100), y.current = ue;
|
|
6870
7025
|
}
|
|
6871
7026
|
p.current.lipsync && Object.keys(p.current.lipsync).length > 0 ? (p.current.setSlowdownRate && p.current.setSlowdownRate(1.05), p.current.speakText(L, ge)) : setTimeout(async () => {
|
|
6872
7027
|
await H(), p.current && p.current.lipsync && (p.current.setSlowdownRate && p.current.setSlowdownRate(1.05), p.current.speakText(L, ge));
|
|
6873
7028
|
}, 100);
|
|
6874
|
-
} catch (
|
|
6875
|
-
console.error("Error speaking text:",
|
|
7029
|
+
} catch (B) {
|
|
7030
|
+
console.error("Error speaking text:", B), X(B.message || "Failed to speak text");
|
|
6876
7031
|
}
|
|
6877
|
-
}, [$, H, v.lipsyncLang]),
|
|
7032
|
+
}, [$, H, v.lipsyncLang]), K = T(() => {
|
|
6878
7033
|
p.current && (p.current.stopSpeaking(), p.current.setSlowdownRate && p.current.setSlowdownRate(1), z.current = null, pe(!1));
|
|
6879
7034
|
}, []), j = T(() => {
|
|
6880
7035
|
if (p.current && p.current.pauseSpeaking) {
|
|
6881
7036
|
const L = p.current;
|
|
6882
7037
|
if (L.isSpeaking || L.audioPlaylist && L.audioPlaylist.length > 0 || L.speechQueue && L.speechQueue.length > 0) {
|
|
6883
7038
|
y.current && (clearInterval(y.current), y.current = null);
|
|
6884
|
-
let
|
|
7039
|
+
let B = "";
|
|
6885
7040
|
if (z.current && W.current.length > 0) {
|
|
6886
|
-
const J = W.current.length, ge = L.speechQueue ? L.speechQueue.filter((Ae) => Ae && Ae.text && Array.isArray(Ae.text) && Ae.text.length > 0).length : 0, Y = L.audioPlaylist && L.audioPlaylist.length > 0,
|
|
6887
|
-
if (
|
|
7041
|
+
const J = W.current.length, ge = L.speechQueue ? L.speechQueue.filter((Ae) => Ae && Ae.text && Array.isArray(Ae.text) && Ae.text.length > 0).length : 0, Y = L.audioPlaylist && L.audioPlaylist.length > 0, ue = ge + (Y ? 1 : 0), Se = J - ue;
|
|
7042
|
+
if (ue > 0 && Se < J && (B = W.current.slice(Se).join(". ").trim(), !B && ge > 0 && L.speechQueue)) {
|
|
6888
7043
|
const be = L.speechQueue.filter((ye) => ye && ye.text && Array.isArray(ye.text) && ye.text.length > 0).map((ye) => ye.text.map((ke) => ke.word || "").filter((ke) => ke.length > 0).join(" ")).filter((ye) => ye.length > 0).join(" ");
|
|
6889
|
-
be && be.trim() && (
|
|
7044
|
+
be && be.trim() && (B = be.trim());
|
|
6890
7045
|
}
|
|
6891
7046
|
}
|
|
6892
7047
|
z.current && (P.current = {
|
|
6893
|
-
remainingText:
|
|
7048
|
+
remainingText: B || null,
|
|
6894
7049
|
originalText: z.current.text,
|
|
6895
7050
|
options: z.current.options
|
|
6896
7051
|
}), L.speechQueue && (L.speechQueue.length = 0), p.current.pauseSpeaking(), E.current = !0, pe(!0);
|
|
@@ -6909,12 +7064,12 @@ const Ve = Me(({
|
|
|
6909
7064
|
return;
|
|
6910
7065
|
}
|
|
6911
7066
|
pe(!1), E.current = !1, await H();
|
|
6912
|
-
const
|
|
7067
|
+
const B = {
|
|
6913
7068
|
...F,
|
|
6914
7069
|
lipsyncLang: F.lipsyncLang || v.lipsyncLang || "en"
|
|
6915
7070
|
};
|
|
6916
7071
|
try {
|
|
6917
|
-
await U(L,
|
|
7072
|
+
await U(L, B);
|
|
6918
7073
|
} catch (J) {
|
|
6919
7074
|
console.error("Error resuming speech:", J), pe(!1), E.current = !1;
|
|
6920
7075
|
}
|
|
@@ -6963,9 +7118,9 @@ const Ve = Me(({
|
|
|
6963
7118
|
}, [b]), te = T(() => {
|
|
6964
7119
|
p.current && p.current.onResize && p.current.onResize();
|
|
6965
7120
|
}, []);
|
|
6966
|
-
return Ee(
|
|
7121
|
+
return Ee(I, () => ({
|
|
6967
7122
|
speakText: U,
|
|
6968
|
-
stopSpeaking:
|
|
7123
|
+
stopSpeaking: K,
|
|
6969
7124
|
pauseSpeaking: j,
|
|
6970
7125
|
resumeSpeaking: q,
|
|
6971
7126
|
resumeAudioContext: H,
|
|
@@ -7047,7 +7202,7 @@ const Ve = Me(({
|
|
|
7047
7202
|
/* @__PURE__ */ me(
|
|
7048
7203
|
"div",
|
|
7049
7204
|
{
|
|
7050
|
-
ref:
|
|
7205
|
+
ref: D,
|
|
7051
7206
|
className: "talking-head-viewer",
|
|
7052
7207
|
style: {
|
|
7053
7208
|
width: "100%",
|
|
@@ -7065,7 +7220,7 @@ const Ve = Me(({
|
|
|
7065
7220
|
fontSize: "18px",
|
|
7066
7221
|
zIndex: 10
|
|
7067
7222
|
}, children: "Loading avatar..." }),
|
|
7068
|
-
|
|
7223
|
+
_ && /* @__PURE__ */ me("div", { className: "error-overlay", style: {
|
|
7069
7224
|
position: "absolute",
|
|
7070
7225
|
top: "50%",
|
|
7071
7226
|
left: "50%",
|
|
@@ -7076,7 +7231,7 @@ const Ve = Me(({
|
|
|
7076
7231
|
zIndex: 10,
|
|
7077
7232
|
padding: "20px",
|
|
7078
7233
|
borderRadius: "8px"
|
|
7079
|
-
}, children:
|
|
7234
|
+
}, children: _ })
|
|
7080
7235
|
]
|
|
7081
7236
|
}
|
|
7082
7237
|
);
|
|
@@ -7094,7 +7249,7 @@ const pt = Me(({
|
|
|
7094
7249
|
style: s = {},
|
|
7095
7250
|
avatarConfig: o = {}
|
|
7096
7251
|
}, l) => {
|
|
7097
|
-
const
|
|
7252
|
+
const u = N(null), r = N(null), [h, a] = ce(!0), [c, d] = ce(null), [g, x] = ce(!1), b = Fe(), I = o.ttsService || b.service, D = I === "browser" ? {
|
|
7098
7253
|
endpoint: "",
|
|
7099
7254
|
apiKey: null,
|
|
7100
7255
|
defaultVoice: "Google US English"
|
|
@@ -7103,14 +7258,14 @@ const pt = Me(({
|
|
|
7103
7258
|
// Override API key if provided via avatarConfig
|
|
7104
7259
|
apiKey: o.ttsApiKey !== void 0 && o.ttsApiKey !== null ? o.ttsApiKey : b.apiKey,
|
|
7105
7260
|
// Override endpoint for ElevenLabs if service is explicitly set
|
|
7106
|
-
endpoint:
|
|
7261
|
+
endpoint: I === "elevenlabs" && o.ttsApiKey ? "https://api.elevenlabs.io/v1/text-to-speech" : b.endpoint
|
|
7107
7262
|
}, p = {
|
|
7108
7263
|
url: "/avatars/brunette.glb",
|
|
7109
7264
|
// Use brunette avatar (working glTF file)
|
|
7110
7265
|
body: "F",
|
|
7111
7266
|
avatarMood: "neutral",
|
|
7112
|
-
ttsLang:
|
|
7113
|
-
ttsVoice: o.ttsVoice ||
|
|
7267
|
+
ttsLang: I === "browser" ? "en-US" : "en",
|
|
7268
|
+
ttsVoice: o.ttsVoice || D.defaultVoice,
|
|
7114
7269
|
lipsyncLang: "en",
|
|
7115
7270
|
// English lip-sync
|
|
7116
7271
|
showFullAvatar: !0,
|
|
@@ -7119,35 +7274,35 @@ const pt = Me(({
|
|
|
7119
7274
|
movementIntensity: 0.5,
|
|
7120
7275
|
...o
|
|
7121
7276
|
}, M = {
|
|
7122
|
-
ttsEndpoint:
|
|
7123
|
-
ttsApikey:
|
|
7124
|
-
ttsService:
|
|
7277
|
+
ttsEndpoint: D.endpoint,
|
|
7278
|
+
ttsApikey: D.apiKey,
|
|
7279
|
+
ttsService: I,
|
|
7125
7280
|
lipsyncModules: ["en"],
|
|
7126
7281
|
cameraView: "upper"
|
|
7127
7282
|
}, z = T(async () => {
|
|
7128
|
-
if (!(!
|
|
7283
|
+
if (!(!u.current || r.current))
|
|
7129
7284
|
try {
|
|
7130
|
-
if (a(!0), d(null), r.current = new
|
|
7131
|
-
if (
|
|
7132
|
-
const X = Math.min(100, Math.round(
|
|
7285
|
+
if (a(!0), d(null), r.current = new De(u.current, M), await r.current.showAvatar(p, (_) => {
|
|
7286
|
+
if (_.lengthComputable) {
|
|
7287
|
+
const X = Math.min(100, Math.round(_.loaded / _.total * 100));
|
|
7133
7288
|
t(X);
|
|
7134
7289
|
}
|
|
7135
7290
|
}), r.current.morphs && r.current.morphs.length > 0) {
|
|
7136
|
-
const
|
|
7137
|
-
console.log("Available morph targets:", Object.keys(
|
|
7138
|
-
const X = Object.keys(
|
|
7291
|
+
const _ = r.current.morphs[0].morphTargetDictionary;
|
|
7292
|
+
console.log("Available morph targets:", Object.keys(_));
|
|
7293
|
+
const X = Object.keys(_).filter(($) => $.startsWith("viseme_"));
|
|
7139
7294
|
console.log("Viseme morph targets found:", X), X.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"));
|
|
7140
7295
|
}
|
|
7141
|
-
if (await new Promise((
|
|
7296
|
+
if (await new Promise((_) => {
|
|
7142
7297
|
const X = () => {
|
|
7143
|
-
r.current.lipsync && Object.keys(r.current.lipsync).length > 0 ? (console.log("Lip-sync modules loaded:", Object.keys(r.current.lipsync)),
|
|
7298
|
+
r.current.lipsync && Object.keys(r.current.lipsync).length > 0 ? (console.log("Lip-sync modules loaded:", Object.keys(r.current.lipsync)), _()) : (console.log("Waiting for lip-sync modules to load..."), setTimeout(X, 100));
|
|
7144
7299
|
};
|
|
7145
7300
|
X();
|
|
7146
7301
|
}), r.current && r.current.setShowFullAvatar)
|
|
7147
7302
|
try {
|
|
7148
7303
|
r.current.setShowFullAvatar(!0), console.log("Avatar initialized in full body mode");
|
|
7149
|
-
} catch (
|
|
7150
|
-
console.warn("Error setting full body mode on initialization:",
|
|
7304
|
+
} catch (_) {
|
|
7305
|
+
console.warn("Error setting full body mode on initialization:", _);
|
|
7151
7306
|
}
|
|
7152
7307
|
a(!1), x(!0), n(r.current);
|
|
7153
7308
|
const Z = () => {
|
|
@@ -7290,7 +7445,7 @@ const pt = Me(({
|
|
|
7290
7445
|
/* @__PURE__ */ me(
|
|
7291
7446
|
"div",
|
|
7292
7447
|
{
|
|
7293
|
-
ref:
|
|
7448
|
+
ref: u,
|
|
7294
7449
|
className: "talking-head-viewer",
|
|
7295
7450
|
style: {
|
|
7296
7451
|
width: "100%",
|
|
@@ -7299,7 +7454,7 @@ const pt = Me(({
|
|
|
7299
7454
|
}
|
|
7300
7455
|
}
|
|
7301
7456
|
),
|
|
7302
|
-
|
|
7457
|
+
h && /* @__PURE__ */ me("div", { className: "loading-overlay", style: {
|
|
7303
7458
|
position: "absolute",
|
|
7304
7459
|
top: "50%",
|
|
7305
7460
|
left: "50%",
|
|
@@ -7332,9 +7487,9 @@ const gt = Me(({
|
|
|
7332
7487
|
ttsService: s = null,
|
|
7333
7488
|
ttsVoice: o = null,
|
|
7334
7489
|
ttsApiKey: l = null,
|
|
7335
|
-
bodyMovement:
|
|
7490
|
+
bodyMovement: u = "idle",
|
|
7336
7491
|
movementIntensity: r = 0.5,
|
|
7337
|
-
showFullAvatar:
|
|
7492
|
+
showFullAvatar: h = !1,
|
|
7338
7493
|
cameraView: a = "upper",
|
|
7339
7494
|
onReady: c = () => {
|
|
7340
7495
|
},
|
|
@@ -7345,36 +7500,36 @@ const gt = Me(({
|
|
|
7345
7500
|
onSpeechEnd: x = () => {
|
|
7346
7501
|
},
|
|
7347
7502
|
className: b = "",
|
|
7348
|
-
style:
|
|
7349
|
-
animations:
|
|
7503
|
+
style: I = {},
|
|
7504
|
+
animations: D = {},
|
|
7350
7505
|
autoSpeak: p = !1
|
|
7351
7506
|
}, M) => {
|
|
7352
|
-
const z =
|
|
7507
|
+
const z = N(null), y = N(null), E = N(h), P = N(null), W = N(null), oe = N(!1), S = N({ remainingText: null, originalText: null, options: null }), Z = N([]), [_, X] = ce(!0), [$, se] = ce(null), [ae, pe] = ce(!1), [ee, le] = ce(!1);
|
|
7353
7508
|
de(() => {
|
|
7354
7509
|
oe.current = ee;
|
|
7355
7510
|
}, [ee]), de(() => {
|
|
7356
|
-
E.current =
|
|
7357
|
-
}, [
|
|
7511
|
+
E.current = h;
|
|
7512
|
+
}, [h]);
|
|
7358
7513
|
const O = Fe(), v = s || O.service;
|
|
7359
|
-
let
|
|
7360
|
-
v === "browser" ?
|
|
7514
|
+
let R;
|
|
7515
|
+
v === "browser" ? R = {
|
|
7361
7516
|
service: "browser",
|
|
7362
7517
|
endpoint: "",
|
|
7363
7518
|
apiKey: null,
|
|
7364
7519
|
defaultVoice: "Google US English"
|
|
7365
|
-
} : v === "elevenlabs" ?
|
|
7520
|
+
} : v === "elevenlabs" ? R = {
|
|
7366
7521
|
service: "elevenlabs",
|
|
7367
7522
|
endpoint: "https://api.elevenlabs.io/v1/text-to-speech",
|
|
7368
7523
|
apiKey: l || O.apiKey,
|
|
7369
|
-
defaultVoice: o || O.defaultVoice ||
|
|
7370
|
-
voices: O.voices ||
|
|
7371
|
-
} : v === "deepgram" ?
|
|
7524
|
+
defaultVoice: o || O.defaultVoice || Ie.defaultVoice,
|
|
7525
|
+
voices: O.voices || Ie.voices
|
|
7526
|
+
} : v === "deepgram" ? R = {
|
|
7372
7527
|
service: "deepgram",
|
|
7373
7528
|
endpoint: "https://api.deepgram.com/v1/speak",
|
|
7374
7529
|
apiKey: l || O.apiKey,
|
|
7375
7530
|
defaultVoice: o || O.defaultVoice || Te.defaultVoice,
|
|
7376
7531
|
voices: O.voices || Te.voices
|
|
7377
|
-
} :
|
|
7532
|
+
} : R = {
|
|
7378
7533
|
...O,
|
|
7379
7534
|
apiKey: l !== null ? l : O.apiKey
|
|
7380
7535
|
};
|
|
@@ -7383,21 +7538,21 @@ const gt = Me(({
|
|
|
7383
7538
|
body: e,
|
|
7384
7539
|
avatarMood: n,
|
|
7385
7540
|
ttsLang: v === "browser" ? "en-US" : i,
|
|
7386
|
-
ttsVoice: o ||
|
|
7541
|
+
ttsVoice: o || R.defaultVoice,
|
|
7387
7542
|
lipsyncLang: "en",
|
|
7388
|
-
showFullAvatar:
|
|
7389
|
-
bodyMovement:
|
|
7543
|
+
showFullAvatar: h,
|
|
7544
|
+
bodyMovement: u,
|
|
7390
7545
|
movementIntensity: r
|
|
7391
7546
|
}, H = {
|
|
7392
|
-
ttsEndpoint:
|
|
7393
|
-
ttsApikey:
|
|
7547
|
+
ttsEndpoint: R.endpoint,
|
|
7548
|
+
ttsApikey: R.apiKey,
|
|
7394
7549
|
ttsService: v,
|
|
7395
7550
|
lipsyncModules: ["en"],
|
|
7396
7551
|
cameraView: a
|
|
7397
7552
|
}, U = T(async () => {
|
|
7398
7553
|
if (!(!z.current || y.current))
|
|
7399
7554
|
try {
|
|
7400
|
-
X(!0), se(null), y.current = new
|
|
7555
|
+
X(!0), se(null), y.current = new De(z.current, H), console.log("Avatar config being passed:", {
|
|
7401
7556
|
url: k.url,
|
|
7402
7557
|
body: k.body,
|
|
7403
7558
|
avatarMood: k.avatarMood
|
|
@@ -7420,7 +7575,7 @@ const gt = Me(({
|
|
|
7420
7575
|
de(() => (U(), () => {
|
|
7421
7576
|
y.current && (y.current.stop(), y.current.dispose(), y.current = null);
|
|
7422
7577
|
}), [U]);
|
|
7423
|
-
const
|
|
7578
|
+
const K = T(async () => {
|
|
7424
7579
|
if (y.current)
|
|
7425
7580
|
try {
|
|
7426
7581
|
const C = y.current.audioCtx || y.current.audioContext;
|
|
@@ -7437,8 +7592,8 @@ const gt = Me(({
|
|
|
7437
7592
|
console.warn("No text provided to speak");
|
|
7438
7593
|
return;
|
|
7439
7594
|
}
|
|
7440
|
-
await
|
|
7441
|
-
const L = C.split(/[.!?]+/).filter((
|
|
7595
|
+
await K(), S.current = { remainingText: null, originalText: null, options: null }, Z.current = [], P.current = { text: C, options: te }, W.current && (clearInterval(W.current), W.current = null), le(!1), oe.current = !1;
|
|
7596
|
+
const L = C.split(/[.!?]+/).filter((B) => B.trim().length > 0);
|
|
7442
7597
|
Z.current = L;
|
|
7443
7598
|
const F = {
|
|
7444
7599
|
lipsyncLang: te.lipsyncLang || "en",
|
|
@@ -7448,10 +7603,10 @@ const gt = Me(({
|
|
|
7448
7603
|
};
|
|
7449
7604
|
try {
|
|
7450
7605
|
y.current.speakText(C, F);
|
|
7451
|
-
} catch (
|
|
7452
|
-
console.error("Error speaking text:",
|
|
7606
|
+
} catch (B) {
|
|
7607
|
+
console.error("Error speaking text:", B), se(B.message || "Failed to speak text");
|
|
7453
7608
|
}
|
|
7454
|
-
}, [ae, x,
|
|
7609
|
+
}, [ae, x, K]);
|
|
7455
7610
|
de(() => {
|
|
7456
7611
|
ae && G && p && y.current && j(G);
|
|
7457
7612
|
}, [ae, G, p, j]);
|
|
@@ -7462,7 +7617,7 @@ const gt = Me(({
|
|
|
7462
7617
|
if (C || te.length > 0 || L.length > 0) {
|
|
7463
7618
|
W.current && (clearInterval(W.current), W.current = null);
|
|
7464
7619
|
let F = "";
|
|
7465
|
-
L.length > 0 && (F = L.map((
|
|
7620
|
+
L.length > 0 && (F = L.map((B) => B.text && Array.isArray(B.text) ? B.text.map((J) => J.word).join(" ") : B.text || "").join(" ")), S.current = {
|
|
7466
7621
|
remainingText: F || null,
|
|
7467
7622
|
originalText: P.current?.text || null,
|
|
7468
7623
|
options: P.current?.options || null
|
|
@@ -7474,13 +7629,13 @@ const gt = Me(({
|
|
|
7474
7629
|
}, []), Le = T(async () => {
|
|
7475
7630
|
if (!(!y.current || !ee))
|
|
7476
7631
|
try {
|
|
7477
|
-
await
|
|
7632
|
+
await K(), le(!1), oe.current = !1;
|
|
7478
7633
|
const C = S.current?.remainingText, te = S.current?.originalText || P.current?.text, L = S.current?.options || P.current?.options || {}, F = C || te;
|
|
7479
7634
|
F && j(F, L);
|
|
7480
7635
|
} catch (C) {
|
|
7481
7636
|
console.warn("Error resuming speech:", C), le(!1), oe.current = !1;
|
|
7482
7637
|
}
|
|
7483
|
-
}, [ee, j,
|
|
7638
|
+
}, [ee, j, K]), we = T(() => {
|
|
7484
7639
|
y.current && (y.current.stopSpeaking(), W.current && (clearInterval(W.current), W.current = null), le(!1), oe.current = !1);
|
|
7485
7640
|
}, []);
|
|
7486
7641
|
return Ee(M, () => ({
|
|
@@ -7488,7 +7643,7 @@ const gt = Me(({
|
|
|
7488
7643
|
pauseSpeaking: q,
|
|
7489
7644
|
resumeSpeaking: Le,
|
|
7490
7645
|
stopSpeaking: we,
|
|
7491
|
-
resumeAudioContext:
|
|
7646
|
+
resumeAudioContext: K,
|
|
7492
7647
|
isPaused: () => ee,
|
|
7493
7648
|
setMood: (C) => y.current?.setMood(C),
|
|
7494
7649
|
setBodyMovement: (C) => {
|
|
@@ -7504,7 +7659,7 @@ const gt = Me(({
|
|
|
7504
7659
|
},
|
|
7505
7660
|
isReady: ae,
|
|
7506
7661
|
talkingHead: y.current
|
|
7507
|
-
})), /* @__PURE__ */ Pe("div", { className: `simple-talking-avatar-container ${b}`, style:
|
|
7662
|
+
})), /* @__PURE__ */ Pe("div", { className: `simple-talking-avatar-container ${b}`, style: I, children: [
|
|
7508
7663
|
/* @__PURE__ */ me(
|
|
7509
7664
|
"div",
|
|
7510
7665
|
{
|
|
@@ -7517,7 +7672,7 @@ const gt = Me(({
|
|
|
7517
7672
|
}
|
|
7518
7673
|
}
|
|
7519
7674
|
),
|
|
7520
|
-
|
|
7675
|
+
_ && /* @__PURE__ */ me("div", { className: "loading-overlay", style: {
|
|
7521
7676
|
position: "absolute",
|
|
7522
7677
|
top: "50%",
|
|
7523
7678
|
left: "50%",
|
|
@@ -7555,9 +7710,9 @@ const yt = Me(({
|
|
|
7555
7710
|
},
|
|
7556
7711
|
onCustomAction: l = () => {
|
|
7557
7712
|
},
|
|
7558
|
-
autoStart:
|
|
7713
|
+
autoStart: u = !1
|
|
7559
7714
|
}, r) => {
|
|
7560
|
-
const
|
|
7715
|
+
const h = N(null), a = N({
|
|
7561
7716
|
currentModuleIndex: 0,
|
|
7562
7717
|
currentLessonIndex: 0,
|
|
7563
7718
|
currentQuestionIndex: 0,
|
|
@@ -7567,18 +7722,18 @@ const yt = Me(({
|
|
|
7567
7722
|
curriculumCompleted: !1,
|
|
7568
7723
|
score: 0,
|
|
7569
7724
|
totalQuestions: 0
|
|
7570
|
-
}), c =
|
|
7725
|
+
}), c = N({
|
|
7571
7726
|
onLessonStart: n,
|
|
7572
7727
|
onLessonComplete: i,
|
|
7573
7728
|
onQuestionAnswer: s,
|
|
7574
7729
|
onCurriculumComplete: o,
|
|
7575
7730
|
onCustomAction: l
|
|
7576
|
-
}), d =
|
|
7731
|
+
}), d = N(null), g = N(null), x = N(null), b = N(null), I = N(null), D = N(null), p = N(null), M = N(G?.curriculum || {
|
|
7577
7732
|
title: "Default Curriculum",
|
|
7578
7733
|
description: "No curriculum data provided",
|
|
7579
7734
|
language: "en",
|
|
7580
7735
|
modules: []
|
|
7581
|
-
}), z =
|
|
7736
|
+
}), z = N({
|
|
7582
7737
|
avatarUrl: t.avatarUrl || "/avatars/brunette.glb",
|
|
7583
7738
|
avatarBody: t.avatarBody || "F",
|
|
7584
7739
|
mood: t.mood || "happy",
|
|
@@ -7621,11 +7776,11 @@ const yt = Me(({
|
|
|
7621
7776
|
lipsyncLang: "en"
|
|
7622
7777
|
};
|
|
7623
7778
|
}, [G, t, e]);
|
|
7624
|
-
const y = T(() => (M.current || { modules: [] }).modules[a.current.currentModuleIndex]?.lessons[a.current.currentLessonIndex], []), E = T(() => y()?.questions[a.current.currentQuestionIndex], [y]), P = T((v,
|
|
7779
|
+
const y = T(() => (M.current || { modules: [] }).modules[a.current.currentModuleIndex]?.lessons[a.current.currentLessonIndex], []), E = T(() => y()?.questions[a.current.currentQuestionIndex], [y]), P = T((v, R) => R.type === "multiple_choice" || R.type === "true_false" ? v === R.answer : R.type === "code_test" && typeof v == "object" && v !== null ? v.passed === !0 : !1, []), W = T(() => {
|
|
7625
7780
|
a.current.lessonCompleted = !0, a.current.isQuestionMode = !1;
|
|
7626
7781
|
const v = a.current.totalQuestions > 0 ? Math.round(a.current.score / a.current.totalQuestions * 100) : 100;
|
|
7627
|
-
let
|
|
7628
|
-
if (a.current.totalQuestions > 0 ?
|
|
7782
|
+
let R = "Congratulations! You've completed this lesson";
|
|
7783
|
+
if (a.current.totalQuestions > 0 ? R += ` You got ${a.current.score} correct out of ${a.current.totalQuestions} question${a.current.totalQuestions === 1 ? "" : "s"}, achieving a score of ${v} percent. ` : R += "! ", v >= 80 ? R += "Excellent work! You have a great understanding of this topic." : v >= 60 ? R += "Good job! You understand most of the concepts." : R += "Keep practicing! You're making progress.", c.current.onLessonComplete({
|
|
7629
7784
|
moduleIndex: a.current.currentModuleIndex,
|
|
7630
7785
|
lessonIndex: a.current.currentLessonIndex,
|
|
7631
7786
|
score: a.current.score,
|
|
@@ -7638,15 +7793,15 @@ const yt = Me(({
|
|
|
7638
7793
|
score: a.current.score,
|
|
7639
7794
|
totalQuestions: a.current.totalQuestions,
|
|
7640
7795
|
percentage: v
|
|
7641
|
-
}),
|
|
7642
|
-
if (
|
|
7796
|
+
}), h.current) {
|
|
7797
|
+
if (h.current.setMood("happy"), e.lessonComplete)
|
|
7643
7798
|
try {
|
|
7644
|
-
|
|
7799
|
+
h.current.playAnimation(e.lessonComplete, !0);
|
|
7645
7800
|
} catch {
|
|
7646
|
-
|
|
7801
|
+
h.current.playCelebration();
|
|
7647
7802
|
}
|
|
7648
|
-
const k = M.current || { modules: [] }, H = k.modules[a.current.currentModuleIndex], U = a.current.currentLessonIndex < (H?.lessons?.length || 0) - 1,
|
|
7649
|
-
|
|
7803
|
+
const k = M.current || { modules: [] }, H = k.modules[a.current.currentModuleIndex], U = a.current.currentLessonIndex < (H?.lessons?.length || 0) - 1, K = a.current.currentModuleIndex < (k.modules?.length || 0) - 1, j = U || K, q = z.current || { lipsyncLang: "en" };
|
|
7804
|
+
h.current.speakText(R, {
|
|
7650
7805
|
lipsyncLang: q.lipsyncLang,
|
|
7651
7806
|
onSpeechEnd: () => {
|
|
7652
7807
|
c.current.onCustomAction({
|
|
@@ -7666,49 +7821,49 @@ const yt = Me(({
|
|
|
7666
7821
|
const v = M.current || { modules: [] };
|
|
7667
7822
|
if (c.current.onCurriculumComplete({
|
|
7668
7823
|
modules: v.modules.length,
|
|
7669
|
-
totalLessons: v.modules.reduce((
|
|
7670
|
-
}),
|
|
7671
|
-
if (
|
|
7824
|
+
totalLessons: v.modules.reduce((R, k) => R + k.lessons.length, 0)
|
|
7825
|
+
}), h.current) {
|
|
7826
|
+
if (h.current.setMood("celebrating"), e.curriculumComplete)
|
|
7672
7827
|
try {
|
|
7673
|
-
|
|
7828
|
+
h.current.playAnimation(e.curriculumComplete, !0);
|
|
7674
7829
|
} catch {
|
|
7675
|
-
|
|
7830
|
+
h.current.playCelebration();
|
|
7676
7831
|
}
|
|
7677
|
-
const
|
|
7678
|
-
|
|
7832
|
+
const R = z.current || { lipsyncLang: "en" };
|
|
7833
|
+
h.current.speakText("Amazing! You've completed the entire curriculum! You're now ready to move on to more advanced topics. Well done!", { lipsyncLang: R.lipsyncLang });
|
|
7679
7834
|
}
|
|
7680
7835
|
}, [e.curriculumComplete]), S = T(() => {
|
|
7681
7836
|
const v = y();
|
|
7682
7837
|
a.current.isQuestionMode = !0, a.current.currentQuestionIndex = 0, a.current.totalQuestions = v?.questions?.length || 0, a.current.score = 0;
|
|
7683
|
-
const
|
|
7684
|
-
|
|
7838
|
+
const R = E();
|
|
7839
|
+
R && c.current.onCustomAction({
|
|
7685
7840
|
type: "questionStart",
|
|
7686
7841
|
moduleIndex: a.current.currentModuleIndex,
|
|
7687
7842
|
lessonIndex: a.current.currentLessonIndex,
|
|
7688
7843
|
questionIndex: a.current.currentQuestionIndex,
|
|
7689
7844
|
totalQuestions: a.current.totalQuestions,
|
|
7690
|
-
question:
|
|
7845
|
+
question: R,
|
|
7691
7846
|
score: a.current.score
|
|
7692
7847
|
});
|
|
7693
7848
|
const k = () => {
|
|
7694
|
-
if (!
|
|
7695
|
-
if (
|
|
7849
|
+
if (!h.current || !R) return;
|
|
7850
|
+
if (h.current.setMood("happy"), e.questionStart)
|
|
7696
7851
|
try {
|
|
7697
|
-
|
|
7852
|
+
h.current.playAnimation(e.questionStart, !0);
|
|
7698
7853
|
} catch (U) {
|
|
7699
7854
|
console.warn("Failed to play questionStart animation:", U);
|
|
7700
7855
|
}
|
|
7701
7856
|
const H = z.current || { lipsyncLang: "en" };
|
|
7702
|
-
|
|
7857
|
+
R.type === "code_test" ? h.current.speakText(`Let's test your coding skills! Here's your first challenge: ${R.question}`, { lipsyncLang: H.lipsyncLang }) : R.type === "multiple_choice" ? h.current.speakText(`Now let me ask you some questions. Here's the first one: ${R.question}`, { lipsyncLang: H.lipsyncLang }) : R.type === "true_false" ? h.current.speakText(`Let's start with some true or false questions. First question: ${R.question}`, { lipsyncLang: H.lipsyncLang }) : h.current.speakText(`Now let me ask you some questions. Here's the first one: ${R.question}`, { lipsyncLang: H.lipsyncLang });
|
|
7703
7858
|
};
|
|
7704
|
-
if (
|
|
7859
|
+
if (h.current && h.current.isReady && R)
|
|
7705
7860
|
k();
|
|
7706
|
-
else if (
|
|
7861
|
+
else if (h.current && h.current.isReady) {
|
|
7707
7862
|
const H = z.current || { lipsyncLang: "en" };
|
|
7708
|
-
|
|
7863
|
+
h.current.speakText("Now let me ask you some questions to test your understanding.", { lipsyncLang: H.lipsyncLang });
|
|
7709
7864
|
} else {
|
|
7710
7865
|
const H = setInterval(() => {
|
|
7711
|
-
|
|
7866
|
+
h.current && h.current.isReady && (clearInterval(H), R && k());
|
|
7712
7867
|
}, 100);
|
|
7713
7868
|
setTimeout(() => {
|
|
7714
7869
|
clearInterval(H);
|
|
@@ -7717,53 +7872,53 @@ const yt = Me(({
|
|
|
7717
7872
|
}, [e.questionStart, y, E]), Z = T(() => {
|
|
7718
7873
|
const v = y();
|
|
7719
7874
|
if (a.current.currentQuestionIndex < (v?.questions?.length || 0) - 1) {
|
|
7720
|
-
|
|
7721
|
-
const
|
|
7722
|
-
|
|
7875
|
+
h.current && h.current.stopSpeaking && h.current.stopSpeaking(), a.current.currentQuestionIndex += 1;
|
|
7876
|
+
const R = E();
|
|
7877
|
+
R && c.current.onCustomAction({
|
|
7723
7878
|
type: "nextQuestion",
|
|
7724
7879
|
moduleIndex: a.current.currentModuleIndex,
|
|
7725
7880
|
lessonIndex: a.current.currentLessonIndex,
|
|
7726
7881
|
questionIndex: a.current.currentQuestionIndex,
|
|
7727
7882
|
totalQuestions: a.current.totalQuestions,
|
|
7728
|
-
question:
|
|
7883
|
+
question: R,
|
|
7729
7884
|
score: a.current.score
|
|
7730
7885
|
});
|
|
7731
7886
|
const k = () => {
|
|
7732
|
-
if (!
|
|
7733
|
-
if (
|
|
7887
|
+
if (!h.current || !R) return;
|
|
7888
|
+
if (h.current.setMood("happy"), h.current.setBodyMovement("idle"), e.nextQuestion)
|
|
7734
7889
|
try {
|
|
7735
|
-
|
|
7890
|
+
h.current.playAnimation(e.nextQuestion, !0);
|
|
7736
7891
|
} catch (q) {
|
|
7737
7892
|
console.warn("Failed to play nextQuestion animation:", q);
|
|
7738
7893
|
}
|
|
7739
|
-
const H = z.current || { lipsyncLang: "en" },
|
|
7740
|
-
if (
|
|
7741
|
-
const q = j ? `Great! Here's your final coding challenge: ${
|
|
7742
|
-
|
|
7894
|
+
const H = z.current || { lipsyncLang: "en" }, K = y()?.questions?.length || 0, j = a.current.currentQuestionIndex >= K - 1;
|
|
7895
|
+
if (R.type === "code_test") {
|
|
7896
|
+
const q = j ? `Great! Here's your final coding challenge: ${R.question}` : `Great! Now let's move on to your next coding challenge: ${R.question}`;
|
|
7897
|
+
h.current.speakText(q, {
|
|
7743
7898
|
lipsyncLang: H.lipsyncLang
|
|
7744
7899
|
});
|
|
7745
|
-
} else if (
|
|
7746
|
-
const q = j ? `Alright! Here's your final question: ${
|
|
7747
|
-
|
|
7900
|
+
} else if (R.type === "multiple_choice") {
|
|
7901
|
+
const q = j ? `Alright! Here's your final question: ${R.question}` : `Alright! Here's your next question: ${R.question}`;
|
|
7902
|
+
h.current.speakText(q, {
|
|
7748
7903
|
lipsyncLang: H.lipsyncLang
|
|
7749
7904
|
});
|
|
7750
|
-
} else if (
|
|
7751
|
-
const q = j ? `Now let's try this final one: ${
|
|
7752
|
-
|
|
7905
|
+
} else if (R.type === "true_false") {
|
|
7906
|
+
const q = j ? `Now let's try this final one: ${R.question}` : `Now let's try this one: ${R.question}`;
|
|
7907
|
+
h.current.speakText(q, {
|
|
7753
7908
|
lipsyncLang: H.lipsyncLang
|
|
7754
7909
|
});
|
|
7755
7910
|
} else {
|
|
7756
|
-
const q = j ? `Here's your final question: ${
|
|
7757
|
-
|
|
7911
|
+
const q = j ? `Here's your final question: ${R.question}` : `Here's the next question: ${R.question}`;
|
|
7912
|
+
h.current.speakText(q, {
|
|
7758
7913
|
lipsyncLang: H.lipsyncLang
|
|
7759
7914
|
});
|
|
7760
7915
|
}
|
|
7761
7916
|
};
|
|
7762
|
-
if (
|
|
7917
|
+
if (h.current && h.current.isReady && R)
|
|
7763
7918
|
k();
|
|
7764
|
-
else if (
|
|
7919
|
+
else if (R) {
|
|
7765
7920
|
const H = setInterval(() => {
|
|
7766
|
-
|
|
7921
|
+
h.current && h.current.isReady && (clearInterval(H), k());
|
|
7767
7922
|
}, 100);
|
|
7768
7923
|
setTimeout(() => {
|
|
7769
7924
|
clearInterval(H);
|
|
@@ -7777,11 +7932,11 @@ const yt = Me(({
|
|
|
7777
7932
|
totalQuestions: a.current.totalQuestions,
|
|
7778
7933
|
score: a.current.score
|
|
7779
7934
|
});
|
|
7780
|
-
}, [e.nextQuestion, y, E]),
|
|
7781
|
-
const v = M.current || { modules: [] },
|
|
7782
|
-
if (a.current.currentLessonIndex < (
|
|
7935
|
+
}, [e.nextQuestion, y, E]), _ = T(() => {
|
|
7936
|
+
const v = M.current || { modules: [] }, R = v.modules[a.current.currentModuleIndex];
|
|
7937
|
+
if (a.current.currentLessonIndex < (R?.lessons?.length || 0) - 1) {
|
|
7783
7938
|
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;
|
|
7784
|
-
const H = v.modules[a.current.currentModuleIndex], U = a.current.currentLessonIndex < (H?.lessons?.length || 0) - 1,
|
|
7939
|
+
const H = v.modules[a.current.currentModuleIndex], U = a.current.currentLessonIndex < (H?.lessons?.length || 0) - 1, K = a.current.currentModuleIndex < (v.modules?.length || 0) - 1, j = U || K;
|
|
7785
7940
|
c.current.onCustomAction({
|
|
7786
7941
|
type: "lessonStart",
|
|
7787
7942
|
moduleIndex: a.current.currentModuleIndex,
|
|
@@ -7791,10 +7946,10 @@ const yt = Me(({
|
|
|
7791
7946
|
moduleIndex: a.current.currentModuleIndex,
|
|
7792
7947
|
lessonIndex: a.current.currentLessonIndex,
|
|
7793
7948
|
lesson: y()
|
|
7794
|
-
}),
|
|
7949
|
+
}), h.current && (h.current.setMood("happy"), h.current.setBodyMovement("idle"));
|
|
7795
7950
|
} else if (a.current.currentModuleIndex < (v.modules?.length || 0) - 1) {
|
|
7796
7951
|
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;
|
|
7797
|
-
const U = v.modules[a.current.currentModuleIndex],
|
|
7952
|
+
const U = v.modules[a.current.currentModuleIndex], K = a.current.currentLessonIndex < (U?.lessons?.length || 0) - 1, j = a.current.currentModuleIndex < (v.modules?.length || 0) - 1, q = K || j;
|
|
7798
7953
|
c.current.onCustomAction({
|
|
7799
7954
|
type: "lessonStart",
|
|
7800
7955
|
moduleIndex: a.current.currentModuleIndex,
|
|
@@ -7804,27 +7959,27 @@ const yt = Me(({
|
|
|
7804
7959
|
moduleIndex: a.current.currentModuleIndex,
|
|
7805
7960
|
lessonIndex: a.current.currentLessonIndex,
|
|
7806
7961
|
lesson: y()
|
|
7807
|
-
}),
|
|
7962
|
+
}), h.current && (h.current.setMood("happy"), h.current.setBodyMovement("idle"));
|
|
7808
7963
|
} else
|
|
7809
|
-
|
|
7964
|
+
I.current && I.current();
|
|
7810
7965
|
}, []), X = T(() => {
|
|
7811
7966
|
const v = y();
|
|
7812
|
-
let
|
|
7967
|
+
let R = null;
|
|
7813
7968
|
if (v?.avatar_script && v?.body) {
|
|
7814
7969
|
const k = v.avatar_script.trim(), H = v.body.trim(), U = k.match(/[.!?]$/) ? " " : ". ";
|
|
7815
|
-
|
|
7970
|
+
R = `${k}${U}${H}`;
|
|
7816
7971
|
} else
|
|
7817
|
-
|
|
7818
|
-
if (
|
|
7819
|
-
a.current.isTeaching = !0, a.current.isQuestionMode = !1, a.current.score = 0, a.current.totalQuestions = 0,
|
|
7972
|
+
R = v?.avatar_script || v?.body || null;
|
|
7973
|
+
if (h.current && h.current.isReady && R) {
|
|
7974
|
+
a.current.isTeaching = !0, a.current.isQuestionMode = !1, a.current.score = 0, a.current.totalQuestions = 0, h.current.setMood("happy");
|
|
7820
7975
|
let k = !1;
|
|
7821
7976
|
if (e.teaching)
|
|
7822
7977
|
try {
|
|
7823
|
-
|
|
7978
|
+
h.current.playAnimation(e.teaching, !0), k = !0;
|
|
7824
7979
|
} catch (U) {
|
|
7825
7980
|
console.warn("Failed to play teaching animation:", U);
|
|
7826
7981
|
}
|
|
7827
|
-
k ||
|
|
7982
|
+
k || h.current.setBodyMovement("gesturing");
|
|
7828
7983
|
const H = z.current || { lipsyncLang: "en" };
|
|
7829
7984
|
c.current.onLessonStart({
|
|
7830
7985
|
moduleIndex: a.current.currentModuleIndex,
|
|
@@ -7835,7 +7990,7 @@ const yt = Me(({
|
|
|
7835
7990
|
moduleIndex: a.current.currentModuleIndex,
|
|
7836
7991
|
lessonIndex: a.current.currentLessonIndex,
|
|
7837
7992
|
lesson: v
|
|
7838
|
-
}),
|
|
7993
|
+
}), h.current.speakText(R, {
|
|
7839
7994
|
lipsyncLang: H.lipsyncLang,
|
|
7840
7995
|
onSpeechEnd: () => {
|
|
7841
7996
|
a.current.isTeaching = !1, c.current.onCustomAction({
|
|
@@ -7855,29 +8010,29 @@ const yt = Me(({
|
|
|
7855
8010
|
});
|
|
7856
8011
|
}
|
|
7857
8012
|
}, [e.teaching, y]), $ = T((v) => {
|
|
7858
|
-
const
|
|
8013
|
+
const R = E(), k = P(v, R);
|
|
7859
8014
|
if (k && (a.current.score += 1), c.current.onQuestionAnswer({
|
|
7860
8015
|
moduleIndex: a.current.currentModuleIndex,
|
|
7861
8016
|
lessonIndex: a.current.currentLessonIndex,
|
|
7862
8017
|
questionIndex: a.current.currentQuestionIndex,
|
|
7863
8018
|
answer: v,
|
|
7864
8019
|
isCorrect: k,
|
|
7865
|
-
question:
|
|
7866
|
-
}),
|
|
8020
|
+
question: R
|
|
8021
|
+
}), h.current)
|
|
7867
8022
|
if (k) {
|
|
7868
|
-
if (
|
|
8023
|
+
if (h.current.setMood("happy"), e.correct)
|
|
7869
8024
|
try {
|
|
7870
|
-
|
|
8025
|
+
h.current.playReaction("happy");
|
|
7871
8026
|
} catch {
|
|
7872
|
-
|
|
8027
|
+
h.current.setBodyMovement("happy");
|
|
7873
8028
|
}
|
|
7874
|
-
|
|
8029
|
+
h.current.setBodyMovement("gesturing");
|
|
7875
8030
|
const U = y()?.questions?.length || 0;
|
|
7876
8031
|
a.current.currentQuestionIndex >= U - 1;
|
|
7877
|
-
const
|
|
7878
|
-
console.log("[CurriculumLearning] Answer feedback - questionIndex:", a.current.currentQuestionIndex, "totalQuestions:", U, "hasNextQuestion:",
|
|
7879
|
-
const j =
|
|
7880
|
-
|
|
8032
|
+
const K = a.current.currentQuestionIndex < U - 1;
|
|
8033
|
+
console.log("[CurriculumLearning] Answer feedback - questionIndex:", a.current.currentQuestionIndex, "totalQuestions:", U, "hasNextQuestion:", K);
|
|
8034
|
+
const j = R.type === "code_test" ? `Great job! Your code passed all the tests! ${R.explanation || ""}` : `Excellent! That's correct! ${R.explanation || ""}`, q = z.current || { lipsyncLang: "en" };
|
|
8035
|
+
h.current.speakText(j, {
|
|
7881
8036
|
lipsyncLang: q.lipsyncLang,
|
|
7882
8037
|
onSpeechEnd: () => {
|
|
7883
8038
|
c.current.onCustomAction({
|
|
@@ -7886,24 +8041,24 @@ const yt = Me(({
|
|
|
7886
8041
|
lessonIndex: a.current.currentLessonIndex,
|
|
7887
8042
|
questionIndex: a.current.currentQuestionIndex,
|
|
7888
8043
|
isCorrect: !0,
|
|
7889
|
-
hasNextQuestion:
|
|
8044
|
+
hasNextQuestion: K,
|
|
7890
8045
|
score: a.current.score,
|
|
7891
8046
|
totalQuestions: a.current.totalQuestions
|
|
7892
8047
|
});
|
|
7893
8048
|
}
|
|
7894
8049
|
});
|
|
7895
8050
|
} else {
|
|
7896
|
-
if (
|
|
8051
|
+
if (h.current.setMood("sad"), e.incorrect)
|
|
7897
8052
|
try {
|
|
7898
|
-
|
|
8053
|
+
h.current.playAnimation(e.incorrect, !0);
|
|
7899
8054
|
} catch {
|
|
7900
|
-
|
|
8055
|
+
h.current.setBodyMovement("idle");
|
|
7901
8056
|
}
|
|
7902
|
-
|
|
7903
|
-
const U = y()?.questions?.length || 0,
|
|
8057
|
+
h.current.setBodyMovement("gesturing");
|
|
8058
|
+
const U = y()?.questions?.length || 0, K = a.current.currentQuestionIndex >= U - 1, j = a.current.currentQuestionIndex < U - 1;
|
|
7904
8059
|
console.log("[CurriculumLearning] Answer feedback (incorrect) - questionIndex:", a.current.currentQuestionIndex, "totalQuestions:", U, "hasNextQuestion:", j);
|
|
7905
|
-
const q =
|
|
7906
|
-
|
|
8060
|
+
const q = R.type === "code_test" ? `Your code didn't pass all the tests. ${R.explanation || "Try again!"}` : `Not quite right, but don't worry! ${R.explanation || ""}${K ? "" : " Let's move on to the next question."}`, Le = z.current || { lipsyncLang: "en" };
|
|
8061
|
+
h.current.speakText(q, {
|
|
7907
8062
|
lipsyncLang: Le.lipsyncLang,
|
|
7908
8063
|
onSpeechEnd: () => {
|
|
7909
8064
|
c.current.onCustomAction({
|
|
@@ -7934,12 +8089,12 @@ const yt = Me(({
|
|
|
7934
8089
|
});
|
|
7935
8090
|
}
|
|
7936
8091
|
}, [e.correct, e.incorrect, E, y, P]), se = T((v) => {
|
|
7937
|
-
const
|
|
8092
|
+
const R = E();
|
|
7938
8093
|
if (!v || typeof v != "object") {
|
|
7939
8094
|
console.error("Invalid code test result format. Expected object with {passed: boolean, ...}");
|
|
7940
8095
|
return;
|
|
7941
8096
|
}
|
|
7942
|
-
if (
|
|
8097
|
+
if (R?.type !== "code_test") {
|
|
7943
8098
|
console.warn("Current question is not a code test. Use handleAnswerSelect for other question types.");
|
|
7944
8099
|
return;
|
|
7945
8100
|
}
|
|
@@ -7959,7 +8114,7 @@ const yt = Me(({
|
|
|
7959
8114
|
lessonIndex: a.current.currentLessonIndex,
|
|
7960
8115
|
questionIndex: a.current.currentQuestionIndex,
|
|
7961
8116
|
testResult: k,
|
|
7962
|
-
question:
|
|
8117
|
+
question: R
|
|
7963
8118
|
}), p.current && p.current(k);
|
|
7964
8119
|
}, [E, P]), ae = T(() => {
|
|
7965
8120
|
if (a.current.currentQuestionIndex > 0) {
|
|
@@ -7974,21 +8129,21 @@ const yt = Me(({
|
|
|
7974
8129
|
question: v,
|
|
7975
8130
|
score: a.current.score
|
|
7976
8131
|
});
|
|
7977
|
-
const
|
|
7978
|
-
if (!
|
|
7979
|
-
|
|
8132
|
+
const R = () => {
|
|
8133
|
+
if (!h.current || !v) return;
|
|
8134
|
+
h.current.setMood("happy"), h.current.setBodyMovement("idle");
|
|
7980
8135
|
const k = z.current || { lipsyncLang: "en" };
|
|
7981
|
-
v.type === "code_test" ?
|
|
8136
|
+
v.type === "code_test" ? h.current.speakText(`Let's go back to this coding challenge: ${v.question}`, {
|
|
7982
8137
|
lipsyncLang: k.lipsyncLang
|
|
7983
|
-
}) :
|
|
8138
|
+
}) : h.current.speakText(`Going back to: ${v.question}`, {
|
|
7984
8139
|
lipsyncLang: k.lipsyncLang
|
|
7985
8140
|
});
|
|
7986
8141
|
};
|
|
7987
|
-
if (
|
|
7988
|
-
|
|
8142
|
+
if (h.current && h.current.isReady && v)
|
|
8143
|
+
R();
|
|
7989
8144
|
else if (v) {
|
|
7990
8145
|
const k = setInterval(() => {
|
|
7991
|
-
|
|
8146
|
+
h.current && h.current.isReady && (clearInterval(k), R());
|
|
7992
8147
|
}, 100);
|
|
7993
8148
|
setTimeout(() => {
|
|
7994
8149
|
clearInterval(k);
|
|
@@ -8006,7 +8161,7 @@ const yt = Me(({
|
|
|
8006
8161
|
moduleIndex: a.current.currentModuleIndex,
|
|
8007
8162
|
lessonIndex: a.current.currentLessonIndex,
|
|
8008
8163
|
lesson: y()
|
|
8009
|
-
}),
|
|
8164
|
+
}), h.current && (h.current.setMood("happy"), h.current.setBodyMovement("idle"));
|
|
8010
8165
|
else if (a.current.currentModuleIndex > 0) {
|
|
8011
8166
|
const H = v.modules[a.current.currentModuleIndex - 1];
|
|
8012
8167
|
a.current.currentModuleIndex -= 1, a.current.currentLessonIndex = (H?.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({
|
|
@@ -8017,19 +8172,19 @@ const yt = Me(({
|
|
|
8017
8172
|
moduleIndex: a.current.currentModuleIndex,
|
|
8018
8173
|
lessonIndex: a.current.currentLessonIndex,
|
|
8019
8174
|
lesson: y()
|
|
8020
|
-
}),
|
|
8175
|
+
}), h.current && (h.current.setMood("happy"), h.current.setBodyMovement("idle"));
|
|
8021
8176
|
}
|
|
8022
8177
|
}, [y]), ee = T(() => {
|
|
8023
8178
|
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;
|
|
8024
8179
|
}, []), le = T((v) => {
|
|
8025
8180
|
console.log("Avatar is ready!", v);
|
|
8026
|
-
const
|
|
8027
|
-
|
|
8181
|
+
const R = y(), k = R?.avatar_script || R?.body;
|
|
8182
|
+
u && k && setTimeout(() => {
|
|
8028
8183
|
d.current && d.current();
|
|
8029
8184
|
}, 10);
|
|
8030
|
-
}, [
|
|
8185
|
+
}, [u, y]);
|
|
8031
8186
|
Xe(() => {
|
|
8032
|
-
d.current = X, g.current =
|
|
8187
|
+
d.current = X, g.current = _, x.current = W, b.current = Z, I.current = oe, D.current = S, p.current = $;
|
|
8033
8188
|
}), Ee(r, () => ({
|
|
8034
8189
|
// Curriculum control methods
|
|
8035
8190
|
startTeaching: X,
|
|
@@ -8038,7 +8193,7 @@ const yt = Me(({
|
|
|
8038
8193
|
handleCodeTestResult: se,
|
|
8039
8194
|
nextQuestion: Z,
|
|
8040
8195
|
previousQuestion: ae,
|
|
8041
|
-
nextLesson:
|
|
8196
|
+
nextLesson: _,
|
|
8042
8197
|
previousLesson: pe,
|
|
8043
8198
|
completeLesson: W,
|
|
8044
8199
|
completeCurriculum: oe,
|
|
@@ -8047,56 +8202,56 @@ const yt = Me(({
|
|
|
8047
8202
|
getCurrentQuestion: () => E(),
|
|
8048
8203
|
getCurrentLesson: () => y(),
|
|
8049
8204
|
// Direct access to avatar ref (always returns current value)
|
|
8050
|
-
getAvatarRef: () =>
|
|
8205
|
+
getAvatarRef: () => h.current,
|
|
8051
8206
|
// Convenience methods that delegate to avatar (always check current ref)
|
|
8052
|
-
speakText: async (v,
|
|
8053
|
-
await
|
|
8207
|
+
speakText: async (v, R = {}) => {
|
|
8208
|
+
await h.current?.resumeAudioContext?.();
|
|
8054
8209
|
const k = z.current || { lipsyncLang: "en" };
|
|
8055
|
-
|
|
8210
|
+
h.current?.speakText(v, { ...R, lipsyncLang: R.lipsyncLang || k.lipsyncLang });
|
|
8056
8211
|
},
|
|
8057
8212
|
resumeAudioContext: async () => {
|
|
8058
|
-
if (
|
|
8059
|
-
return await
|
|
8060
|
-
const v =
|
|
8213
|
+
if (h.current?.resumeAudioContext)
|
|
8214
|
+
return await h.current.resumeAudioContext();
|
|
8215
|
+
const v = h.current?.talkingHead;
|
|
8061
8216
|
if (v?.audioCtx) {
|
|
8062
|
-
const
|
|
8063
|
-
if (
|
|
8217
|
+
const R = v.audioCtx;
|
|
8218
|
+
if (R.state === "suspended" || R.state === "interrupted")
|
|
8064
8219
|
try {
|
|
8065
|
-
await
|
|
8220
|
+
await R.resume(), console.log("Audio context resumed via talkingHead");
|
|
8066
8221
|
} catch (k) {
|
|
8067
8222
|
console.warn("Failed to resume audio context:", k);
|
|
8068
8223
|
}
|
|
8069
8224
|
} else
|
|
8070
8225
|
console.warn("Audio context not available yet");
|
|
8071
8226
|
},
|
|
8072
|
-
stopSpeaking: () =>
|
|
8073
|
-
pauseSpeaking: () =>
|
|
8074
|
-
resumeSpeaking: async () => await
|
|
8075
|
-
isPaused: () =>
|
|
8076
|
-
setMood: (v) =>
|
|
8077
|
-
playAnimation: (v,
|
|
8078
|
-
setBodyMovement: (v) =>
|
|
8079
|
-
setMovementIntensity: (v) =>
|
|
8080
|
-
playRandomDance: () =>
|
|
8081
|
-
playReaction: (v) =>
|
|
8082
|
-
playCelebration: () =>
|
|
8083
|
-
setShowFullAvatar: (v) =>
|
|
8084
|
-
setTimingAdjustment: (v) =>
|
|
8085
|
-
lockAvatarPosition: () =>
|
|
8086
|
-
unlockAvatarPosition: () =>
|
|
8227
|
+
stopSpeaking: () => h.current?.stopSpeaking(),
|
|
8228
|
+
pauseSpeaking: () => h.current?.pauseSpeaking(),
|
|
8229
|
+
resumeSpeaking: async () => await h.current?.resumeSpeaking(),
|
|
8230
|
+
isPaused: () => h.current && typeof h.current.isPaused < "u" ? h.current.isPaused : !1,
|
|
8231
|
+
setMood: (v) => h.current?.setMood(v),
|
|
8232
|
+
playAnimation: (v, R) => h.current?.playAnimation(v, R),
|
|
8233
|
+
setBodyMovement: (v) => h.current?.setBodyMovement(v),
|
|
8234
|
+
setMovementIntensity: (v) => h.current?.setMovementIntensity(v),
|
|
8235
|
+
playRandomDance: () => h.current?.playRandomDance(),
|
|
8236
|
+
playReaction: (v) => h.current?.playReaction(v),
|
|
8237
|
+
playCelebration: () => h.current?.playCelebration(),
|
|
8238
|
+
setShowFullAvatar: (v) => h.current?.setShowFullAvatar(v),
|
|
8239
|
+
setTimingAdjustment: (v) => h.current?.setTimingAdjustment(v),
|
|
8240
|
+
lockAvatarPosition: () => h.current?.lockAvatarPosition(),
|
|
8241
|
+
unlockAvatarPosition: () => h.current?.unlockAvatarPosition(),
|
|
8087
8242
|
// Custom action trigger
|
|
8088
|
-
triggerCustomAction: (v,
|
|
8243
|
+
triggerCustomAction: (v, R) => {
|
|
8089
8244
|
c.current.onCustomAction({
|
|
8090
8245
|
type: v,
|
|
8091
|
-
...
|
|
8246
|
+
...R,
|
|
8092
8247
|
state: { ...a.current }
|
|
8093
8248
|
});
|
|
8094
8249
|
},
|
|
8095
8250
|
// Responsive resize handler
|
|
8096
|
-
handleResize: () =>
|
|
8251
|
+
handleResize: () => h.current?.handleResize(),
|
|
8097
8252
|
// Avatar readiness check (always returns current value)
|
|
8098
|
-
isAvatarReady: () =>
|
|
8099
|
-
}), [X, S, $, se, Z,
|
|
8253
|
+
isAvatarReady: () => h.current?.isReady || !1
|
|
8254
|
+
}), [X, S, $, se, Z, _, W, oe, ee, E, y]);
|
|
8100
8255
|
const O = z.current || {
|
|
8101
8256
|
avatarUrl: "/avatars/brunette.glb",
|
|
8102
8257
|
avatarBody: "F",
|
|
@@ -8113,7 +8268,7 @@ const yt = Me(({
|
|
|
8113
8268
|
return /* @__PURE__ */ me("div", { style: { width: "100%", height: "100%" }, children: /* @__PURE__ */ me(
|
|
8114
8269
|
Ve,
|
|
8115
8270
|
{
|
|
8116
|
-
ref:
|
|
8271
|
+
ref: h,
|
|
8117
8272
|
avatarUrl: O.avatarUrl,
|
|
8118
8273
|
avatarBody: O.avatarBody,
|
|
8119
8274
|
mood: O.mood,
|