@sage-rsc/talking-head-react 1.1.9 → 1.2.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.cjs +2 -2
- package/dist/index.js +415 -417
- package/package.json +1 -1
- package/src/lib/talkinghead.mjs +31 -16
package/dist/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { jsxs as Pe, jsx as pe } from "react/jsx-runtime";
|
|
2
|
-
import { forwardRef as Me, useRef as
|
|
2
|
+
import { forwardRef as Me, useRef as V, useState as de, useEffect as me, useCallback as O, useImperativeHandle as Fe, useLayoutEffect as Xe } from "react";
|
|
3
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";
|
|
@@ -7,8 +7,8 @@ import { DRACOLoader as Qe } from "three/addons/loaders/DRACOLoader.js";
|
|
|
7
7
|
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
|
-
let m,
|
|
11
|
-
const w = [0, 0, 0, 0],
|
|
10
|
+
let m, le, ue;
|
|
11
|
+
const w = [0, 0, 0, 0], M = new f.Vector3(), ze = new f.Vector3(), ae = new f.Vector3(), Ce = new f.Vector3();
|
|
12
12
|
new f.Plane();
|
|
13
13
|
new f.Ray();
|
|
14
14
|
new f.Euler();
|
|
@@ -321,7 +321,7 @@ class et {
|
|
|
321
321
|
/// Bone's parent object
|
|
322
322
|
vBasis: r.position.clone(),
|
|
323
323
|
// Original local position
|
|
324
|
-
vWorld: r.parent.getWorldPosition(
|
|
324
|
+
vWorld: r.parent.getWorldPosition(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(
|
|
341
|
+
u.boneParent.matrixWorld.decompose(M, re, ae), M.copy(He).applyQuaternion(re).setY(0).normalize(), re.premultiply(Oe.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],
|
|
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), w[0] = M.x, w[1] = M.y, w[2] = -M.z, w[3] = M.length() / 3, o.children)
|
|
360
360
|
for (n = 0, s = o.children.length; n < s; n++)
|
|
361
361
|
m = o.children[n], w[0] -= m.v[0] * t / 3, w[1] -= m.v[1] * t / 3, w[2] += m.v[2] * t / 3, w[3] -= m.v[3] * t / 3;
|
|
362
|
-
if (m = this.opt.sensitivityFactor, w[0] *= o.ext * m, w[1] *= o.ext * m, w[2] *= o.ext * m, w[3] *= o.ext * m, o.isX && (m = w[0] / t, o.ea[0] = (m - o.ev[0]) / t, o.ev[0] = m, o.a[0] = -o.k[0] * o.p[0] - o.c[0] * o.v[0] - o.ea[0], o.p[0] += o.v[0] * t + o.a[0] * t * t / 2 + w[0], m = o.v[0] + o.a[0] * t / 2, m = -o.k[0] * o.p[0] - o.c[0] * m - o.ea[0], o.v[0] = o.v[0] + (m + o.a[0]) * t / 2), o.isY && (m = w[1] / t, o.ea[1] = (m - o.ev[1]) / t, o.ev[1] = m, o.a[1] = -o.k[1] * o.p[1] - o.c[1] * o.v[1] - o.ea[1], o.p[1] += o.v[1] * t + o.a[1] * t * t / 2 + w[1], m = o.v[1] + o.a[1] * t / 2, m = -o.k[1] * o.p[1] - o.c[1] * m - o.ea[1], o.v[1] = o.v[1] + (m + o.a[1]) * t / 2), o.isZ && (m = w[2] / t, o.ea[2] = (m - o.ev[2]) / t, o.ev[2] = m, o.a[2] = -o.k[2] * o.p[2] - o.c[2] * o.v[2] - o.ea[2], o.p[2] += o.v[2] * t + o.a[2] * t * t / 2 + w[2], m = o.v[2] + o.a[2] * t / 2, m = -o.k[2] * o.p[2] - o.c[2] * m - o.ea[2], o.v[2] = o.v[2] + (m + o.a[2]) * t / 2), o.isT && (m = w[3] / t, o.ea[3] = (m - o.ev[3]) / t, o.ev[3] = m, o.a[3] = -o.k[3] * o.p[3] - o.c[3] * o.v[3] - o.ea[3], o.p[3] += o.v[3] * t + o.a[3] * t * t / 2 + w[3], m = o.v[3] + o.a[3] * t / 2, m = -o.k[3] * o.p[3] - o.c[3] * m - o.ea[3], o.v[3] = o.v[3] + (m + o.a[3]) * t / 2), this.timerMs < this.opt.warmupMs && (o.v[0] *= 1e-4, o.p[0] *= 1e-4, o.v[1] *= 1e-4, o.p[1] *= 1e-4, o.v[2] *= 1e-4, o.p[2] *= 1e-4, o.v[3] *= 1e-4, o.p[3] *= 1e-4), w[0] = o.p[0], w[1] = o.p[1], w[2] = o.p[2], w[3] = o.p[3], m = this.opt.movementFactor, w[0] *= m, w[1] *= m, w[2] *= m, w[3] *= m, o.dl && (m = o.dl, w[0] += m[0], w[1] += m[1], w[2] += m[2]), o.dw && (m = o.dw,
|
|
362
|
+
if (m = this.opt.sensitivityFactor, w[0] *= o.ext * m, w[1] *= o.ext * m, w[2] *= o.ext * m, w[3] *= o.ext * m, o.isX && (m = w[0] / t, o.ea[0] = (m - o.ev[0]) / t, o.ev[0] = m, o.a[0] = -o.k[0] * o.p[0] - o.c[0] * o.v[0] - o.ea[0], o.p[0] += o.v[0] * t + o.a[0] * t * t / 2 + w[0], m = o.v[0] + o.a[0] * t / 2, m = -o.k[0] * o.p[0] - o.c[0] * m - o.ea[0], o.v[0] = o.v[0] + (m + o.a[0]) * t / 2), o.isY && (m = w[1] / t, o.ea[1] = (m - o.ev[1]) / t, o.ev[1] = m, o.a[1] = -o.k[1] * o.p[1] - o.c[1] * o.v[1] - o.ea[1], o.p[1] += o.v[1] * t + o.a[1] * t * t / 2 + w[1], m = o.v[1] + o.a[1] * t / 2, m = -o.k[1] * o.p[1] - o.c[1] * m - o.ea[1], o.v[1] = o.v[1] + (m + o.a[1]) * t / 2), o.isZ && (m = w[2] / t, o.ea[2] = (m - o.ev[2]) / t, o.ev[2] = m, o.a[2] = -o.k[2] * o.p[2] - o.c[2] * o.v[2] - o.ea[2], o.p[2] += o.v[2] * t + o.a[2] * t * t / 2 + w[2], m = o.v[2] + o.a[2] * t / 2, m = -o.k[2] * o.p[2] - o.c[2] * m - o.ea[2], o.v[2] = o.v[2] + (m + o.a[2]) * t / 2), o.isT && (m = w[3] / t, o.ea[3] = (m - o.ev[3]) / t, o.ev[3] = m, o.a[3] = -o.k[3] * o.p[3] - o.c[3] * o.v[3] - o.ea[3], o.p[3] += o.v[3] * t + o.a[3] * t * t / 2 + w[3], m = o.v[3] + o.a[3] * t / 2, m = -o.k[3] * o.p[3] - o.c[3] * m - o.ea[3], o.v[3] = o.v[3] + (m + o.a[3]) * t / 2), this.timerMs < this.opt.warmupMs && (o.v[0] *= 1e-4, o.p[0] *= 1e-4, o.v[1] *= 1e-4, o.p[1] *= 1e-4, o.v[2] *= 1e-4, o.p[2] *= 1e-4, o.v[3] *= 1e-4, o.p[3] *= 1e-4), w[0] = o.p[0], w[1] = o.p[1], w[2] = o.p[2], w[3] = o.p[3], m = this.opt.movementFactor, w[0] *= m, w[1] *= m, w[2] *= m, w[3] *= m, o.dl && (m = o.dl, w[0] += m[0], w[1] += m[1], w[2] += m[2]), o.dw && (m = o.dw, M.set(
|
|
363
363
|
o.vBasis.x + w[0],
|
|
364
364
|
o.vBasis.y + w[1],
|
|
365
365
|
o.vBasis.z + w[2]
|
|
366
|
-
),
|
|
366
|
+
), M.applyMatrix4(fe), M.x += m[0], M.y += m[1], M.z += m[2], M.applyMatrix4(xe), w[0] += M.x - o.vBasis.x, w[1] += M.y - o.vBasis.y, w[2] += M.z - o.vBasis.z), o.limits && this.opt.isLimits && (m = o.limits, m[0] && (m[0][0] !== null && w[0] < m[0][0] && (w[0] = m[0][0]), m[0][1] !== null && w[0] > m[0][1] && (w[0] = m[0][1])), m[1] && (m[1][0] !== null && w[1] < m[1][0] && (w[1] = m[1][0]), m[1][1] !== null && w[1] > m[1][1] && (w[1] = m[1][1])), m[2] && (m[2][0] !== null && w[2] < m[2][0] && (w[2] = m[2][0]), m[2][1] !== null && w[2] > m[2][1] && (w[2] = m[2][1])), m[3] && (m[3][0] !== null && w[3] < m[3][0] && (w[3] = m[3][0]), m[3][1] !== null && w[3] > m[3][1] && (w[3] = m[3][1]))), o.isPoint)
|
|
367
367
|
o.bone.position.set(
|
|
368
368
|
o.vBasis.x + w[0],
|
|
369
369
|
o.vBasis.y + w[1],
|
|
370
370
|
o.vBasis.z - w[2]
|
|
371
371
|
);
|
|
372
|
-
else if (o.boneParent.quaternion.copy(o.qBasis), o.pivot && this.opt.isPivots && (o.boneParent.updateWorldMatrix(!1, !1), o.boneParent.matrixWorld.decompose(
|
|
372
|
+
else if (o.boneParent.quaternion.copy(o.qBasis), o.pivot && this.opt.isPivots && (o.boneParent.updateWorldMatrix(!1, !1), o.boneParent.matrixWorld.decompose(M, re, ae), M.copy(He).applyQuaternion(re).setY(0).normalize(), re.premultiply(Oe.setFromUnitVectors(He, M).invert()).normalize(), o.boneParent.quaternion.multiply(re.invert()), o.boneParent.quaternion.multiply(o.qWorldInverseYaw)), o.isZ && (m = Math.atan(w[0] / o.l), re.setFromAxisAngle($e, -m), o.boneParent.quaternion.multiply(re)), o.isY && (m = o.l / 3, m = m * Math.tanh(w[1] / m), o.bone.position.setLength(o.l + m)), o.isX && (m = Math.atan(w[2] / o.l), re.setFromAxisAngle(Ke, -m), o.boneParent.quaternion.multiply(re)), o.isT && (m = 1.5 * Math.tanh(w[3] * 1.5), re.setFromAxisAngle(Je, -m), o.boneParent.quaternion.multiply(re)), o.boneParent.updateWorldMatrix(!1, !0), o.excludes && this.opt.isExcludes)
|
|
373
373
|
for (n = 0, s = o.excludes.length; n < s; n++)
|
|
374
|
-
m = o.excludes[n], 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),
|
|
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) && (ue = M.length(), le = ae.length(), !(le > m.radius + ue) && (le < Math.abs(m.radius - ue) || (le = (le * le + ue * ue - m.radiusSq) / (2 * le), ae.normalize(), Ce.copy(ae).multiplyScalar(le), le = Math.sqrt(ue * ue - le * le), M.subVectors(M, Ce).projectOnPlane(ae).normalize().multiplyScalar(le), ze.subVectors(o.vBasis, Ce).projectOnPlane(ae).normalize(), ue = ze.dot(M), ue < 0 && (ue = Math.sqrt(le * le - ue * ue), ze.multiplyScalar(ue), 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),
|
|
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),
|
|
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
|
}
|
|
@@ -2629,7 +2629,7 @@ const ct = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
|
|
|
2629
2629
|
fr: rt,
|
|
2630
2630
|
fi: ut,
|
|
2631
2631
|
lt: ct
|
|
2632
|
-
}, K = new f.Quaternion(),
|
|
2632
|
+
}, K = new f.Quaternion(), Z = new f.Euler(), ve = new f.Vector3(), Re = new f.Vector3(), We = new f.Box3();
|
|
2633
2633
|
new f.Matrix4();
|
|
2634
2634
|
new f.Matrix4();
|
|
2635
2635
|
new f.Vector3();
|
|
@@ -4398,9 +4398,9 @@ class Be {
|
|
|
4398
4398
|
updatePoseDelta() {
|
|
4399
4399
|
for (const [t, e] of Object.entries(this.poseDelta.props)) {
|
|
4400
4400
|
if (e.x === 0 && e.y === 0 && e.z === 0) continue;
|
|
4401
|
-
|
|
4401
|
+
Z.set(e.x, e.y, e.z);
|
|
4402
4402
|
const n = this.poseAvatar.props[t];
|
|
4403
|
-
n.isQuaternion ? (K.setFromEuler(
|
|
4403
|
+
n.isQuaternion ? (K.setFromEuler(Z), n.multiply(K)) : n.isVector3 && n.add(Z);
|
|
4404
4404
|
}
|
|
4405
4405
|
}
|
|
4406
4406
|
/**
|
|
@@ -5172,7 +5172,7 @@ class Be {
|
|
|
5172
5172
|
}, i.x ? new f.Vector3(i.x, i.y, i.z) : null, !0, i.d);
|
|
5173
5173
|
break;
|
|
5174
5174
|
}
|
|
5175
|
-
if ((h || r) && (
|
|
5175
|
+
if ((h || r) && (Z.setFromQuaternion(this.poseAvatar.props["Head.quaternion"]), Z.x = Math.max(-0.9, Math.min(0.9, 2 * Z.x - 0.5)), Z.y = Math.max(-0.9, Math.min(0.9, -2.5 * Z.y)), h ? (Object.assign(this.mtAvatar.eyesLookDown, { system: Z.x < 0 ? -Z.x : 0, needsUpdate: !0 }), Object.assign(this.mtAvatar.eyesLookUp, { system: Z.x < 0 ? 0 : Z.x, needsUpdate: !0 }), Object.assign(this.mtAvatar.eyeLookInLeft, { system: Z.y < 0 ? -Z.y : 0, needsUpdate: !0 }), Object.assign(this.mtAvatar.eyeLookOutLeft, { system: Z.y < 0 ? 0 : Z.y, needsUpdate: !0 }), Object.assign(this.mtAvatar.eyeLookInRight, { system: Z.y < 0 ? 0 : Z.y, needsUpdate: !0 }), Object.assign(this.mtAvatar.eyeLookOutRight, { system: Z.y < 0 ? -Z.y : 0, needsUpdate: !0 }), r && (n = -this.mtAvatar.bodyRotateY.value, i = this.gaussianRandom(-0.2, 0.2), this.animQueue.push(this.animFactory({
|
|
5176
5176
|
name: "headmove",
|
|
5177
5177
|
dt: [[1e3, 2e3], [1e3, 2e3, 1, 2], [1e3, 2e3], [1e3, 2e3, 1, 2]],
|
|
5178
5178
|
vs: {
|
|
@@ -5264,10 +5264,10 @@ class Be {
|
|
|
5264
5264
|
let u = "", a = "", d = 0, c = [], g = [];
|
|
5265
5265
|
const b = Array.from(this.segmenter.segment(t), (x) => x.segment);
|
|
5266
5266
|
for (let x = 0; x < b.length; x++) {
|
|
5267
|
-
const S = x === b.length - 1,
|
|
5267
|
+
const S = x === b.length - 1, G = b[x].match(l);
|
|
5268
5268
|
let p = b[x].match(s);
|
|
5269
|
-
const
|
|
5270
|
-
if (p && !S && !
|
|
5269
|
+
const B = b[x].match(h), H = b[x].match(o);
|
|
5270
|
+
if (p && !S && !B && b[x + 1].match(s) && (p = !1), n && (u += b[x]), G && (!i || i.every((y) => x < y[0] || x > y[1])) && (a += b[x]), (H || p || S) && (a.length && (a = this.lipsyncPreProcessText(a, r), a.length && c.push({
|
|
5271
5271
|
mark: d,
|
|
5272
5272
|
word: a
|
|
5273
5273
|
})), u.length && (g.push({
|
|
@@ -5300,7 +5300,7 @@ class Be {
|
|
|
5300
5300
|
};
|
|
5301
5301
|
n && (y.onSubtitles = n), c.length && !e.avatarMute && (y.text = c, e.avatarMood && (y.mood = e.avatarMood), e.ttsLang && (y.lang = e.ttsLang), e.ttsVoice && (y.voice = e.ttsVoice), e.ttsRate && (y.rate = e.ttsRate), e.ttsVoice && (y.pitch = e.ttsPitch), e.ttsVolume && (y.volume = e.ttsVolume)), this.speechQueue.push(y), c = [], a = "", d = 0, g = [];
|
|
5302
5302
|
}
|
|
5303
|
-
if (
|
|
5303
|
+
if (B) {
|
|
5304
5304
|
let y = this.animEmojis[b[x]];
|
|
5305
5305
|
y && y.link && (y = this.animEmojis[y.link]), y && this.speechQueue.push({ emoji: y });
|
|
5306
5306
|
}
|
|
@@ -5398,10 +5398,10 @@ class Be {
|
|
|
5398
5398
|
let b = 0.6 + this.convertRange(g, [0, u], [0, 0.4]);
|
|
5399
5399
|
if (u = Math.min(u, d.visemes.length * 200), c > 0)
|
|
5400
5400
|
for (let x = 0; x < d.visemes.length; x++) {
|
|
5401
|
-
const S = r + d.times[x] / c * u,
|
|
5401
|
+
const S = r + d.times[x] / c * u, G = d.durations[x] / c * u;
|
|
5402
5402
|
o.push({
|
|
5403
5403
|
template: { name: "viseme" },
|
|
5404
|
-
ts: [S - Math.min(60, 2 *
|
|
5404
|
+
ts: [S - Math.min(60, 2 * G / 3), S + Math.min(25, G / 2), S + G + Math.min(60, G / 2)],
|
|
5405
5405
|
vs: {
|
|
5406
5406
|
["viseme_" + d.visemes[x]]: [null, d.visemes[x] === "PP" || d.visemes[x] === "FF" ? 0.9 : b, 0]
|
|
5407
5407
|
}
|
|
@@ -5483,7 +5483,7 @@ class Be {
|
|
|
5483
5483
|
s.lang = o, s.rate = Math.max(0.1, Math.min(10, l)), s.pitch = Math.max(0, Math.min(2, h)), s.volume = Math.max(0, Math.min(1, r));
|
|
5484
5484
|
const u = speechSynthesis.getVoices(), a = t.voice || this.avatar.ttsVoice || this.opt.ttsVoice;
|
|
5485
5485
|
if (a && u.length > 0) {
|
|
5486
|
-
const p = u.find((
|
|
5486
|
+
const p = u.find((B) => B.name.includes(a) || B.lang === o);
|
|
5487
5487
|
p && (s.voice = p);
|
|
5488
5488
|
}
|
|
5489
5489
|
const d = i.length * 100 / s.rate, c = this.audioCtx.createBuffer(1, this.audioCtx.sampleRate * (d / 1e3), this.audioCtx.sampleRate), g = this.avatar.lipsyncLang || this.opt.lipsyncLang || "en", b = this.lipsyncPreProcessText(i, g), x = this.lipsyncWordsToVisemes(b, g);
|
|
@@ -5498,19 +5498,19 @@ class Be {
|
|
|
5498
5498
|
const S = [];
|
|
5499
5499
|
if (x && x.visemes && x.visemes.length > 0) {
|
|
5500
5500
|
const p = x.times[x.visemes.length - 1] + x.durations[x.visemes.length - 1];
|
|
5501
|
-
for (let
|
|
5502
|
-
const
|
|
5501
|
+
for (let B = 0; B < x.visemes.length; B++) {
|
|
5502
|
+
const H = x.visemes[B], y = x.times[B] / p, I = x.durations[B] / p, z = y * d, A = I * d;
|
|
5503
5503
|
S.push({
|
|
5504
5504
|
template: { name: "viseme" },
|
|
5505
5505
|
ts: [z - Math.min(60, 2 * A / 3), z + Math.min(25, A / 2), z + A + Math.min(60, A / 2)],
|
|
5506
5506
|
vs: {
|
|
5507
|
-
["viseme_" +
|
|
5507
|
+
["viseme_" + H]: [null, H === "PP" || H === "FF" ? 0.9 : 0.6, 0]
|
|
5508
5508
|
}
|
|
5509
5509
|
});
|
|
5510
5510
|
}
|
|
5511
5511
|
}
|
|
5512
|
-
const
|
|
5513
|
-
this.audioPlaylist.push({ anim:
|
|
5512
|
+
const G = [...t.anim, ...S];
|
|
5513
|
+
this.audioPlaylist.push({ anim: G, 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);
|
|
@@ -6161,10 +6161,10 @@ class Be {
|
|
|
6161
6161
|
}
|
|
6162
6162
|
this.objectLeftEye.updateMatrixWorld(!0), this.objectRightEye.updateMatrixWorld(!0), ve.setFromMatrixPosition(this.objectLeftEye.matrixWorld), Re.setFromMatrixPosition(this.objectRightEye.matrixWorld), ve.add(Re).divideScalar(2), K.copy(this.armature.quaternion), K.multiply(this.poseTarget.props["Hips.quaternion"]), K.multiply(this.poseTarget.props["Spine.quaternion"]), K.multiply(this.poseTarget.props["Spine1.quaternion"]), K.multiply(this.poseTarget.props["Spine2.quaternion"]), K.multiply(this.poseTarget.props["Neck.quaternion"]), K.multiply(this.poseTarget.props["Head.quaternion"]);
|
|
6163
6163
|
const n = new f.Vector3().subVectors(e, ve).normalize(), i = Math.atan2(n.x, n.z), s = Math.asin(-n.y);
|
|
6164
|
-
|
|
6165
|
-
const l = new f.Quaternion().setFromEuler(
|
|
6166
|
-
|
|
6167
|
-
let r =
|
|
6164
|
+
Z.set(s, i, 0, "YXZ");
|
|
6165
|
+
const l = new f.Quaternion().setFromEuler(Z), h = new f.Quaternion().copy(l).multiply(K.clone().invert());
|
|
6166
|
+
Z.setFromQuaternion(h, "YXZ");
|
|
6167
|
+
let r = Z.x / (40 / 24) + 0.2, u = Z.y / (9 / 4), a = Math.min(0.6, Math.max(-0.3, r)), d = Math.min(0.8, Math.max(-0.8, u)), c = (Math.random() - 0.5) / 4, g = (Math.random() - 0.5) / 4;
|
|
6168
6168
|
if (t) {
|
|
6169
6169
|
let b = this.animQueue.findIndex((S) => S.template.name === "lookat");
|
|
6170
6170
|
b !== -1 && this.animQueue.splice(b, 1);
|
|
@@ -6199,20 +6199,20 @@ class Be {
|
|
|
6199
6199
|
const s = new f.Vector3().setFromMatrixPosition(this.objectLeftEye.matrixWorld), o = new f.Vector3().setFromMatrixPosition(this.objectRightEye.matrixWorld), l = new f.Vector3().addVectors(s, o).divideScalar(2);
|
|
6200
6200
|
l.project(this.camera);
|
|
6201
6201
|
let h = (l.x + 1) / 2 * i.width + i.left, r = -(l.y - 1) / 2 * i.height + i.top;
|
|
6202
|
-
t === null && (t = h), e === null && (e = r), K.copy(this.armature.quaternion), K.multiply(this.poseTarget.props["Hips.quaternion"]), K.multiply(this.poseTarget.props["Spine.quaternion"]), K.multiply(this.poseTarget.props["Spine1.quaternion"]), K.multiply(this.poseTarget.props["Spine2.quaternion"]), K.multiply(this.poseTarget.props["Neck.quaternion"]), K.multiply(this.poseTarget.props["Head.quaternion"]),
|
|
6203
|
-
let u =
|
|
6202
|
+
t === null && (t = h), e === null && (e = r), K.copy(this.armature.quaternion), K.multiply(this.poseTarget.props["Hips.quaternion"]), K.multiply(this.poseTarget.props["Spine.quaternion"]), K.multiply(this.poseTarget.props["Spine1.quaternion"]), K.multiply(this.poseTarget.props["Spine2.quaternion"]), K.multiply(this.poseTarget.props["Neck.quaternion"]), K.multiply(this.poseTarget.props["Head.quaternion"]), Z.setFromQuaternion(K);
|
|
6203
|
+
let u = Z.x / (40 / 24), a = Z.y / (9 / 4), d = Math.min(0.4, Math.max(-0.4, this.camera.rotation.x)), c = Math.min(0.4, Math.max(-0.4, this.camera.rotation.y)), g = Math.max(window.innerWidth - h, h), b = Math.max(window.innerHeight - r, r), x = this.convertRange(e, [r - b, r + b], [-0.3, 0.6]) - u + d, S = this.convertRange(t, [h - g, h + g], [-0.8, 0.8]) - a + c;
|
|
6204
6204
|
x = Math.min(0.6, Math.max(-0.3, x)), S = Math.min(0.8, Math.max(-0.8, S));
|
|
6205
|
-
let
|
|
6205
|
+
let G = (Math.random() - 0.5) / 4, p = (Math.random() - 0.5) / 4;
|
|
6206
6206
|
if (n) {
|
|
6207
|
-
let
|
|
6208
|
-
|
|
6209
|
-
const
|
|
6207
|
+
let B = this.animQueue.findIndex((y) => y.template.name === "lookat");
|
|
6208
|
+
B !== -1 && this.animQueue.splice(B, 1);
|
|
6209
|
+
const H = {
|
|
6210
6210
|
name: "lookat",
|
|
6211
6211
|
dt: [750, n],
|
|
6212
6212
|
vs: {
|
|
6213
|
-
bodyRotateX: [x +
|
|
6213
|
+
bodyRotateX: [x + G],
|
|
6214
6214
|
bodyRotateY: [S + p],
|
|
6215
|
-
eyesRotateX: [-3 *
|
|
6215
|
+
eyesRotateX: [-3 * G + 0.1],
|
|
6216
6216
|
eyesRotateY: [-5 * p],
|
|
6217
6217
|
browInnerUp: [[0, 0.7]],
|
|
6218
6218
|
mouthLeft: [[0, 0.7]],
|
|
@@ -6221,7 +6221,7 @@ class Be {
|
|
|
6221
6221
|
headMove: [0]
|
|
6222
6222
|
}
|
|
6223
6223
|
};
|
|
6224
|
-
this.animQueue.push(this.animFactory(
|
|
6224
|
+
this.animQueue.push(this.animFactory(H));
|
|
6225
6225
|
}
|
|
6226
6226
|
}
|
|
6227
6227
|
/**
|
|
@@ -6474,7 +6474,7 @@ class Be {
|
|
|
6474
6474
|
return "LeftShoulder";
|
|
6475
6475
|
if (A.includes("right") && (A.includes("shoulder") || A.includes("clavicle")) && c.has("RightShoulder"))
|
|
6476
6476
|
return "RightShoulder";
|
|
6477
|
-
const
|
|
6477
|
+
const Y = {
|
|
6478
6478
|
// Arm bones - exact matches
|
|
6479
6479
|
LeftArm: "LeftArm",
|
|
6480
6480
|
leftArm: "LeftArm",
|
|
@@ -6514,8 +6514,8 @@ class Be {
|
|
|
6514
6514
|
Root: "Hips",
|
|
6515
6515
|
root: "Hips"
|
|
6516
6516
|
};
|
|
6517
|
-
if (
|
|
6518
|
-
const k =
|
|
6517
|
+
if (Y[z]) {
|
|
6518
|
+
const k = Y[z];
|
|
6519
6519
|
if (c.has(k))
|
|
6520
6520
|
return k;
|
|
6521
6521
|
}
|
|
@@ -6523,8 +6523,8 @@ class Be {
|
|
|
6523
6523
|
if (k.toLowerCase() === A)
|
|
6524
6524
|
return k;
|
|
6525
6525
|
for (const k of c) {
|
|
6526
|
-
const
|
|
6527
|
-
if ((A.includes("left") &&
|
|
6526
|
+
const C = k.toLowerCase();
|
|
6527
|
+
if ((A.includes("left") && C.includes("left") || A.includes("right") && C.includes("right")) && (A.includes("arm") && C.includes("arm") && !C.includes("fore") || A.includes("forearm") && C.includes("forearm") || A.includes("hand") && C.includes("hand") && !C.includes("index") && !C.includes("thumb") || A.includes("shoulder") && C.includes("shoulder")))
|
|
6528
6528
|
return k;
|
|
6529
6529
|
}
|
|
6530
6530
|
return null;
|
|
@@ -6535,35 +6535,33 @@ class Be {
|
|
|
6535
6535
|
}), console.log("=== Ready Player Me Animation Bone Analysis ==="), console.log("FBX bone names:", Array.from(x).sort().join(", ")), console.log("Avatar skeleton bone names:", Array.from(c).sort().join(", "));
|
|
6536
6536
|
const S = Array.from(x).filter(
|
|
6537
6537
|
(I) => I.toLowerCase().includes("arm") || I.toLowerCase().includes("hand") || I.toLowerCase().includes("shoulder")
|
|
6538
|
-
),
|
|
6538
|
+
), G = Array.from(c).filter(
|
|
6539
6539
|
(I) => I.includes("Arm") || I.includes("Hand") || I.includes("Shoulder")
|
|
6540
6540
|
);
|
|
6541
|
-
console.log("FBX arm/hand/shoulder bones:", S.sort().join(", ")), console.log("Avatar arm/hand/shoulder bones:",
|
|
6542
|
-
const p = [],
|
|
6541
|
+
console.log("FBX arm/hand/shoulder bones:", S.sort().join(", ")), console.log("Avatar arm/hand/shoulder bones:", G.sort().join(", "));
|
|
6542
|
+
const p = [], B = /* @__PURE__ */ new Set();
|
|
6543
6543
|
if (d.tracks.forEach((I) => {
|
|
6544
|
-
const A = I.name.replaceAll("mixamorig", "").split("."),
|
|
6545
|
-
if (
|
|
6546
|
-
const
|
|
6547
|
-
|
|
6548
|
-
const $ =
|
|
6549
|
-
|
|
6550
|
-
|
|
6551
|
-
|
|
6552
|
-
|
|
6553
|
-
|
|
6554
|
-
|
|
6555
|
-
|
|
6556
|
-
|
|
6557
|
-
|
|
6558
|
-
}
|
|
6559
|
-
B.values[Z] = ne, B.values[Z + 1] = O, B.values[Z + 2] = v, B.values[Z + 3] = R;
|
|
6544
|
+
const A = I.name.replaceAll("mixamorig", "").split("."), Y = A[0], k = A[1], C = b(Y);
|
|
6545
|
+
if (C && k) {
|
|
6546
|
+
const q = `${C}.${k}`, N = I.clone();
|
|
6547
|
+
N.name = q;
|
|
6548
|
+
const $ = C.includes("Arm") || C.includes("Hand") || C.includes("Shoulder"), ie = C.includes("Left");
|
|
6549
|
+
C.includes("Right");
|
|
6550
|
+
const oe = C.includes("ForeArm") || C.includes("Forearm"), he = C.includes("Hand") && !C.includes("Index") && !C.includes("Thumb") && !C.includes("Middle") && !C.includes("Ring") && !C.includes("Pinky");
|
|
6551
|
+
if ($ && (k === "quaternion" || k === "rotation") && k === "quaternion" && N.values && N.values.length >= 4) {
|
|
6552
|
+
const ee = N.times.length;
|
|
6553
|
+
for (let ne = 0; ne < ee; ne++) {
|
|
6554
|
+
const D = ne * 4;
|
|
6555
|
+
if (D + 3 < N.values.length) {
|
|
6556
|
+
let v = N.values[D], R = N.values[D + 1], T = N.values[D + 2], F = N.values[D + 3], P = new f.Quaternion(v, R, T, F);
|
|
6557
|
+
ie && (he ? (P.conjugate(), P = new f.Quaternion().setFromAxisAngle(new f.Vector3(0, 1, 0), Math.PI).multiply(P)) : oe && (P = new f.Quaternion().setFromAxisAngle(new f.Vector3(0, 1, 0), Math.PI).multiply(P), P = new f.Quaternion().setFromAxisAngle(new f.Vector3(1, 0, 0), Math.PI / 2).multiply(P))), N.values[D] = P.x, N.values[D + 1] = P.y, N.values[D + 2] = P.z, N.values[D + 3] = P.w;
|
|
6560
6558
|
}
|
|
6561
6559
|
}
|
|
6562
6560
|
}
|
|
6563
|
-
p.push(
|
|
6561
|
+
p.push(N), Y !== C && g.set(Y, C);
|
|
6564
6562
|
} else
|
|
6565
|
-
|
|
6566
|
-
}),
|
|
6563
|
+
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`);
|
|
6564
|
+
}), B.size > 0 && console.warn(`⚠️ ${B.size} bone(s) could not be mapped:`, Array.from(B).sort().join(", ")), p.length > 0) {
|
|
6567
6565
|
d = new f.AnimationClip(d.name, d.duration, p), console.log(`✓ Created animation with ${p.length} mapped tracks (from ${d.tracks.length} original tracks)`), g.size > 0 && console.log(
|
|
6568
6566
|
`✓ Mapped ${g.size} bone(s):`,
|
|
6569
6567
|
Array.from(g.entries()).map(([z, A]) => `${z}→${A}`).join(", ")
|
|
@@ -6574,18 +6572,18 @@ class Be {
|
|
|
6574
6572
|
I.length > 0 ? console.log(`✓ Arm bones mapped: ${I.join(", ")}`) : console.warn("⚠️ No arm bones were mapped! This may cause arm rigging issues.");
|
|
6575
6573
|
} else
|
|
6576
6574
|
console.error("❌ No tracks could be mapped! Animation may not work correctly.");
|
|
6577
|
-
const
|
|
6575
|
+
const H = {};
|
|
6578
6576
|
d.tracks.forEach((I) => {
|
|
6579
6577
|
I.name = I.name.replaceAll("mixamorig", "");
|
|
6580
6578
|
const z = I.name.split(".");
|
|
6581
6579
|
if (z[1] === "position") {
|
|
6582
6580
|
for (let A = 0; A < I.values.length; A++)
|
|
6583
6581
|
I.values[A] = I.values[A] * s;
|
|
6584
|
-
|
|
6585
|
-
} else z[1] === "quaternion" ?
|
|
6582
|
+
H[I.name] = new f.Vector3(I.values[0], I.values[1], I.values[2]);
|
|
6583
|
+
} else z[1] === "quaternion" ? H[I.name] = new f.Quaternion(I.values[0], I.values[1], I.values[2], I.values[3]) : z[1] === "rotation" && (H[z[0] + ".quaternion"] = new f.Quaternion().setFromEuler(new f.Euler(I.values[0], I.values[1], I.values[2], "XYZ")).normalize());
|
|
6586
6584
|
});
|
|
6587
|
-
const y = { props:
|
|
6588
|
-
|
|
6585
|
+
const y = { props: H };
|
|
6586
|
+
H["Hips.position"] && (H["Hips.position"].y < 0.5 ? y.lying = !0 : y.standing = !0), this.animClips.push({
|
|
6589
6587
|
url: t + "-" + i,
|
|
6590
6588
|
clip: d,
|
|
6591
6589
|
pose: y
|
|
@@ -6723,12 +6721,12 @@ class Be {
|
|
|
6723
6721
|
const x = t.iterations || 10;
|
|
6724
6722
|
if (e)
|
|
6725
6723
|
for (let S = 0; S < x; S++) {
|
|
6726
|
-
let
|
|
6727
|
-
for (let p = 0,
|
|
6728
|
-
const
|
|
6729
|
-
|
|
6724
|
+
let G = !1;
|
|
6725
|
+
for (let p = 0, B = b.length; p < B; p++) {
|
|
6726
|
+
const H = b[p].bone;
|
|
6727
|
+
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();
|
|
6730
6728
|
let y = s.dot(l);
|
|
6731
|
-
y > 1 ? y = 1 : y < -1 && (y = -1), y = Math.acos(y), !(y < 1e-5) && (b[p].minAngle !== void 0 && y < b[p].minAngle && (y = b[p].minAngle), b[p].maxAngle !== void 0 && y > b[p].maxAngle && (y = b[p].maxAngle), a.crossVectors(l, s), a.normalize(), K.setFromAxisAngle(a, y),
|
|
6729
|
+
y > 1 ? y = 1 : y < -1 && (y = -1), y = Math.acos(y), !(y < 1e-5) && (b[p].minAngle !== void 0 && y < b[p].minAngle && (y = b[p].minAngle), b[p].maxAngle !== void 0 && y > b[p].maxAngle && (y = b[p].maxAngle), a.crossVectors(l, s), a.normalize(), K.setFromAxisAngle(a, y), H.quaternion.multiply(K), H.rotation.setFromVector3(d.setFromEuler(H.rotation).clamp(new f.Vector3(
|
|
6732
6730
|
b[p].minx !== void 0 ? b[p].minx : -1 / 0,
|
|
6733
6731
|
b[p].miny !== void 0 ? b[p].miny : -1 / 0,
|
|
6734
6732
|
b[p].minz !== void 0 ? b[p].minz : -1 / 0
|
|
@@ -6736,9 +6734,9 @@ class Be {
|
|
|
6736
6734
|
b[p].maxx !== void 0 ? b[p].maxx : 1 / 0,
|
|
6737
6735
|
b[p].maxy !== void 0 ? b[p].maxy : 1 / 0,
|
|
6738
6736
|
b[p].maxz !== void 0 ? b[p].maxz : 1 / 0
|
|
6739
|
-
))),
|
|
6737
|
+
))), H.updateMatrixWorld(!0), G = !0);
|
|
6740
6738
|
}
|
|
6741
|
-
if (!
|
|
6739
|
+
if (!G) break;
|
|
6742
6740
|
}
|
|
6743
6741
|
i && b.forEach((S) => {
|
|
6744
6742
|
this.poseTarget.props[S.link + ".quaternion"].copy(S.bone.quaternion), this.poseTarget.props[S.link + ".quaternion"].t = this.animClock, this.poseTarget.props[S.link + ".quaternion"].d = i;
|
|
@@ -6801,16 +6799,16 @@ function Ee() {
|
|
|
6801
6799
|
};
|
|
6802
6800
|
}
|
|
6803
6801
|
function kt() {
|
|
6804
|
-
const
|
|
6805
|
-
return Object.entries(
|
|
6802
|
+
const X = Ee(), t = [];
|
|
6803
|
+
return Object.entries(X.voices).forEach(([e, n]) => {
|
|
6806
6804
|
t.push({
|
|
6807
6805
|
value: n,
|
|
6808
|
-
label: `${e.charAt(0).toUpperCase() + e.slice(1)} (${
|
|
6806
|
+
label: `${e.charAt(0).toUpperCase() + e.slice(1)} (${X.service})`
|
|
6809
6807
|
});
|
|
6810
6808
|
}), t;
|
|
6811
6809
|
}
|
|
6812
6810
|
const Ve = Me(({
|
|
6813
|
-
avatarUrl:
|
|
6811
|
+
avatarUrl: X = "/avatars/brunette.glb",
|
|
6814
6812
|
avatarBody: t = "F",
|
|
6815
6813
|
mood: e = "neutral",
|
|
6816
6814
|
ttsLang: n = "en",
|
|
@@ -6831,116 +6829,116 @@ const Ve = Me(({
|
|
|
6831
6829
|
style: b = {},
|
|
6832
6830
|
animations: x = {}
|
|
6833
6831
|
}, S) => {
|
|
6834
|
-
const
|
|
6832
|
+
const G = V(null), p = V(null), B = V(r), H = V(null), y = V(null), I = V(!1), z = V({ remainingText: null, originalText: null, options: null }), A = V([]), Y = V(0), [k, C] = de(!0), [q, N] = de(null), [$, ie] = de(!1), [oe, he] = de(!1);
|
|
6835
6833
|
me(() => {
|
|
6836
6834
|
I.current = oe;
|
|
6837
6835
|
}, [oe]), me(() => {
|
|
6838
|
-
|
|
6836
|
+
B.current = r;
|
|
6839
6837
|
}, [r]);
|
|
6840
|
-
const
|
|
6841
|
-
let
|
|
6842
|
-
ne === "browser" ?
|
|
6838
|
+
const ee = Ee(), ne = i || ee.service;
|
|
6839
|
+
let D;
|
|
6840
|
+
ne === "browser" ? D = {
|
|
6843
6841
|
service: "browser",
|
|
6844
6842
|
endpoint: "",
|
|
6845
6843
|
apiKey: null,
|
|
6846
6844
|
defaultVoice: "Google US English"
|
|
6847
|
-
} : ne === "elevenlabs" ?
|
|
6845
|
+
} : ne === "elevenlabs" ? D = {
|
|
6848
6846
|
service: "elevenlabs",
|
|
6849
6847
|
endpoint: "https://api.elevenlabs.io/v1/text-to-speech",
|
|
6850
|
-
apiKey: o ||
|
|
6851
|
-
defaultVoice: s ||
|
|
6852
|
-
voices:
|
|
6853
|
-
} : ne === "deepgram" ?
|
|
6848
|
+
apiKey: o || ee.apiKey,
|
|
6849
|
+
defaultVoice: s || ee.defaultVoice || Ie.defaultVoice,
|
|
6850
|
+
voices: ee.voices || Ie.voices
|
|
6851
|
+
} : ne === "deepgram" ? D = {
|
|
6854
6852
|
service: "deepgram",
|
|
6855
6853
|
endpoint: "https://api.deepgram.com/v1/speak",
|
|
6856
|
-
apiKey: o ||
|
|
6857
|
-
defaultVoice: s ||
|
|
6858
|
-
voices:
|
|
6859
|
-
} :
|
|
6860
|
-
...
|
|
6854
|
+
apiKey: o || ee.apiKey,
|
|
6855
|
+
defaultVoice: s || ee.defaultVoice || Te.defaultVoice,
|
|
6856
|
+
voices: ee.voices || Te.voices
|
|
6857
|
+
} : D = {
|
|
6858
|
+
...ee,
|
|
6861
6859
|
// Override API key if provided via props
|
|
6862
|
-
apiKey: o !== null ? o :
|
|
6860
|
+
apiKey: o !== null ? o : ee.apiKey
|
|
6863
6861
|
};
|
|
6864
6862
|
const v = {
|
|
6865
|
-
url:
|
|
6863
|
+
url: X,
|
|
6866
6864
|
body: t,
|
|
6867
6865
|
avatarMood: e,
|
|
6868
6866
|
ttsLang: ne === "browser" ? "en-US" : n,
|
|
6869
|
-
ttsVoice: s ||
|
|
6867
|
+
ttsVoice: s || D.defaultVoice,
|
|
6870
6868
|
lipsyncLang: "en",
|
|
6871
6869
|
showFullAvatar: r,
|
|
6872
6870
|
bodyMovement: l,
|
|
6873
6871
|
movementIntensity: h
|
|
6874
6872
|
}, R = {
|
|
6875
|
-
ttsEndpoint:
|
|
6876
|
-
ttsApikey:
|
|
6873
|
+
ttsEndpoint: D.endpoint,
|
|
6874
|
+
ttsApikey: D.apiKey,
|
|
6877
6875
|
ttsService: ne,
|
|
6878
6876
|
lipsyncModules: ["en"],
|
|
6879
6877
|
cameraView: u
|
|
6880
|
-
},
|
|
6881
|
-
if (!(!
|
|
6878
|
+
}, T = O(async () => {
|
|
6879
|
+
if (!(!G.current || p.current))
|
|
6882
6880
|
try {
|
|
6883
|
-
if (
|
|
6884
|
-
if (
|
|
6885
|
-
const te = Math.min(100, Math.round(
|
|
6881
|
+
if (C(!0), N(null), p.current = new Be(G.current, R), p.current.controls && (p.current.controls.enableRotate = !1, p.current.controls.enableZoom = !1, p.current.controls.enablePan = !1, p.current.controls.enableDamping = !1), x && Object.keys(x).length > 0 && (p.current.customAnimations = x), await p.current.showAvatar(v, (W) => {
|
|
6882
|
+
if (W.lengthComputable) {
|
|
6883
|
+
const te = Math.min(100, Math.round(W.loaded / W.total * 100));
|
|
6886
6884
|
d(te);
|
|
6887
6885
|
}
|
|
6888
|
-
}), await new Promise((
|
|
6886
|
+
}), await new Promise((W) => {
|
|
6889
6887
|
const te = () => {
|
|
6890
|
-
p.current.lipsync && Object.keys(p.current.lipsync).length > 0 ?
|
|
6888
|
+
p.current.lipsync && Object.keys(p.current.lipsync).length > 0 ? W() : setTimeout(te, 100);
|
|
6891
6889
|
};
|
|
6892
6890
|
te();
|
|
6893
6891
|
}), p.current && p.current.setShowFullAvatar)
|
|
6894
6892
|
try {
|
|
6895
6893
|
p.current.setShowFullAvatar(r);
|
|
6896
|
-
} catch (
|
|
6897
|
-
console.warn("Error setting full body mode on initialization:",
|
|
6894
|
+
} catch (W) {
|
|
6895
|
+
console.warn("Error setting full body mode on initialization:", W);
|
|
6898
6896
|
}
|
|
6899
|
-
p.current && p.current.controls && (p.current.controls.enableRotate = !1, p.current.controls.enableZoom = !1, p.current.controls.enablePan = !1, p.current.controls.enableDamping = !1, p.current.controls.update()),
|
|
6900
|
-
const
|
|
6897
|
+
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()), C(!1), ie(!0), a(p.current);
|
|
6898
|
+
const U = () => {
|
|
6901
6899
|
document.visibilityState === "visible" ? p.current?.start() : p.current?.stop();
|
|
6902
6900
|
};
|
|
6903
|
-
return document.addEventListener("visibilitychange",
|
|
6904
|
-
document.removeEventListener("visibilitychange",
|
|
6901
|
+
return document.addEventListener("visibilitychange", U), () => {
|
|
6902
|
+
document.removeEventListener("visibilitychange", U);
|
|
6905
6903
|
};
|
|
6906
6904
|
} catch (L) {
|
|
6907
|
-
console.error("Error initializing TalkingHead:", L),
|
|
6905
|
+
console.error("Error initializing TalkingHead:", L), N(L.message || "Failed to initialize avatar"), C(!1), c(L);
|
|
6908
6906
|
}
|
|
6909
|
-
}, [
|
|
6910
|
-
me(() => (
|
|
6907
|
+
}, [X, t, e, n, i, s, o, r, l, h, u]);
|
|
6908
|
+
me(() => (T(), () => {
|
|
6911
6909
|
p.current && (p.current.stop(), p.current.dispose(), p.current = null);
|
|
6912
|
-
}), [
|
|
6913
|
-
if (!
|
|
6914
|
-
const L = new ResizeObserver((
|
|
6915
|
-
for (const te of
|
|
6910
|
+
}), [T]), me(() => {
|
|
6911
|
+
if (!G.current || !p.current) return;
|
|
6912
|
+
const L = new ResizeObserver((W) => {
|
|
6913
|
+
for (const te of W)
|
|
6916
6914
|
p.current && p.current.onResize && p.current.onResize();
|
|
6917
6915
|
});
|
|
6918
|
-
L.observe(
|
|
6919
|
-
const
|
|
6916
|
+
L.observe(G.current);
|
|
6917
|
+
const U = () => {
|
|
6920
6918
|
p.current && p.current.onResize && p.current.onResize();
|
|
6921
6919
|
};
|
|
6922
|
-
return window.addEventListener("resize",
|
|
6923
|
-
L.disconnect(), window.removeEventListener("resize",
|
|
6920
|
+
return window.addEventListener("resize", U), () => {
|
|
6921
|
+
L.disconnect(), window.removeEventListener("resize", U);
|
|
6924
6922
|
};
|
|
6925
6923
|
}, [$]);
|
|
6926
|
-
const
|
|
6924
|
+
const F = O(async () => {
|
|
6927
6925
|
if (p.current && p.current.audioCtx)
|
|
6928
6926
|
try {
|
|
6929
6927
|
(p.current.audioCtx.state === "suspended" || p.current.audioCtx.state === "interrupted") && (await p.current.audioCtx.resume(), console.log("Audio context resumed"));
|
|
6930
6928
|
} catch (L) {
|
|
6931
6929
|
console.warn("Failed to resume audio context:", L);
|
|
6932
6930
|
}
|
|
6933
|
-
}, []),
|
|
6931
|
+
}, []), P = O(async (L, U = {}) => {
|
|
6934
6932
|
if (p.current && $)
|
|
6935
6933
|
try {
|
|
6936
|
-
y.current && (clearInterval(y.current), y.current = null),
|
|
6937
|
-
const
|
|
6938
|
-
A.current = te,
|
|
6934
|
+
y.current && (clearInterval(y.current), y.current = null), H.current = { text: L, options: U }, z.current = { remainingText: null, originalText: null, options: null };
|
|
6935
|
+
const W = /[!\.\?\n\p{Extended_Pictographic}]/ug, te = L.split(W).map((Q) => Q.trim()).filter((Q) => Q.length > 0);
|
|
6936
|
+
A.current = te, Y.current = 0, he(!1), I.current = !1, await F();
|
|
6939
6937
|
const ge = {
|
|
6940
|
-
...
|
|
6941
|
-
lipsyncLang:
|
|
6938
|
+
...U,
|
|
6939
|
+
lipsyncLang: U.lipsyncLang || v.lipsyncLang || "en"
|
|
6942
6940
|
};
|
|
6943
|
-
if (
|
|
6941
|
+
if (U.onSpeechEnd && p.current) {
|
|
6944
6942
|
const Q = p.current;
|
|
6945
6943
|
let ce = null, Se = 0;
|
|
6946
6944
|
const Le = 1200;
|
|
@@ -6952,7 +6950,7 @@ const Ve = Me(({
|
|
|
6952
6950
|
if (ce && (clearInterval(ce), ce = null, y.current = null), !be && !I.current) {
|
|
6953
6951
|
be = !0;
|
|
6954
6952
|
try {
|
|
6955
|
-
|
|
6953
|
+
U.onSpeechEnd();
|
|
6956
6954
|
} catch (Ne) {
|
|
6957
6955
|
console.error("Error in onSpeechEnd callback (timeout):", Ne);
|
|
6958
6956
|
}
|
|
@@ -6964,7 +6962,7 @@ const Ve = Me(({
|
|
|
6964
6962
|
if (Q && !I.current && Q.isSpeaking === !1 && (!Q.speechQueue || Q.speechQueue.length === 0) && (!Q.audioPlaylist || Q.audioPlaylist.length === 0) && Q.isAudioPlaying === !1 && !be && !I.current) {
|
|
6965
6963
|
be = !0, ce && (clearInterval(ce), ce = null, y.current = null);
|
|
6966
6964
|
try {
|
|
6967
|
-
|
|
6965
|
+
U.onSpeechEnd();
|
|
6968
6966
|
} catch (Ze) {
|
|
6969
6967
|
console.error("Error in onSpeechEnd callback:", Ze);
|
|
6970
6968
|
}
|
|
@@ -6973,70 +6971,70 @@ const Ve = Me(({
|
|
|
6973
6971
|
}, 100), y.current = ce;
|
|
6974
6972
|
}
|
|
6975
6973
|
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 () => {
|
|
6976
|
-
await
|
|
6974
|
+
await F(), p.current && p.current.lipsync && (p.current.setSlowdownRate && p.current.setSlowdownRate(1.05), p.current.speakText(L, ge));
|
|
6977
6975
|
}, 100);
|
|
6978
|
-
} catch (
|
|
6979
|
-
console.error("Error speaking text:",
|
|
6976
|
+
} catch (W) {
|
|
6977
|
+
console.error("Error speaking text:", W), N(W.message || "Failed to speak text");
|
|
6980
6978
|
}
|
|
6981
|
-
}, [$,
|
|
6982
|
-
p.current && (p.current.stopSpeaking(), p.current.setSlowdownRate && p.current.setSlowdownRate(1),
|
|
6983
|
-
}, []),
|
|
6979
|
+
}, [$, F, v.lipsyncLang]), _ = O(() => {
|
|
6980
|
+
p.current && (p.current.stopSpeaking(), p.current.setSlowdownRate && p.current.setSlowdownRate(1), H.current = null, he(!1));
|
|
6981
|
+
}, []), j = O(() => {
|
|
6984
6982
|
if (p.current && p.current.pauseSpeaking) {
|
|
6985
6983
|
const L = p.current;
|
|
6986
6984
|
if (L.isSpeaking || L.audioPlaylist && L.audioPlaylist.length > 0 || L.speechQueue && L.speechQueue.length > 0) {
|
|
6987
6985
|
y.current && (clearInterval(y.current), y.current = null);
|
|
6988
|
-
let
|
|
6989
|
-
if (
|
|
6986
|
+
let W = "";
|
|
6987
|
+
if (H.current && A.current.length > 0) {
|
|
6990
6988
|
const te = A.current.length, ge = L.speechQueue ? L.speechQueue.filter((Le) => Le && Le.text && Array.isArray(Le.text) && Le.text.length > 0).length : 0, Q = L.audioPlaylist && L.audioPlaylist.length > 0, ce = ge + (Q ? 1 : 0), Se = te - ce;
|
|
6991
|
-
if (ce > 0 && Se < te && (
|
|
6989
|
+
if (ce > 0 && Se < te && (W = A.current.slice(Se).join(". ").trim(), !W && ge > 0 && L.speechQueue)) {
|
|
6992
6990
|
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(" ");
|
|
6993
|
-
be && be.trim() && (
|
|
6991
|
+
be && be.trim() && (W = be.trim());
|
|
6994
6992
|
}
|
|
6995
6993
|
}
|
|
6996
|
-
|
|
6997
|
-
remainingText:
|
|
6998
|
-
originalText:
|
|
6999
|
-
options:
|
|
7000
|
-
}), L.speechQueue && (L.speechQueue.length = 0), p.current.pauseSpeaking(), I.current = !0,
|
|
6994
|
+
H.current && (z.current = {
|
|
6995
|
+
remainingText: W || null,
|
|
6996
|
+
originalText: H.current.text,
|
|
6997
|
+
options: H.current.options
|
|
6998
|
+
}), L.speechQueue && (L.speechQueue.length = 0), p.current.pauseSpeaking(), I.current = !0, he(!0);
|
|
7001
6999
|
}
|
|
7002
7000
|
}
|
|
7003
|
-
}, []), J =
|
|
7001
|
+
}, []), J = O(async () => {
|
|
7004
7002
|
if (!p.current || !oe)
|
|
7005
7003
|
return;
|
|
7006
|
-
let L = "",
|
|
7004
|
+
let L = "", U = {};
|
|
7007
7005
|
if (z.current && z.current.remainingText)
|
|
7008
|
-
L = z.current.remainingText,
|
|
7009
|
-
else if (
|
|
7010
|
-
L =
|
|
7006
|
+
L = z.current.remainingText, U = z.current.options || {}, z.current = { remainingText: null, originalText: null, options: null };
|
|
7007
|
+
else if (H.current && H.current.text)
|
|
7008
|
+
L = H.current.text, U = H.current.options || {};
|
|
7011
7009
|
else {
|
|
7012
|
-
console.warn("Resume called but no paused speech found"),
|
|
7010
|
+
console.warn("Resume called but no paused speech found"), he(!1), I.current = !1;
|
|
7013
7011
|
return;
|
|
7014
7012
|
}
|
|
7015
|
-
|
|
7016
|
-
const
|
|
7017
|
-
...
|
|
7018
|
-
lipsyncLang:
|
|
7013
|
+
he(!1), I.current = !1, await F();
|
|
7014
|
+
const W = {
|
|
7015
|
+
...U,
|
|
7016
|
+
lipsyncLang: U.lipsyncLang || v.lipsyncLang || "en"
|
|
7019
7017
|
};
|
|
7020
7018
|
try {
|
|
7021
|
-
await
|
|
7019
|
+
await P(L, W);
|
|
7022
7020
|
} catch (te) {
|
|
7023
|
-
console.error("Error resuming speech:", te),
|
|
7021
|
+
console.error("Error resuming speech:", te), he(!1), I.current = !1;
|
|
7024
7022
|
}
|
|
7025
|
-
}, [
|
|
7023
|
+
}, [F, oe, P, v]), Ae = O((L) => {
|
|
7026
7024
|
p.current && p.current.setMood(L);
|
|
7027
|
-
}, []), we =
|
|
7025
|
+
}, []), we = O((L) => {
|
|
7028
7026
|
p.current && p.current.setSlowdownRate && p.current.setSlowdownRate(L);
|
|
7029
|
-
}, []), E =
|
|
7027
|
+
}, []), E = O((L, U = !1) => {
|
|
7030
7028
|
if (p.current && p.current.playAnimation) {
|
|
7031
7029
|
if (x && x[L] && (L = x[L]), p.current.setShowFullAvatar)
|
|
7032
7030
|
try {
|
|
7033
|
-
p.current.setShowFullAvatar(
|
|
7031
|
+
p.current.setShowFullAvatar(B.current);
|
|
7034
7032
|
} catch (te) {
|
|
7035
7033
|
console.warn("Error setting full body mode:", te);
|
|
7036
7034
|
}
|
|
7037
7035
|
if (L.includes("."))
|
|
7038
7036
|
try {
|
|
7039
|
-
p.current.playAnimation(L, null, 10, 0, 0.01,
|
|
7037
|
+
p.current.playAnimation(L, null, 10, 0, 0.01, U);
|
|
7040
7038
|
} catch (te) {
|
|
7041
7039
|
console.warn(`Failed to play ${L}:`, te);
|
|
7042
7040
|
try {
|
|
@@ -7050,7 +7048,7 @@ const Ve = Me(({
|
|
|
7050
7048
|
let ge = !1;
|
|
7051
7049
|
for (const Q of te)
|
|
7052
7050
|
try {
|
|
7053
|
-
p.current.playAnimation(L + Q, null, 10, 0, 0.01,
|
|
7051
|
+
p.current.playAnimation(L + Q, null, 10, 0, 0.01, U), ge = !0;
|
|
7054
7052
|
break;
|
|
7055
7053
|
} catch {
|
|
7056
7054
|
}
|
|
@@ -7064,15 +7062,15 @@ const Ve = Me(({
|
|
|
7064
7062
|
}
|
|
7065
7063
|
}
|
|
7066
7064
|
}
|
|
7067
|
-
}, [x]), se =
|
|
7065
|
+
}, [x]), se = O(() => {
|
|
7068
7066
|
p.current && p.current.onResize && p.current.onResize();
|
|
7069
7067
|
}, []);
|
|
7070
7068
|
return Fe(S, () => ({
|
|
7071
|
-
speakText:
|
|
7072
|
-
stopSpeaking:
|
|
7073
|
-
pauseSpeaking:
|
|
7069
|
+
speakText: P,
|
|
7070
|
+
stopSpeaking: _,
|
|
7071
|
+
pauseSpeaking: j,
|
|
7074
7072
|
resumeSpeaking: J,
|
|
7075
|
-
resumeAudioContext:
|
|
7073
|
+
resumeAudioContext: F,
|
|
7076
7074
|
setMood: Ae,
|
|
7077
7075
|
setTimingAdjustment: we,
|
|
7078
7076
|
playAnimation: E,
|
|
@@ -7083,16 +7081,16 @@ const Ve = Me(({
|
|
|
7083
7081
|
setBodyMovement: (L) => {
|
|
7084
7082
|
if (p.current && p.current.setShowFullAvatar && p.current.setBodyMovement)
|
|
7085
7083
|
try {
|
|
7086
|
-
p.current.setShowFullAvatar(
|
|
7087
|
-
} catch (
|
|
7088
|
-
console.warn("Error setting body movement:",
|
|
7084
|
+
p.current.setShowFullAvatar(B.current), p.current.setBodyMovement(L);
|
|
7085
|
+
} catch (U) {
|
|
7086
|
+
console.warn("Error setting body movement:", U);
|
|
7089
7087
|
}
|
|
7090
7088
|
},
|
|
7091
7089
|
setMovementIntensity: (L) => p.current?.setMovementIntensity(L),
|
|
7092
7090
|
playRandomDance: () => {
|
|
7093
7091
|
if (p.current && p.current.setShowFullAvatar && p.current.playRandomDance)
|
|
7094
7092
|
try {
|
|
7095
|
-
p.current.setShowFullAvatar(
|
|
7093
|
+
p.current.setShowFullAvatar(B.current), p.current.playRandomDance();
|
|
7096
7094
|
} catch (L) {
|
|
7097
7095
|
console.warn("Error playing random dance:", L);
|
|
7098
7096
|
}
|
|
@@ -7100,15 +7098,15 @@ const Ve = Me(({
|
|
|
7100
7098
|
playReaction: (L) => {
|
|
7101
7099
|
if (p.current && p.current.setShowFullAvatar && p.current.playReaction)
|
|
7102
7100
|
try {
|
|
7103
|
-
p.current.setShowFullAvatar(
|
|
7104
|
-
} catch (
|
|
7105
|
-
console.warn("Error playing reaction:",
|
|
7101
|
+
p.current.setShowFullAvatar(B.current), p.current.playReaction(L);
|
|
7102
|
+
} catch (U) {
|
|
7103
|
+
console.warn("Error playing reaction:", U);
|
|
7106
7104
|
}
|
|
7107
7105
|
},
|
|
7108
7106
|
playCelebration: () => {
|
|
7109
7107
|
if (p.current && p.current.setShowFullAvatar && p.current.playCelebration)
|
|
7110
7108
|
try {
|
|
7111
|
-
p.current.setShowFullAvatar(
|
|
7109
|
+
p.current.setShowFullAvatar(B.current), p.current.playCelebration();
|
|
7112
7110
|
} catch (L) {
|
|
7113
7111
|
console.warn("Error playing celebration:", L);
|
|
7114
7112
|
}
|
|
@@ -7116,9 +7114,9 @@ const Ve = Me(({
|
|
|
7116
7114
|
setShowFullAvatar: (L) => {
|
|
7117
7115
|
if (p.current && p.current.setShowFullAvatar)
|
|
7118
7116
|
try {
|
|
7119
|
-
|
|
7120
|
-
} catch (
|
|
7121
|
-
console.warn("Error setting showFullAvatar:",
|
|
7117
|
+
B.current = L, p.current.setShowFullAvatar(L);
|
|
7118
|
+
} catch (U) {
|
|
7119
|
+
console.warn("Error setting showFullAvatar:", U);
|
|
7122
7120
|
}
|
|
7123
7121
|
},
|
|
7124
7122
|
lockAvatarPosition: () => {
|
|
@@ -7151,7 +7149,7 @@ const Ve = Me(({
|
|
|
7151
7149
|
/* @__PURE__ */ pe(
|
|
7152
7150
|
"div",
|
|
7153
7151
|
{
|
|
7154
|
-
ref:
|
|
7152
|
+
ref: G,
|
|
7155
7153
|
className: "talking-head-viewer",
|
|
7156
7154
|
style: {
|
|
7157
7155
|
width: "100%",
|
|
@@ -7169,7 +7167,7 @@ const Ve = Me(({
|
|
|
7169
7167
|
fontSize: "18px",
|
|
7170
7168
|
zIndex: 10
|
|
7171
7169
|
}, children: "Loading avatar..." }),
|
|
7172
|
-
|
|
7170
|
+
q && /* @__PURE__ */ pe("div", { className: "error-overlay", style: {
|
|
7173
7171
|
position: "absolute",
|
|
7174
7172
|
top: "50%",
|
|
7175
7173
|
left: "50%",
|
|
@@ -7180,14 +7178,14 @@ const Ve = Me(({
|
|
|
7180
7178
|
zIndex: 10,
|
|
7181
7179
|
padding: "20px",
|
|
7182
7180
|
borderRadius: "8px"
|
|
7183
|
-
}, children:
|
|
7181
|
+
}, children: q })
|
|
7184
7182
|
]
|
|
7185
7183
|
}
|
|
7186
7184
|
);
|
|
7187
7185
|
});
|
|
7188
7186
|
Ve.displayName = "TalkingHeadAvatar";
|
|
7189
7187
|
const pt = Me(({
|
|
7190
|
-
text:
|
|
7188
|
+
text: X = "Hello! I'm a talking avatar. How are you today?",
|
|
7191
7189
|
onLoading: t = () => {
|
|
7192
7190
|
},
|
|
7193
7191
|
onError: e = () => {
|
|
@@ -7198,7 +7196,7 @@ const pt = Me(({
|
|
|
7198
7196
|
style: s = {},
|
|
7199
7197
|
avatarConfig: o = {}
|
|
7200
7198
|
}, l) => {
|
|
7201
|
-
const h =
|
|
7199
|
+
const h = V(null), r = V(null), [u, a] = de(!0), [d, c] = de(null), [g, b] = de(!1), x = Ee(), S = o.ttsService || x.service, G = S === "browser" ? {
|
|
7202
7200
|
endpoint: "",
|
|
7203
7201
|
apiKey: null,
|
|
7204
7202
|
defaultVoice: "Google US English"
|
|
@@ -7214,7 +7212,7 @@ const pt = Me(({
|
|
|
7214
7212
|
body: "F",
|
|
7215
7213
|
avatarMood: "neutral",
|
|
7216
7214
|
ttsLang: S === "browser" ? "en-US" : "en",
|
|
7217
|
-
ttsVoice: o.ttsVoice ||
|
|
7215
|
+
ttsVoice: o.ttsVoice || G.defaultVoice,
|
|
7218
7216
|
lipsyncLang: "en",
|
|
7219
7217
|
// English lip-sync
|
|
7220
7218
|
showFullAvatar: !0,
|
|
@@ -7222,81 +7220,81 @@ const pt = Me(({
|
|
|
7222
7220
|
bodyMovement: "idle",
|
|
7223
7221
|
movementIntensity: 0.5,
|
|
7224
7222
|
...o
|
|
7225
|
-
},
|
|
7226
|
-
ttsEndpoint:
|
|
7227
|
-
ttsApikey:
|
|
7223
|
+
}, B = {
|
|
7224
|
+
ttsEndpoint: G.endpoint,
|
|
7225
|
+
ttsApikey: G.apiKey,
|
|
7228
7226
|
ttsService: S,
|
|
7229
7227
|
lipsyncModules: ["en"],
|
|
7230
7228
|
cameraView: "upper"
|
|
7231
|
-
},
|
|
7229
|
+
}, H = O(async () => {
|
|
7232
7230
|
if (!(!h.current || r.current))
|
|
7233
7231
|
try {
|
|
7234
|
-
if (a(!0), c(null), r.current = new Be(h.current,
|
|
7235
|
-
if (
|
|
7236
|
-
const
|
|
7237
|
-
t(
|
|
7232
|
+
if (a(!0), c(null), r.current = new Be(h.current, B), await r.current.showAvatar(p, (q) => {
|
|
7233
|
+
if (q.lengthComputable) {
|
|
7234
|
+
const N = Math.min(100, Math.round(q.loaded / q.total * 100));
|
|
7235
|
+
t(N);
|
|
7238
7236
|
}
|
|
7239
7237
|
}), r.current.morphs && r.current.morphs.length > 0) {
|
|
7240
|
-
const
|
|
7241
|
-
console.log("Available morph targets:", Object.keys(
|
|
7242
|
-
const
|
|
7243
|
-
console.log("Viseme morph targets found:",
|
|
7238
|
+
const q = r.current.morphs[0].morphTargetDictionary;
|
|
7239
|
+
console.log("Available morph targets:", Object.keys(q));
|
|
7240
|
+
const N = Object.keys(q).filter(($) => $.startsWith("viseme_"));
|
|
7241
|
+
console.log("Viseme morph targets found:", N), N.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"));
|
|
7244
7242
|
}
|
|
7245
|
-
if (await new Promise((
|
|
7246
|
-
const
|
|
7247
|
-
r.current.lipsync && Object.keys(r.current.lipsync).length > 0 ? (console.log("Lip-sync modules loaded:", Object.keys(r.current.lipsync)),
|
|
7243
|
+
if (await new Promise((q) => {
|
|
7244
|
+
const N = () => {
|
|
7245
|
+
r.current.lipsync && Object.keys(r.current.lipsync).length > 0 ? (console.log("Lip-sync modules loaded:", Object.keys(r.current.lipsync)), q()) : (console.log("Waiting for lip-sync modules to load..."), setTimeout(N, 100));
|
|
7248
7246
|
};
|
|
7249
|
-
|
|
7247
|
+
N();
|
|
7250
7248
|
}), r.current && r.current.setShowFullAvatar)
|
|
7251
7249
|
try {
|
|
7252
7250
|
r.current.setShowFullAvatar(!0), console.log("Avatar initialized in full body mode");
|
|
7253
|
-
} catch (
|
|
7254
|
-
console.warn("Error setting full body mode on initialization:",
|
|
7251
|
+
} catch (q) {
|
|
7252
|
+
console.warn("Error setting full body mode on initialization:", q);
|
|
7255
7253
|
}
|
|
7256
7254
|
a(!1), b(!0), n(r.current);
|
|
7257
|
-
const
|
|
7255
|
+
const C = () => {
|
|
7258
7256
|
document.visibilityState === "visible" ? r.current?.start() : r.current?.stop();
|
|
7259
7257
|
};
|
|
7260
|
-
return document.addEventListener("visibilitychange",
|
|
7261
|
-
document.removeEventListener("visibilitychange",
|
|
7258
|
+
return document.addEventListener("visibilitychange", C), () => {
|
|
7259
|
+
document.removeEventListener("visibilitychange", C);
|
|
7262
7260
|
};
|
|
7263
7261
|
} catch (k) {
|
|
7264
7262
|
console.error("Error initializing TalkingHead:", k), c(k.message || "Failed to initialize avatar"), a(!1), e(k);
|
|
7265
7263
|
}
|
|
7266
7264
|
}, []);
|
|
7267
|
-
me(() => (
|
|
7265
|
+
me(() => (H(), () => {
|
|
7268
7266
|
r.current && (r.current.stop(), r.current.dispose(), r.current = null);
|
|
7269
|
-
}), [
|
|
7270
|
-
const y =
|
|
7267
|
+
}), [H]);
|
|
7268
|
+
const y = O((k) => {
|
|
7271
7269
|
if (r.current && g)
|
|
7272
7270
|
try {
|
|
7273
7271
|
console.log("Speaking text:", k), console.log("Avatar config:", p), console.log("TalkingHead instance:", r.current), r.current.lipsync && Object.keys(r.current.lipsync).length > 0 ? (console.log("Lip-sync modules loaded:", Object.keys(r.current.lipsync)), r.current.setSlowdownRate && (r.current.setSlowdownRate(1.05), console.log("Applied timing adjustment for better lip-sync")), r.current.speakText(k)) : (console.warn("Lip-sync modules not ready, waiting..."), setTimeout(() => {
|
|
7274
7272
|
r.current && r.current.lipsync ? (console.log("Lip-sync now ready, speaking..."), r.current.setSlowdownRate && (r.current.setSlowdownRate(1.05), console.log("Applied timing adjustment for better lip-sync")), r.current.speakText(k)) : console.error("Lip-sync still not ready after waiting");
|
|
7275
7273
|
}, 500));
|
|
7276
|
-
} catch (
|
|
7277
|
-
console.error("Error speaking text:",
|
|
7274
|
+
} catch (C) {
|
|
7275
|
+
console.error("Error speaking text:", C), c(C.message || "Failed to speak text");
|
|
7278
7276
|
}
|
|
7279
7277
|
else
|
|
7280
7278
|
console.warn("Avatar not ready for speaking. isReady:", g, "talkingHeadRef:", !!r.current);
|
|
7281
|
-
}, [g, p]), I =
|
|
7279
|
+
}, [g, p]), I = O(() => {
|
|
7282
7280
|
r.current && (r.current.stopSpeaking(), r.current.setSlowdownRate && (r.current.setSlowdownRate(1), console.log("Reset timing to normal")));
|
|
7283
|
-
}, []), z =
|
|
7281
|
+
}, []), z = O((k) => {
|
|
7284
7282
|
r.current && r.current.setMood(k);
|
|
7285
|
-
}, []), A =
|
|
7283
|
+
}, []), A = O((k) => {
|
|
7286
7284
|
r.current && r.current.setSlowdownRate && (r.current.setSlowdownRate(k), console.log("Timing adjustment set to:", k));
|
|
7287
|
-
}, []),
|
|
7285
|
+
}, []), Y = O((k, C = !1) => {
|
|
7288
7286
|
if (r.current && r.current.playAnimation) {
|
|
7289
7287
|
if (r.current.setShowFullAvatar)
|
|
7290
7288
|
try {
|
|
7291
7289
|
r.current.setShowFullAvatar(!0);
|
|
7292
|
-
} catch (
|
|
7293
|
-
console.warn("Error setting full body mode:",
|
|
7290
|
+
} catch (N) {
|
|
7291
|
+
console.warn("Error setting full body mode:", N);
|
|
7294
7292
|
}
|
|
7295
7293
|
if (k.includes("."))
|
|
7296
7294
|
try {
|
|
7297
|
-
r.current.playAnimation(k, null, 10, 0, 0.01,
|
|
7298
|
-
} catch (
|
|
7299
|
-
console.log(`Failed to play ${k}:`,
|
|
7295
|
+
r.current.playAnimation(k, null, 10, 0, 0.01, C), console.log("Playing animation:", k);
|
|
7296
|
+
} catch (N) {
|
|
7297
|
+
console.log(`Failed to play ${k}:`, N);
|
|
7300
7298
|
try {
|
|
7301
7299
|
r.current.setBodyMovement("idle"), console.log("Fallback to idle animation");
|
|
7302
7300
|
} catch ($) {
|
|
@@ -7304,11 +7302,11 @@ const pt = Me(({
|
|
|
7304
7302
|
}
|
|
7305
7303
|
}
|
|
7306
7304
|
else {
|
|
7307
|
-
const
|
|
7305
|
+
const N = [".fbx", ".glb", ".gltf"];
|
|
7308
7306
|
let $ = !1;
|
|
7309
|
-
for (const ie of
|
|
7307
|
+
for (const ie of N)
|
|
7310
7308
|
try {
|
|
7311
|
-
r.current.playAnimation(k + ie, null, 10, 0, 0.01,
|
|
7309
|
+
r.current.playAnimation(k + ie, null, 10, 0, 0.01, C), console.log("Playing animation:", k + ie), $ = !0;
|
|
7312
7310
|
break;
|
|
7313
7311
|
} catch {
|
|
7314
7312
|
console.log(`Failed to play ${k}${ie}, trying next format...`);
|
|
@@ -7330,15 +7328,15 @@ const pt = Me(({
|
|
|
7330
7328
|
stopSpeaking: I,
|
|
7331
7329
|
setMood: z,
|
|
7332
7330
|
setTimingAdjustment: A,
|
|
7333
|
-
playAnimation:
|
|
7331
|
+
playAnimation: Y,
|
|
7334
7332
|
isReady: g,
|
|
7335
7333
|
talkingHead: r.current,
|
|
7336
7334
|
setBodyMovement: (k) => {
|
|
7337
7335
|
if (r.current && r.current.setShowFullAvatar && r.current.setBodyMovement)
|
|
7338
7336
|
try {
|
|
7339
7337
|
r.current.setShowFullAvatar(!0), r.current.setBodyMovement(k), console.log("Body movement set with full body mode:", k);
|
|
7340
|
-
} catch (
|
|
7341
|
-
console.warn("Error setting body movement:",
|
|
7338
|
+
} catch (C) {
|
|
7339
|
+
console.warn("Error setting body movement:", C);
|
|
7342
7340
|
}
|
|
7343
7341
|
},
|
|
7344
7342
|
setMovementIntensity: (k) => r.current?.setMovementIntensity(k),
|
|
@@ -7354,8 +7352,8 @@ const pt = Me(({
|
|
|
7354
7352
|
if (r.current && r.current.setShowFullAvatar && r.current.playReaction)
|
|
7355
7353
|
try {
|
|
7356
7354
|
r.current.setShowFullAvatar(!0), r.current.playReaction(k), console.log("Reaction played with full body mode:", k);
|
|
7357
|
-
} catch (
|
|
7358
|
-
console.warn("Error playing reaction:",
|
|
7355
|
+
} catch (C) {
|
|
7356
|
+
console.warn("Error playing reaction:", C);
|
|
7359
7357
|
}
|
|
7360
7358
|
},
|
|
7361
7359
|
playCelebration: () => {
|
|
@@ -7370,8 +7368,8 @@ const pt = Me(({
|
|
|
7370
7368
|
if (r.current && r.current.setShowFullAvatar)
|
|
7371
7369
|
try {
|
|
7372
7370
|
r.current.setShowFullAvatar(k), console.log("Show full avatar set to:", k);
|
|
7373
|
-
} catch (
|
|
7374
|
-
console.warn("Error setting showFullAvatar:",
|
|
7371
|
+
} catch (C) {
|
|
7372
|
+
console.warn("Error setting showFullAvatar:", C);
|
|
7375
7373
|
}
|
|
7376
7374
|
},
|
|
7377
7375
|
lockAvatarPosition: () => {
|
|
@@ -7428,7 +7426,7 @@ const pt = Me(({
|
|
|
7428
7426
|
});
|
|
7429
7427
|
pt.displayName = "TalkingHeadComponent";
|
|
7430
7428
|
const gt = Me(({
|
|
7431
|
-
text:
|
|
7429
|
+
text: X = null,
|
|
7432
7430
|
avatarUrl: t = "/avatars/brunette.glb",
|
|
7433
7431
|
avatarBody: e = "F",
|
|
7434
7432
|
mood: n = "neutral",
|
|
@@ -7450,16 +7448,16 @@ const gt = Me(({
|
|
|
7450
7448
|
},
|
|
7451
7449
|
className: x = "",
|
|
7452
7450
|
style: S = {},
|
|
7453
|
-
animations:
|
|
7451
|
+
animations: G = {},
|
|
7454
7452
|
autoSpeak: p = !1
|
|
7455
|
-
},
|
|
7456
|
-
const
|
|
7453
|
+
}, B) => {
|
|
7454
|
+
const H = V(null), y = V(null), I = V(u), z = V(null), A = V(null), Y = V(!1), k = V({ remainingText: null, originalText: null, options: null }), C = V([]), [q, N] = de(!0), [$, ie] = de(null), [oe, he] = de(!1), [ee, ne] = de(!1);
|
|
7457
7455
|
me(() => {
|
|
7458
|
-
|
|
7459
|
-
}, [
|
|
7456
|
+
Y.current = ee;
|
|
7457
|
+
}, [ee]), me(() => {
|
|
7460
7458
|
I.current = u;
|
|
7461
7459
|
}, [u]);
|
|
7462
|
-
const
|
|
7460
|
+
const D = Ee(), v = s || D.service;
|
|
7463
7461
|
let R;
|
|
7464
7462
|
v === "browser" ? R = {
|
|
7465
7463
|
service: "browser",
|
|
@@ -7469,20 +7467,20 @@ const gt = Me(({
|
|
|
7469
7467
|
} : v === "elevenlabs" ? R = {
|
|
7470
7468
|
service: "elevenlabs",
|
|
7471
7469
|
endpoint: "https://api.elevenlabs.io/v1/text-to-speech",
|
|
7472
|
-
apiKey: l ||
|
|
7473
|
-
defaultVoice: o ||
|
|
7474
|
-
voices:
|
|
7470
|
+
apiKey: l || D.apiKey,
|
|
7471
|
+
defaultVoice: o || D.defaultVoice || Ie.defaultVoice,
|
|
7472
|
+
voices: D.voices || Ie.voices
|
|
7475
7473
|
} : v === "deepgram" ? R = {
|
|
7476
7474
|
service: "deepgram",
|
|
7477
7475
|
endpoint: "https://api.deepgram.com/v1/speak",
|
|
7478
|
-
apiKey: l ||
|
|
7479
|
-
defaultVoice: o ||
|
|
7480
|
-
voices:
|
|
7476
|
+
apiKey: l || D.apiKey,
|
|
7477
|
+
defaultVoice: o || D.defaultVoice || Te.defaultVoice,
|
|
7478
|
+
voices: D.voices || Te.voices
|
|
7481
7479
|
} : R = {
|
|
7482
|
-
...
|
|
7483
|
-
apiKey: l !== null ? l :
|
|
7480
|
+
...D,
|
|
7481
|
+
apiKey: l !== null ? l : D.apiKey
|
|
7484
7482
|
};
|
|
7485
|
-
const
|
|
7483
|
+
const T = {
|
|
7486
7484
|
url: t,
|
|
7487
7485
|
body: e,
|
|
7488
7486
|
avatarMood: n,
|
|
@@ -7492,25 +7490,25 @@ const gt = Me(({
|
|
|
7492
7490
|
showFullAvatar: u,
|
|
7493
7491
|
bodyMovement: h,
|
|
7494
7492
|
movementIntensity: r
|
|
7495
|
-
},
|
|
7493
|
+
}, F = {
|
|
7496
7494
|
ttsEndpoint: R.endpoint,
|
|
7497
7495
|
ttsApikey: R.apiKey,
|
|
7498
7496
|
ttsService: v,
|
|
7499
7497
|
lipsyncModules: ["en"],
|
|
7500
7498
|
cameraView: a
|
|
7501
|
-
},
|
|
7502
|
-
if (!(!
|
|
7499
|
+
}, P = O(async () => {
|
|
7500
|
+
if (!(!H.current || y.current))
|
|
7503
7501
|
try {
|
|
7504
|
-
|
|
7505
|
-
url:
|
|
7506
|
-
body:
|
|
7507
|
-
avatarMood:
|
|
7508
|
-
}), await y.current.showAvatar(
|
|
7502
|
+
N(!0), ie(null), y.current = new Be(H.current, F), console.log("Avatar config being passed:", {
|
|
7503
|
+
url: T.url,
|
|
7504
|
+
body: T.body,
|
|
7505
|
+
avatarMood: T.avatarMood
|
|
7506
|
+
}), await y.current.showAvatar(T, (se) => {
|
|
7509
7507
|
if (se.lengthComputable) {
|
|
7510
7508
|
const L = Math.min(100, Math.round(se.loaded / se.total * 100));
|
|
7511
7509
|
c(L);
|
|
7512
7510
|
}
|
|
7513
|
-
}), y.current?.avatar && console.log("Avatar body after initialization:", y.current.avatar.body),
|
|
7511
|
+
}), y.current?.avatar && console.log("Avatar body after initialization:", y.current.avatar.body), N(!1), he(!0), d(y.current);
|
|
7514
7512
|
const E = () => {
|
|
7515
7513
|
document.visibilityState === "visible" ? y.current?.start() : y.current?.stop();
|
|
7516
7514
|
};
|
|
@@ -7518,13 +7516,13 @@ const gt = Me(({
|
|
|
7518
7516
|
document.removeEventListener("visibilitychange", E);
|
|
7519
7517
|
};
|
|
7520
7518
|
} catch (E) {
|
|
7521
|
-
console.error("Error initializing TalkingHead:", E), ie(E.message || "Failed to initialize avatar"),
|
|
7519
|
+
console.error("Error initializing TalkingHead:", E), ie(E.message || "Failed to initialize avatar"), N(!1), g(E);
|
|
7522
7520
|
}
|
|
7523
7521
|
}, []);
|
|
7524
|
-
me(() => (
|
|
7522
|
+
me(() => (P(), () => {
|
|
7525
7523
|
y.current && (y.current.stop(), y.current.dispose(), y.current = null);
|
|
7526
|
-
}), [
|
|
7527
|
-
const
|
|
7524
|
+
}), [P]);
|
|
7525
|
+
const _ = O(async () => {
|
|
7528
7526
|
if (y.current)
|
|
7529
7527
|
try {
|
|
7530
7528
|
const E = y.current.audioCtx || y.current.audioContext;
|
|
@@ -7532,7 +7530,7 @@ const gt = Me(({
|
|
|
7532
7530
|
} catch (E) {
|
|
7533
7531
|
console.warn("Failed to resume audio context:", E);
|
|
7534
7532
|
}
|
|
7535
|
-
}, []),
|
|
7533
|
+
}, []), j = O(async (E, se = {}) => {
|
|
7536
7534
|
if (!y.current || !oe) {
|
|
7537
7535
|
console.warn("Avatar not ready for speaking");
|
|
7538
7536
|
return;
|
|
@@ -7541,59 +7539,59 @@ const gt = Me(({
|
|
|
7541
7539
|
console.warn("No text provided to speak");
|
|
7542
7540
|
return;
|
|
7543
7541
|
}
|
|
7544
|
-
await
|
|
7545
|
-
const L = E.split(/[.!?]+/).filter((
|
|
7546
|
-
|
|
7547
|
-
const
|
|
7542
|
+
await _(), k.current = { remainingText: null, originalText: null, options: null }, C.current = [], z.current = { text: E, options: se }, A.current && (clearInterval(A.current), A.current = null), ne(!1), Y.current = !1;
|
|
7543
|
+
const L = E.split(/[.!?]+/).filter((W) => W.trim().length > 0);
|
|
7544
|
+
C.current = L;
|
|
7545
|
+
const U = {
|
|
7548
7546
|
lipsyncLang: se.lipsyncLang || "en",
|
|
7549
7547
|
onSpeechEnd: () => {
|
|
7550
7548
|
A.current && (clearInterval(A.current), A.current = null), se.onSpeechEnd && se.onSpeechEnd(), b();
|
|
7551
7549
|
}
|
|
7552
7550
|
};
|
|
7553
7551
|
try {
|
|
7554
|
-
y.current.speakText(E,
|
|
7555
|
-
} catch (
|
|
7556
|
-
console.error("Error speaking text:",
|
|
7552
|
+
y.current.speakText(E, U);
|
|
7553
|
+
} catch (W) {
|
|
7554
|
+
console.error("Error speaking text:", W), ie(W.message || "Failed to speak text");
|
|
7557
7555
|
}
|
|
7558
|
-
}, [oe, b,
|
|
7556
|
+
}, [oe, b, _]);
|
|
7559
7557
|
me(() => {
|
|
7560
|
-
oe &&
|
|
7561
|
-
}, [oe,
|
|
7562
|
-
const J =
|
|
7558
|
+
oe && X && p && y.current && j(X);
|
|
7559
|
+
}, [oe, X, p, j]);
|
|
7560
|
+
const J = O(() => {
|
|
7563
7561
|
if (y.current)
|
|
7564
7562
|
try {
|
|
7565
7563
|
const E = y.current.isSpeaking || !1, se = y.current.audioPlaylist || [], L = y.current.speechQueue || [];
|
|
7566
7564
|
if (E || se.length > 0 || L.length > 0) {
|
|
7567
7565
|
A.current && (clearInterval(A.current), A.current = null);
|
|
7568
|
-
let
|
|
7569
|
-
L.length > 0 && (
|
|
7570
|
-
remainingText:
|
|
7566
|
+
let U = "";
|
|
7567
|
+
L.length > 0 && (U = L.map((W) => W.text && Array.isArray(W.text) ? W.text.map((te) => te.word).join(" ") : W.text || "").join(" ")), k.current = {
|
|
7568
|
+
remainingText: U || null,
|
|
7571
7569
|
originalText: z.current?.text || null,
|
|
7572
7570
|
options: z.current?.options || null
|
|
7573
|
-
}, y.current.speechQueue.length = 0, y.current.pauseSpeaking(), ne(!0),
|
|
7571
|
+
}, y.current.speechQueue.length = 0, y.current.pauseSpeaking(), ne(!0), Y.current = !0;
|
|
7574
7572
|
}
|
|
7575
7573
|
} catch (E) {
|
|
7576
7574
|
console.warn("Error pausing speech:", E);
|
|
7577
7575
|
}
|
|
7578
|
-
}, []), Ae =
|
|
7579
|
-
if (!(!y.current || !
|
|
7576
|
+
}, []), Ae = O(async () => {
|
|
7577
|
+
if (!(!y.current || !ee))
|
|
7580
7578
|
try {
|
|
7581
|
-
await
|
|
7582
|
-
const E = k.current?.remainingText, se = k.current?.originalText || z.current?.text, L = k.current?.options || z.current?.options || {},
|
|
7583
|
-
|
|
7579
|
+
await _(), ne(!1), Y.current = !1;
|
|
7580
|
+
const E = k.current?.remainingText, se = k.current?.originalText || z.current?.text, L = k.current?.options || z.current?.options || {}, U = E || se;
|
|
7581
|
+
U && j(U, L);
|
|
7584
7582
|
} catch (E) {
|
|
7585
|
-
console.warn("Error resuming speech:", E), ne(!1),
|
|
7583
|
+
console.warn("Error resuming speech:", E), ne(!1), Y.current = !1;
|
|
7586
7584
|
}
|
|
7587
|
-
}, [
|
|
7588
|
-
y.current && (y.current.stopSpeaking(), A.current && (clearInterval(A.current), A.current = null), ne(!1),
|
|
7585
|
+
}, [ee, j, _]), we = O(() => {
|
|
7586
|
+
y.current && (y.current.stopSpeaking(), A.current && (clearInterval(A.current), A.current = null), ne(!1), Y.current = !1);
|
|
7589
7587
|
}, []);
|
|
7590
|
-
return Fe(
|
|
7591
|
-
speakText:
|
|
7588
|
+
return Fe(B, () => ({
|
|
7589
|
+
speakText: j,
|
|
7592
7590
|
pauseSpeaking: J,
|
|
7593
7591
|
resumeSpeaking: Ae,
|
|
7594
7592
|
stopSpeaking: we,
|
|
7595
|
-
resumeAudioContext:
|
|
7596
|
-
isPaused: () =>
|
|
7593
|
+
resumeAudioContext: _,
|
|
7594
|
+
isPaused: () => ee,
|
|
7597
7595
|
setMood: (E) => y.current?.setMood(E),
|
|
7598
7596
|
setBodyMovement: (E) => {
|
|
7599
7597
|
y.current && y.current.setBodyMovement(E);
|
|
@@ -7612,7 +7610,7 @@ const gt = Me(({
|
|
|
7612
7610
|
/* @__PURE__ */ pe(
|
|
7613
7611
|
"div",
|
|
7614
7612
|
{
|
|
7615
|
-
ref:
|
|
7613
|
+
ref: H,
|
|
7616
7614
|
className: "talking-head-viewer",
|
|
7617
7615
|
style: {
|
|
7618
7616
|
width: "100%",
|
|
@@ -7621,7 +7619,7 @@ const gt = Me(({
|
|
|
7621
7619
|
}
|
|
7622
7620
|
}
|
|
7623
7621
|
),
|
|
7624
|
-
|
|
7622
|
+
q && /* @__PURE__ */ pe("div", { className: "loading-overlay", style: {
|
|
7625
7623
|
position: "absolute",
|
|
7626
7624
|
top: "50%",
|
|
7627
7625
|
left: "50%",
|
|
@@ -7646,7 +7644,7 @@ const gt = Me(({
|
|
|
7646
7644
|
});
|
|
7647
7645
|
gt.displayName = "SimpleTalkingAvatar";
|
|
7648
7646
|
const yt = Me(({
|
|
7649
|
-
curriculumData:
|
|
7647
|
+
curriculumData: X = null,
|
|
7650
7648
|
avatarConfig: t = {},
|
|
7651
7649
|
animations: e = {},
|
|
7652
7650
|
onLessonStart: n = () => {
|
|
@@ -7661,7 +7659,7 @@ const yt = Me(({
|
|
|
7661
7659
|
},
|
|
7662
7660
|
autoStart: h = !1
|
|
7663
7661
|
}, r) => {
|
|
7664
|
-
const u =
|
|
7662
|
+
const u = V(null), a = V({
|
|
7665
7663
|
currentModuleIndex: 0,
|
|
7666
7664
|
currentLessonIndex: 0,
|
|
7667
7665
|
currentQuestionIndex: 0,
|
|
@@ -7671,18 +7669,18 @@ const yt = Me(({
|
|
|
7671
7669
|
curriculumCompleted: !1,
|
|
7672
7670
|
score: 0,
|
|
7673
7671
|
totalQuestions: 0
|
|
7674
|
-
}), d =
|
|
7672
|
+
}), d = V({
|
|
7675
7673
|
onLessonStart: n,
|
|
7676
7674
|
onLessonComplete: i,
|
|
7677
7675
|
onQuestionAnswer: s,
|
|
7678
7676
|
onCurriculumComplete: o,
|
|
7679
7677
|
onCustomAction: l
|
|
7680
|
-
}), c =
|
|
7678
|
+
}), c = V(null), g = V(null), b = V(null), x = V(null), S = V(null), G = V(null), p = V(null), B = V(X?.curriculum || {
|
|
7681
7679
|
title: "Default Curriculum",
|
|
7682
7680
|
description: "No curriculum data provided",
|
|
7683
7681
|
language: "en",
|
|
7684
7682
|
modules: []
|
|
7685
|
-
}),
|
|
7683
|
+
}), H = V({
|
|
7686
7684
|
avatarUrl: t.avatarUrl || "/avatars/brunette.glb",
|
|
7687
7685
|
avatarBody: t.avatarBody || "F",
|
|
7688
7686
|
mood: t.mood || "happy",
|
|
@@ -7705,12 +7703,12 @@ const yt = Me(({
|
|
|
7705
7703
|
onCustomAction: l
|
|
7706
7704
|
};
|
|
7707
7705
|
}, [n, i, s, o, l]), me(() => {
|
|
7708
|
-
|
|
7706
|
+
B.current = X?.curriculum || {
|
|
7709
7707
|
title: "Default Curriculum",
|
|
7710
7708
|
description: "No curriculum data provided",
|
|
7711
7709
|
language: "en",
|
|
7712
7710
|
modules: []
|
|
7713
|
-
},
|
|
7711
|
+
}, H.current = {
|
|
7714
7712
|
avatarUrl: t.avatarUrl || "/avatars/brunette.glb",
|
|
7715
7713
|
avatarBody: t.avatarBody || "F",
|
|
7716
7714
|
mood: t.mood || "happy",
|
|
@@ -7724,8 +7722,8 @@ const yt = Me(({
|
|
|
7724
7722
|
animations: e,
|
|
7725
7723
|
lipsyncLang: "en"
|
|
7726
7724
|
};
|
|
7727
|
-
}, [
|
|
7728
|
-
const y =
|
|
7725
|
+
}, [X, t, e]);
|
|
7726
|
+
const y = O(() => (B.current || { modules: [] }).modules[a.current.currentModuleIndex]?.lessons[a.current.currentLessonIndex], []), I = O(() => y()?.questions[a.current.currentQuestionIndex], [y]), z = O((v, R) => R.type === "multiple_choice" || R.type === "true_false" ? v === R.answer : R.type === "code_test" && typeof v == "object" && v !== null ? v.passed === !0 : !1, []), A = O(() => {
|
|
7729
7727
|
a.current.lessonCompleted = !0, a.current.isQuestionMode = !1;
|
|
7730
7728
|
const v = a.current.totalQuestions > 0 ? Math.round(a.current.score / a.current.totalQuestions * 100) : 100;
|
|
7731
7729
|
let R = "Congratulations! You've completed this lesson";
|
|
@@ -7749,7 +7747,7 @@ const yt = Me(({
|
|
|
7749
7747
|
} catch {
|
|
7750
7748
|
u.current.playCelebration();
|
|
7751
7749
|
}
|
|
7752
|
-
const
|
|
7750
|
+
const T = B.current || { modules: [] }, F = T.modules[a.current.currentModuleIndex], P = a.current.currentLessonIndex < (F?.lessons?.length || 0) - 1, _ = a.current.currentModuleIndex < (T.modules?.length || 0) - 1, j = P || _, J = H.current || { lipsyncLang: "en" };
|
|
7753
7751
|
u.current.speakText(R, {
|
|
7754
7752
|
lipsyncLang: J.lipsyncLang,
|
|
7755
7753
|
onSpeechEnd: () => {
|
|
@@ -7760,17 +7758,17 @@ const yt = Me(({
|
|
|
7760
7758
|
score: a.current.score,
|
|
7761
7759
|
totalQuestions: a.current.totalQuestions,
|
|
7762
7760
|
percentage: v,
|
|
7763
|
-
hasNextLesson:
|
|
7761
|
+
hasNextLesson: j
|
|
7764
7762
|
});
|
|
7765
7763
|
}
|
|
7766
7764
|
});
|
|
7767
7765
|
}
|
|
7768
|
-
}, [e.lessonComplete]),
|
|
7766
|
+
}, [e.lessonComplete]), Y = O(() => {
|
|
7769
7767
|
a.current.curriculumCompleted = !0;
|
|
7770
|
-
const v =
|
|
7768
|
+
const v = B.current || { modules: [] };
|
|
7771
7769
|
if (d.current.onCurriculumComplete({
|
|
7772
7770
|
modules: v.modules.length,
|
|
7773
|
-
totalLessons: v.modules.reduce((R,
|
|
7771
|
+
totalLessons: v.modules.reduce((R, T) => R + T.lessons.length, 0)
|
|
7774
7772
|
}), u.current) {
|
|
7775
7773
|
if (u.current.setMood("celebrating"), e.curriculumComplete)
|
|
7776
7774
|
try {
|
|
@@ -7778,10 +7776,10 @@ const yt = Me(({
|
|
|
7778
7776
|
} catch {
|
|
7779
7777
|
u.current.playCelebration();
|
|
7780
7778
|
}
|
|
7781
|
-
const R =
|
|
7779
|
+
const R = H.current || { lipsyncLang: "en" };
|
|
7782
7780
|
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 });
|
|
7783
7781
|
}
|
|
7784
|
-
}, [e.curriculumComplete]), k =
|
|
7782
|
+
}, [e.curriculumComplete]), k = O(() => {
|
|
7785
7783
|
const v = y();
|
|
7786
7784
|
a.current.isQuestionMode = !0, a.current.currentQuestionIndex = 0, a.current.totalQuestions = v?.questions?.length || 0, a.current.score = 0;
|
|
7787
7785
|
const R = I();
|
|
@@ -7794,31 +7792,31 @@ const yt = Me(({
|
|
|
7794
7792
|
question: R,
|
|
7795
7793
|
score: a.current.score
|
|
7796
7794
|
});
|
|
7797
|
-
const
|
|
7795
|
+
const T = () => {
|
|
7798
7796
|
if (!u.current || !R) return;
|
|
7799
7797
|
if (u.current.setMood("happy"), e.questionStart)
|
|
7800
7798
|
try {
|
|
7801
7799
|
u.current.playAnimation(e.questionStart, !0);
|
|
7802
|
-
} catch (
|
|
7803
|
-
console.warn("Failed to play questionStart animation:",
|
|
7800
|
+
} catch (P) {
|
|
7801
|
+
console.warn("Failed to play questionStart animation:", P);
|
|
7804
7802
|
}
|
|
7805
|
-
const
|
|
7806
|
-
R.type === "code_test" ? u.current.speakText(`Let's test your coding skills! Here's your first challenge: ${R.question}`, { lipsyncLang:
|
|
7803
|
+
const F = H.current || { lipsyncLang: "en" };
|
|
7804
|
+
R.type === "code_test" ? u.current.speakText(`Let's test your coding skills! Here's your first challenge: ${R.question}`, { lipsyncLang: F.lipsyncLang }) : R.type === "multiple_choice" ? u.current.speakText(`Now let me ask you some questions. Here's the first one: ${R.question}`, { lipsyncLang: F.lipsyncLang }) : R.type === "true_false" ? u.current.speakText(`Let's start with some true or false questions. First question: ${R.question}`, { lipsyncLang: F.lipsyncLang }) : u.current.speakText(`Now let me ask you some questions. Here's the first one: ${R.question}`, { lipsyncLang: F.lipsyncLang });
|
|
7807
7805
|
};
|
|
7808
7806
|
if (u.current && u.current.isReady && R)
|
|
7809
|
-
|
|
7807
|
+
T();
|
|
7810
7808
|
else if (u.current && u.current.isReady) {
|
|
7811
|
-
const
|
|
7812
|
-
u.current.speakText("Now let me ask you some questions to test your understanding.", { lipsyncLang:
|
|
7809
|
+
const F = H.current || { lipsyncLang: "en" };
|
|
7810
|
+
u.current.speakText("Now let me ask you some questions to test your understanding.", { lipsyncLang: F.lipsyncLang });
|
|
7813
7811
|
} else {
|
|
7814
|
-
const
|
|
7815
|
-
u.current && u.current.isReady && (clearInterval(
|
|
7812
|
+
const F = setInterval(() => {
|
|
7813
|
+
u.current && u.current.isReady && (clearInterval(F), R && T());
|
|
7816
7814
|
}, 100);
|
|
7817
7815
|
setTimeout(() => {
|
|
7818
|
-
clearInterval(
|
|
7816
|
+
clearInterval(F);
|
|
7819
7817
|
}, 5e3);
|
|
7820
7818
|
}
|
|
7821
|
-
}, [e.questionStart, y, I]),
|
|
7819
|
+
}, [e.questionStart, y, I]), C = O(() => {
|
|
7822
7820
|
const v = y();
|
|
7823
7821
|
if (a.current.currentQuestionIndex < (v?.questions?.length || 0) - 1) {
|
|
7824
7822
|
u.current && u.current.stopSpeaking && u.current.stopSpeaking(), a.current.currentQuestionIndex += 1;
|
|
@@ -7832,7 +7830,7 @@ const yt = Me(({
|
|
|
7832
7830
|
question: R,
|
|
7833
7831
|
score: a.current.score
|
|
7834
7832
|
});
|
|
7835
|
-
const
|
|
7833
|
+
const T = () => {
|
|
7836
7834
|
if (!u.current || !R) return;
|
|
7837
7835
|
if (u.current.setMood("happy"), u.current.setBodyMovement("idle"), e.nextQuestion)
|
|
7838
7836
|
try {
|
|
@@ -7840,37 +7838,37 @@ const yt = Me(({
|
|
|
7840
7838
|
} catch (J) {
|
|
7841
7839
|
console.warn("Failed to play nextQuestion animation:", J);
|
|
7842
7840
|
}
|
|
7843
|
-
const
|
|
7841
|
+
const F = H.current || { lipsyncLang: "en" }, _ = y()?.questions?.length || 0, j = a.current.currentQuestionIndex >= _ - 1;
|
|
7844
7842
|
if (R.type === "code_test") {
|
|
7845
|
-
const J =
|
|
7843
|
+
const J = j ? `Great! Here's your final coding challenge: ${R.question}` : `Great! Now let's move on to your next coding challenge: ${R.question}`;
|
|
7846
7844
|
u.current.speakText(J, {
|
|
7847
|
-
lipsyncLang:
|
|
7845
|
+
lipsyncLang: F.lipsyncLang
|
|
7848
7846
|
});
|
|
7849
7847
|
} else if (R.type === "multiple_choice") {
|
|
7850
|
-
const J =
|
|
7848
|
+
const J = j ? `Alright! Here's your final question: ${R.question}` : `Alright! Here's your next question: ${R.question}`;
|
|
7851
7849
|
u.current.speakText(J, {
|
|
7852
|
-
lipsyncLang:
|
|
7850
|
+
lipsyncLang: F.lipsyncLang
|
|
7853
7851
|
});
|
|
7854
7852
|
} else if (R.type === "true_false") {
|
|
7855
|
-
const J =
|
|
7853
|
+
const J = j ? `Now let's try this final one: ${R.question}` : `Now let's try this one: ${R.question}`;
|
|
7856
7854
|
u.current.speakText(J, {
|
|
7857
|
-
lipsyncLang:
|
|
7855
|
+
lipsyncLang: F.lipsyncLang
|
|
7858
7856
|
});
|
|
7859
7857
|
} else {
|
|
7860
|
-
const J =
|
|
7858
|
+
const J = j ? `Here's your final question: ${R.question}` : `Here's the next question: ${R.question}`;
|
|
7861
7859
|
u.current.speakText(J, {
|
|
7862
|
-
lipsyncLang:
|
|
7860
|
+
lipsyncLang: F.lipsyncLang
|
|
7863
7861
|
});
|
|
7864
7862
|
}
|
|
7865
7863
|
};
|
|
7866
7864
|
if (u.current && u.current.isReady && R)
|
|
7867
|
-
|
|
7865
|
+
T();
|
|
7868
7866
|
else if (R) {
|
|
7869
|
-
const
|
|
7870
|
-
u.current && u.current.isReady && (clearInterval(
|
|
7867
|
+
const F = setInterval(() => {
|
|
7868
|
+
u.current && u.current.isReady && (clearInterval(F), T());
|
|
7871
7869
|
}, 100);
|
|
7872
7870
|
setTimeout(() => {
|
|
7873
|
-
clearInterval(
|
|
7871
|
+
clearInterval(F);
|
|
7874
7872
|
}, 5e3);
|
|
7875
7873
|
}
|
|
7876
7874
|
} else
|
|
@@ -7881,16 +7879,16 @@ const yt = Me(({
|
|
|
7881
7879
|
totalQuestions: a.current.totalQuestions,
|
|
7882
7880
|
score: a.current.score
|
|
7883
7881
|
});
|
|
7884
|
-
}, [e.nextQuestion, y, I]),
|
|
7885
|
-
const v =
|
|
7882
|
+
}, [e.nextQuestion, y, I]), q = O(() => {
|
|
7883
|
+
const v = B.current || { modules: [] }, R = v.modules[a.current.currentModuleIndex];
|
|
7886
7884
|
if (a.current.currentLessonIndex < (R?.lessons?.length || 0) - 1) {
|
|
7887
7885
|
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;
|
|
7888
|
-
const
|
|
7886
|
+
const F = v.modules[a.current.currentModuleIndex], P = a.current.currentLessonIndex < (F?.lessons?.length || 0) - 1, _ = a.current.currentModuleIndex < (v.modules?.length || 0) - 1, j = P || _;
|
|
7889
7887
|
d.current.onCustomAction({
|
|
7890
7888
|
type: "lessonStart",
|
|
7891
7889
|
moduleIndex: a.current.currentModuleIndex,
|
|
7892
7890
|
lessonIndex: a.current.currentLessonIndex,
|
|
7893
|
-
hasNextLesson:
|
|
7891
|
+
hasNextLesson: j
|
|
7894
7892
|
}), d.current.onLessonStart({
|
|
7895
7893
|
moduleIndex: a.current.currentModuleIndex,
|
|
7896
7894
|
lessonIndex: a.current.currentLessonIndex,
|
|
@@ -7898,7 +7896,7 @@ const yt = Me(({
|
|
|
7898
7896
|
}), u.current && (u.current.setMood("happy"), u.current.setBodyMovement("idle"));
|
|
7899
7897
|
} else if (a.current.currentModuleIndex < (v.modules?.length || 0) - 1) {
|
|
7900
7898
|
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;
|
|
7901
|
-
const
|
|
7899
|
+
const P = v.modules[a.current.currentModuleIndex], _ = a.current.currentLessonIndex < (P?.lessons?.length || 0) - 1, j = a.current.currentModuleIndex < (v.modules?.length || 0) - 1, J = _ || j;
|
|
7902
7900
|
d.current.onCustomAction({
|
|
7903
7901
|
type: "lessonStart",
|
|
7904
7902
|
moduleIndex: a.current.currentModuleIndex,
|
|
@@ -7911,25 +7909,25 @@ const yt = Me(({
|
|
|
7911
7909
|
}), u.current && (u.current.setMood("happy"), u.current.setBodyMovement("idle"));
|
|
7912
7910
|
} else
|
|
7913
7911
|
S.current && S.current();
|
|
7914
|
-
}, []),
|
|
7912
|
+
}, []), N = O(() => {
|
|
7915
7913
|
const v = y();
|
|
7916
7914
|
let R = null;
|
|
7917
7915
|
if (v?.avatar_script && v?.body) {
|
|
7918
|
-
const
|
|
7919
|
-
R = `${
|
|
7916
|
+
const T = v.avatar_script.trim(), F = v.body.trim(), P = T.match(/[.!?]$/) ? " " : ". ";
|
|
7917
|
+
R = `${T}${P}${F}`;
|
|
7920
7918
|
} else
|
|
7921
7919
|
R = v?.avatar_script || v?.body || null;
|
|
7922
7920
|
if (u.current && u.current.isReady && R) {
|
|
7923
7921
|
a.current.isTeaching = !0, a.current.isQuestionMode = !1, a.current.score = 0, a.current.totalQuestions = 0, u.current.setMood("happy");
|
|
7924
|
-
let
|
|
7922
|
+
let T = !1;
|
|
7925
7923
|
if (e.teaching)
|
|
7926
7924
|
try {
|
|
7927
|
-
u.current.playAnimation(e.teaching, !0),
|
|
7928
|
-
} catch (
|
|
7929
|
-
console.warn("Failed to play teaching animation:",
|
|
7925
|
+
u.current.playAnimation(e.teaching, !0), T = !0;
|
|
7926
|
+
} catch (P) {
|
|
7927
|
+
console.warn("Failed to play teaching animation:", P);
|
|
7930
7928
|
}
|
|
7931
|
-
|
|
7932
|
-
const
|
|
7929
|
+
T || u.current.setBodyMovement("gesturing");
|
|
7930
|
+
const F = H.current || { lipsyncLang: "en" };
|
|
7933
7931
|
d.current.onLessonStart({
|
|
7934
7932
|
moduleIndex: a.current.currentModuleIndex,
|
|
7935
7933
|
lessonIndex: a.current.currentLessonIndex,
|
|
@@ -7940,7 +7938,7 @@ const yt = Me(({
|
|
|
7940
7938
|
lessonIndex: a.current.currentLessonIndex,
|
|
7941
7939
|
lesson: v
|
|
7942
7940
|
}), u.current.speakText(R, {
|
|
7943
|
-
lipsyncLang:
|
|
7941
|
+
lipsyncLang: F.lipsyncLang,
|
|
7944
7942
|
onSpeechEnd: () => {
|
|
7945
7943
|
a.current.isTeaching = !1, d.current.onCustomAction({
|
|
7946
7944
|
type: "teachingComplete",
|
|
@@ -7958,17 +7956,17 @@ const yt = Me(({
|
|
|
7958
7956
|
}
|
|
7959
7957
|
});
|
|
7960
7958
|
}
|
|
7961
|
-
}, [e.teaching, y]), $ =
|
|
7962
|
-
const R = I(),
|
|
7963
|
-
if (
|
|
7959
|
+
}, [e.teaching, y]), $ = O((v) => {
|
|
7960
|
+
const R = I(), T = z(v, R);
|
|
7961
|
+
if (T && (a.current.score += 1), d.current.onQuestionAnswer({
|
|
7964
7962
|
moduleIndex: a.current.currentModuleIndex,
|
|
7965
7963
|
lessonIndex: a.current.currentLessonIndex,
|
|
7966
7964
|
questionIndex: a.current.currentQuestionIndex,
|
|
7967
7965
|
answer: v,
|
|
7968
|
-
isCorrect:
|
|
7966
|
+
isCorrect: T,
|
|
7969
7967
|
question: R
|
|
7970
7968
|
}), u.current)
|
|
7971
|
-
if (
|
|
7969
|
+
if (T) {
|
|
7972
7970
|
if (u.current.setMood("happy"), e.correct)
|
|
7973
7971
|
try {
|
|
7974
7972
|
u.current.playReaction("happy");
|
|
@@ -7976,12 +7974,12 @@ const yt = Me(({
|
|
|
7976
7974
|
u.current.setBodyMovement("happy");
|
|
7977
7975
|
}
|
|
7978
7976
|
u.current.setBodyMovement("gesturing");
|
|
7979
|
-
const
|
|
7980
|
-
a.current.currentQuestionIndex >=
|
|
7981
|
-
const
|
|
7982
|
-
console.log("[CurriculumLearning] Answer feedback - questionIndex:", a.current.currentQuestionIndex, "totalQuestions:",
|
|
7983
|
-
const
|
|
7984
|
-
u.current.speakText(
|
|
7977
|
+
const P = y()?.questions?.length || 0;
|
|
7978
|
+
a.current.currentQuestionIndex >= P - 1;
|
|
7979
|
+
const _ = a.current.currentQuestionIndex < P - 1;
|
|
7980
|
+
console.log("[CurriculumLearning] Answer feedback - questionIndex:", a.current.currentQuestionIndex, "totalQuestions:", P, "hasNextQuestion:", _);
|
|
7981
|
+
const j = R.type === "code_test" ? `Great job! Your code passed all the tests! ${R.explanation || ""}` : `Excellent! That's correct! ${R.explanation || ""}`, J = H.current || { lipsyncLang: "en" };
|
|
7982
|
+
u.current.speakText(j, {
|
|
7985
7983
|
lipsyncLang: J.lipsyncLang,
|
|
7986
7984
|
onSpeechEnd: () => {
|
|
7987
7985
|
d.current.onCustomAction({
|
|
@@ -7990,7 +7988,7 @@ const yt = Me(({
|
|
|
7990
7988
|
lessonIndex: a.current.currentLessonIndex,
|
|
7991
7989
|
questionIndex: a.current.currentQuestionIndex,
|
|
7992
7990
|
isCorrect: !0,
|
|
7993
|
-
hasNextQuestion:
|
|
7991
|
+
hasNextQuestion: _,
|
|
7994
7992
|
score: a.current.score,
|
|
7995
7993
|
totalQuestions: a.current.totalQuestions
|
|
7996
7994
|
});
|
|
@@ -8004,9 +8002,9 @@ const yt = Me(({
|
|
|
8004
8002
|
u.current.setBodyMovement("idle");
|
|
8005
8003
|
}
|
|
8006
8004
|
u.current.setBodyMovement("gesturing");
|
|
8007
|
-
const
|
|
8008
|
-
console.log("[CurriculumLearning] Answer feedback (incorrect) - questionIndex:", a.current.currentQuestionIndex, "totalQuestions:",
|
|
8009
|
-
const J = R.type === "code_test" ? `Your code didn't pass all the tests. ${R.explanation || "Try again!"}` : `Not quite right, but don't worry! ${R.explanation || ""}${
|
|
8005
|
+
const P = y()?.questions?.length || 0, _ = a.current.currentQuestionIndex >= P - 1, j = a.current.currentQuestionIndex < P - 1;
|
|
8006
|
+
console.log("[CurriculumLearning] Answer feedback (incorrect) - questionIndex:", a.current.currentQuestionIndex, "totalQuestions:", P, "hasNextQuestion:", j);
|
|
8007
|
+
const J = R.type === "code_test" ? `Your code didn't pass all the tests. ${R.explanation || "Try again!"}` : `Not quite right, but don't worry! ${R.explanation || ""}${_ ? "" : " Let's move on to the next question."}`, Ae = H.current || { lipsyncLang: "en" };
|
|
8010
8008
|
u.current.speakText(J, {
|
|
8011
8009
|
lipsyncLang: Ae.lipsyncLang,
|
|
8012
8010
|
onSpeechEnd: () => {
|
|
@@ -8016,7 +8014,7 @@ const yt = Me(({
|
|
|
8016
8014
|
lessonIndex: a.current.currentLessonIndex,
|
|
8017
8015
|
questionIndex: a.current.currentQuestionIndex,
|
|
8018
8016
|
isCorrect: !1,
|
|
8019
|
-
hasNextQuestion:
|
|
8017
|
+
hasNextQuestion: j,
|
|
8020
8018
|
score: a.current.score,
|
|
8021
8019
|
totalQuestions: a.current.totalQuestions
|
|
8022
8020
|
});
|
|
@@ -8024,20 +8022,20 @@ const yt = Me(({
|
|
|
8024
8022
|
});
|
|
8025
8023
|
}
|
|
8026
8024
|
else {
|
|
8027
|
-
const
|
|
8025
|
+
const P = y()?.questions?.length || 0;
|
|
8028
8026
|
d.current.onCustomAction({
|
|
8029
8027
|
type: "answerFeedbackComplete",
|
|
8030
8028
|
moduleIndex: a.current.currentModuleIndex,
|
|
8031
8029
|
lessonIndex: a.current.currentLessonIndex,
|
|
8032
8030
|
questionIndex: a.current.currentQuestionIndex,
|
|
8033
|
-
isCorrect:
|
|
8034
|
-
hasNextQuestion: a.current.currentQuestionIndex <
|
|
8031
|
+
isCorrect: T,
|
|
8032
|
+
hasNextQuestion: a.current.currentQuestionIndex < P - 1,
|
|
8035
8033
|
score: a.current.score,
|
|
8036
8034
|
totalQuestions: a.current.totalQuestions,
|
|
8037
8035
|
avatarNotReady: !0
|
|
8038
8036
|
});
|
|
8039
8037
|
}
|
|
8040
|
-
}, [e.correct, e.incorrect, I, y, z]), ie =
|
|
8038
|
+
}, [e.correct, e.incorrect, I, y, z]), ie = O((v) => {
|
|
8041
8039
|
const R = I();
|
|
8042
8040
|
if (!v || typeof v != "object") {
|
|
8043
8041
|
console.error("Invalid code test result format. Expected object with {passed: boolean, ...}");
|
|
@@ -8047,7 +8045,7 @@ const yt = Me(({
|
|
|
8047
8045
|
console.warn("Current question is not a code test. Use handleAnswerSelect for other question types.");
|
|
8048
8046
|
return;
|
|
8049
8047
|
}
|
|
8050
|
-
const
|
|
8048
|
+
const T = {
|
|
8051
8049
|
passed: v.passed === !0,
|
|
8052
8050
|
results: v.results || [],
|
|
8053
8051
|
output: v.output || "",
|
|
@@ -8062,10 +8060,10 @@ const yt = Me(({
|
|
|
8062
8060
|
moduleIndex: a.current.currentModuleIndex,
|
|
8063
8061
|
lessonIndex: a.current.currentLessonIndex,
|
|
8064
8062
|
questionIndex: a.current.currentQuestionIndex,
|
|
8065
|
-
testResult:
|
|
8063
|
+
testResult: T,
|
|
8066
8064
|
question: R
|
|
8067
|
-
}), p.current && p.current(
|
|
8068
|
-
}, [I, z]), oe =
|
|
8065
|
+
}), p.current && p.current(T);
|
|
8066
|
+
}, [I, z]), oe = O(() => {
|
|
8069
8067
|
if (a.current.currentQuestionIndex > 0) {
|
|
8070
8068
|
a.current.currentQuestionIndex -= 1;
|
|
8071
8069
|
const v = I();
|
|
@@ -8081,26 +8079,26 @@ const yt = Me(({
|
|
|
8081
8079
|
const R = () => {
|
|
8082
8080
|
if (!u.current || !v) return;
|
|
8083
8081
|
u.current.setMood("happy"), u.current.setBodyMovement("idle");
|
|
8084
|
-
const
|
|
8082
|
+
const T = H.current || { lipsyncLang: "en" };
|
|
8085
8083
|
v.type === "code_test" ? u.current.speakText(`Let's go back to this coding challenge: ${v.question}`, {
|
|
8086
|
-
lipsyncLang:
|
|
8084
|
+
lipsyncLang: T.lipsyncLang
|
|
8087
8085
|
}) : u.current.speakText(`Going back to: ${v.question}`, {
|
|
8088
|
-
lipsyncLang:
|
|
8086
|
+
lipsyncLang: T.lipsyncLang
|
|
8089
8087
|
});
|
|
8090
8088
|
};
|
|
8091
8089
|
if (u.current && u.current.isReady && v)
|
|
8092
8090
|
R();
|
|
8093
8091
|
else if (v) {
|
|
8094
|
-
const
|
|
8095
|
-
u.current && u.current.isReady && (clearInterval(
|
|
8092
|
+
const T = setInterval(() => {
|
|
8093
|
+
u.current && u.current.isReady && (clearInterval(T), R());
|
|
8096
8094
|
}, 100);
|
|
8097
8095
|
setTimeout(() => {
|
|
8098
|
-
clearInterval(
|
|
8096
|
+
clearInterval(T);
|
|
8099
8097
|
}, 5e3);
|
|
8100
8098
|
}
|
|
8101
8099
|
}
|
|
8102
|
-
}, [I]),
|
|
8103
|
-
const v =
|
|
8100
|
+
}, [I]), he = O(() => {
|
|
8101
|
+
const v = B.current || { modules: [] };
|
|
8104
8102
|
if (v.modules[a.current.currentModuleIndex], a.current.currentLessonIndex > 0)
|
|
8105
8103
|
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({
|
|
8106
8104
|
type: "lessonStart",
|
|
@@ -8112,8 +8110,8 @@ const yt = Me(({
|
|
|
8112
8110
|
lesson: y()
|
|
8113
8111
|
}), u.current && (u.current.setMood("happy"), u.current.setBodyMovement("idle"));
|
|
8114
8112
|
else if (a.current.currentModuleIndex > 0) {
|
|
8115
|
-
const
|
|
8116
|
-
a.current.currentModuleIndex -= 1, a.current.currentLessonIndex = (
|
|
8113
|
+
const F = v.modules[a.current.currentModuleIndex - 1];
|
|
8114
|
+
a.current.currentModuleIndex -= 1, a.current.currentLessonIndex = (F?.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({
|
|
8117
8115
|
type: "lessonStart",
|
|
8118
8116
|
moduleIndex: a.current.currentModuleIndex,
|
|
8119
8117
|
lessonIndex: a.current.currentLessonIndex
|
|
@@ -8123,30 +8121,30 @@ const yt = Me(({
|
|
|
8123
8121
|
lesson: y()
|
|
8124
8122
|
}), u.current && (u.current.setMood("happy"), u.current.setBodyMovement("idle"));
|
|
8125
8123
|
}
|
|
8126
|
-
}, [y]),
|
|
8124
|
+
}, [y]), ee = O(() => {
|
|
8127
8125
|
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;
|
|
8128
|
-
}, []), ne =
|
|
8126
|
+
}, []), ne = O((v) => {
|
|
8129
8127
|
console.log("Avatar is ready!", v);
|
|
8130
|
-
const R = y(),
|
|
8131
|
-
h &&
|
|
8128
|
+
const R = y(), T = R?.avatar_script || R?.body;
|
|
8129
|
+
h && T && setTimeout(() => {
|
|
8132
8130
|
c.current && c.current();
|
|
8133
8131
|
}, 10);
|
|
8134
8132
|
}, [h, y]);
|
|
8135
8133
|
Xe(() => {
|
|
8136
|
-
c.current =
|
|
8134
|
+
c.current = N, g.current = q, b.current = A, x.current = C, S.current = Y, G.current = k, p.current = $;
|
|
8137
8135
|
}), Fe(r, () => ({
|
|
8138
8136
|
// Curriculum control methods
|
|
8139
|
-
startTeaching:
|
|
8137
|
+
startTeaching: N,
|
|
8140
8138
|
startQuestions: k,
|
|
8141
8139
|
handleAnswerSelect: $,
|
|
8142
8140
|
handleCodeTestResult: ie,
|
|
8143
|
-
nextQuestion:
|
|
8141
|
+
nextQuestion: C,
|
|
8144
8142
|
previousQuestion: oe,
|
|
8145
|
-
nextLesson:
|
|
8146
|
-
previousLesson:
|
|
8143
|
+
nextLesson: q,
|
|
8144
|
+
previousLesson: he,
|
|
8147
8145
|
completeLesson: A,
|
|
8148
|
-
completeCurriculum:
|
|
8149
|
-
resetCurriculum:
|
|
8146
|
+
completeCurriculum: Y,
|
|
8147
|
+
resetCurriculum: ee,
|
|
8150
8148
|
getState: () => ({ ...a.current }),
|
|
8151
8149
|
getCurrentQuestion: () => I(),
|
|
8152
8150
|
getCurrentLesson: () => y(),
|
|
@@ -8155,8 +8153,8 @@ const yt = Me(({
|
|
|
8155
8153
|
// Convenience methods that delegate to avatar (always check current ref)
|
|
8156
8154
|
speakText: async (v, R = {}) => {
|
|
8157
8155
|
await u.current?.resumeAudioContext?.();
|
|
8158
|
-
const
|
|
8159
|
-
u.current?.speakText(v, { ...R, lipsyncLang: R.lipsyncLang ||
|
|
8156
|
+
const T = H.current || { lipsyncLang: "en" };
|
|
8157
|
+
u.current?.speakText(v, { ...R, lipsyncLang: R.lipsyncLang || T.lipsyncLang });
|
|
8160
8158
|
},
|
|
8161
8159
|
resumeAudioContext: async () => {
|
|
8162
8160
|
if (u.current?.resumeAudioContext)
|
|
@@ -8167,8 +8165,8 @@ const yt = Me(({
|
|
|
8167
8165
|
if (R.state === "suspended" || R.state === "interrupted")
|
|
8168
8166
|
try {
|
|
8169
8167
|
await R.resume(), console.log("Audio context resumed via talkingHead");
|
|
8170
|
-
} catch (
|
|
8171
|
-
console.warn("Failed to resume audio context:",
|
|
8168
|
+
} catch (T) {
|
|
8169
|
+
console.warn("Failed to resume audio context:", T);
|
|
8172
8170
|
}
|
|
8173
8171
|
} else
|
|
8174
8172
|
console.warn("Audio context not available yet");
|
|
@@ -8200,8 +8198,8 @@ const yt = Me(({
|
|
|
8200
8198
|
handleResize: () => u.current?.handleResize(),
|
|
8201
8199
|
// Avatar readiness check (always returns current value)
|
|
8202
8200
|
isAvatarReady: () => u.current?.isReady || !1
|
|
8203
|
-
}), [
|
|
8204
|
-
const
|
|
8201
|
+
}), [N, k, $, ie, C, q, A, Y, ee, I, y]);
|
|
8202
|
+
const D = H.current || {
|
|
8205
8203
|
avatarUrl: "/avatars/brunette.glb",
|
|
8206
8204
|
avatarBody: "F",
|
|
8207
8205
|
mood: "happy",
|
|
@@ -8218,18 +8216,18 @@ const yt = Me(({
|
|
|
8218
8216
|
Ve,
|
|
8219
8217
|
{
|
|
8220
8218
|
ref: u,
|
|
8221
|
-
avatarUrl:
|
|
8222
|
-
avatarBody:
|
|
8223
|
-
mood:
|
|
8224
|
-
ttsLang:
|
|
8225
|
-
ttsService:
|
|
8226
|
-
ttsVoice:
|
|
8227
|
-
ttsApiKey:
|
|
8228
|
-
bodyMovement:
|
|
8229
|
-
movementIntensity:
|
|
8230
|
-
showFullAvatar:
|
|
8219
|
+
avatarUrl: D.avatarUrl,
|
|
8220
|
+
avatarBody: D.avatarBody,
|
|
8221
|
+
mood: D.mood,
|
|
8222
|
+
ttsLang: D.ttsLang,
|
|
8223
|
+
ttsService: D.ttsService,
|
|
8224
|
+
ttsVoice: D.ttsVoice,
|
|
8225
|
+
ttsApiKey: D.ttsApiKey,
|
|
8226
|
+
bodyMovement: D.bodyMovement,
|
|
8227
|
+
movementIntensity: D.movementIntensity,
|
|
8228
|
+
showFullAvatar: D.showFullAvatar,
|
|
8231
8229
|
cameraView: "upper",
|
|
8232
|
-
animations:
|
|
8230
|
+
animations: D.animations,
|
|
8233
8231
|
onReady: ne,
|
|
8234
8232
|
onLoading: () => {
|
|
8235
8233
|
},
|
|
@@ -8343,7 +8341,7 @@ const Ge = {
|
|
|
8343
8341
|
duration: 5e3,
|
|
8344
8342
|
description: "Excited, energetic movement"
|
|
8345
8343
|
}
|
|
8346
|
-
}, wt = (
|
|
8344
|
+
}, wt = (X) => Ge[X] || null, zt = (X) => Ge.hasOwnProperty(X);
|
|
8347
8345
|
export {
|
|
8348
8346
|
yt as CurriculumLearning,
|
|
8349
8347
|
gt as SimpleTalkingAvatar,
|