@sage-rsc/talking-head-react 1.0.84 → 1.1.1

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.js CHANGED
@@ -1,6 +1,6 @@
1
1
  import { jsxs as Pe, jsx as me } from "react/jsx-runtime";
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 x from "three";
2
+ import { forwardRef as Me, useRef as D, useState as ce, useEffect as de, useCallback as T, useImperativeHandle as Ee, useLayoutEffect as Xe } from "react";
3
+ import * as f from "three";
4
4
  import { OrbitControls as Ye } from "three/addons/controls/OrbitControls.js";
5
5
  import { GLTFLoader as je } from "three/addons/loaders/GLTFLoader.js";
6
6
  import { DRACOLoader as Qe } from "three/addons/loaders/DRACOLoader.js";
@@ -8,13 +8,13 @@ import { FBXLoader as De } from "three/addons/loaders/FBXLoader.js";
8
8
  import { RoomEnvironment as qe } from "three/addons/environments/RoomEnvironment.js";
9
9
  import Ke from "three/addons/libs/stats.module.js";
10
10
  let m, re, ue;
11
- const A = [0, 0, 0, 0], w = new x.Vector3(), ze = new x.Vector3(), ne = new x.Vector3(), Ce = new x.Vector3();
12
- new x.Plane();
13
- new x.Ray();
14
- new x.Euler();
15
- const ie = new x.Quaternion(), Ne = new x.Quaternion(), fe = new x.Matrix4(), xe = new x.Matrix4();
16
- new x.Vector3();
17
- const He = new x.Vector3(0, 0, 1), _e = new x.Vector3(1, 0, 0), Je = new x.Vector3(0, 1, 0), $e = new x.Vector3(0, 0, 1);
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(), Oe = new f.Quaternion(), fe = new f.Matrix4(), xe = new f.Matrix4();
16
+ new f.Vector3();
17
+ const He = new f.Vector3(0, 0, 1), _e = new f.Vector3(1, 0, 0), Je = new f.Vector3(0, 1, 0), $e = new f.Vector3(0, 0, 1);
18
18
  class et {
19
19
  constructor(t = null) {
20
20
  this.opt = Object.assign({
@@ -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(Ne.setFromUnitVectors(He, w).invert()).normalize(), u.qWorldInverseYaw = ie.clone().normalize(), this.data.push(u), this.dict[h] = u;
341
+ u.boneParent.matrixWorld.decompose(w, ie, ne), w.copy(He).applyQuaternion(ie).setY(0).normalize(), ie.premultiply(Oe.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(Ne.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)
372
+ else if (o.boneParent.quaternion.copy(o.qBasis), o.pivot && this.opt.isPivots && (o.boneParent.updateWorldMatrix(!1, !1), o.boneParent.matrixWorld.decompose(w, ie, ne), w.copy(He).applyQuaternion(ie).setY(0).normalize(), ie.premultiply(Oe.setFromUnitVectors(He, w).invert()).normalize(), o.boneParent.quaternion.multiply(ie.invert()), o.boneParent.quaternion.multiply(o.qWorldInverseYaw)), o.isZ && (m = Math.atan(A[0] / o.l), ie.setFromAxisAngle($e, -m), o.boneParent.quaternion.multiply(ie)), o.isY && (m = o.l / 3, m = m * Math.tanh(A[1] / m), o.bone.position.setLength(o.l + m)), o.isX && (m = Math.atan(A[2] / o.l), ie.setFromAxisAngle(_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 x.SphereGeometry(m.radii[n], 6, 6), s = new x.MeshBasicMaterial({
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 x.Mesh(i, s), m.objects[n].renderOrder = 997, e.add(m.objects[n]), m.deltaLocals[n] && m.objects[n].position.set(
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 x.BufferGeometry(), n = m.bones.map((h) => [0, 0, 0]).flat();
412
- e.setAttribute("position", new x.Float32BufferAttribute(n, 3));
413
- const i = new x.Color(this.opt.helperBoneColor1), s = new x.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 x.Float32BufferAttribute(o, 3));
415
- const l = new x.PointsMaterial({
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 x.Points(e, l), m.object.renderOrder = 998, m.object.matrix = this.armature.matrixWorld, m.object.matrixAutoUpdate = !1, this.scene.add(m.object);
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 x.BufferGeometry(), n = m.bones.map((h) => [0, 0, 0, 0, 0, 0]).flat();
427
- e.setAttribute("position", new x.Float32BufferAttribute(n, 3));
428
- const i = new x.Color(this.opt.helperLinkColor1), s = new x.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 x.Float32BufferAttribute(o, 3));
430
- const l = new x.LineBasicMaterial({
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 x.LineSegments(e, l), m.object.renderOrder = 999, m.object.matrix = this.armature.matrixWorld, m.object.matrixAutoUpdate = !1, this.scene.add(m.object);
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
  /**
@@ -521,10 +521,10 @@ class tt {
521
521
  for (let l = 0; l < o; l++) {
522
522
  const h = l * s, r = Math.min(h + i, t.length), u = t.slice(h, r), a = this.calculateEnergy(u);
523
523
  n.energy.push(a);
524
- const d = this.calculateSpectralCentroid(u);
525
- n.spectralCentroid.push(d);
526
- const c = this.calculateZeroCrossingRate(u);
527
- n.zeroCrossingRate.push(c);
524
+ const c = this.calculateSpectralCentroid(u);
525
+ n.spectralCentroid.push(c);
526
+ const d = this.calculateZeroCrossingRate(u);
527
+ n.zeroCrossingRate.push(d);
528
528
  const g = this.calculateMFCC(u);
529
529
  n.mfcc.push(g);
530
530
  }
@@ -606,10 +606,10 @@ class tt {
606
606
  for (let h = 0; h < e; h += i) {
607
607
  let r = 1, u = 0;
608
608
  for (let a = 0; a < i / 2; a++) {
609
- const d = n[(h + a) * 2], c = n[(h + a) * 2 + 1], g = n[(h + a + i / 2) * 2] * r - n[(h + a + i / 2) * 2 + 1] * u, y = n[(h + a + i / 2) * 2] * u + n[(h + a + i / 2) * 2 + 1] * r;
610
- n[(h + a) * 2] = d + g, n[(h + a) * 2 + 1] = c + y, n[(h + a + i / 2) * 2] = d - g, n[(h + a + i / 2) * 2 + 1] = c - y;
611
- const b = r * o - u * l, I = r * l + u * o;
612
- r = b, u = I;
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
+ const b = r * o - u * l, R = r * l + u * o;
612
+ r = b, u = R;
613
613
  }
614
614
  }
615
615
  }
@@ -703,15 +703,15 @@ class tt {
703
703
  const o = this.textToVisemes(e);
704
704
  let l = 0, h = 0;
705
705
  for (let r = 0; r < s.length && l < o.length; r++) {
706
- const u = s[r], a = o[l], d = t.energy[Math.floor(u / 0.023)] || 0, c = this.calculateVisemeDuration(a, d);
706
+ const u = s[r], a = o[l], c = t.energy[Math.floor(u / 0.023)] || 0, d = this.calculateVisemeDuration(a, c);
707
707
  i.push({
708
708
  viseme: a,
709
709
  startTime: h,
710
- endTime: h + c,
711
- duration: c,
712
- intensity: Math.min(1, d * 2)
710
+ endTime: h + d,
711
+ duration: d,
712
+ intensity: Math.min(1, c * 2)
713
713
  // Map energy to viseme intensity
714
- }), h += c, l++;
714
+ }), h += d, l++;
715
715
  }
716
716
  for (; l < o.length; ) {
717
717
  const r = o[l], u = this.calculateVisemeDuration(r, 0.5);
@@ -1207,10 +1207,10 @@ class nt {
1207
1207
  Object.keys(this.rules).forEach((e) => {
1208
1208
  this.rules[e] = this.rules[e].map((n) => {
1209
1209
  const i = n.indexOf("["), s = n.indexOf("]"), o = n.indexOf("="), l = n.substring(0, i), h = n.substring(i + 1, s), r = n.substring(s + 1, o), u = n.substring(o + 1), a = { regex: "", move: 0, visemes: [] };
1210
- let d = "";
1211
- d += [...l].map((g) => t[g] || g).join("");
1212
- const c = [...h];
1213
- return c[0] = c[0].toLowerCase(), d += c.join(""), a.move = c.length, d += [...r].map((g) => t[g] || g).join(""), a.regex = new RegExp(d), u.length && u.split(" ").forEach((g) => {
1210
+ let c = "";
1211
+ c += [...l].map((g) => t[g] || g).join("");
1212
+ const d = [...h];
1213
+ return d[0] = d[0].toLowerCase(), c += d.join(""), a.move = d.length, c += [...r].map((g) => t[g] || g).join(""), a.regex = new RegExp(c), u.length && u.split(" ").forEach((g) => {
1214
1214
  a.visemes.push(g);
1215
1215
  }), a;
1216
1216
  });
@@ -1380,11 +1380,11 @@ class nt {
1380
1380
  if ((e.words.substring(0, e.i) + s.toLowerCase() + e.words.substring(e.i + 1)).match(h.regex)) {
1381
1381
  h.visemes.forEach((a) => {
1382
1382
  if (e.visemes.length && e.visemes[e.visemes.length - 1] === a) {
1383
- const d = 0.7 * (this.visemeDurations[a] || 1);
1384
- e.durations[e.durations.length - 1] += d, n += d;
1383
+ const c = 0.7 * (this.visemeDurations[a] || 1);
1384
+ e.durations[e.durations.length - 1] += c, n += c;
1385
1385
  } else {
1386
- const d = this.visemeDurations[a] || 1;
1387
- e.visemes.push(a), e.times.push(n), e.durations.push(d), n += d;
1386
+ const c = this.visemeDurations[a] || 1;
1387
+ e.visemes.push(a), e.times.push(n), e.durations.push(c), n += c;
1388
1388
  }
1389
1389
  }), e.i += h.move;
1390
1390
  break;
@@ -1617,10 +1617,10 @@ class ot {
1617
1617
  Object.keys(this.rules).forEach((e) => {
1618
1618
  this.rules[e] = this.rules[e].map((n) => {
1619
1619
  const i = n.indexOf("["), s = n.indexOf("]"), o = n.indexOf("="), l = n.substring(0, i), h = n.substring(i + 1, s), r = n.substring(s + 1, o), u = n.substring(o + 1), a = { regex: "", move: 0, visemes: [] };
1620
- let d = "";
1621
- d += [...l].map((g) => t[g] || g).join("");
1622
- const c = [...h];
1623
- return c[0] = c[0].toLowerCase(), d += c.join(""), a.move = c.length, d += [...r].map((g) => t[g] || g).join(""), a.regex = new RegExp(d), u.length && u.split(" ").forEach((g) => {
1620
+ let c = "";
1621
+ c += [...l].map((g) => t[g] || g).join("");
1622
+ const d = [...h];
1623
+ return d[0] = d[0].toLowerCase(), c += d.join(""), a.move = d.length, c += [...r].map((g) => t[g] || g).join(""), a.regex = new RegExp(c), u.length && u.split(" ").forEach((g) => {
1624
1624
  a.visemes.push(g);
1625
1625
  }), a;
1626
1626
  });
@@ -1735,13 +1735,13 @@ class ot {
1735
1735
  for (let h = 0; h < o.length; h++) {
1736
1736
  const r = o[h];
1737
1737
  if ((e.words.substring(0, e.i) + s.toLowerCase() + e.words.substring(e.i + 1)).match(r.regex)) {
1738
- r.visemes.forEach((d) => {
1739
- if (e.visemes.length && e.visemes[e.visemes.length - 1] === d) {
1740
- const c = 0.7 * (this.visemeDurations[d] || 1);
1741
- e.durations[e.durations.length - 1] += c, n += c;
1738
+ r.visemes.forEach((c) => {
1739
+ if (e.visemes.length && e.visemes[e.visemes.length - 1] === c) {
1740
+ const d = 0.7 * (this.visemeDurations[c] || 1);
1741
+ e.durations[e.durations.length - 1] += d, n += d;
1742
1742
  } else {
1743
- const c = this.visemeDurations[d] || 1;
1744
- e.visemes.push(d), e.times.push(n), e.durations.push(c), n += c;
1743
+ const d = this.visemeDurations[c] || 1;
1744
+ e.visemes.push(c), e.times.push(n), e.durations.push(d), n += d;
1745
1745
  }
1746
1746
  }), e.i += r.move, l = !0;
1747
1747
  break;
@@ -2132,10 +2132,10 @@ class at {
2132
2132
  Object.keys(this.rules).forEach((e) => {
2133
2133
  this.rules[e] = this.rules[e].map((n) => {
2134
2134
  const i = n.indexOf("["), s = n.indexOf("]"), o = n.indexOf("="), l = n.substring(0, i), h = n.substring(i + 1, s), r = n.substring(s + 1, o), u = n.substring(o + 1), a = { regex: "", move: 0, visemes: [] };
2135
- let d = "";
2136
- d += [...l].map((g) => t[g] || g).join("");
2137
- const c = [...h];
2138
- return c[0] = c[0].toLowerCase(), d += c.join(""), a.move = c.length, d += [...r].map((g) => t[g] || g).join(""), a.regex = new RegExp(d, "i"), u.length && u.split(" ").forEach((g) => {
2135
+ let c = "";
2136
+ c += [...l].map((g) => t[g] || g).join("");
2137
+ const d = [...h];
2138
+ return d[0] = d[0].toLowerCase(), c += d.join(""), a.move = d.length, c += [...r].map((g) => t[g] || g).join(""), a.regex = new RegExp(c, "i"), u.length && u.split(" ").forEach((g) => {
2139
2139
  g && a.visemes.push(g);
2140
2140
  }), a;
2141
2141
  });
@@ -2270,13 +2270,13 @@ class at {
2270
2270
  for (let h = 0; h < o.length; h++) {
2271
2271
  const r = o[h];
2272
2272
  if ((e.words.substring(0, e.i) + s.toLowerCase() + e.words.substring(e.i + 1)).match(r.regex)) {
2273
- r.visemes.forEach((d) => {
2274
- if (e.visemes.length && e.visemes[e.visemes.length - 1] === d) {
2275
- const c = 0.7 * (this.visemeDurations[d] || 1);
2276
- e.durations[e.durations.length - 1] += c, n += c;
2273
+ r.visemes.forEach((c) => {
2274
+ if (e.visemes.length && e.visemes[e.visemes.length - 1] === c) {
2275
+ const d = 0.7 * (this.visemeDurations[c] || 1);
2276
+ e.durations[e.durations.length - 1] += d, n += d;
2277
2277
  } else {
2278
- const c = this.visemeDurations[d] || 1;
2279
- e.visemes.push(d), e.times.push(n), e.durations.push(c), n += c;
2278
+ const d = this.visemeDurations[c] || 1;
2279
+ e.visemes.push(c), e.times.push(n), e.durations.push(d), n += d;
2280
2280
  }
2281
2281
  }), e.i += r.move, l = !0;
2282
2282
  break;
@@ -2629,14 +2629,14 @@ const ct = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
2629
2629
  fr: rt,
2630
2630
  fi: ut,
2631
2631
  lt: ct
2632
- }, Q = new x.Quaternion(), W = new x.Euler(), ve = new x.Vector3(), Re = new x.Vector3(), We = new x.Box3();
2633
- new x.Matrix4();
2634
- new x.Matrix4();
2635
- new x.Vector3();
2636
- new x.Vector3(0, 0, 1);
2637
- const mt = new x.Vector3(1, 0, 0);
2638
- new x.Vector3(0, 1, 0);
2639
- new x.Vector3(0, 0, 1);
2632
+ }, Q = new f.Quaternion(), V = new f.Euler(), ve = new f.Vector3(), Ie = new f.Vector3(), We = new f.Box3();
2633
+ new f.Matrix4();
2634
+ new f.Matrix4();
2635
+ new f.Vector3();
2636
+ new f.Vector3(0, 0, 1);
2637
+ const mt = new f.Vector3(1, 0, 0);
2638
+ new f.Vector3(0, 1, 0);
2639
+ new f.Vector3(0, 0, 1);
2640
2640
  class Be {
2641
2641
  /**
2642
2642
  * Avatar.
@@ -4073,22 +4073,22 @@ class Be {
4073
4073
  if (this.isAvatarOnly = this.opt.avatarOnly, this.isAvatarOnly)
4074
4074
  this.scene = this.opt.avatarOnlyScene, this.camera = this.opt.avatarOnlyCamera;
4075
4075
  else {
4076
- this.renderer = new x.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 = x.SRGBColorSpace, this.renderer.toneMapping = x.ACESFilmicToneMapping, this.renderer.shadowMap.enabled = !1, this.nodeAvatar.appendChild(this.renderer.domElement), this.camera = new x.PerspectiveCamera(10, this.nodeAvatar.clientWidth / this.nodeAvatar.clientHeight, 0.1, 2e3), this.scene = new x.Scene(), this.lightAmbient = new x.AmbientLight(
4077
- new x.Color(this.opt.lightAmbientColor),
4076
+ this.renderer = new f.WebGLRenderer({ antialias: !0, alpha: !0 }), this.renderer.setPixelRatio(this.opt.modelPixelRatio * window.devicePixelRatio), this.renderer.setSize(this.nodeAvatar.clientWidth, this.nodeAvatar.clientHeight), this.renderer.outputColorSpace = f.SRGBColorSpace, this.renderer.toneMapping = f.ACESFilmicToneMapping, this.renderer.shadowMap.enabled = !1, this.nodeAvatar.appendChild(this.renderer.domElement), this.camera = new f.PerspectiveCamera(10, this.nodeAvatar.clientWidth / this.nodeAvatar.clientHeight, 0.1, 2e3), this.scene = new f.Scene(), this.lightAmbient = new f.AmbientLight(
4077
+ new f.Color(this.opt.lightAmbientColor),
4078
4078
  this.opt.lightAmbientIntensity
4079
- ), this.lightDirect = new x.DirectionalLight(
4080
- new x.Color(this.opt.lightDirectColor),
4079
+ ), this.lightDirect = new f.DirectionalLight(
4080
+ new f.Color(this.opt.lightDirectColor),
4081
4081
  this.opt.lightDirectIntensity
4082
- ), this.lightSpot = new x.SpotLight(
4083
- new x.Color(this.opt.lightSpotColor),
4082
+ ), this.lightSpot = new f.SpotLight(
4083
+ new f.Color(this.opt.lightSpotColor),
4084
4084
  this.opt.lightSpotIntensity,
4085
4085
  0,
4086
4086
  this.opt.lightSpotDispersion
4087
4087
  ), this.setLighting(this.opt);
4088
- const l = new x.PMREMGenerator(this.renderer);
4088
+ const l = new f.PMREMGenerator(this.renderer);
4089
4089
  l.compileEquirectangularShader(), this.scene.environment = l.fromScene(new qe()).texture, this.resizeobserver = new ResizeObserver(this.onResize.bind(this)), this.resizeobserver.observe(this.nodeAvatar), this.controls = new Ye(this.camera, this.renderer.domElement), this.controls.enableZoom = this.opt.cameraZoomEnable, this.controls.enableRotate = this.opt.cameraRotateEnable, this.controls.enablePan = this.opt.cameraPanEnable, this.controls.minDistance = 2, this.controls.maxDistance = 2e3, this.controls.autoRotateSpeed = 0, this.controls.autoRotate = !1, this.controls.update(), this.cameraClock = null;
4090
4090
  }
4091
- this.ikMesh = new x.SkinnedMesh();
4091
+ this.ikMesh = new f.SkinnedMesh();
4092
4092
  const s = {
4093
4093
  LeftShoulder: null,
4094
4094
  LeftArm: "LeftShoulder",
@@ -4102,9 +4102,9 @@ class Be {
4102
4102
  RightHandMiddle1: "RightHand"
4103
4103
  }, o = [];
4104
4104
  Object.entries(s).forEach((l, h) => {
4105
- const r = new x.Bone();
4105
+ const r = new f.Bone();
4106
4106
  r.name = l[0], l[1] ? this.ikMesh.getObjectByName(l[1]).add(r) : this.ikMesh.add(r), o.push(r);
4107
- }), this.ikMesh.bind(new x.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 = [];
4107
+ }), this.ikMesh.bind(new f.Skeleton(o)), this.dynamicbones = new et(), this.isStreaming = !1, this.streamWorkletNode = null, this.streamAudioStartTime = null, this.streamWaitForAudioChunks = !0, this.streamLipsyncLang = null, this.streamLipsyncType = "visemes", this.streamLipsyncQueue = [];
4108
4108
  }
4109
4109
  /**
4110
4110
  * Helper that re/creates the audio context and the other nodes.
@@ -4194,7 +4194,7 @@ class Be {
4194
4194
  for (let [n, i] of Object.entries(t)) {
4195
4195
  const s = n.split(".");
4196
4196
  let o = Array.isArray(i.x) ? this.gaussianRandom(...i.x) : i.x, l = Array.isArray(i.y) ? this.gaussianRandom(...i.y) : i.y, h = Array.isArray(i.z) ? this.gaussianRandom(...i.z) : i.z;
4197
- s[1] === "position" || s[1] === "scale" ? e[n] = new x.Vector3(o, l, h) : s[1] === "rotation" ? (n = s[0] + ".quaternion", e[n] = new x.Quaternion().setFromEuler(new x.Euler(o, l, h, "XYZ")).normalize()) : s[1] === "quaternion" && (e[n] = new x.Quaternion(o, l, h, i.w).normalize());
4197
+ s[1] === "position" || s[1] === "scale" ? e[n] = new f.Vector3(o, l, h) : s[1] === "rotation" ? (n = s[0] + ".quaternion", e[n] = new f.Quaternion().setFromEuler(new f.Euler(o, l, h, "XYZ")).normalize()) : s[1] === "quaternion" && (e[n] = new f.Quaternion(o, l, h, i.w).normalize());
4198
4198
  }
4199
4199
  return e;
4200
4200
  }
@@ -4225,16 +4225,16 @@ class Be {
4225
4225
  let l = null, h = null;
4226
4226
  for (const [r, u] of Object.entries(n))
4227
4227
  if (s.morphTargetDictionary.hasOwnProperty(r)) {
4228
- const a = s.morphTargetDictionary[r], d = o.morphAttributes.position[a], c = o.morphAttributes.normal?.[a];
4229
- l || (l = new x.Float32BufferAttribute(d.count * 3, 3), c && (h = new x.Float32BufferAttribute(d.count * 3, 3)));
4230
- for (let g = 0; g < d.count; g++) {
4231
- const y = l.getX(g) + d.getX(g) * u, b = l.getY(g) + d.getY(g) * u, I = l.getZ(g) + d.getZ(g) * u;
4232
- l.setXYZ(g, y, b, I);
4228
+ const a = s.morphTargetDictionary[r], c = o.morphAttributes.position[a], d = o.morphAttributes.normal?.[a];
4229
+ l || (l = new f.Float32BufferAttribute(c.count * 3, 3), d && (h = new f.Float32BufferAttribute(c.count * 3, 3)));
4230
+ for (let g = 0; g < c.count; g++) {
4231
+ const x = l.getX(g) + c.getX(g) * u, b = l.getY(g) + c.getY(g) * u, R = l.getZ(g) + c.getZ(g) * u;
4232
+ l.setXYZ(g, x, b, R);
4233
4233
  }
4234
- if (c)
4235
- for (let g = 0; g < d.count; g++) {
4236
- const y = h.getX(g) + c.getX(g) * u, b = h.getY(g) + c.getY(g) * u, I = h.getZ(g) + c.getZ(g) * u;
4237
- h.setXYZ(g, y, b, I);
4234
+ if (d)
4235
+ for (let g = 0; g < c.count; g++) {
4236
+ const x = h.getX(g) + d.getX(g) * u, b = h.getY(g) + d.getY(g) * u, R = h.getZ(g) + d.getZ(g) * u;
4237
+ h.setXYZ(g, x, b, R);
4238
4238
  }
4239
4239
  }
4240
4240
  if (l) {
@@ -4299,8 +4299,8 @@ class Be {
4299
4299
  u && ["fixed", "system", "systemd", "realtime", "base", "v", "value", "applied"].forEach((a) => {
4300
4300
  l[r][a] = u[a];
4301
4301
  }), this.morphs.forEach((a) => {
4302
- const d = a.morphTargetDictionary[r];
4303
- d !== void 0 && (l[r].ms.push(a.morphTargetInfluences), l[r].is.push(d), a.morphTargetInfluences[d] = l[r].applied);
4302
+ const c = a.morphTargetDictionary[r];
4303
+ c !== void 0 && (l[r].ms.push(a.morphTargetInfluences), l[r].is.push(c), a.morphTargetInfluences[c] = l[r].applied);
4304
4304
  });
4305
4305
  }), this.mtAvatar = l, this.poseAvatar = { props: {} }, this.posePropNames.forEach((r) => {
4306
4306
  const u = r.split("."), a = this.armature.getObjectByName(u[0]);
@@ -4314,7 +4314,7 @@ class Be {
4314
4314
  console.error("Dynamic bones setup failed: " + r);
4315
4315
  }
4316
4316
  this.objectLeftToeBase = this.armature.getObjectByName("LeftToeBase"), this.objectRightToeBase = this.armature.getObjectByName("RightToeBase"), this.objectLeftEye = this.armature.getObjectByName("LeftEye"), this.objectRightEye = this.armature.getObjectByName("RightEye"), this.objectLeftArm = this.armature.getObjectByName("LeftArm"), this.objectRightArm = this.armature.getObjectByName("RightArm"), this.objectHips = this.armature.getObjectByName("Hips"), this.objectHead = this.armature.getObjectByName("Head"), this.objectNeck = this.armature.getObjectByName("Neck");
4317
- const h = new x.Vector3();
4317
+ const h = new f.Vector3();
4318
4318
  this.objectLeftEye.getWorldPosition(h), this.avatarHeight = h.y + 0.2, this.viewName || this.setView(this.opt.cameraView), this.setMood(this.avatar.avatarMood || this.moodName || this.opt.avatarMood), this.avatar.body === "M" && this.poseTemplates.wide && (this.poseName = "wide", this.setPoseFromTemplate(this.poseTemplates.wide, 0), console.log("Set initial male-appropriate pose: wide")), this.initializeFBXAnimationLoader(), this.bodyMovement && this.bodyMovement !== "idle" && this.applyBodyMovementAnimation(), this.start();
4319
4319
  }
4320
4320
  /**
@@ -4358,14 +4358,14 @@ class Be {
4358
4358
  default:
4359
4359
  a += 12, u = u * a;
4360
4360
  }
4361
- r = r * a, this.controlsEnd = new x.Vector3(r, u, 0), this.cameraEnd = new x.Vector3(r, u, a).applyEuler(new x.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;
4361
+ r = r * a, this.controlsEnd = new f.Vector3(r, u, 0), this.cameraEnd = new f.Vector3(r, u, a).applyEuler(new f.Euler(o, l, 0)), this.cameraClock === null && (this.controls.target.copy(this.controlsEnd), this.camera.position.copy(this.cameraEnd)), this.controlsStart = this.controls.target.clone(), this.cameraStart = this.camera.position.clone(), this.cameraClock = 0;
4362
4362
  }
4363
4363
  /**
4364
4364
  * Change light colors and intensities.
4365
4365
  * @param {Object} opt Options
4366
4366
  */
4367
4367
  setLighting(t) {
4368
- this.isAvatarOnly || (t = t || {}, t.hasOwnProperty("lightAmbientColor") && this.lightAmbient.color.set(new x.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 x.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 x.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 x.Vector3(0, 1.5, 0))), t.hasOwnProperty("lightSpotDispersion") && (this.lightSpot.angle = t.lightSpotDispersion));
4368
+ this.isAvatarOnly || (t = t || {}, t.hasOwnProperty("lightAmbientColor") && this.lightAmbient.color.set(new f.Color(t.lightAmbientColor)), t.hasOwnProperty("lightAmbientIntensity") && (this.lightAmbient.intensity = t.lightAmbientIntensity, this.lightAmbient.visible = t.lightAmbientIntensity !== 0), t.hasOwnProperty("lightDirectColor") && this.lightDirect.color.set(new f.Color(t.lightDirectColor)), t.hasOwnProperty("lightDirectIntensity") && (this.lightDirect.intensity = t.lightDirectIntensity, this.lightDirect.visible = t.lightDirectIntensity !== 0), t.hasOwnProperty("lightDirectPhi") && t.hasOwnProperty("lightDirectTheta") && this.lightDirect.position.setFromSphericalCoords(2, t.lightDirectPhi, t.lightDirectTheta), t.hasOwnProperty("lightSpotColor") && this.lightSpot.color.set(new f.Color(t.lightSpotColor)), t.hasOwnProperty("lightSpotIntensity") && (this.lightSpot.intensity = t.lightSpotIntensity, this.lightSpot.visible = t.lightSpotIntensity !== 0), t.hasOwnProperty("lightSpotPhi") && t.hasOwnProperty("lightSpotTheta") && (this.lightSpot.position.setFromSphericalCoords(2, t.lightSpotPhi, t.lightSpotTheta), this.lightSpot.position.add(new f.Vector3(0, 1.5, 0))), t.hasOwnProperty("lightSpotDispersion") && (this.lightSpot.angle = t.lightSpotDispersion));
4369
4369
  }
4370
4370
  /**
4371
4371
  * Render scene.
@@ -4398,9 +4398,9 @@ class Be {
4398
4398
  updatePoseDelta() {
4399
4399
  for (const [t, e] of Object.entries(this.poseDelta.props)) {
4400
4400
  if (e.x === 0 && e.y === 0 && e.z === 0) continue;
4401
- W.set(e.x, e.y, e.z);
4401
+ V.set(e.x, e.y, e.z);
4402
4402
  const n = this.poseAvatar.props[t];
4403
- n.isQuaternion ? (Q.setFromEuler(W), n.multiply(Q)) : n.isVector3 && n.add(W);
4403
+ n.isQuaternion ? (Q.setFromEuler(V), n.multiply(Q)) : n.isVector3 && n.add(V);
4404
4404
  }
4405
4405
  }
4406
4406
  /**
@@ -4480,7 +4480,7 @@ class Be {
4480
4480
  return Object.entries(t).forEach((i, s) => {
4481
4481
  const o = i[0].split(".");
4482
4482
  if (o[1] === "position" || o[1] === "rotation" || o[1] === "quaternion") {
4483
- const l = o[1] === "quaternion" ? o[0] + ".rotation" : i[0], h = i[1].isQuaternion ? new x.Euler().setFromQuaternion(i[1]) : i[1];
4483
+ const l = o[1] === "quaternion" ? o[0] + ".rotation" : i[0], h = i[1].isQuaternion ? new f.Euler().setFromQuaternion(i[1]) : i[1];
4484
4484
  n += (s ? ", " : "") + "'" + l + "':{", n += "x:" + Math.round(h.x * e) / e, n += ", y:" + Math.round(h.y * e) / e, n += ", z:" + Math.round(h.z * e) / e, n += "}";
4485
4485
  }
4486
4486
  }), n += "}", n;
@@ -4666,43 +4666,31 @@ class Be {
4666
4666
  x: this.armature.position.x,
4667
4667
  y: this.armature.position.y,
4668
4668
  z: this.armature.position.z
4669
- }, console.log("Original position stored:", this.originalPosition));
4670
- const t = 2;
4671
- this.lockedPosition = {
4672
- x: 0,
4673
- // Keep centered horizontally
4674
- y: t,
4675
- // Set to the upward offset directly
4676
- z: 0
4677
- // Keep centered horizontally
4678
- }, this.armature.position.set(
4679
- this.lockedPosition.x,
4680
- this.lockedPosition.y,
4681
- this.lockedPosition.z
4682
- ), console.log("BEFORE: Avatar position was:", this.armature.position.x, this.armature.position.y, this.armature.position.z), console.log("AFTER: Avatar position moved up and locked at:", this.lockedPosition), console.log("Current view:", this.viewName);
4669
+ }, console.log("Original position stored:", this.originalPosition)), this.lockedPosition = {
4670
+ x: this.armature.position.x,
4671
+ y: this.armature.position.y,
4672
+ z: this.armature.position.z
4673
+ }, console.log("Avatar position locked at current position:", this.lockedPosition);
4683
4674
  }
4684
4675
  /**
4685
- * Unlock avatar position and reset to center.
4676
+ * Unlock avatar position and restore original position.
4686
4677
  */
4687
4678
  unlockAvatarPosition() {
4688
- this.armature && (this.armature.position.set(0, 0, 0), console.log("Avatar position reset to center (0,0,0)")), this.lockedPosition = null, console.log("Avatar position unlocked");
4679
+ this.armature && this.originalPosition ? (this.armature.position.set(
4680
+ this.originalPosition.x,
4681
+ this.originalPosition.y,
4682
+ this.originalPosition.z
4683
+ ), console.log("Avatar position restored to original:", this.originalPosition)) : this.armature && (this.armature.position.set(0, 0, 0), console.log("Avatar position reset to center (0,0,0)")), this.lockedPosition = null, this.originalPosition = null, console.log("Avatar position unlocked");
4689
4684
  }
4690
4685
  /**
4691
4686
  * Ensure avatar stays at locked position.
4692
4687
  */
4693
4688
  maintainLockedPosition() {
4694
- if (this.lockedPosition && this.armature) {
4695
- const t = this.armature.position.y, e = this.lockedPosition.y - 2, n = this.lockedPosition.y + 0.1;
4696
- t < e ? this.armature.position.set(
4697
- this.lockedPosition.x,
4698
- e,
4699
- this.lockedPosition.z
4700
- ) : t > n && this.armature.position.set(
4701
- this.lockedPosition.x,
4702
- n,
4703
- this.lockedPosition.z
4704
- ), this.armature.position.x = this.lockedPosition.x, this.armature.position.z = this.lockedPosition.z;
4705
- }
4689
+ this.lockedPosition && this.armature && this.armature.position.set(
4690
+ this.lockedPosition.x,
4691
+ this.lockedPosition.y,
4692
+ this.lockedPosition.z
4693
+ );
4706
4694
  }
4707
4695
  /**
4708
4696
  * Create body movement animation.
@@ -4999,10 +4987,10 @@ class Be {
4999
4987
  if (l.alt.length > 1) {
5000
4988
  const u = Math.random();
5001
4989
  let a = 0;
5002
- for (let d = 0; d < l.alt.length; d++) {
5003
- let c = this.valueFn(l.alt[d].p);
5004
- if (a += c === void 0 ? (1 - a) / (l.alt.length - 1 - d) : c, u < a) {
5005
- r = l.alt[d];
4990
+ for (let c = 0; c < l.alt.length; c++) {
4991
+ let d = this.valueFn(l.alt[c].p);
4992
+ if (a += d === void 0 ? (1 - a) / (l.alt.length - 1 - c) : d, u < a) {
4993
+ r = l.alt[c];
5006
4994
  break;
5007
4995
  }
5008
4996
  }
@@ -5023,8 +5011,8 @@ class Be {
5023
5011
  }
5024
5012
  s ? o.ts = o.ts.map((r) => h + r * n) : o.ts = o.ts.map((r) => this.animClock + h + r * n), l.vs && l.vs.pose && console.log("Pose being selected from vs.pose:", l.vs.pose, "for avatar body:", this.avatar?.body);
5025
5013
  for (let [r, u] of Object.entries(l.vs)) {
5026
- const a = this.getBaselineValue(r), d = u.map((c) => (c = this.valueFn(c), c === null ? null : typeof c == "function" ? c : typeof c == "string" || c instanceof String ? r === "pose" && this.avatar && this.avatar.body === "M" && (c === "hip" || c === "side") ? (console.log("Intercepting pose", c, "in animation factory, overriding to wide for male avatar"), "wide") : c.slice() : Array.isArray(c) ? r === "gesture" ? c.slice() : (a === void 0 ? 0 : a) + i * this.gaussianRandom(...c) : typeof c == "boolean" ? c : c instanceof Object && c.constructor === Object ? Object.assign({}, c) : (a === void 0 ? 0 : a) + i * c));
5027
- r === "eyesRotateY" ? (o.vs.eyeLookOutLeft = [null, ...d.map((c) => c > 0 ? c : 0)], o.vs.eyeLookInLeft = [null, ...d.map((c) => c > 0 ? 0 : -c)], o.vs.eyeLookOutRight = [null, ...d.map((c) => c > 0 ? 0 : -c)], o.vs.eyeLookInRight = [null, ...d.map((c) => c > 0 ? c : 0)]) : r === "eyesRotateX" ? (o.vs.eyesLookDown = [null, ...d.map((c) => c > 0 ? c : 0)], o.vs.eyesLookUp = [null, ...d.map((c) => c > 0 ? 0 : -c)]) : o.vs[r] = [null, ...d];
5014
+ const a = this.getBaselineValue(r), c = u.map((d) => (d = this.valueFn(d), d === null ? null : typeof d == "function" ? d : typeof d == "string" || d instanceof String ? r === "pose" && this.avatar && this.avatar.body === "M" && (d === "hip" || d === "side") ? (console.log("Intercepting pose", d, "in animation factory, overriding to wide for male avatar"), "wide") : d.slice() : Array.isArray(d) ? r === "gesture" ? d.slice() : (a === void 0 ? 0 : a) + i * this.gaussianRandom(...d) : typeof d == "boolean" ? d : d instanceof Object && d.constructor === Object ? Object.assign({}, d) : (a === void 0 ? 0 : a) + i * d));
5015
+ r === "eyesRotateY" ? (o.vs.eyeLookOutLeft = [null, ...c.map((d) => d > 0 ? d : 0)], o.vs.eyeLookInLeft = [null, ...c.map((d) => d > 0 ? 0 : -d)], o.vs.eyeLookOutRight = [null, ...c.map((d) => d > 0 ? 0 : -d)], o.vs.eyeLookInRight = [null, ...c.map((d) => d > 0 ? d : 0)]) : r === "eyesRotateX" ? (o.vs.eyesLookDown = [null, ...c.map((d) => d > 0 ? d : 0)], o.vs.eyesLookUp = [null, ...c.map((d) => d > 0 ? 0 : -d)]) : o.vs[r] = [null, ...c];
5028
5016
  }
5029
5017
  for (let r of Object.keys(o.vs))
5030
5018
  for (; o.vs[r].length <= o.ts.length; ) o.vs[r].push(o.vs[r][o.vs[r].length - 1]);
@@ -5111,20 +5099,20 @@ class Be {
5111
5099
  const a = this.animQueue[n];
5112
5100
  if (!(!a || !a.ts || !a.ts.length || this.animClock < a.ts[0])) {
5113
5101
  for (i = a.ndx || 0, o = a.ts.length; i < o && !(this.animClock < a.ts[i]); i++)
5114
- for (let [d, c] of Object.entries(a.vs))
5115
- if (this.mtAvatar.hasOwnProperty(d)) {
5116
- if (c[i + 1] === null) continue;
5117
- const g = this.mtAvatar[d];
5118
- if (c[i] === null && (c[i] = g.value), i === o - 1)
5119
- g.newvalue = c[i];
5102
+ for (let [c, d] of Object.entries(a.vs))
5103
+ if (this.mtAvatar.hasOwnProperty(c)) {
5104
+ if (d[i + 1] === null) continue;
5105
+ const g = this.mtAvatar[c];
5106
+ if (d[i] === null && (d[i] = g.value), i === o - 1)
5107
+ g.newvalue = d[i];
5120
5108
  else {
5121
- g.newvalue = c[i + 1];
5122
- const y = a.ts[i + 1] - a.ts[i];
5109
+ g.newvalue = d[i + 1];
5110
+ const x = a.ts[i + 1] - a.ts[i];
5123
5111
  let b = 1;
5124
- y > 1e-4 && (b = (this.animClock - a.ts[i]) / y), b < 1 && (g.easing && (b = g.easing(b)), g.newvalue = (1 - b) * c[i] + b * g.newvalue), g.ref && g.ref !== a.vs && g.ref.hasOwnProperty(d) && delete g.ref[d], g.ref = a.vs;
5112
+ x > 1e-4 && (b = (this.animClock - a.ts[i]) / x), b < 1 && (g.easing && (b = g.easing(b)), g.newvalue = (1 - b) * d[i] + b * g.newvalue), g.ref && g.ref !== a.vs && g.ref.hasOwnProperty(c) && delete g.ref[c], g.ref = a.vs;
5125
5113
  }
5126
5114
  if (l)
5127
- switch (d) {
5115
+ switch (c) {
5128
5116
  case "viseme_aa":
5129
5117
  case "viseme_E":
5130
5118
  case "viseme_I":
@@ -5133,11 +5121,11 @@ class Be {
5133
5121
  g.newvalue *= 1 + l / 255 - 0.5;
5134
5122
  }
5135
5123
  g.needsUpdate = !0;
5136
- } else d === "eyeContact" && c[i] !== null && h !== !1 ? h = !!c[i] : d === "headMove" && c[i] !== null && r !== !1 ? c[i] === 0 ? r = !1 : (Math.random() < c[i] && (r = !0), c[i] = null) : c[i] !== null && (u.push({ mt: d, val: c[i] }), c[i] = null);
5124
+ } else c === "eyeContact" && d[i] !== null && h !== !1 ? h = !!d[i] : c === "headMove" && d[i] !== null && r !== !1 ? d[i] === 0 ? r = !1 : (Math.random() < d[i] && (r = !0), d[i] = null) : d[i] !== null && (u.push({ mt: c, val: d[i] }), d[i] = null);
5137
5125
  i === o ? (a.hasOwnProperty("mood") && this.setMood(a.mood), a.loop ? (o = this.isSpeaking && (a.template.name === "head" || a.template.name === "eyes") ? 4 : 1, this.animQueue[n] = this.animFactory(a.template, a.loop > 0 ? a.loop - 1 : a.loop, 1, 1 / o)) : (this.animQueue.splice(n--, 1), s--)) : a.ndx = i - 1;
5138
5126
  }
5139
5127
  }
5140
- for (let a = 0, d = u.length; a < d; a++)
5128
+ for (let a = 0, c = u.length; a < c; a++)
5141
5129
  switch (i = u[a].val, u[a].mt) {
5142
5130
  case "speak":
5143
5131
  this.speakText(i);
@@ -5155,8 +5143,8 @@ class Be {
5155
5143
  i && typeof i == "function" && i();
5156
5144
  break;
5157
5145
  case "moveto":
5158
- Object.entries(i.props).forEach((c) => {
5159
- c[1] ? this.poseTarget.props[c[0]].copy(c[1]) : this.poseTarget.props[c[0]].copy(this.getPoseTemplateProp(c[0])), this.poseTarget.props[c[0]].t = this.animClock, this.poseTarget.props[c[0]].d = c[1] && c[1].d ? c[1].d : c.duration || 2e3;
5146
+ Object.entries(i.props).forEach((d) => {
5147
+ d[1] ? this.poseTarget.props[d[0]].copy(d[1]) : this.poseTarget.props[d[0]].copy(this.getPoseTemplateProp(d[0])), this.poseTarget.props[d[0]].t = this.animClock, this.poseTarget.props[d[0]].d = d[1] && d[1].d ? d[1].d : d.duration || 2e3;
5160
5148
  });
5161
5149
  break;
5162
5150
  case "handLeft":
@@ -5169,7 +5157,7 @@ class Be {
5169
5157
  { link: "LeftForeArm", minx: -0.5, maxx: 1.5, miny: -1.5, maxy: 1.5, minz: -0.5, maxz: 3 },
5170
5158
  { link: "LeftArm", minx: -1.5, maxx: 1.5, miny: 0, maxy: 0, minz: -1, maxz: 3 }
5171
5159
  ]
5172
- }, i.x ? new x.Vector3(i.x, i.y, i.z) : null, !0, i.d);
5160
+ }, i.x ? new f.Vector3(i.x, i.y, i.z) : null, !0, i.d);
5173
5161
  break;
5174
5162
  case "handRight":
5175
5163
  this.ikSolve({
@@ -5181,10 +5169,10 @@ class Be {
5181
5169
  { link: "RightForeArm", minx: -0.5, maxx: 1.5, miny: -1.5, maxy: 1.5, minz: -3, maxz: 0.5, maxAngle: 0.2 },
5182
5170
  { link: "RightArm", minx: -1.5, maxx: 1.5, miny: 0, maxy: 0, minz: -1, maxz: 3 }
5183
5171
  ]
5184
- }, i.x ? new x.Vector3(i.x, i.y, i.z) : null, !0, i.d);
5172
+ }, i.x ? new f.Vector3(i.x, i.y, i.z) : null, !0, i.d);
5185
5173
  break;
5186
5174
  }
5187
- if ((h || r) && (W.setFromQuaternion(this.poseAvatar.props["Head.quaternion"]), W.x = Math.max(-0.9, Math.min(0.9, 2 * W.x - 0.5)), W.y = Math.max(-0.9, Math.min(0.9, -2.5 * W.y)), h ? (Object.assign(this.mtAvatar.eyesLookDown, { system: W.x < 0 ? -W.x : 0, needsUpdate: !0 }), Object.assign(this.mtAvatar.eyesLookUp, { system: W.x < 0 ? 0 : W.x, needsUpdate: !0 }), Object.assign(this.mtAvatar.eyeLookInLeft, { system: W.y < 0 ? -W.y : 0, needsUpdate: !0 }), Object.assign(this.mtAvatar.eyeLookOutLeft, { system: W.y < 0 ? 0 : W.y, needsUpdate: !0 }), Object.assign(this.mtAvatar.eyeLookInRight, { system: W.y < 0 ? 0 : W.y, needsUpdate: !0 }), Object.assign(this.mtAvatar.eyeLookOutRight, { system: W.y < 0 ? -W.y : 0, needsUpdate: !0 }), r && (n = -this.mtAvatar.bodyRotateY.value, i = this.gaussianRandom(-0.2, 0.2), this.animQueue.push(this.animFactory({
5175
+ 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({
5188
5176
  name: "headmove",
5189
5177
  dt: [[1e3, 2e3], [1e3, 2e3, 1, 2], [1e3, 2e3], [1e3, 2e3, 1, 2]],
5190
5178
  vs: {
@@ -5205,13 +5193,13 @@ class Be {
5205
5193
  eyeLookOutRight: [null, 0],
5206
5194
  eyeContact: [0]
5207
5195
  }
5208
- })))), e > 2 * this.animFrameDur && (e = 2 * this.animFrameDur), (this.viewName !== "full" || this.isAvatarOnly) && (n = this.mtRandomized[Math.floor(Math.random() * this.mtRandomized.length)], i = this.mtAvatar[n], i.needsUpdate || Object.assign(i, { base: (this.mood.baseline[n] || 0) + (1 + l / 255) * Math.random() / 5, needsUpdate: !0 })), this.updatePoseBase(this.animClock), this.mixer && this.mixer.update(e / 1e3 * this.mixer.timeScale), this.updatePoseDelta(), (this.isSpeaking || this.isListening) && h ? l > this.volumeMax ? (this.volumeHeadBase = 0.05, Math.random() > 0.6 && (this.volumeHeadTarget = -0.05 - Math.random() / 15), this.volumeMax = l) : (this.volumeMax *= 0.92, this.volumeHeadTarget = this.volumeHeadBase - 0.9 * (this.volumeHeadBase - this.volumeHeadTarget)) : (this.volumeHeadTarget = 0, this.volumeMax = 0), n = this.volumeHeadTarget - this.volumeHeadCurrent, i = Math.abs(n), i > 1e-4 && (o = i * (this.volumeHeadEasing(Math.min(1, this.volumeHeadVelocity * e / 1e3 / i) / 2 + 0.5) - 0.5), this.volumeHeadCurrent += Math.sign(n) * Math.min(i, o)), Math.abs(this.volumeHeadCurrent) > 1e-4 && (Q.setFromAxisAngle(mt, this.volumeHeadCurrent), this.objectNeck.quaternion.multiply(Q)), We.setFromObject(this.armature), this.objectLeftToeBase.getWorldPosition(ve), ve.sub(this.armature.position), this.objectRightToeBase.getWorldPosition(Re), Re.sub(this.armature.position), this.objectHips.position.y -= We.min.y / 2, this.objectHips.position.x -= (ve.x + Re.x) / 4, this.objectHips.position.z -= (ve.z + Re.z) / 2, this.dynamicbones.update(e), this.fbxAnimationLoader && this.fbxAnimationLoader.update(), this.opt.update && this.opt.update(e), this.updateMorphTargets(e), this.isAvatarOnly)
5196
+ })))), e > 2 * this.animFrameDur && (e = 2 * this.animFrameDur), (this.viewName !== "full" || this.isAvatarOnly) && (n = this.mtRandomized[Math.floor(Math.random() * this.mtRandomized.length)], i = this.mtAvatar[n], i.needsUpdate || Object.assign(i, { base: (this.mood.baseline[n] || 0) + (1 + l / 255) * Math.random() / 5, needsUpdate: !0 })), this.updatePoseBase(this.animClock), this.mixer && this.mixer.update(e / 1e3 * this.mixer.timeScale), this.updatePoseDelta(), (this.isSpeaking || this.isListening) && h ? l > this.volumeMax ? (this.volumeHeadBase = 0.05, Math.random() > 0.6 && (this.volumeHeadTarget = -0.05 - Math.random() / 15), this.volumeMax = l) : (this.volumeMax *= 0.92, this.volumeHeadTarget = this.volumeHeadBase - 0.9 * (this.volumeHeadBase - this.volumeHeadTarget)) : (this.volumeHeadTarget = 0, this.volumeMax = 0), n = this.volumeHeadTarget - this.volumeHeadCurrent, i = Math.abs(n), i > 1e-4 && (o = i * (this.volumeHeadEasing(Math.min(1, this.volumeHeadVelocity * e / 1e3 / i) / 2 + 0.5) - 0.5), this.volumeHeadCurrent += Math.sign(n) * Math.min(i, o)), Math.abs(this.volumeHeadCurrent) > 1e-4 && (Q.setFromAxisAngle(mt, this.volumeHeadCurrent), this.objectNeck.quaternion.multiply(Q)), We.setFromObject(this.armature), this.objectLeftToeBase.getWorldPosition(ve), ve.sub(this.armature.position), this.objectRightToeBase.getWorldPosition(Ie), Ie.sub(this.armature.position), this.objectHips.position.y -= We.min.y / 2, this.objectHips.position.x -= (ve.x + Ie.x) / 4, this.objectHips.position.z -= (ve.z + Ie.z) / 2, this.dynamicbones.update(e), this.fbxAnimationLoader && this.fbxAnimationLoader.update(), this.opt.update && this.opt.update(e), this.updateMorphTargets(e), this.isAvatarOnly)
5209
5197
  this.stats && this.stats.end();
5210
5198
  else {
5211
5199
  if (this.cameraClock !== null && this.cameraClock < 1e3) {
5212
5200
  this.cameraClock += e, this.cameraClock > 1e3 && (this.cameraClock = 1e3);
5213
- let a = new x.Spherical().setFromVector3(this.cameraStart), d = new x.Spherical().setFromVector3(this.cameraEnd);
5214
- a.phi += this.easing(this.cameraClock / 1e3) * (d.phi - a.phi), a.theta += this.easing(this.cameraClock / 1e3) * (d.theta - a.theta), a.radius += this.easing(this.cameraClock / 1e3) * (d.radius - a.radius), a.makeSafe(), this.camera.position.setFromSpherical(a), this.controlsStart.x !== this.controlsEnd.x ? this.controls.target.copy(this.controlsStart.lerp(this.controlsEnd, this.easing(this.cameraClock / 1e3))) : (a.setFromVector3(this.controlsStart), d.setFromVector3(this.controlsEnd), a.phi += this.easing(this.cameraClock / 1e3) * (d.phi - a.phi), a.theta += this.easing(this.cameraClock / 1e3) * (d.theta - a.theta), a.radius += this.easing(this.cameraClock / 1e3) * (d.radius - a.radius), a.makeSafe(), this.controls.target.setFromSpherical(a)), this.controls.update();
5201
+ let a = new f.Spherical().setFromVector3(this.cameraStart), c = new f.Spherical().setFromVector3(this.cameraEnd);
5202
+ a.phi += this.easing(this.cameraClock / 1e3) * (c.phi - a.phi), a.theta += this.easing(this.cameraClock / 1e3) * (c.theta - a.theta), a.radius += this.easing(this.cameraClock / 1e3) * (c.radius - a.radius), a.makeSafe(), this.camera.position.setFromSpherical(a), this.controlsStart.x !== this.controlsEnd.x ? this.controls.target.copy(this.controlsStart.lerp(this.controlsEnd, this.easing(this.cameraClock / 1e3))) : (a.setFromVector3(this.controlsStart), c.setFromVector3(this.controlsEnd), a.phi += this.easing(this.cameraClock / 1e3) * (c.phi - a.phi), a.theta += this.easing(this.cameraClock / 1e3) * (c.theta - a.theta), a.radius += this.easing(this.cameraClock / 1e3) * (c.radius - a.radius), a.makeSafe(), this.controls.target.setFromSpherical(a)), this.controls.update();
5215
5203
  }
5216
5204
  this.controls.autoRotate && this.controls.update(), this.stats && this.stats.end(), this.render();
5217
5205
  }
@@ -5273,48 +5261,48 @@ class Be {
5273
5261
  speakText(t, e = null, n = null, i = null) {
5274
5262
  e = e || {};
5275
5263
  const s = /[!\.\?\n\p{Extended_Pictographic}]/ug, o = /[ ]/ug, l = /[\p{L}\p{N},\.\p{Quotation_Mark}!€\$\+\p{Dash_Punctuation}%&\?]/ug, h = /[\p{Extended_Pictographic}]/ug, r = e.lipsyncLang || this.avatar.lipsyncLang || this.opt.lipsyncLang;
5276
- let u = "", a = "", d = 0, c = [], g = [];
5277
- const y = Array.from(this.segmenter.segment(t), (b) => b.segment);
5278
- for (let b = 0; b < y.length; b++) {
5279
- const I = b === y.length - 1, V = y[b].match(l);
5280
- let p = y[b].match(s);
5281
- const M = y[b].match(h), z = y[b].match(o);
5282
- if (p && !I && !M && y[b + 1].match(s) && (p = !1), n && (u += y[b]), V && (!i || i.every((f) => b < f[0] || b > f[1])) && (a += y[b]), (z || p || I) && (a.length && (a = this.lipsyncPreProcessText(a, r), a.length && c.push({
5283
- mark: d,
5264
+ let u = "", a = "", c = 0, d = [], g = [];
5265
+ const x = Array.from(this.segmenter.segment(t), (b) => b.segment);
5266
+ for (let b = 0; b < x.length; b++) {
5267
+ const R = b === x.length - 1, B = x[b].match(l);
5268
+ let p = x[b].match(s);
5269
+ const M = x[b].match(h), z = x[b].match(o);
5270
+ if (p && !R && !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 || R) && (a.length && (a = this.lipsyncPreProcessText(a, r), a.length && d.push({
5271
+ mark: c,
5284
5272
  word: a
5285
5273
  })), u.length && (g.push({
5286
- mark: d,
5274
+ mark: c,
5287
5275
  template: { name: "subtitles" },
5288
5276
  ts: [0],
5289
5277
  vs: {
5290
5278
  subtitles: [u]
5291
5279
  }
5292
5280
  }), u = ""), a.length)) {
5293
- const f = this.lipsyncWordsToVisemes(a, r);
5294
- if (f && f.visemes && f.visemes.length) {
5295
- const E = f.times[f.visemes.length - 1] + f.durations[f.visemes.length - 1];
5296
- for (let P = 0; P < f.visemes.length; P++)
5281
+ const y = this.lipsyncWordsToVisemes(a, r);
5282
+ if (y && y.visemes && y.visemes.length) {
5283
+ const E = y.times[y.visemes.length - 1] + y.durations[y.visemes.length - 1];
5284
+ for (let P = 0; P < y.visemes.length; P++)
5297
5285
  g.push({
5298
- mark: d,
5286
+ mark: c,
5299
5287
  template: { name: "viseme" },
5300
- ts: [(f.times[P] - 0.6) / E, (f.times[P] + 0.5) / E, (f.times[P] + f.durations[P] + 0.5) / E],
5288
+ ts: [(y.times[P] - 0.6) / E, (y.times[P] + 0.5) / E, (y.times[P] + y.durations[P] + 0.5) / E],
5301
5289
  vs: {
5302
- ["viseme_" + f.visemes[P]]: [null, f.visemes[P] === "PP" || f.visemes[P] === "FF" ? 0.9 : 0.6, 0]
5290
+ ["viseme_" + y.visemes[P]]: [null, y.visemes[P] === "PP" || y.visemes[P] === "FF" ? 0.9 : 0.6, 0]
5303
5291
  }
5304
5292
  });
5305
5293
  }
5306
- a = "", d++;
5294
+ a = "", c++;
5307
5295
  }
5308
- if (p || I) {
5309
- if (c.length || I && g.length) {
5310
- const f = {
5296
+ if (p || R) {
5297
+ if (d.length || R && g.length) {
5298
+ const y = {
5311
5299
  anim: g
5312
5300
  };
5313
- n && (f.onSubtitles = n), c.length && !e.avatarMute && (f.text = c, e.avatarMood && (f.mood = e.avatarMood), e.ttsLang && (f.lang = e.ttsLang), e.ttsVoice && (f.voice = e.ttsVoice), e.ttsRate && (f.rate = e.ttsRate), e.ttsVoice && (f.pitch = e.ttsPitch), e.ttsVolume && (f.volume = e.ttsVolume)), this.speechQueue.push(f), c = [], a = "", d = 0, g = [];
5301
+ n && (y.onSubtitles = n), d.length && !e.avatarMute && (y.text = d, e.avatarMood && (y.mood = e.avatarMood), e.ttsLang && (y.lang = e.ttsLang), e.ttsVoice && (y.voice = e.ttsVoice), e.ttsRate && (y.rate = e.ttsRate), e.ttsVoice && (y.pitch = e.ttsPitch), e.ttsVolume && (y.volume = e.ttsVolume)), this.speechQueue.push(y), d = [], a = "", c = 0, g = [];
5314
5302
  }
5315
5303
  if (M) {
5316
- let f = this.animEmojis[y[b]];
5317
- f && f.link && (f = this.animEmojis[f.link]), f && this.speechQueue.push({ emoji: f });
5304
+ let y = this.animEmojis[x[b]];
5305
+ y && y.link && (y = this.animEmojis[y.link]), y && this.speechQueue.push({ emoji: y });
5318
5306
  }
5319
5307
  this.speechQueue.push({ break: 100 });
5320
5308
  }
@@ -5404,18 +5392,18 @@ class Be {
5404
5392
  subtitles: [" " + h]
5405
5393
  }
5406
5394
  }), !t.visemes)) {
5407
- const a = this.lipsyncPreProcessText(h, i), d = this.lipsyncWordsToVisemes(a, i);
5408
- if (d && d.visemes && d.visemes.length) {
5409
- const c = d.times[d.visemes.length - 1] + d.durations[d.visemes.length - 1], g = Math.min(u, Math.max(0, u - d.visemes.length * 150));
5410
- let y = 0.6 + this.convertRange(g, [0, u], [0, 0.4]);
5411
- if (u = Math.min(u, d.visemes.length * 200), c > 0)
5412
- for (let b = 0; b < d.visemes.length; b++) {
5413
- const I = r + d.times[b] / c * u, V = d.durations[b] / c * u;
5395
+ const a = this.lipsyncPreProcessText(h, i), c = this.lipsyncWordsToVisemes(a, i);
5396
+ if (c && c.visemes && c.visemes.length) {
5397
+ const d = c.times[c.visemes.length - 1] + c.durations[c.visemes.length - 1], g = Math.min(u, Math.max(0, u - c.visemes.length * 150));
5398
+ let x = 0.6 + this.convertRange(g, [0, u], [0, 0.4]);
5399
+ if (u = Math.min(u, c.visemes.length * 200), d > 0)
5400
+ for (let b = 0; b < c.visemes.length; b++) {
5401
+ const R = r + c.times[b] / d * u, B = c.durations[b] / d * u;
5414
5402
  o.push({
5415
5403
  template: { name: "viseme" },
5416
- ts: [I - Math.min(60, 2 * V / 3), I + Math.min(25, V / 2), I + V + Math.min(60, V / 2)],
5404
+ ts: [R - Math.min(60, 2 * B / 3), R + Math.min(25, B / 2), R + B + Math.min(60, B / 2)],
5417
5405
  vs: {
5418
- ["viseme_" + d.visemes[b]]: [null, d.visemes[b] === "PP" || d.visemes[b] === "FF" ? 0.9 : y, 0]
5406
+ ["viseme_" + c.visemes[b]]: [null, c.visemes[b] === "PP" || c.visemes[b] === "FF" ? 0.9 : x, 0]
5419
5407
  }
5420
5408
  });
5421
5409
  }
@@ -5498,31 +5486,31 @@ class Be {
5498
5486
  const p = u.find((M) => M.name.includes(a) || M.lang === o);
5499
5487
  p && (s.voice = p);
5500
5488
  }
5501
- const d = i.length * 100 / s.rate, c = this.audioCtx.createBuffer(1, this.audioCtx.sampleRate * (d / 1e3), this.audioCtx.sampleRate), g = this.avatar.lipsyncLang || this.opt.lipsyncLang || "en", y = this.lipsyncPreProcessText(i, g), b = this.lipsyncWordsToVisemes(y, g);
5489
+ const c = i.length * 100 / s.rate, d = this.audioCtx.createBuffer(1, this.audioCtx.sampleRate * (c / 1e3), this.audioCtx.sampleRate), g = this.avatar.lipsyncLang || this.opt.lipsyncLang || "en", x = this.lipsyncPreProcessText(i, g), b = this.lipsyncWordsToVisemes(x, g);
5502
5490
  console.log("Browser TTS Lip-sync Debug:", {
5503
5491
  text: i,
5504
5492
  lipsyncLang: g,
5505
- processedText: y,
5493
+ processedText: x,
5506
5494
  lipsyncData: b,
5507
5495
  hasVisemes: b && b.visemes && b.visemes.length > 0,
5508
- estimatedDuration: d
5496
+ estimatedDuration: c
5509
5497
  });
5510
- const I = [];
5498
+ const R = [];
5511
5499
  if (b && b.visemes && b.visemes.length > 0) {
5512
5500
  const p = b.times[b.visemes.length - 1] + b.durations[b.visemes.length - 1];
5513
5501
  for (let M = 0; M < b.visemes.length; M++) {
5514
- const z = b.visemes[M], f = b.times[M] / p, E = b.durations[M] / p, P = f * d, U = E * d;
5515
- I.push({
5502
+ const z = b.visemes[M], y = b.times[M] / p, E = b.durations[M] / p, P = y * c, W = E * c;
5503
+ R.push({
5516
5504
  template: { name: "viseme" },
5517
- ts: [P - Math.min(60, 2 * U / 3), P + Math.min(25, U / 2), P + U + Math.min(60, U / 2)],
5505
+ ts: [P - Math.min(60, 2 * W / 3), P + Math.min(25, W / 2), P + W + Math.min(60, W / 2)],
5518
5506
  vs: {
5519
5507
  ["viseme_" + z]: [null, z === "PP" || z === "FF" ? 0.9 : 0.6, 0]
5520
5508
  }
5521
5509
  });
5522
5510
  }
5523
5511
  }
5524
- const V = [...t.anim, ...I];
5525
- this.audioPlaylist.push({ anim: V, audio: c }), this.onSubtitles = t.onSubtitles || null, this.resetLips(), t.mood && this.setMood(t.mood), this.playAudio(), s.onend = () => {
5512
+ const B = [...t.anim, ...R];
5513
+ this.audioPlaylist.push({ anim: B, audio: d }), this.onSubtitles = t.onSubtitles || null, this.resetLips(), t.mood && this.setMood(t.mood), this.playAudio(), s.onend = () => {
5526
5514
  e();
5527
5515
  }, s.onerror = (p) => {
5528
5516
  console.error("Speech synthesis error:", p.error), n(p.error);
@@ -5534,7 +5522,7 @@ class Be {
5534
5522
  * @param {Object} line Speech line object
5535
5523
  */
5536
5524
  async synthesizeWithElevenLabsTTS(t) {
5537
- const e = t.text.map((d) => d.word).join(" "), n = t.voice || this.avatar.ttsVoice || this.opt.ttsVoice || "21m00Tcm4TlvDq8ikWAM", i = {
5525
+ const e = t.text.map((c) => c.word).join(" "), n = t.voice || this.avatar.ttsVoice || this.opt.ttsVoice || "21m00Tcm4TlvDq8ikWAM", i = {
5538
5526
  text: e,
5539
5527
  model_id: "eleven_monolingual_v1",
5540
5528
  voice_settings: {
@@ -5564,18 +5552,18 @@ class Be {
5564
5552
  lipsyncKeys: this.lipsync ? Object.keys(this.lipsync) : [],
5565
5553
  lipsyncLang: h
5566
5554
  });
5567
- const d = this.lipsyncPreProcessText(e, h), c = this.lipsyncWordsToVisemes(d, h);
5555
+ const c = this.lipsyncPreProcessText(e, h), d = this.lipsyncWordsToVisemes(c, h);
5568
5556
  if (console.log("Lip-sync data:", {
5569
- processedText: d,
5570
- lipsyncData: c,
5571
- hasVisemes: c && c.visemes && c.visemes.length > 0
5572
- }), c && c.visemes && c.visemes.length > 0)
5557
+ processedText: c,
5558
+ lipsyncData: d,
5559
+ hasVisemes: d && d.visemes && d.visemes.length > 0
5560
+ }), d && d.visemes && d.visemes.length > 0)
5573
5561
  r = {
5574
- visemes: c.visemes.map((g, y) => ({
5562
+ visemes: d.visemes.map((g, x) => ({
5575
5563
  viseme: g,
5576
- startTime: y * l.duration / c.visemes.length,
5577
- endTime: (y + 1) * l.duration / c.visemes.length,
5578
- duration: l.duration / c.visemes.length,
5564
+ startTime: x * l.duration / d.visemes.length,
5565
+ endTime: (x + 1) * l.duration / d.visemes.length,
5566
+ duration: l.duration / d.visemes.length,
5579
5567
  intensity: 0.7
5580
5568
  })),
5581
5569
  words: [],
@@ -5584,17 +5572,17 @@ class Be {
5584
5572
  };
5585
5573
  else
5586
5574
  throw new Error("No visemes generated from text");
5587
- } catch (d) {
5588
- console.error("Text-based lip-sync failed, using fallback:", d);
5589
- const c = e.toLowerCase().split(/\s+/), g = [];
5590
- for (const y of c)
5591
- for (const b of y) {
5592
- let I = "aa";
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);
5575
+ } catch (c) {
5576
+ console.error("Text-based lip-sync failed, using fallback:", c);
5577
+ const d = e.toLowerCase().split(/\s+/), g = [];
5578
+ for (const x of d)
5579
+ for (const b of x) {
5580
+ let R = "aa";
5581
+ "aeiou".includes(b) ? R = "aa" : "bp".includes(b) ? R = "PP" : "fv".includes(b) ? R = "FF" : "st".includes(b) ? R = "SS" : "dln".includes(b) ? R = "DD" : "kg".includes(b) ? R = "kk" : "rw".includes(b) && (R = "RR"), g.push(R);
5594
5582
  }
5595
5583
  r = {
5596
- visemes: g.map((y, b) => ({
5597
- viseme: y,
5584
+ visemes: g.map((x, b) => ({
5585
+ viseme: x,
5598
5586
  startTime: b * l.duration / g.length,
5599
5587
  endTime: (b + 1) * l.duration / g.length,
5600
5588
  duration: l.duration / g.length,
@@ -5620,13 +5608,13 @@ class Be {
5620
5608
  const u = [];
5621
5609
  if (r.visemes && r.visemes.length > 0) {
5622
5610
  console.log("ElevenLabs: Generating lip-sync animation from", r.visemes.length, "visemes");
5623
- for (let d = 0; d < r.visemes.length; d++) {
5624
- const c = r.visemes[d], g = c.startTime * 1e3, y = c.duration * 1e3, b = c.intensity;
5611
+ for (let c = 0; c < r.visemes.length; c++) {
5612
+ const d = r.visemes[c], g = d.startTime * 1e3, x = d.duration * 1e3, b = d.intensity;
5625
5613
  u.push({
5626
5614
  template: { name: "viseme" },
5627
- ts: [g - Math.min(60, 2 * y / 3), g + Math.min(25, y / 2), g + y + Math.min(60, y / 2)],
5615
+ ts: [g - Math.min(60, 2 * x / 3), g + Math.min(25, x / 2), g + x + Math.min(60, x / 2)],
5628
5616
  vs: {
5629
- ["viseme_" + c.viseme]: [null, b, 0]
5617
+ ["viseme_" + d.viseme]: [null, b, 0]
5630
5618
  }
5631
5619
  });
5632
5620
  }
@@ -5641,7 +5629,7 @@ class Be {
5641
5629
  * @param {Object} line Speech line object
5642
5630
  */
5643
5631
  async synthesizeWithDeepgramTTS(t) {
5644
- const e = t.text.map((d) => d.word).join(" "), n = t.voice || this.avatar.ttsVoice || this.opt.ttsVoice || "aura-2-thalia-en", i = `${this.opt.ttsEndpoint}?model=${n}`, s = await fetch(i, {
5632
+ const e = t.text.map((c) => c.word).join(" "), n = t.voice || this.avatar.ttsVoice || this.opt.ttsVoice || "aura-2-thalia-en", i = `${this.opt.ttsEndpoint}?model=${n}`, s = await fetch(i, {
5645
5633
  method: "POST",
5646
5634
  headers: {
5647
5635
  Authorization: `Token ${this.opt.ttsApikey}`,
@@ -5662,18 +5650,18 @@ class Be {
5662
5650
  lipsyncKeys: this.lipsync ? Object.keys(this.lipsync) : [],
5663
5651
  lipsyncLang: h
5664
5652
  });
5665
- const d = this.lipsyncPreProcessText(e, h), c = this.lipsyncWordsToVisemes(d, h);
5653
+ const c = this.lipsyncPreProcessText(e, h), d = this.lipsyncWordsToVisemes(c, h);
5666
5654
  if (console.log("Lip-sync data:", {
5667
- processedText: d,
5668
- lipsyncData: c,
5669
- hasVisemes: c && c.visemes && c.visemes.length > 0
5670
- }), c && c.visemes && c.visemes.length > 0)
5655
+ processedText: c,
5656
+ lipsyncData: d,
5657
+ hasVisemes: d && d.visemes && d.visemes.length > 0
5658
+ }), d && d.visemes && d.visemes.length > 0)
5671
5659
  r = {
5672
- visemes: c.visemes.map((g, y) => ({
5660
+ visemes: d.visemes.map((g, x) => ({
5673
5661
  viseme: g,
5674
- startTime: y * l.duration / c.visemes.length,
5675
- endTime: (y + 1) * l.duration / c.visemes.length,
5676
- duration: l.duration / c.visemes.length,
5662
+ startTime: x * l.duration / d.visemes.length,
5663
+ endTime: (x + 1) * l.duration / d.visemes.length,
5664
+ duration: l.duration / d.visemes.length,
5677
5665
  intensity: 0.7
5678
5666
  })),
5679
5667
  words: [],
@@ -5682,17 +5670,17 @@ class Be {
5682
5670
  };
5683
5671
  else
5684
5672
  throw new Error("No visemes generated from text");
5685
- } catch (d) {
5686
- console.error("Text-based lip-sync failed, using fallback:", d);
5687
- const c = e.toLowerCase().split(/\s+/), g = [];
5688
- for (const y of c)
5689
- for (const b of y) {
5690
- let I = "aa";
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);
5673
+ } catch (c) {
5674
+ console.error("Text-based lip-sync failed, using fallback:", c);
5675
+ const d = e.toLowerCase().split(/\s+/), g = [];
5676
+ for (const x of d)
5677
+ for (const b of x) {
5678
+ let R = "aa";
5679
+ "aeiou".includes(b) ? R = "aa" : "bp".includes(b) ? R = "PP" : "fv".includes(b) ? R = "FF" : "st".includes(b) ? R = "SS" : "dln".includes(b) ? R = "DD" : "kg".includes(b) ? R = "kk" : "rw".includes(b) && (R = "RR"), g.push(R);
5692
5680
  }
5693
5681
  r = {
5694
- visemes: g.map((y, b) => ({
5695
- viseme: y,
5682
+ visemes: g.map((x, b) => ({
5683
+ viseme: x,
5696
5684
  startTime: b * l.duration / g.length,
5697
5685
  endTime: (b + 1) * l.duration / g.length,
5698
5686
  duration: l.duration / g.length,
@@ -5718,13 +5706,13 @@ class Be {
5718
5706
  const u = [];
5719
5707
  if (r.visemes && r.visemes.length > 0) {
5720
5708
  console.log("Deepgram: Generating lip-sync animation from", r.visemes.length, "visemes");
5721
- for (let d = 0; d < r.visemes.length; d++) {
5722
- const c = r.visemes[d], g = c.startTime * 1e3, y = c.duration * 1e3, b = c.intensity;
5709
+ for (let c = 0; c < r.visemes.length; c++) {
5710
+ const d = r.visemes[c], g = d.startTime * 1e3, x = d.duration * 1e3, b = d.intensity;
5723
5711
  u.push({
5724
5712
  template: { name: "viseme" },
5725
- ts: [g - Math.min(60, 2 * y / 3), g + Math.min(25, y / 2), g + y + Math.min(60, y / 2)],
5713
+ ts: [g - Math.min(60, 2 * x / 3), g + Math.min(25, x / 2), g + x + Math.min(60, x / 2)],
5726
5714
  vs: {
5727
- ["viseme_" + c.viseme]: [null, b, 0]
5715
+ ["viseme_" + d.viseme]: [null, b, 0]
5728
5716
  }
5729
5717
  });
5730
5718
  }
@@ -5771,12 +5759,12 @@ class Be {
5771
5759
  });
5772
5760
  const r = [];
5773
5761
  for (let a = 0; a < h.visemes.length; a++) {
5774
- const d = h.visemes[a], c = d.startTime * 1e3, g = d.duration * 1e3, y = d.intensity;
5762
+ const c = h.visemes[a], d = c.startTime * 1e3, g = c.duration * 1e3, x = c.intensity;
5775
5763
  r.push({
5776
5764
  template: { name: "viseme" },
5777
- ts: [c - Math.min(60, 2 * g / 3), c + Math.min(25, g / 2), c + g + Math.min(60, g / 2)],
5765
+ ts: [d - Math.min(60, 2 * g / 3), d + Math.min(25, g / 2), d + g + Math.min(60, g / 2)],
5778
5766
  vs: {
5779
- ["viseme_" + d.viseme]: [null, y, 0]
5767
+ ["viseme_" + c.viseme]: [null, x, 0]
5780
5768
  }
5781
5769
  });
5782
5770
  }
@@ -5822,25 +5810,25 @@ class Be {
5822
5810
  this.speakWithHands();
5823
5811
  const h = [0];
5824
5812
  let r = 0;
5825
- t.text.forEach((d, c) => {
5826
- if (c > 0) {
5813
+ t.text.forEach((c, d) => {
5814
+ if (d > 0) {
5827
5815
  let g = h[h.length - 1];
5828
- s.timepoints[r] && (g = s.timepoints[r].timeSeconds * 1e3, s.timepoints[r].markName === "" + d.mark && r++), h.push(g);
5816
+ s.timepoints[r] && (g = s.timepoints[r].timeSeconds * 1e3, s.timepoints[r].markName === "" + c.mark && r++), h.push(g);
5829
5817
  }
5830
5818
  });
5831
5819
  const u = [{ mark: 0, time: 0 }];
5832
- h.forEach((d, c) => {
5833
- if (c > 0) {
5834
- let g = d - h[c - 1];
5835
- u[c - 1].duration = g, u.push({ mark: c, time: d });
5820
+ h.forEach((c, d) => {
5821
+ if (d > 0) {
5822
+ let g = c - h[d - 1];
5823
+ u[d - 1].duration = g, u.push({ mark: d, time: c });
5836
5824
  }
5837
5825
  });
5838
5826
  let a = 1e3 * l.duration;
5839
- a > this.opt.ttsTrimEnd && (a = a - this.opt.ttsTrimEnd), u[u.length - 1].duration = a - u[u.length - 1].time, t.anim.forEach((d) => {
5840
- const c = u[d.mark];
5841
- if (c)
5842
- for (let g = 0; g < d.ts.length; g++)
5843
- d.ts[g] = c.time + d.ts[g] * c.duration + this.opt.ttsTrimStart;
5827
+ a > this.opt.ttsTrimEnd && (a = a - this.opt.ttsTrimEnd), u[u.length - 1].duration = a - u[u.length - 1].time, t.anim.forEach((c) => {
5828
+ const d = u[c.mark];
5829
+ if (d)
5830
+ for (let g = 0; g < c.ts.length; g++)
5831
+ c.ts[g] = d.time + c.ts[g] * d.duration + this.opt.ttsTrimStart;
5844
5832
  }), this.audioPlaylist.push({ anim: t.anim, audio: l }), this.onSubtitles = t.onSubtitles || null, this.resetLips(), t.mood && this.setMood(t.mood), this.playAudio();
5845
5833
  } else
5846
5834
  this.startSpeaking(!0);
@@ -6059,15 +6047,15 @@ class Be {
6059
6047
  const l = this.streamLipsyncLang || this.avatar.lipsyncLang || this.opt.lipsyncLang, h = this.lipsyncPreProcessText(i, l), r = this.lipsyncWordsToVisemes(h, l);
6060
6048
  if (r && r.visemes && r.visemes.length) {
6061
6049
  const u = r.times[r.visemes.length - 1] + r.durations[r.visemes.length - 1], a = Math.min(o, Math.max(0, o - r.visemes.length * 150));
6062
- let d = 0.6 + this.convertRange(a, [0, o], [0, 0.4]);
6050
+ let c = 0.6 + this.convertRange(a, [0, o], [0, 0.4]);
6063
6051
  if (o = Math.min(o, r.visemes.length * 200), u > 0)
6064
- for (let c = 0; c < r.visemes.length; c++) {
6065
- const g = e + s + r.times[c] / u * o, y = r.durations[c] / u * o;
6052
+ for (let d = 0; d < r.visemes.length; d++) {
6053
+ const g = e + s + r.times[d] / u * o, x = r.durations[d] / u * o;
6066
6054
  this.animQueue.push({
6067
6055
  template: { name: "viseme" },
6068
- ts: [g - Math.min(60, 2 * y / 3), g + Math.min(25, y / 2), g + y + Math.min(60, y / 2)],
6056
+ ts: [g - Math.min(60, 2 * x / 3), g + Math.min(25, x / 2), g + x + Math.min(60, x / 2)],
6069
6057
  vs: {
6070
- ["viseme_" + r.visemes[c]]: [null, r.visemes[c] === "PP" || r.visemes[c] === "FF" ? 0.9 : d, 0]
6058
+ ["viseme_" + r.visemes[d]]: [null, r.visemes[d] === "PP" || r.visemes[d] === "FF" ? 0.9 : c, 0]
6071
6059
  }
6072
6060
  });
6073
6061
  }
@@ -6158,7 +6146,7 @@ class Be {
6158
6146
  */
6159
6147
  lookAtCamera(t) {
6160
6148
  let e;
6161
- if (this.speakTo && (e = new x.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) {
6149
+ if (this.speakTo && (e = new f.Vector3(), this.speakTo.objectLeftEye?.isObject3D ? (this.speakTo.armature.objectHead, this.speakTo.objectLeftEye.updateMatrixWorld(!0), this.speakTo.objectRightEye.updateMatrixWorld(!0), ve.setFromMatrixPosition(this.speakTo.objectLeftEye.matrixWorld), Ie.setFromMatrixPosition(this.speakTo.objectRightEye.matrixWorld), e.addVectors(ve, Ie).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) {
6162
6150
  if (this.avatar.hasOwnProperty("avatarIgnoreCamera")) {
6163
6151
  if (this.avatar.avatarIgnoreCamera) {
6164
6152
  this.lookAhead(t);
@@ -6171,22 +6159,22 @@ class Be {
6171
6159
  this.lookAt(null, null, t);
6172
6160
  return;
6173
6161
  }
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"]);
6175
- const n = new x.Vector3().subVectors(e, ve).normalize(), i = Math.atan2(n.x, n.z), s = Math.asin(-n.y);
6176
- W.set(s, i, 0, "YXZ");
6177
- const l = new x.Quaternion().setFromEuler(W), h = new x.Quaternion().copy(l).multiply(Q.clone().invert());
6178
- W.setFromQuaternion(h, "YXZ");
6179
- let r = W.x / (40 / 24) + 0.2, u = W.y / (9 / 4), a = Math.min(0.6, Math.max(-0.3, r)), d = Math.min(0.8, Math.max(-0.8, u)), c = (Math.random() - 0.5) / 4, g = (Math.random() - 0.5) / 4;
6162
+ this.objectLeftEye.updateMatrixWorld(!0), this.objectRightEye.updateMatrixWorld(!0), ve.setFromMatrixPosition(this.objectLeftEye.matrixWorld), Ie.setFromMatrixPosition(this.objectRightEye.matrixWorld), ve.add(Ie).divideScalar(2), Q.copy(this.armature.quaternion), Q.multiply(this.poseTarget.props["Hips.quaternion"]), Q.multiply(this.poseTarget.props["Spine.quaternion"]), Q.multiply(this.poseTarget.props["Spine1.quaternion"]), Q.multiply(this.poseTarget.props["Spine2.quaternion"]), Q.multiply(this.poseTarget.props["Neck.quaternion"]), Q.multiply(this.poseTarget.props["Head.quaternion"]);
6163
+ const n = new f.Vector3().subVectors(e, ve).normalize(), i = Math.atan2(n.x, n.z), s = Math.asin(-n.y);
6164
+ V.set(s, i, 0, "YXZ");
6165
+ const l = new f.Quaternion().setFromEuler(V), h = new f.Quaternion().copy(l).multiply(Q.clone().invert());
6166
+ V.setFromQuaternion(h, "YXZ");
6167
+ 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;
6180
6168
  if (t) {
6181
- let y = this.animQueue.findIndex((I) => I.template.name === "lookat");
6182
- y !== -1 && this.animQueue.splice(y, 1);
6169
+ let x = this.animQueue.findIndex((R) => R.template.name === "lookat");
6170
+ x !== -1 && this.animQueue.splice(x, 1);
6183
6171
  const b = {
6184
6172
  name: "lookat",
6185
6173
  dt: [750, t],
6186
6174
  vs: {
6187
- bodyRotateX: [a + c],
6188
- bodyRotateY: [d + g],
6189
- eyesRotateX: [-3 * c + 0.1],
6175
+ bodyRotateX: [a + d],
6176
+ bodyRotateY: [c + g],
6177
+ eyesRotateX: [-3 * d + 0.1],
6190
6178
  eyesRotateY: [-5 * g],
6191
6179
  browInnerUp: [[0, 0.7]],
6192
6180
  mouthLeft: [[0, 0.7]],
@@ -6208,23 +6196,23 @@ class Be {
6208
6196
  if (!this.camera) return;
6209
6197
  const i = this.nodeAvatar.getBoundingClientRect();
6210
6198
  this.objectLeftEye.updateMatrixWorld(!0), this.objectRightEye.updateMatrixWorld(!0);
6211
- const s = new x.Vector3().setFromMatrixPosition(this.objectLeftEye.matrixWorld), o = new x.Vector3().setFromMatrixPosition(this.objectRightEye.matrixWorld), l = new x.Vector3().addVectors(s, o).divideScalar(2);
6199
+ const s = new f.Vector3().setFromMatrixPosition(this.objectLeftEye.matrixWorld), o = new f.Vector3().setFromMatrixPosition(this.objectRightEye.matrixWorld), l = new f.Vector3().addVectors(s, o).divideScalar(2);
6212
6200
  l.project(this.camera);
6213
6201
  let h = (l.x + 1) / 2 * i.width + i.left, r = -(l.y - 1) / 2 * i.height + i.top;
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"]), W.setFromQuaternion(Q);
6215
- let u = W.x / (40 / 24), a = W.y / (9 / 4), d = Math.min(0.4, Math.max(-0.4, this.camera.rotation.x)), c = Math.min(0.4, Math.max(-0.4, this.camera.rotation.y)), g = Math.max(window.innerWidth - h, h), y = Math.max(window.innerHeight - r, r), b = this.convertRange(e, [r - y, r + y], [-0.3, 0.6]) - u + d, I = this.convertRange(t, [h - g, h + g], [-0.8, 0.8]) - a + c;
6216
- b = Math.min(0.6, Math.max(-0.3, b)), I = Math.min(0.8, Math.max(-0.8, I));
6217
- let V = (Math.random() - 0.5) / 4, p = (Math.random() - 0.5) / 4;
6202
+ t === null && (t = h), e === null && (e = r), Q.copy(this.armature.quaternion), Q.multiply(this.poseTarget.props["Hips.quaternion"]), Q.multiply(this.poseTarget.props["Spine.quaternion"]), Q.multiply(this.poseTarget.props["Spine1.quaternion"]), Q.multiply(this.poseTarget.props["Spine2.quaternion"]), Q.multiply(this.poseTarget.props["Neck.quaternion"]), Q.multiply(this.poseTarget.props["Head.quaternion"]), V.setFromQuaternion(Q);
6203
+ 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, R = this.convertRange(t, [h - g, h + g], [-0.8, 0.8]) - a + d;
6204
+ b = Math.min(0.6, Math.max(-0.3, b)), R = Math.min(0.8, Math.max(-0.8, R));
6205
+ let B = (Math.random() - 0.5) / 4, p = (Math.random() - 0.5) / 4;
6218
6206
  if (n) {
6219
- let M = this.animQueue.findIndex((f) => f.template.name === "lookat");
6207
+ let M = this.animQueue.findIndex((y) => y.template.name === "lookat");
6220
6208
  M !== -1 && this.animQueue.splice(M, 1);
6221
6209
  const z = {
6222
6210
  name: "lookat",
6223
6211
  dt: [750, n],
6224
6212
  vs: {
6225
- bodyRotateX: [b + V],
6226
- bodyRotateY: [I + p],
6227
- eyesRotateX: [-3 * V + 0.1],
6213
+ bodyRotateX: [b + B],
6214
+ bodyRotateY: [R + p],
6215
+ eyesRotateX: [-3 * B + 0.1],
6228
6216
  eyesRotateY: [-5 * p],
6229
6217
  browInnerUp: [[0, 0.7]],
6230
6218
  mouthLeft: [[0, 0.7]],
@@ -6244,14 +6232,14 @@ class Be {
6244
6232
  */
6245
6233
  touchAt(t, e) {
6246
6234
  if (!this.camera) return;
6247
- const n = this.nodeAvatar.getBoundingClientRect(), i = new x.Vector2(
6235
+ const n = this.nodeAvatar.getBoundingClientRect(), i = new f.Vector2(
6248
6236
  (t - n.left) / n.width * 2 - 1,
6249
6237
  -((e - n.top) / n.height) * 2 + 1
6250
- ), s = new x.Raycaster();
6238
+ ), s = new f.Raycaster();
6251
6239
  s.setFromCamera(i, this.camera);
6252
6240
  const o = s.intersectObject(this.armature);
6253
6241
  if (o.length > 0) {
6254
- const l = o[0].point, h = new x.Vector3(), r = new x.Vector3();
6242
+ const l = o[0].point, h = new f.Vector3(), r = new f.Vector3();
6255
6243
  this.objectLeftArm.getWorldPosition(h), this.objectRightArm.getWorldPosition(r);
6256
6244
  const u = h.distanceToSquared(l), a = r.distanceToSquared(l);
6257
6245
  u < a ? (this.ikSolve({
@@ -6295,7 +6283,7 @@ class Be {
6295
6283
  { link: "LeftForeArm", minx: -0.5, maxx: 1.5, miny: -1.5, maxy: 1.5, minz: -0.5, maxz: 3 },
6296
6284
  { link: "LeftArm", minx: -1.5, maxx: 1.5, miny: -1.5, maxy: 1.5, minz: -1, maxz: 3 }
6297
6285
  ]
6298
- }, new x.Vector3(
6286
+ }, new f.Vector3(
6299
6287
  this.gaussianRandom(0, 0.5),
6300
6288
  this.gaussianRandom(-0.8, -0.2),
6301
6289
  this.gaussianRandom(0, 0.5)
@@ -6307,15 +6295,15 @@ class Be {
6307
6295
  { link: "RightForeArm", minx: -0.5, maxx: 1.5, miny: -1.5, maxy: 1.5, minz: -3, maxz: 0.5 },
6308
6296
  { link: "RightArm" }
6309
6297
  ]
6310
- }, new x.Vector3(
6298
+ }, new f.Vector3(
6311
6299
  this.gaussianRandom(-0.5, 0),
6312
6300
  this.gaussianRandom(-0.8, -0.2),
6313
6301
  this.gaussianRandom(0, 0.5)
6314
6302
  ), !0);
6315
6303
  const n = [], i = [];
6316
6304
  n.push(100 + Math.round(Math.random() * 500)), i.push({ duration: 1e3, props: {
6317
- "LeftHand.quaternion": new x.Quaternion().setFromEuler(new x.Euler(0, -1 - Math.random(), 0)),
6318
- "RightHand.quaternion": new x.Quaternion().setFromEuler(new x.Euler(0, 1 + Math.random(), 0))
6305
+ "LeftHand.quaternion": new f.Quaternion().setFromEuler(new f.Euler(0, -1 - Math.random(), 0)),
6306
+ "RightHand.quaternion": new f.Quaternion().setFromEuler(new f.Euler(0, 1 + Math.random(), 0))
6319
6307
  } }), ["LeftArm", "LeftForeArm", "RightArm", "RightForeArm"].forEach((o) => {
6320
6308
  i[0].props[o + ".quaternion"] = this.ikMesh.getObjectByName(o).quaternion.clone();
6321
6309
  }), n.push(1e3 + Math.round(Math.random() * 500)), i.push({ duration: 2e3, props: {} }), ["LeftArm", "LeftForeArm", "RightArm", "RightForeArm", "LeftHand", "RightHand"].forEach((o) => {
@@ -6392,6 +6380,29 @@ class Be {
6392
6380
  * @param {number} [ndx=0] Index of the clip
6393
6381
  * @param {number} [scale=0.01] Position scale factor
6394
6382
  */
6383
+ /**
6384
+ * Get all bone names from the avatar's armature
6385
+ * @returns {Set<string>} Set of bone names
6386
+ */
6387
+ getAvailableBoneNames() {
6388
+ const t = /* @__PURE__ */ new Set();
6389
+ return this.armature && this.armature.traverse((e) => {
6390
+ (e.isBone || e.type === "Bone") && t.add(e.name);
6391
+ }), t;
6392
+ }
6393
+ /**
6394
+ * Filter animation tracks to only include bones that exist in the avatar
6395
+ * @param {THREE.AnimationClip} clip - Animation clip to filter
6396
+ * @param {Set<string>} availableBones - Set of available bone names
6397
+ * @returns {THREE.AnimationClip} Filtered animation clip
6398
+ */
6399
+ filterAnimationTracks(t, e) {
6400
+ const n = [], i = /* @__PURE__ */ new Set();
6401
+ return t.tracks.forEach((s) => {
6402
+ const l = s.name.split(".")[0];
6403
+ e.has(l) ? n.push(s) : i.add(l);
6404
+ }), 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);
6405
+ }
6395
6406
  async playAnimation(t, e = null, n = 10, i = 0, s = 0.01, o = !1) {
6396
6407
  if (!this.armature) return;
6397
6408
  this.positionWasLocked = !o, o ? console.log("Position locking disabled for FBX animation:", t) : (this.lockAvatarPosition(), console.log("Position locked immediately before FBX animation:", t));
@@ -6400,9 +6411,9 @@ class Be {
6400
6411
  let h = this.animQueue.find((a) => a.template.name === "pose");
6401
6412
  h && (h.ts[0] = 1 / 0), Object.entries(l.pose.props).forEach((a) => {
6402
6413
  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;
6403
- }), this.mixer ? console.log("Using existing mixer for FBX animation, preserving morph targets") : (this.mixer = new x.AnimationMixer(this.armature), console.log("Created new mixer for FBX animation")), this.mixer.addEventListener("finished", this.stopAnimation.bind(this), { once: !0 });
6414
+ }), 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 });
6404
6415
  const r = Math.ceil(n / l.clip.duration), u = this.mixer.clipAction(l.clip);
6405
- u.setLoop(x.LoopRepeat, r), u.clampWhenFinished = !0, this.currentFBXAction = u;
6416
+ u.setLoop(f.LoopRepeat, r), u.clampWhenFinished = !0, this.currentFBXAction = u;
6406
6417
  try {
6407
6418
  u.fadeIn(0.5).play(), console.log("FBX animation started successfully:", t);
6408
6419
  } catch (a) {
@@ -6420,58 +6431,64 @@ class Be {
6420
6431
  }
6421
6432
  let r = !1;
6422
6433
  try {
6423
- const d = await fetch(t, { method: "HEAD" });
6424
- if (r = d.ok, !r) {
6425
- console.error(`FBX file not found at ${t}. Status: ${d.status}`), console.error("Please check:"), console.error("1. File path is correct (note: path is case-sensitive)"), console.error("2. File exists in your public folder"), console.error("3. File is accessible (not blocked by server)");
6434
+ const c = await fetch(t, { method: "HEAD" });
6435
+ if (r = c.ok, !r) {
6436
+ console.error(`FBX file not found at ${t}. Status: ${c.status}`), console.error("Please check:"), console.error("1. File path is correct (note: path is case-sensitive)"), console.error("2. File exists in your public folder"), console.error("3. File is accessible (not blocked by server)");
6426
6437
  return;
6427
6438
  }
6428
- } catch (d) {
6429
- console.warn(`Could not verify file existence for ${t}, attempting to load anyway:`, d);
6439
+ } catch (c) {
6440
+ console.warn(`Could not verify file existence for ${t}, attempting to load anyway:`, c);
6430
6441
  }
6431
6442
  const u = new De();
6432
6443
  let a;
6433
6444
  try {
6434
6445
  a = await u.loadAsync(t, e);
6435
- } catch (d) {
6436
- console.error(`Failed to load FBX animation from ${t}:`, d), console.error("Error details:", {
6437
- message: d.message,
6446
+ } catch (c) {
6447
+ console.error(`Failed to load FBX animation from ${t}:`, c), console.error("Error details:", {
6448
+ message: c.message,
6438
6449
  url: t,
6439
6450
  suggestion: "Make sure the file is a valid FBX file and the path is correct"
6440
- }), d.message && d.message.includes("version number") && (console.error("FBX Loader Error: Cannot find version number"), console.error("This error usually means:"), console.error("1. The file is not a valid FBX file (might be GLB, corrupted, or wrong format)"), console.error("2. The file might be corrupted"), console.error("3. The file path might be incorrect"), console.error("4. The server returned an HTML error page instead of the FBX file"), console.error("5. The file might not exist at that path"), console.error(""), console.error("Solution: Please verify:"), console.error(` - File exists at: ${t}`), console.error(" - File is a valid FBX binary file"), console.error(" - File path matches your public folder structure"), console.error(" - File is not corrupted"));
6451
+ }), 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"));
6441
6452
  try {
6442
- const c = await fetch(t), g = c.headers.get("content-type"), y = await c.text();
6453
+ const d = await fetch(t), g = d.headers.get("content-type"), x = await d.text();
6443
6454
  console.error("Response details:", {
6444
- status: c.status,
6455
+ status: d.status,
6445
6456
  contentType: g,
6446
- firstBytes: y.substring(0, 100),
6447
- isHTML: y.trim().startsWith("<!DOCTYPE") || y.trim().startsWith("<html")
6448
- }), (y.trim().startsWith("<!DOCTYPE") || y.trim().startsWith("<html")) && console.error("The server returned an HTML page instead of an FBX file. The file path is likely incorrect.");
6449
- } catch (c) {
6450
- console.error("Could not fetch file for debugging:", c);
6457
+ firstBytes: x.substring(0, 100),
6458
+ isHTML: x.trim().startsWith("<!DOCTYPE") || x.trim().startsWith("<html")
6459
+ }), (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.");
6460
+ } catch (d) {
6461
+ console.error("Could not fetch file for debugging:", d);
6451
6462
  }
6452
6463
  return;
6453
6464
  }
6454
6465
  if (a && a.animations && a.animations[i]) {
6455
- let d = a.animations[i];
6456
- const c = {};
6457
- d.tracks.forEach((y) => {
6458
- y.name = y.name.replaceAll("mixamorig", "");
6459
- const b = y.name.split(".");
6460
- if (b[1] === "position") {
6461
- for (let I = 0; I < y.values.length; I++)
6462
- y.values[I] = y.values[I] * s;
6463
- c[y.name] = new x.Vector3(y.values[0], y.values[1], y.values[2]);
6464
- } else b[1] === "quaternion" ? c[y.name] = new x.Quaternion(y.values[0], y.values[1], y.values[2], y.values[3]) : b[1] === "rotation" && (c[b[0] + ".quaternion"] = new x.Quaternion().setFromEuler(new x.Euler(y.values[0], y.values[1], y.values[2], "XYZ")).normalize());
6466
+ let c = a.animations[i];
6467
+ const d = this.getAvailableBoneNames(), g = this.filterAnimationTracks(c, d);
6468
+ if (!g) {
6469
+ console.error(`Cannot play FBX animation "${t}": No compatible bones found.`);
6470
+ return;
6471
+ }
6472
+ c = g;
6473
+ const x = {};
6474
+ c.tracks.forEach((R) => {
6475
+ R.name = R.name.replaceAll("mixamorig", "");
6476
+ const B = R.name.split(".");
6477
+ if (B[1] === "position") {
6478
+ for (let p = 0; p < R.values.length; p++)
6479
+ R.values[p] = R.values[p] * s;
6480
+ x[R.name] = new f.Vector3(R.values[0], R.values[1], R.values[2]);
6481
+ } else B[1] === "quaternion" ? x[R.name] = new f.Quaternion(R.values[0], R.values[1], R.values[2], R.values[3]) : B[1] === "rotation" && (x[B[0] + ".quaternion"] = new f.Quaternion().setFromEuler(new f.Euler(R.values[0], R.values[1], R.values[2], "XYZ")).normalize());
6465
6482
  });
6466
- const g = { props: c };
6467
- c["Hips.position"] && (c["Hips.position"].y < 0.5 ? g.lying = !0 : g.standing = !0), this.animClips.push({
6483
+ const b = { props: x };
6484
+ x["Hips.position"] && (x["Hips.position"].y < 0.5 ? b.lying = !0 : b.standing = !0), this.animClips.push({
6468
6485
  url: t + "-" + i,
6469
- clip: d,
6470
- pose: g
6486
+ clip: c,
6487
+ pose: b
6471
6488
  }), this.playAnimation(t, e, n, i, s);
6472
6489
  } else {
6473
- const d = "Animation " + t + " (ndx=" + i + ") not found";
6474
- console.error(d), a && a.animations ? console.error(`FBX file loaded but has ${a.animations.length} animation(s), requested index ${i}`) : console.error(a ? "FBX file loaded but contains no animations" : "FBX file failed to load or is invalid");
6490
+ const c = "Animation " + t + " (ndx=" + i + ") not found";
6491
+ console.error(c), a && a.animations ? console.error(`FBX file loaded but has ${a.animations.length} animation(s), requested index ${i}`) : console.error(a ? "FBX file loaded but contains no animations" : "FBX file failed to load or is invalid");
6475
6492
  }
6476
6493
  }
6477
6494
  }
@@ -6509,10 +6526,10 @@ class Be {
6509
6526
  if (h && h.animations && h.animations[i]) {
6510
6527
  let r = h.animations[i];
6511
6528
  const u = {};
6512
- r.tracks.forEach((d) => {
6513
- d.name = d.name.replaceAll("mixamorig", "");
6514
- const c = d.name.split(".");
6515
- c[1] === "position" ? u[d.name] = new x.Vector3(d.values[0] * s, d.values[1] * s, d.values[2] * s) : c[1] === "quaternion" ? u[d.name] = new x.Quaternion(d.values[0], d.values[1], d.values[2], d.values[3]) : c[1] === "rotation" && (u[c[0] + ".quaternion"] = new x.Quaternion().setFromEuler(new x.Euler(d.values[0], d.values[1], d.values[2], "XYZ")).normalize());
6529
+ r.tracks.forEach((c) => {
6530
+ c.name = c.name.replaceAll("mixamorig", "");
6531
+ const d = c.name.split(".");
6532
+ 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());
6516
6533
  });
6517
6534
  const a = { props: u };
6518
6535
  u["Hips.position"] && (u["Hips.position"].y < 0.5 ? a.lying = !0 : a.standing = !0), this.animPoses.push({
@@ -6545,7 +6562,7 @@ class Be {
6545
6562
  if (s) {
6546
6563
  this.gestureTimeout && (clearTimeout(this.gestureTimeout), this.gestureTimeout = null);
6547
6564
  let l = this.animQueue.findIndex((h) => h.template.name === "talkinghands");
6548
- 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 x.Quaternion(0, 1, 0, 0), -0.25), this.gesture["LeftArm.quaternion"].rotateTowards(new x.Quaternion(0, 1, 0, 0), -0.25));
6565
+ 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));
6549
6566
  for (let [h, r] of Object.entries(this.gesture))
6550
6567
  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);
6551
6568
  e && Number.isFinite(e) && (this.gestureTimeout = setTimeout(this.stopGesture.bind(this, i), 1e3 * e));
@@ -6557,13 +6574,13 @@ class Be {
6557
6574
  if (l.gesture = !0, e && Number.isFinite(e)) {
6558
6575
  const h = l.ts[0], u = l.ts[l.ts.length - 1] - h;
6559
6576
  if (e * 1e3 - u > 0) {
6560
- const d = [];
6561
- for (let y = 1; y < l.ts.length; y++) d.push(l.ts[y] - l.ts[y - 1]);
6562
- const c = o.template?.rescale || d.map((y) => y / u), g = e * 1e3 - u;
6563
- l.ts = l.ts.map((y, b, I) => b === 0 ? h : I[b - 1] + d[b - 1] + c[b - 1] * g);
6577
+ const c = [];
6578
+ for (let x = 1; x < l.ts.length; x++) c.push(l.ts[x] - l.ts[x - 1]);
6579
+ const d = o.template?.rescale || c.map((x) => x / u), g = e * 1e3 - u;
6580
+ l.ts = l.ts.map((x, b, R) => b === 0 ? h : R[b - 1] + c[b - 1] + d[b - 1] * g);
6564
6581
  } else {
6565
- const d = e * 1e3 / u;
6566
- l.ts = l.ts.map((c) => h + d * (c - h));
6582
+ const c = e * 1e3 / u;
6583
+ l.ts = l.ts.map((d) => h + c * (d - h));
6567
6584
  }
6568
6585
  }
6569
6586
  this.animQueue.push(l);
@@ -6593,34 +6610,34 @@ class Be {
6593
6610
  * @param {numeric} [d=null] If set, apply in d milliseconds
6594
6611
  */
6595
6612
  ikSolve(t, e = null, n = !1, i = null) {
6596
- const s = new x.Vector3(), o = new x.Vector3(), l = new x.Vector3(), h = new x.Vector3(), r = new x.Quaternion(), u = new x.Vector3(), a = new x.Vector3(), d = new x.Vector3(), c = this.ikMesh.getObjectByName(t.root);
6597
- c.position.setFromMatrixPosition(this.armature.getObjectByName(t.root).matrixWorld), c.quaternion.setFromRotationMatrix(this.armature.getObjectByName(t.root).matrixWorld), e && n && e.applyQuaternion(this.armature.quaternion).add(c.position);
6598
- const g = this.ikMesh.getObjectByName(t.effector), y = t.links;
6599
- y.forEach((I) => {
6600
- I.bone = this.ikMesh.getObjectByName(I.link), I.bone.quaternion.copy(this.getPoseTemplateProp(I.link + ".quaternion"));
6601
- }), c.updateMatrixWorld(!0);
6613
+ 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);
6614
+ d.position.setFromMatrixPosition(this.armature.getObjectByName(t.root).matrixWorld), d.quaternion.setFromRotationMatrix(this.armature.getObjectByName(t.root).matrixWorld), e && n && e.applyQuaternion(this.armature.quaternion).add(d.position);
6615
+ const g = this.ikMesh.getObjectByName(t.effector), x = t.links;
6616
+ x.forEach((R) => {
6617
+ R.bone = this.ikMesh.getObjectByName(R.link), R.bone.quaternion.copy(this.getPoseTemplateProp(R.link + ".quaternion"));
6618
+ }), d.updateMatrixWorld(!0);
6602
6619
  const b = t.iterations || 10;
6603
6620
  if (e)
6604
- for (let I = 0; I < b; I++) {
6605
- let V = !1;
6606
- for (let p = 0, M = y.length; p < M; p++) {
6607
- const z = y[p].bone;
6621
+ for (let R = 0; R < b; R++) {
6622
+ let B = !1;
6623
+ for (let p = 0, M = x.length; p < M; p++) {
6624
+ const z = x[p].bone;
6608
6625
  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();
6609
- let f = s.dot(l);
6610
- f > 1 ? f = 1 : f < -1 && (f = -1), f = Math.acos(f), !(f < 1e-5) && (y[p].minAngle !== void 0 && f < y[p].minAngle && (f = y[p].minAngle), y[p].maxAngle !== void 0 && f > y[p].maxAngle && (f = y[p].maxAngle), a.crossVectors(l, s), a.normalize(), Q.setFromAxisAngle(a, f), z.quaternion.multiply(Q), z.rotation.setFromVector3(d.setFromEuler(z.rotation).clamp(new x.Vector3(
6611
- y[p].minx !== void 0 ? y[p].minx : -1 / 0,
6612
- y[p].miny !== void 0 ? y[p].miny : -1 / 0,
6613
- y[p].minz !== void 0 ? y[p].minz : -1 / 0
6614
- ), new x.Vector3(
6615
- y[p].maxx !== void 0 ? y[p].maxx : 1 / 0,
6616
- y[p].maxy !== void 0 ? y[p].maxy : 1 / 0,
6617
- y[p].maxz !== void 0 ? y[p].maxz : 1 / 0
6618
- ))), z.updateMatrixWorld(!0), V = !0);
6626
+ let y = s.dot(l);
6627
+ y > 1 ? y = 1 : y < -1 && (y = -1), y = Math.acos(y), !(y < 1e-5) && (x[p].minAngle !== void 0 && y < x[p].minAngle && (y = x[p].minAngle), x[p].maxAngle !== void 0 && y > x[p].maxAngle && (y = x[p].maxAngle), a.crossVectors(l, s), a.normalize(), Q.setFromAxisAngle(a, y), z.quaternion.multiply(Q), z.rotation.setFromVector3(c.setFromEuler(z.rotation).clamp(new f.Vector3(
6628
+ x[p].minx !== void 0 ? x[p].minx : -1 / 0,
6629
+ x[p].miny !== void 0 ? x[p].miny : -1 / 0,
6630
+ x[p].minz !== void 0 ? x[p].minz : -1 / 0
6631
+ ), new f.Vector3(
6632
+ x[p].maxx !== void 0 ? x[p].maxx : 1 / 0,
6633
+ x[p].maxy !== void 0 ? x[p].maxy : 1 / 0,
6634
+ x[p].maxz !== void 0 ? x[p].maxz : 1 / 0
6635
+ ))), z.updateMatrixWorld(!0), B = !0);
6619
6636
  }
6620
- if (!V) break;
6637
+ if (!B) break;
6621
6638
  }
6622
- i && y.forEach((I) => {
6623
- 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;
6639
+ i && x.forEach((R) => {
6640
+ this.poseTarget.props[R.link + ".quaternion"].copy(R.bone.quaternion), this.poseTarget.props[R.link + ".quaternion"].t = this.animClock, this.poseTarget.props[R.link + ".quaternion"].d = i;
6624
6641
  });
6625
6642
  }
6626
6643
  /**
@@ -6630,7 +6647,7 @@ class Be {
6630
6647
  this.isRunning = !1, this.stop(), this.stopSpeaking(), this.streamStop(), this.isAvatarOnly ? this.armature && (this.armature.parent && this.armature.parent.remove(this.armature), this.clearThree(this.armature)) : (this.clearThree(this.scene), this.resizeobserver.disconnect(), this.renderer && (this.renderer.dispose(), this.renderer.domElement && this.renderer.domElement.parentNode && this.renderer.domElement.parentNode.removeChild(this.renderer.domElement), this.renderer = null)), this.clearThree(this.ikMesh), this.dynamicbones.dispose();
6631
6648
  }
6632
6649
  }
6633
- const Ie = {
6650
+ const Re = {
6634
6651
  apiKey: "sk_ace57ef3ef65a92b9d3bee2a00183b78ca790bc3e10964f2",
6635
6652
  // Replace with your actual API key (should start with sk_)
6636
6653
  endpoint: "https://api.elevenlabs.io/v1/text-to-speech",
@@ -6673,10 +6690,10 @@ const Ie = {
6673
6690
  function Fe() {
6674
6691
  return {
6675
6692
  service: "elevenlabs",
6676
- endpoint: Ie.endpoint,
6677
- apiKey: Ie.apiKey,
6678
- defaultVoice: Ie.defaultVoice,
6679
- voices: Ie.voices
6693
+ endpoint: Re.endpoint,
6694
+ apiKey: Re.apiKey,
6695
+ defaultVoice: Re.defaultVoice,
6696
+ voices: Re.voices
6680
6697
  };
6681
6698
  }
6682
6699
  function kt() {
@@ -6702,40 +6719,40 @@ const Ve = Me(({
6702
6719
  cameraView: u = "upper",
6703
6720
  onReady: a = () => {
6704
6721
  },
6705
- onLoading: d = () => {
6722
+ onLoading: c = () => {
6706
6723
  },
6707
- onError: c = () => {
6724
+ onError: d = () => {
6708
6725
  },
6709
6726
  className: g = "",
6710
- style: y = {},
6727
+ style: x = {},
6711
6728
  animations: b = {}
6712
- }, I) => {
6713
- const V = O(null), p = O(null), M = O(r), z = O(null), f = O(null), E = O(!1), P = O({ remainingText: null, originalText: null, options: null }), U = O([]), oe = O(0), [S, Z] = ce(!0), [K, X] = ce(null), [$, se] = ce(!1), [ae, pe] = ce(!1);
6729
+ }, R) => {
6730
+ const B = D(null), p = D(null), M = D(r), z = D(null), y = D(null), E = D(!1), P = D({ remainingText: null, originalText: null, options: null }), W = D([]), oe = D(0), [S, Z] = ce(!0), [K, X] = ce(null), [$, se] = ce(!1), [ae, pe] = ce(!1);
6714
6731
  de(() => {
6715
6732
  E.current = ae;
6716
6733
  }, [ae]), de(() => {
6717
6734
  M.current = r;
6718
6735
  }, [r]);
6719
6736
  const ee = Fe(), le = i || ee.service;
6720
- let D;
6721
- le === "browser" ? D = {
6737
+ let O;
6738
+ le === "browser" ? O = {
6722
6739
  service: "browser",
6723
6740
  endpoint: "",
6724
6741
  apiKey: null,
6725
6742
  defaultVoice: "Google US English"
6726
- } : le === "elevenlabs" ? D = {
6743
+ } : le === "elevenlabs" ? O = {
6727
6744
  service: "elevenlabs",
6728
6745
  endpoint: "https://api.elevenlabs.io/v1/text-to-speech",
6729
6746
  apiKey: o || ee.apiKey,
6730
- defaultVoice: s || ee.defaultVoice || Ie.defaultVoice,
6731
- voices: ee.voices || Ie.voices
6732
- } : le === "deepgram" ? D = {
6747
+ defaultVoice: s || ee.defaultVoice || Re.defaultVoice,
6748
+ voices: ee.voices || Re.voices
6749
+ } : le === "deepgram" ? O = {
6733
6750
  service: "deepgram",
6734
6751
  endpoint: "https://api.deepgram.com/v1/speak",
6735
6752
  apiKey: o || ee.apiKey,
6736
6753
  defaultVoice: s || ee.defaultVoice || Te.defaultVoice,
6737
6754
  voices: ee.voices || Te.voices
6738
- } : D = {
6755
+ } : O = {
6739
6756
  ...ee,
6740
6757
  // Override API key if provided via props
6741
6758
  apiKey: o !== null ? o : ee.apiKey
@@ -6745,35 +6762,35 @@ const Ve = Me(({
6745
6762
  body: t,
6746
6763
  avatarMood: e,
6747
6764
  ttsLang: le === "browser" ? "en-US" : n,
6748
- ttsVoice: s || D.defaultVoice,
6765
+ ttsVoice: s || O.defaultVoice,
6749
6766
  lipsyncLang: "en",
6750
6767
  showFullAvatar: r,
6751
6768
  bodyMovement: l,
6752
6769
  movementIntensity: h
6753
- }, R = {
6754
- ttsEndpoint: D.endpoint,
6755
- ttsApikey: D.apiKey,
6770
+ }, I = {
6771
+ ttsEndpoint: O.endpoint,
6772
+ ttsApikey: O.apiKey,
6756
6773
  ttsService: le,
6757
6774
  lipsyncModules: ["en"],
6758
6775
  cameraView: u
6759
6776
  }, k = T(async () => {
6760
- if (!(!V.current || p.current))
6777
+ if (!(!B.current || p.current))
6761
6778
  try {
6762
- if (Z(!0), X(null), p.current = new Be(V.current, R), p.current.controls && (p.current.controls.enableRotate = !1, p.current.controls.enableZoom = !1, p.current.controls.enablePan = !1, p.current.controls.enableDamping = !1), b && Object.keys(b).length > 0 && (p.current.customAnimations = b), await p.current.showAvatar(v, (B) => {
6763
- if (B.lengthComputable) {
6764
- const J = Math.min(100, Math.round(B.loaded / B.total * 100));
6765
- d(J);
6779
+ if (Z(!0), X(null), p.current = new Be(B.current, I), 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) => {
6780
+ if (N.lengthComputable) {
6781
+ const J = Math.min(100, Math.round(N.loaded / N.total * 100));
6782
+ c(J);
6766
6783
  }
6767
- }), await new Promise((B) => {
6784
+ }), await new Promise((N) => {
6768
6785
  const J = () => {
6769
- p.current.lipsync && Object.keys(p.current.lipsync).length > 0 ? B() : setTimeout(J, 100);
6786
+ p.current.lipsync && Object.keys(p.current.lipsync).length > 0 ? N() : setTimeout(J, 100);
6770
6787
  };
6771
6788
  J();
6772
6789
  }), p.current && p.current.setShowFullAvatar)
6773
6790
  try {
6774
6791
  p.current.setShowFullAvatar(r);
6775
- } catch (B) {
6776
- console.warn("Error setting full body mode on initialization:", B);
6792
+ } catch (N) {
6793
+ console.warn("Error setting full body mode on initialization:", N);
6777
6794
  }
6778
6795
  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);
6779
6796
  const F = () => {
@@ -6783,18 +6800,18 @@ const Ve = Me(({
6783
6800
  document.removeEventListener("visibilitychange", F);
6784
6801
  };
6785
6802
  } catch (L) {
6786
- console.error("Error initializing TalkingHead:", L), X(L.message || "Failed to initialize avatar"), Z(!1), c(L);
6803
+ console.error("Error initializing TalkingHead:", L), X(L.message || "Failed to initialize avatar"), Z(!1), d(L);
6787
6804
  }
6788
6805
  }, [G, t, e, n, i, s, o, r, l, h, u]);
6789
6806
  de(() => (k(), () => {
6790
6807
  p.current && (p.current.stop(), p.current.dispose(), p.current = null);
6791
6808
  }), [k]), de(() => {
6792
- if (!V.current || !p.current) return;
6793
- const L = new ResizeObserver((B) => {
6794
- for (const J of B)
6809
+ if (!B.current || !p.current) return;
6810
+ const L = new ResizeObserver((N) => {
6811
+ for (const J of N)
6795
6812
  p.current && p.current.onResize && p.current.onResize();
6796
6813
  });
6797
- L.observe(V.current);
6814
+ L.observe(B.current);
6798
6815
  const F = () => {
6799
6816
  p.current && p.current.onResize && p.current.onResize();
6800
6817
  };
@@ -6809,12 +6826,12 @@ const Ve = Me(({
6809
6826
  } catch (L) {
6810
6827
  console.warn("Failed to resume audio context:", L);
6811
6828
  }
6812
- }, []), N = T(async (L, F = {}) => {
6829
+ }, []), U = T(async (L, F = {}) => {
6813
6830
  if (p.current && $)
6814
6831
  try {
6815
- f.current && (clearInterval(f.current), f.current = null), z.current = { text: L, options: F }, P.current = { remainingText: null, originalText: null, options: null };
6816
- const B = /[!\.\?\n\p{Extended_Pictographic}]/ug, J = L.split(B).map((Y) => Y.trim()).filter((Y) => Y.length > 0);
6817
- U.current = J, oe.current = 0, pe(!1), E.current = !1, await H();
6832
+ y.current && (clearInterval(y.current), y.current = null), z.current = { text: L, options: F }, P.current = { remainingText: null, originalText: null, options: null };
6833
+ const N = /[!\.\?\n\p{Extended_Pictographic}]/ug, J = L.split(N).map((Y) => Y.trim()).filter((Y) => Y.length > 0);
6834
+ W.current = J, oe.current = 0, pe(!1), E.current = !1, await H();
6818
6835
  const ge = {
6819
6836
  ...F,
6820
6837
  lipsyncLang: F.lipsyncLang || v.lipsyncLang || "en"
@@ -6828,12 +6845,12 @@ const Ve = Me(({
6828
6845
  if (Se++, E.current)
6829
6846
  return;
6830
6847
  if (Se > Ae) {
6831
- if (he && (clearInterval(he), he = null, f.current = null), !be && !E.current) {
6848
+ if (he && (clearInterval(he), he = null, y.current = null), !be && !E.current) {
6832
6849
  be = !0;
6833
6850
  try {
6834
6851
  F.onSpeechEnd();
6835
- } catch (Oe) {
6836
- console.error("Error in onSpeechEnd callback (timeout):", Oe);
6852
+ } catch (Ne) {
6853
+ console.error("Error in onSpeechEnd callback (timeout):", Ne);
6837
6854
  }
6838
6855
  }
6839
6856
  return;
@@ -6841,7 +6858,7 @@ const Ve = Me(({
6841
6858
  const ye = !Y.speechQueue || Y.speechQueue.length === 0, ke = !Y.audioPlaylist || Y.audioPlaylist.length === 0;
6842
6859
  Y && Y.isSpeaking === !1 && ye && ke && Y.isAudioPlaying === !1 && !be && !E.current && setTimeout(() => {
6843
6860
  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) {
6844
- be = !0, he && (clearInterval(he), he = null, f.current = null);
6861
+ be = !0, he && (clearInterval(he), he = null, y.current = null);
6845
6862
  try {
6846
6863
  F.onSpeechEnd();
6847
6864
  } catch (Ze) {
@@ -6849,13 +6866,13 @@ const Ve = Me(({
6849
6866
  }
6850
6867
  }
6851
6868
  }, 100);
6852
- }, 100), f.current = he;
6869
+ }, 100), y.current = he;
6853
6870
  }
6854
6871
  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 () => {
6855
6872
  await H(), p.current && p.current.lipsync && (p.current.setSlowdownRate && p.current.setSlowdownRate(1.05), p.current.speakText(L, ge));
6856
6873
  }, 100);
6857
- } catch (B) {
6858
- console.error("Error speaking text:", B), X(B.message || "Failed to speak text");
6874
+ } catch (N) {
6875
+ console.error("Error speaking text:", N), X(N.message || "Failed to speak text");
6859
6876
  }
6860
6877
  }, [$, H, v.lipsyncLang]), _ = T(() => {
6861
6878
  p.current && (p.current.stopSpeaking(), p.current.setSlowdownRate && p.current.setSlowdownRate(1), z.current = null, pe(!1));
@@ -6863,17 +6880,17 @@ const Ve = Me(({
6863
6880
  if (p.current && p.current.pauseSpeaking) {
6864
6881
  const L = p.current;
6865
6882
  if (L.isSpeaking || L.audioPlaylist && L.audioPlaylist.length > 0 || L.speechQueue && L.speechQueue.length > 0) {
6866
- f.current && (clearInterval(f.current), f.current = null);
6867
- let B = "";
6868
- if (z.current && U.current.length > 0) {
6869
- const J = U.current.length, ge = L.speechQueue ? L.speechQueue.filter((Ae) => Ae && Ae.text && Array.isArray(Ae.text) && Ae.text.length > 0).length : 0, Y = L.audioPlaylist && L.audioPlaylist.length > 0, he = ge + (Y ? 1 : 0), Se = J - he;
6870
- if (he > 0 && Se < J && (B = U.current.slice(Se).join(". ").trim(), !B && ge > 0 && L.speechQueue)) {
6883
+ y.current && (clearInterval(y.current), y.current = null);
6884
+ let N = "";
6885
+ if (z.current && W.current.length > 0) {
6886
+ const J = W.current.length, ge = L.speechQueue ? L.speechQueue.filter((Ae) => Ae && Ae.text && Array.isArray(Ae.text) && Ae.text.length > 0).length : 0, Y = L.audioPlaylist && L.audioPlaylist.length > 0, he = ge + (Y ? 1 : 0), Se = J - he;
6887
+ if (he > 0 && Se < J && (N = W.current.slice(Se).join(". ").trim(), !N && ge > 0 && L.speechQueue)) {
6871
6888
  const be = L.speechQueue.filter((ye) => ye && ye.text && Array.isArray(ye.text) && ye.text.length > 0).map((ye) => ye.text.map((ke) => ke.word || "").filter((ke) => ke.length > 0).join(" ")).filter((ye) => ye.length > 0).join(" ");
6872
- be && be.trim() && (B = be.trim());
6889
+ be && be.trim() && (N = be.trim());
6873
6890
  }
6874
6891
  }
6875
6892
  z.current && (P.current = {
6876
- remainingText: B || null,
6893
+ remainingText: N || null,
6877
6894
  originalText: z.current.text,
6878
6895
  options: z.current.options
6879
6896
  }), L.speechQueue && (L.speechQueue.length = 0), p.current.pauseSpeaking(), E.current = !0, pe(!0);
@@ -6892,16 +6909,16 @@ const Ve = Me(({
6892
6909
  return;
6893
6910
  }
6894
6911
  pe(!1), E.current = !1, await H();
6895
- const B = {
6912
+ const N = {
6896
6913
  ...F,
6897
6914
  lipsyncLang: F.lipsyncLang || v.lipsyncLang || "en"
6898
6915
  };
6899
6916
  try {
6900
- await N(L, B);
6917
+ await U(L, N);
6901
6918
  } catch (J) {
6902
6919
  console.error("Error resuming speech:", J), pe(!1), E.current = !1;
6903
6920
  }
6904
- }, [H, ae, N, v]), Le = T((L) => {
6921
+ }, [H, ae, U, v]), Le = T((L) => {
6905
6922
  p.current && p.current.setMood(L);
6906
6923
  }, []), we = T((L) => {
6907
6924
  p.current && p.current.setSlowdownRate && p.current.setSlowdownRate(L);
@@ -6946,8 +6963,8 @@ const Ve = Me(({
6946
6963
  }, [b]), te = T(() => {
6947
6964
  p.current && p.current.onResize && p.current.onResize();
6948
6965
  }, []);
6949
- return Ee(I, () => ({
6950
- speakText: N,
6966
+ return Ee(R, () => ({
6967
+ speakText: U,
6951
6968
  stopSpeaking: _,
6952
6969
  pauseSpeaking: j,
6953
6970
  resumeSpeaking: q,
@@ -7024,13 +7041,13 @@ const Ve = Me(({
7024
7041
  width: "100%",
7025
7042
  height: "100%",
7026
7043
  position: "relative",
7027
- ...y
7044
+ ...x
7028
7045
  },
7029
7046
  children: [
7030
7047
  /* @__PURE__ */ me(
7031
7048
  "div",
7032
7049
  {
7033
- ref: V,
7050
+ ref: B,
7034
7051
  className: "talking-head-viewer",
7035
7052
  style: {
7036
7053
  width: "100%",
@@ -7077,7 +7094,7 @@ const pt = Me(({
7077
7094
  style: s = {},
7078
7095
  avatarConfig: o = {}
7079
7096
  }, l) => {
7080
- const h = O(null), r = O(null), [u, a] = ce(!0), [d, c] = ce(null), [g, y] = ce(!1), b = Fe(), I = o.ttsService || b.service, V = I === "browser" ? {
7097
+ const h = D(null), r = D(null), [u, a] = ce(!0), [c, d] = ce(null), [g, x] = ce(!1), b = Fe(), R = o.ttsService || b.service, B = R === "browser" ? {
7081
7098
  endpoint: "",
7082
7099
  apiKey: null,
7083
7100
  defaultVoice: "Google US English"
@@ -7086,14 +7103,14 @@ const pt = Me(({
7086
7103
  // Override API key if provided via avatarConfig
7087
7104
  apiKey: o.ttsApiKey !== void 0 && o.ttsApiKey !== null ? o.ttsApiKey : b.apiKey,
7088
7105
  // Override endpoint for ElevenLabs if service is explicitly set
7089
- endpoint: I === "elevenlabs" && o.ttsApiKey ? "https://api.elevenlabs.io/v1/text-to-speech" : b.endpoint
7106
+ endpoint: R === "elevenlabs" && o.ttsApiKey ? "https://api.elevenlabs.io/v1/text-to-speech" : b.endpoint
7090
7107
  }, p = {
7091
7108
  url: "/avatars/brunette.glb",
7092
7109
  // Use brunette avatar (working glTF file)
7093
7110
  body: "F",
7094
7111
  avatarMood: "neutral",
7095
- ttsLang: I === "browser" ? "en-US" : "en",
7096
- ttsVoice: o.ttsVoice || V.defaultVoice,
7112
+ ttsLang: R === "browser" ? "en-US" : "en",
7113
+ ttsVoice: o.ttsVoice || B.defaultVoice,
7097
7114
  lipsyncLang: "en",
7098
7115
  // English lip-sync
7099
7116
  showFullAvatar: !0,
@@ -7102,15 +7119,15 @@ const pt = Me(({
7102
7119
  movementIntensity: 0.5,
7103
7120
  ...o
7104
7121
  }, M = {
7105
- ttsEndpoint: V.endpoint,
7106
- ttsApikey: V.apiKey,
7107
- ttsService: I,
7122
+ ttsEndpoint: B.endpoint,
7123
+ ttsApikey: B.apiKey,
7124
+ ttsService: R,
7108
7125
  lipsyncModules: ["en"],
7109
7126
  cameraView: "upper"
7110
7127
  }, z = T(async () => {
7111
7128
  if (!(!h.current || r.current))
7112
7129
  try {
7113
- if (a(!0), c(null), r.current = new Be(h.current, M), await r.current.showAvatar(p, (K) => {
7130
+ if (a(!0), d(null), r.current = new Be(h.current, M), await r.current.showAvatar(p, (K) => {
7114
7131
  if (K.lengthComputable) {
7115
7132
  const X = Math.min(100, Math.round(K.loaded / K.total * 100));
7116
7133
  t(X);
@@ -7132,7 +7149,7 @@ const pt = Me(({
7132
7149
  } catch (K) {
7133
7150
  console.warn("Error setting full body mode on initialization:", K);
7134
7151
  }
7135
- a(!1), y(!0), n(r.current);
7152
+ a(!1), x(!0), n(r.current);
7136
7153
  const Z = () => {
7137
7154
  document.visibilityState === "visible" ? r.current?.start() : r.current?.stop();
7138
7155
  };
@@ -7140,20 +7157,20 @@ const pt = Me(({
7140
7157
  document.removeEventListener("visibilitychange", Z);
7141
7158
  };
7142
7159
  } catch (S) {
7143
- console.error("Error initializing TalkingHead:", S), c(S.message || "Failed to initialize avatar"), a(!1), e(S);
7160
+ console.error("Error initializing TalkingHead:", S), d(S.message || "Failed to initialize avatar"), a(!1), e(S);
7144
7161
  }
7145
7162
  }, []);
7146
7163
  de(() => (z(), () => {
7147
7164
  r.current && (r.current.stop(), r.current.dispose(), r.current = null);
7148
7165
  }), [z]);
7149
- const f = T((S) => {
7166
+ const y = T((S) => {
7150
7167
  if (r.current && g)
7151
7168
  try {
7152
7169
  console.log("Speaking text:", S), 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(S)) : (console.warn("Lip-sync modules not ready, waiting..."), setTimeout(() => {
7153
7170
  r.current && r.current.lipsync ? (console.log("Lip-sync now ready, speaking..."), r.current.setSlowdownRate && (r.current.setSlowdownRate(1.05), console.log("Applied timing adjustment for better lip-sync")), r.current.speakText(S)) : console.error("Lip-sync still not ready after waiting");
7154
7171
  }, 500));
7155
7172
  } catch (Z) {
7156
- console.error("Error speaking text:", Z), c(Z.message || "Failed to speak text");
7173
+ console.error("Error speaking text:", Z), d(Z.message || "Failed to speak text");
7157
7174
  }
7158
7175
  else
7159
7176
  console.warn("Avatar not ready for speaking. isReady:", g, "talkingHeadRef:", !!r.current);
@@ -7161,7 +7178,7 @@ const pt = Me(({
7161
7178
  r.current && (r.current.stopSpeaking(), r.current.setSlowdownRate && (r.current.setSlowdownRate(1), console.log("Reset timing to normal")));
7162
7179
  }, []), P = T((S) => {
7163
7180
  r.current && r.current.setMood(S);
7164
- }, []), U = T((S) => {
7181
+ }, []), W = T((S) => {
7165
7182
  r.current && r.current.setSlowdownRate && (r.current.setSlowdownRate(S), console.log("Timing adjustment set to:", S));
7166
7183
  }, []), oe = T((S, Z = !1) => {
7167
7184
  if (r.current && r.current.playAnimation) {
@@ -7205,10 +7222,10 @@ const pt = Me(({
7205
7222
  console.warn("Animation system not available or animation not found:", S);
7206
7223
  }, []);
7207
7224
  return Ee(l, () => ({
7208
- speakText: f,
7225
+ speakText: y,
7209
7226
  stopSpeaking: E,
7210
7227
  setMood: P,
7211
- setTimingAdjustment: U,
7228
+ setTimingAdjustment: W,
7212
7229
  playAnimation: oe,
7213
7230
  isReady: g,
7214
7231
  talkingHead: r.current,
@@ -7291,7 +7308,7 @@ const pt = Me(({
7291
7308
  fontSize: "18px",
7292
7309
  zIndex: 10
7293
7310
  }, children: "Loading avatar..." }),
7294
- d && /* @__PURE__ */ me("div", { className: "error-overlay", style: {
7311
+ c && /* @__PURE__ */ me("div", { className: "error-overlay", style: {
7295
7312
  position: "absolute",
7296
7313
  top: "50%",
7297
7314
  left: "50%",
@@ -7302,7 +7319,7 @@ const pt = Me(({
7302
7319
  zIndex: 10,
7303
7320
  padding: "20px",
7304
7321
  borderRadius: "8px"
7305
- }, children: d })
7322
+ }, children: c })
7306
7323
  ] });
7307
7324
  });
7308
7325
  pt.displayName = "TalkingHeadComponent";
@@ -7319,79 +7336,79 @@ const gt = Me(({
7319
7336
  movementIntensity: r = 0.5,
7320
7337
  showFullAvatar: u = !1,
7321
7338
  cameraView: a = "upper",
7322
- onReady: d = () => {
7339
+ onReady: c = () => {
7323
7340
  },
7324
- onLoading: c = () => {
7341
+ onLoading: d = () => {
7325
7342
  },
7326
7343
  onError: g = () => {
7327
7344
  },
7328
- onSpeechEnd: y = () => {
7345
+ onSpeechEnd: x = () => {
7329
7346
  },
7330
7347
  className: b = "",
7331
- style: I = {},
7332
- animations: V = {},
7348
+ style: R = {},
7349
+ animations: B = {},
7333
7350
  autoSpeak: p = !1
7334
7351
  }, M) => {
7335
- const z = O(null), f = O(null), E = O(u), P = O(null), U = O(null), oe = O(!1), S = O({ remainingText: null, originalText: null, options: null }), Z = O([]), [K, X] = ce(!0), [$, se] = ce(null), [ae, pe] = ce(!1), [ee, le] = ce(!1);
7352
+ const z = D(null), y = D(null), E = D(u), P = D(null), W = D(null), oe = D(!1), S = D({ remainingText: null, originalText: null, options: null }), Z = D([]), [K, X] = ce(!0), [$, se] = ce(null), [ae, pe] = ce(!1), [ee, le] = ce(!1);
7336
7353
  de(() => {
7337
7354
  oe.current = ee;
7338
7355
  }, [ee]), de(() => {
7339
7356
  E.current = u;
7340
7357
  }, [u]);
7341
- const D = Fe(), v = s || D.service;
7342
- let R;
7343
- v === "browser" ? R = {
7358
+ const O = Fe(), v = s || O.service;
7359
+ let I;
7360
+ v === "browser" ? I = {
7344
7361
  service: "browser",
7345
7362
  endpoint: "",
7346
7363
  apiKey: null,
7347
7364
  defaultVoice: "Google US English"
7348
- } : v === "elevenlabs" ? R = {
7365
+ } : v === "elevenlabs" ? I = {
7349
7366
  service: "elevenlabs",
7350
7367
  endpoint: "https://api.elevenlabs.io/v1/text-to-speech",
7351
- apiKey: l || D.apiKey,
7352
- defaultVoice: o || D.defaultVoice || Ie.defaultVoice,
7353
- voices: D.voices || Ie.voices
7354
- } : v === "deepgram" ? R = {
7368
+ apiKey: l || O.apiKey,
7369
+ defaultVoice: o || O.defaultVoice || Re.defaultVoice,
7370
+ voices: O.voices || Re.voices
7371
+ } : v === "deepgram" ? I = {
7355
7372
  service: "deepgram",
7356
7373
  endpoint: "https://api.deepgram.com/v1/speak",
7357
- apiKey: l || D.apiKey,
7358
- defaultVoice: o || D.defaultVoice || Te.defaultVoice,
7359
- voices: D.voices || Te.voices
7360
- } : R = {
7361
- ...D,
7362
- apiKey: l !== null ? l : D.apiKey
7374
+ apiKey: l || O.apiKey,
7375
+ defaultVoice: o || O.defaultVoice || Te.defaultVoice,
7376
+ voices: O.voices || Te.voices
7377
+ } : I = {
7378
+ ...O,
7379
+ apiKey: l !== null ? l : O.apiKey
7363
7380
  };
7364
7381
  const k = {
7365
7382
  url: t,
7366
7383
  body: e,
7367
7384
  avatarMood: n,
7368
7385
  ttsLang: v === "browser" ? "en-US" : i,
7369
- ttsVoice: o || R.defaultVoice,
7386
+ ttsVoice: o || I.defaultVoice,
7370
7387
  lipsyncLang: "en",
7371
7388
  showFullAvatar: u,
7372
7389
  bodyMovement: h,
7373
7390
  movementIntensity: r
7374
7391
  }, H = {
7375
- ttsEndpoint: R.endpoint,
7376
- ttsApikey: R.apiKey,
7392
+ ttsEndpoint: I.endpoint,
7393
+ ttsApikey: I.apiKey,
7377
7394
  ttsService: v,
7378
7395
  lipsyncModules: ["en"],
7379
7396
  cameraView: a
7380
- }, N = T(async () => {
7381
- if (!(!z.current || f.current))
7397
+ }, U = T(async () => {
7398
+ if (!(!z.current || y.current))
7382
7399
  try {
7383
- X(!0), se(null), f.current = new Be(z.current, H), console.log("Avatar config being passed:", {
7400
+ X(!0), se(null), y.current = new Be(z.current, H), console.log("Avatar config being passed:", {
7384
7401
  url: k.url,
7385
7402
  body: k.body,
7386
7403
  avatarMood: k.avatarMood
7387
- }), await f.current.showAvatar(k, (te) => {
7404
+ }), await y.current.showAvatar(k, (te) => {
7388
7405
  if (te.lengthComputable) {
7389
7406
  const L = Math.min(100, Math.round(te.loaded / te.total * 100));
7390
- c(L);
7407
+ d(L);
7391
7408
  }
7392
- }), f.current?.avatar && console.log("Avatar body after initialization:", f.current.avatar.body), X(!1), pe(!0), d(f.current);
7409
+ }), y.current?.avatar && console.log("Avatar body after initialization:", y.current.avatar.body), X(!1), pe(!0), c(y.current);
7393
7410
  const C = () => {
7394
- document.visibilityState === "visible" ? f.current?.start() : f.current?.stop();
7411
+ document.visibilityState === "visible" ? y.current?.start() : y.current?.stop();
7395
7412
  };
7396
7413
  return document.addEventListener("visibilitychange", C), () => {
7397
7414
  document.removeEventListener("visibilitychange", C);
@@ -7400,19 +7417,19 @@ const gt = Me(({
7400
7417
  console.error("Error initializing TalkingHead:", C), se(C.message || "Failed to initialize avatar"), X(!1), g(C);
7401
7418
  }
7402
7419
  }, []);
7403
- de(() => (N(), () => {
7404
- f.current && (f.current.stop(), f.current.dispose(), f.current = null);
7405
- }), [N]);
7420
+ de(() => (U(), () => {
7421
+ y.current && (y.current.stop(), y.current.dispose(), y.current = null);
7422
+ }), [U]);
7406
7423
  const _ = T(async () => {
7407
- if (f.current)
7424
+ if (y.current)
7408
7425
  try {
7409
- const C = f.current.audioCtx || f.current.audioContext;
7426
+ const C = y.current.audioCtx || y.current.audioContext;
7410
7427
  C && (C.state === "suspended" || C.state === "interrupted") && (await C.resume(), console.log("Audio context resumed"));
7411
7428
  } catch (C) {
7412
7429
  console.warn("Failed to resume audio context:", C);
7413
7430
  }
7414
7431
  }, []), j = T(async (C, te = {}) => {
7415
- if (!f.current || !ae) {
7432
+ if (!y.current || !ae) {
7416
7433
  console.warn("Avatar not ready for speaking");
7417
7434
  return;
7418
7435
  }
@@ -7420,42 +7437,42 @@ const gt = Me(({
7420
7437
  console.warn("No text provided to speak");
7421
7438
  return;
7422
7439
  }
7423
- await _(), S.current = { remainingText: null, originalText: null, options: null }, Z.current = [], P.current = { text: C, options: te }, U.current && (clearInterval(U.current), U.current = null), le(!1), oe.current = !1;
7424
- const L = C.split(/[.!?]+/).filter((B) => B.trim().length > 0);
7440
+ await _(), S.current = { remainingText: null, originalText: null, options: null }, Z.current = [], P.current = { text: C, options: te }, W.current && (clearInterval(W.current), W.current = null), le(!1), oe.current = !1;
7441
+ const L = C.split(/[.!?]+/).filter((N) => N.trim().length > 0);
7425
7442
  Z.current = L;
7426
7443
  const F = {
7427
7444
  lipsyncLang: te.lipsyncLang || "en",
7428
7445
  onSpeechEnd: () => {
7429
- U.current && (clearInterval(U.current), U.current = null), te.onSpeechEnd && te.onSpeechEnd(), y();
7446
+ W.current && (clearInterval(W.current), W.current = null), te.onSpeechEnd && te.onSpeechEnd(), x();
7430
7447
  }
7431
7448
  };
7432
7449
  try {
7433
- f.current.speakText(C, F);
7434
- } catch (B) {
7435
- console.error("Error speaking text:", B), se(B.message || "Failed to speak text");
7450
+ y.current.speakText(C, F);
7451
+ } catch (N) {
7452
+ console.error("Error speaking text:", N), se(N.message || "Failed to speak text");
7436
7453
  }
7437
- }, [ae, y, _]);
7454
+ }, [ae, x, _]);
7438
7455
  de(() => {
7439
- ae && G && p && f.current && j(G);
7456
+ ae && G && p && y.current && j(G);
7440
7457
  }, [ae, G, p, j]);
7441
7458
  const q = T(() => {
7442
- if (f.current)
7459
+ if (y.current)
7443
7460
  try {
7444
- const C = f.current.isSpeaking || !1, te = f.current.audioPlaylist || [], L = f.current.speechQueue || [];
7461
+ const C = y.current.isSpeaking || !1, te = y.current.audioPlaylist || [], L = y.current.speechQueue || [];
7445
7462
  if (C || te.length > 0 || L.length > 0) {
7446
- U.current && (clearInterval(U.current), U.current = null);
7463
+ W.current && (clearInterval(W.current), W.current = null);
7447
7464
  let F = "";
7448
- L.length > 0 && (F = L.map((B) => B.text && Array.isArray(B.text) ? B.text.map((J) => J.word).join(" ") : B.text || "").join(" ")), S.current = {
7465
+ L.length > 0 && (F = L.map((N) => N.text && Array.isArray(N.text) ? N.text.map((J) => J.word).join(" ") : N.text || "").join(" ")), S.current = {
7449
7466
  remainingText: F || null,
7450
7467
  originalText: P.current?.text || null,
7451
7468
  options: P.current?.options || null
7452
- }, f.current.speechQueue.length = 0, f.current.pauseSpeaking(), le(!0), oe.current = !0;
7469
+ }, y.current.speechQueue.length = 0, y.current.pauseSpeaking(), le(!0), oe.current = !0;
7453
7470
  }
7454
7471
  } catch (C) {
7455
7472
  console.warn("Error pausing speech:", C);
7456
7473
  }
7457
7474
  }, []), Le = T(async () => {
7458
- if (!(!f.current || !ee))
7475
+ if (!(!y.current || !ee))
7459
7476
  try {
7460
7477
  await _(), le(!1), oe.current = !1;
7461
7478
  const C = S.current?.remainingText, te = S.current?.originalText || P.current?.text, L = S.current?.options || P.current?.options || {}, F = C || te;
@@ -7464,7 +7481,7 @@ const gt = Me(({
7464
7481
  console.warn("Error resuming speech:", C), le(!1), oe.current = !1;
7465
7482
  }
7466
7483
  }, [ee, j, _]), we = T(() => {
7467
- f.current && (f.current.stopSpeaking(), U.current && (clearInterval(U.current), U.current = null), le(!1), oe.current = !1);
7484
+ y.current && (y.current.stopSpeaking(), W.current && (clearInterval(W.current), W.current = null), le(!1), oe.current = !1);
7468
7485
  }, []);
7469
7486
  return Ee(M, () => ({
7470
7487
  speakText: j,
@@ -7473,21 +7490,21 @@ const gt = Me(({
7473
7490
  stopSpeaking: we,
7474
7491
  resumeAudioContext: _,
7475
7492
  isPaused: () => ee,
7476
- setMood: (C) => f.current?.setMood(C),
7493
+ setMood: (C) => y.current?.setMood(C),
7477
7494
  setBodyMovement: (C) => {
7478
- f.current && f.current.setBodyMovement(C);
7495
+ y.current && y.current.setBodyMovement(C);
7479
7496
  },
7480
7497
  playAnimation: (C, te = !1) => {
7481
- f.current && f.current.playAnimation && f.current.playAnimation(C, null, 10, 0, 0.01, te);
7498
+ y.current && y.current.playAnimation && y.current.playAnimation(C, null, 10, 0, 0.01, te);
7482
7499
  },
7483
- playReaction: (C) => f.current?.playReaction(C),
7484
- playCelebration: () => f.current?.playCelebration(),
7500
+ playReaction: (C) => y.current?.playReaction(C),
7501
+ playCelebration: () => y.current?.playCelebration(),
7485
7502
  setShowFullAvatar: (C) => {
7486
- f.current && (E.current = C, f.current.setShowFullAvatar(C));
7503
+ y.current && (E.current = C, y.current.setShowFullAvatar(C));
7487
7504
  },
7488
7505
  isReady: ae,
7489
- talkingHead: f.current
7490
- })), /* @__PURE__ */ Pe("div", { className: `simple-talking-avatar-container ${b}`, style: I, children: [
7506
+ talkingHead: y.current
7507
+ })), /* @__PURE__ */ Pe("div", { className: `simple-talking-avatar-container ${b}`, style: R, children: [
7491
7508
  /* @__PURE__ */ me(
7492
7509
  "div",
7493
7510
  {
@@ -7540,7 +7557,7 @@ const yt = Me(({
7540
7557
  },
7541
7558
  autoStart: h = !1
7542
7559
  }, r) => {
7543
- const u = O(null), a = O({
7560
+ const u = D(null), a = D({
7544
7561
  currentModuleIndex: 0,
7545
7562
  currentLessonIndex: 0,
7546
7563
  currentQuestionIndex: 0,
@@ -7550,18 +7567,18 @@ const yt = Me(({
7550
7567
  curriculumCompleted: !1,
7551
7568
  score: 0,
7552
7569
  totalQuestions: 0
7553
- }), d = O({
7570
+ }), c = D({
7554
7571
  onLessonStart: n,
7555
7572
  onLessonComplete: i,
7556
7573
  onQuestionAnswer: s,
7557
7574
  onCurriculumComplete: o,
7558
7575
  onCustomAction: l
7559
- }), c = O(null), g = O(null), y = O(null), b = O(null), I = O(null), V = O(null), p = O(null), M = O(G?.curriculum || {
7576
+ }), d = D(null), g = D(null), x = D(null), b = D(null), R = D(null), B = D(null), p = D(null), M = D(G?.curriculum || {
7560
7577
  title: "Default Curriculum",
7561
7578
  description: "No curriculum data provided",
7562
7579
  language: "en",
7563
7580
  modules: []
7564
- }), z = O({
7581
+ }), z = D({
7565
7582
  avatarUrl: t.avatarUrl || "/avatars/brunette.glb",
7566
7583
  avatarBody: t.avatarBody || "F",
7567
7584
  mood: t.mood || "happy",
@@ -7576,7 +7593,7 @@ const yt = Me(({
7576
7593
  lipsyncLang: "en"
7577
7594
  });
7578
7595
  de(() => {
7579
- d.current = {
7596
+ c.current = {
7580
7597
  onLessonStart: n,
7581
7598
  onLessonComplete: i,
7582
7599
  onQuestionAnswer: s,
@@ -7604,17 +7621,17 @@ const yt = Me(({
7604
7621
  lipsyncLang: "en"
7605
7622
  };
7606
7623
  }, [G, t, e]);
7607
- const f = T(() => (M.current || { modules: [] }).modules[a.current.currentModuleIndex]?.lessons[a.current.currentLessonIndex], []), E = T(() => f()?.questions[a.current.currentQuestionIndex], [f]), 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, []), U = T(() => {
7624
+ const y = T(() => (M.current || { modules: [] }).modules[a.current.currentModuleIndex]?.lessons[a.current.currentLessonIndex], []), E = T(() => y()?.questions[a.current.currentQuestionIndex], [y]), P = T((v, I) => I.type === "multiple_choice" || I.type === "true_false" ? v === I.answer : I.type === "code_test" && typeof v == "object" && v !== null ? v.passed === !0 : !1, []), W = T(() => {
7608
7625
  a.current.lessonCompleted = !0, a.current.isQuestionMode = !1;
7609
7626
  const v = a.current.totalQuestions > 0 ? Math.round(a.current.score / a.current.totalQuestions * 100) : 100;
7610
- let R = "Congratulations! You've completed this lesson";
7611
- if (a.current.totalQuestions > 0 ? R += ` You got ${a.current.score} correct out of ${a.current.totalQuestions} question${a.current.totalQuestions === 1 ? "" : "s"}, achieving a score of ${v} percent. ` : R += "! ", v >= 80 ? R += "Excellent work! You have a great understanding of this topic." : v >= 60 ? R += "Good job! You understand most of the concepts." : R += "Keep practicing! You're making progress.", d.current.onLessonComplete({
7627
+ let I = "Congratulations! You've completed this lesson";
7628
+ if (a.current.totalQuestions > 0 ? I += ` You got ${a.current.score} correct out of ${a.current.totalQuestions} question${a.current.totalQuestions === 1 ? "" : "s"}, achieving a score of ${v} percent. ` : I += "! ", v >= 80 ? I += "Excellent work! You have a great understanding of this topic." : v >= 60 ? I += "Good job! You understand most of the concepts." : I += "Keep practicing! You're making progress.", c.current.onLessonComplete({
7612
7629
  moduleIndex: a.current.currentModuleIndex,
7613
7630
  lessonIndex: a.current.currentLessonIndex,
7614
7631
  score: a.current.score,
7615
7632
  totalQuestions: a.current.totalQuestions,
7616
7633
  percentage: v
7617
- }), d.current.onCustomAction({
7634
+ }), c.current.onCustomAction({
7618
7635
  type: "lessonComplete",
7619
7636
  moduleIndex: a.current.currentModuleIndex,
7620
7637
  lessonIndex: a.current.currentLessonIndex,
@@ -7628,11 +7645,11 @@ const yt = Me(({
7628
7645
  } catch {
7629
7646
  u.current.playCelebration();
7630
7647
  }
7631
- const k = M.current || { modules: [] }, H = k.modules[a.current.currentModuleIndex], N = a.current.currentLessonIndex < (H?.lessons?.length || 0) - 1, _ = a.current.currentModuleIndex < (k.modules?.length || 0) - 1, j = N || _, q = z.current || { lipsyncLang: "en" };
7632
- u.current.speakText(R, {
7648
+ const k = M.current || { modules: [] }, H = k.modules[a.current.currentModuleIndex], U = a.current.currentLessonIndex < (H?.lessons?.length || 0) - 1, _ = a.current.currentModuleIndex < (k.modules?.length || 0) - 1, j = U || _, q = z.current || { lipsyncLang: "en" };
7649
+ u.current.speakText(I, {
7633
7650
  lipsyncLang: q.lipsyncLang,
7634
7651
  onSpeechEnd: () => {
7635
- d.current.onCustomAction({
7652
+ c.current.onCustomAction({
7636
7653
  type: "lessonCompleteFeedbackDone",
7637
7654
  moduleIndex: a.current.currentModuleIndex,
7638
7655
  lessonIndex: a.current.currentLessonIndex,
@@ -7647,9 +7664,9 @@ const yt = Me(({
7647
7664
  }, [e.lessonComplete]), oe = T(() => {
7648
7665
  a.current.curriculumCompleted = !0;
7649
7666
  const v = M.current || { modules: [] };
7650
- if (d.current.onCurriculumComplete({
7667
+ if (c.current.onCurriculumComplete({
7651
7668
  modules: v.modules.length,
7652
- totalLessons: v.modules.reduce((R, k) => R + k.lessons.length, 0)
7669
+ totalLessons: v.modules.reduce((I, k) => I + k.lessons.length, 0)
7653
7670
  }), u.current) {
7654
7671
  if (u.current.setMood("celebrating"), e.curriculumComplete)
7655
7672
  try {
@@ -7657,94 +7674,94 @@ const yt = Me(({
7657
7674
  } catch {
7658
7675
  u.current.playCelebration();
7659
7676
  }
7660
- const R = z.current || { lipsyncLang: "en" };
7661
- 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 });
7677
+ const I = z.current || { lipsyncLang: "en" };
7678
+ u.current.speakText("Amazing! You've completed the entire curriculum! You're now ready to move on to more advanced topics. Well done!", { lipsyncLang: I.lipsyncLang });
7662
7679
  }
7663
7680
  }, [e.curriculumComplete]), S = T(() => {
7664
- const v = f();
7681
+ const v = y();
7665
7682
  a.current.isQuestionMode = !0, a.current.currentQuestionIndex = 0, a.current.totalQuestions = v?.questions?.length || 0, a.current.score = 0;
7666
- const R = E();
7667
- R && d.current.onCustomAction({
7683
+ const I = E();
7684
+ I && c.current.onCustomAction({
7668
7685
  type: "questionStart",
7669
7686
  moduleIndex: a.current.currentModuleIndex,
7670
7687
  lessonIndex: a.current.currentLessonIndex,
7671
7688
  questionIndex: a.current.currentQuestionIndex,
7672
7689
  totalQuestions: a.current.totalQuestions,
7673
- question: R,
7690
+ question: I,
7674
7691
  score: a.current.score
7675
7692
  });
7676
7693
  const k = () => {
7677
- if (!u.current || !R) return;
7694
+ if (!u.current || !I) return;
7678
7695
  if (u.current.setMood("happy"), e.questionStart)
7679
7696
  try {
7680
7697
  u.current.playAnimation(e.questionStart, !0);
7681
- } catch (N) {
7682
- console.warn("Failed to play questionStart animation:", N);
7698
+ } catch (U) {
7699
+ console.warn("Failed to play questionStart animation:", U);
7683
7700
  }
7684
7701
  const H = z.current || { lipsyncLang: "en" };
7685
- 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 });
7702
+ I.type === "code_test" ? u.current.speakText(`Let's test your coding skills! Here's your first challenge: ${I.question}`, { lipsyncLang: H.lipsyncLang }) : I.type === "multiple_choice" ? u.current.speakText(`Now let me ask you some questions. Here's the first one: ${I.question}`, { lipsyncLang: H.lipsyncLang }) : I.type === "true_false" ? u.current.speakText(`Let's start with some true or false questions. First question: ${I.question}`, { lipsyncLang: H.lipsyncLang }) : u.current.speakText(`Now let me ask you some questions. Here's the first one: ${I.question}`, { lipsyncLang: H.lipsyncLang });
7686
7703
  };
7687
- if (u.current && u.current.isReady && R)
7704
+ if (u.current && u.current.isReady && I)
7688
7705
  k();
7689
7706
  else if (u.current && u.current.isReady) {
7690
7707
  const H = z.current || { lipsyncLang: "en" };
7691
7708
  u.current.speakText("Now let me ask you some questions to test your understanding.", { lipsyncLang: H.lipsyncLang });
7692
7709
  } else {
7693
7710
  const H = setInterval(() => {
7694
- u.current && u.current.isReady && (clearInterval(H), R && k());
7711
+ u.current && u.current.isReady && (clearInterval(H), I && k());
7695
7712
  }, 100);
7696
7713
  setTimeout(() => {
7697
7714
  clearInterval(H);
7698
7715
  }, 5e3);
7699
7716
  }
7700
- }, [e.questionStart, f, E]), Z = T(() => {
7701
- const v = f();
7717
+ }, [e.questionStart, y, E]), Z = T(() => {
7718
+ const v = y();
7702
7719
  if (a.current.currentQuestionIndex < (v?.questions?.length || 0) - 1) {
7703
7720
  u.current && u.current.stopSpeaking && u.current.stopSpeaking(), a.current.currentQuestionIndex += 1;
7704
- const R = E();
7705
- R && d.current.onCustomAction({
7721
+ const I = E();
7722
+ I && c.current.onCustomAction({
7706
7723
  type: "nextQuestion",
7707
7724
  moduleIndex: a.current.currentModuleIndex,
7708
7725
  lessonIndex: a.current.currentLessonIndex,
7709
7726
  questionIndex: a.current.currentQuestionIndex,
7710
7727
  totalQuestions: a.current.totalQuestions,
7711
- question: R,
7728
+ question: I,
7712
7729
  score: a.current.score
7713
7730
  });
7714
7731
  const k = () => {
7715
- if (!u.current || !R) return;
7732
+ if (!u.current || !I) return;
7716
7733
  if (u.current.setMood("happy"), u.current.setBodyMovement("idle"), e.nextQuestion)
7717
7734
  try {
7718
7735
  u.current.playAnimation(e.nextQuestion, !0);
7719
7736
  } catch (q) {
7720
7737
  console.warn("Failed to play nextQuestion animation:", q);
7721
7738
  }
7722
- const H = z.current || { lipsyncLang: "en" }, _ = f()?.questions?.length || 0, j = a.current.currentQuestionIndex >= _ - 1;
7723
- if (R.type === "code_test") {
7724
- 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}`;
7739
+ const H = z.current || { lipsyncLang: "en" }, _ = y()?.questions?.length || 0, j = a.current.currentQuestionIndex >= _ - 1;
7740
+ if (I.type === "code_test") {
7741
+ const q = j ? `Great! Here's your final coding challenge: ${I.question}` : `Great! Now let's move on to your next coding challenge: ${I.question}`;
7725
7742
  u.current.speakText(q, {
7726
7743
  lipsyncLang: H.lipsyncLang
7727
7744
  });
7728
- } else if (R.type === "multiple_choice") {
7729
- const q = j ? `Alright! Here's your final question: ${R.question}` : `Alright! Here's your next question: ${R.question}`;
7745
+ } else if (I.type === "multiple_choice") {
7746
+ const q = j ? `Alright! Here's your final question: ${I.question}` : `Alright! Here's your next question: ${I.question}`;
7730
7747
  u.current.speakText(q, {
7731
7748
  lipsyncLang: H.lipsyncLang
7732
7749
  });
7733
- } else if (R.type === "true_false") {
7734
- const q = j ? `Now let's try this final one: ${R.question}` : `Now let's try this one: ${R.question}`;
7750
+ } else if (I.type === "true_false") {
7751
+ const q = j ? `Now let's try this final one: ${I.question}` : `Now let's try this one: ${I.question}`;
7735
7752
  u.current.speakText(q, {
7736
7753
  lipsyncLang: H.lipsyncLang
7737
7754
  });
7738
7755
  } else {
7739
- const q = j ? `Here's your final question: ${R.question}` : `Here's the next question: ${R.question}`;
7756
+ const q = j ? `Here's your final question: ${I.question}` : `Here's the next question: ${I.question}`;
7740
7757
  u.current.speakText(q, {
7741
7758
  lipsyncLang: H.lipsyncLang
7742
7759
  });
7743
7760
  }
7744
7761
  };
7745
- if (u.current && u.current.isReady && R)
7762
+ if (u.current && u.current.isReady && I)
7746
7763
  k();
7747
- else if (R) {
7764
+ else if (I) {
7748
7765
  const H = setInterval(() => {
7749
7766
  u.current && u.current.isReady && (clearInterval(H), k());
7750
7767
  }, 100);
@@ -7753,81 +7770,81 @@ const yt = Me(({
7753
7770
  }, 5e3);
7754
7771
  }
7755
7772
  } else
7756
- d.current.onCustomAction({
7773
+ c.current.onCustomAction({
7757
7774
  type: "allQuestionsComplete",
7758
7775
  moduleIndex: a.current.currentModuleIndex,
7759
7776
  lessonIndex: a.current.currentLessonIndex,
7760
7777
  totalQuestions: a.current.totalQuestions,
7761
7778
  score: a.current.score
7762
7779
  });
7763
- }, [e.nextQuestion, f, E]), K = T(() => {
7764
- const v = M.current || { modules: [] }, R = v.modules[a.current.currentModuleIndex];
7765
- if (a.current.currentLessonIndex < (R?.lessons?.length || 0) - 1) {
7780
+ }, [e.nextQuestion, y, E]), K = T(() => {
7781
+ const v = M.current || { modules: [] }, I = v.modules[a.current.currentModuleIndex];
7782
+ if (a.current.currentLessonIndex < (I?.lessons?.length || 0) - 1) {
7766
7783
  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;
7767
- const H = v.modules[a.current.currentModuleIndex], N = a.current.currentLessonIndex < (H?.lessons?.length || 0) - 1, _ = a.current.currentModuleIndex < (v.modules?.length || 0) - 1, j = N || _;
7768
- d.current.onCustomAction({
7784
+ 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 || _;
7785
+ c.current.onCustomAction({
7769
7786
  type: "lessonStart",
7770
7787
  moduleIndex: a.current.currentModuleIndex,
7771
7788
  lessonIndex: a.current.currentLessonIndex,
7772
7789
  hasNextLesson: j
7773
- }), d.current.onLessonStart({
7790
+ }), c.current.onLessonStart({
7774
7791
  moduleIndex: a.current.currentModuleIndex,
7775
7792
  lessonIndex: a.current.currentLessonIndex,
7776
- lesson: f()
7793
+ lesson: y()
7777
7794
  }), u.current && (u.current.setMood("happy"), u.current.setBodyMovement("idle"));
7778
7795
  } else if (a.current.currentModuleIndex < (v.modules?.length || 0) - 1) {
7779
7796
  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;
7780
- const N = v.modules[a.current.currentModuleIndex], _ = a.current.currentLessonIndex < (N?.lessons?.length || 0) - 1, j = a.current.currentModuleIndex < (v.modules?.length || 0) - 1, q = _ || j;
7781
- d.current.onCustomAction({
7797
+ 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;
7798
+ c.current.onCustomAction({
7782
7799
  type: "lessonStart",
7783
7800
  moduleIndex: a.current.currentModuleIndex,
7784
7801
  lessonIndex: a.current.currentLessonIndex,
7785
7802
  hasNextLesson: q
7786
- }), d.current.onLessonStart({
7803
+ }), c.current.onLessonStart({
7787
7804
  moduleIndex: a.current.currentModuleIndex,
7788
7805
  lessonIndex: a.current.currentLessonIndex,
7789
- lesson: f()
7806
+ lesson: y()
7790
7807
  }), u.current && (u.current.setMood("happy"), u.current.setBodyMovement("idle"));
7791
7808
  } else
7792
- I.current && I.current();
7809
+ R.current && R.current();
7793
7810
  }, []), X = T(() => {
7794
- const v = f();
7795
- let R = null;
7811
+ const v = y();
7812
+ let I = null;
7796
7813
  if (v?.avatar_script && v?.body) {
7797
- const k = v.avatar_script.trim(), H = v.body.trim(), N = k.match(/[.!?]$/) ? " " : ". ";
7798
- R = `${k}${N}${H}`;
7814
+ const k = v.avatar_script.trim(), H = v.body.trim(), U = k.match(/[.!?]$/) ? " " : ". ";
7815
+ I = `${k}${U}${H}`;
7799
7816
  } else
7800
- R = v?.avatar_script || v?.body || null;
7801
- if (u.current && u.current.isReady && R) {
7817
+ I = v?.avatar_script || v?.body || null;
7818
+ if (u.current && u.current.isReady && I) {
7802
7819
  a.current.isTeaching = !0, a.current.isQuestionMode = !1, a.current.score = 0, a.current.totalQuestions = 0, u.current.setMood("happy");
7803
7820
  let k = !1;
7804
7821
  if (e.teaching)
7805
7822
  try {
7806
7823
  u.current.playAnimation(e.teaching, !0), k = !0;
7807
- } catch (N) {
7808
- console.warn("Failed to play teaching animation:", N);
7824
+ } catch (U) {
7825
+ console.warn("Failed to play teaching animation:", U);
7809
7826
  }
7810
7827
  k || u.current.setBodyMovement("gesturing");
7811
7828
  const H = z.current || { lipsyncLang: "en" };
7812
- d.current.onLessonStart({
7829
+ c.current.onLessonStart({
7813
7830
  moduleIndex: a.current.currentModuleIndex,
7814
7831
  lessonIndex: a.current.currentLessonIndex,
7815
7832
  lesson: v
7816
- }), d.current.onCustomAction({
7833
+ }), c.current.onCustomAction({
7817
7834
  type: "teachingStart",
7818
7835
  moduleIndex: a.current.currentModuleIndex,
7819
7836
  lessonIndex: a.current.currentLessonIndex,
7820
7837
  lesson: v
7821
- }), u.current.speakText(R, {
7838
+ }), u.current.speakText(I, {
7822
7839
  lipsyncLang: H.lipsyncLang,
7823
7840
  onSpeechEnd: () => {
7824
- a.current.isTeaching = !1, d.current.onCustomAction({
7841
+ a.current.isTeaching = !1, c.current.onCustomAction({
7825
7842
  type: "teachingComplete",
7826
7843
  moduleIndex: a.current.currentModuleIndex,
7827
7844
  lessonIndex: a.current.currentLessonIndex,
7828
7845
  lesson: v,
7829
7846
  hasQuestions: v.questions && v.questions.length > 0
7830
- }), v?.code_example && d.current.onCustomAction({
7847
+ }), v?.code_example && c.current.onCustomAction({
7831
7848
  type: "codeExampleReady",
7832
7849
  moduleIndex: a.current.currentModuleIndex,
7833
7850
  lessonIndex: a.current.currentLessonIndex,
@@ -7837,15 +7854,15 @@ const yt = Me(({
7837
7854
  }
7838
7855
  });
7839
7856
  }
7840
- }, [e.teaching, f]), $ = T((v) => {
7841
- const R = E(), k = P(v, R);
7842
- if (k && (a.current.score += 1), d.current.onQuestionAnswer({
7857
+ }, [e.teaching, y]), $ = T((v) => {
7858
+ const I = E(), k = P(v, I);
7859
+ if (k && (a.current.score += 1), c.current.onQuestionAnswer({
7843
7860
  moduleIndex: a.current.currentModuleIndex,
7844
7861
  lessonIndex: a.current.currentLessonIndex,
7845
7862
  questionIndex: a.current.currentQuestionIndex,
7846
7863
  answer: v,
7847
7864
  isCorrect: k,
7848
- question: R
7865
+ question: I
7849
7866
  }), u.current)
7850
7867
  if (k) {
7851
7868
  if (u.current.setMood("happy"), e.correct)
@@ -7855,15 +7872,15 @@ const yt = Me(({
7855
7872
  u.current.setBodyMovement("happy");
7856
7873
  }
7857
7874
  u.current.setBodyMovement("gesturing");
7858
- const N = f()?.questions?.length || 0;
7859
- a.current.currentQuestionIndex >= N - 1;
7860
- const _ = a.current.currentQuestionIndex < N - 1;
7861
- console.log("[CurriculumLearning] Answer feedback - questionIndex:", a.current.currentQuestionIndex, "totalQuestions:", N, "hasNextQuestion:", _);
7862
- 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" };
7875
+ const U = y()?.questions?.length || 0;
7876
+ a.current.currentQuestionIndex >= U - 1;
7877
+ const _ = a.current.currentQuestionIndex < U - 1;
7878
+ console.log("[CurriculumLearning] Answer feedback - questionIndex:", a.current.currentQuestionIndex, "totalQuestions:", U, "hasNextQuestion:", _);
7879
+ const j = I.type === "code_test" ? `Great job! Your code passed all the tests! ${I.explanation || ""}` : `Excellent! That's correct! ${I.explanation || ""}`, q = z.current || { lipsyncLang: "en" };
7863
7880
  u.current.speakText(j, {
7864
7881
  lipsyncLang: q.lipsyncLang,
7865
7882
  onSpeechEnd: () => {
7866
- d.current.onCustomAction({
7883
+ c.current.onCustomAction({
7867
7884
  type: "answerFeedbackComplete",
7868
7885
  moduleIndex: a.current.currentModuleIndex,
7869
7886
  lessonIndex: a.current.currentLessonIndex,
@@ -7883,13 +7900,13 @@ const yt = Me(({
7883
7900
  u.current.setBodyMovement("idle");
7884
7901
  }
7885
7902
  u.current.setBodyMovement("gesturing");
7886
- const N = f()?.questions?.length || 0, _ = a.current.currentQuestionIndex >= N - 1, j = a.current.currentQuestionIndex < N - 1;
7887
- console.log("[CurriculumLearning] Answer feedback (incorrect) - questionIndex:", a.current.currentQuestionIndex, "totalQuestions:", N, "hasNextQuestion:", j);
7888
- 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" };
7903
+ const U = y()?.questions?.length || 0, _ = a.current.currentQuestionIndex >= U - 1, j = a.current.currentQuestionIndex < U - 1;
7904
+ console.log("[CurriculumLearning] Answer feedback (incorrect) - questionIndex:", a.current.currentQuestionIndex, "totalQuestions:", U, "hasNextQuestion:", j);
7905
+ const q = I.type === "code_test" ? `Your code didn't pass all the tests. ${I.explanation || "Try again!"}` : `Not quite right, but don't worry! ${I.explanation || ""}${_ ? "" : " Let's move on to the next question."}`, Le = z.current || { lipsyncLang: "en" };
7889
7906
  u.current.speakText(q, {
7890
7907
  lipsyncLang: Le.lipsyncLang,
7891
7908
  onSpeechEnd: () => {
7892
- d.current.onCustomAction({
7909
+ c.current.onCustomAction({
7893
7910
  type: "answerFeedbackComplete",
7894
7911
  moduleIndex: a.current.currentModuleIndex,
7895
7912
  lessonIndex: a.current.currentLessonIndex,
@@ -7903,26 +7920,26 @@ const yt = Me(({
7903
7920
  });
7904
7921
  }
7905
7922
  else {
7906
- const N = f()?.questions?.length || 0;
7907
- d.current.onCustomAction({
7923
+ const U = y()?.questions?.length || 0;
7924
+ c.current.onCustomAction({
7908
7925
  type: "answerFeedbackComplete",
7909
7926
  moduleIndex: a.current.currentModuleIndex,
7910
7927
  lessonIndex: a.current.currentLessonIndex,
7911
7928
  questionIndex: a.current.currentQuestionIndex,
7912
7929
  isCorrect: k,
7913
- hasNextQuestion: a.current.currentQuestionIndex < N - 1,
7930
+ hasNextQuestion: a.current.currentQuestionIndex < U - 1,
7914
7931
  score: a.current.score,
7915
7932
  totalQuestions: a.current.totalQuestions,
7916
7933
  avatarNotReady: !0
7917
7934
  });
7918
7935
  }
7919
- }, [e.correct, e.incorrect, E, f, P]), se = T((v) => {
7920
- const R = E();
7936
+ }, [e.correct, e.incorrect, E, y, P]), se = T((v) => {
7937
+ const I = E();
7921
7938
  if (!v || typeof v != "object") {
7922
7939
  console.error("Invalid code test result format. Expected object with {passed: boolean, ...}");
7923
7940
  return;
7924
7941
  }
7925
- if (R?.type !== "code_test") {
7942
+ if (I?.type !== "code_test") {
7926
7943
  console.warn("Current question is not a code test. Use handleAnswerSelect for other question types.");
7927
7944
  return;
7928
7945
  }
@@ -7936,19 +7953,19 @@ const yt = Me(({
7936
7953
  passedCount: v.passedCount || 0,
7937
7954
  failedCount: v.failedCount || 0
7938
7955
  };
7939
- d.current.onCustomAction({
7956
+ c.current.onCustomAction({
7940
7957
  type: "codeTestSubmitted",
7941
7958
  moduleIndex: a.current.currentModuleIndex,
7942
7959
  lessonIndex: a.current.currentLessonIndex,
7943
7960
  questionIndex: a.current.currentQuestionIndex,
7944
7961
  testResult: k,
7945
- question: R
7962
+ question: I
7946
7963
  }), p.current && p.current(k);
7947
7964
  }, [E, P]), ae = T(() => {
7948
7965
  if (a.current.currentQuestionIndex > 0) {
7949
7966
  a.current.currentQuestionIndex -= 1;
7950
7967
  const v = E();
7951
- v && d.current.onCustomAction({
7968
+ v && c.current.onCustomAction({
7952
7969
  type: "questionStart",
7953
7970
  moduleIndex: a.current.currentModuleIndex,
7954
7971
  lessonIndex: a.current.currentLessonIndex,
@@ -7957,7 +7974,7 @@ const yt = Me(({
7957
7974
  question: v,
7958
7975
  score: a.current.score
7959
7976
  });
7960
- const R = () => {
7977
+ const I = () => {
7961
7978
  if (!u.current || !v) return;
7962
7979
  u.current.setMood("happy"), u.current.setBodyMovement("idle");
7963
7980
  const k = z.current || { lipsyncLang: "en" };
@@ -7968,10 +7985,10 @@ const yt = Me(({
7968
7985
  });
7969
7986
  };
7970
7987
  if (u.current && u.current.isReady && v)
7971
- R();
7988
+ I();
7972
7989
  else if (v) {
7973
7990
  const k = setInterval(() => {
7974
- u.current && u.current.isReady && (clearInterval(k), R());
7991
+ u.current && u.current.isReady && (clearInterval(k), I());
7975
7992
  }, 100);
7976
7993
  setTimeout(() => {
7977
7994
  clearInterval(k);
@@ -7981,38 +7998,38 @@ const yt = Me(({
7981
7998
  }, [E]), pe = T(() => {
7982
7999
  const v = M.current || { modules: [] };
7983
8000
  if (v.modules[a.current.currentModuleIndex], a.current.currentLessonIndex > 0)
7984
- a.current.currentLessonIndex -= 1, a.current.currentQuestionIndex = 0, a.current.lessonCompleted = !1, a.current.isQuestionMode = !1, a.current.isTeaching = !1, a.current.score = 0, a.current.totalQuestions = 0, d.current.onCustomAction({
8001
+ a.current.currentLessonIndex -= 1, a.current.currentQuestionIndex = 0, a.current.lessonCompleted = !1, a.current.isQuestionMode = !1, a.current.isTeaching = !1, a.current.score = 0, a.current.totalQuestions = 0, c.current.onCustomAction({
7985
8002
  type: "lessonStart",
7986
8003
  moduleIndex: a.current.currentModuleIndex,
7987
8004
  lessonIndex: a.current.currentLessonIndex
7988
- }), d.current.onLessonStart({
8005
+ }), c.current.onLessonStart({
7989
8006
  moduleIndex: a.current.currentModuleIndex,
7990
8007
  lessonIndex: a.current.currentLessonIndex,
7991
- lesson: f()
8008
+ lesson: y()
7992
8009
  }), u.current && (u.current.setMood("happy"), u.current.setBodyMovement("idle"));
7993
8010
  else if (a.current.currentModuleIndex > 0) {
7994
8011
  const H = v.modules[a.current.currentModuleIndex - 1];
7995
- a.current.currentModuleIndex -= 1, a.current.currentLessonIndex = (H?.lessons?.length || 1) - 1, a.current.currentQuestionIndex = 0, a.current.lessonCompleted = !1, a.current.isQuestionMode = !1, a.current.isTeaching = !1, a.current.score = 0, a.current.totalQuestions = 0, d.current.onCustomAction({
8012
+ a.current.currentModuleIndex -= 1, a.current.currentLessonIndex = (H?.lessons?.length || 1) - 1, a.current.currentQuestionIndex = 0, a.current.lessonCompleted = !1, a.current.isQuestionMode = !1, a.current.isTeaching = !1, a.current.score = 0, a.current.totalQuestions = 0, c.current.onCustomAction({
7996
8013
  type: "lessonStart",
7997
8014
  moduleIndex: a.current.currentModuleIndex,
7998
8015
  lessonIndex: a.current.currentLessonIndex
7999
- }), d.current.onLessonStart({
8016
+ }), c.current.onLessonStart({
8000
8017
  moduleIndex: a.current.currentModuleIndex,
8001
8018
  lessonIndex: a.current.currentLessonIndex,
8002
- lesson: f()
8019
+ lesson: y()
8003
8020
  }), u.current && (u.current.setMood("happy"), u.current.setBodyMovement("idle"));
8004
8021
  }
8005
- }, [f]), ee = T(() => {
8022
+ }, [y]), ee = T(() => {
8006
8023
  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;
8007
8024
  }, []), le = T((v) => {
8008
8025
  console.log("Avatar is ready!", v);
8009
- const R = f(), k = R?.avatar_script || R?.body;
8026
+ const I = y(), k = I?.avatar_script || I?.body;
8010
8027
  h && k && setTimeout(() => {
8011
- c.current && c.current();
8028
+ d.current && d.current();
8012
8029
  }, 10);
8013
- }, [h, f]);
8030
+ }, [h, y]);
8014
8031
  Xe(() => {
8015
- c.current = X, g.current = K, y.current = U, b.current = Z, I.current = oe, V.current = S, p.current = $;
8032
+ d.current = X, g.current = K, x.current = W, b.current = Z, R.current = oe, B.current = S, p.current = $;
8016
8033
  }), Ee(r, () => ({
8017
8034
  // Curriculum control methods
8018
8035
  startTeaching: X,
@@ -8023,29 +8040,29 @@ const yt = Me(({
8023
8040
  previousQuestion: ae,
8024
8041
  nextLesson: K,
8025
8042
  previousLesson: pe,
8026
- completeLesson: U,
8043
+ completeLesson: W,
8027
8044
  completeCurriculum: oe,
8028
8045
  resetCurriculum: ee,
8029
8046
  getState: () => ({ ...a.current }),
8030
8047
  getCurrentQuestion: () => E(),
8031
- getCurrentLesson: () => f(),
8048
+ getCurrentLesson: () => y(),
8032
8049
  // Direct access to avatar ref (always returns current value)
8033
8050
  getAvatarRef: () => u.current,
8034
8051
  // Convenience methods that delegate to avatar (always check current ref)
8035
- speakText: async (v, R = {}) => {
8052
+ speakText: async (v, I = {}) => {
8036
8053
  await u.current?.resumeAudioContext?.();
8037
8054
  const k = z.current || { lipsyncLang: "en" };
8038
- u.current?.speakText(v, { ...R, lipsyncLang: R.lipsyncLang || k.lipsyncLang });
8055
+ u.current?.speakText(v, { ...I, lipsyncLang: I.lipsyncLang || k.lipsyncLang });
8039
8056
  },
8040
8057
  resumeAudioContext: async () => {
8041
8058
  if (u.current?.resumeAudioContext)
8042
8059
  return await u.current.resumeAudioContext();
8043
8060
  const v = u.current?.talkingHead;
8044
8061
  if (v?.audioCtx) {
8045
- const R = v.audioCtx;
8046
- if (R.state === "suspended" || R.state === "interrupted")
8062
+ const I = v.audioCtx;
8063
+ if (I.state === "suspended" || I.state === "interrupted")
8047
8064
  try {
8048
- await R.resume(), console.log("Audio context resumed via talkingHead");
8065
+ await I.resume(), console.log("Audio context resumed via talkingHead");
8049
8066
  } catch (k) {
8050
8067
  console.warn("Failed to resume audio context:", k);
8051
8068
  }
@@ -8057,7 +8074,7 @@ const yt = Me(({
8057
8074
  resumeSpeaking: async () => await u.current?.resumeSpeaking(),
8058
8075
  isPaused: () => u.current && typeof u.current.isPaused < "u" ? u.current.isPaused : !1,
8059
8076
  setMood: (v) => u.current?.setMood(v),
8060
- playAnimation: (v, R) => u.current?.playAnimation(v, R),
8077
+ playAnimation: (v, I) => u.current?.playAnimation(v, I),
8061
8078
  setBodyMovement: (v) => u.current?.setBodyMovement(v),
8062
8079
  setMovementIntensity: (v) => u.current?.setMovementIntensity(v),
8063
8080
  playRandomDance: () => u.current?.playRandomDance(),
@@ -8068,10 +8085,10 @@ const yt = Me(({
8068
8085
  lockAvatarPosition: () => u.current?.lockAvatarPosition(),
8069
8086
  unlockAvatarPosition: () => u.current?.unlockAvatarPosition(),
8070
8087
  // Custom action trigger
8071
- triggerCustomAction: (v, R) => {
8072
- d.current.onCustomAction({
8088
+ triggerCustomAction: (v, I) => {
8089
+ c.current.onCustomAction({
8073
8090
  type: v,
8074
- ...R,
8091
+ ...I,
8075
8092
  state: { ...a.current }
8076
8093
  });
8077
8094
  },
@@ -8079,8 +8096,8 @@ const yt = Me(({
8079
8096
  handleResize: () => u.current?.handleResize(),
8080
8097
  // Avatar readiness check (always returns current value)
8081
8098
  isAvatarReady: () => u.current?.isReady || !1
8082
- }), [X, S, $, se, Z, K, U, oe, ee, E, f]);
8083
- const D = z.current || {
8099
+ }), [X, S, $, se, Z, K, W, oe, ee, E, y]);
8100
+ const O = z.current || {
8084
8101
  avatarUrl: "/avatars/brunette.glb",
8085
8102
  avatarBody: "F",
8086
8103
  mood: "happy",
@@ -8097,18 +8114,18 @@ const yt = Me(({
8097
8114
  Ve,
8098
8115
  {
8099
8116
  ref: u,
8100
- avatarUrl: D.avatarUrl,
8101
- avatarBody: D.avatarBody,
8102
- mood: D.mood,
8103
- ttsLang: D.ttsLang,
8104
- ttsService: D.ttsService,
8105
- ttsVoice: D.ttsVoice,
8106
- ttsApiKey: D.ttsApiKey,
8107
- bodyMovement: D.bodyMovement,
8108
- movementIntensity: D.movementIntensity,
8109
- showFullAvatar: D.showFullAvatar,
8117
+ avatarUrl: O.avatarUrl,
8118
+ avatarBody: O.avatarBody,
8119
+ mood: O.mood,
8120
+ ttsLang: O.ttsLang,
8121
+ ttsService: O.ttsService,
8122
+ ttsVoice: O.ttsVoice,
8123
+ ttsApiKey: O.ttsApiKey,
8124
+ bodyMovement: O.bodyMovement,
8125
+ movementIntensity: O.movementIntensity,
8126
+ showFullAvatar: O.showFullAvatar,
8110
8127
  cameraView: "upper",
8111
- animations: D.animations,
8128
+ animations: O.animations,
8112
8129
  onReady: le,
8113
8130
  onLoading: () => {
8114
8131
  },