@sage-rsc/talking-head-react 1.1.7 → 1.1.8
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 +951 -875
- package/package.json +1 -1
- package/src/lib/talkinghead.mjs +141 -0
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
|
|
3
|
-
import * as
|
|
2
|
+
import { forwardRef as Me, useRef as O, useState as ce, useEffect as de, useCallback as F, useImperativeHandle as Ee, useLayoutEffect as Xe } from "react";
|
|
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 De } from "three/addons/loaders/FBXLoader.js";
|
|
8
8
|
import { RoomEnvironment as qe } from "three/addons/environments/RoomEnvironment.js";
|
|
9
9
|
import Ke from "three/addons/libs/stats.module.js";
|
|
10
10
|
let m, re, ue;
|
|
11
|
-
const
|
|
12
|
-
new
|
|
13
|
-
new
|
|
14
|
-
new
|
|
15
|
-
const
|
|
16
|
-
new
|
|
17
|
-
const He = new
|
|
11
|
+
const S = [0, 0, 0, 0], C = new f.Vector3(), ze = new f.Vector3(), ie = new f.Vector3(), Ce = new f.Vector3();
|
|
12
|
+
new f.Plane();
|
|
13
|
+
new f.Ray();
|
|
14
|
+
new f.Euler();
|
|
15
|
+
const oe = new f.Quaternion(), Oe = new f.Quaternion(), fe = new f.Matrix4(), xe = new f.Matrix4();
|
|
16
|
+
new f.Vector3();
|
|
17
|
+
const He = new f.Vector3(0, 0, 1), _e = 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({
|
|
@@ -321,7 +321,7 @@ class et {
|
|
|
321
321
|
/// Bone's parent object
|
|
322
322
|
vBasis: r.position.clone(),
|
|
323
323
|
// Original local position
|
|
324
|
-
vWorld: r.parent.getWorldPosition(
|
|
324
|
+
vWorld: r.parent.getWorldPosition(C).clone(),
|
|
325
325
|
// World position, parent
|
|
326
326
|
qBasis: r.parent.quaternion.clone(),
|
|
327
327
|
// Original quaternion, parent
|
|
@@ -338,7 +338,7 @@ class et {
|
|
|
338
338
|
ea: [0, 0, 0, 0]
|
|
339
339
|
// External acceleration [m/s^2]
|
|
340
340
|
};
|
|
341
|
-
u.boneParent.matrixWorld.decompose(
|
|
341
|
+
u.boneParent.matrixWorld.decompose(C, oe, ie), C.copy(He).applyQuaternion(oe).setY(0).normalize(), oe.premultiply(Oe.setFromUnitVectors(He, C).invert()).normalize(), u.qWorldInverseYaw = oe.clone().normalize(), this.data.push(u), this.dict[h] = u;
|
|
342
342
|
try {
|
|
343
343
|
this.setValue(h, "type", s.type), this.setValue(h, "stiffness", s.stiffness), this.setValue(h, "damping", s.damping), this.setValue(h, "external", s.external), this.setValue(h, "limits", s.limits), this.setValue(h, "excludes", s.excludes), this.setValue(h, "deltaLocal", s.deltaLocal), this.setValue(h, "deltaWorld", s.deltaWorld), this.setValue(h, "pivot", s.pivot), this.setValue(h, "helper", s.helper);
|
|
344
344
|
} catch (a) {
|
|
@@ -356,22 +356,22 @@ class et {
|
|
|
356
356
|
for (this.timerMs += t, t > 1e3 && (this.timerMs = 0), t /= 1e3, e = 0, i = this.objectsUpdate.length; e < i; e++)
|
|
357
357
|
o = this.objectsUpdate[e], o.updateMatrix(), o.parent === null ? o.matrixWorld.copy(o.matrix) : o.matrixWorld.multiplyMatrices(o.parent.matrixWorld, o.matrix), o.matrixWorldNeedsUpdate = !1;
|
|
358
358
|
for (e = 0, i = this.data.length; e < i; e++) {
|
|
359
|
-
if (o = this.data[e],
|
|
359
|
+
if (o = this.data[e], C.copy(o.vWorld), fe.copy(o.boneParent.matrixWorld), xe.copy(fe).invert(), o.vWorld.setFromMatrixPosition(fe), C.applyMatrix4(xe), C.length() > 0.5 && (console.info("Info: Unrealistic jump of " + C.length().toFixed(2) + " meters."), C.setLength(0.5)), C.applyQuaternion(o.bone.quaternion), S[0] = C.x, S[1] = C.y, S[2] = -C.z, S[3] = C.length() / 3, o.children)
|
|
360
360
|
for (n = 0, s = o.children.length; n < s; n++)
|
|
361
|
-
m = o.children[n],
|
|
362
|
-
if (m = this.opt.sensitivityFactor,
|
|
363
|
-
o.vBasis.x +
|
|
364
|
-
o.vBasis.y +
|
|
365
|
-
o.vBasis.z +
|
|
366
|
-
),
|
|
361
|
+
m = o.children[n], S[0] -= m.v[0] * t / 3, S[1] -= m.v[1] * t / 3, S[2] += m.v[2] * t / 3, S[3] -= m.v[3] * t / 3;
|
|
362
|
+
if (m = this.opt.sensitivityFactor, S[0] *= o.ext * m, S[1] *= o.ext * m, S[2] *= o.ext * m, S[3] *= o.ext * m, o.isX && (m = S[0] / t, o.ea[0] = (m - o.ev[0]) / t, o.ev[0] = m, o.a[0] = -o.k[0] * o.p[0] - o.c[0] * o.v[0] - o.ea[0], o.p[0] += o.v[0] * t + o.a[0] * t * t / 2 + S[0], m = o.v[0] + o.a[0] * t / 2, m = -o.k[0] * o.p[0] - o.c[0] * m - o.ea[0], o.v[0] = o.v[0] + (m + o.a[0]) * t / 2), o.isY && (m = S[1] / t, o.ea[1] = (m - o.ev[1]) / t, o.ev[1] = m, o.a[1] = -o.k[1] * o.p[1] - o.c[1] * o.v[1] - o.ea[1], o.p[1] += o.v[1] * t + o.a[1] * t * t / 2 + S[1], m = o.v[1] + o.a[1] * t / 2, m = -o.k[1] * o.p[1] - o.c[1] * m - o.ea[1], o.v[1] = o.v[1] + (m + o.a[1]) * t / 2), o.isZ && (m = S[2] / t, o.ea[2] = (m - o.ev[2]) / t, o.ev[2] = m, o.a[2] = -o.k[2] * o.p[2] - o.c[2] * o.v[2] - o.ea[2], o.p[2] += o.v[2] * t + o.a[2] * t * t / 2 + S[2], m = o.v[2] + o.a[2] * t / 2, m = -o.k[2] * o.p[2] - o.c[2] * m - o.ea[2], o.v[2] = o.v[2] + (m + o.a[2]) * t / 2), o.isT && (m = S[3] / t, o.ea[3] = (m - o.ev[3]) / t, o.ev[3] = m, o.a[3] = -o.k[3] * o.p[3] - o.c[3] * o.v[3] - o.ea[3], o.p[3] += o.v[3] * t + o.a[3] * t * t / 2 + S[3], m = o.v[3] + o.a[3] * t / 2, m = -o.k[3] * o.p[3] - o.c[3] * m - o.ea[3], o.v[3] = o.v[3] + (m + o.a[3]) * t / 2), this.timerMs < this.opt.warmupMs && (o.v[0] *= 1e-4, o.p[0] *= 1e-4, o.v[1] *= 1e-4, o.p[1] *= 1e-4, o.v[2] *= 1e-4, o.p[2] *= 1e-4, o.v[3] *= 1e-4, o.p[3] *= 1e-4), S[0] = o.p[0], S[1] = o.p[1], S[2] = o.p[2], S[3] = o.p[3], m = this.opt.movementFactor, S[0] *= m, S[1] *= m, S[2] *= m, S[3] *= m, o.dl && (m = o.dl, S[0] += m[0], S[1] += m[1], S[2] += m[2]), o.dw && (m = o.dw, C.set(
|
|
363
|
+
o.vBasis.x + S[0],
|
|
364
|
+
o.vBasis.y + S[1],
|
|
365
|
+
o.vBasis.z + S[2]
|
|
366
|
+
), C.applyMatrix4(fe), C.x += m[0], C.y += m[1], C.z += m[2], C.applyMatrix4(xe), S[0] += C.x - o.vBasis.x, S[1] += C.y - o.vBasis.y, S[2] += C.z - o.vBasis.z), o.limits && this.opt.isLimits && (m = o.limits, m[0] && (m[0][0] !== null && S[0] < m[0][0] && (S[0] = m[0][0]), m[0][1] !== null && S[0] > m[0][1] && (S[0] = m[0][1])), m[1] && (m[1][0] !== null && S[1] < m[1][0] && (S[1] = m[1][0]), m[1][1] !== null && S[1] > m[1][1] && (S[1] = m[1][1])), m[2] && (m[2][0] !== null && S[2] < m[2][0] && (S[2] = m[2][0]), m[2][1] !== null && S[2] > m[2][1] && (S[2] = m[2][1])), m[3] && (m[3][0] !== null && S[3] < m[3][0] && (S[3] = m[3][0]), m[3][1] !== null && S[3] > m[3][1] && (S[3] = m[3][1]))), o.isPoint)
|
|
367
367
|
o.bone.position.set(
|
|
368
|
-
o.vBasis.x +
|
|
369
|
-
o.vBasis.y +
|
|
370
|
-
o.vBasis.z -
|
|
368
|
+
o.vBasis.x + S[0],
|
|
369
|
+
o.vBasis.y + S[1],
|
|
370
|
+
o.vBasis.z - S[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(
|
|
372
|
+
else if (o.boneParent.quaternion.copy(o.qBasis), o.pivot && this.opt.isPivots && (o.boneParent.updateWorldMatrix(!1, !1), o.boneParent.matrixWorld.decompose(C, oe, ie), C.copy(He).applyQuaternion(oe).setY(0).normalize(), oe.premultiply(Oe.setFromUnitVectors(He, C).invert()).normalize(), o.boneParent.quaternion.multiply(oe.invert()), o.boneParent.quaternion.multiply(o.qWorldInverseYaw)), o.isZ && (m = Math.atan(S[0] / o.l), oe.setFromAxisAngle($e, -m), o.boneParent.quaternion.multiply(oe)), o.isY && (m = o.l / 3, m = m * Math.tanh(S[1] / m), o.bone.position.setLength(o.l + m)), o.isX && (m = Math.atan(S[2] / o.l), oe.setFromAxisAngle(_e, -m), o.boneParent.quaternion.multiply(oe)), o.isT && (m = 1.5 * Math.tanh(S[3] * 1.5), oe.setFromAxisAngle(Je, -m), o.boneParent.quaternion.multiply(oe)), 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],
|
|
374
|
+
m = o.excludes[n], ie.set(0, 0, 0), m.deltaLocal && (ie.x += m.deltaLocal[0], ie.y += m.deltaLocal[1], ie.z += m.deltaLocal[2]), ie.applyMatrix4(m.bone.matrixWorld), xe.copy(o.boneParent.matrixWorld).invert(), ie.applyMatrix4(xe), C.copy(o.bone.position), !(C.distanceToSquared(ie) >= m.radiusSq) && (ue = C.length(), re = ie.length(), !(re > m.radius + ue) && (re < Math.abs(m.radius - ue) || (re = (re * re + ue * ue - m.radiusSq) / (2 * re), ie.normalize(), Ce.copy(ie).multiplyScalar(re), re = Math.sqrt(ue * ue - re * re), C.subVectors(C, Ce).projectOnPlane(ie).normalize().multiplyScalar(re), ze.subVectors(o.vBasis, Ce).projectOnPlane(ie).normalize(), ue = ze.dot(C), ue < 0 && (ue = Math.sqrt(re * re - ue * ue), ze.multiplyScalar(ue), C.add(ze)), C.add(Ce).normalize(), ie.copy(o.bone.position).normalize(), oe.setFromUnitVectors(ie, C), o.boneParent.quaternion.premultiply(oe), o.boneParent.updateWorldMatrix(!1, !0))));
|
|
375
375
|
}
|
|
376
376
|
this.helpers.isActive && this.updateHelpers();
|
|
377
377
|
}
|
|
@@ -393,7 +393,7 @@ class et {
|
|
|
393
393
|
i || (m.excludes.bones.push(n.bone), m.excludes.radii.push(n.radius), m.excludes.deltaLocals.push(n.deltaLocal ? [...n.deltaLocal] : null), m.excludes.objects.push(null));
|
|
394
394
|
}));
|
|
395
395
|
}), m = this.helpers.excludes, this.opt.isExcludes && m.bones.length && m.bones.forEach((e, n) => {
|
|
396
|
-
const i = new
|
|
396
|
+
const i = new f.SphereGeometry(m.radii[n], 6, 6), s = new f.MeshBasicMaterial({
|
|
397
397
|
depthTest: !1,
|
|
398
398
|
depthWrite: !1,
|
|
399
399
|
toneMapped: !1,
|
|
@@ -401,18 +401,18 @@ class et {
|
|
|
401
401
|
wireframe: !0,
|
|
402
402
|
color: this.opt.helperExcludesColor
|
|
403
403
|
});
|
|
404
|
-
m.objects[n] = new
|
|
404
|
+
m.objects[n] = new f.Mesh(i, s), m.objects[n].renderOrder = 997, e.add(m.objects[n]), m.deltaLocals[n] && m.objects[n].position.set(
|
|
405
405
|
m.deltaLocals[n][0],
|
|
406
406
|
m.deltaLocals[n][1],
|
|
407
407
|
m.deltaLocals[n][2]
|
|
408
408
|
);
|
|
409
409
|
}), m = this.helpers.points, m.bones.length) {
|
|
410
410
|
this.helpers.isActive = !0;
|
|
411
|
-
const e = new
|
|
412
|
-
e.setAttribute("position", new
|
|
413
|
-
const i = new
|
|
414
|
-
e.setAttribute("color", new
|
|
415
|
-
const l = new
|
|
411
|
+
const e = new f.BufferGeometry(), n = m.bones.map((h) => [0, 0, 0]).flat();
|
|
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((h) => h && this.opt.isPivots ? [s.r, s.g, s.b] : [i.r, i.g, i.b]).flat();
|
|
414
|
+
e.setAttribute("color", new f.Float32BufferAttribute(o, 3));
|
|
415
|
+
const l = new f.PointsMaterial({
|
|
416
416
|
depthTest: !1,
|
|
417
417
|
depthWrite: !1,
|
|
418
418
|
toneMapped: !1,
|
|
@@ -420,21 +420,21 @@ class et {
|
|
|
420
420
|
size: 0.2,
|
|
421
421
|
vertexColors: !0
|
|
422
422
|
});
|
|
423
|
-
m.object = new
|
|
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
|
|
427
|
-
e.setAttribute("position", new
|
|
428
|
-
const i = new
|
|
429
|
-
e.setAttribute("color", new
|
|
430
|
-
const l = new
|
|
426
|
+
const e = new f.BufferGeometry(), n = m.bones.map((h) => [0, 0, 0, 0, 0, 0]).flat();
|
|
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((h) => [i.r, i.g, i.b, s.r, s.g, s.b]).flat();
|
|
429
|
+
e.setAttribute("color", new f.Float32BufferAttribute(o, 3));
|
|
430
|
+
const l = new f.LineBasicMaterial({
|
|
431
431
|
vertexColors: !0,
|
|
432
432
|
depthTest: !1,
|
|
433
433
|
depthWrite: !1,
|
|
434
434
|
toneMapped: !1,
|
|
435
435
|
transparent: !0
|
|
436
436
|
});
|
|
437
|
-
m.object = new
|
|
437
|
+
m.object = new f.LineSegments(e, l), m.object.renderOrder = 999, m.object.matrix = this.armature.matrixWorld, m.object.matrixAutoUpdate = !1, this.scene.add(m.object);
|
|
438
438
|
}
|
|
439
439
|
}
|
|
440
440
|
/**
|
|
@@ -445,14 +445,14 @@ class et {
|
|
|
445
445
|
xe.copy(this.armature.matrixWorld).invert();
|
|
446
446
|
const t = m.object.geometry.getAttribute("position");
|
|
447
447
|
for (let e = 0, n = m.bones.length; e < n; e++)
|
|
448
|
-
fe.multiplyMatrices(xe, m.bones[e].matrixWorld),
|
|
448
|
+
fe.multiplyMatrices(xe, m.bones[e].matrixWorld), C.setFromMatrixPosition(fe), t.setXYZ(e, C.x, C.y, C.z);
|
|
449
449
|
t.needsUpdate = !0, m.object.updateMatrixWorld();
|
|
450
450
|
}
|
|
451
451
|
if (m = this.helpers.lines, m.bones.length) {
|
|
452
452
|
xe.copy(this.armature.matrixWorld).invert();
|
|
453
453
|
const t = m.object.geometry.getAttribute("position");
|
|
454
454
|
for (let e = 0, n = 0, i = m.bones.length; e < i; e++, n += 2)
|
|
455
|
-
fe.multiplyMatrices(xe, m.bones[e].matrixWorld),
|
|
455
|
+
fe.multiplyMatrices(xe, m.bones[e].matrixWorld), C.setFromMatrixPosition(fe), t.setXYZ(n, C.x, C.y, C.z), fe.multiplyMatrices(xe, m.bones[e].parent.matrixWorld), C.setFromMatrixPosition(fe), t.setXYZ(n + 1, C.x, C.y, C.z);
|
|
456
456
|
t.needsUpdate = !0, m.object.updateMatrixWorld();
|
|
457
457
|
}
|
|
458
458
|
}
|
|
@@ -521,10 +521,10 @@ class tt {
|
|
|
521
521
|
for (let l = 0; l < o; l++) {
|
|
522
522
|
const h = l * s, r = Math.min(h + i, t.length), u = t.slice(h, r), a = this.calculateEnergy(u);
|
|
523
523
|
n.energy.push(a);
|
|
524
|
-
const
|
|
525
|
-
n.spectralCentroid.push(
|
|
526
|
-
const
|
|
527
|
-
n.zeroCrossingRate.push(
|
|
524
|
+
const c = this.calculateSpectralCentroid(u);
|
|
525
|
+
n.spectralCentroid.push(c);
|
|
526
|
+
const d = this.calculateZeroCrossingRate(u);
|
|
527
|
+
n.zeroCrossingRate.push(d);
|
|
528
528
|
const g = this.calculateMFCC(u);
|
|
529
529
|
n.mfcc.push(g);
|
|
530
530
|
}
|
|
@@ -606,10 +606,10 @@ class tt {
|
|
|
606
606
|
for (let h = 0; h < e; h += i) {
|
|
607
607
|
let r = 1, u = 0;
|
|
608
608
|
for (let a = 0; a < i / 2; a++) {
|
|
609
|
-
const
|
|
610
|
-
n[(h + a) * 2] =
|
|
611
|
-
const
|
|
612
|
-
r =
|
|
609
|
+
const c = n[(h + a) * 2], d = n[(h + a) * 2 + 1], g = n[(h + a + i / 2) * 2] * r - n[(h + a + i / 2) * 2 + 1] * u, b = n[(h + a + i / 2) * 2] * u + n[(h + a + i / 2) * 2 + 1] * r;
|
|
610
|
+
n[(h + a) * 2] = c + g, n[(h + a) * 2 + 1] = d + b, n[(h + a + i / 2) * 2] = c - g, n[(h + a + i / 2) * 2 + 1] = d - b;
|
|
611
|
+
const x = r * o - u * l, A = r * l + u * o;
|
|
612
|
+
r = x, u = A;
|
|
613
613
|
}
|
|
614
614
|
}
|
|
615
615
|
}
|
|
@@ -703,15 +703,15 @@ class tt {
|
|
|
703
703
|
const o = this.textToVisemes(e);
|
|
704
704
|
let l = 0, h = 0;
|
|
705
705
|
for (let r = 0; r < s.length && l < o.length; r++) {
|
|
706
|
-
const u = s[r], a = o[l],
|
|
706
|
+
const u = s[r], a = o[l], c = t.energy[Math.floor(u / 0.023)] || 0, d = this.calculateVisemeDuration(a, c);
|
|
707
707
|
i.push({
|
|
708
708
|
viseme: a,
|
|
709
709
|
startTime: h,
|
|
710
|
-
endTime: h +
|
|
711
|
-
duration:
|
|
712
|
-
intensity: Math.min(1,
|
|
710
|
+
endTime: h + d,
|
|
711
|
+
duration: d,
|
|
712
|
+
intensity: Math.min(1, c * 2)
|
|
713
713
|
// Map energy to viseme intensity
|
|
714
|
-
}), h +=
|
|
714
|
+
}), h += d, l++;
|
|
715
715
|
}
|
|
716
716
|
for (; l < o.length; ) {
|
|
717
717
|
const r = o[l], u = this.calculateVisemeDuration(r, 0.5);
|
|
@@ -1207,10 +1207,10 @@ class nt {
|
|
|
1207
1207
|
Object.keys(this.rules).forEach((e) => {
|
|
1208
1208
|
this.rules[e] = this.rules[e].map((n) => {
|
|
1209
1209
|
const i = n.indexOf("["), s = n.indexOf("]"), o = n.indexOf("="), l = n.substring(0, i), h = n.substring(i + 1, s), r = n.substring(s + 1, o), u = n.substring(o + 1), a = { regex: "", move: 0, visemes: [] };
|
|
1210
|
-
let
|
|
1211
|
-
|
|
1212
|
-
const
|
|
1213
|
-
return
|
|
1210
|
+
let c = "";
|
|
1211
|
+
c += [...l].map((g) => t[g] || g).join("");
|
|
1212
|
+
const d = [...h];
|
|
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), u.length && u.split(" ").forEach((g) => {
|
|
1214
1214
|
a.visemes.push(g);
|
|
1215
1215
|
}), a;
|
|
1216
1216
|
});
|
|
@@ -1380,11 +1380,11 @@ class nt {
|
|
|
1380
1380
|
if ((e.words.substring(0, e.i) + s.toLowerCase() + e.words.substring(e.i + 1)).match(h.regex)) {
|
|
1381
1381
|
h.visemes.forEach((a) => {
|
|
1382
1382
|
if (e.visemes.length && e.visemes[e.visemes.length - 1] === a) {
|
|
1383
|
-
const
|
|
1384
|
-
e.durations[e.durations.length - 1] +=
|
|
1383
|
+
const c = 0.7 * (this.visemeDurations[a] || 1);
|
|
1384
|
+
e.durations[e.durations.length - 1] += c, n += c;
|
|
1385
1385
|
} else {
|
|
1386
|
-
const
|
|
1387
|
-
e.visemes.push(a), e.times.push(n), e.durations.push(
|
|
1386
|
+
const c = this.visemeDurations[a] || 1;
|
|
1387
|
+
e.visemes.push(a), e.times.push(n), e.durations.push(c), n += c;
|
|
1388
1388
|
}
|
|
1389
1389
|
}), e.i += h.move;
|
|
1390
1390
|
break;
|
|
@@ -1617,10 +1617,10 @@ class ot {
|
|
|
1617
1617
|
Object.keys(this.rules).forEach((e) => {
|
|
1618
1618
|
this.rules[e] = this.rules[e].map((n) => {
|
|
1619
1619
|
const i = n.indexOf("["), s = n.indexOf("]"), o = n.indexOf("="), l = n.substring(0, i), h = n.substring(i + 1, s), r = n.substring(s + 1, o), u = n.substring(o + 1), a = { regex: "", move: 0, visemes: [] };
|
|
1620
|
-
let
|
|
1621
|
-
|
|
1622
|
-
const
|
|
1623
|
-
return
|
|
1620
|
+
let c = "";
|
|
1621
|
+
c += [...l].map((g) => t[g] || g).join("");
|
|
1622
|
+
const d = [...h];
|
|
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), u.length && u.split(" ").forEach((g) => {
|
|
1624
1624
|
a.visemes.push(g);
|
|
1625
1625
|
}), a;
|
|
1626
1626
|
});
|
|
@@ -1735,13 +1735,13 @@ class ot {
|
|
|
1735
1735
|
for (let h = 0; h < o.length; h++) {
|
|
1736
1736
|
const r = o[h];
|
|
1737
1737
|
if ((e.words.substring(0, e.i) + s.toLowerCase() + e.words.substring(e.i + 1)).match(r.regex)) {
|
|
1738
|
-
r.visemes.forEach((
|
|
1739
|
-
if (e.visemes.length && e.visemes[e.visemes.length - 1] ===
|
|
1740
|
-
const
|
|
1741
|
-
e.durations[e.durations.length - 1] +=
|
|
1738
|
+
r.visemes.forEach((c) => {
|
|
1739
|
+
if (e.visemes.length && e.visemes[e.visemes.length - 1] === c) {
|
|
1740
|
+
const d = 0.7 * (this.visemeDurations[c] || 1);
|
|
1741
|
+
e.durations[e.durations.length - 1] += d, n += d;
|
|
1742
1742
|
} else {
|
|
1743
|
-
const
|
|
1744
|
-
e.visemes.push(
|
|
1743
|
+
const d = this.visemeDurations[c] || 1;
|
|
1744
|
+
e.visemes.push(c), e.times.push(n), e.durations.push(d), n += d;
|
|
1745
1745
|
}
|
|
1746
1746
|
}), e.i += r.move, l = !0;
|
|
1747
1747
|
break;
|
|
@@ -2132,10 +2132,10 @@ class at {
|
|
|
2132
2132
|
Object.keys(this.rules).forEach((e) => {
|
|
2133
2133
|
this.rules[e] = this.rules[e].map((n) => {
|
|
2134
2134
|
const i = n.indexOf("["), s = n.indexOf("]"), o = n.indexOf("="), l = n.substring(0, i), h = n.substring(i + 1, s), r = n.substring(s + 1, o), u = n.substring(o + 1), a = { regex: "", move: 0, visemes: [] };
|
|
2135
|
-
let
|
|
2136
|
-
|
|
2137
|
-
const
|
|
2138
|
-
return
|
|
2135
|
+
let c = "";
|
|
2136
|
+
c += [...l].map((g) => t[g] || g).join("");
|
|
2137
|
+
const d = [...h];
|
|
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"), u.length && u.split(" ").forEach((g) => {
|
|
2139
2139
|
g && a.visemes.push(g);
|
|
2140
2140
|
}), a;
|
|
2141
2141
|
});
|
|
@@ -2270,13 +2270,13 @@ class at {
|
|
|
2270
2270
|
for (let h = 0; h < o.length; h++) {
|
|
2271
2271
|
const r = o[h];
|
|
2272
2272
|
if ((e.words.substring(0, e.i) + s.toLowerCase() + e.words.substring(e.i + 1)).match(r.regex)) {
|
|
2273
|
-
r.visemes.forEach((
|
|
2274
|
-
if (e.visemes.length && e.visemes[e.visemes.length - 1] ===
|
|
2275
|
-
const
|
|
2276
|
-
e.durations[e.durations.length - 1] +=
|
|
2273
|
+
r.visemes.forEach((c) => {
|
|
2274
|
+
if (e.visemes.length && e.visemes[e.visemes.length - 1] === c) {
|
|
2275
|
+
const d = 0.7 * (this.visemeDurations[c] || 1);
|
|
2276
|
+
e.durations[e.durations.length - 1] += d, n += d;
|
|
2277
2277
|
} else {
|
|
2278
|
-
const
|
|
2279
|
-
e.visemes.push(
|
|
2278
|
+
const d = this.visemeDurations[c] || 1;
|
|
2279
|
+
e.visemes.push(c), e.times.push(n), e.durations.push(d), n += d;
|
|
2280
2280
|
}
|
|
2281
2281
|
}), e.i += r.move, l = !0;
|
|
2282
2282
|
break;
|
|
@@ -2629,14 +2629,14 @@ const ct = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
|
|
|
2629
2629
|
fr: rt,
|
|
2630
2630
|
fi: ut,
|
|
2631
2631
|
lt: ct
|
|
2632
|
-
}, Q = new
|
|
2633
|
-
new
|
|
2634
|
-
new
|
|
2635
|
-
new
|
|
2636
|
-
new
|
|
2637
|
-
const mt = new
|
|
2638
|
-
new
|
|
2639
|
-
new
|
|
2632
|
+
}, Q = new f.Quaternion(), G = new f.Euler(), ve = new f.Vector3(), Re = new f.Vector3(), We = new f.Box3();
|
|
2633
|
+
new f.Matrix4();
|
|
2634
|
+
new f.Matrix4();
|
|
2635
|
+
new f.Vector3();
|
|
2636
|
+
new f.Vector3(0, 0, 1);
|
|
2637
|
+
const mt = new f.Vector3(1, 0, 0);
|
|
2638
|
+
new f.Vector3(0, 1, 0);
|
|
2639
|
+
new f.Vector3(0, 0, 1);
|
|
2640
2640
|
class Be {
|
|
2641
2641
|
/**
|
|
2642
2642
|
* Avatar.
|
|
@@ -4073,22 +4073,22 @@ class Be {
|
|
|
4073
4073
|
if (this.isAvatarOnly = this.opt.avatarOnly, this.isAvatarOnly)
|
|
4074
4074
|
this.scene = this.opt.avatarOnlyScene, this.camera = this.opt.avatarOnlyCamera;
|
|
4075
4075
|
else {
|
|
4076
|
-
this.renderer = new
|
|
4077
|
-
new
|
|
4076
|
+
this.renderer = new f.WebGLRenderer({ antialias: !0, alpha: !0 }), this.renderer.setPixelRatio(this.opt.modelPixelRatio * window.devicePixelRatio), this.renderer.setSize(this.nodeAvatar.clientWidth, this.nodeAvatar.clientHeight), this.renderer.outputColorSpace = f.SRGBColorSpace, this.renderer.toneMapping = f.ACESFilmicToneMapping, this.renderer.shadowMap.enabled = !1, this.nodeAvatar.appendChild(this.renderer.domElement), this.camera = new f.PerspectiveCamera(10, this.nodeAvatar.clientWidth / this.nodeAvatar.clientHeight, 0.1, 2e3), this.scene = new f.Scene(), this.lightAmbient = new f.AmbientLight(
|
|
4077
|
+
new f.Color(this.opt.lightAmbientColor),
|
|
4078
4078
|
this.opt.lightAmbientIntensity
|
|
4079
|
-
), this.lightDirect = new
|
|
4080
|
-
new
|
|
4079
|
+
), this.lightDirect = new f.DirectionalLight(
|
|
4080
|
+
new f.Color(this.opt.lightDirectColor),
|
|
4081
4081
|
this.opt.lightDirectIntensity
|
|
4082
|
-
), this.lightSpot = new
|
|
4083
|
-
new
|
|
4082
|
+
), this.lightSpot = new f.SpotLight(
|
|
4083
|
+
new f.Color(this.opt.lightSpotColor),
|
|
4084
4084
|
this.opt.lightSpotIntensity,
|
|
4085
4085
|
0,
|
|
4086
4086
|
this.opt.lightSpotDispersion
|
|
4087
4087
|
), this.setLighting(this.opt);
|
|
4088
|
-
const l = new
|
|
4088
|
+
const l = new f.PMREMGenerator(this.renderer);
|
|
4089
4089
|
l.compileEquirectangularShader(), this.scene.environment = l.fromScene(new qe()).texture, this.resizeobserver = new ResizeObserver(this.onResize.bind(this)), this.resizeobserver.observe(this.nodeAvatar), this.controls = new Ye(this.camera, this.renderer.domElement), this.controls.enableZoom = this.opt.cameraZoomEnable, this.controls.enableRotate = this.opt.cameraRotateEnable, this.controls.enablePan = this.opt.cameraPanEnable, this.controls.minDistance = 2, this.controls.maxDistance = 2e3, this.controls.autoRotateSpeed = 0, this.controls.autoRotate = !1, this.controls.update(), this.cameraClock = null;
|
|
4090
4090
|
}
|
|
4091
|
-
this.ikMesh = new
|
|
4091
|
+
this.ikMesh = new f.SkinnedMesh();
|
|
4092
4092
|
const s = {
|
|
4093
4093
|
LeftShoulder: null,
|
|
4094
4094
|
LeftArm: "LeftShoulder",
|
|
@@ -4102,9 +4102,9 @@ class Be {
|
|
|
4102
4102
|
RightHandMiddle1: "RightHand"
|
|
4103
4103
|
}, o = [];
|
|
4104
4104
|
Object.entries(s).forEach((l, h) => {
|
|
4105
|
-
const r = new
|
|
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
|
-
}), this.ikMesh.bind(new
|
|
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 = [];
|
|
4108
4108
|
}
|
|
4109
4109
|
/**
|
|
4110
4110
|
* Helper that re/creates the audio context and the other nodes.
|
|
@@ -4194,7 +4194,7 @@ class Be {
|
|
|
4194
4194
|
for (let [n, i] of Object.entries(t)) {
|
|
4195
4195
|
const s = n.split(".");
|
|
4196
4196
|
let o = Array.isArray(i.x) ? this.gaussianRandom(...i.x) : i.x, l = Array.isArray(i.y) ? this.gaussianRandom(...i.y) : i.y, h = Array.isArray(i.z) ? this.gaussianRandom(...i.z) : i.z;
|
|
4197
|
-
s[1] === "position" || s[1] === "scale" ? e[n] = new
|
|
4197
|
+
s[1] === "position" || s[1] === "scale" ? e[n] = new f.Vector3(o, l, h) : s[1] === "rotation" ? (n = s[0] + ".quaternion", e[n] = new f.Quaternion().setFromEuler(new f.Euler(o, l, h, "XYZ")).normalize()) : s[1] === "quaternion" && (e[n] = new f.Quaternion(o, l, h, i.w).normalize());
|
|
4198
4198
|
}
|
|
4199
4199
|
return e;
|
|
4200
4200
|
}
|
|
@@ -4225,16 +4225,16 @@ class Be {
|
|
|
4225
4225
|
let l = null, h = null;
|
|
4226
4226
|
for (const [r, u] of Object.entries(n))
|
|
4227
4227
|
if (s.morphTargetDictionary.hasOwnProperty(r)) {
|
|
4228
|
-
const a = s.morphTargetDictionary[r],
|
|
4229
|
-
l || (l = new
|
|
4230
|
-
for (let g = 0; g <
|
|
4231
|
-
const
|
|
4232
|
-
l.setXYZ(g,
|
|
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 && (h = new f.Float32BufferAttribute(c.count * 3, 3)));
|
|
4230
|
+
for (let g = 0; g < c.count; g++) {
|
|
4231
|
+
const b = l.getX(g) + c.getX(g) * u, x = l.getY(g) + c.getY(g) * u, A = l.getZ(g) + c.getZ(g) * u;
|
|
4232
|
+
l.setXYZ(g, b, x, A);
|
|
4233
4233
|
}
|
|
4234
|
-
if (
|
|
4235
|
-
for (let g = 0; g <
|
|
4236
|
-
const
|
|
4237
|
-
h.setXYZ(g,
|
|
4234
|
+
if (d)
|
|
4235
|
+
for (let g = 0; g < c.count; g++) {
|
|
4236
|
+
const b = h.getX(g) + d.getX(g) * u, x = h.getY(g) + d.getY(g) * u, A = h.getZ(g) + d.getZ(g) * u;
|
|
4237
|
+
h.setXYZ(g, b, x, A);
|
|
4238
4238
|
}
|
|
4239
4239
|
}
|
|
4240
4240
|
if (l) {
|
|
@@ -4299,8 +4299,8 @@ class Be {
|
|
|
4299
4299
|
u && ["fixed", "system", "systemd", "realtime", "base", "v", "value", "applied"].forEach((a) => {
|
|
4300
4300
|
l[r][a] = u[a];
|
|
4301
4301
|
}), this.morphs.forEach((a) => {
|
|
4302
|
-
const
|
|
4303
|
-
|
|
4302
|
+
const c = a.morphTargetDictionary[r];
|
|
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
4306
|
const u = r.split("."), a = this.armature.getObjectByName(u[0]);
|
|
@@ -4314,7 +4314,7 @@ 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 h = new
|
|
4317
|
+
const h = new f.Vector3();
|
|
4318
4318
|
this.objectLeftEye.getWorldPosition(h), this.avatarHeight = h.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
|
/**
|
|
@@ -4358,14 +4358,14 @@ class Be {
|
|
|
4358
4358
|
default:
|
|
4359
4359
|
a += 12, u = u * a;
|
|
4360
4360
|
}
|
|
4361
|
-
r = r * a, this.controlsEnd = new
|
|
4361
|
+
r = r * a, this.controlsEnd = new f.Vector3(r, u, 0), this.cameraEnd = new f.Vector3(r, u, 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.
|
|
4365
4365
|
* @param {Object} opt Options
|
|
4366
4366
|
*/
|
|
4367
4367
|
setLighting(t) {
|
|
4368
|
-
this.isAvatarOnly || (t = t || {}, t.hasOwnProperty("lightAmbientColor") && this.lightAmbient.color.set(new
|
|
4368
|
+
this.isAvatarOnly || (t = t || {}, t.hasOwnProperty("lightAmbientColor") && this.lightAmbient.color.set(new f.Color(t.lightAmbientColor)), t.hasOwnProperty("lightAmbientIntensity") && (this.lightAmbient.intensity = t.lightAmbientIntensity, this.lightAmbient.visible = t.lightAmbientIntensity !== 0), t.hasOwnProperty("lightDirectColor") && this.lightDirect.color.set(new f.Color(t.lightDirectColor)), t.hasOwnProperty("lightDirectIntensity") && (this.lightDirect.intensity = t.lightDirectIntensity, this.lightDirect.visible = t.lightDirectIntensity !== 0), t.hasOwnProperty("lightDirectPhi") && t.hasOwnProperty("lightDirectTheta") && this.lightDirect.position.setFromSphericalCoords(2, t.lightDirectPhi, t.lightDirectTheta), t.hasOwnProperty("lightSpotColor") && this.lightSpot.color.set(new f.Color(t.lightSpotColor)), t.hasOwnProperty("lightSpotIntensity") && (this.lightSpot.intensity = t.lightSpotIntensity, this.lightSpot.visible = t.lightSpotIntensity !== 0), t.hasOwnProperty("lightSpotPhi") && t.hasOwnProperty("lightSpotTheta") && (this.lightSpot.position.setFromSphericalCoords(2, t.lightSpotPhi, t.lightSpotTheta), this.lightSpot.position.add(new f.Vector3(0, 1.5, 0))), t.hasOwnProperty("lightSpotDispersion") && (this.lightSpot.angle = t.lightSpotDispersion));
|
|
4369
4369
|
}
|
|
4370
4370
|
/**
|
|
4371
4371
|
* Render scene.
|
|
@@ -4398,9 +4398,9 @@ class Be {
|
|
|
4398
4398
|
updatePoseDelta() {
|
|
4399
4399
|
for (const [t, e] of Object.entries(this.poseDelta.props)) {
|
|
4400
4400
|
if (e.x === 0 && e.y === 0 && e.z === 0) continue;
|
|
4401
|
-
|
|
4401
|
+
G.set(e.x, e.y, e.z);
|
|
4402
4402
|
const n = this.poseAvatar.props[t];
|
|
4403
|
-
n.isQuaternion ? (Q.setFromEuler(
|
|
4403
|
+
n.isQuaternion ? (Q.setFromEuler(G), n.multiply(Q)) : n.isVector3 && n.add(G);
|
|
4404
4404
|
}
|
|
4405
4405
|
}
|
|
4406
4406
|
/**
|
|
@@ -4480,7 +4480,7 @@ 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], h = i[1].isQuaternion ? new
|
|
4483
|
+
const l = o[1] === "quaternion" ? o[0] + ".rotation" : i[0], h = i[1].isQuaternion ? new f.Euler().setFromQuaternion(i[1]) : i[1];
|
|
4484
4484
|
n += (s ? ", " : "") + "'" + l + "':{", n += "x:" + Math.round(h.x * e) / e, n += ", y:" + Math.round(h.y * e) / e, n += ", z:" + Math.round(h.z * e) / e, n += "}";
|
|
4485
4485
|
}
|
|
4486
4486
|
}), n += "}", n;
|
|
@@ -4987,10 +4987,10 @@ class Be {
|
|
|
4987
4987
|
if (l.alt.length > 1) {
|
|
4988
4988
|
const u = Math.random();
|
|
4989
4989
|
let a = 0;
|
|
4990
|
-
for (let
|
|
4991
|
-
let
|
|
4992
|
-
if (a +=
|
|
4993
|
-
r = l.alt[
|
|
4990
|
+
for (let c = 0; c < l.alt.length; c++) {
|
|
4991
|
+
let d = this.valueFn(l.alt[c].p);
|
|
4992
|
+
if (a += d === void 0 ? (1 - a) / (l.alt.length - 1 - c) : d, u < a) {
|
|
4993
|
+
r = l.alt[c];
|
|
4994
4994
|
break;
|
|
4995
4995
|
}
|
|
4996
4996
|
}
|
|
@@ -5011,8 +5011,8 @@ class Be {
|
|
|
5011
5011
|
}
|
|
5012
5012
|
s ? o.ts = o.ts.map((r) => h + r * n) : o.ts = o.ts.map((r) => this.animClock + h + 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
5013
|
for (let [r, u] of Object.entries(l.vs)) {
|
|
5014
|
-
const a = this.getBaselineValue(r),
|
|
5015
|
-
r === "eyesRotateY" ? (o.vs.eyeLookOutLeft = [null, ...
|
|
5014
|
+
const a = this.getBaselineValue(r), c = u.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
|
+
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))
|
|
5018
5018
|
for (; o.vs[r].length <= o.ts.length; ) o.vs[r].push(o.vs[r][o.vs[r].length - 1]);
|
|
@@ -5099,20 +5099,20 @@ class Be {
|
|
|
5099
5099
|
const a = this.animQueue[n];
|
|
5100
5100
|
if (!(!a || !a.ts || !a.ts.length || this.animClock < a.ts[0])) {
|
|
5101
5101
|
for (i = a.ndx || 0, o = a.ts.length; i < o && !(this.animClock < a.ts[i]); i++)
|
|
5102
|
-
for (let [
|
|
5103
|
-
if (this.mtAvatar.hasOwnProperty(
|
|
5104
|
-
if (
|
|
5105
|
-
const g = this.mtAvatar[
|
|
5106
|
-
if (
|
|
5107
|
-
g.newvalue =
|
|
5102
|
+
for (let [c, d] of Object.entries(a.vs))
|
|
5103
|
+
if (this.mtAvatar.hasOwnProperty(c)) {
|
|
5104
|
+
if (d[i + 1] === null) continue;
|
|
5105
|
+
const g = this.mtAvatar[c];
|
|
5106
|
+
if (d[i] === null && (d[i] = g.value), i === o - 1)
|
|
5107
|
+
g.newvalue = d[i];
|
|
5108
5108
|
else {
|
|
5109
|
-
g.newvalue =
|
|
5110
|
-
const
|
|
5111
|
-
let
|
|
5112
|
-
|
|
5109
|
+
g.newvalue = d[i + 1];
|
|
5110
|
+
const b = a.ts[i + 1] - a.ts[i];
|
|
5111
|
+
let x = 1;
|
|
5112
|
+
b > 1e-4 && (x = (this.animClock - a.ts[i]) / b), x < 1 && (g.easing && (x = g.easing(x)), g.newvalue = (1 - x) * d[i] + x * g.newvalue), g.ref && g.ref !== a.vs && g.ref.hasOwnProperty(c) && delete g.ref[c], g.ref = a.vs;
|
|
5113
5113
|
}
|
|
5114
5114
|
if (l)
|
|
5115
|
-
switch (
|
|
5115
|
+
switch (c) {
|
|
5116
5116
|
case "viseme_aa":
|
|
5117
5117
|
case "viseme_E":
|
|
5118
5118
|
case "viseme_I":
|
|
@@ -5121,11 +5121,11 @@ class Be {
|
|
|
5121
5121
|
g.newvalue *= 1 + l / 255 - 0.5;
|
|
5122
5122
|
}
|
|
5123
5123
|
g.needsUpdate = !0;
|
|
5124
|
-
} else
|
|
5124
|
+
} else c === "eyeContact" && d[i] !== null && h !== !1 ? h = !!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 && (u.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,
|
|
5128
|
+
for (let a = 0, c = u.length; a < c; a++)
|
|
5129
5129
|
switch (i = u[a].val, u[a].mt) {
|
|
5130
5130
|
case "speak":
|
|
5131
5131
|
this.speakText(i);
|
|
@@ -5143,8 +5143,8 @@ class Be {
|
|
|
5143
5143
|
i && typeof i == "function" && i();
|
|
5144
5144
|
break;
|
|
5145
5145
|
case "moveto":
|
|
5146
|
-
Object.entries(i.props).forEach((
|
|
5147
|
-
|
|
5146
|
+
Object.entries(i.props).forEach((d) => {
|
|
5147
|
+
d[1] ? this.poseTarget.props[d[0]].copy(d[1]) : this.poseTarget.props[d[0]].copy(this.getPoseTemplateProp(d[0])), this.poseTarget.props[d[0]].t = this.animClock, this.poseTarget.props[d[0]].d = d[1] && d[1].d ? d[1].d : d.duration || 2e3;
|
|
5148
5148
|
});
|
|
5149
5149
|
break;
|
|
5150
5150
|
case "handLeft":
|
|
@@ -5157,7 +5157,7 @@ class Be {
|
|
|
5157
5157
|
{ link: "LeftForeArm", minx: -0.5, maxx: 1.5, miny: -1.5, maxy: 1.5, minz: -0.5, maxz: 3 },
|
|
5158
5158
|
{ link: "LeftArm", minx: -1.5, maxx: 1.5, miny: 0, maxy: 0, minz: -1, maxz: 3 }
|
|
5159
5159
|
]
|
|
5160
|
-
}, i.x ? new
|
|
5160
|
+
}, i.x ? new f.Vector3(i.x, i.y, i.z) : null, !0, i.d);
|
|
5161
5161
|
break;
|
|
5162
5162
|
case "handRight":
|
|
5163
5163
|
this.ikSolve({
|
|
@@ -5169,10 +5169,10 @@ class Be {
|
|
|
5169
5169
|
{ link: "RightForeArm", minx: -0.5, maxx: 1.5, miny: -1.5, maxy: 1.5, minz: -3, maxz: 0.5, maxAngle: 0.2 },
|
|
5170
5170
|
{ link: "RightArm", minx: -1.5, maxx: 1.5, miny: 0, maxy: 0, minz: -1, maxz: 3 }
|
|
5171
5171
|
]
|
|
5172
|
-
}, i.x ? new
|
|
5172
|
+
}, i.x ? new f.Vector3(i.x, i.y, i.z) : null, !0, i.d);
|
|
5173
5173
|
break;
|
|
5174
5174
|
}
|
|
5175
|
-
if ((h || r) && (
|
|
5175
|
+
if ((h || r) && (G.setFromQuaternion(this.poseAvatar.props["Head.quaternion"]), G.x = Math.max(-0.9, Math.min(0.9, 2 * G.x - 0.5)), G.y = Math.max(-0.9, Math.min(0.9, -2.5 * G.y)), h ? (Object.assign(this.mtAvatar.eyesLookDown, { system: G.x < 0 ? -G.x : 0, needsUpdate: !0 }), Object.assign(this.mtAvatar.eyesLookUp, { system: G.x < 0 ? 0 : G.x, needsUpdate: !0 }), Object.assign(this.mtAvatar.eyeLookInLeft, { system: G.y < 0 ? -G.y : 0, needsUpdate: !0 }), Object.assign(this.mtAvatar.eyeLookOutLeft, { system: G.y < 0 ? 0 : G.y, needsUpdate: !0 }), Object.assign(this.mtAvatar.eyeLookInRight, { system: G.y < 0 ? 0 : G.y, needsUpdate: !0 }), Object.assign(this.mtAvatar.eyeLookOutRight, { system: G.y < 0 ? -G.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,13 +5193,13 @@ 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) && h ? 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(
|
|
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) && h ? 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) {
|
|
5200
5200
|
this.cameraClock += e, this.cameraClock > 1e3 && (this.cameraClock = 1e3);
|
|
5201
|
-
let a = new
|
|
5202
|
-
a.phi += this.easing(this.cameraClock / 1e3) * (
|
|
5201
|
+
let a = new f.Spherical().setFromVector3(this.cameraStart), c = new f.Spherical().setFromVector3(this.cameraEnd);
|
|
5202
|
+
a.phi += this.easing(this.cameraClock / 1e3) * (c.phi - a.phi), a.theta += this.easing(this.cameraClock / 1e3) * (c.theta - a.theta), a.radius += this.easing(this.cameraClock / 1e3) * (c.radius - a.radius), a.makeSafe(), this.camera.position.setFromSpherical(a), this.controlsStart.x !== this.controlsEnd.x ? this.controls.target.copy(this.controlsStart.lerp(this.controlsEnd, this.easing(this.cameraClock / 1e3))) : (a.setFromVector3(this.controlsStart), c.setFromVector3(this.controlsEnd), a.phi += this.easing(this.cameraClock / 1e3) * (c.phi - a.phi), a.theta += this.easing(this.cameraClock / 1e3) * (c.theta - a.theta), a.radius += this.easing(this.cameraClock / 1e3) * (c.radius - a.radius), a.makeSafe(), this.controls.target.setFromSpherical(a)), this.controls.update();
|
|
5203
5203
|
}
|
|
5204
5204
|
this.controls.autoRotate && this.controls.update(), this.stats && this.stats.end(), this.render();
|
|
5205
5205
|
}
|
|
@@ -5261,48 +5261,48 @@ class Be {
|
|
|
5261
5261
|
speakText(t, e = null, n = null, i = null) {
|
|
5262
5262
|
e = e || {};
|
|
5263
5263
|
const s = /[!\.\?\n\p{Extended_Pictographic}]/ug, o = /[ ]/ug, l = /[\p{L}\p{N},\.\p{Quotation_Mark}!€\$\+\p{Dash_Punctuation}%&\?]/ug, h = /[\p{Extended_Pictographic}]/ug, r = e.lipsyncLang || this.avatar.lipsyncLang || this.opt.lipsyncLang;
|
|
5264
|
-
let u = "", a = "",
|
|
5265
|
-
const
|
|
5266
|
-
for (let
|
|
5267
|
-
const
|
|
5268
|
-
let p =
|
|
5269
|
-
const
|
|
5270
|
-
if (p && !
|
|
5271
|
-
mark:
|
|
5264
|
+
let u = "", a = "", c = 0, d = [], g = [];
|
|
5265
|
+
const b = Array.from(this.segmenter.segment(t), (x) => x.segment);
|
|
5266
|
+
for (let x = 0; x < b.length; x++) {
|
|
5267
|
+
const A = x === b.length - 1, B = b[x].match(l);
|
|
5268
|
+
let p = b[x].match(s);
|
|
5269
|
+
const E = b[x].match(h), I = b[x].match(o);
|
|
5270
|
+
if (p && !A && !E && b[x + 1].match(s) && (p = !1), n && (u += b[x]), B && (!i || i.every((y) => x < y[0] || x > y[1])) && (a += b[x]), (I || p || A) && (a.length && (a = this.lipsyncPreProcessText(a, r), a.length && d.push({
|
|
5271
|
+
mark: c,
|
|
5272
5272
|
word: a
|
|
5273
5273
|
})), u.length && (g.push({
|
|
5274
|
-
mark:
|
|
5274
|
+
mark: c,
|
|
5275
5275
|
template: { name: "subtitles" },
|
|
5276
5276
|
ts: [0],
|
|
5277
5277
|
vs: {
|
|
5278
5278
|
subtitles: [u]
|
|
5279
5279
|
}
|
|
5280
5280
|
}), u = ""), a.length)) {
|
|
5281
|
-
const
|
|
5282
|
-
if (
|
|
5283
|
-
const
|
|
5284
|
-
for (let
|
|
5281
|
+
const y = this.lipsyncWordsToVisemes(a, r);
|
|
5282
|
+
if (y && y.visemes && y.visemes.length) {
|
|
5283
|
+
const H = y.times[y.visemes.length - 1] + y.durations[y.visemes.length - 1];
|
|
5284
|
+
for (let w = 0; w < y.visemes.length; w++)
|
|
5285
5285
|
g.push({
|
|
5286
|
-
mark:
|
|
5286
|
+
mark: c,
|
|
5287
5287
|
template: { name: "viseme" },
|
|
5288
|
-
ts: [(
|
|
5288
|
+
ts: [(y.times[w] - 0.6) / H, (y.times[w] + 0.5) / H, (y.times[w] + y.durations[w] + 0.5) / H],
|
|
5289
5289
|
vs: {
|
|
5290
|
-
["viseme_" +
|
|
5290
|
+
["viseme_" + y.visemes[w]]: [null, y.visemes[w] === "PP" || y.visemes[w] === "FF" ? 0.9 : 0.6, 0]
|
|
5291
5291
|
}
|
|
5292
5292
|
});
|
|
5293
5293
|
}
|
|
5294
|
-
a = "",
|
|
5294
|
+
a = "", c++;
|
|
5295
5295
|
}
|
|
5296
|
-
if (p ||
|
|
5297
|
-
if (
|
|
5298
|
-
const
|
|
5296
|
+
if (p || A) {
|
|
5297
|
+
if (d.length || A && g.length) {
|
|
5298
|
+
const y = {
|
|
5299
5299
|
anim: g
|
|
5300
5300
|
};
|
|
5301
|
-
n && (
|
|
5301
|
+
n && (y.onSubtitles = n), d.length && !e.avatarMute && (y.text = d, e.avatarMood && (y.mood = e.avatarMood), e.ttsLang && (y.lang = e.ttsLang), e.ttsVoice && (y.voice = e.ttsVoice), e.ttsRate && (y.rate = e.ttsRate), e.ttsVoice && (y.pitch = e.ttsPitch), e.ttsVolume && (y.volume = e.ttsVolume)), this.speechQueue.push(y), d = [], a = "", c = 0, g = [];
|
|
5302
5302
|
}
|
|
5303
|
-
if (
|
|
5304
|
-
let
|
|
5305
|
-
|
|
5303
|
+
if (E) {
|
|
5304
|
+
let y = this.animEmojis[b[x]];
|
|
5305
|
+
y && y.link && (y = this.animEmojis[y.link]), y && this.speechQueue.push({ emoji: y });
|
|
5306
5306
|
}
|
|
5307
5307
|
this.speechQueue.push({ break: 100 });
|
|
5308
5308
|
}
|
|
@@ -5392,18 +5392,18 @@ class Be {
|
|
|
5392
5392
|
subtitles: [" " + h]
|
|
5393
5393
|
}
|
|
5394
5394
|
}), !t.visemes)) {
|
|
5395
|
-
const a = this.lipsyncPreProcessText(h, i),
|
|
5396
|
-
if (
|
|
5397
|
-
const
|
|
5398
|
-
let
|
|
5399
|
-
if (u = Math.min(u,
|
|
5400
|
-
for (let
|
|
5401
|
-
const
|
|
5395
|
+
const a = this.lipsyncPreProcessText(h, i), c = this.lipsyncWordsToVisemes(a, i);
|
|
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(u, Math.max(0, u - c.visemes.length * 150));
|
|
5398
|
+
let b = 0.6 + this.convertRange(g, [0, u], [0, 0.4]);
|
|
5399
|
+
if (u = Math.min(u, c.visemes.length * 200), d > 0)
|
|
5400
|
+
for (let x = 0; x < c.visemes.length; x++) {
|
|
5401
|
+
const A = r + c.times[x] / d * u, B = c.durations[x] / d * u;
|
|
5402
5402
|
o.push({
|
|
5403
5403
|
template: { name: "viseme" },
|
|
5404
|
-
ts: [
|
|
5404
|
+
ts: [A - Math.min(60, 2 * B / 3), A + Math.min(25, B / 2), A + B + Math.min(60, B / 2)],
|
|
5405
5405
|
vs: {
|
|
5406
|
-
["viseme_" +
|
|
5406
|
+
["viseme_" + c.visemes[x]]: [null, c.visemes[x] === "PP" || c.visemes[x] === "FF" ? 0.9 : b, 0]
|
|
5407
5407
|
}
|
|
5408
5408
|
});
|
|
5409
5409
|
}
|
|
@@ -5483,34 +5483,34 @@ class Be {
|
|
|
5483
5483
|
s.lang = o, s.rate = Math.max(0.1, Math.min(10, l)), s.pitch = Math.max(0, Math.min(2, h)), s.volume = Math.max(0, Math.min(1, r));
|
|
5484
5484
|
const u = speechSynthesis.getVoices(), a = t.voice || this.avatar.ttsVoice || this.opt.ttsVoice;
|
|
5485
5485
|
if (a && u.length > 0) {
|
|
5486
|
-
const p = u.find((
|
|
5486
|
+
const p = u.find((E) => E.name.includes(a) || E.lang === o);
|
|
5487
5487
|
p && (s.voice = p);
|
|
5488
5488
|
}
|
|
5489
|
-
const
|
|
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", b = this.lipsyncPreProcessText(i, g), x = this.lipsyncWordsToVisemes(b, g);
|
|
5490
5490
|
console.log("Browser TTS Lip-sync Debug:", {
|
|
5491
5491
|
text: i,
|
|
5492
5492
|
lipsyncLang: g,
|
|
5493
|
-
processedText:
|
|
5494
|
-
lipsyncData:
|
|
5495
|
-
hasVisemes:
|
|
5496
|
-
estimatedDuration:
|
|
5493
|
+
processedText: b,
|
|
5494
|
+
lipsyncData: x,
|
|
5495
|
+
hasVisemes: x && x.visemes && x.visemes.length > 0,
|
|
5496
|
+
estimatedDuration: c
|
|
5497
5497
|
});
|
|
5498
|
-
const
|
|
5499
|
-
if (
|
|
5500
|
-
const p =
|
|
5501
|
-
for (let
|
|
5502
|
-
const
|
|
5503
|
-
|
|
5498
|
+
const A = [];
|
|
5499
|
+
if (x && x.visemes && x.visemes.length > 0) {
|
|
5500
|
+
const p = x.times[x.visemes.length - 1] + x.durations[x.visemes.length - 1];
|
|
5501
|
+
for (let E = 0; E < x.visemes.length; E++) {
|
|
5502
|
+
const I = x.visemes[E], y = x.times[E] / p, H = x.durations[E] / p, w = y * c, D = H * c;
|
|
5503
|
+
A.push({
|
|
5504
5504
|
template: { name: "viseme" },
|
|
5505
|
-
ts: [
|
|
5505
|
+
ts: [w - Math.min(60, 2 * D / 3), w + Math.min(25, D / 2), w + D + Math.min(60, D / 2)],
|
|
5506
5506
|
vs: {
|
|
5507
|
-
["viseme_" +
|
|
5507
|
+
["viseme_" + I]: [null, I === "PP" || I === "FF" ? 0.9 : 0.6, 0]
|
|
5508
5508
|
}
|
|
5509
5509
|
});
|
|
5510
5510
|
}
|
|
5511
5511
|
}
|
|
5512
|
-
const
|
|
5513
|
-
this.audioPlaylist.push({ anim:
|
|
5512
|
+
const B = [...t.anim, ...A];
|
|
5513
|
+
this.audioPlaylist.push({ anim: B, 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);
|
|
@@ -5522,7 +5522,7 @@ class Be {
|
|
|
5522
5522
|
* @param {Object} line Speech line object
|
|
5523
5523
|
*/
|
|
5524
5524
|
async synthesizeWithElevenLabsTTS(t) {
|
|
5525
|
-
const e = t.text.map((
|
|
5525
|
+
const e = t.text.map((c) => c.word).join(" "), n = t.voice || this.avatar.ttsVoice || this.opt.ttsVoice || "21m00Tcm4TlvDq8ikWAM", i = {
|
|
5526
5526
|
text: e,
|
|
5527
5527
|
model_id: "eleven_monolingual_v1",
|
|
5528
5528
|
voice_settings: {
|
|
@@ -5552,18 +5552,18 @@ class Be {
|
|
|
5552
5552
|
lipsyncKeys: this.lipsync ? Object.keys(this.lipsync) : [],
|
|
5553
5553
|
lipsyncLang: h
|
|
5554
5554
|
});
|
|
5555
|
-
const
|
|
5555
|
+
const c = this.lipsyncPreProcessText(e, h), d = this.lipsyncWordsToVisemes(c, h);
|
|
5556
5556
|
if (console.log("Lip-sync data:", {
|
|
5557
|
-
processedText:
|
|
5558
|
-
lipsyncData:
|
|
5559
|
-
hasVisemes:
|
|
5560
|
-
}),
|
|
5557
|
+
processedText: c,
|
|
5558
|
+
lipsyncData: d,
|
|
5559
|
+
hasVisemes: d && d.visemes && d.visemes.length > 0
|
|
5560
|
+
}), d && d.visemes && d.visemes.length > 0)
|
|
5561
5561
|
r = {
|
|
5562
|
-
visemes:
|
|
5562
|
+
visemes: d.visemes.map((g, b) => ({
|
|
5563
5563
|
viseme: g,
|
|
5564
|
-
startTime:
|
|
5565
|
-
endTime: (
|
|
5566
|
-
duration: l.duration /
|
|
5564
|
+
startTime: b * l.duration / d.visemes.length,
|
|
5565
|
+
endTime: (b + 1) * l.duration / d.visemes.length,
|
|
5566
|
+
duration: l.duration / d.visemes.length,
|
|
5567
5567
|
intensity: 0.7
|
|
5568
5568
|
})),
|
|
5569
5569
|
words: [],
|
|
@@ -5572,19 +5572,19 @@ class Be {
|
|
|
5572
5572
|
};
|
|
5573
5573
|
else
|
|
5574
5574
|
throw new Error("No visemes generated from text");
|
|
5575
|
-
} catch (
|
|
5576
|
-
console.error("Text-based lip-sync failed, using fallback:",
|
|
5577
|
-
const
|
|
5578
|
-
for (const
|
|
5579
|
-
for (const
|
|
5580
|
-
let
|
|
5581
|
-
"aeiou".includes(
|
|
5575
|
+
} catch (c) {
|
|
5576
|
+
console.error("Text-based lip-sync failed, using fallback:", c);
|
|
5577
|
+
const d = e.toLowerCase().split(/\s+/), g = [];
|
|
5578
|
+
for (const b of d)
|
|
5579
|
+
for (const x of b) {
|
|
5580
|
+
let A = "aa";
|
|
5581
|
+
"aeiou".includes(x) ? A = "aa" : "bp".includes(x) ? A = "PP" : "fv".includes(x) ? A = "FF" : "st".includes(x) ? A = "SS" : "dln".includes(x) ? A = "DD" : "kg".includes(x) ? A = "kk" : "rw".includes(x) && (A = "RR"), g.push(A);
|
|
5582
5582
|
}
|
|
5583
5583
|
r = {
|
|
5584
|
-
visemes: g.map((
|
|
5585
|
-
viseme:
|
|
5586
|
-
startTime:
|
|
5587
|
-
endTime: (
|
|
5584
|
+
visemes: g.map((b, x) => ({
|
|
5585
|
+
viseme: b,
|
|
5586
|
+
startTime: x * l.duration / g.length,
|
|
5587
|
+
endTime: (x + 1) * l.duration / g.length,
|
|
5588
5588
|
duration: l.duration / g.length,
|
|
5589
5589
|
intensity: 0.6
|
|
5590
5590
|
})),
|
|
@@ -5608,13 +5608,13 @@ class Be {
|
|
|
5608
5608
|
const u = [];
|
|
5609
5609
|
if (r.visemes && r.visemes.length > 0) {
|
|
5610
5610
|
console.log("ElevenLabs: Generating lip-sync animation from", r.visemes.length, "visemes");
|
|
5611
|
-
for (let
|
|
5612
|
-
const
|
|
5611
|
+
for (let c = 0; c < r.visemes.length; c++) {
|
|
5612
|
+
const d = r.visemes[c], g = d.startTime * 1e3, b = d.duration * 1e3, x = d.intensity;
|
|
5613
5613
|
u.push({
|
|
5614
5614
|
template: { name: "viseme" },
|
|
5615
|
-
ts: [g - Math.min(60, 2 *
|
|
5615
|
+
ts: [g - Math.min(60, 2 * b / 3), g + Math.min(25, b / 2), g + b + Math.min(60, b / 2)],
|
|
5616
5616
|
vs: {
|
|
5617
|
-
["viseme_" +
|
|
5617
|
+
["viseme_" + d.viseme]: [null, x, 0]
|
|
5618
5618
|
}
|
|
5619
5619
|
});
|
|
5620
5620
|
}
|
|
@@ -5629,7 +5629,7 @@ class Be {
|
|
|
5629
5629
|
* @param {Object} line Speech line object
|
|
5630
5630
|
*/
|
|
5631
5631
|
async synthesizeWithDeepgramTTS(t) {
|
|
5632
|
-
const e = t.text.map((
|
|
5632
|
+
const e = t.text.map((c) => c.word).join(" "), n = t.voice || this.avatar.ttsVoice || this.opt.ttsVoice || "aura-2-thalia-en", i = `${this.opt.ttsEndpoint}?model=${n}`, s = await fetch(i, {
|
|
5633
5633
|
method: "POST",
|
|
5634
5634
|
headers: {
|
|
5635
5635
|
Authorization: `Token ${this.opt.ttsApikey}`,
|
|
@@ -5650,18 +5650,18 @@ class Be {
|
|
|
5650
5650
|
lipsyncKeys: this.lipsync ? Object.keys(this.lipsync) : [],
|
|
5651
5651
|
lipsyncLang: h
|
|
5652
5652
|
});
|
|
5653
|
-
const
|
|
5653
|
+
const c = this.lipsyncPreProcessText(e, h), d = this.lipsyncWordsToVisemes(c, h);
|
|
5654
5654
|
if (console.log("Lip-sync data:", {
|
|
5655
|
-
processedText:
|
|
5656
|
-
lipsyncData:
|
|
5657
|
-
hasVisemes:
|
|
5658
|
-
}),
|
|
5655
|
+
processedText: c,
|
|
5656
|
+
lipsyncData: d,
|
|
5657
|
+
hasVisemes: d && d.visemes && d.visemes.length > 0
|
|
5658
|
+
}), d && d.visemes && d.visemes.length > 0)
|
|
5659
5659
|
r = {
|
|
5660
|
-
visemes:
|
|
5660
|
+
visemes: d.visemes.map((g, b) => ({
|
|
5661
5661
|
viseme: g,
|
|
5662
|
-
startTime:
|
|
5663
|
-
endTime: (
|
|
5664
|
-
duration: l.duration /
|
|
5662
|
+
startTime: b * l.duration / d.visemes.length,
|
|
5663
|
+
endTime: (b + 1) * l.duration / d.visemes.length,
|
|
5664
|
+
duration: l.duration / d.visemes.length,
|
|
5665
5665
|
intensity: 0.7
|
|
5666
5666
|
})),
|
|
5667
5667
|
words: [],
|
|
@@ -5670,19 +5670,19 @@ class Be {
|
|
|
5670
5670
|
};
|
|
5671
5671
|
else
|
|
5672
5672
|
throw new Error("No visemes generated from text");
|
|
5673
|
-
} catch (
|
|
5674
|
-
console.error("Text-based lip-sync failed, using fallback:",
|
|
5675
|
-
const
|
|
5676
|
-
for (const
|
|
5677
|
-
for (const
|
|
5678
|
-
let
|
|
5679
|
-
"aeiou".includes(
|
|
5673
|
+
} catch (c) {
|
|
5674
|
+
console.error("Text-based lip-sync failed, using fallback:", c);
|
|
5675
|
+
const d = e.toLowerCase().split(/\s+/), g = [];
|
|
5676
|
+
for (const b of d)
|
|
5677
|
+
for (const x of b) {
|
|
5678
|
+
let A = "aa";
|
|
5679
|
+
"aeiou".includes(x) ? A = "aa" : "bp".includes(x) ? A = "PP" : "fv".includes(x) ? A = "FF" : "st".includes(x) ? A = "SS" : "dln".includes(x) ? A = "DD" : "kg".includes(x) ? A = "kk" : "rw".includes(x) && (A = "RR"), g.push(A);
|
|
5680
5680
|
}
|
|
5681
5681
|
r = {
|
|
5682
|
-
visemes: g.map((
|
|
5683
|
-
viseme:
|
|
5684
|
-
startTime:
|
|
5685
|
-
endTime: (
|
|
5682
|
+
visemes: g.map((b, x) => ({
|
|
5683
|
+
viseme: b,
|
|
5684
|
+
startTime: x * l.duration / g.length,
|
|
5685
|
+
endTime: (x + 1) * l.duration / g.length,
|
|
5686
5686
|
duration: l.duration / g.length,
|
|
5687
5687
|
intensity: 0.6
|
|
5688
5688
|
})),
|
|
@@ -5706,13 +5706,13 @@ class Be {
|
|
|
5706
5706
|
const u = [];
|
|
5707
5707
|
if (r.visemes && r.visemes.length > 0) {
|
|
5708
5708
|
console.log("Deepgram: Generating lip-sync animation from", r.visemes.length, "visemes");
|
|
5709
|
-
for (let
|
|
5710
|
-
const
|
|
5709
|
+
for (let c = 0; c < r.visemes.length; c++) {
|
|
5710
|
+
const d = r.visemes[c], g = d.startTime * 1e3, b = d.duration * 1e3, x = d.intensity;
|
|
5711
5711
|
u.push({
|
|
5712
5712
|
template: { name: "viseme" },
|
|
5713
|
-
ts: [g - Math.min(60, 2 *
|
|
5713
|
+
ts: [g - Math.min(60, 2 * b / 3), g + Math.min(25, b / 2), g + b + Math.min(60, b / 2)],
|
|
5714
5714
|
vs: {
|
|
5715
|
-
["viseme_" +
|
|
5715
|
+
["viseme_" + d.viseme]: [null, x, 0]
|
|
5716
5716
|
}
|
|
5717
5717
|
});
|
|
5718
5718
|
}
|
|
@@ -5759,12 +5759,12 @@ class Be {
|
|
|
5759
5759
|
});
|
|
5760
5760
|
const r = [];
|
|
5761
5761
|
for (let a = 0; a < h.visemes.length; a++) {
|
|
5762
|
-
const
|
|
5762
|
+
const c = h.visemes[a], d = c.startTime * 1e3, g = c.duration * 1e3, b = c.intensity;
|
|
5763
5763
|
r.push({
|
|
5764
5764
|
template: { name: "viseme" },
|
|
5765
|
-
ts: [
|
|
5765
|
+
ts: [d - Math.min(60, 2 * g / 3), d + Math.min(25, g / 2), d + g + Math.min(60, g / 2)],
|
|
5766
5766
|
vs: {
|
|
5767
|
-
["viseme_" +
|
|
5767
|
+
["viseme_" + c.viseme]: [null, b, 0]
|
|
5768
5768
|
}
|
|
5769
5769
|
});
|
|
5770
5770
|
}
|
|
@@ -5810,25 +5810,25 @@ class Be {
|
|
|
5810
5810
|
this.speakWithHands();
|
|
5811
5811
|
const h = [0];
|
|
5812
5812
|
let r = 0;
|
|
5813
|
-
t.text.forEach((
|
|
5814
|
-
if (
|
|
5813
|
+
t.text.forEach((c, d) => {
|
|
5814
|
+
if (d > 0) {
|
|
5815
5815
|
let g = h[h.length - 1];
|
|
5816
|
-
s.timepoints[r] && (g = s.timepoints[r].timeSeconds * 1e3, s.timepoints[r].markName === "" +
|
|
5816
|
+
s.timepoints[r] && (g = s.timepoints[r].timeSeconds * 1e3, s.timepoints[r].markName === "" + c.mark && r++), h.push(g);
|
|
5817
5817
|
}
|
|
5818
5818
|
});
|
|
5819
5819
|
const u = [{ mark: 0, time: 0 }];
|
|
5820
|
-
h.forEach((
|
|
5821
|
-
if (
|
|
5822
|
-
let g =
|
|
5823
|
-
u[
|
|
5820
|
+
h.forEach((c, d) => {
|
|
5821
|
+
if (d > 0) {
|
|
5822
|
+
let g = c - h[d - 1];
|
|
5823
|
+
u[d - 1].duration = g, u.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), u[u.length - 1].duration = a - u[u.length - 1].time, t.anim.forEach((
|
|
5828
|
-
const
|
|
5829
|
-
if (
|
|
5830
|
-
for (let g = 0; g <
|
|
5831
|
-
|
|
5827
|
+
a > this.opt.ttsTrimEnd && (a = a - this.opt.ttsTrimEnd), u[u.length - 1].duration = a - u[u.length - 1].time, t.anim.forEach((c) => {
|
|
5828
|
+
const d = u[c.mark];
|
|
5829
|
+
if (d)
|
|
5830
|
+
for (let g = 0; g < c.ts.length; g++)
|
|
5831
|
+
c.ts[g] = d.time + c.ts[g] * d.duration + this.opt.ttsTrimStart;
|
|
5832
5832
|
}), this.audioPlaylist.push({ anim: t.anim, audio: l }), this.onSubtitles = t.onSubtitles || null, this.resetLips(), t.mood && this.setMood(t.mood), this.playAudio();
|
|
5833
5833
|
} else
|
|
5834
5834
|
this.startSpeaking(!0);
|
|
@@ -6047,15 +6047,15 @@ class Be {
|
|
|
6047
6047
|
const l = this.streamLipsyncLang || this.avatar.lipsyncLang || this.opt.lipsyncLang, h = this.lipsyncPreProcessText(i, l), r = this.lipsyncWordsToVisemes(h, l);
|
|
6048
6048
|
if (r && r.visemes && r.visemes.length) {
|
|
6049
6049
|
const u = 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
|
-
let
|
|
6050
|
+
let c = 0.6 + this.convertRange(a, [0, o], [0, 0.4]);
|
|
6051
6051
|
if (o = Math.min(o, r.visemes.length * 200), u > 0)
|
|
6052
|
-
for (let
|
|
6053
|
-
const g = e + s + r.times[
|
|
6052
|
+
for (let d = 0; d < r.visemes.length; d++) {
|
|
6053
|
+
const g = e + s + r.times[d] / u * o, b = r.durations[d] / u * o;
|
|
6054
6054
|
this.animQueue.push({
|
|
6055
6055
|
template: { name: "viseme" },
|
|
6056
|
-
ts: [g - Math.min(60, 2 *
|
|
6056
|
+
ts: [g - Math.min(60, 2 * b / 3), g + Math.min(25, b / 2), g + b + Math.min(60, b / 2)],
|
|
6057
6057
|
vs: {
|
|
6058
|
-
["viseme_" + r.visemes[
|
|
6058
|
+
["viseme_" + r.visemes[d]]: [null, r.visemes[d] === "PP" || r.visemes[d] === "FF" ? 0.9 : c, 0]
|
|
6059
6059
|
}
|
|
6060
6060
|
});
|
|
6061
6061
|
}
|
|
@@ -6146,7 +6146,7 @@ class Be {
|
|
|
6146
6146
|
*/
|
|
6147
6147
|
lookAtCamera(t) {
|
|
6148
6148
|
let e;
|
|
6149
|
-
if (this.speakTo && (e = new
|
|
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,22 +6159,22 @@ 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),
|
|
6163
|
-
const n = new
|
|
6164
|
-
|
|
6165
|
-
const l = new
|
|
6166
|
-
|
|
6167
|
-
let r =
|
|
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
|
+
const n = new f.Vector3().subVectors(e, ve).normalize(), i = Math.atan2(n.x, n.z), s = Math.asin(-n.y);
|
|
6164
|
+
G.set(s, i, 0, "YXZ");
|
|
6165
|
+
const l = new f.Quaternion().setFromEuler(G), h = new f.Quaternion().copy(l).multiply(Q.clone().invert());
|
|
6166
|
+
G.setFromQuaternion(h, "YXZ");
|
|
6167
|
+
let r = G.x / (40 / 24) + 0.2, u = G.y / (9 / 4), a = Math.min(0.6, Math.max(-0.3, r)), c = Math.min(0.8, Math.max(-0.8, u)), d = (Math.random() - 0.5) / 4, g = (Math.random() - 0.5) / 4;
|
|
6168
6168
|
if (t) {
|
|
6169
|
-
let
|
|
6170
|
-
|
|
6171
|
-
const
|
|
6169
|
+
let b = this.animQueue.findIndex((A) => A.template.name === "lookat");
|
|
6170
|
+
b !== -1 && this.animQueue.splice(b, 1);
|
|
6171
|
+
const x = {
|
|
6172
6172
|
name: "lookat",
|
|
6173
6173
|
dt: [750, t],
|
|
6174
6174
|
vs: {
|
|
6175
|
-
bodyRotateX: [a +
|
|
6176
|
-
bodyRotateY: [
|
|
6177
|
-
eyesRotateX: [-3 *
|
|
6175
|
+
bodyRotateX: [a + d],
|
|
6176
|
+
bodyRotateY: [c + g],
|
|
6177
|
+
eyesRotateX: [-3 * d + 0.1],
|
|
6178
6178
|
eyesRotateY: [-5 * g],
|
|
6179
6179
|
browInnerUp: [[0, 0.7]],
|
|
6180
6180
|
mouthLeft: [[0, 0.7]],
|
|
@@ -6183,7 +6183,7 @@ class Be {
|
|
|
6183
6183
|
headMove: [0]
|
|
6184
6184
|
}
|
|
6185
6185
|
};
|
|
6186
|
-
this.animQueue.push(this.animFactory(
|
|
6186
|
+
this.animQueue.push(this.animFactory(x));
|
|
6187
6187
|
}
|
|
6188
6188
|
}
|
|
6189
6189
|
/**
|
|
@@ -6196,23 +6196,23 @@ class Be {
|
|
|
6196
6196
|
if (!this.camera) return;
|
|
6197
6197
|
const i = this.nodeAvatar.getBoundingClientRect();
|
|
6198
6198
|
this.objectLeftEye.updateMatrixWorld(!0), this.objectRightEye.updateMatrixWorld(!0);
|
|
6199
|
-
const s = new
|
|
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
6201
|
let h = (l.x + 1) / 2 * i.width + i.left, r = -(l.y - 1) / 2 * i.height + i.top;
|
|
6202
|
-
t === null && (t = h), 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"]),
|
|
6203
|
-
let u =
|
|
6204
|
-
|
|
6205
|
-
let
|
|
6202
|
+
t === null && (t = h), 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"]), G.setFromQuaternion(Q);
|
|
6203
|
+
let u = G.x / (40 / 24), a = G.y / (9 / 4), c = Math.min(0.4, Math.max(-0.4, this.camera.rotation.x)), d = Math.min(0.4, Math.max(-0.4, this.camera.rotation.y)), g = Math.max(window.innerWidth - h, h), b = Math.max(window.innerHeight - r, r), x = this.convertRange(e, [r - b, r + b], [-0.3, 0.6]) - u + c, A = this.convertRange(t, [h - g, h + g], [-0.8, 0.8]) - a + d;
|
|
6204
|
+
x = Math.min(0.6, Math.max(-0.3, x)), A = Math.min(0.8, Math.max(-0.8, A));
|
|
6205
|
+
let B = (Math.random() - 0.5) / 4, p = (Math.random() - 0.5) / 4;
|
|
6206
6206
|
if (n) {
|
|
6207
|
-
let
|
|
6208
|
-
|
|
6209
|
-
const
|
|
6207
|
+
let E = this.animQueue.findIndex((y) => y.template.name === "lookat");
|
|
6208
|
+
E !== -1 && this.animQueue.splice(E, 1);
|
|
6209
|
+
const I = {
|
|
6210
6210
|
name: "lookat",
|
|
6211
6211
|
dt: [750, n],
|
|
6212
6212
|
vs: {
|
|
6213
|
-
bodyRotateX: [
|
|
6214
|
-
bodyRotateY: [
|
|
6215
|
-
eyesRotateX: [-3 *
|
|
6213
|
+
bodyRotateX: [x + B],
|
|
6214
|
+
bodyRotateY: [A + p],
|
|
6215
|
+
eyesRotateX: [-3 * B + 0.1],
|
|
6216
6216
|
eyesRotateY: [-5 * p],
|
|
6217
6217
|
browInnerUp: [[0, 0.7]],
|
|
6218
6218
|
mouthLeft: [[0, 0.7]],
|
|
@@ -6221,7 +6221,7 @@ class Be {
|
|
|
6221
6221
|
headMove: [0]
|
|
6222
6222
|
}
|
|
6223
6223
|
};
|
|
6224
|
-
this.animQueue.push(this.animFactory(
|
|
6224
|
+
this.animQueue.push(this.animFactory(I));
|
|
6225
6225
|
}
|
|
6226
6226
|
}
|
|
6227
6227
|
/**
|
|
@@ -6232,14 +6232,14 @@ class Be {
|
|
|
6232
6232
|
*/
|
|
6233
6233
|
touchAt(t, e) {
|
|
6234
6234
|
if (!this.camera) return;
|
|
6235
|
-
const n = this.nodeAvatar.getBoundingClientRect(), i = new
|
|
6235
|
+
const n = this.nodeAvatar.getBoundingClientRect(), i = new f.Vector2(
|
|
6236
6236
|
(t - n.left) / n.width * 2 - 1,
|
|
6237
6237
|
-((e - n.top) / n.height) * 2 + 1
|
|
6238
|
-
), s = new
|
|
6238
|
+
), s = new f.Raycaster();
|
|
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, h = new
|
|
6242
|
+
const l = o[0].point, h = new f.Vector3(), r = new f.Vector3();
|
|
6243
6243
|
this.objectLeftArm.getWorldPosition(h), this.objectRightArm.getWorldPosition(r);
|
|
6244
6244
|
const u = h.distanceToSquared(l), a = r.distanceToSquared(l);
|
|
6245
6245
|
u < a ? (this.ikSolve({
|
|
@@ -6283,7 +6283,7 @@ class Be {
|
|
|
6283
6283
|
{ link: "LeftForeArm", minx: -0.5, maxx: 1.5, miny: -1.5, maxy: 1.5, minz: -0.5, maxz: 3 },
|
|
6284
6284
|
{ link: "LeftArm", minx: -1.5, maxx: 1.5, miny: -1.5, maxy: 1.5, minz: -1, maxz: 3 }
|
|
6285
6285
|
]
|
|
6286
|
-
}, new
|
|
6286
|
+
}, new f.Vector3(
|
|
6287
6287
|
this.gaussianRandom(0, 0.5),
|
|
6288
6288
|
this.gaussianRandom(-0.8, -0.2),
|
|
6289
6289
|
this.gaussianRandom(0, 0.5)
|
|
@@ -6295,15 +6295,15 @@ class Be {
|
|
|
6295
6295
|
{ link: "RightForeArm", minx: -0.5, maxx: 1.5, miny: -1.5, maxy: 1.5, minz: -3, maxz: 0.5 },
|
|
6296
6296
|
{ link: "RightArm" }
|
|
6297
6297
|
]
|
|
6298
|
-
}, new
|
|
6298
|
+
}, new f.Vector3(
|
|
6299
6299
|
this.gaussianRandom(-0.5, 0),
|
|
6300
6300
|
this.gaussianRandom(-0.8, -0.2),
|
|
6301
6301
|
this.gaussianRandom(0, 0.5)
|
|
6302
6302
|
), !0);
|
|
6303
6303
|
const n = [], i = [];
|
|
6304
6304
|
n.push(100 + Math.round(Math.random() * 500)), i.push({ duration: 1e3, props: {
|
|
6305
|
-
"LeftHand.quaternion": new
|
|
6306
|
-
"RightHand.quaternion": new
|
|
6305
|
+
"LeftHand.quaternion": new f.Quaternion().setFromEuler(new f.Euler(0, -1 - Math.random(), 0)),
|
|
6306
|
+
"RightHand.quaternion": new f.Quaternion().setFromEuler(new f.Euler(0, 1 + Math.random(), 0))
|
|
6307
6307
|
} }), ["LeftArm", "LeftForeArm", "RightArm", "RightForeArm"].forEach((o) => {
|
|
6308
6308
|
i[0].props[o + ".quaternion"] = this.ikMesh.getObjectByName(o).quaternion.clone();
|
|
6309
6309
|
}), n.push(1e3 + Math.round(Math.random() * 500)), i.push({ duration: 2e3, props: {} }), ["LeftArm", "LeftForeArm", "RightArm", "RightForeArm", "LeftHand", "RightHand"].forEach((o) => {
|
|
@@ -6388,9 +6388,9 @@ class Be {
|
|
|
6388
6388
|
let h = this.animQueue.find((a) => a.template.name === "pose");
|
|
6389
6389
|
h && (h.ts[0] = 1 / 0), Object.entries(l.pose.props).forEach((a) => {
|
|
6390
6390
|
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;
|
|
6391
|
-
}), this.mixer ? console.log("Using existing mixer for FBX animation, preserving morph targets") : (this.mixer = new
|
|
6391
|
+
}), 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 });
|
|
6392
6392
|
const r = Math.ceil(n / l.clip.duration), u = this.mixer.clipAction(l.clip);
|
|
6393
|
-
u.setLoop(
|
|
6393
|
+
u.setLoop(f.LoopRepeat, r), u.clampWhenFinished = !0, this.currentFBXAction = u;
|
|
6394
6394
|
try {
|
|
6395
6395
|
u.fadeIn(0.5).play(), console.log("FBX animation started successfully:", t);
|
|
6396
6396
|
} catch (a) {
|
|
@@ -6408,58 +6408,134 @@ class Be {
|
|
|
6408
6408
|
}
|
|
6409
6409
|
let r = !1;
|
|
6410
6410
|
try {
|
|
6411
|
-
const
|
|
6412
|
-
if (r =
|
|
6413
|
-
console.error(`FBX file not found at ${t}. Status: ${
|
|
6411
|
+
const c = await fetch(t, { method: "HEAD" });
|
|
6412
|
+
if (r = c.ok, !r) {
|
|
6413
|
+
console.error(`FBX file not found at ${t}. Status: ${c.status}`), console.error("Please check:"), console.error("1. File path is correct (note: path is case-sensitive)"), console.error("2. File exists in your public folder"), console.error("3. File is accessible (not blocked by server)");
|
|
6414
6414
|
return;
|
|
6415
6415
|
}
|
|
6416
|
-
} catch (
|
|
6417
|
-
console.warn(`Could not verify file existence for ${t}, attempting to load anyway:`,
|
|
6416
|
+
} catch (c) {
|
|
6417
|
+
console.warn(`Could not verify file existence for ${t}, attempting to load anyway:`, c);
|
|
6418
6418
|
}
|
|
6419
|
-
const u = new
|
|
6419
|
+
const u = new De();
|
|
6420
6420
|
let a;
|
|
6421
6421
|
try {
|
|
6422
6422
|
a = await u.loadAsync(t, e);
|
|
6423
|
-
} catch (
|
|
6424
|
-
console.error(`Failed to load FBX animation from ${t}:`,
|
|
6425
|
-
message:
|
|
6423
|
+
} catch (c) {
|
|
6424
|
+
console.error(`Failed to load FBX animation from ${t}:`, c), console.error("Error details:", {
|
|
6425
|
+
message: c.message,
|
|
6426
6426
|
url: t,
|
|
6427
6427
|
suggestion: "Make sure the file is a valid FBX file and the path is correct"
|
|
6428
|
-
}),
|
|
6428
|
+
}), c.message && c.message.includes("version number") && (console.error("FBX Loader Error: Cannot find version number"), console.error("This error usually means:"), console.error("1. The file is not a valid FBX file (might be GLB, corrupted, or wrong format)"), console.error("2. The file might be corrupted"), console.error("3. The file path might be incorrect"), console.error("4. The server returned an HTML error page instead of the FBX file"), console.error("5. The file might not exist at that path"), console.error(""), console.error("Solution: Please verify:"), console.error(` - File exists at: ${t}`), console.error(" - File is a valid FBX binary file"), console.error(" - File path matches your public folder structure"), console.error(" - File is not corrupted"));
|
|
6429
6429
|
try {
|
|
6430
|
-
const
|
|
6430
|
+
const d = await fetch(t), g = d.headers.get("content-type"), b = await d.text();
|
|
6431
6431
|
console.error("Response details:", {
|
|
6432
|
-
status:
|
|
6432
|
+
status: d.status,
|
|
6433
6433
|
contentType: g,
|
|
6434
|
-
firstBytes:
|
|
6435
|
-
isHTML:
|
|
6436
|
-
}), (
|
|
6437
|
-
} catch (
|
|
6438
|
-
console.error("Could not fetch file for debugging:",
|
|
6434
|
+
firstBytes: b.substring(0, 100),
|
|
6435
|
+
isHTML: b.trim().startsWith("<!DOCTYPE") || b.trim().startsWith("<html")
|
|
6436
|
+
}), (b.trim().startsWith("<!DOCTYPE") || b.trim().startsWith("<html")) && console.error("The server returned an HTML page instead of an FBX file. The file path is likely incorrect.");
|
|
6437
|
+
} catch (d) {
|
|
6438
|
+
console.error("Could not fetch file for debugging:", d);
|
|
6439
6439
|
}
|
|
6440
6440
|
return;
|
|
6441
6441
|
}
|
|
6442
6442
|
if (a && a.animations && a.animations[i]) {
|
|
6443
|
-
let
|
|
6444
|
-
const
|
|
6445
|
-
|
|
6446
|
-
|
|
6447
|
-
|
|
6448
|
-
|
|
6449
|
-
|
|
6450
|
-
|
|
6451
|
-
|
|
6452
|
-
|
|
6443
|
+
let c = a.animations[i];
|
|
6444
|
+
const d = /* @__PURE__ */ new Set();
|
|
6445
|
+
this.armature && this.armature.traverse((I) => {
|
|
6446
|
+
(I.isBone || I.type === "Bone") && d.add(I.name);
|
|
6447
|
+
});
|
|
6448
|
+
const g = /* @__PURE__ */ new Map(), b = (I) => {
|
|
6449
|
+
if (d.has(I))
|
|
6450
|
+
return I;
|
|
6451
|
+
let y = I.replace(/^mixamorig/i, "");
|
|
6452
|
+
if (d.has(y))
|
|
6453
|
+
return y;
|
|
6454
|
+
const H = {
|
|
6455
|
+
// Arm bones - handle common variations
|
|
6456
|
+
LeftArm: "LeftArm",
|
|
6457
|
+
leftArm: "LeftArm",
|
|
6458
|
+
LEFTARM: "LeftArm",
|
|
6459
|
+
RightArm: "RightArm",
|
|
6460
|
+
rightArm: "RightArm",
|
|
6461
|
+
RIGHTARM: "RightArm",
|
|
6462
|
+
LeftForeArm: "LeftForeArm",
|
|
6463
|
+
leftForeArm: "LeftForeArm",
|
|
6464
|
+
leftForearm: "LeftForeArm",
|
|
6465
|
+
LeftForearm: "LeftForeArm",
|
|
6466
|
+
RightForeArm: "RightForeArm",
|
|
6467
|
+
rightForeArm: "RightForeArm",
|
|
6468
|
+
rightForearm: "RightForeArm",
|
|
6469
|
+
RightForearm: "RightForeArm",
|
|
6470
|
+
LeftHand: "LeftHand",
|
|
6471
|
+
leftHand: "LeftHand",
|
|
6472
|
+
RightHand: "RightHand",
|
|
6473
|
+
rightHand: "RightHand",
|
|
6474
|
+
LeftShoulder: "LeftShoulder",
|
|
6475
|
+
leftShoulder: "LeftShoulder",
|
|
6476
|
+
RightShoulder: "RightShoulder",
|
|
6477
|
+
rightShoulder: "RightShoulder",
|
|
6478
|
+
// Spine
|
|
6479
|
+
Spine: "Spine1",
|
|
6480
|
+
spine: "Spine1",
|
|
6481
|
+
Spine1: "Spine1",
|
|
6482
|
+
Spine2: "Spine2",
|
|
6483
|
+
// Head/Neck
|
|
6484
|
+
Head: "Head",
|
|
6485
|
+
head: "Head",
|
|
6486
|
+
Neck: "Neck",
|
|
6487
|
+
neck: "Neck",
|
|
6488
|
+
// Hips
|
|
6489
|
+
Hips: "Hips",
|
|
6490
|
+
hips: "Hips",
|
|
6491
|
+
Root: "Hips",
|
|
6492
|
+
root: "Hips"
|
|
6493
|
+
};
|
|
6494
|
+
if (H[y]) {
|
|
6495
|
+
const w = H[y];
|
|
6496
|
+
if (d.has(w))
|
|
6497
|
+
return w;
|
|
6498
|
+
}
|
|
6499
|
+
for (const w of d)
|
|
6500
|
+
if (w.toLowerCase() === y.toLowerCase())
|
|
6501
|
+
return w;
|
|
6502
|
+
return null;
|
|
6503
|
+
}, x = /* @__PURE__ */ new Set();
|
|
6504
|
+
c.tracks.forEach((I) => {
|
|
6505
|
+
const y = I.name.split(".");
|
|
6506
|
+
x.add(y[0]);
|
|
6507
|
+
}), console.log("Ready Player Me FBX bone names:", Array.from(x).sort().join(", ")), console.log("Avatar skeleton bone names:", Array.from(d).sort().join(", "));
|
|
6508
|
+
const A = [], B = /* @__PURE__ */ new Set();
|
|
6509
|
+
c.tracks.forEach((I) => {
|
|
6510
|
+
const H = I.name.replaceAll("mixamorig", "").split("."), w = H[0], D = H[1], $ = b(w);
|
|
6511
|
+
if ($ && D) {
|
|
6512
|
+
const k = `${$}.${D}`, V = I.clone();
|
|
6513
|
+
V.name = k, A.push(V), w !== $ && g.set(w, $);
|
|
6514
|
+
} else
|
|
6515
|
+
B.add(w), (w.toLowerCase().includes("arm") || w.toLowerCase().includes("hand") || w.toLowerCase().includes("shoulder")) && console.warn(`⚠️ Arm bone "${w}" could not be mapped to avatar skeleton`);
|
|
6516
|
+
}), B.size > 0 && console.warn(`⚠️ ${B.size} bone(s) could not be mapped:`, Array.from(B).sort().join(", ")), A.length > 0 && (c = new f.AnimationClip(c.name, c.duration, A), g.size > 0 && console.log(
|
|
6517
|
+
`Mapped ${g.size} bone(s) for Ready Player Me animation:`,
|
|
6518
|
+
Array.from(g.entries()).slice(0, 5).map(([I, y]) => `${I}→${y}`).join(", ")
|
|
6519
|
+
));
|
|
6520
|
+
const p = {};
|
|
6521
|
+
c.tracks.forEach((I) => {
|
|
6522
|
+
I.name = I.name.replaceAll("mixamorig", "");
|
|
6523
|
+
const y = I.name.split(".");
|
|
6524
|
+
if (y[1] === "position") {
|
|
6525
|
+
for (let H = 0; H < I.values.length; H++)
|
|
6526
|
+
I.values[H] = I.values[H] * s;
|
|
6527
|
+
p[I.name] = new f.Vector3(I.values[0], I.values[1], I.values[2]);
|
|
6528
|
+
} else y[1] === "quaternion" ? p[I.name] = new f.Quaternion(I.values[0], I.values[1], I.values[2], I.values[3]) : y[1] === "rotation" && (p[y[0] + ".quaternion"] = new f.Quaternion().setFromEuler(new f.Euler(I.values[0], I.values[1], I.values[2], "XYZ")).normalize());
|
|
6453
6529
|
});
|
|
6454
|
-
const
|
|
6455
|
-
|
|
6530
|
+
const E = { props: p };
|
|
6531
|
+
p["Hips.position"] && (p["Hips.position"].y < 0.5 ? E.lying = !0 : E.standing = !0), this.animClips.push({
|
|
6456
6532
|
url: t + "-" + i,
|
|
6457
|
-
clip:
|
|
6458
|
-
pose:
|
|
6533
|
+
clip: c,
|
|
6534
|
+
pose: E
|
|
6459
6535
|
}), this.playAnimation(t, e, n, i, s);
|
|
6460
6536
|
} else {
|
|
6461
|
-
const
|
|
6462
|
-
console.error(
|
|
6537
|
+
const c = "Animation " + t + " (ndx=" + i + ") not found";
|
|
6538
|
+
console.error(c), a && a.animations ? console.error(`FBX file loaded but has ${a.animations.length} animation(s), requested index ${i}`) : console.error(a ? "FBX file loaded but contains no animations" : "FBX file failed to load or is invalid");
|
|
6463
6539
|
}
|
|
6464
6540
|
}
|
|
6465
6541
|
}
|
|
@@ -6493,14 +6569,14 @@ class Be {
|
|
|
6493
6569
|
let l = this.animQueue.find((h) => h.template.name === "pose");
|
|
6494
6570
|
l && (l.ts[0] = this.animClock + n * 1e3 + 2e3), this.setPoseFromTemplate(o);
|
|
6495
6571
|
} else {
|
|
6496
|
-
let h = await new
|
|
6572
|
+
let h = await new De().loadAsync(t, e);
|
|
6497
6573
|
if (h && h.animations && h.animations[i]) {
|
|
6498
6574
|
let r = h.animations[i];
|
|
6499
6575
|
const u = {};
|
|
6500
|
-
r.tracks.forEach((
|
|
6501
|
-
|
|
6502
|
-
const
|
|
6503
|
-
|
|
6576
|
+
r.tracks.forEach((c) => {
|
|
6577
|
+
c.name = c.name.replaceAll("mixamorig", "");
|
|
6578
|
+
const d = c.name.split(".");
|
|
6579
|
+
d[1] === "position" ? u[c.name] = new f.Vector3(c.values[0] * s, c.values[1] * s, c.values[2] * s) : d[1] === "quaternion" ? u[c.name] = new f.Quaternion(c.values[0], c.values[1], c.values[2], c.values[3]) : d[1] === "rotation" && (u[d[0] + ".quaternion"] = new f.Quaternion().setFromEuler(new f.Euler(c.values[0], c.values[1], c.values[2], "XYZ")).normalize());
|
|
6504
6580
|
});
|
|
6505
6581
|
const a = { props: u };
|
|
6506
6582
|
u["Hips.position"] && (u["Hips.position"].y < 0.5 ? a.lying = !0 : a.standing = !0), this.animPoses.push({
|
|
@@ -6533,7 +6609,7 @@ class Be {
|
|
|
6533
6609
|
if (s) {
|
|
6534
6610
|
this.gestureTimeout && (clearTimeout(this.gestureTimeout), this.gestureTimeout = null);
|
|
6535
6611
|
let l = this.animQueue.findIndex((h) => h.template.name === "talkinghands");
|
|
6536
|
-
l !== -1 && (this.animQueue[l].ts = this.animQueue[l].ts.map((h) => 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
|
|
6612
|
+
l !== -1 && (this.animQueue[l].ts = this.animQueue[l].ts.map((h) => 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));
|
|
6537
6613
|
for (let [h, r] of Object.entries(this.gesture))
|
|
6538
6614
|
r.t = this.animClock, r.d = i, this.poseTarget.props.hasOwnProperty(h) && (this.poseTarget.props[h].copy(r), this.poseTarget.props[h].t = this.animClock, this.poseTarget.props[h].d = i);
|
|
6539
6615
|
e && Number.isFinite(e) && (this.gestureTimeout = setTimeout(this.stopGesture.bind(this, i), 1e3 * e));
|
|
@@ -6545,13 +6621,13 @@ class Be {
|
|
|
6545
6621
|
if (l.gesture = !0, e && Number.isFinite(e)) {
|
|
6546
6622
|
const h = l.ts[0], u = l.ts[l.ts.length - 1] - h;
|
|
6547
6623
|
if (e * 1e3 - u > 0) {
|
|
6548
|
-
const
|
|
6549
|
-
for (let
|
|
6550
|
-
const
|
|
6551
|
-
l.ts = l.ts.map((
|
|
6624
|
+
const c = [];
|
|
6625
|
+
for (let b = 1; b < l.ts.length; b++) c.push(l.ts[b] - l.ts[b - 1]);
|
|
6626
|
+
const d = o.template?.rescale || c.map((b) => b / u), g = e * 1e3 - u;
|
|
6627
|
+
l.ts = l.ts.map((b, x, A) => x === 0 ? h : A[x - 1] + c[x - 1] + d[x - 1] * g);
|
|
6552
6628
|
} else {
|
|
6553
|
-
const
|
|
6554
|
-
l.ts = l.ts.map((
|
|
6629
|
+
const c = e * 1e3 / u;
|
|
6630
|
+
l.ts = l.ts.map((d) => h + c * (d - h));
|
|
6555
6631
|
}
|
|
6556
6632
|
}
|
|
6557
6633
|
this.animQueue.push(l);
|
|
@@ -6581,34 +6657,34 @@ class Be {
|
|
|
6581
6657
|
* @param {numeric} [d=null] If set, apply in d milliseconds
|
|
6582
6658
|
*/
|
|
6583
6659
|
ikSolve(t, e = null, n = !1, i = null) {
|
|
6584
|
-
const s = new
|
|
6585
|
-
|
|
6586
|
-
const g = this.ikMesh.getObjectByName(t.effector),
|
|
6587
|
-
|
|
6588
|
-
|
|
6589
|
-
}),
|
|
6590
|
-
const
|
|
6660
|
+
const s = new f.Vector3(), o = new f.Vector3(), l = new f.Vector3(), h = new f.Vector3(), r = new f.Quaternion(), u = new f.Vector3(), a = new f.Vector3(), c = new f.Vector3(), d = this.ikMesh.getObjectByName(t.root);
|
|
6661
|
+
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);
|
|
6662
|
+
const g = this.ikMesh.getObjectByName(t.effector), b = t.links;
|
|
6663
|
+
b.forEach((A) => {
|
|
6664
|
+
A.bone = this.ikMesh.getObjectByName(A.link), A.bone.quaternion.copy(this.getPoseTemplateProp(A.link + ".quaternion"));
|
|
6665
|
+
}), d.updateMatrixWorld(!0);
|
|
6666
|
+
const x = t.iterations || 10;
|
|
6591
6667
|
if (e)
|
|
6592
|
-
for (let
|
|
6593
|
-
let
|
|
6594
|
-
for (let p = 0,
|
|
6595
|
-
const
|
|
6596
|
-
|
|
6597
|
-
let
|
|
6598
|
-
|
|
6599
|
-
|
|
6600
|
-
|
|
6601
|
-
|
|
6602
|
-
), new
|
|
6603
|
-
|
|
6604
|
-
|
|
6605
|
-
|
|
6606
|
-
))),
|
|
6668
|
+
for (let A = 0; A < x; A++) {
|
|
6669
|
+
let B = !1;
|
|
6670
|
+
for (let p = 0, E = b.length; p < E; p++) {
|
|
6671
|
+
const I = b[p].bone;
|
|
6672
|
+
I.matrixWorld.decompose(h, r, u), r.invert(), o.setFromMatrixPosition(g.matrixWorld), l.subVectors(o, h), l.applyQuaternion(r), l.normalize(), s.subVectors(e, h), s.applyQuaternion(r), s.normalize();
|
|
6673
|
+
let y = s.dot(l);
|
|
6674
|
+
y > 1 ? y = 1 : y < -1 && (y = -1), y = Math.acos(y), !(y < 1e-5) && (b[p].minAngle !== void 0 && y < b[p].minAngle && (y = b[p].minAngle), b[p].maxAngle !== void 0 && y > b[p].maxAngle && (y = b[p].maxAngle), a.crossVectors(l, s), a.normalize(), Q.setFromAxisAngle(a, y), I.quaternion.multiply(Q), I.rotation.setFromVector3(c.setFromEuler(I.rotation).clamp(new f.Vector3(
|
|
6675
|
+
b[p].minx !== void 0 ? b[p].minx : -1 / 0,
|
|
6676
|
+
b[p].miny !== void 0 ? b[p].miny : -1 / 0,
|
|
6677
|
+
b[p].minz !== void 0 ? b[p].minz : -1 / 0
|
|
6678
|
+
), new f.Vector3(
|
|
6679
|
+
b[p].maxx !== void 0 ? b[p].maxx : 1 / 0,
|
|
6680
|
+
b[p].maxy !== void 0 ? b[p].maxy : 1 / 0,
|
|
6681
|
+
b[p].maxz !== void 0 ? b[p].maxz : 1 / 0
|
|
6682
|
+
))), I.updateMatrixWorld(!0), B = !0);
|
|
6607
6683
|
}
|
|
6608
|
-
if (!
|
|
6684
|
+
if (!B) break;
|
|
6609
6685
|
}
|
|
6610
|
-
i &&
|
|
6611
|
-
this.poseTarget.props[
|
|
6686
|
+
i && b.forEach((A) => {
|
|
6687
|
+
this.poseTarget.props[A.link + ".quaternion"].copy(A.bone.quaternion), this.poseTarget.props[A.link + ".quaternion"].t = this.animClock, this.poseTarget.props[A.link + ".quaternion"].d = i;
|
|
6612
6688
|
});
|
|
6613
6689
|
}
|
|
6614
6690
|
/**
|
|
@@ -6618,7 +6694,7 @@ class Be {
|
|
|
6618
6694
|
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();
|
|
6619
6695
|
}
|
|
6620
6696
|
}
|
|
6621
|
-
const
|
|
6697
|
+
const Ie = {
|
|
6622
6698
|
apiKey: "sk_ace57ef3ef65a92b9d3bee2a00183b78ca790bc3e10964f2",
|
|
6623
6699
|
// Replace with your actual API key (should start with sk_)
|
|
6624
6700
|
endpoint: "https://api.elevenlabs.io/v1/text-to-speech",
|
|
@@ -6661,23 +6737,23 @@ const Re = {
|
|
|
6661
6737
|
function Fe() {
|
|
6662
6738
|
return {
|
|
6663
6739
|
service: "elevenlabs",
|
|
6664
|
-
endpoint:
|
|
6665
|
-
apiKey:
|
|
6666
|
-
defaultVoice:
|
|
6667
|
-
voices:
|
|
6740
|
+
endpoint: Ie.endpoint,
|
|
6741
|
+
apiKey: Ie.apiKey,
|
|
6742
|
+
defaultVoice: Ie.defaultVoice,
|
|
6743
|
+
voices: Ie.voices
|
|
6668
6744
|
};
|
|
6669
6745
|
}
|
|
6670
6746
|
function kt() {
|
|
6671
|
-
const
|
|
6672
|
-
return Object.entries(
|
|
6747
|
+
const Z = Fe(), t = [];
|
|
6748
|
+
return Object.entries(Z.voices).forEach(([e, n]) => {
|
|
6673
6749
|
t.push({
|
|
6674
6750
|
value: n,
|
|
6675
|
-
label: `${e.charAt(0).toUpperCase() + e.slice(1)} (${
|
|
6751
|
+
label: `${e.charAt(0).toUpperCase() + e.slice(1)} (${Z.service})`
|
|
6676
6752
|
});
|
|
6677
6753
|
}), t;
|
|
6678
6754
|
}
|
|
6679
6755
|
const Ve = Me(({
|
|
6680
|
-
avatarUrl:
|
|
6756
|
+
avatarUrl: Z = "/avatars/brunette.glb",
|
|
6681
6757
|
avatarBody: t = "F",
|
|
6682
6758
|
mood: e = "neutral",
|
|
6683
6759
|
ttsLang: n = "en",
|
|
@@ -6690,220 +6766,220 @@ const Ve = Me(({
|
|
|
6690
6766
|
cameraView: u = "upper",
|
|
6691
6767
|
onReady: a = () => {
|
|
6692
6768
|
},
|
|
6693
|
-
onLoading:
|
|
6769
|
+
onLoading: c = () => {
|
|
6694
6770
|
},
|
|
6695
|
-
onError:
|
|
6771
|
+
onError: d = () => {
|
|
6696
6772
|
},
|
|
6697
6773
|
className: g = "",
|
|
6698
|
-
style:
|
|
6699
|
-
animations:
|
|
6700
|
-
},
|
|
6701
|
-
const
|
|
6774
|
+
style: b = {},
|
|
6775
|
+
animations: x = {}
|
|
6776
|
+
}, A) => {
|
|
6777
|
+
const B = O(null), p = O(null), E = O(r), I = O(null), y = O(null), H = O(!1), w = O({ remainingText: null, originalText: null, options: null }), D = O([]), $ = O(0), [k, V] = ce(!0), [K, X] = ce(null), [ee, se] = ce(!1), [ae, pe] = ce(!1);
|
|
6702
6778
|
de(() => {
|
|
6703
|
-
|
|
6779
|
+
H.current = ae;
|
|
6704
6780
|
}, [ae]), de(() => {
|
|
6705
|
-
|
|
6781
|
+
E.current = r;
|
|
6706
6782
|
}, [r]);
|
|
6707
|
-
const
|
|
6708
|
-
let
|
|
6709
|
-
le === "browser" ?
|
|
6783
|
+
const te = Fe(), le = i || te.service;
|
|
6784
|
+
let U;
|
|
6785
|
+
le === "browser" ? U = {
|
|
6710
6786
|
service: "browser",
|
|
6711
6787
|
endpoint: "",
|
|
6712
6788
|
apiKey: null,
|
|
6713
6789
|
defaultVoice: "Google US English"
|
|
6714
|
-
} : le === "elevenlabs" ?
|
|
6790
|
+
} : le === "elevenlabs" ? U = {
|
|
6715
6791
|
service: "elevenlabs",
|
|
6716
6792
|
endpoint: "https://api.elevenlabs.io/v1/text-to-speech",
|
|
6717
|
-
apiKey: o ||
|
|
6718
|
-
defaultVoice: s ||
|
|
6719
|
-
voices:
|
|
6720
|
-
} : le === "deepgram" ?
|
|
6793
|
+
apiKey: o || te.apiKey,
|
|
6794
|
+
defaultVoice: s || te.defaultVoice || Ie.defaultVoice,
|
|
6795
|
+
voices: te.voices || Ie.voices
|
|
6796
|
+
} : le === "deepgram" ? U = {
|
|
6721
6797
|
service: "deepgram",
|
|
6722
6798
|
endpoint: "https://api.deepgram.com/v1/speak",
|
|
6723
|
-
apiKey: o ||
|
|
6724
|
-
defaultVoice: s ||
|
|
6725
|
-
voices:
|
|
6726
|
-
} :
|
|
6727
|
-
...
|
|
6799
|
+
apiKey: o || te.apiKey,
|
|
6800
|
+
defaultVoice: s || te.defaultVoice || Te.defaultVoice,
|
|
6801
|
+
voices: te.voices || Te.voices
|
|
6802
|
+
} : U = {
|
|
6803
|
+
...te,
|
|
6728
6804
|
// Override API key if provided via props
|
|
6729
|
-
apiKey: o !== null ? o :
|
|
6805
|
+
apiKey: o !== null ? o : te.apiKey
|
|
6730
6806
|
};
|
|
6731
6807
|
const v = {
|
|
6732
|
-
url:
|
|
6808
|
+
url: Z,
|
|
6733
6809
|
body: t,
|
|
6734
6810
|
avatarMood: e,
|
|
6735
6811
|
ttsLang: le === "browser" ? "en-US" : n,
|
|
6736
|
-
ttsVoice: s ||
|
|
6812
|
+
ttsVoice: s || U.defaultVoice,
|
|
6737
6813
|
lipsyncLang: "en",
|
|
6738
6814
|
showFullAvatar: r,
|
|
6739
6815
|
bodyMovement: l,
|
|
6740
6816
|
movementIntensity: h
|
|
6741
|
-
},
|
|
6742
|
-
ttsEndpoint:
|
|
6743
|
-
ttsApikey:
|
|
6817
|
+
}, R = {
|
|
6818
|
+
ttsEndpoint: U.endpoint,
|
|
6819
|
+
ttsApikey: U.apiKey,
|
|
6744
6820
|
ttsService: le,
|
|
6745
6821
|
lipsyncModules: ["en"],
|
|
6746
6822
|
cameraView: u
|
|
6747
|
-
},
|
|
6748
|
-
if (!(!
|
|
6823
|
+
}, z = F(async () => {
|
|
6824
|
+
if (!(!B.current || p.current))
|
|
6749
6825
|
try {
|
|
6750
|
-
if (
|
|
6751
|
-
if (
|
|
6752
|
-
const J = Math.min(100, Math.round(
|
|
6753
|
-
|
|
6826
|
+
if (V(!0), X(null), p.current = new Be(B.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), x && Object.keys(x).length > 0 && (p.current.customAnimations = x), await p.current.showAvatar(v, (N) => {
|
|
6827
|
+
if (N.lengthComputable) {
|
|
6828
|
+
const J = Math.min(100, Math.round(N.loaded / N.total * 100));
|
|
6829
|
+
c(J);
|
|
6754
6830
|
}
|
|
6755
|
-
}), await new Promise((
|
|
6831
|
+
}), await new Promise((N) => {
|
|
6756
6832
|
const J = () => {
|
|
6757
|
-
p.current.lipsync && Object.keys(p.current.lipsync).length > 0 ?
|
|
6833
|
+
p.current.lipsync && Object.keys(p.current.lipsync).length > 0 ? N() : setTimeout(J, 100);
|
|
6758
6834
|
};
|
|
6759
6835
|
J();
|
|
6760
6836
|
}), p.current && p.current.setShowFullAvatar)
|
|
6761
6837
|
try {
|
|
6762
6838
|
p.current.setShowFullAvatar(r);
|
|
6763
|
-
} catch (
|
|
6764
|
-
console.warn("Error setting full body mode on initialization:",
|
|
6839
|
+
} catch (N) {
|
|
6840
|
+
console.warn("Error setting full body mode on initialization:", N);
|
|
6765
6841
|
}
|
|
6766
|
-
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()),
|
|
6767
|
-
const
|
|
6842
|
+
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()), V(!1), se(!0), a(p.current);
|
|
6843
|
+
const P = () => {
|
|
6768
6844
|
document.visibilityState === "visible" ? p.current?.start() : p.current?.stop();
|
|
6769
6845
|
};
|
|
6770
|
-
return document.addEventListener("visibilitychange",
|
|
6771
|
-
document.removeEventListener("visibilitychange",
|
|
6846
|
+
return document.addEventListener("visibilitychange", P), () => {
|
|
6847
|
+
document.removeEventListener("visibilitychange", P);
|
|
6772
6848
|
};
|
|
6773
6849
|
} catch (L) {
|
|
6774
|
-
console.error("Error initializing TalkingHead:", L), X(L.message || "Failed to initialize avatar"),
|
|
6850
|
+
console.error("Error initializing TalkingHead:", L), X(L.message || "Failed to initialize avatar"), V(!1), d(L);
|
|
6775
6851
|
}
|
|
6776
|
-
}, [
|
|
6777
|
-
de(() => (
|
|
6852
|
+
}, [Z, t, e, n, i, s, o, r, l, h, u]);
|
|
6853
|
+
de(() => (z(), () => {
|
|
6778
6854
|
p.current && (p.current.stop(), p.current.dispose(), p.current = null);
|
|
6779
|
-
}), [
|
|
6780
|
-
if (!
|
|
6781
|
-
const L = new ResizeObserver((
|
|
6782
|
-
for (const J of
|
|
6855
|
+
}), [z]), de(() => {
|
|
6856
|
+
if (!B.current || !p.current) return;
|
|
6857
|
+
const L = new ResizeObserver((N) => {
|
|
6858
|
+
for (const J of N)
|
|
6783
6859
|
p.current && p.current.onResize && p.current.onResize();
|
|
6784
6860
|
});
|
|
6785
|
-
L.observe(
|
|
6786
|
-
const
|
|
6861
|
+
L.observe(B.current);
|
|
6862
|
+
const P = () => {
|
|
6787
6863
|
p.current && p.current.onResize && p.current.onResize();
|
|
6788
6864
|
};
|
|
6789
|
-
return window.addEventListener("resize",
|
|
6790
|
-
L.disconnect(), window.removeEventListener("resize",
|
|
6865
|
+
return window.addEventListener("resize", P), () => {
|
|
6866
|
+
L.disconnect(), window.removeEventListener("resize", P);
|
|
6791
6867
|
};
|
|
6792
|
-
}, [
|
|
6793
|
-
const
|
|
6868
|
+
}, [ee]);
|
|
6869
|
+
const M = F(async () => {
|
|
6794
6870
|
if (p.current && p.current.audioCtx)
|
|
6795
6871
|
try {
|
|
6796
6872
|
(p.current.audioCtx.state === "suspended" || p.current.audioCtx.state === "interrupted") && (await p.current.audioCtx.resume(), console.log("Audio context resumed"));
|
|
6797
6873
|
} catch (L) {
|
|
6798
6874
|
console.warn("Failed to resume audio context:", L);
|
|
6799
6875
|
}
|
|
6800
|
-
}, []),
|
|
6801
|
-
if (p.current &&
|
|
6876
|
+
}, []), W = F(async (L, P = {}) => {
|
|
6877
|
+
if (p.current && ee)
|
|
6802
6878
|
try {
|
|
6803
|
-
|
|
6804
|
-
const
|
|
6805
|
-
|
|
6879
|
+
y.current && (clearInterval(y.current), y.current = null), I.current = { text: L, options: P }, w.current = { remainingText: null, originalText: null, options: null };
|
|
6880
|
+
const N = /[!\.\?\n\p{Extended_Pictographic}]/ug, J = L.split(N).map((Y) => Y.trim()).filter((Y) => Y.length > 0);
|
|
6881
|
+
D.current = J, $.current = 0, pe(!1), H.current = !1, await M();
|
|
6806
6882
|
const ge = {
|
|
6807
|
-
...
|
|
6808
|
-
lipsyncLang:
|
|
6883
|
+
...P,
|
|
6884
|
+
lipsyncLang: P.lipsyncLang || v.lipsyncLang || "en"
|
|
6809
6885
|
};
|
|
6810
|
-
if (
|
|
6886
|
+
if (P.onSpeechEnd && p.current) {
|
|
6811
6887
|
const Y = p.current;
|
|
6812
6888
|
let he = null, Se = 0;
|
|
6813
6889
|
const Ae = 1200;
|
|
6814
6890
|
let be = !1;
|
|
6815
6891
|
he = setInterval(() => {
|
|
6816
|
-
if (Se++,
|
|
6892
|
+
if (Se++, H.current)
|
|
6817
6893
|
return;
|
|
6818
6894
|
if (Se > Ae) {
|
|
6819
|
-
if (he && (clearInterval(he), he = null,
|
|
6895
|
+
if (he && (clearInterval(he), he = null, y.current = null), !be && !H.current) {
|
|
6820
6896
|
be = !0;
|
|
6821
6897
|
try {
|
|
6822
|
-
|
|
6823
|
-
} catch (
|
|
6824
|
-
console.error("Error in onSpeechEnd callback (timeout):",
|
|
6898
|
+
P.onSpeechEnd();
|
|
6899
|
+
} catch (Ne) {
|
|
6900
|
+
console.error("Error in onSpeechEnd callback (timeout):", Ne);
|
|
6825
6901
|
}
|
|
6826
6902
|
}
|
|
6827
6903
|
return;
|
|
6828
6904
|
}
|
|
6829
6905
|
const ye = !Y.speechQueue || Y.speechQueue.length === 0, ke = !Y.audioPlaylist || Y.audioPlaylist.length === 0;
|
|
6830
|
-
Y && Y.isSpeaking === !1 && ye && ke && Y.isAudioPlaying === !1 && !be && !
|
|
6831
|
-
if (Y && !
|
|
6832
|
-
be = !0, he && (clearInterval(he), he = null,
|
|
6906
|
+
Y && Y.isSpeaking === !1 && ye && ke && Y.isAudioPlaying === !1 && !be && !H.current && setTimeout(() => {
|
|
6907
|
+
if (Y && !H.current && Y.isSpeaking === !1 && (!Y.speechQueue || Y.speechQueue.length === 0) && (!Y.audioPlaylist || Y.audioPlaylist.length === 0) && Y.isAudioPlaying === !1 && !be && !H.current) {
|
|
6908
|
+
be = !0, he && (clearInterval(he), he = null, y.current = null);
|
|
6833
6909
|
try {
|
|
6834
|
-
|
|
6910
|
+
P.onSpeechEnd();
|
|
6835
6911
|
} catch (Ze) {
|
|
6836
6912
|
console.error("Error in onSpeechEnd callback:", Ze);
|
|
6837
6913
|
}
|
|
6838
6914
|
}
|
|
6839
6915
|
}, 100);
|
|
6840
|
-
}, 100),
|
|
6916
|
+
}, 100), y.current = he;
|
|
6841
6917
|
}
|
|
6842
6918
|
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 () => {
|
|
6843
|
-
await
|
|
6919
|
+
await M(), p.current && p.current.lipsync && (p.current.setSlowdownRate && p.current.setSlowdownRate(1.05), p.current.speakText(L, ge));
|
|
6844
6920
|
}, 100);
|
|
6845
|
-
} catch (
|
|
6846
|
-
console.error("Error speaking text:",
|
|
6921
|
+
} catch (N) {
|
|
6922
|
+
console.error("Error speaking text:", N), X(N.message || "Failed to speak text");
|
|
6847
6923
|
}
|
|
6848
|
-
}, [
|
|
6849
|
-
p.current && (p.current.stopSpeaking(), p.current.setSlowdownRate && p.current.setSlowdownRate(1),
|
|
6850
|
-
}, []), j =
|
|
6924
|
+
}, [ee, M, v.lipsyncLang]), _ = F(() => {
|
|
6925
|
+
p.current && (p.current.stopSpeaking(), p.current.setSlowdownRate && p.current.setSlowdownRate(1), I.current = null, pe(!1));
|
|
6926
|
+
}, []), j = F(() => {
|
|
6851
6927
|
if (p.current && p.current.pauseSpeaking) {
|
|
6852
6928
|
const L = p.current;
|
|
6853
6929
|
if (L.isSpeaking || L.audioPlaylist && L.audioPlaylist.length > 0 || L.speechQueue && L.speechQueue.length > 0) {
|
|
6854
|
-
|
|
6855
|
-
let
|
|
6856
|
-
if (
|
|
6857
|
-
const J =
|
|
6858
|
-
if (he > 0 && Se < J && (
|
|
6930
|
+
y.current && (clearInterval(y.current), y.current = null);
|
|
6931
|
+
let N = "";
|
|
6932
|
+
if (I.current && D.current.length > 0) {
|
|
6933
|
+
const J = D.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, he = ge + (Y ? 1 : 0), Se = J - he;
|
|
6934
|
+
if (he > 0 && Se < J && (N = D.current.slice(Se).join(". ").trim(), !N && ge > 0 && L.speechQueue)) {
|
|
6859
6935
|
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(" ");
|
|
6860
|
-
be && be.trim() && (
|
|
6936
|
+
be && be.trim() && (N = be.trim());
|
|
6861
6937
|
}
|
|
6862
6938
|
}
|
|
6863
|
-
|
|
6864
|
-
remainingText:
|
|
6865
|
-
originalText:
|
|
6866
|
-
options:
|
|
6867
|
-
}), L.speechQueue && (L.speechQueue.length = 0), p.current.pauseSpeaking(),
|
|
6939
|
+
I.current && (w.current = {
|
|
6940
|
+
remainingText: N || null,
|
|
6941
|
+
originalText: I.current.text,
|
|
6942
|
+
options: I.current.options
|
|
6943
|
+
}), L.speechQueue && (L.speechQueue.length = 0), p.current.pauseSpeaking(), H.current = !0, pe(!0);
|
|
6868
6944
|
}
|
|
6869
6945
|
}
|
|
6870
|
-
}, []), q =
|
|
6946
|
+
}, []), q = F(async () => {
|
|
6871
6947
|
if (!p.current || !ae)
|
|
6872
6948
|
return;
|
|
6873
|
-
let L = "",
|
|
6874
|
-
if (
|
|
6875
|
-
L =
|
|
6876
|
-
else if (
|
|
6877
|
-
L =
|
|
6949
|
+
let L = "", P = {};
|
|
6950
|
+
if (w.current && w.current.remainingText)
|
|
6951
|
+
L = w.current.remainingText, P = w.current.options || {}, w.current = { remainingText: null, originalText: null, options: null };
|
|
6952
|
+
else if (I.current && I.current.text)
|
|
6953
|
+
L = I.current.text, P = I.current.options || {};
|
|
6878
6954
|
else {
|
|
6879
|
-
console.warn("Resume called but no paused speech found"), pe(!1),
|
|
6955
|
+
console.warn("Resume called but no paused speech found"), pe(!1), H.current = !1;
|
|
6880
6956
|
return;
|
|
6881
6957
|
}
|
|
6882
|
-
pe(!1),
|
|
6883
|
-
const
|
|
6884
|
-
...
|
|
6885
|
-
lipsyncLang:
|
|
6958
|
+
pe(!1), H.current = !1, await M();
|
|
6959
|
+
const N = {
|
|
6960
|
+
...P,
|
|
6961
|
+
lipsyncLang: P.lipsyncLang || v.lipsyncLang || "en"
|
|
6886
6962
|
};
|
|
6887
6963
|
try {
|
|
6888
|
-
await
|
|
6964
|
+
await W(L, N);
|
|
6889
6965
|
} catch (J) {
|
|
6890
|
-
console.error("Error resuming speech:", J), pe(!1),
|
|
6966
|
+
console.error("Error resuming speech:", J), pe(!1), H.current = !1;
|
|
6891
6967
|
}
|
|
6892
|
-
}, [
|
|
6968
|
+
}, [M, ae, W, v]), Le = F((L) => {
|
|
6893
6969
|
p.current && p.current.setMood(L);
|
|
6894
|
-
}, []), we =
|
|
6970
|
+
}, []), we = F((L) => {
|
|
6895
6971
|
p.current && p.current.setSlowdownRate && p.current.setSlowdownRate(L);
|
|
6896
|
-
}, []),
|
|
6972
|
+
}, []), T = F((L, P = !1) => {
|
|
6897
6973
|
if (p.current && p.current.playAnimation) {
|
|
6898
|
-
if (
|
|
6974
|
+
if (x && x[L] && (L = x[L]), p.current.setShowFullAvatar)
|
|
6899
6975
|
try {
|
|
6900
|
-
p.current.setShowFullAvatar(
|
|
6976
|
+
p.current.setShowFullAvatar(E.current);
|
|
6901
6977
|
} catch (J) {
|
|
6902
6978
|
console.warn("Error setting full body mode:", J);
|
|
6903
6979
|
}
|
|
6904
6980
|
if (L.includes("."))
|
|
6905
6981
|
try {
|
|
6906
|
-
p.current.playAnimation(L, null, 10, 0, 0.01,
|
|
6982
|
+
p.current.playAnimation(L, null, 10, 0, 0.01, P);
|
|
6907
6983
|
} catch (J) {
|
|
6908
6984
|
console.warn(`Failed to play ${L}:`, J);
|
|
6909
6985
|
try {
|
|
@@ -6917,7 +6993,7 @@ const Ve = Me(({
|
|
|
6917
6993
|
let ge = !1;
|
|
6918
6994
|
for (const Y of J)
|
|
6919
6995
|
try {
|
|
6920
|
-
p.current.playAnimation(L + Y, null, 10, 0, 0.01,
|
|
6996
|
+
p.current.playAnimation(L + Y, null, 10, 0, 0.01, P), ge = !0;
|
|
6921
6997
|
break;
|
|
6922
6998
|
} catch {
|
|
6923
6999
|
}
|
|
@@ -6931,35 +7007,35 @@ const Ve = Me(({
|
|
|
6931
7007
|
}
|
|
6932
7008
|
}
|
|
6933
7009
|
}
|
|
6934
|
-
}, [
|
|
7010
|
+
}, [x]), ne = F(() => {
|
|
6935
7011
|
p.current && p.current.onResize && p.current.onResize();
|
|
6936
7012
|
}, []);
|
|
6937
|
-
return Ee(
|
|
6938
|
-
speakText:
|
|
7013
|
+
return Ee(A, () => ({
|
|
7014
|
+
speakText: W,
|
|
6939
7015
|
stopSpeaking: _,
|
|
6940
7016
|
pauseSpeaking: j,
|
|
6941
7017
|
resumeSpeaking: q,
|
|
6942
|
-
resumeAudioContext:
|
|
7018
|
+
resumeAudioContext: M,
|
|
6943
7019
|
setMood: Le,
|
|
6944
7020
|
setTimingAdjustment: we,
|
|
6945
|
-
playAnimation:
|
|
6946
|
-
isReady:
|
|
7021
|
+
playAnimation: T,
|
|
7022
|
+
isReady: ee,
|
|
6947
7023
|
isPaused: ae,
|
|
6948
7024
|
talkingHead: p.current,
|
|
6949
|
-
handleResize:
|
|
7025
|
+
handleResize: ne,
|
|
6950
7026
|
setBodyMovement: (L) => {
|
|
6951
7027
|
if (p.current && p.current.setShowFullAvatar && p.current.setBodyMovement)
|
|
6952
7028
|
try {
|
|
6953
|
-
p.current.setShowFullAvatar(
|
|
6954
|
-
} catch (
|
|
6955
|
-
console.warn("Error setting body movement:",
|
|
7029
|
+
p.current.setShowFullAvatar(E.current), p.current.setBodyMovement(L);
|
|
7030
|
+
} catch (P) {
|
|
7031
|
+
console.warn("Error setting body movement:", P);
|
|
6956
7032
|
}
|
|
6957
7033
|
},
|
|
6958
7034
|
setMovementIntensity: (L) => p.current?.setMovementIntensity(L),
|
|
6959
7035
|
playRandomDance: () => {
|
|
6960
7036
|
if (p.current && p.current.setShowFullAvatar && p.current.playRandomDance)
|
|
6961
7037
|
try {
|
|
6962
|
-
p.current.setShowFullAvatar(
|
|
7038
|
+
p.current.setShowFullAvatar(E.current), p.current.playRandomDance();
|
|
6963
7039
|
} catch (L) {
|
|
6964
7040
|
console.warn("Error playing random dance:", L);
|
|
6965
7041
|
}
|
|
@@ -6967,15 +7043,15 @@ const Ve = Me(({
|
|
|
6967
7043
|
playReaction: (L) => {
|
|
6968
7044
|
if (p.current && p.current.setShowFullAvatar && p.current.playReaction)
|
|
6969
7045
|
try {
|
|
6970
|
-
p.current.setShowFullAvatar(
|
|
6971
|
-
} catch (
|
|
6972
|
-
console.warn("Error playing reaction:",
|
|
7046
|
+
p.current.setShowFullAvatar(E.current), p.current.playReaction(L);
|
|
7047
|
+
} catch (P) {
|
|
7048
|
+
console.warn("Error playing reaction:", P);
|
|
6973
7049
|
}
|
|
6974
7050
|
},
|
|
6975
7051
|
playCelebration: () => {
|
|
6976
7052
|
if (p.current && p.current.setShowFullAvatar && p.current.playCelebration)
|
|
6977
7053
|
try {
|
|
6978
|
-
p.current.setShowFullAvatar(
|
|
7054
|
+
p.current.setShowFullAvatar(E.current), p.current.playCelebration();
|
|
6979
7055
|
} catch (L) {
|
|
6980
7056
|
console.warn("Error playing celebration:", L);
|
|
6981
7057
|
}
|
|
@@ -6983,9 +7059,9 @@ const Ve = Me(({
|
|
|
6983
7059
|
setShowFullAvatar: (L) => {
|
|
6984
7060
|
if (p.current && p.current.setShowFullAvatar)
|
|
6985
7061
|
try {
|
|
6986
|
-
|
|
6987
|
-
} catch (
|
|
6988
|
-
console.warn("Error setting showFullAvatar:",
|
|
7062
|
+
E.current = L, p.current.setShowFullAvatar(L);
|
|
7063
|
+
} catch (P) {
|
|
7064
|
+
console.warn("Error setting showFullAvatar:", P);
|
|
6989
7065
|
}
|
|
6990
7066
|
},
|
|
6991
7067
|
lockAvatarPosition: () => {
|
|
@@ -7012,13 +7088,13 @@ const Ve = Me(({
|
|
|
7012
7088
|
width: "100%",
|
|
7013
7089
|
height: "100%",
|
|
7014
7090
|
position: "relative",
|
|
7015
|
-
...
|
|
7091
|
+
...b
|
|
7016
7092
|
},
|
|
7017
7093
|
children: [
|
|
7018
7094
|
/* @__PURE__ */ me(
|
|
7019
7095
|
"div",
|
|
7020
7096
|
{
|
|
7021
|
-
ref:
|
|
7097
|
+
ref: B,
|
|
7022
7098
|
className: "talking-head-viewer",
|
|
7023
7099
|
style: {
|
|
7024
7100
|
width: "100%",
|
|
@@ -7027,7 +7103,7 @@ const Ve = Me(({
|
|
|
7027
7103
|
}
|
|
7028
7104
|
}
|
|
7029
7105
|
),
|
|
7030
|
-
|
|
7106
|
+
k && /* @__PURE__ */ me("div", { className: "loading-overlay", style: {
|
|
7031
7107
|
position: "absolute",
|
|
7032
7108
|
top: "50%",
|
|
7033
7109
|
left: "50%",
|
|
@@ -7054,7 +7130,7 @@ const Ve = Me(({
|
|
|
7054
7130
|
});
|
|
7055
7131
|
Ve.displayName = "TalkingHeadAvatar";
|
|
7056
7132
|
const pt = Me(({
|
|
7057
|
-
text:
|
|
7133
|
+
text: Z = "Hello! I'm a talking avatar. How are you today?",
|
|
7058
7134
|
onLoading: t = () => {
|
|
7059
7135
|
},
|
|
7060
7136
|
onError: e = () => {
|
|
@@ -7065,23 +7141,23 @@ const pt = Me(({
|
|
|
7065
7141
|
style: s = {},
|
|
7066
7142
|
avatarConfig: o = {}
|
|
7067
7143
|
}, l) => {
|
|
7068
|
-
const h =
|
|
7144
|
+
const h = O(null), r = O(null), [u, a] = ce(!0), [c, d] = ce(null), [g, b] = ce(!1), x = Fe(), A = o.ttsService || x.service, B = A === "browser" ? {
|
|
7069
7145
|
endpoint: "",
|
|
7070
7146
|
apiKey: null,
|
|
7071
7147
|
defaultVoice: "Google US English"
|
|
7072
7148
|
} : {
|
|
7073
|
-
...
|
|
7149
|
+
...x,
|
|
7074
7150
|
// Override API key if provided via avatarConfig
|
|
7075
|
-
apiKey: o.ttsApiKey !== void 0 && o.ttsApiKey !== null ? o.ttsApiKey :
|
|
7151
|
+
apiKey: o.ttsApiKey !== void 0 && o.ttsApiKey !== null ? o.ttsApiKey : x.apiKey,
|
|
7076
7152
|
// Override endpoint for ElevenLabs if service is explicitly set
|
|
7077
|
-
endpoint:
|
|
7153
|
+
endpoint: A === "elevenlabs" && o.ttsApiKey ? "https://api.elevenlabs.io/v1/text-to-speech" : x.endpoint
|
|
7078
7154
|
}, p = {
|
|
7079
7155
|
url: "/avatars/brunette.glb",
|
|
7080
7156
|
// Use brunette avatar (working glTF file)
|
|
7081
7157
|
body: "F",
|
|
7082
7158
|
avatarMood: "neutral",
|
|
7083
|
-
ttsLang:
|
|
7084
|
-
ttsVoice: o.ttsVoice ||
|
|
7159
|
+
ttsLang: A === "browser" ? "en-US" : "en",
|
|
7160
|
+
ttsVoice: o.ttsVoice || B.defaultVoice,
|
|
7085
7161
|
lipsyncLang: "en",
|
|
7086
7162
|
// English lip-sync
|
|
7087
7163
|
showFullAvatar: !0,
|
|
@@ -7089,16 +7165,16 @@ const pt = Me(({
|
|
|
7089
7165
|
bodyMovement: "idle",
|
|
7090
7166
|
movementIntensity: 0.5,
|
|
7091
7167
|
...o
|
|
7092
|
-
},
|
|
7093
|
-
ttsEndpoint:
|
|
7094
|
-
ttsApikey:
|
|
7095
|
-
ttsService:
|
|
7168
|
+
}, E = {
|
|
7169
|
+
ttsEndpoint: B.endpoint,
|
|
7170
|
+
ttsApikey: B.apiKey,
|
|
7171
|
+
ttsService: A,
|
|
7096
7172
|
lipsyncModules: ["en"],
|
|
7097
7173
|
cameraView: "upper"
|
|
7098
|
-
},
|
|
7174
|
+
}, I = F(async () => {
|
|
7099
7175
|
if (!(!h.current || r.current))
|
|
7100
7176
|
try {
|
|
7101
|
-
if (a(!0),
|
|
7177
|
+
if (a(!0), d(null), r.current = new Be(h.current, E), await r.current.showAvatar(p, (K) => {
|
|
7102
7178
|
if (K.lengthComputable) {
|
|
7103
7179
|
const X = Math.min(100, Math.round(K.loaded / K.total * 100));
|
|
7104
7180
|
t(X);
|
|
@@ -7106,7 +7182,7 @@ const pt = Me(({
|
|
|
7106
7182
|
}), r.current.morphs && r.current.morphs.length > 0) {
|
|
7107
7183
|
const K = r.current.morphs[0].morphTargetDictionary;
|
|
7108
7184
|
console.log("Available morph targets:", Object.keys(K));
|
|
7109
|
-
const X = Object.keys(K).filter((
|
|
7185
|
+
const X = Object.keys(K).filter((ee) => ee.startsWith("viseme_"));
|
|
7110
7186
|
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"));
|
|
7111
7187
|
}
|
|
7112
7188
|
if (await new Promise((K) => {
|
|
@@ -7120,38 +7196,38 @@ const pt = Me(({
|
|
|
7120
7196
|
} catch (K) {
|
|
7121
7197
|
console.warn("Error setting full body mode on initialization:", K);
|
|
7122
7198
|
}
|
|
7123
|
-
a(!1),
|
|
7124
|
-
const
|
|
7199
|
+
a(!1), b(!0), n(r.current);
|
|
7200
|
+
const V = () => {
|
|
7125
7201
|
document.visibilityState === "visible" ? r.current?.start() : r.current?.stop();
|
|
7126
7202
|
};
|
|
7127
|
-
return document.addEventListener("visibilitychange",
|
|
7128
|
-
document.removeEventListener("visibilitychange",
|
|
7203
|
+
return document.addEventListener("visibilitychange", V), () => {
|
|
7204
|
+
document.removeEventListener("visibilitychange", V);
|
|
7129
7205
|
};
|
|
7130
|
-
} catch (
|
|
7131
|
-
console.error("Error initializing TalkingHead:",
|
|
7206
|
+
} catch (k) {
|
|
7207
|
+
console.error("Error initializing TalkingHead:", k), d(k.message || "Failed to initialize avatar"), a(!1), e(k);
|
|
7132
7208
|
}
|
|
7133
7209
|
}, []);
|
|
7134
|
-
de(() => (
|
|
7210
|
+
de(() => (I(), () => {
|
|
7135
7211
|
r.current && (r.current.stop(), r.current.dispose(), r.current = null);
|
|
7136
|
-
}), [
|
|
7137
|
-
const
|
|
7212
|
+
}), [I]);
|
|
7213
|
+
const y = F((k) => {
|
|
7138
7214
|
if (r.current && g)
|
|
7139
7215
|
try {
|
|
7140
|
-
console.log("Speaking text:",
|
|
7141
|
-
r.current && r.current.lipsync ? (console.log("Lip-sync now ready, speaking..."), r.current.setSlowdownRate && (r.current.setSlowdownRate(1.05), console.log("Applied timing adjustment for better lip-sync")), r.current.speakText(
|
|
7216
|
+
console.log("Speaking text:", k), console.log("Avatar config:", p), console.log("TalkingHead instance:", r.current), r.current.lipsync && Object.keys(r.current.lipsync).length > 0 ? (console.log("Lip-sync modules loaded:", Object.keys(r.current.lipsync)), r.current.setSlowdownRate && (r.current.setSlowdownRate(1.05), console.log("Applied timing adjustment for better lip-sync")), r.current.speakText(k)) : (console.warn("Lip-sync modules not ready, waiting..."), setTimeout(() => {
|
|
7217
|
+
r.current && r.current.lipsync ? (console.log("Lip-sync now ready, speaking..."), r.current.setSlowdownRate && (r.current.setSlowdownRate(1.05), console.log("Applied timing adjustment for better lip-sync")), r.current.speakText(k)) : console.error("Lip-sync still not ready after waiting");
|
|
7142
7218
|
}, 500));
|
|
7143
|
-
} catch (
|
|
7144
|
-
console.error("Error speaking text:",
|
|
7219
|
+
} catch (V) {
|
|
7220
|
+
console.error("Error speaking text:", V), d(V.message || "Failed to speak text");
|
|
7145
7221
|
}
|
|
7146
7222
|
else
|
|
7147
7223
|
console.warn("Avatar not ready for speaking. isReady:", g, "talkingHeadRef:", !!r.current);
|
|
7148
|
-
}, [g, p]),
|
|
7224
|
+
}, [g, p]), H = F(() => {
|
|
7149
7225
|
r.current && (r.current.stopSpeaking(), r.current.setSlowdownRate && (r.current.setSlowdownRate(1), console.log("Reset timing to normal")));
|
|
7150
|
-
}, []),
|
|
7151
|
-
r.current && r.current.setMood(
|
|
7152
|
-
}, []),
|
|
7153
|
-
r.current && r.current.setSlowdownRate && (r.current.setSlowdownRate(
|
|
7154
|
-
}, []),
|
|
7226
|
+
}, []), w = F((k) => {
|
|
7227
|
+
r.current && r.current.setMood(k);
|
|
7228
|
+
}, []), D = F((k) => {
|
|
7229
|
+
r.current && r.current.setSlowdownRate && (r.current.setSlowdownRate(k), console.log("Timing adjustment set to:", k));
|
|
7230
|
+
}, []), $ = F((k, V = !1) => {
|
|
7155
7231
|
if (r.current && r.current.playAnimation) {
|
|
7156
7232
|
if (r.current.setShowFullAvatar)
|
|
7157
7233
|
try {
|
|
@@ -7159,29 +7235,29 @@ const pt = Me(({
|
|
|
7159
7235
|
} catch (X) {
|
|
7160
7236
|
console.warn("Error setting full body mode:", X);
|
|
7161
7237
|
}
|
|
7162
|
-
if (
|
|
7238
|
+
if (k.includes("."))
|
|
7163
7239
|
try {
|
|
7164
|
-
r.current.playAnimation(
|
|
7240
|
+
r.current.playAnimation(k, null, 10, 0, 0.01, V), console.log("Playing animation:", k);
|
|
7165
7241
|
} catch (X) {
|
|
7166
|
-
console.log(`Failed to play ${
|
|
7242
|
+
console.log(`Failed to play ${k}:`, X);
|
|
7167
7243
|
try {
|
|
7168
7244
|
r.current.setBodyMovement("idle"), console.log("Fallback to idle animation");
|
|
7169
|
-
} catch (
|
|
7170
|
-
console.warn("Fallback animation also failed:",
|
|
7245
|
+
} catch (ee) {
|
|
7246
|
+
console.warn("Fallback animation also failed:", ee);
|
|
7171
7247
|
}
|
|
7172
7248
|
}
|
|
7173
7249
|
else {
|
|
7174
7250
|
const X = [".fbx", ".glb", ".gltf"];
|
|
7175
|
-
let
|
|
7251
|
+
let ee = !1;
|
|
7176
7252
|
for (const se of X)
|
|
7177
7253
|
try {
|
|
7178
|
-
r.current.playAnimation(
|
|
7254
|
+
r.current.playAnimation(k + se, null, 10, 0, 0.01, V), console.log("Playing animation:", k + se), ee = !0;
|
|
7179
7255
|
break;
|
|
7180
7256
|
} catch {
|
|
7181
|
-
console.log(`Failed to play ${
|
|
7257
|
+
console.log(`Failed to play ${k}${se}, trying next format...`);
|
|
7182
7258
|
}
|
|
7183
|
-
if (
|
|
7184
|
-
console.warn("Animation system not available or animation not found:",
|
|
7259
|
+
if (!ee) {
|
|
7260
|
+
console.warn("Animation system not available or animation not found:", k);
|
|
7185
7261
|
try {
|
|
7186
7262
|
r.current.setBodyMovement("idle"), console.log("Fallback to idle animation");
|
|
7187
7263
|
} catch (se) {
|
|
@@ -7190,71 +7266,71 @@ const pt = Me(({
|
|
|
7190
7266
|
}
|
|
7191
7267
|
}
|
|
7192
7268
|
} else
|
|
7193
|
-
console.warn("Animation system not available or animation not found:",
|
|
7269
|
+
console.warn("Animation system not available or animation not found:", k);
|
|
7194
7270
|
}, []);
|
|
7195
7271
|
return Ee(l, () => ({
|
|
7196
|
-
speakText:
|
|
7197
|
-
stopSpeaking:
|
|
7198
|
-
setMood:
|
|
7199
|
-
setTimingAdjustment:
|
|
7200
|
-
playAnimation:
|
|
7272
|
+
speakText: y,
|
|
7273
|
+
stopSpeaking: H,
|
|
7274
|
+
setMood: w,
|
|
7275
|
+
setTimingAdjustment: D,
|
|
7276
|
+
playAnimation: $,
|
|
7201
7277
|
isReady: g,
|
|
7202
7278
|
talkingHead: r.current,
|
|
7203
|
-
setBodyMovement: (
|
|
7279
|
+
setBodyMovement: (k) => {
|
|
7204
7280
|
if (r.current && r.current.setShowFullAvatar && r.current.setBodyMovement)
|
|
7205
7281
|
try {
|
|
7206
|
-
r.current.setShowFullAvatar(!0), r.current.setBodyMovement(
|
|
7207
|
-
} catch (
|
|
7208
|
-
console.warn("Error setting body movement:",
|
|
7282
|
+
r.current.setShowFullAvatar(!0), r.current.setBodyMovement(k), console.log("Body movement set with full body mode:", k);
|
|
7283
|
+
} catch (V) {
|
|
7284
|
+
console.warn("Error setting body movement:", V);
|
|
7209
7285
|
}
|
|
7210
7286
|
},
|
|
7211
|
-
setMovementIntensity: (
|
|
7287
|
+
setMovementIntensity: (k) => r.current?.setMovementIntensity(k),
|
|
7212
7288
|
playRandomDance: () => {
|
|
7213
7289
|
if (r.current && r.current.setShowFullAvatar && r.current.playRandomDance)
|
|
7214
7290
|
try {
|
|
7215
7291
|
r.current.setShowFullAvatar(!0), r.current.playRandomDance(), console.log("Random dance played with full body mode");
|
|
7216
|
-
} catch (
|
|
7217
|
-
console.warn("Error playing random dance:",
|
|
7292
|
+
} catch (k) {
|
|
7293
|
+
console.warn("Error playing random dance:", k);
|
|
7218
7294
|
}
|
|
7219
7295
|
},
|
|
7220
|
-
playReaction: (
|
|
7296
|
+
playReaction: (k) => {
|
|
7221
7297
|
if (r.current && r.current.setShowFullAvatar && r.current.playReaction)
|
|
7222
7298
|
try {
|
|
7223
|
-
r.current.setShowFullAvatar(!0), r.current.playReaction(
|
|
7224
|
-
} catch (
|
|
7225
|
-
console.warn("Error playing reaction:",
|
|
7299
|
+
r.current.setShowFullAvatar(!0), r.current.playReaction(k), console.log("Reaction played with full body mode:", k);
|
|
7300
|
+
} catch (V) {
|
|
7301
|
+
console.warn("Error playing reaction:", V);
|
|
7226
7302
|
}
|
|
7227
7303
|
},
|
|
7228
7304
|
playCelebration: () => {
|
|
7229
7305
|
if (r.current && r.current.setShowFullAvatar && r.current.playCelebration)
|
|
7230
7306
|
try {
|
|
7231
7307
|
r.current.setShowFullAvatar(!0), r.current.playCelebration(), console.log("Celebration played with full body mode");
|
|
7232
|
-
} catch (
|
|
7233
|
-
console.warn("Error playing celebration:",
|
|
7308
|
+
} catch (k) {
|
|
7309
|
+
console.warn("Error playing celebration:", k);
|
|
7234
7310
|
}
|
|
7235
7311
|
},
|
|
7236
|
-
setShowFullAvatar: (
|
|
7312
|
+
setShowFullAvatar: (k) => {
|
|
7237
7313
|
if (r.current && r.current.setShowFullAvatar)
|
|
7238
7314
|
try {
|
|
7239
|
-
r.current.setShowFullAvatar(
|
|
7240
|
-
} catch (
|
|
7241
|
-
console.warn("Error setting showFullAvatar:",
|
|
7315
|
+
r.current.setShowFullAvatar(k), console.log("Show full avatar set to:", k);
|
|
7316
|
+
} catch (V) {
|
|
7317
|
+
console.warn("Error setting showFullAvatar:", V);
|
|
7242
7318
|
}
|
|
7243
7319
|
},
|
|
7244
7320
|
lockAvatarPosition: () => {
|
|
7245
7321
|
if (r.current && r.current.lockAvatarPosition)
|
|
7246
7322
|
try {
|
|
7247
7323
|
r.current.lockAvatarPosition();
|
|
7248
|
-
} catch (
|
|
7249
|
-
console.warn("Error locking avatar position:",
|
|
7324
|
+
} catch (k) {
|
|
7325
|
+
console.warn("Error locking avatar position:", k);
|
|
7250
7326
|
}
|
|
7251
7327
|
},
|
|
7252
7328
|
unlockAvatarPosition: () => {
|
|
7253
7329
|
if (r.current && r.current.unlockAvatarPosition)
|
|
7254
7330
|
try {
|
|
7255
7331
|
r.current.unlockAvatarPosition();
|
|
7256
|
-
} catch (
|
|
7257
|
-
console.warn("Error unlocking avatar position:",
|
|
7332
|
+
} catch (k) {
|
|
7333
|
+
console.warn("Error unlocking avatar position:", k);
|
|
7258
7334
|
}
|
|
7259
7335
|
}
|
|
7260
7336
|
})), /* @__PURE__ */ Pe("div", { className: `talking-head-container ${i}`, style: s, children: [
|
|
@@ -7279,7 +7355,7 @@ const pt = Me(({
|
|
|
7279
7355
|
fontSize: "18px",
|
|
7280
7356
|
zIndex: 10
|
|
7281
7357
|
}, children: "Loading avatar..." }),
|
|
7282
|
-
|
|
7358
|
+
c && /* @__PURE__ */ me("div", { className: "error-overlay", style: {
|
|
7283
7359
|
position: "absolute",
|
|
7284
7360
|
top: "50%",
|
|
7285
7361
|
left: "50%",
|
|
@@ -7290,12 +7366,12 @@ const pt = Me(({
|
|
|
7290
7366
|
zIndex: 10,
|
|
7291
7367
|
padding: "20px",
|
|
7292
7368
|
borderRadius: "8px"
|
|
7293
|
-
}, children:
|
|
7369
|
+
}, children: c })
|
|
7294
7370
|
] });
|
|
7295
7371
|
});
|
|
7296
7372
|
pt.displayName = "TalkingHeadComponent";
|
|
7297
7373
|
const gt = Me(({
|
|
7298
|
-
text:
|
|
7374
|
+
text: Z = null,
|
|
7299
7375
|
avatarUrl: t = "/avatars/brunette.glb",
|
|
7300
7376
|
avatarBody: e = "F",
|
|
7301
7377
|
mood: n = "neutral",
|
|
@@ -7307,179 +7383,179 @@ const gt = Me(({
|
|
|
7307
7383
|
movementIntensity: r = 0.5,
|
|
7308
7384
|
showFullAvatar: u = !1,
|
|
7309
7385
|
cameraView: a = "upper",
|
|
7310
|
-
onReady:
|
|
7386
|
+
onReady: c = () => {
|
|
7311
7387
|
},
|
|
7312
|
-
onLoading:
|
|
7388
|
+
onLoading: d = () => {
|
|
7313
7389
|
},
|
|
7314
7390
|
onError: g = () => {
|
|
7315
7391
|
},
|
|
7316
|
-
onSpeechEnd:
|
|
7392
|
+
onSpeechEnd: b = () => {
|
|
7317
7393
|
},
|
|
7318
|
-
className:
|
|
7319
|
-
style:
|
|
7320
|
-
animations:
|
|
7394
|
+
className: x = "",
|
|
7395
|
+
style: A = {},
|
|
7396
|
+
animations: B = {},
|
|
7321
7397
|
autoSpeak: p = !1
|
|
7322
|
-
},
|
|
7323
|
-
const
|
|
7398
|
+
}, E) => {
|
|
7399
|
+
const I = O(null), y = O(null), H = O(u), w = O(null), D = O(null), $ = O(!1), k = O({ remainingText: null, originalText: null, options: null }), V = O([]), [K, X] = ce(!0), [ee, se] = ce(null), [ae, pe] = ce(!1), [te, le] = ce(!1);
|
|
7324
7400
|
de(() => {
|
|
7325
|
-
|
|
7326
|
-
}, [
|
|
7327
|
-
|
|
7401
|
+
$.current = te;
|
|
7402
|
+
}, [te]), de(() => {
|
|
7403
|
+
H.current = u;
|
|
7328
7404
|
}, [u]);
|
|
7329
|
-
const
|
|
7330
|
-
let
|
|
7331
|
-
v === "browser" ?
|
|
7405
|
+
const U = Fe(), v = s || U.service;
|
|
7406
|
+
let R;
|
|
7407
|
+
v === "browser" ? R = {
|
|
7332
7408
|
service: "browser",
|
|
7333
7409
|
endpoint: "",
|
|
7334
7410
|
apiKey: null,
|
|
7335
7411
|
defaultVoice: "Google US English"
|
|
7336
|
-
} : v === "elevenlabs" ?
|
|
7412
|
+
} : v === "elevenlabs" ? R = {
|
|
7337
7413
|
service: "elevenlabs",
|
|
7338
7414
|
endpoint: "https://api.elevenlabs.io/v1/text-to-speech",
|
|
7339
|
-
apiKey: l ||
|
|
7340
|
-
defaultVoice: o ||
|
|
7341
|
-
voices:
|
|
7342
|
-
} : v === "deepgram" ?
|
|
7415
|
+
apiKey: l || U.apiKey,
|
|
7416
|
+
defaultVoice: o || U.defaultVoice || Ie.defaultVoice,
|
|
7417
|
+
voices: U.voices || Ie.voices
|
|
7418
|
+
} : v === "deepgram" ? R = {
|
|
7343
7419
|
service: "deepgram",
|
|
7344
7420
|
endpoint: "https://api.deepgram.com/v1/speak",
|
|
7345
|
-
apiKey: l ||
|
|
7346
|
-
defaultVoice: o ||
|
|
7347
|
-
voices:
|
|
7348
|
-
} :
|
|
7349
|
-
...
|
|
7350
|
-
apiKey: l !== null ? l :
|
|
7421
|
+
apiKey: l || U.apiKey,
|
|
7422
|
+
defaultVoice: o || U.defaultVoice || Te.defaultVoice,
|
|
7423
|
+
voices: U.voices || Te.voices
|
|
7424
|
+
} : R = {
|
|
7425
|
+
...U,
|
|
7426
|
+
apiKey: l !== null ? l : U.apiKey
|
|
7351
7427
|
};
|
|
7352
|
-
const
|
|
7428
|
+
const z = {
|
|
7353
7429
|
url: t,
|
|
7354
7430
|
body: e,
|
|
7355
7431
|
avatarMood: n,
|
|
7356
7432
|
ttsLang: v === "browser" ? "en-US" : i,
|
|
7357
|
-
ttsVoice: o ||
|
|
7433
|
+
ttsVoice: o || R.defaultVoice,
|
|
7358
7434
|
lipsyncLang: "en",
|
|
7359
7435
|
showFullAvatar: u,
|
|
7360
7436
|
bodyMovement: h,
|
|
7361
7437
|
movementIntensity: r
|
|
7362
|
-
},
|
|
7363
|
-
ttsEndpoint:
|
|
7364
|
-
ttsApikey:
|
|
7438
|
+
}, M = {
|
|
7439
|
+
ttsEndpoint: R.endpoint,
|
|
7440
|
+
ttsApikey: R.apiKey,
|
|
7365
7441
|
ttsService: v,
|
|
7366
7442
|
lipsyncModules: ["en"],
|
|
7367
7443
|
cameraView: a
|
|
7368
|
-
},
|
|
7369
|
-
if (!(!
|
|
7444
|
+
}, W = F(async () => {
|
|
7445
|
+
if (!(!I.current || y.current))
|
|
7370
7446
|
try {
|
|
7371
|
-
X(!0), se(null),
|
|
7372
|
-
url:
|
|
7373
|
-
body:
|
|
7374
|
-
avatarMood:
|
|
7375
|
-
}), await
|
|
7376
|
-
if (
|
|
7377
|
-
const L = Math.min(100, Math.round(
|
|
7378
|
-
|
|
7447
|
+
X(!0), se(null), y.current = new Be(I.current, M), console.log("Avatar config being passed:", {
|
|
7448
|
+
url: z.url,
|
|
7449
|
+
body: z.body,
|
|
7450
|
+
avatarMood: z.avatarMood
|
|
7451
|
+
}), await y.current.showAvatar(z, (ne) => {
|
|
7452
|
+
if (ne.lengthComputable) {
|
|
7453
|
+
const L = Math.min(100, Math.round(ne.loaded / ne.total * 100));
|
|
7454
|
+
d(L);
|
|
7379
7455
|
}
|
|
7380
|
-
}),
|
|
7381
|
-
const
|
|
7382
|
-
document.visibilityState === "visible" ?
|
|
7456
|
+
}), y.current?.avatar && console.log("Avatar body after initialization:", y.current.avatar.body), X(!1), pe(!0), c(y.current);
|
|
7457
|
+
const T = () => {
|
|
7458
|
+
document.visibilityState === "visible" ? y.current?.start() : y.current?.stop();
|
|
7383
7459
|
};
|
|
7384
|
-
return document.addEventListener("visibilitychange",
|
|
7385
|
-
document.removeEventListener("visibilitychange",
|
|
7460
|
+
return document.addEventListener("visibilitychange", T), () => {
|
|
7461
|
+
document.removeEventListener("visibilitychange", T);
|
|
7386
7462
|
};
|
|
7387
|
-
} catch (
|
|
7388
|
-
console.error("Error initializing TalkingHead:",
|
|
7463
|
+
} catch (T) {
|
|
7464
|
+
console.error("Error initializing TalkingHead:", T), se(T.message || "Failed to initialize avatar"), X(!1), g(T);
|
|
7389
7465
|
}
|
|
7390
7466
|
}, []);
|
|
7391
|
-
de(() => (
|
|
7392
|
-
|
|
7393
|
-
}), [
|
|
7394
|
-
const _ =
|
|
7395
|
-
if (
|
|
7467
|
+
de(() => (W(), () => {
|
|
7468
|
+
y.current && (y.current.stop(), y.current.dispose(), y.current = null);
|
|
7469
|
+
}), [W]);
|
|
7470
|
+
const _ = F(async () => {
|
|
7471
|
+
if (y.current)
|
|
7396
7472
|
try {
|
|
7397
|
-
const
|
|
7398
|
-
|
|
7399
|
-
} catch (
|
|
7400
|
-
console.warn("Failed to resume audio context:",
|
|
7473
|
+
const T = y.current.audioCtx || y.current.audioContext;
|
|
7474
|
+
T && (T.state === "suspended" || T.state === "interrupted") && (await T.resume(), console.log("Audio context resumed"));
|
|
7475
|
+
} catch (T) {
|
|
7476
|
+
console.warn("Failed to resume audio context:", T);
|
|
7401
7477
|
}
|
|
7402
|
-
}, []), j =
|
|
7403
|
-
if (!
|
|
7478
|
+
}, []), j = F(async (T, ne = {}) => {
|
|
7479
|
+
if (!y.current || !ae) {
|
|
7404
7480
|
console.warn("Avatar not ready for speaking");
|
|
7405
7481
|
return;
|
|
7406
7482
|
}
|
|
7407
|
-
if (!
|
|
7483
|
+
if (!T || T.trim() === "") {
|
|
7408
7484
|
console.warn("No text provided to speak");
|
|
7409
7485
|
return;
|
|
7410
7486
|
}
|
|
7411
|
-
await _(),
|
|
7412
|
-
const L =
|
|
7413
|
-
|
|
7414
|
-
const
|
|
7415
|
-
lipsyncLang:
|
|
7487
|
+
await _(), k.current = { remainingText: null, originalText: null, options: null }, V.current = [], w.current = { text: T, options: ne }, D.current && (clearInterval(D.current), D.current = null), le(!1), $.current = !1;
|
|
7488
|
+
const L = T.split(/[.!?]+/).filter((N) => N.trim().length > 0);
|
|
7489
|
+
V.current = L;
|
|
7490
|
+
const P = {
|
|
7491
|
+
lipsyncLang: ne.lipsyncLang || "en",
|
|
7416
7492
|
onSpeechEnd: () => {
|
|
7417
|
-
|
|
7493
|
+
D.current && (clearInterval(D.current), D.current = null), ne.onSpeechEnd && ne.onSpeechEnd(), b();
|
|
7418
7494
|
}
|
|
7419
7495
|
};
|
|
7420
7496
|
try {
|
|
7421
|
-
|
|
7422
|
-
} catch (
|
|
7423
|
-
console.error("Error speaking text:",
|
|
7497
|
+
y.current.speakText(T, P);
|
|
7498
|
+
} catch (N) {
|
|
7499
|
+
console.error("Error speaking text:", N), se(N.message || "Failed to speak text");
|
|
7424
7500
|
}
|
|
7425
|
-
}, [ae,
|
|
7501
|
+
}, [ae, b, _]);
|
|
7426
7502
|
de(() => {
|
|
7427
|
-
ae &&
|
|
7428
|
-
}, [ae,
|
|
7429
|
-
const q =
|
|
7430
|
-
if (
|
|
7503
|
+
ae && Z && p && y.current && j(Z);
|
|
7504
|
+
}, [ae, Z, p, j]);
|
|
7505
|
+
const q = F(() => {
|
|
7506
|
+
if (y.current)
|
|
7431
7507
|
try {
|
|
7432
|
-
const
|
|
7433
|
-
if (
|
|
7434
|
-
|
|
7435
|
-
let
|
|
7436
|
-
L.length > 0 && (
|
|
7437
|
-
remainingText:
|
|
7438
|
-
originalText:
|
|
7439
|
-
options:
|
|
7440
|
-
},
|
|
7508
|
+
const T = y.current.isSpeaking || !1, ne = y.current.audioPlaylist || [], L = y.current.speechQueue || [];
|
|
7509
|
+
if (T || ne.length > 0 || L.length > 0) {
|
|
7510
|
+
D.current && (clearInterval(D.current), D.current = null);
|
|
7511
|
+
let P = "";
|
|
7512
|
+
L.length > 0 && (P = L.map((N) => N.text && Array.isArray(N.text) ? N.text.map((J) => J.word).join(" ") : N.text || "").join(" ")), k.current = {
|
|
7513
|
+
remainingText: P || null,
|
|
7514
|
+
originalText: w.current?.text || null,
|
|
7515
|
+
options: w.current?.options || null
|
|
7516
|
+
}, y.current.speechQueue.length = 0, y.current.pauseSpeaking(), le(!0), $.current = !0;
|
|
7441
7517
|
}
|
|
7442
|
-
} catch (
|
|
7443
|
-
console.warn("Error pausing speech:",
|
|
7518
|
+
} catch (T) {
|
|
7519
|
+
console.warn("Error pausing speech:", T);
|
|
7444
7520
|
}
|
|
7445
|
-
}, []), Le =
|
|
7446
|
-
if (!(!
|
|
7521
|
+
}, []), Le = F(async () => {
|
|
7522
|
+
if (!(!y.current || !te))
|
|
7447
7523
|
try {
|
|
7448
|
-
await _(), le(!1),
|
|
7449
|
-
const
|
|
7450
|
-
|
|
7451
|
-
} catch (
|
|
7452
|
-
console.warn("Error resuming speech:",
|
|
7524
|
+
await _(), le(!1), $.current = !1;
|
|
7525
|
+
const T = k.current?.remainingText, ne = k.current?.originalText || w.current?.text, L = k.current?.options || w.current?.options || {}, P = T || ne;
|
|
7526
|
+
P && j(P, L);
|
|
7527
|
+
} catch (T) {
|
|
7528
|
+
console.warn("Error resuming speech:", T), le(!1), $.current = !1;
|
|
7453
7529
|
}
|
|
7454
|
-
}, [
|
|
7455
|
-
|
|
7530
|
+
}, [te, j, _]), we = F(() => {
|
|
7531
|
+
y.current && (y.current.stopSpeaking(), D.current && (clearInterval(D.current), D.current = null), le(!1), $.current = !1);
|
|
7456
7532
|
}, []);
|
|
7457
|
-
return Ee(
|
|
7533
|
+
return Ee(E, () => ({
|
|
7458
7534
|
speakText: j,
|
|
7459
7535
|
pauseSpeaking: q,
|
|
7460
7536
|
resumeSpeaking: Le,
|
|
7461
7537
|
stopSpeaking: we,
|
|
7462
7538
|
resumeAudioContext: _,
|
|
7463
|
-
isPaused: () =>
|
|
7464
|
-
setMood: (
|
|
7465
|
-
setBodyMovement: (
|
|
7466
|
-
|
|
7539
|
+
isPaused: () => te,
|
|
7540
|
+
setMood: (T) => y.current?.setMood(T),
|
|
7541
|
+
setBodyMovement: (T) => {
|
|
7542
|
+
y.current && y.current.setBodyMovement(T);
|
|
7467
7543
|
},
|
|
7468
|
-
playAnimation: (
|
|
7469
|
-
|
|
7544
|
+
playAnimation: (T, ne = !1) => {
|
|
7545
|
+
y.current && y.current.playAnimation && y.current.playAnimation(T, null, 10, 0, 0.01, ne);
|
|
7470
7546
|
},
|
|
7471
|
-
playReaction: (
|
|
7472
|
-
playCelebration: () =>
|
|
7473
|
-
setShowFullAvatar: (
|
|
7474
|
-
|
|
7547
|
+
playReaction: (T) => y.current?.playReaction(T),
|
|
7548
|
+
playCelebration: () => y.current?.playCelebration(),
|
|
7549
|
+
setShowFullAvatar: (T) => {
|
|
7550
|
+
y.current && (H.current = T, y.current.setShowFullAvatar(T));
|
|
7475
7551
|
},
|
|
7476
7552
|
isReady: ae,
|
|
7477
|
-
talkingHead:
|
|
7478
|
-
})), /* @__PURE__ */ Pe("div", { className: `simple-talking-avatar-container ${
|
|
7553
|
+
talkingHead: y.current
|
|
7554
|
+
})), /* @__PURE__ */ Pe("div", { className: `simple-talking-avatar-container ${x}`, style: A, children: [
|
|
7479
7555
|
/* @__PURE__ */ me(
|
|
7480
7556
|
"div",
|
|
7481
7557
|
{
|
|
7482
|
-
ref:
|
|
7558
|
+
ref: I,
|
|
7483
7559
|
className: "talking-head-viewer",
|
|
7484
7560
|
style: {
|
|
7485
7561
|
width: "100%",
|
|
@@ -7497,7 +7573,7 @@ const gt = Me(({
|
|
|
7497
7573
|
fontSize: "18px",
|
|
7498
7574
|
zIndex: 10
|
|
7499
7575
|
}, children: "Loading avatar..." }),
|
|
7500
|
-
|
|
7576
|
+
ee && /* @__PURE__ */ me("div", { className: "error-overlay", style: {
|
|
7501
7577
|
position: "absolute",
|
|
7502
7578
|
top: "50%",
|
|
7503
7579
|
left: "50%",
|
|
@@ -7508,12 +7584,12 @@ const gt = Me(({
|
|
|
7508
7584
|
zIndex: 10,
|
|
7509
7585
|
padding: "20px",
|
|
7510
7586
|
borderRadius: "8px"
|
|
7511
|
-
}, children:
|
|
7587
|
+
}, children: ee })
|
|
7512
7588
|
] });
|
|
7513
7589
|
});
|
|
7514
7590
|
gt.displayName = "SimpleTalkingAvatar";
|
|
7515
7591
|
const yt = Me(({
|
|
7516
|
-
curriculumData:
|
|
7592
|
+
curriculumData: Z = null,
|
|
7517
7593
|
avatarConfig: t = {},
|
|
7518
7594
|
animations: e = {},
|
|
7519
7595
|
onLessonStart: n = () => {
|
|
@@ -7528,7 +7604,7 @@ const yt = Me(({
|
|
|
7528
7604
|
},
|
|
7529
7605
|
autoStart: h = !1
|
|
7530
7606
|
}, r) => {
|
|
7531
|
-
const u =
|
|
7607
|
+
const u = O(null), a = O({
|
|
7532
7608
|
currentModuleIndex: 0,
|
|
7533
7609
|
currentLessonIndex: 0,
|
|
7534
7610
|
currentQuestionIndex: 0,
|
|
@@ -7538,18 +7614,18 @@ const yt = Me(({
|
|
|
7538
7614
|
curriculumCompleted: !1,
|
|
7539
7615
|
score: 0,
|
|
7540
7616
|
totalQuestions: 0
|
|
7541
|
-
}),
|
|
7617
|
+
}), c = O({
|
|
7542
7618
|
onLessonStart: n,
|
|
7543
7619
|
onLessonComplete: i,
|
|
7544
7620
|
onQuestionAnswer: s,
|
|
7545
7621
|
onCurriculumComplete: o,
|
|
7546
7622
|
onCustomAction: l
|
|
7547
|
-
}),
|
|
7623
|
+
}), d = O(null), g = O(null), b = O(null), x = O(null), A = O(null), B = O(null), p = O(null), E = O(Z?.curriculum || {
|
|
7548
7624
|
title: "Default Curriculum",
|
|
7549
7625
|
description: "No curriculum data provided",
|
|
7550
7626
|
language: "en",
|
|
7551
7627
|
modules: []
|
|
7552
|
-
}),
|
|
7628
|
+
}), I = O({
|
|
7553
7629
|
avatarUrl: t.avatarUrl || "/avatars/brunette.glb",
|
|
7554
7630
|
avatarBody: t.avatarBody || "F",
|
|
7555
7631
|
mood: t.mood || "happy",
|
|
@@ -7564,7 +7640,7 @@ const yt = Me(({
|
|
|
7564
7640
|
lipsyncLang: "en"
|
|
7565
7641
|
});
|
|
7566
7642
|
de(() => {
|
|
7567
|
-
|
|
7643
|
+
c.current = {
|
|
7568
7644
|
onLessonStart: n,
|
|
7569
7645
|
onLessonComplete: i,
|
|
7570
7646
|
onQuestionAnswer: s,
|
|
@@ -7572,12 +7648,12 @@ const yt = Me(({
|
|
|
7572
7648
|
onCustomAction: l
|
|
7573
7649
|
};
|
|
7574
7650
|
}, [n, i, s, o, l]), de(() => {
|
|
7575
|
-
|
|
7651
|
+
E.current = Z?.curriculum || {
|
|
7576
7652
|
title: "Default Curriculum",
|
|
7577
7653
|
description: "No curriculum data provided",
|
|
7578
7654
|
language: "en",
|
|
7579
7655
|
modules: []
|
|
7580
|
-
},
|
|
7656
|
+
}, I.current = {
|
|
7581
7657
|
avatarUrl: t.avatarUrl || "/avatars/brunette.glb",
|
|
7582
7658
|
avatarBody: t.avatarBody || "F",
|
|
7583
7659
|
mood: t.mood || "happy",
|
|
@@ -7591,18 +7667,18 @@ const yt = Me(({
|
|
|
7591
7667
|
animations: e,
|
|
7592
7668
|
lipsyncLang: "en"
|
|
7593
7669
|
};
|
|
7594
|
-
}, [
|
|
7595
|
-
const
|
|
7670
|
+
}, [Z, t, e]);
|
|
7671
|
+
const y = F(() => (E.current || { modules: [] }).modules[a.current.currentModuleIndex]?.lessons[a.current.currentLessonIndex], []), H = F(() => y()?.questions[a.current.currentQuestionIndex], [y]), w = F((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, []), D = F(() => {
|
|
7596
7672
|
a.current.lessonCompleted = !0, a.current.isQuestionMode = !1;
|
|
7597
7673
|
const v = a.current.totalQuestions > 0 ? Math.round(a.current.score / a.current.totalQuestions * 100) : 100;
|
|
7598
|
-
let
|
|
7599
|
-
if (a.current.totalQuestions > 0 ?
|
|
7674
|
+
let R = "Congratulations! You've completed this lesson";
|
|
7675
|
+
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({
|
|
7600
7676
|
moduleIndex: a.current.currentModuleIndex,
|
|
7601
7677
|
lessonIndex: a.current.currentLessonIndex,
|
|
7602
7678
|
score: a.current.score,
|
|
7603
7679
|
totalQuestions: a.current.totalQuestions,
|
|
7604
7680
|
percentage: v
|
|
7605
|
-
}),
|
|
7681
|
+
}), c.current.onCustomAction({
|
|
7606
7682
|
type: "lessonComplete",
|
|
7607
7683
|
moduleIndex: a.current.currentModuleIndex,
|
|
7608
7684
|
lessonIndex: a.current.currentLessonIndex,
|
|
@@ -7616,11 +7692,11 @@ const yt = Me(({
|
|
|
7616
7692
|
} catch {
|
|
7617
7693
|
u.current.playCelebration();
|
|
7618
7694
|
}
|
|
7619
|
-
const
|
|
7620
|
-
u.current.speakText(
|
|
7695
|
+
const z = E.current || { modules: [] }, M = z.modules[a.current.currentModuleIndex], W = a.current.currentLessonIndex < (M?.lessons?.length || 0) - 1, _ = a.current.currentModuleIndex < (z.modules?.length || 0) - 1, j = W || _, q = I.current || { lipsyncLang: "en" };
|
|
7696
|
+
u.current.speakText(R, {
|
|
7621
7697
|
lipsyncLang: q.lipsyncLang,
|
|
7622
7698
|
onSpeechEnd: () => {
|
|
7623
|
-
|
|
7699
|
+
c.current.onCustomAction({
|
|
7624
7700
|
type: "lessonCompleteFeedbackDone",
|
|
7625
7701
|
moduleIndex: a.current.currentModuleIndex,
|
|
7626
7702
|
lessonIndex: a.current.currentLessonIndex,
|
|
@@ -7632,12 +7708,12 @@ const yt = Me(({
|
|
|
7632
7708
|
}
|
|
7633
7709
|
});
|
|
7634
7710
|
}
|
|
7635
|
-
}, [e.lessonComplete]),
|
|
7711
|
+
}, [e.lessonComplete]), $ = F(() => {
|
|
7636
7712
|
a.current.curriculumCompleted = !0;
|
|
7637
|
-
const v =
|
|
7638
|
-
if (
|
|
7713
|
+
const v = E.current || { modules: [] };
|
|
7714
|
+
if (c.current.onCurriculumComplete({
|
|
7639
7715
|
modules: v.modules.length,
|
|
7640
|
-
totalLessons: v.modules.reduce((
|
|
7716
|
+
totalLessons: v.modules.reduce((R, z) => R + z.lessons.length, 0)
|
|
7641
7717
|
}), u.current) {
|
|
7642
7718
|
if (u.current.setMood("celebrating"), e.curriculumComplete)
|
|
7643
7719
|
try {
|
|
@@ -7645,177 +7721,177 @@ const yt = Me(({
|
|
|
7645
7721
|
} catch {
|
|
7646
7722
|
u.current.playCelebration();
|
|
7647
7723
|
}
|
|
7648
|
-
const
|
|
7649
|
-
u.current.speakText("Amazing! You've completed the entire curriculum! You're now ready to move on to more advanced topics. Well done!", { lipsyncLang:
|
|
7724
|
+
const R = I.current || { lipsyncLang: "en" };
|
|
7725
|
+
u.current.speakText("Amazing! You've completed the entire curriculum! You're now ready to move on to more advanced topics. Well done!", { lipsyncLang: R.lipsyncLang });
|
|
7650
7726
|
}
|
|
7651
|
-
}, [e.curriculumComplete]),
|
|
7652
|
-
const v =
|
|
7727
|
+
}, [e.curriculumComplete]), k = F(() => {
|
|
7728
|
+
const v = y();
|
|
7653
7729
|
a.current.isQuestionMode = !0, a.current.currentQuestionIndex = 0, a.current.totalQuestions = v?.questions?.length || 0, a.current.score = 0;
|
|
7654
|
-
const
|
|
7655
|
-
|
|
7730
|
+
const R = H();
|
|
7731
|
+
R && c.current.onCustomAction({
|
|
7656
7732
|
type: "questionStart",
|
|
7657
7733
|
moduleIndex: a.current.currentModuleIndex,
|
|
7658
7734
|
lessonIndex: a.current.currentLessonIndex,
|
|
7659
7735
|
questionIndex: a.current.currentQuestionIndex,
|
|
7660
7736
|
totalQuestions: a.current.totalQuestions,
|
|
7661
|
-
question:
|
|
7737
|
+
question: R,
|
|
7662
7738
|
score: a.current.score
|
|
7663
7739
|
});
|
|
7664
|
-
const
|
|
7665
|
-
if (!u.current || !
|
|
7740
|
+
const z = () => {
|
|
7741
|
+
if (!u.current || !R) return;
|
|
7666
7742
|
if (u.current.setMood("happy"), e.questionStart)
|
|
7667
7743
|
try {
|
|
7668
7744
|
u.current.playAnimation(e.questionStart, !0);
|
|
7669
|
-
} catch (
|
|
7670
|
-
console.warn("Failed to play questionStart animation:",
|
|
7745
|
+
} catch (W) {
|
|
7746
|
+
console.warn("Failed to play questionStart animation:", W);
|
|
7671
7747
|
}
|
|
7672
|
-
const
|
|
7673
|
-
|
|
7748
|
+
const M = I.current || { lipsyncLang: "en" };
|
|
7749
|
+
R.type === "code_test" ? u.current.speakText(`Let's test your coding skills! Here's your first challenge: ${R.question}`, { lipsyncLang: M.lipsyncLang }) : R.type === "multiple_choice" ? u.current.speakText(`Now let me ask you some questions. Here's the first one: ${R.question}`, { lipsyncLang: M.lipsyncLang }) : R.type === "true_false" ? u.current.speakText(`Let's start with some true or false questions. First question: ${R.question}`, { lipsyncLang: M.lipsyncLang }) : u.current.speakText(`Now let me ask you some questions. Here's the first one: ${R.question}`, { lipsyncLang: M.lipsyncLang });
|
|
7674
7750
|
};
|
|
7675
|
-
if (u.current && u.current.isReady &&
|
|
7676
|
-
|
|
7751
|
+
if (u.current && u.current.isReady && R)
|
|
7752
|
+
z();
|
|
7677
7753
|
else if (u.current && u.current.isReady) {
|
|
7678
|
-
const
|
|
7679
|
-
u.current.speakText("Now let me ask you some questions to test your understanding.", { lipsyncLang:
|
|
7754
|
+
const M = I.current || { lipsyncLang: "en" };
|
|
7755
|
+
u.current.speakText("Now let me ask you some questions to test your understanding.", { lipsyncLang: M.lipsyncLang });
|
|
7680
7756
|
} else {
|
|
7681
|
-
const
|
|
7682
|
-
u.current && u.current.isReady && (clearInterval(
|
|
7757
|
+
const M = setInterval(() => {
|
|
7758
|
+
u.current && u.current.isReady && (clearInterval(M), R && z());
|
|
7683
7759
|
}, 100);
|
|
7684
7760
|
setTimeout(() => {
|
|
7685
|
-
clearInterval(
|
|
7761
|
+
clearInterval(M);
|
|
7686
7762
|
}, 5e3);
|
|
7687
7763
|
}
|
|
7688
|
-
}, [e.questionStart,
|
|
7689
|
-
const v =
|
|
7764
|
+
}, [e.questionStart, y, H]), V = F(() => {
|
|
7765
|
+
const v = y();
|
|
7690
7766
|
if (a.current.currentQuestionIndex < (v?.questions?.length || 0) - 1) {
|
|
7691
7767
|
u.current && u.current.stopSpeaking && u.current.stopSpeaking(), a.current.currentQuestionIndex += 1;
|
|
7692
|
-
const
|
|
7693
|
-
|
|
7768
|
+
const R = H();
|
|
7769
|
+
R && c.current.onCustomAction({
|
|
7694
7770
|
type: "nextQuestion",
|
|
7695
7771
|
moduleIndex: a.current.currentModuleIndex,
|
|
7696
7772
|
lessonIndex: a.current.currentLessonIndex,
|
|
7697
7773
|
questionIndex: a.current.currentQuestionIndex,
|
|
7698
7774
|
totalQuestions: a.current.totalQuestions,
|
|
7699
|
-
question:
|
|
7775
|
+
question: R,
|
|
7700
7776
|
score: a.current.score
|
|
7701
7777
|
});
|
|
7702
|
-
const
|
|
7703
|
-
if (!u.current || !
|
|
7778
|
+
const z = () => {
|
|
7779
|
+
if (!u.current || !R) return;
|
|
7704
7780
|
if (u.current.setMood("happy"), u.current.setBodyMovement("idle"), e.nextQuestion)
|
|
7705
7781
|
try {
|
|
7706
7782
|
u.current.playAnimation(e.nextQuestion, !0);
|
|
7707
7783
|
} catch (q) {
|
|
7708
7784
|
console.warn("Failed to play nextQuestion animation:", q);
|
|
7709
7785
|
}
|
|
7710
|
-
const
|
|
7711
|
-
if (
|
|
7712
|
-
const q = j ? `Great! Here's your final coding challenge: ${
|
|
7786
|
+
const M = I.current || { lipsyncLang: "en" }, _ = y()?.questions?.length || 0, j = a.current.currentQuestionIndex >= _ - 1;
|
|
7787
|
+
if (R.type === "code_test") {
|
|
7788
|
+
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}`;
|
|
7713
7789
|
u.current.speakText(q, {
|
|
7714
|
-
lipsyncLang:
|
|
7790
|
+
lipsyncLang: M.lipsyncLang
|
|
7715
7791
|
});
|
|
7716
|
-
} else if (
|
|
7717
|
-
const q = j ? `Alright! Here's your final question: ${
|
|
7792
|
+
} else if (R.type === "multiple_choice") {
|
|
7793
|
+
const q = j ? `Alright! Here's your final question: ${R.question}` : `Alright! Here's your next question: ${R.question}`;
|
|
7718
7794
|
u.current.speakText(q, {
|
|
7719
|
-
lipsyncLang:
|
|
7795
|
+
lipsyncLang: M.lipsyncLang
|
|
7720
7796
|
});
|
|
7721
|
-
} else if (
|
|
7722
|
-
const q = j ? `Now let's try this final one: ${
|
|
7797
|
+
} else if (R.type === "true_false") {
|
|
7798
|
+
const q = j ? `Now let's try this final one: ${R.question}` : `Now let's try this one: ${R.question}`;
|
|
7723
7799
|
u.current.speakText(q, {
|
|
7724
|
-
lipsyncLang:
|
|
7800
|
+
lipsyncLang: M.lipsyncLang
|
|
7725
7801
|
});
|
|
7726
7802
|
} else {
|
|
7727
|
-
const q = j ? `Here's your final question: ${
|
|
7803
|
+
const q = j ? `Here's your final question: ${R.question}` : `Here's the next question: ${R.question}`;
|
|
7728
7804
|
u.current.speakText(q, {
|
|
7729
|
-
lipsyncLang:
|
|
7805
|
+
lipsyncLang: M.lipsyncLang
|
|
7730
7806
|
});
|
|
7731
7807
|
}
|
|
7732
7808
|
};
|
|
7733
|
-
if (u.current && u.current.isReady &&
|
|
7734
|
-
|
|
7735
|
-
else if (
|
|
7736
|
-
const
|
|
7737
|
-
u.current && u.current.isReady && (clearInterval(
|
|
7809
|
+
if (u.current && u.current.isReady && R)
|
|
7810
|
+
z();
|
|
7811
|
+
else if (R) {
|
|
7812
|
+
const M = setInterval(() => {
|
|
7813
|
+
u.current && u.current.isReady && (clearInterval(M), z());
|
|
7738
7814
|
}, 100);
|
|
7739
7815
|
setTimeout(() => {
|
|
7740
|
-
clearInterval(
|
|
7816
|
+
clearInterval(M);
|
|
7741
7817
|
}, 5e3);
|
|
7742
7818
|
}
|
|
7743
7819
|
} else
|
|
7744
|
-
|
|
7820
|
+
c.current.onCustomAction({
|
|
7745
7821
|
type: "allQuestionsComplete",
|
|
7746
7822
|
moduleIndex: a.current.currentModuleIndex,
|
|
7747
7823
|
lessonIndex: a.current.currentLessonIndex,
|
|
7748
7824
|
totalQuestions: a.current.totalQuestions,
|
|
7749
7825
|
score: a.current.score
|
|
7750
7826
|
});
|
|
7751
|
-
}, [e.nextQuestion,
|
|
7752
|
-
const v =
|
|
7753
|
-
if (a.current.currentLessonIndex < (
|
|
7827
|
+
}, [e.nextQuestion, y, H]), K = F(() => {
|
|
7828
|
+
const v = E.current || { modules: [] }, R = v.modules[a.current.currentModuleIndex];
|
|
7829
|
+
if (a.current.currentLessonIndex < (R?.lessons?.length || 0) - 1) {
|
|
7754
7830
|
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;
|
|
7755
|
-
const
|
|
7756
|
-
|
|
7831
|
+
const M = v.modules[a.current.currentModuleIndex], W = a.current.currentLessonIndex < (M?.lessons?.length || 0) - 1, _ = a.current.currentModuleIndex < (v.modules?.length || 0) - 1, j = W || _;
|
|
7832
|
+
c.current.onCustomAction({
|
|
7757
7833
|
type: "lessonStart",
|
|
7758
7834
|
moduleIndex: a.current.currentModuleIndex,
|
|
7759
7835
|
lessonIndex: a.current.currentLessonIndex,
|
|
7760
7836
|
hasNextLesson: j
|
|
7761
|
-
}),
|
|
7837
|
+
}), c.current.onLessonStart({
|
|
7762
7838
|
moduleIndex: a.current.currentModuleIndex,
|
|
7763
7839
|
lessonIndex: a.current.currentLessonIndex,
|
|
7764
|
-
lesson:
|
|
7840
|
+
lesson: y()
|
|
7765
7841
|
}), u.current && (u.current.setMood("happy"), u.current.setBodyMovement("idle"));
|
|
7766
7842
|
} else if (a.current.currentModuleIndex < (v.modules?.length || 0) - 1) {
|
|
7767
7843
|
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;
|
|
7768
|
-
const
|
|
7769
|
-
|
|
7844
|
+
const W = v.modules[a.current.currentModuleIndex], _ = a.current.currentLessonIndex < (W?.lessons?.length || 0) - 1, j = a.current.currentModuleIndex < (v.modules?.length || 0) - 1, q = _ || j;
|
|
7845
|
+
c.current.onCustomAction({
|
|
7770
7846
|
type: "lessonStart",
|
|
7771
7847
|
moduleIndex: a.current.currentModuleIndex,
|
|
7772
7848
|
lessonIndex: a.current.currentLessonIndex,
|
|
7773
7849
|
hasNextLesson: q
|
|
7774
|
-
}),
|
|
7850
|
+
}), c.current.onLessonStart({
|
|
7775
7851
|
moduleIndex: a.current.currentModuleIndex,
|
|
7776
7852
|
lessonIndex: a.current.currentLessonIndex,
|
|
7777
|
-
lesson:
|
|
7853
|
+
lesson: y()
|
|
7778
7854
|
}), u.current && (u.current.setMood("happy"), u.current.setBodyMovement("idle"));
|
|
7779
7855
|
} else
|
|
7780
|
-
|
|
7781
|
-
}, []), X =
|
|
7782
|
-
const v =
|
|
7783
|
-
let
|
|
7856
|
+
A.current && A.current();
|
|
7857
|
+
}, []), X = F(() => {
|
|
7858
|
+
const v = y();
|
|
7859
|
+
let R = null;
|
|
7784
7860
|
if (v?.avatar_script && v?.body) {
|
|
7785
|
-
const
|
|
7786
|
-
|
|
7861
|
+
const z = v.avatar_script.trim(), M = v.body.trim(), W = z.match(/[.!?]$/) ? " " : ". ";
|
|
7862
|
+
R = `${z}${W}${M}`;
|
|
7787
7863
|
} else
|
|
7788
|
-
|
|
7789
|
-
if (u.current && u.current.isReady &&
|
|
7864
|
+
R = v?.avatar_script || v?.body || null;
|
|
7865
|
+
if (u.current && u.current.isReady && R) {
|
|
7790
7866
|
a.current.isTeaching = !0, a.current.isQuestionMode = !1, a.current.score = 0, a.current.totalQuestions = 0, u.current.setMood("happy");
|
|
7791
|
-
let
|
|
7867
|
+
let z = !1;
|
|
7792
7868
|
if (e.teaching)
|
|
7793
7869
|
try {
|
|
7794
|
-
u.current.playAnimation(e.teaching, !0),
|
|
7795
|
-
} catch (
|
|
7796
|
-
console.warn("Failed to play teaching animation:",
|
|
7870
|
+
u.current.playAnimation(e.teaching, !0), z = !0;
|
|
7871
|
+
} catch (W) {
|
|
7872
|
+
console.warn("Failed to play teaching animation:", W);
|
|
7797
7873
|
}
|
|
7798
|
-
|
|
7799
|
-
const
|
|
7800
|
-
|
|
7874
|
+
z || u.current.setBodyMovement("gesturing");
|
|
7875
|
+
const M = I.current || { lipsyncLang: "en" };
|
|
7876
|
+
c.current.onLessonStart({
|
|
7801
7877
|
moduleIndex: a.current.currentModuleIndex,
|
|
7802
7878
|
lessonIndex: a.current.currentLessonIndex,
|
|
7803
7879
|
lesson: v
|
|
7804
|
-
}),
|
|
7880
|
+
}), c.current.onCustomAction({
|
|
7805
7881
|
type: "teachingStart",
|
|
7806
7882
|
moduleIndex: a.current.currentModuleIndex,
|
|
7807
7883
|
lessonIndex: a.current.currentLessonIndex,
|
|
7808
7884
|
lesson: v
|
|
7809
|
-
}), u.current.speakText(
|
|
7810
|
-
lipsyncLang:
|
|
7885
|
+
}), u.current.speakText(R, {
|
|
7886
|
+
lipsyncLang: M.lipsyncLang,
|
|
7811
7887
|
onSpeechEnd: () => {
|
|
7812
|
-
a.current.isTeaching = !1,
|
|
7888
|
+
a.current.isTeaching = !1, c.current.onCustomAction({
|
|
7813
7889
|
type: "teachingComplete",
|
|
7814
7890
|
moduleIndex: a.current.currentModuleIndex,
|
|
7815
7891
|
lessonIndex: a.current.currentLessonIndex,
|
|
7816
7892
|
lesson: v,
|
|
7817
7893
|
hasQuestions: v.questions && v.questions.length > 0
|
|
7818
|
-
}), v?.code_example &&
|
|
7894
|
+
}), v?.code_example && c.current.onCustomAction({
|
|
7819
7895
|
type: "codeExampleReady",
|
|
7820
7896
|
moduleIndex: a.current.currentModuleIndex,
|
|
7821
7897
|
lessonIndex: a.current.currentLessonIndex,
|
|
@@ -7825,17 +7901,17 @@ const yt = Me(({
|
|
|
7825
7901
|
}
|
|
7826
7902
|
});
|
|
7827
7903
|
}
|
|
7828
|
-
}, [e.teaching,
|
|
7829
|
-
const
|
|
7830
|
-
if (
|
|
7904
|
+
}, [e.teaching, y]), ee = F((v) => {
|
|
7905
|
+
const R = H(), z = w(v, R);
|
|
7906
|
+
if (z && (a.current.score += 1), c.current.onQuestionAnswer({
|
|
7831
7907
|
moduleIndex: a.current.currentModuleIndex,
|
|
7832
7908
|
lessonIndex: a.current.currentLessonIndex,
|
|
7833
7909
|
questionIndex: a.current.currentQuestionIndex,
|
|
7834
7910
|
answer: v,
|
|
7835
|
-
isCorrect:
|
|
7836
|
-
question:
|
|
7911
|
+
isCorrect: z,
|
|
7912
|
+
question: R
|
|
7837
7913
|
}), u.current)
|
|
7838
|
-
if (
|
|
7914
|
+
if (z) {
|
|
7839
7915
|
if (u.current.setMood("happy"), e.correct)
|
|
7840
7916
|
try {
|
|
7841
7917
|
u.current.playReaction("happy");
|
|
@@ -7843,15 +7919,15 @@ const yt = Me(({
|
|
|
7843
7919
|
u.current.setBodyMovement("happy");
|
|
7844
7920
|
}
|
|
7845
7921
|
u.current.setBodyMovement("gesturing");
|
|
7846
|
-
const
|
|
7847
|
-
a.current.currentQuestionIndex >=
|
|
7848
|
-
const _ = a.current.currentQuestionIndex <
|
|
7849
|
-
console.log("[CurriculumLearning] Answer feedback - questionIndex:", a.current.currentQuestionIndex, "totalQuestions:",
|
|
7850
|
-
const j =
|
|
7922
|
+
const W = y()?.questions?.length || 0;
|
|
7923
|
+
a.current.currentQuestionIndex >= W - 1;
|
|
7924
|
+
const _ = a.current.currentQuestionIndex < W - 1;
|
|
7925
|
+
console.log("[CurriculumLearning] Answer feedback - questionIndex:", a.current.currentQuestionIndex, "totalQuestions:", W, "hasNextQuestion:", _);
|
|
7926
|
+
const j = R.type === "code_test" ? `Great job! Your code passed all the tests! ${R.explanation || ""}` : `Excellent! That's correct! ${R.explanation || ""}`, q = I.current || { lipsyncLang: "en" };
|
|
7851
7927
|
u.current.speakText(j, {
|
|
7852
7928
|
lipsyncLang: q.lipsyncLang,
|
|
7853
7929
|
onSpeechEnd: () => {
|
|
7854
|
-
|
|
7930
|
+
c.current.onCustomAction({
|
|
7855
7931
|
type: "answerFeedbackComplete",
|
|
7856
7932
|
moduleIndex: a.current.currentModuleIndex,
|
|
7857
7933
|
lessonIndex: a.current.currentLessonIndex,
|
|
@@ -7871,13 +7947,13 @@ const yt = Me(({
|
|
|
7871
7947
|
u.current.setBodyMovement("idle");
|
|
7872
7948
|
}
|
|
7873
7949
|
u.current.setBodyMovement("gesturing");
|
|
7874
|
-
const
|
|
7875
|
-
console.log("[CurriculumLearning] Answer feedback (incorrect) - questionIndex:", a.current.currentQuestionIndex, "totalQuestions:",
|
|
7876
|
-
const q =
|
|
7950
|
+
const W = y()?.questions?.length || 0, _ = a.current.currentQuestionIndex >= W - 1, j = a.current.currentQuestionIndex < W - 1;
|
|
7951
|
+
console.log("[CurriculumLearning] Answer feedback (incorrect) - questionIndex:", a.current.currentQuestionIndex, "totalQuestions:", W, "hasNextQuestion:", j);
|
|
7952
|
+
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 || ""}${_ ? "" : " Let's move on to the next question."}`, Le = I.current || { lipsyncLang: "en" };
|
|
7877
7953
|
u.current.speakText(q, {
|
|
7878
7954
|
lipsyncLang: Le.lipsyncLang,
|
|
7879
7955
|
onSpeechEnd: () => {
|
|
7880
|
-
|
|
7956
|
+
c.current.onCustomAction({
|
|
7881
7957
|
type: "answerFeedbackComplete",
|
|
7882
7958
|
moduleIndex: a.current.currentModuleIndex,
|
|
7883
7959
|
lessonIndex: a.current.currentLessonIndex,
|
|
@@ -7891,30 +7967,30 @@ const yt = Me(({
|
|
|
7891
7967
|
});
|
|
7892
7968
|
}
|
|
7893
7969
|
else {
|
|
7894
|
-
const
|
|
7895
|
-
|
|
7970
|
+
const W = y()?.questions?.length || 0;
|
|
7971
|
+
c.current.onCustomAction({
|
|
7896
7972
|
type: "answerFeedbackComplete",
|
|
7897
7973
|
moduleIndex: a.current.currentModuleIndex,
|
|
7898
7974
|
lessonIndex: a.current.currentLessonIndex,
|
|
7899
7975
|
questionIndex: a.current.currentQuestionIndex,
|
|
7900
|
-
isCorrect:
|
|
7901
|
-
hasNextQuestion: a.current.currentQuestionIndex <
|
|
7976
|
+
isCorrect: z,
|
|
7977
|
+
hasNextQuestion: a.current.currentQuestionIndex < W - 1,
|
|
7902
7978
|
score: a.current.score,
|
|
7903
7979
|
totalQuestions: a.current.totalQuestions,
|
|
7904
7980
|
avatarNotReady: !0
|
|
7905
7981
|
});
|
|
7906
7982
|
}
|
|
7907
|
-
}, [e.correct, e.incorrect,
|
|
7908
|
-
const
|
|
7983
|
+
}, [e.correct, e.incorrect, H, y, w]), se = F((v) => {
|
|
7984
|
+
const R = H();
|
|
7909
7985
|
if (!v || typeof v != "object") {
|
|
7910
7986
|
console.error("Invalid code test result format. Expected object with {passed: boolean, ...}");
|
|
7911
7987
|
return;
|
|
7912
7988
|
}
|
|
7913
|
-
if (
|
|
7989
|
+
if (R?.type !== "code_test") {
|
|
7914
7990
|
console.warn("Current question is not a code test. Use handleAnswerSelect for other question types.");
|
|
7915
7991
|
return;
|
|
7916
7992
|
}
|
|
7917
|
-
const
|
|
7993
|
+
const z = {
|
|
7918
7994
|
passed: v.passed === !0,
|
|
7919
7995
|
results: v.results || [],
|
|
7920
7996
|
output: v.output || "",
|
|
@@ -7924,19 +8000,19 @@ const yt = Me(({
|
|
|
7924
8000
|
passedCount: v.passedCount || 0,
|
|
7925
8001
|
failedCount: v.failedCount || 0
|
|
7926
8002
|
};
|
|
7927
|
-
|
|
8003
|
+
c.current.onCustomAction({
|
|
7928
8004
|
type: "codeTestSubmitted",
|
|
7929
8005
|
moduleIndex: a.current.currentModuleIndex,
|
|
7930
8006
|
lessonIndex: a.current.currentLessonIndex,
|
|
7931
8007
|
questionIndex: a.current.currentQuestionIndex,
|
|
7932
|
-
testResult:
|
|
7933
|
-
question:
|
|
7934
|
-
}), p.current && p.current(
|
|
7935
|
-
}, [
|
|
8008
|
+
testResult: z,
|
|
8009
|
+
question: R
|
|
8010
|
+
}), p.current && p.current(z);
|
|
8011
|
+
}, [H, w]), ae = F(() => {
|
|
7936
8012
|
if (a.current.currentQuestionIndex > 0) {
|
|
7937
8013
|
a.current.currentQuestionIndex -= 1;
|
|
7938
|
-
const v =
|
|
7939
|
-
v &&
|
|
8014
|
+
const v = H();
|
|
8015
|
+
v && c.current.onCustomAction({
|
|
7940
8016
|
type: "questionStart",
|
|
7941
8017
|
moduleIndex: a.current.currentModuleIndex,
|
|
7942
8018
|
lessonIndex: a.current.currentLessonIndex,
|
|
@@ -7945,97 +8021,97 @@ const yt = Me(({
|
|
|
7945
8021
|
question: v,
|
|
7946
8022
|
score: a.current.score
|
|
7947
8023
|
});
|
|
7948
|
-
const
|
|
8024
|
+
const R = () => {
|
|
7949
8025
|
if (!u.current || !v) return;
|
|
7950
8026
|
u.current.setMood("happy"), u.current.setBodyMovement("idle");
|
|
7951
|
-
const
|
|
8027
|
+
const z = I.current || { lipsyncLang: "en" };
|
|
7952
8028
|
v.type === "code_test" ? u.current.speakText(`Let's go back to this coding challenge: ${v.question}`, {
|
|
7953
|
-
lipsyncLang:
|
|
8029
|
+
lipsyncLang: z.lipsyncLang
|
|
7954
8030
|
}) : u.current.speakText(`Going back to: ${v.question}`, {
|
|
7955
|
-
lipsyncLang:
|
|
8031
|
+
lipsyncLang: z.lipsyncLang
|
|
7956
8032
|
});
|
|
7957
8033
|
};
|
|
7958
8034
|
if (u.current && u.current.isReady && v)
|
|
7959
|
-
|
|
8035
|
+
R();
|
|
7960
8036
|
else if (v) {
|
|
7961
|
-
const
|
|
7962
|
-
u.current && u.current.isReady && (clearInterval(
|
|
8037
|
+
const z = setInterval(() => {
|
|
8038
|
+
u.current && u.current.isReady && (clearInterval(z), R());
|
|
7963
8039
|
}, 100);
|
|
7964
8040
|
setTimeout(() => {
|
|
7965
|
-
clearInterval(
|
|
8041
|
+
clearInterval(z);
|
|
7966
8042
|
}, 5e3);
|
|
7967
8043
|
}
|
|
7968
8044
|
}
|
|
7969
|
-
}, [
|
|
7970
|
-
const v =
|
|
8045
|
+
}, [H]), pe = F(() => {
|
|
8046
|
+
const v = E.current || { modules: [] };
|
|
7971
8047
|
if (v.modules[a.current.currentModuleIndex], a.current.currentLessonIndex > 0)
|
|
7972
|
-
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,
|
|
8048
|
+
a.current.currentLessonIndex -= 1, a.current.currentQuestionIndex = 0, a.current.lessonCompleted = !1, a.current.isQuestionMode = !1, a.current.isTeaching = !1, a.current.score = 0, a.current.totalQuestions = 0, c.current.onCustomAction({
|
|
7973
8049
|
type: "lessonStart",
|
|
7974
8050
|
moduleIndex: a.current.currentModuleIndex,
|
|
7975
8051
|
lessonIndex: a.current.currentLessonIndex
|
|
7976
|
-
}),
|
|
8052
|
+
}), c.current.onLessonStart({
|
|
7977
8053
|
moduleIndex: a.current.currentModuleIndex,
|
|
7978
8054
|
lessonIndex: a.current.currentLessonIndex,
|
|
7979
|
-
lesson:
|
|
8055
|
+
lesson: y()
|
|
7980
8056
|
}), u.current && (u.current.setMood("happy"), u.current.setBodyMovement("idle"));
|
|
7981
8057
|
else if (a.current.currentModuleIndex > 0) {
|
|
7982
|
-
const
|
|
7983
|
-
a.current.currentModuleIndex -= 1, a.current.currentLessonIndex = (
|
|
8058
|
+
const M = v.modules[a.current.currentModuleIndex - 1];
|
|
8059
|
+
a.current.currentModuleIndex -= 1, a.current.currentLessonIndex = (M?.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({
|
|
7984
8060
|
type: "lessonStart",
|
|
7985
8061
|
moduleIndex: a.current.currentModuleIndex,
|
|
7986
8062
|
lessonIndex: a.current.currentLessonIndex
|
|
7987
|
-
}),
|
|
8063
|
+
}), c.current.onLessonStart({
|
|
7988
8064
|
moduleIndex: a.current.currentModuleIndex,
|
|
7989
8065
|
lessonIndex: a.current.currentLessonIndex,
|
|
7990
|
-
lesson:
|
|
8066
|
+
lesson: y()
|
|
7991
8067
|
}), u.current && (u.current.setMood("happy"), u.current.setBodyMovement("idle"));
|
|
7992
8068
|
}
|
|
7993
|
-
}, [
|
|
8069
|
+
}, [y]), te = F(() => {
|
|
7994
8070
|
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;
|
|
7995
|
-
}, []), le =
|
|
8071
|
+
}, []), le = F((v) => {
|
|
7996
8072
|
console.log("Avatar is ready!", v);
|
|
7997
|
-
const
|
|
7998
|
-
h &&
|
|
7999
|
-
|
|
8073
|
+
const R = y(), z = R?.avatar_script || R?.body;
|
|
8074
|
+
h && z && setTimeout(() => {
|
|
8075
|
+
d.current && d.current();
|
|
8000
8076
|
}, 10);
|
|
8001
|
-
}, [h,
|
|
8077
|
+
}, [h, y]);
|
|
8002
8078
|
Xe(() => {
|
|
8003
|
-
|
|
8079
|
+
d.current = X, g.current = K, b.current = D, x.current = V, A.current = $, B.current = k, p.current = ee;
|
|
8004
8080
|
}), Ee(r, () => ({
|
|
8005
8081
|
// Curriculum control methods
|
|
8006
8082
|
startTeaching: X,
|
|
8007
|
-
startQuestions:
|
|
8008
|
-
handleAnswerSelect:
|
|
8083
|
+
startQuestions: k,
|
|
8084
|
+
handleAnswerSelect: ee,
|
|
8009
8085
|
handleCodeTestResult: se,
|
|
8010
|
-
nextQuestion:
|
|
8086
|
+
nextQuestion: V,
|
|
8011
8087
|
previousQuestion: ae,
|
|
8012
8088
|
nextLesson: K,
|
|
8013
8089
|
previousLesson: pe,
|
|
8014
|
-
completeLesson:
|
|
8015
|
-
completeCurriculum:
|
|
8016
|
-
resetCurriculum:
|
|
8090
|
+
completeLesson: D,
|
|
8091
|
+
completeCurriculum: $,
|
|
8092
|
+
resetCurriculum: te,
|
|
8017
8093
|
getState: () => ({ ...a.current }),
|
|
8018
|
-
getCurrentQuestion: () =>
|
|
8019
|
-
getCurrentLesson: () =>
|
|
8094
|
+
getCurrentQuestion: () => H(),
|
|
8095
|
+
getCurrentLesson: () => y(),
|
|
8020
8096
|
// Direct access to avatar ref (always returns current value)
|
|
8021
8097
|
getAvatarRef: () => u.current,
|
|
8022
8098
|
// Convenience methods that delegate to avatar (always check current ref)
|
|
8023
|
-
speakText: async (v,
|
|
8099
|
+
speakText: async (v, R = {}) => {
|
|
8024
8100
|
await u.current?.resumeAudioContext?.();
|
|
8025
|
-
const
|
|
8026
|
-
u.current?.speakText(v, { ...
|
|
8101
|
+
const z = I.current || { lipsyncLang: "en" };
|
|
8102
|
+
u.current?.speakText(v, { ...R, lipsyncLang: R.lipsyncLang || z.lipsyncLang });
|
|
8027
8103
|
},
|
|
8028
8104
|
resumeAudioContext: async () => {
|
|
8029
8105
|
if (u.current?.resumeAudioContext)
|
|
8030
8106
|
return await u.current.resumeAudioContext();
|
|
8031
8107
|
const v = u.current?.talkingHead;
|
|
8032
8108
|
if (v?.audioCtx) {
|
|
8033
|
-
const
|
|
8034
|
-
if (
|
|
8109
|
+
const R = v.audioCtx;
|
|
8110
|
+
if (R.state === "suspended" || R.state === "interrupted")
|
|
8035
8111
|
try {
|
|
8036
|
-
await
|
|
8037
|
-
} catch (
|
|
8038
|
-
console.warn("Failed to resume audio context:",
|
|
8112
|
+
await R.resume(), console.log("Audio context resumed via talkingHead");
|
|
8113
|
+
} catch (z) {
|
|
8114
|
+
console.warn("Failed to resume audio context:", z);
|
|
8039
8115
|
}
|
|
8040
8116
|
} else
|
|
8041
8117
|
console.warn("Audio context not available yet");
|
|
@@ -8045,7 +8121,7 @@ const yt = Me(({
|
|
|
8045
8121
|
resumeSpeaking: async () => await u.current?.resumeSpeaking(),
|
|
8046
8122
|
isPaused: () => u.current && typeof u.current.isPaused < "u" ? u.current.isPaused : !1,
|
|
8047
8123
|
setMood: (v) => u.current?.setMood(v),
|
|
8048
|
-
playAnimation: (v,
|
|
8124
|
+
playAnimation: (v, R) => u.current?.playAnimation(v, R),
|
|
8049
8125
|
setBodyMovement: (v) => u.current?.setBodyMovement(v),
|
|
8050
8126
|
setMovementIntensity: (v) => u.current?.setMovementIntensity(v),
|
|
8051
8127
|
playRandomDance: () => u.current?.playRandomDance(),
|
|
@@ -8056,10 +8132,10 @@ const yt = Me(({
|
|
|
8056
8132
|
lockAvatarPosition: () => u.current?.lockAvatarPosition(),
|
|
8057
8133
|
unlockAvatarPosition: () => u.current?.unlockAvatarPosition(),
|
|
8058
8134
|
// Custom action trigger
|
|
8059
|
-
triggerCustomAction: (v,
|
|
8060
|
-
|
|
8135
|
+
triggerCustomAction: (v, R) => {
|
|
8136
|
+
c.current.onCustomAction({
|
|
8061
8137
|
type: v,
|
|
8062
|
-
...
|
|
8138
|
+
...R,
|
|
8063
8139
|
state: { ...a.current }
|
|
8064
8140
|
});
|
|
8065
8141
|
},
|
|
@@ -8067,8 +8143,8 @@ const yt = Me(({
|
|
|
8067
8143
|
handleResize: () => u.current?.handleResize(),
|
|
8068
8144
|
// Avatar readiness check (always returns current value)
|
|
8069
8145
|
isAvatarReady: () => u.current?.isReady || !1
|
|
8070
|
-
}), [X,
|
|
8071
|
-
const
|
|
8146
|
+
}), [X, k, ee, se, V, K, D, $, te, H, y]);
|
|
8147
|
+
const U = I.current || {
|
|
8072
8148
|
avatarUrl: "/avatars/brunette.glb",
|
|
8073
8149
|
avatarBody: "F",
|
|
8074
8150
|
mood: "happy",
|
|
@@ -8085,18 +8161,18 @@ const yt = Me(({
|
|
|
8085
8161
|
Ve,
|
|
8086
8162
|
{
|
|
8087
8163
|
ref: u,
|
|
8088
|
-
avatarUrl:
|
|
8089
|
-
avatarBody:
|
|
8090
|
-
mood:
|
|
8091
|
-
ttsLang:
|
|
8092
|
-
ttsService:
|
|
8093
|
-
ttsVoice:
|
|
8094
|
-
ttsApiKey:
|
|
8095
|
-
bodyMovement:
|
|
8096
|
-
movementIntensity:
|
|
8097
|
-
showFullAvatar:
|
|
8164
|
+
avatarUrl: U.avatarUrl,
|
|
8165
|
+
avatarBody: U.avatarBody,
|
|
8166
|
+
mood: U.mood,
|
|
8167
|
+
ttsLang: U.ttsLang,
|
|
8168
|
+
ttsService: U.ttsService,
|
|
8169
|
+
ttsVoice: U.ttsVoice,
|
|
8170
|
+
ttsApiKey: U.ttsApiKey,
|
|
8171
|
+
bodyMovement: U.bodyMovement,
|
|
8172
|
+
movementIntensity: U.movementIntensity,
|
|
8173
|
+
showFullAvatar: U.showFullAvatar,
|
|
8098
8174
|
cameraView: "upper",
|
|
8099
|
-
animations:
|
|
8175
|
+
animations: U.animations,
|
|
8100
8176
|
onReady: le,
|
|
8101
8177
|
onLoading: () => {
|
|
8102
8178
|
},
|
|
@@ -8210,7 +8286,7 @@ const Ge = {
|
|
|
8210
8286
|
duration: 5e3,
|
|
8211
8287
|
description: "Excited, energetic movement"
|
|
8212
8288
|
}
|
|
8213
|
-
}, wt = (
|
|
8289
|
+
}, wt = (Z) => Ge[Z] || null, zt = (Z) => Ge.hasOwnProperty(Z);
|
|
8214
8290
|
export {
|
|
8215
8291
|
yt as CurriculumLearning,
|
|
8216
8292
|
gt as SimpleTalkingAvatar,
|