@sage-rsc/talking-head-react 1.2.0 → 1.2.2
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 +444 -466
- package/package.json +1 -1
- package/src/lib/talkinghead.mjs +3 -46
package/dist/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { jsxs as Pe, jsx as
|
|
2
|
-
import { forwardRef as Me, useRef as
|
|
1
|
+
import { jsxs as Pe, jsx as me } from "react/jsx-runtime";
|
|
2
|
+
import { forwardRef as Me, useRef as O, useState as ce, useEffect as de, useCallback as B, 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,12 +7,12 @@ 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, re, ue;
|
|
11
|
+
const w = [0, 0, 0, 0], T = new f.Vector3(), ze = new f.Vector3(), ie = new f.Vector3(), Ce = new f.Vector3();
|
|
12
12
|
new f.Plane();
|
|
13
13
|
new f.Ray();
|
|
14
14
|
new f.Euler();
|
|
15
|
-
const
|
|
15
|
+
const oe = new f.Quaternion(), Oe = new f.Quaternion(), fe = new f.Matrix4(), xe = new f.Matrix4();
|
|
16
16
|
new f.Vector3();
|
|
17
17
|
const He = new f.Vector3(0, 0, 1), Ke = new f.Vector3(1, 0, 0), Je = new f.Vector3(0, 1, 0), $e = new f.Vector3(0, 0, 1);
|
|
18
18
|
class et {
|
|
@@ -321,7 +321,7 @@ class et {
|
|
|
321
321
|
/// Bone's parent object
|
|
322
322
|
vBasis: r.position.clone(),
|
|
323
323
|
// Original local position
|
|
324
|
-
vWorld: r.parent.getWorldPosition(
|
|
324
|
+
vWorld: r.parent.getWorldPosition(T).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(T, oe, ie), T.copy(He).applyQuaternion(oe).setY(0).normalize(), oe.premultiply(Oe.setFromUnitVectors(He, T).invert()).normalize(), u.qWorldInverseYaw = oe.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], T.copy(o.vWorld), fe.copy(o.boneParent.matrixWorld), xe.copy(fe).invert(), o.vWorld.setFromMatrixPosition(fe), T.applyMatrix4(xe), T.length() > 0.5 && (console.info("Info: Unrealistic jump of " + T.length().toFixed(2) + " meters."), T.setLength(0.5)), T.applyQuaternion(o.bone.quaternion), w[0] = T.x, w[1] = T.y, w[2] = -T.z, w[3] = T.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, T.set(
|
|
363
363
|
o.vBasis.x + w[0],
|
|
364
364
|
o.vBasis.y + w[1],
|
|
365
365
|
o.vBasis.z + w[2]
|
|
366
|
-
),
|
|
366
|
+
), T.applyMatrix4(fe), T.x += m[0], T.y += m[1], T.z += m[2], T.applyMatrix4(xe), w[0] += T.x - o.vBasis.x, w[1] += T.y - o.vBasis.y, w[2] += T.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(T, oe, ie), T.copy(He).applyQuaternion(oe).setY(0).normalize(), oe.premultiply(Oe.setFromUnitVectors(He, T).invert()).normalize(), o.boneParent.quaternion.multiply(oe.invert()), o.boneParent.quaternion.multiply(o.qWorldInverseYaw)), o.isZ && (m = Math.atan(w[0] / o.l), oe.setFromAxisAngle($e, -m), o.boneParent.quaternion.multiply(oe)), 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), oe.setFromAxisAngle(Ke, -m), o.boneParent.quaternion.multiply(oe)), o.isT && (m = 1.5 * Math.tanh(w[3] * 1.5), oe.setFromAxisAngle(Je, -m), o.boneParent.quaternion.multiply(oe)), 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],
|
|
374
|
+
m = o.excludes[n], ie.set(0, 0, 0), m.deltaLocal && (ie.x += m.deltaLocal[0], ie.y += m.deltaLocal[1], ie.z += m.deltaLocal[2]), ie.applyMatrix4(m.bone.matrixWorld), xe.copy(o.boneParent.matrixWorld).invert(), ie.applyMatrix4(xe), T.copy(o.bone.position), !(T.distanceToSquared(ie) >= m.radiusSq) && (ue = T.length(), re = ie.length(), !(re > m.radius + ue) && (re < Math.abs(m.radius - ue) || (re = (re * re + ue * ue - m.radiusSq) / (2 * re), ie.normalize(), Ce.copy(ie).multiplyScalar(re), re = Math.sqrt(ue * ue - re * re), T.subVectors(T, Ce).projectOnPlane(ie).normalize().multiplyScalar(re), ze.subVectors(o.vBasis, Ce).projectOnPlane(ie).normalize(), ue = ze.dot(T), ue < 0 && (ue = Math.sqrt(re * re - ue * ue), ze.multiplyScalar(ue), T.add(ze)), T.add(Ce).normalize(), ie.copy(o.bone.position).normalize(), oe.setFromUnitVectors(ie, T), o.boneParent.quaternion.premultiply(oe), 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), T.setFromMatrixPosition(fe), t.setXYZ(e, T.x, T.y, T.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), T.setFromMatrixPosition(fe), t.setXYZ(n, T.x, T.y, T.z), fe.multiplyMatrices(xe, m.bones[e].parent.matrixWorld), T.setFromMatrixPosition(fe), t.setXYZ(n + 1, T.x, T.y, T.z);
|
|
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
|
+
}, _ = 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 ? (_.setFromEuler(Z), n.multiply(_)) : 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 && (_.setFromAxisAngle(mt, this.volumeHeadCurrent), this.objectNeck.quaternion.multiply(_)), 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) {
|
|
@@ -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, U = b[x].match(l);
|
|
5268
5268
|
let p = b[x].match(s);
|
|
5269
|
-
const
|
|
5270
|
-
if (p && !S && !
|
|
5269
|
+
const F = b[x].match(h), C = b[x].match(o);
|
|
5270
|
+
if (p && !S && !F && b[x + 1].match(s) && (p = !1), n && (u += b[x]), U && (!i || i.every((y) => x < y[0] || x > y[1])) && (a += b[x]), (C || 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 (F) {
|
|
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, U = 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 * U / 3), S + Math.min(25, U / 2), S + U + Math.min(60, U / 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((F) => F.name.includes(a) || F.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 F = 0; F < x.visemes.length; F++) {
|
|
5502
|
+
const C = x.visemes[F], y = x.times[F] / p, I = x.durations[F] / 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_" + C]: [null, C === "PP" || C === "FF" ? 0.9 : 0.6, 0]
|
|
5508
5508
|
}
|
|
5509
5509
|
});
|
|
5510
5510
|
}
|
|
5511
5511
|
}
|
|
5512
|
-
const
|
|
5513
|
-
this.audioPlaylist.push({ anim:
|
|
5512
|
+
const U = [...t.anim, ...S];
|
|
5513
|
+
this.audioPlaylist.push({ anim: U, 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);
|
|
@@ -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), _.copy(this.armature.quaternion), _.multiply(this.poseTarget.props["Hips.quaternion"]), _.multiply(this.poseTarget.props["Spine.quaternion"]), _.multiply(this.poseTarget.props["Spine1.quaternion"]), _.multiply(this.poseTarget.props["Spine2.quaternion"]), _.multiply(this.poseTarget.props["Neck.quaternion"]), _.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(_.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,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),
|
|
6202
|
+
t === null && (t = h), e === null && (e = r), _.copy(this.armature.quaternion), _.multiply(this.poseTarget.props["Hips.quaternion"]), _.multiply(this.poseTarget.props["Spine.quaternion"]), _.multiply(this.poseTarget.props["Spine1.quaternion"]), _.multiply(this.poseTarget.props["Spine2.quaternion"]), _.multiply(this.poseTarget.props["Neck.quaternion"]), _.multiply(this.poseTarget.props["Head.quaternion"]), Z.setFromQuaternion(_);
|
|
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
|
-
let
|
|
6205
|
+
let U = (Math.random() - 0.5) / 4, p = (Math.random() - 0.5) / 4;
|
|
6206
6206
|
if (n) {
|
|
6207
|
-
let
|
|
6208
|
-
|
|
6209
|
-
const
|
|
6207
|
+
let F = this.animQueue.findIndex((y) => y.template.name === "lookat");
|
|
6208
|
+
F !== -1 && this.animQueue.splice(F, 1);
|
|
6209
|
+
const C = {
|
|
6210
6210
|
name: "lookat",
|
|
6211
6211
|
dt: [750, n],
|
|
6212
6212
|
vs: {
|
|
6213
|
-
bodyRotateX: [x +
|
|
6213
|
+
bodyRotateX: [x + U],
|
|
6214
6214
|
bodyRotateY: [S + p],
|
|
6215
|
-
eyesRotateX: [-3 *
|
|
6215
|
+
eyesRotateX: [-3 * U + 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(C));
|
|
6225
6225
|
}
|
|
6226
6226
|
}
|
|
6227
6227
|
/**
|
|
@@ -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 E = k.toLowerCase();
|
|
6527
|
+
if ((A.includes("left") && E.includes("left") || A.includes("right") && E.includes("right")) && (A.includes("arm") && E.includes("arm") && !E.includes("fore") || A.includes("forearm") && E.includes("forearm") || A.includes("hand") && E.includes("hand") && !E.includes("index") && !E.includes("thumb") || A.includes("shoulder") && E.includes("shoulder")))
|
|
6528
6528
|
return k;
|
|
6529
6529
|
}
|
|
6530
6530
|
return null;
|
|
@@ -6535,41 +6535,19 @@ 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
|
+
), U = 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:", U.sort().join(", "));
|
|
6542
|
+
const p = [], F = /* @__PURE__ */ new Set();
|
|
6543
6543
|
if (d.tracks.forEach((I) => {
|
|
6544
|
-
const A = I.name.replaceAll("mixamorig", "").split("."), Y = A[0], k = A[1],
|
|
6545
|
-
if (
|
|
6546
|
-
const
|
|
6547
|
-
|
|
6548
|
-
const ee = C.includes("Arm") || C.includes("Hand") || C.includes("Shoulder");
|
|
6549
|
-
C.includes("Left"), C.includes("Right");
|
|
6550
|
-
const ie = C.includes("ForeArm") || C.includes("Forearm"), oe = C.includes("Hand") && !C.includes("Index") && !C.includes("Thumb") && !C.includes("Middle") && !C.includes("Ring") && !C.includes("Pinky");
|
|
6551
|
-
if (ee && (k === "quaternion" || k === "rotation") && k === "quaternion" && B.values && B.values.length >= 4) {
|
|
6552
|
-
const he = B.times.length;
|
|
6553
|
-
for (let K = 0; K < he; K++) {
|
|
6554
|
-
const Q = K * 4;
|
|
6555
|
-
if (Q + 3 < B.values.length) {
|
|
6556
|
-
let W = B.values[Q], v = B.values[Q + 1], R = B.values[Q + 2], T = B.values[Q + 3];
|
|
6557
|
-
const M = new f.Quaternion(W, v, R, T);
|
|
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;
|
|
6566
|
-
}
|
|
6567
|
-
}
|
|
6568
|
-
}
|
|
6569
|
-
p.push(B), Y !== C && g.set(Y, C);
|
|
6544
|
+
const A = I.name.replaceAll("mixamorig", "").split("."), Y = A[0], k = A[1], E = b(Y);
|
|
6545
|
+
if (E && k) {
|
|
6546
|
+
const q = `${E}.${k}`, G = I.clone();
|
|
6547
|
+
G.name = q, p.push(G), Y !== E && g.set(Y, E);
|
|
6570
6548
|
} else
|
|
6571
|
-
|
|
6572
|
-
}),
|
|
6549
|
+
F.add(Y), (Y.toLowerCase().includes("arm") || Y.toLowerCase().includes("hand") || Y.toLowerCase().includes("shoulder")) && console.warn(`⚠️ Arm bone "${Y}" could not be mapped to avatar skeleton`);
|
|
6550
|
+
}), F.size > 0 && console.warn(`⚠️ ${F.size} bone(s) could not be mapped:`, Array.from(F).sort().join(", ")), p.length > 0) {
|
|
6573
6551
|
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
6552
|
`✓ Mapped ${g.size} bone(s):`,
|
|
6575
6553
|
Array.from(g.entries()).map(([z, A]) => `${z}→${A}`).join(", ")
|
|
@@ -6580,18 +6558,18 @@ class Be {
|
|
|
6580
6558
|
I.length > 0 ? console.log(`✓ Arm bones mapped: ${I.join(", ")}`) : console.warn("⚠️ No arm bones were mapped! This may cause arm rigging issues.");
|
|
6581
6559
|
} else
|
|
6582
6560
|
console.error("❌ No tracks could be mapped! Animation may not work correctly.");
|
|
6583
|
-
const
|
|
6561
|
+
const C = {};
|
|
6584
6562
|
d.tracks.forEach((I) => {
|
|
6585
6563
|
I.name = I.name.replaceAll("mixamorig", "");
|
|
6586
6564
|
const z = I.name.split(".");
|
|
6587
6565
|
if (z[1] === "position") {
|
|
6588
6566
|
for (let A = 0; A < I.values.length; A++)
|
|
6589
6567
|
I.values[A] = I.values[A] * s;
|
|
6590
|
-
|
|
6591
|
-
} else z[1] === "quaternion" ?
|
|
6568
|
+
C[I.name] = new f.Vector3(I.values[0], I.values[1], I.values[2]);
|
|
6569
|
+
} else z[1] === "quaternion" ? C[I.name] = new f.Quaternion(I.values[0], I.values[1], I.values[2], I.values[3]) : z[1] === "rotation" && (C[z[0] + ".quaternion"] = new f.Quaternion().setFromEuler(new f.Euler(I.values[0], I.values[1], I.values[2], "XYZ")).normalize());
|
|
6592
6570
|
});
|
|
6593
|
-
const y = { props:
|
|
6594
|
-
|
|
6571
|
+
const y = { props: C };
|
|
6572
|
+
C["Hips.position"] && (C["Hips.position"].y < 0.5 ? y.lying = !0 : y.standing = !0), this.animClips.push({
|
|
6595
6573
|
url: t + "-" + i,
|
|
6596
6574
|
clip: d,
|
|
6597
6575
|
pose: y
|
|
@@ -6729,12 +6707,12 @@ class Be {
|
|
|
6729
6707
|
const x = t.iterations || 10;
|
|
6730
6708
|
if (e)
|
|
6731
6709
|
for (let S = 0; S < x; S++) {
|
|
6732
|
-
let
|
|
6733
|
-
for (let p = 0,
|
|
6734
|
-
const
|
|
6735
|
-
|
|
6710
|
+
let U = !1;
|
|
6711
|
+
for (let p = 0, F = b.length; p < F; p++) {
|
|
6712
|
+
const C = b[p].bone;
|
|
6713
|
+
C.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
6714
|
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(),
|
|
6715
|
+
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(), _.setFromAxisAngle(a, y), C.quaternion.multiply(_), C.rotation.setFromVector3(d.setFromEuler(C.rotation).clamp(new f.Vector3(
|
|
6738
6716
|
b[p].minx !== void 0 ? b[p].minx : -1 / 0,
|
|
6739
6717
|
b[p].miny !== void 0 ? b[p].miny : -1 / 0,
|
|
6740
6718
|
b[p].minz !== void 0 ? b[p].minz : -1 / 0
|
|
@@ -6742,9 +6720,9 @@ class Be {
|
|
|
6742
6720
|
b[p].maxx !== void 0 ? b[p].maxx : 1 / 0,
|
|
6743
6721
|
b[p].maxy !== void 0 ? b[p].maxy : 1 / 0,
|
|
6744
6722
|
b[p].maxz !== void 0 ? b[p].maxz : 1 / 0
|
|
6745
|
-
))),
|
|
6723
|
+
))), C.updateMatrixWorld(!0), U = !0);
|
|
6746
6724
|
}
|
|
6747
|
-
if (!
|
|
6725
|
+
if (!U) break;
|
|
6748
6726
|
}
|
|
6749
6727
|
i && b.forEach((S) => {
|
|
6750
6728
|
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;
|
|
@@ -6837,41 +6815,41 @@ const Ve = Me(({
|
|
|
6837
6815
|
style: b = {},
|
|
6838
6816
|
animations: x = {}
|
|
6839
6817
|
}, S) => {
|
|
6840
|
-
const
|
|
6841
|
-
|
|
6842
|
-
I.current =
|
|
6843
|
-
}, [
|
|
6844
|
-
|
|
6818
|
+
const U = O(null), p = O(null), F = O(r), C = O(null), y = O(null), I = O(!1), z = O({ remainingText: null, originalText: null, options: null }), A = O([]), Y = O(0), [k, E] = ce(!0), [q, G] = ce(null), [ee, se] = ce(!1), [ae, pe] = ce(!1);
|
|
6819
|
+
de(() => {
|
|
6820
|
+
I.current = ae;
|
|
6821
|
+
}, [ae]), de(() => {
|
|
6822
|
+
F.current = r;
|
|
6845
6823
|
}, [r]);
|
|
6846
|
-
const
|
|
6824
|
+
const te = Ee(), le = i || te.service;
|
|
6847
6825
|
let W;
|
|
6848
|
-
|
|
6826
|
+
le === "browser" ? W = {
|
|
6849
6827
|
service: "browser",
|
|
6850
6828
|
endpoint: "",
|
|
6851
6829
|
apiKey: null,
|
|
6852
6830
|
defaultVoice: "Google US English"
|
|
6853
|
-
} :
|
|
6831
|
+
} : le === "elevenlabs" ? W = {
|
|
6854
6832
|
service: "elevenlabs",
|
|
6855
6833
|
endpoint: "https://api.elevenlabs.io/v1/text-to-speech",
|
|
6856
|
-
apiKey: o ||
|
|
6857
|
-
defaultVoice: s ||
|
|
6858
|
-
voices:
|
|
6859
|
-
} :
|
|
6834
|
+
apiKey: o || te.apiKey,
|
|
6835
|
+
defaultVoice: s || te.defaultVoice || Ie.defaultVoice,
|
|
6836
|
+
voices: te.voices || Ie.voices
|
|
6837
|
+
} : le === "deepgram" ? W = {
|
|
6860
6838
|
service: "deepgram",
|
|
6861
6839
|
endpoint: "https://api.deepgram.com/v1/speak",
|
|
6862
|
-
apiKey: o ||
|
|
6863
|
-
defaultVoice: s ||
|
|
6864
|
-
voices:
|
|
6840
|
+
apiKey: o || te.apiKey,
|
|
6841
|
+
defaultVoice: s || te.defaultVoice || Te.defaultVoice,
|
|
6842
|
+
voices: te.voices || Te.voices
|
|
6865
6843
|
} : W = {
|
|
6866
|
-
...
|
|
6844
|
+
...te,
|
|
6867
6845
|
// Override API key if provided via props
|
|
6868
|
-
apiKey: o !== null ? o :
|
|
6846
|
+
apiKey: o !== null ? o : te.apiKey
|
|
6869
6847
|
};
|
|
6870
6848
|
const v = {
|
|
6871
6849
|
url: X,
|
|
6872
6850
|
body: t,
|
|
6873
6851
|
avatarMood: e,
|
|
6874
|
-
ttsLang:
|
|
6852
|
+
ttsLang: le === "browser" ? "en-US" : n,
|
|
6875
6853
|
ttsVoice: s || W.defaultVoice,
|
|
6876
6854
|
lipsyncLang: "en",
|
|
6877
6855
|
showFullAvatar: r,
|
|
@@ -6880,85 +6858,85 @@ const Ve = Me(({
|
|
|
6880
6858
|
}, R = {
|
|
6881
6859
|
ttsEndpoint: W.endpoint,
|
|
6882
6860
|
ttsApikey: W.apiKey,
|
|
6883
|
-
ttsService:
|
|
6861
|
+
ttsService: le,
|
|
6884
6862
|
lipsyncModules: ["en"],
|
|
6885
6863
|
cameraView: u
|
|
6886
|
-
},
|
|
6887
|
-
if (!(!
|
|
6864
|
+
}, H = B(async () => {
|
|
6865
|
+
if (!(!U.current || p.current))
|
|
6888
6866
|
try {
|
|
6889
|
-
if (
|
|
6890
|
-
if (
|
|
6891
|
-
const
|
|
6892
|
-
d(
|
|
6867
|
+
if (E(!0), G(null), p.current = new Be(U.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, (D) => {
|
|
6868
|
+
if (D.lengthComputable) {
|
|
6869
|
+
const $ = Math.min(100, Math.round(D.loaded / D.total * 100));
|
|
6870
|
+
d($);
|
|
6893
6871
|
}
|
|
6894
|
-
}), await new Promise((
|
|
6895
|
-
const
|
|
6896
|
-
p.current.lipsync && Object.keys(p.current.lipsync).length > 0 ?
|
|
6872
|
+
}), await new Promise((D) => {
|
|
6873
|
+
const $ = () => {
|
|
6874
|
+
p.current.lipsync && Object.keys(p.current.lipsync).length > 0 ? D() : setTimeout($, 100);
|
|
6897
6875
|
};
|
|
6898
|
-
|
|
6876
|
+
$();
|
|
6899
6877
|
}), p.current && p.current.setShowFullAvatar)
|
|
6900
6878
|
try {
|
|
6901
6879
|
p.current.setShowFullAvatar(r);
|
|
6902
|
-
} catch (
|
|
6903
|
-
console.warn("Error setting full body mode on initialization:",
|
|
6880
|
+
} catch (D) {
|
|
6881
|
+
console.warn("Error setting full body mode on initialization:", D);
|
|
6904
6882
|
}
|
|
6905
|
-
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()),
|
|
6906
|
-
const
|
|
6883
|
+
p.current && p.current.controls && (p.current.controls.enableRotate = !1, p.current.controls.enableZoom = !1, p.current.controls.enablePan = !1, p.current.controls.enableDamping = !1, p.current.controls.update()), E(!1), se(!0), a(p.current);
|
|
6884
|
+
const N = () => {
|
|
6907
6885
|
document.visibilityState === "visible" ? p.current?.start() : p.current?.stop();
|
|
6908
6886
|
};
|
|
6909
|
-
return document.addEventListener("visibilitychange",
|
|
6910
|
-
document.removeEventListener("visibilitychange",
|
|
6887
|
+
return document.addEventListener("visibilitychange", N), () => {
|
|
6888
|
+
document.removeEventListener("visibilitychange", N);
|
|
6911
6889
|
};
|
|
6912
6890
|
} catch (L) {
|
|
6913
|
-
console.error("Error initializing TalkingHead:", L),
|
|
6891
|
+
console.error("Error initializing TalkingHead:", L), G(L.message || "Failed to initialize avatar"), E(!1), c(L);
|
|
6914
6892
|
}
|
|
6915
6893
|
}, [X, t, e, n, i, s, o, r, l, h, u]);
|
|
6916
|
-
|
|
6894
|
+
de(() => (H(), () => {
|
|
6917
6895
|
p.current && (p.current.stop(), p.current.dispose(), p.current = null);
|
|
6918
|
-
}), [
|
|
6919
|
-
if (!
|
|
6920
|
-
const L = new ResizeObserver((
|
|
6921
|
-
for (const
|
|
6896
|
+
}), [H]), de(() => {
|
|
6897
|
+
if (!U.current || !p.current) return;
|
|
6898
|
+
const L = new ResizeObserver((D) => {
|
|
6899
|
+
for (const $ of D)
|
|
6922
6900
|
p.current && p.current.onResize && p.current.onResize();
|
|
6923
6901
|
});
|
|
6924
|
-
L.observe(
|
|
6925
|
-
const
|
|
6902
|
+
L.observe(U.current);
|
|
6903
|
+
const N = () => {
|
|
6926
6904
|
p.current && p.current.onResize && p.current.onResize();
|
|
6927
6905
|
};
|
|
6928
|
-
return window.addEventListener("resize",
|
|
6929
|
-
L.disconnect(), window.removeEventListener("resize",
|
|
6906
|
+
return window.addEventListener("resize", N), () => {
|
|
6907
|
+
L.disconnect(), window.removeEventListener("resize", N);
|
|
6930
6908
|
};
|
|
6931
6909
|
}, [ee]);
|
|
6932
|
-
const
|
|
6910
|
+
const P = B(async () => {
|
|
6933
6911
|
if (p.current && p.current.audioCtx)
|
|
6934
6912
|
try {
|
|
6935
6913
|
(p.current.audioCtx.state === "suspended" || p.current.audioCtx.state === "interrupted") && (await p.current.audioCtx.resume(), console.log("Audio context resumed"));
|
|
6936
6914
|
} catch (L) {
|
|
6937
6915
|
console.warn("Failed to resume audio context:", L);
|
|
6938
6916
|
}
|
|
6939
|
-
}, []),
|
|
6917
|
+
}, []), V = B(async (L, N = {}) => {
|
|
6940
6918
|
if (p.current && ee)
|
|
6941
6919
|
try {
|
|
6942
|
-
y.current && (clearInterval(y.current), y.current = null),
|
|
6943
|
-
const
|
|
6944
|
-
A.current =
|
|
6920
|
+
y.current && (clearInterval(y.current), y.current = null), C.current = { text: L, options: N }, z.current = { remainingText: null, originalText: null, options: null };
|
|
6921
|
+
const D = /[!\.\?\n\p{Extended_Pictographic}]/ug, $ = L.split(D).map((j) => j.trim()).filter((j) => j.length > 0);
|
|
6922
|
+
A.current = $, Y.current = 0, pe(!1), I.current = !1, await P();
|
|
6945
6923
|
const ge = {
|
|
6946
|
-
...
|
|
6947
|
-
lipsyncLang:
|
|
6924
|
+
...N,
|
|
6925
|
+
lipsyncLang: N.lipsyncLang || v.lipsyncLang || "en"
|
|
6948
6926
|
};
|
|
6949
|
-
if (
|
|
6927
|
+
if (N.onSpeechEnd && p.current) {
|
|
6950
6928
|
const j = p.current;
|
|
6951
|
-
let
|
|
6929
|
+
let he = null, Se = 0;
|
|
6952
6930
|
const Le = 1200;
|
|
6953
6931
|
let be = !1;
|
|
6954
|
-
|
|
6932
|
+
he = setInterval(() => {
|
|
6955
6933
|
if (Se++, I.current)
|
|
6956
6934
|
return;
|
|
6957
6935
|
if (Se > Le) {
|
|
6958
|
-
if (
|
|
6936
|
+
if (he && (clearInterval(he), he = null, y.current = null), !be && !I.current) {
|
|
6959
6937
|
be = !0;
|
|
6960
6938
|
try {
|
|
6961
|
-
|
|
6939
|
+
N.onSpeechEnd();
|
|
6962
6940
|
} catch (Ne) {
|
|
6963
6941
|
console.error("Error in onSpeechEnd callback (timeout):", Ne);
|
|
6964
6942
|
}
|
|
@@ -6968,83 +6946,83 @@ const Ve = Me(({
|
|
|
6968
6946
|
const ye = !j.speechQueue || j.speechQueue.length === 0, ke = !j.audioPlaylist || j.audioPlaylist.length === 0;
|
|
6969
6947
|
j && j.isSpeaking === !1 && ye && ke && j.isAudioPlaying === !1 && !be && !I.current && setTimeout(() => {
|
|
6970
6948
|
if (j && !I.current && j.isSpeaking === !1 && (!j.speechQueue || j.speechQueue.length === 0) && (!j.audioPlaylist || j.audioPlaylist.length === 0) && j.isAudioPlaying === !1 && !be && !I.current) {
|
|
6971
|
-
be = !0,
|
|
6949
|
+
be = !0, he && (clearInterval(he), he = null, y.current = null);
|
|
6972
6950
|
try {
|
|
6973
|
-
|
|
6951
|
+
N.onSpeechEnd();
|
|
6974
6952
|
} catch (Ze) {
|
|
6975
6953
|
console.error("Error in onSpeechEnd callback:", Ze);
|
|
6976
6954
|
}
|
|
6977
6955
|
}
|
|
6978
6956
|
}, 100);
|
|
6979
|
-
}, 100), y.current =
|
|
6957
|
+
}, 100), y.current = he;
|
|
6980
6958
|
}
|
|
6981
6959
|
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
|
|
6960
|
+
await P(), p.current && p.current.lipsync && (p.current.setSlowdownRate && p.current.setSlowdownRate(1.05), p.current.speakText(L, ge));
|
|
6983
6961
|
}, 100);
|
|
6984
|
-
} catch (
|
|
6985
|
-
console.error("Error speaking text:",
|
|
6962
|
+
} catch (D) {
|
|
6963
|
+
console.error("Error speaking text:", D), G(D.message || "Failed to speak text");
|
|
6986
6964
|
}
|
|
6987
|
-
}, [ee,
|
|
6988
|
-
p.current && (p.current.stopSpeaking(), p.current.setSlowdownRate && p.current.setSlowdownRate(1),
|
|
6989
|
-
}, []),
|
|
6965
|
+
}, [ee, P, v.lipsyncLang]), J = B(() => {
|
|
6966
|
+
p.current && (p.current.stopSpeaking(), p.current.setSlowdownRate && p.current.setSlowdownRate(1), C.current = null, pe(!1));
|
|
6967
|
+
}, []), Q = B(() => {
|
|
6990
6968
|
if (p.current && p.current.pauseSpeaking) {
|
|
6991
6969
|
const L = p.current;
|
|
6992
6970
|
if (L.isSpeaking || L.audioPlaylist && L.audioPlaylist.length > 0 || L.speechQueue && L.speechQueue.length > 0) {
|
|
6993
6971
|
y.current && (clearInterval(y.current), y.current = null);
|
|
6994
|
-
let
|
|
6995
|
-
if (
|
|
6996
|
-
const
|
|
6997
|
-
if (
|
|
6972
|
+
let D = "";
|
|
6973
|
+
if (C.current && A.current.length > 0) {
|
|
6974
|
+
const $ = A.current.length, ge = L.speechQueue ? L.speechQueue.filter((Le) => Le && Le.text && Array.isArray(Le.text) && Le.text.length > 0).length : 0, j = L.audioPlaylist && L.audioPlaylist.length > 0, he = ge + (j ? 1 : 0), Se = $ - he;
|
|
6975
|
+
if (he > 0 && Se < $ && (D = A.current.slice(Se).join(". ").trim(), !D && ge > 0 && L.speechQueue)) {
|
|
6998
6976
|
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() && (
|
|
6977
|
+
be && be.trim() && (D = be.trim());
|
|
7000
6978
|
}
|
|
7001
6979
|
}
|
|
7002
|
-
|
|
7003
|
-
remainingText:
|
|
7004
|
-
originalText:
|
|
7005
|
-
options:
|
|
7006
|
-
}), L.speechQueue && (L.speechQueue.length = 0), p.current.pauseSpeaking(), I.current = !0,
|
|
6980
|
+
C.current && (z.current = {
|
|
6981
|
+
remainingText: D || null,
|
|
6982
|
+
originalText: C.current.text,
|
|
6983
|
+
options: C.current.options
|
|
6984
|
+
}), L.speechQueue && (L.speechQueue.length = 0), p.current.pauseSpeaking(), I.current = !0, pe(!0);
|
|
7007
6985
|
}
|
|
7008
6986
|
}
|
|
7009
|
-
}, []),
|
|
7010
|
-
if (!p.current || !
|
|
6987
|
+
}, []), K = B(async () => {
|
|
6988
|
+
if (!p.current || !ae)
|
|
7011
6989
|
return;
|
|
7012
|
-
let L = "",
|
|
6990
|
+
let L = "", N = {};
|
|
7013
6991
|
if (z.current && z.current.remainingText)
|
|
7014
|
-
L = z.current.remainingText,
|
|
7015
|
-
else if (
|
|
7016
|
-
L =
|
|
6992
|
+
L = z.current.remainingText, N = z.current.options || {}, z.current = { remainingText: null, originalText: null, options: null };
|
|
6993
|
+
else if (C.current && C.current.text)
|
|
6994
|
+
L = C.current.text, N = C.current.options || {};
|
|
7017
6995
|
else {
|
|
7018
|
-
console.warn("Resume called but no paused speech found"),
|
|
6996
|
+
console.warn("Resume called but no paused speech found"), pe(!1), I.current = !1;
|
|
7019
6997
|
return;
|
|
7020
6998
|
}
|
|
7021
|
-
|
|
7022
|
-
const
|
|
7023
|
-
...
|
|
7024
|
-
lipsyncLang:
|
|
6999
|
+
pe(!1), I.current = !1, await P();
|
|
7000
|
+
const D = {
|
|
7001
|
+
...N,
|
|
7002
|
+
lipsyncLang: N.lipsyncLang || v.lipsyncLang || "en"
|
|
7025
7003
|
};
|
|
7026
7004
|
try {
|
|
7027
|
-
await
|
|
7028
|
-
} catch (
|
|
7029
|
-
console.error("Error resuming speech:",
|
|
7005
|
+
await V(L, D);
|
|
7006
|
+
} catch ($) {
|
|
7007
|
+
console.error("Error resuming speech:", $), pe(!1), I.current = !1;
|
|
7030
7008
|
}
|
|
7031
|
-
}, [
|
|
7009
|
+
}, [P, ae, V, v]), Ae = B((L) => {
|
|
7032
7010
|
p.current && p.current.setMood(L);
|
|
7033
|
-
}, []), we =
|
|
7011
|
+
}, []), we = B((L) => {
|
|
7034
7012
|
p.current && p.current.setSlowdownRate && p.current.setSlowdownRate(L);
|
|
7035
|
-
}, []),
|
|
7013
|
+
}, []), M = B((L, N = !1) => {
|
|
7036
7014
|
if (p.current && p.current.playAnimation) {
|
|
7037
7015
|
if (x && x[L] && (L = x[L]), p.current.setShowFullAvatar)
|
|
7038
7016
|
try {
|
|
7039
|
-
p.current.setShowFullAvatar(
|
|
7040
|
-
} catch (
|
|
7041
|
-
console.warn("Error setting full body mode:",
|
|
7017
|
+
p.current.setShowFullAvatar(F.current);
|
|
7018
|
+
} catch ($) {
|
|
7019
|
+
console.warn("Error setting full body mode:", $);
|
|
7042
7020
|
}
|
|
7043
7021
|
if (L.includes("."))
|
|
7044
7022
|
try {
|
|
7045
|
-
p.current.playAnimation(L, null, 10, 0, 0.01,
|
|
7046
|
-
} catch (
|
|
7047
|
-
console.warn(`Failed to play ${L}:`,
|
|
7023
|
+
p.current.playAnimation(L, null, 10, 0, 0.01, N);
|
|
7024
|
+
} catch ($) {
|
|
7025
|
+
console.warn(`Failed to play ${L}:`, $);
|
|
7048
7026
|
try {
|
|
7049
7027
|
p.current.setBodyMovement("idle");
|
|
7050
7028
|
} catch (ge) {
|
|
@@ -7052,11 +7030,11 @@ const Ve = Me(({
|
|
|
7052
7030
|
}
|
|
7053
7031
|
}
|
|
7054
7032
|
else {
|
|
7055
|
-
const
|
|
7033
|
+
const $ = [".fbx", ".glb", ".gltf"];
|
|
7056
7034
|
let ge = !1;
|
|
7057
|
-
for (const j of
|
|
7035
|
+
for (const j of $)
|
|
7058
7036
|
try {
|
|
7059
|
-
p.current.playAnimation(L + j, null, 10, 0, 0.01,
|
|
7037
|
+
p.current.playAnimation(L + j, null, 10, 0, 0.01, N), ge = !0;
|
|
7060
7038
|
break;
|
|
7061
7039
|
} catch {
|
|
7062
7040
|
}
|
|
@@ -7070,35 +7048,35 @@ const Ve = Me(({
|
|
|
7070
7048
|
}
|
|
7071
7049
|
}
|
|
7072
7050
|
}
|
|
7073
|
-
}, [x]),
|
|
7051
|
+
}, [x]), ne = B(() => {
|
|
7074
7052
|
p.current && p.current.onResize && p.current.onResize();
|
|
7075
7053
|
}, []);
|
|
7076
7054
|
return Fe(S, () => ({
|
|
7077
|
-
speakText:
|
|
7078
|
-
stopSpeaking:
|
|
7079
|
-
pauseSpeaking:
|
|
7080
|
-
resumeSpeaking:
|
|
7081
|
-
resumeAudioContext:
|
|
7055
|
+
speakText: V,
|
|
7056
|
+
stopSpeaking: J,
|
|
7057
|
+
pauseSpeaking: Q,
|
|
7058
|
+
resumeSpeaking: K,
|
|
7059
|
+
resumeAudioContext: P,
|
|
7082
7060
|
setMood: Ae,
|
|
7083
7061
|
setTimingAdjustment: we,
|
|
7084
|
-
playAnimation:
|
|
7062
|
+
playAnimation: M,
|
|
7085
7063
|
isReady: ee,
|
|
7086
|
-
isPaused:
|
|
7064
|
+
isPaused: ae,
|
|
7087
7065
|
talkingHead: p.current,
|
|
7088
|
-
handleResize:
|
|
7066
|
+
handleResize: ne,
|
|
7089
7067
|
setBodyMovement: (L) => {
|
|
7090
7068
|
if (p.current && p.current.setShowFullAvatar && p.current.setBodyMovement)
|
|
7091
7069
|
try {
|
|
7092
|
-
p.current.setShowFullAvatar(
|
|
7093
|
-
} catch (
|
|
7094
|
-
console.warn("Error setting body movement:",
|
|
7070
|
+
p.current.setShowFullAvatar(F.current), p.current.setBodyMovement(L);
|
|
7071
|
+
} catch (N) {
|
|
7072
|
+
console.warn("Error setting body movement:", N);
|
|
7095
7073
|
}
|
|
7096
7074
|
},
|
|
7097
7075
|
setMovementIntensity: (L) => p.current?.setMovementIntensity(L),
|
|
7098
7076
|
playRandomDance: () => {
|
|
7099
7077
|
if (p.current && p.current.setShowFullAvatar && p.current.playRandomDance)
|
|
7100
7078
|
try {
|
|
7101
|
-
p.current.setShowFullAvatar(
|
|
7079
|
+
p.current.setShowFullAvatar(F.current), p.current.playRandomDance();
|
|
7102
7080
|
} catch (L) {
|
|
7103
7081
|
console.warn("Error playing random dance:", L);
|
|
7104
7082
|
}
|
|
@@ -7106,15 +7084,15 @@ const Ve = Me(({
|
|
|
7106
7084
|
playReaction: (L) => {
|
|
7107
7085
|
if (p.current && p.current.setShowFullAvatar && p.current.playReaction)
|
|
7108
7086
|
try {
|
|
7109
|
-
p.current.setShowFullAvatar(
|
|
7110
|
-
} catch (
|
|
7111
|
-
console.warn("Error playing reaction:",
|
|
7087
|
+
p.current.setShowFullAvatar(F.current), p.current.playReaction(L);
|
|
7088
|
+
} catch (N) {
|
|
7089
|
+
console.warn("Error playing reaction:", N);
|
|
7112
7090
|
}
|
|
7113
7091
|
},
|
|
7114
7092
|
playCelebration: () => {
|
|
7115
7093
|
if (p.current && p.current.setShowFullAvatar && p.current.playCelebration)
|
|
7116
7094
|
try {
|
|
7117
|
-
p.current.setShowFullAvatar(
|
|
7095
|
+
p.current.setShowFullAvatar(F.current), p.current.playCelebration();
|
|
7118
7096
|
} catch (L) {
|
|
7119
7097
|
console.warn("Error playing celebration:", L);
|
|
7120
7098
|
}
|
|
@@ -7122,9 +7100,9 @@ const Ve = Me(({
|
|
|
7122
7100
|
setShowFullAvatar: (L) => {
|
|
7123
7101
|
if (p.current && p.current.setShowFullAvatar)
|
|
7124
7102
|
try {
|
|
7125
|
-
|
|
7126
|
-
} catch (
|
|
7127
|
-
console.warn("Error setting showFullAvatar:",
|
|
7103
|
+
F.current = L, p.current.setShowFullAvatar(L);
|
|
7104
|
+
} catch (N) {
|
|
7105
|
+
console.warn("Error setting showFullAvatar:", N);
|
|
7128
7106
|
}
|
|
7129
7107
|
},
|
|
7130
7108
|
lockAvatarPosition: () => {
|
|
@@ -7154,10 +7132,10 @@ const Ve = Me(({
|
|
|
7154
7132
|
...b
|
|
7155
7133
|
},
|
|
7156
7134
|
children: [
|
|
7157
|
-
/* @__PURE__ */
|
|
7135
|
+
/* @__PURE__ */ me(
|
|
7158
7136
|
"div",
|
|
7159
7137
|
{
|
|
7160
|
-
ref:
|
|
7138
|
+
ref: U,
|
|
7161
7139
|
className: "talking-head-viewer",
|
|
7162
7140
|
style: {
|
|
7163
7141
|
width: "100%",
|
|
@@ -7166,7 +7144,7 @@ const Ve = Me(({
|
|
|
7166
7144
|
}
|
|
7167
7145
|
}
|
|
7168
7146
|
),
|
|
7169
|
-
k && /* @__PURE__ */
|
|
7147
|
+
k && /* @__PURE__ */ me("div", { className: "loading-overlay", style: {
|
|
7170
7148
|
position: "absolute",
|
|
7171
7149
|
top: "50%",
|
|
7172
7150
|
left: "50%",
|
|
@@ -7175,7 +7153,7 @@ const Ve = Me(({
|
|
|
7175
7153
|
fontSize: "18px",
|
|
7176
7154
|
zIndex: 10
|
|
7177
7155
|
}, children: "Loading avatar..." }),
|
|
7178
|
-
|
|
7156
|
+
q && /* @__PURE__ */ me("div", { className: "error-overlay", style: {
|
|
7179
7157
|
position: "absolute",
|
|
7180
7158
|
top: "50%",
|
|
7181
7159
|
left: "50%",
|
|
@@ -7186,7 +7164,7 @@ const Ve = Me(({
|
|
|
7186
7164
|
zIndex: 10,
|
|
7187
7165
|
padding: "20px",
|
|
7188
7166
|
borderRadius: "8px"
|
|
7189
|
-
}, children:
|
|
7167
|
+
}, children: q })
|
|
7190
7168
|
]
|
|
7191
7169
|
}
|
|
7192
7170
|
);
|
|
@@ -7204,7 +7182,7 @@ const pt = Me(({
|
|
|
7204
7182
|
style: s = {},
|
|
7205
7183
|
avatarConfig: o = {}
|
|
7206
7184
|
}, l) => {
|
|
7207
|
-
const h =
|
|
7185
|
+
const h = O(null), r = O(null), [u, a] = ce(!0), [d, c] = ce(null), [g, b] = ce(!1), x = Ee(), S = o.ttsService || x.service, U = S === "browser" ? {
|
|
7208
7186
|
endpoint: "",
|
|
7209
7187
|
apiKey: null,
|
|
7210
7188
|
defaultVoice: "Google US English"
|
|
@@ -7220,7 +7198,7 @@ const pt = Me(({
|
|
|
7220
7198
|
body: "F",
|
|
7221
7199
|
avatarMood: "neutral",
|
|
7222
7200
|
ttsLang: S === "browser" ? "en-US" : "en",
|
|
7223
|
-
ttsVoice: o.ttsVoice ||
|
|
7201
|
+
ttsVoice: o.ttsVoice || U.defaultVoice,
|
|
7224
7202
|
lipsyncLang: "en",
|
|
7225
7203
|
// English lip-sync
|
|
7226
7204
|
showFullAvatar: !0,
|
|
@@ -7228,81 +7206,81 @@ const pt = Me(({
|
|
|
7228
7206
|
bodyMovement: "idle",
|
|
7229
7207
|
movementIntensity: 0.5,
|
|
7230
7208
|
...o
|
|
7231
|
-
},
|
|
7232
|
-
ttsEndpoint:
|
|
7233
|
-
ttsApikey:
|
|
7209
|
+
}, F = {
|
|
7210
|
+
ttsEndpoint: U.endpoint,
|
|
7211
|
+
ttsApikey: U.apiKey,
|
|
7234
7212
|
ttsService: S,
|
|
7235
7213
|
lipsyncModules: ["en"],
|
|
7236
7214
|
cameraView: "upper"
|
|
7237
|
-
},
|
|
7215
|
+
}, C = B(async () => {
|
|
7238
7216
|
if (!(!h.current || r.current))
|
|
7239
7217
|
try {
|
|
7240
|
-
if (a(!0), c(null), r.current = new Be(h.current,
|
|
7241
|
-
if (
|
|
7242
|
-
const
|
|
7243
|
-
t(
|
|
7218
|
+
if (a(!0), c(null), r.current = new Be(h.current, F), await r.current.showAvatar(p, (q) => {
|
|
7219
|
+
if (q.lengthComputable) {
|
|
7220
|
+
const G = Math.min(100, Math.round(q.loaded / q.total * 100));
|
|
7221
|
+
t(G);
|
|
7244
7222
|
}
|
|
7245
7223
|
}), 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:",
|
|
7224
|
+
const q = r.current.morphs[0].morphTargetDictionary;
|
|
7225
|
+
console.log("Available morph targets:", Object.keys(q));
|
|
7226
|
+
const G = Object.keys(q).filter((ee) => ee.startsWith("viseme_"));
|
|
7227
|
+
console.log("Viseme morph targets found:", G), G.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
7228
|
}
|
|
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)),
|
|
7229
|
+
if (await new Promise((q) => {
|
|
7230
|
+
const G = () => {
|
|
7231
|
+
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(G, 100));
|
|
7254
7232
|
};
|
|
7255
|
-
|
|
7233
|
+
G();
|
|
7256
7234
|
}), r.current && r.current.setShowFullAvatar)
|
|
7257
7235
|
try {
|
|
7258
7236
|
r.current.setShowFullAvatar(!0), console.log("Avatar initialized in full body mode");
|
|
7259
|
-
} catch (
|
|
7260
|
-
console.warn("Error setting full body mode on initialization:",
|
|
7237
|
+
} catch (q) {
|
|
7238
|
+
console.warn("Error setting full body mode on initialization:", q);
|
|
7261
7239
|
}
|
|
7262
7240
|
a(!1), b(!0), n(r.current);
|
|
7263
|
-
const
|
|
7241
|
+
const E = () => {
|
|
7264
7242
|
document.visibilityState === "visible" ? r.current?.start() : r.current?.stop();
|
|
7265
7243
|
};
|
|
7266
|
-
return document.addEventListener("visibilitychange",
|
|
7267
|
-
document.removeEventListener("visibilitychange",
|
|
7244
|
+
return document.addEventListener("visibilitychange", E), () => {
|
|
7245
|
+
document.removeEventListener("visibilitychange", E);
|
|
7268
7246
|
};
|
|
7269
7247
|
} catch (k) {
|
|
7270
7248
|
console.error("Error initializing TalkingHead:", k), c(k.message || "Failed to initialize avatar"), a(!1), e(k);
|
|
7271
7249
|
}
|
|
7272
7250
|
}, []);
|
|
7273
|
-
|
|
7251
|
+
de(() => (C(), () => {
|
|
7274
7252
|
r.current && (r.current.stop(), r.current.dispose(), r.current = null);
|
|
7275
|
-
}), [
|
|
7276
|
-
const y =
|
|
7253
|
+
}), [C]);
|
|
7254
|
+
const y = B((k) => {
|
|
7277
7255
|
if (r.current && g)
|
|
7278
7256
|
try {
|
|
7279
7257
|
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(() => {
|
|
7280
7258
|
r.current && r.current.lipsync ? (console.log("Lip-sync now ready, speaking..."), r.current.setSlowdownRate && (r.current.setSlowdownRate(1.05), console.log("Applied timing adjustment for better lip-sync")), r.current.speakText(k)) : console.error("Lip-sync still not ready after waiting");
|
|
7281
7259
|
}, 500));
|
|
7282
|
-
} catch (
|
|
7283
|
-
console.error("Error speaking text:",
|
|
7260
|
+
} catch (E) {
|
|
7261
|
+
console.error("Error speaking text:", E), c(E.message || "Failed to speak text");
|
|
7284
7262
|
}
|
|
7285
7263
|
else
|
|
7286
7264
|
console.warn("Avatar not ready for speaking. isReady:", g, "talkingHeadRef:", !!r.current);
|
|
7287
|
-
}, [g, p]), I =
|
|
7265
|
+
}, [g, p]), I = B(() => {
|
|
7288
7266
|
r.current && (r.current.stopSpeaking(), r.current.setSlowdownRate && (r.current.setSlowdownRate(1), console.log("Reset timing to normal")));
|
|
7289
|
-
}, []), z =
|
|
7267
|
+
}, []), z = B((k) => {
|
|
7290
7268
|
r.current && r.current.setMood(k);
|
|
7291
|
-
}, []), A =
|
|
7269
|
+
}, []), A = B((k) => {
|
|
7292
7270
|
r.current && r.current.setSlowdownRate && (r.current.setSlowdownRate(k), console.log("Timing adjustment set to:", k));
|
|
7293
|
-
}, []), Y =
|
|
7271
|
+
}, []), Y = B((k, E = !1) => {
|
|
7294
7272
|
if (r.current && r.current.playAnimation) {
|
|
7295
7273
|
if (r.current.setShowFullAvatar)
|
|
7296
7274
|
try {
|
|
7297
7275
|
r.current.setShowFullAvatar(!0);
|
|
7298
|
-
} catch (
|
|
7299
|
-
console.warn("Error setting full body mode:",
|
|
7276
|
+
} catch (G) {
|
|
7277
|
+
console.warn("Error setting full body mode:", G);
|
|
7300
7278
|
}
|
|
7301
7279
|
if (k.includes("."))
|
|
7302
7280
|
try {
|
|
7303
|
-
r.current.playAnimation(k, null, 10, 0, 0.01,
|
|
7304
|
-
} catch (
|
|
7305
|
-
console.log(`Failed to play ${k}:`,
|
|
7281
|
+
r.current.playAnimation(k, null, 10, 0, 0.01, E), console.log("Playing animation:", k);
|
|
7282
|
+
} catch (G) {
|
|
7283
|
+
console.log(`Failed to play ${k}:`, G);
|
|
7306
7284
|
try {
|
|
7307
7285
|
r.current.setBodyMovement("idle"), console.log("Fallback to idle animation");
|
|
7308
7286
|
} catch (ee) {
|
|
@@ -7310,21 +7288,21 @@ const pt = Me(({
|
|
|
7310
7288
|
}
|
|
7311
7289
|
}
|
|
7312
7290
|
else {
|
|
7313
|
-
const
|
|
7291
|
+
const G = [".fbx", ".glb", ".gltf"];
|
|
7314
7292
|
let ee = !1;
|
|
7315
|
-
for (const
|
|
7293
|
+
for (const se of G)
|
|
7316
7294
|
try {
|
|
7317
|
-
r.current.playAnimation(k +
|
|
7295
|
+
r.current.playAnimation(k + se, null, 10, 0, 0.01, E), console.log("Playing animation:", k + se), ee = !0;
|
|
7318
7296
|
break;
|
|
7319
7297
|
} catch {
|
|
7320
|
-
console.log(`Failed to play ${k}${
|
|
7298
|
+
console.log(`Failed to play ${k}${se}, trying next format...`);
|
|
7321
7299
|
}
|
|
7322
7300
|
if (!ee) {
|
|
7323
7301
|
console.warn("Animation system not available or animation not found:", k);
|
|
7324
7302
|
try {
|
|
7325
7303
|
r.current.setBodyMovement("idle"), console.log("Fallback to idle animation");
|
|
7326
|
-
} catch (
|
|
7327
|
-
console.warn("Fallback animation also failed:",
|
|
7304
|
+
} catch (se) {
|
|
7305
|
+
console.warn("Fallback animation also failed:", se);
|
|
7328
7306
|
}
|
|
7329
7307
|
}
|
|
7330
7308
|
}
|
|
@@ -7343,8 +7321,8 @@ const pt = Me(({
|
|
|
7343
7321
|
if (r.current && r.current.setShowFullAvatar && r.current.setBodyMovement)
|
|
7344
7322
|
try {
|
|
7345
7323
|
r.current.setShowFullAvatar(!0), r.current.setBodyMovement(k), console.log("Body movement set with full body mode:", k);
|
|
7346
|
-
} catch (
|
|
7347
|
-
console.warn("Error setting body movement:",
|
|
7324
|
+
} catch (E) {
|
|
7325
|
+
console.warn("Error setting body movement:", E);
|
|
7348
7326
|
}
|
|
7349
7327
|
},
|
|
7350
7328
|
setMovementIntensity: (k) => r.current?.setMovementIntensity(k),
|
|
@@ -7360,8 +7338,8 @@ const pt = Me(({
|
|
|
7360
7338
|
if (r.current && r.current.setShowFullAvatar && r.current.playReaction)
|
|
7361
7339
|
try {
|
|
7362
7340
|
r.current.setShowFullAvatar(!0), r.current.playReaction(k), console.log("Reaction played with full body mode:", k);
|
|
7363
|
-
} catch (
|
|
7364
|
-
console.warn("Error playing reaction:",
|
|
7341
|
+
} catch (E) {
|
|
7342
|
+
console.warn("Error playing reaction:", E);
|
|
7365
7343
|
}
|
|
7366
7344
|
},
|
|
7367
7345
|
playCelebration: () => {
|
|
@@ -7376,8 +7354,8 @@ const pt = Me(({
|
|
|
7376
7354
|
if (r.current && r.current.setShowFullAvatar)
|
|
7377
7355
|
try {
|
|
7378
7356
|
r.current.setShowFullAvatar(k), console.log("Show full avatar set to:", k);
|
|
7379
|
-
} catch (
|
|
7380
|
-
console.warn("Error setting showFullAvatar:",
|
|
7357
|
+
} catch (E) {
|
|
7358
|
+
console.warn("Error setting showFullAvatar:", E);
|
|
7381
7359
|
}
|
|
7382
7360
|
},
|
|
7383
7361
|
lockAvatarPosition: () => {
|
|
@@ -7397,7 +7375,7 @@ const pt = Me(({
|
|
|
7397
7375
|
}
|
|
7398
7376
|
}
|
|
7399
7377
|
})), /* @__PURE__ */ Pe("div", { className: `talking-head-container ${i}`, style: s, children: [
|
|
7400
|
-
/* @__PURE__ */
|
|
7378
|
+
/* @__PURE__ */ me(
|
|
7401
7379
|
"div",
|
|
7402
7380
|
{
|
|
7403
7381
|
ref: h,
|
|
@@ -7409,7 +7387,7 @@ const pt = Me(({
|
|
|
7409
7387
|
}
|
|
7410
7388
|
}
|
|
7411
7389
|
),
|
|
7412
|
-
u && /* @__PURE__ */
|
|
7390
|
+
u && /* @__PURE__ */ me("div", { className: "loading-overlay", style: {
|
|
7413
7391
|
position: "absolute",
|
|
7414
7392
|
top: "50%",
|
|
7415
7393
|
left: "50%",
|
|
@@ -7418,7 +7396,7 @@ const pt = Me(({
|
|
|
7418
7396
|
fontSize: "18px",
|
|
7419
7397
|
zIndex: 10
|
|
7420
7398
|
}, children: "Loading avatar..." }),
|
|
7421
|
-
d && /* @__PURE__ */
|
|
7399
|
+
d && /* @__PURE__ */ me("div", { className: "error-overlay", style: {
|
|
7422
7400
|
position: "absolute",
|
|
7423
7401
|
top: "50%",
|
|
7424
7402
|
left: "50%",
|
|
@@ -7456,13 +7434,13 @@ const gt = Me(({
|
|
|
7456
7434
|
},
|
|
7457
7435
|
className: x = "",
|
|
7458
7436
|
style: S = {},
|
|
7459
|
-
animations:
|
|
7437
|
+
animations: U = {},
|
|
7460
7438
|
autoSpeak: p = !1
|
|
7461
|
-
},
|
|
7462
|
-
const
|
|
7463
|
-
|
|
7464
|
-
Y.current =
|
|
7465
|
-
}, [
|
|
7439
|
+
}, F) => {
|
|
7440
|
+
const C = O(null), y = O(null), I = O(u), z = O(null), A = O(null), Y = O(!1), k = O({ remainingText: null, originalText: null, options: null }), E = O([]), [q, G] = ce(!0), [ee, se] = ce(null), [ae, pe] = ce(!1), [te, le] = ce(!1);
|
|
7441
|
+
de(() => {
|
|
7442
|
+
Y.current = te;
|
|
7443
|
+
}, [te]), de(() => {
|
|
7466
7444
|
I.current = u;
|
|
7467
7445
|
}, [u]);
|
|
7468
7446
|
const W = Ee(), v = s || W.service;
|
|
@@ -7488,7 +7466,7 @@ const gt = Me(({
|
|
|
7488
7466
|
...W,
|
|
7489
7467
|
apiKey: l !== null ? l : W.apiKey
|
|
7490
7468
|
};
|
|
7491
|
-
const
|
|
7469
|
+
const H = {
|
|
7492
7470
|
url: t,
|
|
7493
7471
|
body: e,
|
|
7494
7472
|
avatarMood: n,
|
|
@@ -7498,127 +7476,127 @@ const gt = Me(({
|
|
|
7498
7476
|
showFullAvatar: u,
|
|
7499
7477
|
bodyMovement: h,
|
|
7500
7478
|
movementIntensity: r
|
|
7501
|
-
},
|
|
7479
|
+
}, P = {
|
|
7502
7480
|
ttsEndpoint: R.endpoint,
|
|
7503
7481
|
ttsApikey: R.apiKey,
|
|
7504
7482
|
ttsService: v,
|
|
7505
7483
|
lipsyncModules: ["en"],
|
|
7506
7484
|
cameraView: a
|
|
7507
|
-
},
|
|
7508
|
-
if (!(!
|
|
7485
|
+
}, V = B(async () => {
|
|
7486
|
+
if (!(!C.current || y.current))
|
|
7509
7487
|
try {
|
|
7510
|
-
|
|
7511
|
-
url:
|
|
7512
|
-
body:
|
|
7513
|
-
avatarMood:
|
|
7514
|
-
}), await y.current.showAvatar(
|
|
7515
|
-
if (
|
|
7516
|
-
const L = Math.min(100, Math.round(
|
|
7488
|
+
G(!0), se(null), y.current = new Be(C.current, P), console.log("Avatar config being passed:", {
|
|
7489
|
+
url: H.url,
|
|
7490
|
+
body: H.body,
|
|
7491
|
+
avatarMood: H.avatarMood
|
|
7492
|
+
}), await y.current.showAvatar(H, (ne) => {
|
|
7493
|
+
if (ne.lengthComputable) {
|
|
7494
|
+
const L = Math.min(100, Math.round(ne.loaded / ne.total * 100));
|
|
7517
7495
|
c(L);
|
|
7518
7496
|
}
|
|
7519
|
-
}), y.current?.avatar && console.log("Avatar body after initialization:", y.current.avatar.body),
|
|
7520
|
-
const
|
|
7497
|
+
}), y.current?.avatar && console.log("Avatar body after initialization:", y.current.avatar.body), G(!1), pe(!0), d(y.current);
|
|
7498
|
+
const M = () => {
|
|
7521
7499
|
document.visibilityState === "visible" ? y.current?.start() : y.current?.stop();
|
|
7522
7500
|
};
|
|
7523
|
-
return document.addEventListener("visibilitychange",
|
|
7524
|
-
document.removeEventListener("visibilitychange",
|
|
7501
|
+
return document.addEventListener("visibilitychange", M), () => {
|
|
7502
|
+
document.removeEventListener("visibilitychange", M);
|
|
7525
7503
|
};
|
|
7526
|
-
} catch (
|
|
7527
|
-
console.error("Error initializing TalkingHead:",
|
|
7504
|
+
} catch (M) {
|
|
7505
|
+
console.error("Error initializing TalkingHead:", M), se(M.message || "Failed to initialize avatar"), G(!1), g(M);
|
|
7528
7506
|
}
|
|
7529
7507
|
}, []);
|
|
7530
|
-
|
|
7508
|
+
de(() => (V(), () => {
|
|
7531
7509
|
y.current && (y.current.stop(), y.current.dispose(), y.current = null);
|
|
7532
|
-
}), [
|
|
7533
|
-
const
|
|
7510
|
+
}), [V]);
|
|
7511
|
+
const J = B(async () => {
|
|
7534
7512
|
if (y.current)
|
|
7535
7513
|
try {
|
|
7536
|
-
const
|
|
7537
|
-
|
|
7538
|
-
} catch (
|
|
7539
|
-
console.warn("Failed to resume audio context:",
|
|
7514
|
+
const M = y.current.audioCtx || y.current.audioContext;
|
|
7515
|
+
M && (M.state === "suspended" || M.state === "interrupted") && (await M.resume(), console.log("Audio context resumed"));
|
|
7516
|
+
} catch (M) {
|
|
7517
|
+
console.warn("Failed to resume audio context:", M);
|
|
7540
7518
|
}
|
|
7541
|
-
}, []),
|
|
7542
|
-
if (!y.current || !
|
|
7519
|
+
}, []), Q = B(async (M, ne = {}) => {
|
|
7520
|
+
if (!y.current || !ae) {
|
|
7543
7521
|
console.warn("Avatar not ready for speaking");
|
|
7544
7522
|
return;
|
|
7545
7523
|
}
|
|
7546
|
-
if (!
|
|
7524
|
+
if (!M || M.trim() === "") {
|
|
7547
7525
|
console.warn("No text provided to speak");
|
|
7548
7526
|
return;
|
|
7549
7527
|
}
|
|
7550
|
-
await
|
|
7551
|
-
const L =
|
|
7552
|
-
|
|
7553
|
-
const
|
|
7554
|
-
lipsyncLang:
|
|
7528
|
+
await J(), k.current = { remainingText: null, originalText: null, options: null }, E.current = [], z.current = { text: M, options: ne }, A.current && (clearInterval(A.current), A.current = null), le(!1), Y.current = !1;
|
|
7529
|
+
const L = M.split(/[.!?]+/).filter((D) => D.trim().length > 0);
|
|
7530
|
+
E.current = L;
|
|
7531
|
+
const N = {
|
|
7532
|
+
lipsyncLang: ne.lipsyncLang || "en",
|
|
7555
7533
|
onSpeechEnd: () => {
|
|
7556
|
-
A.current && (clearInterval(A.current), A.current = null),
|
|
7534
|
+
A.current && (clearInterval(A.current), A.current = null), ne.onSpeechEnd && ne.onSpeechEnd(), b();
|
|
7557
7535
|
}
|
|
7558
7536
|
};
|
|
7559
7537
|
try {
|
|
7560
|
-
y.current.speakText(
|
|
7561
|
-
} catch (
|
|
7562
|
-
console.error("Error speaking text:",
|
|
7538
|
+
y.current.speakText(M, N);
|
|
7539
|
+
} catch (D) {
|
|
7540
|
+
console.error("Error speaking text:", D), se(D.message || "Failed to speak text");
|
|
7563
7541
|
}
|
|
7564
|
-
}, [
|
|
7565
|
-
|
|
7566
|
-
|
|
7567
|
-
}, [
|
|
7568
|
-
const
|
|
7542
|
+
}, [ae, b, J]);
|
|
7543
|
+
de(() => {
|
|
7544
|
+
ae && X && p && y.current && Q(X);
|
|
7545
|
+
}, [ae, X, p, Q]);
|
|
7546
|
+
const K = B(() => {
|
|
7569
7547
|
if (y.current)
|
|
7570
7548
|
try {
|
|
7571
|
-
const
|
|
7572
|
-
if (
|
|
7549
|
+
const M = y.current.isSpeaking || !1, ne = y.current.audioPlaylist || [], L = y.current.speechQueue || [];
|
|
7550
|
+
if (M || ne.length > 0 || L.length > 0) {
|
|
7573
7551
|
A.current && (clearInterval(A.current), A.current = null);
|
|
7574
|
-
let
|
|
7575
|
-
L.length > 0 && (
|
|
7576
|
-
remainingText:
|
|
7552
|
+
let N = "";
|
|
7553
|
+
L.length > 0 && (N = L.map((D) => D.text && Array.isArray(D.text) ? D.text.map(($) => $.word).join(" ") : D.text || "").join(" ")), k.current = {
|
|
7554
|
+
remainingText: N || null,
|
|
7577
7555
|
originalText: z.current?.text || null,
|
|
7578
7556
|
options: z.current?.options || null
|
|
7579
|
-
}, y.current.speechQueue.length = 0, y.current.pauseSpeaking(),
|
|
7557
|
+
}, y.current.speechQueue.length = 0, y.current.pauseSpeaking(), le(!0), Y.current = !0;
|
|
7580
7558
|
}
|
|
7581
|
-
} catch (
|
|
7582
|
-
console.warn("Error pausing speech:",
|
|
7559
|
+
} catch (M) {
|
|
7560
|
+
console.warn("Error pausing speech:", M);
|
|
7583
7561
|
}
|
|
7584
|
-
}, []), Ae =
|
|
7585
|
-
if (!(!y.current || !
|
|
7562
|
+
}, []), Ae = B(async () => {
|
|
7563
|
+
if (!(!y.current || !te))
|
|
7586
7564
|
try {
|
|
7587
|
-
await
|
|
7588
|
-
const
|
|
7589
|
-
|
|
7590
|
-
} catch (
|
|
7591
|
-
console.warn("Error resuming speech:",
|
|
7565
|
+
await J(), le(!1), Y.current = !1;
|
|
7566
|
+
const M = k.current?.remainingText, ne = k.current?.originalText || z.current?.text, L = k.current?.options || z.current?.options || {}, N = M || ne;
|
|
7567
|
+
N && Q(N, L);
|
|
7568
|
+
} catch (M) {
|
|
7569
|
+
console.warn("Error resuming speech:", M), le(!1), Y.current = !1;
|
|
7592
7570
|
}
|
|
7593
|
-
}, [
|
|
7594
|
-
y.current && (y.current.stopSpeaking(), A.current && (clearInterval(A.current), A.current = null),
|
|
7571
|
+
}, [te, Q, J]), we = B(() => {
|
|
7572
|
+
y.current && (y.current.stopSpeaking(), A.current && (clearInterval(A.current), A.current = null), le(!1), Y.current = !1);
|
|
7595
7573
|
}, []);
|
|
7596
|
-
return Fe(
|
|
7597
|
-
speakText:
|
|
7598
|
-
pauseSpeaking:
|
|
7574
|
+
return Fe(F, () => ({
|
|
7575
|
+
speakText: Q,
|
|
7576
|
+
pauseSpeaking: K,
|
|
7599
7577
|
resumeSpeaking: Ae,
|
|
7600
7578
|
stopSpeaking: we,
|
|
7601
|
-
resumeAudioContext:
|
|
7602
|
-
isPaused: () =>
|
|
7603
|
-
setMood: (
|
|
7604
|
-
setBodyMovement: (
|
|
7605
|
-
y.current && y.current.setBodyMovement(
|
|
7579
|
+
resumeAudioContext: J,
|
|
7580
|
+
isPaused: () => te,
|
|
7581
|
+
setMood: (M) => y.current?.setMood(M),
|
|
7582
|
+
setBodyMovement: (M) => {
|
|
7583
|
+
y.current && y.current.setBodyMovement(M);
|
|
7606
7584
|
},
|
|
7607
|
-
playAnimation: (
|
|
7608
|
-
y.current && y.current.playAnimation && y.current.playAnimation(
|
|
7585
|
+
playAnimation: (M, ne = !1) => {
|
|
7586
|
+
y.current && y.current.playAnimation && y.current.playAnimation(M, null, 10, 0, 0.01, ne);
|
|
7609
7587
|
},
|
|
7610
|
-
playReaction: (
|
|
7588
|
+
playReaction: (M) => y.current?.playReaction(M),
|
|
7611
7589
|
playCelebration: () => y.current?.playCelebration(),
|
|
7612
|
-
setShowFullAvatar: (
|
|
7613
|
-
y.current && (I.current =
|
|
7590
|
+
setShowFullAvatar: (M) => {
|
|
7591
|
+
y.current && (I.current = M, y.current.setShowFullAvatar(M));
|
|
7614
7592
|
},
|
|
7615
|
-
isReady:
|
|
7593
|
+
isReady: ae,
|
|
7616
7594
|
talkingHead: y.current
|
|
7617
7595
|
})), /* @__PURE__ */ Pe("div", { className: `simple-talking-avatar-container ${x}`, style: S, children: [
|
|
7618
|
-
/* @__PURE__ */
|
|
7596
|
+
/* @__PURE__ */ me(
|
|
7619
7597
|
"div",
|
|
7620
7598
|
{
|
|
7621
|
-
ref:
|
|
7599
|
+
ref: C,
|
|
7622
7600
|
className: "talking-head-viewer",
|
|
7623
7601
|
style: {
|
|
7624
7602
|
width: "100%",
|
|
@@ -7627,7 +7605,7 @@ const gt = Me(({
|
|
|
7627
7605
|
}
|
|
7628
7606
|
}
|
|
7629
7607
|
),
|
|
7630
|
-
|
|
7608
|
+
q && /* @__PURE__ */ me("div", { className: "loading-overlay", style: {
|
|
7631
7609
|
position: "absolute",
|
|
7632
7610
|
top: "50%",
|
|
7633
7611
|
left: "50%",
|
|
@@ -7636,7 +7614,7 @@ const gt = Me(({
|
|
|
7636
7614
|
fontSize: "18px",
|
|
7637
7615
|
zIndex: 10
|
|
7638
7616
|
}, children: "Loading avatar..." }),
|
|
7639
|
-
ee && /* @__PURE__ */
|
|
7617
|
+
ee && /* @__PURE__ */ me("div", { className: "error-overlay", style: {
|
|
7640
7618
|
position: "absolute",
|
|
7641
7619
|
top: "50%",
|
|
7642
7620
|
left: "50%",
|
|
@@ -7667,7 +7645,7 @@ const yt = Me(({
|
|
|
7667
7645
|
},
|
|
7668
7646
|
autoStart: h = !1
|
|
7669
7647
|
}, r) => {
|
|
7670
|
-
const u =
|
|
7648
|
+
const u = O(null), a = O({
|
|
7671
7649
|
currentModuleIndex: 0,
|
|
7672
7650
|
currentLessonIndex: 0,
|
|
7673
7651
|
currentQuestionIndex: 0,
|
|
@@ -7677,18 +7655,18 @@ const yt = Me(({
|
|
|
7677
7655
|
curriculumCompleted: !1,
|
|
7678
7656
|
score: 0,
|
|
7679
7657
|
totalQuestions: 0
|
|
7680
|
-
}), d =
|
|
7658
|
+
}), d = O({
|
|
7681
7659
|
onLessonStart: n,
|
|
7682
7660
|
onLessonComplete: i,
|
|
7683
7661
|
onQuestionAnswer: s,
|
|
7684
7662
|
onCurriculumComplete: o,
|
|
7685
7663
|
onCustomAction: l
|
|
7686
|
-
}), c =
|
|
7664
|
+
}), c = O(null), g = O(null), b = O(null), x = O(null), S = O(null), U = O(null), p = O(null), F = O(X?.curriculum || {
|
|
7687
7665
|
title: "Default Curriculum",
|
|
7688
7666
|
description: "No curriculum data provided",
|
|
7689
7667
|
language: "en",
|
|
7690
7668
|
modules: []
|
|
7691
|
-
}),
|
|
7669
|
+
}), C = O({
|
|
7692
7670
|
avatarUrl: t.avatarUrl || "/avatars/brunette.glb",
|
|
7693
7671
|
avatarBody: t.avatarBody || "F",
|
|
7694
7672
|
mood: t.mood || "happy",
|
|
@@ -7702,7 +7680,7 @@ const yt = Me(({
|
|
|
7702
7680
|
animations: e,
|
|
7703
7681
|
lipsyncLang: "en"
|
|
7704
7682
|
});
|
|
7705
|
-
|
|
7683
|
+
de(() => {
|
|
7706
7684
|
d.current = {
|
|
7707
7685
|
onLessonStart: n,
|
|
7708
7686
|
onLessonComplete: i,
|
|
@@ -7710,13 +7688,13 @@ const yt = Me(({
|
|
|
7710
7688
|
onCurriculumComplete: o,
|
|
7711
7689
|
onCustomAction: l
|
|
7712
7690
|
};
|
|
7713
|
-
}, [n, i, s, o, l]),
|
|
7714
|
-
|
|
7691
|
+
}, [n, i, s, o, l]), de(() => {
|
|
7692
|
+
F.current = X?.curriculum || {
|
|
7715
7693
|
title: "Default Curriculum",
|
|
7716
7694
|
description: "No curriculum data provided",
|
|
7717
7695
|
language: "en",
|
|
7718
7696
|
modules: []
|
|
7719
|
-
},
|
|
7697
|
+
}, C.current = {
|
|
7720
7698
|
avatarUrl: t.avatarUrl || "/avatars/brunette.glb",
|
|
7721
7699
|
avatarBody: t.avatarBody || "F",
|
|
7722
7700
|
mood: t.mood || "happy",
|
|
@@ -7731,7 +7709,7 @@ const yt = Me(({
|
|
|
7731
7709
|
lipsyncLang: "en"
|
|
7732
7710
|
};
|
|
7733
7711
|
}, [X, t, e]);
|
|
7734
|
-
const y =
|
|
7712
|
+
const y = B(() => (F.current || { modules: [] }).modules[a.current.currentModuleIndex]?.lessons[a.current.currentLessonIndex], []), I = B(() => y()?.questions[a.current.currentQuestionIndex], [y]), z = B((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 = B(() => {
|
|
7735
7713
|
a.current.lessonCompleted = !0, a.current.isQuestionMode = !1;
|
|
7736
7714
|
const v = a.current.totalQuestions > 0 ? Math.round(a.current.score / a.current.totalQuestions * 100) : 100;
|
|
7737
7715
|
let R = "Congratulations! You've completed this lesson";
|
|
@@ -7755,9 +7733,9 @@ const yt = Me(({
|
|
|
7755
7733
|
} catch {
|
|
7756
7734
|
u.current.playCelebration();
|
|
7757
7735
|
}
|
|
7758
|
-
const
|
|
7736
|
+
const H = F.current || { modules: [] }, P = H.modules[a.current.currentModuleIndex], V = a.current.currentLessonIndex < (P?.lessons?.length || 0) - 1, J = a.current.currentModuleIndex < (H.modules?.length || 0) - 1, Q = V || J, K = C.current || { lipsyncLang: "en" };
|
|
7759
7737
|
u.current.speakText(R, {
|
|
7760
|
-
lipsyncLang:
|
|
7738
|
+
lipsyncLang: K.lipsyncLang,
|
|
7761
7739
|
onSpeechEnd: () => {
|
|
7762
7740
|
d.current.onCustomAction({
|
|
7763
7741
|
type: "lessonCompleteFeedbackDone",
|
|
@@ -7766,17 +7744,17 @@ const yt = Me(({
|
|
|
7766
7744
|
score: a.current.score,
|
|
7767
7745
|
totalQuestions: a.current.totalQuestions,
|
|
7768
7746
|
percentage: v,
|
|
7769
|
-
hasNextLesson:
|
|
7747
|
+
hasNextLesson: Q
|
|
7770
7748
|
});
|
|
7771
7749
|
}
|
|
7772
7750
|
});
|
|
7773
7751
|
}
|
|
7774
|
-
}, [e.lessonComplete]), Y =
|
|
7752
|
+
}, [e.lessonComplete]), Y = B(() => {
|
|
7775
7753
|
a.current.curriculumCompleted = !0;
|
|
7776
|
-
const v =
|
|
7754
|
+
const v = F.current || { modules: [] };
|
|
7777
7755
|
if (d.current.onCurriculumComplete({
|
|
7778
7756
|
modules: v.modules.length,
|
|
7779
|
-
totalLessons: v.modules.reduce((R,
|
|
7757
|
+
totalLessons: v.modules.reduce((R, H) => R + H.lessons.length, 0)
|
|
7780
7758
|
}), u.current) {
|
|
7781
7759
|
if (u.current.setMood("celebrating"), e.curriculumComplete)
|
|
7782
7760
|
try {
|
|
@@ -7784,10 +7762,10 @@ const yt = Me(({
|
|
|
7784
7762
|
} catch {
|
|
7785
7763
|
u.current.playCelebration();
|
|
7786
7764
|
}
|
|
7787
|
-
const R =
|
|
7765
|
+
const R = C.current || { lipsyncLang: "en" };
|
|
7788
7766
|
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
7767
|
}
|
|
7790
|
-
}, [e.curriculumComplete]), k =
|
|
7768
|
+
}, [e.curriculumComplete]), k = B(() => {
|
|
7791
7769
|
const v = y();
|
|
7792
7770
|
a.current.isQuestionMode = !0, a.current.currentQuestionIndex = 0, a.current.totalQuestions = v?.questions?.length || 0, a.current.score = 0;
|
|
7793
7771
|
const R = I();
|
|
@@ -7800,31 +7778,31 @@ const yt = Me(({
|
|
|
7800
7778
|
question: R,
|
|
7801
7779
|
score: a.current.score
|
|
7802
7780
|
});
|
|
7803
|
-
const
|
|
7781
|
+
const H = () => {
|
|
7804
7782
|
if (!u.current || !R) return;
|
|
7805
7783
|
if (u.current.setMood("happy"), e.questionStart)
|
|
7806
7784
|
try {
|
|
7807
7785
|
u.current.playAnimation(e.questionStart, !0);
|
|
7808
|
-
} catch (
|
|
7809
|
-
console.warn("Failed to play questionStart animation:",
|
|
7786
|
+
} catch (V) {
|
|
7787
|
+
console.warn("Failed to play questionStart animation:", V);
|
|
7810
7788
|
}
|
|
7811
|
-
const
|
|
7812
|
-
R.type === "code_test" ? u.current.speakText(`Let's test your coding skills! Here's your first challenge: ${R.question}`, { lipsyncLang:
|
|
7789
|
+
const P = C.current || { lipsyncLang: "en" };
|
|
7790
|
+
R.type === "code_test" ? u.current.speakText(`Let's test your coding skills! Here's your first challenge: ${R.question}`, { lipsyncLang: P.lipsyncLang }) : R.type === "multiple_choice" ? u.current.speakText(`Now let me ask you some questions. Here's the first one: ${R.question}`, { lipsyncLang: P.lipsyncLang }) : R.type === "true_false" ? u.current.speakText(`Let's start with some true or false questions. First question: ${R.question}`, { lipsyncLang: P.lipsyncLang }) : u.current.speakText(`Now let me ask you some questions. Here's the first one: ${R.question}`, { lipsyncLang: P.lipsyncLang });
|
|
7813
7791
|
};
|
|
7814
7792
|
if (u.current && u.current.isReady && R)
|
|
7815
|
-
|
|
7793
|
+
H();
|
|
7816
7794
|
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:
|
|
7795
|
+
const P = C.current || { lipsyncLang: "en" };
|
|
7796
|
+
u.current.speakText("Now let me ask you some questions to test your understanding.", { lipsyncLang: P.lipsyncLang });
|
|
7819
7797
|
} else {
|
|
7820
|
-
const
|
|
7821
|
-
u.current && u.current.isReady && (clearInterval(
|
|
7798
|
+
const P = setInterval(() => {
|
|
7799
|
+
u.current && u.current.isReady && (clearInterval(P), R && H());
|
|
7822
7800
|
}, 100);
|
|
7823
7801
|
setTimeout(() => {
|
|
7824
|
-
clearInterval(
|
|
7802
|
+
clearInterval(P);
|
|
7825
7803
|
}, 5e3);
|
|
7826
7804
|
}
|
|
7827
|
-
}, [e.questionStart, y, I]),
|
|
7805
|
+
}, [e.questionStart, y, I]), E = B(() => {
|
|
7828
7806
|
const v = y();
|
|
7829
7807
|
if (a.current.currentQuestionIndex < (v?.questions?.length || 0) - 1) {
|
|
7830
7808
|
u.current && u.current.stopSpeaking && u.current.stopSpeaking(), a.current.currentQuestionIndex += 1;
|
|
@@ -7838,45 +7816,45 @@ const yt = Me(({
|
|
|
7838
7816
|
question: R,
|
|
7839
7817
|
score: a.current.score
|
|
7840
7818
|
});
|
|
7841
|
-
const
|
|
7819
|
+
const H = () => {
|
|
7842
7820
|
if (!u.current || !R) return;
|
|
7843
7821
|
if (u.current.setMood("happy"), u.current.setBodyMovement("idle"), e.nextQuestion)
|
|
7844
7822
|
try {
|
|
7845
7823
|
u.current.playAnimation(e.nextQuestion, !0);
|
|
7846
|
-
} catch (
|
|
7847
|
-
console.warn("Failed to play nextQuestion animation:",
|
|
7824
|
+
} catch (K) {
|
|
7825
|
+
console.warn("Failed to play nextQuestion animation:", K);
|
|
7848
7826
|
}
|
|
7849
|
-
const
|
|
7827
|
+
const P = C.current || { lipsyncLang: "en" }, J = y()?.questions?.length || 0, Q = a.current.currentQuestionIndex >= J - 1;
|
|
7850
7828
|
if (R.type === "code_test") {
|
|
7851
|
-
const
|
|
7852
|
-
u.current.speakText(
|
|
7853
|
-
lipsyncLang:
|
|
7829
|
+
const K = Q ? `Great! Here's your final coding challenge: ${R.question}` : `Great! Now let's move on to your next coding challenge: ${R.question}`;
|
|
7830
|
+
u.current.speakText(K, {
|
|
7831
|
+
lipsyncLang: P.lipsyncLang
|
|
7854
7832
|
});
|
|
7855
7833
|
} else if (R.type === "multiple_choice") {
|
|
7856
|
-
const
|
|
7857
|
-
u.current.speakText(
|
|
7858
|
-
lipsyncLang:
|
|
7834
|
+
const K = Q ? `Alright! Here's your final question: ${R.question}` : `Alright! Here's your next question: ${R.question}`;
|
|
7835
|
+
u.current.speakText(K, {
|
|
7836
|
+
lipsyncLang: P.lipsyncLang
|
|
7859
7837
|
});
|
|
7860
7838
|
} else if (R.type === "true_false") {
|
|
7861
|
-
const
|
|
7862
|
-
u.current.speakText(
|
|
7863
|
-
lipsyncLang:
|
|
7839
|
+
const K = Q ? `Now let's try this final one: ${R.question}` : `Now let's try this one: ${R.question}`;
|
|
7840
|
+
u.current.speakText(K, {
|
|
7841
|
+
lipsyncLang: P.lipsyncLang
|
|
7864
7842
|
});
|
|
7865
7843
|
} else {
|
|
7866
|
-
const
|
|
7867
|
-
u.current.speakText(
|
|
7868
|
-
lipsyncLang:
|
|
7844
|
+
const K = Q ? `Here's your final question: ${R.question}` : `Here's the next question: ${R.question}`;
|
|
7845
|
+
u.current.speakText(K, {
|
|
7846
|
+
lipsyncLang: P.lipsyncLang
|
|
7869
7847
|
});
|
|
7870
7848
|
}
|
|
7871
7849
|
};
|
|
7872
7850
|
if (u.current && u.current.isReady && R)
|
|
7873
|
-
|
|
7851
|
+
H();
|
|
7874
7852
|
else if (R) {
|
|
7875
|
-
const
|
|
7876
|
-
u.current && u.current.isReady && (clearInterval(
|
|
7853
|
+
const P = setInterval(() => {
|
|
7854
|
+
u.current && u.current.isReady && (clearInterval(P), H());
|
|
7877
7855
|
}, 100);
|
|
7878
7856
|
setTimeout(() => {
|
|
7879
|
-
clearInterval(
|
|
7857
|
+
clearInterval(P);
|
|
7880
7858
|
}, 5e3);
|
|
7881
7859
|
}
|
|
7882
7860
|
} else
|
|
@@ -7887,16 +7865,16 @@ const yt = Me(({
|
|
|
7887
7865
|
totalQuestions: a.current.totalQuestions,
|
|
7888
7866
|
score: a.current.score
|
|
7889
7867
|
});
|
|
7890
|
-
}, [e.nextQuestion, y, I]),
|
|
7891
|
-
const v =
|
|
7868
|
+
}, [e.nextQuestion, y, I]), q = B(() => {
|
|
7869
|
+
const v = F.current || { modules: [] }, R = v.modules[a.current.currentModuleIndex];
|
|
7892
7870
|
if (a.current.currentLessonIndex < (R?.lessons?.length || 0) - 1) {
|
|
7893
7871
|
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
|
|
7872
|
+
const P = v.modules[a.current.currentModuleIndex], V = a.current.currentLessonIndex < (P?.lessons?.length || 0) - 1, J = a.current.currentModuleIndex < (v.modules?.length || 0) - 1, Q = V || J;
|
|
7895
7873
|
d.current.onCustomAction({
|
|
7896
7874
|
type: "lessonStart",
|
|
7897
7875
|
moduleIndex: a.current.currentModuleIndex,
|
|
7898
7876
|
lessonIndex: a.current.currentLessonIndex,
|
|
7899
|
-
hasNextLesson:
|
|
7877
|
+
hasNextLesson: Q
|
|
7900
7878
|
}), d.current.onLessonStart({
|
|
7901
7879
|
moduleIndex: a.current.currentModuleIndex,
|
|
7902
7880
|
lessonIndex: a.current.currentLessonIndex,
|
|
@@ -7904,12 +7882,12 @@ const yt = Me(({
|
|
|
7904
7882
|
}), u.current && (u.current.setMood("happy"), u.current.setBodyMovement("idle"));
|
|
7905
7883
|
} else if (a.current.currentModuleIndex < (v.modules?.length || 0) - 1) {
|
|
7906
7884
|
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
|
|
7885
|
+
const V = v.modules[a.current.currentModuleIndex], J = a.current.currentLessonIndex < (V?.lessons?.length || 0) - 1, Q = a.current.currentModuleIndex < (v.modules?.length || 0) - 1, K = J || Q;
|
|
7908
7886
|
d.current.onCustomAction({
|
|
7909
7887
|
type: "lessonStart",
|
|
7910
7888
|
moduleIndex: a.current.currentModuleIndex,
|
|
7911
7889
|
lessonIndex: a.current.currentLessonIndex,
|
|
7912
|
-
hasNextLesson:
|
|
7890
|
+
hasNextLesson: K
|
|
7913
7891
|
}), d.current.onLessonStart({
|
|
7914
7892
|
moduleIndex: a.current.currentModuleIndex,
|
|
7915
7893
|
lessonIndex: a.current.currentLessonIndex,
|
|
@@ -7917,25 +7895,25 @@ const yt = Me(({
|
|
|
7917
7895
|
}), u.current && (u.current.setMood("happy"), u.current.setBodyMovement("idle"));
|
|
7918
7896
|
} else
|
|
7919
7897
|
S.current && S.current();
|
|
7920
|
-
}, []),
|
|
7898
|
+
}, []), G = B(() => {
|
|
7921
7899
|
const v = y();
|
|
7922
7900
|
let R = null;
|
|
7923
7901
|
if (v?.avatar_script && v?.body) {
|
|
7924
|
-
const
|
|
7925
|
-
R = `${
|
|
7902
|
+
const H = v.avatar_script.trim(), P = v.body.trim(), V = H.match(/[.!?]$/) ? " " : ". ";
|
|
7903
|
+
R = `${H}${V}${P}`;
|
|
7926
7904
|
} else
|
|
7927
7905
|
R = v?.avatar_script || v?.body || null;
|
|
7928
7906
|
if (u.current && u.current.isReady && R) {
|
|
7929
7907
|
a.current.isTeaching = !0, a.current.isQuestionMode = !1, a.current.score = 0, a.current.totalQuestions = 0, u.current.setMood("happy");
|
|
7930
|
-
let
|
|
7908
|
+
let H = !1;
|
|
7931
7909
|
if (e.teaching)
|
|
7932
7910
|
try {
|
|
7933
|
-
u.current.playAnimation(e.teaching, !0),
|
|
7934
|
-
} catch (
|
|
7935
|
-
console.warn("Failed to play teaching animation:",
|
|
7911
|
+
u.current.playAnimation(e.teaching, !0), H = !0;
|
|
7912
|
+
} catch (V) {
|
|
7913
|
+
console.warn("Failed to play teaching animation:", V);
|
|
7936
7914
|
}
|
|
7937
|
-
|
|
7938
|
-
const
|
|
7915
|
+
H || u.current.setBodyMovement("gesturing");
|
|
7916
|
+
const P = C.current || { lipsyncLang: "en" };
|
|
7939
7917
|
d.current.onLessonStart({
|
|
7940
7918
|
moduleIndex: a.current.currentModuleIndex,
|
|
7941
7919
|
lessonIndex: a.current.currentLessonIndex,
|
|
@@ -7946,7 +7924,7 @@ const yt = Me(({
|
|
|
7946
7924
|
lessonIndex: a.current.currentLessonIndex,
|
|
7947
7925
|
lesson: v
|
|
7948
7926
|
}), u.current.speakText(R, {
|
|
7949
|
-
lipsyncLang:
|
|
7927
|
+
lipsyncLang: P.lipsyncLang,
|
|
7950
7928
|
onSpeechEnd: () => {
|
|
7951
7929
|
a.current.isTeaching = !1, d.current.onCustomAction({
|
|
7952
7930
|
type: "teachingComplete",
|
|
@@ -7964,17 +7942,17 @@ const yt = Me(({
|
|
|
7964
7942
|
}
|
|
7965
7943
|
});
|
|
7966
7944
|
}
|
|
7967
|
-
}, [e.teaching, y]), ee =
|
|
7968
|
-
const R = I(),
|
|
7969
|
-
if (
|
|
7945
|
+
}, [e.teaching, y]), ee = B((v) => {
|
|
7946
|
+
const R = I(), H = z(v, R);
|
|
7947
|
+
if (H && (a.current.score += 1), d.current.onQuestionAnswer({
|
|
7970
7948
|
moduleIndex: a.current.currentModuleIndex,
|
|
7971
7949
|
lessonIndex: a.current.currentLessonIndex,
|
|
7972
7950
|
questionIndex: a.current.currentQuestionIndex,
|
|
7973
7951
|
answer: v,
|
|
7974
|
-
isCorrect:
|
|
7952
|
+
isCorrect: H,
|
|
7975
7953
|
question: R
|
|
7976
7954
|
}), u.current)
|
|
7977
|
-
if (
|
|
7955
|
+
if (H) {
|
|
7978
7956
|
if (u.current.setMood("happy"), e.correct)
|
|
7979
7957
|
try {
|
|
7980
7958
|
u.current.playReaction("happy");
|
|
@@ -7982,13 +7960,13 @@ const yt = Me(({
|
|
|
7982
7960
|
u.current.setBodyMovement("happy");
|
|
7983
7961
|
}
|
|
7984
7962
|
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:
|
|
7963
|
+
const V = y()?.questions?.length || 0;
|
|
7964
|
+
a.current.currentQuestionIndex >= V - 1;
|
|
7965
|
+
const J = a.current.currentQuestionIndex < V - 1;
|
|
7966
|
+
console.log("[CurriculumLearning] Answer feedback - questionIndex:", a.current.currentQuestionIndex, "totalQuestions:", V, "hasNextQuestion:", J);
|
|
7967
|
+
const Q = R.type === "code_test" ? `Great job! Your code passed all the tests! ${R.explanation || ""}` : `Excellent! That's correct! ${R.explanation || ""}`, K = C.current || { lipsyncLang: "en" };
|
|
7968
|
+
u.current.speakText(Q, {
|
|
7969
|
+
lipsyncLang: K.lipsyncLang,
|
|
7992
7970
|
onSpeechEnd: () => {
|
|
7993
7971
|
d.current.onCustomAction({
|
|
7994
7972
|
type: "answerFeedbackComplete",
|
|
@@ -7996,7 +7974,7 @@ const yt = Me(({
|
|
|
7996
7974
|
lessonIndex: a.current.currentLessonIndex,
|
|
7997
7975
|
questionIndex: a.current.currentQuestionIndex,
|
|
7998
7976
|
isCorrect: !0,
|
|
7999
|
-
hasNextQuestion:
|
|
7977
|
+
hasNextQuestion: J,
|
|
8000
7978
|
score: a.current.score,
|
|
8001
7979
|
totalQuestions: a.current.totalQuestions
|
|
8002
7980
|
});
|
|
@@ -8010,10 +7988,10 @@ const yt = Me(({
|
|
|
8010
7988
|
u.current.setBodyMovement("idle");
|
|
8011
7989
|
}
|
|
8012
7990
|
u.current.setBodyMovement("gesturing");
|
|
8013
|
-
const
|
|
8014
|
-
console.log("[CurriculumLearning] Answer feedback (incorrect) - questionIndex:", a.current.currentQuestionIndex, "totalQuestions:",
|
|
8015
|
-
const
|
|
8016
|
-
u.current.speakText(
|
|
7991
|
+
const V = y()?.questions?.length || 0, J = a.current.currentQuestionIndex >= V - 1, Q = a.current.currentQuestionIndex < V - 1;
|
|
7992
|
+
console.log("[CurriculumLearning] Answer feedback (incorrect) - questionIndex:", a.current.currentQuestionIndex, "totalQuestions:", V, "hasNextQuestion:", Q);
|
|
7993
|
+
const K = 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 || ""}${J ? "" : " Let's move on to the next question."}`, Ae = C.current || { lipsyncLang: "en" };
|
|
7994
|
+
u.current.speakText(K, {
|
|
8017
7995
|
lipsyncLang: Ae.lipsyncLang,
|
|
8018
7996
|
onSpeechEnd: () => {
|
|
8019
7997
|
d.current.onCustomAction({
|
|
@@ -8022,7 +8000,7 @@ const yt = Me(({
|
|
|
8022
8000
|
lessonIndex: a.current.currentLessonIndex,
|
|
8023
8001
|
questionIndex: a.current.currentQuestionIndex,
|
|
8024
8002
|
isCorrect: !1,
|
|
8025
|
-
hasNextQuestion:
|
|
8003
|
+
hasNextQuestion: Q,
|
|
8026
8004
|
score: a.current.score,
|
|
8027
8005
|
totalQuestions: a.current.totalQuestions
|
|
8028
8006
|
});
|
|
@@ -8030,20 +8008,20 @@ const yt = Me(({
|
|
|
8030
8008
|
});
|
|
8031
8009
|
}
|
|
8032
8010
|
else {
|
|
8033
|
-
const
|
|
8011
|
+
const V = y()?.questions?.length || 0;
|
|
8034
8012
|
d.current.onCustomAction({
|
|
8035
8013
|
type: "answerFeedbackComplete",
|
|
8036
8014
|
moduleIndex: a.current.currentModuleIndex,
|
|
8037
8015
|
lessonIndex: a.current.currentLessonIndex,
|
|
8038
8016
|
questionIndex: a.current.currentQuestionIndex,
|
|
8039
|
-
isCorrect:
|
|
8040
|
-
hasNextQuestion: a.current.currentQuestionIndex <
|
|
8017
|
+
isCorrect: H,
|
|
8018
|
+
hasNextQuestion: a.current.currentQuestionIndex < V - 1,
|
|
8041
8019
|
score: a.current.score,
|
|
8042
8020
|
totalQuestions: a.current.totalQuestions,
|
|
8043
8021
|
avatarNotReady: !0
|
|
8044
8022
|
});
|
|
8045
8023
|
}
|
|
8046
|
-
}, [e.correct, e.incorrect, I, y, z]),
|
|
8024
|
+
}, [e.correct, e.incorrect, I, y, z]), se = B((v) => {
|
|
8047
8025
|
const R = I();
|
|
8048
8026
|
if (!v || typeof v != "object") {
|
|
8049
8027
|
console.error("Invalid code test result format. Expected object with {passed: boolean, ...}");
|
|
@@ -8053,7 +8031,7 @@ const yt = Me(({
|
|
|
8053
8031
|
console.warn("Current question is not a code test. Use handleAnswerSelect for other question types.");
|
|
8054
8032
|
return;
|
|
8055
8033
|
}
|
|
8056
|
-
const
|
|
8034
|
+
const H = {
|
|
8057
8035
|
passed: v.passed === !0,
|
|
8058
8036
|
results: v.results || [],
|
|
8059
8037
|
output: v.output || "",
|
|
@@ -8068,10 +8046,10 @@ const yt = Me(({
|
|
|
8068
8046
|
moduleIndex: a.current.currentModuleIndex,
|
|
8069
8047
|
lessonIndex: a.current.currentLessonIndex,
|
|
8070
8048
|
questionIndex: a.current.currentQuestionIndex,
|
|
8071
|
-
testResult:
|
|
8049
|
+
testResult: H,
|
|
8072
8050
|
question: R
|
|
8073
|
-
}), p.current && p.current(
|
|
8074
|
-
}, [I, z]),
|
|
8051
|
+
}), p.current && p.current(H);
|
|
8052
|
+
}, [I, z]), ae = B(() => {
|
|
8075
8053
|
if (a.current.currentQuestionIndex > 0) {
|
|
8076
8054
|
a.current.currentQuestionIndex -= 1;
|
|
8077
8055
|
const v = I();
|
|
@@ -8087,26 +8065,26 @@ const yt = Me(({
|
|
|
8087
8065
|
const R = () => {
|
|
8088
8066
|
if (!u.current || !v) return;
|
|
8089
8067
|
u.current.setMood("happy"), u.current.setBodyMovement("idle");
|
|
8090
|
-
const
|
|
8068
|
+
const H = C.current || { lipsyncLang: "en" };
|
|
8091
8069
|
v.type === "code_test" ? u.current.speakText(`Let's go back to this coding challenge: ${v.question}`, {
|
|
8092
|
-
lipsyncLang:
|
|
8070
|
+
lipsyncLang: H.lipsyncLang
|
|
8093
8071
|
}) : u.current.speakText(`Going back to: ${v.question}`, {
|
|
8094
|
-
lipsyncLang:
|
|
8072
|
+
lipsyncLang: H.lipsyncLang
|
|
8095
8073
|
});
|
|
8096
8074
|
};
|
|
8097
8075
|
if (u.current && u.current.isReady && v)
|
|
8098
8076
|
R();
|
|
8099
8077
|
else if (v) {
|
|
8100
|
-
const
|
|
8101
|
-
u.current && u.current.isReady && (clearInterval(
|
|
8078
|
+
const H = setInterval(() => {
|
|
8079
|
+
u.current && u.current.isReady && (clearInterval(H), R());
|
|
8102
8080
|
}, 100);
|
|
8103
8081
|
setTimeout(() => {
|
|
8104
|
-
clearInterval(
|
|
8082
|
+
clearInterval(H);
|
|
8105
8083
|
}, 5e3);
|
|
8106
8084
|
}
|
|
8107
8085
|
}
|
|
8108
|
-
}, [I]),
|
|
8109
|
-
const v =
|
|
8086
|
+
}, [I]), pe = B(() => {
|
|
8087
|
+
const v = F.current || { modules: [] };
|
|
8110
8088
|
if (v.modules[a.current.currentModuleIndex], a.current.currentLessonIndex > 0)
|
|
8111
8089
|
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
8090
|
type: "lessonStart",
|
|
@@ -8118,8 +8096,8 @@ const yt = Me(({
|
|
|
8118
8096
|
lesson: y()
|
|
8119
8097
|
}), u.current && (u.current.setMood("happy"), u.current.setBodyMovement("idle"));
|
|
8120
8098
|
else if (a.current.currentModuleIndex > 0) {
|
|
8121
|
-
const
|
|
8122
|
-
a.current.currentModuleIndex -= 1, a.current.currentLessonIndex = (
|
|
8099
|
+
const P = v.modules[a.current.currentModuleIndex - 1];
|
|
8100
|
+
a.current.currentModuleIndex -= 1, a.current.currentLessonIndex = (P?.lessons?.length || 1) - 1, a.current.currentQuestionIndex = 0, a.current.lessonCompleted = !1, a.current.isQuestionMode = !1, a.current.isTeaching = !1, a.current.score = 0, a.current.totalQuestions = 0, d.current.onCustomAction({
|
|
8123
8101
|
type: "lessonStart",
|
|
8124
8102
|
moduleIndex: a.current.currentModuleIndex,
|
|
8125
8103
|
lessonIndex: a.current.currentLessonIndex
|
|
@@ -8129,30 +8107,30 @@ const yt = Me(({
|
|
|
8129
8107
|
lesson: y()
|
|
8130
8108
|
}), u.current && (u.current.setMood("happy"), u.current.setBodyMovement("idle"));
|
|
8131
8109
|
}
|
|
8132
|
-
}, [y]),
|
|
8110
|
+
}, [y]), te = B(() => {
|
|
8133
8111
|
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
|
-
}, []),
|
|
8112
|
+
}, []), le = B((v) => {
|
|
8135
8113
|
console.log("Avatar is ready!", v);
|
|
8136
|
-
const R = y(),
|
|
8137
|
-
h &&
|
|
8114
|
+
const R = y(), H = R?.avatar_script || R?.body;
|
|
8115
|
+
h && H && setTimeout(() => {
|
|
8138
8116
|
c.current && c.current();
|
|
8139
8117
|
}, 10);
|
|
8140
8118
|
}, [h, y]);
|
|
8141
8119
|
Xe(() => {
|
|
8142
|
-
c.current =
|
|
8120
|
+
c.current = G, g.current = q, b.current = A, x.current = E, S.current = Y, U.current = k, p.current = ee;
|
|
8143
8121
|
}), Fe(r, () => ({
|
|
8144
8122
|
// Curriculum control methods
|
|
8145
|
-
startTeaching:
|
|
8123
|
+
startTeaching: G,
|
|
8146
8124
|
startQuestions: k,
|
|
8147
8125
|
handleAnswerSelect: ee,
|
|
8148
|
-
handleCodeTestResult:
|
|
8149
|
-
nextQuestion:
|
|
8150
|
-
previousQuestion:
|
|
8151
|
-
nextLesson:
|
|
8152
|
-
previousLesson:
|
|
8126
|
+
handleCodeTestResult: se,
|
|
8127
|
+
nextQuestion: E,
|
|
8128
|
+
previousQuestion: ae,
|
|
8129
|
+
nextLesson: q,
|
|
8130
|
+
previousLesson: pe,
|
|
8153
8131
|
completeLesson: A,
|
|
8154
8132
|
completeCurriculum: Y,
|
|
8155
|
-
resetCurriculum:
|
|
8133
|
+
resetCurriculum: te,
|
|
8156
8134
|
getState: () => ({ ...a.current }),
|
|
8157
8135
|
getCurrentQuestion: () => I(),
|
|
8158
8136
|
getCurrentLesson: () => y(),
|
|
@@ -8161,8 +8139,8 @@ const yt = Me(({
|
|
|
8161
8139
|
// Convenience methods that delegate to avatar (always check current ref)
|
|
8162
8140
|
speakText: async (v, R = {}) => {
|
|
8163
8141
|
await u.current?.resumeAudioContext?.();
|
|
8164
|
-
const
|
|
8165
|
-
u.current?.speakText(v, { ...R, lipsyncLang: R.lipsyncLang ||
|
|
8142
|
+
const H = C.current || { lipsyncLang: "en" };
|
|
8143
|
+
u.current?.speakText(v, { ...R, lipsyncLang: R.lipsyncLang || H.lipsyncLang });
|
|
8166
8144
|
},
|
|
8167
8145
|
resumeAudioContext: async () => {
|
|
8168
8146
|
if (u.current?.resumeAudioContext)
|
|
@@ -8173,8 +8151,8 @@ const yt = Me(({
|
|
|
8173
8151
|
if (R.state === "suspended" || R.state === "interrupted")
|
|
8174
8152
|
try {
|
|
8175
8153
|
await R.resume(), console.log("Audio context resumed via talkingHead");
|
|
8176
|
-
} catch (
|
|
8177
|
-
console.warn("Failed to resume audio context:",
|
|
8154
|
+
} catch (H) {
|
|
8155
|
+
console.warn("Failed to resume audio context:", H);
|
|
8178
8156
|
}
|
|
8179
8157
|
} else
|
|
8180
8158
|
console.warn("Audio context not available yet");
|
|
@@ -8206,8 +8184,8 @@ const yt = Me(({
|
|
|
8206
8184
|
handleResize: () => u.current?.handleResize(),
|
|
8207
8185
|
// Avatar readiness check (always returns current value)
|
|
8208
8186
|
isAvatarReady: () => u.current?.isReady || !1
|
|
8209
|
-
}), [
|
|
8210
|
-
const W =
|
|
8187
|
+
}), [G, k, ee, se, E, q, A, Y, te, I, y]);
|
|
8188
|
+
const W = C.current || {
|
|
8211
8189
|
avatarUrl: "/avatars/brunette.glb",
|
|
8212
8190
|
avatarBody: "F",
|
|
8213
8191
|
mood: "happy",
|
|
@@ -8220,7 +8198,7 @@ const yt = Me(({
|
|
|
8220
8198
|
showFullAvatar: !1,
|
|
8221
8199
|
animations: e
|
|
8222
8200
|
};
|
|
8223
|
-
return /* @__PURE__ */
|
|
8201
|
+
return /* @__PURE__ */ me("div", { style: { width: "100%", height: "100%" }, children: /* @__PURE__ */ me(
|
|
8224
8202
|
Ve,
|
|
8225
8203
|
{
|
|
8226
8204
|
ref: u,
|
|
@@ -8236,7 +8214,7 @@ const yt = Me(({
|
|
|
8236
8214
|
showFullAvatar: W.showFullAvatar,
|
|
8237
8215
|
cameraView: "upper",
|
|
8238
8216
|
animations: W.animations,
|
|
8239
|
-
onReady:
|
|
8217
|
+
onReady: le,
|
|
8240
8218
|
onLoading: () => {
|
|
8241
8219
|
},
|
|
8242
8220
|
onError: (v) => {
|