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