@sage-rsc/talking-head-react 1.3.2 → 1.3.4

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,5 +1,5 @@
1
1
  import { jsxs as Pe, jsx as ye } from "react/jsx-runtime";
2
- import { forwardRef as Me, useRef as W, useState as pe, useEffect as ce, useCallback as N, useImperativeHandle as Fe, useLayoutEffect as Xe } from "react";
2
+ import { forwardRef as Me, useRef as W, useState as pe, useEffect as ce, useCallback as O, useImperativeHandle as Fe, useLayoutEffect as Xe } from "react";
3
3
  import * as y 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";
@@ -8,11 +8,11 @@ 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 _e from "three/addons/libs/stats.module.js";
10
10
  let m, ue, he;
11
- const C = [0, 0, 0, 0], T = new y.Vector3(), ze = new y.Vector3(), ae = new y.Vector3(), Ce = new y.Vector3();
11
+ const C = [0, 0, 0, 0], M = new y.Vector3(), ze = new y.Vector3(), ae = new y.Vector3(), Ce = new y.Vector3();
12
12
  new y.Plane();
13
13
  new y.Ray();
14
14
  new y.Euler();
15
- const re = new y.Quaternion(), Oe = new y.Quaternion(), fe = new y.Matrix4(), xe = new y.Matrix4();
15
+ const re = new y.Quaternion(), Ne = new y.Quaternion(), fe = new y.Matrix4(), xe = new y.Matrix4();
16
16
  new y.Vector3();
17
17
  const He = new y.Vector3(0, 0, 1), Ke = new y.Vector3(1, 0, 0), Je = new y.Vector3(0, 1, 0), $e = new y.Vector3(0, 0, 1);
