@sage-rsc/talking-head-react 1.2.0 → 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 +332 -340
- package/package.json +1 -1
- package/src/lib/talkinghead.mjs +19 -13
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 V, useState as de, useEffect as me, useCallback 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";
|
|
@@ -8,7 +8,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
10
|
let m, le, ue;
|
|
11
|
-
const w = [0, 0, 0, 0],
|
|
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
|
-
},
|
|
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();
|
|
@@ -4400,7 +4400,7 @@ class Be {
|
|
|
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 ? (
|
|
4403
|
+
n.isQuaternion ? (K.setFromEuler(Z), n.multiply(K)) : n.isVector3 && n.add(Z);
|
|
4404
4404
|
}
|
|
4405
4405
|
}
|
|
4406
4406
|
/**
|
|
@@ -5193,7 +5193,7 @@ class Be {
|
|
|
5193
5193
|
eyeLookOutRight: [null, 0],
|
|
5194
5194
|
eyeContact: [0]
|
|
5195
5195
|
}
|
|
5196
|
-
})))), e > 2 * this.animFrameDur && (e = 2 * this.animFrameDur), (this.viewName !== "full" || this.isAvatarOnly) && (n = this.mtRandomized[Math.floor(Math.random() * this.mtRandomized.length)], i = this.mtAvatar[n], i.needsUpdate || Object.assign(i, { base: (this.mood.baseline[n] || 0) + (1 + l / 255) * Math.random() / 5, needsUpdate: !0 })), this.updatePoseBase(this.animClock), this.mixer && this.mixer.update(e / 1e3 * this.mixer.timeScale), this.updatePoseDelta(), (this.isSpeaking || this.isListening) && h ? l > this.volumeMax ? (this.volumeHeadBase = 0.05, Math.random() > 0.6 && (this.volumeHeadTarget = -0.05 - Math.random() / 15), this.volumeMax = l) : (this.volumeMax *= 0.92, this.volumeHeadTarget = this.volumeHeadBase - 0.9 * (this.volumeHeadBase - this.volumeHeadTarget)) : (this.volumeHeadTarget = 0, this.volumeMax = 0), n = this.volumeHeadTarget - this.volumeHeadCurrent, i = Math.abs(n), i > 1e-4 && (o = i * (this.volumeHeadEasing(Math.min(1, this.volumeHeadVelocity * e / 1e3 / i) / 2 + 0.5) - 0.5), this.volumeHeadCurrent += Math.sign(n) * Math.min(i, o)), Math.abs(this.volumeHeadCurrent) > 1e-4 && (
|
|
5196
|
+
})))), e > 2 * this.animFrameDur && (e = 2 * this.animFrameDur), (this.viewName !== "full" || this.isAvatarOnly) && (n = this.mtRandomized[Math.floor(Math.random() * this.mtRandomized.length)], i = this.mtAvatar[n], i.needsUpdate || Object.assign(i, { base: (this.mood.baseline[n] || 0) + (1 + l / 255) * Math.random() / 5, needsUpdate: !0 })), this.updatePoseBase(this.animClock), this.mixer && this.mixer.update(e / 1e3 * this.mixer.timeScale), this.updatePoseDelta(), (this.isSpeaking || this.isListening) && h ? l > this.volumeMax ? (this.volumeHeadBase = 0.05, Math.random() > 0.6 && (this.volumeHeadTarget = -0.05 - Math.random() / 15), this.volumeMax = l) : (this.volumeMax *= 0.92, this.volumeHeadTarget = this.volumeHeadBase - 0.9 * (this.volumeHeadBase - this.volumeHeadTarget)) : (this.volumeHeadTarget = 0, this.volumeMax = 0), n = this.volumeHeadTarget - this.volumeHeadCurrent, i = Math.abs(n), i > 1e-4 && (o = i * (this.volumeHeadEasing(Math.min(1, this.volumeHeadVelocity * e / 1e3 / i) / 2 + 0.5) - 0.5), this.volumeHeadCurrent += Math.sign(n) * Math.min(i, o)), Math.abs(this.volumeHeadCurrent) > 1e-4 && (K.setFromAxisAngle(mt, this.volumeHeadCurrent), this.objectNeck.quaternion.multiply(K)), We.setFromObject(this.armature), this.objectLeftToeBase.getWorldPosition(ve), ve.sub(this.armature.position), this.objectRightToeBase.getWorldPosition(Re), Re.sub(this.armature.position), this.objectHips.position.y -= We.min.y / 2, this.objectHips.position.x -= (ve.x + Re.x) / 4, this.objectHips.position.z -= (ve.z + Re.z) / 2, this.dynamicbones.update(e), this.fbxAnimationLoader && this.fbxAnimationLoader.update(), this.opt.update && this.opt.update(e), this.updateMorphTargets(e), this.isAvatarOnly)
|
|
5197
5197
|
this.stats && this.stats.end();
|
|
5198
5198
|
else {
|
|
5199
5199
|
if (this.cameraClock !== null && this.cameraClock < 1e3) {
|
|
@@ -5266,8 +5266,8 @@ class Be {
|
|
|
5266
5266
|
for (let x = 0; x < b.length; x++) {
|
|
5267
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
|
}
|
|
@@ -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,8 +5498,8 @@ 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 H = x.visemes[
|
|
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)],
|
|
@@ -6159,10 +6159,10 @@ class Be {
|
|
|
6159
6159
|
this.lookAt(null, null, t);
|
|
6160
6160
|
return;
|
|
6161
6161
|
}
|
|
6162
|
-
this.objectLeftEye.updateMatrixWorld(!0), this.objectRightEye.updateMatrixWorld(!0), ve.setFromMatrixPosition(this.objectLeftEye.matrixWorld), Re.setFromMatrixPosition(this.objectRightEye.matrixWorld), ve.add(Re).divideScalar(2),
|
|
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
6164
|
Z.set(s, i, 0, "YXZ");
|
|
6165
|
-
const l = new f.Quaternion().setFromEuler(Z), h = new f.Quaternion().copy(l).multiply(
|
|
6165
|
+
const l = new f.Quaternion().setFromEuler(Z), h = new f.Quaternion().copy(l).multiply(K.clone().invert());
|
|
6166
6166
|
Z.setFromQuaternion(h, "YXZ");
|
|
6167
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) {
|
|
@@ -6199,13 +6199,13 @@ 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),
|
|
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
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
6205
|
let G = (Math.random() - 0.5) / 4, p = (Math.random() - 0.5) / 4;
|
|
6206
6206
|
if (n) {
|
|
6207
|
-
let
|
|
6208
|
-
|
|
6207
|
+
let B = this.animQueue.findIndex((y) => y.template.name === "lookat");
|
|
6208
|
+
B !== -1 && this.animQueue.splice(B, 1);
|
|
6209
6209
|
const H = {
|
|
6210
6210
|
name: "lookat",
|
|
6211
6211
|
dt: [750, n],
|
|
@@ -6539,37 +6539,29 @@ class Be {
|
|
|
6539
6539
|
(I) => I.includes("Arm") || I.includes("Hand") || I.includes("Shoulder")
|
|
6540
6540
|
);
|
|
6541
6541
|
console.log("FBX arm/hand/shoulder bones:", S.sort().join(", ")), console.log("Avatar arm/hand/shoulder bones:", G.sort().join(", "));
|
|
6542
|
-
const p = [],
|
|
6542
|
+
const p = [], B = /* @__PURE__ */ new Set();
|
|
6543
6543
|
if (d.tracks.forEach((I) => {
|
|
6544
6544
|
const A = I.name.replaceAll("mixamorig", "").split("."), Y = A[0], k = A[1], C = b(Y);
|
|
6545
6545
|
if (C && k) {
|
|
6546
|
-
const
|
|
6547
|
-
|
|
6548
|
-
const
|
|
6549
|
-
C.includes("
|
|
6550
|
-
const
|
|
6551
|
-
if (
|
|
6552
|
-
const
|
|
6553
|
-
for (let
|
|
6554
|
-
const
|
|
6555
|
-
if (
|
|
6556
|
-
let
|
|
6557
|
-
|
|
6558
|
-
if (oe) {
|
|
6559
|
-
const O = new f.Quaternion().setFromAxisAngle(new f.Vector3(0, 1, 0), Math.PI);
|
|
6560
|
-
M.multiply(O);
|
|
6561
|
-
} else if (ie) {
|
|
6562
|
-
const O = new f.Quaternion().setFromAxisAngle(new f.Vector3(0, 0, 1), Math.PI / 2);
|
|
6563
|
-
M.multiply(O);
|
|
6564
|
-
}
|
|
6565
|
-
B.values[Q] = M.x, B.values[Q + 1] = M.y, B.values[Q + 2] = M.z, B.values[Q + 3] = M.w;
|
|
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;
|
|
6566
6558
|
}
|
|
6567
6559
|
}
|
|
6568
6560
|
}
|
|
6569
|
-
p.push(
|
|
6561
|
+
p.push(N), Y !== C && g.set(Y, C);
|
|
6570
6562
|
} else
|
|
6571
|
-
|
|
6572
|
-
}),
|
|
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) {
|
|
6573
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(
|
|
6574
6566
|
`✓ Mapped ${g.size} bone(s):`,
|
|
6575
6567
|
Array.from(g.entries()).map(([z, A]) => `${z}→${A}`).join(", ")
|
|
@@ -6730,11 +6722,11 @@ class Be {
|
|
|
6730
6722
|
if (e)
|
|
6731
6723
|
for (let S = 0; S < x; S++) {
|
|
6732
6724
|
let G = !1;
|
|
6733
|
-
for (let p = 0,
|
|
6725
|
+
for (let p = 0, B = b.length; p < B; p++) {
|
|
6734
6726
|
const H = b[p].bone;
|
|
6735
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();
|
|
6736
6728
|
let y = s.dot(l);
|
|
6737
|
-
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(),
|
|
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(
|
|
6738
6730
|
b[p].minx !== void 0 ? b[p].minx : -1 / 0,
|
|
6739
6731
|
b[p].miny !== void 0 ? b[p].miny : -1 / 0,
|
|
6740
6732
|
b[p].minz !== void 0 ? b[p].minz : -1 / 0
|
|
@@ -6837,117 +6829,117 @@ const Ve = Me(({
|
|
|
6837
6829
|
style: b = {},
|
|
6838
6830
|
animations: x = {}
|
|
6839
6831
|
}, S) => {
|
|
6840
|
-
const G = V(null), p = V(null),
|
|
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);
|
|
6841
6833
|
me(() => {
|
|
6842
6834
|
I.current = oe;
|
|
6843
6835
|
}, [oe]), me(() => {
|
|
6844
|
-
|
|
6836
|
+
B.current = r;
|
|
6845
6837
|
}, [r]);
|
|
6846
|
-
const
|
|
6847
|
-
let
|
|
6848
|
-
|
|
6838
|
+
const ee = Ee(), ne = i || ee.service;
|
|
6839
|
+
let D;
|
|
6840
|
+
ne === "browser" ? D = {
|
|
6849
6841
|
service: "browser",
|
|
6850
6842
|
endpoint: "",
|
|
6851
6843
|
apiKey: null,
|
|
6852
6844
|
defaultVoice: "Google US English"
|
|
6853
|
-
} :
|
|
6845
|
+
} : ne === "elevenlabs" ? D = {
|
|
6854
6846
|
service: "elevenlabs",
|
|
6855
6847
|
endpoint: "https://api.elevenlabs.io/v1/text-to-speech",
|
|
6856
|
-
apiKey: o ||
|
|
6857
|
-
defaultVoice: s ||
|
|
6858
|
-
voices:
|
|
6859
|
-
} :
|
|
6848
|
+
apiKey: o || ee.apiKey,
|
|
6849
|
+
defaultVoice: s || ee.defaultVoice || Ie.defaultVoice,
|
|
6850
|
+
voices: ee.voices || Ie.voices
|
|
6851
|
+
} : ne === "deepgram" ? D = {
|
|
6860
6852
|
service: "deepgram",
|
|
6861
6853
|
endpoint: "https://api.deepgram.com/v1/speak",
|
|
6862
|
-
apiKey: o ||
|
|
6863
|
-
defaultVoice: s ||
|
|
6864
|
-
voices:
|
|
6865
|
-
} :
|
|
6866
|
-
...
|
|
6854
|
+
apiKey: o || ee.apiKey,
|
|
6855
|
+
defaultVoice: s || ee.defaultVoice || Te.defaultVoice,
|
|
6856
|
+
voices: ee.voices || Te.voices
|
|
6857
|
+
} : D = {
|
|
6858
|
+
...ee,
|
|
6867
6859
|
// Override API key if provided via props
|
|
6868
|
-
apiKey: o !== null ? o :
|
|
6860
|
+
apiKey: o !== null ? o : ee.apiKey
|
|
6869
6861
|
};
|
|
6870
6862
|
const v = {
|
|
6871
6863
|
url: X,
|
|
6872
6864
|
body: t,
|
|
6873
6865
|
avatarMood: e,
|
|
6874
|
-
ttsLang:
|
|
6875
|
-
ttsVoice: s ||
|
|
6866
|
+
ttsLang: ne === "browser" ? "en-US" : n,
|
|
6867
|
+
ttsVoice: s || D.defaultVoice,
|
|
6876
6868
|
lipsyncLang: "en",
|
|
6877
6869
|
showFullAvatar: r,
|
|
6878
6870
|
bodyMovement: l,
|
|
6879
6871
|
movementIntensity: h
|
|
6880
6872
|
}, R = {
|
|
6881
|
-
ttsEndpoint:
|
|
6882
|
-
ttsApikey:
|
|
6883
|
-
ttsService:
|
|
6873
|
+
ttsEndpoint: D.endpoint,
|
|
6874
|
+
ttsApikey: D.apiKey,
|
|
6875
|
+
ttsService: ne,
|
|
6884
6876
|
lipsyncModules: ["en"],
|
|
6885
6877
|
cameraView: u
|
|
6886
|
-
}, T =
|
|
6878
|
+
}, T = O(async () => {
|
|
6887
6879
|
if (!(!G.current || p.current))
|
|
6888
6880
|
try {
|
|
6889
|
-
if (C(!0),
|
|
6890
|
-
if (
|
|
6891
|
-
const
|
|
6892
|
-
d(
|
|
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));
|
|
6884
|
+
d(te);
|
|
6893
6885
|
}
|
|
6894
|
-
}), await new Promise((
|
|
6895
|
-
const
|
|
6896
|
-
p.current.lipsync && Object.keys(p.current.lipsync).length > 0 ?
|
|
6886
|
+
}), await new Promise((W) => {
|
|
6887
|
+
const te = () => {
|
|
6888
|
+
p.current.lipsync && Object.keys(p.current.lipsync).length > 0 ? W() : setTimeout(te, 100);
|
|
6897
6889
|
};
|
|
6898
|
-
|
|
6890
|
+
te();
|
|
6899
6891
|
}), p.current && p.current.setShowFullAvatar)
|
|
6900
6892
|
try {
|
|
6901
6893
|
p.current.setShowFullAvatar(r);
|
|
6902
|
-
} catch (
|
|
6903
|
-
console.warn("Error setting full body mode on initialization:",
|
|
6894
|
+
} catch (W) {
|
|
6895
|
+
console.warn("Error setting full body mode on initialization:", W);
|
|
6904
6896
|
}
|
|
6905
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);
|
|
6906
|
-
const
|
|
6898
|
+
const U = () => {
|
|
6907
6899
|
document.visibilityState === "visible" ? p.current?.start() : p.current?.stop();
|
|
6908
6900
|
};
|
|
6909
|
-
return document.addEventListener("visibilitychange",
|
|
6910
|
-
document.removeEventListener("visibilitychange",
|
|
6901
|
+
return document.addEventListener("visibilitychange", U), () => {
|
|
6902
|
+
document.removeEventListener("visibilitychange", U);
|
|
6911
6903
|
};
|
|
6912
6904
|
} catch (L) {
|
|
6913
|
-
console.error("Error initializing TalkingHead:", L),
|
|
6905
|
+
console.error("Error initializing TalkingHead:", L), N(L.message || "Failed to initialize avatar"), C(!1), c(L);
|
|
6914
6906
|
}
|
|
6915
6907
|
}, [X, t, e, n, i, s, o, r, l, h, u]);
|
|
6916
6908
|
me(() => (T(), () => {
|
|
6917
6909
|
p.current && (p.current.stop(), p.current.dispose(), p.current = null);
|
|
6918
6910
|
}), [T]), me(() => {
|
|
6919
6911
|
if (!G.current || !p.current) return;
|
|
6920
|
-
const L = new ResizeObserver((
|
|
6921
|
-
for (const
|
|
6912
|
+
const L = new ResizeObserver((W) => {
|
|
6913
|
+
for (const te of W)
|
|
6922
6914
|
p.current && p.current.onResize && p.current.onResize();
|
|
6923
6915
|
});
|
|
6924
6916
|
L.observe(G.current);
|
|
6925
|
-
const
|
|
6917
|
+
const U = () => {
|
|
6926
6918
|
p.current && p.current.onResize && p.current.onResize();
|
|
6927
6919
|
};
|
|
6928
|
-
return window.addEventListener("resize",
|
|
6929
|
-
L.disconnect(), window.removeEventListener("resize",
|
|
6920
|
+
return window.addEventListener("resize", U), () => {
|
|
6921
|
+
L.disconnect(), window.removeEventListener("resize", U);
|
|
6930
6922
|
};
|
|
6931
|
-
}, [
|
|
6932
|
-
const
|
|
6923
|
+
}, [$]);
|
|
6924
|
+
const F = O(async () => {
|
|
6933
6925
|
if (p.current && p.current.audioCtx)
|
|
6934
6926
|
try {
|
|
6935
6927
|
(p.current.audioCtx.state === "suspended" || p.current.audioCtx.state === "interrupted") && (await p.current.audioCtx.resume(), console.log("Audio context resumed"));
|
|
6936
6928
|
} catch (L) {
|
|
6937
6929
|
console.warn("Failed to resume audio context:", L);
|
|
6938
6930
|
}
|
|
6939
|
-
}, []),
|
|
6940
|
-
if (p.current &&
|
|
6931
|
+
}, []), P = O(async (L, U = {}) => {
|
|
6932
|
+
if (p.current && $)
|
|
6941
6933
|
try {
|
|
6942
|
-
y.current && (clearInterval(y.current), y.current = null), H.current = { text: L, options:
|
|
6943
|
-
const
|
|
6944
|
-
A.current =
|
|
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();
|
|
6945
6937
|
const ge = {
|
|
6946
|
-
...
|
|
6947
|
-
lipsyncLang:
|
|
6938
|
+
...U,
|
|
6939
|
+
lipsyncLang: U.lipsyncLang || v.lipsyncLang || "en"
|
|
6948
6940
|
};
|
|
6949
|
-
if (
|
|
6950
|
-
const
|
|
6941
|
+
if (U.onSpeechEnd && p.current) {
|
|
6942
|
+
const Q = p.current;
|
|
6951
6943
|
let ce = null, Se = 0;
|
|
6952
6944
|
const Le = 1200;
|
|
6953
6945
|
let be = !1;
|
|
@@ -6958,19 +6950,19 @@ const Ve = Me(({
|
|
|
6958
6950
|
if (ce && (clearInterval(ce), ce = null, y.current = null), !be && !I.current) {
|
|
6959
6951
|
be = !0;
|
|
6960
6952
|
try {
|
|
6961
|
-
|
|
6953
|
+
U.onSpeechEnd();
|
|
6962
6954
|
} catch (Ne) {
|
|
6963
6955
|
console.error("Error in onSpeechEnd callback (timeout):", Ne);
|
|
6964
6956
|
}
|
|
6965
6957
|
}
|
|
6966
6958
|
return;
|
|
6967
6959
|
}
|
|
6968
|
-
const ye = !
|
|
6969
|
-
|
|
6970
|
-
if (
|
|
6960
|
+
const ye = !Q.speechQueue || Q.speechQueue.length === 0, ke = !Q.audioPlaylist || Q.audioPlaylist.length === 0;
|
|
6961
|
+
Q && Q.isSpeaking === !1 && ye && ke && Q.isAudioPlaying === !1 && !be && !I.current && setTimeout(() => {
|
|
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) {
|
|
6971
6963
|
be = !0, ce && (clearInterval(ce), ce = null, y.current = null);
|
|
6972
6964
|
try {
|
|
6973
|
-
|
|
6965
|
+
U.onSpeechEnd();
|
|
6974
6966
|
} catch (Ze) {
|
|
6975
6967
|
console.error("Error in onSpeechEnd callback:", Ze);
|
|
6976
6968
|
}
|
|
@@ -6979,72 +6971,72 @@ const Ve = Me(({
|
|
|
6979
6971
|
}, 100), y.current = ce;
|
|
6980
6972
|
}
|
|
6981
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 () => {
|
|
6982
|
-
await
|
|
6974
|
+
await F(), p.current && p.current.lipsync && (p.current.setSlowdownRate && p.current.setSlowdownRate(1.05), p.current.speakText(L, ge));
|
|
6983
6975
|
}, 100);
|
|
6984
|
-
} catch (
|
|
6985
|
-
console.error("Error speaking text:",
|
|
6976
|
+
} catch (W) {
|
|
6977
|
+
console.error("Error speaking text:", W), N(W.message || "Failed to speak text");
|
|
6986
6978
|
}
|
|
6987
|
-
}, [
|
|
6979
|
+
}, [$, F, v.lipsyncLang]), _ = O(() => {
|
|
6988
6980
|
p.current && (p.current.stopSpeaking(), p.current.setSlowdownRate && p.current.setSlowdownRate(1), H.current = null, he(!1));
|
|
6989
|
-
}, []),
|
|
6981
|
+
}, []), j = O(() => {
|
|
6990
6982
|
if (p.current && p.current.pauseSpeaking) {
|
|
6991
6983
|
const L = p.current;
|
|
6992
6984
|
if (L.isSpeaking || L.audioPlaylist && L.audioPlaylist.length > 0 || L.speechQueue && L.speechQueue.length > 0) {
|
|
6993
6985
|
y.current && (clearInterval(y.current), y.current = null);
|
|
6994
|
-
let
|
|
6986
|
+
let W = "";
|
|
6995
6987
|
if (H.current && A.current.length > 0) {
|
|
6996
|
-
const
|
|
6997
|
-
if (ce > 0 && Se <
|
|
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;
|
|
6989
|
+
if (ce > 0 && Se < te && (W = A.current.slice(Se).join(". ").trim(), !W && ge > 0 && L.speechQueue)) {
|
|
6998
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(" ");
|
|
6999
|
-
be && be.trim() && (
|
|
6991
|
+
be && be.trim() && (W = be.trim());
|
|
7000
6992
|
}
|
|
7001
6993
|
}
|
|
7002
6994
|
H.current && (z.current = {
|
|
7003
|
-
remainingText:
|
|
6995
|
+
remainingText: W || null,
|
|
7004
6996
|
originalText: H.current.text,
|
|
7005
6997
|
options: H.current.options
|
|
7006
6998
|
}), L.speechQueue && (L.speechQueue.length = 0), p.current.pauseSpeaking(), I.current = !0, he(!0);
|
|
7007
6999
|
}
|
|
7008
7000
|
}
|
|
7009
|
-
}, []),
|
|
7001
|
+
}, []), J = O(async () => {
|
|
7010
7002
|
if (!p.current || !oe)
|
|
7011
7003
|
return;
|
|
7012
|
-
let L = "",
|
|
7004
|
+
let L = "", U = {};
|
|
7013
7005
|
if (z.current && z.current.remainingText)
|
|
7014
|
-
L = z.current.remainingText,
|
|
7006
|
+
L = z.current.remainingText, U = z.current.options || {}, z.current = { remainingText: null, originalText: null, options: null };
|
|
7015
7007
|
else if (H.current && H.current.text)
|
|
7016
|
-
L = H.current.text,
|
|
7008
|
+
L = H.current.text, U = H.current.options || {};
|
|
7017
7009
|
else {
|
|
7018
7010
|
console.warn("Resume called but no paused speech found"), he(!1), I.current = !1;
|
|
7019
7011
|
return;
|
|
7020
7012
|
}
|
|
7021
|
-
he(!1), I.current = !1, await
|
|
7022
|
-
const
|
|
7023
|
-
...
|
|
7024
|
-
lipsyncLang:
|
|
7013
|
+
he(!1), I.current = !1, await F();
|
|
7014
|
+
const W = {
|
|
7015
|
+
...U,
|
|
7016
|
+
lipsyncLang: U.lipsyncLang || v.lipsyncLang || "en"
|
|
7025
7017
|
};
|
|
7026
7018
|
try {
|
|
7027
|
-
await
|
|
7028
|
-
} catch (
|
|
7029
|
-
console.error("Error resuming speech:",
|
|
7019
|
+
await P(L, W);
|
|
7020
|
+
} catch (te) {
|
|
7021
|
+
console.error("Error resuming speech:", te), he(!1), I.current = !1;
|
|
7030
7022
|
}
|
|
7031
|
-
}, [
|
|
7023
|
+
}, [F, oe, P, v]), Ae = O((L) => {
|
|
7032
7024
|
p.current && p.current.setMood(L);
|
|
7033
|
-
}, []), we =
|
|
7025
|
+
}, []), we = O((L) => {
|
|
7034
7026
|
p.current && p.current.setSlowdownRate && p.current.setSlowdownRate(L);
|
|
7035
|
-
}, []), E =
|
|
7027
|
+
}, []), E = O((L, U = !1) => {
|
|
7036
7028
|
if (p.current && p.current.playAnimation) {
|
|
7037
7029
|
if (x && x[L] && (L = x[L]), p.current.setShowFullAvatar)
|
|
7038
7030
|
try {
|
|
7039
|
-
p.current.setShowFullAvatar(
|
|
7040
|
-
} catch (
|
|
7041
|
-
console.warn("Error setting full body mode:",
|
|
7031
|
+
p.current.setShowFullAvatar(B.current);
|
|
7032
|
+
} catch (te) {
|
|
7033
|
+
console.warn("Error setting full body mode:", te);
|
|
7042
7034
|
}
|
|
7043
7035
|
if (L.includes("."))
|
|
7044
7036
|
try {
|
|
7045
|
-
p.current.playAnimation(L, null, 10, 0, 0.01,
|
|
7046
|
-
} catch (
|
|
7047
|
-
console.warn(`Failed to play ${L}:`,
|
|
7037
|
+
p.current.playAnimation(L, null, 10, 0, 0.01, U);
|
|
7038
|
+
} catch (te) {
|
|
7039
|
+
console.warn(`Failed to play ${L}:`, te);
|
|
7048
7040
|
try {
|
|
7049
7041
|
p.current.setBodyMovement("idle");
|
|
7050
7042
|
} catch (ge) {
|
|
@@ -7052,11 +7044,11 @@ const Ve = Me(({
|
|
|
7052
7044
|
}
|
|
7053
7045
|
}
|
|
7054
7046
|
else {
|
|
7055
|
-
const
|
|
7047
|
+
const te = [".fbx", ".glb", ".gltf"];
|
|
7056
7048
|
let ge = !1;
|
|
7057
|
-
for (const
|
|
7049
|
+
for (const Q of te)
|
|
7058
7050
|
try {
|
|
7059
|
-
p.current.playAnimation(L +
|
|
7051
|
+
p.current.playAnimation(L + Q, null, 10, 0, 0.01, U), ge = !0;
|
|
7060
7052
|
break;
|
|
7061
7053
|
} catch {
|
|
7062
7054
|
}
|
|
@@ -7064,41 +7056,41 @@ const Ve = Me(({
|
|
|
7064
7056
|
console.warn("Animation not found:", L);
|
|
7065
7057
|
try {
|
|
7066
7058
|
p.current.setBodyMovement("idle");
|
|
7067
|
-
} catch (
|
|
7068
|
-
console.warn("Fallback animation also failed:",
|
|
7059
|
+
} catch (Q) {
|
|
7060
|
+
console.warn("Fallback animation also failed:", Q);
|
|
7069
7061
|
}
|
|
7070
7062
|
}
|
|
7071
7063
|
}
|
|
7072
7064
|
}
|
|
7073
|
-
}, [x]), se =
|
|
7065
|
+
}, [x]), se = O(() => {
|
|
7074
7066
|
p.current && p.current.onResize && p.current.onResize();
|
|
7075
7067
|
}, []);
|
|
7076
7068
|
return Fe(S, () => ({
|
|
7077
|
-
speakText:
|
|
7078
|
-
stopSpeaking:
|
|
7079
|
-
pauseSpeaking:
|
|
7080
|
-
resumeSpeaking:
|
|
7081
|
-
resumeAudioContext:
|
|
7069
|
+
speakText: P,
|
|
7070
|
+
stopSpeaking: _,
|
|
7071
|
+
pauseSpeaking: j,
|
|
7072
|
+
resumeSpeaking: J,
|
|
7073
|
+
resumeAudioContext: F,
|
|
7082
7074
|
setMood: Ae,
|
|
7083
7075
|
setTimingAdjustment: we,
|
|
7084
7076
|
playAnimation: E,
|
|
7085
|
-
isReady:
|
|
7077
|
+
isReady: $,
|
|
7086
7078
|
isPaused: oe,
|
|
7087
7079
|
talkingHead: p.current,
|
|
7088
7080
|
handleResize: se,
|
|
7089
7081
|
setBodyMovement: (L) => {
|
|
7090
7082
|
if (p.current && p.current.setShowFullAvatar && p.current.setBodyMovement)
|
|
7091
7083
|
try {
|
|
7092
|
-
p.current.setShowFullAvatar(
|
|
7093
|
-
} catch (
|
|
7094
|
-
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);
|
|
7095
7087
|
}
|
|
7096
7088
|
},
|
|
7097
7089
|
setMovementIntensity: (L) => p.current?.setMovementIntensity(L),
|
|
7098
7090
|
playRandomDance: () => {
|
|
7099
7091
|
if (p.current && p.current.setShowFullAvatar && p.current.playRandomDance)
|
|
7100
7092
|
try {
|
|
7101
|
-
p.current.setShowFullAvatar(
|
|
7093
|
+
p.current.setShowFullAvatar(B.current), p.current.playRandomDance();
|
|
7102
7094
|
} catch (L) {
|
|
7103
7095
|
console.warn("Error playing random dance:", L);
|
|
7104
7096
|
}
|
|
@@ -7106,15 +7098,15 @@ const Ve = Me(({
|
|
|
7106
7098
|
playReaction: (L) => {
|
|
7107
7099
|
if (p.current && p.current.setShowFullAvatar && p.current.playReaction)
|
|
7108
7100
|
try {
|
|
7109
|
-
p.current.setShowFullAvatar(
|
|
7110
|
-
} catch (
|
|
7111
|
-
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);
|
|
7112
7104
|
}
|
|
7113
7105
|
},
|
|
7114
7106
|
playCelebration: () => {
|
|
7115
7107
|
if (p.current && p.current.setShowFullAvatar && p.current.playCelebration)
|
|
7116
7108
|
try {
|
|
7117
|
-
p.current.setShowFullAvatar(
|
|
7109
|
+
p.current.setShowFullAvatar(B.current), p.current.playCelebration();
|
|
7118
7110
|
} catch (L) {
|
|
7119
7111
|
console.warn("Error playing celebration:", L);
|
|
7120
7112
|
}
|
|
@@ -7122,9 +7114,9 @@ const Ve = Me(({
|
|
|
7122
7114
|
setShowFullAvatar: (L) => {
|
|
7123
7115
|
if (p.current && p.current.setShowFullAvatar)
|
|
7124
7116
|
try {
|
|
7125
|
-
|
|
7126
|
-
} catch (
|
|
7127
|
-
console.warn("Error setting showFullAvatar:",
|
|
7117
|
+
B.current = L, p.current.setShowFullAvatar(L);
|
|
7118
|
+
} catch (U) {
|
|
7119
|
+
console.warn("Error setting showFullAvatar:", U);
|
|
7128
7120
|
}
|
|
7129
7121
|
},
|
|
7130
7122
|
lockAvatarPosition: () => {
|
|
@@ -7175,7 +7167,7 @@ const Ve = Me(({
|
|
|
7175
7167
|
fontSize: "18px",
|
|
7176
7168
|
zIndex: 10
|
|
7177
7169
|
}, children: "Loading avatar..." }),
|
|
7178
|
-
|
|
7170
|
+
q && /* @__PURE__ */ pe("div", { className: "error-overlay", style: {
|
|
7179
7171
|
position: "absolute",
|
|
7180
7172
|
top: "50%",
|
|
7181
7173
|
left: "50%",
|
|
@@ -7186,7 +7178,7 @@ const Ve = Me(({
|
|
|
7186
7178
|
zIndex: 10,
|
|
7187
7179
|
padding: "20px",
|
|
7188
7180
|
borderRadius: "8px"
|
|
7189
|
-
}, children:
|
|
7181
|
+
}, children: q })
|
|
7190
7182
|
]
|
|
7191
7183
|
}
|
|
7192
7184
|
);
|
|
@@ -7228,36 +7220,36 @@ const pt = Me(({
|
|
|
7228
7220
|
bodyMovement: "idle",
|
|
7229
7221
|
movementIntensity: 0.5,
|
|
7230
7222
|
...o
|
|
7231
|
-
},
|
|
7223
|
+
}, B = {
|
|
7232
7224
|
ttsEndpoint: G.endpoint,
|
|
7233
7225
|
ttsApikey: G.apiKey,
|
|
7234
7226
|
ttsService: S,
|
|
7235
7227
|
lipsyncModules: ["en"],
|
|
7236
7228
|
cameraView: "upper"
|
|
7237
|
-
}, H =
|
|
7229
|
+
}, H = O(async () => {
|
|
7238
7230
|
if (!(!h.current || r.current))
|
|
7239
7231
|
try {
|
|
7240
|
-
if (a(!0), c(null), r.current = new Be(h.current,
|
|
7241
|
-
if (
|
|
7242
|
-
const
|
|
7243
|
-
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);
|
|
7244
7236
|
}
|
|
7245
7237
|
}), r.current.morphs && r.current.morphs.length > 0) {
|
|
7246
|
-
const
|
|
7247
|
-
console.log("Available morph targets:", Object.keys(
|
|
7248
|
-
const
|
|
7249
|
-
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"));
|
|
7250
7242
|
}
|
|
7251
|
-
if (await new Promise((
|
|
7252
|
-
const
|
|
7253
|
-
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));
|
|
7254
7246
|
};
|
|
7255
|
-
|
|
7247
|
+
N();
|
|
7256
7248
|
}), r.current && r.current.setShowFullAvatar)
|
|
7257
7249
|
try {
|
|
7258
7250
|
r.current.setShowFullAvatar(!0), console.log("Avatar initialized in full body mode");
|
|
7259
|
-
} catch (
|
|
7260
|
-
console.warn("Error setting full body mode on initialization:",
|
|
7251
|
+
} catch (q) {
|
|
7252
|
+
console.warn("Error setting full body mode on initialization:", q);
|
|
7261
7253
|
}
|
|
7262
7254
|
a(!1), b(!0), n(r.current);
|
|
7263
7255
|
const C = () => {
|
|
@@ -7273,7 +7265,7 @@ const pt = Me(({
|
|
|
7273
7265
|
me(() => (H(), () => {
|
|
7274
7266
|
r.current && (r.current.stop(), r.current.dispose(), r.current = null);
|
|
7275
7267
|
}), [H]);
|
|
7276
|
-
const y =
|
|
7268
|
+
const y = O((k) => {
|
|
7277
7269
|
if (r.current && g)
|
|
7278
7270
|
try {
|
|
7279
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(() => {
|
|
@@ -7284,42 +7276,42 @@ const pt = Me(({
|
|
|
7284
7276
|
}
|
|
7285
7277
|
else
|
|
7286
7278
|
console.warn("Avatar not ready for speaking. isReady:", g, "talkingHeadRef:", !!r.current);
|
|
7287
|
-
}, [g, p]), I =
|
|
7279
|
+
}, [g, p]), I = O(() => {
|
|
7288
7280
|
r.current && (r.current.stopSpeaking(), r.current.setSlowdownRate && (r.current.setSlowdownRate(1), console.log("Reset timing to normal")));
|
|
7289
|
-
}, []), z =
|
|
7281
|
+
}, []), z = O((k) => {
|
|
7290
7282
|
r.current && r.current.setMood(k);
|
|
7291
|
-
}, []), A =
|
|
7283
|
+
}, []), A = O((k) => {
|
|
7292
7284
|
r.current && r.current.setSlowdownRate && (r.current.setSlowdownRate(k), console.log("Timing adjustment set to:", k));
|
|
7293
|
-
}, []), Y =
|
|
7285
|
+
}, []), Y = O((k, C = !1) => {
|
|
7294
7286
|
if (r.current && r.current.playAnimation) {
|
|
7295
7287
|
if (r.current.setShowFullAvatar)
|
|
7296
7288
|
try {
|
|
7297
7289
|
r.current.setShowFullAvatar(!0);
|
|
7298
|
-
} catch (
|
|
7299
|
-
console.warn("Error setting full body mode:",
|
|
7290
|
+
} catch (N) {
|
|
7291
|
+
console.warn("Error setting full body mode:", N);
|
|
7300
7292
|
}
|
|
7301
7293
|
if (k.includes("."))
|
|
7302
7294
|
try {
|
|
7303
7295
|
r.current.playAnimation(k, null, 10, 0, 0.01, C), console.log("Playing animation:", k);
|
|
7304
|
-
} catch (
|
|
7305
|
-
console.log(`Failed to play ${k}:`,
|
|
7296
|
+
} catch (N) {
|
|
7297
|
+
console.log(`Failed to play ${k}:`, N);
|
|
7306
7298
|
try {
|
|
7307
7299
|
r.current.setBodyMovement("idle"), console.log("Fallback to idle animation");
|
|
7308
|
-
} catch (
|
|
7309
|
-
console.warn("Fallback animation also failed:",
|
|
7300
|
+
} catch ($) {
|
|
7301
|
+
console.warn("Fallback animation also failed:", $);
|
|
7310
7302
|
}
|
|
7311
7303
|
}
|
|
7312
7304
|
else {
|
|
7313
|
-
const
|
|
7314
|
-
let
|
|
7315
|
-
for (const ie of
|
|
7305
|
+
const N = [".fbx", ".glb", ".gltf"];
|
|
7306
|
+
let $ = !1;
|
|
7307
|
+
for (const ie of N)
|
|
7316
7308
|
try {
|
|
7317
|
-
r.current.playAnimation(k + ie, null, 10, 0, 0.01, C), console.log("Playing animation:", k + ie),
|
|
7309
|
+
r.current.playAnimation(k + ie, null, 10, 0, 0.01, C), console.log("Playing animation:", k + ie), $ = !0;
|
|
7318
7310
|
break;
|
|
7319
7311
|
} catch {
|
|
7320
7312
|
console.log(`Failed to play ${k}${ie}, trying next format...`);
|
|
7321
7313
|
}
|
|
7322
|
-
if (
|
|
7314
|
+
if (!$) {
|
|
7323
7315
|
console.warn("Animation system not available or animation not found:", k);
|
|
7324
7316
|
try {
|
|
7325
7317
|
r.current.setBodyMovement("idle"), console.log("Fallback to idle animation");
|
|
@@ -7458,14 +7450,14 @@ const gt = Me(({
|
|
|
7458
7450
|
style: S = {},
|
|
7459
7451
|
animations: G = {},
|
|
7460
7452
|
autoSpeak: p = !1
|
|
7461
|
-
},
|
|
7462
|
-
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([]), [
|
|
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);
|
|
7463
7455
|
me(() => {
|
|
7464
|
-
Y.current =
|
|
7465
|
-
}, [
|
|
7456
|
+
Y.current = ee;
|
|
7457
|
+
}, [ee]), me(() => {
|
|
7466
7458
|
I.current = u;
|
|
7467
7459
|
}, [u]);
|
|
7468
|
-
const
|
|
7460
|
+
const D = Ee(), v = s || D.service;
|
|
7469
7461
|
let R;
|
|
7470
7462
|
v === "browser" ? R = {
|
|
7471
7463
|
service: "browser",
|
|
@@ -7475,18 +7467,18 @@ const gt = Me(({
|
|
|
7475
7467
|
} : v === "elevenlabs" ? R = {
|
|
7476
7468
|
service: "elevenlabs",
|
|
7477
7469
|
endpoint: "https://api.elevenlabs.io/v1/text-to-speech",
|
|
7478
|
-
apiKey: l ||
|
|
7479
|
-
defaultVoice: o ||
|
|
7480
|
-
voices:
|
|
7470
|
+
apiKey: l || D.apiKey,
|
|
7471
|
+
defaultVoice: o || D.defaultVoice || Ie.defaultVoice,
|
|
7472
|
+
voices: D.voices || Ie.voices
|
|
7481
7473
|
} : v === "deepgram" ? R = {
|
|
7482
7474
|
service: "deepgram",
|
|
7483
7475
|
endpoint: "https://api.deepgram.com/v1/speak",
|
|
7484
|
-
apiKey: l ||
|
|
7485
|
-
defaultVoice: o ||
|
|
7486
|
-
voices:
|
|
7476
|
+
apiKey: l || D.apiKey,
|
|
7477
|
+
defaultVoice: o || D.defaultVoice || Te.defaultVoice,
|
|
7478
|
+
voices: D.voices || Te.voices
|
|
7487
7479
|
} : R = {
|
|
7488
|
-
...
|
|
7489
|
-
apiKey: l !== null ? l :
|
|
7480
|
+
...D,
|
|
7481
|
+
apiKey: l !== null ? l : D.apiKey
|
|
7490
7482
|
};
|
|
7491
7483
|
const T = {
|
|
7492
7484
|
url: t,
|
|
@@ -7498,16 +7490,16 @@ const gt = Me(({
|
|
|
7498
7490
|
showFullAvatar: u,
|
|
7499
7491
|
bodyMovement: h,
|
|
7500
7492
|
movementIntensity: r
|
|
7501
|
-
},
|
|
7493
|
+
}, F = {
|
|
7502
7494
|
ttsEndpoint: R.endpoint,
|
|
7503
7495
|
ttsApikey: R.apiKey,
|
|
7504
7496
|
ttsService: v,
|
|
7505
7497
|
lipsyncModules: ["en"],
|
|
7506
7498
|
cameraView: a
|
|
7507
|
-
},
|
|
7499
|
+
}, P = O(async () => {
|
|
7508
7500
|
if (!(!H.current || y.current))
|
|
7509
7501
|
try {
|
|
7510
|
-
|
|
7502
|
+
N(!0), ie(null), y.current = new Be(H.current, F), console.log("Avatar config being passed:", {
|
|
7511
7503
|
url: T.url,
|
|
7512
7504
|
body: T.body,
|
|
7513
7505
|
avatarMood: T.avatarMood
|
|
@@ -7516,7 +7508,7 @@ const gt = Me(({
|
|
|
7516
7508
|
const L = Math.min(100, Math.round(se.loaded / se.total * 100));
|
|
7517
7509
|
c(L);
|
|
7518
7510
|
}
|
|
7519
|
-
}), 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);
|
|
7520
7512
|
const E = () => {
|
|
7521
7513
|
document.visibilityState === "visible" ? y.current?.start() : y.current?.stop();
|
|
7522
7514
|
};
|
|
@@ -7524,13 +7516,13 @@ const gt = Me(({
|
|
|
7524
7516
|
document.removeEventListener("visibilitychange", E);
|
|
7525
7517
|
};
|
|
7526
7518
|
} catch (E) {
|
|
7527
|
-
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);
|
|
7528
7520
|
}
|
|
7529
7521
|
}, []);
|
|
7530
|
-
me(() => (
|
|
7522
|
+
me(() => (P(), () => {
|
|
7531
7523
|
y.current && (y.current.stop(), y.current.dispose(), y.current = null);
|
|
7532
|
-
}), [
|
|
7533
|
-
const
|
|
7524
|
+
}), [P]);
|
|
7525
|
+
const _ = O(async () => {
|
|
7534
7526
|
if (y.current)
|
|
7535
7527
|
try {
|
|
7536
7528
|
const E = y.current.audioCtx || y.current.audioContext;
|
|
@@ -7538,7 +7530,7 @@ const gt = Me(({
|
|
|
7538
7530
|
} catch (E) {
|
|
7539
7531
|
console.warn("Failed to resume audio context:", E);
|
|
7540
7532
|
}
|
|
7541
|
-
}, []),
|
|
7533
|
+
}, []), j = O(async (E, se = {}) => {
|
|
7542
7534
|
if (!y.current || !oe) {
|
|
7543
7535
|
console.warn("Avatar not ready for speaking");
|
|
7544
7536
|
return;
|
|
@@ -7547,59 +7539,59 @@ const gt = Me(({
|
|
|
7547
7539
|
console.warn("No text provided to speak");
|
|
7548
7540
|
return;
|
|
7549
7541
|
}
|
|
7550
|
-
await
|
|
7551
|
-
const L = E.split(/[.!?]+/).filter((
|
|
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);
|
|
7552
7544
|
C.current = L;
|
|
7553
|
-
const
|
|
7545
|
+
const U = {
|
|
7554
7546
|
lipsyncLang: se.lipsyncLang || "en",
|
|
7555
7547
|
onSpeechEnd: () => {
|
|
7556
7548
|
A.current && (clearInterval(A.current), A.current = null), se.onSpeechEnd && se.onSpeechEnd(), b();
|
|
7557
7549
|
}
|
|
7558
7550
|
};
|
|
7559
7551
|
try {
|
|
7560
|
-
y.current.speakText(E,
|
|
7561
|
-
} catch (
|
|
7562
|
-
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");
|
|
7563
7555
|
}
|
|
7564
|
-
}, [oe, b,
|
|
7556
|
+
}, [oe, b, _]);
|
|
7565
7557
|
me(() => {
|
|
7566
|
-
oe && X && p && y.current &&
|
|
7567
|
-
}, [oe, X, p,
|
|
7568
|
-
const
|
|
7558
|
+
oe && X && p && y.current && j(X);
|
|
7559
|
+
}, [oe, X, p, j]);
|
|
7560
|
+
const J = O(() => {
|
|
7569
7561
|
if (y.current)
|
|
7570
7562
|
try {
|
|
7571
7563
|
const E = y.current.isSpeaking || !1, se = y.current.audioPlaylist || [], L = y.current.speechQueue || [];
|
|
7572
7564
|
if (E || se.length > 0 || L.length > 0) {
|
|
7573
7565
|
A.current && (clearInterval(A.current), A.current = null);
|
|
7574
|
-
let
|
|
7575
|
-
L.length > 0 && (
|
|
7576
|
-
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,
|
|
7577
7569
|
originalText: z.current?.text || null,
|
|
7578
7570
|
options: z.current?.options || null
|
|
7579
|
-
}, y.current.speechQueue.length = 0, y.current.pauseSpeaking(),
|
|
7571
|
+
}, y.current.speechQueue.length = 0, y.current.pauseSpeaking(), ne(!0), Y.current = !0;
|
|
7580
7572
|
}
|
|
7581
7573
|
} catch (E) {
|
|
7582
7574
|
console.warn("Error pausing speech:", E);
|
|
7583
7575
|
}
|
|
7584
|
-
}, []), Ae =
|
|
7585
|
-
if (!(!y.current || !
|
|
7576
|
+
}, []), Ae = O(async () => {
|
|
7577
|
+
if (!(!y.current || !ee))
|
|
7586
7578
|
try {
|
|
7587
|
-
await
|
|
7588
|
-
const E = k.current?.remainingText, se = k.current?.originalText || z.current?.text, L = k.current?.options || z.current?.options || {},
|
|
7589
|
-
|
|
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);
|
|
7590
7582
|
} catch (E) {
|
|
7591
|
-
console.warn("Error resuming speech:", E),
|
|
7583
|
+
console.warn("Error resuming speech:", E), ne(!1), Y.current = !1;
|
|
7592
7584
|
}
|
|
7593
|
-
}, [
|
|
7594
|
-
y.current && (y.current.stopSpeaking(), A.current && (clearInterval(A.current), A.current = null),
|
|
7585
|
+
}, [ee, j, _]), we = O(() => {
|
|
7586
|
+
y.current && (y.current.stopSpeaking(), A.current && (clearInterval(A.current), A.current = null), ne(!1), Y.current = !1);
|
|
7595
7587
|
}, []);
|
|
7596
|
-
return Fe(
|
|
7597
|
-
speakText:
|
|
7598
|
-
pauseSpeaking:
|
|
7588
|
+
return Fe(B, () => ({
|
|
7589
|
+
speakText: j,
|
|
7590
|
+
pauseSpeaking: J,
|
|
7599
7591
|
resumeSpeaking: Ae,
|
|
7600
7592
|
stopSpeaking: we,
|
|
7601
|
-
resumeAudioContext:
|
|
7602
|
-
isPaused: () =>
|
|
7593
|
+
resumeAudioContext: _,
|
|
7594
|
+
isPaused: () => ee,
|
|
7603
7595
|
setMood: (E) => y.current?.setMood(E),
|
|
7604
7596
|
setBodyMovement: (E) => {
|
|
7605
7597
|
y.current && y.current.setBodyMovement(E);
|
|
@@ -7627,7 +7619,7 @@ const gt = Me(({
|
|
|
7627
7619
|
}
|
|
7628
7620
|
}
|
|
7629
7621
|
),
|
|
7630
|
-
|
|
7622
|
+
q && /* @__PURE__ */ pe("div", { className: "loading-overlay", style: {
|
|
7631
7623
|
position: "absolute",
|
|
7632
7624
|
top: "50%",
|
|
7633
7625
|
left: "50%",
|
|
@@ -7636,7 +7628,7 @@ const gt = Me(({
|
|
|
7636
7628
|
fontSize: "18px",
|
|
7637
7629
|
zIndex: 10
|
|
7638
7630
|
}, children: "Loading avatar..." }),
|
|
7639
|
-
|
|
7631
|
+
$ && /* @__PURE__ */ pe("div", { className: "error-overlay", style: {
|
|
7640
7632
|
position: "absolute",
|
|
7641
7633
|
top: "50%",
|
|
7642
7634
|
left: "50%",
|
|
@@ -7647,7 +7639,7 @@ const gt = Me(({
|
|
|
7647
7639
|
zIndex: 10,
|
|
7648
7640
|
padding: "20px",
|
|
7649
7641
|
borderRadius: "8px"
|
|
7650
|
-
}, children:
|
|
7642
|
+
}, children: $ })
|
|
7651
7643
|
] });
|
|
7652
7644
|
});
|
|
7653
7645
|
gt.displayName = "SimpleTalkingAvatar";
|
|
@@ -7683,7 +7675,7 @@ const yt = Me(({
|
|
|
7683
7675
|
onQuestionAnswer: s,
|
|
7684
7676
|
onCurriculumComplete: o,
|
|
7685
7677
|
onCustomAction: l
|
|
7686
|
-
}), c = V(null), g = V(null), b = V(null), x = V(null), S = V(null), G = V(null), p = V(null),
|
|
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 || {
|
|
7687
7679
|
title: "Default Curriculum",
|
|
7688
7680
|
description: "No curriculum data provided",
|
|
7689
7681
|
language: "en",
|
|
@@ -7711,7 +7703,7 @@ const yt = Me(({
|
|
|
7711
7703
|
onCustomAction: l
|
|
7712
7704
|
};
|
|
7713
7705
|
}, [n, i, s, o, l]), me(() => {
|
|
7714
|
-
|
|
7706
|
+
B.current = X?.curriculum || {
|
|
7715
7707
|
title: "Default Curriculum",
|
|
7716
7708
|
description: "No curriculum data provided",
|
|
7717
7709
|
language: "en",
|
|
@@ -7731,7 +7723,7 @@ const yt = Me(({
|
|
|
7731
7723
|
lipsyncLang: "en"
|
|
7732
7724
|
};
|
|
7733
7725
|
}, [X, t, e]);
|
|
7734
|
-
const y =
|
|
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(() => {
|
|
7735
7727
|
a.current.lessonCompleted = !0, a.current.isQuestionMode = !1;
|
|
7736
7728
|
const v = a.current.totalQuestions > 0 ? Math.round(a.current.score / a.current.totalQuestions * 100) : 100;
|
|
7737
7729
|
let R = "Congratulations! You've completed this lesson";
|
|
@@ -7755,9 +7747,9 @@ const yt = Me(({
|
|
|
7755
7747
|
} catch {
|
|
7756
7748
|
u.current.playCelebration();
|
|
7757
7749
|
}
|
|
7758
|
-
const T =
|
|
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" };
|
|
7759
7751
|
u.current.speakText(R, {
|
|
7760
|
-
lipsyncLang:
|
|
7752
|
+
lipsyncLang: J.lipsyncLang,
|
|
7761
7753
|
onSpeechEnd: () => {
|
|
7762
7754
|
d.current.onCustomAction({
|
|
7763
7755
|
type: "lessonCompleteFeedbackDone",
|
|
@@ -7766,14 +7758,14 @@ const yt = Me(({
|
|
|
7766
7758
|
score: a.current.score,
|
|
7767
7759
|
totalQuestions: a.current.totalQuestions,
|
|
7768
7760
|
percentage: v,
|
|
7769
|
-
hasNextLesson:
|
|
7761
|
+
hasNextLesson: j
|
|
7770
7762
|
});
|
|
7771
7763
|
}
|
|
7772
7764
|
});
|
|
7773
7765
|
}
|
|
7774
|
-
}, [e.lessonComplete]), Y =
|
|
7766
|
+
}, [e.lessonComplete]), Y = O(() => {
|
|
7775
7767
|
a.current.curriculumCompleted = !0;
|
|
7776
|
-
const v =
|
|
7768
|
+
const v = B.current || { modules: [] };
|
|
7777
7769
|
if (d.current.onCurriculumComplete({
|
|
7778
7770
|
modules: v.modules.length,
|
|
7779
7771
|
totalLessons: v.modules.reduce((R, T) => R + T.lessons.length, 0)
|
|
@@ -7787,7 +7779,7 @@ const yt = Me(({
|
|
|
7787
7779
|
const R = H.current || { lipsyncLang: "en" };
|
|
7788
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 });
|
|
7789
7781
|
}
|
|
7790
|
-
}, [e.curriculumComplete]), k =
|
|
7782
|
+
}, [e.curriculumComplete]), k = O(() => {
|
|
7791
7783
|
const v = y();
|
|
7792
7784
|
a.current.isQuestionMode = !0, a.current.currentQuestionIndex = 0, a.current.totalQuestions = v?.questions?.length || 0, a.current.score = 0;
|
|
7793
7785
|
const R = I();
|
|
@@ -7805,26 +7797,26 @@ const yt = Me(({
|
|
|
7805
7797
|
if (u.current.setMood("happy"), e.questionStart)
|
|
7806
7798
|
try {
|
|
7807
7799
|
u.current.playAnimation(e.questionStart, !0);
|
|
7808
|
-
} catch (
|
|
7809
|
-
console.warn("Failed to play questionStart animation:",
|
|
7800
|
+
} catch (P) {
|
|
7801
|
+
console.warn("Failed to play questionStart animation:", P);
|
|
7810
7802
|
}
|
|
7811
|
-
const
|
|
7812
|
-
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 });
|
|
7813
7805
|
};
|
|
7814
7806
|
if (u.current && u.current.isReady && R)
|
|
7815
7807
|
T();
|
|
7816
7808
|
else if (u.current && u.current.isReady) {
|
|
7817
|
-
const
|
|
7818
|
-
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 });
|
|
7819
7811
|
} else {
|
|
7820
|
-
const
|
|
7821
|
-
u.current && u.current.isReady && (clearInterval(
|
|
7812
|
+
const F = setInterval(() => {
|
|
7813
|
+
u.current && u.current.isReady && (clearInterval(F), R && T());
|
|
7822
7814
|
}, 100);
|
|
7823
7815
|
setTimeout(() => {
|
|
7824
|
-
clearInterval(
|
|
7816
|
+
clearInterval(F);
|
|
7825
7817
|
}, 5e3);
|
|
7826
7818
|
}
|
|
7827
|
-
}, [e.questionStart, y, I]), C =
|
|
7819
|
+
}, [e.questionStart, y, I]), C = O(() => {
|
|
7828
7820
|
const v = y();
|
|
7829
7821
|
if (a.current.currentQuestionIndex < (v?.questions?.length || 0) - 1) {
|
|
7830
7822
|
u.current && u.current.stopSpeaking && u.current.stopSpeaking(), a.current.currentQuestionIndex += 1;
|
|
@@ -7843,40 +7835,40 @@ const yt = Me(({
|
|
|
7843
7835
|
if (u.current.setMood("happy"), u.current.setBodyMovement("idle"), e.nextQuestion)
|
|
7844
7836
|
try {
|
|
7845
7837
|
u.current.playAnimation(e.nextQuestion, !0);
|
|
7846
|
-
} catch (
|
|
7847
|
-
console.warn("Failed to play nextQuestion animation:",
|
|
7838
|
+
} catch (J) {
|
|
7839
|
+
console.warn("Failed to play nextQuestion animation:", J);
|
|
7848
7840
|
}
|
|
7849
|
-
const
|
|
7841
|
+
const F = H.current || { lipsyncLang: "en" }, _ = y()?.questions?.length || 0, j = a.current.currentQuestionIndex >= _ - 1;
|
|
7850
7842
|
if (R.type === "code_test") {
|
|
7851
|
-
const
|
|
7852
|
-
u.current.speakText(
|
|
7853
|
-
lipsyncLang:
|
|
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}`;
|
|
7844
|
+
u.current.speakText(J, {
|
|
7845
|
+
lipsyncLang: F.lipsyncLang
|
|
7854
7846
|
});
|
|
7855
7847
|
} else if (R.type === "multiple_choice") {
|
|
7856
|
-
const
|
|
7857
|
-
u.current.speakText(
|
|
7858
|
-
lipsyncLang:
|
|
7848
|
+
const J = j ? `Alright! Here's your final question: ${R.question}` : `Alright! Here's your next question: ${R.question}`;
|
|
7849
|
+
u.current.speakText(J, {
|
|
7850
|
+
lipsyncLang: F.lipsyncLang
|
|
7859
7851
|
});
|
|
7860
7852
|
} else if (R.type === "true_false") {
|
|
7861
|
-
const
|
|
7862
|
-
u.current.speakText(
|
|
7863
|
-
lipsyncLang:
|
|
7853
|
+
const J = j ? `Now let's try this final one: ${R.question}` : `Now let's try this one: ${R.question}`;
|
|
7854
|
+
u.current.speakText(J, {
|
|
7855
|
+
lipsyncLang: F.lipsyncLang
|
|
7864
7856
|
});
|
|
7865
7857
|
} else {
|
|
7866
|
-
const
|
|
7867
|
-
u.current.speakText(
|
|
7868
|
-
lipsyncLang:
|
|
7858
|
+
const J = j ? `Here's your final question: ${R.question}` : `Here's the next question: ${R.question}`;
|
|
7859
|
+
u.current.speakText(J, {
|
|
7860
|
+
lipsyncLang: F.lipsyncLang
|
|
7869
7861
|
});
|
|
7870
7862
|
}
|
|
7871
7863
|
};
|
|
7872
7864
|
if (u.current && u.current.isReady && R)
|
|
7873
7865
|
T();
|
|
7874
7866
|
else if (R) {
|
|
7875
|
-
const
|
|
7876
|
-
u.current && u.current.isReady && (clearInterval(
|
|
7867
|
+
const F = setInterval(() => {
|
|
7868
|
+
u.current && u.current.isReady && (clearInterval(F), T());
|
|
7877
7869
|
}, 100);
|
|
7878
7870
|
setTimeout(() => {
|
|
7879
|
-
clearInterval(
|
|
7871
|
+
clearInterval(F);
|
|
7880
7872
|
}, 5e3);
|
|
7881
7873
|
}
|
|
7882
7874
|
} else
|
|
@@ -7887,16 +7879,16 @@ const yt = Me(({
|
|
|
7887
7879
|
totalQuestions: a.current.totalQuestions,
|
|
7888
7880
|
score: a.current.score
|
|
7889
7881
|
});
|
|
7890
|
-
}, [e.nextQuestion, y, I]),
|
|
7891
|
-
const v =
|
|
7882
|
+
}, [e.nextQuestion, y, I]), q = O(() => {
|
|
7883
|
+
const v = B.current || { modules: [] }, R = v.modules[a.current.currentModuleIndex];
|
|
7892
7884
|
if (a.current.currentLessonIndex < (R?.lessons?.length || 0) - 1) {
|
|
7893
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;
|
|
7894
|
-
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 || _;
|
|
7895
7887
|
d.current.onCustomAction({
|
|
7896
7888
|
type: "lessonStart",
|
|
7897
7889
|
moduleIndex: a.current.currentModuleIndex,
|
|
7898
7890
|
lessonIndex: a.current.currentLessonIndex,
|
|
7899
|
-
hasNextLesson:
|
|
7891
|
+
hasNextLesson: j
|
|
7900
7892
|
}), d.current.onLessonStart({
|
|
7901
7893
|
moduleIndex: a.current.currentModuleIndex,
|
|
7902
7894
|
lessonIndex: a.current.currentLessonIndex,
|
|
@@ -7904,12 +7896,12 @@ const yt = Me(({
|
|
|
7904
7896
|
}), u.current && (u.current.setMood("happy"), u.current.setBodyMovement("idle"));
|
|
7905
7897
|
} else if (a.current.currentModuleIndex < (v.modules?.length || 0) - 1) {
|
|
7906
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;
|
|
7907
|
-
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;
|
|
7908
7900
|
d.current.onCustomAction({
|
|
7909
7901
|
type: "lessonStart",
|
|
7910
7902
|
moduleIndex: a.current.currentModuleIndex,
|
|
7911
7903
|
lessonIndex: a.current.currentLessonIndex,
|
|
7912
|
-
hasNextLesson:
|
|
7904
|
+
hasNextLesson: J
|
|
7913
7905
|
}), d.current.onLessonStart({
|
|
7914
7906
|
moduleIndex: a.current.currentModuleIndex,
|
|
7915
7907
|
lessonIndex: a.current.currentLessonIndex,
|
|
@@ -7917,12 +7909,12 @@ const yt = Me(({
|
|
|
7917
7909
|
}), u.current && (u.current.setMood("happy"), u.current.setBodyMovement("idle"));
|
|
7918
7910
|
} else
|
|
7919
7911
|
S.current && S.current();
|
|
7920
|
-
}, []),
|
|
7912
|
+
}, []), N = O(() => {
|
|
7921
7913
|
const v = y();
|
|
7922
7914
|
let R = null;
|
|
7923
7915
|
if (v?.avatar_script && v?.body) {
|
|
7924
|
-
const T = v.avatar_script.trim(),
|
|
7925
|
-
R = `${T}${
|
|
7916
|
+
const T = v.avatar_script.trim(), F = v.body.trim(), P = T.match(/[.!?]$/) ? " " : ". ";
|
|
7917
|
+
R = `${T}${P}${F}`;
|
|
7926
7918
|
} else
|
|
7927
7919
|
R = v?.avatar_script || v?.body || null;
|
|
7928
7920
|
if (u.current && u.current.isReady && R) {
|
|
@@ -7931,11 +7923,11 @@ const yt = Me(({
|
|
|
7931
7923
|
if (e.teaching)
|
|
7932
7924
|
try {
|
|
7933
7925
|
u.current.playAnimation(e.teaching, !0), T = !0;
|
|
7934
|
-
} catch (
|
|
7935
|
-
console.warn("Failed to play teaching animation:",
|
|
7926
|
+
} catch (P) {
|
|
7927
|
+
console.warn("Failed to play teaching animation:", P);
|
|
7936
7928
|
}
|
|
7937
7929
|
T || u.current.setBodyMovement("gesturing");
|
|
7938
|
-
const
|
|
7930
|
+
const F = H.current || { lipsyncLang: "en" };
|
|
7939
7931
|
d.current.onLessonStart({
|
|
7940
7932
|
moduleIndex: a.current.currentModuleIndex,
|
|
7941
7933
|
lessonIndex: a.current.currentLessonIndex,
|
|
@@ -7946,7 +7938,7 @@ const yt = Me(({
|
|
|
7946
7938
|
lessonIndex: a.current.currentLessonIndex,
|
|
7947
7939
|
lesson: v
|
|
7948
7940
|
}), u.current.speakText(R, {
|
|
7949
|
-
lipsyncLang:
|
|
7941
|
+
lipsyncLang: F.lipsyncLang,
|
|
7950
7942
|
onSpeechEnd: () => {
|
|
7951
7943
|
a.current.isTeaching = !1, d.current.onCustomAction({
|
|
7952
7944
|
type: "teachingComplete",
|
|
@@ -7964,7 +7956,7 @@ const yt = Me(({
|
|
|
7964
7956
|
}
|
|
7965
7957
|
});
|
|
7966
7958
|
}
|
|
7967
|
-
}, [e.teaching, y]),
|
|
7959
|
+
}, [e.teaching, y]), $ = O((v) => {
|
|
7968
7960
|
const R = I(), T = z(v, R);
|
|
7969
7961
|
if (T && (a.current.score += 1), d.current.onQuestionAnswer({
|
|
7970
7962
|
moduleIndex: a.current.currentModuleIndex,
|
|
@@ -7982,13 +7974,13 @@ const yt = Me(({
|
|
|
7982
7974
|
u.current.setBodyMovement("happy");
|
|
7983
7975
|
}
|
|
7984
7976
|
u.current.setBodyMovement("gesturing");
|
|
7985
|
-
const
|
|
7986
|
-
a.current.currentQuestionIndex >=
|
|
7987
|
-
const
|
|
7988
|
-
console.log("[CurriculumLearning] Answer feedback - questionIndex:", a.current.currentQuestionIndex, "totalQuestions:",
|
|
7989
|
-
const
|
|
7990
|
-
u.current.speakText(
|
|
7991
|
-
lipsyncLang:
|
|
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, {
|
|
7983
|
+
lipsyncLang: J.lipsyncLang,
|
|
7992
7984
|
onSpeechEnd: () => {
|
|
7993
7985
|
d.current.onCustomAction({
|
|
7994
7986
|
type: "answerFeedbackComplete",
|
|
@@ -7996,7 +7988,7 @@ const yt = Me(({
|
|
|
7996
7988
|
lessonIndex: a.current.currentLessonIndex,
|
|
7997
7989
|
questionIndex: a.current.currentQuestionIndex,
|
|
7998
7990
|
isCorrect: !0,
|
|
7999
|
-
hasNextQuestion:
|
|
7991
|
+
hasNextQuestion: _,
|
|
8000
7992
|
score: a.current.score,
|
|
8001
7993
|
totalQuestions: a.current.totalQuestions
|
|
8002
7994
|
});
|
|
@@ -8010,10 +8002,10 @@ const yt = Me(({
|
|
|
8010
8002
|
u.current.setBodyMovement("idle");
|
|
8011
8003
|
}
|
|
8012
8004
|
u.current.setBodyMovement("gesturing");
|
|
8013
|
-
const
|
|
8014
|
-
console.log("[CurriculumLearning] Answer feedback (incorrect) - questionIndex:", a.current.currentQuestionIndex, "totalQuestions:",
|
|
8015
|
-
const
|
|
8016
|
-
u.current.speakText(
|
|
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" };
|
|
8008
|
+
u.current.speakText(J, {
|
|
8017
8009
|
lipsyncLang: Ae.lipsyncLang,
|
|
8018
8010
|
onSpeechEnd: () => {
|
|
8019
8011
|
d.current.onCustomAction({
|
|
@@ -8022,7 +8014,7 @@ const yt = Me(({
|
|
|
8022
8014
|
lessonIndex: a.current.currentLessonIndex,
|
|
8023
8015
|
questionIndex: a.current.currentQuestionIndex,
|
|
8024
8016
|
isCorrect: !1,
|
|
8025
|
-
hasNextQuestion:
|
|
8017
|
+
hasNextQuestion: j,
|
|
8026
8018
|
score: a.current.score,
|
|
8027
8019
|
totalQuestions: a.current.totalQuestions
|
|
8028
8020
|
});
|
|
@@ -8030,20 +8022,20 @@ const yt = Me(({
|
|
|
8030
8022
|
});
|
|
8031
8023
|
}
|
|
8032
8024
|
else {
|
|
8033
|
-
const
|
|
8025
|
+
const P = y()?.questions?.length || 0;
|
|
8034
8026
|
d.current.onCustomAction({
|
|
8035
8027
|
type: "answerFeedbackComplete",
|
|
8036
8028
|
moduleIndex: a.current.currentModuleIndex,
|
|
8037
8029
|
lessonIndex: a.current.currentLessonIndex,
|
|
8038
8030
|
questionIndex: a.current.currentQuestionIndex,
|
|
8039
8031
|
isCorrect: T,
|
|
8040
|
-
hasNextQuestion: a.current.currentQuestionIndex <
|
|
8032
|
+
hasNextQuestion: a.current.currentQuestionIndex < P - 1,
|
|
8041
8033
|
score: a.current.score,
|
|
8042
8034
|
totalQuestions: a.current.totalQuestions,
|
|
8043
8035
|
avatarNotReady: !0
|
|
8044
8036
|
});
|
|
8045
8037
|
}
|
|
8046
|
-
}, [e.correct, e.incorrect, I, y, z]), ie =
|
|
8038
|
+
}, [e.correct, e.incorrect, I, y, z]), ie = O((v) => {
|
|
8047
8039
|
const R = I();
|
|
8048
8040
|
if (!v || typeof v != "object") {
|
|
8049
8041
|
console.error("Invalid code test result format. Expected object with {passed: boolean, ...}");
|
|
@@ -8071,7 +8063,7 @@ const yt = Me(({
|
|
|
8071
8063
|
testResult: T,
|
|
8072
8064
|
question: R
|
|
8073
8065
|
}), p.current && p.current(T);
|
|
8074
|
-
}, [I, z]), oe =
|
|
8066
|
+
}, [I, z]), oe = O(() => {
|
|
8075
8067
|
if (a.current.currentQuestionIndex > 0) {
|
|
8076
8068
|
a.current.currentQuestionIndex -= 1;
|
|
8077
8069
|
const v = I();
|
|
@@ -8105,8 +8097,8 @@ const yt = Me(({
|
|
|
8105
8097
|
}, 5e3);
|
|
8106
8098
|
}
|
|
8107
8099
|
}
|
|
8108
|
-
}, [I]), he =
|
|
8109
|
-
const v =
|
|
8100
|
+
}, [I]), he = O(() => {
|
|
8101
|
+
const v = B.current || { modules: [] };
|
|
8110
8102
|
if (v.modules[a.current.currentModuleIndex], a.current.currentLessonIndex > 0)
|
|
8111
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({
|
|
8112
8104
|
type: "lessonStart",
|
|
@@ -8118,8 +8110,8 @@ const yt = Me(({
|
|
|
8118
8110
|
lesson: y()
|
|
8119
8111
|
}), u.current && (u.current.setMood("happy"), u.current.setBodyMovement("idle"));
|
|
8120
8112
|
else if (a.current.currentModuleIndex > 0) {
|
|
8121
|
-
const
|
|
8122
|
-
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({
|
|
8123
8115
|
type: "lessonStart",
|
|
8124
8116
|
moduleIndex: a.current.currentModuleIndex,
|
|
8125
8117
|
lessonIndex: a.current.currentLessonIndex
|
|
@@ -8129,9 +8121,9 @@ const yt = Me(({
|
|
|
8129
8121
|
lesson: y()
|
|
8130
8122
|
}), u.current && (u.current.setMood("happy"), u.current.setBodyMovement("idle"));
|
|
8131
8123
|
}
|
|
8132
|
-
}, [y]),
|
|
8124
|
+
}, [y]), ee = O(() => {
|
|
8133
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;
|
|
8134
|
-
}, []),
|
|
8126
|
+
}, []), ne = O((v) => {
|
|
8135
8127
|
console.log("Avatar is ready!", v);
|
|
8136
8128
|
const R = y(), T = R?.avatar_script || R?.body;
|
|
8137
8129
|
h && T && setTimeout(() => {
|
|
@@ -8139,20 +8131,20 @@ const yt = Me(({
|
|
|
8139
8131
|
}, 10);
|
|
8140
8132
|
}, [h, y]);
|
|
8141
8133
|
Xe(() => {
|
|
8142
|
-
c.current =
|
|
8134
|
+
c.current = N, g.current = q, b.current = A, x.current = C, S.current = Y, G.current = k, p.current = $;
|
|
8143
8135
|
}), Fe(r, () => ({
|
|
8144
8136
|
// Curriculum control methods
|
|
8145
|
-
startTeaching:
|
|
8137
|
+
startTeaching: N,
|
|
8146
8138
|
startQuestions: k,
|
|
8147
|
-
handleAnswerSelect:
|
|
8139
|
+
handleAnswerSelect: $,
|
|
8148
8140
|
handleCodeTestResult: ie,
|
|
8149
8141
|
nextQuestion: C,
|
|
8150
8142
|
previousQuestion: oe,
|
|
8151
|
-
nextLesson:
|
|
8143
|
+
nextLesson: q,
|
|
8152
8144
|
previousLesson: he,
|
|
8153
8145
|
completeLesson: A,
|
|
8154
8146
|
completeCurriculum: Y,
|
|
8155
|
-
resetCurriculum:
|
|
8147
|
+
resetCurriculum: ee,
|
|
8156
8148
|
getState: () => ({ ...a.current }),
|
|
8157
8149
|
getCurrentQuestion: () => I(),
|
|
8158
8150
|
getCurrentLesson: () => y(),
|
|
@@ -8206,8 +8198,8 @@ const yt = Me(({
|
|
|
8206
8198
|
handleResize: () => u.current?.handleResize(),
|
|
8207
8199
|
// Avatar readiness check (always returns current value)
|
|
8208
8200
|
isAvatarReady: () => u.current?.isReady || !1
|
|
8209
|
-
}), [
|
|
8210
|
-
const
|
|
8201
|
+
}), [N, k, $, ie, C, q, A, Y, ee, I, y]);
|
|
8202
|
+
const D = H.current || {
|
|
8211
8203
|
avatarUrl: "/avatars/brunette.glb",
|
|
8212
8204
|
avatarBody: "F",
|
|
8213
8205
|
mood: "happy",
|
|
@@ -8224,19 +8216,19 @@ const yt = Me(({
|
|
|
8224
8216
|
Ve,
|
|
8225
8217
|
{
|
|
8226
8218
|
ref: u,
|
|
8227
|
-
avatarUrl:
|
|
8228
|
-
avatarBody:
|
|
8229
|
-
mood:
|
|
8230
|
-
ttsLang:
|
|
8231
|
-
ttsService:
|
|
8232
|
-
ttsVoice:
|
|
8233
|
-
ttsApiKey:
|
|
8234
|
-
bodyMovement:
|
|
8235
|
-
movementIntensity:
|
|
8236
|
-
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,
|
|
8237
8229
|
cameraView: "upper",
|
|
8238
|
-
animations:
|
|
8239
|
-
onReady:
|
|
8230
|
+
animations: D.animations,
|
|
8231
|
+
onReady: ne,
|
|
8240
8232
|
onLoading: () => {
|
|
8241
8233
|
},
|
|
8242
8234
|
onError: (v) => {
|