@sage-rsc/talking-head-react 1.1.5 → 1.1.6
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/README.md +2 -2
- package/dist/index.cjs +9 -2
- package/dist/index.js +729 -665
- package/package.json +1 -1
- package/src/lib/talkinghead.mjs +144 -12
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
|
|
8
|
-
import { RoomEnvironment as
|
|
9
|
-
import
|
|
10
|
-
let
|
|
11
|
-
const A = [0, 0, 0, 0], z = new
|
|
12
|
-
new
|
|
13
|
-
new
|
|
14
|
-
new
|
|
15
|
-
const oe = new
|
|
16
|
-
new
|
|
17
|
-
const He = new
|
|
7
|
+
import { FBXLoader as Be } from "three/addons/loaders/FBXLoader.js";
|
|
8
|
+
import { RoomEnvironment as _e } from "three/addons/environments/RoomEnvironment.js";
|
|
9
|
+
import qe from "three/addons/libs/stats.module.js";
|
|
10
|
+
let p, re, he;
|
|
11
|
+
const A = [0, 0, 0, 0], z = 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), Ke = new f.Vector3(1, 0, 0), $e = new f.Vector3(0, 1, 0), Je = new f.Vector3(0, 0, 1);
|
|
18
18
|
class et {
|
|
19
19
|
constructor(t = null) {
|
|
20
20
|
this.opt = Object.assign({
|
|
@@ -264,7 +264,7 @@ class et {
|
|
|
264
264
|
"pivot",
|
|
265
265
|
"helper"
|
|
266
266
|
].forEach((n) => {
|
|
267
|
-
|
|
267
|
+
p = this.getValue(t.name, n), p && (e[n] = p);
|
|
268
268
|
}), e;
|
|
269
269
|
});
|
|
270
270
|
}
|
|
@@ -279,7 +279,7 @@ class et {
|
|
|
279
279
|
this.armature.traverse((o) => {
|
|
280
280
|
e.has(o) || (e.set(o, t), t++);
|
|
281
281
|
}), this.data.sort((o, l) => e.get(o.bone) - e.get(l.bone)), this.data.forEach((o) => {
|
|
282
|
-
|
|
282
|
+
p = this.dict[o.boneParent.name], p && (p.children || (p.children = []), p.children.push(o));
|
|
283
283
|
}), this.objectsUpdate = [];
|
|
284
284
|
const n = /* @__PURE__ */ new WeakSet(), i = (o) => o.parent?.isBone ? [o, ...i(o.parent)] : [o], s = (o) => {
|
|
285
285
|
i(o).forEach((u) => {
|
|
@@ -358,20 +358,20 @@ class et {
|
|
|
358
358
|
for (e = 0, i = this.data.length; e < i; e++) {
|
|
359
359
|
if (o = this.data[e], z.copy(o.vWorld), fe.copy(o.boneParent.matrixWorld), xe.copy(fe).invert(), o.vWorld.setFromMatrixPosition(fe), z.applyMatrix4(xe), z.length() > 0.5 && (console.info("Info: Unrealistic jump of " + z.length().toFixed(2) + " meters."), z.setLength(0.5)), z.applyQuaternion(o.bone.quaternion), A[0] = z.x, A[1] = z.y, A[2] = -z.z, A[3] = z.length() / 3, o.children)
|
|
360
360
|
for (n = 0, s = o.children.length; n < s; n++)
|
|
361
|
-
|
|
362
|
-
if (
|
|
361
|
+
p = o.children[n], A[0] -= p.v[0] * t / 3, A[1] -= p.v[1] * t / 3, A[2] += p.v[2] * t / 3, A[3] -= p.v[3] * t / 3;
|
|
362
|
+
if (p = this.opt.sensitivityFactor, A[0] *= o.ext * p, A[1] *= o.ext * p, A[2] *= o.ext * p, A[3] *= o.ext * p, o.isX && (p = A[0] / t, o.ea[0] = (p - o.ev[0]) / t, o.ev[0] = p, 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 + A[0], p = o.v[0] + o.a[0] * t / 2, p = -o.k[0] * o.p[0] - o.c[0] * p - o.ea[0], o.v[0] = o.v[0] + (p + o.a[0]) * t / 2), o.isY && (p = A[1] / t, o.ea[1] = (p - o.ev[1]) / t, o.ev[1] = p, 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 + A[1], p = o.v[1] + o.a[1] * t / 2, p = -o.k[1] * o.p[1] - o.c[1] * p - o.ea[1], o.v[1] = o.v[1] + (p + o.a[1]) * t / 2), o.isZ && (p = A[2] / t, o.ea[2] = (p - o.ev[2]) / t, o.ev[2] = p, 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 + A[2], p = o.v[2] + o.a[2] * t / 2, p = -o.k[2] * o.p[2] - o.c[2] * p - o.ea[2], o.v[2] = o.v[2] + (p + o.a[2]) * t / 2), o.isT && (p = A[3] / t, o.ea[3] = (p - o.ev[3]) / t, o.ev[3] = p, 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 + A[3], p = o.v[3] + o.a[3] * t / 2, p = -o.k[3] * o.p[3] - o.c[3] * p - o.ea[3], o.v[3] = o.v[3] + (p + 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), A[0] = o.p[0], A[1] = o.p[1], A[2] = o.p[2], A[3] = o.p[3], p = this.opt.movementFactor, A[0] *= p, A[1] *= p, A[2] *= p, A[3] *= p, o.dl && (p = o.dl, A[0] += p[0], A[1] += p[1], A[2] += p[2]), o.dw && (p = o.dw, z.set(
|
|
363
363
|
o.vBasis.x + A[0],
|
|
364
364
|
o.vBasis.y + A[1],
|
|
365
365
|
o.vBasis.z + A[2]
|
|
366
|
-
), z.applyMatrix4(fe), z.x +=
|
|
366
|
+
), z.applyMatrix4(fe), z.x += p[0], z.y += p[1], z.z += p[2], z.applyMatrix4(xe), A[0] += z.x - o.vBasis.x, A[1] += z.y - o.vBasis.y, A[2] += z.z - o.vBasis.z), o.limits && this.opt.isLimits && (p = o.limits, p[0] && (p[0][0] !== null && A[0] < p[0][0] && (A[0] = p[0][0]), p[0][1] !== null && A[0] > p[0][1] && (A[0] = p[0][1])), p[1] && (p[1][0] !== null && A[1] < p[1][0] && (A[1] = p[1][0]), p[1][1] !== null && A[1] > p[1][1] && (A[1] = p[1][1])), p[2] && (p[2][0] !== null && A[2] < p[2][0] && (A[2] = p[2][0]), p[2][1] !== null && A[2] > p[2][1] && (A[2] = p[2][1])), p[3] && (p[3][0] !== null && A[3] < p[3][0] && (A[3] = p[3][0]), p[3][1] !== null && A[3] > p[3][1] && (A[3] = p[3][1]))), o.isPoint)
|
|
367
367
|
o.bone.position.set(
|
|
368
368
|
o.vBasis.x + A[0],
|
|
369
369
|
o.vBasis.y + A[1],
|
|
370
370
|
o.vBasis.z - A[2]
|
|
371
371
|
);
|
|
372
|
-
else if (o.boneParent.quaternion.copy(o.qBasis), o.pivot && this.opt.isPivots && (o.boneParent.updateWorldMatrix(!1, !1), o.boneParent.matrixWorld.decompose(z, oe, ie), z.copy(He).applyQuaternion(oe).setY(0).normalize(), oe.premultiply(Oe.setFromUnitVectors(He, z).invert()).normalize(), o.boneParent.quaternion.multiply(oe.invert()), o.boneParent.quaternion.multiply(o.qWorldInverseYaw)), o.isZ && (
|
|
372
|
+
else if (o.boneParent.quaternion.copy(o.qBasis), o.pivot && this.opt.isPivots && (o.boneParent.updateWorldMatrix(!1, !1), o.boneParent.matrixWorld.decompose(z, oe, ie), z.copy(He).applyQuaternion(oe).setY(0).normalize(), oe.premultiply(Oe.setFromUnitVectors(He, z).invert()).normalize(), o.boneParent.quaternion.multiply(oe.invert()), o.boneParent.quaternion.multiply(o.qWorldInverseYaw)), o.isZ && (p = Math.atan(A[0] / o.l), oe.setFromAxisAngle(Je, -p), o.boneParent.quaternion.multiply(oe)), o.isY && (p = o.l / 3, p = p * Math.tanh(A[1] / p), o.bone.position.setLength(o.l + p)), o.isX && (p = Math.atan(A[2] / o.l), oe.setFromAxisAngle(Ke, -p), o.boneParent.quaternion.multiply(oe)), o.isT && (p = 1.5 * Math.tanh(A[3] * 1.5), oe.setFromAxisAngle($e, -p), 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
|
-
|
|
374
|
+
p = o.excludes[n], ie.set(0, 0, 0), p.deltaLocal && (ie.x += p.deltaLocal[0], ie.y += p.deltaLocal[1], ie.z += p.deltaLocal[2]), ie.applyMatrix4(p.bone.matrixWorld), xe.copy(o.boneParent.matrixWorld).invert(), ie.applyMatrix4(xe), z.copy(o.bone.position), !(z.distanceToSquared(ie) >= p.radiusSq) && (he = z.length(), re = ie.length(), !(re > p.radius + he) && (re < Math.abs(p.radius - he) || (re = (re * re + he * he - p.radiusSq) / (2 * re), ie.normalize(), Ce.copy(ie).multiplyScalar(re), re = Math.sqrt(he * he - re * re), z.subVectors(z, Ce).projectOnPlane(ie).normalize().multiplyScalar(re), ze.subVectors(o.vBasis, Ce).projectOnPlane(ie).normalize(), he = ze.dot(z), he < 0 && (he = Math.sqrt(re * re - he * he), ze.multiplyScalar(he), z.add(ze)), z.add(Ce).normalize(), ie.copy(o.bone.position).normalize(), oe.setFromUnitVectors(ie, z), o.boneParent.quaternion.premultiply(oe), o.boneParent.updateWorldMatrix(!1, !0))));
|
|
375
375
|
}
|
|
376
376
|
this.helpers.isActive && this.updateHelpers();
|
|
377
377
|
}
|
|
@@ -382,18 +382,18 @@ class et {
|
|
|
382
382
|
* @param {boolean} [keepSetting=false] If true, keep the previos all setting
|
|
383
383
|
*/
|
|
384
384
|
showHelpers(t) {
|
|
385
|
-
if (this.hideHelpers(), this.helpers.isShowAll = t === void 0 ? this.helpers.isShowAll : t === !0,
|
|
386
|
-
(this.helpers.isShowAll || e.helper === !0) && (
|
|
385
|
+
if (this.hideHelpers(), this.helpers.isShowAll = t === void 0 ? this.helpers.isShowAll : t === !0, p = this.helpers, this.data.forEach((e) => {
|
|
386
|
+
(this.helpers.isShowAll || e.helper === !0) && (p.points.bones.push(e.bone), p.points.pivots.push(e.pivot), e.type !== 0 && p.lines.bones.push(e.bone), e.excludes && e.excludes.forEach((n) => {
|
|
387
387
|
let i = !1;
|
|
388
|
-
for (let s = 0; s <
|
|
389
|
-
if (
|
|
388
|
+
for (let s = 0; s < p.excludes.bones.length; s++)
|
|
389
|
+
if (p.excludes.bones[s] === n.bone && p.excludes.radii[s] === n.radius && !(p.excludes.deltaLocals[s] === null && n.deltaLocal !== null) && !(p.excludes.deltaLocals[s] !== null && n.deltaLocal === null) && !(p.excludes.deltaLocals[s] !== null && p.excludes.deltaLocals[s].some((o, l) => o !== n.deltaLocal[l]))) {
|
|
390
390
|
i = !0;
|
|
391
391
|
break;
|
|
392
392
|
}
|
|
393
|
-
i || (
|
|
393
|
+
i || (p.excludes.bones.push(n.bone), p.excludes.radii.push(n.radius), p.excludes.deltaLocals.push(n.deltaLocal ? [...n.deltaLocal] : null), p.excludes.objects.push(null));
|
|
394
394
|
}));
|
|
395
|
-
}),
|
|
396
|
-
const i = new
|
|
395
|
+
}), p = this.helpers.excludes, this.opt.isExcludes && p.bones.length && p.bones.forEach((e, n) => {
|
|
396
|
+
const i = new f.SphereGeometry(p.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
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
404
|
+
p.objects[n] = new f.Mesh(i, s), p.objects[n].renderOrder = 997, e.add(p.objects[n]), p.deltaLocals[n] && p.objects[n].position.set(
|
|
405
|
+
p.deltaLocals[n][0],
|
|
406
|
+
p.deltaLocals[n][1],
|
|
407
|
+
p.deltaLocals[n][2]
|
|
408
408
|
);
|
|
409
|
-
}),
|
|
409
|
+
}), p = this.helpers.points, p.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 = p.bones.map((u) => [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 = p.pivots.map((u) => u && 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,40 +420,40 @@ class et {
|
|
|
420
420
|
size: 0.2,
|
|
421
421
|
vertexColors: !0
|
|
422
422
|
});
|
|
423
|
-
|
|
423
|
+
p.object = new f.Points(e, l), p.object.renderOrder = 998, p.object.matrix = this.armature.matrixWorld, p.object.matrixAutoUpdate = !1, this.scene.add(p.object);
|
|
424
424
|
}
|
|
425
|
-
if (
|
|
426
|
-
const e = new
|
|
427
|
-
e.setAttribute("position", new
|
|
428
|
-
const i = new
|
|
429
|
-
e.setAttribute("color", new
|
|
430
|
-
const l = new
|
|
425
|
+
if (p = this.helpers.lines, p.bones.length) {
|
|
426
|
+
const e = new f.BufferGeometry(), n = p.bones.map((u) => [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 = p.bones.map((u) => [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
|
-
|
|
437
|
+
p.object = new f.LineSegments(e, l), p.object.renderOrder = 999, p.object.matrix = this.armature.matrixWorld, p.object.matrixAutoUpdate = !1, this.scene.add(p.object);
|
|
438
438
|
}
|
|
439
439
|
}
|
|
440
440
|
/**
|
|
441
441
|
* Update the positions of dynamic bone helpers.
|
|
442
442
|
*/
|
|
443
443
|
updateHelpers() {
|
|
444
|
-
if (
|
|
444
|
+
if (p = this.helpers.points, p.bones.length) {
|
|
445
445
|
xe.copy(this.armature.matrixWorld).invert();
|
|
446
|
-
const t =
|
|
447
|
-
for (let e = 0, n =
|
|
448
|
-
fe.multiplyMatrices(xe,
|
|
449
|
-
t.needsUpdate = !0,
|
|
446
|
+
const t = p.object.geometry.getAttribute("position");
|
|
447
|
+
for (let e = 0, n = p.bones.length; e < n; e++)
|
|
448
|
+
fe.multiplyMatrices(xe, p.bones[e].matrixWorld), z.setFromMatrixPosition(fe), t.setXYZ(e, z.x, z.y, z.z);
|
|
449
|
+
t.needsUpdate = !0, p.object.updateMatrixWorld();
|
|
450
450
|
}
|
|
451
|
-
if (
|
|
451
|
+
if (p = this.helpers.lines, p.bones.length) {
|
|
452
452
|
xe.copy(this.armature.matrixWorld).invert();
|
|
453
|
-
const t =
|
|
454
|
-
for (let e = 0, n = 0, i =
|
|
455
|
-
fe.multiplyMatrices(xe,
|
|
456
|
-
t.needsUpdate = !0,
|
|
453
|
+
const t = p.object.geometry.getAttribute("position");
|
|
454
|
+
for (let e = 0, n = 0, i = p.bones.length; e < i; e++, n += 2)
|
|
455
|
+
fe.multiplyMatrices(xe, p.bones[e].matrixWorld), z.setFromMatrixPosition(fe), t.setXYZ(n, z.x, z.y, z.z), fe.multiplyMatrices(xe, p.bones[e].parent.matrixWorld), z.setFromMatrixPosition(fe), t.setXYZ(n + 1, z.x, z.y, z.z);
|
|
456
|
+
t.needsUpdate = !0, p.object.updateMatrixWorld();
|
|
457
457
|
}
|
|
458
458
|
}
|
|
459
459
|
/**
|
|
@@ -462,9 +462,9 @@ class et {
|
|
|
462
462
|
hideHelpers() {
|
|
463
463
|
[this.helpers.points, this.helpers.lines].forEach((t) => {
|
|
464
464
|
t.bones = [], t.object && (this.scene.remove(t.object), t.object.geometry.dispose(), t.object.material.dispose(), t.object = null);
|
|
465
|
-
}),
|
|
466
|
-
t && (
|
|
467
|
-
}),
|
|
465
|
+
}), p = this.helpers.excludes, p.objects.forEach((t, e) => {
|
|
466
|
+
t && (p.bones[e].remove(t), t.geometry.dispose(), t.material.dispose());
|
|
467
|
+
}), p.bones = [], p.deltaLocals = [], p.radii = [], p.objects = [], this.helpers.isActive = !1;
|
|
468
468
|
}
|
|
469
469
|
/**
|
|
470
470
|
* Start dynamic bones.
|
|
@@ -608,8 +608,8 @@ class tt {
|
|
|
608
608
|
for (let a = 0; a < i / 2; a++) {
|
|
609
609
|
const c = n[(u + a) * 2], d = n[(u + a) * 2 + 1], g = n[(u + a + i / 2) * 2] * r - n[(u + a + i / 2) * 2 + 1] * h, x = n[(u + a + i / 2) * 2] * h + n[(u + a + i / 2) * 2 + 1] * r;
|
|
610
610
|
n[(u + a) * 2] = c + g, n[(u + a) * 2 + 1] = d + x, n[(u + a + i / 2) * 2] = c - g, n[(u + a + i / 2) * 2 + 1] = d - x;
|
|
611
|
-
const
|
|
612
|
-
r =
|
|
611
|
+
const b = r * o - h * l, I = r * l + h * o;
|
|
612
|
+
r = b, h = I;
|
|
613
613
|
}
|
|
614
614
|
}
|
|
615
615
|
}
|
|
@@ -2629,15 +2629,15 @@ const ct = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
|
|
|
2629
2629
|
fr: rt,
|
|
2630
2630
|
fi: ht,
|
|
2631
2631
|
lt: ct
|
|
2632
|
-
},
|
|
2633
|
-
new
|
|
2634
|
-
new
|
|
2635
|
-
new
|
|
2636
|
-
new
|
|
2637
|
-
const mt = new
|
|
2638
|
-
new
|
|
2639
|
-
new
|
|
2640
|
-
class
|
|
2632
|
+
}, _ = new f.Quaternion(), V = new f.Euler(), Re = new f.Vector3(), ve = 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
|
+
class Ne {
|
|
2641
2641
|
/**
|
|
2642
2642
|
* Avatar.
|
|
2643
2643
|
* @typedef {Object} Avatar
|
|
@@ -2763,7 +2763,7 @@ class Be {
|
|
|
2763
2763
|
avatarOnlyCamera: null,
|
|
2764
2764
|
statsNode: null,
|
|
2765
2765
|
statsStyle: null
|
|
2766
|
-
}, Object.assign(this.opt, e || {}), this.opt.statsNode && (this.stats = new
|
|
2766
|
+
}, Object.assign(this.opt, e || {}), this.opt.statsNode && (this.stats = new qe(), this.opt.statsStyle && (this.stats.dom.style.cssText = this.opt.statsStyle), this.opt.statsNode.appendChild(this.stats.dom)), this.poseTemplates = {
|
|
2767
2767
|
side: {
|
|
2768
2768
|
standing: !0,
|
|
2769
2769
|
props: {
|
|
@@ -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
|
|
4089
|
-
l.compileEquirectangularShader(), this.scene.environment = l.fromScene(new
|
|
4088
|
+
const l = new f.PMREMGenerator(this.renderer);
|
|
4089
|
+
l.compileEquirectangularShader(), this.scene.environment = l.fromScene(new _e()).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, u) => {
|
|
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, u = 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, u) : s[1] === "rotation" ? (n = s[0] + ".quaternion", e[n] = new f.Quaternion().setFromEuler(new f.Euler(o, l, u, "XYZ")).normalize()) : s[1] === "quaternion" && (e[n] = new f.Quaternion(o, l, u, i.w).normalize());
|
|
4198
4198
|
}
|
|
4199
4199
|
return e;
|
|
4200
4200
|
}
|
|
@@ -4226,15 +4226,15 @@ class Be {
|
|
|
4226
4226
|
for (const [r, h] of Object.entries(n))
|
|
4227
4227
|
if (s.morphTargetDictionary.hasOwnProperty(r)) {
|
|
4228
4228
|
const a = s.morphTargetDictionary[r], c = o.morphAttributes.position[a], d = o.morphAttributes.normal?.[a];
|
|
4229
|
-
l || (l = new
|
|
4229
|
+
l || (l = new f.Float32BufferAttribute(c.count * 3, 3), d && (u = new f.Float32BufferAttribute(c.count * 3, 3)));
|
|
4230
4230
|
for (let g = 0; g < c.count; g++) {
|
|
4231
|
-
const x = l.getX(g) + c.getX(g) * h,
|
|
4232
|
-
l.setXYZ(g, x,
|
|
4231
|
+
const x = l.getX(g) + c.getX(g) * h, b = l.getY(g) + c.getY(g) * h, I = l.getZ(g) + c.getZ(g) * h;
|
|
4232
|
+
l.setXYZ(g, x, b, I);
|
|
4233
4233
|
}
|
|
4234
4234
|
if (d)
|
|
4235
4235
|
for (let g = 0; g < c.count; g++) {
|
|
4236
|
-
const x = u.getX(g) + d.getX(g) * h,
|
|
4237
|
-
u.setXYZ(g, x,
|
|
4236
|
+
const x = u.getX(g) + d.getX(g) * h, b = u.getY(g) + d.getY(g) * h, I = u.getZ(g) + d.getZ(g) * h;
|
|
4237
|
+
u.setXYZ(g, x, b, I);
|
|
4238
4238
|
}
|
|
4239
4239
|
}
|
|
4240
4240
|
if (l) {
|
|
@@ -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 u = new
|
|
4317
|
+
const u = new f.Vector3();
|
|
4318
4318
|
this.objectLeftEye.getWorldPosition(u), this.avatarHeight = u.y + 0.2, this.viewName || this.setView(this.opt.cameraView), this.setMood(this.avatar.avatarMood || this.moodName || this.opt.avatarMood), this.avatar.body === "M" && this.poseTemplates.wide && (this.poseName = "wide", this.setPoseFromTemplate(this.poseTemplates.wide, 0), console.log("Set initial male-appropriate pose: wide")), this.initializeFBXAnimationLoader(), this.bodyMovement && this.bodyMovement !== "idle" && this.applyBodyMovementAnimation(), this.start();
|
|
4319
4319
|
}
|
|
4320
4320
|
/**
|
|
@@ -4358,14 +4358,14 @@ class Be {
|
|
|
4358
4358
|
default:
|
|
4359
4359
|
a += 12, h = h * a;
|
|
4360
4360
|
}
|
|
4361
|
-
r = r * a, this.controlsEnd = new
|
|
4361
|
+
r = r * a, this.controlsEnd = new f.Vector3(r, h, 0), this.cameraEnd = new f.Vector3(r, h, a).applyEuler(new f.Euler(o, l, 0)), this.cameraClock === null && (this.controls.target.copy(this.controlsEnd), this.camera.position.copy(this.cameraEnd)), this.controlsStart = this.controls.target.clone(), this.cameraStart = this.camera.position.clone(), this.cameraClock = 0;
|
|
4362
4362
|
}
|
|
4363
4363
|
/**
|
|
4364
4364
|
* Change light colors and intensities.
|
|
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.
|
|
@@ -4400,7 +4400,7 @@ class Be {
|
|
|
4400
4400
|
if (e.x === 0 && e.y === 0 && e.z === 0) continue;
|
|
4401
4401
|
V.set(e.x, e.y, e.z);
|
|
4402
4402
|
const n = this.poseAvatar.props[t];
|
|
4403
|
-
n.isQuaternion ? (
|
|
4403
|
+
n.isQuaternion ? (_.setFromEuler(V), n.multiply(_)) : n.isVector3 && n.add(V);
|
|
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], u = i[1].isQuaternion ? new
|
|
4483
|
+
const l = o[1] === "quaternion" ? o[0] + ".rotation" : i[0], u = i[1].isQuaternion ? new f.Euler().setFromQuaternion(i[1]) : i[1];
|
|
4484
4484
|
n += (s ? ", " : "") + "'" + l + "':{", n += "x:" + Math.round(u.x * e) / e, n += ", y:" + Math.round(u.y * e) / e, n += ", z:" + Math.round(u.z * e) / e, n += "}";
|
|
4485
4485
|
}
|
|
4486
4486
|
}), n += "}", n;
|
|
@@ -5108,8 +5108,8 @@ class Be {
|
|
|
5108
5108
|
else {
|
|
5109
5109
|
g.newvalue = d[i + 1];
|
|
5110
5110
|
const x = a.ts[i + 1] - a.ts[i];
|
|
5111
|
-
let
|
|
5112
|
-
x > 1e-4 && (
|
|
5111
|
+
let b = 1;
|
|
5112
|
+
x > 1e-4 && (b = (this.animClock - a.ts[i]) / x), b < 1 && (g.easing && (b = g.easing(b)), g.newvalue = (1 - b) * d[i] + b * 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
5115
|
switch (c) {
|
|
@@ -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,7 +5169,7 @@ 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
5175
|
if ((u || r) && (V.setFromQuaternion(this.poseAvatar.props["Head.quaternion"]), V.x = Math.max(-0.9, Math.min(0.9, 2 * V.x - 0.5)), V.y = Math.max(-0.9, Math.min(0.9, -2.5 * V.y)), u ? (Object.assign(this.mtAvatar.eyesLookDown, { system: V.x < 0 ? -V.x : 0, needsUpdate: !0 }), Object.assign(this.mtAvatar.eyesLookUp, { system: V.x < 0 ? 0 : V.x, needsUpdate: !0 }), Object.assign(this.mtAvatar.eyeLookInLeft, { system: V.y < 0 ? -V.y : 0, needsUpdate: !0 }), Object.assign(this.mtAvatar.eyeLookOutLeft, { system: V.y < 0 ? 0 : V.y, needsUpdate: !0 }), Object.assign(this.mtAvatar.eyeLookInRight, { system: V.y < 0 ? 0 : V.y, needsUpdate: !0 }), Object.assign(this.mtAvatar.eyeLookOutRight, { system: V.y < 0 ? -V.y : 0, needsUpdate: !0 }), r && (n = -this.mtAvatar.bodyRotateY.value, i = this.gaussianRandom(-0.2, 0.2), this.animQueue.push(this.animFactory({
|
|
@@ -5193,12 +5193,12 @@ 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) && u ? l > this.volumeMax ? (this.volumeHeadBase = 0.05, Math.random() > 0.6 && (this.volumeHeadTarget = -0.05 - Math.random() / 15), this.volumeMax = l) : (this.volumeMax *= 0.92, this.volumeHeadTarget = this.volumeHeadBase - 0.9 * (this.volumeHeadBase - this.volumeHeadTarget)) : (this.volumeHeadTarget = 0, this.volumeMax = 0), n = this.volumeHeadTarget - this.volumeHeadCurrent, i = Math.abs(n), i > 1e-4 && (o = i * (this.volumeHeadEasing(Math.min(1, this.volumeHeadVelocity * e / 1e3 / i) / 2 + 0.5) - 0.5), this.volumeHeadCurrent += Math.sign(n) * Math.min(i, o)), Math.abs(this.volumeHeadCurrent) > 1e-4 && (
|
|
5196
|
+
})))), e > 2 * this.animFrameDur && (e = 2 * this.animFrameDur), (this.viewName !== "full" || this.isAvatarOnly) && (n = this.mtRandomized[Math.floor(Math.random() * this.mtRandomized.length)], i = this.mtAvatar[n], i.needsUpdate || Object.assign(i, { base: (this.mood.baseline[n] || 0) + (1 + l / 255) * Math.random() / 5, needsUpdate: !0 })), this.updatePoseBase(this.animClock), this.mixer && this.mixer.update(e / 1e3 * this.mixer.timeScale), this.updatePoseDelta(), (this.isSpeaking || this.isListening) && u ? l > this.volumeMax ? (this.volumeHeadBase = 0.05, Math.random() > 0.6 && (this.volumeHeadTarget = -0.05 - Math.random() / 15), this.volumeMax = l) : (this.volumeMax *= 0.92, this.volumeHeadTarget = this.volumeHeadBase - 0.9 * (this.volumeHeadBase - this.volumeHeadTarget)) : (this.volumeHeadTarget = 0, this.volumeMax = 0), n = this.volumeHeadTarget - this.volumeHeadCurrent, i = Math.abs(n), i > 1e-4 && (o = i * (this.volumeHeadEasing(Math.min(1, this.volumeHeadVelocity * e / 1e3 / i) / 2 + 0.5) - 0.5), this.volumeHeadCurrent += Math.sign(n) * Math.min(i, o)), Math.abs(this.volumeHeadCurrent) > 1e-4 && (_.setFromAxisAngle(mt, this.volumeHeadCurrent), this.objectNeck.quaternion.multiply(_)), We.setFromObject(this.armature), this.objectLeftToeBase.getWorldPosition(Re), Re.sub(this.armature.position), this.objectRightToeBase.getWorldPosition(ve), ve.sub(this.armature.position), this.objectHips.position.y -= We.min.y / 2, this.objectHips.position.x -= (Re.x + ve.x) / 4, this.objectHips.position.z -= (Re.z + ve.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
|
|
5201
|
+
let a = new f.Spherical().setFromVector3(this.cameraStart), c = new f.Spherical().setFromVector3(this.cameraEnd);
|
|
5202
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();
|
|
@@ -5262,12 +5262,12 @@ class Be {
|
|
|
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, u = /[\p{Extended_Pictographic}]/ug, r = e.lipsyncLang || this.avatar.lipsyncLang || this.opt.lipsyncLang;
|
|
5264
5264
|
let h = "", a = "", c = 0, d = [], g = [];
|
|
5265
|
-
const x = Array.from(this.segmenter.segment(t), (
|
|
5266
|
-
for (let
|
|
5267
|
-
const
|
|
5268
|
-
let
|
|
5269
|
-
const
|
|
5270
|
-
if (
|
|
5265
|
+
const x = Array.from(this.segmenter.segment(t), (b) => b.segment);
|
|
5266
|
+
for (let b = 0; b < x.length; b++) {
|
|
5267
|
+
const I = b === x.length - 1, H = x[b].match(l);
|
|
5268
|
+
let m = x[b].match(s);
|
|
5269
|
+
const T = x[b].match(u), k = x[b].match(o);
|
|
5270
|
+
if (m && !I && !T && x[b + 1].match(s) && (m = !1), n && (h += x[b]), H && (!i || i.every((y) => b < y[0] || b > y[1])) && (a += x[b]), (k || m || I) && (a.length && (a = this.lipsyncPreProcessText(a, r), a.length && d.push({
|
|
5271
5271
|
mark: c,
|
|
5272
5272
|
word: a
|
|
5273
5273
|
})), h.length && (g.push({
|
|
@@ -5280,28 +5280,28 @@ class Be {
|
|
|
5280
5280
|
}), h = ""), a.length)) {
|
|
5281
5281
|
const y = this.lipsyncWordsToVisemes(a, r);
|
|
5282
5282
|
if (y && y.visemes && y.visemes.length) {
|
|
5283
|
-
const
|
|
5284
|
-
for (let
|
|
5283
|
+
const M = y.times[y.visemes.length - 1] + y.durations[y.visemes.length - 1];
|
|
5284
|
+
for (let P = 0; P < y.visemes.length; P++)
|
|
5285
5285
|
g.push({
|
|
5286
5286
|
mark: c,
|
|
5287
5287
|
template: { name: "viseme" },
|
|
5288
|
-
ts: [(y.times[
|
|
5288
|
+
ts: [(y.times[P] - 0.6) / M, (y.times[P] + 0.5) / M, (y.times[P] + y.durations[P] + 0.5) / M],
|
|
5289
5289
|
vs: {
|
|
5290
|
-
["viseme_" + y.visemes[
|
|
5290
|
+
["viseme_" + y.visemes[P]]: [null, y.visemes[P] === "PP" || y.visemes[P] === "FF" ? 0.9 : 0.6, 0]
|
|
5291
5291
|
}
|
|
5292
5292
|
});
|
|
5293
5293
|
}
|
|
5294
5294
|
a = "", c++;
|
|
5295
5295
|
}
|
|
5296
|
-
if (
|
|
5297
|
-
if (d.length ||
|
|
5296
|
+
if (m || I) {
|
|
5297
|
+
if (d.length || I && g.length) {
|
|
5298
5298
|
const y = {
|
|
5299
5299
|
anim: g
|
|
5300
5300
|
};
|
|
5301
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 y = this.animEmojis[x[
|
|
5303
|
+
if (T) {
|
|
5304
|
+
let y = this.animEmojis[x[b]];
|
|
5305
5305
|
y && y.link && (y = this.animEmojis[y.link]), y && this.speechQueue.push({ emoji: y });
|
|
5306
5306
|
}
|
|
5307
5307
|
this.speechQueue.push({ break: 100 });
|
|
@@ -5397,13 +5397,13 @@ class Be {
|
|
|
5397
5397
|
const d = c.times[c.visemes.length - 1] + c.durations[c.visemes.length - 1], g = Math.min(h, Math.max(0, h - c.visemes.length * 150));
|
|
5398
5398
|
let x = 0.6 + this.convertRange(g, [0, h], [0, 0.4]);
|
|
5399
5399
|
if (h = Math.min(h, c.visemes.length * 200), d > 0)
|
|
5400
|
-
for (let
|
|
5401
|
-
const
|
|
5400
|
+
for (let b = 0; b < c.visemes.length; b++) {
|
|
5401
|
+
const I = r + c.times[b] / d * h, H = c.durations[b] / d * h;
|
|
5402
5402
|
o.push({
|
|
5403
5403
|
template: { name: "viseme" },
|
|
5404
|
-
ts: [
|
|
5404
|
+
ts: [I - Math.min(60, 2 * H / 3), I + Math.min(25, H / 2), I + H + Math.min(60, H / 2)],
|
|
5405
5405
|
vs: {
|
|
5406
|
-
["viseme_" + c.visemes[
|
|
5406
|
+
["viseme_" + c.visemes[b]]: [null, c.visemes[b] === "PP" || c.visemes[b] === "FF" ? 0.9 : x, 0]
|
|
5407
5407
|
}
|
|
5408
5408
|
});
|
|
5409
5409
|
}
|
|
@@ -5479,41 +5479,41 @@ class Be {
|
|
|
5479
5479
|
*/
|
|
5480
5480
|
async synthesizeWithBrowserTTS(t) {
|
|
5481
5481
|
return new Promise((e, n) => {
|
|
5482
|
-
const i = t.text.map((
|
|
5482
|
+
const i = t.text.map((m) => m.word).join(" "), s = new SpeechSynthesisUtterance(i), o = t.lang || this.avatar.ttsLang || this.opt.ttsLang || "en-US", l = (t.rate || this.avatar.ttsRate || this.opt.ttsRate || 1) + this.mood.speech.deltaRate, u = (t.pitch || this.avatar.ttsPitch || this.opt.ttsPitch || 1) + this.mood.speech.deltaPitch, r = (t.volume || this.avatar.ttsVolume || this.opt.ttsVolume || 1) + this.mood.speech.deltaVolume;
|
|
5483
5483
|
s.lang = o, s.rate = Math.max(0.1, Math.min(10, l)), s.pitch = Math.max(0, Math.min(2, u)), s.volume = Math.max(0, Math.min(1, r));
|
|
5484
5484
|
const h = speechSynthesis.getVoices(), a = t.voice || this.avatar.ttsVoice || this.opt.ttsVoice;
|
|
5485
5485
|
if (a && h.length > 0) {
|
|
5486
|
-
const
|
|
5487
|
-
|
|
5486
|
+
const m = h.find((T) => T.name.includes(a) || T.lang === o);
|
|
5487
|
+
m && (s.voice = m);
|
|
5488
5488
|
}
|
|
5489
|
-
const c = i.length * 100 / s.rate, d = this.audioCtx.createBuffer(1, this.audioCtx.sampleRate * (c / 1e3), this.audioCtx.sampleRate), g = this.avatar.lipsyncLang || this.opt.lipsyncLang || "en", x = this.lipsyncPreProcessText(i, g),
|
|
5489
|
+
const c = i.length * 100 / s.rate, d = this.audioCtx.createBuffer(1, this.audioCtx.sampleRate * (c / 1e3), this.audioCtx.sampleRate), g = this.avatar.lipsyncLang || this.opt.lipsyncLang || "en", x = this.lipsyncPreProcessText(i, g), b = this.lipsyncWordsToVisemes(x, g);
|
|
5490
5490
|
console.log("Browser TTS Lip-sync Debug:", {
|
|
5491
5491
|
text: i,
|
|
5492
5492
|
lipsyncLang: g,
|
|
5493
5493
|
processedText: x,
|
|
5494
|
-
lipsyncData:
|
|
5495
|
-
hasVisemes:
|
|
5494
|
+
lipsyncData: b,
|
|
5495
|
+
hasVisemes: b && b.visemes && b.visemes.length > 0,
|
|
5496
5496
|
estimatedDuration: c
|
|
5497
5497
|
});
|
|
5498
|
-
const
|
|
5499
|
-
if (
|
|
5500
|
-
const
|
|
5501
|
-
for (let
|
|
5502
|
-
const k =
|
|
5503
|
-
|
|
5498
|
+
const I = [];
|
|
5499
|
+
if (b && b.visemes && b.visemes.length > 0) {
|
|
5500
|
+
const m = b.times[b.visemes.length - 1] + b.durations[b.visemes.length - 1];
|
|
5501
|
+
for (let T = 0; T < b.visemes.length; T++) {
|
|
5502
|
+
const k = b.visemes[T], y = b.times[T] / m, M = b.durations[T] / m, P = y * c, D = M * c;
|
|
5503
|
+
I.push({
|
|
5504
5504
|
template: { name: "viseme" },
|
|
5505
|
-
ts: [
|
|
5505
|
+
ts: [P - Math.min(60, 2 * D / 3), P + Math.min(25, D / 2), P + D + Math.min(60, D / 2)],
|
|
5506
5506
|
vs: {
|
|
5507
5507
|
["viseme_" + k]: [null, k === "PP" || k === "FF" ? 0.9 : 0.6, 0]
|
|
5508
5508
|
}
|
|
5509
5509
|
});
|
|
5510
5510
|
}
|
|
5511
5511
|
}
|
|
5512
|
-
const
|
|
5513
|
-
this.audioPlaylist.push({ anim:
|
|
5512
|
+
const H = [...t.anim, ...I];
|
|
5513
|
+
this.audioPlaylist.push({ anim: H, audio: d }), this.onSubtitles = t.onSubtitles || null, this.resetLips(), t.mood && this.setMood(t.mood), this.playAudio(), s.onend = () => {
|
|
5514
5514
|
e();
|
|
5515
|
-
}, s.onerror = (
|
|
5516
|
-
console.error("Speech synthesis error:",
|
|
5515
|
+
}, s.onerror = (m) => {
|
|
5516
|
+
console.error("Speech synthesis error:", m.error), n(m.error);
|
|
5517
5517
|
}, speechSynthesis.speak(s);
|
|
5518
5518
|
});
|
|
5519
5519
|
}
|
|
@@ -5576,15 +5576,15 @@ class Be {
|
|
|
5576
5576
|
console.error("Text-based lip-sync failed, using fallback:", c);
|
|
5577
5577
|
const d = e.toLowerCase().split(/\s+/), g = [];
|
|
5578
5578
|
for (const x of d)
|
|
5579
|
-
for (const
|
|
5580
|
-
let
|
|
5581
|
-
"aeiou".includes(
|
|
5579
|
+
for (const b of x) {
|
|
5580
|
+
let I = "aa";
|
|
5581
|
+
"aeiou".includes(b) ? I = "aa" : "bp".includes(b) ? I = "PP" : "fv".includes(b) ? I = "FF" : "st".includes(b) ? I = "SS" : "dln".includes(b) ? I = "DD" : "kg".includes(b) ? I = "kk" : "rw".includes(b) && (I = "RR"), g.push(I);
|
|
5582
5582
|
}
|
|
5583
5583
|
r = {
|
|
5584
|
-
visemes: g.map((x,
|
|
5584
|
+
visemes: g.map((x, b) => ({
|
|
5585
5585
|
viseme: x,
|
|
5586
|
-
startTime:
|
|
5587
|
-
endTime: (
|
|
5586
|
+
startTime: b * l.duration / g.length,
|
|
5587
|
+
endTime: (b + 1) * l.duration / g.length,
|
|
5588
5588
|
duration: l.duration / g.length,
|
|
5589
5589
|
intensity: 0.6
|
|
5590
5590
|
})),
|
|
@@ -5609,12 +5609,12 @@ class Be {
|
|
|
5609
5609
|
if (r.visemes && r.visemes.length > 0) {
|
|
5610
5610
|
console.log("ElevenLabs: Generating lip-sync animation from", r.visemes.length, "visemes");
|
|
5611
5611
|
for (let c = 0; c < r.visemes.length; c++) {
|
|
5612
|
-
const d = r.visemes[c], g = d.startTime * 1e3, x = d.duration * 1e3,
|
|
5612
|
+
const d = r.visemes[c], g = d.startTime * 1e3, x = d.duration * 1e3, b = d.intensity;
|
|
5613
5613
|
h.push({
|
|
5614
5614
|
template: { name: "viseme" },
|
|
5615
5615
|
ts: [g - Math.min(60, 2 * x / 3), g + Math.min(25, x / 2), g + x + Math.min(60, x / 2)],
|
|
5616
5616
|
vs: {
|
|
5617
|
-
["viseme_" + d.viseme]: [null,
|
|
5617
|
+
["viseme_" + d.viseme]: [null, b, 0]
|
|
5618
5618
|
}
|
|
5619
5619
|
});
|
|
5620
5620
|
}
|
|
@@ -5674,15 +5674,15 @@ class Be {
|
|
|
5674
5674
|
console.error("Text-based lip-sync failed, using fallback:", c);
|
|
5675
5675
|
const d = e.toLowerCase().split(/\s+/), g = [];
|
|
5676
5676
|
for (const x of d)
|
|
5677
|
-
for (const
|
|
5678
|
-
let
|
|
5679
|
-
"aeiou".includes(
|
|
5677
|
+
for (const b of x) {
|
|
5678
|
+
let I = "aa";
|
|
5679
|
+
"aeiou".includes(b) ? I = "aa" : "bp".includes(b) ? I = "PP" : "fv".includes(b) ? I = "FF" : "st".includes(b) ? I = "SS" : "dln".includes(b) ? I = "DD" : "kg".includes(b) ? I = "kk" : "rw".includes(b) && (I = "RR"), g.push(I);
|
|
5680
5680
|
}
|
|
5681
5681
|
r = {
|
|
5682
|
-
visemes: g.map((x,
|
|
5682
|
+
visemes: g.map((x, b) => ({
|
|
5683
5683
|
viseme: x,
|
|
5684
|
-
startTime:
|
|
5685
|
-
endTime: (
|
|
5684
|
+
startTime: b * l.duration / g.length,
|
|
5685
|
+
endTime: (b + 1) * l.duration / g.length,
|
|
5686
5686
|
duration: l.duration / g.length,
|
|
5687
5687
|
intensity: 0.6
|
|
5688
5688
|
})),
|
|
@@ -5707,12 +5707,12 @@ class Be {
|
|
|
5707
5707
|
if (r.visemes && r.visemes.length > 0) {
|
|
5708
5708
|
console.log("Deepgram: Generating lip-sync animation from", r.visemes.length, "visemes");
|
|
5709
5709
|
for (let c = 0; c < r.visemes.length; c++) {
|
|
5710
|
-
const d = r.visemes[c], g = d.startTime * 1e3, x = d.duration * 1e3,
|
|
5710
|
+
const d = r.visemes[c], g = d.startTime * 1e3, x = d.duration * 1e3, b = d.intensity;
|
|
5711
5711
|
h.push({
|
|
5712
5712
|
template: { name: "viseme" },
|
|
5713
5713
|
ts: [g - Math.min(60, 2 * x / 3), g + Math.min(25, x / 2), g + x + Math.min(60, x / 2)],
|
|
5714
5714
|
vs: {
|
|
5715
|
-
["viseme_" + d.viseme]: [null,
|
|
5715
|
+
["viseme_" + d.viseme]: [null, b, 0]
|
|
5716
5716
|
}
|
|
5717
5717
|
});
|
|
5718
5718
|
}
|
|
@@ -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), Re.setFromMatrixPosition(this.speakTo.objectLeftEye.matrixWorld), ve.setFromMatrixPosition(this.speakTo.objectRightEye.matrixWorld), e.addVectors(Re, ve).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,16 +6159,16 @@ class Be {
|
|
|
6159
6159
|
this.lookAt(null, null, t);
|
|
6160
6160
|
return;
|
|
6161
6161
|
}
|
|
6162
|
-
this.objectLeftEye.updateMatrixWorld(!0), this.objectRightEye.updateMatrixWorld(!0),
|
|
6163
|
-
const n = new
|
|
6162
|
+
this.objectLeftEye.updateMatrixWorld(!0), this.objectRightEye.updateMatrixWorld(!0), Re.setFromMatrixPosition(this.objectLeftEye.matrixWorld), ve.setFromMatrixPosition(this.objectRightEye.matrixWorld), Re.add(ve).divideScalar(2), _.copy(this.armature.quaternion), _.multiply(this.poseTarget.props["Hips.quaternion"]), _.multiply(this.poseTarget.props["Spine.quaternion"]), _.multiply(this.poseTarget.props["Spine1.quaternion"]), _.multiply(this.poseTarget.props["Spine2.quaternion"]), _.multiply(this.poseTarget.props["Neck.quaternion"]), _.multiply(this.poseTarget.props["Head.quaternion"]);
|
|
6163
|
+
const n = new f.Vector3().subVectors(e, Re).normalize(), i = Math.atan2(n.x, n.z), s = Math.asin(-n.y);
|
|
6164
6164
|
V.set(s, i, 0, "YXZ");
|
|
6165
|
-
const l = new
|
|
6165
|
+
const l = new f.Quaternion().setFromEuler(V), u = new f.Quaternion().copy(l).multiply(_.clone().invert());
|
|
6166
6166
|
V.setFromQuaternion(u, "YXZ");
|
|
6167
6167
|
let r = V.x / (40 / 24) + 0.2, h = V.y / (9 / 4), a = Math.min(0.6, Math.max(-0.3, r)), c = Math.min(0.8, Math.max(-0.8, h)), d = (Math.random() - 0.5) / 4, g = (Math.random() - 0.5) / 4;
|
|
6168
6168
|
if (t) {
|
|
6169
|
-
let x = this.animQueue.findIndex((
|
|
6169
|
+
let x = this.animQueue.findIndex((I) => I.template.name === "lookat");
|
|
6170
6170
|
x !== -1 && this.animQueue.splice(x, 1);
|
|
6171
|
-
const
|
|
6171
|
+
const b = {
|
|
6172
6172
|
name: "lookat",
|
|
6173
6173
|
dt: [750, t],
|
|
6174
6174
|
vs: {
|
|
@@ -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(b));
|
|
6187
6187
|
}
|
|
6188
6188
|
}
|
|
6189
6189
|
/**
|
|
@@ -6196,24 +6196,24 @@ 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 u = (l.x + 1) / 2 * i.width + i.left, r = -(l.y - 1) / 2 * i.height + i.top;
|
|
6202
|
-
t === null && (t = u), e === null && (e = r),
|
|
6203
|
-
let h = V.x / (40 / 24), a = V.y / (9 / 4), c = Math.min(0.4, Math.max(-0.4, this.camera.rotation.x)), d = Math.min(0.4, Math.max(-0.4, this.camera.rotation.y)), g = Math.max(window.innerWidth - u, u), x = Math.max(window.innerHeight - r, r),
|
|
6204
|
-
|
|
6205
|
-
let
|
|
6202
|
+
t === null && (t = u), e === null && (e = r), _.copy(this.armature.quaternion), _.multiply(this.poseTarget.props["Hips.quaternion"]), _.multiply(this.poseTarget.props["Spine.quaternion"]), _.multiply(this.poseTarget.props["Spine1.quaternion"]), _.multiply(this.poseTarget.props["Spine2.quaternion"]), _.multiply(this.poseTarget.props["Neck.quaternion"]), _.multiply(this.poseTarget.props["Head.quaternion"]), V.setFromQuaternion(_);
|
|
6203
|
+
let h = V.x / (40 / 24), a = V.y / (9 / 4), c = Math.min(0.4, Math.max(-0.4, this.camera.rotation.x)), d = Math.min(0.4, Math.max(-0.4, this.camera.rotation.y)), g = Math.max(window.innerWidth - u, u), x = Math.max(window.innerHeight - r, r), b = this.convertRange(e, [r - x, r + x], [-0.3, 0.6]) - h + c, I = this.convertRange(t, [u - g, u + g], [-0.8, 0.8]) - a + d;
|
|
6204
|
+
b = Math.min(0.6, Math.max(-0.3, b)), I = Math.min(0.8, Math.max(-0.8, I));
|
|
6205
|
+
let H = (Math.random() - 0.5) / 4, m = (Math.random() - 0.5) / 4;
|
|
6206
6206
|
if (n) {
|
|
6207
|
-
let
|
|
6208
|
-
|
|
6207
|
+
let T = this.animQueue.findIndex((y) => y.template.name === "lookat");
|
|
6208
|
+
T !== -1 && this.animQueue.splice(T, 1);
|
|
6209
6209
|
const k = {
|
|
6210
6210
|
name: "lookat",
|
|
6211
6211
|
dt: [750, n],
|
|
6212
6212
|
vs: {
|
|
6213
|
-
bodyRotateX: [
|
|
6214
|
-
bodyRotateY: [
|
|
6215
|
-
eyesRotateX: [-3 *
|
|
6216
|
-
eyesRotateY: [-5 *
|
|
6213
|
+
bodyRotateX: [b + H],
|
|
6214
|
+
bodyRotateY: [I + m],
|
|
6215
|
+
eyesRotateX: [-3 * H + 0.1],
|
|
6216
|
+
eyesRotateY: [-5 * m],
|
|
6217
6217
|
browInnerUp: [[0, 0.7]],
|
|
6218
6218
|
mouthLeft: [[0, 0.7]],
|
|
6219
6219
|
mouthRight: [[0, 0.7]],
|
|
@@ -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, u = new
|
|
6242
|
+
const l = o[0].point, u = new f.Vector3(), r = new f.Vector3();
|
|
6243
6243
|
this.objectLeftArm.getWorldPosition(u), this.objectRightArm.getWorldPosition(r);
|
|
6244
6244
|
const h = u.distanceToSquared(l), a = r.distanceToSquared(l);
|
|
6245
6245
|
h < 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) => {
|
|
@@ -6421,11 +6421,22 @@ class Be {
|
|
|
6421
6421
|
Spine01: "Spine1",
|
|
6422
6422
|
Spine02: "Spine2",
|
|
6423
6423
|
Spine03: "Spine2",
|
|
6424
|
+
Spine1: "Spine1",
|
|
6425
|
+
Spine2: "Spine2",
|
|
6426
|
+
Spine: "Spine1",
|
|
6427
|
+
// Head and neck
|
|
6428
|
+
Head: "Head",
|
|
6429
|
+
Neck: "Neck",
|
|
6430
|
+
Neck1: "Neck",
|
|
6431
|
+
Neck2: "Neck",
|
|
6424
6432
|
// Left arm mapping
|
|
6425
6433
|
L_Upperarm: "LeftArm",
|
|
6426
6434
|
L_Forearm: "LeftForeArm",
|
|
6427
6435
|
L_Hand: "LeftHand",
|
|
6428
6436
|
L_Shoulder: "LeftShoulder",
|
|
6437
|
+
L_Clavicle: "LeftShoulder",
|
|
6438
|
+
L_UpperArm: "LeftArm",
|
|
6439
|
+
L_ForeArm: "LeftForeArm",
|
|
6429
6440
|
L_Index1: "LeftHandIndex1",
|
|
6430
6441
|
L_Index2: "LeftHandIndex2",
|
|
6431
6442
|
L_Index3: "LeftHandIndex3",
|
|
@@ -6449,6 +6460,9 @@ class Be {
|
|
|
6449
6460
|
R_Forearm: "RightForeArm",
|
|
6450
6461
|
R_Hand: "RightHand",
|
|
6451
6462
|
R_Shoulder: "RightShoulder",
|
|
6463
|
+
R_Clavicle: "RightShoulder",
|
|
6464
|
+
R_UpperArm: "RightArm",
|
|
6465
|
+
R_ForeArm: "RightForeArm",
|
|
6452
6466
|
R_Index1: "RightHandIndex1",
|
|
6453
6467
|
R_Index2: "RightHandIndex2",
|
|
6454
6468
|
R_Index3: "RightHandIndex3",
|
|
@@ -6471,9 +6485,17 @@ class Be {
|
|
|
6471
6485
|
L_Thigh: "LeftUpLeg",
|
|
6472
6486
|
L_Calf: "LeftLeg",
|
|
6473
6487
|
L_Foot: "LeftFoot",
|
|
6488
|
+
L_UpLeg: "LeftUpLeg",
|
|
6489
|
+
L_Leg: "LeftLeg",
|
|
6474
6490
|
R_Thigh: "RightUpLeg",
|
|
6475
6491
|
R_Calf: "RightLeg",
|
|
6476
|
-
R_Foot: "RightFoot"
|
|
6492
|
+
R_Foot: "RightFoot",
|
|
6493
|
+
R_UpLeg: "RightUpLeg",
|
|
6494
|
+
R_Leg: "RightLeg",
|
|
6495
|
+
// Root/Hips
|
|
6496
|
+
Hips: "Hips",
|
|
6497
|
+
Root: "Hips",
|
|
6498
|
+
Pelvis: "Hips"
|
|
6477
6499
|
};
|
|
6478
6500
|
if (i[n]) {
|
|
6479
6501
|
const a = i[n];
|
|
@@ -6529,9 +6551,37 @@ class Be {
|
|
|
6529
6551
|
if (e.has(c))
|
|
6530
6552
|
return c;
|
|
6531
6553
|
}
|
|
6554
|
+
if (s.match(/^[rl]_clavicle/)) {
|
|
6555
|
+
const c = `${s.startsWith("r") ? "Right" : "Left"}Shoulder`;
|
|
6556
|
+
if (e.has(c))
|
|
6557
|
+
return c;
|
|
6558
|
+
}
|
|
6559
|
+
if (s.match(/^[rl]_shoulder/)) {
|
|
6560
|
+
const c = `${s.startsWith("r") ? "Right" : "Left"}Shoulder`;
|
|
6561
|
+
if (e.has(c))
|
|
6562
|
+
return c;
|
|
6563
|
+
}
|
|
6564
|
+
if (s.match(/^spine0?(\d+)$/)) {
|
|
6565
|
+
const a = s.match(/^spine0?(\d+)$/)[1];
|
|
6566
|
+
if (a === "1") {
|
|
6567
|
+
if (e.has("Spine1")) return "Spine1";
|
|
6568
|
+
} else if ((a === "2" || a === "3") && e.has("Spine2"))
|
|
6569
|
+
return "Spine2";
|
|
6570
|
+
}
|
|
6571
|
+
if (s.match(/^neck\d*$/) && e.has("Neck"))
|
|
6572
|
+
return "Neck";
|
|
6573
|
+
if (s === "head" && e.has("Head"))
|
|
6574
|
+
return "Head";
|
|
6575
|
+
if (s.match(/^(hips|pelvis|root)$/) && e.has("Hips"))
|
|
6576
|
+
return "Hips";
|
|
6532
6577
|
for (const a of e)
|
|
6533
6578
|
if (a.toLowerCase() === s)
|
|
6534
6579
|
return a;
|
|
6580
|
+
for (const a of e) {
|
|
6581
|
+
const c = a.toLowerCase();
|
|
6582
|
+
if ((c.includes(s) || s.includes(c)) && (c === s || c.replace(/[^a-z0-9]/g, "") === s.replace(/[^a-z0-9]/g, "")))
|
|
6583
|
+
return a;
|
|
6584
|
+
}
|
|
6535
6585
|
return null;
|
|
6536
6586
|
}
|
|
6537
6587
|
/**
|
|
@@ -6542,51 +6592,65 @@ class Be {
|
|
|
6542
6592
|
* @returns {THREE.AnimationClip} Filtered animation clip with mapped bone names
|
|
6543
6593
|
*/
|
|
6544
6594
|
filterAnimationTracks(t, e) {
|
|
6545
|
-
const n = [], i = /* @__PURE__ */ new Set(), s = /* @__PURE__ */ new Map();
|
|
6546
|
-
|
|
6547
|
-
|
|
6548
|
-
|
|
6549
|
-
|
|
6550
|
-
|
|
6551
|
-
|
|
6552
|
-
|
|
6553
|
-
|
|
6554
|
-
c
|
|
6555
|
-
|
|
6556
|
-
|
|
6557
|
-
|
|
6558
|
-
|
|
6559
|
-
|
|
6560
|
-
|
|
6561
|
-
|
|
6562
|
-
|
|
6563
|
-
|
|
6564
|
-
|
|
6565
|
-
|
|
6595
|
+
const n = [], i = /* @__PURE__ */ new Set(), s = /* @__PURE__ */ new Map(), o = /* @__PURE__ */ new Set();
|
|
6596
|
+
this._loggedAvailableBones || (console.log("Available avatar bones:", Array.from(e).sort().join(", ")), this._loggedAvailableBones = !0), t.tracks.forEach((u) => {
|
|
6597
|
+
const h = u.name.split(".")[0];
|
|
6598
|
+
o.add(h);
|
|
6599
|
+
}), console.log(`
|
|
6600
|
+
=== FBX Animation "${t.name}" Bone Analysis ===`), console.log("FBX bone names in animation:", Array.from(o).sort().join(", ")), console.log(`Total FBX bones: ${o.size}, Avatar bones: ${e.size}
|
|
6601
|
+
`), t.tracks.forEach((u) => {
|
|
6602
|
+
const r = u.name.split("."), h = r[0], a = r[1], c = this.mapBoneName(h, e);
|
|
6603
|
+
if (c) {
|
|
6604
|
+
const d = `${c}.${a}`, g = u.clone();
|
|
6605
|
+
g.name = d;
|
|
6606
|
+
const x = c.includes("Arm") || c.includes("Hand") || c.includes("Shoulder"), b = c.includes("ForeArm");
|
|
6607
|
+
if (x && (a === "quaternion" || a === "rotation")) {
|
|
6608
|
+
if (a === "quaternion" && g.values && g.values.length >= 4) {
|
|
6609
|
+
const I = g.times.length;
|
|
6610
|
+
for (let H = 0; H < I; H++) {
|
|
6611
|
+
const m = H * 4;
|
|
6612
|
+
if (m + 3 < g.values.length) {
|
|
6613
|
+
let T = g.values[m], k = g.values[m + 1], y = g.values[m + 2], M = g.values[m + 3];
|
|
6614
|
+
if (b || c.includes("Hand")) {
|
|
6615
|
+
const P = Math.PI, D = Math.cos(P / 2), J = Math.sin(P / 2), S = D * M - J * T, G = D * T + J * M, Q = D * k - J * y, Z = D * y + J * k;
|
|
6616
|
+
T = G, k = Q, y = Z, M = S;
|
|
6566
6617
|
}
|
|
6567
|
-
|
|
6618
|
+
g.values[m] = T, g.values[m + 1] = k, g.values[m + 2] = y, g.values[m + 3] = M;
|
|
6568
6619
|
}
|
|
6569
6620
|
}
|
|
6570
|
-
} else if (
|
|
6571
|
-
const
|
|
6572
|
-
for (let
|
|
6573
|
-
const
|
|
6574
|
-
|
|
6621
|
+
} else if (a === "rotation" && g.values && g.values.length >= 3) {
|
|
6622
|
+
const I = g.times.length;
|
|
6623
|
+
for (let H = 0; H < I; H++) {
|
|
6624
|
+
const m = H * 3;
|
|
6625
|
+
m + 2 < g.values.length && (b || c.includes("Hand")) && (g.values[m + 1] += Math.PI);
|
|
6575
6626
|
}
|
|
6576
6627
|
}
|
|
6577
6628
|
}
|
|
6578
|
-
n.push(
|
|
6629
|
+
n.push(g), h !== c && s.set(h, c);
|
|
6579
6630
|
} else
|
|
6580
|
-
i.add(
|
|
6581
|
-
}),
|
|
6582
|
-
|
|
6583
|
-
|
|
6584
|
-
|
|
6585
|
-
|
|
6586
|
-
`
|
|
6587
|
-
|
|
6588
|
-
|
|
6589
|
-
|
|
6631
|
+
i.add(h);
|
|
6632
|
+
}), console.log(`
|
|
6633
|
+
=== Mapping Results for "${t.name}" ===`), s.size > 0 && (console.info(`✓ Successfully mapped ${s.size} bone(s):`), Array.from(s.entries()).forEach(([u, r]) => {
|
|
6634
|
+
console.log(` ${u} → ${r}`);
|
|
6635
|
+
})), i.size > 0 && (console.warn(`
|
|
6636
|
+
✗ Could not map ${i.size} bone(s):`), Array.from(i).sort().forEach((u) => {
|
|
6637
|
+
console.log(` - ${u}`);
|
|
6638
|
+
const r = u.replace(/^(CC_Base_|mixamorig)/i, "").replace(/^[RL]_/, (a) => a.toLowerCase()), h = [];
|
|
6639
|
+
for (const a of e) {
|
|
6640
|
+
const c = a.toLowerCase(), d = r.toLowerCase();
|
|
6641
|
+
(c.includes(d) || d.includes(c)) && h.push(a);
|
|
6642
|
+
}
|
|
6643
|
+
h.length > 0 && console.log(` → Possible matches: ${h.slice(0, 3).join(", ")}`);
|
|
6644
|
+
}));
|
|
6645
|
+
const l = /* @__PURE__ */ new Set();
|
|
6646
|
+
return o.forEach((u) => {
|
|
6647
|
+
e.has(u) && !s.has(u) && l.add(u);
|
|
6648
|
+
}), l.size > 0 && (console.info(`
|
|
6649
|
+
✓ Direct matches (no mapping needed): ${l.size} bone(s)`), Array.from(l).sort().slice(0, 10).forEach((u) => {
|
|
6650
|
+
console.log(` - ${u}`);
|
|
6651
|
+
}), l.size > 10 && console.log(` ... and ${l.size - 10} more`)), console.log(`
|
|
6652
|
+
=== Summary ===`), console.log(`Total FBX tracks: ${t.tracks.length}`), console.log(`Valid tracks: ${n.length}`), console.log(`Mapped bones: ${s.size}`), console.log(`Direct matches: ${l.size}`), console.log(`Missing bones: ${i.size}`), console.log(`========================================
|
|
6653
|
+
`), n.length === 0 && console.error(`No valid tracks found for animation "${t.name}". All bones are missing or couldn't be mapped.`), n.length === 0 ? null : new f.AnimationClip(t.name, t.duration, n);
|
|
6590
6654
|
}
|
|
6591
6655
|
async playAnimation(t, e = null, n = 10, i = 0, s = 0.01, o = !1) {
|
|
6592
6656
|
if (!this.armature) return;
|
|
@@ -6596,9 +6660,9 @@ class Be {
|
|
|
6596
6660
|
let u = this.animQueue.find((a) => a.template.name === "pose");
|
|
6597
6661
|
u && (u.ts[0] = 1 / 0), Object.entries(l.pose.props).forEach((a) => {
|
|
6598
6662
|
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;
|
|
6599
|
-
}), this.mixer ? console.log("Using existing mixer for FBX animation, preserving morph targets") : (this.mixer = new
|
|
6663
|
+
}), 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 });
|
|
6600
6664
|
const r = Math.ceil(n / l.clip.duration), h = this.mixer.clipAction(l.clip);
|
|
6601
|
-
h.setLoop(
|
|
6665
|
+
h.setLoop(f.LoopRepeat, r), h.clampWhenFinished = !0, this.currentFBXAction = h;
|
|
6602
6666
|
try {
|
|
6603
6667
|
h.fadeIn(0.5).play(), console.log("FBX animation started successfully:", t);
|
|
6604
6668
|
} catch (a) {
|
|
@@ -6624,7 +6688,7 @@ class Be {
|
|
|
6624
6688
|
} catch (c) {
|
|
6625
6689
|
console.warn(`Could not verify file existence for ${t}, attempting to load anyway:`, c);
|
|
6626
6690
|
}
|
|
6627
|
-
const h = new
|
|
6691
|
+
const h = new Be();
|
|
6628
6692
|
let a;
|
|
6629
6693
|
try {
|
|
6630
6694
|
a = await h.loadAsync(t, e);
|
|
@@ -6656,20 +6720,20 @@ class Be {
|
|
|
6656
6720
|
}
|
|
6657
6721
|
c = g;
|
|
6658
6722
|
const x = {};
|
|
6659
|
-
c.tracks.forEach((
|
|
6660
|
-
|
|
6661
|
-
const
|
|
6662
|
-
if (
|
|
6663
|
-
for (let
|
|
6664
|
-
|
|
6665
|
-
x[
|
|
6666
|
-
} else
|
|
6723
|
+
c.tracks.forEach((I) => {
|
|
6724
|
+
I.name = I.name.replaceAll("mixamorig", "");
|
|
6725
|
+
const H = I.name.split(".");
|
|
6726
|
+
if (H[1] === "position") {
|
|
6727
|
+
for (let m = 0; m < I.values.length; m++)
|
|
6728
|
+
I.values[m] = I.values[m] * s;
|
|
6729
|
+
x[I.name] = new f.Vector3(I.values[0], I.values[1], I.values[2]);
|
|
6730
|
+
} else H[1] === "quaternion" ? x[I.name] = new f.Quaternion(I.values[0], I.values[1], I.values[2], I.values[3]) : H[1] === "rotation" && (x[H[0] + ".quaternion"] = new f.Quaternion().setFromEuler(new f.Euler(I.values[0], I.values[1], I.values[2], "XYZ")).normalize());
|
|
6667
6731
|
});
|
|
6668
|
-
const
|
|
6669
|
-
x["Hips.position"] && (x["Hips.position"].y < 0.5 ?
|
|
6732
|
+
const b = { props: x };
|
|
6733
|
+
x["Hips.position"] && (x["Hips.position"].y < 0.5 ? b.lying = !0 : b.standing = !0), this.animClips.push({
|
|
6670
6734
|
url: t + "-" + i,
|
|
6671
6735
|
clip: c,
|
|
6672
|
-
pose:
|
|
6736
|
+
pose: b
|
|
6673
6737
|
}), this.playAnimation(t, e, n, i, s);
|
|
6674
6738
|
} else {
|
|
6675
6739
|
const c = "Animation " + t + " (ndx=" + i + ") not found";
|
|
@@ -6707,14 +6771,14 @@ class Be {
|
|
|
6707
6771
|
let l = this.animQueue.find((u) => u.template.name === "pose");
|
|
6708
6772
|
l && (l.ts[0] = this.animClock + n * 1e3 + 2e3), this.setPoseFromTemplate(o);
|
|
6709
6773
|
} else {
|
|
6710
|
-
let u = await new
|
|
6774
|
+
let u = await new Be().loadAsync(t, e);
|
|
6711
6775
|
if (u && u.animations && u.animations[i]) {
|
|
6712
6776
|
let r = u.animations[i];
|
|
6713
6777
|
const h = {};
|
|
6714
6778
|
r.tracks.forEach((c) => {
|
|
6715
6779
|
c.name = c.name.replaceAll("mixamorig", "");
|
|
6716
6780
|
const d = c.name.split(".");
|
|
6717
|
-
d[1] === "position" ? h[c.name] = new
|
|
6781
|
+
d[1] === "position" ? h[c.name] = new f.Vector3(c.values[0] * s, c.values[1] * s, c.values[2] * s) : d[1] === "quaternion" ? h[c.name] = new f.Quaternion(c.values[0], c.values[1], c.values[2], c.values[3]) : d[1] === "rotation" && (h[d[0] + ".quaternion"] = new f.Quaternion().setFromEuler(new f.Euler(c.values[0], c.values[1], c.values[2], "XYZ")).normalize());
|
|
6718
6782
|
});
|
|
6719
6783
|
const a = { props: h };
|
|
6720
6784
|
h["Hips.position"] && (h["Hips.position"].y < 0.5 ? a.lying = !0 : a.standing = !0), this.animPoses.push({
|
|
@@ -6747,7 +6811,7 @@ class Be {
|
|
|
6747
6811
|
if (s) {
|
|
6748
6812
|
this.gestureTimeout && (clearTimeout(this.gestureTimeout), this.gestureTimeout = null);
|
|
6749
6813
|
let l = this.animQueue.findIndex((u) => u.template.name === "talkinghands");
|
|
6750
|
-
l !== -1 && (this.animQueue[l].ts = this.animQueue[l].ts.map((u) => 0)), this.gesture = this.propsToThreeObjects(s), n && (this.gesture = this.mirrorPose(this.gesture)), t === "namaste" && this.avatar.body === "M" && (this.gesture["RightArm.quaternion"].rotateTowards(new
|
|
6814
|
+
l !== -1 && (this.animQueue[l].ts = this.animQueue[l].ts.map((u) => 0)), this.gesture = this.propsToThreeObjects(s), n && (this.gesture = this.mirrorPose(this.gesture)), t === "namaste" && this.avatar.body === "M" && (this.gesture["RightArm.quaternion"].rotateTowards(new f.Quaternion(0, 1, 0, 0), -0.25), this.gesture["LeftArm.quaternion"].rotateTowards(new f.Quaternion(0, 1, 0, 0), -0.25));
|
|
6751
6815
|
for (let [u, r] of Object.entries(this.gesture))
|
|
6752
6816
|
r.t = this.animClock, r.d = i, this.poseTarget.props.hasOwnProperty(u) && (this.poseTarget.props[u].copy(r), this.poseTarget.props[u].t = this.animClock, this.poseTarget.props[u].d = i);
|
|
6753
6817
|
e && Number.isFinite(e) && (this.gestureTimeout = setTimeout(this.stopGesture.bind(this, i), 1e3 * e));
|
|
@@ -6762,7 +6826,7 @@ class Be {
|
|
|
6762
6826
|
const c = [];
|
|
6763
6827
|
for (let x = 1; x < l.ts.length; x++) c.push(l.ts[x] - l.ts[x - 1]);
|
|
6764
6828
|
const d = o.template?.rescale || c.map((x) => x / h), g = e * 1e3 - h;
|
|
6765
|
-
l.ts = l.ts.map((x,
|
|
6829
|
+
l.ts = l.ts.map((x, b, I) => b === 0 ? u : I[b - 1] + c[b - 1] + d[b - 1] * g);
|
|
6766
6830
|
} else {
|
|
6767
6831
|
const c = e * 1e3 / h;
|
|
6768
6832
|
l.ts = l.ts.map((d) => u + c * (d - u));
|
|
@@ -6795,34 +6859,34 @@ class Be {
|
|
|
6795
6859
|
* @param {numeric} [d=null] If set, apply in d milliseconds
|
|
6796
6860
|
*/
|
|
6797
6861
|
ikSolve(t, e = null, n = !1, i = null) {
|
|
6798
|
-
const s = new
|
|
6862
|
+
const s = new f.Vector3(), o = new f.Vector3(), l = new f.Vector3(), u = new f.Vector3(), r = new f.Quaternion(), h = new f.Vector3(), a = new f.Vector3(), c = new f.Vector3(), d = this.ikMesh.getObjectByName(t.root);
|
|
6799
6863
|
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);
|
|
6800
6864
|
const g = this.ikMesh.getObjectByName(t.effector), x = t.links;
|
|
6801
|
-
x.forEach((
|
|
6802
|
-
|
|
6865
|
+
x.forEach((I) => {
|
|
6866
|
+
I.bone = this.ikMesh.getObjectByName(I.link), I.bone.quaternion.copy(this.getPoseTemplateProp(I.link + ".quaternion"));
|
|
6803
6867
|
}), d.updateMatrixWorld(!0);
|
|
6804
|
-
const
|
|
6868
|
+
const b = t.iterations || 10;
|
|
6805
6869
|
if (e)
|
|
6806
|
-
for (let
|
|
6807
|
-
let
|
|
6808
|
-
for (let
|
|
6809
|
-
const k = x[
|
|
6870
|
+
for (let I = 0; I < b; I++) {
|
|
6871
|
+
let H = !1;
|
|
6872
|
+
for (let m = 0, T = x.length; m < T; m++) {
|
|
6873
|
+
const k = x[m].bone;
|
|
6810
6874
|
k.matrixWorld.decompose(u, r, h), r.invert(), o.setFromMatrixPosition(g.matrixWorld), l.subVectors(o, u), l.applyQuaternion(r), l.normalize(), s.subVectors(e, u), s.applyQuaternion(r), s.normalize();
|
|
6811
6875
|
let y = s.dot(l);
|
|
6812
|
-
y > 1 ? y = 1 : y < -1 && (y = -1), y = Math.acos(y), !(y < 1e-5) && (x[
|
|
6813
|
-
x[
|
|
6814
|
-
x[
|
|
6815
|
-
x[
|
|
6816
|
-
), new
|
|
6817
|
-
x[
|
|
6818
|
-
x[
|
|
6819
|
-
x[
|
|
6820
|
-
))), k.updateMatrixWorld(!0),
|
|
6876
|
+
y > 1 ? y = 1 : y < -1 && (y = -1), y = Math.acos(y), !(y < 1e-5) && (x[m].minAngle !== void 0 && y < x[m].minAngle && (y = x[m].minAngle), x[m].maxAngle !== void 0 && y > x[m].maxAngle && (y = x[m].maxAngle), a.crossVectors(l, s), a.normalize(), _.setFromAxisAngle(a, y), k.quaternion.multiply(_), k.rotation.setFromVector3(c.setFromEuler(k.rotation).clamp(new f.Vector3(
|
|
6877
|
+
x[m].minx !== void 0 ? x[m].minx : -1 / 0,
|
|
6878
|
+
x[m].miny !== void 0 ? x[m].miny : -1 / 0,
|
|
6879
|
+
x[m].minz !== void 0 ? x[m].minz : -1 / 0
|
|
6880
|
+
), new f.Vector3(
|
|
6881
|
+
x[m].maxx !== void 0 ? x[m].maxx : 1 / 0,
|
|
6882
|
+
x[m].maxy !== void 0 ? x[m].maxy : 1 / 0,
|
|
6883
|
+
x[m].maxz !== void 0 ? x[m].maxz : 1 / 0
|
|
6884
|
+
))), k.updateMatrixWorld(!0), H = !0);
|
|
6821
6885
|
}
|
|
6822
|
-
if (!
|
|
6886
|
+
if (!H) break;
|
|
6823
6887
|
}
|
|
6824
|
-
i && x.forEach((
|
|
6825
|
-
this.poseTarget.props[
|
|
6888
|
+
i && x.forEach((I) => {
|
|
6889
|
+
this.poseTarget.props[I.link + ".quaternion"].copy(I.bone.quaternion), this.poseTarget.props[I.link + ".quaternion"].t = this.animClock, this.poseTarget.props[I.link + ".quaternion"].d = i;
|
|
6826
6890
|
});
|
|
6827
6891
|
}
|
|
6828
6892
|
/**
|
|
@@ -6882,16 +6946,16 @@ function Fe() {
|
|
|
6882
6946
|
};
|
|
6883
6947
|
}
|
|
6884
6948
|
function kt() {
|
|
6885
|
-
const
|
|
6886
|
-
return Object.entries(
|
|
6949
|
+
const X = Fe(), t = [];
|
|
6950
|
+
return Object.entries(X.voices).forEach(([e, n]) => {
|
|
6887
6951
|
t.push({
|
|
6888
6952
|
value: n,
|
|
6889
|
-
label: `${e.charAt(0).toUpperCase() + e.slice(1)} (${
|
|
6953
|
+
label: `${e.charAt(0).toUpperCase() + e.slice(1)} (${X.service})`
|
|
6890
6954
|
});
|
|
6891
6955
|
}), t;
|
|
6892
6956
|
}
|
|
6893
6957
|
const Ve = Me(({
|
|
6894
|
-
avatarUrl:
|
|
6958
|
+
avatarUrl: X = "/avatars/brunette.glb",
|
|
6895
6959
|
avatarBody: t = "F",
|
|
6896
6960
|
mood: e = "neutral",
|
|
6897
6961
|
ttsLang: n = "en",
|
|
@@ -6910,15 +6974,15 @@ const Ve = Me(({
|
|
|
6910
6974
|
},
|
|
6911
6975
|
className: g = "",
|
|
6912
6976
|
style: x = {},
|
|
6913
|
-
animations:
|
|
6914
|
-
},
|
|
6915
|
-
const
|
|
6977
|
+
animations: b = {}
|
|
6978
|
+
}, I) => {
|
|
6979
|
+
const H = O(null), m = O(null), T = O(r), k = O(null), y = O(null), M = O(!1), P = O({ remainingText: null, originalText: null, options: null }), D = O([]), J = O(0), [S, G] = ce(!0), [Q, Z] = ce(null), [ee, se] = ce(!1), [ae, pe] = ce(!1);
|
|
6916
6980
|
de(() => {
|
|
6917
|
-
|
|
6981
|
+
M.current = ae;
|
|
6918
6982
|
}, [ae]), de(() => {
|
|
6919
|
-
|
|
6983
|
+
T.current = r;
|
|
6920
6984
|
}, [r]);
|
|
6921
|
-
const
|
|
6985
|
+
const te = Fe(), le = i || te.service;
|
|
6922
6986
|
let U;
|
|
6923
6987
|
le === "browser" ? U = {
|
|
6924
6988
|
service: "browser",
|
|
@@ -6928,22 +6992,22 @@ const Ve = Me(({
|
|
|
6928
6992
|
} : le === "elevenlabs" ? U = {
|
|
6929
6993
|
service: "elevenlabs",
|
|
6930
6994
|
endpoint: "https://api.elevenlabs.io/v1/text-to-speech",
|
|
6931
|
-
apiKey: o ||
|
|
6932
|
-
defaultVoice: s ||
|
|
6933
|
-
voices:
|
|
6995
|
+
apiKey: o || te.apiKey,
|
|
6996
|
+
defaultVoice: s || te.defaultVoice || Ie.defaultVoice,
|
|
6997
|
+
voices: te.voices || Ie.voices
|
|
6934
6998
|
} : le === "deepgram" ? U = {
|
|
6935
6999
|
service: "deepgram",
|
|
6936
7000
|
endpoint: "https://api.deepgram.com/v1/speak",
|
|
6937
|
-
apiKey: o ||
|
|
6938
|
-
defaultVoice: s ||
|
|
6939
|
-
voices:
|
|
7001
|
+
apiKey: o || te.apiKey,
|
|
7002
|
+
defaultVoice: s || te.defaultVoice || Te.defaultVoice,
|
|
7003
|
+
voices: te.voices || Te.voices
|
|
6940
7004
|
} : U = {
|
|
6941
|
-
...
|
|
7005
|
+
...te,
|
|
6942
7006
|
// Override API key if provided via props
|
|
6943
|
-
apiKey: o !== null ? o :
|
|
7007
|
+
apiKey: o !== null ? o : te.apiKey
|
|
6944
7008
|
};
|
|
6945
|
-
const
|
|
6946
|
-
url:
|
|
7009
|
+
const R = {
|
|
7010
|
+
url: X,
|
|
6947
7011
|
body: t,
|
|
6948
7012
|
avatarMood: e,
|
|
6949
7013
|
ttsLang: le === "browser" ? "en-US" : n,
|
|
@@ -6952,88 +7016,88 @@ const Ve = Me(({
|
|
|
6952
7016
|
showFullAvatar: r,
|
|
6953
7017
|
bodyMovement: l,
|
|
6954
7018
|
movementIntensity: u
|
|
6955
|
-
},
|
|
7019
|
+
}, v = {
|
|
6956
7020
|
ttsEndpoint: U.endpoint,
|
|
6957
7021
|
ttsApikey: U.apiKey,
|
|
6958
7022
|
ttsService: le,
|
|
6959
7023
|
lipsyncModules: ["en"],
|
|
6960
7024
|
cameraView: h
|
|
6961
|
-
}, w =
|
|
6962
|
-
if (!(!
|
|
7025
|
+
}, w = F(async () => {
|
|
7026
|
+
if (!(!H.current || m.current))
|
|
6963
7027
|
try {
|
|
6964
|
-
if (G(!0),
|
|
6965
|
-
if (
|
|
6966
|
-
const
|
|
6967
|
-
c(
|
|
7028
|
+
if (G(!0), Z(null), m.current = new Ne(H.current, v), m.current.controls && (m.current.controls.enableRotate = !1, m.current.controls.enableZoom = !1, m.current.controls.enablePan = !1, m.current.controls.enableDamping = !1), b && Object.keys(b).length > 0 && (m.current.customAnimations = b), await m.current.showAvatar(R, (B) => {
|
|
7029
|
+
if (B.lengthComputable) {
|
|
7030
|
+
const $ = Math.min(100, Math.round(B.loaded / B.total * 100));
|
|
7031
|
+
c($);
|
|
6968
7032
|
}
|
|
6969
|
-
}), await new Promise((
|
|
6970
|
-
const
|
|
6971
|
-
|
|
7033
|
+
}), await new Promise((B) => {
|
|
7034
|
+
const $ = () => {
|
|
7035
|
+
m.current.lipsync && Object.keys(m.current.lipsync).length > 0 ? B() : setTimeout($, 100);
|
|
6972
7036
|
};
|
|
6973
|
-
|
|
6974
|
-
}),
|
|
7037
|
+
$();
|
|
7038
|
+
}), m.current && m.current.setShowFullAvatar)
|
|
6975
7039
|
try {
|
|
6976
|
-
|
|
6977
|
-
} catch (
|
|
6978
|
-
console.warn("Error setting full body mode on initialization:",
|
|
7040
|
+
m.current.setShowFullAvatar(r);
|
|
7041
|
+
} catch (B) {
|
|
7042
|
+
console.warn("Error setting full body mode on initialization:", B);
|
|
6979
7043
|
}
|
|
6980
|
-
|
|
6981
|
-
const
|
|
6982
|
-
document.visibilityState === "visible" ?
|
|
7044
|
+
m.current && m.current.controls && (m.current.controls.enableRotate = !1, m.current.controls.enableZoom = !1, m.current.controls.enablePan = !1, m.current.controls.enableDamping = !1, m.current.controls.update()), G(!1), se(!0), a(m.current);
|
|
7045
|
+
const N = () => {
|
|
7046
|
+
document.visibilityState === "visible" ? m.current?.start() : m.current?.stop();
|
|
6983
7047
|
};
|
|
6984
|
-
return document.addEventListener("visibilitychange",
|
|
6985
|
-
document.removeEventListener("visibilitychange",
|
|
7048
|
+
return document.addEventListener("visibilitychange", N), () => {
|
|
7049
|
+
document.removeEventListener("visibilitychange", N);
|
|
6986
7050
|
};
|
|
6987
7051
|
} catch (L) {
|
|
6988
|
-
console.error("Error initializing TalkingHead:", L),
|
|
7052
|
+
console.error("Error initializing TalkingHead:", L), Z(L.message || "Failed to initialize avatar"), G(!1), d(L);
|
|
6989
7053
|
}
|
|
6990
|
-
}, [
|
|
7054
|
+
}, [X, t, e, n, i, s, o, r, l, u, h]);
|
|
6991
7055
|
de(() => (w(), () => {
|
|
6992
|
-
|
|
7056
|
+
m.current && (m.current.stop(), m.current.dispose(), m.current = null);
|
|
6993
7057
|
}), [w]), de(() => {
|
|
6994
|
-
if (!
|
|
6995
|
-
const L = new ResizeObserver((
|
|
6996
|
-
for (const
|
|
6997
|
-
|
|
7058
|
+
if (!H.current || !m.current) return;
|
|
7059
|
+
const L = new ResizeObserver((B) => {
|
|
7060
|
+
for (const $ of B)
|
|
7061
|
+
m.current && m.current.onResize && m.current.onResize();
|
|
6998
7062
|
});
|
|
6999
|
-
L.observe(
|
|
7000
|
-
const
|
|
7001
|
-
|
|
7063
|
+
L.observe(H.current);
|
|
7064
|
+
const N = () => {
|
|
7065
|
+
m.current && m.current.onResize && m.current.onResize();
|
|
7002
7066
|
};
|
|
7003
|
-
return window.addEventListener("resize",
|
|
7004
|
-
L.disconnect(), window.removeEventListener("resize",
|
|
7067
|
+
return window.addEventListener("resize", N), () => {
|
|
7068
|
+
L.disconnect(), window.removeEventListener("resize", N);
|
|
7005
7069
|
};
|
|
7006
|
-
}, [
|
|
7007
|
-
const
|
|
7008
|
-
if (
|
|
7070
|
+
}, [ee]);
|
|
7071
|
+
const E = F(async () => {
|
|
7072
|
+
if (m.current && m.current.audioCtx)
|
|
7009
7073
|
try {
|
|
7010
|
-
(
|
|
7074
|
+
(m.current.audioCtx.state === "suspended" || m.current.audioCtx.state === "interrupted") && (await m.current.audioCtx.resume(), console.log("Audio context resumed"));
|
|
7011
7075
|
} catch (L) {
|
|
7012
7076
|
console.warn("Failed to resume audio context:", L);
|
|
7013
7077
|
}
|
|
7014
|
-
}, []), W =
|
|
7015
|
-
if (
|
|
7078
|
+
}, []), W = F(async (L, N = {}) => {
|
|
7079
|
+
if (m.current && ee)
|
|
7016
7080
|
try {
|
|
7017
|
-
y.current && (clearInterval(y.current), y.current = null), k.current = { text: L, options:
|
|
7018
|
-
const
|
|
7019
|
-
|
|
7081
|
+
y.current && (clearInterval(y.current), y.current = null), k.current = { text: L, options: N }, P.current = { remainingText: null, originalText: null, options: null };
|
|
7082
|
+
const B = /[!\.\?\n\p{Extended_Pictographic}]/ug, $ = L.split(B).map((Y) => Y.trim()).filter((Y) => Y.length > 0);
|
|
7083
|
+
D.current = $, J.current = 0, pe(!1), M.current = !1, await E();
|
|
7020
7084
|
const ge = {
|
|
7021
|
-
...
|
|
7022
|
-
lipsyncLang:
|
|
7085
|
+
...N,
|
|
7086
|
+
lipsyncLang: N.lipsyncLang || R.lipsyncLang || "en"
|
|
7023
7087
|
};
|
|
7024
|
-
if (
|
|
7025
|
-
const Y =
|
|
7088
|
+
if (N.onSpeechEnd && m.current) {
|
|
7089
|
+
const Y = m.current;
|
|
7026
7090
|
let ue = null, Se = 0;
|
|
7027
7091
|
const Ae = 1200;
|
|
7028
7092
|
let be = !1;
|
|
7029
7093
|
ue = setInterval(() => {
|
|
7030
|
-
if (Se++,
|
|
7094
|
+
if (Se++, M.current)
|
|
7031
7095
|
return;
|
|
7032
7096
|
if (Se > Ae) {
|
|
7033
|
-
if (ue && (clearInterval(ue), ue = null, y.current = null), !be && !
|
|
7097
|
+
if (ue && (clearInterval(ue), ue = null, y.current = null), !be && !M.current) {
|
|
7034
7098
|
be = !0;
|
|
7035
7099
|
try {
|
|
7036
|
-
|
|
7100
|
+
N.onSpeechEnd();
|
|
7037
7101
|
} catch (De) {
|
|
7038
7102
|
console.error("Error in onSpeechEnd callback (timeout):", De);
|
|
7039
7103
|
}
|
|
@@ -7041,11 +7105,11 @@ const Ve = Me(({
|
|
|
7041
7105
|
return;
|
|
7042
7106
|
}
|
|
7043
7107
|
const ye = !Y.speechQueue || Y.speechQueue.length === 0, ke = !Y.audioPlaylist || Y.audioPlaylist.length === 0;
|
|
7044
|
-
Y && Y.isSpeaking === !1 && ye && ke && Y.isAudioPlaying === !1 && !be && !
|
|
7045
|
-
if (Y && !
|
|
7108
|
+
Y && Y.isSpeaking === !1 && ye && ke && Y.isAudioPlaying === !1 && !be && !M.current && setTimeout(() => {
|
|
7109
|
+
if (Y && !M.current && Y.isSpeaking === !1 && (!Y.speechQueue || Y.speechQueue.length === 0) && (!Y.audioPlaylist || Y.audioPlaylist.length === 0) && Y.isAudioPlaying === !1 && !be && !M.current) {
|
|
7046
7110
|
be = !0, ue && (clearInterval(ue), ue = null, y.current = null);
|
|
7047
7111
|
try {
|
|
7048
|
-
|
|
7112
|
+
N.onSpeechEnd();
|
|
7049
7113
|
} catch (Ze) {
|
|
7050
7114
|
console.error("Error in onSpeechEnd callback:", Ze);
|
|
7051
7115
|
}
|
|
@@ -7053,167 +7117,167 @@ const Ve = Me(({
|
|
|
7053
7117
|
}, 100);
|
|
7054
7118
|
}, 100), y.current = ue;
|
|
7055
7119
|
}
|
|
7056
|
-
|
|
7057
|
-
await
|
|
7120
|
+
m.current.lipsync && Object.keys(m.current.lipsync).length > 0 ? (m.current.setSlowdownRate && m.current.setSlowdownRate(1.05), m.current.speakText(L, ge)) : setTimeout(async () => {
|
|
7121
|
+
await E(), m.current && m.current.lipsync && (m.current.setSlowdownRate && m.current.setSlowdownRate(1.05), m.current.speakText(L, ge));
|
|
7058
7122
|
}, 100);
|
|
7059
|
-
} catch (
|
|
7060
|
-
console.error("Error speaking text:",
|
|
7123
|
+
} catch (B) {
|
|
7124
|
+
console.error("Error speaking text:", B), Z(B.message || "Failed to speak text");
|
|
7061
7125
|
}
|
|
7062
|
-
}, [
|
|
7063
|
-
|
|
7064
|
-
}, []), j =
|
|
7065
|
-
if (
|
|
7066
|
-
const L =
|
|
7126
|
+
}, [ee, E, R.lipsyncLang]), K = F(() => {
|
|
7127
|
+
m.current && (m.current.stopSpeaking(), m.current.setSlowdownRate && m.current.setSlowdownRate(1), k.current = null, pe(!1));
|
|
7128
|
+
}, []), j = F(() => {
|
|
7129
|
+
if (m.current && m.current.pauseSpeaking) {
|
|
7130
|
+
const L = m.current;
|
|
7067
7131
|
if (L.isSpeaking || L.audioPlaylist && L.audioPlaylist.length > 0 || L.speechQueue && L.speechQueue.length > 0) {
|
|
7068
7132
|
y.current && (clearInterval(y.current), y.current = null);
|
|
7069
|
-
let
|
|
7070
|
-
if (k.current &&
|
|
7071
|
-
const
|
|
7072
|
-
if (ue > 0 && Se <
|
|
7133
|
+
let B = "";
|
|
7134
|
+
if (k.current && D.current.length > 0) {
|
|
7135
|
+
const $ = 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, ue = ge + (Y ? 1 : 0), Se = $ - ue;
|
|
7136
|
+
if (ue > 0 && Se < $ && (B = D.current.slice(Se).join(". ").trim(), !B && ge > 0 && L.speechQueue)) {
|
|
7073
7137
|
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(" ");
|
|
7074
|
-
be && be.trim() && (
|
|
7138
|
+
be && be.trim() && (B = be.trim());
|
|
7075
7139
|
}
|
|
7076
7140
|
}
|
|
7077
|
-
k.current && (
|
|
7078
|
-
remainingText:
|
|
7141
|
+
k.current && (P.current = {
|
|
7142
|
+
remainingText: B || null,
|
|
7079
7143
|
originalText: k.current.text,
|
|
7080
7144
|
options: k.current.options
|
|
7081
|
-
}), L.speechQueue && (L.speechQueue.length = 0),
|
|
7145
|
+
}), L.speechQueue && (L.speechQueue.length = 0), m.current.pauseSpeaking(), M.current = !0, pe(!0);
|
|
7082
7146
|
}
|
|
7083
7147
|
}
|
|
7084
|
-
}, []), q =
|
|
7085
|
-
if (!
|
|
7148
|
+
}, []), q = F(async () => {
|
|
7149
|
+
if (!m.current || !ae)
|
|
7086
7150
|
return;
|
|
7087
|
-
let L = "",
|
|
7088
|
-
if (
|
|
7089
|
-
L =
|
|
7151
|
+
let L = "", N = {};
|
|
7152
|
+
if (P.current && P.current.remainingText)
|
|
7153
|
+
L = P.current.remainingText, N = P.current.options || {}, P.current = { remainingText: null, originalText: null, options: null };
|
|
7090
7154
|
else if (k.current && k.current.text)
|
|
7091
|
-
L = k.current.text,
|
|
7155
|
+
L = k.current.text, N = k.current.options || {};
|
|
7092
7156
|
else {
|
|
7093
|
-
console.warn("Resume called but no paused speech found"), pe(!1),
|
|
7157
|
+
console.warn("Resume called but no paused speech found"), pe(!1), M.current = !1;
|
|
7094
7158
|
return;
|
|
7095
7159
|
}
|
|
7096
|
-
pe(!1),
|
|
7097
|
-
const
|
|
7098
|
-
...
|
|
7099
|
-
lipsyncLang:
|
|
7160
|
+
pe(!1), M.current = !1, await E();
|
|
7161
|
+
const B = {
|
|
7162
|
+
...N,
|
|
7163
|
+
lipsyncLang: N.lipsyncLang || R.lipsyncLang || "en"
|
|
7100
7164
|
};
|
|
7101
7165
|
try {
|
|
7102
|
-
await W(L,
|
|
7103
|
-
} catch (
|
|
7104
|
-
console.error("Error resuming speech:",
|
|
7166
|
+
await W(L, B);
|
|
7167
|
+
} catch ($) {
|
|
7168
|
+
console.error("Error resuming speech:", $), pe(!1), M.current = !1;
|
|
7105
7169
|
}
|
|
7106
|
-
}, [
|
|
7107
|
-
|
|
7108
|
-
}, []), we =
|
|
7109
|
-
|
|
7110
|
-
}, []), C =
|
|
7111
|
-
if (
|
|
7112
|
-
if (
|
|
7170
|
+
}, [E, ae, W, R]), Le = F((L) => {
|
|
7171
|
+
m.current && m.current.setMood(L);
|
|
7172
|
+
}, []), we = F((L) => {
|
|
7173
|
+
m.current && m.current.setSlowdownRate && m.current.setSlowdownRate(L);
|
|
7174
|
+
}, []), C = F((L, N = !1) => {
|
|
7175
|
+
if (m.current && m.current.playAnimation) {
|
|
7176
|
+
if (b && b[L] && (L = b[L]), m.current.setShowFullAvatar)
|
|
7113
7177
|
try {
|
|
7114
|
-
|
|
7115
|
-
} catch (
|
|
7116
|
-
console.warn("Error setting full body mode:",
|
|
7178
|
+
m.current.setShowFullAvatar(T.current);
|
|
7179
|
+
} catch ($) {
|
|
7180
|
+
console.warn("Error setting full body mode:", $);
|
|
7117
7181
|
}
|
|
7118
7182
|
if (L.includes("."))
|
|
7119
7183
|
try {
|
|
7120
|
-
|
|
7121
|
-
} catch (
|
|
7122
|
-
console.warn(`Failed to play ${L}:`,
|
|
7184
|
+
m.current.playAnimation(L, null, 10, 0, 0.01, N);
|
|
7185
|
+
} catch ($) {
|
|
7186
|
+
console.warn(`Failed to play ${L}:`, $);
|
|
7123
7187
|
try {
|
|
7124
|
-
|
|
7188
|
+
m.current.setBodyMovement("idle");
|
|
7125
7189
|
} catch (ge) {
|
|
7126
7190
|
console.warn("Fallback animation also failed:", ge);
|
|
7127
7191
|
}
|
|
7128
7192
|
}
|
|
7129
7193
|
else {
|
|
7130
|
-
const
|
|
7194
|
+
const $ = [".fbx", ".glb", ".gltf"];
|
|
7131
7195
|
let ge = !1;
|
|
7132
|
-
for (const Y of
|
|
7196
|
+
for (const Y of $)
|
|
7133
7197
|
try {
|
|
7134
|
-
|
|
7198
|
+
m.current.playAnimation(L + Y, null, 10, 0, 0.01, N), ge = !0;
|
|
7135
7199
|
break;
|
|
7136
7200
|
} catch {
|
|
7137
7201
|
}
|
|
7138
7202
|
if (!ge) {
|
|
7139
7203
|
console.warn("Animation not found:", L);
|
|
7140
7204
|
try {
|
|
7141
|
-
|
|
7205
|
+
m.current.setBodyMovement("idle");
|
|
7142
7206
|
} catch (Y) {
|
|
7143
7207
|
console.warn("Fallback animation also failed:", Y);
|
|
7144
7208
|
}
|
|
7145
7209
|
}
|
|
7146
7210
|
}
|
|
7147
7211
|
}
|
|
7148
|
-
}, [
|
|
7149
|
-
|
|
7212
|
+
}, [b]), ne = F(() => {
|
|
7213
|
+
m.current && m.current.onResize && m.current.onResize();
|
|
7150
7214
|
}, []);
|
|
7151
|
-
return Ee(
|
|
7215
|
+
return Ee(I, () => ({
|
|
7152
7216
|
speakText: W,
|
|
7153
7217
|
stopSpeaking: K,
|
|
7154
7218
|
pauseSpeaking: j,
|
|
7155
7219
|
resumeSpeaking: q,
|
|
7156
|
-
resumeAudioContext:
|
|
7220
|
+
resumeAudioContext: E,
|
|
7157
7221
|
setMood: Le,
|
|
7158
7222
|
setTimingAdjustment: we,
|
|
7159
7223
|
playAnimation: C,
|
|
7160
|
-
isReady:
|
|
7224
|
+
isReady: ee,
|
|
7161
7225
|
isPaused: ae,
|
|
7162
|
-
talkingHead:
|
|
7226
|
+
talkingHead: m.current,
|
|
7163
7227
|
handleResize: ne,
|
|
7164
7228
|
setBodyMovement: (L) => {
|
|
7165
|
-
if (
|
|
7229
|
+
if (m.current && m.current.setShowFullAvatar && m.current.setBodyMovement)
|
|
7166
7230
|
try {
|
|
7167
|
-
|
|
7168
|
-
} catch (
|
|
7169
|
-
console.warn("Error setting body movement:",
|
|
7231
|
+
m.current.setShowFullAvatar(T.current), m.current.setBodyMovement(L);
|
|
7232
|
+
} catch (N) {
|
|
7233
|
+
console.warn("Error setting body movement:", N);
|
|
7170
7234
|
}
|
|
7171
7235
|
},
|
|
7172
|
-
setMovementIntensity: (L) =>
|
|
7236
|
+
setMovementIntensity: (L) => m.current?.setMovementIntensity(L),
|
|
7173
7237
|
playRandomDance: () => {
|
|
7174
|
-
if (
|
|
7238
|
+
if (m.current && m.current.setShowFullAvatar && m.current.playRandomDance)
|
|
7175
7239
|
try {
|
|
7176
|
-
|
|
7240
|
+
m.current.setShowFullAvatar(T.current), m.current.playRandomDance();
|
|
7177
7241
|
} catch (L) {
|
|
7178
7242
|
console.warn("Error playing random dance:", L);
|
|
7179
7243
|
}
|
|
7180
7244
|
},
|
|
7181
7245
|
playReaction: (L) => {
|
|
7182
|
-
if (
|
|
7246
|
+
if (m.current && m.current.setShowFullAvatar && m.current.playReaction)
|
|
7183
7247
|
try {
|
|
7184
|
-
|
|
7185
|
-
} catch (
|
|
7186
|
-
console.warn("Error playing reaction:",
|
|
7248
|
+
m.current.setShowFullAvatar(T.current), m.current.playReaction(L);
|
|
7249
|
+
} catch (N) {
|
|
7250
|
+
console.warn("Error playing reaction:", N);
|
|
7187
7251
|
}
|
|
7188
7252
|
},
|
|
7189
7253
|
playCelebration: () => {
|
|
7190
|
-
if (
|
|
7254
|
+
if (m.current && m.current.setShowFullAvatar && m.current.playCelebration)
|
|
7191
7255
|
try {
|
|
7192
|
-
|
|
7256
|
+
m.current.setShowFullAvatar(T.current), m.current.playCelebration();
|
|
7193
7257
|
} catch (L) {
|
|
7194
7258
|
console.warn("Error playing celebration:", L);
|
|
7195
7259
|
}
|
|
7196
7260
|
},
|
|
7197
7261
|
setShowFullAvatar: (L) => {
|
|
7198
|
-
if (
|
|
7262
|
+
if (m.current && m.current.setShowFullAvatar)
|
|
7199
7263
|
try {
|
|
7200
|
-
|
|
7201
|
-
} catch (
|
|
7202
|
-
console.warn("Error setting showFullAvatar:",
|
|
7264
|
+
T.current = L, m.current.setShowFullAvatar(L);
|
|
7265
|
+
} catch (N) {
|
|
7266
|
+
console.warn("Error setting showFullAvatar:", N);
|
|
7203
7267
|
}
|
|
7204
7268
|
},
|
|
7205
7269
|
lockAvatarPosition: () => {
|
|
7206
|
-
if (
|
|
7270
|
+
if (m.current && m.current.lockAvatarPosition)
|
|
7207
7271
|
try {
|
|
7208
|
-
|
|
7272
|
+
m.current.lockAvatarPosition();
|
|
7209
7273
|
} catch (L) {
|
|
7210
7274
|
console.warn("Error locking avatar position:", L);
|
|
7211
7275
|
}
|
|
7212
7276
|
},
|
|
7213
7277
|
unlockAvatarPosition: () => {
|
|
7214
|
-
if (
|
|
7278
|
+
if (m.current && m.current.unlockAvatarPosition)
|
|
7215
7279
|
try {
|
|
7216
|
-
|
|
7280
|
+
m.current.unlockAvatarPosition();
|
|
7217
7281
|
} catch (L) {
|
|
7218
7282
|
console.warn("Error unlocking avatar position:", L);
|
|
7219
7283
|
}
|
|
@@ -7232,7 +7296,7 @@ const Ve = Me(({
|
|
|
7232
7296
|
/* @__PURE__ */ me(
|
|
7233
7297
|
"div",
|
|
7234
7298
|
{
|
|
7235
|
-
ref:
|
|
7299
|
+
ref: H,
|
|
7236
7300
|
className: "talking-head-viewer",
|
|
7237
7301
|
style: {
|
|
7238
7302
|
width: "100%",
|
|
@@ -7250,7 +7314,7 @@ const Ve = Me(({
|
|
|
7250
7314
|
fontSize: "18px",
|
|
7251
7315
|
zIndex: 10
|
|
7252
7316
|
}, children: "Loading avatar..." }),
|
|
7253
|
-
|
|
7317
|
+
Q && /* @__PURE__ */ me("div", { className: "error-overlay", style: {
|
|
7254
7318
|
position: "absolute",
|
|
7255
7319
|
top: "50%",
|
|
7256
7320
|
left: "50%",
|
|
@@ -7261,14 +7325,14 @@ const Ve = Me(({
|
|
|
7261
7325
|
zIndex: 10,
|
|
7262
7326
|
padding: "20px",
|
|
7263
7327
|
borderRadius: "8px"
|
|
7264
|
-
}, children:
|
|
7328
|
+
}, children: Q })
|
|
7265
7329
|
]
|
|
7266
7330
|
}
|
|
7267
7331
|
);
|
|
7268
7332
|
});
|
|
7269
7333
|
Ve.displayName = "TalkingHeadAvatar";
|
|
7270
7334
|
const pt = Me(({
|
|
7271
|
-
text:
|
|
7335
|
+
text: X = "Hello! I'm a talking avatar. How are you today?",
|
|
7272
7336
|
onLoading: t = () => {
|
|
7273
7337
|
},
|
|
7274
7338
|
onError: e = () => {
|
|
@@ -7279,23 +7343,23 @@ const pt = Me(({
|
|
|
7279
7343
|
style: s = {},
|
|
7280
7344
|
avatarConfig: o = {}
|
|
7281
7345
|
}, l) => {
|
|
7282
|
-
const u =
|
|
7346
|
+
const u = O(null), r = O(null), [h, a] = ce(!0), [c, d] = ce(null), [g, x] = ce(!1), b = Fe(), I = o.ttsService || b.service, H = I === "browser" ? {
|
|
7283
7347
|
endpoint: "",
|
|
7284
7348
|
apiKey: null,
|
|
7285
7349
|
defaultVoice: "Google US English"
|
|
7286
7350
|
} : {
|
|
7287
|
-
...
|
|
7351
|
+
...b,
|
|
7288
7352
|
// Override API key if provided via avatarConfig
|
|
7289
|
-
apiKey: o.ttsApiKey !== void 0 && o.ttsApiKey !== null ? o.ttsApiKey :
|
|
7353
|
+
apiKey: o.ttsApiKey !== void 0 && o.ttsApiKey !== null ? o.ttsApiKey : b.apiKey,
|
|
7290
7354
|
// Override endpoint for ElevenLabs if service is explicitly set
|
|
7291
|
-
endpoint:
|
|
7292
|
-
},
|
|
7355
|
+
endpoint: I === "elevenlabs" && o.ttsApiKey ? "https://api.elevenlabs.io/v1/text-to-speech" : b.endpoint
|
|
7356
|
+
}, m = {
|
|
7293
7357
|
url: "/avatars/brunette.glb",
|
|
7294
7358
|
// Use brunette avatar (working glTF file)
|
|
7295
7359
|
body: "F",
|
|
7296
7360
|
avatarMood: "neutral",
|
|
7297
|
-
ttsLang:
|
|
7298
|
-
ttsVoice: o.ttsVoice ||
|
|
7361
|
+
ttsLang: I === "browser" ? "en-US" : "en",
|
|
7362
|
+
ttsVoice: o.ttsVoice || H.defaultVoice,
|
|
7299
7363
|
lipsyncLang: "en",
|
|
7300
7364
|
// English lip-sync
|
|
7301
7365
|
showFullAvatar: !0,
|
|
@@ -7303,36 +7367,36 @@ const pt = Me(({
|
|
|
7303
7367
|
bodyMovement: "idle",
|
|
7304
7368
|
movementIntensity: 0.5,
|
|
7305
7369
|
...o
|
|
7306
|
-
},
|
|
7307
|
-
ttsEndpoint:
|
|
7308
|
-
ttsApikey:
|
|
7309
|
-
ttsService:
|
|
7370
|
+
}, T = {
|
|
7371
|
+
ttsEndpoint: H.endpoint,
|
|
7372
|
+
ttsApikey: H.apiKey,
|
|
7373
|
+
ttsService: I,
|
|
7310
7374
|
lipsyncModules: ["en"],
|
|
7311
7375
|
cameraView: "upper"
|
|
7312
|
-
}, k =
|
|
7376
|
+
}, k = F(async () => {
|
|
7313
7377
|
if (!(!u.current || r.current))
|
|
7314
7378
|
try {
|
|
7315
|
-
if (a(!0), d(null), r.current = new
|
|
7316
|
-
if (
|
|
7317
|
-
const
|
|
7318
|
-
t(
|
|
7379
|
+
if (a(!0), d(null), r.current = new Ne(u.current, T), await r.current.showAvatar(m, (Q) => {
|
|
7380
|
+
if (Q.lengthComputable) {
|
|
7381
|
+
const Z = Math.min(100, Math.round(Q.loaded / Q.total * 100));
|
|
7382
|
+
t(Z);
|
|
7319
7383
|
}
|
|
7320
7384
|
}), r.current.morphs && r.current.morphs.length > 0) {
|
|
7321
|
-
const
|
|
7322
|
-
console.log("Available morph targets:", Object.keys(
|
|
7323
|
-
const
|
|
7324
|
-
console.log("Viseme morph targets found:",
|
|
7385
|
+
const Q = r.current.morphs[0].morphTargetDictionary;
|
|
7386
|
+
console.log("Available morph targets:", Object.keys(Q));
|
|
7387
|
+
const Z = Object.keys(Q).filter((ee) => ee.startsWith("viseme_"));
|
|
7388
|
+
console.log("Viseme morph targets found:", Z), Z.length === 0 && (console.warn("No viseme morph targets found! Lip-sync will not work properly."), console.log("Expected viseme targets: viseme_aa, viseme_E, viseme_I, viseme_O, viseme_U, viseme_PP, viseme_SS, viseme_TH, viseme_DD, viseme_FF, viseme_kk, viseme_nn, viseme_RR, viseme_CH, viseme_sil"));
|
|
7325
7389
|
}
|
|
7326
|
-
if (await new Promise((
|
|
7327
|
-
const
|
|
7328
|
-
r.current.lipsync && Object.keys(r.current.lipsync).length > 0 ? (console.log("Lip-sync modules loaded:", Object.keys(r.current.lipsync)),
|
|
7390
|
+
if (await new Promise((Q) => {
|
|
7391
|
+
const Z = () => {
|
|
7392
|
+
r.current.lipsync && Object.keys(r.current.lipsync).length > 0 ? (console.log("Lip-sync modules loaded:", Object.keys(r.current.lipsync)), Q()) : (console.log("Waiting for lip-sync modules to load..."), setTimeout(Z, 100));
|
|
7329
7393
|
};
|
|
7330
|
-
|
|
7394
|
+
Z();
|
|
7331
7395
|
}), r.current && r.current.setShowFullAvatar)
|
|
7332
7396
|
try {
|
|
7333
7397
|
r.current.setShowFullAvatar(!0), console.log("Avatar initialized in full body mode");
|
|
7334
|
-
} catch (
|
|
7335
|
-
console.warn("Error setting full body mode on initialization:",
|
|
7398
|
+
} catch (Q) {
|
|
7399
|
+
console.warn("Error setting full body mode on initialization:", Q);
|
|
7336
7400
|
}
|
|
7337
7401
|
a(!1), x(!0), n(r.current);
|
|
7338
7402
|
const G = () => {
|
|
@@ -7348,10 +7412,10 @@ const pt = Me(({
|
|
|
7348
7412
|
de(() => (k(), () => {
|
|
7349
7413
|
r.current && (r.current.stop(), r.current.dispose(), r.current = null);
|
|
7350
7414
|
}), [k]);
|
|
7351
|
-
const y =
|
|
7415
|
+
const y = F((S) => {
|
|
7352
7416
|
if (r.current && g)
|
|
7353
7417
|
try {
|
|
7354
|
-
console.log("Speaking text:", S), console.log("Avatar config:",
|
|
7418
|
+
console.log("Speaking text:", S), console.log("Avatar config:", m), console.log("TalkingHead instance:", r.current), r.current.lipsync && Object.keys(r.current.lipsync).length > 0 ? (console.log("Lip-sync modules loaded:", Object.keys(r.current.lipsync)), r.current.setSlowdownRate && (r.current.setSlowdownRate(1.05), console.log("Applied timing adjustment for better lip-sync")), r.current.speakText(S)) : (console.warn("Lip-sync modules not ready, waiting..."), setTimeout(() => {
|
|
7355
7419
|
r.current && r.current.lipsync ? (console.log("Lip-sync now ready, speaking..."), r.current.setSlowdownRate && (r.current.setSlowdownRate(1.05), console.log("Applied timing adjustment for better lip-sync")), r.current.speakText(S)) : console.error("Lip-sync still not ready after waiting");
|
|
7356
7420
|
}, 500));
|
|
7357
7421
|
} catch (G) {
|
|
@@ -7359,42 +7423,42 @@ const pt = Me(({
|
|
|
7359
7423
|
}
|
|
7360
7424
|
else
|
|
7361
7425
|
console.warn("Avatar not ready for speaking. isReady:", g, "talkingHeadRef:", !!r.current);
|
|
7362
|
-
}, [g,
|
|
7426
|
+
}, [g, m]), M = F(() => {
|
|
7363
7427
|
r.current && (r.current.stopSpeaking(), r.current.setSlowdownRate && (r.current.setSlowdownRate(1), console.log("Reset timing to normal")));
|
|
7364
|
-
}, []),
|
|
7428
|
+
}, []), P = F((S) => {
|
|
7365
7429
|
r.current && r.current.setMood(S);
|
|
7366
|
-
}, []),
|
|
7430
|
+
}, []), D = F((S) => {
|
|
7367
7431
|
r.current && r.current.setSlowdownRate && (r.current.setSlowdownRate(S), console.log("Timing adjustment set to:", S));
|
|
7368
|
-
}, []),
|
|
7432
|
+
}, []), J = F((S, G = !1) => {
|
|
7369
7433
|
if (r.current && r.current.playAnimation) {
|
|
7370
7434
|
if (r.current.setShowFullAvatar)
|
|
7371
7435
|
try {
|
|
7372
7436
|
r.current.setShowFullAvatar(!0);
|
|
7373
|
-
} catch (
|
|
7374
|
-
console.warn("Error setting full body mode:",
|
|
7437
|
+
} catch (Z) {
|
|
7438
|
+
console.warn("Error setting full body mode:", Z);
|
|
7375
7439
|
}
|
|
7376
7440
|
if (S.includes("."))
|
|
7377
7441
|
try {
|
|
7378
7442
|
r.current.playAnimation(S, null, 10, 0, 0.01, G), console.log("Playing animation:", S);
|
|
7379
|
-
} catch (
|
|
7380
|
-
console.log(`Failed to play ${S}:`,
|
|
7443
|
+
} catch (Z) {
|
|
7444
|
+
console.log(`Failed to play ${S}:`, Z);
|
|
7381
7445
|
try {
|
|
7382
7446
|
r.current.setBodyMovement("idle"), console.log("Fallback to idle animation");
|
|
7383
|
-
} catch (
|
|
7384
|
-
console.warn("Fallback animation also failed:",
|
|
7447
|
+
} catch (ee) {
|
|
7448
|
+
console.warn("Fallback animation also failed:", ee);
|
|
7385
7449
|
}
|
|
7386
7450
|
}
|
|
7387
7451
|
else {
|
|
7388
|
-
const
|
|
7389
|
-
let
|
|
7390
|
-
for (const se of
|
|
7452
|
+
const Z = [".fbx", ".glb", ".gltf"];
|
|
7453
|
+
let ee = !1;
|
|
7454
|
+
for (const se of Z)
|
|
7391
7455
|
try {
|
|
7392
|
-
r.current.playAnimation(S + se, null, 10, 0, 0.01, G), console.log("Playing animation:", S + se),
|
|
7456
|
+
r.current.playAnimation(S + se, null, 10, 0, 0.01, G), console.log("Playing animation:", S + se), ee = !0;
|
|
7393
7457
|
break;
|
|
7394
7458
|
} catch {
|
|
7395
7459
|
console.log(`Failed to play ${S}${se}, trying next format...`);
|
|
7396
7460
|
}
|
|
7397
|
-
if (
|
|
7461
|
+
if (!ee) {
|
|
7398
7462
|
console.warn("Animation system not available or animation not found:", S);
|
|
7399
7463
|
try {
|
|
7400
7464
|
r.current.setBodyMovement("idle"), console.log("Fallback to idle animation");
|
|
@@ -7408,10 +7472,10 @@ const pt = Me(({
|
|
|
7408
7472
|
}, []);
|
|
7409
7473
|
return Ee(l, () => ({
|
|
7410
7474
|
speakText: y,
|
|
7411
|
-
stopSpeaking:
|
|
7412
|
-
setMood:
|
|
7413
|
-
setTimingAdjustment:
|
|
7414
|
-
playAnimation:
|
|
7475
|
+
stopSpeaking: M,
|
|
7476
|
+
setMood: P,
|
|
7477
|
+
setTimingAdjustment: D,
|
|
7478
|
+
playAnimation: J,
|
|
7415
7479
|
isReady: g,
|
|
7416
7480
|
talkingHead: r.current,
|
|
7417
7481
|
setBodyMovement: (S) => {
|
|
@@ -7509,7 +7573,7 @@ const pt = Me(({
|
|
|
7509
7573
|
});
|
|
7510
7574
|
pt.displayName = "TalkingHeadComponent";
|
|
7511
7575
|
const gt = Me(({
|
|
7512
|
-
text:
|
|
7576
|
+
text: X = null,
|
|
7513
7577
|
avatarUrl: t = "/avatars/brunette.glb",
|
|
7514
7578
|
avatarBody: e = "F",
|
|
7515
7579
|
mood: n = "neutral",
|
|
@@ -7529,37 +7593,37 @@ const gt = Me(({
|
|
|
7529
7593
|
},
|
|
7530
7594
|
onSpeechEnd: x = () => {
|
|
7531
7595
|
},
|
|
7532
|
-
className:
|
|
7533
|
-
style:
|
|
7534
|
-
animations:
|
|
7535
|
-
autoSpeak:
|
|
7536
|
-
},
|
|
7537
|
-
const k =
|
|
7596
|
+
className: b = "",
|
|
7597
|
+
style: I = {},
|
|
7598
|
+
animations: H = {},
|
|
7599
|
+
autoSpeak: m = !1
|
|
7600
|
+
}, T) => {
|
|
7601
|
+
const k = O(null), y = O(null), M = O(h), P = O(null), D = O(null), J = O(!1), S = O({ remainingText: null, originalText: null, options: null }), G = O([]), [Q, Z] = ce(!0), [ee, se] = ce(null), [ae, pe] = ce(!1), [te, le] = ce(!1);
|
|
7538
7602
|
de(() => {
|
|
7539
|
-
|
|
7540
|
-
}, [
|
|
7541
|
-
|
|
7603
|
+
J.current = te;
|
|
7604
|
+
}, [te]), de(() => {
|
|
7605
|
+
M.current = h;
|
|
7542
7606
|
}, [h]);
|
|
7543
|
-
const U = Fe(),
|
|
7544
|
-
let
|
|
7545
|
-
|
|
7607
|
+
const U = Fe(), R = s || U.service;
|
|
7608
|
+
let v;
|
|
7609
|
+
R === "browser" ? v = {
|
|
7546
7610
|
service: "browser",
|
|
7547
7611
|
endpoint: "",
|
|
7548
7612
|
apiKey: null,
|
|
7549
7613
|
defaultVoice: "Google US English"
|
|
7550
|
-
} :
|
|
7614
|
+
} : R === "elevenlabs" ? v = {
|
|
7551
7615
|
service: "elevenlabs",
|
|
7552
7616
|
endpoint: "https://api.elevenlabs.io/v1/text-to-speech",
|
|
7553
7617
|
apiKey: l || U.apiKey,
|
|
7554
7618
|
defaultVoice: o || U.defaultVoice || Ie.defaultVoice,
|
|
7555
7619
|
voices: U.voices || Ie.voices
|
|
7556
|
-
} :
|
|
7620
|
+
} : R === "deepgram" ? v = {
|
|
7557
7621
|
service: "deepgram",
|
|
7558
7622
|
endpoint: "https://api.deepgram.com/v1/speak",
|
|
7559
7623
|
apiKey: l || U.apiKey,
|
|
7560
7624
|
defaultVoice: o || U.defaultVoice || Te.defaultVoice,
|
|
7561
7625
|
voices: U.voices || Te.voices
|
|
7562
|
-
} :
|
|
7626
|
+
} : v = {
|
|
7563
7627
|
...U,
|
|
7564
7628
|
apiKey: l !== null ? l : U.apiKey
|
|
7565
7629
|
};
|
|
@@ -7567,22 +7631,22 @@ const gt = Me(({
|
|
|
7567
7631
|
url: t,
|
|
7568
7632
|
body: e,
|
|
7569
7633
|
avatarMood: n,
|
|
7570
|
-
ttsLang:
|
|
7571
|
-
ttsVoice: o ||
|
|
7634
|
+
ttsLang: R === "browser" ? "en-US" : i,
|
|
7635
|
+
ttsVoice: o || v.defaultVoice,
|
|
7572
7636
|
lipsyncLang: "en",
|
|
7573
7637
|
showFullAvatar: h,
|
|
7574
7638
|
bodyMovement: u,
|
|
7575
7639
|
movementIntensity: r
|
|
7576
|
-
},
|
|
7577
|
-
ttsEndpoint:
|
|
7578
|
-
ttsApikey:
|
|
7579
|
-
ttsService:
|
|
7640
|
+
}, E = {
|
|
7641
|
+
ttsEndpoint: v.endpoint,
|
|
7642
|
+
ttsApikey: v.apiKey,
|
|
7643
|
+
ttsService: R,
|
|
7580
7644
|
lipsyncModules: ["en"],
|
|
7581
7645
|
cameraView: a
|
|
7582
|
-
}, W =
|
|
7646
|
+
}, W = F(async () => {
|
|
7583
7647
|
if (!(!k.current || y.current))
|
|
7584
7648
|
try {
|
|
7585
|
-
|
|
7649
|
+
Z(!0), se(null), y.current = new Ne(k.current, E), console.log("Avatar config being passed:", {
|
|
7586
7650
|
url: w.url,
|
|
7587
7651
|
body: w.body,
|
|
7588
7652
|
avatarMood: w.avatarMood
|
|
@@ -7591,7 +7655,7 @@ const gt = Me(({
|
|
|
7591
7655
|
const L = Math.min(100, Math.round(ne.loaded / ne.total * 100));
|
|
7592
7656
|
d(L);
|
|
7593
7657
|
}
|
|
7594
|
-
}), y.current?.avatar && console.log("Avatar body after initialization:", y.current.avatar.body),
|
|
7658
|
+
}), y.current?.avatar && console.log("Avatar body after initialization:", y.current.avatar.body), Z(!1), pe(!0), c(y.current);
|
|
7595
7659
|
const C = () => {
|
|
7596
7660
|
document.visibilityState === "visible" ? y.current?.start() : y.current?.stop();
|
|
7597
7661
|
};
|
|
@@ -7599,13 +7663,13 @@ const gt = Me(({
|
|
|
7599
7663
|
document.removeEventListener("visibilitychange", C);
|
|
7600
7664
|
};
|
|
7601
7665
|
} catch (C) {
|
|
7602
|
-
console.error("Error initializing TalkingHead:", C), se(C.message || "Failed to initialize avatar"),
|
|
7666
|
+
console.error("Error initializing TalkingHead:", C), se(C.message || "Failed to initialize avatar"), Z(!1), g(C);
|
|
7603
7667
|
}
|
|
7604
7668
|
}, []);
|
|
7605
7669
|
de(() => (W(), () => {
|
|
7606
7670
|
y.current && (y.current.stop(), y.current.dispose(), y.current = null);
|
|
7607
7671
|
}), [W]);
|
|
7608
|
-
const K =
|
|
7672
|
+
const K = F(async () => {
|
|
7609
7673
|
if (y.current)
|
|
7610
7674
|
try {
|
|
7611
7675
|
const C = y.current.audioCtx || y.current.audioContext;
|
|
@@ -7613,7 +7677,7 @@ const gt = Me(({
|
|
|
7613
7677
|
} catch (C) {
|
|
7614
7678
|
console.warn("Failed to resume audio context:", C);
|
|
7615
7679
|
}
|
|
7616
|
-
}, []), j =
|
|
7680
|
+
}, []), j = F(async (C, ne = {}) => {
|
|
7617
7681
|
if (!y.current || !ae) {
|
|
7618
7682
|
console.warn("Avatar not ready for speaking");
|
|
7619
7683
|
return;
|
|
@@ -7622,59 +7686,59 @@ const gt = Me(({
|
|
|
7622
7686
|
console.warn("No text provided to speak");
|
|
7623
7687
|
return;
|
|
7624
7688
|
}
|
|
7625
|
-
await K(), S.current = { remainingText: null, originalText: null, options: null }, G.current = [],
|
|
7626
|
-
const L = C.split(/[.!?]+/).filter((
|
|
7689
|
+
await K(), S.current = { remainingText: null, originalText: null, options: null }, G.current = [], P.current = { text: C, options: ne }, D.current && (clearInterval(D.current), D.current = null), le(!1), J.current = !1;
|
|
7690
|
+
const L = C.split(/[.!?]+/).filter((B) => B.trim().length > 0);
|
|
7627
7691
|
G.current = L;
|
|
7628
|
-
const
|
|
7692
|
+
const N = {
|
|
7629
7693
|
lipsyncLang: ne.lipsyncLang || "en",
|
|
7630
7694
|
onSpeechEnd: () => {
|
|
7631
|
-
|
|
7695
|
+
D.current && (clearInterval(D.current), D.current = null), ne.onSpeechEnd && ne.onSpeechEnd(), x();
|
|
7632
7696
|
}
|
|
7633
7697
|
};
|
|
7634
7698
|
try {
|
|
7635
|
-
y.current.speakText(C,
|
|
7636
|
-
} catch (
|
|
7637
|
-
console.error("Error speaking text:",
|
|
7699
|
+
y.current.speakText(C, N);
|
|
7700
|
+
} catch (B) {
|
|
7701
|
+
console.error("Error speaking text:", B), se(B.message || "Failed to speak text");
|
|
7638
7702
|
}
|
|
7639
7703
|
}, [ae, x, K]);
|
|
7640
7704
|
de(() => {
|
|
7641
|
-
ae &&
|
|
7642
|
-
}, [ae,
|
|
7643
|
-
const q =
|
|
7705
|
+
ae && X && m && y.current && j(X);
|
|
7706
|
+
}, [ae, X, m, j]);
|
|
7707
|
+
const q = F(() => {
|
|
7644
7708
|
if (y.current)
|
|
7645
7709
|
try {
|
|
7646
7710
|
const C = y.current.isSpeaking || !1, ne = y.current.audioPlaylist || [], L = y.current.speechQueue || [];
|
|
7647
7711
|
if (C || ne.length > 0 || L.length > 0) {
|
|
7648
|
-
|
|
7649
|
-
let
|
|
7650
|
-
L.length > 0 && (
|
|
7651
|
-
remainingText:
|
|
7652
|
-
originalText:
|
|
7653
|
-
options:
|
|
7654
|
-
}, y.current.speechQueue.length = 0, y.current.pauseSpeaking(), le(!0),
|
|
7712
|
+
D.current && (clearInterval(D.current), D.current = null);
|
|
7713
|
+
let N = "";
|
|
7714
|
+
L.length > 0 && (N = L.map((B) => B.text && Array.isArray(B.text) ? B.text.map(($) => $.word).join(" ") : B.text || "").join(" ")), S.current = {
|
|
7715
|
+
remainingText: N || null,
|
|
7716
|
+
originalText: P.current?.text || null,
|
|
7717
|
+
options: P.current?.options || null
|
|
7718
|
+
}, y.current.speechQueue.length = 0, y.current.pauseSpeaking(), le(!0), J.current = !0;
|
|
7655
7719
|
}
|
|
7656
7720
|
} catch (C) {
|
|
7657
7721
|
console.warn("Error pausing speech:", C);
|
|
7658
7722
|
}
|
|
7659
|
-
}, []), Le =
|
|
7660
|
-
if (!(!y.current || !
|
|
7723
|
+
}, []), Le = F(async () => {
|
|
7724
|
+
if (!(!y.current || !te))
|
|
7661
7725
|
try {
|
|
7662
|
-
await K(), le(!1),
|
|
7663
|
-
const C = S.current?.remainingText, ne = S.current?.originalText ||
|
|
7664
|
-
|
|
7726
|
+
await K(), le(!1), J.current = !1;
|
|
7727
|
+
const C = S.current?.remainingText, ne = S.current?.originalText || P.current?.text, L = S.current?.options || P.current?.options || {}, N = C || ne;
|
|
7728
|
+
N && j(N, L);
|
|
7665
7729
|
} catch (C) {
|
|
7666
|
-
console.warn("Error resuming speech:", C), le(!1),
|
|
7730
|
+
console.warn("Error resuming speech:", C), le(!1), J.current = !1;
|
|
7667
7731
|
}
|
|
7668
|
-
}, [
|
|
7669
|
-
y.current && (y.current.stopSpeaking(),
|
|
7732
|
+
}, [te, j, K]), we = F(() => {
|
|
7733
|
+
y.current && (y.current.stopSpeaking(), D.current && (clearInterval(D.current), D.current = null), le(!1), J.current = !1);
|
|
7670
7734
|
}, []);
|
|
7671
|
-
return Ee(
|
|
7735
|
+
return Ee(T, () => ({
|
|
7672
7736
|
speakText: j,
|
|
7673
7737
|
pauseSpeaking: q,
|
|
7674
7738
|
resumeSpeaking: Le,
|
|
7675
7739
|
stopSpeaking: we,
|
|
7676
7740
|
resumeAudioContext: K,
|
|
7677
|
-
isPaused: () =>
|
|
7741
|
+
isPaused: () => te,
|
|
7678
7742
|
setMood: (C) => y.current?.setMood(C),
|
|
7679
7743
|
setBodyMovement: (C) => {
|
|
7680
7744
|
y.current && y.current.setBodyMovement(C);
|
|
@@ -7685,11 +7749,11 @@ const gt = Me(({
|
|
|
7685
7749
|
playReaction: (C) => y.current?.playReaction(C),
|
|
7686
7750
|
playCelebration: () => y.current?.playCelebration(),
|
|
7687
7751
|
setShowFullAvatar: (C) => {
|
|
7688
|
-
y.current && (
|
|
7752
|
+
y.current && (M.current = C, y.current.setShowFullAvatar(C));
|
|
7689
7753
|
},
|
|
7690
7754
|
isReady: ae,
|
|
7691
7755
|
talkingHead: y.current
|
|
7692
|
-
})), /* @__PURE__ */ Pe("div", { className: `simple-talking-avatar-container ${
|
|
7756
|
+
})), /* @__PURE__ */ Pe("div", { className: `simple-talking-avatar-container ${b}`, style: I, children: [
|
|
7693
7757
|
/* @__PURE__ */ me(
|
|
7694
7758
|
"div",
|
|
7695
7759
|
{
|
|
@@ -7702,7 +7766,7 @@ const gt = Me(({
|
|
|
7702
7766
|
}
|
|
7703
7767
|
}
|
|
7704
7768
|
),
|
|
7705
|
-
|
|
7769
|
+
Q && /* @__PURE__ */ me("div", { className: "loading-overlay", style: {
|
|
7706
7770
|
position: "absolute",
|
|
7707
7771
|
top: "50%",
|
|
7708
7772
|
left: "50%",
|
|
@@ -7711,7 +7775,7 @@ const gt = Me(({
|
|
|
7711
7775
|
fontSize: "18px",
|
|
7712
7776
|
zIndex: 10
|
|
7713
7777
|
}, children: "Loading avatar..." }),
|
|
7714
|
-
|
|
7778
|
+
ee && /* @__PURE__ */ me("div", { className: "error-overlay", style: {
|
|
7715
7779
|
position: "absolute",
|
|
7716
7780
|
top: "50%",
|
|
7717
7781
|
left: "50%",
|
|
@@ -7722,12 +7786,12 @@ const gt = Me(({
|
|
|
7722
7786
|
zIndex: 10,
|
|
7723
7787
|
padding: "20px",
|
|
7724
7788
|
borderRadius: "8px"
|
|
7725
|
-
}, children:
|
|
7789
|
+
}, children: ee })
|
|
7726
7790
|
] });
|
|
7727
7791
|
});
|
|
7728
7792
|
gt.displayName = "SimpleTalkingAvatar";
|
|
7729
7793
|
const yt = Me(({
|
|
7730
|
-
curriculumData:
|
|
7794
|
+
curriculumData: X = null,
|
|
7731
7795
|
avatarConfig: t = {},
|
|
7732
7796
|
animations: e = {},
|
|
7733
7797
|
onLessonStart: n = () => {
|
|
@@ -7742,7 +7806,7 @@ const yt = Me(({
|
|
|
7742
7806
|
},
|
|
7743
7807
|
autoStart: u = !1
|
|
7744
7808
|
}, r) => {
|
|
7745
|
-
const h =
|
|
7809
|
+
const h = O(null), a = O({
|
|
7746
7810
|
currentModuleIndex: 0,
|
|
7747
7811
|
currentLessonIndex: 0,
|
|
7748
7812
|
currentQuestionIndex: 0,
|
|
@@ -7752,18 +7816,18 @@ const yt = Me(({
|
|
|
7752
7816
|
curriculumCompleted: !1,
|
|
7753
7817
|
score: 0,
|
|
7754
7818
|
totalQuestions: 0
|
|
7755
|
-
}), c =
|
|
7819
|
+
}), c = O({
|
|
7756
7820
|
onLessonStart: n,
|
|
7757
7821
|
onLessonComplete: i,
|
|
7758
7822
|
onQuestionAnswer: s,
|
|
7759
7823
|
onCurriculumComplete: o,
|
|
7760
7824
|
onCustomAction: l
|
|
7761
|
-
}), d =
|
|
7825
|
+
}), d = O(null), g = O(null), x = O(null), b = O(null), I = O(null), H = O(null), m = O(null), T = O(X?.curriculum || {
|
|
7762
7826
|
title: "Default Curriculum",
|
|
7763
7827
|
description: "No curriculum data provided",
|
|
7764
7828
|
language: "en",
|
|
7765
7829
|
modules: []
|
|
7766
|
-
}), k =
|
|
7830
|
+
}), k = O({
|
|
7767
7831
|
avatarUrl: t.avatarUrl || "/avatars/brunette.glb",
|
|
7768
7832
|
avatarBody: t.avatarBody || "F",
|
|
7769
7833
|
mood: t.mood || "happy",
|
|
@@ -7786,7 +7850,7 @@ const yt = Me(({
|
|
|
7786
7850
|
onCustomAction: l
|
|
7787
7851
|
};
|
|
7788
7852
|
}, [n, i, s, o, l]), de(() => {
|
|
7789
|
-
|
|
7853
|
+
T.current = X?.curriculum || {
|
|
7790
7854
|
title: "Default Curriculum",
|
|
7791
7855
|
description: "No curriculum data provided",
|
|
7792
7856
|
language: "en",
|
|
@@ -7805,24 +7869,24 @@ const yt = Me(({
|
|
|
7805
7869
|
animations: e,
|
|
7806
7870
|
lipsyncLang: "en"
|
|
7807
7871
|
};
|
|
7808
|
-
}, [
|
|
7809
|
-
const y =
|
|
7872
|
+
}, [X, t, e]);
|
|
7873
|
+
const y = F(() => (T.current || { modules: [] }).modules[a.current.currentModuleIndex]?.lessons[a.current.currentLessonIndex], []), M = F(() => y()?.questions[a.current.currentQuestionIndex], [y]), P = F((R, v) => v.type === "multiple_choice" || v.type === "true_false" ? R === v.answer : v.type === "code_test" && typeof R == "object" && R !== null ? R.passed === !0 : !1, []), D = F(() => {
|
|
7810
7874
|
a.current.lessonCompleted = !0, a.current.isQuestionMode = !1;
|
|
7811
|
-
const
|
|
7812
|
-
let
|
|
7813
|
-
if (a.current.totalQuestions > 0 ?
|
|
7875
|
+
const R = a.current.totalQuestions > 0 ? Math.round(a.current.score / a.current.totalQuestions * 100) : 100;
|
|
7876
|
+
let v = "Congratulations! You've completed this lesson";
|
|
7877
|
+
if (a.current.totalQuestions > 0 ? v += ` You got ${a.current.score} correct out of ${a.current.totalQuestions} question${a.current.totalQuestions === 1 ? "" : "s"}, achieving a score of ${R} percent. ` : v += "! ", R >= 80 ? v += "Excellent work! You have a great understanding of this topic." : R >= 60 ? v += "Good job! You understand most of the concepts." : v += "Keep practicing! You're making progress.", c.current.onLessonComplete({
|
|
7814
7878
|
moduleIndex: a.current.currentModuleIndex,
|
|
7815
7879
|
lessonIndex: a.current.currentLessonIndex,
|
|
7816
7880
|
score: a.current.score,
|
|
7817
7881
|
totalQuestions: a.current.totalQuestions,
|
|
7818
|
-
percentage:
|
|
7882
|
+
percentage: R
|
|
7819
7883
|
}), c.current.onCustomAction({
|
|
7820
7884
|
type: "lessonComplete",
|
|
7821
7885
|
moduleIndex: a.current.currentModuleIndex,
|
|
7822
7886
|
lessonIndex: a.current.currentLessonIndex,
|
|
7823
7887
|
score: a.current.score,
|
|
7824
7888
|
totalQuestions: a.current.totalQuestions,
|
|
7825
|
-
percentage:
|
|
7889
|
+
percentage: R
|
|
7826
7890
|
}), h.current) {
|
|
7827
7891
|
if (h.current.setMood("happy"), e.lessonComplete)
|
|
7828
7892
|
try {
|
|
@@ -7830,8 +7894,8 @@ const yt = Me(({
|
|
|
7830
7894
|
} catch {
|
|
7831
7895
|
h.current.playCelebration();
|
|
7832
7896
|
}
|
|
7833
|
-
const w =
|
|
7834
|
-
h.current.speakText(
|
|
7897
|
+
const w = T.current || { modules: [] }, E = w.modules[a.current.currentModuleIndex], W = a.current.currentLessonIndex < (E?.lessons?.length || 0) - 1, K = a.current.currentModuleIndex < (w.modules?.length || 0) - 1, j = W || K, q = k.current || { lipsyncLang: "en" };
|
|
7898
|
+
h.current.speakText(v, {
|
|
7835
7899
|
lipsyncLang: q.lipsyncLang,
|
|
7836
7900
|
onSpeechEnd: () => {
|
|
7837
7901
|
c.current.onCustomAction({
|
|
@@ -7840,18 +7904,18 @@ const yt = Me(({
|
|
|
7840
7904
|
lessonIndex: a.current.currentLessonIndex,
|
|
7841
7905
|
score: a.current.score,
|
|
7842
7906
|
totalQuestions: a.current.totalQuestions,
|
|
7843
|
-
percentage:
|
|
7907
|
+
percentage: R,
|
|
7844
7908
|
hasNextLesson: j
|
|
7845
7909
|
});
|
|
7846
7910
|
}
|
|
7847
7911
|
});
|
|
7848
7912
|
}
|
|
7849
|
-
}, [e.lessonComplete]),
|
|
7913
|
+
}, [e.lessonComplete]), J = F(() => {
|
|
7850
7914
|
a.current.curriculumCompleted = !0;
|
|
7851
|
-
const
|
|
7915
|
+
const R = T.current || { modules: [] };
|
|
7852
7916
|
if (c.current.onCurriculumComplete({
|
|
7853
|
-
modules:
|
|
7854
|
-
totalLessons:
|
|
7917
|
+
modules: R.modules.length,
|
|
7918
|
+
totalLessons: R.modules.reduce((v, w) => v + w.lessons.length, 0)
|
|
7855
7919
|
}), h.current) {
|
|
7856
7920
|
if (h.current.setMood("celebrating"), e.curriculumComplete)
|
|
7857
7921
|
try {
|
|
@@ -7859,99 +7923,99 @@ const yt = Me(({
|
|
|
7859
7923
|
} catch {
|
|
7860
7924
|
h.current.playCelebration();
|
|
7861
7925
|
}
|
|
7862
|
-
const
|
|
7863
|
-
h.current.speakText("Amazing! You've completed the entire curriculum! You're now ready to move on to more advanced topics. Well done!", { lipsyncLang:
|
|
7926
|
+
const v = k.current || { lipsyncLang: "en" };
|
|
7927
|
+
h.current.speakText("Amazing! You've completed the entire curriculum! You're now ready to move on to more advanced topics. Well done!", { lipsyncLang: v.lipsyncLang });
|
|
7864
7928
|
}
|
|
7865
|
-
}, [e.curriculumComplete]), S =
|
|
7866
|
-
const
|
|
7867
|
-
a.current.isQuestionMode = !0, a.current.currentQuestionIndex = 0, a.current.totalQuestions =
|
|
7868
|
-
const
|
|
7869
|
-
|
|
7929
|
+
}, [e.curriculumComplete]), S = F(() => {
|
|
7930
|
+
const R = y();
|
|
7931
|
+
a.current.isQuestionMode = !0, a.current.currentQuestionIndex = 0, a.current.totalQuestions = R?.questions?.length || 0, a.current.score = 0;
|
|
7932
|
+
const v = M();
|
|
7933
|
+
v && c.current.onCustomAction({
|
|
7870
7934
|
type: "questionStart",
|
|
7871
7935
|
moduleIndex: a.current.currentModuleIndex,
|
|
7872
7936
|
lessonIndex: a.current.currentLessonIndex,
|
|
7873
7937
|
questionIndex: a.current.currentQuestionIndex,
|
|
7874
7938
|
totalQuestions: a.current.totalQuestions,
|
|
7875
|
-
question:
|
|
7939
|
+
question: v,
|
|
7876
7940
|
score: a.current.score
|
|
7877
7941
|
});
|
|
7878
7942
|
const w = () => {
|
|
7879
|
-
if (!h.current || !
|
|
7943
|
+
if (!h.current || !v) return;
|
|
7880
7944
|
if (h.current.setMood("happy"), e.questionStart)
|
|
7881
7945
|
try {
|
|
7882
7946
|
h.current.playAnimation(e.questionStart, !0);
|
|
7883
7947
|
} catch (W) {
|
|
7884
7948
|
console.warn("Failed to play questionStart animation:", W);
|
|
7885
7949
|
}
|
|
7886
|
-
const
|
|
7887
|
-
|
|
7950
|
+
const E = k.current || { lipsyncLang: "en" };
|
|
7951
|
+
v.type === "code_test" ? h.current.speakText(`Let's test your coding skills! Here's your first challenge: ${v.question}`, { lipsyncLang: E.lipsyncLang }) : v.type === "multiple_choice" ? h.current.speakText(`Now let me ask you some questions. Here's the first one: ${v.question}`, { lipsyncLang: E.lipsyncLang }) : v.type === "true_false" ? h.current.speakText(`Let's start with some true or false questions. First question: ${v.question}`, { lipsyncLang: E.lipsyncLang }) : h.current.speakText(`Now let me ask you some questions. Here's the first one: ${v.question}`, { lipsyncLang: E.lipsyncLang });
|
|
7888
7952
|
};
|
|
7889
|
-
if (h.current && h.current.isReady &&
|
|
7953
|
+
if (h.current && h.current.isReady && v)
|
|
7890
7954
|
w();
|
|
7891
7955
|
else if (h.current && h.current.isReady) {
|
|
7892
|
-
const
|
|
7893
|
-
h.current.speakText("Now let me ask you some questions to test your understanding.", { lipsyncLang:
|
|
7956
|
+
const E = k.current || { lipsyncLang: "en" };
|
|
7957
|
+
h.current.speakText("Now let me ask you some questions to test your understanding.", { lipsyncLang: E.lipsyncLang });
|
|
7894
7958
|
} else {
|
|
7895
|
-
const
|
|
7896
|
-
h.current && h.current.isReady && (clearInterval(
|
|
7959
|
+
const E = setInterval(() => {
|
|
7960
|
+
h.current && h.current.isReady && (clearInterval(E), v && w());
|
|
7897
7961
|
}, 100);
|
|
7898
7962
|
setTimeout(() => {
|
|
7899
|
-
clearInterval(
|
|
7963
|
+
clearInterval(E);
|
|
7900
7964
|
}, 5e3);
|
|
7901
7965
|
}
|
|
7902
|
-
}, [e.questionStart, y,
|
|
7903
|
-
const
|
|
7904
|
-
if (a.current.currentQuestionIndex < (
|
|
7966
|
+
}, [e.questionStart, y, M]), G = F(() => {
|
|
7967
|
+
const R = y();
|
|
7968
|
+
if (a.current.currentQuestionIndex < (R?.questions?.length || 0) - 1) {
|
|
7905
7969
|
h.current && h.current.stopSpeaking && h.current.stopSpeaking(), a.current.currentQuestionIndex += 1;
|
|
7906
|
-
const
|
|
7907
|
-
|
|
7970
|
+
const v = M();
|
|
7971
|
+
v && c.current.onCustomAction({
|
|
7908
7972
|
type: "nextQuestion",
|
|
7909
7973
|
moduleIndex: a.current.currentModuleIndex,
|
|
7910
7974
|
lessonIndex: a.current.currentLessonIndex,
|
|
7911
7975
|
questionIndex: a.current.currentQuestionIndex,
|
|
7912
7976
|
totalQuestions: a.current.totalQuestions,
|
|
7913
|
-
question:
|
|
7977
|
+
question: v,
|
|
7914
7978
|
score: a.current.score
|
|
7915
7979
|
});
|
|
7916
7980
|
const w = () => {
|
|
7917
|
-
if (!h.current || !
|
|
7981
|
+
if (!h.current || !v) return;
|
|
7918
7982
|
if (h.current.setMood("happy"), h.current.setBodyMovement("idle"), e.nextQuestion)
|
|
7919
7983
|
try {
|
|
7920
7984
|
h.current.playAnimation(e.nextQuestion, !0);
|
|
7921
7985
|
} catch (q) {
|
|
7922
7986
|
console.warn("Failed to play nextQuestion animation:", q);
|
|
7923
7987
|
}
|
|
7924
|
-
const
|
|
7925
|
-
if (
|
|
7926
|
-
const q = j ? `Great! Here's your final coding challenge: ${
|
|
7988
|
+
const E = k.current || { lipsyncLang: "en" }, K = y()?.questions?.length || 0, j = a.current.currentQuestionIndex >= K - 1;
|
|
7989
|
+
if (v.type === "code_test") {
|
|
7990
|
+
const q = j ? `Great! Here's your final coding challenge: ${v.question}` : `Great! Now let's move on to your next coding challenge: ${v.question}`;
|
|
7927
7991
|
h.current.speakText(q, {
|
|
7928
|
-
lipsyncLang:
|
|
7992
|
+
lipsyncLang: E.lipsyncLang
|
|
7929
7993
|
});
|
|
7930
|
-
} else if (
|
|
7931
|
-
const q = j ? `Alright! Here's your final question: ${
|
|
7994
|
+
} else if (v.type === "multiple_choice") {
|
|
7995
|
+
const q = j ? `Alright! Here's your final question: ${v.question}` : `Alright! Here's your next question: ${v.question}`;
|
|
7932
7996
|
h.current.speakText(q, {
|
|
7933
|
-
lipsyncLang:
|
|
7997
|
+
lipsyncLang: E.lipsyncLang
|
|
7934
7998
|
});
|
|
7935
|
-
} else if (
|
|
7936
|
-
const q = j ? `Now let's try this final one: ${
|
|
7999
|
+
} else if (v.type === "true_false") {
|
|
8000
|
+
const q = j ? `Now let's try this final one: ${v.question}` : `Now let's try this one: ${v.question}`;
|
|
7937
8001
|
h.current.speakText(q, {
|
|
7938
|
-
lipsyncLang:
|
|
8002
|
+
lipsyncLang: E.lipsyncLang
|
|
7939
8003
|
});
|
|
7940
8004
|
} else {
|
|
7941
|
-
const q = j ? `Here's your final question: ${
|
|
8005
|
+
const q = j ? `Here's your final question: ${v.question}` : `Here's the next question: ${v.question}`;
|
|
7942
8006
|
h.current.speakText(q, {
|
|
7943
|
-
lipsyncLang:
|
|
8007
|
+
lipsyncLang: E.lipsyncLang
|
|
7944
8008
|
});
|
|
7945
8009
|
}
|
|
7946
8010
|
};
|
|
7947
|
-
if (h.current && h.current.isReady &&
|
|
8011
|
+
if (h.current && h.current.isReady && v)
|
|
7948
8012
|
w();
|
|
7949
|
-
else if (
|
|
7950
|
-
const
|
|
7951
|
-
h.current && h.current.isReady && (clearInterval(
|
|
8013
|
+
else if (v) {
|
|
8014
|
+
const E = setInterval(() => {
|
|
8015
|
+
h.current && h.current.isReady && (clearInterval(E), w());
|
|
7952
8016
|
}, 100);
|
|
7953
8017
|
setTimeout(() => {
|
|
7954
|
-
clearInterval(
|
|
8018
|
+
clearInterval(E);
|
|
7955
8019
|
}, 5e3);
|
|
7956
8020
|
}
|
|
7957
8021
|
} else
|
|
@@ -7962,11 +8026,11 @@ const yt = Me(({
|
|
|
7962
8026
|
totalQuestions: a.current.totalQuestions,
|
|
7963
8027
|
score: a.current.score
|
|
7964
8028
|
});
|
|
7965
|
-
}, [e.nextQuestion, y,
|
|
7966
|
-
const
|
|
7967
|
-
if (a.current.currentLessonIndex < (
|
|
8029
|
+
}, [e.nextQuestion, y, M]), Q = F(() => {
|
|
8030
|
+
const R = T.current || { modules: [] }, v = R.modules[a.current.currentModuleIndex];
|
|
8031
|
+
if (a.current.currentLessonIndex < (v?.lessons?.length || 0) - 1) {
|
|
7968
8032
|
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;
|
|
7969
|
-
const
|
|
8033
|
+
const E = R.modules[a.current.currentModuleIndex], W = a.current.currentLessonIndex < (E?.lessons?.length || 0) - 1, K = a.current.currentModuleIndex < (R.modules?.length || 0) - 1, j = W || K;
|
|
7970
8034
|
c.current.onCustomAction({
|
|
7971
8035
|
type: "lessonStart",
|
|
7972
8036
|
moduleIndex: a.current.currentModuleIndex,
|
|
@@ -7977,9 +8041,9 @@ const yt = Me(({
|
|
|
7977
8041
|
lessonIndex: a.current.currentLessonIndex,
|
|
7978
8042
|
lesson: y()
|
|
7979
8043
|
}), h.current && (h.current.setMood("happy"), h.current.setBodyMovement("idle"));
|
|
7980
|
-
} else if (a.current.currentModuleIndex < (
|
|
8044
|
+
} else if (a.current.currentModuleIndex < (R.modules?.length || 0) - 1) {
|
|
7981
8045
|
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;
|
|
7982
|
-
const W =
|
|
8046
|
+
const W = R.modules[a.current.currentModuleIndex], K = a.current.currentLessonIndex < (W?.lessons?.length || 0) - 1, j = a.current.currentModuleIndex < (R.modules?.length || 0) - 1, q = K || j;
|
|
7983
8047
|
c.current.onCustomAction({
|
|
7984
8048
|
type: "lessonStart",
|
|
7985
8049
|
moduleIndex: a.current.currentModuleIndex,
|
|
@@ -7991,16 +8055,16 @@ const yt = Me(({
|
|
|
7991
8055
|
lesson: y()
|
|
7992
8056
|
}), h.current && (h.current.setMood("happy"), h.current.setBodyMovement("idle"));
|
|
7993
8057
|
} else
|
|
7994
|
-
|
|
7995
|
-
}, []),
|
|
7996
|
-
const
|
|
7997
|
-
let
|
|
7998
|
-
if (
|
|
7999
|
-
const w =
|
|
8000
|
-
|
|
8058
|
+
I.current && I.current();
|
|
8059
|
+
}, []), Z = F(() => {
|
|
8060
|
+
const R = y();
|
|
8061
|
+
let v = null;
|
|
8062
|
+
if (R?.avatar_script && R?.body) {
|
|
8063
|
+
const w = R.avatar_script.trim(), E = R.body.trim(), W = w.match(/[.!?]$/) ? " " : ". ";
|
|
8064
|
+
v = `${w}${W}${E}`;
|
|
8001
8065
|
} else
|
|
8002
|
-
|
|
8003
|
-
if (h.current && h.current.isReady &&
|
|
8066
|
+
v = R?.avatar_script || R?.body || null;
|
|
8067
|
+
if (h.current && h.current.isReady && v) {
|
|
8004
8068
|
a.current.isTeaching = !0, a.current.isQuestionMode = !1, a.current.score = 0, a.current.totalQuestions = 0, h.current.setMood("happy");
|
|
8005
8069
|
let w = !1;
|
|
8006
8070
|
if (e.teaching)
|
|
@@ -8010,44 +8074,44 @@ const yt = Me(({
|
|
|
8010
8074
|
console.warn("Failed to play teaching animation:", W);
|
|
8011
8075
|
}
|
|
8012
8076
|
w || h.current.setBodyMovement("gesturing");
|
|
8013
|
-
const
|
|
8077
|
+
const E = k.current || { lipsyncLang: "en" };
|
|
8014
8078
|
c.current.onLessonStart({
|
|
8015
8079
|
moduleIndex: a.current.currentModuleIndex,
|
|
8016
8080
|
lessonIndex: a.current.currentLessonIndex,
|
|
8017
|
-
lesson:
|
|
8081
|
+
lesson: R
|
|
8018
8082
|
}), c.current.onCustomAction({
|
|
8019
8083
|
type: "teachingStart",
|
|
8020
8084
|
moduleIndex: a.current.currentModuleIndex,
|
|
8021
8085
|
lessonIndex: a.current.currentLessonIndex,
|
|
8022
|
-
lesson:
|
|
8023
|
-
}), h.current.speakText(
|
|
8024
|
-
lipsyncLang:
|
|
8086
|
+
lesson: R
|
|
8087
|
+
}), h.current.speakText(v, {
|
|
8088
|
+
lipsyncLang: E.lipsyncLang,
|
|
8025
8089
|
onSpeechEnd: () => {
|
|
8026
8090
|
a.current.isTeaching = !1, c.current.onCustomAction({
|
|
8027
8091
|
type: "teachingComplete",
|
|
8028
8092
|
moduleIndex: a.current.currentModuleIndex,
|
|
8029
8093
|
lessonIndex: a.current.currentLessonIndex,
|
|
8030
|
-
lesson:
|
|
8031
|
-
hasQuestions:
|
|
8032
|
-
}),
|
|
8094
|
+
lesson: R,
|
|
8095
|
+
hasQuestions: R.questions && R.questions.length > 0
|
|
8096
|
+
}), R?.code_example && c.current.onCustomAction({
|
|
8033
8097
|
type: "codeExampleReady",
|
|
8034
8098
|
moduleIndex: a.current.currentModuleIndex,
|
|
8035
8099
|
lessonIndex: a.current.currentLessonIndex,
|
|
8036
|
-
lesson:
|
|
8037
|
-
codeExample:
|
|
8100
|
+
lesson: R,
|
|
8101
|
+
codeExample: R.code_example
|
|
8038
8102
|
});
|
|
8039
8103
|
}
|
|
8040
8104
|
});
|
|
8041
8105
|
}
|
|
8042
|
-
}, [e.teaching, y]),
|
|
8043
|
-
const
|
|
8106
|
+
}, [e.teaching, y]), ee = F((R) => {
|
|
8107
|
+
const v = M(), w = P(R, v);
|
|
8044
8108
|
if (w && (a.current.score += 1), c.current.onQuestionAnswer({
|
|
8045
8109
|
moduleIndex: a.current.currentModuleIndex,
|
|
8046
8110
|
lessonIndex: a.current.currentLessonIndex,
|
|
8047
8111
|
questionIndex: a.current.currentQuestionIndex,
|
|
8048
|
-
answer:
|
|
8112
|
+
answer: R,
|
|
8049
8113
|
isCorrect: w,
|
|
8050
|
-
question:
|
|
8114
|
+
question: v
|
|
8051
8115
|
}), h.current)
|
|
8052
8116
|
if (w) {
|
|
8053
8117
|
if (h.current.setMood("happy"), e.correct)
|
|
@@ -8061,7 +8125,7 @@ const yt = Me(({
|
|
|
8061
8125
|
a.current.currentQuestionIndex >= W - 1;
|
|
8062
8126
|
const K = a.current.currentQuestionIndex < W - 1;
|
|
8063
8127
|
console.log("[CurriculumLearning] Answer feedback - questionIndex:", a.current.currentQuestionIndex, "totalQuestions:", W, "hasNextQuestion:", K);
|
|
8064
|
-
const j =
|
|
8128
|
+
const j = v.type === "code_test" ? `Great job! Your code passed all the tests! ${v.explanation || ""}` : `Excellent! That's correct! ${v.explanation || ""}`, q = k.current || { lipsyncLang: "en" };
|
|
8065
8129
|
h.current.speakText(j, {
|
|
8066
8130
|
lipsyncLang: q.lipsyncLang,
|
|
8067
8131
|
onSpeechEnd: () => {
|
|
@@ -8087,7 +8151,7 @@ const yt = Me(({
|
|
|
8087
8151
|
h.current.setBodyMovement("gesturing");
|
|
8088
8152
|
const W = y()?.questions?.length || 0, K = a.current.currentQuestionIndex >= W - 1, j = a.current.currentQuestionIndex < W - 1;
|
|
8089
8153
|
console.log("[CurriculumLearning] Answer feedback (incorrect) - questionIndex:", a.current.currentQuestionIndex, "totalQuestions:", W, "hasNextQuestion:", j);
|
|
8090
|
-
const q =
|
|
8154
|
+
const q = v.type === "code_test" ? `Your code didn't pass all the tests. ${v.explanation || "Try again!"}` : `Not quite right, but don't worry! ${v.explanation || ""}${K ? "" : " Let's move on to the next question."}`, Le = k.current || { lipsyncLang: "en" };
|
|
8091
8155
|
h.current.speakText(q, {
|
|
8092
8156
|
lipsyncLang: Le.lipsyncLang,
|
|
8093
8157
|
onSpeechEnd: () => {
|
|
@@ -8118,25 +8182,25 @@ const yt = Me(({
|
|
|
8118
8182
|
avatarNotReady: !0
|
|
8119
8183
|
});
|
|
8120
8184
|
}
|
|
8121
|
-
}, [e.correct, e.incorrect,
|
|
8122
|
-
const
|
|
8123
|
-
if (!
|
|
8185
|
+
}, [e.correct, e.incorrect, M, y, P]), se = F((R) => {
|
|
8186
|
+
const v = M();
|
|
8187
|
+
if (!R || typeof R != "object") {
|
|
8124
8188
|
console.error("Invalid code test result format. Expected object with {passed: boolean, ...}");
|
|
8125
8189
|
return;
|
|
8126
8190
|
}
|
|
8127
|
-
if (
|
|
8191
|
+
if (v?.type !== "code_test") {
|
|
8128
8192
|
console.warn("Current question is not a code test. Use handleAnswerSelect for other question types.");
|
|
8129
8193
|
return;
|
|
8130
8194
|
}
|
|
8131
8195
|
const w = {
|
|
8132
|
-
passed:
|
|
8133
|
-
results:
|
|
8134
|
-
output:
|
|
8135
|
-
error:
|
|
8136
|
-
executionTime:
|
|
8137
|
-
testCount:
|
|
8138
|
-
passedCount:
|
|
8139
|
-
failedCount:
|
|
8196
|
+
passed: R.passed === !0,
|
|
8197
|
+
results: R.results || [],
|
|
8198
|
+
output: R.output || "",
|
|
8199
|
+
error: R.error || null,
|
|
8200
|
+
executionTime: R.executionTime || null,
|
|
8201
|
+
testCount: R.testCount || 0,
|
|
8202
|
+
passedCount: R.passedCount || 0,
|
|
8203
|
+
failedCount: R.failedCount || 0
|
|
8140
8204
|
};
|
|
8141
8205
|
c.current.onCustomAction({
|
|
8142
8206
|
type: "codeTestSubmitted",
|
|
@@ -8144,45 +8208,45 @@ const yt = Me(({
|
|
|
8144
8208
|
lessonIndex: a.current.currentLessonIndex,
|
|
8145
8209
|
questionIndex: a.current.currentQuestionIndex,
|
|
8146
8210
|
testResult: w,
|
|
8147
|
-
question:
|
|
8148
|
-
}),
|
|
8149
|
-
}, [
|
|
8211
|
+
question: v
|
|
8212
|
+
}), m.current && m.current(w);
|
|
8213
|
+
}, [M, P]), ae = F(() => {
|
|
8150
8214
|
if (a.current.currentQuestionIndex > 0) {
|
|
8151
8215
|
a.current.currentQuestionIndex -= 1;
|
|
8152
|
-
const
|
|
8153
|
-
|
|
8216
|
+
const R = M();
|
|
8217
|
+
R && c.current.onCustomAction({
|
|
8154
8218
|
type: "questionStart",
|
|
8155
8219
|
moduleIndex: a.current.currentModuleIndex,
|
|
8156
8220
|
lessonIndex: a.current.currentLessonIndex,
|
|
8157
8221
|
questionIndex: a.current.currentQuestionIndex,
|
|
8158
8222
|
totalQuestions: a.current.totalQuestions,
|
|
8159
|
-
question:
|
|
8223
|
+
question: R,
|
|
8160
8224
|
score: a.current.score
|
|
8161
8225
|
});
|
|
8162
|
-
const
|
|
8163
|
-
if (!h.current || !
|
|
8226
|
+
const v = () => {
|
|
8227
|
+
if (!h.current || !R) return;
|
|
8164
8228
|
h.current.setMood("happy"), h.current.setBodyMovement("idle");
|
|
8165
8229
|
const w = k.current || { lipsyncLang: "en" };
|
|
8166
|
-
|
|
8230
|
+
R.type === "code_test" ? h.current.speakText(`Let's go back to this coding challenge: ${R.question}`, {
|
|
8167
8231
|
lipsyncLang: w.lipsyncLang
|
|
8168
|
-
}) : h.current.speakText(`Going back to: ${
|
|
8232
|
+
}) : h.current.speakText(`Going back to: ${R.question}`, {
|
|
8169
8233
|
lipsyncLang: w.lipsyncLang
|
|
8170
8234
|
});
|
|
8171
8235
|
};
|
|
8172
|
-
if (h.current && h.current.isReady &&
|
|
8173
|
-
|
|
8174
|
-
else if (
|
|
8236
|
+
if (h.current && h.current.isReady && R)
|
|
8237
|
+
v();
|
|
8238
|
+
else if (R) {
|
|
8175
8239
|
const w = setInterval(() => {
|
|
8176
|
-
h.current && h.current.isReady && (clearInterval(w),
|
|
8240
|
+
h.current && h.current.isReady && (clearInterval(w), v());
|
|
8177
8241
|
}, 100);
|
|
8178
8242
|
setTimeout(() => {
|
|
8179
8243
|
clearInterval(w);
|
|
8180
8244
|
}, 5e3);
|
|
8181
8245
|
}
|
|
8182
8246
|
}
|
|
8183
|
-
}, [
|
|
8184
|
-
const
|
|
8185
|
-
if (
|
|
8247
|
+
}, [M]), pe = F(() => {
|
|
8248
|
+
const R = T.current || { modules: [] };
|
|
8249
|
+
if (R.modules[a.current.currentModuleIndex], a.current.currentLessonIndex > 0)
|
|
8186
8250
|
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({
|
|
8187
8251
|
type: "lessonStart",
|
|
8188
8252
|
moduleIndex: a.current.currentModuleIndex,
|
|
@@ -8193,8 +8257,8 @@ const yt = Me(({
|
|
|
8193
8257
|
lesson: y()
|
|
8194
8258
|
}), h.current && (h.current.setMood("happy"), h.current.setBodyMovement("idle"));
|
|
8195
8259
|
else if (a.current.currentModuleIndex > 0) {
|
|
8196
|
-
const
|
|
8197
|
-
a.current.currentModuleIndex -= 1, a.current.currentLessonIndex = (
|
|
8260
|
+
const E = R.modules[a.current.currentModuleIndex - 1];
|
|
8261
|
+
a.current.currentModuleIndex -= 1, a.current.currentLessonIndex = (E?.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({
|
|
8198
8262
|
type: "lessonStart",
|
|
8199
8263
|
moduleIndex: a.current.currentModuleIndex,
|
|
8200
8264
|
lessonIndex: a.current.currentLessonIndex
|
|
@@ -8204,50 +8268,50 @@ const yt = Me(({
|
|
|
8204
8268
|
lesson: y()
|
|
8205
8269
|
}), h.current && (h.current.setMood("happy"), h.current.setBodyMovement("idle"));
|
|
8206
8270
|
}
|
|
8207
|
-
}, [y]),
|
|
8271
|
+
}, [y]), te = F(() => {
|
|
8208
8272
|
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;
|
|
8209
|
-
}, []), le =
|
|
8210
|
-
console.log("Avatar is ready!",
|
|
8211
|
-
const
|
|
8273
|
+
}, []), le = F((R) => {
|
|
8274
|
+
console.log("Avatar is ready!", R);
|
|
8275
|
+
const v = y(), w = v?.avatar_script || v?.body;
|
|
8212
8276
|
u && w && setTimeout(() => {
|
|
8213
8277
|
d.current && d.current();
|
|
8214
8278
|
}, 10);
|
|
8215
8279
|
}, [u, y]);
|
|
8216
8280
|
Xe(() => {
|
|
8217
|
-
d.current =
|
|
8281
|
+
d.current = Z, g.current = Q, x.current = D, b.current = G, I.current = J, H.current = S, m.current = ee;
|
|
8218
8282
|
}), Ee(r, () => ({
|
|
8219
8283
|
// Curriculum control methods
|
|
8220
|
-
startTeaching:
|
|
8284
|
+
startTeaching: Z,
|
|
8221
8285
|
startQuestions: S,
|
|
8222
|
-
handleAnswerSelect:
|
|
8286
|
+
handleAnswerSelect: ee,
|
|
8223
8287
|
handleCodeTestResult: se,
|
|
8224
8288
|
nextQuestion: G,
|
|
8225
8289
|
previousQuestion: ae,
|
|
8226
|
-
nextLesson:
|
|
8290
|
+
nextLesson: Q,
|
|
8227
8291
|
previousLesson: pe,
|
|
8228
|
-
completeLesson:
|
|
8229
|
-
completeCurriculum:
|
|
8230
|
-
resetCurriculum:
|
|
8292
|
+
completeLesson: D,
|
|
8293
|
+
completeCurriculum: J,
|
|
8294
|
+
resetCurriculum: te,
|
|
8231
8295
|
getState: () => ({ ...a.current }),
|
|
8232
|
-
getCurrentQuestion: () =>
|
|
8296
|
+
getCurrentQuestion: () => M(),
|
|
8233
8297
|
getCurrentLesson: () => y(),
|
|
8234
8298
|
// Direct access to avatar ref (always returns current value)
|
|
8235
8299
|
getAvatarRef: () => h.current,
|
|
8236
8300
|
// Convenience methods that delegate to avatar (always check current ref)
|
|
8237
|
-
speakText: async (
|
|
8301
|
+
speakText: async (R, v = {}) => {
|
|
8238
8302
|
await h.current?.resumeAudioContext?.();
|
|
8239
8303
|
const w = k.current || { lipsyncLang: "en" };
|
|
8240
|
-
h.current?.speakText(
|
|
8304
|
+
h.current?.speakText(R, { ...v, lipsyncLang: v.lipsyncLang || w.lipsyncLang });
|
|
8241
8305
|
},
|
|
8242
8306
|
resumeAudioContext: async () => {
|
|
8243
8307
|
if (h.current?.resumeAudioContext)
|
|
8244
8308
|
return await h.current.resumeAudioContext();
|
|
8245
|
-
const
|
|
8246
|
-
if (
|
|
8247
|
-
const
|
|
8248
|
-
if (
|
|
8309
|
+
const R = h.current?.talkingHead;
|
|
8310
|
+
if (R?.audioCtx) {
|
|
8311
|
+
const v = R.audioCtx;
|
|
8312
|
+
if (v.state === "suspended" || v.state === "interrupted")
|
|
8249
8313
|
try {
|
|
8250
|
-
await
|
|
8314
|
+
await v.resume(), console.log("Audio context resumed via talkingHead");
|
|
8251
8315
|
} catch (w) {
|
|
8252
8316
|
console.warn("Failed to resume audio context:", w);
|
|
8253
8317
|
}
|
|
@@ -8258,22 +8322,22 @@ const yt = Me(({
|
|
|
8258
8322
|
pauseSpeaking: () => h.current?.pauseSpeaking(),
|
|
8259
8323
|
resumeSpeaking: async () => await h.current?.resumeSpeaking(),
|
|
8260
8324
|
isPaused: () => h.current && typeof h.current.isPaused < "u" ? h.current.isPaused : !1,
|
|
8261
|
-
setMood: (
|
|
8262
|
-
playAnimation: (
|
|
8263
|
-
setBodyMovement: (
|
|
8264
|
-
setMovementIntensity: (
|
|
8325
|
+
setMood: (R) => h.current?.setMood(R),
|
|
8326
|
+
playAnimation: (R, v) => h.current?.playAnimation(R, v),
|
|
8327
|
+
setBodyMovement: (R) => h.current?.setBodyMovement(R),
|
|
8328
|
+
setMovementIntensity: (R) => h.current?.setMovementIntensity(R),
|
|
8265
8329
|
playRandomDance: () => h.current?.playRandomDance(),
|
|
8266
|
-
playReaction: (
|
|
8330
|
+
playReaction: (R) => h.current?.playReaction(R),
|
|
8267
8331
|
playCelebration: () => h.current?.playCelebration(),
|
|
8268
|
-
setShowFullAvatar: (
|
|
8269
|
-
setTimingAdjustment: (
|
|
8332
|
+
setShowFullAvatar: (R) => h.current?.setShowFullAvatar(R),
|
|
8333
|
+
setTimingAdjustment: (R) => h.current?.setTimingAdjustment(R),
|
|
8270
8334
|
lockAvatarPosition: () => h.current?.lockAvatarPosition(),
|
|
8271
8335
|
unlockAvatarPosition: () => h.current?.unlockAvatarPosition(),
|
|
8272
8336
|
// Custom action trigger
|
|
8273
|
-
triggerCustomAction: (
|
|
8337
|
+
triggerCustomAction: (R, v) => {
|
|
8274
8338
|
c.current.onCustomAction({
|
|
8275
|
-
type:
|
|
8276
|
-
...
|
|
8339
|
+
type: R,
|
|
8340
|
+
...v,
|
|
8277
8341
|
state: { ...a.current }
|
|
8278
8342
|
});
|
|
8279
8343
|
},
|
|
@@ -8281,7 +8345,7 @@ const yt = Me(({
|
|
|
8281
8345
|
handleResize: () => h.current?.handleResize(),
|
|
8282
8346
|
// Avatar readiness check (always returns current value)
|
|
8283
8347
|
isAvatarReady: () => h.current?.isReady || !1
|
|
8284
|
-
}), [
|
|
8348
|
+
}), [Z, S, ee, se, G, Q, D, J, te, M, y]);
|
|
8285
8349
|
const U = k.current || {
|
|
8286
8350
|
avatarUrl: "/avatars/brunette.glb",
|
|
8287
8351
|
avatarBody: "F",
|
|
@@ -8314,8 +8378,8 @@ const yt = Me(({
|
|
|
8314
8378
|
onReady: le,
|
|
8315
8379
|
onLoading: () => {
|
|
8316
8380
|
},
|
|
8317
|
-
onError: (
|
|
8318
|
-
console.error("Avatar error:",
|
|
8381
|
+
onError: (R) => {
|
|
8382
|
+
console.error("Avatar error:", R);
|
|
8319
8383
|
}
|
|
8320
8384
|
}
|
|
8321
8385
|
) });
|
|
@@ -8424,7 +8488,7 @@ const Ge = {
|
|
|
8424
8488
|
duration: 5e3,
|
|
8425
8489
|
description: "Excited, energetic movement"
|
|
8426
8490
|
}
|
|
8427
|
-
}, wt = (
|
|
8491
|
+
}, wt = (X) => Ge[X] || null, zt = (X) => Ge.hasOwnProperty(X);
|
|
8428
8492
|
export {
|
|
8429
8493
|
yt as CurriculumLearning,
|
|
8430
8494
|
gt as SimpleTalkingAvatar,
|