@sage-rsc/talking-head-react 1.0.83 → 1.1.0
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 +437 -384
- package/package.json +1 -1
- package/src/lib/talkinghead.mjs +97 -20
package/dist/index.js
CHANGED
|
@@ -1,20 +1,20 @@
|
|
|
1
1
|
import { jsxs as Pe, jsx as me } from "react/jsx-runtime";
|
|
2
2
|
import { forwardRef as Me, useRef as O, useState as ce, useEffect as de, useCallback as T, useImperativeHandle as Ee, useLayoutEffect as Xe } from "react";
|
|
3
|
-
import * as
|
|
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 Oe } from "three/addons/loaders/FBXLoader.js";
|
|
8
8
|
import { RoomEnvironment as qe } from "three/addons/environments/RoomEnvironment.js";
|
|
9
9
|
import Ke from "three/addons/libs/stats.module.js";
|
|
10
10
|
let m, re, ue;
|
|
11
|
-
const A = [0, 0, 0, 0], w = new
|
|
12
|
-
new
|
|
13
|
-
new
|
|
14
|
-
new
|
|
15
|
-
const ie = new
|
|
16
|
-
new
|
|
17
|
-
const He = new
|
|
11
|
+
const A = [0, 0, 0, 0], w = new f.Vector3(), ze = new f.Vector3(), ne = new f.Vector3(), Ce = new f.Vector3();
|
|
12
|
+
new f.Plane();
|
|
13
|
+
new f.Ray();
|
|
14
|
+
new f.Euler();
|
|
15
|
+
const ie = new f.Quaternion(), De = new f.Quaternion(), fe = new f.Matrix4(), xe = new f.Matrix4();
|
|
16
|
+
new f.Vector3();
|
|
17
|
+
const He = new f.Vector3(0, 0, 1), _e = new f.Vector3(1, 0, 0), Je = new f.Vector3(0, 1, 0), $e = new f.Vector3(0, 0, 1);
|
|
18
18
|
class et {
|
|
19
19
|
constructor(t = null) {
|
|
20
20
|
this.opt = Object.assign({
|
|
@@ -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(w, ie, ne), w.copy(He).applyQuaternion(ie).setY(0).normalize(), ie.premultiply(
|
|
341
|
+
u.boneParent.matrixWorld.decompose(w, ie, ne), w.copy(He).applyQuaternion(ie).setY(0).normalize(), ie.premultiply(De.setFromUnitVectors(He, w).invert()).normalize(), u.qWorldInverseYaw = ie.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) {
|
|
@@ -369,7 +369,7 @@ class et {
|
|
|
369
369
|
o.vBasis.y + A[1],
|
|
370
370
|
o.vBasis.z - A[2]
|
|
371
371
|
);
|
|
372
|
-
else if (o.boneParent.quaternion.copy(o.qBasis), o.pivot && this.opt.isPivots && (o.boneParent.updateWorldMatrix(!1, !1), o.boneParent.matrixWorld.decompose(w, ie, ne), w.copy(He).applyQuaternion(ie).setY(0).normalize(), ie.premultiply(
|
|
372
|
+
else if (o.boneParent.quaternion.copy(o.qBasis), o.pivot && this.opt.isPivots && (o.boneParent.updateWorldMatrix(!1, !1), o.boneParent.matrixWorld.decompose(w, ie, ne), w.copy(He).applyQuaternion(ie).setY(0).normalize(), ie.premultiply(De.setFromUnitVectors(He, w).invert()).normalize(), o.boneParent.quaternion.multiply(ie.invert()), o.boneParent.quaternion.multiply(o.qWorldInverseYaw)), o.isZ && (m = Math.atan(A[0] / o.l), ie.setFromAxisAngle($e, -m), o.boneParent.quaternion.multiply(ie)), o.isY && (m = o.l / 3, m = m * Math.tanh(A[1] / m), o.bone.position.setLength(o.l + m)), o.isX && (m = Math.atan(A[2] / o.l), ie.setFromAxisAngle(_e, -m), o.boneParent.quaternion.multiply(ie)), o.isT && (m = 1.5 * Math.tanh(A[3] * 1.5), ie.setFromAxisAngle(Je, -m), o.boneParent.quaternion.multiply(ie)), o.boneParent.updateWorldMatrix(!1, !0), o.excludes && this.opt.isExcludes)
|
|
373
373
|
for (n = 0, s = o.excludes.length; n < s; n++)
|
|
374
374
|
m = o.excludes[n], ne.set(0, 0, 0), m.deltaLocal && (ne.x += m.deltaLocal[0], ne.y += m.deltaLocal[1], ne.z += m.deltaLocal[2]), ne.applyMatrix4(m.bone.matrixWorld), xe.copy(o.boneParent.matrixWorld).invert(), ne.applyMatrix4(xe), w.copy(o.bone.position), !(w.distanceToSquared(ne) >= m.radiusSq) && (ue = w.length(), re = ne.length(), !(re > m.radius + ue) && (re < Math.abs(m.radius - ue) || (re = (re * re + ue * ue - m.radiusSq) / (2 * re), ne.normalize(), Ce.copy(ne).multiplyScalar(re), re = Math.sqrt(ue * ue - re * re), w.subVectors(w, Ce).projectOnPlane(ne).normalize().multiplyScalar(re), ze.subVectors(o.vBasis, Ce).projectOnPlane(ne).normalize(), ue = ze.dot(w), ue < 0 && (ue = Math.sqrt(re * re - ue * ue), ze.multiplyScalar(ue), w.add(ze)), w.add(Ce).normalize(), ne.copy(o.bone.position).normalize(), ie.setFromUnitVectors(ne, w), o.boneParent.quaternion.premultiply(ie), o.boneParent.updateWorldMatrix(!1, !0))));
|
|
375
375
|
}
|
|
@@ -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
|
/**
|
|
@@ -606,8 +606,8 @@ 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 c = n[(h + a) * 2], d = n[(h + a) * 2 + 1], g = n[(h + a + i / 2) * 2] * r - n[(h + a + i / 2) * 2 + 1] * u,
|
|
610
|
-
n[(h + a) * 2] = c + g, n[(h + a) * 2 + 1] = d +
|
|
609
|
+
const c = n[(h + a) * 2], d = n[(h + a) * 2 + 1], g = n[(h + a + i / 2) * 2] * r - n[(h + a + i / 2) * 2 + 1] * u, x = n[(h + a + i / 2) * 2] * u + n[(h + a + i / 2) * 2 + 1] * r;
|
|
610
|
+
n[(h + a) * 2] = c + g, n[(h + a) * 2 + 1] = d + x, n[(h + a + i / 2) * 2] = c - g, n[(h + a + i / 2) * 2 + 1] = d - x;
|
|
611
611
|
const b = r * o - u * l, I = r * l + u * o;
|
|
612
612
|
r = b, u = I;
|
|
613
613
|
}
|
|
@@ -2629,14 +2629,14 @@ const ct = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
|
|
|
2629
2629
|
fr: rt,
|
|
2630
2630
|
fi: ut,
|
|
2631
2631
|
lt: ct
|
|
2632
|
-
}, Q = new
|
|
2633
|
-
new
|
|
2634
|
-
new
|
|
2635
|
-
new
|
|
2636
|
-
new
|
|
2637
|
-
const mt = new
|
|
2638
|
-
new
|
|
2639
|
-
new
|
|
2632
|
+
}, Q = new f.Quaternion(), V = 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.
|
|
@@ -3636,14 +3636,23 @@ class Be {
|
|
|
3636
3636
|
anims: [
|
|
3637
3637
|
{ name: "breathing", delay: 1500, dt: [1200, 500, 1e3], vs: { chestInhale: [0.5, 0.5, 0] } },
|
|
3638
3638
|
{ name: "pose", alt: [
|
|
3639
|
-
{
|
|
3639
|
+
{
|
|
3640
|
+
p: 0.5,
|
|
3641
|
+
delay: [5e3, 3e4],
|
|
3642
|
+
vs: { pose: ["side"] },
|
|
3643
|
+
M: { delay: [5e3, 3e4], vs: { pose: ["wide"] } }
|
|
3644
|
+
},
|
|
3640
3645
|
{
|
|
3641
3646
|
p: 0.3,
|
|
3642
3647
|
delay: [5e3, 3e4],
|
|
3643
3648
|
vs: { pose: ["hip"] },
|
|
3644
3649
|
M: { delay: [5e3, 3e4], vs: { pose: ["wide"] } }
|
|
3645
3650
|
},
|
|
3646
|
-
{
|
|
3651
|
+
{
|
|
3652
|
+
delay: [5e3, 3e4],
|
|
3653
|
+
vs: { pose: ["straight"] },
|
|
3654
|
+
M: { delay: [5e3, 3e4], vs: { pose: ["wide"] } }
|
|
3655
|
+
}
|
|
3647
3656
|
] },
|
|
3648
3657
|
{
|
|
3649
3658
|
name: "head",
|
|
@@ -3665,12 +3674,17 @@ class Be {
|
|
|
3665
3674
|
name: "pose",
|
|
3666
3675
|
idle: {
|
|
3667
3676
|
alt: [
|
|
3668
|
-
{
|
|
3677
|
+
{
|
|
3678
|
+
p: 0.6,
|
|
3679
|
+
delay: [5e3, 3e4],
|
|
3680
|
+
vs: { pose: ["side"] },
|
|
3681
|
+
M: { delay: [5e3, 3e4], vs: { pose: ["wide"] } }
|
|
3682
|
+
},
|
|
3669
3683
|
{
|
|
3670
3684
|
p: 0.2,
|
|
3671
3685
|
delay: [5e3, 3e4],
|
|
3672
3686
|
vs: { pose: ["hip"] },
|
|
3673
|
-
M: { delay: [5e3, 3e4], vs: { pose: ["
|
|
3687
|
+
M: { delay: [5e3, 3e4], vs: { pose: ["wide"] } }
|
|
3674
3688
|
},
|
|
3675
3689
|
{ p: 0.1, delay: [5e3, 3e4], vs: { pose: ["straight"] } },
|
|
3676
3690
|
{ delay: [5e3, 1e4], vs: { pose: ["wide"] } },
|
|
@@ -3679,8 +3693,18 @@ class Be {
|
|
|
3679
3693
|
},
|
|
3680
3694
|
speaking: {
|
|
3681
3695
|
alt: [
|
|
3682
|
-
{
|
|
3683
|
-
|
|
3696
|
+
{
|
|
3697
|
+
p: 0.4,
|
|
3698
|
+
delay: [5e3, 3e4],
|
|
3699
|
+
vs: { pose: ["side"] },
|
|
3700
|
+
M: { delay: [5e3, 3e4], vs: { pose: ["wide"] } }
|
|
3701
|
+
},
|
|
3702
|
+
{
|
|
3703
|
+
p: 0.4,
|
|
3704
|
+
delay: [5e3, 3e4],
|
|
3705
|
+
vs: { pose: ["straight"] },
|
|
3706
|
+
M: { delay: [5e3, 3e4], vs: { pose: ["wide"] } }
|
|
3707
|
+
},
|
|
3684
3708
|
{
|
|
3685
3709
|
delay: [5e3, 2e4],
|
|
3686
3710
|
vs: { pose: ["hip"] },
|
|
@@ -4049,22 +4073,22 @@ class Be {
|
|
|
4049
4073
|
if (this.isAvatarOnly = this.opt.avatarOnly, this.isAvatarOnly)
|
|
4050
4074
|
this.scene = this.opt.avatarOnlyScene, this.camera = this.opt.avatarOnlyCamera;
|
|
4051
4075
|
else {
|
|
4052
|
-
this.renderer = new
|
|
4053
|
-
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),
|
|
4054
4078
|
this.opt.lightAmbientIntensity
|
|
4055
|
-
), this.lightDirect = new
|
|
4056
|
-
new
|
|
4079
|
+
), this.lightDirect = new f.DirectionalLight(
|
|
4080
|
+
new f.Color(this.opt.lightDirectColor),
|
|
4057
4081
|
this.opt.lightDirectIntensity
|
|
4058
|
-
), this.lightSpot = new
|
|
4059
|
-
new
|
|
4082
|
+
), this.lightSpot = new f.SpotLight(
|
|
4083
|
+
new f.Color(this.opt.lightSpotColor),
|
|
4060
4084
|
this.opt.lightSpotIntensity,
|
|
4061
4085
|
0,
|
|
4062
4086
|
this.opt.lightSpotDispersion
|
|
4063
4087
|
), this.setLighting(this.opt);
|
|
4064
|
-
const l = new
|
|
4088
|
+
const l = new f.PMREMGenerator(this.renderer);
|
|
4065
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;
|
|
4066
4090
|
}
|
|
4067
|
-
this.ikMesh = new
|
|
4091
|
+
this.ikMesh = new f.SkinnedMesh();
|
|
4068
4092
|
const s = {
|
|
4069
4093
|
LeftShoulder: null,
|
|
4070
4094
|
LeftArm: "LeftShoulder",
|
|
@@ -4078,9 +4102,9 @@ class Be {
|
|
|
4078
4102
|
RightHandMiddle1: "RightHand"
|
|
4079
4103
|
}, o = [];
|
|
4080
4104
|
Object.entries(s).forEach((l, h) => {
|
|
4081
|
-
const r = new
|
|
4105
|
+
const r = new f.Bone();
|
|
4082
4106
|
r.name = l[0], l[1] ? this.ikMesh.getObjectByName(l[1]).add(r) : this.ikMesh.add(r), o.push(r);
|
|
4083
|
-
}), 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 = [];
|
|
4084
4108
|
}
|
|
4085
4109
|
/**
|
|
4086
4110
|
* Helper that re/creates the audio context and the other nodes.
|
|
@@ -4170,7 +4194,7 @@ class Be {
|
|
|
4170
4194
|
for (let [n, i] of Object.entries(t)) {
|
|
4171
4195
|
const s = n.split(".");
|
|
4172
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;
|
|
4173
|
-
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());
|
|
4174
4198
|
}
|
|
4175
4199
|
return e;
|
|
4176
4200
|
}
|
|
@@ -4202,15 +4226,15 @@ class Be {
|
|
|
4202
4226
|
for (const [r, u] of Object.entries(n))
|
|
4203
4227
|
if (s.morphTargetDictionary.hasOwnProperty(r)) {
|
|
4204
4228
|
const a = s.morphTargetDictionary[r], c = o.morphAttributes.position[a], d = o.morphAttributes.normal?.[a];
|
|
4205
|
-
l || (l = new
|
|
4229
|
+
l || (l = new f.Float32BufferAttribute(c.count * 3, 3), d && (h = new f.Float32BufferAttribute(c.count * 3, 3)));
|
|
4206
4230
|
for (let g = 0; g < c.count; g++) {
|
|
4207
|
-
const
|
|
4208
|
-
l.setXYZ(g,
|
|
4231
|
+
const x = l.getX(g) + c.getX(g) * u, b = l.getY(g) + c.getY(g) * u, I = l.getZ(g) + c.getZ(g) * u;
|
|
4232
|
+
l.setXYZ(g, x, b, I);
|
|
4209
4233
|
}
|
|
4210
4234
|
if (d)
|
|
4211
4235
|
for (let g = 0; g < c.count; g++) {
|
|
4212
|
-
const
|
|
4213
|
-
h.setXYZ(g,
|
|
4236
|
+
const x = h.getX(g) + d.getX(g) * u, b = h.getY(g) + d.getY(g) * u, I = h.getZ(g) + d.getZ(g) * u;
|
|
4237
|
+
h.setXYZ(g, x, b, I);
|
|
4214
4238
|
}
|
|
4215
4239
|
}
|
|
4216
4240
|
if (l) {
|
|
@@ -4290,7 +4314,7 @@ class Be {
|
|
|
4290
4314
|
console.error("Dynamic bones setup failed: " + r);
|
|
4291
4315
|
}
|
|
4292
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");
|
|
4293
|
-
const h = new
|
|
4317
|
+
const h = new f.Vector3();
|
|
4294
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();
|
|
4295
4319
|
}
|
|
4296
4320
|
/**
|
|
@@ -4334,14 +4358,14 @@ class Be {
|
|
|
4334
4358
|
default:
|
|
4335
4359
|
a += 12, u = u * a;
|
|
4336
4360
|
}
|
|
4337
|
-
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;
|
|
4338
4362
|
}
|
|
4339
4363
|
/**
|
|
4340
4364
|
* Change light colors and intensities.
|
|
4341
4365
|
* @param {Object} opt Options
|
|
4342
4366
|
*/
|
|
4343
4367
|
setLighting(t) {
|
|
4344
|
-
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));
|
|
4345
4369
|
}
|
|
4346
4370
|
/**
|
|
4347
4371
|
* Render scene.
|
|
@@ -4374,9 +4398,9 @@ class Be {
|
|
|
4374
4398
|
updatePoseDelta() {
|
|
4375
4399
|
for (const [t, e] of Object.entries(this.poseDelta.props)) {
|
|
4376
4400
|
if (e.x === 0 && e.y === 0 && e.z === 0) continue;
|
|
4377
|
-
|
|
4401
|
+
V.set(e.x, e.y, e.z);
|
|
4378
4402
|
const n = this.poseAvatar.props[t];
|
|
4379
|
-
n.isQuaternion ? (Q.setFromEuler(
|
|
4403
|
+
n.isQuaternion ? (Q.setFromEuler(V), n.multiply(Q)) : n.isVector3 && n.add(V);
|
|
4380
4404
|
}
|
|
4381
4405
|
}
|
|
4382
4406
|
/**
|
|
@@ -4456,7 +4480,7 @@ class Be {
|
|
|
4456
4480
|
return Object.entries(t).forEach((i, s) => {
|
|
4457
4481
|
const o = i[0].split(".");
|
|
4458
4482
|
if (o[1] === "position" || o[1] === "rotation" || o[1] === "quaternion") {
|
|
4459
|
-
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];
|
|
4460
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 += "}";
|
|
4461
4485
|
}
|
|
4462
4486
|
}), n += "}", n;
|
|
@@ -4999,7 +5023,7 @@ class Be {
|
|
|
4999
5023
|
}
|
|
5000
5024
|
s ? o.ts = o.ts.map((r) => h + r * n) : o.ts = o.ts.map((r) => this.animClock + h + r * n), l.vs && l.vs.pose && console.log("Pose being selected from vs.pose:", l.vs.pose, "for avatar body:", this.avatar?.body);
|
|
5001
5025
|
for (let [r, u] of Object.entries(l.vs)) {
|
|
5002
|
-
const a = this.getBaselineValue(r), c = u.map((d) => (d = this.valueFn(d), d === null ? null : typeof d == "function" ? d : typeof d == "string" || d instanceof String ? r === "pose" && this.avatar && this.avatar.body === "M" && d === "hip" ? (console.log("Intercepting
|
|
5026
|
+
const a = this.getBaselineValue(r), c = u.map((d) => (d = this.valueFn(d), d === null ? null : typeof d == "function" ? d : typeof d == "string" || d instanceof String ? r === "pose" && this.avatar && this.avatar.body === "M" && (d === "hip" || d === "side") ? (console.log("Intercepting pose", d, "in animation factory, overriding to wide for male avatar"), "wide") : d.slice() : Array.isArray(d) ? r === "gesture" ? d.slice() : (a === void 0 ? 0 : a) + i * this.gaussianRandom(...d) : typeof d == "boolean" ? d : d instanceof Object && d.constructor === Object ? Object.assign({}, d) : (a === void 0 ? 0 : a) + i * d));
|
|
5003
5027
|
r === "eyesRotateY" ? (o.vs.eyeLookOutLeft = [null, ...c.map((d) => d > 0 ? d : 0)], o.vs.eyeLookInLeft = [null, ...c.map((d) => d > 0 ? 0 : -d)], o.vs.eyeLookOutRight = [null, ...c.map((d) => d > 0 ? 0 : -d)], o.vs.eyeLookInRight = [null, ...c.map((d) => d > 0 ? d : 0)]) : r === "eyesRotateX" ? (o.vs.eyesLookDown = [null, ...c.map((d) => d > 0 ? d : 0)], o.vs.eyesLookUp = [null, ...c.map((d) => d > 0 ? 0 : -d)]) : o.vs[r] = [null, ...c];
|
|
5004
5028
|
}
|
|
5005
5029
|
for (let r of Object.keys(o.vs))
|
|
@@ -5095,9 +5119,9 @@ class Be {
|
|
|
5095
5119
|
g.newvalue = d[i];
|
|
5096
5120
|
else {
|
|
5097
5121
|
g.newvalue = d[i + 1];
|
|
5098
|
-
const
|
|
5122
|
+
const x = a.ts[i + 1] - a.ts[i];
|
|
5099
5123
|
let b = 1;
|
|
5100
|
-
|
|
5124
|
+
x > 1e-4 && (b = (this.animClock - a.ts[i]) / x), b < 1 && (g.easing && (b = g.easing(b)), g.newvalue = (1 - b) * d[i] + b * g.newvalue), g.ref && g.ref !== a.vs && g.ref.hasOwnProperty(c) && delete g.ref[c], g.ref = a.vs;
|
|
5101
5125
|
}
|
|
5102
5126
|
if (l)
|
|
5103
5127
|
switch (c) {
|
|
@@ -5122,7 +5146,7 @@ class Be {
|
|
|
5122
5146
|
this.onSubtitles && typeof this.onSubtitles == "function" && this.onSubtitles(i);
|
|
5123
5147
|
break;
|
|
5124
5148
|
case "pose":
|
|
5125
|
-
this.avatar && this.avatar.body === "M" && i === "hip" &&
|
|
5149
|
+
this.avatar && this.avatar.body === "M" && (i === "hip" || i === "side") && this.poseTemplates.wide && (i = "wide", console.log("Overriding pose", i === "hip" ? "hip" : "side", "to wide for male avatar")), this.poseName = i, console.log("Setting pose to:", this.poseName, "for avatar body:", this.avatar?.body, "state:", this.stateName), this.setPoseFromTemplate(this.poseTemplates[this.poseName]);
|
|
5126
5150
|
break;
|
|
5127
5151
|
case "gesture":
|
|
5128
5152
|
this.playGesture(...i);
|
|
@@ -5145,7 +5169,7 @@ class Be {
|
|
|
5145
5169
|
{ link: "LeftForeArm", minx: -0.5, maxx: 1.5, miny: -1.5, maxy: 1.5, minz: -0.5, maxz: 3 },
|
|
5146
5170
|
{ link: "LeftArm", minx: -1.5, maxx: 1.5, miny: 0, maxy: 0, minz: -1, maxz: 3 }
|
|
5147
5171
|
]
|
|
5148
|
-
}, i.x ? new
|
|
5172
|
+
}, i.x ? new f.Vector3(i.x, i.y, i.z) : null, !0, i.d);
|
|
5149
5173
|
break;
|
|
5150
5174
|
case "handRight":
|
|
5151
5175
|
this.ikSolve({
|
|
@@ -5157,10 +5181,10 @@ class Be {
|
|
|
5157
5181
|
{ link: "RightForeArm", minx: -0.5, maxx: 1.5, miny: -1.5, maxy: 1.5, minz: -3, maxz: 0.5, maxAngle: 0.2 },
|
|
5158
5182
|
{ link: "RightArm", minx: -1.5, maxx: 1.5, miny: 0, maxy: 0, minz: -1, maxz: 3 }
|
|
5159
5183
|
]
|
|
5160
|
-
}, i.x ? new
|
|
5184
|
+
}, i.x ? new f.Vector3(i.x, i.y, i.z) : null, !0, i.d);
|
|
5161
5185
|
break;
|
|
5162
5186
|
}
|
|
5163
|
-
if ((h || r) && (
|
|
5187
|
+
if ((h || r) && (V.setFromQuaternion(this.poseAvatar.props["Head.quaternion"]), V.x = Math.max(-0.9, Math.min(0.9, 2 * V.x - 0.5)), V.y = Math.max(-0.9, Math.min(0.9, -2.5 * V.y)), h ? (Object.assign(this.mtAvatar.eyesLookDown, { system: V.x < 0 ? -V.x : 0, needsUpdate: !0 }), Object.assign(this.mtAvatar.eyesLookUp, { system: V.x < 0 ? 0 : V.x, needsUpdate: !0 }), Object.assign(this.mtAvatar.eyeLookInLeft, { system: V.y < 0 ? -V.y : 0, needsUpdate: !0 }), Object.assign(this.mtAvatar.eyeLookOutLeft, { system: V.y < 0 ? 0 : V.y, needsUpdate: !0 }), Object.assign(this.mtAvatar.eyeLookInRight, { system: V.y < 0 ? 0 : V.y, needsUpdate: !0 }), Object.assign(this.mtAvatar.eyeLookOutRight, { system: V.y < 0 ? -V.y : 0, needsUpdate: !0 }), r && (n = -this.mtAvatar.bodyRotateY.value, i = this.gaussianRandom(-0.2, 0.2), this.animQueue.push(this.animFactory({
|
|
5164
5188
|
name: "headmove",
|
|
5165
5189
|
dt: [[1e3, 2e3], [1e3, 2e3, 1, 2], [1e3, 2e3], [1e3, 2e3, 1, 2]],
|
|
5166
5190
|
vs: {
|
|
@@ -5186,7 +5210,7 @@ class Be {
|
|
|
5186
5210
|
else {
|
|
5187
5211
|
if (this.cameraClock !== null && this.cameraClock < 1e3) {
|
|
5188
5212
|
this.cameraClock += e, this.cameraClock > 1e3 && (this.cameraClock = 1e3);
|
|
5189
|
-
let a = new
|
|
5213
|
+
let a = new f.Spherical().setFromVector3(this.cameraStart), c = new f.Spherical().setFromVector3(this.cameraEnd);
|
|
5190
5214
|
a.phi += this.easing(this.cameraClock / 1e3) * (c.phi - a.phi), a.theta += this.easing(this.cameraClock / 1e3) * (c.theta - a.theta), a.radius += this.easing(this.cameraClock / 1e3) * (c.radius - a.radius), a.makeSafe(), this.camera.position.setFromSpherical(a), this.controlsStart.x !== this.controlsEnd.x ? this.controls.target.copy(this.controlsStart.lerp(this.controlsEnd, this.easing(this.cameraClock / 1e3))) : (a.setFromVector3(this.controlsStart), c.setFromVector3(this.controlsEnd), a.phi += this.easing(this.cameraClock / 1e3) * (c.phi - a.phi), a.theta += this.easing(this.cameraClock / 1e3) * (c.theta - a.theta), a.radius += this.easing(this.cameraClock / 1e3) * (c.radius - a.radius), a.makeSafe(), this.controls.target.setFromSpherical(a)), this.controls.update();
|
|
5191
5215
|
}
|
|
5192
5216
|
this.controls.autoRotate && this.controls.update(), this.stats && this.stats.end(), this.render();
|
|
@@ -5250,12 +5274,12 @@ class Be {
|
|
|
5250
5274
|
e = e || {};
|
|
5251
5275
|
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;
|
|
5252
5276
|
let u = "", a = "", c = 0, d = [], g = [];
|
|
5253
|
-
const
|
|
5254
|
-
for (let b = 0; b <
|
|
5255
|
-
const I = b ===
|
|
5256
|
-
let p =
|
|
5257
|
-
const M =
|
|
5258
|
-
if (p && !I && !M &&
|
|
5277
|
+
const x = Array.from(this.segmenter.segment(t), (b) => b.segment);
|
|
5278
|
+
for (let b = 0; b < x.length; b++) {
|
|
5279
|
+
const I = b === x.length - 1, B = x[b].match(l);
|
|
5280
|
+
let p = x[b].match(s);
|
|
5281
|
+
const M = x[b].match(h), z = x[b].match(o);
|
|
5282
|
+
if (p && !I && !M && x[b + 1].match(s) && (p = !1), n && (u += x[b]), B && (!i || i.every((y) => b < y[0] || b > y[1])) && (a += x[b]), (z || p || I) && (a.length && (a = this.lipsyncPreProcessText(a, r), a.length && d.push({
|
|
5259
5283
|
mark: c,
|
|
5260
5284
|
word: a
|
|
5261
5285
|
})), u.length && (g.push({
|
|
@@ -5266,16 +5290,16 @@ class Be {
|
|
|
5266
5290
|
subtitles: [u]
|
|
5267
5291
|
}
|
|
5268
5292
|
}), u = ""), a.length)) {
|
|
5269
|
-
const
|
|
5270
|
-
if (
|
|
5271
|
-
const E =
|
|
5272
|
-
for (let P = 0; P <
|
|
5293
|
+
const y = this.lipsyncWordsToVisemes(a, r);
|
|
5294
|
+
if (y && y.visemes && y.visemes.length) {
|
|
5295
|
+
const E = y.times[y.visemes.length - 1] + y.durations[y.visemes.length - 1];
|
|
5296
|
+
for (let P = 0; P < y.visemes.length; P++)
|
|
5273
5297
|
g.push({
|
|
5274
5298
|
mark: c,
|
|
5275
5299
|
template: { name: "viseme" },
|
|
5276
|
-
ts: [(
|
|
5300
|
+
ts: [(y.times[P] - 0.6) / E, (y.times[P] + 0.5) / E, (y.times[P] + y.durations[P] + 0.5) / E],
|
|
5277
5301
|
vs: {
|
|
5278
|
-
["viseme_" +
|
|
5302
|
+
["viseme_" + y.visemes[P]]: [null, y.visemes[P] === "PP" || y.visemes[P] === "FF" ? 0.9 : 0.6, 0]
|
|
5279
5303
|
}
|
|
5280
5304
|
});
|
|
5281
5305
|
}
|
|
@@ -5283,14 +5307,14 @@ class Be {
|
|
|
5283
5307
|
}
|
|
5284
5308
|
if (p || I) {
|
|
5285
5309
|
if (d.length || I && g.length) {
|
|
5286
|
-
const
|
|
5310
|
+
const y = {
|
|
5287
5311
|
anim: g
|
|
5288
5312
|
};
|
|
5289
|
-
n && (
|
|
5313
|
+
n && (y.onSubtitles = n), d.length && !e.avatarMute && (y.text = d, e.avatarMood && (y.mood = e.avatarMood), e.ttsLang && (y.lang = e.ttsLang), e.ttsVoice && (y.voice = e.ttsVoice), e.ttsRate && (y.rate = e.ttsRate), e.ttsVoice && (y.pitch = e.ttsPitch), e.ttsVolume && (y.volume = e.ttsVolume)), this.speechQueue.push(y), d = [], a = "", c = 0, g = [];
|
|
5290
5314
|
}
|
|
5291
5315
|
if (M) {
|
|
5292
|
-
let
|
|
5293
|
-
|
|
5316
|
+
let y = this.animEmojis[x[b]];
|
|
5317
|
+
y && y.link && (y = this.animEmojis[y.link]), y && this.speechQueue.push({ emoji: y });
|
|
5294
5318
|
}
|
|
5295
5319
|
this.speechQueue.push({ break: 100 });
|
|
5296
5320
|
}
|
|
@@ -5383,15 +5407,15 @@ class Be {
|
|
|
5383
5407
|
const a = this.lipsyncPreProcessText(h, i), c = this.lipsyncWordsToVisemes(a, i);
|
|
5384
5408
|
if (c && c.visemes && c.visemes.length) {
|
|
5385
5409
|
const d = c.times[c.visemes.length - 1] + c.durations[c.visemes.length - 1], g = Math.min(u, Math.max(0, u - c.visemes.length * 150));
|
|
5386
|
-
let
|
|
5410
|
+
let x = 0.6 + this.convertRange(g, [0, u], [0, 0.4]);
|
|
5387
5411
|
if (u = Math.min(u, c.visemes.length * 200), d > 0)
|
|
5388
5412
|
for (let b = 0; b < c.visemes.length; b++) {
|
|
5389
|
-
const I = r + c.times[b] / d * u,
|
|
5413
|
+
const I = r + c.times[b] / d * u, B = c.durations[b] / d * u;
|
|
5390
5414
|
o.push({
|
|
5391
5415
|
template: { name: "viseme" },
|
|
5392
|
-
ts: [I - Math.min(60, 2 *
|
|
5416
|
+
ts: [I - Math.min(60, 2 * B / 3), I + Math.min(25, B / 2), I + B + Math.min(60, B / 2)],
|
|
5393
5417
|
vs: {
|
|
5394
|
-
["viseme_" + c.visemes[b]]: [null, c.visemes[b] === "PP" || c.visemes[b] === "FF" ? 0.9 :
|
|
5418
|
+
["viseme_" + c.visemes[b]]: [null, c.visemes[b] === "PP" || c.visemes[b] === "FF" ? 0.9 : x, 0]
|
|
5395
5419
|
}
|
|
5396
5420
|
});
|
|
5397
5421
|
}
|
|
@@ -5474,11 +5498,11 @@ class Be {
|
|
|
5474
5498
|
const p = u.find((M) => M.name.includes(a) || M.lang === o);
|
|
5475
5499
|
p && (s.voice = p);
|
|
5476
5500
|
}
|
|
5477
|
-
const c = i.length * 100 / s.rate, d = this.audioCtx.createBuffer(1, this.audioCtx.sampleRate * (c / 1e3), this.audioCtx.sampleRate), g = this.avatar.lipsyncLang || this.opt.lipsyncLang || "en",
|
|
5501
|
+
const c = i.length * 100 / s.rate, d = this.audioCtx.createBuffer(1, this.audioCtx.sampleRate * (c / 1e3), this.audioCtx.sampleRate), g = this.avatar.lipsyncLang || this.opt.lipsyncLang || "en", x = this.lipsyncPreProcessText(i, g), b = this.lipsyncWordsToVisemes(x, g);
|
|
5478
5502
|
console.log("Browser TTS Lip-sync Debug:", {
|
|
5479
5503
|
text: i,
|
|
5480
5504
|
lipsyncLang: g,
|
|
5481
|
-
processedText:
|
|
5505
|
+
processedText: x,
|
|
5482
5506
|
lipsyncData: b,
|
|
5483
5507
|
hasVisemes: b && b.visemes && b.visemes.length > 0,
|
|
5484
5508
|
estimatedDuration: c
|
|
@@ -5487,18 +5511,18 @@ class Be {
|
|
|
5487
5511
|
if (b && b.visemes && b.visemes.length > 0) {
|
|
5488
5512
|
const p = b.times[b.visemes.length - 1] + b.durations[b.visemes.length - 1];
|
|
5489
5513
|
for (let M = 0; M < b.visemes.length; M++) {
|
|
5490
|
-
const z = b.visemes[M],
|
|
5514
|
+
const z = b.visemes[M], y = b.times[M] / p, E = b.durations[M] / p, P = y * c, W = E * c;
|
|
5491
5515
|
I.push({
|
|
5492
5516
|
template: { name: "viseme" },
|
|
5493
|
-
ts: [P - Math.min(60, 2 *
|
|
5517
|
+
ts: [P - Math.min(60, 2 * W / 3), P + Math.min(25, W / 2), P + W + Math.min(60, W / 2)],
|
|
5494
5518
|
vs: {
|
|
5495
5519
|
["viseme_" + z]: [null, z === "PP" || z === "FF" ? 0.9 : 0.6, 0]
|
|
5496
5520
|
}
|
|
5497
5521
|
});
|
|
5498
5522
|
}
|
|
5499
5523
|
}
|
|
5500
|
-
const
|
|
5501
|
-
this.audioPlaylist.push({ anim:
|
|
5524
|
+
const B = [...t.anim, ...I];
|
|
5525
|
+
this.audioPlaylist.push({ anim: B, audio: d }), this.onSubtitles = t.onSubtitles || null, this.resetLips(), t.mood && this.setMood(t.mood), this.playAudio(), s.onend = () => {
|
|
5502
5526
|
e();
|
|
5503
5527
|
}, s.onerror = (p) => {
|
|
5504
5528
|
console.error("Speech synthesis error:", p.error), n(p.error);
|
|
@@ -5547,10 +5571,10 @@ class Be {
|
|
|
5547
5571
|
hasVisemes: d && d.visemes && d.visemes.length > 0
|
|
5548
5572
|
}), d && d.visemes && d.visemes.length > 0)
|
|
5549
5573
|
r = {
|
|
5550
|
-
visemes: d.visemes.map((g,
|
|
5574
|
+
visemes: d.visemes.map((g, x) => ({
|
|
5551
5575
|
viseme: g,
|
|
5552
|
-
startTime:
|
|
5553
|
-
endTime: (
|
|
5576
|
+
startTime: x * l.duration / d.visemes.length,
|
|
5577
|
+
endTime: (x + 1) * l.duration / d.visemes.length,
|
|
5554
5578
|
duration: l.duration / d.visemes.length,
|
|
5555
5579
|
intensity: 0.7
|
|
5556
5580
|
})),
|
|
@@ -5563,14 +5587,14 @@ class Be {
|
|
|
5563
5587
|
} catch (c) {
|
|
5564
5588
|
console.error("Text-based lip-sync failed, using fallback:", c);
|
|
5565
5589
|
const d = e.toLowerCase().split(/\s+/), g = [];
|
|
5566
|
-
for (const
|
|
5567
|
-
for (const b of
|
|
5590
|
+
for (const x of d)
|
|
5591
|
+
for (const b of x) {
|
|
5568
5592
|
let I = "aa";
|
|
5569
5593
|
"aeiou".includes(b) ? I = "aa" : "bp".includes(b) ? I = "PP" : "fv".includes(b) ? I = "FF" : "st".includes(b) ? I = "SS" : "dln".includes(b) ? I = "DD" : "kg".includes(b) ? I = "kk" : "rw".includes(b) && (I = "RR"), g.push(I);
|
|
5570
5594
|
}
|
|
5571
5595
|
r = {
|
|
5572
|
-
visemes: g.map((
|
|
5573
|
-
viseme:
|
|
5596
|
+
visemes: g.map((x, b) => ({
|
|
5597
|
+
viseme: x,
|
|
5574
5598
|
startTime: b * l.duration / g.length,
|
|
5575
5599
|
endTime: (b + 1) * l.duration / g.length,
|
|
5576
5600
|
duration: l.duration / g.length,
|
|
@@ -5597,10 +5621,10 @@ class Be {
|
|
|
5597
5621
|
if (r.visemes && r.visemes.length > 0) {
|
|
5598
5622
|
console.log("ElevenLabs: Generating lip-sync animation from", r.visemes.length, "visemes");
|
|
5599
5623
|
for (let c = 0; c < r.visemes.length; c++) {
|
|
5600
|
-
const d = r.visemes[c], g = d.startTime * 1e3,
|
|
5624
|
+
const d = r.visemes[c], g = d.startTime * 1e3, x = d.duration * 1e3, b = d.intensity;
|
|
5601
5625
|
u.push({
|
|
5602
5626
|
template: { name: "viseme" },
|
|
5603
|
-
ts: [g - Math.min(60, 2 *
|
|
5627
|
+
ts: [g - Math.min(60, 2 * x / 3), g + Math.min(25, x / 2), g + x + Math.min(60, x / 2)],
|
|
5604
5628
|
vs: {
|
|
5605
5629
|
["viseme_" + d.viseme]: [null, b, 0]
|
|
5606
5630
|
}
|
|
@@ -5645,10 +5669,10 @@ class Be {
|
|
|
5645
5669
|
hasVisemes: d && d.visemes && d.visemes.length > 0
|
|
5646
5670
|
}), d && d.visemes && d.visemes.length > 0)
|
|
5647
5671
|
r = {
|
|
5648
|
-
visemes: d.visemes.map((g,
|
|
5672
|
+
visemes: d.visemes.map((g, x) => ({
|
|
5649
5673
|
viseme: g,
|
|
5650
|
-
startTime:
|
|
5651
|
-
endTime: (
|
|
5674
|
+
startTime: x * l.duration / d.visemes.length,
|
|
5675
|
+
endTime: (x + 1) * l.duration / d.visemes.length,
|
|
5652
5676
|
duration: l.duration / d.visemes.length,
|
|
5653
5677
|
intensity: 0.7
|
|
5654
5678
|
})),
|
|
@@ -5661,14 +5685,14 @@ class Be {
|
|
|
5661
5685
|
} catch (c) {
|
|
5662
5686
|
console.error("Text-based lip-sync failed, using fallback:", c);
|
|
5663
5687
|
const d = e.toLowerCase().split(/\s+/), g = [];
|
|
5664
|
-
for (const
|
|
5665
|
-
for (const b of
|
|
5688
|
+
for (const x of d)
|
|
5689
|
+
for (const b of x) {
|
|
5666
5690
|
let I = "aa";
|
|
5667
5691
|
"aeiou".includes(b) ? I = "aa" : "bp".includes(b) ? I = "PP" : "fv".includes(b) ? I = "FF" : "st".includes(b) ? I = "SS" : "dln".includes(b) ? I = "DD" : "kg".includes(b) ? I = "kk" : "rw".includes(b) && (I = "RR"), g.push(I);
|
|
5668
5692
|
}
|
|
5669
5693
|
r = {
|
|
5670
|
-
visemes: g.map((
|
|
5671
|
-
viseme:
|
|
5694
|
+
visemes: g.map((x, b) => ({
|
|
5695
|
+
viseme: x,
|
|
5672
5696
|
startTime: b * l.duration / g.length,
|
|
5673
5697
|
endTime: (b + 1) * l.duration / g.length,
|
|
5674
5698
|
duration: l.duration / g.length,
|
|
@@ -5695,10 +5719,10 @@ class Be {
|
|
|
5695
5719
|
if (r.visemes && r.visemes.length > 0) {
|
|
5696
5720
|
console.log("Deepgram: Generating lip-sync animation from", r.visemes.length, "visemes");
|
|
5697
5721
|
for (let c = 0; c < r.visemes.length; c++) {
|
|
5698
|
-
const d = r.visemes[c], g = d.startTime * 1e3,
|
|
5722
|
+
const d = r.visemes[c], g = d.startTime * 1e3, x = d.duration * 1e3, b = d.intensity;
|
|
5699
5723
|
u.push({
|
|
5700
5724
|
template: { name: "viseme" },
|
|
5701
|
-
ts: [g - Math.min(60, 2 *
|
|
5725
|
+
ts: [g - Math.min(60, 2 * x / 3), g + Math.min(25, x / 2), g + x + Math.min(60, x / 2)],
|
|
5702
5726
|
vs: {
|
|
5703
5727
|
["viseme_" + d.viseme]: [null, b, 0]
|
|
5704
5728
|
}
|
|
@@ -5747,12 +5771,12 @@ class Be {
|
|
|
5747
5771
|
});
|
|
5748
5772
|
const r = [];
|
|
5749
5773
|
for (let a = 0; a < h.visemes.length; a++) {
|
|
5750
|
-
const c = h.visemes[a], d = c.startTime * 1e3, g = c.duration * 1e3,
|
|
5774
|
+
const c = h.visemes[a], d = c.startTime * 1e3, g = c.duration * 1e3, x = c.intensity;
|
|
5751
5775
|
r.push({
|
|
5752
5776
|
template: { name: "viseme" },
|
|
5753
5777
|
ts: [d - Math.min(60, 2 * g / 3), d + Math.min(25, g / 2), d + g + Math.min(60, g / 2)],
|
|
5754
5778
|
vs: {
|
|
5755
|
-
["viseme_" + c.viseme]: [null,
|
|
5779
|
+
["viseme_" + c.viseme]: [null, x, 0]
|
|
5756
5780
|
}
|
|
5757
5781
|
});
|
|
5758
5782
|
}
|
|
@@ -6038,10 +6062,10 @@ class Be {
|
|
|
6038
6062
|
let c = 0.6 + this.convertRange(a, [0, o], [0, 0.4]);
|
|
6039
6063
|
if (o = Math.min(o, r.visemes.length * 200), u > 0)
|
|
6040
6064
|
for (let d = 0; d < r.visemes.length; d++) {
|
|
6041
|
-
const g = e + s + r.times[d] / u * o,
|
|
6065
|
+
const g = e + s + r.times[d] / u * o, x = r.durations[d] / u * o;
|
|
6042
6066
|
this.animQueue.push({
|
|
6043
6067
|
template: { name: "viseme" },
|
|
6044
|
-
ts: [g - Math.min(60, 2 *
|
|
6068
|
+
ts: [g - Math.min(60, 2 * x / 3), g + Math.min(25, x / 2), g + x + Math.min(60, x / 2)],
|
|
6045
6069
|
vs: {
|
|
6046
6070
|
["viseme_" + r.visemes[d]]: [null, r.visemes[d] === "PP" || r.visemes[d] === "FF" ? 0.9 : c, 0]
|
|
6047
6071
|
}
|
|
@@ -6134,7 +6158,7 @@ class Be {
|
|
|
6134
6158
|
*/
|
|
6135
6159
|
lookAtCamera(t) {
|
|
6136
6160
|
let e;
|
|
6137
|
-
if (this.speakTo && (e = new
|
|
6161
|
+
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) {
|
|
6138
6162
|
if (this.avatar.hasOwnProperty("avatarIgnoreCamera")) {
|
|
6139
6163
|
if (this.avatar.avatarIgnoreCamera) {
|
|
6140
6164
|
this.lookAhead(t);
|
|
@@ -6148,14 +6172,14 @@ class Be {
|
|
|
6148
6172
|
return;
|
|
6149
6173
|
}
|
|
6150
6174
|
this.objectLeftEye.updateMatrixWorld(!0), this.objectRightEye.updateMatrixWorld(!0), ve.setFromMatrixPosition(this.objectLeftEye.matrixWorld), Re.setFromMatrixPosition(this.objectRightEye.matrixWorld), ve.add(Re).divideScalar(2), Q.copy(this.armature.quaternion), Q.multiply(this.poseTarget.props["Hips.quaternion"]), Q.multiply(this.poseTarget.props["Spine.quaternion"]), Q.multiply(this.poseTarget.props["Spine1.quaternion"]), Q.multiply(this.poseTarget.props["Spine2.quaternion"]), Q.multiply(this.poseTarget.props["Neck.quaternion"]), Q.multiply(this.poseTarget.props["Head.quaternion"]);
|
|
6151
|
-
const n = new
|
|
6152
|
-
|
|
6153
|
-
const l = new
|
|
6154
|
-
|
|
6155
|
-
let r =
|
|
6175
|
+
const n = new f.Vector3().subVectors(e, ve).normalize(), i = Math.atan2(n.x, n.z), s = Math.asin(-n.y);
|
|
6176
|
+
V.set(s, i, 0, "YXZ");
|
|
6177
|
+
const l = new f.Quaternion().setFromEuler(V), h = new f.Quaternion().copy(l).multiply(Q.clone().invert());
|
|
6178
|
+
V.setFromQuaternion(h, "YXZ");
|
|
6179
|
+
let r = V.x / (40 / 24) + 0.2, u = V.y / (9 / 4), a = Math.min(0.6, Math.max(-0.3, r)), c = Math.min(0.8, Math.max(-0.8, u)), d = (Math.random() - 0.5) / 4, g = (Math.random() - 0.5) / 4;
|
|
6156
6180
|
if (t) {
|
|
6157
|
-
let
|
|
6158
|
-
|
|
6181
|
+
let x = this.animQueue.findIndex((I) => I.template.name === "lookat");
|
|
6182
|
+
x !== -1 && this.animQueue.splice(x, 1);
|
|
6159
6183
|
const b = {
|
|
6160
6184
|
name: "lookat",
|
|
6161
6185
|
dt: [750, t],
|
|
@@ -6184,23 +6208,23 @@ class Be {
|
|
|
6184
6208
|
if (!this.camera) return;
|
|
6185
6209
|
const i = this.nodeAvatar.getBoundingClientRect();
|
|
6186
6210
|
this.objectLeftEye.updateMatrixWorld(!0), this.objectRightEye.updateMatrixWorld(!0);
|
|
6187
|
-
const s = new
|
|
6211
|
+
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);
|
|
6188
6212
|
l.project(this.camera);
|
|
6189
6213
|
let h = (l.x + 1) / 2 * i.width + i.left, r = -(l.y - 1) / 2 * i.height + i.top;
|
|
6190
|
-
t === null && (t = h), e === null && (e = r), Q.copy(this.armature.quaternion), Q.multiply(this.poseTarget.props["Hips.quaternion"]), Q.multiply(this.poseTarget.props["Spine.quaternion"]), Q.multiply(this.poseTarget.props["Spine1.quaternion"]), Q.multiply(this.poseTarget.props["Spine2.quaternion"]), Q.multiply(this.poseTarget.props["Neck.quaternion"]), Q.multiply(this.poseTarget.props["Head.quaternion"]),
|
|
6191
|
-
let u =
|
|
6214
|
+
t === null && (t = h), e === null && (e = r), Q.copy(this.armature.quaternion), Q.multiply(this.poseTarget.props["Hips.quaternion"]), Q.multiply(this.poseTarget.props["Spine.quaternion"]), Q.multiply(this.poseTarget.props["Spine1.quaternion"]), Q.multiply(this.poseTarget.props["Spine2.quaternion"]), Q.multiply(this.poseTarget.props["Neck.quaternion"]), Q.multiply(this.poseTarget.props["Head.quaternion"]), V.setFromQuaternion(Q);
|
|
6215
|
+
let u = V.x / (40 / 24), a = V.y / (9 / 4), c = Math.min(0.4, Math.max(-0.4, this.camera.rotation.x)), d = Math.min(0.4, Math.max(-0.4, this.camera.rotation.y)), g = Math.max(window.innerWidth - h, h), x = Math.max(window.innerHeight - r, r), b = this.convertRange(e, [r - x, r + x], [-0.3, 0.6]) - u + c, I = this.convertRange(t, [h - g, h + g], [-0.8, 0.8]) - a + d;
|
|
6192
6216
|
b = Math.min(0.6, Math.max(-0.3, b)), I = Math.min(0.8, Math.max(-0.8, I));
|
|
6193
|
-
let
|
|
6217
|
+
let B = (Math.random() - 0.5) / 4, p = (Math.random() - 0.5) / 4;
|
|
6194
6218
|
if (n) {
|
|
6195
|
-
let M = this.animQueue.findIndex((
|
|
6219
|
+
let M = this.animQueue.findIndex((y) => y.template.name === "lookat");
|
|
6196
6220
|
M !== -1 && this.animQueue.splice(M, 1);
|
|
6197
6221
|
const z = {
|
|
6198
6222
|
name: "lookat",
|
|
6199
6223
|
dt: [750, n],
|
|
6200
6224
|
vs: {
|
|
6201
|
-
bodyRotateX: [b +
|
|
6225
|
+
bodyRotateX: [b + B],
|
|
6202
6226
|
bodyRotateY: [I + p],
|
|
6203
|
-
eyesRotateX: [-3 *
|
|
6227
|
+
eyesRotateX: [-3 * B + 0.1],
|
|
6204
6228
|
eyesRotateY: [-5 * p],
|
|
6205
6229
|
browInnerUp: [[0, 0.7]],
|
|
6206
6230
|
mouthLeft: [[0, 0.7]],
|
|
@@ -6220,14 +6244,14 @@ class Be {
|
|
|
6220
6244
|
*/
|
|
6221
6245
|
touchAt(t, e) {
|
|
6222
6246
|
if (!this.camera) return;
|
|
6223
|
-
const n = this.nodeAvatar.getBoundingClientRect(), i = new
|
|
6247
|
+
const n = this.nodeAvatar.getBoundingClientRect(), i = new f.Vector2(
|
|
6224
6248
|
(t - n.left) / n.width * 2 - 1,
|
|
6225
6249
|
-((e - n.top) / n.height) * 2 + 1
|
|
6226
|
-
), s = new
|
|
6250
|
+
), s = new f.Raycaster();
|
|
6227
6251
|
s.setFromCamera(i, this.camera);
|
|
6228
6252
|
const o = s.intersectObject(this.armature);
|
|
6229
6253
|
if (o.length > 0) {
|
|
6230
|
-
const l = o[0].point, h = new
|
|
6254
|
+
const l = o[0].point, h = new f.Vector3(), r = new f.Vector3();
|
|
6231
6255
|
this.objectLeftArm.getWorldPosition(h), this.objectRightArm.getWorldPosition(r);
|
|
6232
6256
|
const u = h.distanceToSquared(l), a = r.distanceToSquared(l);
|
|
6233
6257
|
u < a ? (this.ikSolve({
|
|
@@ -6271,7 +6295,7 @@ class Be {
|
|
|
6271
6295
|
{ link: "LeftForeArm", minx: -0.5, maxx: 1.5, miny: -1.5, maxy: 1.5, minz: -0.5, maxz: 3 },
|
|
6272
6296
|
{ link: "LeftArm", minx: -1.5, maxx: 1.5, miny: -1.5, maxy: 1.5, minz: -1, maxz: 3 }
|
|
6273
6297
|
]
|
|
6274
|
-
}, new
|
|
6298
|
+
}, new f.Vector3(
|
|
6275
6299
|
this.gaussianRandom(0, 0.5),
|
|
6276
6300
|
this.gaussianRandom(-0.8, -0.2),
|
|
6277
6301
|
this.gaussianRandom(0, 0.5)
|
|
@@ -6283,15 +6307,15 @@ class Be {
|
|
|
6283
6307
|
{ link: "RightForeArm", minx: -0.5, maxx: 1.5, miny: -1.5, maxy: 1.5, minz: -3, maxz: 0.5 },
|
|
6284
6308
|
{ link: "RightArm" }
|
|
6285
6309
|
]
|
|
6286
|
-
}, new
|
|
6310
|
+
}, new f.Vector3(
|
|
6287
6311
|
this.gaussianRandom(-0.5, 0),
|
|
6288
6312
|
this.gaussianRandom(-0.8, -0.2),
|
|
6289
6313
|
this.gaussianRandom(0, 0.5)
|
|
6290
6314
|
), !0);
|
|
6291
6315
|
const n = [], i = [];
|
|
6292
6316
|
n.push(100 + Math.round(Math.random() * 500)), i.push({ duration: 1e3, props: {
|
|
6293
|
-
"LeftHand.quaternion": new
|
|
6294
|
-
"RightHand.quaternion": new
|
|
6317
|
+
"LeftHand.quaternion": new f.Quaternion().setFromEuler(new f.Euler(0, -1 - Math.random(), 0)),
|
|
6318
|
+
"RightHand.quaternion": new f.Quaternion().setFromEuler(new f.Euler(0, 1 + Math.random(), 0))
|
|
6295
6319
|
} }), ["LeftArm", "LeftForeArm", "RightArm", "RightForeArm"].forEach((o) => {
|
|
6296
6320
|
i[0].props[o + ".quaternion"] = this.ikMesh.getObjectByName(o).quaternion.clone();
|
|
6297
6321
|
}), n.push(1e3 + Math.round(Math.random() * 500)), i.push({ duration: 2e3, props: {} }), ["LeftArm", "LeftForeArm", "RightArm", "RightForeArm", "LeftHand", "RightHand"].forEach((o) => {
|
|
@@ -6368,6 +6392,29 @@ class Be {
|
|
|
6368
6392
|
* @param {number} [ndx=0] Index of the clip
|
|
6369
6393
|
* @param {number} [scale=0.01] Position scale factor
|
|
6370
6394
|
*/
|
|
6395
|
+
/**
|
|
6396
|
+
* Get all bone names from the avatar's armature
|
|
6397
|
+
* @returns {Set<string>} Set of bone names
|
|
6398
|
+
*/
|
|
6399
|
+
getAvailableBoneNames() {
|
|
6400
|
+
const t = /* @__PURE__ */ new Set();
|
|
6401
|
+
return this.armature && this.armature.traverse((e) => {
|
|
6402
|
+
(e.isBone || e.type === "Bone") && t.add(e.name);
|
|
6403
|
+
}), t;
|
|
6404
|
+
}
|
|
6405
|
+
/**
|
|
6406
|
+
* Filter animation tracks to only include bones that exist in the avatar
|
|
6407
|
+
* @param {THREE.AnimationClip} clip - Animation clip to filter
|
|
6408
|
+
* @param {Set<string>} availableBones - Set of available bone names
|
|
6409
|
+
* @returns {THREE.AnimationClip} Filtered animation clip
|
|
6410
|
+
*/
|
|
6411
|
+
filterAnimationTracks(t, e) {
|
|
6412
|
+
const n = [], i = /* @__PURE__ */ new Set();
|
|
6413
|
+
return t.tracks.forEach((s) => {
|
|
6414
|
+
const l = s.name.split(".")[0];
|
|
6415
|
+
e.has(l) ? n.push(s) : i.add(l);
|
|
6416
|
+
}), i.size > 0 ? (console.warn(`FBX animation "${t.name}" contains tracks for ${i.size} bone(s) not found in avatar skeleton:`, Array.from(i).slice(0, 10).join(", "), i.size > 10 ? "..." : ""), console.info(`Filtered ${t.tracks.length} tracks down to ${n.length} valid tracks`)) : n.length > 0 && console.info(`FBX animation "${t.name}" is fully compatible: all ${n.length} tracks match avatar skeleton`), n.length === 0 ? (console.error(`No valid tracks found for animation "${t.name}". All bones are missing from avatar skeleton.`), null) : new f.AnimationClip(t.name, t.duration, n);
|
|
6417
|
+
}
|
|
6371
6418
|
async playAnimation(t, e = null, n = 10, i = 0, s = 0.01, o = !1) {
|
|
6372
6419
|
if (!this.armature) return;
|
|
6373
6420
|
this.positionWasLocked = !o, o ? console.log("Position locking disabled for FBX animation:", t) : (this.lockAvatarPosition(), console.log("Position locked immediately before FBX animation:", t));
|
|
@@ -6376,9 +6423,9 @@ class Be {
|
|
|
6376
6423
|
let h = this.animQueue.find((a) => a.template.name === "pose");
|
|
6377
6424
|
h && (h.ts[0] = 1 / 0), Object.entries(l.pose.props).forEach((a) => {
|
|
6378
6425
|
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;
|
|
6379
|
-
}), this.mixer ? console.log("Using existing mixer for FBX animation, preserving morph targets") : (this.mixer = new
|
|
6426
|
+
}), 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 });
|
|
6380
6427
|
const r = Math.ceil(n / l.clip.duration), u = this.mixer.clipAction(l.clip);
|
|
6381
|
-
u.setLoop(
|
|
6428
|
+
u.setLoop(f.LoopRepeat, r), u.clampWhenFinished = !0, this.currentFBXAction = u;
|
|
6382
6429
|
try {
|
|
6383
6430
|
u.fadeIn(0.5).play(), console.log("FBX animation started successfully:", t);
|
|
6384
6431
|
} catch (a) {
|
|
@@ -6404,7 +6451,7 @@ class Be {
|
|
|
6404
6451
|
} catch (c) {
|
|
6405
6452
|
console.warn(`Could not verify file existence for ${t}, attempting to load anyway:`, c);
|
|
6406
6453
|
}
|
|
6407
|
-
const u = new
|
|
6454
|
+
const u = new Oe();
|
|
6408
6455
|
let a;
|
|
6409
6456
|
try {
|
|
6410
6457
|
a = await u.loadAsync(t, e);
|
|
@@ -6415,13 +6462,13 @@ class Be {
|
|
|
6415
6462
|
suggestion: "Make sure the file is a valid FBX file and the path is correct"
|
|
6416
6463
|
}), c.message && c.message.includes("version number") && (console.error("FBX Loader Error: Cannot find version number"), console.error("This error usually means:"), console.error("1. The file is not a valid FBX file (might be GLB, corrupted, or wrong format)"), console.error("2. The file might be corrupted"), console.error("3. The file path might be incorrect"), console.error("4. The server returned an HTML error page instead of the FBX file"), console.error("5. The file might not exist at that path"), console.error(""), console.error("Solution: Please verify:"), console.error(` - File exists at: ${t}`), console.error(" - File is a valid FBX binary file"), console.error(" - File path matches your public folder structure"), console.error(" - File is not corrupted"));
|
|
6417
6464
|
try {
|
|
6418
|
-
const d = await fetch(t), g = d.headers.get("content-type"),
|
|
6465
|
+
const d = await fetch(t), g = d.headers.get("content-type"), x = await d.text();
|
|
6419
6466
|
console.error("Response details:", {
|
|
6420
6467
|
status: d.status,
|
|
6421
6468
|
contentType: g,
|
|
6422
|
-
firstBytes:
|
|
6423
|
-
isHTML:
|
|
6424
|
-
}), (
|
|
6469
|
+
firstBytes: x.substring(0, 100),
|
|
6470
|
+
isHTML: x.trim().startsWith("<!DOCTYPE") || x.trim().startsWith("<html")
|
|
6471
|
+
}), (x.trim().startsWith("<!DOCTYPE") || x.trim().startsWith("<html")) && console.error("The server returned an HTML page instead of an FBX file. The file path is likely incorrect.");
|
|
6425
6472
|
} catch (d) {
|
|
6426
6473
|
console.error("Could not fetch file for debugging:", d);
|
|
6427
6474
|
}
|
|
@@ -6429,21 +6476,27 @@ class Be {
|
|
|
6429
6476
|
}
|
|
6430
6477
|
if (a && a.animations && a.animations[i]) {
|
|
6431
6478
|
let c = a.animations[i];
|
|
6432
|
-
const d =
|
|
6433
|
-
|
|
6434
|
-
|
|
6435
|
-
|
|
6436
|
-
|
|
6437
|
-
|
|
6438
|
-
|
|
6439
|
-
|
|
6440
|
-
|
|
6479
|
+
const d = this.getAvailableBoneNames(), g = this.filterAnimationTracks(c, d);
|
|
6480
|
+
if (!g) {
|
|
6481
|
+
console.error(`Cannot play FBX animation "${t}": No compatible bones found.`);
|
|
6482
|
+
return;
|
|
6483
|
+
}
|
|
6484
|
+
c = g;
|
|
6485
|
+
const x = {};
|
|
6486
|
+
c.tracks.forEach((I) => {
|
|
6487
|
+
I.name = I.name.replaceAll("mixamorig", "");
|
|
6488
|
+
const B = I.name.split(".");
|
|
6489
|
+
if (B[1] === "position") {
|
|
6490
|
+
for (let p = 0; p < I.values.length; p++)
|
|
6491
|
+
I.values[p] = I.values[p] * s;
|
|
6492
|
+
x[I.name] = new f.Vector3(I.values[0], I.values[1], I.values[2]);
|
|
6493
|
+
} else B[1] === "quaternion" ? x[I.name] = new f.Quaternion(I.values[0], I.values[1], I.values[2], I.values[3]) : B[1] === "rotation" && (x[B[0] + ".quaternion"] = new f.Quaternion().setFromEuler(new f.Euler(I.values[0], I.values[1], I.values[2], "XYZ")).normalize());
|
|
6441
6494
|
});
|
|
6442
|
-
const
|
|
6443
|
-
|
|
6495
|
+
const b = { props: x };
|
|
6496
|
+
x["Hips.position"] && (x["Hips.position"].y < 0.5 ? b.lying = !0 : b.standing = !0), this.animClips.push({
|
|
6444
6497
|
url: t + "-" + i,
|
|
6445
6498
|
clip: c,
|
|
6446
|
-
pose:
|
|
6499
|
+
pose: b
|
|
6447
6500
|
}), this.playAnimation(t, e, n, i, s);
|
|
6448
6501
|
} else {
|
|
6449
6502
|
const c = "Animation " + t + " (ndx=" + i + ") not found";
|
|
@@ -6481,14 +6534,14 @@ class Be {
|
|
|
6481
6534
|
let l = this.animQueue.find((h) => h.template.name === "pose");
|
|
6482
6535
|
l && (l.ts[0] = this.animClock + n * 1e3 + 2e3), this.setPoseFromTemplate(o);
|
|
6483
6536
|
} else {
|
|
6484
|
-
let h = await new
|
|
6537
|
+
let h = await new Oe().loadAsync(t, e);
|
|
6485
6538
|
if (h && h.animations && h.animations[i]) {
|
|
6486
6539
|
let r = h.animations[i];
|
|
6487
6540
|
const u = {};
|
|
6488
6541
|
r.tracks.forEach((c) => {
|
|
6489
6542
|
c.name = c.name.replaceAll("mixamorig", "");
|
|
6490
6543
|
const d = c.name.split(".");
|
|
6491
|
-
d[1] === "position" ? u[c.name] = new
|
|
6544
|
+
d[1] === "position" ? u[c.name] = new f.Vector3(c.values[0] * s, c.values[1] * s, c.values[2] * s) : d[1] === "quaternion" ? u[c.name] = new f.Quaternion(c.values[0], c.values[1], c.values[2], c.values[3]) : d[1] === "rotation" && (u[d[0] + ".quaternion"] = new f.Quaternion().setFromEuler(new f.Euler(c.values[0], c.values[1], c.values[2], "XYZ")).normalize());
|
|
6492
6545
|
});
|
|
6493
6546
|
const a = { props: u };
|
|
6494
6547
|
u["Hips.position"] && (u["Hips.position"].y < 0.5 ? a.lying = !0 : a.standing = !0), this.animPoses.push({
|
|
@@ -6521,7 +6574,7 @@ class Be {
|
|
|
6521
6574
|
if (s) {
|
|
6522
6575
|
this.gestureTimeout && (clearTimeout(this.gestureTimeout), this.gestureTimeout = null);
|
|
6523
6576
|
let l = this.animQueue.findIndex((h) => h.template.name === "talkinghands");
|
|
6524
|
-
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
|
|
6577
|
+
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));
|
|
6525
6578
|
for (let [h, r] of Object.entries(this.gesture))
|
|
6526
6579
|
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);
|
|
6527
6580
|
e && Number.isFinite(e) && (this.gestureTimeout = setTimeout(this.stopGesture.bind(this, i), 1e3 * e));
|
|
@@ -6534,9 +6587,9 @@ class Be {
|
|
|
6534
6587
|
const h = l.ts[0], u = l.ts[l.ts.length - 1] - h;
|
|
6535
6588
|
if (e * 1e3 - u > 0) {
|
|
6536
6589
|
const c = [];
|
|
6537
|
-
for (let
|
|
6538
|
-
const d = o.template?.rescale || c.map((
|
|
6539
|
-
l.ts = l.ts.map((
|
|
6590
|
+
for (let x = 1; x < l.ts.length; x++) c.push(l.ts[x] - l.ts[x - 1]);
|
|
6591
|
+
const d = o.template?.rescale || c.map((x) => x / u), g = e * 1e3 - u;
|
|
6592
|
+
l.ts = l.ts.map((x, b, I) => b === 0 ? h : I[b - 1] + c[b - 1] + d[b - 1] * g);
|
|
6540
6593
|
} else {
|
|
6541
6594
|
const c = e * 1e3 / u;
|
|
6542
6595
|
l.ts = l.ts.map((d) => h + c * (d - h));
|
|
@@ -6569,33 +6622,33 @@ class Be {
|
|
|
6569
6622
|
* @param {numeric} [d=null] If set, apply in d milliseconds
|
|
6570
6623
|
*/
|
|
6571
6624
|
ikSolve(t, e = null, n = !1, i = null) {
|
|
6572
|
-
const s = new
|
|
6625
|
+
const s = new f.Vector3(), o = new f.Vector3(), l = new f.Vector3(), h = new f.Vector3(), r = new f.Quaternion(), u = new f.Vector3(), a = new f.Vector3(), c = new f.Vector3(), d = this.ikMesh.getObjectByName(t.root);
|
|
6573
6626
|
d.position.setFromMatrixPosition(this.armature.getObjectByName(t.root).matrixWorld), d.quaternion.setFromRotationMatrix(this.armature.getObjectByName(t.root).matrixWorld), e && n && e.applyQuaternion(this.armature.quaternion).add(d.position);
|
|
6574
|
-
const g = this.ikMesh.getObjectByName(t.effector),
|
|
6575
|
-
|
|
6627
|
+
const g = this.ikMesh.getObjectByName(t.effector), x = t.links;
|
|
6628
|
+
x.forEach((I) => {
|
|
6576
6629
|
I.bone = this.ikMesh.getObjectByName(I.link), I.bone.quaternion.copy(this.getPoseTemplateProp(I.link + ".quaternion"));
|
|
6577
6630
|
}), d.updateMatrixWorld(!0);
|
|
6578
6631
|
const b = t.iterations || 10;
|
|
6579
6632
|
if (e)
|
|
6580
6633
|
for (let I = 0; I < b; I++) {
|
|
6581
|
-
let
|
|
6582
|
-
for (let p = 0, M =
|
|
6583
|
-
const z =
|
|
6634
|
+
let B = !1;
|
|
6635
|
+
for (let p = 0, M = x.length; p < M; p++) {
|
|
6636
|
+
const z = x[p].bone;
|
|
6584
6637
|
z.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();
|
|
6585
|
-
let
|
|
6586
|
-
|
|
6587
|
-
|
|
6588
|
-
|
|
6589
|
-
|
|
6590
|
-
), new
|
|
6591
|
-
|
|
6592
|
-
|
|
6593
|
-
|
|
6594
|
-
))), z.updateMatrixWorld(!0),
|
|
6638
|
+
let y = s.dot(l);
|
|
6639
|
+
y > 1 ? y = 1 : y < -1 && (y = -1), y = Math.acos(y), !(y < 1e-5) && (x[p].minAngle !== void 0 && y < x[p].minAngle && (y = x[p].minAngle), x[p].maxAngle !== void 0 && y > x[p].maxAngle && (y = x[p].maxAngle), a.crossVectors(l, s), a.normalize(), Q.setFromAxisAngle(a, y), z.quaternion.multiply(Q), z.rotation.setFromVector3(c.setFromEuler(z.rotation).clamp(new f.Vector3(
|
|
6640
|
+
x[p].minx !== void 0 ? x[p].minx : -1 / 0,
|
|
6641
|
+
x[p].miny !== void 0 ? x[p].miny : -1 / 0,
|
|
6642
|
+
x[p].minz !== void 0 ? x[p].minz : -1 / 0
|
|
6643
|
+
), new f.Vector3(
|
|
6644
|
+
x[p].maxx !== void 0 ? x[p].maxx : 1 / 0,
|
|
6645
|
+
x[p].maxy !== void 0 ? x[p].maxy : 1 / 0,
|
|
6646
|
+
x[p].maxz !== void 0 ? x[p].maxz : 1 / 0
|
|
6647
|
+
))), z.updateMatrixWorld(!0), B = !0);
|
|
6595
6648
|
}
|
|
6596
|
-
if (!
|
|
6649
|
+
if (!B) break;
|
|
6597
6650
|
}
|
|
6598
|
-
i &&
|
|
6651
|
+
i && x.forEach((I) => {
|
|
6599
6652
|
this.poseTarget.props[I.link + ".quaternion"].copy(I.bone.quaternion), this.poseTarget.props[I.link + ".quaternion"].t = this.animClock, this.poseTarget.props[I.link + ".quaternion"].d = i;
|
|
6600
6653
|
});
|
|
6601
6654
|
}
|
|
@@ -6655,7 +6708,7 @@ function Fe() {
|
|
|
6655
6708
|
voices: Ie.voices
|
|
6656
6709
|
};
|
|
6657
6710
|
}
|
|
6658
|
-
function
|
|
6711
|
+
function St() {
|
|
6659
6712
|
const G = Fe(), t = [];
|
|
6660
6713
|
return Object.entries(G.voices).forEach(([e, n]) => {
|
|
6661
6714
|
t.push({
|
|
@@ -6683,10 +6736,10 @@ const Ve = Me(({
|
|
|
6683
6736
|
onError: d = () => {
|
|
6684
6737
|
},
|
|
6685
6738
|
className: g = "",
|
|
6686
|
-
style:
|
|
6739
|
+
style: x = {},
|
|
6687
6740
|
animations: b = {}
|
|
6688
6741
|
}, I) => {
|
|
6689
|
-
const
|
|
6742
|
+
const B = O(null), p = O(null), M = O(r), z = O(null), y = O(null), E = O(!1), P = O({ remainingText: null, originalText: null, options: null }), W = O([]), oe = O(0), [k, Z] = ce(!0), [K, X] = ce(null), [$, se] = ce(!1), [ae, pe] = ce(!1);
|
|
6690
6743
|
de(() => {
|
|
6691
6744
|
E.current = ae;
|
|
6692
6745
|
}, [ae]), de(() => {
|
|
@@ -6732,24 +6785,24 @@ const Ve = Me(({
|
|
|
6732
6785
|
ttsService: le,
|
|
6733
6786
|
lipsyncModules: ["en"],
|
|
6734
6787
|
cameraView: u
|
|
6735
|
-
},
|
|
6736
|
-
if (!(!
|
|
6788
|
+
}, S = T(async () => {
|
|
6789
|
+
if (!(!B.current || p.current))
|
|
6737
6790
|
try {
|
|
6738
|
-
if (Z(!0), X(null), p.current = new Be(
|
|
6739
|
-
if (
|
|
6740
|
-
const J = Math.min(100, Math.round(
|
|
6791
|
+
if (Z(!0), X(null), p.current = new Be(B.current, R), p.current.controls && (p.current.controls.enableRotate = !1, p.current.controls.enableZoom = !1, p.current.controls.enablePan = !1, p.current.controls.enableDamping = !1), b && Object.keys(b).length > 0 && (p.current.customAnimations = b), await p.current.showAvatar(v, (N) => {
|
|
6792
|
+
if (N.lengthComputable) {
|
|
6793
|
+
const J = Math.min(100, Math.round(N.loaded / N.total * 100));
|
|
6741
6794
|
c(J);
|
|
6742
6795
|
}
|
|
6743
|
-
}), await new Promise((
|
|
6796
|
+
}), await new Promise((N) => {
|
|
6744
6797
|
const J = () => {
|
|
6745
|
-
p.current.lipsync && Object.keys(p.current.lipsync).length > 0 ?
|
|
6798
|
+
p.current.lipsync && Object.keys(p.current.lipsync).length > 0 ? N() : setTimeout(J, 100);
|
|
6746
6799
|
};
|
|
6747
6800
|
J();
|
|
6748
6801
|
}), p.current && p.current.setShowFullAvatar)
|
|
6749
6802
|
try {
|
|
6750
6803
|
p.current.setShowFullAvatar(r);
|
|
6751
|
-
} catch (
|
|
6752
|
-
console.warn("Error setting full body mode on initialization:",
|
|
6804
|
+
} catch (N) {
|
|
6805
|
+
console.warn("Error setting full body mode on initialization:", N);
|
|
6753
6806
|
}
|
|
6754
6807
|
p.current && p.current.controls && (p.current.controls.enableRotate = !1, p.current.controls.enableZoom = !1, p.current.controls.enablePan = !1, p.current.controls.enableDamping = !1, p.current.controls.update()), Z(!1), se(!0), a(p.current);
|
|
6755
6808
|
const F = () => {
|
|
@@ -6762,15 +6815,15 @@ const Ve = Me(({
|
|
|
6762
6815
|
console.error("Error initializing TalkingHead:", L), X(L.message || "Failed to initialize avatar"), Z(!1), d(L);
|
|
6763
6816
|
}
|
|
6764
6817
|
}, [G, t, e, n, i, s, o, r, l, h, u]);
|
|
6765
|
-
de(() => (
|
|
6818
|
+
de(() => (S(), () => {
|
|
6766
6819
|
p.current && (p.current.stop(), p.current.dispose(), p.current = null);
|
|
6767
|
-
}), [
|
|
6768
|
-
if (!
|
|
6769
|
-
const L = new ResizeObserver((
|
|
6770
|
-
for (const J of
|
|
6820
|
+
}), [S]), de(() => {
|
|
6821
|
+
if (!B.current || !p.current) return;
|
|
6822
|
+
const L = new ResizeObserver((N) => {
|
|
6823
|
+
for (const J of N)
|
|
6771
6824
|
p.current && p.current.onResize && p.current.onResize();
|
|
6772
6825
|
});
|
|
6773
|
-
L.observe(
|
|
6826
|
+
L.observe(B.current);
|
|
6774
6827
|
const F = () => {
|
|
6775
6828
|
p.current && p.current.onResize && p.current.onResize();
|
|
6776
6829
|
};
|
|
@@ -6785,39 +6838,39 @@ const Ve = Me(({
|
|
|
6785
6838
|
} catch (L) {
|
|
6786
6839
|
console.warn("Failed to resume audio context:", L);
|
|
6787
6840
|
}
|
|
6788
|
-
}, []),
|
|
6841
|
+
}, []), U = T(async (L, F = {}) => {
|
|
6789
6842
|
if (p.current && $)
|
|
6790
6843
|
try {
|
|
6791
|
-
|
|
6792
|
-
const
|
|
6793
|
-
|
|
6844
|
+
y.current && (clearInterval(y.current), y.current = null), z.current = { text: L, options: F }, P.current = { remainingText: null, originalText: null, options: null };
|
|
6845
|
+
const N = /[!\.\?\n\p{Extended_Pictographic}]/ug, J = L.split(N).map((Y) => Y.trim()).filter((Y) => Y.length > 0);
|
|
6846
|
+
W.current = J, oe.current = 0, pe(!1), E.current = !1, await H();
|
|
6794
6847
|
const ge = {
|
|
6795
6848
|
...F,
|
|
6796
6849
|
lipsyncLang: F.lipsyncLang || v.lipsyncLang || "en"
|
|
6797
6850
|
};
|
|
6798
6851
|
if (F.onSpeechEnd && p.current) {
|
|
6799
6852
|
const Y = p.current;
|
|
6800
|
-
let he = null,
|
|
6853
|
+
let he = null, ke = 0;
|
|
6801
6854
|
const Ae = 1200;
|
|
6802
6855
|
let be = !1;
|
|
6803
6856
|
he = setInterval(() => {
|
|
6804
|
-
if (
|
|
6857
|
+
if (ke++, E.current)
|
|
6805
6858
|
return;
|
|
6806
|
-
if (
|
|
6807
|
-
if (he && (clearInterval(he), he = null,
|
|
6859
|
+
if (ke > Ae) {
|
|
6860
|
+
if (he && (clearInterval(he), he = null, y.current = null), !be && !E.current) {
|
|
6808
6861
|
be = !0;
|
|
6809
6862
|
try {
|
|
6810
6863
|
F.onSpeechEnd();
|
|
6811
|
-
} catch (
|
|
6812
|
-
console.error("Error in onSpeechEnd callback (timeout):",
|
|
6864
|
+
} catch (Ne) {
|
|
6865
|
+
console.error("Error in onSpeechEnd callback (timeout):", Ne);
|
|
6813
6866
|
}
|
|
6814
6867
|
}
|
|
6815
6868
|
return;
|
|
6816
6869
|
}
|
|
6817
|
-
const ye = !Y.speechQueue || Y.speechQueue.length === 0,
|
|
6818
|
-
Y && Y.isSpeaking === !1 && ye &&
|
|
6870
|
+
const ye = !Y.speechQueue || Y.speechQueue.length === 0, Se = !Y.audioPlaylist || Y.audioPlaylist.length === 0;
|
|
6871
|
+
Y && Y.isSpeaking === !1 && ye && Se && Y.isAudioPlaying === !1 && !be && !E.current && setTimeout(() => {
|
|
6819
6872
|
if (Y && !E.current && Y.isSpeaking === !1 && (!Y.speechQueue || Y.speechQueue.length === 0) && (!Y.audioPlaylist || Y.audioPlaylist.length === 0) && Y.isAudioPlaying === !1 && !be && !E.current) {
|
|
6820
|
-
be = !0, he && (clearInterval(he), he = null,
|
|
6873
|
+
be = !0, he && (clearInterval(he), he = null, y.current = null);
|
|
6821
6874
|
try {
|
|
6822
6875
|
F.onSpeechEnd();
|
|
6823
6876
|
} catch (Ze) {
|
|
@@ -6825,13 +6878,13 @@ const Ve = Me(({
|
|
|
6825
6878
|
}
|
|
6826
6879
|
}
|
|
6827
6880
|
}, 100);
|
|
6828
|
-
}, 100),
|
|
6881
|
+
}, 100), y.current = he;
|
|
6829
6882
|
}
|
|
6830
6883
|
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 () => {
|
|
6831
6884
|
await H(), p.current && p.current.lipsync && (p.current.setSlowdownRate && p.current.setSlowdownRate(1.05), p.current.speakText(L, ge));
|
|
6832
6885
|
}, 100);
|
|
6833
|
-
} catch (
|
|
6834
|
-
console.error("Error speaking text:",
|
|
6886
|
+
} catch (N) {
|
|
6887
|
+
console.error("Error speaking text:", N), X(N.message || "Failed to speak text");
|
|
6835
6888
|
}
|
|
6836
6889
|
}, [$, H, v.lipsyncLang]), _ = T(() => {
|
|
6837
6890
|
p.current && (p.current.stopSpeaking(), p.current.setSlowdownRate && p.current.setSlowdownRate(1), z.current = null, pe(!1));
|
|
@@ -6839,17 +6892,17 @@ const Ve = Me(({
|
|
|
6839
6892
|
if (p.current && p.current.pauseSpeaking) {
|
|
6840
6893
|
const L = p.current;
|
|
6841
6894
|
if (L.isSpeaking || L.audioPlaylist && L.audioPlaylist.length > 0 || L.speechQueue && L.speechQueue.length > 0) {
|
|
6842
|
-
|
|
6843
|
-
let
|
|
6844
|
-
if (z.current &&
|
|
6845
|
-
const J =
|
|
6846
|
-
if (he > 0 &&
|
|
6847
|
-
const be = L.speechQueue.filter((ye) => ye && ye.text && Array.isArray(ye.text) && ye.text.length > 0).map((ye) => ye.text.map((
|
|
6848
|
-
be && be.trim() && (
|
|
6895
|
+
y.current && (clearInterval(y.current), y.current = null);
|
|
6896
|
+
let N = "";
|
|
6897
|
+
if (z.current && W.current.length > 0) {
|
|
6898
|
+
const J = W.current.length, ge = L.speechQueue ? L.speechQueue.filter((Ae) => Ae && Ae.text && Array.isArray(Ae.text) && Ae.text.length > 0).length : 0, Y = L.audioPlaylist && L.audioPlaylist.length > 0, he = ge + (Y ? 1 : 0), ke = J - he;
|
|
6899
|
+
if (he > 0 && ke < J && (N = W.current.slice(ke).join(". ").trim(), !N && ge > 0 && L.speechQueue)) {
|
|
6900
|
+
const be = L.speechQueue.filter((ye) => ye && ye.text && Array.isArray(ye.text) && ye.text.length > 0).map((ye) => ye.text.map((Se) => Se.word || "").filter((Se) => Se.length > 0).join(" ")).filter((ye) => ye.length > 0).join(" ");
|
|
6901
|
+
be && be.trim() && (N = be.trim());
|
|
6849
6902
|
}
|
|
6850
6903
|
}
|
|
6851
6904
|
z.current && (P.current = {
|
|
6852
|
-
remainingText:
|
|
6905
|
+
remainingText: N || null,
|
|
6853
6906
|
originalText: z.current.text,
|
|
6854
6907
|
options: z.current.options
|
|
6855
6908
|
}), L.speechQueue && (L.speechQueue.length = 0), p.current.pauseSpeaking(), E.current = !0, pe(!0);
|
|
@@ -6868,16 +6921,16 @@ const Ve = Me(({
|
|
|
6868
6921
|
return;
|
|
6869
6922
|
}
|
|
6870
6923
|
pe(!1), E.current = !1, await H();
|
|
6871
|
-
const
|
|
6924
|
+
const N = {
|
|
6872
6925
|
...F,
|
|
6873
6926
|
lipsyncLang: F.lipsyncLang || v.lipsyncLang || "en"
|
|
6874
6927
|
};
|
|
6875
6928
|
try {
|
|
6876
|
-
await
|
|
6929
|
+
await U(L, N);
|
|
6877
6930
|
} catch (J) {
|
|
6878
6931
|
console.error("Error resuming speech:", J), pe(!1), E.current = !1;
|
|
6879
6932
|
}
|
|
6880
|
-
}, [H, ae,
|
|
6933
|
+
}, [H, ae, U, v]), Le = T((L) => {
|
|
6881
6934
|
p.current && p.current.setMood(L);
|
|
6882
6935
|
}, []), we = T((L) => {
|
|
6883
6936
|
p.current && p.current.setSlowdownRate && p.current.setSlowdownRate(L);
|
|
@@ -6923,7 +6976,7 @@ const Ve = Me(({
|
|
|
6923
6976
|
p.current && p.current.onResize && p.current.onResize();
|
|
6924
6977
|
}, []);
|
|
6925
6978
|
return Ee(I, () => ({
|
|
6926
|
-
speakText:
|
|
6979
|
+
speakText: U,
|
|
6927
6980
|
stopSpeaking: _,
|
|
6928
6981
|
pauseSpeaking: j,
|
|
6929
6982
|
resumeSpeaking: q,
|
|
@@ -7000,13 +7053,13 @@ const Ve = Me(({
|
|
|
7000
7053
|
width: "100%",
|
|
7001
7054
|
height: "100%",
|
|
7002
7055
|
position: "relative",
|
|
7003
|
-
...
|
|
7056
|
+
...x
|
|
7004
7057
|
},
|
|
7005
7058
|
children: [
|
|
7006
7059
|
/* @__PURE__ */ me(
|
|
7007
7060
|
"div",
|
|
7008
7061
|
{
|
|
7009
|
-
ref:
|
|
7062
|
+
ref: B,
|
|
7010
7063
|
className: "talking-head-viewer",
|
|
7011
7064
|
style: {
|
|
7012
7065
|
width: "100%",
|
|
@@ -7015,7 +7068,7 @@ const Ve = Me(({
|
|
|
7015
7068
|
}
|
|
7016
7069
|
}
|
|
7017
7070
|
),
|
|
7018
|
-
|
|
7071
|
+
k && /* @__PURE__ */ me("div", { className: "loading-overlay", style: {
|
|
7019
7072
|
position: "absolute",
|
|
7020
7073
|
top: "50%",
|
|
7021
7074
|
left: "50%",
|
|
@@ -7053,7 +7106,7 @@ const pt = Me(({
|
|
|
7053
7106
|
style: s = {},
|
|
7054
7107
|
avatarConfig: o = {}
|
|
7055
7108
|
}, l) => {
|
|
7056
|
-
const h = O(null), r = O(null), [u, a] = ce(!0), [c, d] = ce(null), [g,
|
|
7109
|
+
const h = O(null), r = O(null), [u, a] = ce(!0), [c, d] = ce(null), [g, x] = ce(!1), b = Fe(), I = o.ttsService || b.service, B = I === "browser" ? {
|
|
7057
7110
|
endpoint: "",
|
|
7058
7111
|
apiKey: null,
|
|
7059
7112
|
defaultVoice: "Google US English"
|
|
@@ -7069,7 +7122,7 @@ const pt = Me(({
|
|
|
7069
7122
|
body: "F",
|
|
7070
7123
|
avatarMood: "neutral",
|
|
7071
7124
|
ttsLang: I === "browser" ? "en-US" : "en",
|
|
7072
|
-
ttsVoice: o.ttsVoice ||
|
|
7125
|
+
ttsVoice: o.ttsVoice || B.defaultVoice,
|
|
7073
7126
|
lipsyncLang: "en",
|
|
7074
7127
|
// English lip-sync
|
|
7075
7128
|
showFullAvatar: !0,
|
|
@@ -7078,8 +7131,8 @@ const pt = Me(({
|
|
|
7078
7131
|
movementIntensity: 0.5,
|
|
7079
7132
|
...o
|
|
7080
7133
|
}, M = {
|
|
7081
|
-
ttsEndpoint:
|
|
7082
|
-
ttsApikey:
|
|
7134
|
+
ttsEndpoint: B.endpoint,
|
|
7135
|
+
ttsApikey: B.apiKey,
|
|
7083
7136
|
ttsService: I,
|
|
7084
7137
|
lipsyncModules: ["en"],
|
|
7085
7138
|
cameraView: "upper"
|
|
@@ -7108,25 +7161,25 @@ const pt = Me(({
|
|
|
7108
7161
|
} catch (K) {
|
|
7109
7162
|
console.warn("Error setting full body mode on initialization:", K);
|
|
7110
7163
|
}
|
|
7111
|
-
a(!1),
|
|
7164
|
+
a(!1), x(!0), n(r.current);
|
|
7112
7165
|
const Z = () => {
|
|
7113
7166
|
document.visibilityState === "visible" ? r.current?.start() : r.current?.stop();
|
|
7114
7167
|
};
|
|
7115
7168
|
return document.addEventListener("visibilitychange", Z), () => {
|
|
7116
7169
|
document.removeEventListener("visibilitychange", Z);
|
|
7117
7170
|
};
|
|
7118
|
-
} catch (
|
|
7119
|
-
console.error("Error initializing TalkingHead:",
|
|
7171
|
+
} catch (k) {
|
|
7172
|
+
console.error("Error initializing TalkingHead:", k), d(k.message || "Failed to initialize avatar"), a(!1), e(k);
|
|
7120
7173
|
}
|
|
7121
7174
|
}, []);
|
|
7122
7175
|
de(() => (z(), () => {
|
|
7123
7176
|
r.current && (r.current.stop(), r.current.dispose(), r.current = null);
|
|
7124
7177
|
}), [z]);
|
|
7125
|
-
const
|
|
7178
|
+
const y = T((k) => {
|
|
7126
7179
|
if (r.current && g)
|
|
7127
7180
|
try {
|
|
7128
|
-
console.log("Speaking text:",
|
|
7129
|
-
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(
|
|
7181
|
+
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(() => {
|
|
7182
|
+
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");
|
|
7130
7183
|
}, 500));
|
|
7131
7184
|
} catch (Z) {
|
|
7132
7185
|
console.error("Error speaking text:", Z), d(Z.message || "Failed to speak text");
|
|
@@ -7135,11 +7188,11 @@ const pt = Me(({
|
|
|
7135
7188
|
console.warn("Avatar not ready for speaking. isReady:", g, "talkingHeadRef:", !!r.current);
|
|
7136
7189
|
}, [g, p]), E = T(() => {
|
|
7137
7190
|
r.current && (r.current.stopSpeaking(), r.current.setSlowdownRate && (r.current.setSlowdownRate(1), console.log("Reset timing to normal")));
|
|
7138
|
-
}, []), P = T((
|
|
7139
|
-
r.current && r.current.setMood(
|
|
7140
|
-
}, []),
|
|
7141
|
-
r.current && r.current.setSlowdownRate && (r.current.setSlowdownRate(
|
|
7142
|
-
}, []), oe = T((
|
|
7191
|
+
}, []), P = T((k) => {
|
|
7192
|
+
r.current && r.current.setMood(k);
|
|
7193
|
+
}, []), W = T((k) => {
|
|
7194
|
+
r.current && r.current.setSlowdownRate && (r.current.setSlowdownRate(k), console.log("Timing adjustment set to:", k));
|
|
7195
|
+
}, []), oe = T((k, Z = !1) => {
|
|
7143
7196
|
if (r.current && r.current.playAnimation) {
|
|
7144
7197
|
if (r.current.setShowFullAvatar)
|
|
7145
7198
|
try {
|
|
@@ -7147,11 +7200,11 @@ const pt = Me(({
|
|
|
7147
7200
|
} catch (X) {
|
|
7148
7201
|
console.warn("Error setting full body mode:", X);
|
|
7149
7202
|
}
|
|
7150
|
-
if (
|
|
7203
|
+
if (k.includes("."))
|
|
7151
7204
|
try {
|
|
7152
|
-
r.current.playAnimation(
|
|
7205
|
+
r.current.playAnimation(k, null, 10, 0, 0.01, Z), console.log("Playing animation:", k);
|
|
7153
7206
|
} catch (X) {
|
|
7154
|
-
console.log(`Failed to play ${
|
|
7207
|
+
console.log(`Failed to play ${k}:`, X);
|
|
7155
7208
|
try {
|
|
7156
7209
|
r.current.setBodyMovement("idle"), console.log("Fallback to idle animation");
|
|
7157
7210
|
} catch ($) {
|
|
@@ -7163,13 +7216,13 @@ const pt = Me(({
|
|
|
7163
7216
|
let $ = !1;
|
|
7164
7217
|
for (const se of X)
|
|
7165
7218
|
try {
|
|
7166
|
-
r.current.playAnimation(
|
|
7219
|
+
r.current.playAnimation(k + se, null, 10, 0, 0.01, Z), console.log("Playing animation:", k + se), $ = !0;
|
|
7167
7220
|
break;
|
|
7168
7221
|
} catch {
|
|
7169
|
-
console.log(`Failed to play ${
|
|
7222
|
+
console.log(`Failed to play ${k}${se}, trying next format...`);
|
|
7170
7223
|
}
|
|
7171
7224
|
if (!$) {
|
|
7172
|
-
console.warn("Animation system not available or animation not found:",
|
|
7225
|
+
console.warn("Animation system not available or animation not found:", k);
|
|
7173
7226
|
try {
|
|
7174
7227
|
r.current.setBodyMovement("idle"), console.log("Fallback to idle animation");
|
|
7175
7228
|
} catch (se) {
|
|
@@ -7178,37 +7231,37 @@ const pt = Me(({
|
|
|
7178
7231
|
}
|
|
7179
7232
|
}
|
|
7180
7233
|
} else
|
|
7181
|
-
console.warn("Animation system not available or animation not found:",
|
|
7234
|
+
console.warn("Animation system not available or animation not found:", k);
|
|
7182
7235
|
}, []);
|
|
7183
7236
|
return Ee(l, () => ({
|
|
7184
|
-
speakText:
|
|
7237
|
+
speakText: y,
|
|
7185
7238
|
stopSpeaking: E,
|
|
7186
7239
|
setMood: P,
|
|
7187
|
-
setTimingAdjustment:
|
|
7240
|
+
setTimingAdjustment: W,
|
|
7188
7241
|
playAnimation: oe,
|
|
7189
7242
|
isReady: g,
|
|
7190
7243
|
talkingHead: r.current,
|
|
7191
|
-
setBodyMovement: (
|
|
7244
|
+
setBodyMovement: (k) => {
|
|
7192
7245
|
if (r.current && r.current.setShowFullAvatar && r.current.setBodyMovement)
|
|
7193
7246
|
try {
|
|
7194
|
-
r.current.setShowFullAvatar(!0), r.current.setBodyMovement(
|
|
7247
|
+
r.current.setShowFullAvatar(!0), r.current.setBodyMovement(k), console.log("Body movement set with full body mode:", k);
|
|
7195
7248
|
} catch (Z) {
|
|
7196
7249
|
console.warn("Error setting body movement:", Z);
|
|
7197
7250
|
}
|
|
7198
7251
|
},
|
|
7199
|
-
setMovementIntensity: (
|
|
7252
|
+
setMovementIntensity: (k) => r.current?.setMovementIntensity(k),
|
|
7200
7253
|
playRandomDance: () => {
|
|
7201
7254
|
if (r.current && r.current.setShowFullAvatar && r.current.playRandomDance)
|
|
7202
7255
|
try {
|
|
7203
7256
|
r.current.setShowFullAvatar(!0), r.current.playRandomDance(), console.log("Random dance played with full body mode");
|
|
7204
|
-
} catch (
|
|
7205
|
-
console.warn("Error playing random dance:",
|
|
7257
|
+
} catch (k) {
|
|
7258
|
+
console.warn("Error playing random dance:", k);
|
|
7206
7259
|
}
|
|
7207
7260
|
},
|
|
7208
|
-
playReaction: (
|
|
7261
|
+
playReaction: (k) => {
|
|
7209
7262
|
if (r.current && r.current.setShowFullAvatar && r.current.playReaction)
|
|
7210
7263
|
try {
|
|
7211
|
-
r.current.setShowFullAvatar(!0), r.current.playReaction(
|
|
7264
|
+
r.current.setShowFullAvatar(!0), r.current.playReaction(k), console.log("Reaction played with full body mode:", k);
|
|
7212
7265
|
} catch (Z) {
|
|
7213
7266
|
console.warn("Error playing reaction:", Z);
|
|
7214
7267
|
}
|
|
@@ -7217,14 +7270,14 @@ const pt = Me(({
|
|
|
7217
7270
|
if (r.current && r.current.setShowFullAvatar && r.current.playCelebration)
|
|
7218
7271
|
try {
|
|
7219
7272
|
r.current.setShowFullAvatar(!0), r.current.playCelebration(), console.log("Celebration played with full body mode");
|
|
7220
|
-
} catch (
|
|
7221
|
-
console.warn("Error playing celebration:",
|
|
7273
|
+
} catch (k) {
|
|
7274
|
+
console.warn("Error playing celebration:", k);
|
|
7222
7275
|
}
|
|
7223
7276
|
},
|
|
7224
|
-
setShowFullAvatar: (
|
|
7277
|
+
setShowFullAvatar: (k) => {
|
|
7225
7278
|
if (r.current && r.current.setShowFullAvatar)
|
|
7226
7279
|
try {
|
|
7227
|
-
r.current.setShowFullAvatar(
|
|
7280
|
+
r.current.setShowFullAvatar(k), console.log("Show full avatar set to:", k);
|
|
7228
7281
|
} catch (Z) {
|
|
7229
7282
|
console.warn("Error setting showFullAvatar:", Z);
|
|
7230
7283
|
}
|
|
@@ -7233,16 +7286,16 @@ const pt = Me(({
|
|
|
7233
7286
|
if (r.current && r.current.lockAvatarPosition)
|
|
7234
7287
|
try {
|
|
7235
7288
|
r.current.lockAvatarPosition();
|
|
7236
|
-
} catch (
|
|
7237
|
-
console.warn("Error locking avatar position:",
|
|
7289
|
+
} catch (k) {
|
|
7290
|
+
console.warn("Error locking avatar position:", k);
|
|
7238
7291
|
}
|
|
7239
7292
|
},
|
|
7240
7293
|
unlockAvatarPosition: () => {
|
|
7241
7294
|
if (r.current && r.current.unlockAvatarPosition)
|
|
7242
7295
|
try {
|
|
7243
7296
|
r.current.unlockAvatarPosition();
|
|
7244
|
-
} catch (
|
|
7245
|
-
console.warn("Error unlocking avatar position:",
|
|
7297
|
+
} catch (k) {
|
|
7298
|
+
console.warn("Error unlocking avatar position:", k);
|
|
7246
7299
|
}
|
|
7247
7300
|
}
|
|
7248
7301
|
})), /* @__PURE__ */ Pe("div", { className: `talking-head-container ${i}`, style: s, children: [
|
|
@@ -7301,14 +7354,14 @@ const gt = Me(({
|
|
|
7301
7354
|
},
|
|
7302
7355
|
onError: g = () => {
|
|
7303
7356
|
},
|
|
7304
|
-
onSpeechEnd:
|
|
7357
|
+
onSpeechEnd: x = () => {
|
|
7305
7358
|
},
|
|
7306
7359
|
className: b = "",
|
|
7307
7360
|
style: I = {},
|
|
7308
|
-
animations:
|
|
7361
|
+
animations: B = {},
|
|
7309
7362
|
autoSpeak: p = !1
|
|
7310
7363
|
}, M) => {
|
|
7311
|
-
const z = O(null),
|
|
7364
|
+
const z = O(null), y = O(null), E = O(u), P = O(null), W = O(null), oe = O(!1), k = O({ remainingText: null, originalText: null, options: null }), Z = O([]), [K, X] = ce(!0), [$, se] = ce(null), [ae, pe] = ce(!1), [ee, le] = ce(!1);
|
|
7312
7365
|
de(() => {
|
|
7313
7366
|
oe.current = ee;
|
|
7314
7367
|
}, [ee]), de(() => {
|
|
@@ -7337,7 +7390,7 @@ const gt = Me(({
|
|
|
7337
7390
|
...D,
|
|
7338
7391
|
apiKey: l !== null ? l : D.apiKey
|
|
7339
7392
|
};
|
|
7340
|
-
const
|
|
7393
|
+
const S = {
|
|
7341
7394
|
url: t,
|
|
7342
7395
|
body: e,
|
|
7343
7396
|
avatarMood: n,
|
|
@@ -7353,21 +7406,21 @@ const gt = Me(({
|
|
|
7353
7406
|
ttsService: v,
|
|
7354
7407
|
lipsyncModules: ["en"],
|
|
7355
7408
|
cameraView: a
|
|
7356
|
-
},
|
|
7357
|
-
if (!(!z.current ||
|
|
7409
|
+
}, U = T(async () => {
|
|
7410
|
+
if (!(!z.current || y.current))
|
|
7358
7411
|
try {
|
|
7359
|
-
X(!0), se(null),
|
|
7360
|
-
url:
|
|
7361
|
-
body:
|
|
7362
|
-
avatarMood:
|
|
7363
|
-
}), await
|
|
7412
|
+
X(!0), se(null), y.current = new Be(z.current, H), console.log("Avatar config being passed:", {
|
|
7413
|
+
url: S.url,
|
|
7414
|
+
body: S.body,
|
|
7415
|
+
avatarMood: S.avatarMood
|
|
7416
|
+
}), await y.current.showAvatar(S, (te) => {
|
|
7364
7417
|
if (te.lengthComputable) {
|
|
7365
7418
|
const L = Math.min(100, Math.round(te.loaded / te.total * 100));
|
|
7366
7419
|
d(L);
|
|
7367
7420
|
}
|
|
7368
|
-
}),
|
|
7421
|
+
}), y.current?.avatar && console.log("Avatar body after initialization:", y.current.avatar.body), X(!1), pe(!0), c(y.current);
|
|
7369
7422
|
const C = () => {
|
|
7370
|
-
document.visibilityState === "visible" ?
|
|
7423
|
+
document.visibilityState === "visible" ? y.current?.start() : y.current?.stop();
|
|
7371
7424
|
};
|
|
7372
7425
|
return document.addEventListener("visibilitychange", C), () => {
|
|
7373
7426
|
document.removeEventListener("visibilitychange", C);
|
|
@@ -7376,19 +7429,19 @@ const gt = Me(({
|
|
|
7376
7429
|
console.error("Error initializing TalkingHead:", C), se(C.message || "Failed to initialize avatar"), X(!1), g(C);
|
|
7377
7430
|
}
|
|
7378
7431
|
}, []);
|
|
7379
|
-
de(() => (
|
|
7380
|
-
|
|
7381
|
-
}), [
|
|
7432
|
+
de(() => (U(), () => {
|
|
7433
|
+
y.current && (y.current.stop(), y.current.dispose(), y.current = null);
|
|
7434
|
+
}), [U]);
|
|
7382
7435
|
const _ = T(async () => {
|
|
7383
|
-
if (
|
|
7436
|
+
if (y.current)
|
|
7384
7437
|
try {
|
|
7385
|
-
const C =
|
|
7438
|
+
const C = y.current.audioCtx || y.current.audioContext;
|
|
7386
7439
|
C && (C.state === "suspended" || C.state === "interrupted") && (await C.resume(), console.log("Audio context resumed"));
|
|
7387
7440
|
} catch (C) {
|
|
7388
7441
|
console.warn("Failed to resume audio context:", C);
|
|
7389
7442
|
}
|
|
7390
7443
|
}, []), j = T(async (C, te = {}) => {
|
|
7391
|
-
if (!
|
|
7444
|
+
if (!y.current || !ae) {
|
|
7392
7445
|
console.warn("Avatar not ready for speaking");
|
|
7393
7446
|
return;
|
|
7394
7447
|
}
|
|
@@ -7396,51 +7449,51 @@ const gt = Me(({
|
|
|
7396
7449
|
console.warn("No text provided to speak");
|
|
7397
7450
|
return;
|
|
7398
7451
|
}
|
|
7399
|
-
await _(),
|
|
7400
|
-
const L = C.split(/[.!?]+/).filter((
|
|
7452
|
+
await _(), k.current = { remainingText: null, originalText: null, options: null }, Z.current = [], P.current = { text: C, options: te }, W.current && (clearInterval(W.current), W.current = null), le(!1), oe.current = !1;
|
|
7453
|
+
const L = C.split(/[.!?]+/).filter((N) => N.trim().length > 0);
|
|
7401
7454
|
Z.current = L;
|
|
7402
7455
|
const F = {
|
|
7403
7456
|
lipsyncLang: te.lipsyncLang || "en",
|
|
7404
7457
|
onSpeechEnd: () => {
|
|
7405
|
-
|
|
7458
|
+
W.current && (clearInterval(W.current), W.current = null), te.onSpeechEnd && te.onSpeechEnd(), x();
|
|
7406
7459
|
}
|
|
7407
7460
|
};
|
|
7408
7461
|
try {
|
|
7409
|
-
|
|
7410
|
-
} catch (
|
|
7411
|
-
console.error("Error speaking text:",
|
|
7462
|
+
y.current.speakText(C, F);
|
|
7463
|
+
} catch (N) {
|
|
7464
|
+
console.error("Error speaking text:", N), se(N.message || "Failed to speak text");
|
|
7412
7465
|
}
|
|
7413
|
-
}, [ae,
|
|
7466
|
+
}, [ae, x, _]);
|
|
7414
7467
|
de(() => {
|
|
7415
|
-
ae && G && p &&
|
|
7468
|
+
ae && G && p && y.current && j(G);
|
|
7416
7469
|
}, [ae, G, p, j]);
|
|
7417
7470
|
const q = T(() => {
|
|
7418
|
-
if (
|
|
7471
|
+
if (y.current)
|
|
7419
7472
|
try {
|
|
7420
|
-
const C =
|
|
7473
|
+
const C = y.current.isSpeaking || !1, te = y.current.audioPlaylist || [], L = y.current.speechQueue || [];
|
|
7421
7474
|
if (C || te.length > 0 || L.length > 0) {
|
|
7422
|
-
|
|
7475
|
+
W.current && (clearInterval(W.current), W.current = null);
|
|
7423
7476
|
let F = "";
|
|
7424
|
-
L.length > 0 && (F = L.map((
|
|
7477
|
+
L.length > 0 && (F = L.map((N) => N.text && Array.isArray(N.text) ? N.text.map((J) => J.word).join(" ") : N.text || "").join(" ")), k.current = {
|
|
7425
7478
|
remainingText: F || null,
|
|
7426
7479
|
originalText: P.current?.text || null,
|
|
7427
7480
|
options: P.current?.options || null
|
|
7428
|
-
},
|
|
7481
|
+
}, y.current.speechQueue.length = 0, y.current.pauseSpeaking(), le(!0), oe.current = !0;
|
|
7429
7482
|
}
|
|
7430
7483
|
} catch (C) {
|
|
7431
7484
|
console.warn("Error pausing speech:", C);
|
|
7432
7485
|
}
|
|
7433
7486
|
}, []), Le = T(async () => {
|
|
7434
|
-
if (!(!
|
|
7487
|
+
if (!(!y.current || !ee))
|
|
7435
7488
|
try {
|
|
7436
7489
|
await _(), le(!1), oe.current = !1;
|
|
7437
|
-
const C =
|
|
7490
|
+
const C = k.current?.remainingText, te = k.current?.originalText || P.current?.text, L = k.current?.options || P.current?.options || {}, F = C || te;
|
|
7438
7491
|
F && j(F, L);
|
|
7439
7492
|
} catch (C) {
|
|
7440
7493
|
console.warn("Error resuming speech:", C), le(!1), oe.current = !1;
|
|
7441
7494
|
}
|
|
7442
7495
|
}, [ee, j, _]), we = T(() => {
|
|
7443
|
-
|
|
7496
|
+
y.current && (y.current.stopSpeaking(), W.current && (clearInterval(W.current), W.current = null), le(!1), oe.current = !1);
|
|
7444
7497
|
}, []);
|
|
7445
7498
|
return Ee(M, () => ({
|
|
7446
7499
|
speakText: j,
|
|
@@ -7449,20 +7502,20 @@ const gt = Me(({
|
|
|
7449
7502
|
stopSpeaking: we,
|
|
7450
7503
|
resumeAudioContext: _,
|
|
7451
7504
|
isPaused: () => ee,
|
|
7452
|
-
setMood: (C) =>
|
|
7505
|
+
setMood: (C) => y.current?.setMood(C),
|
|
7453
7506
|
setBodyMovement: (C) => {
|
|
7454
|
-
|
|
7507
|
+
y.current && y.current.setBodyMovement(C);
|
|
7455
7508
|
},
|
|
7456
7509
|
playAnimation: (C, te = !1) => {
|
|
7457
|
-
|
|
7510
|
+
y.current && y.current.playAnimation && y.current.playAnimation(C, null, 10, 0, 0.01, te);
|
|
7458
7511
|
},
|
|
7459
|
-
playReaction: (C) =>
|
|
7460
|
-
playCelebration: () =>
|
|
7512
|
+
playReaction: (C) => y.current?.playReaction(C),
|
|
7513
|
+
playCelebration: () => y.current?.playCelebration(),
|
|
7461
7514
|
setShowFullAvatar: (C) => {
|
|
7462
|
-
|
|
7515
|
+
y.current && (E.current = C, y.current.setShowFullAvatar(C));
|
|
7463
7516
|
},
|
|
7464
7517
|
isReady: ae,
|
|
7465
|
-
talkingHead:
|
|
7518
|
+
talkingHead: y.current
|
|
7466
7519
|
})), /* @__PURE__ */ Pe("div", { className: `simple-talking-avatar-container ${b}`, style: I, children: [
|
|
7467
7520
|
/* @__PURE__ */ me(
|
|
7468
7521
|
"div",
|
|
@@ -7532,7 +7585,7 @@ const yt = Me(({
|
|
|
7532
7585
|
onQuestionAnswer: s,
|
|
7533
7586
|
onCurriculumComplete: o,
|
|
7534
7587
|
onCustomAction: l
|
|
7535
|
-
}), d = O(null), g = O(null),
|
|
7588
|
+
}), d = O(null), g = O(null), x = O(null), b = O(null), I = O(null), B = O(null), p = O(null), M = O(G?.curriculum || {
|
|
7536
7589
|
title: "Default Curriculum",
|
|
7537
7590
|
description: "No curriculum data provided",
|
|
7538
7591
|
language: "en",
|
|
@@ -7580,7 +7633,7 @@ const yt = Me(({
|
|
|
7580
7633
|
lipsyncLang: "en"
|
|
7581
7634
|
};
|
|
7582
7635
|
}, [G, t, e]);
|
|
7583
|
-
const
|
|
7636
|
+
const y = T(() => (M.current || { modules: [] }).modules[a.current.currentModuleIndex]?.lessons[a.current.currentLessonIndex], []), E = T(() => y()?.questions[a.current.currentQuestionIndex], [y]), P = T((v, R) => R.type === "multiple_choice" || R.type === "true_false" ? v === R.answer : R.type === "code_test" && typeof v == "object" && v !== null ? v.passed === !0 : !1, []), W = T(() => {
|
|
7584
7637
|
a.current.lessonCompleted = !0, a.current.isQuestionMode = !1;
|
|
7585
7638
|
const v = a.current.totalQuestions > 0 ? Math.round(a.current.score / a.current.totalQuestions * 100) : 100;
|
|
7586
7639
|
let R = "Congratulations! You've completed this lesson";
|
|
@@ -7604,7 +7657,7 @@ const yt = Me(({
|
|
|
7604
7657
|
} catch {
|
|
7605
7658
|
u.current.playCelebration();
|
|
7606
7659
|
}
|
|
7607
|
-
const
|
|
7660
|
+
const S = M.current || { modules: [] }, H = S.modules[a.current.currentModuleIndex], U = a.current.currentLessonIndex < (H?.lessons?.length || 0) - 1, _ = a.current.currentModuleIndex < (S.modules?.length || 0) - 1, j = U || _, q = z.current || { lipsyncLang: "en" };
|
|
7608
7661
|
u.current.speakText(R, {
|
|
7609
7662
|
lipsyncLang: q.lipsyncLang,
|
|
7610
7663
|
onSpeechEnd: () => {
|
|
@@ -7625,7 +7678,7 @@ const yt = Me(({
|
|
|
7625
7678
|
const v = M.current || { modules: [] };
|
|
7626
7679
|
if (c.current.onCurriculumComplete({
|
|
7627
7680
|
modules: v.modules.length,
|
|
7628
|
-
totalLessons: v.modules.reduce((R,
|
|
7681
|
+
totalLessons: v.modules.reduce((R, S) => R + S.lessons.length, 0)
|
|
7629
7682
|
}), u.current) {
|
|
7630
7683
|
if (u.current.setMood("celebrating"), e.curriculumComplete)
|
|
7631
7684
|
try {
|
|
@@ -7636,8 +7689,8 @@ const yt = Me(({
|
|
|
7636
7689
|
const R = z.current || { lipsyncLang: "en" };
|
|
7637
7690
|
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 });
|
|
7638
7691
|
}
|
|
7639
|
-
}, [e.curriculumComplete]),
|
|
7640
|
-
const v =
|
|
7692
|
+
}, [e.curriculumComplete]), k = T(() => {
|
|
7693
|
+
const v = y();
|
|
7641
7694
|
a.current.isQuestionMode = !0, a.current.currentQuestionIndex = 0, a.current.totalQuestions = v?.questions?.length || 0, a.current.score = 0;
|
|
7642
7695
|
const R = E();
|
|
7643
7696
|
R && c.current.onCustomAction({
|
|
@@ -7649,32 +7702,32 @@ const yt = Me(({
|
|
|
7649
7702
|
question: R,
|
|
7650
7703
|
score: a.current.score
|
|
7651
7704
|
});
|
|
7652
|
-
const
|
|
7705
|
+
const S = () => {
|
|
7653
7706
|
if (!u.current || !R) return;
|
|
7654
7707
|
if (u.current.setMood("happy"), e.questionStart)
|
|
7655
7708
|
try {
|
|
7656
7709
|
u.current.playAnimation(e.questionStart, !0);
|
|
7657
|
-
} catch (
|
|
7658
|
-
console.warn("Failed to play questionStart animation:",
|
|
7710
|
+
} catch (U) {
|
|
7711
|
+
console.warn("Failed to play questionStart animation:", U);
|
|
7659
7712
|
}
|
|
7660
7713
|
const H = z.current || { lipsyncLang: "en" };
|
|
7661
7714
|
R.type === "code_test" ? u.current.speakText(`Let's test your coding skills! Here's your first challenge: ${R.question}`, { lipsyncLang: H.lipsyncLang }) : R.type === "multiple_choice" ? u.current.speakText(`Now let me ask you some questions. Here's the first one: ${R.question}`, { lipsyncLang: H.lipsyncLang }) : R.type === "true_false" ? u.current.speakText(`Let's start with some true or false questions. First question: ${R.question}`, { lipsyncLang: H.lipsyncLang }) : u.current.speakText(`Now let me ask you some questions. Here's the first one: ${R.question}`, { lipsyncLang: H.lipsyncLang });
|
|
7662
7715
|
};
|
|
7663
7716
|
if (u.current && u.current.isReady && R)
|
|
7664
|
-
|
|
7717
|
+
S();
|
|
7665
7718
|
else if (u.current && u.current.isReady) {
|
|
7666
7719
|
const H = z.current || { lipsyncLang: "en" };
|
|
7667
7720
|
u.current.speakText("Now let me ask you some questions to test your understanding.", { lipsyncLang: H.lipsyncLang });
|
|
7668
7721
|
} else {
|
|
7669
7722
|
const H = setInterval(() => {
|
|
7670
|
-
u.current && u.current.isReady && (clearInterval(H), R &&
|
|
7723
|
+
u.current && u.current.isReady && (clearInterval(H), R && S());
|
|
7671
7724
|
}, 100);
|
|
7672
7725
|
setTimeout(() => {
|
|
7673
7726
|
clearInterval(H);
|
|
7674
7727
|
}, 5e3);
|
|
7675
7728
|
}
|
|
7676
|
-
}, [e.questionStart,
|
|
7677
|
-
const v =
|
|
7729
|
+
}, [e.questionStart, y, E]), Z = T(() => {
|
|
7730
|
+
const v = y();
|
|
7678
7731
|
if (a.current.currentQuestionIndex < (v?.questions?.length || 0) - 1) {
|
|
7679
7732
|
u.current && u.current.stopSpeaking && u.current.stopSpeaking(), a.current.currentQuestionIndex += 1;
|
|
7680
7733
|
const R = E();
|
|
@@ -7687,7 +7740,7 @@ const yt = Me(({
|
|
|
7687
7740
|
question: R,
|
|
7688
7741
|
score: a.current.score
|
|
7689
7742
|
});
|
|
7690
|
-
const
|
|
7743
|
+
const S = () => {
|
|
7691
7744
|
if (!u.current || !R) return;
|
|
7692
7745
|
if (u.current.setMood("happy"), u.current.setBodyMovement("idle"), e.nextQuestion)
|
|
7693
7746
|
try {
|
|
@@ -7695,7 +7748,7 @@ const yt = Me(({
|
|
|
7695
7748
|
} catch (q) {
|
|
7696
7749
|
console.warn("Failed to play nextQuestion animation:", q);
|
|
7697
7750
|
}
|
|
7698
|
-
const H = z.current || { lipsyncLang: "en" }, _ =
|
|
7751
|
+
const H = z.current || { lipsyncLang: "en" }, _ = y()?.questions?.length || 0, j = a.current.currentQuestionIndex >= _ - 1;
|
|
7699
7752
|
if (R.type === "code_test") {
|
|
7700
7753
|
const q = j ? `Great! Here's your final coding challenge: ${R.question}` : `Great! Now let's move on to your next coding challenge: ${R.question}`;
|
|
7701
7754
|
u.current.speakText(q, {
|
|
@@ -7719,10 +7772,10 @@ const yt = Me(({
|
|
|
7719
7772
|
}
|
|
7720
7773
|
};
|
|
7721
7774
|
if (u.current && u.current.isReady && R)
|
|
7722
|
-
|
|
7775
|
+
S();
|
|
7723
7776
|
else if (R) {
|
|
7724
7777
|
const H = setInterval(() => {
|
|
7725
|
-
u.current && u.current.isReady && (clearInterval(H),
|
|
7778
|
+
u.current && u.current.isReady && (clearInterval(H), S());
|
|
7726
7779
|
}, 100);
|
|
7727
7780
|
setTimeout(() => {
|
|
7728
7781
|
clearInterval(H);
|
|
@@ -7736,11 +7789,11 @@ const yt = Me(({
|
|
|
7736
7789
|
totalQuestions: a.current.totalQuestions,
|
|
7737
7790
|
score: a.current.score
|
|
7738
7791
|
});
|
|
7739
|
-
}, [e.nextQuestion,
|
|
7792
|
+
}, [e.nextQuestion, y, E]), K = T(() => {
|
|
7740
7793
|
const v = M.current || { modules: [] }, R = v.modules[a.current.currentModuleIndex];
|
|
7741
7794
|
if (a.current.currentLessonIndex < (R?.lessons?.length || 0) - 1) {
|
|
7742
7795
|
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;
|
|
7743
|
-
const H = v.modules[a.current.currentModuleIndex],
|
|
7796
|
+
const H = v.modules[a.current.currentModuleIndex], U = a.current.currentLessonIndex < (H?.lessons?.length || 0) - 1, _ = a.current.currentModuleIndex < (v.modules?.length || 0) - 1, j = U || _;
|
|
7744
7797
|
c.current.onCustomAction({
|
|
7745
7798
|
type: "lessonStart",
|
|
7746
7799
|
moduleIndex: a.current.currentModuleIndex,
|
|
@@ -7749,11 +7802,11 @@ const yt = Me(({
|
|
|
7749
7802
|
}), c.current.onLessonStart({
|
|
7750
7803
|
moduleIndex: a.current.currentModuleIndex,
|
|
7751
7804
|
lessonIndex: a.current.currentLessonIndex,
|
|
7752
|
-
lesson:
|
|
7805
|
+
lesson: y()
|
|
7753
7806
|
}), u.current && (u.current.setMood("happy"), u.current.setBodyMovement("idle"));
|
|
7754
7807
|
} else if (a.current.currentModuleIndex < (v.modules?.length || 0) - 1) {
|
|
7755
7808
|
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;
|
|
7756
|
-
const
|
|
7809
|
+
const U = v.modules[a.current.currentModuleIndex], _ = a.current.currentLessonIndex < (U?.lessons?.length || 0) - 1, j = a.current.currentModuleIndex < (v.modules?.length || 0) - 1, q = _ || j;
|
|
7757
7810
|
c.current.onCustomAction({
|
|
7758
7811
|
type: "lessonStart",
|
|
7759
7812
|
moduleIndex: a.current.currentModuleIndex,
|
|
@@ -7762,28 +7815,28 @@ const yt = Me(({
|
|
|
7762
7815
|
}), c.current.onLessonStart({
|
|
7763
7816
|
moduleIndex: a.current.currentModuleIndex,
|
|
7764
7817
|
lessonIndex: a.current.currentLessonIndex,
|
|
7765
|
-
lesson:
|
|
7818
|
+
lesson: y()
|
|
7766
7819
|
}), u.current && (u.current.setMood("happy"), u.current.setBodyMovement("idle"));
|
|
7767
7820
|
} else
|
|
7768
7821
|
I.current && I.current();
|
|
7769
7822
|
}, []), X = T(() => {
|
|
7770
|
-
const v =
|
|
7823
|
+
const v = y();
|
|
7771
7824
|
let R = null;
|
|
7772
7825
|
if (v?.avatar_script && v?.body) {
|
|
7773
|
-
const
|
|
7774
|
-
R = `${
|
|
7826
|
+
const S = v.avatar_script.trim(), H = v.body.trim(), U = S.match(/[.!?]$/) ? " " : ". ";
|
|
7827
|
+
R = `${S}${U}${H}`;
|
|
7775
7828
|
} else
|
|
7776
7829
|
R = v?.avatar_script || v?.body || null;
|
|
7777
7830
|
if (u.current && u.current.isReady && R) {
|
|
7778
7831
|
a.current.isTeaching = !0, a.current.isQuestionMode = !1, a.current.score = 0, a.current.totalQuestions = 0, u.current.setMood("happy");
|
|
7779
|
-
let
|
|
7832
|
+
let S = !1;
|
|
7780
7833
|
if (e.teaching)
|
|
7781
7834
|
try {
|
|
7782
|
-
u.current.playAnimation(e.teaching, !0),
|
|
7783
|
-
} catch (
|
|
7784
|
-
console.warn("Failed to play teaching animation:",
|
|
7835
|
+
u.current.playAnimation(e.teaching, !0), S = !0;
|
|
7836
|
+
} catch (U) {
|
|
7837
|
+
console.warn("Failed to play teaching animation:", U);
|
|
7785
7838
|
}
|
|
7786
|
-
|
|
7839
|
+
S || u.current.setBodyMovement("gesturing");
|
|
7787
7840
|
const H = z.current || { lipsyncLang: "en" };
|
|
7788
7841
|
c.current.onLessonStart({
|
|
7789
7842
|
moduleIndex: a.current.currentModuleIndex,
|
|
@@ -7813,17 +7866,17 @@ const yt = Me(({
|
|
|
7813
7866
|
}
|
|
7814
7867
|
});
|
|
7815
7868
|
}
|
|
7816
|
-
}, [e.teaching,
|
|
7817
|
-
const R = E(),
|
|
7818
|
-
if (
|
|
7869
|
+
}, [e.teaching, y]), $ = T((v) => {
|
|
7870
|
+
const R = E(), S = P(v, R);
|
|
7871
|
+
if (S && (a.current.score += 1), c.current.onQuestionAnswer({
|
|
7819
7872
|
moduleIndex: a.current.currentModuleIndex,
|
|
7820
7873
|
lessonIndex: a.current.currentLessonIndex,
|
|
7821
7874
|
questionIndex: a.current.currentQuestionIndex,
|
|
7822
7875
|
answer: v,
|
|
7823
|
-
isCorrect:
|
|
7876
|
+
isCorrect: S,
|
|
7824
7877
|
question: R
|
|
7825
7878
|
}), u.current)
|
|
7826
|
-
if (
|
|
7879
|
+
if (S) {
|
|
7827
7880
|
if (u.current.setMood("happy"), e.correct)
|
|
7828
7881
|
try {
|
|
7829
7882
|
u.current.playReaction("happy");
|
|
@@ -7831,10 +7884,10 @@ const yt = Me(({
|
|
|
7831
7884
|
u.current.setBodyMovement("happy");
|
|
7832
7885
|
}
|
|
7833
7886
|
u.current.setBodyMovement("gesturing");
|
|
7834
|
-
const
|
|
7835
|
-
a.current.currentQuestionIndex >=
|
|
7836
|
-
const _ = a.current.currentQuestionIndex <
|
|
7837
|
-
console.log("[CurriculumLearning] Answer feedback - questionIndex:", a.current.currentQuestionIndex, "totalQuestions:",
|
|
7887
|
+
const U = y()?.questions?.length || 0;
|
|
7888
|
+
a.current.currentQuestionIndex >= U - 1;
|
|
7889
|
+
const _ = a.current.currentQuestionIndex < U - 1;
|
|
7890
|
+
console.log("[CurriculumLearning] Answer feedback - questionIndex:", a.current.currentQuestionIndex, "totalQuestions:", U, "hasNextQuestion:", _);
|
|
7838
7891
|
const j = R.type === "code_test" ? `Great job! Your code passed all the tests! ${R.explanation || ""}` : `Excellent! That's correct! ${R.explanation || ""}`, q = z.current || { lipsyncLang: "en" };
|
|
7839
7892
|
u.current.speakText(j, {
|
|
7840
7893
|
lipsyncLang: q.lipsyncLang,
|
|
@@ -7859,8 +7912,8 @@ const yt = Me(({
|
|
|
7859
7912
|
u.current.setBodyMovement("idle");
|
|
7860
7913
|
}
|
|
7861
7914
|
u.current.setBodyMovement("gesturing");
|
|
7862
|
-
const
|
|
7863
|
-
console.log("[CurriculumLearning] Answer feedback (incorrect) - questionIndex:", a.current.currentQuestionIndex, "totalQuestions:",
|
|
7915
|
+
const U = y()?.questions?.length || 0, _ = a.current.currentQuestionIndex >= U - 1, j = a.current.currentQuestionIndex < U - 1;
|
|
7916
|
+
console.log("[CurriculumLearning] Answer feedback (incorrect) - questionIndex:", a.current.currentQuestionIndex, "totalQuestions:", U, "hasNextQuestion:", j);
|
|
7864
7917
|
const q = R.type === "code_test" ? `Your code didn't pass all the tests. ${R.explanation || "Try again!"}` : `Not quite right, but don't worry! ${R.explanation || ""}${_ ? "" : " Let's move on to the next question."}`, Le = z.current || { lipsyncLang: "en" };
|
|
7865
7918
|
u.current.speakText(q, {
|
|
7866
7919
|
lipsyncLang: Le.lipsyncLang,
|
|
@@ -7879,20 +7932,20 @@ const yt = Me(({
|
|
|
7879
7932
|
});
|
|
7880
7933
|
}
|
|
7881
7934
|
else {
|
|
7882
|
-
const
|
|
7935
|
+
const U = y()?.questions?.length || 0;
|
|
7883
7936
|
c.current.onCustomAction({
|
|
7884
7937
|
type: "answerFeedbackComplete",
|
|
7885
7938
|
moduleIndex: a.current.currentModuleIndex,
|
|
7886
7939
|
lessonIndex: a.current.currentLessonIndex,
|
|
7887
7940
|
questionIndex: a.current.currentQuestionIndex,
|
|
7888
|
-
isCorrect:
|
|
7889
|
-
hasNextQuestion: a.current.currentQuestionIndex <
|
|
7941
|
+
isCorrect: S,
|
|
7942
|
+
hasNextQuestion: a.current.currentQuestionIndex < U - 1,
|
|
7890
7943
|
score: a.current.score,
|
|
7891
7944
|
totalQuestions: a.current.totalQuestions,
|
|
7892
7945
|
avatarNotReady: !0
|
|
7893
7946
|
});
|
|
7894
7947
|
}
|
|
7895
|
-
}, [e.correct, e.incorrect, E,
|
|
7948
|
+
}, [e.correct, e.incorrect, E, y, P]), se = T((v) => {
|
|
7896
7949
|
const R = E();
|
|
7897
7950
|
if (!v || typeof v != "object") {
|
|
7898
7951
|
console.error("Invalid code test result format. Expected object with {passed: boolean, ...}");
|
|
@@ -7902,7 +7955,7 @@ const yt = Me(({
|
|
|
7902
7955
|
console.warn("Current question is not a code test. Use handleAnswerSelect for other question types.");
|
|
7903
7956
|
return;
|
|
7904
7957
|
}
|
|
7905
|
-
const
|
|
7958
|
+
const S = {
|
|
7906
7959
|
passed: v.passed === !0,
|
|
7907
7960
|
results: v.results || [],
|
|
7908
7961
|
output: v.output || "",
|
|
@@ -7917,9 +7970,9 @@ const yt = Me(({
|
|
|
7917
7970
|
moduleIndex: a.current.currentModuleIndex,
|
|
7918
7971
|
lessonIndex: a.current.currentLessonIndex,
|
|
7919
7972
|
questionIndex: a.current.currentQuestionIndex,
|
|
7920
|
-
testResult:
|
|
7973
|
+
testResult: S,
|
|
7921
7974
|
question: R
|
|
7922
|
-
}), p.current && p.current(
|
|
7975
|
+
}), p.current && p.current(S);
|
|
7923
7976
|
}, [E, P]), ae = T(() => {
|
|
7924
7977
|
if (a.current.currentQuestionIndex > 0) {
|
|
7925
7978
|
a.current.currentQuestionIndex -= 1;
|
|
@@ -7936,21 +7989,21 @@ const yt = Me(({
|
|
|
7936
7989
|
const R = () => {
|
|
7937
7990
|
if (!u.current || !v) return;
|
|
7938
7991
|
u.current.setMood("happy"), u.current.setBodyMovement("idle");
|
|
7939
|
-
const
|
|
7992
|
+
const S = z.current || { lipsyncLang: "en" };
|
|
7940
7993
|
v.type === "code_test" ? u.current.speakText(`Let's go back to this coding challenge: ${v.question}`, {
|
|
7941
|
-
lipsyncLang:
|
|
7994
|
+
lipsyncLang: S.lipsyncLang
|
|
7942
7995
|
}) : u.current.speakText(`Going back to: ${v.question}`, {
|
|
7943
|
-
lipsyncLang:
|
|
7996
|
+
lipsyncLang: S.lipsyncLang
|
|
7944
7997
|
});
|
|
7945
7998
|
};
|
|
7946
7999
|
if (u.current && u.current.isReady && v)
|
|
7947
8000
|
R();
|
|
7948
8001
|
else if (v) {
|
|
7949
|
-
const
|
|
7950
|
-
u.current && u.current.isReady && (clearInterval(
|
|
8002
|
+
const S = setInterval(() => {
|
|
8003
|
+
u.current && u.current.isReady && (clearInterval(S), R());
|
|
7951
8004
|
}, 100);
|
|
7952
8005
|
setTimeout(() => {
|
|
7953
|
-
clearInterval(
|
|
8006
|
+
clearInterval(S);
|
|
7954
8007
|
}, 5e3);
|
|
7955
8008
|
}
|
|
7956
8009
|
}
|
|
@@ -7964,7 +8017,7 @@ const yt = Me(({
|
|
|
7964
8017
|
}), c.current.onLessonStart({
|
|
7965
8018
|
moduleIndex: a.current.currentModuleIndex,
|
|
7966
8019
|
lessonIndex: a.current.currentLessonIndex,
|
|
7967
|
-
lesson:
|
|
8020
|
+
lesson: y()
|
|
7968
8021
|
}), u.current && (u.current.setMood("happy"), u.current.setBodyMovement("idle"));
|
|
7969
8022
|
else if (a.current.currentModuleIndex > 0) {
|
|
7970
8023
|
const H = v.modules[a.current.currentModuleIndex - 1];
|
|
@@ -7975,43 +8028,43 @@ const yt = Me(({
|
|
|
7975
8028
|
}), c.current.onLessonStart({
|
|
7976
8029
|
moduleIndex: a.current.currentModuleIndex,
|
|
7977
8030
|
lessonIndex: a.current.currentLessonIndex,
|
|
7978
|
-
lesson:
|
|
8031
|
+
lesson: y()
|
|
7979
8032
|
}), u.current && (u.current.setMood("happy"), u.current.setBodyMovement("idle"));
|
|
7980
8033
|
}
|
|
7981
|
-
}, [
|
|
8034
|
+
}, [y]), ee = T(() => {
|
|
7982
8035
|
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;
|
|
7983
8036
|
}, []), le = T((v) => {
|
|
7984
8037
|
console.log("Avatar is ready!", v);
|
|
7985
|
-
const R =
|
|
7986
|
-
h &&
|
|
8038
|
+
const R = y(), S = R?.avatar_script || R?.body;
|
|
8039
|
+
h && S && setTimeout(() => {
|
|
7987
8040
|
d.current && d.current();
|
|
7988
8041
|
}, 10);
|
|
7989
|
-
}, [h,
|
|
8042
|
+
}, [h, y]);
|
|
7990
8043
|
Xe(() => {
|
|
7991
|
-
d.current = X, g.current = K,
|
|
8044
|
+
d.current = X, g.current = K, x.current = W, b.current = Z, I.current = oe, B.current = k, p.current = $;
|
|
7992
8045
|
}), Ee(r, () => ({
|
|
7993
8046
|
// Curriculum control methods
|
|
7994
8047
|
startTeaching: X,
|
|
7995
|
-
startQuestions:
|
|
8048
|
+
startQuestions: k,
|
|
7996
8049
|
handleAnswerSelect: $,
|
|
7997
8050
|
handleCodeTestResult: se,
|
|
7998
8051
|
nextQuestion: Z,
|
|
7999
8052
|
previousQuestion: ae,
|
|
8000
8053
|
nextLesson: K,
|
|
8001
8054
|
previousLesson: pe,
|
|
8002
|
-
completeLesson:
|
|
8055
|
+
completeLesson: W,
|
|
8003
8056
|
completeCurriculum: oe,
|
|
8004
8057
|
resetCurriculum: ee,
|
|
8005
8058
|
getState: () => ({ ...a.current }),
|
|
8006
8059
|
getCurrentQuestion: () => E(),
|
|
8007
|
-
getCurrentLesson: () =>
|
|
8060
|
+
getCurrentLesson: () => y(),
|
|
8008
8061
|
// Direct access to avatar ref (always returns current value)
|
|
8009
8062
|
getAvatarRef: () => u.current,
|
|
8010
8063
|
// Convenience methods that delegate to avatar (always check current ref)
|
|
8011
8064
|
speakText: async (v, R = {}) => {
|
|
8012
8065
|
await u.current?.resumeAudioContext?.();
|
|
8013
|
-
const
|
|
8014
|
-
u.current?.speakText(v, { ...R, lipsyncLang: R.lipsyncLang ||
|
|
8066
|
+
const S = z.current || { lipsyncLang: "en" };
|
|
8067
|
+
u.current?.speakText(v, { ...R, lipsyncLang: R.lipsyncLang || S.lipsyncLang });
|
|
8015
8068
|
},
|
|
8016
8069
|
resumeAudioContext: async () => {
|
|
8017
8070
|
if (u.current?.resumeAudioContext)
|
|
@@ -8022,8 +8075,8 @@ const yt = Me(({
|
|
|
8022
8075
|
if (R.state === "suspended" || R.state === "interrupted")
|
|
8023
8076
|
try {
|
|
8024
8077
|
await R.resume(), console.log("Audio context resumed via talkingHead");
|
|
8025
|
-
} catch (
|
|
8026
|
-
console.warn("Failed to resume audio context:",
|
|
8078
|
+
} catch (S) {
|
|
8079
|
+
console.warn("Failed to resume audio context:", S);
|
|
8027
8080
|
}
|
|
8028
8081
|
} else
|
|
8029
8082
|
console.warn("Audio context not available yet");
|
|
@@ -8055,7 +8108,7 @@ const yt = Me(({
|
|
|
8055
8108
|
handleResize: () => u.current?.handleResize(),
|
|
8056
8109
|
// Avatar readiness check (always returns current value)
|
|
8057
8110
|
isAvatarReady: () => u.current?.isReady || !1
|
|
8058
|
-
}), [X,
|
|
8111
|
+
}), [X, k, $, se, Z, K, W, oe, ee, E, y]);
|
|
8059
8112
|
const D = z.current || {
|
|
8060
8113
|
avatarUrl: "/avatars/brunette.glb",
|
|
8061
8114
|
avatarBody: "F",
|
|
@@ -8207,6 +8260,6 @@ export {
|
|
|
8207
8260
|
Ge as animations,
|
|
8208
8261
|
Fe as getActiveTTSConfig,
|
|
8209
8262
|
wt as getAnimation,
|
|
8210
|
-
|
|
8263
|
+
St as getVoiceOptions,
|
|
8211
8264
|
zt as hasAnimation
|
|
8212
8265
|
};
|