@sage-rsc/talking-head-react 1.1.6 → 1.1.8
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 -9
- package/dist/index.js +1070 -1272
- package/package.json +1 -1
- package/src/lib/talkinghead.mjs +137 -536
package/dist/index.js
CHANGED
|
@@ -4,17 +4,17 @@ import * as f from "three";
|
|
|
4
4
|
import { OrbitControls as Ye } from "three/addons/controls/OrbitControls.js";
|
|
5
5
|
import { GLTFLoader as je } from "three/addons/loaders/GLTFLoader.js";
|
|
6
6
|
import { DRACOLoader as Qe } from "three/addons/loaders/DRACOLoader.js";
|
|
7
|
-
import { FBXLoader as
|
|
8
|
-
import { RoomEnvironment as
|
|
9
|
-
import
|
|
10
|
-
let
|
|
11
|
-
const
|
|
7
|
+
import { FBXLoader as De } from "three/addons/loaders/FBXLoader.js";
|
|
8
|
+
import { RoomEnvironment as qe } from "three/addons/environments/RoomEnvironment.js";
|
|
9
|
+
import Ke from "three/addons/libs/stats.module.js";
|
|
10
|
+
let m, re, ue;
|
|
11
|
+
const S = [0, 0, 0, 0], C = 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
15
|
const oe = new f.Quaternion(), Oe = new f.Quaternion(), fe = new f.Matrix4(), xe = new f.Matrix4();
|
|
16
16
|
new f.Vector3();
|
|
17
|
-
const He = new f.Vector3(0, 0, 1),
|
|
17
|
+
const He = new f.Vector3(0, 0, 1), _e = new f.Vector3(1, 0, 0), Je = new f.Vector3(0, 1, 0), $e = new f.Vector3(0, 0, 1);
|
|
18
18
|
class et {
|
|
19
19
|
constructor(t = null) {
|
|
20
20
|
this.opt = Object.assign({
|
|
@@ -192,7 +192,7 @@ class et {
|
|
|
192
192
|
const l = this.armature.getObjectByName(s.bone);
|
|
193
193
|
if (!l) throw new Error("Bone '" + s.bone + "' not found in #" + o + " exclude.");
|
|
194
194
|
if (Number.isNaN(s.radius) && s.radius >= 0) throw new Error("Radius must be a non-negative number in #" + o + " exclude.");
|
|
195
|
-
const
|
|
195
|
+
const h = {
|
|
196
196
|
bone: l,
|
|
197
197
|
// Bone object
|
|
198
198
|
radius: s.radius,
|
|
@@ -203,9 +203,9 @@ class et {
|
|
|
203
203
|
};
|
|
204
204
|
if (s.deltaLocal) {
|
|
205
205
|
if (!Array.isArray(s.deltaLocal) || s.deltaLocal.length !== 3 || s.deltaLocal.some((r) => Number.isNaN(r))) throw new Error("deltaLocal must be an array of three numbers in #" + o + " exclude.");
|
|
206
|
-
|
|
206
|
+
h.deltaLocal = [...s.deltaLocal];
|
|
207
207
|
}
|
|
208
|
-
i.excludes.push(
|
|
208
|
+
i.excludes.push(h);
|
|
209
209
|
});
|
|
210
210
|
}
|
|
211
211
|
this.showHelpers();
|
|
@@ -264,7 +264,7 @@ class et {
|
|
|
264
264
|
"pivot",
|
|
265
265
|
"helper"
|
|
266
266
|
].forEach((n) => {
|
|
267
|
-
|
|
267
|
+
m = this.getValue(t.name, n), m && (e[n] = m);
|
|
268
268
|
}), e;
|
|
269
269
|
});
|
|
270
270
|
}
|
|
@@ -279,11 +279,11 @@ class et {
|
|
|
279
279
|
this.armature.traverse((o) => {
|
|
280
280
|
e.has(o) || (e.set(o, t), t++);
|
|
281
281
|
}), this.data.sort((o, l) => e.get(o.bone) - e.get(l.bone)), this.data.forEach((o) => {
|
|
282
|
-
|
|
282
|
+
m = this.dict[o.boneParent.name], m && (m.children || (m.children = []), m.children.push(o));
|
|
283
283
|
}), this.objectsUpdate = [];
|
|
284
284
|
const n = /* @__PURE__ */ new WeakSet(), i = (o) => o.parent?.isBone ? [o, ...i(o.parent)] : [o], s = (o) => {
|
|
285
|
-
i(o).forEach((
|
|
286
|
-
n.has(
|
|
285
|
+
i(o).forEach((h) => {
|
|
286
|
+
n.has(h) || (this.objectsUpdate.push(h), n.add(h));
|
|
287
287
|
});
|
|
288
288
|
};
|
|
289
289
|
this.data.forEach((o) => {
|
|
@@ -308,12 +308,12 @@ class et {
|
|
|
308
308
|
i(t?.isScene, "First parameter must be Scene."), this.scene = t, i(e?.isObject3D, "Second parameter must be the armature Object3D."), this.armature = e, i(Array.isArray(n), "Third parameter must be an array of bone configs."), this.config = n, this.config.forEach((s, o) => {
|
|
309
309
|
const l = "Config item #" + o + ": ";
|
|
310
310
|
i(s.bone, l + "Bone not specified.");
|
|
311
|
-
const
|
|
312
|
-
i(typeof
|
|
313
|
-
const r = this.armature.getObjectByName(
|
|
314
|
-
i(r, l + "Bone '" +
|
|
315
|
-
const
|
|
316
|
-
name:
|
|
311
|
+
const h = s.bone;
|
|
312
|
+
i(typeof h == "string" && h.length > 0, l + "Bone name must be a non-empty string.");
|
|
313
|
+
const r = this.armature.getObjectByName(h);
|
|
314
|
+
i(r, l + "Bone '" + h + "' not found."), i(r.parent?.isBone, l + "Bone must have a parent bone."), i(this.data.every((a) => a.bone !== r), l + "Bone '" + h + "' already exists."), r.updateMatrixWorld(!0);
|
|
315
|
+
const u = {
|
|
316
|
+
name: h,
|
|
317
317
|
// Bone name
|
|
318
318
|
bone: r,
|
|
319
319
|
// Bone object
|
|
@@ -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(C).clone(),
|
|
325
325
|
// World position, parent
|
|
326
326
|
qBasis: r.parent.quaternion.clone(),
|
|
327
327
|
// Original quaternion, parent
|
|
@@ -338,9 +338,9 @@ class et {
|
|
|
338
338
|
ea: [0, 0, 0, 0]
|
|
339
339
|
// External acceleration [m/s^2]
|
|
340
340
|
};
|
|
341
|
-
|
|
341
|
+
u.boneParent.matrixWorld.decompose(C, oe, ie), C.copy(He).applyQuaternion(oe).setY(0).normalize(), oe.premultiply(Oe.setFromUnitVectors(He, C).invert()).normalize(), u.qWorldInverseYaw = oe.clone().normalize(), this.data.push(u), this.dict[h] = u;
|
|
342
342
|
try {
|
|
343
|
-
this.setValue(
|
|
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) {
|
|
345
345
|
i(!1, l + a);
|
|
346
346
|
}
|
|
@@ -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], C.copy(o.vWorld), fe.copy(o.boneParent.matrixWorld), xe.copy(fe).invert(), o.vWorld.setFromMatrixPosition(fe), C.applyMatrix4(xe), C.length() > 0.5 && (console.info("Info: Unrealistic jump of " + C.length().toFixed(2) + " meters."), C.setLength(0.5)), C.applyQuaternion(o.bone.quaternion), S[0] = C.x, S[1] = C.y, S[2] = -C.z, S[3] = C.length() / 3, o.children)
|
|
360
360
|
for (n = 0, s = o.children.length; n < s; n++)
|
|
361
|
-
|
|
362
|
-
if (
|
|
363
|
-
o.vBasis.x +
|
|
364
|
-
o.vBasis.y +
|
|
365
|
-
o.vBasis.z +
|
|
366
|
-
),
|
|
361
|
+
m = o.children[n], S[0] -= m.v[0] * t / 3, S[1] -= m.v[1] * t / 3, S[2] += m.v[2] * t / 3, S[3] -= m.v[3] * t / 3;
|
|
362
|
+
if (m = this.opt.sensitivityFactor, S[0] *= o.ext * m, S[1] *= o.ext * m, S[2] *= o.ext * m, S[3] *= o.ext * m, o.isX && (m = S[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 + S[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 = S[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 + S[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 = S[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 + S[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 = S[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 + S[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), S[0] = o.p[0], S[1] = o.p[1], S[2] = o.p[2], S[3] = o.p[3], m = this.opt.movementFactor, S[0] *= m, S[1] *= m, S[2] *= m, S[3] *= m, o.dl && (m = o.dl, S[0] += m[0], S[1] += m[1], S[2] += m[2]), o.dw && (m = o.dw, C.set(
|
|
363
|
+
o.vBasis.x + S[0],
|
|
364
|
+
o.vBasis.y + S[1],
|
|
365
|
+
o.vBasis.z + S[2]
|
|
366
|
+
), C.applyMatrix4(fe), C.x += m[0], C.y += m[1], C.z += m[2], C.applyMatrix4(xe), S[0] += C.x - o.vBasis.x, S[1] += C.y - o.vBasis.y, S[2] += C.z - o.vBasis.z), o.limits && this.opt.isLimits && (m = o.limits, m[0] && (m[0][0] !== null && S[0] < m[0][0] && (S[0] = m[0][0]), m[0][1] !== null && S[0] > m[0][1] && (S[0] = m[0][1])), m[1] && (m[1][0] !== null && S[1] < m[1][0] && (S[1] = m[1][0]), m[1][1] !== null && S[1] > m[1][1] && (S[1] = m[1][1])), m[2] && (m[2][0] !== null && S[2] < m[2][0] && (S[2] = m[2][0]), m[2][1] !== null && S[2] > m[2][1] && (S[2] = m[2][1])), m[3] && (m[3][0] !== null && S[3] < m[3][0] && (S[3] = m[3][0]), m[3][1] !== null && S[3] > m[3][1] && (S[3] = m[3][1]))), o.isPoint)
|
|
367
367
|
o.bone.position.set(
|
|
368
|
-
o.vBasis.x +
|
|
369
|
-
o.vBasis.y +
|
|
370
|
-
o.vBasis.z -
|
|
368
|
+
o.vBasis.x + S[0],
|
|
369
|
+
o.vBasis.y + S[1],
|
|
370
|
+
o.vBasis.z - S[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(C, oe, ie), C.copy(He).applyQuaternion(oe).setY(0).normalize(), oe.premultiply(Oe.setFromUnitVectors(He, C).invert()).normalize(), o.boneParent.quaternion.multiply(oe.invert()), o.boneParent.quaternion.multiply(o.qWorldInverseYaw)), o.isZ && (m = Math.atan(S[0] / o.l), oe.setFromAxisAngle($e, -m), o.boneParent.quaternion.multiply(oe)), o.isY && (m = o.l / 3, m = m * Math.tanh(S[1] / m), o.bone.position.setLength(o.l + m)), o.isX && (m = Math.atan(S[2] / o.l), oe.setFromAxisAngle(_e, -m), o.boneParent.quaternion.multiply(oe)), o.isT && (m = 1.5 * Math.tanh(S[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
|
-
|
|
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), C.copy(o.bone.position), !(C.distanceToSquared(ie) >= m.radiusSq) && (ue = C.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), C.subVectors(C, Ce).projectOnPlane(ie).normalize().multiplyScalar(re), ze.subVectors(o.vBasis, Ce).projectOnPlane(ie).normalize(), ue = ze.dot(C), ue < 0 && (ue = Math.sqrt(re * re - ue * ue), ze.multiplyScalar(ue), C.add(ze)), C.add(Ce).normalize(), ie.copy(o.bone.position).normalize(), oe.setFromUnitVectors(ie, C), o.boneParent.quaternion.premultiply(oe), o.boneParent.updateWorldMatrix(!1, !0))));
|
|
375
375
|
}
|
|
376
376
|
this.helpers.isActive && this.updateHelpers();
|
|
377
377
|
}
|
|
@@ -382,18 +382,18 @@ class et {
|
|
|
382
382
|
* @param {boolean} [keepSetting=false] If true, keep the previos all setting
|
|
383
383
|
*/
|
|
384
384
|
showHelpers(t) {
|
|
385
|
-
if (this.hideHelpers(), this.helpers.isShowAll = t === void 0 ? this.helpers.isShowAll : t === !0,
|
|
386
|
-
(this.helpers.isShowAll || e.helper === !0) && (
|
|
385
|
+
if (this.hideHelpers(), this.helpers.isShowAll = t === void 0 ? this.helpers.isShowAll : t === !0, m = this.helpers, this.data.forEach((e) => {
|
|
386
|
+
(this.helpers.isShowAll || e.helper === !0) && (m.points.bones.push(e.bone), m.points.pivots.push(e.pivot), e.type !== 0 && m.lines.bones.push(e.bone), e.excludes && e.excludes.forEach((n) => {
|
|
387
387
|
let i = !1;
|
|
388
|
-
for (let s = 0; s <
|
|
389
|
-
if (
|
|
388
|
+
for (let s = 0; s < m.excludes.bones.length; s++)
|
|
389
|
+
if (m.excludes.bones[s] === n.bone && m.excludes.radii[s] === n.radius && !(m.excludes.deltaLocals[s] === null && n.deltaLocal !== null) && !(m.excludes.deltaLocals[s] !== null && n.deltaLocal === null) && !(m.excludes.deltaLocals[s] !== null && m.excludes.deltaLocals[s].some((o, l) => o !== n.deltaLocal[l]))) {
|
|
390
390
|
i = !0;
|
|
391
391
|
break;
|
|
392
392
|
}
|
|
393
|
-
i || (
|
|
393
|
+
i || (m.excludes.bones.push(n.bone), m.excludes.radii.push(n.radius), m.excludes.deltaLocals.push(n.deltaLocal ? [...n.deltaLocal] : null), m.excludes.objects.push(null));
|
|
394
394
|
}));
|
|
395
|
-
}),
|
|
396
|
-
const i = new f.SphereGeometry(
|
|
395
|
+
}), m = this.helpers.excludes, this.opt.isExcludes && m.bones.length && m.bones.forEach((e, n) => {
|
|
396
|
+
const i = new f.SphereGeometry(m.radii[n], 6, 6), s = new f.MeshBasicMaterial({
|
|
397
397
|
depthTest: !1,
|
|
398
398
|
depthWrite: !1,
|
|
399
399
|
toneMapped: !1,
|
|
@@ -401,16 +401,16 @@ class et {
|
|
|
401
401
|
wireframe: !0,
|
|
402
402
|
color: this.opt.helperExcludesColor
|
|
403
403
|
});
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
404
|
+
m.objects[n] = new f.Mesh(i, s), m.objects[n].renderOrder = 997, e.add(m.objects[n]), m.deltaLocals[n] && m.objects[n].position.set(
|
|
405
|
+
m.deltaLocals[n][0],
|
|
406
|
+
m.deltaLocals[n][1],
|
|
407
|
+
m.deltaLocals[n][2]
|
|
408
408
|
);
|
|
409
|
-
}),
|
|
409
|
+
}), m = this.helpers.points, m.bones.length) {
|
|
410
410
|
this.helpers.isActive = !0;
|
|
411
|
-
const e = new f.BufferGeometry(), n =
|
|
411
|
+
const e = new f.BufferGeometry(), n = m.bones.map((h) => [0, 0, 0]).flat();
|
|
412
412
|
e.setAttribute("position", new f.Float32BufferAttribute(n, 3));
|
|
413
|
-
const i = new f.Color(this.opt.helperBoneColor1), s = new f.Color(this.opt.helperBoneColor2), o =
|
|
413
|
+
const i = new f.Color(this.opt.helperBoneColor1), s = new f.Color(this.opt.helperBoneColor2), o = m.pivots.map((h) => h && this.opt.isPivots ? [s.r, s.g, s.b] : [i.r, i.g, i.b]).flat();
|
|
414
414
|
e.setAttribute("color", new f.Float32BufferAttribute(o, 3));
|
|
415
415
|
const l = new f.PointsMaterial({
|
|
416
416
|
depthTest: !1,
|
|
@@ -420,12 +420,12 @@ class et {
|
|
|
420
420
|
size: 0.2,
|
|
421
421
|
vertexColors: !0
|
|
422
422
|
});
|
|
423
|
-
|
|
423
|
+
m.object = new f.Points(e, l), m.object.renderOrder = 998, m.object.matrix = this.armature.matrixWorld, m.object.matrixAutoUpdate = !1, this.scene.add(m.object);
|
|
424
424
|
}
|
|
425
|
-
if (
|
|
426
|
-
const e = new f.BufferGeometry(), n =
|
|
425
|
+
if (m = this.helpers.lines, m.bones.length) {
|
|
426
|
+
const e = new f.BufferGeometry(), n = m.bones.map((h) => [0, 0, 0, 0, 0, 0]).flat();
|
|
427
427
|
e.setAttribute("position", new f.Float32BufferAttribute(n, 3));
|
|
428
|
-
const i = new f.Color(this.opt.helperLinkColor1), s = new f.Color(this.opt.helperLinkColor2), o =
|
|
428
|
+
const i = new f.Color(this.opt.helperLinkColor1), s = new f.Color(this.opt.helperLinkColor2), o = m.bones.map((h) => [i.r, i.g, i.b, s.r, s.g, s.b]).flat();
|
|
429
429
|
e.setAttribute("color", new f.Float32BufferAttribute(o, 3));
|
|
430
430
|
const l = new f.LineBasicMaterial({
|
|
431
431
|
vertexColors: !0,
|
|
@@ -434,26 +434,26 @@ class et {
|
|
|
434
434
|
toneMapped: !1,
|
|
435
435
|
transparent: !0
|
|
436
436
|
});
|
|
437
|
-
|
|
437
|
+
m.object = new f.LineSegments(e, l), m.object.renderOrder = 999, m.object.matrix = this.armature.matrixWorld, m.object.matrixAutoUpdate = !1, this.scene.add(m.object);
|
|
438
438
|
}
|
|
439
439
|
}
|
|
440
440
|
/**
|
|
441
441
|
* Update the positions of dynamic bone helpers.
|
|
442
442
|
*/
|
|
443
443
|
updateHelpers() {
|
|
444
|
-
if (
|
|
444
|
+
if (m = this.helpers.points, m.bones.length) {
|
|
445
445
|
xe.copy(this.armature.matrixWorld).invert();
|
|
446
|
-
const t =
|
|
447
|
-
for (let e = 0, n =
|
|
448
|
-
fe.multiplyMatrices(xe,
|
|
449
|
-
t.needsUpdate = !0,
|
|
446
|
+
const t = m.object.geometry.getAttribute("position");
|
|
447
|
+
for (let e = 0, n = m.bones.length; e < n; e++)
|
|
448
|
+
fe.multiplyMatrices(xe, m.bones[e].matrixWorld), C.setFromMatrixPosition(fe), t.setXYZ(e, C.x, C.y, C.z);
|
|
449
|
+
t.needsUpdate = !0, m.object.updateMatrixWorld();
|
|
450
450
|
}
|
|
451
|
-
if (
|
|
451
|
+
if (m = this.helpers.lines, m.bones.length) {
|
|
452
452
|
xe.copy(this.armature.matrixWorld).invert();
|
|
453
|
-
const t =
|
|
454
|
-
for (let e = 0, n = 0, i =
|
|
455
|
-
fe.multiplyMatrices(xe,
|
|
456
|
-
t.needsUpdate = !0,
|
|
453
|
+
const t = m.object.geometry.getAttribute("position");
|
|
454
|
+
for (let e = 0, n = 0, i = m.bones.length; e < i; e++, n += 2)
|
|
455
|
+
fe.multiplyMatrices(xe, m.bones[e].matrixWorld), C.setFromMatrixPosition(fe), t.setXYZ(n, C.x, C.y, C.z), fe.multiplyMatrices(xe, m.bones[e].parent.matrixWorld), C.setFromMatrixPosition(fe), t.setXYZ(n + 1, C.x, C.y, C.z);
|
|
456
|
+
t.needsUpdate = !0, m.object.updateMatrixWorld();
|
|
457
457
|
}
|
|
458
458
|
}
|
|
459
459
|
/**
|
|
@@ -462,9 +462,9 @@ class et {
|
|
|
462
462
|
hideHelpers() {
|
|
463
463
|
[this.helpers.points, this.helpers.lines].forEach((t) => {
|
|
464
464
|
t.bones = [], t.object && (this.scene.remove(t.object), t.object.geometry.dispose(), t.object.material.dispose(), t.object = null);
|
|
465
|
-
}),
|
|
466
|
-
t && (
|
|
467
|
-
}),
|
|
465
|
+
}), m = this.helpers.excludes, m.objects.forEach((t, e) => {
|
|
466
|
+
t && (m.bones[e].remove(t), t.geometry.dispose(), t.material.dispose());
|
|
467
|
+
}), m.bones = [], m.deltaLocals = [], m.radii = [], m.objects = [], this.helpers.isActive = !1;
|
|
468
468
|
}
|
|
469
469
|
/**
|
|
470
470
|
* Start dynamic bones.
|
|
@@ -519,13 +519,13 @@ class tt {
|
|
|
519
519
|
phonemeBoundaries: []
|
|
520
520
|
}, i = 1024, s = 512, o = Math.floor((t.length - i) / s) + 1;
|
|
521
521
|
for (let l = 0; l < o; l++) {
|
|
522
|
-
const
|
|
522
|
+
const h = l * s, r = Math.min(h + i, t.length), u = t.slice(h, r), a = this.calculateEnergy(u);
|
|
523
523
|
n.energy.push(a);
|
|
524
|
-
const c = this.calculateSpectralCentroid(
|
|
524
|
+
const c = this.calculateSpectralCentroid(u);
|
|
525
525
|
n.spectralCentroid.push(c);
|
|
526
|
-
const d = this.calculateZeroCrossingRate(
|
|
526
|
+
const d = this.calculateZeroCrossingRate(u);
|
|
527
527
|
n.zeroCrossingRate.push(d);
|
|
528
|
-
const g = this.calculateMFCC(
|
|
528
|
+
const g = this.calculateMFCC(u);
|
|
529
529
|
n.mfcc.push(g);
|
|
530
530
|
}
|
|
531
531
|
return n.onsets = this.detectOnsets(n.energy), n.phonemeBoundaries = this.detectPhonemeBoundaries(n), n;
|
|
@@ -597,19 +597,19 @@ class tt {
|
|
|
597
597
|
for (; s & o; )
|
|
598
598
|
s ^= o, o >>= 1;
|
|
599
599
|
if (s ^= o, i < s) {
|
|
600
|
-
const l = n[i * 2],
|
|
601
|
-
n[i * 2] = n[s * 2], n[i * 2 + 1] = n[s * 2 + 1], n[s * 2] = l, n[s * 2 + 1] =
|
|
600
|
+
const l = n[i * 2], h = n[i * 2 + 1];
|
|
601
|
+
n[i * 2] = n[s * 2], n[i * 2 + 1] = n[s * 2 + 1], n[s * 2] = l, n[s * 2 + 1] = h;
|
|
602
602
|
}
|
|
603
603
|
}
|
|
604
604
|
for (let i = 2; i <= e; i <<= 1) {
|
|
605
605
|
const s = -2 * Math.PI / i, o = Math.cos(s), l = Math.sin(s);
|
|
606
|
-
for (let
|
|
607
|
-
let r = 1,
|
|
606
|
+
for (let h = 0; h < e; h += i) {
|
|
607
|
+
let r = 1, u = 0;
|
|
608
608
|
for (let a = 0; a < i / 2; a++) {
|
|
609
|
-
const c = n[(
|
|
610
|
-
n[(
|
|
611
|
-
const
|
|
612
|
-
r =
|
|
609
|
+
const c = n[(h + a) * 2], d = n[(h + a) * 2 + 1], g = n[(h + a + i / 2) * 2] * r - n[(h + a + i / 2) * 2 + 1] * u, b = n[(h + a + i / 2) * 2] * u + n[(h + a + i / 2) * 2 + 1] * r;
|
|
610
|
+
n[(h + a) * 2] = c + g, n[(h + a) * 2 + 1] = d + b, n[(h + a + i / 2) * 2] = c - g, n[(h + a + i / 2) * 2 + 1] = d - b;
|
|
611
|
+
const x = r * o - u * l, A = r * l + u * o;
|
|
612
|
+
r = x, u = A;
|
|
613
613
|
}
|
|
614
614
|
}
|
|
615
615
|
}
|
|
@@ -624,8 +624,8 @@ class tt {
|
|
|
624
624
|
const e = [];
|
|
625
625
|
let s = -0.1;
|
|
626
626
|
for (let o = 1; o < t.length; o++) {
|
|
627
|
-
const l = t[o] - t[o - 1],
|
|
628
|
-
l > 0.1 &&
|
|
627
|
+
const l = t[o] - t[o - 1], h = o * 0.023;
|
|
628
|
+
l > 0.1 && h - s > 0.1 && (e.push(h), s = h);
|
|
629
629
|
}
|
|
630
630
|
return e;
|
|
631
631
|
}
|
|
@@ -637,8 +637,8 @@ class tt {
|
|
|
637
637
|
detectPhonemeBoundaries(t) {
|
|
638
638
|
const e = [], { energy: n, spectralCentroid: i, zeroCrossingRate: s } = t;
|
|
639
639
|
for (let o = 1; o < n.length; o++) {
|
|
640
|
-
const l = o * 0.023,
|
|
641
|
-
|
|
640
|
+
const l = o * 0.023, h = Math.abs(n[o] - n[o - 1]), r = Math.abs(i[o] - i[o - 1]), u = Math.abs(s[o] - s[o - 1]);
|
|
641
|
+
h + r * 0.1 + u * 0.5 > 0.2 && e.push(l);
|
|
642
642
|
}
|
|
643
643
|
return e;
|
|
644
644
|
}
|
|
@@ -654,14 +654,14 @@ class tt {
|
|
|
654
654
|
t.phonemeBoundaries, t.onsets;
|
|
655
655
|
const s = [];
|
|
656
656
|
let o = 0;
|
|
657
|
-
for (let
|
|
658
|
-
const r = i[
|
|
657
|
+
for (let h = 0; h < i.length; h++) {
|
|
658
|
+
const r = i[h], u = this.estimateWordDuration(r, n / i.length);
|
|
659
659
|
s.push({
|
|
660
660
|
word: r,
|
|
661
661
|
startTime: o,
|
|
662
|
-
endTime: o +
|
|
663
|
-
duration:
|
|
664
|
-
}), o +=
|
|
662
|
+
endTime: o + u,
|
|
663
|
+
duration: u
|
|
664
|
+
}), o += u;
|
|
665
665
|
}
|
|
666
666
|
const l = this.generateVisemeTimings(t, e, n);
|
|
667
667
|
return {
|
|
@@ -701,27 +701,27 @@ class tt {
|
|
|
701
701
|
const i = [], s = t.phonemeBoundaries;
|
|
702
702
|
t.onsets;
|
|
703
703
|
const o = this.textToVisemes(e);
|
|
704
|
-
let l = 0,
|
|
704
|
+
let l = 0, h = 0;
|
|
705
705
|
for (let r = 0; r < s.length && l < o.length; r++) {
|
|
706
|
-
const
|
|
706
|
+
const u = s[r], a = o[l], c = t.energy[Math.floor(u / 0.023)] || 0, d = this.calculateVisemeDuration(a, c);
|
|
707
707
|
i.push({
|
|
708
708
|
viseme: a,
|
|
709
|
-
startTime:
|
|
710
|
-
endTime:
|
|
709
|
+
startTime: h,
|
|
710
|
+
endTime: h + d,
|
|
711
711
|
duration: d,
|
|
712
712
|
intensity: Math.min(1, c * 2)
|
|
713
713
|
// Map energy to viseme intensity
|
|
714
|
-
}),
|
|
714
|
+
}), h += d, l++;
|
|
715
715
|
}
|
|
716
716
|
for (; l < o.length; ) {
|
|
717
|
-
const r = o[l],
|
|
717
|
+
const r = o[l], u = this.calculateVisemeDuration(r, 0.5);
|
|
718
718
|
i.push({
|
|
719
719
|
viseme: r,
|
|
720
|
-
startTime:
|
|
721
|
-
endTime:
|
|
722
|
-
duration:
|
|
720
|
+
startTime: h,
|
|
721
|
+
endTime: h + u,
|
|
722
|
+
duration: u,
|
|
723
723
|
intensity: 0.6
|
|
724
|
-
}),
|
|
724
|
+
}), h += u, l++;
|
|
725
725
|
}
|
|
726
726
|
return i;
|
|
727
727
|
}
|
|
@@ -775,16 +775,16 @@ class tt {
|
|
|
775
775
|
let o = 0;
|
|
776
776
|
for (; o < s.length; ) {
|
|
777
777
|
let l = !1;
|
|
778
|
-
for (let
|
|
779
|
-
const r = s.substr(o,
|
|
778
|
+
for (let h = 3; h >= 2; h--) {
|
|
779
|
+
const r = s.substr(o, h);
|
|
780
780
|
if (e[r]) {
|
|
781
|
-
n.push(e[r]), o +=
|
|
781
|
+
n.push(e[r]), o += h, l = !0;
|
|
782
782
|
break;
|
|
783
783
|
}
|
|
784
784
|
}
|
|
785
785
|
if (!l) {
|
|
786
|
-
const
|
|
787
|
-
e[
|
|
786
|
+
const h = s[o];
|
|
787
|
+
e[h] && n.push(e[h]), o++;
|
|
788
788
|
}
|
|
789
789
|
}
|
|
790
790
|
}
|
|
@@ -1206,11 +1206,11 @@ class nt {
|
|
|
1206
1206
|
};
|
|
1207
1207
|
Object.keys(this.rules).forEach((e) => {
|
|
1208
1208
|
this.rules[e] = this.rules[e].map((n) => {
|
|
1209
|
-
const i = n.indexOf("["), s = n.indexOf("]"), o = n.indexOf("="), l = n.substring(0, i),
|
|
1209
|
+
const i = n.indexOf("["), s = n.indexOf("]"), o = n.indexOf("="), l = n.substring(0, i), h = n.substring(i + 1, s), r = n.substring(s + 1, o), u = n.substring(o + 1), a = { regex: "", move: 0, visemes: [] };
|
|
1210
1210
|
let c = "";
|
|
1211
1211
|
c += [...l].map((g) => t[g] || g).join("");
|
|
1212
|
-
const d = [...
|
|
1213
|
-
return d[0] = d[0].toLowerCase(), c += d.join(""), a.move = d.length, c += [...r].map((g) => t[g] || g).join(""), a.regex = new RegExp(c),
|
|
1212
|
+
const d = [...h];
|
|
1213
|
+
return d[0] = d[0].toLowerCase(), c += d.join(""), a.move = d.length, c += [...r].map((g) => t[g] || g).join(""), a.regex = new RegExp(c), u.length && u.split(" ").forEach((g) => {
|
|
1214
1214
|
a.visemes.push(g);
|
|
1215
1215
|
}), a;
|
|
1216
1216
|
});
|
|
@@ -1324,8 +1324,8 @@ class nt {
|
|
|
1324
1324
|
*/
|
|
1325
1325
|
convertDecade(t) {
|
|
1326
1326
|
const e = parseInt(t), n = !isNaN(e) && t.length === 2, i = !isNaN(e) && t.length > 2 && e > 0 && e <= 3e3, s = i && e % 1e3 === 0 ? Math.floor(e / 1e3) : null, o = i && !s ? Math.floor(e / 100) : null, l = n || i ? Math.floor(e % 100 / 10) * 10 : null;
|
|
1327
|
-
let
|
|
1328
|
-
return s ?
|
|
1327
|
+
let h = [];
|
|
1328
|
+
return s ? h.push(this.convertNumberToWords(s).trim(), "thousands") : (o && h.push(this.convertNumberToWords(o).trim()), l ? h.push(this.decades[l] || this.convertNumberToWords(l).trim() + "s") : o ? h.push("hundreds") : h.push(t)), h.join(" ");
|
|
1329
1329
|
}
|
|
1330
1330
|
/**
|
|
1331
1331
|
* Convert ordinal number to text.
|
|
@@ -1376,9 +1376,9 @@ class nt {
|
|
|
1376
1376
|
const s = i[e.i], o = this.rules[s];
|
|
1377
1377
|
if (o)
|
|
1378
1378
|
for (let l = 0; l < o.length; l++) {
|
|
1379
|
-
const
|
|
1380
|
-
if ((e.words.substring(0, e.i) + s.toLowerCase() + e.words.substring(e.i + 1)).match(
|
|
1381
|
-
|
|
1379
|
+
const h = o[l];
|
|
1380
|
+
if ((e.words.substring(0, e.i) + s.toLowerCase() + e.words.substring(e.i + 1)).match(h.regex)) {
|
|
1381
|
+
h.visemes.forEach((a) => {
|
|
1382
1382
|
if (e.visemes.length && e.visemes[e.visemes.length - 1] === a) {
|
|
1383
1383
|
const c = 0.7 * (this.visemeDurations[a] || 1);
|
|
1384
1384
|
e.durations[e.durations.length - 1] += c, n += c;
|
|
@@ -1386,7 +1386,7 @@ class nt {
|
|
|
1386
1386
|
const c = this.visemeDurations[a] || 1;
|
|
1387
1387
|
e.visemes.push(a), e.times.push(n), e.durations.push(c), n += c;
|
|
1388
1388
|
}
|
|
1389
|
-
}), e.i +=
|
|
1389
|
+
}), e.i += h.move;
|
|
1390
1390
|
break;
|
|
1391
1391
|
}
|
|
1392
1392
|
}
|
|
@@ -1616,11 +1616,11 @@ class ot {
|
|
|
1616
1616
|
};
|
|
1617
1617
|
Object.keys(this.rules).forEach((e) => {
|
|
1618
1618
|
this.rules[e] = this.rules[e].map((n) => {
|
|
1619
|
-
const i = n.indexOf("["), s = n.indexOf("]"), o = n.indexOf("="), l = n.substring(0, i),
|
|
1619
|
+
const i = n.indexOf("["), s = n.indexOf("]"), o = n.indexOf("="), l = n.substring(0, i), h = n.substring(i + 1, s), r = n.substring(s + 1, o), u = n.substring(o + 1), a = { regex: "", move: 0, visemes: [] };
|
|
1620
1620
|
let c = "";
|
|
1621
1621
|
c += [...l].map((g) => t[g] || g).join("");
|
|
1622
|
-
const d = [...
|
|
1623
|
-
return d[0] = d[0].toLowerCase(), c += d.join(""), a.move = d.length, c += [...r].map((g) => t[g] || g).join(""), a.regex = new RegExp(c),
|
|
1622
|
+
const d = [...h];
|
|
1623
|
+
return d[0] = d[0].toLowerCase(), c += d.join(""), a.move = d.length, c += [...r].map((g) => t[g] || g).join(""), a.regex = new RegExp(c), u.length && u.split(" ").forEach((g) => {
|
|
1624
1624
|
a.visemes.push(g);
|
|
1625
1625
|
}), a;
|
|
1626
1626
|
});
|
|
@@ -1732,8 +1732,8 @@ class ot {
|
|
|
1732
1732
|
const s = i[e.i], o = this.rules[s];
|
|
1733
1733
|
if (o) {
|
|
1734
1734
|
let l = !1;
|
|
1735
|
-
for (let
|
|
1736
|
-
const r = o[
|
|
1735
|
+
for (let h = 0; h < o.length; h++) {
|
|
1736
|
+
const r = o[h];
|
|
1737
1737
|
if ((e.words.substring(0, e.i) + s.toLowerCase() + e.words.substring(e.i + 1)).match(r.regex)) {
|
|
1738
1738
|
r.visemes.forEach((c) => {
|
|
1739
1739
|
if (e.visemes.length && e.visemes[e.visemes.length - 1] === c) {
|
|
@@ -2131,11 +2131,11 @@ class at {
|
|
|
2131
2131
|
};
|
|
2132
2132
|
Object.keys(this.rules).forEach((e) => {
|
|
2133
2133
|
this.rules[e] = this.rules[e].map((n) => {
|
|
2134
|
-
const i = n.indexOf("["), s = n.indexOf("]"), o = n.indexOf("="), l = n.substring(0, i),
|
|
2134
|
+
const i = n.indexOf("["), s = n.indexOf("]"), o = n.indexOf("="), l = n.substring(0, i), h = n.substring(i + 1, s), r = n.substring(s + 1, o), u = n.substring(o + 1), a = { regex: "", move: 0, visemes: [] };
|
|
2135
2135
|
let c = "";
|
|
2136
2136
|
c += [...l].map((g) => t[g] || g).join("");
|
|
2137
|
-
const d = [...
|
|
2138
|
-
return d[0] = d[0].toLowerCase(), c += d.join(""), a.move = d.length, c += [...r].map((g) => t[g] || g).join(""), a.regex = new RegExp(c, "i"),
|
|
2137
|
+
const d = [...h];
|
|
2138
|
+
return d[0] = d[0].toLowerCase(), c += d.join(""), a.move = d.length, c += [...r].map((g) => t[g] || g).join(""), a.regex = new RegExp(c, "i"), u.length && u.split(" ").forEach((g) => {
|
|
2139
2139
|
g && a.visemes.push(g);
|
|
2140
2140
|
}), a;
|
|
2141
2141
|
});
|
|
@@ -2267,8 +2267,8 @@ class at {
|
|
|
2267
2267
|
const s = i[e.i], o = this.rules[s];
|
|
2268
2268
|
if (o) {
|
|
2269
2269
|
let l = !1;
|
|
2270
|
-
for (let
|
|
2271
|
-
const r = o[
|
|
2270
|
+
for (let h = 0; h < o.length; h++) {
|
|
2271
|
+
const r = o[h];
|
|
2272
2272
|
if ((e.words.substring(0, e.i) + s.toLowerCase() + e.words.substring(e.i + 1)).match(r.regex)) {
|
|
2273
2273
|
r.visemes.forEach((c) => {
|
|
2274
2274
|
if (e.visemes.length && e.visemes[e.visemes.length - 1] === c) {
|
|
@@ -2381,10 +2381,10 @@ class lt {
|
|
|
2381
2381
|
const e = [];
|
|
2382
2382
|
let n = parseFloat(t);
|
|
2383
2383
|
if (n === void 0) return t;
|
|
2384
|
-
let i = (s, o, l,
|
|
2384
|
+
let i = (s, o, l, h, r) => {
|
|
2385
2385
|
if (s < o) return s;
|
|
2386
|
-
const
|
|
2387
|
-
return e.push(l + (
|
|
2386
|
+
const u = Math.floor(s / o);
|
|
2387
|
+
return e.push(l + (u === 1 ? h : this.numberToFinnishWords(u.toString()) + r)), s - u * o;
|
|
2388
2388
|
};
|
|
2389
2389
|
if (n < 0 && (e.push("miinus "), n = Math.abs(n)), n = i(n, 1e9, " ", "miljardi", " miljardia"), n = i(n, 1e6, " ", "miljoona", " miljoonaa"), n = i(n, 1e3, "", "tuhat", "tuhatta"), n = i(n, 100, " ", "sata", "sataa"), n > 20 && (n = i(n, 10, "", "", "kymmentä")), n >= 1) {
|
|
2390
2390
|
let s = Math.floor(n);
|
|
@@ -2436,11 +2436,11 @@ class lt {
|
|
|
2436
2436
|
return e;
|
|
2437
2437
|
}
|
|
2438
2438
|
}
|
|
2439
|
-
const
|
|
2439
|
+
const ut = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
|
|
2440
2440
|
__proto__: null,
|
|
2441
2441
|
LipsyncFi: lt
|
|
2442
2442
|
}, Symbol.toStringTag, { value: "Module" }));
|
|
2443
|
-
class
|
|
2443
|
+
class ht {
|
|
2444
2444
|
/**
|
|
2445
2445
|
* @constructor
|
|
2446
2446
|
*/
|
|
@@ -2559,10 +2559,10 @@ class ut {
|
|
|
2559
2559
|
const e = [];
|
|
2560
2560
|
let n = parseFloat(t);
|
|
2561
2561
|
if (n === void 0) return t;
|
|
2562
|
-
let i = (s, o, l,
|
|
2562
|
+
let i = (s, o, l, h, r) => {
|
|
2563
2563
|
if (s < o) return s;
|
|
2564
|
-
const
|
|
2565
|
-
return
|
|
2564
|
+
const u = Math.floor(s / o);
|
|
2565
|
+
return u === 1 ? e.push(this.numbers[1]) : e.push(this.numberToLithuanianWords(u.toString())), u % 10 === 1 ? e.push(l) : u % 10 === 0 || u % 100 > 10 && u % 100 < 20 ? e.push(r) : e.push(h), s - u * o;
|
|
2566
2566
|
};
|
|
2567
2567
|
n < 0 && (e.push("minus"), n = Math.abs(n)), n = i(n, 1e9, "milijardas", "milijardai", "milijardų"), n = i(n, 1e6, "milijonas", "milijonai", "milijonų"), n = i(n, 1e3, "tūkstantis", "tūkstančiai", "tūkstančių"), n = i(n, 100, "šimtas", "šimtai", "šimtų");
|
|
2568
2568
|
for (let s = this.tens.length - 1; s >= 1; s--)
|
|
@@ -2608,11 +2608,11 @@ class ut {
|
|
|
2608
2608
|
const o = i[s].toLowerCase(), l = this.visemes[o];
|
|
2609
2609
|
if (l)
|
|
2610
2610
|
if (e.visemes.length && e.visemes[e.visemes.length - 1] === l) {
|
|
2611
|
-
const
|
|
2612
|
-
e.durations[e.durations.length - 1] +=
|
|
2611
|
+
const h = 0.7 * (this.durations[o] || 1);
|
|
2612
|
+
e.durations[e.durations.length - 1] += h, n += h;
|
|
2613
2613
|
} else {
|
|
2614
|
-
const
|
|
2615
|
-
e.visemes.push(l), e.times.push(n), e.durations.push(
|
|
2614
|
+
const h = this.durations[o] || 1;
|
|
2615
|
+
e.visemes.push(l), e.times.push(n), e.durations.push(h), n += h;
|
|
2616
2616
|
}
|
|
2617
2617
|
else
|
|
2618
2618
|
n += this.pauses[i[s]] || 0;
|
|
@@ -2622,14 +2622,14 @@ class ut {
|
|
|
2622
2622
|
}
|
|
2623
2623
|
const ct = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
|
|
2624
2624
|
__proto__: null,
|
|
2625
|
-
LipsyncLt:
|
|
2625
|
+
LipsyncLt: ht
|
|
2626
2626
|
}, Symbol.toStringTag, { value: "Module" })), dt = new URL("data:text/javascript;base64,Y2xhc3MgUGxheWJhY2tXb3JrbGV0IGV4dGVuZHMgQXVkaW9Xb3JrbGV0UHJvY2Vzc29yIHsKICBzdGF0aWMgRlNNID0gewogICAgSURMRTogMCwKICAgIFBMQVlJTkc6IDEsCiAgfTsKCiAgY29uc3RydWN0b3Iob3B0aW9ucykgewogICAgc3VwZXIoKTsKICAgIHRoaXMucG9ydC5vbm1lc3NhZ2UgPSB0aGlzLmhhbmRsZU1lc3NhZ2UuYmluZCh0aGlzKTsKCiAgICB0aGlzLl9zYW1wbGVSYXRlID0gb3B0aW9ucz8ucHJvY2Vzc29yT3B0aW9ucz8uc2FtcGxlUmF0ZSB8fCBzYW1wbGVSYXRlOwogICAgdGhpcy5fc2NhbGUgPSAxIC8gMzI3Njg7IC8vIFBDTTE2IC0+IGZsb2F0CgogICAgLy8gU2lsZW5jZSBkZXRlY3Rpb24gdGhyZXNob2xkICgxIHNlY29uZCkgYXMgYSBmYWxsYmFjayBzYWZldHkgbmV0CiAgICBjb25zdCBzaWxlbmNlRHVyYXRpb25TZWNvbmRzID0gMS4wOwogICAgdGhpcy5fc2lsZW5jZVRocmVzaG9sZEJsb2NrcyA9IE1hdGguY2VpbCgodGhpcy5fc2FtcGxlUmF0ZSAqIHNpbGVuY2VEdXJhdGlvblNlY29uZHMpIC8gMTI4KTsKCiAgICAvLyBNZXRyaWNzIGNvbmZpZ3VyYXRpb24gdmlhIG9wdGlvbnMKICAgIGNvbnN0IG1ldHJpY3NDZmcgPSBvcHRpb25zPy5wcm9jZXNzb3JPcHRpb25zPy5tZXRyaWNzIHx8IHt9OwogICAgdGhpcy5fbWV0cmljc0VuYWJsZWQgPSBtZXRyaWNzQ2ZnLmVuYWJsZWQgIT09IGZhbHNlOwogICAgY29uc3QgaW50ZXJ2YWxIeiA9ICh0eXBlb2YgbWV0cmljc0NmZy5pbnRlcnZhbEh6ID09PSAibnVtYmVyIiAmJiBtZXRyaWNzQ2ZnLmludGVydmFsSHogPiAwKQogICAgICA/IG1ldHJpY3NDZmcuaW50ZXJ2YWxIeiA6IDI7CiAgICAvLyBNZXRyaWNzIHN0YXRlIChsb3ctb3ZlcmhlYWQpCiAgICB0aGlzLl9mcmFtZXNQcm9jZXNzZWQgPSAwOwogICAgdGhpcy5fdW5kZXJydW5CbG9ja3MgPSAwOwogICAgdGhpcy5fbWF4UXVldWVTYW1wbGVzID0gMDsKICAgIHRoaXMuX2xhc3RNZXRyaWNzU2VudEF0RnJhbWUgPSAwOwogICAgLy8gQ29udmVydCB0byBmcmFtZXMgYmV0d2VlbiByZXBvcnRzCiAgICB0aGlzLl9tZXRyaWNzSW50ZXJ2YWxGcmFtZXMgPSBNYXRoLm1heCgxMjgsIE1hdGgucm91bmQodGhpcy5fc2FtcGxlUmF0ZSAvIGludGVydmFsSHopKTsKCiAgICB0aGlzLnJlc2V0KCk7CiAgfQoKICAvKioKICAgKiBSZXNldHMgdGhlIHdvcmtsZXQgdG8gaXRzIGluaXRpYWwgSURMRSBzdGF0ZS4KICAgKi8KICByZXNldCgpIHsKICAgIHRoaXMuX2J1ZmZlclF1ZXVlID0gW107CiAgICB0aGlzLl9jdXJyZW50Q2h1bmsgPSBudWxsOwogICAgdGhpcy5fY3VycmVudENodW5rT2Zmc2V0ID0gMDsKICAgIHRoaXMuX3N0YXRlID0gUGxheWJhY2tXb3JrbGV0LkZTTS5JRExFOwoKICAgIHRoaXMuX25vTW9yZURhdGFSZWNlaXZlZCA9IGZhbHNlOwogICAgdGhpcy5fc2lsZW5jZUZyYW1lc0NvdW50ID0gMDsKICAgIHRoaXMuX2hhc1NlbnRFbmRlZCA9IGZhbHNlOwogICAgLy8gUmVzZXQgbWF4IHF1ZXVlIHRyYWNrZXIgb25seSB3aGVuIGdvaW5nIGlkbGUKICAgIHRoaXMuX21heFF1ZXVlU2FtcGxlcyA9IDA7CiAgfQoKICBoYW5kbGVNZXNzYWdlKGV2ZW50KSB7CiAgICBjb25zdCB7IHR5cGUsIGRhdGEgfSA9IGV2ZW50LmRhdGE7CgogICAgLy8gSU5URVJSVVBUOiBUaGUgbWFpbiB0aHJlYWQgd2FudHMgdG8gc3RvcCBpbW1lZGlhdGVseS4KICAgIGlmICh0eXBlID09PSAic3RvcCIpIHsKICAgICAgdGhpcy5yZXNldCgpOwogICAgICAvLyBTZW5kIGZpbmFsIG1ldHJpY3Mgc2hvd2luZyBjbGVhcmVkIHN0YXRlCiAgICAgIGlmICh0aGlzLl9tZXRyaWNzRW5hYmxlZCkgewogICAgICAgIHRyeSB7CiAgICAgICAgICB0aGlzLnBvcnQucG9zdE1lc3NhZ2UoewogICAgICAgICAgICB0eXBlOiAibWV0cmljcyIsCiAgICAgICAgICAgIGRhdGE6IHsKICAgICAgICAgICAgICBzdGF0ZTogUGxheWJhY2tXb3JrbGV0LkZTTS5JRExFLAogICAgICAgICAgICAgIHF1ZXVlZFNhbXBsZXM6IDAsCiAgICAgICAgICAgICAgcXVldWVkTXM6IDAsCiAgICAgICAgICAgICAgbWF4UXVldWVkTXM6IE1hdGgucm91bmQoKHRoaXMuX21heFF1ZXVlU2FtcGxlcyAvIHRoaXMuX3NhbXBsZVJhdGUpICogMTAwMCksCiAgICAgICAgICAgICAgdW5kZXJydW5CbG9ja3M6IHRoaXMuX3VuZGVycnVuQmxvY2tzLAogICAgICAgICAgICAgIGZyYW1lc1Byb2Nlc3NlZDogdGhpcy5fZnJhbWVzUHJvY2Vzc2VkCiAgICAgICAgICAgIH0KICAgICAgICAgIH0pOwogICAgICAgIH0gY2F0Y2ggKF8pIHsgfQogICAgICB9CiAgICAgIHJldHVybjsKICAgIH0KCiAgICAvLyBNYWluIHRocmVhZCBoYXMgc2lnbmFsZWQgdGhhdCBubyBtb3JlIGF1ZGlvIGNodW5rcyB3aWxsIGJlIHNlbnQgZm9yIHRoaXMgdXR0ZXJhbmNlLgogICAgaWYgKHR5cGUgPT09ICJuby1tb3JlLWRhdGEiKSB7CiAgICAgIHRoaXMuX25vTW9yZURhdGFSZWNlaXZlZCA9IHRydWU7CiAgICAgIHJldHVybjsKICAgIH0KCiAgICAvLyBVcGRhdGUgbWV0cmljcyBjb25maWd1cmF0aW9uIGF0IHJ1bnRpbWUKICAgIGlmICh0eXBlID09PSAiY29uZmlnLW1ldHJpY3MiICYmIGRhdGEgJiYgdHlwZW9mIGRhdGEgPT09ICJvYmplY3QiKSB7CiAgICAgIGlmICgiZW5hYmxlZCIgaW4gZGF0YSkgdGhpcy5fbWV0cmljc0VuYWJsZWQgPSAhIWRhdGEuZW5hYmxlZDsKICAgICAgaWYgKHR5cGVvZiBkYXRhLmludGVydmFsSHogPT09ICJudW1iZXIiICYmIGRhdGEuaW50ZXJ2YWxIeiA+IDApIHsKICAgICAgICBjb25zdCBpbnRlcnZhbEh6ID0gZGF0YS5pbnRlcnZhbEh6OwogICAgICAgIHRoaXMuX21ldHJpY3NJbnRlcnZhbEZyYW1lcyA9IE1hdGgubWF4KDEyOCwgTWF0aC5yb3VuZCh0aGlzLl9zYW1wbGVSYXRlIC8gaW50ZXJ2YWxIeikpOwogICAgICB9CiAgICAgIC8vIFJlc2V0IHBhY2luZyBzbyB0aGUgbmV4dCByZXBvcnQgYWxpZ25zIHdpdGggbmV3IGludGVydmFsCiAgICAgIHRoaXMuX2xhc3RNZXRyaWNzU2VudEF0RnJhbWUgPSB0aGlzLl9mcmFtZXNQcm9jZXNzZWQ7CiAgICAgIHJldHVybjsKICAgIH0KCiAgICAvLyBOZXcgYXVkaW8gZGF0YSBoYXMgYXJyaXZlZC4KICAgIGlmICh0eXBlID09PSAiYXVkaW9EYXRhIiAmJiBkYXRhIGluc3RhbmNlb2YgQXJyYXlCdWZmZXIpIHsKICAgICAgdGhpcy5fbm9Nb3JlRGF0YVJlY2VpdmVkID0gZmFsc2U7CiAgICAgIC8vIElmIHdlIHdlcmUgaWRsZSwgdGhpcyBuZXcgZGF0YSBraWNrcyBvZmYgdGhlIHBsYXliYWNrLgogICAgICBpZiAodGhpcy5fc3RhdGUgPT09IFBsYXliYWNrV29ya2xldC5GU00uSURMRSkgewogICAgICAgIHRoaXMuX3N0YXRlID0gUGxheWJhY2tXb3JrbGV0LkZTTS5QTEFZSU5HOwogICAgICAgIHRoaXMucG9ydC5wb3N0TWVzc2FnZSh7IHR5cGU6ICJwbGF5YmFjay1zdGFydGVkIiB9KTsKICAgICAgfQoKICAgICAgLy8gV2Ugb25seSBxdWV1ZSBkYXRhIGlmIHdlIGFyZSBpbiB0aGUgUExBWUlORyBzdGF0ZS4gVGhpcyBwcmV2ZW50cwogICAgICAvLyBkYXRhIGZyb20gYSBwcmV2aW91cywgaW50ZXJydXB0ZWQgc3RyZWFtIGZyb20gbGluZ2VyaW5nLgogICAgICBpZiAodGhpcy5fc3RhdGUgPT09IFBsYXliYWNrV29ya2xldC5GU00uUExBWUlORykgewogICAgICAgIC8vIFN0b3JlIGFzIEludDE2QXJyYXkgdmlldyB0byBhdm9pZCBjb25zdHJ1Y3RpbmcgaXQgaW4gcHJvY2VzcygpCiAgICAgICAgdGhpcy5fYnVmZmVyUXVldWUucHVzaChuZXcgSW50MTZBcnJheShkYXRhKSk7CiAgICAgICAgdGhpcy5fc2lsZW5jZUZyYW1lc0NvdW50ID0gMDsgLy8gUmVzZXQgc2lsZW5jZSBjb3VudGVyIG9uIG5ldyBkYXRhCiAgICAgIH0KICAgIH0KICB9CgogIHByb2Nlc3MoaW5wdXRzLCBvdXRwdXRzLCBwYXJhbWV0ZXJzKSB7CiAgICBjb25zdCBvdXRwdXRDaGFubmVsID0gb3V0cHV0c1swXT8uWzBdOwogICAgaWYgKCFvdXRwdXRDaGFubmVsKSB7CiAgICAgIHJldHVybiB0cnVlOyAvLyBLZWVwIGFsaXZlIGV2ZW4gaWYgb3V0cHV0IGlzIHRlbXBvcmFyaWx5IGRpc2Nvbm5lY3RlZAogICAgfQoKICAgIC8vIElmIHdlIGFyZSBub3QgcGxheWluZywganVzdCBvdXRwdXQgc2lsZW5jZSBhbmQgd2FpdC4KICAgIGlmICh0aGlzLl9zdGF0ZSAhPT0gUGxheWJhY2tXb3JrbGV0LkZTTS5QTEFZSU5HKSB7CiAgICAgIG91dHB1dENoYW5uZWwuZmlsbCgwKTsKICAgICAgcmV0dXJuIHRydWU7IC8vIEFsd2F5cyByZXR1cm4gdHJ1ZSB0byBrZWVwIHRoZSBwcm9jZXNzb3IgYWxpdmUKICAgIH0KCiAgICAvLyBDb3JlIFBMQVlJTkcgTG9naWMKICAgIGNvbnN0IGJsb2NrU2l6ZSA9IG91dHB1dENoYW5uZWwubGVuZ3RoOwogICAgbGV0IHNhbXBsZXNDb3BpZWQgPSAwOwoKICAgIHdoaWxlIChzYW1wbGVzQ29waWVkIDwgYmxvY2tTaXplKSB7CiAgICAgIGlmICghdGhpcy5fY3VycmVudENodW5rIHx8IHRoaXMuX2N1cnJlbnRDaHVua09mZnNldCA+PSB0aGlzLl9jdXJyZW50Q2h1bmsubGVuZ3RoKSB7CiAgICAgICAgaWYgKHRoaXMuX2J1ZmZlclF1ZXVlLmxlbmd0aCA+IDApIHsKICAgICAgICAgIHRoaXMuX2N1cnJlbnRDaHVuayA9IHRoaXMuX2J1ZmZlclF1ZXVlLnNoaWZ0KCk7CiAgICAgICAgICB0aGlzLl9jdXJyZW50Q2h1bmtPZmZzZXQgPSAwOwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAvLyBCdWZmZXIgaXMgZW1wdHkuIENoZWNrIGZvciBlbmQgY29uZGl0aW9ucy4KICAgICAgICAgIGNvbnN0IGlzVGltZWRPdXQgPSB0aGlzLl9zaWxlbmNlRnJhbWVzQ291bnQgPiB0aGlzLl9zaWxlbmNlVGhyZXNob2xkQmxvY2tzOwoKICAgICAgICAgIGlmICh0aGlzLl9ub01vcmVEYXRhUmVjZWl2ZWQgfHwgaXNUaW1lZE91dCkgewogICAgICAgICAgICAvLyBFTkQgT0YgUExBWUJBQ0s6IEVpdGhlciBleHBsaWNpdGx5IHNpZ25hbGVkIG9yIHRpbWVkIG91dC4KICAgICAgICAgICAgaWYgKCF0aGlzLl9oYXNTZW50RW5kZWQpIHsKICAgICAgICAgICAgICB0aGlzLnBvcnQucG9zdE1lc3NhZ2UoeyB0eXBlOiAicGxheWJhY2stZW5kZWQiIH0pOwogICAgICAgICAgICAgIHRoaXMuX2hhc1NlbnRFbmRlZCA9IHRydWU7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgLy8gU2VuZCBmaW5hbCBtZXRyaWNzIHNob3dpbmcgY2xlYXJlZCBzdGF0ZQogICAgICAgICAgICBpZiAodGhpcy5fbWV0cmljc0VuYWJsZWQpIHsKICAgICAgICAgICAgICB0cnkgewogICAgICAgICAgICAgICAgdGhpcy5wb3J0LnBvc3RNZXNzYWdlKHsKICAgICAgICAgICAgICAgICAgdHlwZTogIm1ldHJpY3MiLAogICAgICAgICAgICAgICAgICBkYXRhOiB7CiAgICAgICAgICAgICAgICAgICAgc3RhdGU6IFBsYXliYWNrV29ya2xldC5GU00uSURMRSwKICAgICAgICAgICAgICAgICAgICBxdWV1ZWRTYW1wbGVzOiAwLAogICAgICAgICAgICAgICAgICAgIHF1ZXVlZE1zOiAwLAogICAgICAgICAgICAgICAgICAgIG1heFF1ZXVlZE1zOiBNYXRoLnJvdW5kKCh0aGlzLl9tYXhRdWV1ZVNhbXBsZXMgLyB0aGlzLl9zYW1wbGVSYXRlKSAqIDEwMDApLAogICAgICAgICAgICAgICAgICAgIHVuZGVycnVuQmxvY2tzOiB0aGlzLl91bmRlcnJ1bkJsb2NrcywKICAgICAgICAgICAgICAgICAgICBmcmFtZXNQcm9jZXNzZWQ6IHRoaXMuX2ZyYW1lc1Byb2Nlc3NlZAogICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICB9KTsKICAgICAgICAgICAgICB9IGNhdGNoIChfKSB7IH0KICAgICAgICAgICAgfQogICAgICAgICAgICB0aGlzLnJlc2V0KCk7IC8vIFJlc2V0IHRvIElETEUgc3RhdGUgZm9yIHJldXNlCiAgICAgICAgICAgIGJyZWFrOyAvLyBFeGl0IHdoaWxlIGxvb3AKICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgIC8vIEJVRkZFUiBVTkRFUlJVTiAoTEFHKTogUGxheSBzaWxlbmNlIGFuZCB3YWl0IGZvciBtb3JlIGRhdGEuCiAgICAgICAgICAgIHRoaXMuX3NpbGVuY2VGcmFtZXNDb3VudCsrOwogICAgICAgICAgICBpZiAodGhpcy5fbWV0cmljc0VuYWJsZWQpIHRoaXMuX3VuZGVycnVuQmxvY2tzKys7CiAgICAgICAgICAgIGJyZWFrOyAvLyBFeGl0IHdoaWxlIGxvb3AKICAgICAgICAgIH0KICAgICAgICB9CiAgICAgIH0KCiAgICAgIC8vIElmIHdlIGhhdmUgYSBjaHVuayAoY291bGQgYmUgYSBuZXcgb25lIGZyb20gdGhlIGxvZ2ljIGFib3ZlKSwgcHJvY2VzcyBpdC4KICAgICAgaWYgKHRoaXMuX2N1cnJlbnRDaHVuaykgewogICAgICAgIGNvbnN0IHNhbXBsZXNUb0NvcHkgPSBNYXRoLm1pbigKICAgICAgICAgIGJsb2NrU2l6ZSAtIHNhbXBsZXNDb3BpZWQsCiAgICAgICAgICB0aGlzLl9jdXJyZW50Q2h1bmsubGVuZ3RoIC0gdGhpcy5fY3VycmVudENodW5rT2Zmc2V0CiAgICAgICAgKTsKICAgICAgICAvLyBEaXJlY3RseSB3cml0ZSB0byBvdXRwdXRDaGFubmVsIHRvIGF2b2lkIGV4dHJhIGNvcHkKICAgICAgICBjb25zdCBzcmMgPSB0aGlzLl9jdXJyZW50Q2h1bms7CiAgICAgICAgY29uc3QgYmFzZVNyYyA9IHRoaXMuX2N1cnJlbnRDaHVua09mZnNldDsKICAgICAgICBjb25zdCBiYXNlRHN0ID0gc2FtcGxlc0NvcGllZDsKICAgICAgICBjb25zdCBzY2FsZSA9IHRoaXMuX3NjYWxlOwogICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgc2FtcGxlc1RvQ29weTsgaSsrKSB7CiAgICAgICAgICBvdXRwdXRDaGFubmVsW2Jhc2VEc3QgKyBpXSA9IHNyY1tiYXNlU3JjICsgaV0gKiBzY2FsZTsKICAgICAgICB9CgogICAgICAgIHRoaXMuX2N1cnJlbnRDaHVua09mZnNldCArPSBzYW1wbGVzVG9Db3B5OwogICAgICAgIHNhbXBsZXNDb3BpZWQgKz0gc2FtcGxlc1RvQ29weTsKICAgICAgfQogICAgfQoKICAgIC8vIFplcm8tZmlsbCB0aGUgcmVtYWluZGVyLCBpZiBhbnksIG9uY2UgcGVyIGJsb2NrCiAgICBpZiAoc2FtcGxlc0NvcGllZCA8IGJsb2NrU2l6ZSkgewogICAgICBvdXRwdXRDaGFubmVsLmZpbGwoMCwgc2FtcGxlc0NvcGllZCk7CiAgICB9CgogICAgLy8gVXBkYXRlIG1ldHJpY3MgKG9wdGlvbmFsKQogICAgaWYgKHRoaXMuX21ldHJpY3NFbmFibGVkKSB7CiAgICAgIHRoaXMuX2ZyYW1lc1Byb2Nlc3NlZCArPSBibG9ja1NpemU7CgogICAgICAvLyBUcmFjayBxdWV1ZSBkZXB0aCBpbiBzYW1wbGVzIChhcHByb3hpbWF0ZSkKICAgICAgbGV0IHF1ZXVlZFNhbXBsZXMgPSAwOwogICAgICBpZiAodGhpcy5fY3VycmVudENodW5rKSBxdWV1ZWRTYW1wbGVzICs9IE1hdGgubWF4KDAsIHRoaXMuX2N1cnJlbnRDaHVuay5sZW5ndGggLSB0aGlzLl9jdXJyZW50Q2h1bmtPZmZzZXQpOwogICAgICBmb3IgKGxldCBpID0gMDsgaSA8IHRoaXMuX2J1ZmZlclF1ZXVlLmxlbmd0aDsgaSsrKSBxdWV1ZWRTYW1wbGVzICs9IHRoaXMuX2J1ZmZlclF1ZXVlW2ldLmxlbmd0aDsKICAgICAgaWYgKHF1ZXVlZFNhbXBsZXMgPiB0aGlzLl9tYXhRdWV1ZVNhbXBsZXMpIHRoaXMuX21heFF1ZXVlU2FtcGxlcyA9IHF1ZXVlZFNhbXBsZXM7CgogICAgICAvLyBQZXJpb2RpY2FsbHkgc2VuZCBtZXRyaWNzIHRvIG1haW4gdGhyZWFkCiAgICAgIGlmICh0aGlzLl9mcmFtZXNQcm9jZXNzZWQgLSB0aGlzLl9sYXN0TWV0cmljc1NlbnRBdEZyYW1lID49IHRoaXMuX21ldHJpY3NJbnRlcnZhbEZyYW1lcykgewogICAgICAgIHRoaXMuX2xhc3RNZXRyaWNzU2VudEF0RnJhbWUgPSB0aGlzLl9mcmFtZXNQcm9jZXNzZWQ7CiAgICAgICAgdHJ5IHsKICAgICAgICAgIHRoaXMucG9ydC5wb3N0TWVzc2FnZSh7CiAgICAgICAgICAgIHR5cGU6ICJtZXRyaWNzIiwKICAgICAgICAgICAgZGF0YTogewogICAgICAgICAgICAgIHN0YXRlOiB0aGlzLl9zdGF0ZSwKICAgICAgICAgICAgICBxdWV1ZWRTYW1wbGVzLAogICAgICAgICAgICAgIHF1ZXVlZE1zOiBNYXRoLnJvdW5kKChxdWV1ZWRTYW1wbGVzIC8gdGhpcy5fc2FtcGxlUmF0ZSkgKiAxMDAwKSwKICAgICAgICAgICAgICBtYXhRdWV1ZWRNczogTWF0aC5yb3VuZCgodGhpcy5fbWF4UXVldWVTYW1wbGVzIC8gdGhpcy5fc2FtcGxlUmF0ZSkgKiAxMDAwKSwKICAgICAgICAgICAgICB1bmRlcnJ1bkJsb2NrczogdGhpcy5fdW5kZXJydW5CbG9ja3MsCiAgICAgICAgICAgICAgZnJhbWVzUHJvY2Vzc2VkOiB0aGlzLl9mcmFtZXNQcm9jZXNzZWQKICAgICAgICAgICAgfQogICAgICAgICAgfSk7CiAgICAgICAgfSBjYXRjaCAoXykgeyB9CiAgICAgICAgLy8gRG9uJ3QgcmVzZXQgbWF4IHRyYWNrZXIgLSBrZWVwIHNlc3Npb24gcGVhayB1bnRpbCBpZGxlCiAgICAgIH0KICAgIH0KCiAgICAvLyBBTFdBWVMgcmV0dXJuIHRydWUgdG8ga2VlcCB0aGUgcHJvY2Vzc29yIGFsaXZlIGZvciByZXVzZS4KICAgIHJldHVybiB0cnVlOwogIH0KfQoKcmVnaXN0ZXJQcm9jZXNzb3IoInBsYXliYWNrLXdvcmtsZXQiLCBQbGF5YmFja1dvcmtsZXQpOwo=", import.meta.url), Ue = {
|
|
2627
2627
|
en: it,
|
|
2628
2628
|
de: st,
|
|
2629
2629
|
fr: rt,
|
|
2630
|
-
fi:
|
|
2630
|
+
fi: ut,
|
|
2631
2631
|
lt: ct
|
|
2632
|
-
},
|
|
2632
|
+
}, Q = new f.Quaternion(), G = 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();
|
|
@@ -2637,7 +2637,7 @@ new f.Vector3(0, 0, 1);
|
|
|
2637
2637
|
const mt = new f.Vector3(1, 0, 0);
|
|
2638
2638
|
new f.Vector3(0, 1, 0);
|
|
2639
2639
|
new f.Vector3(0, 0, 1);
|
|
2640
|
-
class
|
|
2640
|
+
class Be {
|
|
2641
2641
|
/**
|
|
2642
2642
|
* Avatar.
|
|
2643
2643
|
* @typedef {Object} Avatar
|
|
@@ -2763,7 +2763,7 @@ class Ne {
|
|
|
2763
2763
|
avatarOnlyCamera: null,
|
|
2764
2764
|
statsNode: null,
|
|
2765
2765
|
statsStyle: null
|
|
2766
|
-
}, Object.assign(this.opt, e || {}), this.opt.statsNode && (this.stats = new
|
|
2766
|
+
}, Object.assign(this.opt, e || {}), this.opt.statsNode && (this.stats = new Ke(), this.opt.statsStyle && (this.stats.dom.style.cssText = this.opt.statsStyle), this.opt.statsNode.appendChild(this.stats.dom)), this.poseTemplates = {
|
|
2767
2767
|
side: {
|
|
2768
2768
|
standing: !0,
|
|
2769
2769
|
props: {
|
|
@@ -3569,15 +3569,15 @@ class Ne {
|
|
|
3569
3569
|
"RightArm.scale": { x: 0, y: 0, z: 0 }
|
|
3570
3570
|
}
|
|
3571
3571
|
}, ["Left", "Right"].forEach((l) => {
|
|
3572
|
-
["Leg", "UpLeg", "Arm", "ForeArm", "Hand"].forEach((
|
|
3573
|
-
this.poseDelta.props[l +
|
|
3574
|
-
}), ["HandThumb", "HandIndex", "HandMiddle", "HandRing", "HandPinky"].forEach((
|
|
3575
|
-
this.poseDelta.props[l +
|
|
3572
|
+
["Leg", "UpLeg", "Arm", "ForeArm", "Hand"].forEach((h) => {
|
|
3573
|
+
this.poseDelta.props[l + h + ".quaternion"] = { x: 0, y: 0, z: 0 };
|
|
3574
|
+
}), ["HandThumb", "HandIndex", "HandMiddle", "HandRing", "HandPinky"].forEach((h) => {
|
|
3575
|
+
this.poseDelta.props[l + h + "1.quaternion"] = { x: 0, y: 0, z: 0 }, this.poseDelta.props[l + h + "2.quaternion"] = { x: 0, y: 0, z: 0 }, this.poseDelta.props[l + h + "3.quaternion"] = { x: 0, y: 0, z: 0 };
|
|
3576
3576
|
});
|
|
3577
3577
|
});
|
|
3578
3578
|
const n = /* @__PURE__ */ new Set();
|
|
3579
3579
|
Object.values(this.poseTemplates).forEach((l) => {
|
|
3580
|
-
Object.keys(this.propsToThreeObjects(l.props)).forEach((
|
|
3580
|
+
Object.keys(this.propsToThreeObjects(l.props)).forEach((h) => n.add(h));
|
|
3581
3581
|
}), Object.keys(this.poseDelta.props).forEach((l) => {
|
|
3582
3582
|
n.add(l);
|
|
3583
3583
|
}), this.posePropNames = [...n], this.poseName = "side", this.poseWeightOnLeft = !0, this.gesture = null, this.poseCurrentTemplate = this.poseTemplates[this.poseName], this.poseStraight = this.propsToThreeObjects(this.poseTemplates.straight.props), this.poseBase = this.poseFactory(this.poseCurrentTemplate), this.poseTarget = this.poseFactory(this.poseCurrentTemplate), this.poseAvatar = null, this.avatarHeight = 1.7, this.animTemplateEyes = {
|
|
@@ -4086,7 +4086,7 @@ class Ne {
|
|
|
4086
4086
|
this.opt.lightSpotDispersion
|
|
4087
4087
|
), this.setLighting(this.opt);
|
|
4088
4088
|
const l = new f.PMREMGenerator(this.renderer);
|
|
4089
|
-
l.compileEquirectangularShader(), this.scene.environment = l.fromScene(new
|
|
4089
|
+
l.compileEquirectangularShader(), this.scene.environment = l.fromScene(new qe()).texture, this.resizeobserver = new ResizeObserver(this.onResize.bind(this)), this.resizeobserver.observe(this.nodeAvatar), this.controls = new Ye(this.camera, this.renderer.domElement), this.controls.enableZoom = this.opt.cameraZoomEnable, this.controls.enableRotate = this.opt.cameraRotateEnable, this.controls.enablePan = this.opt.cameraPanEnable, this.controls.minDistance = 2, this.controls.maxDistance = 2e3, this.controls.autoRotateSpeed = 0, this.controls.autoRotate = !1, this.controls.update(), this.cameraClock = null;
|
|
4090
4090
|
}
|
|
4091
4091
|
this.ikMesh = new f.SkinnedMesh();
|
|
4092
4092
|
const s = {
|
|
@@ -4101,7 +4101,7 @@ class Ne {
|
|
|
4101
4101
|
RightHand: "RightForeArm",
|
|
4102
4102
|
RightHandMiddle1: "RightHand"
|
|
4103
4103
|
}, o = [];
|
|
4104
|
-
Object.entries(s).forEach((l,
|
|
4104
|
+
Object.entries(s).forEach((l, h) => {
|
|
4105
4105
|
const r = new f.Bone();
|
|
4106
4106
|
r.name = l[0], l[1] ? this.ikMesh.getObjectByName(l[1]).add(r) : this.ikMesh.add(r), o.push(r);
|
|
4107
4107
|
}), this.ikMesh.bind(new f.Skeleton(o)), this.dynamicbones = new et(), this.isStreaming = !1, this.streamWorkletNode = null, this.streamAudioStartTime = null, this.streamWaitForAudioChunks = !0, this.streamLipsyncLang = null, this.streamLipsyncType = "visemes", this.streamLipsyncQueue = [];
|
|
@@ -4150,9 +4150,9 @@ class Ne {
|
|
|
4150
4150
|
let e = 3 * t.length / 4;
|
|
4151
4151
|
t[t.length - 1] === "=" && (e--, t[t.length - 2] === "=" && e--);
|
|
4152
4152
|
const n = new ArrayBuffer(e), i = new Uint8Array(n);
|
|
4153
|
-
let s, o = 0, l,
|
|
4153
|
+
let s, o = 0, l, h, r, u;
|
|
4154
4154
|
for (s = 0; s < t.length; s += 4)
|
|
4155
|
-
l = this.b64Lookup[t.charCodeAt(s)],
|
|
4155
|
+
l = this.b64Lookup[t.charCodeAt(s)], h = this.b64Lookup[t.charCodeAt(s + 1)], r = this.b64Lookup[t.charCodeAt(s + 2)], u = this.b64Lookup[t.charCodeAt(s + 3)], i[o++] = l << 2 | h >> 4, i[o++] = (h & 15) << 4 | r >> 2, i[o++] = (r & 3) << 6 | u & 63;
|
|
4156
4156
|
return n;
|
|
4157
4157
|
}
|
|
4158
4158
|
/**
|
|
@@ -4193,8 +4193,8 @@ class Ne {
|
|
|
4193
4193
|
const e = {};
|
|
4194
4194
|
for (let [n, i] of Object.entries(t)) {
|
|
4195
4195
|
const s = n.split(".");
|
|
4196
|
-
let o = Array.isArray(i.x) ? this.gaussianRandom(...i.x) : i.x, l = Array.isArray(i.y) ? this.gaussianRandom(...i.y) : i.y,
|
|
4197
|
-
s[1] === "position" || s[1] === "scale" ? e[n] = new f.Vector3(o, l,
|
|
4196
|
+
let o = Array.isArray(i.x) ? this.gaussianRandom(...i.x) : i.x, l = Array.isArray(i.y) ? this.gaussianRandom(...i.y) : i.y, h = Array.isArray(i.z) ? this.gaussianRandom(...i.z) : i.z;
|
|
4197
|
+
s[1] === "position" || s[1] === "scale" ? e[n] = new f.Vector3(o, l, h) : s[1] === "rotation" ? (n = s[0] + ".quaternion", e[n] = new f.Quaternion().setFromEuler(new f.Euler(o, l, h, "XYZ")).normalize()) : s[1] === "quaternion" && (e[n] = new f.Quaternion(o, l, h, i.w).normalize());
|
|
4198
4198
|
}
|
|
4199
4199
|
return e;
|
|
4200
4200
|
}
|
|
@@ -4222,23 +4222,23 @@ class Ne {
|
|
|
4222
4222
|
t.forEach((s) => {
|
|
4223
4223
|
if (!i && s.morphTargetDictionary.hasOwnProperty(e)) return;
|
|
4224
4224
|
const o = s.geometry;
|
|
4225
|
-
let l = null,
|
|
4226
|
-
for (const [r,
|
|
4225
|
+
let l = null, h = null;
|
|
4226
|
+
for (const [r, u] of Object.entries(n))
|
|
4227
4227
|
if (s.morphTargetDictionary.hasOwnProperty(r)) {
|
|
4228
4228
|
const a = s.morphTargetDictionary[r], c = o.morphAttributes.position[a], d = o.morphAttributes.normal?.[a];
|
|
4229
|
-
l || (l = new f.Float32BufferAttribute(c.count * 3, 3), d && (
|
|
4229
|
+
l || (l = new f.Float32BufferAttribute(c.count * 3, 3), d && (h = new f.Float32BufferAttribute(c.count * 3, 3)));
|
|
4230
4230
|
for (let g = 0; g < c.count; g++) {
|
|
4231
|
-
const
|
|
4232
|
-
l.setXYZ(g,
|
|
4231
|
+
const b = l.getX(g) + c.getX(g) * u, x = l.getY(g) + c.getY(g) * u, A = l.getZ(g) + c.getZ(g) * u;
|
|
4232
|
+
l.setXYZ(g, b, x, A);
|
|
4233
4233
|
}
|
|
4234
4234
|
if (d)
|
|
4235
4235
|
for (let g = 0; g < c.count; g++) {
|
|
4236
|
-
const
|
|
4237
|
-
|
|
4236
|
+
const b = h.getX(g) + d.getX(g) * u, x = h.getY(g) + d.getY(g) * u, A = h.getZ(g) + d.getZ(g) * u;
|
|
4237
|
+
h.setXYZ(g, b, x, A);
|
|
4238
4238
|
}
|
|
4239
4239
|
}
|
|
4240
4240
|
if (l) {
|
|
4241
|
-
o.morphAttributes.position.push(l),
|
|
4241
|
+
o.morphAttributes.position.push(l), h && o.morphAttributes.normal.push(h);
|
|
4242
4242
|
const r = o.morphAttributes.position.length - 1;
|
|
4243
4243
|
s.morphTargetInfluences[r] = 0, s.morphTargetDictionary[e] = r;
|
|
4244
4244
|
}
|
|
@@ -4268,7 +4268,7 @@ class Ne {
|
|
|
4268
4268
|
throw new Error("Blend shapes not found");
|
|
4269
4269
|
const o = new Set(this.mtCustoms);
|
|
4270
4270
|
this.morphs.forEach((r) => {
|
|
4271
|
-
Object.keys(r.morphTargetDictionary).forEach((
|
|
4271
|
+
Object.keys(r.morphTargetDictionary).forEach((u) => o.add(u));
|
|
4272
4272
|
}), this.mtExtras.forEach((r) => {
|
|
4273
4273
|
o.has(r.key) || (this.addMixedMorphTarget(this.morphs, r.key, r.mix), o.add(r.key));
|
|
4274
4274
|
});
|
|
@@ -4295,16 +4295,16 @@ class Ne {
|
|
|
4295
4295
|
ms: [],
|
|
4296
4296
|
is: []
|
|
4297
4297
|
}, l[r].value = l[r].baseline, l[r].applied = l[r].baseline;
|
|
4298
|
-
const
|
|
4299
|
-
|
|
4300
|
-
l[r][a] =
|
|
4298
|
+
const u = this.mtAvatar[r];
|
|
4299
|
+
u && ["fixed", "system", "systemd", "realtime", "base", "v", "value", "applied"].forEach((a) => {
|
|
4300
|
+
l[r][a] = u[a];
|
|
4301
4301
|
}), this.morphs.forEach((a) => {
|
|
4302
4302
|
const c = a.morphTargetDictionary[r];
|
|
4303
4303
|
c !== void 0 && (l[r].ms.push(a.morphTargetInfluences), l[r].is.push(c), a.morphTargetInfluences[c] = l[r].applied);
|
|
4304
4304
|
});
|
|
4305
4305
|
}), this.mtAvatar = l, this.poseAvatar = { props: {} }, this.posePropNames.forEach((r) => {
|
|
4306
|
-
const
|
|
4307
|
-
this.poseAvatar.props[r] = a[
|
|
4306
|
+
const u = r.split("."), a = this.armature.getObjectByName(u[0]);
|
|
4307
|
+
this.poseAvatar.props[r] = a[u[1]], this.poseBase.props.hasOwnProperty(r) ? this.poseAvatar.props[r].copy(this.poseBase.props[r]) : this.poseBase.props[r] = this.poseAvatar.props[r].clone(), this.poseDelta.props.hasOwnProperty(r) && !this.poseTarget.props.hasOwnProperty(r) && (this.poseTarget.props[r] = this.poseAvatar.props[r].clone()), this.poseTarget.props[r].t = this.animClock, this.poseTarget.props[r].d = 2e3;
|
|
4308
4308
|
}), this.ikMesh.traverse((r) => {
|
|
4309
4309
|
r.isBone && r.position.copy(this.armature.getObjectByName(r.name).position);
|
|
4310
4310
|
}), this.isAvatarOnly ? this.scene && this.scene.add(this.armature) : (this.scene.add(i.scene), this.scene.add(this.lightAmbient), this.scene.add(this.lightDirect), this.scene.add(this.lightSpot), this.lightSpot.target = this.armature.getObjectByName("Head")), t.hasOwnProperty("modelDynamicBones"))
|
|
@@ -4314,8 +4314,8 @@ class Ne {
|
|
|
4314
4314
|
console.error("Dynamic bones setup failed: " + r);
|
|
4315
4315
|
}
|
|
4316
4316
|
this.objectLeftToeBase = this.armature.getObjectByName("LeftToeBase"), this.objectRightToeBase = this.armature.getObjectByName("RightToeBase"), this.objectLeftEye = this.armature.getObjectByName("LeftEye"), this.objectRightEye = this.armature.getObjectByName("RightEye"), this.objectLeftArm = this.armature.getObjectByName("LeftArm"), this.objectRightArm = this.armature.getObjectByName("RightArm"), this.objectHips = this.armature.getObjectByName("Hips"), this.objectHead = this.armature.getObjectByName("Head"), this.objectNeck = this.armature.getObjectByName("Neck");
|
|
4317
|
-
const
|
|
4318
|
-
this.objectLeftEye.getWorldPosition(
|
|
4317
|
+
const h = new f.Vector3();
|
|
4318
|
+
this.objectLeftEye.getWorldPosition(h), this.avatarHeight = h.y + 0.2, this.viewName || this.setView(this.opt.cameraView), this.setMood(this.avatar.avatarMood || this.moodName || this.opt.avatarMood), this.avatar.body === "M" && this.poseTemplates.wide && (this.poseName = "wide", this.setPoseFromTemplate(this.poseTemplates.wide, 0), console.log("Set initial male-appropriate pose: wide")), this.initializeFBXAnimationLoader(), this.bodyMovement && this.bodyMovement !== "idle" && this.applyBodyMovementAnimation(), this.start();
|
|
4319
4319
|
}
|
|
4320
4320
|
/**
|
|
4321
4321
|
* Get view names.
|
|
@@ -4343,22 +4343,22 @@ class Ne {
|
|
|
4343
4343
|
return;
|
|
4344
4344
|
}
|
|
4345
4345
|
if (this.viewName = t || this.viewName, e = e || {}, this.isAvatarOnly) return;
|
|
4346
|
-
const n = e.hasOwnProperty("cameraX") ? e.cameraX : this.opt.cameraX, i = e.hasOwnProperty("cameraY") ? e.cameraY : this.opt.cameraY, s = e.hasOwnProperty("cameraDistance") ? e.cameraDistance : this.opt.cameraDistance, o = e.hasOwnProperty("cameraRotateX") ? e.cameraRotateX : this.opt.cameraRotateX, l = e.hasOwnProperty("cameraRotateY") ? e.cameraRotateY : this.opt.cameraRotateY,
|
|
4347
|
-
let r = -n * Math.tan(
|
|
4346
|
+
const n = e.hasOwnProperty("cameraX") ? e.cameraX : this.opt.cameraX, i = e.hasOwnProperty("cameraY") ? e.cameraY : this.opt.cameraY, s = e.hasOwnProperty("cameraDistance") ? e.cameraDistance : this.opt.cameraDistance, o = e.hasOwnProperty("cameraRotateX") ? e.cameraRotateX : this.opt.cameraRotateX, l = e.hasOwnProperty("cameraRotateY") ? e.cameraRotateY : this.opt.cameraRotateY, h = this.camera.fov * (Math.PI / 180);
|
|
4347
|
+
let r = -n * Math.tan(h / 2), u = (1 - i) * Math.tan(h / 2), a = s;
|
|
4348
4348
|
switch (this.viewName) {
|
|
4349
4349
|
case "head":
|
|
4350
|
-
a += 2,
|
|
4350
|
+
a += 2, u = u * a + 4 * this.avatarHeight / 5;
|
|
4351
4351
|
break;
|
|
4352
4352
|
case "upper":
|
|
4353
|
-
a += 4.5,
|
|
4353
|
+
a += 4.5, u = u * a + 2 * this.avatarHeight / 3;
|
|
4354
4354
|
break;
|
|
4355
4355
|
case "mid":
|
|
4356
|
-
a += 8,
|
|
4356
|
+
a += 8, u = u * a + this.avatarHeight / 3;
|
|
4357
4357
|
break;
|
|
4358
4358
|
default:
|
|
4359
|
-
a += 12,
|
|
4359
|
+
a += 12, u = u * a;
|
|
4360
4360
|
}
|
|
4361
|
-
r = r * a, this.controlsEnd = new f.Vector3(r,
|
|
4361
|
+
r = r * a, this.controlsEnd = new f.Vector3(r, u, 0), this.cameraEnd = new f.Vector3(r, u, a).applyEuler(new f.Euler(o, l, 0)), this.cameraClock === null && (this.controls.target.copy(this.controlsEnd), this.camera.position.copy(this.cameraEnd)), this.controlsStart = this.controls.target.clone(), this.cameraStart = this.camera.position.clone(), this.cameraClock = 0;
|
|
4362
4362
|
}
|
|
4363
4363
|
/**
|
|
4364
4364
|
* Change light colors and intensities.
|
|
@@ -4398,9 +4398,9 @@ class Ne {
|
|
|
4398
4398
|
updatePoseDelta() {
|
|
4399
4399
|
for (const [t, e] of Object.entries(this.poseDelta.props)) {
|
|
4400
4400
|
if (e.x === 0 && e.y === 0 && e.z === 0) continue;
|
|
4401
|
-
|
|
4401
|
+
G.set(e.x, e.y, e.z);
|
|
4402
4402
|
const n = this.poseAvatar.props[t];
|
|
4403
|
-
n.isQuaternion ? (
|
|
4403
|
+
n.isQuaternion ? (Q.setFromEuler(G), n.multiply(Q)) : n.isVector3 && n.add(G);
|
|
4404
4404
|
}
|
|
4405
4405
|
}
|
|
4406
4406
|
/**
|
|
@@ -4455,17 +4455,17 @@ class Ne {
|
|
|
4455
4455
|
"HandMiddle",
|
|
4456
4456
|
"HandRing",
|
|
4457
4457
|
"HandPinky"
|
|
4458
|
-
].forEach((
|
|
4459
|
-
a === 0 ? (this.poseDelta.props[o +
|
|
4458
|
+
].forEach((u, a) => {
|
|
4459
|
+
a === 0 ? (this.poseDelta.props[o + u + "1.quaternion"].x = 0, this.poseDelta.props[o + u + "2.quaternion"].z = (o === "Left" ? -1 : 1) * n.applied, this.poseDelta.props[o + u + "3.quaternion"].z = (o === "Left" ? -1 : 1) * n.applied) : (this.poseDelta.props[o + u + "1.quaternion"].x = n.applied, this.poseDelta.props[o + u + "2.quaternion"].x = 1.5 * n.applied, this.poseDelta.props[o + u + "3.quaternion"].x = 1.5 * n.applied);
|
|
4460
4460
|
});
|
|
4461
4461
|
break;
|
|
4462
4462
|
case "chestInhale":
|
|
4463
|
-
const l = n.applied / 20,
|
|
4464
|
-
this.poseDelta.props["Spine1.scale"] =
|
|
4463
|
+
const l = n.applied / 20, h = { x: l, y: l / 2, z: 3 * l }, r = { x: 1 / (1 + l) - 1, y: 1 / (1 + l / 2) - 1, z: 1 / (1 + 3 * l) - 1 };
|
|
4464
|
+
this.poseDelta.props["Spine1.scale"] = h, this.poseDelta.props["Neck.scale"] = r, this.poseDelta.props["LeftArm.scale"] = r, this.poseDelta.props["RightArm.scale"] = r;
|
|
4465
4465
|
break;
|
|
4466
4466
|
default:
|
|
4467
|
-
for (let
|
|
4468
|
-
n.ms[
|
|
4467
|
+
for (let u = 0, a = n.ms.length; u < a; u++)
|
|
4468
|
+
n.ms[u][n.is[u]] = n.applied;
|
|
4469
4469
|
}
|
|
4470
4470
|
}
|
|
4471
4471
|
}
|
|
@@ -4480,8 +4480,8 @@ class Ne {
|
|
|
4480
4480
|
return Object.entries(t).forEach((i, s) => {
|
|
4481
4481
|
const o = i[0].split(".");
|
|
4482
4482
|
if (o[1] === "position" || o[1] === "rotation" || o[1] === "quaternion") {
|
|
4483
|
-
const l = o[1] === "quaternion" ? o[0] + ".rotation" : i[0],
|
|
4484
|
-
n += (s ? ", " : "") + "'" + l + "':{", n += "x:" + Math.round(
|
|
4483
|
+
const l = o[1] === "quaternion" ? o[0] + ".rotation" : i[0], h = i[1].isQuaternion ? new f.Euler().setFromQuaternion(i[1]) : i[1];
|
|
4484
|
+
n += (s ? ", " : "") + "'" + l + "':{", n += "x:" + Math.round(h.x * e) / e, n += ", y:" + Math.round(h.y * e) / e, n += ", z:" + Math.round(h.z * e) / e, n += "}";
|
|
4485
4485
|
}
|
|
4486
4486
|
}), n += "}", n;
|
|
4487
4487
|
}
|
|
@@ -4551,8 +4551,8 @@ class Ne {
|
|
|
4551
4551
|
if (n ? (this.poseCurrentTemplate = this.poseTemplates.oneknee, setTimeout(() => {
|
|
4552
4552
|
this.setPoseFromTemplate(t, e);
|
|
4553
4553
|
}, o)) : this.poseCurrentTemplate = t || this.poseCurrentTemplate, this.poseTarget = this.poseFactory(this.poseCurrentTemplate, o), this.poseWeightOnLeft = !0, (!i && !s || i && s) && (this.poseTarget.props = this.mirrorPose(this.poseTarget.props), this.poseWeightOnLeft = !this.poseWeightOnLeft), this.gesture)
|
|
4554
|
-
for (let [l,
|
|
4555
|
-
this.poseTarget.props.hasOwnProperty(l) && (this.poseTarget.props[l].copy(
|
|
4554
|
+
for (let [l, h] of Object.entries(this.gesture))
|
|
4555
|
+
this.poseTarget.props.hasOwnProperty(l) && (this.poseTarget.props[l].copy(h), this.poseTarget.props[l].t = h.t, this.poseTarget.props[l].d = h.d);
|
|
4556
4556
|
Object.keys(this.poseDelta.props).forEach((l) => {
|
|
4557
4557
|
this.poseTarget.props.hasOwnProperty(l) || (this.poseTarget.props[l] = this.poseBase.props[l].clone(), this.poseTarget.props[l].t = this.animClock, this.poseTarget.props[l].d = o);
|
|
4558
4558
|
});
|
|
@@ -4985,11 +4985,11 @@ class Ne {
|
|
|
4985
4985
|
else if (l.hasOwnProperty("alt")) {
|
|
4986
4986
|
let r = l.alt[0];
|
|
4987
4987
|
if (l.alt.length > 1) {
|
|
4988
|
-
const
|
|
4988
|
+
const u = Math.random();
|
|
4989
4989
|
let a = 0;
|
|
4990
4990
|
for (let c = 0; c < l.alt.length; c++) {
|
|
4991
4991
|
let d = this.valueFn(l.alt[c].p);
|
|
4992
|
-
if (a += d === void 0 ? (1 - a) / (l.alt.length - 1 - c) : d,
|
|
4992
|
+
if (a += d === void 0 ? (1 - a) / (l.alt.length - 1 - c) : d, u < a) {
|
|
4993
4993
|
r = l.alt[c];
|
|
4994
4994
|
break;
|
|
4995
4995
|
}
|
|
@@ -4999,19 +4999,19 @@ class Ne {
|
|
|
4999
4999
|
continue;
|
|
5000
5000
|
} else
|
|
5001
5001
|
break;
|
|
5002
|
-
let
|
|
5003
|
-
if (Array.isArray(
|
|
5004
|
-
l.dt.forEach((r,
|
|
5002
|
+
let h = this.valueFn(l.delay) || 0;
|
|
5003
|
+
if (Array.isArray(h) && (h = this.gaussianRandom(...h)), l.hasOwnProperty("dt"))
|
|
5004
|
+
l.dt.forEach((r, u) => {
|
|
5005
5005
|
let a = this.valueFn(r);
|
|
5006
|
-
Array.isArray(a) && (a = this.gaussianRandom(...a)), o.ts[
|
|
5006
|
+
Array.isArray(a) && (a = this.gaussianRandom(...a)), o.ts[u + 1] = o.ts[u] + a;
|
|
5007
5007
|
});
|
|
5008
5008
|
else {
|
|
5009
|
-
let r = Object.values(l.vs).reduce((
|
|
5009
|
+
let r = Object.values(l.vs).reduce((u, a) => a.length > u ? a.length : u, 0);
|
|
5010
5010
|
o.ts = Array(r + 1).fill(0);
|
|
5011
5011
|
}
|
|
5012
|
-
s ? o.ts = o.ts.map((r) =>
|
|
5013
|
-
for (let [r,
|
|
5014
|
-
const a = this.getBaselineValue(r), c =
|
|
5012
|
+
s ? o.ts = o.ts.map((r) => h + r * n) : o.ts = o.ts.map((r) => this.animClock + h + r * n), l.vs && l.vs.pose && console.log("Pose being selected from vs.pose:", l.vs.pose, "for avatar body:", this.avatar?.body);
|
|
5013
|
+
for (let [r, u] of Object.entries(l.vs)) {
|
|
5014
|
+
const a = this.getBaselineValue(r), c = u.map((d) => (d = this.valueFn(d), d === null ? null : typeof d == "function" ? d : typeof d == "string" || d instanceof String ? r === "pose" && this.avatar && this.avatar.body === "M" && (d === "hip" || d === "side") ? (console.log("Intercepting pose", d, "in animation factory, overriding to wide for male avatar"), "wide") : d.slice() : Array.isArray(d) ? r === "gesture" ? d.slice() : (a === void 0 ? 0 : a) + i * this.gaussianRandom(...d) : typeof d == "boolean" ? d : d instanceof Object && d.constructor === Object ? Object.assign({}, d) : (a === void 0 ? 0 : a) + i * d));
|
|
5015
5015
|
r === "eyesRotateY" ? (o.vs.eyeLookOutLeft = [null, ...c.map((d) => d > 0 ? d : 0)], o.vs.eyeLookInLeft = [null, ...c.map((d) => d > 0 ? 0 : -d)], o.vs.eyeLookOutRight = [null, ...c.map((d) => d > 0 ? 0 : -d)], o.vs.eyeLookInRight = [null, ...c.map((d) => d > 0 ? d : 0)]) : r === "eyesRotateX" ? (o.vs.eyesLookDown = [null, ...c.map((d) => d > 0 ? d : 0)], o.vs.eyesLookUp = [null, ...c.map((d) => d > 0 ? 0 : -d)]) : o.vs[r] = [null, ...c];
|
|
5016
5016
|
}
|
|
5017
5017
|
for (let r of Object.keys(o.vs))
|
|
@@ -5093,8 +5093,8 @@ class Ne {
|
|
|
5093
5093
|
if (this.isSpeaking)
|
|
5094
5094
|
for (l = 0, this.audioAnalyzerNode.getByteFrequencyData(this.volumeFrequencyData), n = 2, s = 10; n < s; n++)
|
|
5095
5095
|
this.volumeFrequencyData[n] > l && (l = this.volumeFrequencyData[n]);
|
|
5096
|
-
let
|
|
5097
|
-
const
|
|
5096
|
+
let h = null, r = null;
|
|
5097
|
+
const u = [];
|
|
5098
5098
|
for (n = 0, s = this.animQueue.length; n < s; n++) {
|
|
5099
5099
|
const a = this.animQueue[n];
|
|
5100
5100
|
if (!(!a || !a.ts || !a.ts.length || this.animClock < a.ts[0])) {
|
|
@@ -5107,9 +5107,9 @@ class Ne {
|
|
|
5107
5107
|
g.newvalue = d[i];
|
|
5108
5108
|
else {
|
|
5109
5109
|
g.newvalue = d[i + 1];
|
|
5110
|
-
const
|
|
5111
|
-
let
|
|
5112
|
-
|
|
5110
|
+
const b = a.ts[i + 1] - a.ts[i];
|
|
5111
|
+
let x = 1;
|
|
5112
|
+
b > 1e-4 && (x = (this.animClock - a.ts[i]) / b), x < 1 && (g.easing && (x = g.easing(x)), g.newvalue = (1 - x) * d[i] + x * g.newvalue), g.ref && g.ref !== a.vs && g.ref.hasOwnProperty(c) && delete g.ref[c], g.ref = a.vs;
|
|
5113
5113
|
}
|
|
5114
5114
|
if (l)
|
|
5115
5115
|
switch (c) {
|
|
@@ -5121,12 +5121,12 @@ class Ne {
|
|
|
5121
5121
|
g.newvalue *= 1 + l / 255 - 0.5;
|
|
5122
5122
|
}
|
|
5123
5123
|
g.needsUpdate = !0;
|
|
5124
|
-
} else c === "eyeContact" && d[i] !== null &&
|
|
5124
|
+
} else c === "eyeContact" && d[i] !== null && h !== !1 ? h = !!d[i] : c === "headMove" && d[i] !== null && r !== !1 ? d[i] === 0 ? r = !1 : (Math.random() < d[i] && (r = !0), d[i] = null) : d[i] !== null && (u.push({ mt: c, val: d[i] }), d[i] = null);
|
|
5125
5125
|
i === o ? (a.hasOwnProperty("mood") && this.setMood(a.mood), a.loop ? (o = this.isSpeaking && (a.template.name === "head" || a.template.name === "eyes") ? 4 : 1, this.animQueue[n] = this.animFactory(a.template, a.loop > 0 ? a.loop - 1 : a.loop, 1, 1 / o)) : (this.animQueue.splice(n--, 1), s--)) : a.ndx = i - 1;
|
|
5126
5126
|
}
|
|
5127
5127
|
}
|
|
5128
|
-
for (let a = 0, c =
|
|
5129
|
-
switch (i =
|
|
5128
|
+
for (let a = 0, c = u.length; a < c; a++)
|
|
5129
|
+
switch (i = u[a].val, u[a].mt) {
|
|
5130
5130
|
case "speak":
|
|
5131
5131
|
this.speakText(i);
|
|
5132
5132
|
break;
|
|
@@ -5172,7 +5172,7 @@ class Ne {
|
|
|
5172
5172
|
}, i.x ? new f.Vector3(i.x, i.y, i.z) : null, !0, i.d);
|
|
5173
5173
|
break;
|
|
5174
5174
|
}
|
|
5175
|
-
if ((
|
|
5175
|
+
if ((h || r) && (G.setFromQuaternion(this.poseAvatar.props["Head.quaternion"]), G.x = Math.max(-0.9, Math.min(0.9, 2 * G.x - 0.5)), G.y = Math.max(-0.9, Math.min(0.9, -2.5 * G.y)), h ? (Object.assign(this.mtAvatar.eyesLookDown, { system: G.x < 0 ? -G.x : 0, needsUpdate: !0 }), Object.assign(this.mtAvatar.eyesLookUp, { system: G.x < 0 ? 0 : G.x, needsUpdate: !0 }), Object.assign(this.mtAvatar.eyeLookInLeft, { system: G.y < 0 ? -G.y : 0, needsUpdate: !0 }), Object.assign(this.mtAvatar.eyeLookOutLeft, { system: G.y < 0 ? 0 : G.y, needsUpdate: !0 }), Object.assign(this.mtAvatar.eyeLookInRight, { system: G.y < 0 ? 0 : G.y, needsUpdate: !0 }), Object.assign(this.mtAvatar.eyeLookOutRight, { system: G.y < 0 ? -G.y : 0, needsUpdate: !0 }), r && (n = -this.mtAvatar.bodyRotateY.value, i = this.gaussianRandom(-0.2, 0.2), this.animQueue.push(this.animFactory({
|
|
5176
5176
|
name: "headmove",
|
|
5177
5177
|
dt: [[1e3, 2e3], [1e3, 2e3, 1, 2], [1e3, 2e3], [1e3, 2e3, 1, 2]],
|
|
5178
5178
|
vs: {
|
|
@@ -5193,7 +5193,7 @@ class Ne {
|
|
|
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) &&
|
|
5196
|
+
})))), e > 2 * this.animFrameDur && (e = 2 * this.animFrameDur), (this.viewName !== "full" || this.isAvatarOnly) && (n = this.mtRandomized[Math.floor(Math.random() * this.mtRandomized.length)], i = this.mtAvatar[n], i.needsUpdate || Object.assign(i, { base: (this.mood.baseline[n] || 0) + (1 + l / 255) * Math.random() / 5, needsUpdate: !0 })), this.updatePoseBase(this.animClock), this.mixer && this.mixer.update(e / 1e3 * this.mixer.timeScale), this.updatePoseDelta(), (this.isSpeaking || this.isListening) && h ? l > this.volumeMax ? (this.volumeHeadBase = 0.05, Math.random() > 0.6 && (this.volumeHeadTarget = -0.05 - Math.random() / 15), this.volumeMax = l) : (this.volumeMax *= 0.92, this.volumeHeadTarget = this.volumeHeadBase - 0.9 * (this.volumeHeadBase - this.volumeHeadTarget)) : (this.volumeHeadTarget = 0, this.volumeMax = 0), n = this.volumeHeadTarget - this.volumeHeadCurrent, i = Math.abs(n), i > 1e-4 && (o = i * (this.volumeHeadEasing(Math.min(1, this.volumeHeadVelocity * e / 1e3 / i) / 2 + 0.5) - 0.5), this.volumeHeadCurrent += Math.sign(n) * Math.min(i, o)), Math.abs(this.volumeHeadCurrent) > 1e-4 && (Q.setFromAxisAngle(mt, this.volumeHeadCurrent), this.objectNeck.quaternion.multiply(Q)), We.setFromObject(this.armature), this.objectLeftToeBase.getWorldPosition(ve), ve.sub(this.armature.position), this.objectRightToeBase.getWorldPosition(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) {
|
|
@@ -5260,48 +5260,48 @@ class Ne {
|
|
|
5260
5260
|
*/
|
|
5261
5261
|
speakText(t, e = null, n = null, i = null) {
|
|
5262
5262
|
e = e || {};
|
|
5263
|
-
const s = /[!\.\?\n\p{Extended_Pictographic}]/ug, o = /[ ]/ug, l = /[\p{L}\p{N},\.\p{Quotation_Mark}!€\$\+\p{Dash_Punctuation}%&\?]/ug,
|
|
5264
|
-
let
|
|
5265
|
-
const
|
|
5266
|
-
for (let
|
|
5267
|
-
const
|
|
5268
|
-
let
|
|
5269
|
-
const
|
|
5270
|
-
if (
|
|
5263
|
+
const s = /[!\.\?\n\p{Extended_Pictographic}]/ug, o = /[ ]/ug, l = /[\p{L}\p{N},\.\p{Quotation_Mark}!€\$\+\p{Dash_Punctuation}%&\?]/ug, h = /[\p{Extended_Pictographic}]/ug, r = e.lipsyncLang || this.avatar.lipsyncLang || this.opt.lipsyncLang;
|
|
5264
|
+
let u = "", a = "", c = 0, d = [], g = [];
|
|
5265
|
+
const b = Array.from(this.segmenter.segment(t), (x) => x.segment);
|
|
5266
|
+
for (let x = 0; x < b.length; x++) {
|
|
5267
|
+
const A = x === b.length - 1, B = b[x].match(l);
|
|
5268
|
+
let p = b[x].match(s);
|
|
5269
|
+
const E = b[x].match(h), I = b[x].match(o);
|
|
5270
|
+
if (p && !A && !E && b[x + 1].match(s) && (p = !1), n && (u += b[x]), B && (!i || i.every((y) => x < y[0] || x > y[1])) && (a += b[x]), (I || p || A) && (a.length && (a = this.lipsyncPreProcessText(a, r), a.length && d.push({
|
|
5271
5271
|
mark: c,
|
|
5272
5272
|
word: a
|
|
5273
|
-
})),
|
|
5273
|
+
})), u.length && (g.push({
|
|
5274
5274
|
mark: c,
|
|
5275
5275
|
template: { name: "subtitles" },
|
|
5276
5276
|
ts: [0],
|
|
5277
5277
|
vs: {
|
|
5278
|
-
subtitles: [
|
|
5278
|
+
subtitles: [u]
|
|
5279
5279
|
}
|
|
5280
|
-
}),
|
|
5280
|
+
}), u = ""), a.length)) {
|
|
5281
5281
|
const y = this.lipsyncWordsToVisemes(a, r);
|
|
5282
5282
|
if (y && y.visemes && y.visemes.length) {
|
|
5283
|
-
const
|
|
5284
|
-
for (let
|
|
5283
|
+
const H = y.times[y.visemes.length - 1] + y.durations[y.visemes.length - 1];
|
|
5284
|
+
for (let w = 0; w < y.visemes.length; w++)
|
|
5285
5285
|
g.push({
|
|
5286
5286
|
mark: c,
|
|
5287
5287
|
template: { name: "viseme" },
|
|
5288
|
-
ts: [(y.times[
|
|
5288
|
+
ts: [(y.times[w] - 0.6) / H, (y.times[w] + 0.5) / H, (y.times[w] + y.durations[w] + 0.5) / H],
|
|
5289
5289
|
vs: {
|
|
5290
|
-
["viseme_" + y.visemes[
|
|
5290
|
+
["viseme_" + y.visemes[w]]: [null, y.visemes[w] === "PP" || y.visemes[w] === "FF" ? 0.9 : 0.6, 0]
|
|
5291
5291
|
}
|
|
5292
5292
|
});
|
|
5293
5293
|
}
|
|
5294
5294
|
a = "", c++;
|
|
5295
5295
|
}
|
|
5296
|
-
if (
|
|
5297
|
-
if (d.length ||
|
|
5296
|
+
if (p || A) {
|
|
5297
|
+
if (d.length || A && g.length) {
|
|
5298
5298
|
const y = {
|
|
5299
5299
|
anim: g
|
|
5300
5300
|
};
|
|
5301
5301
|
n && (y.onSubtitles = n), d.length && !e.avatarMute && (y.text = d, e.avatarMood && (y.mood = e.avatarMood), e.ttsLang && (y.lang = e.ttsLang), e.ttsVoice && (y.voice = e.ttsVoice), e.ttsRate && (y.rate = e.ttsRate), e.ttsVoice && (y.pitch = e.ttsPitch), e.ttsVolume && (y.volume = e.ttsVolume)), this.speechQueue.push(y), d = [], a = "", c = 0, g = [];
|
|
5302
5302
|
}
|
|
5303
|
-
if (
|
|
5304
|
-
let y = this.animEmojis[x
|
|
5303
|
+
if (E) {
|
|
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
|
}
|
|
5307
5307
|
this.speechQueue.push({ break: 100 });
|
|
@@ -5383,27 +5383,27 @@ class Ne {
|
|
|
5383
5383
|
if (t.words) {
|
|
5384
5384
|
let o = [];
|
|
5385
5385
|
for (let l = 0; l < t.words.length; l++) {
|
|
5386
|
-
const
|
|
5387
|
-
let
|
|
5388
|
-
if (
|
|
5386
|
+
const h = t.words[l], r = t.wtimes[l];
|
|
5387
|
+
let u = t.wdurations[l];
|
|
5388
|
+
if (h.length && (n && o.push({
|
|
5389
5389
|
template: { name: "subtitles" },
|
|
5390
5390
|
ts: [r],
|
|
5391
5391
|
vs: {
|
|
5392
|
-
subtitles: [" " +
|
|
5392
|
+
subtitles: [" " + h]
|
|
5393
5393
|
}
|
|
5394
5394
|
}), !t.visemes)) {
|
|
5395
|
-
const a = this.lipsyncPreProcessText(
|
|
5395
|
+
const a = this.lipsyncPreProcessText(h, i), c = this.lipsyncWordsToVisemes(a, i);
|
|
5396
5396
|
if (c && c.visemes && c.visemes.length) {
|
|
5397
|
-
const d = c.times[c.visemes.length - 1] + c.durations[c.visemes.length - 1], g = Math.min(
|
|
5398
|
-
let
|
|
5399
|
-
if (
|
|
5400
|
-
for (let
|
|
5401
|
-
const
|
|
5397
|
+
const d = c.times[c.visemes.length - 1] + c.durations[c.visemes.length - 1], g = Math.min(u, Math.max(0, u - c.visemes.length * 150));
|
|
5398
|
+
let b = 0.6 + this.convertRange(g, [0, u], [0, 0.4]);
|
|
5399
|
+
if (u = Math.min(u, c.visemes.length * 200), d > 0)
|
|
5400
|
+
for (let x = 0; x < c.visemes.length; x++) {
|
|
5401
|
+
const A = r + c.times[x] / d * u, B = c.durations[x] / d * u;
|
|
5402
5402
|
o.push({
|
|
5403
5403
|
template: { name: "viseme" },
|
|
5404
|
-
ts: [
|
|
5404
|
+
ts: [A - Math.min(60, 2 * B / 3), A + Math.min(25, B / 2), A + B + Math.min(60, B / 2)],
|
|
5405
5405
|
vs: {
|
|
5406
|
-
["viseme_" + c.visemes[
|
|
5406
|
+
["viseme_" + c.visemes[x]]: [null, c.visemes[x] === "PP" || c.visemes[x] === "FF" ? 0.9 : b, 0]
|
|
5407
5407
|
}
|
|
5408
5408
|
});
|
|
5409
5409
|
}
|
|
@@ -5412,22 +5412,22 @@ class Ne {
|
|
|
5412
5412
|
}
|
|
5413
5413
|
if (t.visemes)
|
|
5414
5414
|
for (let l = 0; l < t.visemes.length; l++) {
|
|
5415
|
-
const
|
|
5415
|
+
const h = t.visemes[l], r = t.vtimes[l], u = t.vdurations[l];
|
|
5416
5416
|
o.push({
|
|
5417
5417
|
template: { name: "viseme" },
|
|
5418
|
-
ts: [r - 2 *
|
|
5418
|
+
ts: [r - 2 * u / 3, r + u / 2, r + u + u / 2],
|
|
5419
5419
|
vs: {
|
|
5420
|
-
["viseme_" +
|
|
5420
|
+
["viseme_" + h]: [null, h === "PP" || h === "FF" ? 0.9 : 0.6, 0]
|
|
5421
5421
|
}
|
|
5422
5422
|
});
|
|
5423
5423
|
}
|
|
5424
5424
|
if (t.markers)
|
|
5425
5425
|
for (let l = 0; l < t.markers.length; l++) {
|
|
5426
|
-
const
|
|
5426
|
+
const h = t.markers[l], r = t.mtimes[l];
|
|
5427
5427
|
o.push({
|
|
5428
5428
|
template: { name: "markers" },
|
|
5429
5429
|
ts: [r],
|
|
5430
|
-
vs: { function: [
|
|
5430
|
+
vs: { function: [h] }
|
|
5431
5431
|
});
|
|
5432
5432
|
}
|
|
5433
5433
|
o.length && (s.anim = o);
|
|
@@ -5447,7 +5447,7 @@ class Ne {
|
|
|
5447
5447
|
if (this.isAudioPlaying = !0, this.audioPlaylist.length) {
|
|
5448
5448
|
const e = this.audioPlaylist.shift();
|
|
5449
5449
|
if (this.audioCtx.state === "suspended" || this.audioCtx.state === "interrupted") {
|
|
5450
|
-
const s = this.audioCtx.resume(), o = new Promise((l,
|
|
5450
|
+
const s = this.audioCtx.resume(), o = new Promise((l, h) => setTimeout(() => h("p2"), 1e3));
|
|
5451
5451
|
try {
|
|
5452
5452
|
await Promise.race([s, o]);
|
|
5453
5453
|
} catch {
|
|
@@ -5479,41 +5479,41 @@ class Ne {
|
|
|
5479
5479
|
*/
|
|
5480
5480
|
async synthesizeWithBrowserTTS(t) {
|
|
5481
5481
|
return new Promise((e, n) => {
|
|
5482
|
-
const i = t.text.map((
|
|
5483
|
-
s.lang = o, s.rate = Math.max(0.1, Math.min(10, l)), s.pitch = Math.max(0, Math.min(2,
|
|
5484
|
-
const
|
|
5485
|
-
if (a &&
|
|
5486
|
-
const
|
|
5487
|
-
|
|
5482
|
+
const i = t.text.map((p) => p.word).join(" "), s = new SpeechSynthesisUtterance(i), o = t.lang || this.avatar.ttsLang || this.opt.ttsLang || "en-US", l = (t.rate || this.avatar.ttsRate || this.opt.ttsRate || 1) + this.mood.speech.deltaRate, h = (t.pitch || this.avatar.ttsPitch || this.opt.ttsPitch || 1) + this.mood.speech.deltaPitch, r = (t.volume || this.avatar.ttsVolume || this.opt.ttsVolume || 1) + this.mood.speech.deltaVolume;
|
|
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
|
+
const u = speechSynthesis.getVoices(), a = t.voice || this.avatar.ttsVoice || this.opt.ttsVoice;
|
|
5485
|
+
if (a && u.length > 0) {
|
|
5486
|
+
const p = u.find((E) => E.name.includes(a) || E.lang === o);
|
|
5487
|
+
p && (s.voice = p);
|
|
5488
5488
|
}
|
|
5489
|
-
const c = i.length * 100 / s.rate, d = this.audioCtx.createBuffer(1, this.audioCtx.sampleRate * (c / 1e3), this.audioCtx.sampleRate), g = this.avatar.lipsyncLang || this.opt.lipsyncLang || "en",
|
|
5489
|
+
const c = i.length * 100 / s.rate, d = this.audioCtx.createBuffer(1, this.audioCtx.sampleRate * (c / 1e3), this.audioCtx.sampleRate), g = this.avatar.lipsyncLang || this.opt.lipsyncLang || "en", b = this.lipsyncPreProcessText(i, g), x = this.lipsyncWordsToVisemes(b, g);
|
|
5490
5490
|
console.log("Browser TTS Lip-sync Debug:", {
|
|
5491
5491
|
text: i,
|
|
5492
5492
|
lipsyncLang: g,
|
|
5493
|
-
processedText:
|
|
5494
|
-
lipsyncData:
|
|
5495
|
-
hasVisemes:
|
|
5493
|
+
processedText: b,
|
|
5494
|
+
lipsyncData: x,
|
|
5495
|
+
hasVisemes: x && x.visemes && x.visemes.length > 0,
|
|
5496
5496
|
estimatedDuration: c
|
|
5497
5497
|
});
|
|
5498
|
-
const
|
|
5499
|
-
if (
|
|
5500
|
-
const
|
|
5501
|
-
for (let
|
|
5502
|
-
const
|
|
5503
|
-
|
|
5498
|
+
const A = [];
|
|
5499
|
+
if (x && x.visemes && x.visemes.length > 0) {
|
|
5500
|
+
const p = x.times[x.visemes.length - 1] + x.durations[x.visemes.length - 1];
|
|
5501
|
+
for (let E = 0; E < x.visemes.length; E++) {
|
|
5502
|
+
const I = x.visemes[E], y = x.times[E] / p, H = x.durations[E] / p, w = y * c, D = H * c;
|
|
5503
|
+
A.push({
|
|
5504
5504
|
template: { name: "viseme" },
|
|
5505
|
-
ts: [
|
|
5505
|
+
ts: [w - Math.min(60, 2 * D / 3), w + Math.min(25, D / 2), w + D + Math.min(60, D / 2)],
|
|
5506
5506
|
vs: {
|
|
5507
|
-
["viseme_" +
|
|
5507
|
+
["viseme_" + I]: [null, I === "PP" || I === "FF" ? 0.9 : 0.6, 0]
|
|
5508
5508
|
}
|
|
5509
5509
|
});
|
|
5510
5510
|
}
|
|
5511
5511
|
}
|
|
5512
|
-
const
|
|
5513
|
-
this.audioPlaylist.push({ anim:
|
|
5512
|
+
const B = [...t.anim, ...A];
|
|
5513
|
+
this.audioPlaylist.push({ anim: B, audio: d }), this.onSubtitles = t.onSubtitles || null, this.resetLips(), t.mood && this.setMood(t.mood), this.playAudio(), s.onend = () => {
|
|
5514
5514
|
e();
|
|
5515
|
-
}, s.onerror = (
|
|
5516
|
-
console.error("Speech synthesis error:",
|
|
5515
|
+
}, s.onerror = (p) => {
|
|
5516
|
+
console.error("Speech synthesis error:", p.error), n(p.error);
|
|
5517
5517
|
}, speechSynthesis.speak(s);
|
|
5518
5518
|
});
|
|
5519
5519
|
}
|
|
@@ -5544,25 +5544,25 @@ class Ne {
|
|
|
5544
5544
|
throw new Error(`ElevenLabs TTS error: ${s.status} ${s.statusText}`);
|
|
5545
5545
|
const o = await s.arrayBuffer(), l = await this.audioCtx.decodeAudioData(o);
|
|
5546
5546
|
console.log("Using text-based lip-sync for debugging...");
|
|
5547
|
-
const
|
|
5547
|
+
const h = this.avatar.lipsyncLang || this.opt.lipsyncLang || "en";
|
|
5548
5548
|
let r;
|
|
5549
5549
|
try {
|
|
5550
5550
|
console.log("Lip-sync modules available:", {
|
|
5551
5551
|
hasLipsync: !!this.lipsync,
|
|
5552
5552
|
lipsyncKeys: this.lipsync ? Object.keys(this.lipsync) : [],
|
|
5553
|
-
lipsyncLang:
|
|
5553
|
+
lipsyncLang: h
|
|
5554
5554
|
});
|
|
5555
|
-
const c = this.lipsyncPreProcessText(e,
|
|
5555
|
+
const c = this.lipsyncPreProcessText(e, h), d = this.lipsyncWordsToVisemes(c, h);
|
|
5556
5556
|
if (console.log("Lip-sync data:", {
|
|
5557
5557
|
processedText: c,
|
|
5558
5558
|
lipsyncData: d,
|
|
5559
5559
|
hasVisemes: d && d.visemes && d.visemes.length > 0
|
|
5560
5560
|
}), d && d.visemes && d.visemes.length > 0)
|
|
5561
5561
|
r = {
|
|
5562
|
-
visemes: d.visemes.map((g,
|
|
5562
|
+
visemes: d.visemes.map((g, b) => ({
|
|
5563
5563
|
viseme: g,
|
|
5564
|
-
startTime:
|
|
5565
|
-
endTime: (
|
|
5564
|
+
startTime: b * l.duration / d.visemes.length,
|
|
5565
|
+
endTime: (b + 1) * l.duration / d.visemes.length,
|
|
5566
5566
|
duration: l.duration / d.visemes.length,
|
|
5567
5567
|
intensity: 0.7
|
|
5568
5568
|
})),
|
|
@@ -5575,16 +5575,16 @@ class Ne {
|
|
|
5575
5575
|
} catch (c) {
|
|
5576
5576
|
console.error("Text-based lip-sync failed, using fallback:", c);
|
|
5577
5577
|
const d = e.toLowerCase().split(/\s+/), g = [];
|
|
5578
|
-
for (const
|
|
5579
|
-
for (const
|
|
5580
|
-
let
|
|
5581
|
-
"aeiou".includes(
|
|
5578
|
+
for (const b of d)
|
|
5579
|
+
for (const x of b) {
|
|
5580
|
+
let A = "aa";
|
|
5581
|
+
"aeiou".includes(x) ? A = "aa" : "bp".includes(x) ? A = "PP" : "fv".includes(x) ? A = "FF" : "st".includes(x) ? A = "SS" : "dln".includes(x) ? A = "DD" : "kg".includes(x) ? A = "kk" : "rw".includes(x) && (A = "RR"), g.push(A);
|
|
5582
5582
|
}
|
|
5583
5583
|
r = {
|
|
5584
|
-
visemes: g.map((
|
|
5585
|
-
viseme:
|
|
5586
|
-
startTime:
|
|
5587
|
-
endTime: (
|
|
5584
|
+
visemes: g.map((b, x) => ({
|
|
5585
|
+
viseme: b,
|
|
5586
|
+
startTime: x * l.duration / g.length,
|
|
5587
|
+
endTime: (x + 1) * l.duration / g.length,
|
|
5588
5588
|
duration: l.duration / g.length,
|
|
5589
5589
|
intensity: 0.6
|
|
5590
5590
|
})),
|
|
@@ -5605,24 +5605,24 @@ class Ne {
|
|
|
5605
5605
|
visemes: r.visemes ? r.visemes.slice(0, 3) : []
|
|
5606
5606
|
// Show first 3 visemes for debugging
|
|
5607
5607
|
});
|
|
5608
|
-
const
|
|
5608
|
+
const u = [];
|
|
5609
5609
|
if (r.visemes && r.visemes.length > 0) {
|
|
5610
5610
|
console.log("ElevenLabs: Generating lip-sync animation from", r.visemes.length, "visemes");
|
|
5611
5611
|
for (let c = 0; c < r.visemes.length; c++) {
|
|
5612
|
-
const d = r.visemes[c], g = d.startTime * 1e3,
|
|
5613
|
-
|
|
5612
|
+
const d = r.visemes[c], g = d.startTime * 1e3, b = d.duration * 1e3, x = d.intensity;
|
|
5613
|
+
u.push({
|
|
5614
5614
|
template: { name: "viseme" },
|
|
5615
|
-
ts: [g - Math.min(60, 2 *
|
|
5615
|
+
ts: [g - Math.min(60, 2 * b / 3), g + Math.min(25, b / 2), g + b + Math.min(60, b / 2)],
|
|
5616
5616
|
vs: {
|
|
5617
|
-
["viseme_" + d.viseme]: [null,
|
|
5617
|
+
["viseme_" + d.viseme]: [null, x, 0]
|
|
5618
5618
|
}
|
|
5619
5619
|
});
|
|
5620
5620
|
}
|
|
5621
|
-
console.log("ElevenLabs: Generated",
|
|
5621
|
+
console.log("ElevenLabs: Generated", u.length, "lip-sync animation frames");
|
|
5622
5622
|
} else
|
|
5623
5623
|
console.warn("ElevenLabs: No visemes available for lip-sync animation");
|
|
5624
|
-
const a = [...t.anim, ...
|
|
5625
|
-
console.log("ElevenLabs: Combined animation frames:", a.length, "(original:", t.anim.length, "+ lipsync:",
|
|
5624
|
+
const a = [...t.anim, ...u];
|
|
5625
|
+
console.log("ElevenLabs: Combined animation frames:", a.length, "(original:", t.anim.length, "+ lipsync:", u.length, ")"), this.audioPlaylist.push({ anim: a, audio: l }), this.onSubtitles = t.onSubtitles || null, this.resetLips(), t.mood && this.setMood(t.mood), this.playAudio();
|
|
5626
5626
|
}
|
|
5627
5627
|
/**
|
|
5628
5628
|
* Synthesize speech using Deepgram Aura-2 TTS
|
|
@@ -5642,25 +5642,25 @@ class Ne {
|
|
|
5642
5642
|
throw new Error(`Deepgram TTS error: ${s.status} ${s.statusText}`);
|
|
5643
5643
|
const o = await s.arrayBuffer(), l = await this.audioCtx.decodeAudioData(o);
|
|
5644
5644
|
console.log("Using text-based lip-sync for Deepgram...");
|
|
5645
|
-
const
|
|
5645
|
+
const h = this.avatar.lipsyncLang || this.opt.lipsyncLang || "en";
|
|
5646
5646
|
let r;
|
|
5647
5647
|
try {
|
|
5648
5648
|
console.log("Lip-sync modules available:", {
|
|
5649
5649
|
hasLipsync: !!this.lipsync,
|
|
5650
5650
|
lipsyncKeys: this.lipsync ? Object.keys(this.lipsync) : [],
|
|
5651
|
-
lipsyncLang:
|
|
5651
|
+
lipsyncLang: h
|
|
5652
5652
|
});
|
|
5653
|
-
const c = this.lipsyncPreProcessText(e,
|
|
5653
|
+
const c = this.lipsyncPreProcessText(e, h), d = this.lipsyncWordsToVisemes(c, h);
|
|
5654
5654
|
if (console.log("Lip-sync data:", {
|
|
5655
5655
|
processedText: c,
|
|
5656
5656
|
lipsyncData: d,
|
|
5657
5657
|
hasVisemes: d && d.visemes && d.visemes.length > 0
|
|
5658
5658
|
}), d && d.visemes && d.visemes.length > 0)
|
|
5659
5659
|
r = {
|
|
5660
|
-
visemes: d.visemes.map((g,
|
|
5660
|
+
visemes: d.visemes.map((g, b) => ({
|
|
5661
5661
|
viseme: g,
|
|
5662
|
-
startTime:
|
|
5663
|
-
endTime: (
|
|
5662
|
+
startTime: b * l.duration / d.visemes.length,
|
|
5663
|
+
endTime: (b + 1) * l.duration / d.visemes.length,
|
|
5664
5664
|
duration: l.duration / d.visemes.length,
|
|
5665
5665
|
intensity: 0.7
|
|
5666
5666
|
})),
|
|
@@ -5673,16 +5673,16 @@ class Ne {
|
|
|
5673
5673
|
} catch (c) {
|
|
5674
5674
|
console.error("Text-based lip-sync failed, using fallback:", c);
|
|
5675
5675
|
const d = e.toLowerCase().split(/\s+/), g = [];
|
|
5676
|
-
for (const
|
|
5677
|
-
for (const
|
|
5678
|
-
let
|
|
5679
|
-
"aeiou".includes(
|
|
5676
|
+
for (const b of d)
|
|
5677
|
+
for (const x of b) {
|
|
5678
|
+
let A = "aa";
|
|
5679
|
+
"aeiou".includes(x) ? A = "aa" : "bp".includes(x) ? A = "PP" : "fv".includes(x) ? A = "FF" : "st".includes(x) ? A = "SS" : "dln".includes(x) ? A = "DD" : "kg".includes(x) ? A = "kk" : "rw".includes(x) && (A = "RR"), g.push(A);
|
|
5680
5680
|
}
|
|
5681
5681
|
r = {
|
|
5682
|
-
visemes: g.map((
|
|
5683
|
-
viseme:
|
|
5684
|
-
startTime:
|
|
5685
|
-
endTime: (
|
|
5682
|
+
visemes: g.map((b, x) => ({
|
|
5683
|
+
viseme: b,
|
|
5684
|
+
startTime: x * l.duration / g.length,
|
|
5685
|
+
endTime: (x + 1) * l.duration / g.length,
|
|
5686
5686
|
duration: l.duration / g.length,
|
|
5687
5687
|
intensity: 0.6
|
|
5688
5688
|
})),
|
|
@@ -5703,24 +5703,24 @@ class Ne {
|
|
|
5703
5703
|
visemes: r.visemes ? r.visemes.slice(0, 3) : []
|
|
5704
5704
|
// Show first 3 visemes for debugging
|
|
5705
5705
|
});
|
|
5706
|
-
const
|
|
5706
|
+
const u = [];
|
|
5707
5707
|
if (r.visemes && r.visemes.length > 0) {
|
|
5708
5708
|
console.log("Deepgram: Generating lip-sync animation from", r.visemes.length, "visemes");
|
|
5709
5709
|
for (let c = 0; c < r.visemes.length; c++) {
|
|
5710
|
-
const d = r.visemes[c], g = d.startTime * 1e3,
|
|
5711
|
-
|
|
5710
|
+
const d = r.visemes[c], g = d.startTime * 1e3, b = d.duration * 1e3, x = d.intensity;
|
|
5711
|
+
u.push({
|
|
5712
5712
|
template: { name: "viseme" },
|
|
5713
|
-
ts: [g - Math.min(60, 2 *
|
|
5713
|
+
ts: [g - Math.min(60, 2 * b / 3), g + Math.min(25, b / 2), g + b + Math.min(60, b / 2)],
|
|
5714
5714
|
vs: {
|
|
5715
|
-
["viseme_" + d.viseme]: [null,
|
|
5715
|
+
["viseme_" + d.viseme]: [null, x, 0]
|
|
5716
5716
|
}
|
|
5717
5717
|
});
|
|
5718
5718
|
}
|
|
5719
|
-
console.log("Deepgram: Generated",
|
|
5719
|
+
console.log("Deepgram: Generated", u.length, "lip-sync animation frames");
|
|
5720
5720
|
} else
|
|
5721
5721
|
console.warn("Deepgram: No visemes available for lip-sync animation");
|
|
5722
|
-
const a = [...t.anim, ...
|
|
5723
|
-
console.log("Deepgram: Combined animation frames:", a.length, "(original:", t.anim.length, "+ lipsync:",
|
|
5722
|
+
const a = [...t.anim, ...u];
|
|
5723
|
+
console.log("Deepgram: Combined animation frames:", a.length, "(original:", t.anim.length, "+ lipsync:", u.length, ")"), this.audioPlaylist.push({ anim: a, audio: l }), this.onSubtitles = t.onSubtitles || null, this.resetLips(), t.mood && this.setMood(t.mood), this.playAudio();
|
|
5724
5724
|
}
|
|
5725
5725
|
/**
|
|
5726
5726
|
* Synthesize speech using Azure TTS
|
|
@@ -5746,30 +5746,30 @@ class Ne {
|
|
|
5746
5746
|
throw new Error(`Azure TTS error: ${s.status} ${s.statusText}`);
|
|
5747
5747
|
const o = await s.arrayBuffer(), l = await this.audioCtx.decodeAudioData(o);
|
|
5748
5748
|
console.log("Analyzing audio for precise lip-sync...");
|
|
5749
|
-
const
|
|
5749
|
+
const h = await this.audioAnalyzer.analyzeAudio(l, e);
|
|
5750
5750
|
console.log("Azure TTS Audio Analysis:", {
|
|
5751
5751
|
text: e,
|
|
5752
5752
|
audioDuration: l.duration,
|
|
5753
|
-
visemeCount:
|
|
5754
|
-
wordCount:
|
|
5753
|
+
visemeCount: h.visemes.length,
|
|
5754
|
+
wordCount: h.words.length,
|
|
5755
5755
|
features: {
|
|
5756
|
-
onsets:
|
|
5757
|
-
boundaries:
|
|
5756
|
+
onsets: h.features.onsets.length,
|
|
5757
|
+
boundaries: h.features.phonemeBoundaries.length
|
|
5758
5758
|
}
|
|
5759
5759
|
});
|
|
5760
5760
|
const r = [];
|
|
5761
|
-
for (let a = 0; a <
|
|
5762
|
-
const c =
|
|
5761
|
+
for (let a = 0; a < h.visemes.length; a++) {
|
|
5762
|
+
const c = h.visemes[a], d = c.startTime * 1e3, g = c.duration * 1e3, b = c.intensity;
|
|
5763
5763
|
r.push({
|
|
5764
5764
|
template: { name: "viseme" },
|
|
5765
5765
|
ts: [d - Math.min(60, 2 * g / 3), d + Math.min(25, g / 2), d + g + Math.min(60, g / 2)],
|
|
5766
5766
|
vs: {
|
|
5767
|
-
["viseme_" + c.viseme]: [null,
|
|
5767
|
+
["viseme_" + c.viseme]: [null, b, 0]
|
|
5768
5768
|
}
|
|
5769
5769
|
});
|
|
5770
5770
|
}
|
|
5771
|
-
const
|
|
5772
|
-
this.audioPlaylist.push({ anim:
|
|
5771
|
+
const u = [...t.anim, ...r];
|
|
5772
|
+
this.audioPlaylist.push({ anim: u, audio: l }), this.onSubtitles = t.onSubtitles || null, this.resetLips(), t.mood && this.setMood(t.mood), this.playAudio();
|
|
5773
5773
|
}
|
|
5774
5774
|
/**
|
|
5775
5775
|
* Synthesize speech using external TTS service (Google Cloud, etc.)
|
|
@@ -5808,24 +5808,24 @@ class Ne {
|
|
|
5808
5808
|
if (i.status === 200 && s && s.audioContent) {
|
|
5809
5809
|
const o = this.b64ToArrayBuffer(s.audioContent), l = await this.audioCtx.decodeAudioData(o);
|
|
5810
5810
|
this.speakWithHands();
|
|
5811
|
-
const
|
|
5811
|
+
const h = [0];
|
|
5812
5812
|
let r = 0;
|
|
5813
5813
|
t.text.forEach((c, d) => {
|
|
5814
5814
|
if (d > 0) {
|
|
5815
|
-
let g =
|
|
5816
|
-
s.timepoints[r] && (g = s.timepoints[r].timeSeconds * 1e3, s.timepoints[r].markName === "" + c.mark && r++),
|
|
5815
|
+
let g = h[h.length - 1];
|
|
5816
|
+
s.timepoints[r] && (g = s.timepoints[r].timeSeconds * 1e3, s.timepoints[r].markName === "" + c.mark && r++), h.push(g);
|
|
5817
5817
|
}
|
|
5818
5818
|
});
|
|
5819
|
-
const
|
|
5820
|
-
|
|
5819
|
+
const u = [{ mark: 0, time: 0 }];
|
|
5820
|
+
h.forEach((c, d) => {
|
|
5821
5821
|
if (d > 0) {
|
|
5822
|
-
let g = c -
|
|
5823
|
-
|
|
5822
|
+
let g = c - h[d - 1];
|
|
5823
|
+
u[d - 1].duration = g, u.push({ mark: d, time: c });
|
|
5824
5824
|
}
|
|
5825
5825
|
});
|
|
5826
5826
|
let a = 1e3 * l.duration;
|
|
5827
|
-
a > this.opt.ttsTrimEnd && (a = a - this.opt.ttsTrimEnd),
|
|
5828
|
-
const d =
|
|
5827
|
+
a > this.opt.ttsTrimEnd && (a = a - this.opt.ttsTrimEnd), u[u.length - 1].duration = a - u[u.length - 1].time, t.anim.forEach((c) => {
|
|
5828
|
+
const d = u[c.mark];
|
|
5829
5829
|
if (d)
|
|
5830
5830
|
for (let g = 0; g < c.ts.length; g++)
|
|
5831
5831
|
c.ts[g] = d.time + c.ts[g] * d.duration + this.opt.ttsTrimStart;
|
|
@@ -5908,10 +5908,10 @@ class Ne {
|
|
|
5908
5908
|
}
|
|
5909
5909
|
if (!this.workletLoaded)
|
|
5910
5910
|
try {
|
|
5911
|
-
const l = this.audioCtx.audioWorklet.addModule(dt.href),
|
|
5912
|
-
(r,
|
|
5911
|
+
const l = this.audioCtx.audioWorklet.addModule(dt.href), h = new Promise(
|
|
5912
|
+
(r, u) => setTimeout(() => u(new Error("Worklet loading timed out")), 5e3)
|
|
5913
5913
|
);
|
|
5914
|
-
await Promise.race([l,
|
|
5914
|
+
await Promise.race([l, h]), this.workletLoaded = !0;
|
|
5915
5915
|
} catch (l) {
|
|
5916
5916
|
throw console.error("Failed to load audio worklet:", l), new Error("Failed to initialize streaming speech");
|
|
5917
5917
|
}
|
|
@@ -5924,8 +5924,8 @@ class Ne {
|
|
|
5924
5924
|
if (l.data.type === "playback-started" && (this.isSpeaking = !0, this.stateName = "speaking", this.streamWaitForAudioChunks && (this.streamAudioStartTime = this.animClock), this._processStreamLipsyncQueue(), this.speakWithHands(), this.onAudioStart))
|
|
5925
5925
|
try {
|
|
5926
5926
|
this.onAudioStart?.();
|
|
5927
|
-
} catch (
|
|
5928
|
-
console.error(
|
|
5927
|
+
} catch (h) {
|
|
5928
|
+
console.error(h);
|
|
5929
5929
|
}
|
|
5930
5930
|
if (l.data.type === "playback-ended" && (this._streamPause(), this.onAudioEnd))
|
|
5931
5931
|
try {
|
|
@@ -5945,9 +5945,9 @@ class Ne {
|
|
|
5945
5945
|
} catch {
|
|
5946
5946
|
}
|
|
5947
5947
|
if (this.resetLips(), this.lookAtCamera(500), t.mood && this.setMood(t.mood), this.onSubtitles = i || null, this.audioCtx.state === "suspended" || this.audioCtx.state === "interrupted") {
|
|
5948
|
-
const l = this.audioCtx.resume(),
|
|
5948
|
+
const l = this.audioCtx.resume(), h = new Promise((r, u) => setTimeout(() => u("p2"), 1e3));
|
|
5949
5949
|
try {
|
|
5950
|
-
await Promise.race([l,
|
|
5950
|
+
await Promise.race([l, h]);
|
|
5951
5951
|
} catch {
|
|
5952
5952
|
console.warn("Can't play audio. Web Audio API suspended. This is often due to calling some speak method before the first user action, which is typically prevented by the browser.");
|
|
5953
5953
|
return;
|
|
@@ -6044,16 +6044,16 @@ class Ne {
|
|
|
6044
6044
|
subtitles: [" " + i]
|
|
6045
6045
|
}
|
|
6046
6046
|
}), this.streamLipsyncType == "words")) {
|
|
6047
|
-
const l = this.streamLipsyncLang || this.avatar.lipsyncLang || this.opt.lipsyncLang,
|
|
6047
|
+
const l = this.streamLipsyncLang || this.avatar.lipsyncLang || this.opt.lipsyncLang, h = this.lipsyncPreProcessText(i, l), r = this.lipsyncWordsToVisemes(h, l);
|
|
6048
6048
|
if (r && r.visemes && r.visemes.length) {
|
|
6049
|
-
const
|
|
6049
|
+
const u = r.times[r.visemes.length - 1] + r.durations[r.visemes.length - 1], a = Math.min(o, Math.max(0, o - r.visemes.length * 150));
|
|
6050
6050
|
let c = 0.6 + this.convertRange(a, [0, o], [0, 0.4]);
|
|
6051
|
-
if (o = Math.min(o, r.visemes.length * 200),
|
|
6051
|
+
if (o = Math.min(o, r.visemes.length * 200), u > 0)
|
|
6052
6052
|
for (let d = 0; d < r.visemes.length; d++) {
|
|
6053
|
-
const g = e + s + r.times[d] /
|
|
6053
|
+
const g = e + s + r.times[d] / u * o, b = r.durations[d] / u * o;
|
|
6054
6054
|
this.animQueue.push({
|
|
6055
6055
|
template: { name: "viseme" },
|
|
6056
|
-
ts: [g - Math.min(60, 2 *
|
|
6056
|
+
ts: [g - Math.min(60, 2 * b / 3), g + Math.min(25, b / 2), g + b + Math.min(60, b / 2)],
|
|
6057
6057
|
vs: {
|
|
6058
6058
|
["viseme_" + r.visemes[d]]: [null, r.visemes[d] === "PP" || r.visemes[d] === "FF" ? 0.9 : c, 0]
|
|
6059
6059
|
}
|
|
@@ -6146,7 +6146,7 @@ class Ne {
|
|
|
6146
6146
|
*/
|
|
6147
6147
|
lookAtCamera(t) {
|
|
6148
6148
|
let e;
|
|
6149
|
-
if (this.speakTo && (e = new f.Vector3(), this.speakTo.objectLeftEye?.isObject3D ? (this.speakTo.armature.objectHead, this.speakTo.objectLeftEye.updateMatrixWorld(!0), this.speakTo.objectRightEye.updateMatrixWorld(!0),
|
|
6149
|
+
if (this.speakTo && (e = new f.Vector3(), this.speakTo.objectLeftEye?.isObject3D ? (this.speakTo.armature.objectHead, this.speakTo.objectLeftEye.updateMatrixWorld(!0), this.speakTo.objectRightEye.updateMatrixWorld(!0), ve.setFromMatrixPosition(this.speakTo.objectLeftEye.matrixWorld), Re.setFromMatrixPosition(this.speakTo.objectRightEye.matrixWorld), e.addVectors(ve, Re).divideScalar(2)) : this.speakTo.isObject3D ? this.speakTo.getWorldPosition(e) : this.speakTo.isVector3 ? e.set(this.speakTo) : this.speakTo.x && this.speakTo.y && this.speakTo.z && e.set(this.speakTo.x, this.speakTo.y, this.speakTo.z)), !e) {
|
|
6150
6150
|
if (this.avatar.hasOwnProperty("avatarIgnoreCamera")) {
|
|
6151
6151
|
if (this.avatar.avatarIgnoreCamera) {
|
|
6152
6152
|
this.lookAhead(t);
|
|
@@ -6159,16 +6159,16 @@ class Ne {
|
|
|
6159
6159
|
this.lookAt(null, null, t);
|
|
6160
6160
|
return;
|
|
6161
6161
|
}
|
|
6162
|
-
this.objectLeftEye.updateMatrixWorld(!0), this.objectRightEye.updateMatrixWorld(!0),
|
|
6163
|
-
const n = new f.Vector3().subVectors(e,
|
|
6164
|
-
|
|
6165
|
-
const l = new f.Quaternion().setFromEuler(
|
|
6166
|
-
|
|
6167
|
-
let r =
|
|
6162
|
+
this.objectLeftEye.updateMatrixWorld(!0), this.objectRightEye.updateMatrixWorld(!0), ve.setFromMatrixPosition(this.objectLeftEye.matrixWorld), Re.setFromMatrixPosition(this.objectRightEye.matrixWorld), ve.add(Re).divideScalar(2), Q.copy(this.armature.quaternion), Q.multiply(this.poseTarget.props["Hips.quaternion"]), Q.multiply(this.poseTarget.props["Spine.quaternion"]), Q.multiply(this.poseTarget.props["Spine1.quaternion"]), Q.multiply(this.poseTarget.props["Spine2.quaternion"]), Q.multiply(this.poseTarget.props["Neck.quaternion"]), Q.multiply(this.poseTarget.props["Head.quaternion"]);
|
|
6163
|
+
const n = new f.Vector3().subVectors(e, ve).normalize(), i = Math.atan2(n.x, n.z), s = Math.asin(-n.y);
|
|
6164
|
+
G.set(s, i, 0, "YXZ");
|
|
6165
|
+
const l = new f.Quaternion().setFromEuler(G), h = new f.Quaternion().copy(l).multiply(Q.clone().invert());
|
|
6166
|
+
G.setFromQuaternion(h, "YXZ");
|
|
6167
|
+
let r = G.x / (40 / 24) + 0.2, u = G.y / (9 / 4), a = Math.min(0.6, Math.max(-0.3, r)), c = Math.min(0.8, Math.max(-0.8, u)), d = (Math.random() - 0.5) / 4, g = (Math.random() - 0.5) / 4;
|
|
6168
6168
|
if (t) {
|
|
6169
|
-
let
|
|
6170
|
-
|
|
6171
|
-
const
|
|
6169
|
+
let b = this.animQueue.findIndex((A) => A.template.name === "lookat");
|
|
6170
|
+
b !== -1 && this.animQueue.splice(b, 1);
|
|
6171
|
+
const x = {
|
|
6172
6172
|
name: "lookat",
|
|
6173
6173
|
dt: [750, t],
|
|
6174
6174
|
vs: {
|
|
@@ -6183,7 +6183,7 @@ class Ne {
|
|
|
6183
6183
|
headMove: [0]
|
|
6184
6184
|
}
|
|
6185
6185
|
};
|
|
6186
|
-
this.animQueue.push(this.animFactory(
|
|
6186
|
+
this.animQueue.push(this.animFactory(x));
|
|
6187
6187
|
}
|
|
6188
6188
|
}
|
|
6189
6189
|
/**
|
|
@@ -6198,22 +6198,22 @@ class Ne {
|
|
|
6198
6198
|
this.objectLeftEye.updateMatrixWorld(!0), this.objectRightEye.updateMatrixWorld(!0);
|
|
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
|
-
let
|
|
6202
|
-
t === null && (t =
|
|
6203
|
-
let
|
|
6204
|
-
|
|
6205
|
-
let
|
|
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), Q.copy(this.armature.quaternion), Q.multiply(this.poseTarget.props["Hips.quaternion"]), Q.multiply(this.poseTarget.props["Spine.quaternion"]), Q.multiply(this.poseTarget.props["Spine1.quaternion"]), Q.multiply(this.poseTarget.props["Spine2.quaternion"]), Q.multiply(this.poseTarget.props["Neck.quaternion"]), Q.multiply(this.poseTarget.props["Head.quaternion"]), G.setFromQuaternion(Q);
|
|
6203
|
+
let u = G.x / (40 / 24), a = G.y / (9 / 4), c = Math.min(0.4, Math.max(-0.4, this.camera.rotation.x)), d = Math.min(0.4, Math.max(-0.4, this.camera.rotation.y)), g = Math.max(window.innerWidth - h, h), b = Math.max(window.innerHeight - r, r), x = this.convertRange(e, [r - b, r + b], [-0.3, 0.6]) - u + c, A = this.convertRange(t, [h - g, h + g], [-0.8, 0.8]) - a + d;
|
|
6204
|
+
x = Math.min(0.6, Math.max(-0.3, x)), A = Math.min(0.8, Math.max(-0.8, A));
|
|
6205
|
+
let B = (Math.random() - 0.5) / 4, p = (Math.random() - 0.5) / 4;
|
|
6206
6206
|
if (n) {
|
|
6207
|
-
let
|
|
6208
|
-
|
|
6209
|
-
const
|
|
6207
|
+
let E = this.animQueue.findIndex((y) => y.template.name === "lookat");
|
|
6208
|
+
E !== -1 && this.animQueue.splice(E, 1);
|
|
6209
|
+
const I = {
|
|
6210
6210
|
name: "lookat",
|
|
6211
6211
|
dt: [750, n],
|
|
6212
6212
|
vs: {
|
|
6213
|
-
bodyRotateX: [
|
|
6214
|
-
bodyRotateY: [
|
|
6215
|
-
eyesRotateX: [-3 *
|
|
6216
|
-
eyesRotateY: [-5 *
|
|
6213
|
+
bodyRotateX: [x + B],
|
|
6214
|
+
bodyRotateY: [A + p],
|
|
6215
|
+
eyesRotateX: [-3 * B + 0.1],
|
|
6216
|
+
eyesRotateY: [-5 * p],
|
|
6217
6217
|
browInnerUp: [[0, 0.7]],
|
|
6218
6218
|
mouthLeft: [[0, 0.7]],
|
|
6219
6219
|
mouthRight: [[0, 0.7]],
|
|
@@ -6221,7 +6221,7 @@ class Ne {
|
|
|
6221
6221
|
headMove: [0]
|
|
6222
6222
|
}
|
|
6223
6223
|
};
|
|
6224
|
-
this.animQueue.push(this.animFactory(
|
|
6224
|
+
this.animQueue.push(this.animFactory(I));
|
|
6225
6225
|
}
|
|
6226
6226
|
}
|
|
6227
6227
|
/**
|
|
@@ -6239,10 +6239,10 @@ class Ne {
|
|
|
6239
6239
|
s.setFromCamera(i, this.camera);
|
|
6240
6240
|
const o = s.intersectObject(this.armature);
|
|
6241
6241
|
if (o.length > 0) {
|
|
6242
|
-
const l = o[0].point,
|
|
6243
|
-
this.objectLeftArm.getWorldPosition(
|
|
6244
|
-
const
|
|
6245
|
-
|
|
6242
|
+
const l = o[0].point, h = new f.Vector3(), r = new f.Vector3();
|
|
6243
|
+
this.objectLeftArm.getWorldPosition(h), this.objectRightArm.getWorldPosition(r);
|
|
6244
|
+
const u = h.distanceToSquared(l), a = r.distanceToSquared(l);
|
|
6245
|
+
u < a ? (this.ikSolve({
|
|
6246
6246
|
iterations: 20,
|
|
6247
6247
|
root: "LeftShoulder",
|
|
6248
6248
|
effector: "LeftHandMiddle1",
|
|
@@ -6263,8 +6263,8 @@ class Ne {
|
|
|
6263
6263
|
}, l, !1, 1e3), this.setValue("handFistRight", 0));
|
|
6264
6264
|
} else
|
|
6265
6265
|
["LeftArm", "LeftForeArm", "LeftHand", "RightArm", "RightForeArm", "RightHand"].forEach((l) => {
|
|
6266
|
-
let
|
|
6267
|
-
this.poseTarget.props[
|
|
6266
|
+
let h = l + ".quaternion";
|
|
6267
|
+
this.poseTarget.props[h].copy(this.getPoseTemplateProp(h)), this.poseTarget.props[h].t = this.animClock, this.poseTarget.props[h].d = 1e3;
|
|
6268
6268
|
});
|
|
6269
6269
|
return o.length > 0;
|
|
6270
6270
|
}
|
|
@@ -6380,296 +6380,24 @@ class Ne {
|
|
|
6380
6380
|
* @param {number} [ndx=0] Index of the clip
|
|
6381
6381
|
* @param {number} [scale=0.01] Position scale factor
|
|
6382
6382
|
*/
|
|
6383
|
-
/**
|
|
6384
|
-
* Get all bone names from the avatar's armature
|
|
6385
|
-
* @returns {Set<string>} Set of bone names
|
|
6386
|
-
*/
|
|
6387
|
-
getAvailableBoneNames() {
|
|
6388
|
-
const t = /* @__PURE__ */ new Set();
|
|
6389
|
-
return this.armature && this.armature.traverse((e) => {
|
|
6390
|
-
(e.isBone || e.type === "Bone") && t.add(e.name);
|
|
6391
|
-
}), t;
|
|
6392
|
-
}
|
|
6393
|
-
/**
|
|
6394
|
-
* Map bone names from different naming conventions to avatar bone names
|
|
6395
|
-
* @param {string} fbxBoneName - Bone name from FBX animation
|
|
6396
|
-
* @param {Set<string>} availableBones - Set of available bone names in avatar
|
|
6397
|
-
* @returns {string|null} Mapped bone name or null if no match found
|
|
6398
|
-
*/
|
|
6399
|
-
mapBoneName(t, e) {
|
|
6400
|
-
if (e.has(t))
|
|
6401
|
-
return t;
|
|
6402
|
-
let n = t;
|
|
6403
|
-
if (n.startsWith("CC_Base_") && (n = n.replace("CC_Base_", "")), n = n.replace(/^mixamorig/i, ""), e.has(n))
|
|
6404
|
-
return n;
|
|
6405
|
-
if (this._mappingDebugLog || (this._mappingDebugLog = /* @__PURE__ */ new Set()), this._mappingDebugLog.size < 5 && !this._mappingDebugLog.has(t) && (this._mappingDebugLog.add(t), console.debug(`Mapping attempt: "${t}" -> "${n}" (not found in available bones)`)), n.match(/^Spine\d+$/)) {
|
|
6406
|
-
const a = n.match(/\d+/)?.[0];
|
|
6407
|
-
if (a) {
|
|
6408
|
-
const c = `Spine${parseInt(a)}`;
|
|
6409
|
-
if (e.has(c))
|
|
6410
|
-
return c;
|
|
6411
|
-
if (a === "01" && e.has("Spine1"))
|
|
6412
|
-
return "Spine1";
|
|
6413
|
-
if (parseInt(a) >= 2 && e.has("Spine2"))
|
|
6414
|
-
return "Spine2";
|
|
6415
|
-
}
|
|
6416
|
-
}
|
|
6417
|
-
if (n.includes("Twist"))
|
|
6418
|
-
return null;
|
|
6419
|
-
const i = {
|
|
6420
|
-
// Spine mapping
|
|
6421
|
-
Spine01: "Spine1",
|
|
6422
|
-
Spine02: "Spine2",
|
|
6423
|
-
Spine03: "Spine2",
|
|
6424
|
-
Spine1: "Spine1",
|
|
6425
|
-
Spine2: "Spine2",
|
|
6426
|
-
Spine: "Spine1",
|
|
6427
|
-
// Head and neck
|
|
6428
|
-
Head: "Head",
|
|
6429
|
-
Neck: "Neck",
|
|
6430
|
-
Neck1: "Neck",
|
|
6431
|
-
Neck2: "Neck",
|
|
6432
|
-
// Left arm mapping
|
|
6433
|
-
L_Upperarm: "LeftArm",
|
|
6434
|
-
L_Forearm: "LeftForeArm",
|
|
6435
|
-
L_Hand: "LeftHand",
|
|
6436
|
-
L_Shoulder: "LeftShoulder",
|
|
6437
|
-
L_Clavicle: "LeftShoulder",
|
|
6438
|
-
L_UpperArm: "LeftArm",
|
|
6439
|
-
L_ForeArm: "LeftForeArm",
|
|
6440
|
-
L_Index1: "LeftHandIndex1",
|
|
6441
|
-
L_Index2: "LeftHandIndex2",
|
|
6442
|
-
L_Index3: "LeftHandIndex3",
|
|
6443
|
-
L_Middle1: "LeftHandMiddle1",
|
|
6444
|
-
L_Middle2: "LeftHandMiddle2",
|
|
6445
|
-
L_Middle3: "LeftHandMiddle3",
|
|
6446
|
-
L_Mid1: "LeftHandMiddle1",
|
|
6447
|
-
L_Mid2: "LeftHandMiddle2",
|
|
6448
|
-
L_Mid3: "LeftHandMiddle3",
|
|
6449
|
-
L_Ring1: "LeftHandRing1",
|
|
6450
|
-
L_Ring2: "LeftHandRing2",
|
|
6451
|
-
L_Ring3: "LeftHandRing3",
|
|
6452
|
-
L_Pinky1: "LeftHandPinky1",
|
|
6453
|
-
L_Pinky2: "LeftHandPinky2",
|
|
6454
|
-
L_Pinky3: "LeftHandPinky3",
|
|
6455
|
-
L_Thumb1: "LeftHandThumb1",
|
|
6456
|
-
L_Thumb2: "LeftHandThumb2",
|
|
6457
|
-
L_Thumb3: "LeftHandThumb3",
|
|
6458
|
-
// Right arm mapping
|
|
6459
|
-
R_Upperarm: "RightArm",
|
|
6460
|
-
R_Forearm: "RightForeArm",
|
|
6461
|
-
R_Hand: "RightHand",
|
|
6462
|
-
R_Shoulder: "RightShoulder",
|
|
6463
|
-
R_Clavicle: "RightShoulder",
|
|
6464
|
-
R_UpperArm: "RightArm",
|
|
6465
|
-
R_ForeArm: "RightForeArm",
|
|
6466
|
-
R_Index1: "RightHandIndex1",
|
|
6467
|
-
R_Index2: "RightHandIndex2",
|
|
6468
|
-
R_Index3: "RightHandIndex3",
|
|
6469
|
-
R_Middle1: "RightHandMiddle1",
|
|
6470
|
-
R_Middle2: "RightHandMiddle2",
|
|
6471
|
-
R_Middle3: "RightHandMiddle3",
|
|
6472
|
-
R_Mid1: "RightHandMiddle1",
|
|
6473
|
-
R_Mid2: "RightHandMiddle2",
|
|
6474
|
-
R_Mid3: "RightHandMiddle3",
|
|
6475
|
-
R_Ring1: "RightHandRing1",
|
|
6476
|
-
R_Ring2: "RightHandRing2",
|
|
6477
|
-
R_Ring3: "RightHandRing3",
|
|
6478
|
-
R_Pinky1: "RightHandPinky1",
|
|
6479
|
-
R_Pinky2: "RightHandPinky2",
|
|
6480
|
-
R_Pinky3: "RightHandPinky3",
|
|
6481
|
-
R_Thumb1: "RightHandThumb1",
|
|
6482
|
-
R_Thumb2: "RightHandThumb2",
|
|
6483
|
-
R_Thumb3: "RightHandThumb3",
|
|
6484
|
-
// Leg mapping
|
|
6485
|
-
L_Thigh: "LeftUpLeg",
|
|
6486
|
-
L_Calf: "LeftLeg",
|
|
6487
|
-
L_Foot: "LeftFoot",
|
|
6488
|
-
L_UpLeg: "LeftUpLeg",
|
|
6489
|
-
L_Leg: "LeftLeg",
|
|
6490
|
-
R_Thigh: "RightUpLeg",
|
|
6491
|
-
R_Calf: "RightLeg",
|
|
6492
|
-
R_Foot: "RightFoot",
|
|
6493
|
-
R_UpLeg: "RightUpLeg",
|
|
6494
|
-
R_Leg: "RightLeg",
|
|
6495
|
-
// Root/Hips
|
|
6496
|
-
Hips: "Hips",
|
|
6497
|
-
Root: "Hips",
|
|
6498
|
-
Pelvis: "Hips"
|
|
6499
|
-
};
|
|
6500
|
-
if (i[n]) {
|
|
6501
|
-
const a = i[n];
|
|
6502
|
-
if (e.has(a))
|
|
6503
|
-
return a;
|
|
6504
|
-
}
|
|
6505
|
-
const s = n.toLowerCase();
|
|
6506
|
-
n.charAt(0).toUpperCase() + n.slice(1).toLowerCase();
|
|
6507
|
-
const o = s.match(/^[rl]_index(\d+)$/);
|
|
6508
|
-
if (o) {
|
|
6509
|
-
const a = o[1], d = `${s.startsWith("r") ? "Right" : "Left"}HandIndex${a}`;
|
|
6510
|
-
if (e.has(d))
|
|
6511
|
-
return d;
|
|
6512
|
-
}
|
|
6513
|
-
const l = s.match(/^[rl]_pinky(\d+)$/);
|
|
6514
|
-
if (l) {
|
|
6515
|
-
const a = l[1], d = `${s.startsWith("r") ? "Right" : "Left"}HandPinky${a}`;
|
|
6516
|
-
if (e.has(d))
|
|
6517
|
-
return d;
|
|
6518
|
-
}
|
|
6519
|
-
const u = s.match(/^[rl]_ring(\d+)$/);
|
|
6520
|
-
if (u) {
|
|
6521
|
-
const a = u[1], d = `${s.startsWith("r") ? "Right" : "Left"}HandRing${a}`;
|
|
6522
|
-
if (e.has(d))
|
|
6523
|
-
return d;
|
|
6524
|
-
}
|
|
6525
|
-
const r = s.match(/^[rl]_(?:middle|mid)(\d+)$/);
|
|
6526
|
-
if (r) {
|
|
6527
|
-
const a = r[1], d = `${s.startsWith("r") ? "Right" : "Left"}HandMiddle${a}`;
|
|
6528
|
-
if (e.has(d))
|
|
6529
|
-
return d;
|
|
6530
|
-
}
|
|
6531
|
-
const h = s.match(/^[rl]_thumb(\d+)$/);
|
|
6532
|
-
if (h) {
|
|
6533
|
-
const a = h[1], d = `${s.startsWith("r") ? "Right" : "Left"}HandThumb${a}`;
|
|
6534
|
-
if (e.has(d))
|
|
6535
|
-
return d;
|
|
6536
|
-
}
|
|
6537
|
-
if (s.match(/^[rl]_upperarm/)) {
|
|
6538
|
-
const c = `${s.startsWith("r") ? "Right" : "Left"}Arm`;
|
|
6539
|
-
if (e.has(c))
|
|
6540
|
-
return c;
|
|
6541
|
-
}
|
|
6542
|
-
if (s.includes("upperarmtwist") || s.includes("forearmtwist") || s.includes("ribstwist") || s.includes("breast") || s.includes("twist"))
|
|
6543
|
-
return null;
|
|
6544
|
-
if (s.match(/^[rl]_forearm/)) {
|
|
6545
|
-
const c = `${s.startsWith("r") ? "Right" : "Left"}ForeArm`;
|
|
6546
|
-
if (e.has(c))
|
|
6547
|
-
return c;
|
|
6548
|
-
}
|
|
6549
|
-
if (s.match(/^[rl]_hand$/)) {
|
|
6550
|
-
const c = `${s.startsWith("r") ? "Right" : "Left"}Hand`;
|
|
6551
|
-
if (e.has(c))
|
|
6552
|
-
return c;
|
|
6553
|
-
}
|
|
6554
|
-
if (s.match(/^[rl]_clavicle/)) {
|
|
6555
|
-
const c = `${s.startsWith("r") ? "Right" : "Left"}Shoulder`;
|
|
6556
|
-
if (e.has(c))
|
|
6557
|
-
return c;
|
|
6558
|
-
}
|
|
6559
|
-
if (s.match(/^[rl]_shoulder/)) {
|
|
6560
|
-
const c = `${s.startsWith("r") ? "Right" : "Left"}Shoulder`;
|
|
6561
|
-
if (e.has(c))
|
|
6562
|
-
return c;
|
|
6563
|
-
}
|
|
6564
|
-
if (s.match(/^spine0?(\d+)$/)) {
|
|
6565
|
-
const a = s.match(/^spine0?(\d+)$/)[1];
|
|
6566
|
-
if (a === "1") {
|
|
6567
|
-
if (e.has("Spine1")) return "Spine1";
|
|
6568
|
-
} else if ((a === "2" || a === "3") && e.has("Spine2"))
|
|
6569
|
-
return "Spine2";
|
|
6570
|
-
}
|
|
6571
|
-
if (s.match(/^neck\d*$/) && e.has("Neck"))
|
|
6572
|
-
return "Neck";
|
|
6573
|
-
if (s === "head" && e.has("Head"))
|
|
6574
|
-
return "Head";
|
|
6575
|
-
if (s.match(/^(hips|pelvis|root)$/) && e.has("Hips"))
|
|
6576
|
-
return "Hips";
|
|
6577
|
-
for (const a of e)
|
|
6578
|
-
if (a.toLowerCase() === s)
|
|
6579
|
-
return a;
|
|
6580
|
-
for (const a of e) {
|
|
6581
|
-
const c = a.toLowerCase();
|
|
6582
|
-
if ((c.includes(s) || s.includes(c)) && (c === s || c.replace(/[^a-z0-9]/g, "") === s.replace(/[^a-z0-9]/g, "")))
|
|
6583
|
-
return a;
|
|
6584
|
-
}
|
|
6585
|
-
return null;
|
|
6586
|
-
}
|
|
6587
|
-
/**
|
|
6588
|
-
* Filter animation tracks to only include bones that exist in the avatar
|
|
6589
|
-
* Maps bone names from different naming conventions to avatar bone names
|
|
6590
|
-
* @param {THREE.AnimationClip} clip - Animation clip to filter
|
|
6591
|
-
* @param {Set<string>} availableBones - Set of available bone names
|
|
6592
|
-
* @returns {THREE.AnimationClip} Filtered animation clip with mapped bone names
|
|
6593
|
-
*/
|
|
6594
|
-
filterAnimationTracks(t, e) {
|
|
6595
|
-
const n = [], i = /* @__PURE__ */ new Set(), s = /* @__PURE__ */ new Map(), o = /* @__PURE__ */ new Set();
|
|
6596
|
-
this._loggedAvailableBones || (console.log("Available avatar bones:", Array.from(e).sort().join(", ")), this._loggedAvailableBones = !0), t.tracks.forEach((u) => {
|
|
6597
|
-
const h = u.name.split(".")[0];
|
|
6598
|
-
o.add(h);
|
|
6599
|
-
}), console.log(`
|
|
6600
|
-
=== FBX Animation "${t.name}" Bone Analysis ===`), console.log("FBX bone names in animation:", Array.from(o).sort().join(", ")), console.log(`Total FBX bones: ${o.size}, Avatar bones: ${e.size}
|
|
6601
|
-
`), t.tracks.forEach((u) => {
|
|
6602
|
-
const r = u.name.split("."), h = r[0], a = r[1], c = this.mapBoneName(h, e);
|
|
6603
|
-
if (c) {
|
|
6604
|
-
const d = `${c}.${a}`, g = u.clone();
|
|
6605
|
-
g.name = d;
|
|
6606
|
-
const x = c.includes("Arm") || c.includes("Hand") || c.includes("Shoulder"), b = c.includes("ForeArm");
|
|
6607
|
-
if (x && (a === "quaternion" || a === "rotation")) {
|
|
6608
|
-
if (a === "quaternion" && g.values && g.values.length >= 4) {
|
|
6609
|
-
const I = g.times.length;
|
|
6610
|
-
for (let H = 0; H < I; H++) {
|
|
6611
|
-
const m = H * 4;
|
|
6612
|
-
if (m + 3 < g.values.length) {
|
|
6613
|
-
let T = g.values[m], k = g.values[m + 1], y = g.values[m + 2], M = g.values[m + 3];
|
|
6614
|
-
if (b || c.includes("Hand")) {
|
|
6615
|
-
const P = Math.PI, D = Math.cos(P / 2), J = Math.sin(P / 2), S = D * M - J * T, G = D * T + J * M, Q = D * k - J * y, Z = D * y + J * k;
|
|
6616
|
-
T = G, k = Q, y = Z, M = S;
|
|
6617
|
-
}
|
|
6618
|
-
g.values[m] = T, g.values[m + 1] = k, g.values[m + 2] = y, g.values[m + 3] = M;
|
|
6619
|
-
}
|
|
6620
|
-
}
|
|
6621
|
-
} else if (a === "rotation" && g.values && g.values.length >= 3) {
|
|
6622
|
-
const I = g.times.length;
|
|
6623
|
-
for (let H = 0; H < I; H++) {
|
|
6624
|
-
const m = H * 3;
|
|
6625
|
-
m + 2 < g.values.length && (b || c.includes("Hand")) && (g.values[m + 1] += Math.PI);
|
|
6626
|
-
}
|
|
6627
|
-
}
|
|
6628
|
-
}
|
|
6629
|
-
n.push(g), h !== c && s.set(h, c);
|
|
6630
|
-
} else
|
|
6631
|
-
i.add(h);
|
|
6632
|
-
}), console.log(`
|
|
6633
|
-
=== Mapping Results for "${t.name}" ===`), s.size > 0 && (console.info(`✓ Successfully mapped ${s.size} bone(s):`), Array.from(s.entries()).forEach(([u, r]) => {
|
|
6634
|
-
console.log(` ${u} → ${r}`);
|
|
6635
|
-
})), i.size > 0 && (console.warn(`
|
|
6636
|
-
✗ Could not map ${i.size} bone(s):`), Array.from(i).sort().forEach((u) => {
|
|
6637
|
-
console.log(` - ${u}`);
|
|
6638
|
-
const r = u.replace(/^(CC_Base_|mixamorig)/i, "").replace(/^[RL]_/, (a) => a.toLowerCase()), h = [];
|
|
6639
|
-
for (const a of e) {
|
|
6640
|
-
const c = a.toLowerCase(), d = r.toLowerCase();
|
|
6641
|
-
(c.includes(d) || d.includes(c)) && h.push(a);
|
|
6642
|
-
}
|
|
6643
|
-
h.length > 0 && console.log(` → Possible matches: ${h.slice(0, 3).join(", ")}`);
|
|
6644
|
-
}));
|
|
6645
|
-
const l = /* @__PURE__ */ new Set();
|
|
6646
|
-
return o.forEach((u) => {
|
|
6647
|
-
e.has(u) && !s.has(u) && l.add(u);
|
|
6648
|
-
}), l.size > 0 && (console.info(`
|
|
6649
|
-
✓ Direct matches (no mapping needed): ${l.size} bone(s)`), Array.from(l).sort().slice(0, 10).forEach((u) => {
|
|
6650
|
-
console.log(` - ${u}`);
|
|
6651
|
-
}), l.size > 10 && console.log(` ... and ${l.size - 10} more`)), console.log(`
|
|
6652
|
-
=== Summary ===`), console.log(`Total FBX tracks: ${t.tracks.length}`), console.log(`Valid tracks: ${n.length}`), console.log(`Mapped bones: ${s.size}`), console.log(`Direct matches: ${l.size}`), console.log(`Missing bones: ${i.size}`), console.log(`========================================
|
|
6653
|
-
`), n.length === 0 && console.error(`No valid tracks found for animation "${t.name}". All bones are missing or couldn't be mapped.`), n.length === 0 ? null : new f.AnimationClip(t.name, t.duration, n);
|
|
6654
|
-
}
|
|
6655
6383
|
async playAnimation(t, e = null, n = 10, i = 0, s = 0.01, o = !1) {
|
|
6656
6384
|
if (!this.armature) return;
|
|
6657
6385
|
this.positionWasLocked = !o, o ? console.log("Position locking disabled for FBX animation:", t) : (this.lockAvatarPosition(), console.log("Position locked immediately before FBX animation:", t));
|
|
6658
|
-
let l = this.animClips.find((
|
|
6386
|
+
let l = this.animClips.find((h) => h.url === t + "-" + i);
|
|
6659
6387
|
if (l) {
|
|
6660
|
-
let
|
|
6661
|
-
|
|
6388
|
+
let h = this.animQueue.find((a) => a.template.name === "pose");
|
|
6389
|
+
h && (h.ts[0] = 1 / 0), Object.entries(l.pose.props).forEach((a) => {
|
|
6662
6390
|
this.poseBase.props[a[0]] = a[1].clone(), this.poseTarget.props[a[0]] = a[1].clone(), this.poseTarget.props[a[0]].t = 0, this.poseTarget.props[a[0]].d = 1e3;
|
|
6663
6391
|
}), this.mixer ? console.log("Using existing mixer for FBX animation, preserving morph targets") : (this.mixer = new f.AnimationMixer(this.armature), console.log("Created new mixer for FBX animation")), this.mixer.addEventListener("finished", this.stopAnimation.bind(this), { once: !0 });
|
|
6664
|
-
const r = Math.ceil(n / l.clip.duration),
|
|
6665
|
-
|
|
6392
|
+
const r = Math.ceil(n / l.clip.duration), u = this.mixer.clipAction(l.clip);
|
|
6393
|
+
u.setLoop(f.LoopRepeat, r), u.clampWhenFinished = !0, this.currentFBXAction = u;
|
|
6666
6394
|
try {
|
|
6667
|
-
|
|
6395
|
+
u.fadeIn(0.5).play(), console.log("FBX animation started successfully:", t);
|
|
6668
6396
|
} catch (a) {
|
|
6669
6397
|
console.warn("FBX animation failed to start:", a), this.stopAnimation();
|
|
6670
6398
|
return;
|
|
6671
6399
|
}
|
|
6672
|
-
if (
|
|
6400
|
+
if (u.getClip().tracks.length === 0) {
|
|
6673
6401
|
console.warn("FBX animation has no valid tracks, stopping"), this.stopAnimation();
|
|
6674
6402
|
return;
|
|
6675
6403
|
}
|
|
@@ -6688,10 +6416,10 @@ class Ne {
|
|
|
6688
6416
|
} catch (c) {
|
|
6689
6417
|
console.warn(`Could not verify file existence for ${t}, attempting to load anyway:`, c);
|
|
6690
6418
|
}
|
|
6691
|
-
const
|
|
6419
|
+
const u = new De();
|
|
6692
6420
|
let a;
|
|
6693
6421
|
try {
|
|
6694
|
-
a = await
|
|
6422
|
+
a = await u.loadAsync(t, e);
|
|
6695
6423
|
} catch (c) {
|
|
6696
6424
|
console.error(`Failed to load FBX animation from ${t}:`, c), console.error("Error details:", {
|
|
6697
6425
|
message: c.message,
|
|
@@ -6699,13 +6427,13 @@ class Ne {
|
|
|
6699
6427
|
suggestion: "Make sure the file is a valid FBX file and the path is correct"
|
|
6700
6428
|
}), c.message && c.message.includes("version number") && (console.error("FBX Loader Error: Cannot find version number"), console.error("This error usually means:"), console.error("1. The file is not a valid FBX file (might be GLB, corrupted, or wrong format)"), console.error("2. The file might be corrupted"), console.error("3. The file path might be incorrect"), console.error("4. The server returned an HTML error page instead of the FBX file"), console.error("5. The file might not exist at that path"), console.error(""), console.error("Solution: Please verify:"), console.error(` - File exists at: ${t}`), console.error(" - File is a valid FBX binary file"), console.error(" - File path matches your public folder structure"), console.error(" - File is not corrupted"));
|
|
6701
6429
|
try {
|
|
6702
|
-
const d = await fetch(t), g = d.headers.get("content-type"),
|
|
6430
|
+
const d = await fetch(t), g = d.headers.get("content-type"), b = await d.text();
|
|
6703
6431
|
console.error("Response details:", {
|
|
6704
6432
|
status: d.status,
|
|
6705
6433
|
contentType: g,
|
|
6706
|
-
firstBytes:
|
|
6707
|
-
isHTML:
|
|
6708
|
-
}), (
|
|
6434
|
+
firstBytes: b.substring(0, 100),
|
|
6435
|
+
isHTML: b.trim().startsWith("<!DOCTYPE") || b.trim().startsWith("<html")
|
|
6436
|
+
}), (b.trim().startsWith("<!DOCTYPE") || b.trim().startsWith("<html")) && console.error("The server returned an HTML page instead of an FBX file. The file path is likely incorrect.");
|
|
6709
6437
|
} catch (d) {
|
|
6710
6438
|
console.error("Could not fetch file for debugging:", d);
|
|
6711
6439
|
}
|
|
@@ -6713,27 +6441,97 @@ class Ne {
|
|
|
6713
6441
|
}
|
|
6714
6442
|
if (a && a.animations && a.animations[i]) {
|
|
6715
6443
|
let c = a.animations[i];
|
|
6716
|
-
const d =
|
|
6717
|
-
|
|
6718
|
-
|
|
6719
|
-
|
|
6720
|
-
|
|
6721
|
-
|
|
6722
|
-
|
|
6444
|
+
const d = /* @__PURE__ */ new Set();
|
|
6445
|
+
this.armature && this.armature.traverse((I) => {
|
|
6446
|
+
(I.isBone || I.type === "Bone") && d.add(I.name);
|
|
6447
|
+
});
|
|
6448
|
+
const g = /* @__PURE__ */ new Map(), b = (I) => {
|
|
6449
|
+
if (d.has(I))
|
|
6450
|
+
return I;
|
|
6451
|
+
let y = I.replace(/^mixamorig/i, "");
|
|
6452
|
+
if (d.has(y))
|
|
6453
|
+
return y;
|
|
6454
|
+
const H = {
|
|
6455
|
+
// Arm bones - handle common variations
|
|
6456
|
+
LeftArm: "LeftArm",
|
|
6457
|
+
leftArm: "LeftArm",
|
|
6458
|
+
LEFTARM: "LeftArm",
|
|
6459
|
+
RightArm: "RightArm",
|
|
6460
|
+
rightArm: "RightArm",
|
|
6461
|
+
RIGHTARM: "RightArm",
|
|
6462
|
+
LeftForeArm: "LeftForeArm",
|
|
6463
|
+
leftForeArm: "LeftForeArm",
|
|
6464
|
+
leftForearm: "LeftForeArm",
|
|
6465
|
+
LeftForearm: "LeftForeArm",
|
|
6466
|
+
RightForeArm: "RightForeArm",
|
|
6467
|
+
rightForeArm: "RightForeArm",
|
|
6468
|
+
rightForearm: "RightForeArm",
|
|
6469
|
+
RightForearm: "RightForeArm",
|
|
6470
|
+
LeftHand: "LeftHand",
|
|
6471
|
+
leftHand: "LeftHand",
|
|
6472
|
+
RightHand: "RightHand",
|
|
6473
|
+
rightHand: "RightHand",
|
|
6474
|
+
LeftShoulder: "LeftShoulder",
|
|
6475
|
+
leftShoulder: "LeftShoulder",
|
|
6476
|
+
RightShoulder: "RightShoulder",
|
|
6477
|
+
rightShoulder: "RightShoulder",
|
|
6478
|
+
// Spine
|
|
6479
|
+
Spine: "Spine1",
|
|
6480
|
+
spine: "Spine1",
|
|
6481
|
+
Spine1: "Spine1",
|
|
6482
|
+
Spine2: "Spine2",
|
|
6483
|
+
// Head/Neck
|
|
6484
|
+
Head: "Head",
|
|
6485
|
+
head: "Head",
|
|
6486
|
+
Neck: "Neck",
|
|
6487
|
+
neck: "Neck",
|
|
6488
|
+
// Hips
|
|
6489
|
+
Hips: "Hips",
|
|
6490
|
+
hips: "Hips",
|
|
6491
|
+
Root: "Hips",
|
|
6492
|
+
root: "Hips"
|
|
6493
|
+
};
|
|
6494
|
+
if (H[y]) {
|
|
6495
|
+
const w = H[y];
|
|
6496
|
+
if (d.has(w))
|
|
6497
|
+
return w;
|
|
6498
|
+
}
|
|
6499
|
+
for (const w of d)
|
|
6500
|
+
if (w.toLowerCase() === y.toLowerCase())
|
|
6501
|
+
return w;
|
|
6502
|
+
return null;
|
|
6503
|
+
}, x = /* @__PURE__ */ new Set();
|
|
6504
|
+
c.tracks.forEach((I) => {
|
|
6505
|
+
const y = I.name.split(".");
|
|
6506
|
+
x.add(y[0]);
|
|
6507
|
+
}), console.log("Ready Player Me FBX bone names:", Array.from(x).sort().join(", ")), console.log("Avatar skeleton bone names:", Array.from(d).sort().join(", "));
|
|
6508
|
+
const A = [], B = /* @__PURE__ */ new Set();
|
|
6509
|
+
c.tracks.forEach((I) => {
|
|
6510
|
+
const H = I.name.replaceAll("mixamorig", "").split("."), w = H[0], D = H[1], $ = b(w);
|
|
6511
|
+
if ($ && D) {
|
|
6512
|
+
const k = `${$}.${D}`, V = I.clone();
|
|
6513
|
+
V.name = k, A.push(V), w !== $ && g.set(w, $);
|
|
6514
|
+
} else
|
|
6515
|
+
B.add(w), (w.toLowerCase().includes("arm") || w.toLowerCase().includes("hand") || w.toLowerCase().includes("shoulder")) && console.warn(`⚠️ Arm bone "${w}" could not be mapped to avatar skeleton`);
|
|
6516
|
+
}), B.size > 0 && console.warn(`⚠️ ${B.size} bone(s) could not be mapped:`, Array.from(B).sort().join(", ")), A.length > 0 && (c = new f.AnimationClip(c.name, c.duration, A), g.size > 0 && console.log(
|
|
6517
|
+
`Mapped ${g.size} bone(s) for Ready Player Me animation:`,
|
|
6518
|
+
Array.from(g.entries()).slice(0, 5).map(([I, y]) => `${I}→${y}`).join(", ")
|
|
6519
|
+
));
|
|
6520
|
+
const p = {};
|
|
6723
6521
|
c.tracks.forEach((I) => {
|
|
6724
6522
|
I.name = I.name.replaceAll("mixamorig", "");
|
|
6725
|
-
const
|
|
6726
|
-
if (
|
|
6727
|
-
for (let
|
|
6728
|
-
I.values[
|
|
6729
|
-
|
|
6730
|
-
} else
|
|
6523
|
+
const y = I.name.split(".");
|
|
6524
|
+
if (y[1] === "position") {
|
|
6525
|
+
for (let H = 0; H < I.values.length; H++)
|
|
6526
|
+
I.values[H] = I.values[H] * s;
|
|
6527
|
+
p[I.name] = new f.Vector3(I.values[0], I.values[1], I.values[2]);
|
|
6528
|
+
} else y[1] === "quaternion" ? p[I.name] = new f.Quaternion(I.values[0], I.values[1], I.values[2], I.values[3]) : y[1] === "rotation" && (p[y[0] + ".quaternion"] = new f.Quaternion().setFromEuler(new f.Euler(I.values[0], I.values[1], I.values[2], "XYZ")).normalize());
|
|
6731
6529
|
});
|
|
6732
|
-
const
|
|
6733
|
-
|
|
6530
|
+
const E = { props: p };
|
|
6531
|
+
p["Hips.position"] && (p["Hips.position"].y < 0.5 ? E.lying = !0 : E.standing = !0), this.animClips.push({
|
|
6734
6532
|
url: t + "-" + i,
|
|
6735
6533
|
clip: c,
|
|
6736
|
-
pose:
|
|
6534
|
+
pose: E
|
|
6737
6535
|
}), this.playAnimation(t, e, n, i, s);
|
|
6738
6536
|
} else {
|
|
6739
6537
|
const c = "Animation " + t + " (ndx=" + i + ") not found";
|
|
@@ -6763,25 +6561,25 @@ class Ne {
|
|
|
6763
6561
|
if (!this.armature) return;
|
|
6764
6562
|
let o = this.poseTemplates[t];
|
|
6765
6563
|
if (!o) {
|
|
6766
|
-
const l = this.animPoses.find((
|
|
6564
|
+
const l = this.animPoses.find((h) => h.url === t + "-" + i);
|
|
6767
6565
|
l && (o = l.pose);
|
|
6768
6566
|
}
|
|
6769
6567
|
if (o) {
|
|
6770
6568
|
this.poseName = t, this.mixer = null;
|
|
6771
|
-
let l = this.animQueue.find((
|
|
6569
|
+
let l = this.animQueue.find((h) => h.template.name === "pose");
|
|
6772
6570
|
l && (l.ts[0] = this.animClock + n * 1e3 + 2e3), this.setPoseFromTemplate(o);
|
|
6773
6571
|
} else {
|
|
6774
|
-
let
|
|
6775
|
-
if (
|
|
6776
|
-
let r =
|
|
6777
|
-
const
|
|
6572
|
+
let h = await new De().loadAsync(t, e);
|
|
6573
|
+
if (h && h.animations && h.animations[i]) {
|
|
6574
|
+
let r = h.animations[i];
|
|
6575
|
+
const u = {};
|
|
6778
6576
|
r.tracks.forEach((c) => {
|
|
6779
6577
|
c.name = c.name.replaceAll("mixamorig", "");
|
|
6780
6578
|
const d = c.name.split(".");
|
|
6781
|
-
d[1] === "position" ?
|
|
6579
|
+
d[1] === "position" ? u[c.name] = new f.Vector3(c.values[0] * s, c.values[1] * s, c.values[2] * s) : d[1] === "quaternion" ? u[c.name] = new f.Quaternion(c.values[0], c.values[1], c.values[2], c.values[3]) : d[1] === "rotation" && (u[d[0] + ".quaternion"] = new f.Quaternion().setFromEuler(new f.Euler(c.values[0], c.values[1], c.values[2], "XYZ")).normalize());
|
|
6782
6580
|
});
|
|
6783
|
-
const a = { props:
|
|
6784
|
-
|
|
6581
|
+
const a = { props: u };
|
|
6582
|
+
u["Hips.position"] && (u["Hips.position"].y < 0.5 ? a.lying = !0 : a.standing = !0), this.animPoses.push({
|
|
6785
6583
|
url: t + "-" + i,
|
|
6786
6584
|
pose: a
|
|
6787
6585
|
}), this.playPose(t, e, n, i, s);
|
|
@@ -6810,10 +6608,10 @@ class Ne {
|
|
|
6810
6608
|
let s = this.gestureTemplates[t];
|
|
6811
6609
|
if (s) {
|
|
6812
6610
|
this.gestureTimeout && (clearTimeout(this.gestureTimeout), this.gestureTimeout = null);
|
|
6813
|
-
let l = this.animQueue.findIndex((
|
|
6814
|
-
l !== -1 && (this.animQueue[l].ts = this.animQueue[l].ts.map((
|
|
6815
|
-
for (let [
|
|
6816
|
-
r.t = this.animClock, r.d = i, this.poseTarget.props.hasOwnProperty(
|
|
6611
|
+
let l = this.animQueue.findIndex((h) => h.template.name === "talkinghands");
|
|
6612
|
+
l !== -1 && (this.animQueue[l].ts = this.animQueue[l].ts.map((h) => 0)), this.gesture = this.propsToThreeObjects(s), n && (this.gesture = this.mirrorPose(this.gesture)), t === "namaste" && this.avatar.body === "M" && (this.gesture["RightArm.quaternion"].rotateTowards(new f.Quaternion(0, 1, 0, 0), -0.25), this.gesture["LeftArm.quaternion"].rotateTowards(new f.Quaternion(0, 1, 0, 0), -0.25));
|
|
6613
|
+
for (let [h, r] of Object.entries(this.gesture))
|
|
6614
|
+
r.t = this.animClock, r.d = i, this.poseTarget.props.hasOwnProperty(h) && (this.poseTarget.props[h].copy(r), this.poseTarget.props[h].t = this.animClock, this.poseTarget.props[h].d = i);
|
|
6817
6615
|
e && Number.isFinite(e) && (this.gestureTimeout = setTimeout(this.stopGesture.bind(this, i), 1e3 * e));
|
|
6818
6616
|
}
|
|
6819
6617
|
let o = this.animEmojis[t];
|
|
@@ -6821,15 +6619,15 @@ class Ne {
|
|
|
6821
6619
|
this.lookAtCamera(500);
|
|
6822
6620
|
const l = this.animFactory(o);
|
|
6823
6621
|
if (l.gesture = !0, e && Number.isFinite(e)) {
|
|
6824
|
-
const
|
|
6825
|
-
if (e * 1e3 -
|
|
6622
|
+
const h = l.ts[0], u = l.ts[l.ts.length - 1] - h;
|
|
6623
|
+
if (e * 1e3 - u > 0) {
|
|
6826
6624
|
const c = [];
|
|
6827
|
-
for (let
|
|
6828
|
-
const d = o.template?.rescale || c.map((
|
|
6829
|
-
l.ts = l.ts.map((
|
|
6625
|
+
for (let b = 1; b < l.ts.length; b++) c.push(l.ts[b] - l.ts[b - 1]);
|
|
6626
|
+
const d = o.template?.rescale || c.map((b) => b / u), g = e * 1e3 - u;
|
|
6627
|
+
l.ts = l.ts.map((b, x, A) => x === 0 ? h : A[x - 1] + c[x - 1] + d[x - 1] * g);
|
|
6830
6628
|
} else {
|
|
6831
|
-
const c = e * 1e3 /
|
|
6832
|
-
l.ts = l.ts.map((d) =>
|
|
6629
|
+
const c = e * 1e3 / u;
|
|
6630
|
+
l.ts = l.ts.map((d) => h + c * (d - h));
|
|
6833
6631
|
}
|
|
6834
6632
|
}
|
|
6835
6633
|
this.animQueue.push(l);
|
|
@@ -6859,34 +6657,34 @@ class Ne {
|
|
|
6859
6657
|
* @param {numeric} [d=null] If set, apply in d milliseconds
|
|
6860
6658
|
*/
|
|
6861
6659
|
ikSolve(t, e = null, n = !1, i = null) {
|
|
6862
|
-
const s = new f.Vector3(), o = new f.Vector3(), l = new f.Vector3(),
|
|
6660
|
+
const s = new f.Vector3(), o = new f.Vector3(), l = new f.Vector3(), h = new f.Vector3(), r = new f.Quaternion(), u = new f.Vector3(), a = new f.Vector3(), c = new f.Vector3(), d = this.ikMesh.getObjectByName(t.root);
|
|
6863
6661
|
d.position.setFromMatrixPosition(this.armature.getObjectByName(t.root).matrixWorld), d.quaternion.setFromRotationMatrix(this.armature.getObjectByName(t.root).matrixWorld), e && n && e.applyQuaternion(this.armature.quaternion).add(d.position);
|
|
6864
|
-
const g = this.ikMesh.getObjectByName(t.effector),
|
|
6865
|
-
|
|
6866
|
-
|
|
6662
|
+
const g = this.ikMesh.getObjectByName(t.effector), b = t.links;
|
|
6663
|
+
b.forEach((A) => {
|
|
6664
|
+
A.bone = this.ikMesh.getObjectByName(A.link), A.bone.quaternion.copy(this.getPoseTemplateProp(A.link + ".quaternion"));
|
|
6867
6665
|
}), d.updateMatrixWorld(!0);
|
|
6868
|
-
const
|
|
6666
|
+
const x = t.iterations || 10;
|
|
6869
6667
|
if (e)
|
|
6870
|
-
for (let
|
|
6871
|
-
let
|
|
6872
|
-
for (let
|
|
6873
|
-
const
|
|
6874
|
-
|
|
6668
|
+
for (let A = 0; A < x; A++) {
|
|
6669
|
+
let B = !1;
|
|
6670
|
+
for (let p = 0, E = b.length; p < E; p++) {
|
|
6671
|
+
const I = b[p].bone;
|
|
6672
|
+
I.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();
|
|
6875
6673
|
let y = s.dot(l);
|
|
6876
|
-
y > 1 ? y = 1 : y < -1 && (y = -1), y = Math.acos(y), !(y < 1e-5) && (
|
|
6877
|
-
|
|
6878
|
-
|
|
6879
|
-
|
|
6674
|
+
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(), Q.setFromAxisAngle(a, y), I.quaternion.multiply(Q), I.rotation.setFromVector3(c.setFromEuler(I.rotation).clamp(new f.Vector3(
|
|
6675
|
+
b[p].minx !== void 0 ? b[p].minx : -1 / 0,
|
|
6676
|
+
b[p].miny !== void 0 ? b[p].miny : -1 / 0,
|
|
6677
|
+
b[p].minz !== void 0 ? b[p].minz : -1 / 0
|
|
6880
6678
|
), new f.Vector3(
|
|
6881
|
-
|
|
6882
|
-
|
|
6883
|
-
|
|
6884
|
-
))),
|
|
6679
|
+
b[p].maxx !== void 0 ? b[p].maxx : 1 / 0,
|
|
6680
|
+
b[p].maxy !== void 0 ? b[p].maxy : 1 / 0,
|
|
6681
|
+
b[p].maxz !== void 0 ? b[p].maxz : 1 / 0
|
|
6682
|
+
))), I.updateMatrixWorld(!0), B = !0);
|
|
6885
6683
|
}
|
|
6886
|
-
if (!
|
|
6684
|
+
if (!B) break;
|
|
6887
6685
|
}
|
|
6888
|
-
i &&
|
|
6889
|
-
this.poseTarget.props[
|
|
6686
|
+
i && b.forEach((A) => {
|
|
6687
|
+
this.poseTarget.props[A.link + ".quaternion"].copy(A.bone.quaternion), this.poseTarget.props[A.link + ".quaternion"].t = this.animClock, this.poseTarget.props[A.link + ".quaternion"].d = i;
|
|
6890
6688
|
});
|
|
6891
6689
|
}
|
|
6892
6690
|
/**
|
|
@@ -6946,16 +6744,16 @@ function Fe() {
|
|
|
6946
6744
|
};
|
|
6947
6745
|
}
|
|
6948
6746
|
function kt() {
|
|
6949
|
-
const
|
|
6950
|
-
return Object.entries(
|
|
6747
|
+
const Z = Fe(), t = [];
|
|
6748
|
+
return Object.entries(Z.voices).forEach(([e, n]) => {
|
|
6951
6749
|
t.push({
|
|
6952
6750
|
value: n,
|
|
6953
|
-
label: `${e.charAt(0).toUpperCase() + e.slice(1)} (${
|
|
6751
|
+
label: `${e.charAt(0).toUpperCase() + e.slice(1)} (${Z.service})`
|
|
6954
6752
|
});
|
|
6955
6753
|
}), t;
|
|
6956
6754
|
}
|
|
6957
6755
|
const Ve = Me(({
|
|
6958
|
-
avatarUrl:
|
|
6756
|
+
avatarUrl: Z = "/avatars/brunette.glb",
|
|
6959
6757
|
avatarBody: t = "F",
|
|
6960
6758
|
mood: e = "neutral",
|
|
6961
6759
|
ttsLang: n = "en",
|
|
@@ -6963,9 +6761,9 @@ const Ve = Me(({
|
|
|
6963
6761
|
ttsVoice: s = null,
|
|
6964
6762
|
ttsApiKey: o = null,
|
|
6965
6763
|
bodyMovement: l = "idle",
|
|
6966
|
-
movementIntensity:
|
|
6764
|
+
movementIntensity: h = 0.5,
|
|
6967
6765
|
showFullAvatar: r = !0,
|
|
6968
|
-
cameraView:
|
|
6766
|
+
cameraView: u = "upper",
|
|
6969
6767
|
onReady: a = () => {
|
|
6970
6768
|
},
|
|
6971
6769
|
onLoading: c = () => {
|
|
@@ -6973,14 +6771,14 @@ const Ve = Me(({
|
|
|
6973
6771
|
onError: d = () => {
|
|
6974
6772
|
},
|
|
6975
6773
|
className: g = "",
|
|
6976
|
-
style:
|
|
6977
|
-
animations:
|
|
6978
|
-
},
|
|
6979
|
-
const
|
|
6774
|
+
style: b = {},
|
|
6775
|
+
animations: x = {}
|
|
6776
|
+
}, A) => {
|
|
6777
|
+
const B = O(null), p = O(null), E = O(r), I = O(null), y = O(null), H = O(!1), w = O({ remainingText: null, originalText: null, options: null }), D = O([]), $ = O(0), [k, V] = ce(!0), [K, X] = ce(null), [ee, se] = ce(!1), [ae, pe] = ce(!1);
|
|
6980
6778
|
de(() => {
|
|
6981
|
-
|
|
6779
|
+
H.current = ae;
|
|
6982
6780
|
}, [ae]), de(() => {
|
|
6983
|
-
|
|
6781
|
+
E.current = r;
|
|
6984
6782
|
}, [r]);
|
|
6985
6783
|
const te = Fe(), le = i || te.service;
|
|
6986
6784
|
let U;
|
|
@@ -7006,8 +6804,8 @@ const Ve = Me(({
|
|
|
7006
6804
|
// Override API key if provided via props
|
|
7007
6805
|
apiKey: o !== null ? o : te.apiKey
|
|
7008
6806
|
};
|
|
7009
|
-
const
|
|
7010
|
-
url:
|
|
6807
|
+
const v = {
|
|
6808
|
+
url: Z,
|
|
7011
6809
|
body: t,
|
|
7012
6810
|
avatarMood: e,
|
|
7013
6811
|
ttsLang: le === "browser" ? "en-US" : n,
|
|
@@ -7015,269 +6813,269 @@ const Ve = Me(({
|
|
|
7015
6813
|
lipsyncLang: "en",
|
|
7016
6814
|
showFullAvatar: r,
|
|
7017
6815
|
bodyMovement: l,
|
|
7018
|
-
movementIntensity:
|
|
7019
|
-
},
|
|
6816
|
+
movementIntensity: h
|
|
6817
|
+
}, R = {
|
|
7020
6818
|
ttsEndpoint: U.endpoint,
|
|
7021
6819
|
ttsApikey: U.apiKey,
|
|
7022
6820
|
ttsService: le,
|
|
7023
6821
|
lipsyncModules: ["en"],
|
|
7024
|
-
cameraView:
|
|
7025
|
-
},
|
|
7026
|
-
if (!(!
|
|
6822
|
+
cameraView: u
|
|
6823
|
+
}, z = F(async () => {
|
|
6824
|
+
if (!(!B.current || p.current))
|
|
7027
6825
|
try {
|
|
7028
|
-
if (
|
|
7029
|
-
if (
|
|
7030
|
-
const
|
|
7031
|
-
c(
|
|
6826
|
+
if (V(!0), X(null), p.current = new Be(B.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, (N) => {
|
|
6827
|
+
if (N.lengthComputable) {
|
|
6828
|
+
const J = Math.min(100, Math.round(N.loaded / N.total * 100));
|
|
6829
|
+
c(J);
|
|
7032
6830
|
}
|
|
7033
|
-
}), await new Promise((
|
|
7034
|
-
const
|
|
7035
|
-
|
|
6831
|
+
}), await new Promise((N) => {
|
|
6832
|
+
const J = () => {
|
|
6833
|
+
p.current.lipsync && Object.keys(p.current.lipsync).length > 0 ? N() : setTimeout(J, 100);
|
|
7036
6834
|
};
|
|
7037
|
-
|
|
7038
|
-
}),
|
|
6835
|
+
J();
|
|
6836
|
+
}), p.current && p.current.setShowFullAvatar)
|
|
7039
6837
|
try {
|
|
7040
|
-
|
|
7041
|
-
} catch (
|
|
7042
|
-
console.warn("Error setting full body mode on initialization:",
|
|
6838
|
+
p.current.setShowFullAvatar(r);
|
|
6839
|
+
} catch (N) {
|
|
6840
|
+
console.warn("Error setting full body mode on initialization:", N);
|
|
7043
6841
|
}
|
|
7044
|
-
|
|
7045
|
-
const
|
|
7046
|
-
document.visibilityState === "visible" ?
|
|
6842
|
+
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()), V(!1), se(!0), a(p.current);
|
|
6843
|
+
const P = () => {
|
|
6844
|
+
document.visibilityState === "visible" ? p.current?.start() : p.current?.stop();
|
|
7047
6845
|
};
|
|
7048
|
-
return document.addEventListener("visibilitychange",
|
|
7049
|
-
document.removeEventListener("visibilitychange",
|
|
6846
|
+
return document.addEventListener("visibilitychange", P), () => {
|
|
6847
|
+
document.removeEventListener("visibilitychange", P);
|
|
7050
6848
|
};
|
|
7051
6849
|
} catch (L) {
|
|
7052
|
-
console.error("Error initializing TalkingHead:", L),
|
|
6850
|
+
console.error("Error initializing TalkingHead:", L), X(L.message || "Failed to initialize avatar"), V(!1), d(L);
|
|
7053
6851
|
}
|
|
7054
|
-
}, [
|
|
7055
|
-
de(() => (
|
|
7056
|
-
|
|
7057
|
-
}), [
|
|
7058
|
-
if (!
|
|
7059
|
-
const L = new ResizeObserver((
|
|
7060
|
-
for (const
|
|
7061
|
-
|
|
6852
|
+
}, [Z, t, e, n, i, s, o, r, l, h, u]);
|
|
6853
|
+
de(() => (z(), () => {
|
|
6854
|
+
p.current && (p.current.stop(), p.current.dispose(), p.current = null);
|
|
6855
|
+
}), [z]), de(() => {
|
|
6856
|
+
if (!B.current || !p.current) return;
|
|
6857
|
+
const L = new ResizeObserver((N) => {
|
|
6858
|
+
for (const J of N)
|
|
6859
|
+
p.current && p.current.onResize && p.current.onResize();
|
|
7062
6860
|
});
|
|
7063
|
-
L.observe(
|
|
7064
|
-
const
|
|
7065
|
-
|
|
6861
|
+
L.observe(B.current);
|
|
6862
|
+
const P = () => {
|
|
6863
|
+
p.current && p.current.onResize && p.current.onResize();
|
|
7066
6864
|
};
|
|
7067
|
-
return window.addEventListener("resize",
|
|
7068
|
-
L.disconnect(), window.removeEventListener("resize",
|
|
6865
|
+
return window.addEventListener("resize", P), () => {
|
|
6866
|
+
L.disconnect(), window.removeEventListener("resize", P);
|
|
7069
6867
|
};
|
|
7070
6868
|
}, [ee]);
|
|
7071
|
-
const
|
|
7072
|
-
if (
|
|
6869
|
+
const M = F(async () => {
|
|
6870
|
+
if (p.current && p.current.audioCtx)
|
|
7073
6871
|
try {
|
|
7074
|
-
(
|
|
6872
|
+
(p.current.audioCtx.state === "suspended" || p.current.audioCtx.state === "interrupted") && (await p.current.audioCtx.resume(), console.log("Audio context resumed"));
|
|
7075
6873
|
} catch (L) {
|
|
7076
6874
|
console.warn("Failed to resume audio context:", L);
|
|
7077
6875
|
}
|
|
7078
|
-
}, []), W = F(async (L,
|
|
7079
|
-
if (
|
|
6876
|
+
}, []), W = F(async (L, P = {}) => {
|
|
6877
|
+
if (p.current && ee)
|
|
7080
6878
|
try {
|
|
7081
|
-
y.current && (clearInterval(y.current), y.current = null),
|
|
7082
|
-
const
|
|
7083
|
-
D.current =
|
|
6879
|
+
y.current && (clearInterval(y.current), y.current = null), I.current = { text: L, options: P }, w.current = { remainingText: null, originalText: null, options: null };
|
|
6880
|
+
const N = /[!\.\?\n\p{Extended_Pictographic}]/ug, J = L.split(N).map((Y) => Y.trim()).filter((Y) => Y.length > 0);
|
|
6881
|
+
D.current = J, $.current = 0, pe(!1), H.current = !1, await M();
|
|
7084
6882
|
const ge = {
|
|
7085
|
-
...
|
|
7086
|
-
lipsyncLang:
|
|
6883
|
+
...P,
|
|
6884
|
+
lipsyncLang: P.lipsyncLang || v.lipsyncLang || "en"
|
|
7087
6885
|
};
|
|
7088
|
-
if (
|
|
7089
|
-
const Y =
|
|
7090
|
-
let
|
|
6886
|
+
if (P.onSpeechEnd && p.current) {
|
|
6887
|
+
const Y = p.current;
|
|
6888
|
+
let he = null, Se = 0;
|
|
7091
6889
|
const Ae = 1200;
|
|
7092
6890
|
let be = !1;
|
|
7093
|
-
|
|
7094
|
-
if (Se++,
|
|
6891
|
+
he = setInterval(() => {
|
|
6892
|
+
if (Se++, H.current)
|
|
7095
6893
|
return;
|
|
7096
6894
|
if (Se > Ae) {
|
|
7097
|
-
if (
|
|
6895
|
+
if (he && (clearInterval(he), he = null, y.current = null), !be && !H.current) {
|
|
7098
6896
|
be = !0;
|
|
7099
6897
|
try {
|
|
7100
|
-
|
|
7101
|
-
} catch (
|
|
7102
|
-
console.error("Error in onSpeechEnd callback (timeout):",
|
|
6898
|
+
P.onSpeechEnd();
|
|
6899
|
+
} catch (Ne) {
|
|
6900
|
+
console.error("Error in onSpeechEnd callback (timeout):", Ne);
|
|
7103
6901
|
}
|
|
7104
6902
|
}
|
|
7105
6903
|
return;
|
|
7106
6904
|
}
|
|
7107
6905
|
const ye = !Y.speechQueue || Y.speechQueue.length === 0, ke = !Y.audioPlaylist || Y.audioPlaylist.length === 0;
|
|
7108
|
-
Y && Y.isSpeaking === !1 && ye && ke && Y.isAudioPlaying === !1 && !be && !
|
|
7109
|
-
if (Y && !
|
|
7110
|
-
be = !0,
|
|
6906
|
+
Y && Y.isSpeaking === !1 && ye && ke && Y.isAudioPlaying === !1 && !be && !H.current && setTimeout(() => {
|
|
6907
|
+
if (Y && !H.current && Y.isSpeaking === !1 && (!Y.speechQueue || Y.speechQueue.length === 0) && (!Y.audioPlaylist || Y.audioPlaylist.length === 0) && Y.isAudioPlaying === !1 && !be && !H.current) {
|
|
6908
|
+
be = !0, he && (clearInterval(he), he = null, y.current = null);
|
|
7111
6909
|
try {
|
|
7112
|
-
|
|
6910
|
+
P.onSpeechEnd();
|
|
7113
6911
|
} catch (Ze) {
|
|
7114
6912
|
console.error("Error in onSpeechEnd callback:", Ze);
|
|
7115
6913
|
}
|
|
7116
6914
|
}
|
|
7117
6915
|
}, 100);
|
|
7118
|
-
}, 100), y.current =
|
|
6916
|
+
}, 100), y.current = he;
|
|
7119
6917
|
}
|
|
7120
|
-
|
|
7121
|
-
await
|
|
6918
|
+
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 () => {
|
|
6919
|
+
await M(), p.current && p.current.lipsync && (p.current.setSlowdownRate && p.current.setSlowdownRate(1.05), p.current.speakText(L, ge));
|
|
7122
6920
|
}, 100);
|
|
7123
|
-
} catch (
|
|
7124
|
-
console.error("Error speaking text:",
|
|
6921
|
+
} catch (N) {
|
|
6922
|
+
console.error("Error speaking text:", N), X(N.message || "Failed to speak text");
|
|
7125
6923
|
}
|
|
7126
|
-
}, [ee,
|
|
7127
|
-
|
|
6924
|
+
}, [ee, M, v.lipsyncLang]), _ = F(() => {
|
|
6925
|
+
p.current && (p.current.stopSpeaking(), p.current.setSlowdownRate && p.current.setSlowdownRate(1), I.current = null, pe(!1));
|
|
7128
6926
|
}, []), j = F(() => {
|
|
7129
|
-
if (
|
|
7130
|
-
const L =
|
|
6927
|
+
if (p.current && p.current.pauseSpeaking) {
|
|
6928
|
+
const L = p.current;
|
|
7131
6929
|
if (L.isSpeaking || L.audioPlaylist && L.audioPlaylist.length > 0 || L.speechQueue && L.speechQueue.length > 0) {
|
|
7132
6930
|
y.current && (clearInterval(y.current), y.current = null);
|
|
7133
|
-
let
|
|
7134
|
-
if (
|
|
7135
|
-
const
|
|
7136
|
-
if (
|
|
6931
|
+
let N = "";
|
|
6932
|
+
if (I.current && D.current.length > 0) {
|
|
6933
|
+
const J = D.current.length, ge = L.speechQueue ? L.speechQueue.filter((Ae) => Ae && Ae.text && Array.isArray(Ae.text) && Ae.text.length > 0).length : 0, Y = L.audioPlaylist && L.audioPlaylist.length > 0, he = ge + (Y ? 1 : 0), Se = J - he;
|
|
6934
|
+
if (he > 0 && Se < J && (N = D.current.slice(Se).join(". ").trim(), !N && ge > 0 && L.speechQueue)) {
|
|
7137
6935
|
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(" ");
|
|
7138
|
-
be && be.trim() && (
|
|
6936
|
+
be && be.trim() && (N = be.trim());
|
|
7139
6937
|
}
|
|
7140
6938
|
}
|
|
7141
|
-
|
|
7142
|
-
remainingText:
|
|
7143
|
-
originalText:
|
|
7144
|
-
options:
|
|
7145
|
-
}), L.speechQueue && (L.speechQueue.length = 0),
|
|
6939
|
+
I.current && (w.current = {
|
|
6940
|
+
remainingText: N || null,
|
|
6941
|
+
originalText: I.current.text,
|
|
6942
|
+
options: I.current.options
|
|
6943
|
+
}), L.speechQueue && (L.speechQueue.length = 0), p.current.pauseSpeaking(), H.current = !0, pe(!0);
|
|
7146
6944
|
}
|
|
7147
6945
|
}
|
|
7148
6946
|
}, []), q = F(async () => {
|
|
7149
|
-
if (!
|
|
6947
|
+
if (!p.current || !ae)
|
|
7150
6948
|
return;
|
|
7151
|
-
let L = "",
|
|
7152
|
-
if (
|
|
7153
|
-
L =
|
|
7154
|
-
else if (
|
|
7155
|
-
L =
|
|
6949
|
+
let L = "", P = {};
|
|
6950
|
+
if (w.current && w.current.remainingText)
|
|
6951
|
+
L = w.current.remainingText, P = w.current.options || {}, w.current = { remainingText: null, originalText: null, options: null };
|
|
6952
|
+
else if (I.current && I.current.text)
|
|
6953
|
+
L = I.current.text, P = I.current.options || {};
|
|
7156
6954
|
else {
|
|
7157
|
-
console.warn("Resume called but no paused speech found"), pe(!1),
|
|
6955
|
+
console.warn("Resume called but no paused speech found"), pe(!1), H.current = !1;
|
|
7158
6956
|
return;
|
|
7159
6957
|
}
|
|
7160
|
-
pe(!1),
|
|
7161
|
-
const
|
|
7162
|
-
...
|
|
7163
|
-
lipsyncLang:
|
|
6958
|
+
pe(!1), H.current = !1, await M();
|
|
6959
|
+
const N = {
|
|
6960
|
+
...P,
|
|
6961
|
+
lipsyncLang: P.lipsyncLang || v.lipsyncLang || "en"
|
|
7164
6962
|
};
|
|
7165
6963
|
try {
|
|
7166
|
-
await W(L,
|
|
7167
|
-
} catch (
|
|
7168
|
-
console.error("Error resuming speech:",
|
|
6964
|
+
await W(L, N);
|
|
6965
|
+
} catch (J) {
|
|
6966
|
+
console.error("Error resuming speech:", J), pe(!1), H.current = !1;
|
|
7169
6967
|
}
|
|
7170
|
-
}, [
|
|
7171
|
-
|
|
6968
|
+
}, [M, ae, W, v]), Le = F((L) => {
|
|
6969
|
+
p.current && p.current.setMood(L);
|
|
7172
6970
|
}, []), we = F((L) => {
|
|
7173
|
-
|
|
7174
|
-
}, []),
|
|
7175
|
-
if (
|
|
7176
|
-
if (
|
|
6971
|
+
p.current && p.current.setSlowdownRate && p.current.setSlowdownRate(L);
|
|
6972
|
+
}, []), T = F((L, P = !1) => {
|
|
6973
|
+
if (p.current && p.current.playAnimation) {
|
|
6974
|
+
if (x && x[L] && (L = x[L]), p.current.setShowFullAvatar)
|
|
7177
6975
|
try {
|
|
7178
|
-
|
|
7179
|
-
} catch (
|
|
7180
|
-
console.warn("Error setting full body mode:",
|
|
6976
|
+
p.current.setShowFullAvatar(E.current);
|
|
6977
|
+
} catch (J) {
|
|
6978
|
+
console.warn("Error setting full body mode:", J);
|
|
7181
6979
|
}
|
|
7182
6980
|
if (L.includes("."))
|
|
7183
6981
|
try {
|
|
7184
|
-
|
|
7185
|
-
} catch (
|
|
7186
|
-
console.warn(`Failed to play ${L}:`,
|
|
6982
|
+
p.current.playAnimation(L, null, 10, 0, 0.01, P);
|
|
6983
|
+
} catch (J) {
|
|
6984
|
+
console.warn(`Failed to play ${L}:`, J);
|
|
7187
6985
|
try {
|
|
7188
|
-
|
|
6986
|
+
p.current.setBodyMovement("idle");
|
|
7189
6987
|
} catch (ge) {
|
|
7190
6988
|
console.warn("Fallback animation also failed:", ge);
|
|
7191
6989
|
}
|
|
7192
6990
|
}
|
|
7193
6991
|
else {
|
|
7194
|
-
const
|
|
6992
|
+
const J = [".fbx", ".glb", ".gltf"];
|
|
7195
6993
|
let ge = !1;
|
|
7196
|
-
for (const Y of
|
|
6994
|
+
for (const Y of J)
|
|
7197
6995
|
try {
|
|
7198
|
-
|
|
6996
|
+
p.current.playAnimation(L + Y, null, 10, 0, 0.01, P), ge = !0;
|
|
7199
6997
|
break;
|
|
7200
6998
|
} catch {
|
|
7201
6999
|
}
|
|
7202
7000
|
if (!ge) {
|
|
7203
7001
|
console.warn("Animation not found:", L);
|
|
7204
7002
|
try {
|
|
7205
|
-
|
|
7003
|
+
p.current.setBodyMovement("idle");
|
|
7206
7004
|
} catch (Y) {
|
|
7207
7005
|
console.warn("Fallback animation also failed:", Y);
|
|
7208
7006
|
}
|
|
7209
7007
|
}
|
|
7210
7008
|
}
|
|
7211
7009
|
}
|
|
7212
|
-
}, [
|
|
7213
|
-
|
|
7010
|
+
}, [x]), ne = F(() => {
|
|
7011
|
+
p.current && p.current.onResize && p.current.onResize();
|
|
7214
7012
|
}, []);
|
|
7215
|
-
return Ee(
|
|
7013
|
+
return Ee(A, () => ({
|
|
7216
7014
|
speakText: W,
|
|
7217
|
-
stopSpeaking:
|
|
7015
|
+
stopSpeaking: _,
|
|
7218
7016
|
pauseSpeaking: j,
|
|
7219
7017
|
resumeSpeaking: q,
|
|
7220
|
-
resumeAudioContext:
|
|
7018
|
+
resumeAudioContext: M,
|
|
7221
7019
|
setMood: Le,
|
|
7222
7020
|
setTimingAdjustment: we,
|
|
7223
|
-
playAnimation:
|
|
7021
|
+
playAnimation: T,
|
|
7224
7022
|
isReady: ee,
|
|
7225
7023
|
isPaused: ae,
|
|
7226
|
-
talkingHead:
|
|
7024
|
+
talkingHead: p.current,
|
|
7227
7025
|
handleResize: ne,
|
|
7228
7026
|
setBodyMovement: (L) => {
|
|
7229
|
-
if (
|
|
7027
|
+
if (p.current && p.current.setShowFullAvatar && p.current.setBodyMovement)
|
|
7230
7028
|
try {
|
|
7231
|
-
|
|
7232
|
-
} catch (
|
|
7233
|
-
console.warn("Error setting body movement:",
|
|
7029
|
+
p.current.setShowFullAvatar(E.current), p.current.setBodyMovement(L);
|
|
7030
|
+
} catch (P) {
|
|
7031
|
+
console.warn("Error setting body movement:", P);
|
|
7234
7032
|
}
|
|
7235
7033
|
},
|
|
7236
|
-
setMovementIntensity: (L) =>
|
|
7034
|
+
setMovementIntensity: (L) => p.current?.setMovementIntensity(L),
|
|
7237
7035
|
playRandomDance: () => {
|
|
7238
|
-
if (
|
|
7036
|
+
if (p.current && p.current.setShowFullAvatar && p.current.playRandomDance)
|
|
7239
7037
|
try {
|
|
7240
|
-
|
|
7038
|
+
p.current.setShowFullAvatar(E.current), p.current.playRandomDance();
|
|
7241
7039
|
} catch (L) {
|
|
7242
7040
|
console.warn("Error playing random dance:", L);
|
|
7243
7041
|
}
|
|
7244
7042
|
},
|
|
7245
7043
|
playReaction: (L) => {
|
|
7246
|
-
if (
|
|
7044
|
+
if (p.current && p.current.setShowFullAvatar && p.current.playReaction)
|
|
7247
7045
|
try {
|
|
7248
|
-
|
|
7249
|
-
} catch (
|
|
7250
|
-
console.warn("Error playing reaction:",
|
|
7046
|
+
p.current.setShowFullAvatar(E.current), p.current.playReaction(L);
|
|
7047
|
+
} catch (P) {
|
|
7048
|
+
console.warn("Error playing reaction:", P);
|
|
7251
7049
|
}
|
|
7252
7050
|
},
|
|
7253
7051
|
playCelebration: () => {
|
|
7254
|
-
if (
|
|
7052
|
+
if (p.current && p.current.setShowFullAvatar && p.current.playCelebration)
|
|
7255
7053
|
try {
|
|
7256
|
-
|
|
7054
|
+
p.current.setShowFullAvatar(E.current), p.current.playCelebration();
|
|
7257
7055
|
} catch (L) {
|
|
7258
7056
|
console.warn("Error playing celebration:", L);
|
|
7259
7057
|
}
|
|
7260
7058
|
},
|
|
7261
7059
|
setShowFullAvatar: (L) => {
|
|
7262
|
-
if (
|
|
7060
|
+
if (p.current && p.current.setShowFullAvatar)
|
|
7263
7061
|
try {
|
|
7264
|
-
|
|
7265
|
-
} catch (
|
|
7266
|
-
console.warn("Error setting showFullAvatar:",
|
|
7062
|
+
E.current = L, p.current.setShowFullAvatar(L);
|
|
7063
|
+
} catch (P) {
|
|
7064
|
+
console.warn("Error setting showFullAvatar:", P);
|
|
7267
7065
|
}
|
|
7268
7066
|
},
|
|
7269
7067
|
lockAvatarPosition: () => {
|
|
7270
|
-
if (
|
|
7068
|
+
if (p.current && p.current.lockAvatarPosition)
|
|
7271
7069
|
try {
|
|
7272
|
-
|
|
7070
|
+
p.current.lockAvatarPosition();
|
|
7273
7071
|
} catch (L) {
|
|
7274
7072
|
console.warn("Error locking avatar position:", L);
|
|
7275
7073
|
}
|
|
7276
7074
|
},
|
|
7277
7075
|
unlockAvatarPosition: () => {
|
|
7278
|
-
if (
|
|
7076
|
+
if (p.current && p.current.unlockAvatarPosition)
|
|
7279
7077
|
try {
|
|
7280
|
-
|
|
7078
|
+
p.current.unlockAvatarPosition();
|
|
7281
7079
|
} catch (L) {
|
|
7282
7080
|
console.warn("Error unlocking avatar position:", L);
|
|
7283
7081
|
}
|
|
@@ -7290,13 +7088,13 @@ const Ve = Me(({
|
|
|
7290
7088
|
width: "100%",
|
|
7291
7089
|
height: "100%",
|
|
7292
7090
|
position: "relative",
|
|
7293
|
-
...
|
|
7091
|
+
...b
|
|
7294
7092
|
},
|
|
7295
7093
|
children: [
|
|
7296
7094
|
/* @__PURE__ */ me(
|
|
7297
7095
|
"div",
|
|
7298
7096
|
{
|
|
7299
|
-
ref:
|
|
7097
|
+
ref: B,
|
|
7300
7098
|
className: "talking-head-viewer",
|
|
7301
7099
|
style: {
|
|
7302
7100
|
width: "100%",
|
|
@@ -7305,7 +7103,7 @@ const Ve = Me(({
|
|
|
7305
7103
|
}
|
|
7306
7104
|
}
|
|
7307
7105
|
),
|
|
7308
|
-
|
|
7106
|
+
k && /* @__PURE__ */ me("div", { className: "loading-overlay", style: {
|
|
7309
7107
|
position: "absolute",
|
|
7310
7108
|
top: "50%",
|
|
7311
7109
|
left: "50%",
|
|
@@ -7314,7 +7112,7 @@ const Ve = Me(({
|
|
|
7314
7112
|
fontSize: "18px",
|
|
7315
7113
|
zIndex: 10
|
|
7316
7114
|
}, children: "Loading avatar..." }),
|
|
7317
|
-
|
|
7115
|
+
K && /* @__PURE__ */ me("div", { className: "error-overlay", style: {
|
|
7318
7116
|
position: "absolute",
|
|
7319
7117
|
top: "50%",
|
|
7320
7118
|
left: "50%",
|
|
@@ -7325,14 +7123,14 @@ const Ve = Me(({
|
|
|
7325
7123
|
zIndex: 10,
|
|
7326
7124
|
padding: "20px",
|
|
7327
7125
|
borderRadius: "8px"
|
|
7328
|
-
}, children:
|
|
7126
|
+
}, children: K })
|
|
7329
7127
|
]
|
|
7330
7128
|
}
|
|
7331
7129
|
);
|
|
7332
7130
|
});
|
|
7333
7131
|
Ve.displayName = "TalkingHeadAvatar";
|
|
7334
7132
|
const pt = Me(({
|
|
7335
|
-
text:
|
|
7133
|
+
text: Z = "Hello! I'm a talking avatar. How are you today?",
|
|
7336
7134
|
onLoading: t = () => {
|
|
7337
7135
|
},
|
|
7338
7136
|
onError: e = () => {
|
|
@@ -7343,23 +7141,23 @@ const pt = Me(({
|
|
|
7343
7141
|
style: s = {},
|
|
7344
7142
|
avatarConfig: o = {}
|
|
7345
7143
|
}, l) => {
|
|
7346
|
-
const
|
|
7144
|
+
const h = O(null), r = O(null), [u, a] = ce(!0), [c, d] = ce(null), [g, b] = ce(!1), x = Fe(), A = o.ttsService || x.service, B = A === "browser" ? {
|
|
7347
7145
|
endpoint: "",
|
|
7348
7146
|
apiKey: null,
|
|
7349
7147
|
defaultVoice: "Google US English"
|
|
7350
7148
|
} : {
|
|
7351
|
-
...
|
|
7149
|
+
...x,
|
|
7352
7150
|
// Override API key if provided via avatarConfig
|
|
7353
|
-
apiKey: o.ttsApiKey !== void 0 && o.ttsApiKey !== null ? o.ttsApiKey :
|
|
7151
|
+
apiKey: o.ttsApiKey !== void 0 && o.ttsApiKey !== null ? o.ttsApiKey : x.apiKey,
|
|
7354
7152
|
// Override endpoint for ElevenLabs if service is explicitly set
|
|
7355
|
-
endpoint:
|
|
7356
|
-
},
|
|
7153
|
+
endpoint: A === "elevenlabs" && o.ttsApiKey ? "https://api.elevenlabs.io/v1/text-to-speech" : x.endpoint
|
|
7154
|
+
}, p = {
|
|
7357
7155
|
url: "/avatars/brunette.glb",
|
|
7358
7156
|
// Use brunette avatar (working glTF file)
|
|
7359
7157
|
body: "F",
|
|
7360
7158
|
avatarMood: "neutral",
|
|
7361
|
-
ttsLang:
|
|
7362
|
-
ttsVoice: o.ttsVoice ||
|
|
7159
|
+
ttsLang: A === "browser" ? "en-US" : "en",
|
|
7160
|
+
ttsVoice: o.ttsVoice || B.defaultVoice,
|
|
7363
7161
|
lipsyncLang: "en",
|
|
7364
7162
|
// English lip-sync
|
|
7365
7163
|
showFullAvatar: !0,
|
|
@@ -7367,81 +7165,81 @@ const pt = Me(({
|
|
|
7367
7165
|
bodyMovement: "idle",
|
|
7368
7166
|
movementIntensity: 0.5,
|
|
7369
7167
|
...o
|
|
7370
|
-
},
|
|
7371
|
-
ttsEndpoint:
|
|
7372
|
-
ttsApikey:
|
|
7373
|
-
ttsService:
|
|
7168
|
+
}, E = {
|
|
7169
|
+
ttsEndpoint: B.endpoint,
|
|
7170
|
+
ttsApikey: B.apiKey,
|
|
7171
|
+
ttsService: A,
|
|
7374
7172
|
lipsyncModules: ["en"],
|
|
7375
7173
|
cameraView: "upper"
|
|
7376
|
-
},
|
|
7377
|
-
if (!(!
|
|
7174
|
+
}, I = F(async () => {
|
|
7175
|
+
if (!(!h.current || r.current))
|
|
7378
7176
|
try {
|
|
7379
|
-
if (a(!0), d(null), r.current = new
|
|
7380
|
-
if (
|
|
7381
|
-
const
|
|
7382
|
-
t(
|
|
7177
|
+
if (a(!0), d(null), r.current = new Be(h.current, E), await r.current.showAvatar(p, (K) => {
|
|
7178
|
+
if (K.lengthComputable) {
|
|
7179
|
+
const X = Math.min(100, Math.round(K.loaded / K.total * 100));
|
|
7180
|
+
t(X);
|
|
7383
7181
|
}
|
|
7384
7182
|
}), r.current.morphs && r.current.morphs.length > 0) {
|
|
7385
|
-
const
|
|
7386
|
-
console.log("Available morph targets:", Object.keys(
|
|
7387
|
-
const
|
|
7388
|
-
console.log("Viseme morph targets found:",
|
|
7183
|
+
const K = r.current.morphs[0].morphTargetDictionary;
|
|
7184
|
+
console.log("Available morph targets:", Object.keys(K));
|
|
7185
|
+
const X = Object.keys(K).filter((ee) => ee.startsWith("viseme_"));
|
|
7186
|
+
console.log("Viseme morph targets found:", X), X.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"));
|
|
7389
7187
|
}
|
|
7390
|
-
if (await new Promise((
|
|
7391
|
-
const
|
|
7392
|
-
r.current.lipsync && Object.keys(r.current.lipsync).length > 0 ? (console.log("Lip-sync modules loaded:", Object.keys(r.current.lipsync)),
|
|
7188
|
+
if (await new Promise((K) => {
|
|
7189
|
+
const X = () => {
|
|
7190
|
+
r.current.lipsync && Object.keys(r.current.lipsync).length > 0 ? (console.log("Lip-sync modules loaded:", Object.keys(r.current.lipsync)), K()) : (console.log("Waiting for lip-sync modules to load..."), setTimeout(X, 100));
|
|
7393
7191
|
};
|
|
7394
|
-
|
|
7192
|
+
X();
|
|
7395
7193
|
}), r.current && r.current.setShowFullAvatar)
|
|
7396
7194
|
try {
|
|
7397
7195
|
r.current.setShowFullAvatar(!0), console.log("Avatar initialized in full body mode");
|
|
7398
|
-
} catch (
|
|
7399
|
-
console.warn("Error setting full body mode on initialization:",
|
|
7196
|
+
} catch (K) {
|
|
7197
|
+
console.warn("Error setting full body mode on initialization:", K);
|
|
7400
7198
|
}
|
|
7401
|
-
a(!1),
|
|
7402
|
-
const
|
|
7199
|
+
a(!1), b(!0), n(r.current);
|
|
7200
|
+
const V = () => {
|
|
7403
7201
|
document.visibilityState === "visible" ? r.current?.start() : r.current?.stop();
|
|
7404
7202
|
};
|
|
7405
|
-
return document.addEventListener("visibilitychange",
|
|
7406
|
-
document.removeEventListener("visibilitychange",
|
|
7203
|
+
return document.addEventListener("visibilitychange", V), () => {
|
|
7204
|
+
document.removeEventListener("visibilitychange", V);
|
|
7407
7205
|
};
|
|
7408
|
-
} catch (
|
|
7409
|
-
console.error("Error initializing TalkingHead:",
|
|
7206
|
+
} catch (k) {
|
|
7207
|
+
console.error("Error initializing TalkingHead:", k), d(k.message || "Failed to initialize avatar"), a(!1), e(k);
|
|
7410
7208
|
}
|
|
7411
7209
|
}, []);
|
|
7412
|
-
de(() => (
|
|
7210
|
+
de(() => (I(), () => {
|
|
7413
7211
|
r.current && (r.current.stop(), r.current.dispose(), r.current = null);
|
|
7414
|
-
}), [
|
|
7415
|
-
const y = F((
|
|
7212
|
+
}), [I]);
|
|
7213
|
+
const y = F((k) => {
|
|
7416
7214
|
if (r.current && g)
|
|
7417
7215
|
try {
|
|
7418
|
-
console.log("Speaking text:",
|
|
7419
|
-
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(
|
|
7216
|
+
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(() => {
|
|
7217
|
+
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");
|
|
7420
7218
|
}, 500));
|
|
7421
|
-
} catch (
|
|
7422
|
-
console.error("Error speaking text:",
|
|
7219
|
+
} catch (V) {
|
|
7220
|
+
console.error("Error speaking text:", V), d(V.message || "Failed to speak text");
|
|
7423
7221
|
}
|
|
7424
7222
|
else
|
|
7425
7223
|
console.warn("Avatar not ready for speaking. isReady:", g, "talkingHeadRef:", !!r.current);
|
|
7426
|
-
}, [g,
|
|
7224
|
+
}, [g, p]), H = F(() => {
|
|
7427
7225
|
r.current && (r.current.stopSpeaking(), r.current.setSlowdownRate && (r.current.setSlowdownRate(1), console.log("Reset timing to normal")));
|
|
7428
|
-
}, []),
|
|
7429
|
-
r.current && r.current.setMood(
|
|
7430
|
-
}, []), D = F((
|
|
7431
|
-
r.current && r.current.setSlowdownRate && (r.current.setSlowdownRate(
|
|
7432
|
-
}, []),
|
|
7226
|
+
}, []), w = F((k) => {
|
|
7227
|
+
r.current && r.current.setMood(k);
|
|
7228
|
+
}, []), D = F((k) => {
|
|
7229
|
+
r.current && r.current.setSlowdownRate && (r.current.setSlowdownRate(k), console.log("Timing adjustment set to:", k));
|
|
7230
|
+
}, []), $ = F((k, V = !1) => {
|
|
7433
7231
|
if (r.current && r.current.playAnimation) {
|
|
7434
7232
|
if (r.current.setShowFullAvatar)
|
|
7435
7233
|
try {
|
|
7436
7234
|
r.current.setShowFullAvatar(!0);
|
|
7437
|
-
} catch (
|
|
7438
|
-
console.warn("Error setting full body mode:",
|
|
7235
|
+
} catch (X) {
|
|
7236
|
+
console.warn("Error setting full body mode:", X);
|
|
7439
7237
|
}
|
|
7440
|
-
if (
|
|
7238
|
+
if (k.includes("."))
|
|
7441
7239
|
try {
|
|
7442
|
-
r.current.playAnimation(
|
|
7443
|
-
} catch (
|
|
7444
|
-
console.log(`Failed to play ${
|
|
7240
|
+
r.current.playAnimation(k, null, 10, 0, 0.01, V), console.log("Playing animation:", k);
|
|
7241
|
+
} catch (X) {
|
|
7242
|
+
console.log(`Failed to play ${k}:`, X);
|
|
7445
7243
|
try {
|
|
7446
7244
|
r.current.setBodyMovement("idle"), console.log("Fallback to idle animation");
|
|
7447
7245
|
} catch (ee) {
|
|
@@ -7449,17 +7247,17 @@ const pt = Me(({
|
|
|
7449
7247
|
}
|
|
7450
7248
|
}
|
|
7451
7249
|
else {
|
|
7452
|
-
const
|
|
7250
|
+
const X = [".fbx", ".glb", ".gltf"];
|
|
7453
7251
|
let ee = !1;
|
|
7454
|
-
for (const se of
|
|
7252
|
+
for (const se of X)
|
|
7455
7253
|
try {
|
|
7456
|
-
r.current.playAnimation(
|
|
7254
|
+
r.current.playAnimation(k + se, null, 10, 0, 0.01, V), console.log("Playing animation:", k + se), ee = !0;
|
|
7457
7255
|
break;
|
|
7458
7256
|
} catch {
|
|
7459
|
-
console.log(`Failed to play ${
|
|
7257
|
+
console.log(`Failed to play ${k}${se}, trying next format...`);
|
|
7460
7258
|
}
|
|
7461
7259
|
if (!ee) {
|
|
7462
|
-
console.warn("Animation system not available or animation not found:",
|
|
7260
|
+
console.warn("Animation system not available or animation not found:", k);
|
|
7463
7261
|
try {
|
|
7464
7262
|
r.current.setBodyMovement("idle"), console.log("Fallback to idle animation");
|
|
7465
7263
|
} catch (se) {
|
|
@@ -7468,78 +7266,78 @@ const pt = Me(({
|
|
|
7468
7266
|
}
|
|
7469
7267
|
}
|
|
7470
7268
|
} else
|
|
7471
|
-
console.warn("Animation system not available or animation not found:",
|
|
7269
|
+
console.warn("Animation system not available or animation not found:", k);
|
|
7472
7270
|
}, []);
|
|
7473
7271
|
return Ee(l, () => ({
|
|
7474
7272
|
speakText: y,
|
|
7475
|
-
stopSpeaking:
|
|
7476
|
-
setMood:
|
|
7273
|
+
stopSpeaking: H,
|
|
7274
|
+
setMood: w,
|
|
7477
7275
|
setTimingAdjustment: D,
|
|
7478
|
-
playAnimation:
|
|
7276
|
+
playAnimation: $,
|
|
7479
7277
|
isReady: g,
|
|
7480
7278
|
talkingHead: r.current,
|
|
7481
|
-
setBodyMovement: (
|
|
7279
|
+
setBodyMovement: (k) => {
|
|
7482
7280
|
if (r.current && r.current.setShowFullAvatar && r.current.setBodyMovement)
|
|
7483
7281
|
try {
|
|
7484
|
-
r.current.setShowFullAvatar(!0), r.current.setBodyMovement(
|
|
7485
|
-
} catch (
|
|
7486
|
-
console.warn("Error setting body movement:",
|
|
7282
|
+
r.current.setShowFullAvatar(!0), r.current.setBodyMovement(k), console.log("Body movement set with full body mode:", k);
|
|
7283
|
+
} catch (V) {
|
|
7284
|
+
console.warn("Error setting body movement:", V);
|
|
7487
7285
|
}
|
|
7488
7286
|
},
|
|
7489
|
-
setMovementIntensity: (
|
|
7287
|
+
setMovementIntensity: (k) => r.current?.setMovementIntensity(k),
|
|
7490
7288
|
playRandomDance: () => {
|
|
7491
7289
|
if (r.current && r.current.setShowFullAvatar && r.current.playRandomDance)
|
|
7492
7290
|
try {
|
|
7493
7291
|
r.current.setShowFullAvatar(!0), r.current.playRandomDance(), console.log("Random dance played with full body mode");
|
|
7494
|
-
} catch (
|
|
7495
|
-
console.warn("Error playing random dance:",
|
|
7292
|
+
} catch (k) {
|
|
7293
|
+
console.warn("Error playing random dance:", k);
|
|
7496
7294
|
}
|
|
7497
7295
|
},
|
|
7498
|
-
playReaction: (
|
|
7296
|
+
playReaction: (k) => {
|
|
7499
7297
|
if (r.current && r.current.setShowFullAvatar && r.current.playReaction)
|
|
7500
7298
|
try {
|
|
7501
|
-
r.current.setShowFullAvatar(!0), r.current.playReaction(
|
|
7502
|
-
} catch (
|
|
7503
|
-
console.warn("Error playing reaction:",
|
|
7299
|
+
r.current.setShowFullAvatar(!0), r.current.playReaction(k), console.log("Reaction played with full body mode:", k);
|
|
7300
|
+
} catch (V) {
|
|
7301
|
+
console.warn("Error playing reaction:", V);
|
|
7504
7302
|
}
|
|
7505
7303
|
},
|
|
7506
7304
|
playCelebration: () => {
|
|
7507
7305
|
if (r.current && r.current.setShowFullAvatar && r.current.playCelebration)
|
|
7508
7306
|
try {
|
|
7509
7307
|
r.current.setShowFullAvatar(!0), r.current.playCelebration(), console.log("Celebration played with full body mode");
|
|
7510
|
-
} catch (
|
|
7511
|
-
console.warn("Error playing celebration:",
|
|
7308
|
+
} catch (k) {
|
|
7309
|
+
console.warn("Error playing celebration:", k);
|
|
7512
7310
|
}
|
|
7513
7311
|
},
|
|
7514
|
-
setShowFullAvatar: (
|
|
7312
|
+
setShowFullAvatar: (k) => {
|
|
7515
7313
|
if (r.current && r.current.setShowFullAvatar)
|
|
7516
7314
|
try {
|
|
7517
|
-
r.current.setShowFullAvatar(
|
|
7518
|
-
} catch (
|
|
7519
|
-
console.warn("Error setting showFullAvatar:",
|
|
7315
|
+
r.current.setShowFullAvatar(k), console.log("Show full avatar set to:", k);
|
|
7316
|
+
} catch (V) {
|
|
7317
|
+
console.warn("Error setting showFullAvatar:", V);
|
|
7520
7318
|
}
|
|
7521
7319
|
},
|
|
7522
7320
|
lockAvatarPosition: () => {
|
|
7523
7321
|
if (r.current && r.current.lockAvatarPosition)
|
|
7524
7322
|
try {
|
|
7525
7323
|
r.current.lockAvatarPosition();
|
|
7526
|
-
} catch (
|
|
7527
|
-
console.warn("Error locking avatar position:",
|
|
7324
|
+
} catch (k) {
|
|
7325
|
+
console.warn("Error locking avatar position:", k);
|
|
7528
7326
|
}
|
|
7529
7327
|
},
|
|
7530
7328
|
unlockAvatarPosition: () => {
|
|
7531
7329
|
if (r.current && r.current.unlockAvatarPosition)
|
|
7532
7330
|
try {
|
|
7533
7331
|
r.current.unlockAvatarPosition();
|
|
7534
|
-
} catch (
|
|
7535
|
-
console.warn("Error unlocking avatar position:",
|
|
7332
|
+
} catch (k) {
|
|
7333
|
+
console.warn("Error unlocking avatar position:", k);
|
|
7536
7334
|
}
|
|
7537
7335
|
}
|
|
7538
7336
|
})), /* @__PURE__ */ Pe("div", { className: `talking-head-container ${i}`, style: s, children: [
|
|
7539
7337
|
/* @__PURE__ */ me(
|
|
7540
7338
|
"div",
|
|
7541
7339
|
{
|
|
7542
|
-
ref:
|
|
7340
|
+
ref: h,
|
|
7543
7341
|
className: "talking-head-viewer",
|
|
7544
7342
|
style: {
|
|
7545
7343
|
width: "100%",
|
|
@@ -7548,7 +7346,7 @@ const pt = Me(({
|
|
|
7548
7346
|
}
|
|
7549
7347
|
}
|
|
7550
7348
|
),
|
|
7551
|
-
|
|
7349
|
+
u && /* @__PURE__ */ me("div", { className: "loading-overlay", style: {
|
|
7552
7350
|
position: "absolute",
|
|
7553
7351
|
top: "50%",
|
|
7554
7352
|
left: "50%",
|
|
@@ -7573,7 +7371,7 @@ const pt = Me(({
|
|
|
7573
7371
|
});
|
|
7574
7372
|
pt.displayName = "TalkingHeadComponent";
|
|
7575
7373
|
const gt = Me(({
|
|
7576
|
-
text:
|
|
7374
|
+
text: Z = null,
|
|
7577
7375
|
avatarUrl: t = "/avatars/brunette.glb",
|
|
7578
7376
|
avatarBody: e = "F",
|
|
7579
7377
|
mood: n = "neutral",
|
|
@@ -7581,9 +7379,9 @@ const gt = Me(({
|
|
|
7581
7379
|
ttsService: s = null,
|
|
7582
7380
|
ttsVoice: o = null,
|
|
7583
7381
|
ttsApiKey: l = null,
|
|
7584
|
-
bodyMovement:
|
|
7382
|
+
bodyMovement: h = "idle",
|
|
7585
7383
|
movementIntensity: r = 0.5,
|
|
7586
|
-
showFullAvatar:
|
|
7384
|
+
showFullAvatar: u = !1,
|
|
7587
7385
|
cameraView: a = "upper",
|
|
7588
7386
|
onReady: c = () => {
|
|
7589
7387
|
},
|
|
@@ -7591,173 +7389,173 @@ const gt = Me(({
|
|
|
7591
7389
|
},
|
|
7592
7390
|
onError: g = () => {
|
|
7593
7391
|
},
|
|
7594
|
-
onSpeechEnd:
|
|
7392
|
+
onSpeechEnd: b = () => {
|
|
7595
7393
|
},
|
|
7596
|
-
className:
|
|
7597
|
-
style:
|
|
7598
|
-
animations:
|
|
7599
|
-
autoSpeak:
|
|
7600
|
-
},
|
|
7601
|
-
const
|
|
7394
|
+
className: x = "",
|
|
7395
|
+
style: A = {},
|
|
7396
|
+
animations: B = {},
|
|
7397
|
+
autoSpeak: p = !1
|
|
7398
|
+
}, E) => {
|
|
7399
|
+
const I = O(null), y = O(null), H = O(u), w = O(null), D = O(null), $ = O(!1), k = O({ remainingText: null, originalText: null, options: null }), V = O([]), [K, X] = ce(!0), [ee, se] = ce(null), [ae, pe] = ce(!1), [te, le] = ce(!1);
|
|
7602
7400
|
de(() => {
|
|
7603
|
-
|
|
7401
|
+
$.current = te;
|
|
7604
7402
|
}, [te]), de(() => {
|
|
7605
|
-
|
|
7606
|
-
}, [
|
|
7607
|
-
const U = Fe(),
|
|
7608
|
-
let
|
|
7609
|
-
|
|
7403
|
+
H.current = u;
|
|
7404
|
+
}, [u]);
|
|
7405
|
+
const U = Fe(), v = s || U.service;
|
|
7406
|
+
let R;
|
|
7407
|
+
v === "browser" ? R = {
|
|
7610
7408
|
service: "browser",
|
|
7611
7409
|
endpoint: "",
|
|
7612
7410
|
apiKey: null,
|
|
7613
7411
|
defaultVoice: "Google US English"
|
|
7614
|
-
} :
|
|
7412
|
+
} : v === "elevenlabs" ? R = {
|
|
7615
7413
|
service: "elevenlabs",
|
|
7616
7414
|
endpoint: "https://api.elevenlabs.io/v1/text-to-speech",
|
|
7617
7415
|
apiKey: l || U.apiKey,
|
|
7618
7416
|
defaultVoice: o || U.defaultVoice || Ie.defaultVoice,
|
|
7619
7417
|
voices: U.voices || Ie.voices
|
|
7620
|
-
} :
|
|
7418
|
+
} : v === "deepgram" ? R = {
|
|
7621
7419
|
service: "deepgram",
|
|
7622
7420
|
endpoint: "https://api.deepgram.com/v1/speak",
|
|
7623
7421
|
apiKey: l || U.apiKey,
|
|
7624
7422
|
defaultVoice: o || U.defaultVoice || Te.defaultVoice,
|
|
7625
7423
|
voices: U.voices || Te.voices
|
|
7626
|
-
} :
|
|
7424
|
+
} : R = {
|
|
7627
7425
|
...U,
|
|
7628
7426
|
apiKey: l !== null ? l : U.apiKey
|
|
7629
7427
|
};
|
|
7630
|
-
const
|
|
7428
|
+
const z = {
|
|
7631
7429
|
url: t,
|
|
7632
7430
|
body: e,
|
|
7633
7431
|
avatarMood: n,
|
|
7634
|
-
ttsLang:
|
|
7635
|
-
ttsVoice: o ||
|
|
7432
|
+
ttsLang: v === "browser" ? "en-US" : i,
|
|
7433
|
+
ttsVoice: o || R.defaultVoice,
|
|
7636
7434
|
lipsyncLang: "en",
|
|
7637
|
-
showFullAvatar:
|
|
7638
|
-
bodyMovement:
|
|
7435
|
+
showFullAvatar: u,
|
|
7436
|
+
bodyMovement: h,
|
|
7639
7437
|
movementIntensity: r
|
|
7640
|
-
},
|
|
7641
|
-
ttsEndpoint:
|
|
7642
|
-
ttsApikey:
|
|
7643
|
-
ttsService:
|
|
7438
|
+
}, M = {
|
|
7439
|
+
ttsEndpoint: R.endpoint,
|
|
7440
|
+
ttsApikey: R.apiKey,
|
|
7441
|
+
ttsService: v,
|
|
7644
7442
|
lipsyncModules: ["en"],
|
|
7645
7443
|
cameraView: a
|
|
7646
7444
|
}, W = F(async () => {
|
|
7647
|
-
if (!(!
|
|
7445
|
+
if (!(!I.current || y.current))
|
|
7648
7446
|
try {
|
|
7649
|
-
|
|
7650
|
-
url:
|
|
7651
|
-
body:
|
|
7652
|
-
avatarMood:
|
|
7653
|
-
}), await y.current.showAvatar(
|
|
7447
|
+
X(!0), se(null), y.current = new Be(I.current, M), console.log("Avatar config being passed:", {
|
|
7448
|
+
url: z.url,
|
|
7449
|
+
body: z.body,
|
|
7450
|
+
avatarMood: z.avatarMood
|
|
7451
|
+
}), await y.current.showAvatar(z, (ne) => {
|
|
7654
7452
|
if (ne.lengthComputable) {
|
|
7655
7453
|
const L = Math.min(100, Math.round(ne.loaded / ne.total * 100));
|
|
7656
7454
|
d(L);
|
|
7657
7455
|
}
|
|
7658
|
-
}), y.current?.avatar && console.log("Avatar body after initialization:", y.current.avatar.body),
|
|
7659
|
-
const
|
|
7456
|
+
}), y.current?.avatar && console.log("Avatar body after initialization:", y.current.avatar.body), X(!1), pe(!0), c(y.current);
|
|
7457
|
+
const T = () => {
|
|
7660
7458
|
document.visibilityState === "visible" ? y.current?.start() : y.current?.stop();
|
|
7661
7459
|
};
|
|
7662
|
-
return document.addEventListener("visibilitychange",
|
|
7663
|
-
document.removeEventListener("visibilitychange",
|
|
7460
|
+
return document.addEventListener("visibilitychange", T), () => {
|
|
7461
|
+
document.removeEventListener("visibilitychange", T);
|
|
7664
7462
|
};
|
|
7665
|
-
} catch (
|
|
7666
|
-
console.error("Error initializing TalkingHead:",
|
|
7463
|
+
} catch (T) {
|
|
7464
|
+
console.error("Error initializing TalkingHead:", T), se(T.message || "Failed to initialize avatar"), X(!1), g(T);
|
|
7667
7465
|
}
|
|
7668
7466
|
}, []);
|
|
7669
7467
|
de(() => (W(), () => {
|
|
7670
7468
|
y.current && (y.current.stop(), y.current.dispose(), y.current = null);
|
|
7671
7469
|
}), [W]);
|
|
7672
|
-
const
|
|
7470
|
+
const _ = F(async () => {
|
|
7673
7471
|
if (y.current)
|
|
7674
7472
|
try {
|
|
7675
|
-
const
|
|
7676
|
-
|
|
7677
|
-
} catch (
|
|
7678
|
-
console.warn("Failed to resume audio context:",
|
|
7473
|
+
const T = y.current.audioCtx || y.current.audioContext;
|
|
7474
|
+
T && (T.state === "suspended" || T.state === "interrupted") && (await T.resume(), console.log("Audio context resumed"));
|
|
7475
|
+
} catch (T) {
|
|
7476
|
+
console.warn("Failed to resume audio context:", T);
|
|
7679
7477
|
}
|
|
7680
|
-
}, []), j = F(async (
|
|
7478
|
+
}, []), j = F(async (T, ne = {}) => {
|
|
7681
7479
|
if (!y.current || !ae) {
|
|
7682
7480
|
console.warn("Avatar not ready for speaking");
|
|
7683
7481
|
return;
|
|
7684
7482
|
}
|
|
7685
|
-
if (!
|
|
7483
|
+
if (!T || T.trim() === "") {
|
|
7686
7484
|
console.warn("No text provided to speak");
|
|
7687
7485
|
return;
|
|
7688
7486
|
}
|
|
7689
|
-
await
|
|
7690
|
-
const L =
|
|
7691
|
-
|
|
7692
|
-
const
|
|
7487
|
+
await _(), k.current = { remainingText: null, originalText: null, options: null }, V.current = [], w.current = { text: T, options: ne }, D.current && (clearInterval(D.current), D.current = null), le(!1), $.current = !1;
|
|
7488
|
+
const L = T.split(/[.!?]+/).filter((N) => N.trim().length > 0);
|
|
7489
|
+
V.current = L;
|
|
7490
|
+
const P = {
|
|
7693
7491
|
lipsyncLang: ne.lipsyncLang || "en",
|
|
7694
7492
|
onSpeechEnd: () => {
|
|
7695
|
-
D.current && (clearInterval(D.current), D.current = null), ne.onSpeechEnd && ne.onSpeechEnd(),
|
|
7493
|
+
D.current && (clearInterval(D.current), D.current = null), ne.onSpeechEnd && ne.onSpeechEnd(), b();
|
|
7696
7494
|
}
|
|
7697
7495
|
};
|
|
7698
7496
|
try {
|
|
7699
|
-
y.current.speakText(
|
|
7700
|
-
} catch (
|
|
7701
|
-
console.error("Error speaking text:",
|
|
7497
|
+
y.current.speakText(T, P);
|
|
7498
|
+
} catch (N) {
|
|
7499
|
+
console.error("Error speaking text:", N), se(N.message || "Failed to speak text");
|
|
7702
7500
|
}
|
|
7703
|
-
}, [ae,
|
|
7501
|
+
}, [ae, b, _]);
|
|
7704
7502
|
de(() => {
|
|
7705
|
-
ae &&
|
|
7706
|
-
}, [ae,
|
|
7503
|
+
ae && Z && p && y.current && j(Z);
|
|
7504
|
+
}, [ae, Z, p, j]);
|
|
7707
7505
|
const q = F(() => {
|
|
7708
7506
|
if (y.current)
|
|
7709
7507
|
try {
|
|
7710
|
-
const
|
|
7711
|
-
if (
|
|
7508
|
+
const T = y.current.isSpeaking || !1, ne = y.current.audioPlaylist || [], L = y.current.speechQueue || [];
|
|
7509
|
+
if (T || ne.length > 0 || L.length > 0) {
|
|
7712
7510
|
D.current && (clearInterval(D.current), D.current = null);
|
|
7713
|
-
let
|
|
7714
|
-
L.length > 0 && (
|
|
7715
|
-
remainingText:
|
|
7716
|
-
originalText:
|
|
7717
|
-
options:
|
|
7718
|
-
}, y.current.speechQueue.length = 0, y.current.pauseSpeaking(), le(!0),
|
|
7511
|
+
let P = "";
|
|
7512
|
+
L.length > 0 && (P = L.map((N) => N.text && Array.isArray(N.text) ? N.text.map((J) => J.word).join(" ") : N.text || "").join(" ")), k.current = {
|
|
7513
|
+
remainingText: P || null,
|
|
7514
|
+
originalText: w.current?.text || null,
|
|
7515
|
+
options: w.current?.options || null
|
|
7516
|
+
}, y.current.speechQueue.length = 0, y.current.pauseSpeaking(), le(!0), $.current = !0;
|
|
7719
7517
|
}
|
|
7720
|
-
} catch (
|
|
7721
|
-
console.warn("Error pausing speech:",
|
|
7518
|
+
} catch (T) {
|
|
7519
|
+
console.warn("Error pausing speech:", T);
|
|
7722
7520
|
}
|
|
7723
7521
|
}, []), Le = F(async () => {
|
|
7724
7522
|
if (!(!y.current || !te))
|
|
7725
7523
|
try {
|
|
7726
|
-
await
|
|
7727
|
-
const
|
|
7728
|
-
|
|
7729
|
-
} catch (
|
|
7730
|
-
console.warn("Error resuming speech:",
|
|
7524
|
+
await _(), le(!1), $.current = !1;
|
|
7525
|
+
const T = k.current?.remainingText, ne = k.current?.originalText || w.current?.text, L = k.current?.options || w.current?.options || {}, P = T || ne;
|
|
7526
|
+
P && j(P, L);
|
|
7527
|
+
} catch (T) {
|
|
7528
|
+
console.warn("Error resuming speech:", T), le(!1), $.current = !1;
|
|
7731
7529
|
}
|
|
7732
|
-
}, [te, j,
|
|
7733
|
-
y.current && (y.current.stopSpeaking(), D.current && (clearInterval(D.current), D.current = null), le(!1),
|
|
7530
|
+
}, [te, j, _]), we = F(() => {
|
|
7531
|
+
y.current && (y.current.stopSpeaking(), D.current && (clearInterval(D.current), D.current = null), le(!1), $.current = !1);
|
|
7734
7532
|
}, []);
|
|
7735
|
-
return Ee(
|
|
7533
|
+
return Ee(E, () => ({
|
|
7736
7534
|
speakText: j,
|
|
7737
7535
|
pauseSpeaking: q,
|
|
7738
7536
|
resumeSpeaking: Le,
|
|
7739
7537
|
stopSpeaking: we,
|
|
7740
|
-
resumeAudioContext:
|
|
7538
|
+
resumeAudioContext: _,
|
|
7741
7539
|
isPaused: () => te,
|
|
7742
|
-
setMood: (
|
|
7743
|
-
setBodyMovement: (
|
|
7744
|
-
y.current && y.current.setBodyMovement(
|
|
7540
|
+
setMood: (T) => y.current?.setMood(T),
|
|
7541
|
+
setBodyMovement: (T) => {
|
|
7542
|
+
y.current && y.current.setBodyMovement(T);
|
|
7745
7543
|
},
|
|
7746
|
-
playAnimation: (
|
|
7747
|
-
y.current && y.current.playAnimation && y.current.playAnimation(
|
|
7544
|
+
playAnimation: (T, ne = !1) => {
|
|
7545
|
+
y.current && y.current.playAnimation && y.current.playAnimation(T, null, 10, 0, 0.01, ne);
|
|
7748
7546
|
},
|
|
7749
|
-
playReaction: (
|
|
7547
|
+
playReaction: (T) => y.current?.playReaction(T),
|
|
7750
7548
|
playCelebration: () => y.current?.playCelebration(),
|
|
7751
|
-
setShowFullAvatar: (
|
|
7752
|
-
y.current && (
|
|
7549
|
+
setShowFullAvatar: (T) => {
|
|
7550
|
+
y.current && (H.current = T, y.current.setShowFullAvatar(T));
|
|
7753
7551
|
},
|
|
7754
7552
|
isReady: ae,
|
|
7755
7553
|
talkingHead: y.current
|
|
7756
|
-
})), /* @__PURE__ */ Pe("div", { className: `simple-talking-avatar-container ${
|
|
7554
|
+
})), /* @__PURE__ */ Pe("div", { className: `simple-talking-avatar-container ${x}`, style: A, children: [
|
|
7757
7555
|
/* @__PURE__ */ me(
|
|
7758
7556
|
"div",
|
|
7759
7557
|
{
|
|
7760
|
-
ref:
|
|
7558
|
+
ref: I,
|
|
7761
7559
|
className: "talking-head-viewer",
|
|
7762
7560
|
style: {
|
|
7763
7561
|
width: "100%",
|
|
@@ -7766,7 +7564,7 @@ const gt = Me(({
|
|
|
7766
7564
|
}
|
|
7767
7565
|
}
|
|
7768
7566
|
),
|
|
7769
|
-
|
|
7567
|
+
K && /* @__PURE__ */ me("div", { className: "loading-overlay", style: {
|
|
7770
7568
|
position: "absolute",
|
|
7771
7569
|
top: "50%",
|
|
7772
7570
|
left: "50%",
|
|
@@ -7791,7 +7589,7 @@ const gt = Me(({
|
|
|
7791
7589
|
});
|
|
7792
7590
|
gt.displayName = "SimpleTalkingAvatar";
|
|
7793
7591
|
const yt = Me(({
|
|
7794
|
-
curriculumData:
|
|
7592
|
+
curriculumData: Z = null,
|
|
7795
7593
|
avatarConfig: t = {},
|
|
7796
7594
|
animations: e = {},
|
|
7797
7595
|
onLessonStart: n = () => {
|
|
@@ -7804,9 +7602,9 @@ const yt = Me(({
|
|
|
7804
7602
|
},
|
|
7805
7603
|
onCustomAction: l = () => {
|
|
7806
7604
|
},
|
|
7807
|
-
autoStart:
|
|
7605
|
+
autoStart: h = !1
|
|
7808
7606
|
}, r) => {
|
|
7809
|
-
const
|
|
7607
|
+
const u = O(null), a = O({
|
|
7810
7608
|
currentModuleIndex: 0,
|
|
7811
7609
|
currentLessonIndex: 0,
|
|
7812
7610
|
currentQuestionIndex: 0,
|
|
@@ -7822,12 +7620,12 @@ const yt = Me(({
|
|
|
7822
7620
|
onQuestionAnswer: s,
|
|
7823
7621
|
onCurriculumComplete: o,
|
|
7824
7622
|
onCustomAction: l
|
|
7825
|
-
}), d = O(null), g = O(null),
|
|
7623
|
+
}), d = O(null), g = O(null), b = O(null), x = O(null), A = O(null), B = O(null), p = O(null), E = O(Z?.curriculum || {
|
|
7826
7624
|
title: "Default Curriculum",
|
|
7827
7625
|
description: "No curriculum data provided",
|
|
7828
7626
|
language: "en",
|
|
7829
7627
|
modules: []
|
|
7830
|
-
}),
|
|
7628
|
+
}), I = O({
|
|
7831
7629
|
avatarUrl: t.avatarUrl || "/avatars/brunette.glb",
|
|
7832
7630
|
avatarBody: t.avatarBody || "F",
|
|
7833
7631
|
mood: t.mood || "happy",
|
|
@@ -7850,12 +7648,12 @@ const yt = Me(({
|
|
|
7850
7648
|
onCustomAction: l
|
|
7851
7649
|
};
|
|
7852
7650
|
}, [n, i, s, o, l]), de(() => {
|
|
7853
|
-
|
|
7651
|
+
E.current = Z?.curriculum || {
|
|
7854
7652
|
title: "Default Curriculum",
|
|
7855
7653
|
description: "No curriculum data provided",
|
|
7856
7654
|
language: "en",
|
|
7857
7655
|
modules: []
|
|
7858
|
-
},
|
|
7656
|
+
}, I.current = {
|
|
7859
7657
|
avatarUrl: t.avatarUrl || "/avatars/brunette.glb",
|
|
7860
7658
|
avatarBody: t.avatarBody || "F",
|
|
7861
7659
|
mood: t.mood || "happy",
|
|
@@ -7869,33 +7667,33 @@ const yt = Me(({
|
|
|
7869
7667
|
animations: e,
|
|
7870
7668
|
lipsyncLang: "en"
|
|
7871
7669
|
};
|
|
7872
|
-
}, [
|
|
7873
|
-
const y = F(() => (
|
|
7670
|
+
}, [Z, t, e]);
|
|
7671
|
+
const y = F(() => (E.current || { modules: [] }).modules[a.current.currentModuleIndex]?.lessons[a.current.currentLessonIndex], []), H = F(() => y()?.questions[a.current.currentQuestionIndex], [y]), w = F((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, []), D = F(() => {
|
|
7874
7672
|
a.current.lessonCompleted = !0, a.current.isQuestionMode = !1;
|
|
7875
|
-
const
|
|
7876
|
-
let
|
|
7877
|
-
if (a.current.totalQuestions > 0 ?
|
|
7673
|
+
const v = a.current.totalQuestions > 0 ? Math.round(a.current.score / a.current.totalQuestions * 100) : 100;
|
|
7674
|
+
let R = "Congratulations! You've completed this lesson";
|
|
7675
|
+
if (a.current.totalQuestions > 0 ? R += ` You got ${a.current.score} correct out of ${a.current.totalQuestions} question${a.current.totalQuestions === 1 ? "" : "s"}, achieving a score of ${v} percent. ` : R += "! ", v >= 80 ? R += "Excellent work! You have a great understanding of this topic." : v >= 60 ? R += "Good job! You understand most of the concepts." : R += "Keep practicing! You're making progress.", c.current.onLessonComplete({
|
|
7878
7676
|
moduleIndex: a.current.currentModuleIndex,
|
|
7879
7677
|
lessonIndex: a.current.currentLessonIndex,
|
|
7880
7678
|
score: a.current.score,
|
|
7881
7679
|
totalQuestions: a.current.totalQuestions,
|
|
7882
|
-
percentage:
|
|
7680
|
+
percentage: v
|
|
7883
7681
|
}), c.current.onCustomAction({
|
|
7884
7682
|
type: "lessonComplete",
|
|
7885
7683
|
moduleIndex: a.current.currentModuleIndex,
|
|
7886
7684
|
lessonIndex: a.current.currentLessonIndex,
|
|
7887
7685
|
score: a.current.score,
|
|
7888
7686
|
totalQuestions: a.current.totalQuestions,
|
|
7889
|
-
percentage:
|
|
7890
|
-
}),
|
|
7891
|
-
if (
|
|
7687
|
+
percentage: v
|
|
7688
|
+
}), u.current) {
|
|
7689
|
+
if (u.current.setMood("happy"), e.lessonComplete)
|
|
7892
7690
|
try {
|
|
7893
|
-
|
|
7691
|
+
u.current.playAnimation(e.lessonComplete, !0);
|
|
7894
7692
|
} catch {
|
|
7895
|
-
|
|
7693
|
+
u.current.playCelebration();
|
|
7896
7694
|
}
|
|
7897
|
-
const
|
|
7898
|
-
|
|
7695
|
+
const z = E.current || { modules: [] }, M = z.modules[a.current.currentModuleIndex], W = a.current.currentLessonIndex < (M?.lessons?.length || 0) - 1, _ = a.current.currentModuleIndex < (z.modules?.length || 0) - 1, j = W || _, q = I.current || { lipsyncLang: "en" };
|
|
7696
|
+
u.current.speakText(R, {
|
|
7899
7697
|
lipsyncLang: q.lipsyncLang,
|
|
7900
7698
|
onSpeechEnd: () => {
|
|
7901
7699
|
c.current.onCustomAction({
|
|
@@ -7904,118 +7702,118 @@ const yt = Me(({
|
|
|
7904
7702
|
lessonIndex: a.current.currentLessonIndex,
|
|
7905
7703
|
score: a.current.score,
|
|
7906
7704
|
totalQuestions: a.current.totalQuestions,
|
|
7907
|
-
percentage:
|
|
7705
|
+
percentage: v,
|
|
7908
7706
|
hasNextLesson: j
|
|
7909
7707
|
});
|
|
7910
7708
|
}
|
|
7911
7709
|
});
|
|
7912
7710
|
}
|
|
7913
|
-
}, [e.lessonComplete]),
|
|
7711
|
+
}, [e.lessonComplete]), $ = F(() => {
|
|
7914
7712
|
a.current.curriculumCompleted = !0;
|
|
7915
|
-
const
|
|
7713
|
+
const v = E.current || { modules: [] };
|
|
7916
7714
|
if (c.current.onCurriculumComplete({
|
|
7917
|
-
modules:
|
|
7918
|
-
totalLessons:
|
|
7919
|
-
}),
|
|
7920
|
-
if (
|
|
7715
|
+
modules: v.modules.length,
|
|
7716
|
+
totalLessons: v.modules.reduce((R, z) => R + z.lessons.length, 0)
|
|
7717
|
+
}), u.current) {
|
|
7718
|
+
if (u.current.setMood("celebrating"), e.curriculumComplete)
|
|
7921
7719
|
try {
|
|
7922
|
-
|
|
7720
|
+
u.current.playAnimation(e.curriculumComplete, !0);
|
|
7923
7721
|
} catch {
|
|
7924
|
-
|
|
7722
|
+
u.current.playCelebration();
|
|
7925
7723
|
}
|
|
7926
|
-
const
|
|
7927
|
-
|
|
7724
|
+
const R = I.current || { lipsyncLang: "en" };
|
|
7725
|
+
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 });
|
|
7928
7726
|
}
|
|
7929
|
-
}, [e.curriculumComplete]),
|
|
7930
|
-
const
|
|
7931
|
-
a.current.isQuestionMode = !0, a.current.currentQuestionIndex = 0, a.current.totalQuestions =
|
|
7932
|
-
const
|
|
7933
|
-
|
|
7727
|
+
}, [e.curriculumComplete]), k = F(() => {
|
|
7728
|
+
const v = y();
|
|
7729
|
+
a.current.isQuestionMode = !0, a.current.currentQuestionIndex = 0, a.current.totalQuestions = v?.questions?.length || 0, a.current.score = 0;
|
|
7730
|
+
const R = H();
|
|
7731
|
+
R && c.current.onCustomAction({
|
|
7934
7732
|
type: "questionStart",
|
|
7935
7733
|
moduleIndex: a.current.currentModuleIndex,
|
|
7936
7734
|
lessonIndex: a.current.currentLessonIndex,
|
|
7937
7735
|
questionIndex: a.current.currentQuestionIndex,
|
|
7938
7736
|
totalQuestions: a.current.totalQuestions,
|
|
7939
|
-
question:
|
|
7737
|
+
question: R,
|
|
7940
7738
|
score: a.current.score
|
|
7941
7739
|
});
|
|
7942
|
-
const
|
|
7943
|
-
if (!
|
|
7944
|
-
if (
|
|
7740
|
+
const z = () => {
|
|
7741
|
+
if (!u.current || !R) return;
|
|
7742
|
+
if (u.current.setMood("happy"), e.questionStart)
|
|
7945
7743
|
try {
|
|
7946
|
-
|
|
7744
|
+
u.current.playAnimation(e.questionStart, !0);
|
|
7947
7745
|
} catch (W) {
|
|
7948
7746
|
console.warn("Failed to play questionStart animation:", W);
|
|
7949
7747
|
}
|
|
7950
|
-
const
|
|
7951
|
-
|
|
7748
|
+
const M = I.current || { lipsyncLang: "en" };
|
|
7749
|
+
R.type === "code_test" ? u.current.speakText(`Let's test your coding skills! Here's your first challenge: ${R.question}`, { lipsyncLang: M.lipsyncLang }) : R.type === "multiple_choice" ? u.current.speakText(`Now let me ask you some questions. Here's the first one: ${R.question}`, { lipsyncLang: M.lipsyncLang }) : R.type === "true_false" ? u.current.speakText(`Let's start with some true or false questions. First question: ${R.question}`, { lipsyncLang: M.lipsyncLang }) : u.current.speakText(`Now let me ask you some questions. Here's the first one: ${R.question}`, { lipsyncLang: M.lipsyncLang });
|
|
7952
7750
|
};
|
|
7953
|
-
if (
|
|
7954
|
-
|
|
7955
|
-
else if (
|
|
7956
|
-
const
|
|
7957
|
-
|
|
7751
|
+
if (u.current && u.current.isReady && R)
|
|
7752
|
+
z();
|
|
7753
|
+
else if (u.current && u.current.isReady) {
|
|
7754
|
+
const M = I.current || { lipsyncLang: "en" };
|
|
7755
|
+
u.current.speakText("Now let me ask you some questions to test your understanding.", { lipsyncLang: M.lipsyncLang });
|
|
7958
7756
|
} else {
|
|
7959
|
-
const
|
|
7960
|
-
|
|
7757
|
+
const M = setInterval(() => {
|
|
7758
|
+
u.current && u.current.isReady && (clearInterval(M), R && z());
|
|
7961
7759
|
}, 100);
|
|
7962
7760
|
setTimeout(() => {
|
|
7963
|
-
clearInterval(
|
|
7761
|
+
clearInterval(M);
|
|
7964
7762
|
}, 5e3);
|
|
7965
7763
|
}
|
|
7966
|
-
}, [e.questionStart, y,
|
|
7967
|
-
const
|
|
7968
|
-
if (a.current.currentQuestionIndex < (
|
|
7969
|
-
|
|
7970
|
-
const
|
|
7971
|
-
|
|
7764
|
+
}, [e.questionStart, y, H]), V = F(() => {
|
|
7765
|
+
const v = y();
|
|
7766
|
+
if (a.current.currentQuestionIndex < (v?.questions?.length || 0) - 1) {
|
|
7767
|
+
u.current && u.current.stopSpeaking && u.current.stopSpeaking(), a.current.currentQuestionIndex += 1;
|
|
7768
|
+
const R = H();
|
|
7769
|
+
R && c.current.onCustomAction({
|
|
7972
7770
|
type: "nextQuestion",
|
|
7973
7771
|
moduleIndex: a.current.currentModuleIndex,
|
|
7974
7772
|
lessonIndex: a.current.currentLessonIndex,
|
|
7975
7773
|
questionIndex: a.current.currentQuestionIndex,
|
|
7976
7774
|
totalQuestions: a.current.totalQuestions,
|
|
7977
|
-
question:
|
|
7775
|
+
question: R,
|
|
7978
7776
|
score: a.current.score
|
|
7979
7777
|
});
|
|
7980
|
-
const
|
|
7981
|
-
if (!
|
|
7982
|
-
if (
|
|
7778
|
+
const z = () => {
|
|
7779
|
+
if (!u.current || !R) return;
|
|
7780
|
+
if (u.current.setMood("happy"), u.current.setBodyMovement("idle"), e.nextQuestion)
|
|
7983
7781
|
try {
|
|
7984
|
-
|
|
7782
|
+
u.current.playAnimation(e.nextQuestion, !0);
|
|
7985
7783
|
} catch (q) {
|
|
7986
7784
|
console.warn("Failed to play nextQuestion animation:", q);
|
|
7987
7785
|
}
|
|
7988
|
-
const
|
|
7989
|
-
if (
|
|
7990
|
-
const q = j ? `Great! Here's your final coding challenge: ${
|
|
7991
|
-
|
|
7992
|
-
lipsyncLang:
|
|
7786
|
+
const M = I.current || { lipsyncLang: "en" }, _ = y()?.questions?.length || 0, j = a.current.currentQuestionIndex >= _ - 1;
|
|
7787
|
+
if (R.type === "code_test") {
|
|
7788
|
+
const q = j ? `Great! Here's your final coding challenge: ${R.question}` : `Great! Now let's move on to your next coding challenge: ${R.question}`;
|
|
7789
|
+
u.current.speakText(q, {
|
|
7790
|
+
lipsyncLang: M.lipsyncLang
|
|
7993
7791
|
});
|
|
7994
|
-
} else if (
|
|
7995
|
-
const q = j ? `Alright! Here's your final question: ${
|
|
7996
|
-
|
|
7997
|
-
lipsyncLang:
|
|
7792
|
+
} else if (R.type === "multiple_choice") {
|
|
7793
|
+
const q = j ? `Alright! Here's your final question: ${R.question}` : `Alright! Here's your next question: ${R.question}`;
|
|
7794
|
+
u.current.speakText(q, {
|
|
7795
|
+
lipsyncLang: M.lipsyncLang
|
|
7998
7796
|
});
|
|
7999
|
-
} else if (
|
|
8000
|
-
const q = j ? `Now let's try this final one: ${
|
|
8001
|
-
|
|
8002
|
-
lipsyncLang:
|
|
7797
|
+
} else if (R.type === "true_false") {
|
|
7798
|
+
const q = j ? `Now let's try this final one: ${R.question}` : `Now let's try this one: ${R.question}`;
|
|
7799
|
+
u.current.speakText(q, {
|
|
7800
|
+
lipsyncLang: M.lipsyncLang
|
|
8003
7801
|
});
|
|
8004
7802
|
} else {
|
|
8005
|
-
const q = j ? `Here's your final question: ${
|
|
8006
|
-
|
|
8007
|
-
lipsyncLang:
|
|
7803
|
+
const q = j ? `Here's your final question: ${R.question}` : `Here's the next question: ${R.question}`;
|
|
7804
|
+
u.current.speakText(q, {
|
|
7805
|
+
lipsyncLang: M.lipsyncLang
|
|
8008
7806
|
});
|
|
8009
7807
|
}
|
|
8010
7808
|
};
|
|
8011
|
-
if (
|
|
8012
|
-
|
|
8013
|
-
else if (
|
|
8014
|
-
const
|
|
8015
|
-
|
|
7809
|
+
if (u.current && u.current.isReady && R)
|
|
7810
|
+
z();
|
|
7811
|
+
else if (R) {
|
|
7812
|
+
const M = setInterval(() => {
|
|
7813
|
+
u.current && u.current.isReady && (clearInterval(M), z());
|
|
8016
7814
|
}, 100);
|
|
8017
7815
|
setTimeout(() => {
|
|
8018
|
-
clearInterval(
|
|
7816
|
+
clearInterval(M);
|
|
8019
7817
|
}, 5e3);
|
|
8020
7818
|
}
|
|
8021
7819
|
} else
|
|
@@ -8026,11 +7824,11 @@ const yt = Me(({
|
|
|
8026
7824
|
totalQuestions: a.current.totalQuestions,
|
|
8027
7825
|
score: a.current.score
|
|
8028
7826
|
});
|
|
8029
|
-
}, [e.nextQuestion, y,
|
|
8030
|
-
const
|
|
8031
|
-
if (a.current.currentLessonIndex < (
|
|
7827
|
+
}, [e.nextQuestion, y, H]), K = F(() => {
|
|
7828
|
+
const v = E.current || { modules: [] }, R = v.modules[a.current.currentModuleIndex];
|
|
7829
|
+
if (a.current.currentLessonIndex < (R?.lessons?.length || 0) - 1) {
|
|
8032
7830
|
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;
|
|
8033
|
-
const
|
|
7831
|
+
const M = v.modules[a.current.currentModuleIndex], W = a.current.currentLessonIndex < (M?.lessons?.length || 0) - 1, _ = a.current.currentModuleIndex < (v.modules?.length || 0) - 1, j = W || _;
|
|
8034
7832
|
c.current.onCustomAction({
|
|
8035
7833
|
type: "lessonStart",
|
|
8036
7834
|
moduleIndex: a.current.currentModuleIndex,
|
|
@@ -8040,10 +7838,10 @@ const yt = Me(({
|
|
|
8040
7838
|
moduleIndex: a.current.currentModuleIndex,
|
|
8041
7839
|
lessonIndex: a.current.currentLessonIndex,
|
|
8042
7840
|
lesson: y()
|
|
8043
|
-
}),
|
|
8044
|
-
} else if (a.current.currentModuleIndex < (
|
|
7841
|
+
}), u.current && (u.current.setMood("happy"), u.current.setBodyMovement("idle"));
|
|
7842
|
+
} else if (a.current.currentModuleIndex < (v.modules?.length || 0) - 1) {
|
|
8045
7843
|
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;
|
|
8046
|
-
const W =
|
|
7844
|
+
const W = v.modules[a.current.currentModuleIndex], _ = a.current.currentLessonIndex < (W?.lessons?.length || 0) - 1, j = a.current.currentModuleIndex < (v.modules?.length || 0) - 1, q = _ || j;
|
|
8047
7845
|
c.current.onCustomAction({
|
|
8048
7846
|
type: "lessonStart",
|
|
8049
7847
|
moduleIndex: a.current.currentModuleIndex,
|
|
@@ -8053,80 +7851,80 @@ const yt = Me(({
|
|
|
8053
7851
|
moduleIndex: a.current.currentModuleIndex,
|
|
8054
7852
|
lessonIndex: a.current.currentLessonIndex,
|
|
8055
7853
|
lesson: y()
|
|
8056
|
-
}),
|
|
7854
|
+
}), u.current && (u.current.setMood("happy"), u.current.setBodyMovement("idle"));
|
|
8057
7855
|
} else
|
|
8058
|
-
|
|
8059
|
-
}, []),
|
|
8060
|
-
const
|
|
8061
|
-
let
|
|
8062
|
-
if (
|
|
8063
|
-
const
|
|
8064
|
-
|
|
7856
|
+
A.current && A.current();
|
|
7857
|
+
}, []), X = F(() => {
|
|
7858
|
+
const v = y();
|
|
7859
|
+
let R = null;
|
|
7860
|
+
if (v?.avatar_script && v?.body) {
|
|
7861
|
+
const z = v.avatar_script.trim(), M = v.body.trim(), W = z.match(/[.!?]$/) ? " " : ". ";
|
|
7862
|
+
R = `${z}${W}${M}`;
|
|
8065
7863
|
} else
|
|
8066
|
-
|
|
8067
|
-
if (
|
|
8068
|
-
a.current.isTeaching = !0, a.current.isQuestionMode = !1, a.current.score = 0, a.current.totalQuestions = 0,
|
|
8069
|
-
let
|
|
7864
|
+
R = v?.avatar_script || v?.body || null;
|
|
7865
|
+
if (u.current && u.current.isReady && R) {
|
|
7866
|
+
a.current.isTeaching = !0, a.current.isQuestionMode = !1, a.current.score = 0, a.current.totalQuestions = 0, u.current.setMood("happy");
|
|
7867
|
+
let z = !1;
|
|
8070
7868
|
if (e.teaching)
|
|
8071
7869
|
try {
|
|
8072
|
-
|
|
7870
|
+
u.current.playAnimation(e.teaching, !0), z = !0;
|
|
8073
7871
|
} catch (W) {
|
|
8074
7872
|
console.warn("Failed to play teaching animation:", W);
|
|
8075
7873
|
}
|
|
8076
|
-
|
|
8077
|
-
const
|
|
7874
|
+
z || u.current.setBodyMovement("gesturing");
|
|
7875
|
+
const M = I.current || { lipsyncLang: "en" };
|
|
8078
7876
|
c.current.onLessonStart({
|
|
8079
7877
|
moduleIndex: a.current.currentModuleIndex,
|
|
8080
7878
|
lessonIndex: a.current.currentLessonIndex,
|
|
8081
|
-
lesson:
|
|
7879
|
+
lesson: v
|
|
8082
7880
|
}), c.current.onCustomAction({
|
|
8083
7881
|
type: "teachingStart",
|
|
8084
7882
|
moduleIndex: a.current.currentModuleIndex,
|
|
8085
7883
|
lessonIndex: a.current.currentLessonIndex,
|
|
8086
|
-
lesson:
|
|
8087
|
-
}),
|
|
8088
|
-
lipsyncLang:
|
|
7884
|
+
lesson: v
|
|
7885
|
+
}), u.current.speakText(R, {
|
|
7886
|
+
lipsyncLang: M.lipsyncLang,
|
|
8089
7887
|
onSpeechEnd: () => {
|
|
8090
7888
|
a.current.isTeaching = !1, c.current.onCustomAction({
|
|
8091
7889
|
type: "teachingComplete",
|
|
8092
7890
|
moduleIndex: a.current.currentModuleIndex,
|
|
8093
7891
|
lessonIndex: a.current.currentLessonIndex,
|
|
8094
|
-
lesson:
|
|
8095
|
-
hasQuestions:
|
|
8096
|
-
}),
|
|
7892
|
+
lesson: v,
|
|
7893
|
+
hasQuestions: v.questions && v.questions.length > 0
|
|
7894
|
+
}), v?.code_example && c.current.onCustomAction({
|
|
8097
7895
|
type: "codeExampleReady",
|
|
8098
7896
|
moduleIndex: a.current.currentModuleIndex,
|
|
8099
7897
|
lessonIndex: a.current.currentLessonIndex,
|
|
8100
|
-
lesson:
|
|
8101
|
-
codeExample:
|
|
7898
|
+
lesson: v,
|
|
7899
|
+
codeExample: v.code_example
|
|
8102
7900
|
});
|
|
8103
7901
|
}
|
|
8104
7902
|
});
|
|
8105
7903
|
}
|
|
8106
|
-
}, [e.teaching, y]), ee = F((
|
|
8107
|
-
const
|
|
8108
|
-
if (
|
|
7904
|
+
}, [e.teaching, y]), ee = F((v) => {
|
|
7905
|
+
const R = H(), z = w(v, R);
|
|
7906
|
+
if (z && (a.current.score += 1), c.current.onQuestionAnswer({
|
|
8109
7907
|
moduleIndex: a.current.currentModuleIndex,
|
|
8110
7908
|
lessonIndex: a.current.currentLessonIndex,
|
|
8111
7909
|
questionIndex: a.current.currentQuestionIndex,
|
|
8112
|
-
answer:
|
|
8113
|
-
isCorrect:
|
|
8114
|
-
question:
|
|
8115
|
-
}),
|
|
8116
|
-
if (
|
|
8117
|
-
if (
|
|
7910
|
+
answer: v,
|
|
7911
|
+
isCorrect: z,
|
|
7912
|
+
question: R
|
|
7913
|
+
}), u.current)
|
|
7914
|
+
if (z) {
|
|
7915
|
+
if (u.current.setMood("happy"), e.correct)
|
|
8118
7916
|
try {
|
|
8119
|
-
|
|
7917
|
+
u.current.playReaction("happy");
|
|
8120
7918
|
} catch {
|
|
8121
|
-
|
|
7919
|
+
u.current.setBodyMovement("happy");
|
|
8122
7920
|
}
|
|
8123
|
-
|
|
7921
|
+
u.current.setBodyMovement("gesturing");
|
|
8124
7922
|
const W = y()?.questions?.length || 0;
|
|
8125
7923
|
a.current.currentQuestionIndex >= W - 1;
|
|
8126
|
-
const
|
|
8127
|
-
console.log("[CurriculumLearning] Answer feedback - questionIndex:", a.current.currentQuestionIndex, "totalQuestions:", W, "hasNextQuestion:",
|
|
8128
|
-
const j =
|
|
8129
|
-
|
|
7924
|
+
const _ = a.current.currentQuestionIndex < W - 1;
|
|
7925
|
+
console.log("[CurriculumLearning] Answer feedback - questionIndex:", a.current.currentQuestionIndex, "totalQuestions:", W, "hasNextQuestion:", _);
|
|
7926
|
+
const j = R.type === "code_test" ? `Great job! Your code passed all the tests! ${R.explanation || ""}` : `Excellent! That's correct! ${R.explanation || ""}`, q = I.current || { lipsyncLang: "en" };
|
|
7927
|
+
u.current.speakText(j, {
|
|
8130
7928
|
lipsyncLang: q.lipsyncLang,
|
|
8131
7929
|
onSpeechEnd: () => {
|
|
8132
7930
|
c.current.onCustomAction({
|
|
@@ -8135,24 +7933,24 @@ const yt = Me(({
|
|
|
8135
7933
|
lessonIndex: a.current.currentLessonIndex,
|
|
8136
7934
|
questionIndex: a.current.currentQuestionIndex,
|
|
8137
7935
|
isCorrect: !0,
|
|
8138
|
-
hasNextQuestion:
|
|
7936
|
+
hasNextQuestion: _,
|
|
8139
7937
|
score: a.current.score,
|
|
8140
7938
|
totalQuestions: a.current.totalQuestions
|
|
8141
7939
|
});
|
|
8142
7940
|
}
|
|
8143
7941
|
});
|
|
8144
7942
|
} else {
|
|
8145
|
-
if (
|
|
7943
|
+
if (u.current.setMood("sad"), e.incorrect)
|
|
8146
7944
|
try {
|
|
8147
|
-
|
|
7945
|
+
u.current.playAnimation(e.incorrect, !0);
|
|
8148
7946
|
} catch {
|
|
8149
|
-
|
|
7947
|
+
u.current.setBodyMovement("idle");
|
|
8150
7948
|
}
|
|
8151
|
-
|
|
8152
|
-
const W = y()?.questions?.length || 0,
|
|
7949
|
+
u.current.setBodyMovement("gesturing");
|
|
7950
|
+
const W = y()?.questions?.length || 0, _ = a.current.currentQuestionIndex >= W - 1, j = a.current.currentQuestionIndex < W - 1;
|
|
8153
7951
|
console.log("[CurriculumLearning] Answer feedback (incorrect) - questionIndex:", a.current.currentQuestionIndex, "totalQuestions:", W, "hasNextQuestion:", j);
|
|
8154
|
-
const q =
|
|
8155
|
-
|
|
7952
|
+
const q = R.type === "code_test" ? `Your code didn't pass all the tests. ${R.explanation || "Try again!"}` : `Not quite right, but don't worry! ${R.explanation || ""}${_ ? "" : " Let's move on to the next question."}`, Le = I.current || { lipsyncLang: "en" };
|
|
7953
|
+
u.current.speakText(q, {
|
|
8156
7954
|
lipsyncLang: Le.lipsyncLang,
|
|
8157
7955
|
onSpeechEnd: () => {
|
|
8158
7956
|
c.current.onCustomAction({
|
|
@@ -8175,78 +7973,78 @@ const yt = Me(({
|
|
|
8175
7973
|
moduleIndex: a.current.currentModuleIndex,
|
|
8176
7974
|
lessonIndex: a.current.currentLessonIndex,
|
|
8177
7975
|
questionIndex: a.current.currentQuestionIndex,
|
|
8178
|
-
isCorrect:
|
|
7976
|
+
isCorrect: z,
|
|
8179
7977
|
hasNextQuestion: a.current.currentQuestionIndex < W - 1,
|
|
8180
7978
|
score: a.current.score,
|
|
8181
7979
|
totalQuestions: a.current.totalQuestions,
|
|
8182
7980
|
avatarNotReady: !0
|
|
8183
7981
|
});
|
|
8184
7982
|
}
|
|
8185
|
-
}, [e.correct, e.incorrect,
|
|
8186
|
-
const
|
|
8187
|
-
if (!
|
|
7983
|
+
}, [e.correct, e.incorrect, H, y, w]), se = F((v) => {
|
|
7984
|
+
const R = H();
|
|
7985
|
+
if (!v || typeof v != "object") {
|
|
8188
7986
|
console.error("Invalid code test result format. Expected object with {passed: boolean, ...}");
|
|
8189
7987
|
return;
|
|
8190
7988
|
}
|
|
8191
|
-
if (
|
|
7989
|
+
if (R?.type !== "code_test") {
|
|
8192
7990
|
console.warn("Current question is not a code test. Use handleAnswerSelect for other question types.");
|
|
8193
7991
|
return;
|
|
8194
7992
|
}
|
|
8195
|
-
const
|
|
8196
|
-
passed:
|
|
8197
|
-
results:
|
|
8198
|
-
output:
|
|
8199
|
-
error:
|
|
8200
|
-
executionTime:
|
|
8201
|
-
testCount:
|
|
8202
|
-
passedCount:
|
|
8203
|
-
failedCount:
|
|
7993
|
+
const z = {
|
|
7994
|
+
passed: v.passed === !0,
|
|
7995
|
+
results: v.results || [],
|
|
7996
|
+
output: v.output || "",
|
|
7997
|
+
error: v.error || null,
|
|
7998
|
+
executionTime: v.executionTime || null,
|
|
7999
|
+
testCount: v.testCount || 0,
|
|
8000
|
+
passedCount: v.passedCount || 0,
|
|
8001
|
+
failedCount: v.failedCount || 0
|
|
8204
8002
|
};
|
|
8205
8003
|
c.current.onCustomAction({
|
|
8206
8004
|
type: "codeTestSubmitted",
|
|
8207
8005
|
moduleIndex: a.current.currentModuleIndex,
|
|
8208
8006
|
lessonIndex: a.current.currentLessonIndex,
|
|
8209
8007
|
questionIndex: a.current.currentQuestionIndex,
|
|
8210
|
-
testResult:
|
|
8211
|
-
question:
|
|
8212
|
-
}),
|
|
8213
|
-
}, [
|
|
8008
|
+
testResult: z,
|
|
8009
|
+
question: R
|
|
8010
|
+
}), p.current && p.current(z);
|
|
8011
|
+
}, [H, w]), ae = F(() => {
|
|
8214
8012
|
if (a.current.currentQuestionIndex > 0) {
|
|
8215
8013
|
a.current.currentQuestionIndex -= 1;
|
|
8216
|
-
const
|
|
8217
|
-
|
|
8014
|
+
const v = H();
|
|
8015
|
+
v && c.current.onCustomAction({
|
|
8218
8016
|
type: "questionStart",
|
|
8219
8017
|
moduleIndex: a.current.currentModuleIndex,
|
|
8220
8018
|
lessonIndex: a.current.currentLessonIndex,
|
|
8221
8019
|
questionIndex: a.current.currentQuestionIndex,
|
|
8222
8020
|
totalQuestions: a.current.totalQuestions,
|
|
8223
|
-
question:
|
|
8021
|
+
question: v,
|
|
8224
8022
|
score: a.current.score
|
|
8225
8023
|
});
|
|
8226
|
-
const
|
|
8227
|
-
if (!
|
|
8228
|
-
|
|
8229
|
-
const
|
|
8230
|
-
|
|
8231
|
-
lipsyncLang:
|
|
8232
|
-
}) :
|
|
8233
|
-
lipsyncLang:
|
|
8024
|
+
const R = () => {
|
|
8025
|
+
if (!u.current || !v) return;
|
|
8026
|
+
u.current.setMood("happy"), u.current.setBodyMovement("idle");
|
|
8027
|
+
const z = I.current || { lipsyncLang: "en" };
|
|
8028
|
+
v.type === "code_test" ? u.current.speakText(`Let's go back to this coding challenge: ${v.question}`, {
|
|
8029
|
+
lipsyncLang: z.lipsyncLang
|
|
8030
|
+
}) : u.current.speakText(`Going back to: ${v.question}`, {
|
|
8031
|
+
lipsyncLang: z.lipsyncLang
|
|
8234
8032
|
});
|
|
8235
8033
|
};
|
|
8236
|
-
if (
|
|
8237
|
-
|
|
8238
|
-
else if (
|
|
8239
|
-
const
|
|
8240
|
-
|
|
8034
|
+
if (u.current && u.current.isReady && v)
|
|
8035
|
+
R();
|
|
8036
|
+
else if (v) {
|
|
8037
|
+
const z = setInterval(() => {
|
|
8038
|
+
u.current && u.current.isReady && (clearInterval(z), R());
|
|
8241
8039
|
}, 100);
|
|
8242
8040
|
setTimeout(() => {
|
|
8243
|
-
clearInterval(
|
|
8041
|
+
clearInterval(z);
|
|
8244
8042
|
}, 5e3);
|
|
8245
8043
|
}
|
|
8246
8044
|
}
|
|
8247
|
-
}, [
|
|
8248
|
-
const
|
|
8249
|
-
if (
|
|
8045
|
+
}, [H]), pe = F(() => {
|
|
8046
|
+
const v = E.current || { modules: [] };
|
|
8047
|
+
if (v.modules[a.current.currentModuleIndex], a.current.currentLessonIndex > 0)
|
|
8250
8048
|
a.current.currentLessonIndex -= 1, a.current.currentQuestionIndex = 0, a.current.lessonCompleted = !1, a.current.isQuestionMode = !1, a.current.isTeaching = !1, a.current.score = 0, a.current.totalQuestions = 0, c.current.onCustomAction({
|
|
8251
8049
|
type: "lessonStart",
|
|
8252
8050
|
moduleIndex: a.current.currentModuleIndex,
|
|
@@ -8255,10 +8053,10 @@ const yt = Me(({
|
|
|
8255
8053
|
moduleIndex: a.current.currentModuleIndex,
|
|
8256
8054
|
lessonIndex: a.current.currentLessonIndex,
|
|
8257
8055
|
lesson: y()
|
|
8258
|
-
}),
|
|
8056
|
+
}), u.current && (u.current.setMood("happy"), u.current.setBodyMovement("idle"));
|
|
8259
8057
|
else if (a.current.currentModuleIndex > 0) {
|
|
8260
|
-
const
|
|
8261
|
-
a.current.currentModuleIndex -= 1, a.current.currentLessonIndex = (
|
|
8058
|
+
const M = v.modules[a.current.currentModuleIndex - 1];
|
|
8059
|
+
a.current.currentModuleIndex -= 1, a.current.currentLessonIndex = (M?.lessons?.length || 1) - 1, a.current.currentQuestionIndex = 0, a.current.lessonCompleted = !1, a.current.isQuestionMode = !1, a.current.isTeaching = !1, a.current.score = 0, a.current.totalQuestions = 0, c.current.onCustomAction({
|
|
8262
8060
|
type: "lessonStart",
|
|
8263
8061
|
moduleIndex: a.current.currentModuleIndex,
|
|
8264
8062
|
lessonIndex: a.current.currentLessonIndex
|
|
@@ -8266,87 +8064,87 @@ const yt = Me(({
|
|
|
8266
8064
|
moduleIndex: a.current.currentModuleIndex,
|
|
8267
8065
|
lessonIndex: a.current.currentLessonIndex,
|
|
8268
8066
|
lesson: y()
|
|
8269
|
-
}),
|
|
8067
|
+
}), u.current && (u.current.setMood("happy"), u.current.setBodyMovement("idle"));
|
|
8270
8068
|
}
|
|
8271
8069
|
}, [y]), te = F(() => {
|
|
8272
8070
|
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;
|
|
8273
|
-
}, []), le = F((
|
|
8274
|
-
console.log("Avatar is ready!",
|
|
8275
|
-
const
|
|
8276
|
-
|
|
8071
|
+
}, []), le = F((v) => {
|
|
8072
|
+
console.log("Avatar is ready!", v);
|
|
8073
|
+
const R = y(), z = R?.avatar_script || R?.body;
|
|
8074
|
+
h && z && setTimeout(() => {
|
|
8277
8075
|
d.current && d.current();
|
|
8278
8076
|
}, 10);
|
|
8279
|
-
}, [
|
|
8077
|
+
}, [h, y]);
|
|
8280
8078
|
Xe(() => {
|
|
8281
|
-
d.current =
|
|
8079
|
+
d.current = X, g.current = K, b.current = D, x.current = V, A.current = $, B.current = k, p.current = ee;
|
|
8282
8080
|
}), Ee(r, () => ({
|
|
8283
8081
|
// Curriculum control methods
|
|
8284
|
-
startTeaching:
|
|
8285
|
-
startQuestions:
|
|
8082
|
+
startTeaching: X,
|
|
8083
|
+
startQuestions: k,
|
|
8286
8084
|
handleAnswerSelect: ee,
|
|
8287
8085
|
handleCodeTestResult: se,
|
|
8288
|
-
nextQuestion:
|
|
8086
|
+
nextQuestion: V,
|
|
8289
8087
|
previousQuestion: ae,
|
|
8290
|
-
nextLesson:
|
|
8088
|
+
nextLesson: K,
|
|
8291
8089
|
previousLesson: pe,
|
|
8292
8090
|
completeLesson: D,
|
|
8293
|
-
completeCurriculum:
|
|
8091
|
+
completeCurriculum: $,
|
|
8294
8092
|
resetCurriculum: te,
|
|
8295
8093
|
getState: () => ({ ...a.current }),
|
|
8296
|
-
getCurrentQuestion: () =>
|
|
8094
|
+
getCurrentQuestion: () => H(),
|
|
8297
8095
|
getCurrentLesson: () => y(),
|
|
8298
8096
|
// Direct access to avatar ref (always returns current value)
|
|
8299
|
-
getAvatarRef: () =>
|
|
8097
|
+
getAvatarRef: () => u.current,
|
|
8300
8098
|
// Convenience methods that delegate to avatar (always check current ref)
|
|
8301
|
-
speakText: async (
|
|
8302
|
-
await
|
|
8303
|
-
const
|
|
8304
|
-
|
|
8099
|
+
speakText: async (v, R = {}) => {
|
|
8100
|
+
await u.current?.resumeAudioContext?.();
|
|
8101
|
+
const z = I.current || { lipsyncLang: "en" };
|
|
8102
|
+
u.current?.speakText(v, { ...R, lipsyncLang: R.lipsyncLang || z.lipsyncLang });
|
|
8305
8103
|
},
|
|
8306
8104
|
resumeAudioContext: async () => {
|
|
8307
|
-
if (
|
|
8308
|
-
return await
|
|
8309
|
-
const
|
|
8310
|
-
if (
|
|
8311
|
-
const
|
|
8312
|
-
if (
|
|
8105
|
+
if (u.current?.resumeAudioContext)
|
|
8106
|
+
return await u.current.resumeAudioContext();
|
|
8107
|
+
const v = u.current?.talkingHead;
|
|
8108
|
+
if (v?.audioCtx) {
|
|
8109
|
+
const R = v.audioCtx;
|
|
8110
|
+
if (R.state === "suspended" || R.state === "interrupted")
|
|
8313
8111
|
try {
|
|
8314
|
-
await
|
|
8315
|
-
} catch (
|
|
8316
|
-
console.warn("Failed to resume audio context:",
|
|
8112
|
+
await R.resume(), console.log("Audio context resumed via talkingHead");
|
|
8113
|
+
} catch (z) {
|
|
8114
|
+
console.warn("Failed to resume audio context:", z);
|
|
8317
8115
|
}
|
|
8318
8116
|
} else
|
|
8319
8117
|
console.warn("Audio context not available yet");
|
|
8320
8118
|
},
|
|
8321
|
-
stopSpeaking: () =>
|
|
8322
|
-
pauseSpeaking: () =>
|
|
8323
|
-
resumeSpeaking: async () => await
|
|
8324
|
-
isPaused: () =>
|
|
8325
|
-
setMood: (
|
|
8326
|
-
playAnimation: (
|
|
8327
|
-
setBodyMovement: (
|
|
8328
|
-
setMovementIntensity: (
|
|
8329
|
-
playRandomDance: () =>
|
|
8330
|
-
playReaction: (
|
|
8331
|
-
playCelebration: () =>
|
|
8332
|
-
setShowFullAvatar: (
|
|
8333
|
-
setTimingAdjustment: (
|
|
8334
|
-
lockAvatarPosition: () =>
|
|
8335
|
-
unlockAvatarPosition: () =>
|
|
8119
|
+
stopSpeaking: () => u.current?.stopSpeaking(),
|
|
8120
|
+
pauseSpeaking: () => u.current?.pauseSpeaking(),
|
|
8121
|
+
resumeSpeaking: async () => await u.current?.resumeSpeaking(),
|
|
8122
|
+
isPaused: () => u.current && typeof u.current.isPaused < "u" ? u.current.isPaused : !1,
|
|
8123
|
+
setMood: (v) => u.current?.setMood(v),
|
|
8124
|
+
playAnimation: (v, R) => u.current?.playAnimation(v, R),
|
|
8125
|
+
setBodyMovement: (v) => u.current?.setBodyMovement(v),
|
|
8126
|
+
setMovementIntensity: (v) => u.current?.setMovementIntensity(v),
|
|
8127
|
+
playRandomDance: () => u.current?.playRandomDance(),
|
|
8128
|
+
playReaction: (v) => u.current?.playReaction(v),
|
|
8129
|
+
playCelebration: () => u.current?.playCelebration(),
|
|
8130
|
+
setShowFullAvatar: (v) => u.current?.setShowFullAvatar(v),
|
|
8131
|
+
setTimingAdjustment: (v) => u.current?.setTimingAdjustment(v),
|
|
8132
|
+
lockAvatarPosition: () => u.current?.lockAvatarPosition(),
|
|
8133
|
+
unlockAvatarPosition: () => u.current?.unlockAvatarPosition(),
|
|
8336
8134
|
// Custom action trigger
|
|
8337
|
-
triggerCustomAction: (
|
|
8135
|
+
triggerCustomAction: (v, R) => {
|
|
8338
8136
|
c.current.onCustomAction({
|
|
8339
|
-
type:
|
|
8340
|
-
...
|
|
8137
|
+
type: v,
|
|
8138
|
+
...R,
|
|
8341
8139
|
state: { ...a.current }
|
|
8342
8140
|
});
|
|
8343
8141
|
},
|
|
8344
8142
|
// Responsive resize handler
|
|
8345
|
-
handleResize: () =>
|
|
8143
|
+
handleResize: () => u.current?.handleResize(),
|
|
8346
8144
|
// Avatar readiness check (always returns current value)
|
|
8347
|
-
isAvatarReady: () =>
|
|
8348
|
-
}), [
|
|
8349
|
-
const U =
|
|
8145
|
+
isAvatarReady: () => u.current?.isReady || !1
|
|
8146
|
+
}), [X, k, ee, se, V, K, D, $, te, H, y]);
|
|
8147
|
+
const U = I.current || {
|
|
8350
8148
|
avatarUrl: "/avatars/brunette.glb",
|
|
8351
8149
|
avatarBody: "F",
|
|
8352
8150
|
mood: "happy",
|
|
@@ -8362,7 +8160,7 @@ const yt = Me(({
|
|
|
8362
8160
|
return /* @__PURE__ */ me("div", { style: { width: "100%", height: "100%" }, children: /* @__PURE__ */ me(
|
|
8363
8161
|
Ve,
|
|
8364
8162
|
{
|
|
8365
|
-
ref:
|
|
8163
|
+
ref: u,
|
|
8366
8164
|
avatarUrl: U.avatarUrl,
|
|
8367
8165
|
avatarBody: U.avatarBody,
|
|
8368
8166
|
mood: U.mood,
|
|
@@ -8378,8 +8176,8 @@ const yt = Me(({
|
|
|
8378
8176
|
onReady: le,
|
|
8379
8177
|
onLoading: () => {
|
|
8380
8178
|
},
|
|
8381
|
-
onError: (
|
|
8382
|
-
console.error("Avatar error:",
|
|
8179
|
+
onError: (v) => {
|
|
8180
|
+
console.error("Avatar error:", v);
|
|
8383
8181
|
}
|
|
8384
8182
|
}
|
|
8385
8183
|
) });
|
|
@@ -8488,7 +8286,7 @@ const Ge = {
|
|
|
8488
8286
|
duration: 5e3,
|
|
8489
8287
|
description: "Excited, energetic movement"
|
|
8490
8288
|
}
|
|
8491
|
-
}, wt = (
|
|
8289
|
+
}, wt = (Z) => Ge[Z] || null, zt = (Z) => Ge.hasOwnProperty(Z);
|
|
8492
8290
|
export {
|
|
8493
8291
|
yt as CurriculumLearning,
|
|
8494
8292
|
gt as SimpleTalkingAvatar,
|