18
18
  class et {
@@ -321,7 +321,7 @@ class et {
321
321
  /// Bone's parent object
322
322
  vBasis: r.position.clone(),
323
323
  // Original local position
324
- vWorld: r.parent.getWorldPosition(T).clone(),
324
+ vWorld: r.parent.getWorldPosition(M).clone(),
325
325
  // World position, parent
326
326
  qBasis: r.parent.quaternion.clone(),
327
327
  // Original quaternion, parent
@@ -338,7 +338,7 @@ class et {
338
338
  ea: [0, 0, 0, 0]
339
339
  // External acceleration [m/s^2]
340
340
  };
341
- u.boneParent.matrixWorld.decompose(T, re, ae), T.copy(He).applyQuaternion(re).setY(0).normalize(), re.premultiply(Oe.setFromUnitVectors(He, T).invert()).normalize(), u.qWorldInverseYaw = re.clone().normalize(), this.data.push(u), this.dict[h] = u;
341
+ u.boneParent.matrixWorld.decompose(M, re, ae), M.copy(He).applyQuaternion(re).setY(0).normalize(), re.premultiply(Ne.setFromUnitVectors(He, M).invert()).normalize(), u.qWorldInverseYaw = re.clone().normalize(), this.data.push(u), this.dict[h] = u;
342
342
  try {
343
343
  this.setValue(h, "type", s.type), this.setValue(h, "stiffness", s.stiffness), this.setValue(h, "damping", s.damping), this.setValue(h, "external", s.external), this.setValue(h, "limits", s.limits), this.setValue(h, "excludes", s.excludes), this.setValue(h, "deltaLocal", s.deltaLocal), this.setValue(h, "deltaWorld", s.deltaWorld), this.setValue(h, "pivot", s.pivot), this.setValue(h, "helper", s.helper);
344
344
  } catch (a) {
@@ -356,22 +356,22 @@ class et {
356
356
  for (this.timerMs += t, t > 1e3 && (this.timerMs = 0), t /= 1e3, e = 0, i = this.objectsUpdate.length; e < i; e++)
357
357
  o = this.objectsUpdate[e], o.updateMatrix(), o.parent === null ? o.matrixWorld.copy(o.matrix) : o.matrixWorld.multiplyMatrices(o.parent.matrixWorld, o.matrix), o.matrixWorldNeedsUpdate = !1;
358
358
  for (e = 0, i = this.data.length; e < i; e++) {
359
- if (o = this.data[e], T.copy(o.vWorld), fe.copy(o.boneParent.matrixWorld), xe.copy(fe).invert(), o.vWorld.setFromMatrixPosition(fe), T.applyMatrix4(xe), T.length() > 0.5 && (console.info("Info: Unrealistic jump of " + T.length().toFixed(2) + " meters."), T.setLength(0.5)), T.applyQuaternion(o.bone.quaternion), C[0] = T.x, C[1] = T.y, C[2] = -T.z, C[3] = T.length() / 3, o.children)
359
+ if (o = this.data[e], M.copy(o.vWorld), fe.copy(o.boneParent.matrixWorld), xe.copy(fe).invert(), o.vWorld.setFromMatrixPosition(fe), M.applyMatrix4(xe), M.length() > 0.5 && (console.info("Info: Unrealistic jump of " + M.length().toFixed(2) + " meters."), M.setLength(0.5)), M.applyQuaternion(o.bone.quaternion), C[0] = M.x, C[1] = M.y, C[2] = -M.z, C[3] = M.length() / 3, o.children)
360
360
  for (n = 0, s = o.children.length; n < s; n++)
361
361
  m = o.children[n], C[0] -= m.v[0] * t / 3, C[1] -= m.v[1] * t / 3, C[2] += m.v[2] * t / 3, C[3] -= m.v[3] * t / 3;
362
- if (m = this.opt.sensitivityFactor, C[0] *= o.ext * m, C[1] *= o.ext * m, C[2] *= o.ext * m, C[3] *= o.ext * m, o.isX && (m = C[0] / t, o.ea[0] = (m - o.ev[0]) / t, o.ev[0] = m, o.a[0] = -o.k[0] * o.p[0] - o.c[0] * o.v[0] - o.ea[0], o.p[0] += o.v[0] * t + o.a[0] * t * t / 2 + C[0], m = o.v[0] + o.a[0] * t / 2, m = -o.k[0] * o.p[0] - o.c[0] * m - o.ea[0], o.v[0] = o.v[0] + (m + o.a[0]) * t / 2), o.isY && (m = C[1] / t, o.ea[1] = (m - o.ev[1]) / t, o.ev[1] = m, o.a[1] = -o.k[1] * o.p[1] - o.c[1] * o.v[1] - o.ea[1], o.p[1] += o.v[1] * t + o.a[1] * t * t / 2 + C[1], m = o.v[1] + o.a[1] * t / 2, m = -o.k[1] * o.p[1] - o.c[1] * m - o.ea[1], o.v[1] = o.v[1] + (m + o.a[1]) * t / 2), o.isZ && (m = C[2] / t, o.ea[2] = (m - o.ev[2]) / t, o.ev[2] = m, o.a[2] = -o.k[2] * o.p[2] - o.c[2] * o.v[2] - o.ea[2], o.p[2] += o.v[2] * t + o.a[2] * t * t / 2 + C[2], m = o.v[2] + o.a[2] * t / 2, m = -o.k[2] * o.p[2] - o.c[2] * m - o.ea[2], o.v[2] = o.v[2] + (m + o.a[2]) * t / 2), o.isT && (m = C[3] / t, o.ea[3] = (m - o.ev[3]) / t, o.ev[3] = m, o.a[3] = -o.k[3] * o.p[3] - o.c[3] * o.v[3] - o.ea[3], o.p[3] += o.v[3] * t + o.a[3] * t * t / 2 + C[3], m = o.v[3] + o.a[3] * t / 2, m = -o.k[3] * o.p[3] - o.c[3] * m - o.ea[3], o.v[3] = o.v[3] + (m + o.a[3]) * t / 2), this.timerMs < this.opt.warmupMs && (o.v[0] *= 1e-4, o.p[0] *= 1e-4, o.v[1] *= 1e-4, o.p[1] *= 1e-4, o.v[2] *= 1e-4, o.p[2] *= 1e-4, o.v[3] *= 1e-4, o.p[3] *= 1e-4), C[0] = o.p[0], C[1] = o.p[1], C[2] = o.p[2], C[3] = o.p[3], m = this.opt.movementFactor, C[0] *= m, C[1] *= m, C[2] *= m, C[3] *= m, o.dl && (m = o.dl, C[0] += m[0], C[1] += m[1], C[2] += m[2]), o.dw && (m = o.dw, T.set(
362
+ if (m = this.opt.sensitivityFactor, C[0] *= o.ext * m, C[1] *= o.ext * m, C[2] *= o.ext * m, C[3] *= o.ext * m, o.isX && (m = C[0] / t, o.ea[0] = (m - o.ev[0]) / t, o.ev[0] = m, o.a[0] = -o.k[0] * o.p[0] - o.c[0] * o.v[0] - o.ea[0], o.p[0] += o.v[0] * t + o.a[0] * t * t / 2 + C[0], m = o.v[0] + o.a[0] * t / 2, m = -o.k[0] * o.p[0] - o.c[0] * m - o.ea[0], o.v[0] = o.v[0] + (m + o.a[0]) * t / 2), o.isY && (m = C[1] / t, o.ea[1] = (m - o.ev[1]) / t, o.ev[1] = m, o.a[1] = -o.k[1] * o.p[1] - o.c[1] * o.v[1] - o.ea[1], o.p[1] += o.v[1] * t + o.a[1] * t * t / 2 + C[1], m = o.v[1] + o.a[1] * t / 2, m = -o.k[1] * o.p[1] - o.c[1] * m - o.ea[1], o.v[1] = o.v[1] + (m + o.a[1]) * t / 2), o.isZ && (m = C[2] / t, o.ea[2] = (m - o.ev[2]) / t, o.ev[2] = m, o.a[2] = -o.k[2] * o.p[2] - o.c[2] * o.v[2] - o.ea[2], o.p[2] += o.v[2] * t + o.a[2] * t * t / 2 + C[2], m = o.v[2] + o.a[2] * t / 2, m = -o.k[2] * o.p[2] - o.c[2] * m - o.ea[2], o.v[2] = o.v[2] + (m + o.a[2]) * t / 2), o.isT && (m = C[3] / t, o.ea[3] = (m - o.ev[3]) / t, o.ev[3] = m, o.a[3] = -o.k[3] * o.p[3] - o.c[3] * o.v[3] - o.ea[3], o.p[3] += o.v[3] * t + o.a[3] * t * t / 2 + C[3], m = o.v[3] + o.a[3] * t / 2, m = -o.k[3] * o.p[3] - o.c[3] * m - o.ea[3], o.v[3] = o.v[3] + (m + o.a[3]) * t / 2), this.timerMs < this.opt.warmupMs && (o.v[0] *= 1e-4, o.p[0] *= 1e-4, o.v[1] *= 1e-4, o.p[1] *= 1e-4, o.v[2] *= 1e-4, o.p[2] *= 1e-4, o.v[3] *= 1e-4, o.p[3] *= 1e-4), C[0] = o.p[0], C[1] = o.p[1], C[2] = o.p[2], C[3] = o.p[3], m = this.opt.movementFactor, C[0] *= m, C[1] *= m, C[2] *= m, C[3] *= m, o.dl && (m = o.dl, C[0] += m[0], C[1] += m[1], C[2] += m[2]), o.dw && (m = o.dw, M.set(
363
363
  o.vBasis.x + C[0],
364
364
  o.vBasis.y + C[1],
365
365
  o.vBasis.z + C[2]
366
- ), T.applyMatrix4(fe), T.x += m[0], T.y += m[1], T.z += m[2], T.applyMatrix4(xe), C[0] += T.x - o.vBasis.x, C[1] += T.y - o.vBasis.y, C[2] += T.z - o.vBasis.z), o.limits && this.opt.isLimits && (m = o.limits, m[0] && (m[0][0] !== null && C[0] < m[0][0] && (C[0] = m[0][0]), m[0][1] !== null && C[0] > m[0][1] && (C[0] = m[0][1])), m[1] && (m[1][0] !== null && C[1] < m[1][0] && (C[1] = m[1][0]), m[1][1] !== null && C[1] > m[1][1] && (C[1] = m[1][1])), m[2] && (m[2][0] !== null && C[2] < m[2][0] && (C[2] = m[2][0]), m[2][1] !== null && C[2] > m[2][1] && (C[2] = m[2][1])), m[3] && (m[3][0] !== null && C[3] < m[3][0] && (C[3] = m[3][0]), m[3][1] !== null && C[3] > m[3][1] && (C[3] = m[3][1]))), o.isPoint)
366
+ ), M.applyMatrix4(fe), M.x += m[0], M.y += m[1], M.z += m[2], M.applyMatrix4(xe), C[0] += M.x - o.vBasis.x, C[1] += M.y - o.vBasis.y, C[2] += M.z - o.vBasis.z), o.limits && this.opt.isLimits && (m = o.limits, m[0] && (m[0][0] !== null && C[0] < m[0][0] && (C[0] = m[0][0]), m[0][1] !== null && C[0] > m[0][1] && (C[0] = m[0][1])), m[1] && (m[1][0] !== null && C[1] < m[1][0] && (C[1] = m[1][0]), m[1][1] !== null && C[1] > m[1][1] && (C[1] = m[1][1])), m[2] && (m[2][0] !== null && C[2] < m[2][0] && (C[2] = m[2][0]), m[2][1] !== null && C[2] > m[2][1] && (C[2] = m[2][1])), m[3] && (m[3][0] !== null && C[3] < m[3][0] && (C[3] = m[3][0]), m[3][1] !== null && C[3] > m[3][1] && (C[3] = m[3][1]))), o.isPoint)
367
367
  o.bone.position.set(
368
368
  o.vBasis.x + C[0],
369
369
  o.vBasis.y + C[1],
370
370
  o.vBasis.z - C[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(T, re, ae), T.copy(He).applyQuaternion(re).setY(0).normalize(), re.premultiply(Oe.setFromUnitVectors(He, T).invert()).normalize(), o.boneParent.quaternion.multiply(re.invert()), o.boneParent.quaternion.multiply(o.qWorldInverseYaw)), o.isZ && (m = Math.atan(C[0] / o.l), re.setFromAxisAngle($e, -m), o.boneParent.quaternion.multiply(re)), o.isY && (m = o.l / 3, m = m * Math.tanh(C[1] / m), o.bone.position.setLength(o.l + m)), o.isX && (m = Math.atan(C[2] / o.l), re.setFromAxisAngle(Ke, -m), o.boneParent.quaternion.multiply(re)), o.isT && (m = 1.5 * Math.tanh(C[3] * 1.5), re.setFromAxisAngle(Je, -m), o.boneParent.quaternion.multiply(re)), 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(M, re, ae), M.copy(He).applyQuaternion(re).setY(0).normalize(), re.premultiply(Ne.setFromUnitVectors(He, M).invert()).normalize(), o.boneParent.quaternion.multiply(re.invert()), o.boneParent.quaternion.multiply(o.qWorldInverseYaw)), o.isZ && (m = Math.atan(C[0] / o.l), re.setFromAxisAngle($e, -m), o.boneParent.quaternion.multiply(re)), o.isY && (m = o.l / 3, m = m * Math.tanh(C[1] / m), o.bone.position.setLength(o.l + m)), o.isX && (m = Math.atan(C[2] / o.l), re.setFromAxisAngle(Ke, -m), o.boneParent.quaternion.multiply(re)), o.isT && (m = 1.5 * Math.tanh(C[3] * 1.5), re.setFromAxisAngle(Je, -m), o.boneParent.quaternion.multiply(re)), o.boneParent.updateWorldMatrix(!1, !0), o.excludes && this.opt.isExcludes)
373
373
  for (n = 0, s = o.excludes.length; n < s; n++)
374
- m = o.excludes[n], ae.set(0, 0, 0), m.deltaLocal && (ae.x += m.deltaLocal[0], ae.y += m.deltaLocal[1], ae.z += m.deltaLocal[2]), ae.applyMatrix4(m.bone.matrixWorld), xe.copy(o.boneParent.matrixWorld).invert(), ae.applyMatrix4(xe), T.copy(o.bone.position), !(T.distanceToSquared(ae) >= m.radiusSq) && (he = T.length(), ue = ae.length(), !(ue > m.radius + he) && (ue < Math.abs(m.radius - he) || (ue = (ue * ue + he * he - m.radiusSq) / (2 * ue), ae.normalize(), Ce.copy(ae).multiplyScalar(ue), ue = Math.sqrt(he * he - ue * ue), T.subVectors(T, Ce).projectOnPlane(ae).normalize().multiplyScalar(ue), ze.subVectors(o.vBasis, Ce).projectOnPlane(ae).normalize(), he = ze.dot(T), he < 0 && (he = Math.sqrt(ue * ue - he * he), ze.multiplyScalar(he), T.add(ze)), T.add(Ce).normalize(), ae.copy(o.bone.position).normalize(), re.setFromUnitVectors(ae, T), o.boneParent.quaternion.premultiply(re), o.boneParent.updateWorldMatrix(!1, !0))));
374
+ m = o.excludes[n], ae.set(0, 0, 0), m.deltaLocal && (ae.x += m.deltaLocal[0], ae.y += m.deltaLocal[1], ae.z += m.deltaLocal[2]), ae.applyMatrix4(m.bone.matrixWorld), xe.copy(o.boneParent.matrixWorld).invert(), ae.applyMatrix4(xe), M.copy(o.bone.position), !(M.distanceToSquared(ae) >= m.radiusSq) && (he = M.length(), ue = ae.length(), !(ue > m.radius + he) && (ue < Math.abs(m.radius - he) || (ue = (ue * ue + he * he - m.radiusSq) / (2 * ue), ae.normalize(), Ce.copy(ae).multiplyScalar(ue), ue = Math.sqrt(he * he - ue * ue), M.subVectors(M, Ce).projectOnPlane(ae).normalize().multiplyScalar(ue), ze.subVectors(o.vBasis, Ce).projectOnPlane(ae).normalize(), he = ze.dot(M), he < 0 && (he = Math.sqrt(ue * ue - he * he), ze.multiplyScalar(he), M.add(ze)), M.add(Ce).normalize(), ae.copy(o.bone.position).normalize(), re.setFromUnitVectors(ae, M), o.boneParent.quaternion.premultiply(re), o.boneParent.updateWorldMatrix(!1, !0))));
375
375
  }
376
376
  this.helpers.isActive && this.updateHelpers();
377
377
  }
@@ -445,14 +445,14 @@ class et {
445
445
  xe.copy(this.armature.matrixWorld).invert();
446
446
  const t = m.object.geometry.getAttribute("position");
447
447
  for (let e = 0, n = m.bones.length; e < n; e++)
448
- fe.multiplyMatrices(xe, m.bones[e].matrixWorld), T.setFromMatrixPosition(fe), t.setXYZ(e, T.x, T.y, T.z);
448
+ fe.multiplyMatrices(xe, m.bones[e].matrixWorld), M.setFromMatrixPosition(fe), t.setXYZ(e, M.x, M.y, M.z);
449
449
  t.needsUpdate = !0, m.object.updateMatrixWorld();
450
450
  }
451
451
  if (m = this.helpers.lines, m.bones.length) {
452
452
  xe.copy(this.armature.matrixWorld).invert();
453
453
  const t = m.object.geometry.getAttribute("position");
454
454
  for (let e = 0, n = 0, i = m.bones.length; e < i; e++, n += 2)
455
- fe.multiplyMatrices(xe, m.bones[e].matrixWorld), T.setFromMatrixPosition(fe), t.setXYZ(n, T.x, T.y, T.z), fe.multiplyMatrices(xe, m.bones[e].parent.matrixWorld), T.setFromMatrixPosition(fe), t.setXYZ(n + 1, T.x, T.y, T.z);
455
+ fe.multiplyMatrices(xe, m.bones[e].matrixWorld), M.setFromMatrixPosition(fe), t.setXYZ(n, M.x, M.y, M.z), fe.multiplyMatrices(xe, m.bones[e].parent.matrixWorld), M.setFromMatrixPosition(fe), t.setXYZ(n + 1, M.x, M.y, M.z);
456
456
  t.needsUpdate = !0, m.object.updateMatrixWorld();
457
457
  }
458
458
  }
@@ -5264,10 +5264,10 @@ class Be {
5264
5264
  let u = "", a = "", d = 0, c = [], g = [];
5265
5265
  const x = Array.from(this.segmenter.segment(t), (f) => f.segment);
5266
5266
  for (let f = 0; f < x.length; f++) {
5267
- const k = f === x.length - 1, O = x[f].match(l);
5267
+ const k = f === x.length - 1, N = x[f].match(l);
5268
5268
  let p = x[f].match(s);
5269
5269
  const B = x[f].match(h), H = x[f].match(o);
5270
- if (p && !k && !B && x[f + 1].match(s) && (p = !1), n && (u += x[f]), O && (!i || i.every((v) => f < v[0] || f > v[1])) && (a += x[f]), (H || p || k) && (a.length && (a = this.lipsyncPreProcessText(a, r), a.length && c.push({
5270
+ if (p && !k && !B && x[f + 1].match(s) && (p = !1), n && (u += x[f]), N && (!i || i.every((R) => f < R[0] || f > R[1])) && (a += x[f]), (H || p || k) && (a.length && (a = this.lipsyncPreProcessText(a, r), a.length && c.push({
5271
5271
  mark: d,
5272
5272
  word: a
5273
5273
  })), u.length && (g.push({
@@ -5278,16 +5278,16 @@ class Be {
5278
5278
  subtitles: [u]
5279
5279
  }
5280
5280
  }), u = ""), a.length)) {
5281
- const v = this.lipsyncWordsToVisemes(a, r);
5282
- if (v && v.visemes && v.visemes.length) {
5283
- const L = v.times[v.visemes.length - 1] + v.durations[v.visemes.length - 1];
5284
- for (let I = 0; I < v.visemes.length; I++)
5281
+ const R = this.lipsyncWordsToVisemes(a, r);
5282
+ if (R && R.visemes && R.visemes.length) {
5283
+ const L = R.times[R.visemes.length - 1] + R.durations[R.visemes.length - 1];
5284
+ for (let I = 0; I < R.visemes.length; I++)
5285
5285
  g.push({
5286
5286
  mark: d,
5287
5287
  template: { name: "viseme" },
5288
- ts: [(v.times[I] - 0.6) / L, (v.times[I] + 0.5) / L, (v.times[I] + v.durations[I] + 0.5) / L],
5288
+ ts: [(R.times[I] - 0.6) / L, (R.times[I] + 0.5) / L, (R.times[I] + R.durations[I] + 0.5) / L],
5289
5289
  vs: {
5290
- ["viseme_" + v.visemes[I]]: [null, v.visemes[I] === "PP" || v.visemes[I] === "FF" ? 0.9 : 0.6, 0]
5290
+ ["viseme_" + R.visemes[I]]: [null, R.visemes[I] === "PP" || R.visemes[I] === "FF" ? 0.9 : 0.6, 0]
5291
5291
  }
5292
5292
  });
5293
5293
  }
@@ -5295,14 +5295,14 @@ class Be {
5295
5295
  }
5296
5296
  if (p || k) {
5297
5297
  if (c.length || k && g.length) {
5298
- const v = {
5298
+ const R = {
5299
5299
  anim: g
5300
5300
  };
5301
- n && (v.onSubtitles = n), c.length && !e.avatarMute && (v.text = c, e.avatarMood && (v.mood = e.avatarMood), e.ttsLang && (v.lang = e.ttsLang), e.ttsVoice && (v.voice = e.ttsVoice), e.ttsRate && (v.rate = e.ttsRate), e.ttsVoice && (v.pitch = e.ttsPitch), e.ttsVolume && (v.volume = e.ttsVolume)), this.speechQueue.push(v), c = [], a = "", d = 0, g = [];
5301
+ n && (R.onSubtitles = n), c.length && !e.avatarMute && (R.text = c, e.avatarMood && (R.mood = e.avatarMood), e.ttsLang && (R.lang = e.ttsLang), e.ttsVoice && (R.voice = e.ttsVoice), e.ttsRate && (R.rate = e.ttsRate), e.ttsVoice && (R.pitch = e.ttsPitch), e.ttsVolume && (R.volume = e.ttsVolume)), this.speechQueue.push(R), c = [], a = "", d = 0, g = [];
5302
5302
  }
5303
5303
  if (B) {
5304
- let v = this.animEmojis[x[f]];
5305
- v && v.link && (v = this.animEmojis[v.link]), v && this.speechQueue.push({ emoji: v });
5304
+ let R = this.animEmojis[x[f]];
5305
+ R && R.link && (R = this.animEmojis[R.link]), R && this.speechQueue.push({ emoji: R });
5306
5306
  }
5307
5307
  this.speechQueue.push({ break: 100 });
5308
5308
  }
@@ -5398,10 +5398,10 @@ class Be {
5398
5398
  let x = 0.6 + this.convertRange(g, [0, u], [0, 0.4]);
5399
5399
  if (u = Math.min(u, d.visemes.length * 200), c > 0)
5400
5400
  for (let f = 0; f < d.visemes.length; f++) {
5401
- const k = r + d.times[f] / c * u, O = d.durations[f] / c * u;
5401
+ const k = r + d.times[f] / c * u, N = d.durations[f] / c * u;
5402
5402
  o.push({
5403
5403
  template: { name: "viseme" },
5404
- ts: [k - Math.min(60, 2 * O / 3), k + Math.min(25, O / 2), k + O + Math.min(60, O / 2)],
5404
+ ts: [k - Math.min(60, 2 * N / 3), k + Math.min(25, N / 2), k + N + Math.min(60, N / 2)],
5405
5405
  vs: {
5406
5406
  ["viseme_" + d.visemes[f]]: [null, d.visemes[f] === "PP" || d.visemes[f] === "FF" ? 0.9 : x, 0]
5407
5407
  }
@@ -5499,7 +5499,7 @@ class Be {
5499
5499
  if (f && f.visemes && f.visemes.length > 0) {
5500
5500
  const p = f.times[f.visemes.length - 1] + f.durations[f.visemes.length - 1];
5501
5501
  for (let B = 0; B < f.visemes.length; B++) {
5502
- const H = f.visemes[B], v = f.times[B] / p, L = f.durations[B] / p, I = v * d, z = L * d;
5502
+ const H = f.visemes[B], R = f.times[B] / p, L = f.durations[B] / p, I = R * d, z = L * d;
5503
5503
  k.push({
5504
5504
  template: { name: "viseme" },
5505
5505
  ts: [I - Math.min(60, 2 * z / 3), I + Math.min(25, z / 2), I + z + Math.min(60, z / 2)],
@@ -5509,8 +5509,8 @@ class Be {
5509
5509
  });
5510
5510
  }
5511
5511
  }
5512
- const O = [...t.anim, ...k];
5513
- this.audioPlaylist.push({ anim: O, audio: c }), this.onSubtitles = t.onSubtitles || null, this.resetLips(), t.mood && this.setMood(t.mood), this.playAudio(), s.onend = () => {
5512
+ const N = [...t.anim, ...k];
5513
+ this.audioPlaylist.push({ anim: N, audio: c }), this.onSubtitles = t.onSubtitles || null, this.resetLips(), t.mood && this.setMood(t.mood), this.playAudio(), s.onend = () => {
5514
5514
  e();
5515
5515
  }, s.onerror = (p) => {
5516
5516
  console.error("Speech synthesis error:", p.error), n(p.error);
@@ -6202,17 +6202,17 @@ class Be {
6202
6202
  t === null && (t = h), e === null && (e = r), J.copy(this.armature.quaternion), J.multiply(this.poseTarget.props["Hips.quaternion"]), J.multiply(this.poseTarget.props["Spine.quaternion"]), J.multiply(this.poseTarget.props["Spine1.quaternion"]), J.multiply(this.poseTarget.props["Spine2.quaternion"]), J.multiply(this.poseTarget.props["Neck.quaternion"]), J.multiply(this.poseTarget.props["Head.quaternion"]), G.setFromQuaternion(J);
6203
6203
  let u = G.x / (40 / 24), a = G.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), x = Math.max(window.innerHeight - r, r), f = this.convertRange(e, [r - x, r + x], [-0.3, 0.6]) - u + d, k = this.convertRange(t, [h - g, h + g], [-0.8, 0.8]) - a + c;
6204
6204
  f = Math.min(0.6, Math.max(-0.3, f)), k = Math.min(0.8, Math.max(-0.8, k));
6205
- let O = (Math.random() - 0.5) / 4, p = (Math.random() - 0.5) / 4;
6205
+ let N = (Math.random() - 0.5) / 4, p = (Math.random() - 0.5) / 4;
6206
6206
  if (n) {
6207
- let B = this.animQueue.findIndex((v) => v.template.name === "lookat");
6207
+ let B = this.animQueue.findIndex((R) => R.template.name === "lookat");
6208
6208
  B !== -1 && this.animQueue.splice(B, 1);
6209
6209
  const H = {
6210
6210
  name: "lookat",
6211
6211
  dt: [750, n],
6212
6212
  vs: {
6213
- bodyRotateX: [f + O],
6213
+ bodyRotateX: [f + N],
6214
6214
  bodyRotateY: [k + p],
6215
- eyesRotateX: [-3 * O + 0.1],
6215
+ eyesRotateX: [-3 * N + 0.1],
6216
6216
  eyesRotateY: [-5 * p],
6217
6217
  browInnerUp: [[0, 0.7]],
6218
6218
  mouthLeft: [[0, 0.7]],
@@ -6523,8 +6523,8 @@ class Be {
6523
6523
  if (S.toLowerCase() === z)
6524
6524
  return S;
6525
6525
  for (const S of c) {
6526
- const F = S.toLowerCase();
6527
- if ((z.includes("left") && F.includes("left") || z.includes("right") && F.includes("right")) && (z.includes("arm") && F.includes("arm") && !F.includes("fore") || z.includes("forearm") && F.includes("forearm") || z.includes("hand") && F.includes("hand") && !F.includes("index") && !F.includes("thumb") || z.includes("shoulder") && F.includes("shoulder")))
6526
+ const E = S.toLowerCase();
6527
+ if ((z.includes("left") && E.includes("left") || z.includes("right") && E.includes("right")) && (z.includes("arm") && E.includes("arm") && !E.includes("fore") || z.includes("forearm") && E.includes("forearm") || z.includes("hand") && E.includes("hand") && !E.includes("index") && !E.includes("thumb") || z.includes("shoulder") && E.includes("shoulder")))
6528
6528
  return S;
6529
6529
  }
6530
6530
  return null;
@@ -6535,16 +6535,16 @@ class Be {
6535
6535
  }), console.log("=== Ready Player Me Animation Bone Analysis ==="), console.log("FBX bone names:", Array.from(f).sort().join(", ")), console.log("Avatar skeleton bone names:", Array.from(c).sort().join(", "));
6536
6536
  const k = Array.from(f).filter(
6537
6537
  (L) => L.toLowerCase().includes("arm") || L.toLowerCase().includes("hand") || L.toLowerCase().includes("shoulder")
6538
- ), O = Array.from(c).filter(
6538
+ ), N = Array.from(c).filter(
6539
6539
  (L) => L.includes("Arm") || L.includes("Hand") || L.includes("Shoulder")
6540
6540
  );
6541
- console.log("FBX arm/hand/shoulder bones:", k.sort().join(", ")), console.log("Avatar arm/hand/shoulder bones:", O.sort().join(", "));
6541
+ console.log("FBX arm/hand/shoulder bones:", k.sort().join(", ")), console.log("Avatar arm/hand/shoulder bones:", N.sort().join(", "));
6542
6542
  const p = [], B = /* @__PURE__ */ new Set();
6543
6543
  if (d.tracks.forEach((L) => {
6544
- const z = L.name.replaceAll("mixamorig", "").split("."), Y = z[0], S = z[1], F = x(Y);
6545
- if (F && S) {
6546
- const X = `${F}.${S}`, Z = L.clone();
6547
- Z.name = X, p.push(Z), Y !== F && g.set(Y, F);
6544
+ const z = L.name.replaceAll("mixamorig", "").split("."), Y = z[0], S = z[1], E = x(Y);
6545
+ if (E && S) {
6546
+ const X = `${E}.${S}`, Z = L.clone();
6547
+ Z.name = X, p.push(Z), Y !== E && g.set(Y, E);
6548
6548
  } else
6549
6549
  B.add(Y), (Y.toLowerCase().includes("arm") || Y.toLowerCase().includes("hand") || Y.toLowerCase().includes("shoulder")) && console.warn(`⚠️ Arm bone "${Y}" could not be mapped to avatar skeleton`);
6550
6550
  }), B.size > 0 && console.warn(`⚠️ ${B.size} bone(s) could not be mapped:`, Array.from(B).sort().join(", ")), p.length > 0) {
@@ -6568,11 +6568,11 @@ class Be {
6568
6568
  H[L.name] = new y.Vector3(L.values[0], L.values[1], L.values[2]);
6569
6569
  } else I[1] === "quaternion" ? H[L.name] = new y.Quaternion(L.values[0], L.values[1], L.values[2], L.values[3]) : I[1] === "rotation" && (H[I[0] + ".quaternion"] = new y.Quaternion().setFromEuler(new y.Euler(L.values[0], L.values[1], L.values[2], "XYZ")).normalize());
6570
6570
  });
6571
- const v = { props: H };
6572
- H["Hips.position"] && (H["Hips.position"].y < 0.5 ? v.lying = !0 : v.standing = !0), this.animClips.push({
6571
+ const R = { props: H };
6572
+ H["Hips.position"] && (H["Hips.position"].y < 0.5 ? R.lying = !0 : R.standing = !0), this.animClips.push({
6573
6573
  url: t + "-" + i,
6574
6574
  clip: d,
6575
- pose: v
6575
+ pose: R
6576
6576
  }), this.playAnimation(t, e, n, i, s);
6577
6577
  } else {
6578
6578
  const d = "Animation " + t + " (ndx=" + i + ") not found";
@@ -6707,12 +6707,12 @@ class Be {
6707
6707
  const f = t.iterations || 10;
6708
6708
  if (e)
6709
6709
  for (let k = 0; k < f; k++) {
6710
- let O = !1;
6710
+ let N = !1;
6711
6711
  for (let p = 0, B = x.length; p < B; p++) {
6712
6712
  const H = x[p].bone;
6713
6713
  H.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();
6714
- let v = s.dot(l);
6715
- v > 1 ? v = 1 : v < -1 && (v = -1), v = Math.acos(v), !(v < 1e-5) && (x[p].minAngle !== void 0 && v < x[p].minAngle && (v = x[p].minAngle), x[p].maxAngle !== void 0 && v > x[p].maxAngle && (v = x[p].maxAngle), a.crossVectors(l, s), a.normalize(), J.setFromAxisAngle(a, v), H.quaternion.multiply(J), H.rotation.setFromVector3(d.setFromEuler(H.rotation).clamp(new y.Vector3(
6714
+ let R = s.dot(l);
6715
+ R > 1 ? R = 1 : R < -1 && (R = -1), R = Math.acos(R), !(R < 1e-5) && (x[p].minAngle !== void 0 && R < x[p].minAngle && (R = x[p].minAngle), x[p].maxAngle !== void 0 && R > x[p].maxAngle && (R = x[p].maxAngle), a.crossVectors(l, s), a.normalize(), J.setFromAxisAngle(a, R), H.quaternion.multiply(J), H.rotation.setFromVector3(d.setFromEuler(H.rotation).clamp(new y.Vector3(
6716
6716
  x[p].minx !== void 0 ? x[p].minx : -1 / 0,
6717
6717
  x[p].miny !== void 0 ? x[p].miny : -1 / 0,
6718
6718
  x[p].minz !== void 0 ? x[p].minz : -1 / 0
@@ -6720,9 +6720,9 @@ class Be {
6720
6720
  x[p].maxx !== void 0 ? x[p].maxx : 1 / 0,
6721
6721
  x[p].maxy !== void 0 ? x[p].maxy : 1 / 0,
6722
6722
  x[p].maxz !== void 0 ? x[p].maxz : 1 / 0
6723
- ))), H.updateMatrixWorld(!0), O = !0);
6723
+ ))), H.updateMatrixWorld(!0), N = !0);
6724
6724
  }
6725
- if (!O) break;
6725
+ if (!N) break;
6726
6726
  }
6727
6727
  i && x.forEach((k) => {
6728
6728
  this.poseTarget.props[k.link + ".quaternion"].copy(k.bone.quaternion), this.poseTarget.props[k.link + ".quaternion"].t = this.animClock, this.poseTarget.props[k.link + ".quaternion"].d = i;
@@ -6815,7 +6815,7 @@ const Ve = Me(({
6815
6815
  style: x = {},
6816
6816
  animations: f = {}
6817
6817
  }, k) => {
6818
- const O = W(null), p = W(null), B = W(r), H = W(null), v = W(null), L = W(!1), I = W({ remainingText: null, originalText: null, options: null }), z = W([]), Y = W(0), [S, F] = pe(!0), [X, Z] = pe(null), [ne, le] = pe(!1), [ge, de] = pe(!1);
6818
+ const N = W(null), p = W(null), B = W(r), H = W(null), R = W(null), L = W(!1), I = W({ remainingText: null, originalText: null, options: null }), z = W([]), Y = W(0), [S, E] = pe(!0), [X, Z] = pe(null), [oe, le] = pe(!1), [ge, de] = pe(!1);
6819
6819
  ce(() => {
6820
6820
  L.current = ge;
6821
6821
  }, [ge]), ce(() => {
@@ -6855,16 +6855,16 @@ const Ve = Me(({
6855
6855
  showFullAvatar: r,
6856
6856
  bodyMovement: l,
6857
6857
  movementIntensity: h
6858
- }, R = {
6858
+ }, v = {
6859
6859
  ttsEndpoint: j.endpoint,
6860
6860
  ttsApikey: j.apiKey,
6861
6861
  ttsService: be,
6862
6862
  lipsyncModules: ["en"],
6863
6863
  cameraView: u
6864
- }, M = N(async () => {
6865
- if (!(!O.current || p.current))
6864
+ }, F = O(async () => {
6865
+ if (!(!N.current || p.current))
6866
6866
  try {
6867
- if (F(!0), Z(null), p.current = new Be(O.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), f && Object.keys(f).length > 0 && (p.current.customAnimations = f), await p.current.showAvatar(b, (_) => {
6867
+ if (E(!0), Z(null), p.current = new Be(N.current, v), p.current.controls && (p.current.controls.enableRotate = !1, p.current.controls.enableZoom = !1, p.current.controls.enablePan = !1, p.current.controls.enableDamping = !1), f && Object.keys(f).length > 0 && (p.current.customAnimations = f), await p.current.showAvatar(b, (_) => {
6868
6868
  if (_.lengthComputable) {
6869
6869
  const te = Math.min(100, Math.round(_.loaded / _.total * 100));
6870
6870
  d(te);
@@ -6880,7 +6880,7 @@ const Ve = Me(({
6880
6880
  } catch (_) {
6881
6881
  console.warn("Error setting full body mode on initialization:", _);
6882
6882
  }
6883
- p.current && p.current.controls && (p.current.controls.enableRotate = !1, p.current.controls.enableZoom = !1, p.current.controls.enablePan = !1, p.current.controls.enableDamping = !1, p.current.controls.update()), F(!1), le(!0), a(p.current);
6883
+ 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()), E(!1), le(!0), a(p.current);
6884
6884
  const U = () => {
6885
6885
  document.visibilityState === "visible" ? p.current?.start() : p.current?.stop();
6886
6886
  };
@@ -6888,65 +6888,65 @@ const Ve = Me(({
6888
6888
  document.removeEventListener("visibilitychange", U);
6889
6889
  };
6890
6890
  } catch (w) {
6891
- console.error("Error initializing TalkingHead:", w), Z(w.message || "Failed to initialize avatar"), F(!1), c(w);
6891
+ console.error("Error initializing TalkingHead:", w), Z(w.message || "Failed to initialize avatar"), E(!1), c(w);
6892
6892
  }
6893
6893
  }, [V, t, e, n, i, s, o, r, l, h, u]);
6894
- ce(() => (M(), () => {
6894
+ ce(() => (F(), () => {
6895
6895
  p.current && (p.current.stop(), p.current.dispose(), p.current = null);
6896
- }), [M]), ce(() => {
6897
- if (!O.current || !p.current) return;
6896
+ }), [F]), ce(() => {
6897
+ if (!N.current || !p.current) return;
6898
6898
  const w = new ResizeObserver((_) => {
6899
6899
  for (const te of _)
6900
6900
  p.current && p.current.onResize && p.current.onResize();
6901
6901
  });
6902
- w.observe(O.current);
6902
+ w.observe(N.current);
6903
6903
  const U = () => {
6904
6904
  p.current && p.current.onResize && p.current.onResize();
6905
6905
  };
6906
6906
  return window.addEventListener("resize", U), () => {
6907
6907
  w.disconnect(), window.removeEventListener("resize", U);
6908
6908
  };
6909
- }, [ne]);
6910
- const E = N(async () => {
6909
+ }, [oe]);
6910
+ const P = O(async () => {
6911
6911
  if (p.current && p.current.audioCtx)
6912
6912
  try {
6913
6913
  (p.current.audioCtx.state === "suspended" || p.current.audioCtx.state === "interrupted") && (await p.current.audioCtx.resume(), console.log("Audio context resumed"));
6914
6914
  } catch (w) {
6915
6915
  console.warn("Failed to resume audio context:", w);
6916
6916
  }
6917
- }, []), D = N(async (w, U = {}) => {
6918
- if (p.current && ne)
6917
+ }, []), D = O(async (w, U = {}) => {
6918
+ if (p.current && oe)
6919
6919
  try {
6920
- v.current && (clearInterval(v.current), v.current = null), H.current = { text: w, options: U }, I.current = { remainingText: null, originalText: null, options: null };
6920
+ R.current && (clearInterval(R.current), R.current = null), H.current = { text: w, options: U }, I.current = { remainingText: null, originalText: null, options: null };
6921
6921
  const _ = /[!\.\?\n\p{Extended_Pictographic}]/ug, te = w.split(_).map((A) => A.trim()).filter((A) => A.length > 0);
6922
- z.current = te, Y.current = 0, de(!1), L.current = !1, await E();
6922
+ z.current = te, Y.current = 0, de(!1), L.current = !1, await P();
6923
6923
  const me = {
6924
6924
  ...U,
6925
6925
  lipsyncLang: U.lipsyncLang || b.lipsyncLang || "en"
6926
6926
  };
6927
6927
  if (U.onSpeechEnd && p.current) {
6928
6928
  const A = p.current;
6929
- let P = null, K = 0;
6930
- const ie = 1200;
6931
- let se = !1;
6932
- P = setInterval(() => {
6929
+ let T = null, K = 0;
6930
+ const ne = 1200;
6931
+ let ie = !1;
6932
+ T = setInterval(() => {
6933
6933
  if (K++, L.current)
6934
6934
  return;
6935
- if (K > ie) {
6936
- if (P && (clearInterval(P), P = null, v.current = null), !se && !L.current) {
6937
- se = !0;
6935
+ if (K > ne) {
6936
+ if (T && (clearInterval(T), T = null, R.current = null), !ie && !L.current) {
6937
+ ie = !0;
6938
6938
  try {
6939
6939
  U.onSpeechEnd();
6940
- } catch (Ne) {
6941
- console.error("Error in onSpeechEnd callback (timeout):", Ne);
6940
+ } catch (Oe) {
6941
+ console.error("Error in onSpeechEnd callback (timeout):", Oe);
6942
6942
  }
6943
6943
  }
6944
6944
  return;
6945
6945
  }
6946
- const oe = !A.speechQueue || A.speechQueue.length === 0, we = !A.audioPlaylist || A.audioPlaylist.length === 0;
6947
- A && A.isSpeaking === !1 && oe && we && A.isAudioPlaying === !1 && !se && !L.current && setTimeout(() => {
6948
- if (A && !L.current && A.isSpeaking === !1 && (!A.speechQueue || A.speechQueue.length === 0) && (!A.audioPlaylist || A.audioPlaylist.length === 0) && A.isAudioPlaying === !1 && !se && !L.current) {
6949
- se = !0, P && (clearInterval(P), P = null, v.current = null);
6946
+ const se = !A.speechQueue || A.speechQueue.length === 0, we = !A.audioPlaylist || A.audioPlaylist.length === 0;
6947
+ A && A.isSpeaking === !1 && se && we && A.isAudioPlaying === !1 && !ie && !L.current && setTimeout(() => {
6948
+ if (A && !L.current && A.isSpeaking === !1 && (!A.speechQueue || A.speechQueue.length === 0) && (!A.audioPlaylist || A.audioPlaylist.length === 0) && A.isAudioPlaying === !1 && !ie && !L.current) {
6949
+ ie = !0, T && (clearInterval(T), T = null, R.current = null);
6950
6950
  try {
6951
6951
  U.onSpeechEnd();
6952
6952
  } catch (Ze) {
@@ -6954,27 +6954,27 @@ const Ve = Me(({
6954
6954
  }
6955
6955
  }
6956
6956
  }, 100);
6957
- }, 100), v.current = P;
6957
+ }, 100), R.current = T;
6958
6958
  }
6959
6959
  p.current.lipsync && Object.keys(p.current.lipsync).length > 0 ? (p.current.setSlowdownRate && p.current.setSlowdownRate(1.05), p.current.speakText(w, me)) : setTimeout(async () => {
6960
- await E(), p.current && p.current.lipsync && (p.current.setSlowdownRate && p.current.setSlowdownRate(1.05), p.current.speakText(w, me));
6960
+ await P(), p.current && p.current.lipsync && (p.current.setSlowdownRate && p.current.setSlowdownRate(1.05), p.current.speakText(w, me));
6961
6961
  }, 100);
6962
6962
  } catch (_) {
6963
6963
  console.error("Error speaking text:", _), Z(_.message || "Failed to speak text");
6964
6964
  }
6965
- }, [ne, E, b.lipsyncLang]), ee = N(() => {
6965
+ }, [oe, P, b.lipsyncLang]), ee = O(() => {
6966
6966
  p.current && (p.current.stopSpeaking(), p.current.setSlowdownRate && p.current.setSlowdownRate(1), H.current = null, de(!1));
6967
- }, []), Q = N(() => {
6967
+ }, []), Q = O(() => {
6968
6968
  if (p.current && p.current.pauseSpeaking) {
6969
6969
  const w = p.current;
6970
6970
  if (w.isSpeaking || w.audioPlaylist && w.audioPlaylist.length > 0 || w.speechQueue && w.speechQueue.length > 0) {
6971
- v.current && (clearInterval(v.current), v.current = null);
6971
+ R.current && (clearInterval(R.current), R.current = null);
6972
6972
  let _ = "";
6973
6973
  if (H.current && z.current.length > 0) {
6974
- const te = z.current.length, me = w.speechQueue ? w.speechQueue.filter((ie) => ie && ie.text && Array.isArray(ie.text) && ie.text.length > 0).length : 0, A = w.audioPlaylist && w.audioPlaylist.length > 0, P = me + (A ? 1 : 0), K = te - P;
6975
- if (P > 0 && K < te && (_ = z.current.slice(K).join(". ").trim(), !_ && me > 0 && w.speechQueue)) {
6976
- const se = w.speechQueue.filter((oe) => oe && oe.text && Array.isArray(oe.text) && oe.text.length > 0).map((oe) => oe.text.map((we) => we.word || "").filter((we) => we.length > 0).join(" ")).filter((oe) => oe.length > 0).join(" ");
6977
- se && se.trim() && (_ = se.trim());
6974
+ const te = z.current.length, me = w.speechQueue ? w.speechQueue.filter((ne) => ne && ne.text && Array.isArray(ne.text) && ne.text.length > 0).length : 0, A = w.audioPlaylist && w.audioPlaylist.length > 0, T = me + (A ? 1 : 0), K = te - T;
6975
+ if (T > 0 && K < te && (_ = z.current.slice(K).join(". ").trim(), !_ && me > 0 && w.speechQueue)) {
6976
+ const ie = w.speechQueue.filter((se) => se && se.text && Array.isArray(se.text) && se.text.length > 0).map((se) => se.text.map((we) => we.word || "").filter((we) => we.length > 0).join(" ")).filter((se) => se.length > 0).join(" ");
6977
+ ie && ie.trim() && (_ = ie.trim());
6978
6978
  }
6979
6979
  }
6980
6980
  H.current && (I.current = {
@@ -6984,7 +6984,7 @@ const Ve = Me(({
6984
6984
  }), w.speechQueue && (w.speechQueue.length = 0), p.current.pauseSpeaking(), L.current = !0, de(!0);
6985
6985
  }
6986
6986
  }
6987
- }, []), q = N(async () => {
6987
+ }, []), q = O(async () => {
6988
6988
  if (!p.current || !ge)
6989
6989
  return;
6990
6990
  let w = "", U = {};
@@ -6996,7 +6996,7 @@ const Ve = Me(({
6996
6996
  console.warn("Resume called but no paused speech found"), de(!1), L.current = !1;
6997
6997
  return;
6998
6998
  }
6999
- de(!1), L.current = !1, await E();
6999
+ de(!1), L.current = !1, await P();
7000
7000
  const _ = {
7001
7001
  ...U,
7002
7002
  lipsyncLang: U.lipsyncLang || b.lipsyncLang || "en"
@@ -7006,11 +7006,11 @@ const Ve = Me(({
7006
7006
  } catch (te) {
7007
7007
  console.error("Error resuming speech:", te), de(!1), L.current = !1;
7008
7008
  }
7009
- }, [E, ge, D, b]), Ae = N((w) => {
7009
+ }, [P, ge, D, b]), Ae = O((w) => {
7010
7010
  p.current && p.current.setMood(w);
7011
- }, []), Se = N((w) => {
7011
+ }, []), Se = O((w) => {
7012
7012
  p.current && p.current.setSlowdownRate && p.current.setSlowdownRate(w);
7013
- }, []), Le = N((w, U = !1) => {
7013
+ }, []), Le = O((w, U = !1) => {
7014
7014
  if (p.current && p.current.playAnimation) {
7015
7015
  if (f && f[w] && (w = f[w]), p.current.setShowFullAvatar)
7016
7016
  try {
@@ -7048,7 +7048,7 @@ const Ve = Me(({
7048
7048
  }
7049
7049
  }
7050
7050
  }
7051
- }, [f]), ke = N(() => {
7051
+ }, [f]), ke = O(() => {
7052
7052
  p.current && p.current.onResize && p.current.onResize();
7053
7053
  }, []);
7054
7054
  return Fe(k, () => ({
@@ -7056,11 +7056,11 @@ const Ve = Me(({
7056
7056
  stopSpeaking: ee,
7057
7057
  pauseSpeaking: Q,
7058
7058
  resumeSpeaking: q,
7059
- resumeAudioContext: E,
7059
+ resumeAudioContext: P,
7060
7060
  setMood: Ae,
7061
7061
  setTimingAdjustment: Se,
7062
7062
  playAnimation: Le,
7063
- isReady: ne,
7063
+ isReady: oe,
7064
7064
  isPaused: ge,
7065
7065
  talkingHead: p.current,
7066
7066
  handleResize: ke,
@@ -7135,7 +7135,7 @@ const Ve = Me(({
7135
7135
  /* @__PURE__ */ ye(
7136
7136
  "div",
7137
7137
  {
7138
- ref: O,
7138
+ ref: N,
7139
7139
  className: "talking-head-viewer",
7140
7140
  style: {
7141
7141
  width: "100%",
@@ -7182,7 +7182,7 @@ const pt = Me(({
7182
7182
  style: s = {},
7183
7183
  avatarConfig: o = {}
7184
7184
  }, l) => {
7185
- const h = W(null), r = W(null), [u, a] = pe(!0), [d, c] = pe(null), [g, x] = pe(!1), f = Ee(), k = o.ttsService || f.service, O = k === "browser" ? {
7185
+ const h = W(null), r = W(null), [u, a] = pe(!0), [d, c] = pe(null), [g, x] = pe(!1), f = Ee(), k = o.ttsService || f.service, N = k === "browser" ? {
7186
7186
  endpoint: "",
7187
7187
  apiKey: null,
7188
7188
  defaultVoice: "Google US English"
@@ -7198,7 +7198,7 @@ const pt = Me(({
7198
7198
  body: "F",
7199
7199
  avatarMood: "neutral",
7200
7200
  ttsLang: k === "browser" ? "en-US" : "en",
7201
- ttsVoice: o.ttsVoice || O.defaultVoice,
7201
+ ttsVoice: o.ttsVoice || N.defaultVoice,
7202
7202
  lipsyncLang: "en",
7203
7203
  // English lip-sync
7204
7204
  showFullAvatar: !0,
@@ -7207,12 +7207,12 @@ const pt = Me(({
7207
7207
  movementIntensity: 0.5,
7208
7208
  ...o
7209
7209
  }, B = {
7210
- ttsEndpoint: O.endpoint,
7211
- ttsApikey: O.apiKey,
7210
+ ttsEndpoint: N.endpoint,
7211
+ ttsApikey: N.apiKey,
7212
7212
  ttsService: k,
7213
7213
  lipsyncModules: ["en"],
7214
7214
  cameraView: "upper"
7215
- }, H = N(async () => {
7215
+ }, H = O(async () => {
7216
7216
  if (!(!h.current || r.current))
7217
7217
  try {
7218
7218
  if (a(!0), c(null), r.current = new Be(h.current, B), await r.current.showAvatar(p, (X) => {
@@ -7223,7 +7223,7 @@ const pt = Me(({
7223
7223
  }), r.current.morphs && r.current.morphs.length > 0) {
7224
7224
  const X = r.current.morphs[0].morphTargetDictionary;
7225
7225
  console.log("Available morph targets:", Object.keys(X));
7226
- const Z = Object.keys(X).filter((ne) => ne.startsWith("viseme_"));
7226
+ const Z = Object.keys(X).filter((oe) => oe.startsWith("viseme_"));
7227
7227
  console.log("Viseme morph targets found:", Z), Z.length === 0 && (console.warn("No viseme morph targets found! Lip-sync will not work properly."), console.log("Expected viseme targets: viseme_aa, viseme_E, viseme_I, viseme_O, viseme_U, viseme_PP, viseme_SS, viseme_TH, viseme_DD, viseme_FF, viseme_kk, viseme_nn, viseme_RR, viseme_CH, viseme_sil"));
7228
7228
  }
7229
7229
  if (await new Promise((X) => {
@@ -7238,11 +7238,11 @@ const pt = Me(({
7238
7238
  console.warn("Error setting full body mode on initialization:", X);
7239
7239
  }
7240
7240
  a(!1), x(!0), n(r.current);
7241
- const F = () => {
7241
+ const E = () => {
7242
7242
  document.visibilityState === "visible" ? r.current?.start() : r.current?.stop();
7243
7243
  };
7244
- return document.addEventListener("visibilitychange", F), () => {
7245
- document.removeEventListener("visibilitychange", F);
7244
+ return document.addEventListener("visibilitychange", E), () => {
7245
+ document.removeEventListener("visibilitychange", E);
7246
7246
  };
7247
7247
  } catch (S) {
7248
7248
  console.error("Error initializing TalkingHead:", S), c(S.message || "Failed to initialize avatar"), a(!1), e(S);
@@ -7251,24 +7251,24 @@ const pt = Me(({
7251
7251
  ce(() => (H(), () => {
7252
7252
  r.current && (r.current.stop(), r.current.dispose(), r.current = null);
7253
7253
  }), [H]);
7254
- const v = N((S) => {
7254
+ const R = O((S) => {
7255
7255
  if (r.current && g)
7256
7256
  try {
7257
7257
  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(() => {
7258
7258
  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");
7259
7259
  }, 500));
7260
- } catch (F) {
7261
- console.error("Error speaking text:", F), c(F.message || "Failed to speak text");
7260
+ } catch (E) {
7261
+ console.error("Error speaking text:", E), c(E.message || "Failed to speak text");
7262
7262
  }
7263
7263
  else
7264
7264
  console.warn("Avatar not ready for speaking. isReady:", g, "talkingHeadRef:", !!r.current);
7265
- }, [g, p]), L = N(() => {
7265
+ }, [g, p]), L = O(() => {
7266
7266
  r.current && (r.current.stopSpeaking(), r.current.setSlowdownRate && (r.current.setSlowdownRate(1), console.log("Reset timing to normal")));
7267
- }, []), I = N((S) => {
7267
+ }, []), I = O((S) => {
7268
7268
  r.current && r.current.setMood(S);
7269
- }, []), z = N((S) => {
7269
+ }, []), z = O((S) => {
7270
7270
  r.current && r.current.setSlowdownRate && (r.current.setSlowdownRate(S), console.log("Timing adjustment set to:", S));
7271
- }, []), Y = N((S, F = !1) => {
7271
+ }, []), Y = O((S, E = !1) => {
7272
7272
  if (r.current && r.current.playAnimation) {
7273
7273
  if (r.current.setShowFullAvatar)
7274
7274
  try {
@@ -7278,26 +7278,26 @@ const pt = Me(({
7278
7278
  }
7279
7279
  if (S.includes("."))
7280
7280
  try {
7281
- r.current.playAnimation(S, null, 10, 0, 0.01, F), console.log("Playing animation:", S);
7281
+ r.current.playAnimation(S, null, 10, 0, 0.01, E), console.log("Playing animation:", S);
7282
7282
  } catch (Z) {
7283
7283
  console.log(`Failed to play ${S}:`, Z);
7284
7284
  try {
7285
7285
  r.current.setBodyMovement("idle"), console.log("Fallback to idle animation");
7286
- } catch (ne) {
7287
- console.warn("Fallback animation also failed:", ne);
7286
+ } catch (oe) {
7287
+ console.warn("Fallback animation also failed:", oe);
7288
7288
  }
7289
7289
  }
7290
7290
  else {
7291
7291
  const Z = [".fbx", ".glb", ".gltf"];
7292
- let ne = !1;
7292
+ let oe = !1;
7293
7293
  for (const le of Z)
7294
7294
  try {
7295
- r.current.playAnimation(S + le, null, 10, 0, 0.01, F), console.log("Playing animation:", S + le), ne = !0;
7295
+ r.current.playAnimation(S + le, null, 10, 0, 0.01, E), console.log("Playing animation:", S + le), oe = !0;
7296
7296
  break;
7297
7297
  } catch {
7298
7298
  console.log(`Failed to play ${S}${le}, trying next format...`);
7299
7299
  }
7300
- if (!ne) {
7300
+ if (!oe) {
7301
7301
  console.warn("Animation system not available or animation not found:", S);
7302
7302
  try {
7303
7303
  r.current.setBodyMovement("idle"), console.log("Fallback to idle animation");
@@ -7310,7 +7310,7 @@ const pt = Me(({
7310
7310
  console.warn("Animation system not available or animation not found:", S);
7311
7311
  }, []);
7312
7312
  return Fe(l, () => ({
7313
- speakText: v,
7313
+ speakText: R,
7314
7314
  stopSpeaking: L,
7315
7315
  setMood: I,
7316
7316
  setTimingAdjustment: z,
@@ -7321,8 +7321,8 @@ const pt = Me(({
7321
7321
  if (r.current && r.current.setShowFullAvatar && r.current.setBodyMovement)
7322
7322
  try {
7323
7323
  r.current.setShowFullAvatar(!0), r.current.setBodyMovement(S), console.log("Body movement set with full body mode:", S);
7324
- } catch (F) {
7325
- console.warn("Error setting body movement:", F);
7324
+ } catch (E) {
7325
+ console.warn("Error setting body movement:", E);
7326
7326
  }
7327
7327
  },
7328
7328
  setMovementIntensity: (S) => r.current?.setMovementIntensity(S),
@@ -7338,8 +7338,8 @@ const pt = Me(({
7338
7338
  if (r.current && r.current.setShowFullAvatar && r.current.playReaction)
7339
7339
  try {
7340
7340
  r.current.setShowFullAvatar(!0), r.current.playReaction(S), console.log("Reaction played with full body mode:", S);
7341
- } catch (F) {
7342
- console.warn("Error playing reaction:", F);
7341
+ } catch (E) {
7342
+ console.warn("Error playing reaction:", E);
7343
7343
  }
7344
7344
  },
7345
7345
  playCelebration: () => {
@@ -7354,8 +7354,8 @@ const pt = Me(({
7354
7354
  if (r.current && r.current.setShowFullAvatar)
7355
7355
  try {
7356
7356
  r.current.setShowFullAvatar(S), console.log("Show full avatar set to:", S);
7357
- } catch (F) {
7358
- console.warn("Error setting showFullAvatar:", F);
7357
+ } catch (E) {
7358
+ console.warn("Error setting showFullAvatar:", E);
7359
7359
  }
7360
7360
  },
7361
7361
  lockAvatarPosition: () => {
@@ -7441,29 +7441,32 @@ const yt = Me(({
7441
7441
  },
7442
7442
  className: f = "",
7443
7443
  style: k = {},
7444
- animations: O = {},
7444
+ animations: N = {},
7445
7445
  autoAnimationGroup: p = null,
7446
7446
  // e.g., "talking" - will randomly select from this group when speaking
7447
7447
  autoIdleGroup: B = null,
7448
7448
  // e.g., "idle" - will randomly select from this group when idle
7449
7449
  autoSpeak: H = !1
7450
- }, v) => {
7451
- const L = W(null), I = W(null), z = W(u), Y = W(null), S = W(null), F = W(!1), X = W({ remainingText: null, originalText: null, options: null }), Z = W([]), [ne, le] = pe(!0), [ge, de] = pe(null), [$, be] = pe(!1), [j, b] = pe(!1), [R, M] = pe(O), E = W(null);
7450
+ }, R) => {
7451
+ const L = W(null), I = W(null), z = W(u), Y = W(null), S = W(null), E = W(!1), X = W({ remainingText: null, originalText: null, options: null }), Z = W([]), [oe, le] = pe(!0), [ge, de] = pe(null), [$, be] = pe(!1), [j, b] = pe(!1), [v, F] = pe(N), P = W(null);
7452
7452
  ce(() => {
7453
- F.current = j;
7453
+ E.current = j;
7454
7454
  }, [j]), ce(() => {
7455
7455
  (async () => {
7456
- if (O.manifest)
7456
+ if (N.manifest)
7457
7457
  try {
7458
- const P = await gt(O.manifest);
7459
- M(P), console.log("Loaded animations from manifest:", P);
7460
- } catch (P) {
7461
- console.error("Failed to load animation manifest:", P), M(O);
7458
+ const T = await gt(N.manifest);
7459
+ F(T), console.log("Loaded animations from manifest:", T), T._genderSpecific && console.log("Gender-specific animations detected:", {
7460
+ male: Object.keys(T._genderSpecific.male || {}),
7461
+ female: Object.keys(T._genderSpecific.female || {})
7462
+ });
7463
+ } catch (T) {
7464
+ console.error("Failed to load animation manifest:", T), F(N);
7462
7465
  }
7463
7466
  else
7464
- M(O);
7467
+ F(N);
7465
7468
  })();
7466
- }, [O]), ce(() => {
7469
+ }, [N]), ce(() => {
7467
7470
  z.current = u;
7468
7471
  }, [u]);
7469
7472
  const D = Ee(), ee = s || D.service;
@@ -7505,16 +7508,16 @@ const yt = Me(({
7505
7508
  ttsService: ee,
7506
7509
  lipsyncModules: ["en"],
7507
7510
  cameraView: a
7508
- }, Se = N(async () => {
7511
+ }, Se = O(async () => {
7509
7512
  if (!(!L.current || I.current))
7510
7513
  try {
7511
7514
  le(!0), de(null), I.current = new Be(L.current, Ae), console.log("Avatar config being passed:", {
7512
7515
  url: q.url,
7513
7516
  body: q.body,
7514
7517
  avatarMood: q.avatarMood
7515
- }), await I.current.showAvatar(q, (P) => {
7516
- if (P.lengthComputable) {
7517
- const K = Math.min(100, Math.round(P.loaded / P.total * 100));
7518
+ }), await I.current.showAvatar(q, (T) => {
7519
+ if (T.lengthComputable) {
7520
+ const K = Math.min(100, Math.round(T.loaded / T.total * 100));
7518
7521
  c(K);
7519
7522
  }
7520
7523
  }), I.current?.avatar && console.log("Avatar body after initialization:", I.current.avatar.body), le(!1), be(!0), d(I.current);
@@ -7531,7 +7534,7 @@ const yt = Me(({
7531
7534
  ce(() => (Se(), () => {
7532
7535
  I.current && (I.current.stop(), I.current.dispose(), I.current = null);
7533
7536
  }), [Se]);
7534
- const Le = N(async () => {
7537
+ const Le = O(async () => {
7535
7538
  if (I.current)
7536
7539
  try {
7537
7540
  const A = I.current.audioCtx || I.current.audioContext;
@@ -7539,25 +7542,29 @@ const yt = Me(({
7539
7542
  } catch (A) {
7540
7543
  console.warn("Failed to resume audio context:", A);
7541
7544
  }
7542
- }, []), ke = N((A) => {
7543
- if (!R || !R[A])
7545
+ }, []), ke = O((A) => {
7546
+ if (!v || !v[A])
7544
7547
  return null;
7545
- const P = R[A];
7546
- if (Array.isArray(P) && P.length > 0) {
7547
- const K = Math.floor(Math.random() * P.length);
7548
- return P[K];
7548
+ let T = v[A];
7549
+ if (v._genderSpecific) {
7550
+ const ne = (e?.toUpperCase() || "F") === "M" ? "male" : "female", ie = v._genderSpecific[ne];
7551
+ ie && ie[A] ? (T = ie[A], console.log(`Using ${ne} animations for "${A}"`)) : v._genderSpecific.shared && v._genderSpecific.shared[A] && (T = v._genderSpecific.shared[A], console.log(`Using shared animations for "${A}"`));
7552
+ }
7553
+ if (Array.isArray(T) && T.length > 0) {
7554
+ const K = Math.floor(Math.random() * T.length);
7555
+ return T[K];
7549
7556
  }
7550
- return typeof P == "string" ? P : null;
7551
- }, [R]), w = N((A, P = !1) => {
7557
+ return typeof T == "string" ? T : null;
7558
+ }, [v, e]), w = O((A, T = !1) => {
7552
7559
  const K = ke(A);
7553
7560
  if (K && I.current)
7554
7561
  try {
7555
- return I.current.playAnimation(K, null, 10, 0, 0.01, P), console.log(`Playing random animation from "${A}" group:`, K), K;
7556
- } catch (ie) {
7557
- return console.warn(`Failed to play random animation from "${A}" group:`, ie), null;
7562
+ return I.current.playAnimation(K, null, 10, 0, 0.01, T), console.log(`Playing random animation from "${A}" group:`, K), K;
7563
+ } catch (ne) {
7564
+ return console.warn(`Failed to play random animation from "${A}" group:`, ne), null;
7558
7565
  }
7559
7566
  return null;
7560
- }, [ke]), U = N(async (A, P = {}) => {
7567
+ }, [ke]), U = O(async (A, T = {}) => {
7561
7568
  if (!I.current || !$) {
7562
7569
  console.warn("Avatar not ready for speaking");
7563
7570
  return;
@@ -7567,66 +7574,66 @@ const yt = Me(({
7567
7574
  return;
7568
7575
  }
7569
7576
  await Le();
7570
- const K = P.animationGroup || p;
7571
- K && !P.skipAnimation && w(K), X.current = { remainingText: null, originalText: null, options: null }, Z.current = [], Y.current = { text: A, options: P }, S.current && (clearInterval(S.current), S.current = null), b(!1), F.current = !1;
7572
- const ie = A.split(/[.!?]+/).filter((oe) => oe.trim().length > 0);
7573
- Z.current = ie;
7574
- const se = {
7575
- lipsyncLang: P.lipsyncLang || "en",
7577
+ const K = T.animationGroup || p;
7578
+ K && !T.skipAnimation && w(K), X.current = { remainingText: null, originalText: null, options: null }, Z.current = [], Y.current = { text: A, options: T }, S.current && (clearInterval(S.current), S.current = null), b(!1), E.current = !1;
7579
+ const ne = A.split(/[.!?]+/).filter((se) => se.trim().length > 0);
7580
+ Z.current = ne;
7581
+ const ie = {
7582
+ lipsyncLang: T.lipsyncLang || "en",
7576
7583
  onSpeechEnd: () => {
7577
- S.current && (clearInterval(S.current), S.current = null), P.onSpeechEnd && P.onSpeechEnd(), x();
7584
+ S.current && (clearInterval(S.current), S.current = null), T.onSpeechEnd && T.onSpeechEnd(), x();
7578
7585
  }
7579
7586
  };
7580
7587
  try {
7581
- I.current.speakText(A, se);
7582
- } catch (oe) {
7583
- console.error("Error speaking text:", oe), de(oe.message || "Failed to speak text");
7588
+ I.current.speakText(A, ie);
7589
+ } catch (se) {
7590
+ console.error("Error speaking text:", se), de(se.message || "Failed to speak text");
7584
7591
  }
7585
7592
  }, [$, x, Le, p, w]);
7586
7593
  ce(() => {
7587
7594
  if (!$ || !B || !I.current)
7588
7595
  return;
7589
- E.current && clearInterval(E.current);
7596
+ P.current && clearInterval(P.current);
7590
7597
  const A = () => {
7591
- I.current && !F.current && w(B);
7598
+ I.current && !E.current && w(B);
7592
7599
  };
7593
- return A(), E.current = setInterval(() => {
7600
+ return A(), P.current = setInterval(() => {
7594
7601
  A();
7595
7602
  }, 12e3 + Math.random() * 3e3), () => {
7596
- E.current && (clearInterval(E.current), E.current = null);
7603
+ P.current && (clearInterval(P.current), P.current = null);
7597
7604
  };
7598
7605
  }, [$, B, w]), ce(() => {
7599
7606
  $ && V && H && I.current && U(V);
7600
7607
  }, [$, V, H, U]);
7601
- const _ = N(() => {
7608
+ const _ = O(() => {
7602
7609
  if (I.current)
7603
7610
  try {
7604
- const A = I.current.isSpeaking || !1, P = I.current.audioPlaylist || [], K = I.current.speechQueue || [];
7605
- if (A || P.length > 0 || K.length > 0) {
7611
+ const A = I.current.isSpeaking || !1, T = I.current.audioPlaylist || [], K = I.current.speechQueue || [];
7612
+ if (A || T.length > 0 || K.length > 0) {
7606
7613
  S.current && (clearInterval(S.current), S.current = null);
7607
- let ie = "";
7608
- K.length > 0 && (ie = K.map((se) => se.text && Array.isArray(se.text) ? se.text.map((oe) => oe.word).join(" ") : se.text || "").join(" ")), X.current = {
7609
- remainingText: ie || null,
7614
+ let ne = "";
7615
+ K.length > 0 && (ne = K.map((ie) => ie.text && Array.isArray(ie.text) ? ie.text.map((se) => se.word).join(" ") : ie.text || "").join(" ")), X.current = {
7616
+ remainingText: ne || null,
7610
7617
  originalText: Y.current?.text || null,
7611
7618
  options: Y.current?.options || null
7612
- }, I.current.speechQueue.length = 0, I.current.pauseSpeaking(), b(!0), F.current = !0;
7619
+ }, I.current.speechQueue.length = 0, I.current.pauseSpeaking(), b(!0), E.current = !0;
7613
7620
  }
7614
7621
  } catch (A) {
7615
7622
  console.warn("Error pausing speech:", A);
7616
7623
  }
7617
- }, []), te = N(async () => {
7624
+ }, []), te = O(async () => {
7618
7625
  if (!(!I.current || !j))
7619
7626
  try {
7620
- await Le(), b(!1), F.current = !1;
7621
- const A = X.current?.remainingText, P = X.current?.originalText || Y.current?.text, K = X.current?.options || Y.current?.options || {}, ie = A || P;
7622
- ie && U(ie, K);
7627
+ await Le(), b(!1), E.current = !1;
7628
+ const A = X.current?.remainingText, T = X.current?.originalText || Y.current?.text, K = X.current?.options || Y.current?.options || {}, ne = A || T;
7629
+ ne && U(ne, K);
7623
7630
  } catch (A) {
7624
- console.warn("Error resuming speech:", A), b(!1), F.current = !1;
7631
+ console.warn("Error resuming speech:", A), b(!1), E.current = !1;
7625
7632
  }
7626
- }, [j, U, Le]), me = N(() => {
7627
- I.current && (I.current.stopSpeaking(), S.current && (clearInterval(S.current), S.current = null), b(!1), F.current = !1);
7633
+ }, [j, U, Le]), me = O(() => {
7634
+ I.current && (I.current.stopSpeaking(), S.current && (clearInterval(S.current), S.current = null), b(!1), E.current = !1);
7628
7635
  }, []);
7629
- return Fe(v, () => ({
7636
+ return Fe(R, () => ({
7630
7637
  speakText: U,
7631
7638
  pauseSpeaking: _,
7632
7639
  resumeSpeaking: te,
@@ -7637,10 +7644,10 @@ const yt = Me(({
7637
7644
  setBodyMovement: (A) => {
7638
7645
  I.current && I.current.setBodyMovement(A);
7639
7646
  },
7640
- playAnimation: (A, P = !1) => {
7641
- I.current && I.current.playAnimation && I.current.playAnimation(A, null, 10, 0, 0.01, P);
7647
+ playAnimation: (A, T = !1) => {
7648
+ I.current && I.current.playAnimation && I.current.playAnimation(A, null, 10, 0, 0.01, T);
7642
7649
  },
7643
- playRandomAnimation: (A, P = !1) => w(A, P),
7650
+ playRandomAnimation: (A, T = !1) => w(A, T),
7644
7651
  getRandomAnimation: (A) => ke(A),
7645
7652
  playReaction: (A) => I.current?.playReaction(A),
7646
7653
  playCelebration: () => I.current?.playCelebration(),
@@ -7662,7 +7669,7 @@ const yt = Me(({
7662
7669
  }
7663
7670
  }
7664
7671
  ),
7665
- ne && /* @__PURE__ */ ye("div", { className: "loading-overlay", style: {
7672
+ oe && /* @__PURE__ */ ye("div", { className: "loading-overlay", style: {
7666
7673
  position: "absolute",
7667
7674
  top: "50%",
7668
7675
  left: "50%",
@@ -7718,7 +7725,7 @@ const ft = Me(({
7718
7725
  onQuestionAnswer: s,
7719
7726
  onCurriculumComplete: o,
7720
7727
  onCustomAction: l
7721
- }), c = W(null), g = W(null), x = W(null), f = W(null), k = W(null), O = W(null), p = W(null), B = W(V?.curriculum || {
7728
+ }), c = W(null), g = W(null), x = W(null), f = W(null), k = W(null), N = W(null), p = W(null), B = W(V?.curriculum || {
7722
7729
  title: "Default Curriculum",
7723
7730
  description: "No curriculum data provided",
7724
7731
  language: "en",
@@ -7766,11 +7773,11 @@ const ft = Me(({
7766
7773
  lipsyncLang: "en"
7767
7774
  };
7768
7775
  }, [V, t, e]);
7769
- const v = N(() => (B.current || { modules: [] }).modules[a.current.currentModuleIndex]?.lessons[a.current.currentLessonIndex], []), L = N(() => v()?.questions[a.current.currentQuestionIndex], [v]), I = N((b, R) => R.type === "multiple_choice" || R.type === "true_false" ? b === R.answer : R.type === "code_test" && typeof b == "object" && b !== null ? b.passed === !0 : !1, []), z = N(() => {
7776
+ const R = O(() => (B.current || { modules: [] }).modules[a.current.currentModuleIndex]?.lessons[a.current.currentLessonIndex], []), L = O(() => R()?.questions[a.current.currentQuestionIndex], [R]), I = O((b, v) => v.type === "multiple_choice" || v.type === "true_false" ? b === v.answer : v.type === "code_test" && typeof b == "object" && b !== null ? b.passed === !0 : !1, []), z = O(() => {
7770
7777
  a.current.lessonCompleted = !0, a.current.isQuestionMode = !1;
7771
7778
  const b = a.current.totalQuestions > 0 ? Math.round(a.current.score / a.current.totalQuestions * 100) : 100;
7772
- let R = "Congratulations! You've completed this lesson";
7773
- 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 ${b} percent. ` : R += "! ", b >= 80 ? R += "Excellent work! You have a great understanding of this topic." : b >= 60 ? R += "Good job! You understand most of the concepts." : R += "Keep practicing! You're making progress.", d.current.onLessonComplete({
7779
+ let v = "Congratulations! You've completed this lesson";
7780
+ if (a.current.totalQuestions > 0 ? v += ` You got ${a.current.score} correct out of ${a.current.totalQuestions} question${a.current.totalQuestions === 1 ? "" : "s"}, achieving a score of ${b} percent. ` : v += "! ", b >= 80 ? v += "Excellent work! You have a great understanding of this topic." : b >= 60 ? v += "Good job! You understand most of the concepts." : v += "Keep practicing! You're making progress.", d.current.onLessonComplete({
7774
7781
  moduleIndex: a.current.currentModuleIndex,
7775
7782
  lessonIndex: a.current.currentLessonIndex,
7776
7783
  score: a.current.score,
@@ -7790,8 +7797,8 @@ const ft = Me(({
7790
7797
  } catch {
7791
7798
  u.current.playCelebration();
7792
7799
  }
7793
- const M = B.current || { modules: [] }, E = M.modules[a.current.currentModuleIndex], D = a.current.currentLessonIndex < (E?.lessons?.length || 0) - 1, ee = a.current.currentModuleIndex < (M.modules?.length || 0) - 1, Q = D || ee, q = H.current || { lipsyncLang: "en" };
7794
- u.current.speakText(R, {
7800
+ const F = B.current || { modules: [] }, P = F.modules[a.current.currentModuleIndex], D = a.current.currentLessonIndex < (P?.lessons?.length || 0) - 1, ee = a.current.currentModuleIndex < (F.modules?.length || 0) - 1, Q = D || ee, q = H.current || { lipsyncLang: "en" };
7801
+ u.current.speakText(v, {
7795
7802
  lipsyncLang: q.lipsyncLang,
7796
7803
  onSpeechEnd: () => {
7797
7804
  d.current.onCustomAction({
@@ -7806,12 +7813,12 @@ const ft = Me(({
7806
7813
  }
7807
7814
  });
7808
7815
  }
7809
- }, [e.lessonComplete]), Y = N(() => {
7816
+ }, [e.lessonComplete]), Y = O(() => {
7810
7817
  a.current.curriculumCompleted = !0;
7811
7818
  const b = B.current || { modules: [] };
7812
7819
  if (d.current.onCurriculumComplete({
7813
7820
  modules: b.modules.length,
7814
- totalLessons: b.modules.reduce((R, M) => R + M.lessons.length, 0)
7821
+ totalLessons: b.modules.reduce((v, F) => v + F.lessons.length, 0)
7815
7822
  }), u.current) {
7816
7823
  if (u.current.setMood("celebrating"), e.curriculumComplete)
7817
7824
  try {
@@ -7819,99 +7826,99 @@ const ft = Me(({
7819
7826
  } catch {
7820
7827
  u.current.playCelebration();
7821
7828
  }
7822
- const R = H.current || { lipsyncLang: "en" };
7823
- 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 });
7829
+ const v = H.current || { lipsyncLang: "en" };
7830
+ u.current.speakText("Amazing! You've completed the entire curriculum! You're now ready to move on to more advanced topics. Well done!", { lipsyncLang: v.lipsyncLang });
7824
7831
  }
7825
- }, [e.curriculumComplete]), S = N(() => {
7826
- const b = v();
7832
+ }, [e.curriculumComplete]), S = O(() => {
7833
+ const b = R();
7827
7834
  a.current.isQuestionMode = !0, a.current.currentQuestionIndex = 0, a.current.totalQuestions = b?.questions?.length || 0, a.current.score = 0;
7828
- const R = L();
7829
- R && d.current.onCustomAction({
7835
+ const v = L();
7836
+ v && d.current.onCustomAction({
7830
7837
  type: "questionStart",
7831
7838
  moduleIndex: a.current.currentModuleIndex,
7832
7839
  lessonIndex: a.current.currentLessonIndex,
7833
7840
  questionIndex: a.current.currentQuestionIndex,
7834
7841
  totalQuestions: a.current.totalQuestions,
7835
- question: R,
7842
+ question: v,
7836
7843
  score: a.current.score
7837
7844
  });
7838
- const M = () => {
7839
- if (!u.current || !R) return;
7845
+ const F = () => {
7846
+ if (!u.current || !v) return;
7840
7847
  if (u.current.setMood("happy"), e.questionStart)
7841
7848
  try {
7842
7849
  u.current.playAnimation(e.questionStart, !0);
7843
7850
  } catch (D) {
7844
7851
  console.warn("Failed to play questionStart animation:", D);
7845
7852
  }
7846
- const E = H.current || { lipsyncLang: "en" };
7847
- R.type === "code_test" ? u.current.speakText(`Let's test your coding skills! Here's your first challenge: ${R.question}`, { lipsyncLang: E.lipsyncLang }) : R.type === "multiple_choice" ? u.current.speakText(`Now let me ask you some questions. Here's the first one: ${R.question}`, { lipsyncLang: E.lipsyncLang }) : R.type === "true_false" ? u.current.speakText(`Let's start with some true or false questions. First question: ${R.question}`, { lipsyncLang: E.lipsyncLang }) : u.current.speakText(`Now let me ask you some questions. Here's the first one: ${R.question}`, { lipsyncLang: E.lipsyncLang });
7853
+ const P = H.current || { lipsyncLang: "en" };
7854
+ v.type === "code_test" ? u.current.speakText(`Let's test your coding skills! Here's your first challenge: ${v.question}`, { lipsyncLang: P.lipsyncLang }) : v.type === "multiple_choice" ? u.current.speakText(`Now let me ask you some questions. Here's the first one: ${v.question}`, { lipsyncLang: P.lipsyncLang }) : v.type === "true_false" ? u.current.speakText(`Let's start with some true or false questions. First question: ${v.question}`, { lipsyncLang: P.lipsyncLang }) : u.current.speakText(`Now let me ask you some questions. Here's the first one: ${v.question}`, { lipsyncLang: P.lipsyncLang });
7848
7855
  };
7849
- if (u.current && u.current.isReady && R)
7850
- M();
7856
+ if (u.current && u.current.isReady && v)
7857
+ F();
7851
7858
  else if (u.current && u.current.isReady) {
7852
- const E = H.current || { lipsyncLang: "en" };
7853
- u.current.speakText("Now let me ask you some questions to test your understanding.", { lipsyncLang: E.lipsyncLang });
7859
+ const P = H.current || { lipsyncLang: "en" };
7860
+ u.current.speakText("Now let me ask you some questions to test your understanding.", { lipsyncLang: P.lipsyncLang });
7854
7861
  } else {
7855
- const E = setInterval(() => {
7856
- u.current && u.current.isReady && (clearInterval(E), R && M());
7862
+ const P = setInterval(() => {
7863
+ u.current && u.current.isReady && (clearInterval(P), v && F());
7857
7864
  }, 100);
7858
7865
  setTimeout(() => {
7859
- clearInterval(E);
7866
+ clearInterval(P);
7860
7867
  }, 5e3);
7861
7868
  }
7862
- }, [e.questionStart, v, L]), F = N(() => {
7863
- const b = v();
7869
+ }, [e.questionStart, R, L]), E = O(() => {
7870
+ const b = R();
7864
7871
  if (a.current.currentQuestionIndex < (b?.questions?.length || 0) - 1) {
7865
7872
  u.current && u.current.stopSpeaking && u.current.stopSpeaking(), a.current.currentQuestionIndex += 1;
7866
- const R = L();
7867
- R && d.current.onCustomAction({
7873
+ const v = L();
7874
+ v && d.current.onCustomAction({
7868
7875
  type: "nextQuestion",
7869
7876
  moduleIndex: a.current.currentModuleIndex,
7870
7877
  lessonIndex: a.current.currentLessonIndex,
7871
7878
  questionIndex: a.current.currentQuestionIndex,
7872
7879
  totalQuestions: a.current.totalQuestions,
7873
- question: R,
7880
+ question: v,
7874
7881
  score: a.current.score
7875
7882
  });
7876
- const M = () => {
7877
- if (!u.current || !R) return;
7883
+ const F = () => {
7884
+ if (!u.current || !v) return;
7878
7885
  if (u.current.setMood("happy"), u.current.setBodyMovement("idle"), e.nextQuestion)
7879
7886
  try {
7880
7887
  u.current.playAnimation(e.nextQuestion, !0);
7881
7888
  } catch (q) {
7882
7889
  console.warn("Failed to play nextQuestion animation:", q);
7883
7890
  }
7884
- const E = H.current || { lipsyncLang: "en" }, ee = v()?.questions?.length || 0, Q = a.current.currentQuestionIndex >= ee - 1;
7885
- if (R.type === "code_test") {
7886
- const q = Q ? `Great! Here's your final coding challenge: ${R.question}` : `Great! Now let's move on to your next coding challenge: ${R.question}`;
7891
+ const P = H.current || { lipsyncLang: "en" }, ee = R()?.questions?.length || 0, Q = a.current.currentQuestionIndex >= ee - 1;
7892
+ if (v.type === "code_test") {
7893
+ const q = Q ? `Great! Here's your final coding challenge: ${v.question}` : `Great! Now let's move on to your next coding challenge: ${v.question}`;
7887
7894
  u.current.speakText(q, {
7888
- lipsyncLang: E.lipsyncLang
7895
+ lipsyncLang: P.lipsyncLang
7889
7896
  });
7890
- } else if (R.type === "multiple_choice") {
7891
- const q = Q ? `Alright! Here's your final question: ${R.question}` : `Alright! Here's your next question: ${R.question}`;
7897
+ } else if (v.type === "multiple_choice") {
7898
+ const q = Q ? `Alright! Here's your final question: ${v.question}` : `Alright! Here's your next question: ${v.question}`;
7892
7899
  u.current.speakText(q, {
7893
- lipsyncLang: E.lipsyncLang
7900
+ lipsyncLang: P.lipsyncLang
7894
7901
  });
7895
- } else if (R.type === "true_false") {
7896
- const q = Q ? `Now let's try this final one: ${R.question}` : `Now let's try this one: ${R.question}`;
7902
+ } else if (v.type === "true_false") {
7903
+ const q = Q ? `Now let's try this final one: ${v.question}` : `Now let's try this one: ${v.question}`;
7897
7904
  u.current.speakText(q, {
7898
- lipsyncLang: E.lipsyncLang
7905
+ lipsyncLang: P.lipsyncLang
7899
7906
  });
7900
7907
  } else {
7901
- const q = Q ? `Here's your final question: ${R.question}` : `Here's the next question: ${R.question}`;
7908
+ const q = Q ? `Here's your final question: ${v.question}` : `Here's the next question: ${v.question}`;
7902
7909
  u.current.speakText(q, {
7903
- lipsyncLang: E.lipsyncLang
7910
+ lipsyncLang: P.lipsyncLang
7904
7911
  });
7905
7912
  }
7906
7913
  };
7907
- if (u.current && u.current.isReady && R)
7908
- M();
7909
- else if (R) {
7910
- const E = setInterval(() => {
7911
- u.current && u.current.isReady && (clearInterval(E), M());
7914
+ if (u.current && u.current.isReady && v)
7915
+ F();
7916
+ else if (v) {
7917
+ const P = setInterval(() => {
7918
+ u.current && u.current.isReady && (clearInterval(P), F());
7912
7919
  }, 100);
7913
7920
  setTimeout(() => {
7914
- clearInterval(E);
7921
+ clearInterval(P);
7915
7922
  }, 5e3);
7916
7923
  }
7917
7924
  } else
@@ -7922,11 +7929,11 @@ const ft = Me(({
7922
7929
  totalQuestions: a.current.totalQuestions,
7923
7930
  score: a.current.score
7924
7931
  });
7925
- }, [e.nextQuestion, v, L]), X = N(() => {
7926
- const b = B.current || { modules: [] }, R = b.modules[a.current.currentModuleIndex];
7927
- if (a.current.currentLessonIndex < (R?.lessons?.length || 0) - 1) {
7932
+ }, [e.nextQuestion, R, L]), X = O(() => {
7933
+ const b = B.current || { modules: [] }, v = b.modules[a.current.currentModuleIndex];
7934
+ if (a.current.currentLessonIndex < (v?.lessons?.length || 0) - 1) {
7928
7935
  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;
7929
- const E = b.modules[a.current.currentModuleIndex], D = a.current.currentLessonIndex < (E?.lessons?.length || 0) - 1, ee = a.current.currentModuleIndex < (b.modules?.length || 0) - 1, Q = D || ee;
7936
+ const P = b.modules[a.current.currentModuleIndex], D = a.current.currentLessonIndex < (P?.lessons?.length || 0) - 1, ee = a.current.currentModuleIndex < (b.modules?.length || 0) - 1, Q = D || ee;
7930
7937
  d.current.onCustomAction({
7931
7938
  type: "lessonStart",
7932
7939
  moduleIndex: a.current.currentModuleIndex,
@@ -7935,7 +7942,7 @@ const ft = Me(({
7935
7942
  }), d.current.onLessonStart({
7936
7943
  moduleIndex: a.current.currentModuleIndex,
7937
7944
  lessonIndex: a.current.currentLessonIndex,
7938
- lesson: v()
7945
+ lesson: R()
7939
7946
  }), u.current && (u.current.setMood("happy"), u.current.setBodyMovement("idle"));
7940
7947
  } else if (a.current.currentModuleIndex < (b.modules?.length || 0) - 1) {
7941
7948
  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;
@@ -7948,29 +7955,29 @@ const ft = Me(({
7948
7955
  }), d.current.onLessonStart({
7949
7956
  moduleIndex: a.current.currentModuleIndex,
7950
7957
  lessonIndex: a.current.currentLessonIndex,
7951
- lesson: v()
7958
+ lesson: R()
7952
7959
  }), u.current && (u.current.setMood("happy"), u.current.setBodyMovement("idle"));
7953
7960
  } else
7954
7961
  k.current && k.current();
7955
- }, []), Z = N(() => {
7956
- const b = v();
7957
- let R = null;
7962
+ }, []), Z = O(() => {
7963
+ const b = R();
7964
+ let v = null;
7958
7965
  if (b?.avatar_script && b?.body) {
7959
- const M = b.avatar_script.trim(), E = b.body.trim(), D = M.match(/[.!?]$/) ? " " : ". ";
7960
- R = `${M}${D}${E}`;
7966
+ const F = b.avatar_script.trim(), P = b.body.trim(), D = F.match(/[.!?]$/) ? " " : ". ";
7967
+ v = `${F}${D}${P}`;
7961
7968
  } else
7962
- R = b?.avatar_script || b?.body || null;
7963
- if (u.current && u.current.isReady && R) {
7969
+ v = b?.avatar_script || b?.body || null;
7970
+ if (u.current && u.current.isReady && v) {
7964
7971
  a.current.isTeaching = !0, a.current.isQuestionMode = !1, a.current.score = 0, a.current.totalQuestions = 0, u.current.setMood("happy");
7965
- let M = !1;
7972
+ let F = !1;
7966
7973
  if (e.teaching)
7967
7974
  try {
7968
- u.current.playAnimation(e.teaching, !0), M = !0;
7975
+ u.current.playAnimation(e.teaching, !0), F = !0;
7969
7976
  } catch (D) {
7970
7977
  console.warn("Failed to play teaching animation:", D);
7971
7978
  }
7972
- M || u.current.setBodyMovement("gesturing");
7973
- const E = H.current || { lipsyncLang: "en" };
7979
+ F || u.current.setBodyMovement("gesturing");
7980
+ const P = H.current || { lipsyncLang: "en" };
7974
7981
  d.current.onLessonStart({
7975
7982
  moduleIndex: a.current.currentModuleIndex,
7976
7983
  lessonIndex: a.current.currentLessonIndex,
@@ -7980,8 +7987,8 @@ const ft = Me(({
7980
7987
  moduleIndex: a.current.currentModuleIndex,
7981
7988
  lessonIndex: a.current.currentLessonIndex,
7982
7989
  lesson: b
7983
- }), u.current.speakText(R, {
7984
- lipsyncLang: E.lipsyncLang,
7990
+ }), u.current.speakText(v, {
7991
+ lipsyncLang: P.lipsyncLang,
7985
7992
  onSpeechEnd: () => {
7986
7993
  a.current.isTeaching = !1, d.current.onCustomAction({
7987
7994
  type: "teachingComplete",
@@ -7999,17 +8006,17 @@ const ft = Me(({
7999
8006
  }
8000
8007
  });
8001
8008
  }
8002
- }, [e.teaching, v]), ne = N((b) => {
8003
- const R = L(), M = I(b, R);
8004
- if (M && (a.current.score += 1), d.current.onQuestionAnswer({
8009
+ }, [e.teaching, R]), oe = O((b) => {
8010
+ const v = L(), F = I(b, v);
8011
+ if (F && (a.current.score += 1), d.current.onQuestionAnswer({
8005
8012
  moduleIndex: a.current.currentModuleIndex,
8006
8013
  lessonIndex: a.current.currentLessonIndex,
8007
8014
  questionIndex: a.current.currentQuestionIndex,
8008
8015
  answer: b,
8009
- isCorrect: M,
8010
- question: R
8016
+ isCorrect: F,
8017
+ question: v
8011
8018
  }), u.current)
8012
- if (M) {
8019
+ if (F) {
8013
8020
  if (u.current.setMood("happy"), e.correct)
8014
8021
  try {
8015
8022
  u.current.playReaction("happy");
@@ -8017,11 +8024,11 @@ const ft = Me(({
8017
8024
  u.current.setBodyMovement("happy");
8018
8025
  }
8019
8026
  u.current.setBodyMovement("gesturing");
8020
- const D = v()?.questions?.length || 0;
8027
+ const D = R()?.questions?.length || 0;
8021
8028
  a.current.currentQuestionIndex >= D - 1;
8022
8029
  const ee = a.current.currentQuestionIndex < D - 1;
8023
8030
  console.log("[CurriculumLearning] Answer feedback - questionIndex:", a.current.currentQuestionIndex, "totalQuestions:", D, "hasNextQuestion:", ee);
8024
- const Q = R.type === "code_test" ? `Great job! Your code passed all the tests! ${R.explanation || ""}` : `Excellent! That's correct! ${R.explanation || ""}`, q = H.current || { lipsyncLang: "en" };
8031
+ const Q = v.type === "code_test" ? `Great job! Your code passed all the tests! ${v.explanation || ""}` : `Excellent! That's correct! ${v.explanation || ""}`, q = H.current || { lipsyncLang: "en" };
8025
8032
  u.current.speakText(Q, {
8026
8033
  lipsyncLang: q.lipsyncLang,
8027
8034
  onSpeechEnd: () => {
@@ -8045,9 +8052,9 @@ const ft = Me(({
8045
8052
  u.current.setBodyMovement("idle");
8046
8053
  }
8047
8054
  u.current.setBodyMovement("gesturing");
8048
- const D = v()?.questions?.length || 0, ee = a.current.currentQuestionIndex >= D - 1, Q = a.current.currentQuestionIndex < D - 1;
8055
+ const D = R()?.questions?.length || 0, ee = a.current.currentQuestionIndex >= D - 1, Q = a.current.currentQuestionIndex < D - 1;
8049
8056
  console.log("[CurriculumLearning] Answer feedback (incorrect) - questionIndex:", a.current.currentQuestionIndex, "totalQuestions:", D, "hasNextQuestion:", Q);
8050
- 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 || ""}${ee ? "" : " Let's move on to the next question."}`, Ae = H.current || { lipsyncLang: "en" };
8057
+ const q = v.type === "code_test" ? `Your code didn't pass all the tests. ${v.explanation || "Try again!"}` : `Not quite right, but don't worry! ${v.explanation || ""}${ee ? "" : " Let's move on to the next question."}`, Ae = H.current || { lipsyncLang: "en" };
8051
8058
  u.current.speakText(q, {
8052
8059
  lipsyncLang: Ae.lipsyncLang,
8053
8060
  onSpeechEnd: () => {
@@ -8065,30 +8072,30 @@ const ft = Me(({
8065
8072
  });
8066
8073
  }
8067
8074
  else {
8068
- const D = v()?.questions?.length || 0;
8075
+ const D = R()?.questions?.length || 0;
8069
8076
  d.current.onCustomAction({
8070
8077
  type: "answerFeedbackComplete",
8071
8078
  moduleIndex: a.current.currentModuleIndex,
8072
8079
  lessonIndex: a.current.currentLessonIndex,
8073
8080
  questionIndex: a.current.currentQuestionIndex,
8074
- isCorrect: M,
8081
+ isCorrect: F,
8075
8082
  hasNextQuestion: a.current.currentQuestionIndex < D - 1,
8076
8083
  score: a.current.score,
8077
8084
  totalQuestions: a.current.totalQuestions,
8078
8085
  avatarNotReady: !0
8079
8086
  });
8080
8087
  }
8081
- }, [e.correct, e.incorrect, L, v, I]), le = N((b) => {
8082
- const R = L();
8088
+ }, [e.correct, e.incorrect, L, R, I]), le = O((b) => {
8089
+ const v = L();
8083
8090
  if (!b || typeof b != "object") {
8084
8091
  console.error("Invalid code test result format. Expected object with {passed: boolean, ...}");
8085
8092
  return;
8086
8093
  }
8087
- if (R?.type !== "code_test") {
8094
+ if (v?.type !== "code_test") {
8088
8095
  console.warn("Current question is not a code test. Use handleAnswerSelect for other question types.");
8089
8096
  return;
8090
8097
  }
8091
- const M = {
8098
+ const F = {
8092
8099
  passed: b.passed === !0,
8093
8100
  results: b.results || [],
8094
8101
  output: b.output || "",
@@ -8103,10 +8110,10 @@ const ft = Me(({
8103
8110
  moduleIndex: a.current.currentModuleIndex,
8104
8111
  lessonIndex: a.current.currentLessonIndex,
8105
8112
  questionIndex: a.current.currentQuestionIndex,
8106
- testResult: M,
8107
- question: R
8108
- }), p.current && p.current(M);
8109
- }, [L, I]), ge = N(() => {
8113
+ testResult: F,
8114
+ question: v
8115
+ }), p.current && p.current(F);
8116
+ }, [L, I]), ge = O(() => {
8110
8117
  if (a.current.currentQuestionIndex > 0) {
8111
8118
  a.current.currentQuestionIndex -= 1;
8112
8119
  const b = L();
@@ -8119,28 +8126,28 @@ const ft = Me(({
8119
8126
  question: b,
8120
8127
  score: a.current.score
8121
8128
  });
8122
- const R = () => {
8129
+ const v = () => {
8123
8130
  if (!u.current || !b) return;
8124
8131
  u.current.setMood("happy"), u.current.setBodyMovement("idle");
8125
- const M = H.current || { lipsyncLang: "en" };
8132
+ const F = H.current || { lipsyncLang: "en" };
8126
8133
  b.type === "code_test" ? u.current.speakText(`Let's go back to this coding challenge: ${b.question}`, {
8127
- lipsyncLang: M.lipsyncLang
8134
+ lipsyncLang: F.lipsyncLang
8128
8135
  }) : u.current.speakText(`Going back to: ${b.question}`, {
8129
- lipsyncLang: M.lipsyncLang
8136
+ lipsyncLang: F.lipsyncLang
8130
8137
  });
8131
8138
  };
8132
8139
  if (u.current && u.current.isReady && b)
8133
- R();
8140
+ v();
8134
8141
  else if (b) {
8135
- const M = setInterval(() => {
8136
- u.current && u.current.isReady && (clearInterval(M), R());
8142
+ const F = setInterval(() => {
8143
+ u.current && u.current.isReady && (clearInterval(F), v());
8137
8144
  }, 100);
8138
8145
  setTimeout(() => {
8139
- clearInterval(M);
8146
+ clearInterval(F);
8140
8147
  }, 5e3);
8141
8148
  }
8142
8149
  }
8143
- }, [L]), de = N(() => {
8150
+ }, [L]), de = O(() => {
8144
8151
  const b = B.current || { modules: [] };
8145
8152
  if (b.modules[a.current.currentModuleIndex], a.current.currentLessonIndex > 0)
8146
8153
  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({
@@ -8150,38 +8157,38 @@ const ft = Me(({
8150
8157
  }), d.current.onLessonStart({
8151
8158
  moduleIndex: a.current.currentModuleIndex,
8152
8159
  lessonIndex: a.current.currentLessonIndex,
8153
- lesson: v()
8160
+ lesson: R()
8154
8161
  }), u.current && (u.current.setMood("happy"), u.current.setBodyMovement("idle"));
8155
8162
  else if (a.current.currentModuleIndex > 0) {
8156
- const E = b.modules[a.current.currentModuleIndex - 1];
8157
- a.current.currentModuleIndex -= 1, a.current.currentLessonIndex = (E?.lessons?.length || 1) - 1, a.current.currentQuestionIndex = 0, a.current.lessonCompleted = !1, a.current.isQuestionMode = !1, a.current.isTeaching = !1, a.current.score = 0, a.current.totalQuestions = 0, d.current.onCustomAction({
8163
+ const P = b.modules[a.current.currentModuleIndex - 1];
8164
+ a.current.currentModuleIndex -= 1, a.current.currentLessonIndex = (P?.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({
8158
8165
  type: "lessonStart",
8159
8166
  moduleIndex: a.current.currentModuleIndex,
8160
8167
  lessonIndex: a.current.currentLessonIndex
8161
8168
  }), d.current.onLessonStart({
8162
8169
  moduleIndex: a.current.currentModuleIndex,
8163
8170
  lessonIndex: a.current.currentLessonIndex,
8164
- lesson: v()
8171
+ lesson: R()
8165
8172
  }), u.current && (u.current.setMood("happy"), u.current.setBodyMovement("idle"));
8166
8173
  }
8167
- }, [v]), $ = N(() => {
8174
+ }, [R]), $ = O(() => {
8168
8175
  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;
8169
- }, []), be = N((b) => {
8176
+ }, []), be = O((b) => {
8170
8177
  console.log("Avatar is ready!", b);
8171
- const R = v(), M = R?.avatar_script || R?.body;
8172
- h && M && setTimeout(() => {
8178
+ const v = R(), F = v?.avatar_script || v?.body;
8179
+ h && F && setTimeout(() => {
8173
8180
  c.current && c.current();
8174
8181
  }, 10);
8175
- }, [h, v]);
8182
+ }, [h, R]);
8176
8183
  Xe(() => {
8177
- c.current = Z, g.current = X, x.current = z, f.current = F, k.current = Y, O.current = S, p.current = ne;
8184
+ c.current = Z, g.current = X, x.current = z, f.current = E, k.current = Y, N.current = S, p.current = oe;
8178
8185
  }), Fe(r, () => ({
8179
8186
  // Curriculum control methods
8180
8187
  startTeaching: Z,
8181
8188
  startQuestions: S,
8182
- handleAnswerSelect: ne,
8189
+ handleAnswerSelect: oe,
8183
8190
  handleCodeTestResult: le,
8184
- nextQuestion: F,
8191
+ nextQuestion: E,
8185
8192
  previousQuestion: ge,
8186
8193
  nextLesson: X,
8187
8194
  previousLesson: de,
@@ -8190,26 +8197,26 @@ const ft = Me(({
8190
8197
  resetCurriculum: $,
8191
8198
  getState: () => ({ ...a.current }),
8192
8199
  getCurrentQuestion: () => L(),
8193
- getCurrentLesson: () => v(),
8200
+ getCurrentLesson: () => R(),
8194
8201
  // Direct access to avatar ref (always returns current value)
8195
8202
  getAvatarRef: () => u.current,
8196
8203
  // Convenience methods that delegate to avatar (always check current ref)
8197
- speakText: async (b, R = {}) => {
8204
+ speakText: async (b, v = {}) => {
8198
8205
  await u.current?.resumeAudioContext?.();
8199
- const M = H.current || { lipsyncLang: "en" };
8200
- u.current?.speakText(b, { ...R, lipsyncLang: R.lipsyncLang || M.lipsyncLang });
8206
+ const F = H.current || { lipsyncLang: "en" };
8207
+ u.current?.speakText(b, { ...v, lipsyncLang: v.lipsyncLang || F.lipsyncLang });
8201
8208
  },
8202
8209
  resumeAudioContext: async () => {
8203
8210
  if (u.current?.resumeAudioContext)
8204
8211
  return await u.current.resumeAudioContext();
8205
8212
  const b = u.current?.talkingHead;
8206
8213
  if (b?.audioCtx) {
8207
- const R = b.audioCtx;
8208
- if (R.state === "suspended" || R.state === "interrupted")
8214
+ const v = b.audioCtx;
8215
+ if (v.state === "suspended" || v.state === "interrupted")
8209
8216
  try {
8210
- await R.resume(), console.log("Audio context resumed via talkingHead");
8211
- } catch (M) {
8212
- console.warn("Failed to resume audio context:", M);
8217
+ await v.resume(), console.log("Audio context resumed via talkingHead");
8218
+ } catch (F) {
8219
+ console.warn("Failed to resume audio context:", F);
8213
8220
  }
8214
8221
  } else
8215
8222
  console.warn("Audio context not available yet");
@@ -8219,7 +8226,7 @@ const ft = Me(({
8219
8226
  resumeSpeaking: async () => await u.current?.resumeSpeaking(),
8220
8227
  isPaused: () => u.current && typeof u.current.isPaused < "u" ? u.current.isPaused : !1,
8221
8228
  setMood: (b) => u.current?.setMood(b),
8222
- playAnimation: (b, R) => u.current?.playAnimation(b, R),
8229
+ playAnimation: (b, v) => u.current?.playAnimation(b, v),
8223
8230
  setBodyMovement: (b) => u.current?.setBodyMovement(b),
8224
8231
  setMovementIntensity: (b) => u.current?.setMovementIntensity(b),
8225
8232
  playRandomDance: () => u.current?.playRandomDance(),
@@ -8230,10 +8237,10 @@ const ft = Me(({
8230
8237
  lockAvatarPosition: () => u.current?.lockAvatarPosition(),
8231
8238
  unlockAvatarPosition: () => u.current?.unlockAvatarPosition(),
8232
8239
  // Custom action trigger
8233
- triggerCustomAction: (b, R) => {
8240
+ triggerCustomAction: (b, v) => {
8234
8241
  d.current.onCustomAction({
8235
8242
  type: b,
8236
- ...R,
8243
+ ...v,
8237
8244
  state: { ...a.current }
8238
8245
  });
8239
8246
  },
@@ -8241,7 +8248,7 @@ const ft = Me(({
8241
8248
  handleResize: () => u.current?.handleResize(),
8242
8249
  // Avatar readiness check (always returns current value)
8243
8250
  isAvatarReady: () => u.current?.isReady || !1
8244
- }), [Z, S, ne, le, F, X, z, Y, $, L, v]);
8251
+ }), [Z, S, oe, le, E, X, z, Y, $, L, R]);
8245
8252
  const j = H.current || {
8246
8253
  avatarUrl: "/avatars/brunette.glb",
8247
8254
  avatarBody: "F",