@sage-rsc/talking-head-react 1.0.61 → 1.0.63
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +2 -2
- package/dist/index.js +1064 -1044
- package/package.json +1 -1
- package/src/components/TalkingHeadAvatar.jsx +65 -16
package/dist/index.js
CHANGED
|
@@ -1,21 +1,21 @@
|
|
|
1
|
-
import { jsxs as
|
|
2
|
-
import { forwardRef as Ie, useRef as
|
|
1
|
+
import { jsxs as Ee, jsx as ue } from "react/jsx-runtime";
|
|
2
|
+
import { forwardRef as Ie, useRef as G, useState as de, useEffect as me, useCallback as T, useImperativeHandle as Le, useLayoutEffect as We } from "react";
|
|
3
3
|
import * as f from "three";
|
|
4
|
-
import { OrbitControls as
|
|
5
|
-
import { GLTFLoader as
|
|
6
|
-
import { DRACOLoader as
|
|
7
|
-
import { FBXLoader as
|
|
8
|
-
import { RoomEnvironment as
|
|
9
|
-
import
|
|
10
|
-
let m,
|
|
11
|
-
const
|
|
4
|
+
import { OrbitControls as Ve } from "three/addons/controls/OrbitControls.js";
|
|
5
|
+
import { GLTFLoader as Ge } from "three/addons/loaders/GLTFLoader.js";
|
|
6
|
+
import { DRACOLoader as Ze } from "three/addons/loaders/DRACOLoader.js";
|
|
7
|
+
import { FBXLoader as ze } from "three/addons/loaders/FBXLoader.js";
|
|
8
|
+
import { RoomEnvironment as Xe } from "three/addons/environments/RoomEnvironment.js";
|
|
9
|
+
import Ye from "three/addons/libs/stats.module.js";
|
|
10
|
+
let m, _, $;
|
|
11
|
+
const A = [0, 0, 0, 0], k = new f.Vector3(), be = new f.Vector3(), Q = new f.Vector3(), ve = new f.Vector3();
|
|
12
12
|
new f.Plane();
|
|
13
13
|
new f.Ray();
|
|
14
14
|
new f.Euler();
|
|
15
|
-
const q = new f.Quaternion(),
|
|
15
|
+
const q = new f.Quaternion(), Ce = new f.Quaternion(), se = new f.Matrix4(), ae = new f.Matrix4();
|
|
16
16
|
new f.Vector3();
|
|
17
|
-
const Re = new f.Vector3(0, 0, 1),
|
|
18
|
-
class
|
|
17
|
+
const Re = new f.Vector3(0, 0, 1), je = new f.Vector3(1, 0, 0), Qe = new f.Vector3(0, 1, 0), qe = new f.Vector3(0, 0, 1);
|
|
18
|
+
class _e {
|
|
19
19
|
constructor(t = null) {
|
|
20
20
|
this.opt = Object.assign({
|
|
21
21
|
warmupMs: 2e3,
|
|
@@ -80,34 +80,34 @@ class Qe {
|
|
|
80
80
|
throw new Error("Dynamic bones has not been setup yet.");
|
|
81
81
|
if (!this.dict.hasOwnProperty(t))
|
|
82
82
|
throw new Error("Dynamic bone '" + t + "' not found.");
|
|
83
|
-
const
|
|
84
|
-
let
|
|
83
|
+
const n = this.dict[t];
|
|
84
|
+
let i;
|
|
85
85
|
if (e === "type")
|
|
86
|
-
|
|
86
|
+
i = n.type;
|
|
87
87
|
else if (e === "stiffness")
|
|
88
|
-
|
|
88
|
+
i = n.k.every((s) => s === n.k[0]) ? n.k[0] : [...n.k];
|
|
89
89
|
else if (e === "damping")
|
|
90
|
-
|
|
90
|
+
i = n.c.every((s) => s === n.c[0]) ? n.c[0] : [...n.c];
|
|
91
91
|
else if (e === "external")
|
|
92
|
-
|
|
92
|
+
i = n.ext < 1 ? n.ext : null;
|
|
93
93
|
else if (e === "limits")
|
|
94
|
-
|
|
94
|
+
i = n.limits?.map((s) => s === null ? null : [...s]);
|
|
95
95
|
else if (e === "deltaLocal")
|
|
96
|
-
|
|
96
|
+
i = n.dl ? [...n.dl] : null;
|
|
97
97
|
else if (e === "excludes")
|
|
98
|
-
|
|
98
|
+
i = n.excludes ? [...n.excludes.map((s) => {
|
|
99
99
|
const o = { bone: s.bone.name.slice(), radius: s.radius };
|
|
100
100
|
return s.deltaLocal && (o.deltaLocal = [...s.deltaLocal]), o;
|
|
101
101
|
})] : null;
|
|
102
102
|
else if (e === "deltaWorld")
|
|
103
|
-
|
|
103
|
+
i = n.dw ? [...n.dw] : null;
|
|
104
104
|
else if (e === "pivot")
|
|
105
|
-
|
|
105
|
+
i = n.pivot;
|
|
106
106
|
else if (e === "helper")
|
|
107
|
-
|
|
107
|
+
i = n.helper;
|
|
108
108
|
else
|
|
109
109
|
throw new Error("Unsupported property '" + e + "'.");
|
|
110
|
-
return
|
|
110
|
+
return i;
|
|
111
111
|
}
|
|
112
112
|
/**
|
|
113
113
|
* Set property value for a dynamic bone.
|
|
@@ -116,77 +116,77 @@ class Qe {
|
|
|
116
116
|
* @param {string} key Property name
|
|
117
117
|
* @param {any} val Property value
|
|
118
118
|
*/
|
|
119
|
-
setValue(t, e,
|
|
119
|
+
setValue(t, e, n) {
|
|
120
120
|
if (this.scene === null)
|
|
121
121
|
throw new Error("Dynamic bones has not been setup yet.");
|
|
122
122
|
if (!this.dict.hasOwnProperty(t))
|
|
123
123
|
throw new Error("Dynamic bone '" + t + "' not found.");
|
|
124
|
-
const
|
|
124
|
+
const i = this.dict[t];
|
|
125
125
|
if (e === "type") {
|
|
126
|
-
if (!
|
|
127
|
-
if (typeof
|
|
128
|
-
switch (
|
|
126
|
+
if (!n) throw new Error("Parameter 'type' not set.");
|
|
127
|
+
if (typeof n != "string") throw new Error("Type must be a string.");
|
|
128
|
+
switch (n) {
|
|
129
129
|
case "point":
|
|
130
|
-
|
|
130
|
+
i.isPoint = !0, i.isX = !0, i.isY = !0, i.isZ = !0, i.isT = !1;
|
|
131
131
|
break;
|
|
132
132
|
case "link":
|
|
133
|
-
|
|
133
|
+
i.isPoint = !1, i.isX = !0, i.isY = !1, i.isZ = !0, i.isT = !1;
|
|
134
134
|
break;
|
|
135
135
|
case "mix1":
|
|
136
|
-
|
|
136
|
+
i.isPoint = !1, i.isX = !0, i.isY = !0, i.isZ = !0, i.isT = !1;
|
|
137
137
|
break;
|
|
138
138
|
case "mix2":
|
|
139
|
-
|
|
139
|
+
i.isPoint = !1, i.isX = !0, i.isY = !1, i.isZ = !0, i.isT = !0;
|
|
140
140
|
break;
|
|
141
141
|
case "full":
|
|
142
|
-
|
|
142
|
+
i.isPoint = !1, i.isX = !0, i.isY = !0, i.isZ = !0, i.isT = !0;
|
|
143
143
|
break;
|
|
144
144
|
default:
|
|
145
|
-
throw new Error("Unknown type'" +
|
|
145
|
+
throw new Error("Unknown type'" + n + "'.");
|
|
146
146
|
}
|
|
147
|
-
|
|
147
|
+
i.type = n.slice();
|
|
148
148
|
} else if (e === "stiffness") {
|
|
149
|
-
if (!
|
|
150
|
-
if (!Number.isNaN(
|
|
151
|
-
|
|
152
|
-
else if (Array.isArray(
|
|
153
|
-
|
|
149
|
+
if (!n) throw new Error("Parameter 'stiffness' not set.");
|
|
150
|
+
if (!Number.isNaN(n) && n >= 0)
|
|
151
|
+
i.k = Array(4).fill(n);
|
|
152
|
+
else if (Array.isArray(n) && n.length === 4 && n.every((s) => s >= 0))
|
|
153
|
+
i.k = [...n];
|
|
154
154
|
else
|
|
155
155
|
throw new Error("Stiffness must be a non-negative number or an array of four non-negative numbers.");
|
|
156
156
|
} else if (e === "damping") {
|
|
157
|
-
if (!
|
|
158
|
-
if (!Number.isNaN(
|
|
159
|
-
|
|
160
|
-
else if (Array.isArray(
|
|
161
|
-
|
|
157
|
+
if (!n) throw new Error("Parameter 'damping' not set.");
|
|
158
|
+
if (!Number.isNaN(n) && n >= 0)
|
|
159
|
+
i.c = Array(4).fill(n);
|
|
160
|
+
else if (Array.isArray(n) && n.length === 4 && n.every((s) => s >= 0))
|
|
161
|
+
i.c = [...n];
|
|
162
162
|
else
|
|
163
163
|
throw new Error("Damping must be a non-negative number or an array of four non-negative numbers.");
|
|
164
164
|
} else if (e === "external")
|
|
165
|
-
if (
|
|
166
|
-
|
|
167
|
-
else if (!Number.isNaN(
|
|
168
|
-
|
|
165
|
+
if (n == null)
|
|
166
|
+
i.ext = 1;
|
|
167
|
+
else if (!Number.isNaN(n) && n >= 0 && n <= 1)
|
|
168
|
+
i.ext = n;
|
|
169
169
|
else
|
|
170
170
|
throw new Error("External (if set) must be a number between [0,1].");
|
|
171
171
|
else if (e === "limits")
|
|
172
|
-
if (
|
|
173
|
-
|
|
172
|
+
if (n == null)
|
|
173
|
+
i.limits = null;
|
|
174
174
|
else {
|
|
175
|
-
if (!Array.isArray(
|
|
176
|
-
if (!
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
175
|
+
if (!Array.isArray(n) || n.length !== 4) throw new Error("Limits (if set) must null, or an array of four arrays.");
|
|
176
|
+
if (!n.every((s) => s === null || Array.isArray(s) && s.length === 2 && (s[0] === null || !Number.isNaN(s[0])) && (s[1] === null || !Number.isNaN(s)))) throw new Error("Limit values must be null or numbers.");
|
|
177
|
+
i.limits = [
|
|
178
|
+
n[0] ? [...n[0]] : null,
|
|
179
|
+
n[1] ? [...n[1]] : null,
|
|
180
|
+
n[2] ? [...n[2]] : null,
|
|
181
|
+
n[3] ? [...n[3]] : null
|
|
182
182
|
];
|
|
183
183
|
}
|
|
184
184
|
else if (e === "excludes") {
|
|
185
|
-
if (
|
|
186
|
-
|
|
185
|
+
if (n == null)
|
|
186
|
+
i.excludes = null;
|
|
187
187
|
else {
|
|
188
|
-
if (!Array.isArray(
|
|
189
|
-
|
|
188
|
+
if (!Array.isArray(n)) throw new Error("Excludes (if set) must null, or an array.");
|
|
189
|
+
i.excludes = [], n.forEach((s, o) => {
|
|
190
190
|
if (!s.bone) throw new Error("Bone not specified in #" + o + " exclude.");
|
|
191
191
|
if (typeof s.bone != "string" || s.bone.length === 0) throw new Error("Bone name must be a non-empty string in #" + o + " exclude.");
|
|
192
192
|
const l = this.armature.getObjectByName(s.bone);
|
|
@@ -205,41 +205,41 @@ class Qe {
|
|
|
205
205
|
if (!Array.isArray(s.deltaLocal) || s.deltaLocal.length !== 3 || s.deltaLocal.some((a) => Number.isNaN(a))) throw new Error("deltaLocal must be an array of three numbers in #" + o + " exclude.");
|
|
206
206
|
u.deltaLocal = [...s.deltaLocal];
|
|
207
207
|
}
|
|
208
|
-
|
|
208
|
+
i.excludes.push(u);
|
|
209
209
|
});
|
|
210
210
|
}
|
|
211
211
|
this.showHelpers();
|
|
212
212
|
} else if (e === "helper") {
|
|
213
|
-
if (
|
|
214
|
-
|
|
213
|
+
if (n == null)
|
|
214
|
+
i.helper = null;
|
|
215
215
|
else {
|
|
216
|
-
if (
|
|
217
|
-
|
|
216
|
+
if (n !== !1 && n !== !0) throw new Error("Helper, if set, must be false or true.");
|
|
217
|
+
i.helper = n;
|
|
218
218
|
}
|
|
219
219
|
this.showHelpers();
|
|
220
220
|
} else if (e === "pivot")
|
|
221
|
-
if (
|
|
222
|
-
|
|
221
|
+
if (n == null)
|
|
222
|
+
i.pivot = null;
|
|
223
223
|
else {
|
|
224
|
-
if (
|
|
225
|
-
if (
|
|
226
|
-
|
|
224
|
+
if (n !== !1 && n !== !0) throw new Error("Pivot, if set, must be false or true.");
|
|
225
|
+
if (n === !0 && i.type === 0) throw new Error("Point type bone can't be a pivot.");
|
|
226
|
+
i.pivot = n;
|
|
227
227
|
}
|
|
228
228
|
else if (e === "deltaLocal")
|
|
229
|
-
if (
|
|
230
|
-
|
|
229
|
+
if (n == null)
|
|
230
|
+
i.dl = null;
|
|
231
231
|
else {
|
|
232
|
-
if (!Array.isArray(
|
|
233
|
-
if (!
|
|
234
|
-
|
|
232
|
+
if (!Array.isArray(n) || n.length !== 3) throw new Error("deltaLocal, is set, must be an array of three numbers.");
|
|
233
|
+
if (!n.every((s) => !Number.isNaN(s))) throw new Error("deltaLocal values must be numbers.");
|
|
234
|
+
i.dl = [...n];
|
|
235
235
|
}
|
|
236
236
|
else if (e === "deltaWorld")
|
|
237
|
-
if (
|
|
238
|
-
|
|
237
|
+
if (n == null)
|
|
238
|
+
i.dw = null;
|
|
239
239
|
else {
|
|
240
|
-
if (!Array.isArray(
|
|
241
|
-
if (!
|
|
242
|
-
|
|
240
|
+
if (!Array.isArray(n) || n.length !== 3) throw new Error("deltaWorld, is set, must be an array of three values.");
|
|
241
|
+
if (!n.every((s) => !Number.isNaN(s))) throw new Error("deltaWorld values must be numbers.");
|
|
242
|
+
i.dw = [...n];
|
|
243
243
|
}
|
|
244
244
|
else
|
|
245
245
|
throw new Error("Unsupported property " + e);
|
|
@@ -263,8 +263,8 @@ class Qe {
|
|
|
263
263
|
"excludes",
|
|
264
264
|
"pivot",
|
|
265
265
|
"helper"
|
|
266
|
-
].forEach((
|
|
267
|
-
m = this.getValue(t.name,
|
|
266
|
+
].forEach((n) => {
|
|
267
|
+
m = this.getValue(t.name, n), m && (e[n] = m);
|
|
268
268
|
}), e;
|
|
269
269
|
});
|
|
270
270
|
}
|
|
@@ -281,9 +281,9 @@ class Qe {
|
|
|
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
|
-
const
|
|
285
|
-
|
|
286
|
-
|
|
284
|
+
const n = /* @__PURE__ */ new WeakSet(), i = (o) => o.parent?.isBone ? [o, ...i(o.parent)] : [o], s = (o) => {
|
|
285
|
+
i(o).forEach((u) => {
|
|
286
|
+
n.has(u) || (this.objectsUpdate.push(u), n.add(u));
|
|
287
287
|
});
|
|
288
288
|
};
|
|
289
289
|
this.data.forEach((o) => {
|
|
@@ -299,19 +299,19 @@ class Qe {
|
|
|
299
299
|
* @param {Object3D} armature Armature object
|
|
300
300
|
* @param {Object[]} config Array of configuration objects
|
|
301
301
|
*/
|
|
302
|
-
setup(t, e,
|
|
302
|
+
setup(t, e, n) {
|
|
303
303
|
this.dispose();
|
|
304
|
-
const
|
|
304
|
+
const i = (s, o) => {
|
|
305
305
|
if (!s)
|
|
306
306
|
throw this.dispose(), new Error(o);
|
|
307
307
|
};
|
|
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
311
|
const u = s.bone;
|
|
312
|
-
|
|
312
|
+
i(typeof u == "string" && u.length > 0, l + "Bone name must be a non-empty string.");
|
|
313
313
|
const a = this.armature.getObjectByName(u);
|
|
314
|
-
|
|
314
|
+
i(a, l + "Bone '" + u + "' not found."), i(a.parent?.isBone, l + "Bone must have a parent bone."), i(this.data.every((r) => r.bone !== a), l + "Bone '" + u + "' already exists."), a.updateMatrixWorld(!0);
|
|
315
315
|
const h = {
|
|
316
316
|
name: u,
|
|
317
317
|
// Bone name
|
|
@@ -338,11 +338,11 @@ class Qe {
|
|
|
338
338
|
ea: [0, 0, 0, 0]
|
|
339
339
|
// External acceleration [m/s^2]
|
|
340
340
|
};
|
|
341
|
-
h.boneParent.matrixWorld.decompose(k, q, Q), k.copy(Re).applyQuaternion(q).setY(0).normalize(), q.premultiply(
|
|
341
|
+
h.boneParent.matrixWorld.decompose(k, q, Q), k.copy(Re).applyQuaternion(q).setY(0).normalize(), q.premultiply(Ce.setFromUnitVectors(Re, k).invert()).normalize(), h.qWorldInverseYaw = q.clone().normalize(), this.data.push(h), this.dict[u] = h;
|
|
342
342
|
try {
|
|
343
343
|
this.setValue(u, "type", s.type), this.setValue(u, "stiffness", s.stiffness), this.setValue(u, "damping", s.damping), this.setValue(u, "external", s.external), this.setValue(u, "limits", s.limits), this.setValue(u, "excludes", s.excludes), this.setValue(u, "deltaLocal", s.deltaLocal), this.setValue(u, "deltaWorld", s.deltaWorld), this.setValue(u, "pivot", s.pivot), this.setValue(u, "helper", s.helper);
|
|
344
344
|
} catch (r) {
|
|
345
|
-
|
|
345
|
+
i(!1, l + r);
|
|
346
346
|
}
|
|
347
347
|
}), this.sortBones(), this.start();
|
|
348
348
|
}
|
|
@@ -352,26 +352,26 @@ class Qe {
|
|
|
352
352
|
*/
|
|
353
353
|
update(t) {
|
|
354
354
|
if (!this.running) return;
|
|
355
|
-
let e,
|
|
356
|
-
for (this.timerMs += t, t > 1e3 && (this.timerMs = 0), t /= 1e3, e = 0,
|
|
355
|
+
let e, n, i, s, o;
|
|
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
|
-
for (e = 0,
|
|
359
|
-
if (o = this.data[e], k.copy(o.vWorld),
|
|
360
|
-
for (
|
|
361
|
-
m = o.children[
|
|
362
|
-
if (m = this.opt.sensitivityFactor,
|
|
363
|
-
o.vBasis.x +
|
|
364
|
-
o.vBasis.y +
|
|
365
|
-
o.vBasis.z +
|
|
366
|
-
), k.applyMatrix4(
|
|
358
|
+
for (e = 0, i = this.data.length; e < i; e++) {
|
|
359
|
+
if (o = this.data[e], k.copy(o.vWorld), se.copy(o.boneParent.matrixWorld), ae.copy(se).invert(), o.vWorld.setFromMatrixPosition(se), k.applyMatrix4(ae), k.length() > 0.5 && (console.info("Info: Unrealistic jump of " + k.length().toFixed(2) + " meters."), k.setLength(0.5)), k.applyQuaternion(o.bone.quaternion), A[0] = k.x, A[1] = k.y, A[2] = -k.z, A[3] = k.length() / 3, o.children)
|
|
360
|
+
for (n = 0, s = o.children.length; n < s; n++)
|
|
361
|
+
m = o.children[n], A[0] -= m.v[0] * t / 3, A[1] -= m.v[1] * t / 3, A[2] += m.v[2] * t / 3, A[3] -= m.v[3] * t / 3;
|
|
362
|
+
if (m = this.opt.sensitivityFactor, A[0] *= o.ext * m, A[1] *= o.ext * m, A[2] *= o.ext * m, A[3] *= o.ext * m, o.isX && (m = A[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 + A[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 = A[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 + A[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 = A[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 + A[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 = A[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 + A[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), A[0] = o.p[0], A[1] = o.p[1], A[2] = o.p[2], A[3] = o.p[3], m = this.opt.movementFactor, A[0] *= m, A[1] *= m, A[2] *= m, A[3] *= m, o.dl && (m = o.dl, A[0] += m[0], A[1] += m[1], A[2] += m[2]), o.dw && (m = o.dw, k.set(
|
|
363
|
+
o.vBasis.x + A[0],
|
|
364
|
+
o.vBasis.y + A[1],
|
|
365
|
+
o.vBasis.z + A[2]
|
|
366
|
+
), k.applyMatrix4(se), k.x += m[0], k.y += m[1], k.z += m[2], k.applyMatrix4(ae), A[0] += k.x - o.vBasis.x, A[1] += k.y - o.vBasis.y, A[2] += k.z - o.vBasis.z), o.limits && this.opt.isLimits && (m = o.limits, m[0] && (m[0][0] !== null && A[0] < m[0][0] && (A[0] = m[0][0]), m[0][1] !== null && A[0] > m[0][1] && (A[0] = m[0][1])), m[1] && (m[1][0] !== null && A[1] < m[1][0] && (A[1] = m[1][0]), m[1][1] !== null && A[1] > m[1][1] && (A[1] = m[1][1])), m[2] && (m[2][0] !== null && A[2] < m[2][0] && (A[2] = m[2][0]), m[2][1] !== null && A[2] > m[2][1] && (A[2] = m[2][1])), m[3] && (m[3][0] !== null && A[3] < m[3][0] && (A[3] = m[3][0]), m[3][1] !== null && A[3] > m[3][1] && (A[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 + A[0],
|
|
369
|
+
o.vBasis.y + A[1],
|
|
370
|
+
o.vBasis.z - A[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(k, q, Q), k.copy(Re).applyQuaternion(q).setY(0).normalize(), q.premultiply(
|
|
373
|
-
for (
|
|
374
|
-
m = o.excludes[
|
|
372
|
+
else if (o.boneParent.quaternion.copy(o.qBasis), o.pivot && this.opt.isPivots && (o.boneParent.updateWorldMatrix(!1, !1), o.boneParent.matrixWorld.decompose(k, q, Q), k.copy(Re).applyQuaternion(q).setY(0).normalize(), q.premultiply(Ce.setFromUnitVectors(Re, k).invert()).normalize(), o.boneParent.quaternion.multiply(q.invert()), o.boneParent.quaternion.multiply(o.qWorldInverseYaw)), o.isZ && (m = Math.atan(A[0] / o.l), q.setFromAxisAngle(qe, -m), o.boneParent.quaternion.multiply(q)), o.isY && (m = o.l / 3, m = m * Math.tanh(A[1] / m), o.bone.position.setLength(o.l + m)), o.isX && (m = Math.atan(A[2] / o.l), q.setFromAxisAngle(je, -m), o.boneParent.quaternion.multiply(q)), o.isT && (m = 1.5 * Math.tanh(A[3] * 1.5), q.setFromAxisAngle(Qe, -m), o.boneParent.quaternion.multiply(q)), o.boneParent.updateWorldMatrix(!1, !0), o.excludes && this.opt.isExcludes)
|
|
373
|
+
for (n = 0, s = o.excludes.length; n < s; n++)
|
|
374
|
+
m = o.excludes[n], Q.set(0, 0, 0), m.deltaLocal && (Q.x += m.deltaLocal[0], Q.y += m.deltaLocal[1], Q.z += m.deltaLocal[2]), Q.applyMatrix4(m.bone.matrixWorld), ae.copy(o.boneParent.matrixWorld).invert(), Q.applyMatrix4(ae), k.copy(o.bone.position), !(k.distanceToSquared(Q) >= m.radiusSq) && ($ = k.length(), _ = Q.length(), !(_ > m.radius + $) && (_ < Math.abs(m.radius - $) || (_ = (_ * _ + $ * $ - m.radiusSq) / (2 * _), Q.normalize(), ve.copy(Q).multiplyScalar(_), _ = Math.sqrt($ * $ - _ * _), k.subVectors(k, ve).projectOnPlane(Q).normalize().multiplyScalar(_), be.subVectors(o.vBasis, ve).projectOnPlane(Q).normalize(), $ = be.dot(k), $ < 0 && ($ = Math.sqrt(_ * _ - $ * $), be.multiplyScalar($), k.add(be)), k.add(ve).normalize(), Q.copy(o.bone.position).normalize(), q.setFromUnitVectors(Q, k), o.boneParent.quaternion.premultiply(q), o.boneParent.updateWorldMatrix(!1, !0))));
|
|
375
375
|
}
|
|
376
376
|
this.helpers.isActive && this.updateHelpers();
|
|
377
377
|
}
|
|
@@ -383,17 +383,17 @@ class Qe {
|
|
|
383
383
|
*/
|
|
384
384
|
showHelpers(t) {
|
|
385
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((
|
|
387
|
-
let
|
|
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
|
+
let i = !1;
|
|
388
388
|
for (let s = 0; s < m.excludes.bones.length; s++)
|
|
389
|
-
if (m.excludes.bones[s] ===
|
|
390
|
-
|
|
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
|
+
i = !0;
|
|
391
391
|
break;
|
|
392
392
|
}
|
|
393
|
-
|
|
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
|
-
}), m = this.helpers.excludes, this.opt.isExcludes && m.bones.length && m.bones.forEach((e,
|
|
396
|
-
const
|
|
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 Qe {
|
|
|
401
401
|
wireframe: !0,
|
|
402
402
|
color: this.opt.helperExcludesColor
|
|
403
403
|
});
|
|
404
|
-
m.objects[
|
|
405
|
-
m.deltaLocals[
|
|
406
|
-
m.deltaLocals[
|
|
407
|
-
m.deltaLocals[
|
|
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(),
|
|
412
|
-
e.setAttribute("position", new f.Float32BufferAttribute(
|
|
413
|
-
const
|
|
411
|
+
const e = new f.BufferGeometry(), n = m.bones.map((u) => [0, 0, 0]).flat();
|
|
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 = m.pivots.map((u) => u && 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,
|
|
@@ -423,9 +423,9 @@ class Qe {
|
|
|
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
425
|
if (m = this.helpers.lines, m.bones.length) {
|
|
426
|
-
const e = new f.BufferGeometry(),
|
|
427
|
-
e.setAttribute("position", new f.Float32BufferAttribute(
|
|
428
|
-
const
|
|
426
|
+
const e = new f.BufferGeometry(), n = m.bones.map((u) => [0, 0, 0, 0, 0, 0]).flat();
|
|
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 = m.bones.map((u) => [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,
|
|
@@ -442,17 +442,17 @@ class Qe {
|
|
|
442
442
|
*/
|
|
443
443
|
updateHelpers() {
|
|
444
444
|
if (m = this.helpers.points, m.bones.length) {
|
|
445
|
-
|
|
445
|
+
ae.copy(this.armature.matrixWorld).invert();
|
|
446
446
|
const t = m.object.geometry.getAttribute("position");
|
|
447
|
-
for (let e = 0,
|
|
448
|
-
|
|
447
|
+
for (let e = 0, n = m.bones.length; e < n; e++)
|
|
448
|
+
se.multiplyMatrices(ae, m.bones[e].matrixWorld), k.setFromMatrixPosition(se), t.setXYZ(e, k.x, k.y, k.z);
|
|
449
449
|
t.needsUpdate = !0, m.object.updateMatrixWorld();
|
|
450
450
|
}
|
|
451
451
|
if (m = this.helpers.lines, m.bones.length) {
|
|
452
|
-
|
|
452
|
+
ae.copy(this.armature.matrixWorld).invert();
|
|
453
453
|
const t = m.object.geometry.getAttribute("position");
|
|
454
|
-
for (let e = 0,
|
|
455
|
-
|
|
454
|
+
for (let e = 0, n = 0, i = m.bones.length; e < i; e++, n += 2)
|
|
455
|
+
se.multiplyMatrices(ae, m.bones[e].matrixWorld), k.setFromMatrixPosition(se), t.setXYZ(n, k.x, k.y, k.z), se.multiplyMatrices(ae, m.bones[e].parent.matrixWorld), k.setFromMatrixPosition(se), t.setXYZ(n + 1, k.x, k.y, k.z);
|
|
456
456
|
t.needsUpdate = !0, m.object.updateMatrixWorld();
|
|
457
457
|
}
|
|
458
458
|
}
|
|
@@ -478,8 +478,8 @@ class Qe {
|
|
|
478
478
|
stop() {
|
|
479
479
|
this.running = !1, this.hideHelpers();
|
|
480
480
|
for (let t = 0, e = this.data.length; t < e; t++) {
|
|
481
|
-
const
|
|
482
|
-
|
|
481
|
+
const n = this.data[t];
|
|
482
|
+
n.bone.position.copy(n.vBasis), n.boneParent.quaternion.copy(n.qBasis);
|
|
483
483
|
}
|
|
484
484
|
}
|
|
485
485
|
/**
|
|
@@ -489,7 +489,7 @@ class Qe {
|
|
|
489
489
|
this.stop(), this.scene = null, this.armature = null, this.config = [], this.data = [], this.dict = {}, this.objectsUpdate = [], this.timerMs = 0;
|
|
490
490
|
}
|
|
491
491
|
}
|
|
492
|
-
class
|
|
492
|
+
class Ke {
|
|
493
493
|
constructor(t) {
|
|
494
494
|
this.audioContext = t, this.analyzer = null, this.dataArray = null, this.bufferLength = 0;
|
|
495
495
|
}
|
|
@@ -500,8 +500,8 @@ class qe {
|
|
|
500
500
|
* @returns {Object} Timing data with visemes and precise timing
|
|
501
501
|
*/
|
|
502
502
|
async analyzeAudio(t, e) {
|
|
503
|
-
const
|
|
504
|
-
return this.generateTimingData(o, e,
|
|
503
|
+
const n = t.sampleRate, i = t.duration, s = t.getChannelData(0), o = this.extractAudioFeatures(s, n);
|
|
504
|
+
return this.generateTimingData(o, e, i);
|
|
505
505
|
}
|
|
506
506
|
/**
|
|
507
507
|
* Extract audio features from the audio data
|
|
@@ -510,25 +510,25 @@ class qe {
|
|
|
510
510
|
* @returns {Object} Extracted audio features
|
|
511
511
|
*/
|
|
512
512
|
extractAudioFeatures(t, e) {
|
|
513
|
-
const
|
|
513
|
+
const n = {
|
|
514
514
|
energy: [],
|
|
515
515
|
spectralCentroid: [],
|
|
516
516
|
zeroCrossingRate: [],
|
|
517
517
|
mfcc: [],
|
|
518
518
|
onsets: [],
|
|
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 u = l * s, a = Math.min(u +
|
|
523
|
-
|
|
522
|
+
const u = l * s, a = Math.min(u + i, t.length), h = t.slice(u, a), r = this.calculateEnergy(h);
|
|
523
|
+
n.energy.push(r);
|
|
524
524
|
const c = this.calculateSpectralCentroid(h);
|
|
525
|
-
|
|
525
|
+
n.spectralCentroid.push(c);
|
|
526
526
|
const d = this.calculateZeroCrossingRate(h);
|
|
527
|
-
|
|
527
|
+
n.zeroCrossingRate.push(d);
|
|
528
528
|
const g = this.calculateMFCC(h);
|
|
529
|
-
|
|
529
|
+
n.mfcc.push(g);
|
|
530
530
|
}
|
|
531
|
-
return
|
|
531
|
+
return n.onsets = this.detectOnsets(n.energy), n.phonemeBoundaries = this.detectPhonemeBoundaries(n), n;
|
|
532
532
|
}
|
|
533
533
|
/**
|
|
534
534
|
* Calculate energy of an audio frame
|
|
@@ -537,8 +537,8 @@ class qe {
|
|
|
537
537
|
*/
|
|
538
538
|
calculateEnergy(t) {
|
|
539
539
|
let e = 0;
|
|
540
|
-
for (let
|
|
541
|
-
e += t[
|
|
540
|
+
for (let n = 0; n < t.length; n++)
|
|
541
|
+
e += t[n] * t[n];
|
|
542
542
|
return e / t.length;
|
|
543
543
|
}
|
|
544
544
|
/**
|
|
@@ -548,12 +548,12 @@ class qe {
|
|
|
548
548
|
*/
|
|
549
549
|
calculateSpectralCentroid(t) {
|
|
550
550
|
const e = this.fft(t);
|
|
551
|
-
let
|
|
551
|
+
let n = 0, i = 0;
|
|
552
552
|
for (let s = 0; s < e.length / 2; s++) {
|
|
553
553
|
const o = Math.sqrt(e[s * 2] * e[s * 2] + e[s * 2 + 1] * e[s * 2 + 1]);
|
|
554
|
-
|
|
554
|
+
n += s * o, i += o;
|
|
555
555
|
}
|
|
556
|
-
return
|
|
556
|
+
return i > 0 ? n / i : 0;
|
|
557
557
|
}
|
|
558
558
|
/**
|
|
559
559
|
* Calculate zero crossing rate
|
|
@@ -562,8 +562,8 @@ class qe {
|
|
|
562
562
|
*/
|
|
563
563
|
calculateZeroCrossingRate(t) {
|
|
564
564
|
let e = 0;
|
|
565
|
-
for (let
|
|
566
|
-
t[
|
|
565
|
+
for (let n = 1; n < t.length; n++)
|
|
566
|
+
t[n] >= 0 != t[n - 1] >= 0 && e++;
|
|
567
567
|
return e / (t.length - 1);
|
|
568
568
|
}
|
|
569
569
|
/**
|
|
@@ -572,16 +572,16 @@ class qe {
|
|
|
572
572
|
* @returns {Array} MFCC coefficients
|
|
573
573
|
*/
|
|
574
574
|
calculateMFCC(t) {
|
|
575
|
-
const e = this.fft(t),
|
|
576
|
-
for (let
|
|
575
|
+
const e = this.fft(t), n = [];
|
|
576
|
+
for (let i = 0; i < 13; i++) {
|
|
577
577
|
let s = 0;
|
|
578
578
|
for (let o = 0; o < e.length / 2; o++) {
|
|
579
579
|
const l = Math.sqrt(e[o * 2] * e[o * 2] + e[o * 2 + 1] * e[o * 2 + 1]);
|
|
580
|
-
s += l * Math.cos(Math.PI *
|
|
580
|
+
s += l * Math.cos(Math.PI * i * (o + 0.5) / (e.length / 2));
|
|
581
581
|
}
|
|
582
|
-
|
|
582
|
+
n.push(s);
|
|
583
583
|
}
|
|
584
|
-
return
|
|
584
|
+
return n;
|
|
585
585
|
}
|
|
586
586
|
/**
|
|
587
587
|
* Simple FFT implementation
|
|
@@ -589,31 +589,31 @@ class qe {
|
|
|
589
589
|
* @returns {Float32Array} FFT result
|
|
590
590
|
*/
|
|
591
591
|
fft(t) {
|
|
592
|
-
const e = t.length,
|
|
593
|
-
for (let
|
|
594
|
-
i
|
|
595
|
-
for (let
|
|
592
|
+
const e = t.length, n = new Float32Array(e * 2);
|
|
593
|
+
for (let i = 0; i < e; i++)
|
|
594
|
+
n[i * 2] = t[i], n[i * 2 + 1] = 0;
|
|
595
|
+
for (let i = 1, s = 0; i < e; i++) {
|
|
596
596
|
let o = e >> 1;
|
|
597
597
|
for (; s & o; )
|
|
598
598
|
s ^= o, o >>= 1;
|
|
599
|
-
if (s ^= o,
|
|
600
|
-
const l = i
|
|
601
|
-
i
|
|
599
|
+
if (s ^= o, i < s) {
|
|
600
|
+
const l = n[i * 2], u = 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] = u;
|
|
602
602
|
}
|
|
603
603
|
}
|
|
604
|
-
for (let
|
|
605
|
-
const s = -2 * Math.PI /
|
|
606
|
-
for (let u = 0; u < e; u +=
|
|
604
|
+
for (let i = 2; i <= e; i <<= 1) {
|
|
605
|
+
const s = -2 * Math.PI / i, o = Math.cos(s), l = Math.sin(s);
|
|
606
|
+
for (let u = 0; u < e; u += i) {
|
|
607
607
|
let a = 1, h = 0;
|
|
608
|
-
for (let r = 0; r <
|
|
609
|
-
const c =
|
|
610
|
-
|
|
608
|
+
for (let r = 0; r < i / 2; r++) {
|
|
609
|
+
const c = n[(u + r) * 2], d = n[(u + r) * 2 + 1], g = n[(u + r + i / 2) * 2] * a - n[(u + r + i / 2) * 2 + 1] * h, y = n[(u + r + i / 2) * 2] * h + n[(u + r + i / 2) * 2 + 1] * a;
|
|
610
|
+
n[(u + r) * 2] = c + g, n[(u + r) * 2 + 1] = d + y, n[(u + r + i / 2) * 2] = c - g, n[(u + r + i / 2) * 2 + 1] = d - y;
|
|
611
611
|
const x = a * o - h * l, I = a * l + h * o;
|
|
612
612
|
a = x, h = I;
|
|
613
613
|
}
|
|
614
614
|
}
|
|
615
615
|
}
|
|
616
|
-
return
|
|
616
|
+
return n;
|
|
617
617
|
}
|
|
618
618
|
/**
|
|
619
619
|
* Detect onsets in the audio
|
|
@@ -635,9 +635,9 @@ class qe {
|
|
|
635
635
|
* @returns {Array} Phoneme boundary times
|
|
636
636
|
*/
|
|
637
637
|
detectPhonemeBoundaries(t) {
|
|
638
|
-
const e = [], { energy:
|
|
639
|
-
for (let o = 1; o <
|
|
640
|
-
const l = o * 0.023, u = Math.abs(
|
|
638
|
+
const e = [], { energy: n, spectralCentroid: i, zeroCrossingRate: s } = t;
|
|
639
|
+
for (let o = 1; o < n.length; o++) {
|
|
640
|
+
const l = o * 0.023, u = Math.abs(n[o] - n[o - 1]), a = Math.abs(i[o] - i[o - 1]), h = Math.abs(s[o] - s[o - 1]);
|
|
641
641
|
u + a * 0.1 + h * 0.5 > 0.2 && e.push(l);
|
|
642
642
|
}
|
|
643
643
|
return e;
|
|
@@ -649,13 +649,13 @@ class qe {
|
|
|
649
649
|
* @param {number} duration - Audio duration in seconds
|
|
650
650
|
* @returns {Object} Precise timing data
|
|
651
651
|
*/
|
|
652
|
-
generateTimingData(t, e,
|
|
653
|
-
const
|
|
652
|
+
generateTimingData(t, e, n) {
|
|
653
|
+
const i = e.toLowerCase().split(/\s+/);
|
|
654
654
|
t.phonemeBoundaries, t.onsets;
|
|
655
655
|
const s = [];
|
|
656
656
|
let o = 0;
|
|
657
|
-
for (let u = 0; u <
|
|
658
|
-
const a =
|
|
657
|
+
for (let u = 0; u < i.length; u++) {
|
|
658
|
+
const a = i[u], h = this.estimateWordDuration(a, n / i.length);
|
|
659
659
|
s.push({
|
|
660
660
|
word: a,
|
|
661
661
|
startTime: o,
|
|
@@ -663,11 +663,11 @@ class qe {
|
|
|
663
663
|
duration: h
|
|
664
664
|
}), o += h;
|
|
665
665
|
}
|
|
666
|
-
const l = this.generateVisemeTimings(t, e,
|
|
666
|
+
const l = this.generateVisemeTimings(t, e, n);
|
|
667
667
|
return {
|
|
668
668
|
words: s,
|
|
669
669
|
visemes: l,
|
|
670
|
-
duration:
|
|
670
|
+
duration: n,
|
|
671
671
|
features: t
|
|
672
672
|
};
|
|
673
673
|
}
|
|
@@ -678,8 +678,8 @@ class qe {
|
|
|
678
678
|
* @returns {number} Estimated duration
|
|
679
679
|
*/
|
|
680
680
|
estimateWordDuration(t, e) {
|
|
681
|
-
const
|
|
682
|
-
return e *
|
|
681
|
+
const n = Math.max(0.5, Math.min(2, t.length / 5)), i = this.getWordComplexity(t);
|
|
682
|
+
return e * n * i;
|
|
683
683
|
}
|
|
684
684
|
/**
|
|
685
685
|
* Get word complexity factor
|
|
@@ -687,8 +687,8 @@ class qe {
|
|
|
687
687
|
* @returns {number} Complexity factor
|
|
688
688
|
*/
|
|
689
689
|
getWordComplexity(t) {
|
|
690
|
-
const e = (t.match(/[bcdfghjklmnpqrstvwxyz]{2,}/g) || []).length,
|
|
691
|
-
return 1 + e * 0.2 +
|
|
690
|
+
const e = (t.match(/[bcdfghjklmnpqrstvwxyz]{2,}/g) || []).length, n = (t.match(/[aeiou]{2,}/g) || []).length;
|
|
691
|
+
return 1 + e * 0.2 + n * 0.1;
|
|
692
692
|
}
|
|
693
693
|
/**
|
|
694
694
|
* Generate viseme timings based on audio analysis
|
|
@@ -697,14 +697,14 @@ class qe {
|
|
|
697
697
|
* @param {number} duration - Audio duration
|
|
698
698
|
* @returns {Array} Viseme timing data
|
|
699
699
|
*/
|
|
700
|
-
generateVisemeTimings(t, e,
|
|
701
|
-
const
|
|
700
|
+
generateVisemeTimings(t, e, n) {
|
|
701
|
+
const i = [], s = t.phonemeBoundaries;
|
|
702
702
|
t.onsets;
|
|
703
703
|
const o = this.textToVisemes(e);
|
|
704
704
|
let l = 0, u = 0;
|
|
705
705
|
for (let a = 0; a < s.length && l < o.length; a++) {
|
|
706
706
|
const h = s[a], r = o[l], c = t.energy[Math.floor(h / 0.023)] || 0, d = this.calculateVisemeDuration(r, c);
|
|
707
|
-
|
|
707
|
+
i.push({
|
|
708
708
|
viseme: r,
|
|
709
709
|
startTime: u,
|
|
710
710
|
endTime: u + d,
|
|
@@ -715,7 +715,7 @@ class qe {
|
|
|
715
715
|
}
|
|
716
716
|
for (; l < o.length; ) {
|
|
717
717
|
const a = o[l], h = this.calculateVisemeDuration(a, 0.5);
|
|
718
|
-
|
|
718
|
+
i.push({
|
|
719
719
|
viseme: a,
|
|
720
720
|
startTime: u,
|
|
721
721
|
endTime: u + h,
|
|
@@ -723,7 +723,7 @@ class qe {
|
|
|
723
723
|
intensity: 0.6
|
|
724
724
|
}), u += h, l++;
|
|
725
725
|
}
|
|
726
|
-
return
|
|
726
|
+
return i;
|
|
727
727
|
}
|
|
728
728
|
/**
|
|
729
729
|
* Convert text to visemes using phonetic analysis
|
|
@@ -770,25 +770,25 @@ class qe {
|
|
|
770
770
|
w: "RR",
|
|
771
771
|
y: "I",
|
|
772
772
|
h: "kk"
|
|
773
|
-
},
|
|
774
|
-
for (const s of
|
|
773
|
+
}, n = [], i = t.toLowerCase().replace(/[^a-z\s]/g, "").split(/\s+/);
|
|
774
|
+
for (const s of i) {
|
|
775
775
|
let o = 0;
|
|
776
776
|
for (; o < s.length; ) {
|
|
777
777
|
let l = !1;
|
|
778
778
|
for (let u = 3; u >= 2; u--) {
|
|
779
779
|
const a = s.substr(o, u);
|
|
780
780
|
if (e[a]) {
|
|
781
|
-
|
|
781
|
+
n.push(e[a]), o += u, l = !0;
|
|
782
782
|
break;
|
|
783
783
|
}
|
|
784
784
|
}
|
|
785
785
|
if (!l) {
|
|
786
786
|
const u = s[o];
|
|
787
|
-
e[u] &&
|
|
787
|
+
e[u] && n.push(e[u]), o++;
|
|
788
788
|
}
|
|
789
789
|
}
|
|
790
790
|
}
|
|
791
|
-
return
|
|
791
|
+
return n;
|
|
792
792
|
}
|
|
793
793
|
/**
|
|
794
794
|
* Calculate viseme duration based on viseme type and audio energy
|
|
@@ -797,7 +797,7 @@ class qe {
|
|
|
797
797
|
* @returns {number} Duration in seconds
|
|
798
798
|
*/
|
|
799
799
|
calculateVisemeDuration(t, e) {
|
|
800
|
-
const
|
|
800
|
+
const i = {
|
|
801
801
|
aa: 0.15,
|
|
802
802
|
E: 0.12,
|
|
803
803
|
I: 0.1,
|
|
@@ -811,10 +811,10 @@ class qe {
|
|
|
811
811
|
nn: 0.1,
|
|
812
812
|
RR: 0.11
|
|
813
813
|
}[t] || 0.1, s = 0.5 + e * 0.5;
|
|
814
|
-
return
|
|
814
|
+
return i * s;
|
|
815
815
|
}
|
|
816
816
|
}
|
|
817
|
-
class
|
|
817
|
+
class Je {
|
|
818
818
|
/**
|
|
819
819
|
* @constructor
|
|
820
820
|
*/
|
|
@@ -1205,8 +1205,8 @@ class _e {
|
|
|
1205
1205
|
// Start/end of the word
|
|
1206
1206
|
};
|
|
1207
1207
|
Object.keys(this.rules).forEach((e) => {
|
|
1208
|
-
this.rules[e] = this.rules[e].map((
|
|
1209
|
-
const
|
|
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), u = n.substring(i + 1, s), a = n.substring(s + 1, o), h = n.substring(o + 1), r = { regex: "", move: 0, visemes: [] };
|
|
1210
1210
|
let c = "";
|
|
1211
1211
|
c += [...l].map((g) => t[g] || g).join("");
|
|
1212
1212
|
const d = [...u];
|
|
@@ -1278,13 +1278,13 @@ class _e {
|
|
|
1278
1278
|
convert_digit_by_digit(t) {
|
|
1279
1279
|
t = String(t).split("");
|
|
1280
1280
|
let e = "";
|
|
1281
|
-
for (let
|
|
1282
|
-
e += this.digits[t[
|
|
1281
|
+
for (let n = 0; n < t.length; n++)
|
|
1282
|
+
e += this.digits[t[n]] + " ";
|
|
1283
1283
|
return e = e.substring(0, e.length - 1), e;
|
|
1284
1284
|
}
|
|
1285
1285
|
convert_sets_of_two(t) {
|
|
1286
|
-
let e = String(t).substring(0, 2),
|
|
1287
|
-
return
|
|
1286
|
+
let e = String(t).substring(0, 2), n = String(t).substring(2, 4), i = this.convert_tens(e);
|
|
1287
|
+
return i += " " + this.convert_tens(n), i;
|
|
1288
1288
|
}
|
|
1289
1289
|
convert_millions(t) {
|
|
1290
1290
|
return t >= 1e6 ? this.convert_millions(Math.floor(t / 1e6)) + " million " + this.convert_thousands(t % 1e6) : this.convert_thousands(t);
|
|
@@ -1306,14 +1306,14 @@ class _e {
|
|
|
1306
1306
|
* @return {string} String
|
|
1307
1307
|
*/
|
|
1308
1308
|
convertNumberToWords(t, e = !1) {
|
|
1309
|
-
const
|
|
1309
|
+
const n = parseFloat(t);
|
|
1310
1310
|
if (t == "0")
|
|
1311
1311
|
return "zero";
|
|
1312
1312
|
if (t < 0)
|
|
1313
1313
|
return " minus " + this.convertNumberToWords(Math.abs(t).toString(), e).trim();
|
|
1314
|
-
if (
|
|
1315
|
-
const
|
|
1316
|
-
return this.convertNumberToWords(
|
|
1314
|
+
if (n && !Number.isInteger(n)) {
|
|
1315
|
+
const i = n.toString().split(".");
|
|
1316
|
+
return this.convertNumberToWords(i[0], e).trim() + " point " + this.convert_digit_by_digit(i[1]).trim();
|
|
1317
1317
|
} else return t.toString().startsWith("0") ? this.convert_digit_by_digit(t).trim() : !e && (t < 1e3 && t > 99 && t % 100 !== 0 || t > 1e4 && t < 1e6) ? this.convert_digit_by_digit(t).trim() : !e && (t > 1e3 && t < 2e3 || t > 2009 && t < 3e3) ? t % 100 != 0 ? this.convert_sets_of_two(t).trim() : this.convert_tens(t.toString().substring(0, 2)).trim() + " hundred" : this.convert_millions(t).trim();
|
|
1318
1318
|
}
|
|
1319
1319
|
/**
|
|
@@ -1323,7 +1323,7 @@ class _e {
|
|
|
1323
1323
|
* @return {string} Normalized text
|
|
1324
1324
|
*/
|
|
1325
1325
|
convertDecade(t) {
|
|
1326
|
-
const e = parseInt(t),
|
|
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
1327
|
let u = [];
|
|
1328
1328
|
return s ? u.push(this.convertNumberToWords(s).trim(), "thousands") : (o && u.push(this.convertNumberToWords(o).trim()), l ? u.push(this.decades[l] || this.convertNumberToWords(l).trim() + "s") : o ? u.push("hundreds") : u.push(t)), u.join(" ");
|
|
1329
1329
|
}
|
|
@@ -1336,9 +1336,9 @@ class _e {
|
|
|
1336
1336
|
convertOrdinal(t) {
|
|
1337
1337
|
if (this.ordinals.hasOwnProperty(t))
|
|
1338
1338
|
return this.ordinals[t];
|
|
1339
|
-
const e = Math.floor(t / 100),
|
|
1339
|
+
const e = Math.floor(t / 100), n = Math.floor(t % 100 / 10) * 10, i = t % 10;
|
|
1340
1340
|
let s = [];
|
|
1341
|
-
return e && (s.push(this.convertNumberToWords(e).trim()),
|
|
1341
|
+
return e && (s.push(this.convertNumberToWords(e).trim()), n || i ? s.push("hundred") : s.push("hundredth")), n && (i ? s.push(this.convertNumberToWords(n).trim()) : s.push(this.ordinals[n])), i && s.push(this.ordinals[i]), s.join(" ");
|
|
1342
1342
|
}
|
|
1343
1343
|
/**
|
|
1344
1344
|
* Preprocess text:
|
|
@@ -1350,18 +1350,18 @@ class _e {
|
|
|
1350
1350
|
*/
|
|
1351
1351
|
preProcessText(t) {
|
|
1352
1352
|
let e = t.replace('/[#_*":;]/g', "");
|
|
1353
|
-
return e = e.replace(this.symbolsReg, (
|
|
1354
|
-
const s = this.convertDecade(
|
|
1355
|
-
return s ===
|
|
1356
|
-
}), e = e.replace(/\b(\d+)\s*(st|nd|rd|th)(?=\s|[.,!?;:]|$)/gi, (
|
|
1353
|
+
return e = e.replace(this.symbolsReg, (n) => " " + this.symbols[n] + " "), /\d/.test(e) && (e = e.replace(/\b(\d{2,4})[''']?\s?[sS](?=\s|[.,!?;:]|$)/g, (n, i) => {
|
|
1354
|
+
const s = this.convertDecade(i);
|
|
1355
|
+
return s === i ? n : s;
|
|
1356
|
+
}), e = e.replace(/\b(\d+)\s*(st|nd|rd|th)(?=\s|[.,!?;:]|$)/gi, (n, i) => this.convertOrdinal(Number(i))), e = e.replace(/\b(\w*?)(\d+)([A-Za-z]+)\b/g, (n, i, s, o) => {
|
|
1357
1357
|
const l = this.convertNumberToWords(s);
|
|
1358
|
-
return `${
|
|
1359
|
-
}).replace(/\b([A-Za-z]+)(\d+)(\w*?)\b/g, (
|
|
1358
|
+
return `${i}${l} ${o}`;
|
|
1359
|
+
}).replace(/\b([A-Za-z]+)(\d+)(\w*?)\b/g, (n, i, s, o) => {
|
|
1360
1360
|
const l = this.convertNumberToWords(s);
|
|
1361
|
-
return `${
|
|
1362
|
-
}), e = e.replace(/-?(?:\d{1,3}(?:,\d{3})+|\d+)(\.\d+)?/g, (
|
|
1363
|
-
let s =
|
|
1364
|
-
return /,/.test(s) && (s = s.replace(/,/g, ""), o = !0),
|
|
1361
|
+
return `${i} ${l}${o}`;
|
|
1362
|
+
}), e = e.replace(/-?(?:\d{1,3}(?:,\d{3})+|\d+)(\.\d+)?/g, (n, i) => {
|
|
1363
|
+
let s = n, o = !1;
|
|
1364
|
+
return /,/.test(s) && (s = s.replace(/,/g, ""), o = !0), i && (o = !0), this.convertNumberToWords(s, o);
|
|
1365
1365
|
})), e = e.replace(/(\D)\1\1+/g, "$1$1").replaceAll(" ", " ").normalize("NFD").replace(/[\u0300-\u036f]/g, "").normalize("NFC").trim(), e;
|
|
1366
1366
|
}
|
|
1367
1367
|
/**
|
|
@@ -1370,10 +1370,10 @@ class _e {
|
|
|
1370
1370
|
* @return {Object} Oculus LipSync Visemes and durations.
|
|
1371
1371
|
*/
|
|
1372
1372
|
wordsToVisemes(t) {
|
|
1373
|
-
let e = { words: t.toUpperCase(), visemes: [], times: [], durations: [], i: 0 },
|
|
1374
|
-
const
|
|
1375
|
-
for (; e.i <
|
|
1376
|
-
const s =
|
|
1373
|
+
let e = { words: t.toUpperCase(), visemes: [], times: [], durations: [], i: 0 }, n = 0;
|
|
1374
|
+
const i = [...e.words];
|
|
1375
|
+
for (; e.i < i.length; ) {
|
|
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
1379
|
const u = o[l];
|
|
@@ -1381,26 +1381,26 @@ class _e {
|
|
|
1381
1381
|
u.visemes.forEach((r) => {
|
|
1382
1382
|
if (e.visemes.length && e.visemes[e.visemes.length - 1] === r) {
|
|
1383
1383
|
const c = 0.7 * (this.visemeDurations[r] || 1);
|
|
1384
|
-
e.durations[e.durations.length - 1] += c,
|
|
1384
|
+
e.durations[e.durations.length - 1] += c, n += c;
|
|
1385
1385
|
} else {
|
|
1386
1386
|
const c = this.visemeDurations[r] || 1;
|
|
1387
|
-
e.visemes.push(r), e.times.push(
|
|
1387
|
+
e.visemes.push(r), e.times.push(n), e.durations.push(c), n += c;
|
|
1388
1388
|
}
|
|
1389
1389
|
}), e.i += u.move;
|
|
1390
1390
|
break;
|
|
1391
1391
|
}
|
|
1392
1392
|
}
|
|
1393
1393
|
else
|
|
1394
|
-
e.i++,
|
|
1394
|
+
e.i++, n += this.specialDurations[s] || 0;
|
|
1395
1395
|
}
|
|
1396
1396
|
return e;
|
|
1397
1397
|
}
|
|
1398
1398
|
}
|
|
1399
|
-
const
|
|
1399
|
+
const $e = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
|
|
1400
1400
|
__proto__: null,
|
|
1401
|
-
LipsyncEn:
|
|
1401
|
+
LipsyncEn: Je
|
|
1402
1402
|
}, Symbol.toStringTag, { value: "Module" }));
|
|
1403
|
-
class
|
|
1403
|
+
class et {
|
|
1404
1404
|
/**
|
|
1405
1405
|
* @constructor
|
|
1406
1406
|
*/
|
|
@@ -1615,8 +1615,8 @@ class Je {
|
|
|
1615
1615
|
// Word boundary
|
|
1616
1616
|
};
|
|
1617
1617
|
Object.keys(this.rules).forEach((e) => {
|
|
1618
|
-
this.rules[e] = this.rules[e].map((
|
|
1619
|
-
const
|
|
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), u = n.substring(i + 1, s), a = n.substring(s + 1, o), h = n.substring(o + 1), r = { regex: "", move: 0, visemes: [] };
|
|
1620
1620
|
let c = "";
|
|
1621
1621
|
c += [...l].map((g) => t[g] || g).join("");
|
|
1622
1622
|
const d = [...u];
|
|
@@ -1666,31 +1666,31 @@ class Je {
|
|
|
1666
1666
|
convert_digit_by_digit(t) {
|
|
1667
1667
|
t = String(t).split("");
|
|
1668
1668
|
let e = "";
|
|
1669
|
-
for (let
|
|
1670
|
-
e += this.digits[t[
|
|
1669
|
+
for (let n = 0; n < t.length; n++)
|
|
1670
|
+
e += this.digits[t[n]] + " ";
|
|
1671
1671
|
return e = e.substring(0, e.length - 1), e;
|
|
1672
1672
|
}
|
|
1673
1673
|
convert_millions(t) {
|
|
1674
1674
|
if (t >= 1e6) {
|
|
1675
|
-
const e = Math.floor(t / 1e6),
|
|
1676
|
-
let
|
|
1677
|
-
return
|
|
1675
|
+
const e = Math.floor(t / 1e6), n = t % 1e6;
|
|
1676
|
+
let i = this.convert_thousands(e);
|
|
1677
|
+
return i += e === 1 ? " million " : " millionen ", n > 0 && (i += this.convert_thousands(n)), i;
|
|
1678
1678
|
} else
|
|
1679
1679
|
return this.convert_thousands(t);
|
|
1680
1680
|
}
|
|
1681
1681
|
convert_thousands(t) {
|
|
1682
1682
|
if (t >= 1e3) {
|
|
1683
|
-
const e = Math.floor(t / 1e3),
|
|
1684
|
-
let
|
|
1685
|
-
return e === 1 ?
|
|
1683
|
+
const e = Math.floor(t / 1e3), n = t % 1e3;
|
|
1684
|
+
let i = "";
|
|
1685
|
+
return e === 1 ? i = "eintausend" : i = this.convert_hundreds(e) + "tausend", n > 0 && (i += this.convert_hundreds(n)), i;
|
|
1686
1686
|
} else
|
|
1687
1687
|
return this.convert_hundreds(t);
|
|
1688
1688
|
}
|
|
1689
1689
|
convert_hundreds(t) {
|
|
1690
1690
|
if (t > 99) {
|
|
1691
|
-
const e = Math.floor(t / 100),
|
|
1692
|
-
let
|
|
1693
|
-
return e === 1 ?
|
|
1691
|
+
const e = Math.floor(t / 100), n = t % 100;
|
|
1692
|
+
let i = "";
|
|
1693
|
+
return e === 1 ? i = "einhundert" : i = this.ones[e] + "hundert", n > 0 && (i += this.convert_tens(n)), i;
|
|
1694
1694
|
} else
|
|
1695
1695
|
return this.convert_tens(t);
|
|
1696
1696
|
}
|
|
@@ -1700,8 +1700,8 @@ class Je {
|
|
|
1700
1700
|
if (t >= 10 && t < 20)
|
|
1701
1701
|
return this.teens[t - 10];
|
|
1702
1702
|
{
|
|
1703
|
-
const e = Math.floor(t / 10),
|
|
1704
|
-
return
|
|
1703
|
+
const e = Math.floor(t / 10), n = t % 10;
|
|
1704
|
+
return n === 0 ? this.tens[e] : this.ones[n] + "und" + this.tens[e];
|
|
1705
1705
|
}
|
|
1706
1706
|
}
|
|
1707
1707
|
convertNumberToWords(t) {
|
|
@@ -1726,10 +1726,10 @@ class Je {
|
|
|
1726
1726
|
* @return {Object} Oculus LipSync Visemes and durations.
|
|
1727
1727
|
*/
|
|
1728
1728
|
wordsToVisemes(t) {
|
|
1729
|
-
let e = { words: t.toUpperCase(), visemes: [], times: [], durations: [], i: 0 },
|
|
1730
|
-
const
|
|
1731
|
-
for (; e.i <
|
|
1732
|
-
const s =
|
|
1729
|
+
let e = { words: t.toUpperCase(), visemes: [], times: [], durations: [], i: 0 }, n = 0;
|
|
1730
|
+
const i = [...e.words];
|
|
1731
|
+
for (; e.i < i.length; ) {
|
|
1732
|
+
const s = i[e.i], o = this.rules[s];
|
|
1733
1733
|
if (o) {
|
|
1734
1734
|
let l = !1;
|
|
1735
1735
|
for (let u = 0; u < o.length; u++) {
|
|
@@ -1738,27 +1738,27 @@ class Je {
|
|
|
1738
1738
|
a.visemes.forEach((c) => {
|
|
1739
1739
|
if (e.visemes.length && e.visemes[e.visemes.length - 1] === c) {
|
|
1740
1740
|
const d = 0.7 * (this.visemeDurations[c] || 1);
|
|
1741
|
-
e.durations[e.durations.length - 1] += d,
|
|
1741
|
+
e.durations[e.durations.length - 1] += d, n += d;
|
|
1742
1742
|
} else {
|
|
1743
1743
|
const d = this.visemeDurations[c] || 1;
|
|
1744
|
-
e.visemes.push(c), e.times.push(
|
|
1744
|
+
e.visemes.push(c), e.times.push(n), e.durations.push(d), n += d;
|
|
1745
1745
|
}
|
|
1746
1746
|
}), e.i += a.move, l = !0;
|
|
1747
1747
|
break;
|
|
1748
1748
|
}
|
|
1749
1749
|
}
|
|
1750
|
-
l || (e.i++,
|
|
1750
|
+
l || (e.i++, n += this.specialDurations[s] || 0);
|
|
1751
1751
|
} else
|
|
1752
|
-
e.i++,
|
|
1752
|
+
e.i++, n += this.specialDurations[s] || 0;
|
|
1753
1753
|
}
|
|
1754
1754
|
return e;
|
|
1755
1755
|
}
|
|
1756
1756
|
}
|
|
1757
|
-
const
|
|
1757
|
+
const tt = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
|
|
1758
1758
|
__proto__: null,
|
|
1759
|
-
LipsyncDe:
|
|
1759
|
+
LipsyncDe: et
|
|
1760
1760
|
}, Symbol.toStringTag, { value: "Module" }));
|
|
1761
|
-
class
|
|
1761
|
+
class nt {
|
|
1762
1762
|
/**
|
|
1763
1763
|
* @constructor
|
|
1764
1764
|
*/
|
|
@@ -2130,8 +2130,8 @@ class et {
|
|
|
2130
2130
|
// End of word
|
|
2131
2131
|
};
|
|
2132
2132
|
Object.keys(this.rules).forEach((e) => {
|
|
2133
|
-
this.rules[e] = this.rules[e].map((
|
|
2134
|
-
const
|
|
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), u = n.substring(i + 1, s), a = n.substring(s + 1, o), h = n.substring(o + 1), r = { regex: "", move: 0, visemes: [] };
|
|
2135
2135
|
let c = "";
|
|
2136
2136
|
c += [...l].map((g) => t[g] || g).join("");
|
|
2137
2137
|
const d = [...u];
|
|
@@ -2195,8 +2195,8 @@ class et {
|
|
|
2195
2195
|
convert_digit_by_digit(t) {
|
|
2196
2196
|
t = String(t).split("");
|
|
2197
2197
|
let e = "";
|
|
2198
|
-
for (let
|
|
2199
|
-
e += this.digits[t[
|
|
2198
|
+
for (let n = 0; n < t.length; n++)
|
|
2199
|
+
e += this.digits[t[n]] + " ";
|
|
2200
2200
|
return e = e.substring(0, e.length - 1), e;
|
|
2201
2201
|
}
|
|
2202
2202
|
convert_tens(t) {
|
|
@@ -2211,31 +2211,31 @@ class et {
|
|
|
2211
2211
|
const e = t - 80;
|
|
2212
2212
|
return e === 11 ? "quatre-vingt-onze" : "quatre-vingt-" + this.teens[e - 10];
|
|
2213
2213
|
} else {
|
|
2214
|
-
const e = Math.floor(t / 10),
|
|
2215
|
-
return e === 8 &&
|
|
2214
|
+
const e = Math.floor(t / 10), n = t % 10;
|
|
2215
|
+
return e === 8 && n === 0 ? "quatre-vingts" : e === 8 ? "quatre-vingt-" + this.ones[n] : (e === 2 || e === 3 || e === 4 || e === 5 || e === 6) && n === 1 ? this.tens[e] + " et un" : n === 0 ? this.tens[e] : this.tens[e] + "-" + this.ones[n];
|
|
2216
2216
|
}
|
|
2217
2217
|
}
|
|
2218
2218
|
convert_hundreds(t) {
|
|
2219
2219
|
if (t >= 100) {
|
|
2220
|
-
const e = Math.floor(t / 100),
|
|
2221
|
-
let
|
|
2222
|
-
return e === 1 ?
|
|
2220
|
+
const e = Math.floor(t / 100), n = t % 100;
|
|
2221
|
+
let i = "";
|
|
2222
|
+
return e === 1 ? i = "cent" : (i = this.ones[e] + " cent", n === 0 && (i += "s")), n > 0 && (i += " " + this.convert_tens(n)), i;
|
|
2223
2223
|
} else
|
|
2224
2224
|
return this.convert_tens(t);
|
|
2225
2225
|
}
|
|
2226
2226
|
convert_thousands(t) {
|
|
2227
2227
|
if (t >= 1e3) {
|
|
2228
|
-
const e = Math.floor(t / 1e3),
|
|
2229
|
-
let
|
|
2230
|
-
return e === 1 ?
|
|
2228
|
+
const e = Math.floor(t / 1e3), n = t % 1e3;
|
|
2229
|
+
let i = "";
|
|
2230
|
+
return e === 1 ? i = "mille" : i = this.convert_hundreds(e) + " mille", n > 0 && (i += " " + this.convert_hundreds(n)), i;
|
|
2231
2231
|
} else
|
|
2232
2232
|
return this.convert_hundreds(t);
|
|
2233
2233
|
}
|
|
2234
2234
|
convert_millions(t) {
|
|
2235
2235
|
if (t >= 1e6) {
|
|
2236
|
-
const e = Math.floor(t / 1e6),
|
|
2237
|
-
let
|
|
2238
|
-
return e === 1 ?
|
|
2236
|
+
const e = Math.floor(t / 1e6), n = t % 1e6;
|
|
2237
|
+
let i = "";
|
|
2238
|
+
return e === 1 ? i = "un million" : i = this.convert_hundreds(e) + " millions", n > 0 && (i += " " + this.convert_thousands(n)), i;
|
|
2239
2239
|
} else
|
|
2240
2240
|
return this.convert_thousands(t);
|
|
2241
2241
|
}
|
|
@@ -2261,10 +2261,10 @@ class et {
|
|
|
2261
2261
|
* @return {Object} Oculus LipSync Visemes and durations.
|
|
2262
2262
|
*/
|
|
2263
2263
|
wordsToVisemes(t) {
|
|
2264
|
-
let e = { words: t.toUpperCase(), visemes: [], times: [], durations: [], i: 0 },
|
|
2265
|
-
const
|
|
2266
|
-
for (; e.i <
|
|
2267
|
-
const s =
|
|
2264
|
+
let e = { words: t.toUpperCase(), visemes: [], times: [], durations: [], i: 0 }, n = 0;
|
|
2265
|
+
const i = [...e.words];
|
|
2266
|
+
for (; e.i < i.length; ) {
|
|
2267
|
+
const s = i[e.i], o = this.rules[s];
|
|
2268
2268
|
if (o) {
|
|
2269
2269
|
let l = !1;
|
|
2270
2270
|
for (let u = 0; u < o.length; u++) {
|
|
@@ -2273,27 +2273,27 @@ class et {
|
|
|
2273
2273
|
a.visemes.forEach((c) => {
|
|
2274
2274
|
if (e.visemes.length && e.visemes[e.visemes.length - 1] === c) {
|
|
2275
2275
|
const d = 0.7 * (this.visemeDurations[c] || 1);
|
|
2276
|
-
e.durations[e.durations.length - 1] += d,
|
|
2276
|
+
e.durations[e.durations.length - 1] += d, n += d;
|
|
2277
2277
|
} else {
|
|
2278
2278
|
const d = this.visemeDurations[c] || 1;
|
|
2279
|
-
e.visemes.push(c), e.times.push(
|
|
2279
|
+
e.visemes.push(c), e.times.push(n), e.durations.push(d), n += d;
|
|
2280
2280
|
}
|
|
2281
2281
|
}), e.i += a.move, l = !0;
|
|
2282
2282
|
break;
|
|
2283
2283
|
}
|
|
2284
2284
|
}
|
|
2285
|
-
l || (e.i++,
|
|
2285
|
+
l || (e.i++, n += this.specialDurations[s] || 0);
|
|
2286
2286
|
} else
|
|
2287
|
-
e.i++,
|
|
2287
|
+
e.i++, n += this.specialDurations[s] || 0;
|
|
2288
2288
|
}
|
|
2289
2289
|
return e;
|
|
2290
2290
|
}
|
|
2291
2291
|
}
|
|
2292
|
-
const
|
|
2292
|
+
const it = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
|
|
2293
2293
|
__proto__: null,
|
|
2294
|
-
LipsyncFr:
|
|
2294
|
+
LipsyncFr: nt
|
|
2295
2295
|
}, Symbol.toStringTag, { value: "Module" }));
|
|
2296
|
-
class
|
|
2296
|
+
class ot {
|
|
2297
2297
|
/**
|
|
2298
2298
|
* @constructor
|
|
2299
2299
|
*/
|
|
@@ -2379,18 +2379,18 @@ class it {
|
|
|
2379
2379
|
*/
|
|
2380
2380
|
numberToFinnishWords(t) {
|
|
2381
2381
|
const e = [];
|
|
2382
|
-
let
|
|
2383
|
-
if (
|
|
2384
|
-
let
|
|
2382
|
+
let n = parseFloat(t);
|
|
2383
|
+
if (n === void 0) return t;
|
|
2384
|
+
let i = (s, o, l, u, a) => {
|
|
2385
2385
|
if (s < o) return s;
|
|
2386
2386
|
const h = Math.floor(s / o);
|
|
2387
2387
|
return e.push(l + (h === 1 ? u : this.numberToFinnishWords(h.toString()) + a)), s - h * o;
|
|
2388
2388
|
};
|
|
2389
|
-
if (
|
|
2390
|
-
let s = Math.floor(
|
|
2391
|
-
e.push(this.numbers[s]),
|
|
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
|
+
let s = Math.floor(n);
|
|
2391
|
+
e.push(this.numbers[s]), n -= s;
|
|
2392
2392
|
}
|
|
2393
|
-
if (
|
|
2393
|
+
if (n >= 0 && Math.abs(parseFloat(t)) < 1 && e.push("nolla"), n > 0) {
|
|
2394
2394
|
let s = t.split(".");
|
|
2395
2395
|
if (s.length > 1) {
|
|
2396
2396
|
e.push(" pilkku");
|
|
@@ -2418,29 +2418,29 @@ class it {
|
|
|
2418
2418
|
* @return {Object} Oculus LipSync Visemes and durations.
|
|
2419
2419
|
*/
|
|
2420
2420
|
wordsToVisemes(t) {
|
|
2421
|
-
let e = { words: t, visemes: [], times: [], durations: [] },
|
|
2422
|
-
const
|
|
2423
|
-
for (let s = 0; s <
|
|
2424
|
-
const o = this.visemes[
|
|
2421
|
+
let e = { words: t, visemes: [], times: [], durations: [] }, n = 0;
|
|
2422
|
+
const i = [...t];
|
|
2423
|
+
for (let s = 0; s < i.length; s++) {
|
|
2424
|
+
const o = this.visemes[i[s].toLowerCase()];
|
|
2425
2425
|
if (o)
|
|
2426
2426
|
if (e.visemes.length && e.visemes[e.visemes.length - 1] === o) {
|
|
2427
2427
|
const l = 0.7 * (this.visemeDurations[o] || 1);
|
|
2428
|
-
e.durations[e.durations.length - 1] += l,
|
|
2428
|
+
e.durations[e.durations.length - 1] += l, n += l;
|
|
2429
2429
|
} else {
|
|
2430
2430
|
const l = this.visemeDurations[o] || 1;
|
|
2431
|
-
e.visemes.push(o), e.times.push(
|
|
2431
|
+
e.visemes.push(o), e.times.push(n), e.durations.push(l), n += l;
|
|
2432
2432
|
}
|
|
2433
2433
|
else
|
|
2434
|
-
|
|
2434
|
+
n += this.specialDurations[i[s]] || 0;
|
|
2435
2435
|
}
|
|
2436
2436
|
return e;
|
|
2437
2437
|
}
|
|
2438
2438
|
}
|
|
2439
|
-
const
|
|
2439
|
+
const st = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
|
|
2440
2440
|
__proto__: null,
|
|
2441
|
-
LipsyncFi:
|
|
2441
|
+
LipsyncFi: ot
|
|
2442
2442
|
}, Symbol.toStringTag, { value: "Module" }));
|
|
2443
|
-
class
|
|
2443
|
+
class at {
|
|
2444
2444
|
/**
|
|
2445
2445
|
* @constructor
|
|
2446
2446
|
*/
|
|
@@ -2557,24 +2557,24 @@ class ot {
|
|
|
2557
2557
|
*/
|
|
2558
2558
|
numberToLithuanianWords(t) {
|
|
2559
2559
|
const e = [];
|
|
2560
|
-
let
|
|
2561
|
-
if (
|
|
2562
|
-
let
|
|
2560
|
+
let n = parseFloat(t);
|
|
2561
|
+
if (n === void 0) return t;
|
|
2562
|
+
let i = (s, o, l, u, a) => {
|
|
2563
2563
|
if (s < o) return s;
|
|
2564
2564
|
const h = Math.floor(s / o);
|
|
2565
2565
|
return h === 1 ? e.push(this.numbers[1]) : e.push(this.numberToLithuanianWords(h.toString())), h % 10 === 1 ? e.push(l) : h % 10 === 0 || h % 100 > 10 && h % 100 < 20 ? e.push(a) : e.push(u), s - h * 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--)
|
|
2569
|
-
if (
|
|
2570
|
-
e.push(this.tens[s]),
|
|
2569
|
+
if (n >= 10 * s) {
|
|
2570
|
+
e.push(this.tens[s]), n = n - 10 * s;
|
|
2571
2571
|
break;
|
|
2572
2572
|
}
|
|
2573
|
-
if (
|
|
2574
|
-
let s = Math.floor(
|
|
2575
|
-
e.push(this.numbers[s]),
|
|
2573
|
+
if (n >= 1) {
|
|
2574
|
+
let s = Math.floor(n);
|
|
2575
|
+
e.push(this.numbers[s]), n -= s;
|
|
2576
2576
|
}
|
|
2577
|
-
if (
|
|
2577
|
+
if (n >= 0 && Math.abs(parseFloat(t)) < 1 && e.push(this.numbers[0]), n > 0) {
|
|
2578
2578
|
let s = t.split(".");
|
|
2579
2579
|
if (s.length > 1) {
|
|
2580
2580
|
e.push("kablelis");
|
|
@@ -2602,42 +2602,42 @@ class ot {
|
|
|
2602
2602
|
* @return {Object} Oculus LipSync Visemes and durations.
|
|
2603
2603
|
*/
|
|
2604
2604
|
wordsToVisemes(t) {
|
|
2605
|
-
let e = { words: t, visemes: [], times: [], durations: [] },
|
|
2606
|
-
const
|
|
2607
|
-
for (let s = 0; s <
|
|
2608
|
-
const o =
|
|
2605
|
+
let e = { words: t, visemes: [], times: [], durations: [] }, n = 0;
|
|
2606
|
+
const i = [...t];
|
|
2607
|
+
for (let s = 0; s < i.length; s++) {
|
|
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
2611
|
const u = 0.7 * (this.durations[o] || 1);
|
|
2612
|
-
e.durations[e.durations.length - 1] += u,
|
|
2612
|
+
e.durations[e.durations.length - 1] += u, n += u;
|
|
2613
2613
|
} else {
|
|
2614
2614
|
const u = this.durations[o] || 1;
|
|
2615
|
-
e.visemes.push(l), e.times.push(
|
|
2615
|
+
e.visemes.push(l), e.times.push(n), e.durations.push(u), n += u;
|
|
2616
2616
|
}
|
|
2617
2617
|
else
|
|
2618
|
-
|
|
2618
|
+
n += this.pauses[i[s]] || 0;
|
|
2619
2619
|
}
|
|
2620
2620
|
return e;
|
|
2621
2621
|
}
|
|
2622
2622
|
}
|
|
2623
|
-
const
|
|
2623
|
+
const rt = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
|
|
2624
2624
|
__proto__: null,
|
|
2625
|
-
LipsyncLt:
|
|
2626
|
-
}, Symbol.toStringTag, { value: "Module" })), at = new URL("data:text/javascript;base64,Y2xhc3MgUGxheWJhY2tXb3JrbGV0IGV4dGVuZHMgQXVkaW9Xb3JrbGV0UHJvY2Vzc29yIHsKICBzdGF0aWMgRlNNID0gewogICAgSURMRTogMCwKICAgIFBMQVlJTkc6IDEsCiAgfTsKCiAgY29uc3RydWN0b3Iob3B0aW9ucykgewogICAgc3VwZXIoKTsKICAgIHRoaXMucG9ydC5vbm1lc3NhZ2UgPSB0aGlzLmhhbmRsZU1lc3NhZ2UuYmluZCh0aGlzKTsKCiAgICB0aGlzLl9zYW1wbGVSYXRlID0gb3B0aW9ucz8ucHJvY2Vzc29yT3B0aW9ucz8uc2FtcGxlUmF0ZSB8fCBzYW1wbGVSYXRlOwogICAgdGhpcy5fc2NhbGUgPSAxIC8gMzI3Njg7IC8vIFBDTTE2IC0+IGZsb2F0CgogICAgLy8gU2lsZW5jZSBkZXRlY3Rpb24gdGhyZXNob2xkICgxIHNlY29uZCkgYXMgYSBmYWxsYmFjayBzYWZldHkgbmV0CiAgICBjb25zdCBzaWxlbmNlRHVyYXRpb25TZWNvbmRzID0gMS4wOwogICAgdGhpcy5fc2lsZW5jZVRocmVzaG9sZEJsb2NrcyA9IE1hdGguY2VpbCgodGhpcy5fc2FtcGxlUmF0ZSAqIHNpbGVuY2VEdXJhdGlvblNlY29uZHMpIC8gMTI4KTsKCiAgICAvLyBNZXRyaWNzIGNvbmZpZ3VyYXRpb24gdmlhIG9wdGlvbnMKICAgIGNvbnN0IG1ldHJpY3NDZmcgPSBvcHRpb25zPy5wcm9jZXNzb3JPcHRpb25zPy5tZXRyaWNzIHx8IHt9OwogICAgdGhpcy5fbWV0cmljc0VuYWJsZWQgPSBtZXRyaWNzQ2ZnLmVuYWJsZWQgIT09IGZhbHNlOwogICAgY29uc3QgaW50ZXJ2YWxIeiA9ICh0eXBlb2YgbWV0cmljc0NmZy5pbnRlcnZhbEh6ID09PSAibnVtYmVyIiAmJiBtZXRyaWNzQ2ZnLmludGVydmFsSHogPiAwKQogICAgICA/IG1ldHJpY3NDZmcuaW50ZXJ2YWxIeiA6IDI7CiAgICAvLyBNZXRyaWNzIHN0YXRlIChsb3ctb3ZlcmhlYWQpCiAgICB0aGlzLl9mcmFtZXNQcm9jZXNzZWQgPSAwOwogICAgdGhpcy5fdW5kZXJydW5CbG9ja3MgPSAwOwogICAgdGhpcy5fbWF4UXVldWVTYW1wbGVzID0gMDsKICAgIHRoaXMuX2xhc3RNZXRyaWNzU2VudEF0RnJhbWUgPSAwOwogICAgLy8gQ29udmVydCB0byBmcmFtZXMgYmV0d2VlbiByZXBvcnRzCiAgICB0aGlzLl9tZXRyaWNzSW50ZXJ2YWxGcmFtZXMgPSBNYXRoLm1heCgxMjgsIE1hdGgucm91bmQodGhpcy5fc2FtcGxlUmF0ZSAvIGludGVydmFsSHopKTsKCiAgICB0aGlzLnJlc2V0KCk7CiAgfQoKICAvKioKICAgKiBSZXNldHMgdGhlIHdvcmtsZXQgdG8gaXRzIGluaXRpYWwgSURMRSBzdGF0ZS4KICAgKi8KICByZXNldCgpIHsKICAgIHRoaXMuX2J1ZmZlclF1ZXVlID0gW107CiAgICB0aGlzLl9jdXJyZW50Q2h1bmsgPSBudWxsOwogICAgdGhpcy5fY3VycmVudENodW5rT2Zmc2V0ID0gMDsKICAgIHRoaXMuX3N0YXRlID0gUGxheWJhY2tXb3JrbGV0LkZTTS5JRExFOwoKICAgIHRoaXMuX25vTW9yZURhdGFSZWNlaXZlZCA9IGZhbHNlOwogICAgdGhpcy5fc2lsZW5jZUZyYW1lc0NvdW50ID0gMDsKICAgIHRoaXMuX2hhc1NlbnRFbmRlZCA9IGZhbHNlOwogICAgLy8gUmVzZXQgbWF4IHF1ZXVlIHRyYWNrZXIgb25seSB3aGVuIGdvaW5nIGlkbGUKICAgIHRoaXMuX21heFF1ZXVlU2FtcGxlcyA9IDA7CiAgfQoKICBoYW5kbGVNZXNzYWdlKGV2ZW50KSB7CiAgICBjb25zdCB7IHR5cGUsIGRhdGEgfSA9IGV2ZW50LmRhdGE7CgogICAgLy8gSU5URVJSVVBUOiBUaGUgbWFpbiB0aHJlYWQgd2FudHMgdG8gc3RvcCBpbW1lZGlhdGVseS4KICAgIGlmICh0eXBlID09PSAic3RvcCIpIHsKICAgICAgdGhpcy5yZXNldCgpOwogICAgICAvLyBTZW5kIGZpbmFsIG1ldHJpY3Mgc2hvd2luZyBjbGVhcmVkIHN0YXRlCiAgICAgIGlmICh0aGlzLl9tZXRyaWNzRW5hYmxlZCkgewogICAgICAgIHRyeSB7CiAgICAgICAgICB0aGlzLnBvcnQucG9zdE1lc3NhZ2UoewogICAgICAgICAgICB0eXBlOiAibWV0cmljcyIsCiAgICAgICAgICAgIGRhdGE6IHsKICAgICAgICAgICAgICBzdGF0ZTogUGxheWJhY2tXb3JrbGV0LkZTTS5JRExFLAogICAgICAgICAgICAgIHF1ZXVlZFNhbXBsZXM6IDAsCiAgICAgICAgICAgICAgcXVldWVkTXM6IDAsCiAgICAgICAgICAgICAgbWF4UXVldWVkTXM6IE1hdGgucm91bmQoKHRoaXMuX21heFF1ZXVlU2FtcGxlcyAvIHRoaXMuX3NhbXBsZVJhdGUpICogMTAwMCksCiAgICAgICAgICAgICAgdW5kZXJydW5CbG9ja3M6IHRoaXMuX3VuZGVycnVuQmxvY2tzLAogICAgICAgICAgICAgIGZyYW1lc1Byb2Nlc3NlZDogdGhpcy5fZnJhbWVzUHJvY2Vzc2VkCiAgICAgICAgICAgIH0KICAgICAgICAgIH0pOwogICAgICAgIH0gY2F0Y2ggKF8pIHsgfQogICAgICB9CiAgICAgIHJldHVybjsKICAgIH0KCiAgICAvLyBNYWluIHRocmVhZCBoYXMgc2lnbmFsZWQgdGhhdCBubyBtb3JlIGF1ZGlvIGNodW5rcyB3aWxsIGJlIHNlbnQgZm9yIHRoaXMgdXR0ZXJhbmNlLgogICAgaWYgKHR5cGUgPT09ICJuby1tb3JlLWRhdGEiKSB7CiAgICAgIHRoaXMuX25vTW9yZURhdGFSZWNlaXZlZCA9IHRydWU7CiAgICAgIHJldHVybjsKICAgIH0KCiAgICAvLyBVcGRhdGUgbWV0cmljcyBjb25maWd1cmF0aW9uIGF0IHJ1bnRpbWUKICAgIGlmICh0eXBlID09PSAiY29uZmlnLW1ldHJpY3MiICYmIGRhdGEgJiYgdHlwZW9mIGRhdGEgPT09ICJvYmplY3QiKSB7CiAgICAgIGlmICgiZW5hYmxlZCIgaW4gZGF0YSkgdGhpcy5fbWV0cmljc0VuYWJsZWQgPSAhIWRhdGEuZW5hYmxlZDsKICAgICAgaWYgKHR5cGVvZiBkYXRhLmludGVydmFsSHogPT09ICJudW1iZXIiICYmIGRhdGEuaW50ZXJ2YWxIeiA+IDApIHsKICAgICAgICBjb25zdCBpbnRlcnZhbEh6ID0gZGF0YS5pbnRlcnZhbEh6OwogICAgICAgIHRoaXMuX21ldHJpY3NJbnRlcnZhbEZyYW1lcyA9IE1hdGgubWF4KDEyOCwgTWF0aC5yb3VuZCh0aGlzLl9zYW1wbGVSYXRlIC8gaW50ZXJ2YWxIeikpOwogICAgICB9CiAgICAgIC8vIFJlc2V0IHBhY2luZyBzbyB0aGUgbmV4dCByZXBvcnQgYWxpZ25zIHdpdGggbmV3IGludGVydmFsCiAgICAgIHRoaXMuX2xhc3RNZXRyaWNzU2VudEF0RnJhbWUgPSB0aGlzLl9mcmFtZXNQcm9jZXNzZWQ7CiAgICAgIHJldHVybjsKICAgIH0KCiAgICAvLyBOZXcgYXVkaW8gZGF0YSBoYXMgYXJyaXZlZC4KICAgIGlmICh0eXBlID09PSAiYXVkaW9EYXRhIiAmJiBkYXRhIGluc3RhbmNlb2YgQXJyYXlCdWZmZXIpIHsKICAgICAgdGhpcy5fbm9Nb3JlRGF0YVJlY2VpdmVkID0gZmFsc2U7CiAgICAgIC8vIElmIHdlIHdlcmUgaWRsZSwgdGhpcyBuZXcgZGF0YSBraWNrcyBvZmYgdGhlIHBsYXliYWNrLgogICAgICBpZiAodGhpcy5fc3RhdGUgPT09IFBsYXliYWNrV29ya2xldC5GU00uSURMRSkgewogICAgICAgIHRoaXMuX3N0YXRlID0gUGxheWJhY2tXb3JrbGV0LkZTTS5QTEFZSU5HOwogICAgICAgIHRoaXMucG9ydC5wb3N0TWVzc2FnZSh7IHR5cGU6ICJwbGF5YmFjay1zdGFydGVkIiB9KTsKICAgICAgfQoKICAgICAgLy8gV2Ugb25seSBxdWV1ZSBkYXRhIGlmIHdlIGFyZSBpbiB0aGUgUExBWUlORyBzdGF0ZS4gVGhpcyBwcmV2ZW50cwogICAgICAvLyBkYXRhIGZyb20gYSBwcmV2aW91cywgaW50ZXJydXB0ZWQgc3RyZWFtIGZyb20gbGluZ2VyaW5nLgogICAgICBpZiAodGhpcy5fc3RhdGUgPT09IFBsYXliYWNrV29ya2xldC5GU00uUExBWUlORykgewogICAgICAgIC8vIFN0b3JlIGFzIEludDE2QXJyYXkgdmlldyB0byBhdm9pZCBjb25zdHJ1Y3RpbmcgaXQgaW4gcHJvY2VzcygpCiAgICAgICAgdGhpcy5fYnVmZmVyUXVldWUucHVzaChuZXcgSW50MTZBcnJheShkYXRhKSk7CiAgICAgICAgdGhpcy5fc2lsZW5jZUZyYW1lc0NvdW50ID0gMDsgLy8gUmVzZXQgc2lsZW5jZSBjb3VudGVyIG9uIG5ldyBkYXRhCiAgICAgIH0KICAgIH0KICB9CgogIHByb2Nlc3MoaW5wdXRzLCBvdXRwdXRzLCBwYXJhbWV0ZXJzKSB7CiAgICBjb25zdCBvdXRwdXRDaGFubmVsID0gb3V0cHV0c1swXT8uWzBdOwogICAgaWYgKCFvdXRwdXRDaGFubmVsKSB7CiAgICAgIHJldHVybiB0cnVlOyAvLyBLZWVwIGFsaXZlIGV2ZW4gaWYgb3V0cHV0IGlzIHRlbXBvcmFyaWx5IGRpc2Nvbm5lY3RlZAogICAgfQoKICAgIC8vIElmIHdlIGFyZSBub3QgcGxheWluZywganVzdCBvdXRwdXQgc2lsZW5jZSBhbmQgd2FpdC4KICAgIGlmICh0aGlzLl9zdGF0ZSAhPT0gUGxheWJhY2tXb3JrbGV0LkZTTS5QTEFZSU5HKSB7CiAgICAgIG91dHB1dENoYW5uZWwuZmlsbCgwKTsKICAgICAgcmV0dXJuIHRydWU7IC8vIEFsd2F5cyByZXR1cm4gdHJ1ZSB0byBrZWVwIHRoZSBwcm9jZXNzb3IgYWxpdmUKICAgIH0KCiAgICAvLyBDb3JlIFBMQVlJTkcgTG9naWMKICAgIGNvbnN0IGJsb2NrU2l6ZSA9IG91dHB1dENoYW5uZWwubGVuZ3RoOwogICAgbGV0IHNhbXBsZXNDb3BpZWQgPSAwOwoKICAgIHdoaWxlIChzYW1wbGVzQ29waWVkIDwgYmxvY2tTaXplKSB7CiAgICAgIGlmICghdGhpcy5fY3VycmVudENodW5rIHx8IHRoaXMuX2N1cnJlbnRDaHVua09mZnNldCA+PSB0aGlzLl9jdXJyZW50Q2h1bmsubGVuZ3RoKSB7CiAgICAgICAgaWYgKHRoaXMuX2J1ZmZlclF1ZXVlLmxlbmd0aCA+IDApIHsKICAgICAgICAgIHRoaXMuX2N1cnJlbnRDaHVuayA9IHRoaXMuX2J1ZmZlclF1ZXVlLnNoaWZ0KCk7CiAgICAgICAgICB0aGlzLl9jdXJyZW50Q2h1bmtPZmZzZXQgPSAwOwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAvLyBCdWZmZXIgaXMgZW1wdHkuIENoZWNrIGZvciBlbmQgY29uZGl0aW9ucy4KICAgICAgICAgIGNvbnN0IGlzVGltZWRPdXQgPSB0aGlzLl9zaWxlbmNlRnJhbWVzQ291bnQgPiB0aGlzLl9zaWxlbmNlVGhyZXNob2xkQmxvY2tzOwoKICAgICAgICAgIGlmICh0aGlzLl9ub01vcmVEYXRhUmVjZWl2ZWQgfHwgaXNUaW1lZE91dCkgewogICAgICAgICAgICAvLyBFTkQgT0YgUExBWUJBQ0s6IEVpdGhlciBleHBsaWNpdGx5IHNpZ25hbGVkIG9yIHRpbWVkIG91dC4KICAgICAgICAgICAgaWYgKCF0aGlzLl9oYXNTZW50RW5kZWQpIHsKICAgICAgICAgICAgICB0aGlzLnBvcnQucG9zdE1lc3NhZ2UoeyB0eXBlOiAicGxheWJhY2stZW5kZWQiIH0pOwogICAgICAgICAgICAgIHRoaXMuX2hhc1NlbnRFbmRlZCA9IHRydWU7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgLy8gU2VuZCBmaW5hbCBtZXRyaWNzIHNob3dpbmcgY2xlYXJlZCBzdGF0ZQogICAgICAgICAgICBpZiAodGhpcy5fbWV0cmljc0VuYWJsZWQpIHsKICAgICAgICAgICAgICB0cnkgewogICAgICAgICAgICAgICAgdGhpcy5wb3J0LnBvc3RNZXNzYWdlKHsKICAgICAgICAgICAgICAgICAgdHlwZTogIm1ldHJpY3MiLAogICAgICAgICAgICAgICAgICBkYXRhOiB7CiAgICAgICAgICAgICAgICAgICAgc3RhdGU6IFBsYXliYWNrV29ya2xldC5GU00uSURMRSwKICAgICAgICAgICAgICAgICAgICBxdWV1ZWRTYW1wbGVzOiAwLAogICAgICAgICAgICAgICAgICAgIHF1ZXVlZE1zOiAwLAogICAgICAgICAgICAgICAgICAgIG1heFF1ZXVlZE1zOiBNYXRoLnJvdW5kKCh0aGlzLl9tYXhRdWV1ZVNhbXBsZXMgLyB0aGlzLl9zYW1wbGVSYXRlKSAqIDEwMDApLAogICAgICAgICAgICAgICAgICAgIHVuZGVycnVuQmxvY2tzOiB0aGlzLl91bmRlcnJ1bkJsb2NrcywKICAgICAgICAgICAgICAgICAgICBmcmFtZXNQcm9jZXNzZWQ6IHRoaXMuX2ZyYW1lc1Byb2Nlc3NlZAogICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICB9KTsKICAgICAgICAgICAgICB9IGNhdGNoIChfKSB7IH0KICAgICAgICAgICAgfQogICAgICAgICAgICB0aGlzLnJlc2V0KCk7IC8vIFJlc2V0IHRvIElETEUgc3RhdGUgZm9yIHJldXNlCiAgICAgICAgICAgIGJyZWFrOyAvLyBFeGl0IHdoaWxlIGxvb3AKICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgIC8vIEJVRkZFUiBVTkRFUlJVTiAoTEFHKTogUGxheSBzaWxlbmNlIGFuZCB3YWl0IGZvciBtb3JlIGRhdGEuCiAgICAgICAgICAgIHRoaXMuX3NpbGVuY2VGcmFtZXNDb3VudCsrOwogICAgICAgICAgICBpZiAodGhpcy5fbWV0cmljc0VuYWJsZWQpIHRoaXMuX3VuZGVycnVuQmxvY2tzKys7CiAgICAgICAgICAgIGJyZWFrOyAvLyBFeGl0IHdoaWxlIGxvb3AKICAgICAgICAgIH0KICAgICAgICB9CiAgICAgIH0KCiAgICAgIC8vIElmIHdlIGhhdmUgYSBjaHVuayAoY291bGQgYmUgYSBuZXcgb25lIGZyb20gdGhlIGxvZ2ljIGFib3ZlKSwgcHJvY2VzcyBpdC4KICAgICAgaWYgKHRoaXMuX2N1cnJlbnRDaHVuaykgewogICAgICAgIGNvbnN0IHNhbXBsZXNUb0NvcHkgPSBNYXRoLm1pbigKICAgICAgICAgIGJsb2NrU2l6ZSAtIHNhbXBsZXNDb3BpZWQsCiAgICAgICAgICB0aGlzLl9jdXJyZW50Q2h1bmsubGVuZ3RoIC0gdGhpcy5fY3VycmVudENodW5rT2Zmc2V0CiAgICAgICAgKTsKICAgICAgICAvLyBEaXJlY3RseSB3cml0ZSB0byBvdXRwdXRDaGFubmVsIHRvIGF2b2lkIGV4dHJhIGNvcHkKICAgICAgICBjb25zdCBzcmMgPSB0aGlzLl9jdXJyZW50Q2h1bms7CiAgICAgICAgY29uc3QgYmFzZVNyYyA9IHRoaXMuX2N1cnJlbnRDaHVua09mZnNldDsKICAgICAgICBjb25zdCBiYXNlRHN0ID0gc2FtcGxlc0NvcGllZDsKICAgICAgICBjb25zdCBzY2FsZSA9IHRoaXMuX3NjYWxlOwogICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgc2FtcGxlc1RvQ29weTsgaSsrKSB7CiAgICAgICAgICBvdXRwdXRDaGFubmVsW2Jhc2VEc3QgKyBpXSA9IHNyY1tiYXNlU3JjICsgaV0gKiBzY2FsZTsKICAgICAgICB9CgogICAgICAgIHRoaXMuX2N1cnJlbnRDaHVua09mZnNldCArPSBzYW1wbGVzVG9Db3B5OwogICAgICAgIHNhbXBsZXNDb3BpZWQgKz0gc2FtcGxlc1RvQ29weTsKICAgICAgfQogICAgfQoKICAgIC8vIFplcm8tZmlsbCB0aGUgcmVtYWluZGVyLCBpZiBhbnksIG9uY2UgcGVyIGJsb2NrCiAgICBpZiAoc2FtcGxlc0NvcGllZCA8IGJsb2NrU2l6ZSkgewogICAgICBvdXRwdXRDaGFubmVsLmZpbGwoMCwgc2FtcGxlc0NvcGllZCk7CiAgICB9CgogICAgLy8gVXBkYXRlIG1ldHJpY3MgKG9wdGlvbmFsKQogICAgaWYgKHRoaXMuX21ldHJpY3NFbmFibGVkKSB7CiAgICAgIHRoaXMuX2ZyYW1lc1Byb2Nlc3NlZCArPSBibG9ja1NpemU7CgogICAgICAvLyBUcmFjayBxdWV1ZSBkZXB0aCBpbiBzYW1wbGVzIChhcHByb3hpbWF0ZSkKICAgICAgbGV0IHF1ZXVlZFNhbXBsZXMgPSAwOwogICAgICBpZiAodGhpcy5fY3VycmVudENodW5rKSBxdWV1ZWRTYW1wbGVzICs9IE1hdGgubWF4KDAsIHRoaXMuX2N1cnJlbnRDaHVuay5sZW5ndGggLSB0aGlzLl9jdXJyZW50Q2h1bmtPZmZzZXQpOwogICAgICBmb3IgKGxldCBpID0gMDsgaSA8IHRoaXMuX2J1ZmZlclF1ZXVlLmxlbmd0aDsgaSsrKSBxdWV1ZWRTYW1wbGVzICs9IHRoaXMuX2J1ZmZlclF1ZXVlW2ldLmxlbmd0aDsKICAgICAgaWYgKHF1ZXVlZFNhbXBsZXMgPiB0aGlzLl9tYXhRdWV1ZVNhbXBsZXMpIHRoaXMuX21heFF1ZXVlU2FtcGxlcyA9IHF1ZXVlZFNhbXBsZXM7CgogICAgICAvLyBQZXJpb2RpY2FsbHkgc2VuZCBtZXRyaWNzIHRvIG1haW4gdGhyZWFkCiAgICAgIGlmICh0aGlzLl9mcmFtZXNQcm9jZXNzZWQgLSB0aGlzLl9sYXN0TWV0cmljc1NlbnRBdEZyYW1lID49IHRoaXMuX21ldHJpY3NJbnRlcnZhbEZyYW1lcykgewogICAgICAgIHRoaXMuX2xhc3RNZXRyaWNzU2VudEF0RnJhbWUgPSB0aGlzLl9mcmFtZXNQcm9jZXNzZWQ7CiAgICAgICAgdHJ5IHsKICAgICAgICAgIHRoaXMucG9ydC5wb3N0TWVzc2FnZSh7CiAgICAgICAgICAgIHR5cGU6ICJtZXRyaWNzIiwKICAgICAgICAgICAgZGF0YTogewogICAgICAgICAgICAgIHN0YXRlOiB0aGlzLl9zdGF0ZSwKICAgICAgICAgICAgICBxdWV1ZWRTYW1wbGVzLAogICAgICAgICAgICAgIHF1ZXVlZE1zOiBNYXRoLnJvdW5kKChxdWV1ZWRTYW1wbGVzIC8gdGhpcy5fc2FtcGxlUmF0ZSkgKiAxMDAwKSwKICAgICAgICAgICAgICBtYXhRdWV1ZWRNczogTWF0aC5yb3VuZCgodGhpcy5fbWF4UXVldWVTYW1wbGVzIC8gdGhpcy5fc2FtcGxlUmF0ZSkgKiAxMDAwKSwKICAgICAgICAgICAgICB1bmRlcnJ1bkJsb2NrczogdGhpcy5fdW5kZXJydW5CbG9ja3MsCiAgICAgICAgICAgICAgZnJhbWVzUHJvY2Vzc2VkOiB0aGlzLl9mcmFtZXNQcm9jZXNzZWQKICAgICAgICAgICAgfQogICAgICAgICAgfSk7CiAgICAgICAgfSBjYXRjaCAoXykgeyB9CiAgICAgICAgLy8gRG9uJ3QgcmVzZXQgbWF4IHRyYWNrZXIgLSBrZWVwIHNlc3Npb24gcGVhayB1bnRpbCBpZGxlCiAgICAgIH0KICAgIH0KCiAgICAvLyBBTFdBWVMgcmV0dXJuIHRydWUgdG8ga2VlcCB0aGUgcHJvY2Vzc29yIGFsaXZlIGZvciByZXVzZS4KICAgIHJldHVybiB0cnVlOwogIH0KfQoKcmVnaXN0ZXJQcm9jZXNzb3IoInBsYXliYWNrLXdvcmtsZXQiLCBQbGF5YmFja1dvcmtsZXQpOwo=", import.meta.url), Ce = {
|
|
2627
|
-
en:
|
|
2628
|
-
de:
|
|
2629
|
-
fr:
|
|
2630
|
-
fi:
|
|
2631
|
-
lt:
|
|
2632
|
-
}, W = new f.Quaternion(),
|
|
2625
|
+
LipsyncLt: at
|
|
2626
|
+
}, Symbol.toStringTag, { value: "Module" })), lt = new URL("data:text/javascript;base64,Y2xhc3MgUGxheWJhY2tXb3JrbGV0IGV4dGVuZHMgQXVkaW9Xb3JrbGV0UHJvY2Vzc29yIHsKICBzdGF0aWMgRlNNID0gewogICAgSURMRTogMCwKICAgIFBMQVlJTkc6IDEsCiAgfTsKCiAgY29uc3RydWN0b3Iob3B0aW9ucykgewogICAgc3VwZXIoKTsKICAgIHRoaXMucG9ydC5vbm1lc3NhZ2UgPSB0aGlzLmhhbmRsZU1lc3NhZ2UuYmluZCh0aGlzKTsKCiAgICB0aGlzLl9zYW1wbGVSYXRlID0gb3B0aW9ucz8ucHJvY2Vzc29yT3B0aW9ucz8uc2FtcGxlUmF0ZSB8fCBzYW1wbGVSYXRlOwogICAgdGhpcy5fc2NhbGUgPSAxIC8gMzI3Njg7IC8vIFBDTTE2IC0+IGZsb2F0CgogICAgLy8gU2lsZW5jZSBkZXRlY3Rpb24gdGhyZXNob2xkICgxIHNlY29uZCkgYXMgYSBmYWxsYmFjayBzYWZldHkgbmV0CiAgICBjb25zdCBzaWxlbmNlRHVyYXRpb25TZWNvbmRzID0gMS4wOwogICAgdGhpcy5fc2lsZW5jZVRocmVzaG9sZEJsb2NrcyA9IE1hdGguY2VpbCgodGhpcy5fc2FtcGxlUmF0ZSAqIHNpbGVuY2VEdXJhdGlvblNlY29uZHMpIC8gMTI4KTsKCiAgICAvLyBNZXRyaWNzIGNvbmZpZ3VyYXRpb24gdmlhIG9wdGlvbnMKICAgIGNvbnN0IG1ldHJpY3NDZmcgPSBvcHRpb25zPy5wcm9jZXNzb3JPcHRpb25zPy5tZXRyaWNzIHx8IHt9OwogICAgdGhpcy5fbWV0cmljc0VuYWJsZWQgPSBtZXRyaWNzQ2ZnLmVuYWJsZWQgIT09IGZhbHNlOwogICAgY29uc3QgaW50ZXJ2YWxIeiA9ICh0eXBlb2YgbWV0cmljc0NmZy5pbnRlcnZhbEh6ID09PSAibnVtYmVyIiAmJiBtZXRyaWNzQ2ZnLmludGVydmFsSHogPiAwKQogICAgICA/IG1ldHJpY3NDZmcuaW50ZXJ2YWxIeiA6IDI7CiAgICAvLyBNZXRyaWNzIHN0YXRlIChsb3ctb3ZlcmhlYWQpCiAgICB0aGlzLl9mcmFtZXNQcm9jZXNzZWQgPSAwOwogICAgdGhpcy5fdW5kZXJydW5CbG9ja3MgPSAwOwogICAgdGhpcy5fbWF4UXVldWVTYW1wbGVzID0gMDsKICAgIHRoaXMuX2xhc3RNZXRyaWNzU2VudEF0RnJhbWUgPSAwOwogICAgLy8gQ29udmVydCB0byBmcmFtZXMgYmV0d2VlbiByZXBvcnRzCiAgICB0aGlzLl9tZXRyaWNzSW50ZXJ2YWxGcmFtZXMgPSBNYXRoLm1heCgxMjgsIE1hdGgucm91bmQodGhpcy5fc2FtcGxlUmF0ZSAvIGludGVydmFsSHopKTsKCiAgICB0aGlzLnJlc2V0KCk7CiAgfQoKICAvKioKICAgKiBSZXNldHMgdGhlIHdvcmtsZXQgdG8gaXRzIGluaXRpYWwgSURMRSBzdGF0ZS4KICAgKi8KICByZXNldCgpIHsKICAgIHRoaXMuX2J1ZmZlclF1ZXVlID0gW107CiAgICB0aGlzLl9jdXJyZW50Q2h1bmsgPSBudWxsOwogICAgdGhpcy5fY3VycmVudENodW5rT2Zmc2V0ID0gMDsKICAgIHRoaXMuX3N0YXRlID0gUGxheWJhY2tXb3JrbGV0LkZTTS5JRExFOwoKICAgIHRoaXMuX25vTW9yZURhdGFSZWNlaXZlZCA9IGZhbHNlOwogICAgdGhpcy5fc2lsZW5jZUZyYW1lc0NvdW50ID0gMDsKICAgIHRoaXMuX2hhc1NlbnRFbmRlZCA9IGZhbHNlOwogICAgLy8gUmVzZXQgbWF4IHF1ZXVlIHRyYWNrZXIgb25seSB3aGVuIGdvaW5nIGlkbGUKICAgIHRoaXMuX21heFF1ZXVlU2FtcGxlcyA9IDA7CiAgfQoKICBoYW5kbGVNZXNzYWdlKGV2ZW50KSB7CiAgICBjb25zdCB7IHR5cGUsIGRhdGEgfSA9IGV2ZW50LmRhdGE7CgogICAgLy8gSU5URVJSVVBUOiBUaGUgbWFpbiB0aHJlYWQgd2FudHMgdG8gc3RvcCBpbW1lZGlhdGVseS4KICAgIGlmICh0eXBlID09PSAic3RvcCIpIHsKICAgICAgdGhpcy5yZXNldCgpOwogICAgICAvLyBTZW5kIGZpbmFsIG1ldHJpY3Mgc2hvd2luZyBjbGVhcmVkIHN0YXRlCiAgICAgIGlmICh0aGlzLl9tZXRyaWNzRW5hYmxlZCkgewogICAgICAgIHRyeSB7CiAgICAgICAgICB0aGlzLnBvcnQucG9zdE1lc3NhZ2UoewogICAgICAgICAgICB0eXBlOiAibWV0cmljcyIsCiAgICAgICAgICAgIGRhdGE6IHsKICAgICAgICAgICAgICBzdGF0ZTogUGxheWJhY2tXb3JrbGV0LkZTTS5JRExFLAogICAgICAgICAgICAgIHF1ZXVlZFNhbXBsZXM6IDAsCiAgICAgICAgICAgICAgcXVldWVkTXM6IDAsCiAgICAgICAgICAgICAgbWF4UXVldWVkTXM6IE1hdGgucm91bmQoKHRoaXMuX21heFF1ZXVlU2FtcGxlcyAvIHRoaXMuX3NhbXBsZVJhdGUpICogMTAwMCksCiAgICAgICAgICAgICAgdW5kZXJydW5CbG9ja3M6IHRoaXMuX3VuZGVycnVuQmxvY2tzLAogICAgICAgICAgICAgIGZyYW1lc1Byb2Nlc3NlZDogdGhpcy5fZnJhbWVzUHJvY2Vzc2VkCiAgICAgICAgICAgIH0KICAgICAgICAgIH0pOwogICAgICAgIH0gY2F0Y2ggKF8pIHsgfQogICAgICB9CiAgICAgIHJldHVybjsKICAgIH0KCiAgICAvLyBNYWluIHRocmVhZCBoYXMgc2lnbmFsZWQgdGhhdCBubyBtb3JlIGF1ZGlvIGNodW5rcyB3aWxsIGJlIHNlbnQgZm9yIHRoaXMgdXR0ZXJhbmNlLgogICAgaWYgKHR5cGUgPT09ICJuby1tb3JlLWRhdGEiKSB7CiAgICAgIHRoaXMuX25vTW9yZURhdGFSZWNlaXZlZCA9IHRydWU7CiAgICAgIHJldHVybjsKICAgIH0KCiAgICAvLyBVcGRhdGUgbWV0cmljcyBjb25maWd1cmF0aW9uIGF0IHJ1bnRpbWUKICAgIGlmICh0eXBlID09PSAiY29uZmlnLW1ldHJpY3MiICYmIGRhdGEgJiYgdHlwZW9mIGRhdGEgPT09ICJvYmplY3QiKSB7CiAgICAgIGlmICgiZW5hYmxlZCIgaW4gZGF0YSkgdGhpcy5fbWV0cmljc0VuYWJsZWQgPSAhIWRhdGEuZW5hYmxlZDsKICAgICAgaWYgKHR5cGVvZiBkYXRhLmludGVydmFsSHogPT09ICJudW1iZXIiICYmIGRhdGEuaW50ZXJ2YWxIeiA+IDApIHsKICAgICAgICBjb25zdCBpbnRlcnZhbEh6ID0gZGF0YS5pbnRlcnZhbEh6OwogICAgICAgIHRoaXMuX21ldHJpY3NJbnRlcnZhbEZyYW1lcyA9IE1hdGgubWF4KDEyOCwgTWF0aC5yb3VuZCh0aGlzLl9zYW1wbGVSYXRlIC8gaW50ZXJ2YWxIeikpOwogICAgICB9CiAgICAgIC8vIFJlc2V0IHBhY2luZyBzbyB0aGUgbmV4dCByZXBvcnQgYWxpZ25zIHdpdGggbmV3IGludGVydmFsCiAgICAgIHRoaXMuX2xhc3RNZXRyaWNzU2VudEF0RnJhbWUgPSB0aGlzLl9mcmFtZXNQcm9jZXNzZWQ7CiAgICAgIHJldHVybjsKICAgIH0KCiAgICAvLyBOZXcgYXVkaW8gZGF0YSBoYXMgYXJyaXZlZC4KICAgIGlmICh0eXBlID09PSAiYXVkaW9EYXRhIiAmJiBkYXRhIGluc3RhbmNlb2YgQXJyYXlCdWZmZXIpIHsKICAgICAgdGhpcy5fbm9Nb3JlRGF0YVJlY2VpdmVkID0gZmFsc2U7CiAgICAgIC8vIElmIHdlIHdlcmUgaWRsZSwgdGhpcyBuZXcgZGF0YSBraWNrcyBvZmYgdGhlIHBsYXliYWNrLgogICAgICBpZiAodGhpcy5fc3RhdGUgPT09IFBsYXliYWNrV29ya2xldC5GU00uSURMRSkgewogICAgICAgIHRoaXMuX3N0YXRlID0gUGxheWJhY2tXb3JrbGV0LkZTTS5QTEFZSU5HOwogICAgICAgIHRoaXMucG9ydC5wb3N0TWVzc2FnZSh7IHR5cGU6ICJwbGF5YmFjay1zdGFydGVkIiB9KTsKICAgICAgfQoKICAgICAgLy8gV2Ugb25seSBxdWV1ZSBkYXRhIGlmIHdlIGFyZSBpbiB0aGUgUExBWUlORyBzdGF0ZS4gVGhpcyBwcmV2ZW50cwogICAgICAvLyBkYXRhIGZyb20gYSBwcmV2aW91cywgaW50ZXJydXB0ZWQgc3RyZWFtIGZyb20gbGluZ2VyaW5nLgogICAgICBpZiAodGhpcy5fc3RhdGUgPT09IFBsYXliYWNrV29ya2xldC5GU00uUExBWUlORykgewogICAgICAgIC8vIFN0b3JlIGFzIEludDE2QXJyYXkgdmlldyB0byBhdm9pZCBjb25zdHJ1Y3RpbmcgaXQgaW4gcHJvY2VzcygpCiAgICAgICAgdGhpcy5fYnVmZmVyUXVldWUucHVzaChuZXcgSW50MTZBcnJheShkYXRhKSk7CiAgICAgICAgdGhpcy5fc2lsZW5jZUZyYW1lc0NvdW50ID0gMDsgLy8gUmVzZXQgc2lsZW5jZSBjb3VudGVyIG9uIG5ldyBkYXRhCiAgICAgIH0KICAgIH0KICB9CgogIHByb2Nlc3MoaW5wdXRzLCBvdXRwdXRzLCBwYXJhbWV0ZXJzKSB7CiAgICBjb25zdCBvdXRwdXRDaGFubmVsID0gb3V0cHV0c1swXT8uWzBdOwogICAgaWYgKCFvdXRwdXRDaGFubmVsKSB7CiAgICAgIHJldHVybiB0cnVlOyAvLyBLZWVwIGFsaXZlIGV2ZW4gaWYgb3V0cHV0IGlzIHRlbXBvcmFyaWx5IGRpc2Nvbm5lY3RlZAogICAgfQoKICAgIC8vIElmIHdlIGFyZSBub3QgcGxheWluZywganVzdCBvdXRwdXQgc2lsZW5jZSBhbmQgd2FpdC4KICAgIGlmICh0aGlzLl9zdGF0ZSAhPT0gUGxheWJhY2tXb3JrbGV0LkZTTS5QTEFZSU5HKSB7CiAgICAgIG91dHB1dENoYW5uZWwuZmlsbCgwKTsKICAgICAgcmV0dXJuIHRydWU7IC8vIEFsd2F5cyByZXR1cm4gdHJ1ZSB0byBrZWVwIHRoZSBwcm9jZXNzb3IgYWxpdmUKICAgIH0KCiAgICAvLyBDb3JlIFBMQVlJTkcgTG9naWMKICAgIGNvbnN0IGJsb2NrU2l6ZSA9IG91dHB1dENoYW5uZWwubGVuZ3RoOwogICAgbGV0IHNhbXBsZXNDb3BpZWQgPSAwOwoKICAgIHdoaWxlIChzYW1wbGVzQ29waWVkIDwgYmxvY2tTaXplKSB7CiAgICAgIGlmICghdGhpcy5fY3VycmVudENodW5rIHx8IHRoaXMuX2N1cnJlbnRDaHVua09mZnNldCA+PSB0aGlzLl9jdXJyZW50Q2h1bmsubGVuZ3RoKSB7CiAgICAgICAgaWYgKHRoaXMuX2J1ZmZlclF1ZXVlLmxlbmd0aCA+IDApIHsKICAgICAgICAgIHRoaXMuX2N1cnJlbnRDaHVuayA9IHRoaXMuX2J1ZmZlclF1ZXVlLnNoaWZ0KCk7CiAgICAgICAgICB0aGlzLl9jdXJyZW50Q2h1bmtPZmZzZXQgPSAwOwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAvLyBCdWZmZXIgaXMgZW1wdHkuIENoZWNrIGZvciBlbmQgY29uZGl0aW9ucy4KICAgICAgICAgIGNvbnN0IGlzVGltZWRPdXQgPSB0aGlzLl9zaWxlbmNlRnJhbWVzQ291bnQgPiB0aGlzLl9zaWxlbmNlVGhyZXNob2xkQmxvY2tzOwoKICAgICAgICAgIGlmICh0aGlzLl9ub01vcmVEYXRhUmVjZWl2ZWQgfHwgaXNUaW1lZE91dCkgewogICAgICAgICAgICAvLyBFTkQgT0YgUExBWUJBQ0s6IEVpdGhlciBleHBsaWNpdGx5IHNpZ25hbGVkIG9yIHRpbWVkIG91dC4KICAgICAgICAgICAgaWYgKCF0aGlzLl9oYXNTZW50RW5kZWQpIHsKICAgICAgICAgICAgICB0aGlzLnBvcnQucG9zdE1lc3NhZ2UoeyB0eXBlOiAicGxheWJhY2stZW5kZWQiIH0pOwogICAgICAgICAgICAgIHRoaXMuX2hhc1NlbnRFbmRlZCA9IHRydWU7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgLy8gU2VuZCBmaW5hbCBtZXRyaWNzIHNob3dpbmcgY2xlYXJlZCBzdGF0ZQogICAgICAgICAgICBpZiAodGhpcy5fbWV0cmljc0VuYWJsZWQpIHsKICAgICAgICAgICAgICB0cnkgewogICAgICAgICAgICAgICAgdGhpcy5wb3J0LnBvc3RNZXNzYWdlKHsKICAgICAgICAgICAgICAgICAgdHlwZTogIm1ldHJpY3MiLAogICAgICAgICAgICAgICAgICBkYXRhOiB7CiAgICAgICAgICAgICAgICAgICAgc3RhdGU6IFBsYXliYWNrV29ya2xldC5GU00uSURMRSwKICAgICAgICAgICAgICAgICAgICBxdWV1ZWRTYW1wbGVzOiAwLAogICAgICAgICAgICAgICAgICAgIHF1ZXVlZE1zOiAwLAogICAgICAgICAgICAgICAgICAgIG1heFF1ZXVlZE1zOiBNYXRoLnJvdW5kKCh0aGlzLl9tYXhRdWV1ZVNhbXBsZXMgLyB0aGlzLl9zYW1wbGVSYXRlKSAqIDEwMDApLAogICAgICAgICAgICAgICAgICAgIHVuZGVycnVuQmxvY2tzOiB0aGlzLl91bmRlcnJ1bkJsb2NrcywKICAgICAgICAgICAgICAgICAgICBmcmFtZXNQcm9jZXNzZWQ6IHRoaXMuX2ZyYW1lc1Byb2Nlc3NlZAogICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICB9KTsKICAgICAgICAgICAgICB9IGNhdGNoIChfKSB7IH0KICAgICAgICAgICAgfQogICAgICAgICAgICB0aGlzLnJlc2V0KCk7IC8vIFJlc2V0IHRvIElETEUgc3RhdGUgZm9yIHJldXNlCiAgICAgICAgICAgIGJyZWFrOyAvLyBFeGl0IHdoaWxlIGxvb3AKICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgIC8vIEJVRkZFUiBVTkRFUlJVTiAoTEFHKTogUGxheSBzaWxlbmNlIGFuZCB3YWl0IGZvciBtb3JlIGRhdGEuCiAgICAgICAgICAgIHRoaXMuX3NpbGVuY2VGcmFtZXNDb3VudCsrOwogICAgICAgICAgICBpZiAodGhpcy5fbWV0cmljc0VuYWJsZWQpIHRoaXMuX3VuZGVycnVuQmxvY2tzKys7CiAgICAgICAgICAgIGJyZWFrOyAvLyBFeGl0IHdoaWxlIGxvb3AKICAgICAgICAgIH0KICAgICAgICB9CiAgICAgIH0KCiAgICAgIC8vIElmIHdlIGhhdmUgYSBjaHVuayAoY291bGQgYmUgYSBuZXcgb25lIGZyb20gdGhlIGxvZ2ljIGFib3ZlKSwgcHJvY2VzcyBpdC4KICAgICAgaWYgKHRoaXMuX2N1cnJlbnRDaHVuaykgewogICAgICAgIGNvbnN0IHNhbXBsZXNUb0NvcHkgPSBNYXRoLm1pbigKICAgICAgICAgIGJsb2NrU2l6ZSAtIHNhbXBsZXNDb3BpZWQsCiAgICAgICAgICB0aGlzLl9jdXJyZW50Q2h1bmsubGVuZ3RoIC0gdGhpcy5fY3VycmVudENodW5rT2Zmc2V0CiAgICAgICAgKTsKICAgICAgICAvLyBEaXJlY3RseSB3cml0ZSB0byBvdXRwdXRDaGFubmVsIHRvIGF2b2lkIGV4dHJhIGNvcHkKICAgICAgICBjb25zdCBzcmMgPSB0aGlzLl9jdXJyZW50Q2h1bms7CiAgICAgICAgY29uc3QgYmFzZVNyYyA9IHRoaXMuX2N1cnJlbnRDaHVua09mZnNldDsKICAgICAgICBjb25zdCBiYXNlRHN0ID0gc2FtcGxlc0NvcGllZDsKICAgICAgICBjb25zdCBzY2FsZSA9IHRoaXMuX3NjYWxlOwogICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgc2FtcGxlc1RvQ29weTsgaSsrKSB7CiAgICAgICAgICBvdXRwdXRDaGFubmVsW2Jhc2VEc3QgKyBpXSA9IHNyY1tiYXNlU3JjICsgaV0gKiBzY2FsZTsKICAgICAgICB9CgogICAgICAgIHRoaXMuX2N1cnJlbnRDaHVua09mZnNldCArPSBzYW1wbGVzVG9Db3B5OwogICAgICAgIHNhbXBsZXNDb3BpZWQgKz0gc2FtcGxlc1RvQ29weTsKICAgICAgfQogICAgfQoKICAgIC8vIFplcm8tZmlsbCB0aGUgcmVtYWluZGVyLCBpZiBhbnksIG9uY2UgcGVyIGJsb2NrCiAgICBpZiAoc2FtcGxlc0NvcGllZCA8IGJsb2NrU2l6ZSkgewogICAgICBvdXRwdXRDaGFubmVsLmZpbGwoMCwgc2FtcGxlc0NvcGllZCk7CiAgICB9CgogICAgLy8gVXBkYXRlIG1ldHJpY3MgKG9wdGlvbmFsKQogICAgaWYgKHRoaXMuX21ldHJpY3NFbmFibGVkKSB7CiAgICAgIHRoaXMuX2ZyYW1lc1Byb2Nlc3NlZCArPSBibG9ja1NpemU7CgogICAgICAvLyBUcmFjayBxdWV1ZSBkZXB0aCBpbiBzYW1wbGVzIChhcHByb3hpbWF0ZSkKICAgICAgbGV0IHF1ZXVlZFNhbXBsZXMgPSAwOwogICAgICBpZiAodGhpcy5fY3VycmVudENodW5rKSBxdWV1ZWRTYW1wbGVzICs9IE1hdGgubWF4KDAsIHRoaXMuX2N1cnJlbnRDaHVuay5sZW5ndGggLSB0aGlzLl9jdXJyZW50Q2h1bmtPZmZzZXQpOwogICAgICBmb3IgKGxldCBpID0gMDsgaSA8IHRoaXMuX2J1ZmZlclF1ZXVlLmxlbmd0aDsgaSsrKSBxdWV1ZWRTYW1wbGVzICs9IHRoaXMuX2J1ZmZlclF1ZXVlW2ldLmxlbmd0aDsKICAgICAgaWYgKHF1ZXVlZFNhbXBsZXMgPiB0aGlzLl9tYXhRdWV1ZVNhbXBsZXMpIHRoaXMuX21heFF1ZXVlU2FtcGxlcyA9IHF1ZXVlZFNhbXBsZXM7CgogICAgICAvLyBQZXJpb2RpY2FsbHkgc2VuZCBtZXRyaWNzIHRvIG1haW4gdGhyZWFkCiAgICAgIGlmICh0aGlzLl9mcmFtZXNQcm9jZXNzZWQgLSB0aGlzLl9sYXN0TWV0cmljc1NlbnRBdEZyYW1lID49IHRoaXMuX21ldHJpY3NJbnRlcnZhbEZyYW1lcykgewogICAgICAgIHRoaXMuX2xhc3RNZXRyaWNzU2VudEF0RnJhbWUgPSB0aGlzLl9mcmFtZXNQcm9jZXNzZWQ7CiAgICAgICAgdHJ5IHsKICAgICAgICAgIHRoaXMucG9ydC5wb3N0TWVzc2FnZSh7CiAgICAgICAgICAgIHR5cGU6ICJtZXRyaWNzIiwKICAgICAgICAgICAgZGF0YTogewogICAgICAgICAgICAgIHN0YXRlOiB0aGlzLl9zdGF0ZSwKICAgICAgICAgICAgICBxdWV1ZWRTYW1wbGVzLAogICAgICAgICAgICAgIHF1ZXVlZE1zOiBNYXRoLnJvdW5kKChxdWV1ZWRTYW1wbGVzIC8gdGhpcy5fc2FtcGxlUmF0ZSkgKiAxMDAwKSwKICAgICAgICAgICAgICBtYXhRdWV1ZWRNczogTWF0aC5yb3VuZCgodGhpcy5fbWF4UXVldWVTYW1wbGVzIC8gdGhpcy5fc2FtcGxlUmF0ZSkgKiAxMDAwKSwKICAgICAgICAgICAgICB1bmRlcnJ1bkJsb2NrczogdGhpcy5fdW5kZXJydW5CbG9ja3MsCiAgICAgICAgICAgICAgZnJhbWVzUHJvY2Vzc2VkOiB0aGlzLl9mcmFtZXNQcm9jZXNzZWQKICAgICAgICAgICAgfQogICAgICAgICAgfSk7CiAgICAgICAgfSBjYXRjaCAoXykgeyB9CiAgICAgICAgLy8gRG9uJ3QgcmVzZXQgbWF4IHRyYWNrZXIgLSBrZWVwIHNlc3Npb24gcGVhayB1bnRpbCBpZGxlCiAgICAgIH0KICAgIH0KCiAgICAvLyBBTFdBWVMgcmV0dXJuIHRydWUgdG8ga2VlcCB0aGUgcHJvY2Vzc29yIGFsaXZlIGZvciByZXVzZS4KICAgIHJldHVybiB0cnVlOwogIH0KfQoKcmVnaXN0ZXJQcm9jZXNzb3IoInBsYXliYWNrLXdvcmtsZXQiLCBQbGF5YmFja1dvcmtsZXQpOwo=", import.meta.url), He = {
|
|
2627
|
+
en: $e,
|
|
2628
|
+
de: tt,
|
|
2629
|
+
fr: it,
|
|
2630
|
+
fi: st,
|
|
2631
|
+
lt: rt
|
|
2632
|
+
}, W = new f.Quaternion(), F = new f.Euler(), le = new f.Vector3(), he = new f.Vector3(), Te = new f.Box3();
|
|
2633
2633
|
new f.Matrix4();
|
|
2634
2634
|
new f.Matrix4();
|
|
2635
2635
|
new f.Vector3();
|
|
2636
2636
|
new f.Vector3(0, 0, 1);
|
|
2637
|
-
const
|
|
2637
|
+
const ht = 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 Fe {
|
|
2641
2641
|
/**
|
|
2642
2642
|
* Avatar.
|
|
2643
2643
|
* @typedef {Object} Avatar
|
|
@@ -2763,7 +2763,7 @@ class Ee {
|
|
|
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 Ye(), 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: {
|
|
@@ -3575,12 +3575,12 @@ class Ee {
|
|
|
3575
3575
|
this.poseDelta.props[l + u + "1.quaternion"] = { x: 0, y: 0, z: 0 }, this.poseDelta.props[l + u + "2.quaternion"] = { x: 0, y: 0, z: 0 }, this.poseDelta.props[l + u + "3.quaternion"] = { x: 0, y: 0, z: 0 };
|
|
3576
3576
|
});
|
|
3577
3577
|
});
|
|
3578
|
-
const
|
|
3578
|
+
const n = /* @__PURE__ */ new Set();
|
|
3579
3579
|
Object.values(this.poseTemplates).forEach((l) => {
|
|
3580
|
-
Object.keys(this.propsToThreeObjects(l.props)).forEach((u) =>
|
|
3580
|
+
Object.keys(this.propsToThreeObjects(l.props)).forEach((u) => n.add(u));
|
|
3581
3581
|
}), Object.keys(this.poseDelta.props).forEach((l) => {
|
|
3582
|
-
|
|
3583
|
-
}), this.posePropNames = [...
|
|
3582
|
+
n.add(l);
|
|
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 = {
|
|
3584
3584
|
name: "eyes",
|
|
3585
3585
|
idle: { alt: [
|
|
3586
3586
|
{
|
|
@@ -4034,9 +4034,9 @@ class Ee {
|
|
|
4034
4034
|
"CH",
|
|
4035
4035
|
"sil"
|
|
4036
4036
|
], this.segmenter = new Intl.Segmenter("en", { granularity: "grapheme" }), this.initAudioGraph(), this.audioPlaylist = [], this.volumeFrequencyData = new Uint8Array(16), this.volumeMax = 0, this.volumeHeadBase = 0, this.volumeHeadTarget = 0, this.volumeHeadCurrent = 0, this.volumeHeadVelocity = 0.15, this.volumeHeadEasing = this.sigmoidFactory(3), this.isListening = !1, this.listeningAnalyzer = null, this.listeningActive = !1, this.listeningVolume = 0, this.listeningSilenceThresholdLevel = this.opt.listeningSilenceThresholdLevel, this.listeningSilenceThresholdMs = this.opt.listeningSilenceThresholdMs, this.listeningSilenceDurationMax = this.opt.listeningSilenceDurationMax, this.listeningActiveThresholdLevel = this.opt.listeningActiveThresholdLevel, this.listeningActiveThresholdMs = this.opt.listeningActiveThresholdMs, this.listeningActiveDurationMax = this.opt.listeningActiveDurationMax, this.listeningTimer = 0, this.listeningTimerTotal = 0, this.dracoEnabled = this.opt.dracoEnabled, this.dracoDecoderPath = this.opt.dracoDecoderPath;
|
|
4037
|
-
const
|
|
4037
|
+
const i = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
|
|
4038
4038
|
this.b64Lookup = typeof Uint8Array > "u" ? [] : new Uint8Array(256);
|
|
4039
|
-
for (let l = 0; l <
|
|
4039
|
+
for (let l = 0; l < i.length; l++) this.b64Lookup[i.charCodeAt(l)] = l;
|
|
4040
4040
|
if (this.stateName = "idle", this.speechQueue = [], this.isSpeaking = !1, this.isListening = !1, this.opt.ttsEndpoint) {
|
|
4041
4041
|
let l = new Audio();
|
|
4042
4042
|
if (l.canPlayType("audio/ogg"))
|
|
@@ -4062,7 +4062,7 @@ class Ee {
|
|
|
4062
4062
|
this.opt.lightSpotDispersion
|
|
4063
4063
|
), this.setLighting(this.opt);
|
|
4064
4064
|
const l = new f.PMREMGenerator(this.renderer);
|
|
4065
|
-
l.compileEquirectangularShader(), this.scene.environment = l.fromScene(new
|
|
4065
|
+
l.compileEquirectangularShader(), this.scene.environment = l.fromScene(new Xe()).texture, this.resizeobserver = new ResizeObserver(this.onResize.bind(this)), this.resizeobserver.observe(this.nodeAvatar), this.controls = new Ve(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;
|
|
4066
4066
|
}
|
|
4067
4067
|
this.ikMesh = new f.SkinnedMesh();
|
|
4068
4068
|
const s = {
|
|
@@ -4080,14 +4080,14 @@ class Ee {
|
|
|
4080
4080
|
Object.entries(s).forEach((l, u) => {
|
|
4081
4081
|
const a = new f.Bone();
|
|
4082
4082
|
a.name = l[0], l[1] ? this.ikMesh.getObjectByName(l[1]).add(a) : this.ikMesh.add(a), o.push(a);
|
|
4083
|
-
}), this.ikMesh.bind(new f.Skeleton(o)), this.dynamicbones = new
|
|
4083
|
+
}), this.ikMesh.bind(new f.Skeleton(o)), this.dynamicbones = new _e(), this.isStreaming = !1, this.streamWorkletNode = null, this.streamAudioStartTime = null, this.streamWaitForAudioChunks = !0, this.streamLipsyncLang = null, this.streamLipsyncType = "visemes", this.streamLipsyncQueue = [];
|
|
4084
4084
|
}
|
|
4085
4085
|
/**
|
|
4086
4086
|
* Helper that re/creates the audio context and the other nodes.
|
|
4087
4087
|
* @param {number} sampleRate
|
|
4088
4088
|
*/
|
|
4089
4089
|
initAudioGraph(t = null) {
|
|
4090
|
-
if (this.audioCtx && this.audioCtx.state !== "closed" && this.audioCtx.close(), t ? this.audioCtx = new AudioContext({ sampleRate: t }) : this.audioCtx = new AudioContext(), this.audioSpeechSource = this.audioCtx.createBufferSource(), this.audioBackgroundSource = this.audioCtx.createBufferSource(), this.audioBackgroundGainNode = this.audioCtx.createGain(), this.audioSpeechGainNode = this.audioCtx.createGain(), this.audioStreamGainNode = this.audioCtx.createGain(), this.audioAnalyzerNode = this.audioCtx.createAnalyser(), this.audioAnalyzerNode.fftSize = 256, this.audioAnalyzerNode.smoothingTimeConstant = 0.1, this.audioAnalyzerNode.minDecibels = -70, this.audioAnalyzerNode.maxDecibels = -10, this.audioAnalyzer = new
|
|
4090
|
+
if (this.audioCtx && this.audioCtx.state !== "closed" && this.audioCtx.close(), t ? this.audioCtx = new AudioContext({ sampleRate: t }) : this.audioCtx = new AudioContext(), this.audioSpeechSource = this.audioCtx.createBufferSource(), this.audioBackgroundSource = this.audioCtx.createBufferSource(), this.audioBackgroundGainNode = this.audioCtx.createGain(), this.audioSpeechGainNode = this.audioCtx.createGain(), this.audioStreamGainNode = this.audioCtx.createGain(), this.audioAnalyzerNode = this.audioCtx.createAnalyser(), this.audioAnalyzerNode.fftSize = 256, this.audioAnalyzerNode.smoothingTimeConstant = 0.1, this.audioAnalyzerNode.minDecibels = -70, this.audioAnalyzerNode.maxDecibels = -10, this.audioAnalyzer = new Ke(this.audioCtx), this.audioReverbNode = this.audioCtx.createConvolver(), this.audioBackgroundGainNode.connect(this.audioReverbNode), this.audioAnalyzerNode.connect(this.audioSpeechGainNode), this.audioSpeechGainNode.connect(this.audioReverbNode), this.audioStreamGainNode.connect(this.audioReverbNode), this.audioReverbNode.connect(this.audioCtx.destination), this.setReverb(this.currentReverb || null), this.setMixerGain(
|
|
4091
4091
|
this.opt.mixerGainSpeech,
|
|
4092
4092
|
this.opt.mixerGainBackground
|
|
4093
4093
|
), this.workletLoaded = !1, this.streamWorkletNode) {
|
|
@@ -4114,8 +4114,8 @@ class Ee {
|
|
|
4114
4114
|
* @return {Object} Deep copy of the object.
|
|
4115
4115
|
*/
|
|
4116
4116
|
deepCopy(t, e = null) {
|
|
4117
|
-
const
|
|
4118
|
-
return e && typeof e == "function" && e(
|
|
4117
|
+
const n = JSON.parse(JSON.stringify(t));
|
|
4118
|
+
return e && typeof e == "function" && e(n), n;
|
|
4119
4119
|
}
|
|
4120
4120
|
/**
|
|
4121
4121
|
* Convert a Base64 MP3 chunk to ArrayBuffer.
|
|
@@ -4125,11 +4125,11 @@ class Ee {
|
|
|
4125
4125
|
b64ToArrayBuffer(t) {
|
|
4126
4126
|
let e = 3 * t.length / 4;
|
|
4127
4127
|
t[t.length - 1] === "=" && (e--, t[t.length - 2] === "=" && e--);
|
|
4128
|
-
const
|
|
4128
|
+
const n = new ArrayBuffer(e), i = new Uint8Array(n);
|
|
4129
4129
|
let s, o = 0, l, u, a, h;
|
|
4130
4130
|
for (s = 0; s < t.length; s += 4)
|
|
4131
|
-
l = this.b64Lookup[t.charCodeAt(s)], u = this.b64Lookup[t.charCodeAt(s + 1)], a = this.b64Lookup[t.charCodeAt(s + 2)], h = this.b64Lookup[t.charCodeAt(s + 3)],
|
|
4132
|
-
return
|
|
4131
|
+
l = this.b64Lookup[t.charCodeAt(s)], u = this.b64Lookup[t.charCodeAt(s + 1)], a = this.b64Lookup[t.charCodeAt(s + 2)], h = this.b64Lookup[t.charCodeAt(s + 3)], i[o++] = l << 2 | u >> 4, i[o++] = (u & 15) << 4 | a >> 2, i[o++] = (a & 3) << 6 | h & 63;
|
|
4132
|
+
return n;
|
|
4133
4133
|
}
|
|
4134
4134
|
/**
|
|
4135
4135
|
* Concatenate an array of ArrayBuffers.
|
|
@@ -4141,10 +4141,10 @@ class Ee {
|
|
|
4141
4141
|
let e = 0;
|
|
4142
4142
|
for (let o = 0; o < t.length; o++)
|
|
4143
4143
|
e += t[o].byteLength;
|
|
4144
|
-
let
|
|
4144
|
+
let n = new ArrayBuffer(e), i = new Uint8Array(n), s = 0;
|
|
4145
4145
|
for (let o = 0; o < t.length; o++)
|
|
4146
|
-
|
|
4147
|
-
return
|
|
4146
|
+
i.set(new Uint8Array(t[o]), s), s += t[o].byteLength;
|
|
4147
|
+
return n;
|
|
4148
4148
|
}
|
|
4149
4149
|
/**
|
|
4150
4150
|
* Convert PCM buffer to AudioBuffer.
|
|
@@ -4153,11 +4153,11 @@ class Ee {
|
|
|
4153
4153
|
* @return {AudioBuffer} AudioBuffer
|
|
4154
4154
|
*/
|
|
4155
4155
|
pcmToAudioBuffer(t) {
|
|
4156
|
-
const e = new Int16Array(t),
|
|
4156
|
+
const e = new Int16Array(t), n = new Float32Array(e.length);
|
|
4157
4157
|
for (let s = 0; s < e.length; s++)
|
|
4158
|
-
|
|
4159
|
-
const
|
|
4160
|
-
return
|
|
4158
|
+
n[s] = e[s] >= 32768 ? -(65536 - e[s]) / 32768 : e[s] / 32767;
|
|
4159
|
+
const i = this.audioCtx.createBuffer(1, n.length, this.opt.pcmSampleRate);
|
|
4160
|
+
return i.copyToChannel(n, 0, 0), i;
|
|
4161
4161
|
}
|
|
4162
4162
|
/**
|
|
4163
4163
|
* Convert internal notation to THREE objects.
|
|
@@ -4167,10 +4167,10 @@ class Ee {
|
|
|
4167
4167
|
*/
|
|
4168
4168
|
propsToThreeObjects(t) {
|
|
4169
4169
|
const e = {};
|
|
4170
|
-
for (let [
|
|
4171
|
-
const s =
|
|
4172
|
-
let o = Array.isArray(
|
|
4173
|
-
s[1] === "position" || s[1] === "scale" ? e[
|
|
4170
|
+
for (let [n, i] of Object.entries(t)) {
|
|
4171
|
+
const s = n.split(".");
|
|
4172
|
+
let o = Array.isArray(i.x) ? this.gaussianRandom(...i.x) : i.x, l = Array.isArray(i.y) ? this.gaussianRandom(...i.y) : i.y, u = Array.isArray(i.z) ? this.gaussianRandom(...i.z) : i.z;
|
|
4173
|
+
s[1] === "position" || s[1] === "scale" ? e[n] = new f.Vector3(o, l, u) : s[1] === "rotation" ? (n = s[0] + ".quaternion", e[n] = new f.Quaternion().setFromEuler(new f.Euler(o, l, u, "XYZ")).normalize()) : s[1] === "quaternion" && (e[n] = new f.Quaternion(o, l, u, i.w).normalize());
|
|
4174
4174
|
}
|
|
4175
4175
|
return e;
|
|
4176
4176
|
}
|
|
@@ -4194,12 +4194,12 @@ class Ee {
|
|
|
4194
4194
|
* @param {Object} sources Object of existing morph target values, e.g. { mouthOpen: 1.0 }
|
|
4195
4195
|
* @param {boolean} [override=false] If true, override existing morph target
|
|
4196
4196
|
*/
|
|
4197
|
-
addMixedMorphTarget(t, e,
|
|
4197
|
+
addMixedMorphTarget(t, e, n, i = !1) {
|
|
4198
4198
|
t.forEach((s) => {
|
|
4199
|
-
if (!
|
|
4199
|
+
if (!i && s.morphTargetDictionary.hasOwnProperty(e)) return;
|
|
4200
4200
|
const o = s.geometry;
|
|
4201
4201
|
let l = null, u = null;
|
|
4202
|
-
for (const [a, h] of Object.entries(
|
|
4202
|
+
for (const [a, h] of Object.entries(n))
|
|
4203
4203
|
if (s.morphTargetDictionary.hasOwnProperty(a)) {
|
|
4204
4204
|
const r = s.morphTargetDictionary[a], c = o.morphAttributes.position[r], d = o.morphAttributes.normal?.[r];
|
|
4205
4205
|
l || (l = new f.Float32BufferAttribute(c.count * 3, 3), d && (u = new f.Float32BufferAttribute(c.count * 3, 3)));
|
|
@@ -4228,17 +4228,17 @@ class Ee {
|
|
|
4228
4228
|
async showAvatar(t, e = null) {
|
|
4229
4229
|
if (!t || !t.hasOwnProperty("url"))
|
|
4230
4230
|
throw new Error("Invalid parameter. The avatar must have at least 'url' specified.");
|
|
4231
|
-
const
|
|
4231
|
+
const n = new Ge();
|
|
4232
4232
|
if (this.dracoEnabled) {
|
|
4233
|
-
const a = new
|
|
4234
|
-
a.setDecoderPath(this.dracoDecoderPath),
|
|
4233
|
+
const a = new Ze();
|
|
4234
|
+
a.setDecoderPath(this.dracoDecoderPath), n.setDRACOLoader(a);
|
|
4235
4235
|
}
|
|
4236
|
-
let
|
|
4236
|
+
let i = await n.loadAsync(t.url, e);
|
|
4237
4237
|
const s = [this.opt.modelRoot];
|
|
4238
4238
|
if (this.posePropNames.forEach((a) => s.push(a.split(".")[0])), s.forEach((a) => {
|
|
4239
|
-
if (!
|
|
4239
|
+
if (!i.scene.getObjectByName(a))
|
|
4240
4240
|
throw new Error("Avatar object " + a + " not found");
|
|
4241
|
-
}), this.stop(), this.avatar = t, this.bodyMovement = t.bodyMovement || "idle", this.movementIntensity = t.movementIntensity || 0.5, this.showFullAvatar = t.showFullAvatar || !1, this.fbxAnimationLoader = null, this.dynamicbones.dispose(), this.mixer = null, this.isAvatarOnly ? this.armature && this.clearThree(this.armature) : this.armature && this.clearThree(this.scene), this.armature =
|
|
4241
|
+
}), this.stop(), this.avatar = t, this.bodyMovement = t.bodyMovement || "idle", this.movementIntensity = t.movementIntensity || 0.5, this.showFullAvatar = t.showFullAvatar || !1, this.fbxAnimationLoader = null, this.dynamicbones.dispose(), this.mixer = null, this.isAvatarOnly ? this.armature && this.clearThree(this.armature) : this.armature && this.clearThree(this.scene), this.armature = i.scene.getObjectByName(this.opt.modelRoot), this.armature.scale.setScalar(1), this.animations = i.animations, this.userData = i.userData, this.morphs = [], this.armature.traverse((a) => {
|
|
4242
4242
|
a.morphTargetInfluences && a.morphTargetInfluences.length && a.morphTargetDictionary && this.morphs.push(a), a.frustumCulled = !1;
|
|
4243
4243
|
}), this.morphs.length === 0)
|
|
4244
4244
|
throw new Error("Blend shapes not found");
|
|
@@ -4283,7 +4283,7 @@ class Ee {
|
|
|
4283
4283
|
this.poseAvatar.props[a] = r[h[1]], this.poseBase.props.hasOwnProperty(a) ? this.poseAvatar.props[a].copy(this.poseBase.props[a]) : this.poseBase.props[a] = this.poseAvatar.props[a].clone(), this.poseDelta.props.hasOwnProperty(a) && !this.poseTarget.props.hasOwnProperty(a) && (this.poseTarget.props[a] = this.poseAvatar.props[a].clone()), this.poseTarget.props[a].t = this.animClock, this.poseTarget.props[a].d = 2e3;
|
|
4284
4284
|
}), this.ikMesh.traverse((a) => {
|
|
4285
4285
|
a.isBone && a.position.copy(this.armature.getObjectByName(a.name).position);
|
|
4286
|
-
}), this.isAvatarOnly ? this.scene && this.scene.add(this.armature) : (this.scene.add(
|
|
4286
|
+
}), 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"))
|
|
4287
4287
|
try {
|
|
4288
4288
|
this.dynamicbones.setup(this.scene, this.armature, t.modelDynamicBones);
|
|
4289
4289
|
} catch (a) {
|
|
@@ -4319,8 +4319,8 @@ class Ee {
|
|
|
4319
4319
|
return;
|
|
4320
4320
|
}
|
|
4321
4321
|
if (this.viewName = t || this.viewName, e = e || {}, this.isAvatarOnly) return;
|
|
4322
|
-
const
|
|
4323
|
-
let a = -
|
|
4322
|
+
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, u = this.camera.fov * (Math.PI / 180);
|
|
4323
|
+
let a = -n * Math.tan(u / 2), h = (1 - i) * Math.tan(u / 2), r = s;
|
|
4324
4324
|
switch (this.viewName) {
|
|
4325
4325
|
case "head":
|
|
4326
4326
|
r += 2, h = h * r + 4 * this.avatarHeight / 5;
|
|
@@ -4360,11 +4360,11 @@ class Ee {
|
|
|
4360
4360
|
* @param {number} t High precision timestamp in ms.
|
|
4361
4361
|
*/
|
|
4362
4362
|
updatePoseBase(t) {
|
|
4363
|
-
for (const [e,
|
|
4364
|
-
const
|
|
4365
|
-
if (
|
|
4366
|
-
let s = (t -
|
|
4367
|
-
s > 1 || !this.poseBase.props.hasOwnProperty(e) ?
|
|
4363
|
+
for (const [e, n] of Object.entries(this.poseTarget.props)) {
|
|
4364
|
+
const i = this.poseAvatar.props[e];
|
|
4365
|
+
if (i) {
|
|
4366
|
+
let s = (t - n.t) / n.d;
|
|
4367
|
+
s > 1 || !this.poseBase.props.hasOwnProperty(e) ? i.copy(n) : i.isQuaternion ? i.copy(this.poseBase.props[e].slerp(n, this.easing(s))) : i.isVector3 && i.copy(this.poseBase.props[e].lerp(n, this.easing(s)));
|
|
4368
4368
|
}
|
|
4369
4369
|
}
|
|
4370
4370
|
}
|
|
@@ -4374,9 +4374,9 @@ class Ee {
|
|
|
4374
4374
|
updatePoseDelta() {
|
|
4375
4375
|
for (const [t, e] of Object.entries(this.poseDelta.props)) {
|
|
4376
4376
|
if (e.x === 0 && e.y === 0 && e.z === 0) continue;
|
|
4377
|
-
|
|
4378
|
-
const
|
|
4379
|
-
|
|
4377
|
+
F.set(e.x, e.y, e.z);
|
|
4378
|
+
const n = this.poseAvatar.props[t];
|
|
4379
|
+
n.isQuaternion ? (W.setFromEuler(F), n.multiply(W)) : n.isVector3 && n.add(F);
|
|
4380
4380
|
}
|
|
4381
4381
|
}
|
|
4382
4382
|
/**
|
|
@@ -4384,43 +4384,43 @@ class Ee {
|
|
|
4384
4384
|
* @param {number} dt Delta time in ms.
|
|
4385
4385
|
*/
|
|
4386
4386
|
updateMorphTargets(t) {
|
|
4387
|
-
for (let [e,
|
|
4388
|
-
if (!
|
|
4389
|
-
let
|
|
4390
|
-
if (
|
|
4391
|
-
if (
|
|
4392
|
-
|
|
4387
|
+
for (let [e, n] of Object.entries(this.mtAvatar)) {
|
|
4388
|
+
if (!n.needsUpdate) continue;
|
|
4389
|
+
let i = null, s = null;
|
|
4390
|
+
if (n.fixed !== null) {
|
|
4391
|
+
if (i = n.fixed, n.system = null, n.systemd = null, n.newvalue = null, n.ref && n.ref.hasOwnProperty(e) && delete n.ref[e], n.ref = null, n.base = null, n.value === i) {
|
|
4392
|
+
n.needsUpdate = !1;
|
|
4393
4393
|
continue;
|
|
4394
4394
|
}
|
|
4395
|
-
} else
|
|
4396
|
-
if (
|
|
4397
|
-
let o =
|
|
4398
|
-
o >= 0 ? o < 5e-3 ? (s =
|
|
4395
|
+
} else n.realtime !== null ? (n.ref = null, n.base = null, s = n.realtime) : n.system !== null ? (i = n.system, n.newvalue = null, n.ref && n.ref.hasOwnProperty(e) && delete n.ref[e], n.ref = null, n.base = null, n.systemd !== null ? n.systemd === 0 ? (i = null, n.system = null, n.systemd = null) : (n.systemd -= t, n.systemd < 0 && (n.systemd = 0), n.value === i && (i = null)) : n.value === i && (i = null, n.system = null)) : n.newvalue !== null ? (n.ref = null, n.base = null, s = n.newvalue, n.newvalue = null) : n.base !== null ? (i = n.base, n.ref = null, n.value === i && (i = null, n.base = null, n.needsUpdate = !1)) : (n.ref = null, n.baseline !== null && n.value !== n.baseline ? (i = n.baseline, n.base = n.baseline) : n.needsUpdate = !1);
|
|
4396
|
+
if (i !== null) {
|
|
4397
|
+
let o = i - n.value;
|
|
4398
|
+
o >= 0 ? o < 5e-3 ? (s = i, n.v = 0) : (n.v < n.maxv && (n.v += n.acc * t), n.v >= 0 ? s = n.value + o * (1 - Math.exp(-n.v * t)) : s = n.value + n.v * t * (1 - Math.exp(n.v * t))) : o > -5e-3 ? (s = i, n.v = 0) : (n.v > -n.maxv && (n.v -= n.acc * t), n.v >= 0 ? s = n.value + n.v * t * (1 - Math.exp(-n.v * t)) : s = n.value + o * (1 - Math.exp(n.v * t)));
|
|
4399
4399
|
}
|
|
4400
|
-
if (
|
|
4401
|
-
if (s !== null && s !==
|
|
4400
|
+
if (n.limit !== null) {
|
|
4401
|
+
if (s !== null && s !== n.value && (n.value = s, n.onchange !== null && n.onchange(s)), s = n.limit(n.value), s === n.applied) continue;
|
|
4402
4402
|
} else {
|
|
4403
|
-
if (s === null || s ===
|
|
4404
|
-
|
|
4403
|
+
if (s === null || s === n.value) continue;
|
|
4404
|
+
n.value = s, n.onchange !== null && n.onchange(s);
|
|
4405
4405
|
}
|
|
4406
|
-
switch (
|
|
4406
|
+
switch (n.applied = s, n.applied < n.min && (n.applied = n.min), n.applied > n.max && (n.applied = n.max), e) {
|
|
4407
4407
|
case "headRotateX":
|
|
4408
|
-
this.poseDelta.props["Head.quaternion"].x =
|
|
4408
|
+
this.poseDelta.props["Head.quaternion"].x = n.applied + this.mtAvatar.bodyRotateX.applied;
|
|
4409
4409
|
break;
|
|
4410
4410
|
case "headRotateY":
|
|
4411
|
-
this.poseDelta.props["Head.quaternion"].y =
|
|
4411
|
+
this.poseDelta.props["Head.quaternion"].y = n.applied + this.mtAvatar.bodyRotateY.applied;
|
|
4412
4412
|
break;
|
|
4413
4413
|
case "headRotateZ":
|
|
4414
|
-
this.poseDelta.props["Head.quaternion"].z =
|
|
4414
|
+
this.poseDelta.props["Head.quaternion"].z = n.applied + this.mtAvatar.bodyRotateZ.applied;
|
|
4415
4415
|
break;
|
|
4416
4416
|
case "bodyRotateX":
|
|
4417
|
-
this.poseDelta.props["Head.quaternion"].x =
|
|
4417
|
+
this.poseDelta.props["Head.quaternion"].x = n.applied + this.mtAvatar.headRotateX.applied, this.poseDelta.props["Spine1.quaternion"].x = n.applied / 2, this.poseDelta.props["Spine.quaternion"].x = n.applied / 8, this.poseDelta.props["Hips.quaternion"].x = n.applied / 24;
|
|
4418
4418
|
break;
|
|
4419
4419
|
case "bodyRotateY":
|
|
4420
|
-
this.poseDelta.props["Head.quaternion"].y =
|
|
4420
|
+
this.poseDelta.props["Head.quaternion"].y = n.applied + this.mtAvatar.headRotateY.applied, this.poseDelta.props["Spine1.quaternion"].y = n.applied / 2, this.poseDelta.props["Spine.quaternion"].y = n.applied / 2, this.poseDelta.props["Hips.quaternion"].y = n.applied / 4, this.poseDelta.props["LeftUpLeg.quaternion"].y = n.applied / 2, this.poseDelta.props["RightUpLeg.quaternion"].y = n.applied / 2, this.poseDelta.props["LeftLeg.quaternion"].y = n.applied / 4, this.poseDelta.props["RightLeg.quaternion"].y = n.applied / 4;
|
|
4421
4421
|
break;
|
|
4422
4422
|
case "bodyRotateZ":
|
|
4423
|
-
this.poseDelta.props["Head.quaternion"].z =
|
|
4423
|
+
this.poseDelta.props["Head.quaternion"].z = n.applied + this.mtAvatar.headRotateZ.applied, this.poseDelta.props["Spine1.quaternion"].z = n.applied / 12, this.poseDelta.props["Spine.quaternion"].z = n.applied / 12, this.poseDelta.props["Hips.quaternion"].z = n.applied / 24;
|
|
4424
4424
|
break;
|
|
4425
4425
|
case "handFistLeft":
|
|
4426
4426
|
case "handFistRight":
|
|
@@ -4432,16 +4432,16 @@ class Ee {
|
|
|
4432
4432
|
"HandRing",
|
|
4433
4433
|
"HandPinky"
|
|
4434
4434
|
].forEach((h, r) => {
|
|
4435
|
-
r === 0 ? (this.poseDelta.props[o + h + "1.quaternion"].x = 0, this.poseDelta.props[o + h + "2.quaternion"].z = (o === "Left" ? -1 : 1) *
|
|
4435
|
+
r === 0 ? (this.poseDelta.props[o + h + "1.quaternion"].x = 0, this.poseDelta.props[o + h + "2.quaternion"].z = (o === "Left" ? -1 : 1) * n.applied, this.poseDelta.props[o + h + "3.quaternion"].z = (o === "Left" ? -1 : 1) * n.applied) : (this.poseDelta.props[o + h + "1.quaternion"].x = n.applied, this.poseDelta.props[o + h + "2.quaternion"].x = 1.5 * n.applied, this.poseDelta.props[o + h + "3.quaternion"].x = 1.5 * n.applied);
|
|
4436
4436
|
});
|
|
4437
4437
|
break;
|
|
4438
4438
|
case "chestInhale":
|
|
4439
|
-
const l =
|
|
4439
|
+
const l = n.applied / 20, u = { x: l, y: l / 2, z: 3 * l }, a = { x: 1 / (1 + l) - 1, y: 1 / (1 + l / 2) - 1, z: 1 / (1 + 3 * l) - 1 };
|
|
4440
4440
|
this.poseDelta.props["Spine1.scale"] = u, this.poseDelta.props["Neck.scale"] = a, this.poseDelta.props["LeftArm.scale"] = a, this.poseDelta.props["RightArm.scale"] = a;
|
|
4441
4441
|
break;
|
|
4442
4442
|
default:
|
|
4443
|
-
for (let h = 0, r =
|
|
4444
|
-
|
|
4443
|
+
for (let h = 0, r = n.ms.length; h < r; h++)
|
|
4444
|
+
n.ms[h][n.is[h]] = n.applied;
|
|
4445
4445
|
}
|
|
4446
4446
|
}
|
|
4447
4447
|
}
|
|
@@ -4452,14 +4452,14 @@ class Ee {
|
|
|
4452
4452
|
* @return {string} Pose as a string
|
|
4453
4453
|
*/
|
|
4454
4454
|
getPoseString(t, e = 1e3) {
|
|
4455
|
-
let
|
|
4456
|
-
return Object.entries(t).forEach((
|
|
4457
|
-
const o =
|
|
4455
|
+
let n = "{";
|
|
4456
|
+
return Object.entries(t).forEach((i, s) => {
|
|
4457
|
+
const o = i[0].split(".");
|
|
4458
4458
|
if (o[1] === "position" || o[1] === "rotation" || o[1] === "quaternion") {
|
|
4459
|
-
const l = o[1] === "quaternion" ? o[0] + ".rotation" :
|
|
4460
|
-
|
|
4459
|
+
const l = o[1] === "quaternion" ? o[0] + ".rotation" : i[0], u = i[1].isQuaternion ? new f.Euler().setFromQuaternion(i[1]) : i[1];
|
|
4460
|
+
n += (s ? ", " : "") + "'" + l + "':{", n += "x:" + Math.round(u.x * e) / e, n += ", y:" + Math.round(u.y * e) / e, n += ", z:" + Math.round(u.z * e) / e, n += "}";
|
|
4461
4461
|
}
|
|
4462
|
-
}),
|
|
4462
|
+
}), n += "}", n;
|
|
4463
4463
|
}
|
|
4464
4464
|
/**
|
|
4465
4465
|
* Return pose template property taking into account mirror pose and gesture.
|
|
@@ -4468,19 +4468,19 @@ class Ee {
|
|
|
4468
4468
|
*/
|
|
4469
4469
|
getPoseTemplateProp(t) {
|
|
4470
4470
|
const e = t.split(".");
|
|
4471
|
-
let
|
|
4472
|
-
if (this.gesture && this.gesture.hasOwnProperty(
|
|
4473
|
-
return this.gesture[
|
|
4471
|
+
let n = e[0] + "." + (e[1] === "rotation" ? "quaternion" : e[1]);
|
|
4472
|
+
if (this.gesture && this.gesture.hasOwnProperty(n))
|
|
4473
|
+
return this.gesture[n].clone();
|
|
4474
4474
|
{
|
|
4475
|
-
let
|
|
4476
|
-
this.poseWeightOnLeft || (
|
|
4475
|
+
let i = e[0] + "." + (e[1] === "quaternion" ? "rotation" : e[1]);
|
|
4476
|
+
this.poseWeightOnLeft || (i.startsWith("Left") ? (i = "Right" + i.substring(4), n = "Right" + n.substring(4)) : i.startsWith("Right") && (i = "Left" + i.substring(5), n = "Left" + n.substring(5)));
|
|
4477
4477
|
let s;
|
|
4478
|
-
if (this.poseTarget.template.props.hasOwnProperty(
|
|
4478
|
+
if (this.poseTarget.template.props.hasOwnProperty(n)) {
|
|
4479
4479
|
const o = {};
|
|
4480
|
-
o[
|
|
4481
|
-
} else if (this.poseTarget.template.props.hasOwnProperty(
|
|
4480
|
+
o[n] = this.poseTarget.template.props[n], s = this.propsToThreeObjects(o)[n];
|
|
4481
|
+
} else if (this.poseTarget.template.props.hasOwnProperty(i)) {
|
|
4482
4482
|
const o = {};
|
|
4483
|
-
o[
|
|
4483
|
+
o[i] = this.poseTarget.template.props[i], s = this.propsToThreeObjects(o)[n];
|
|
4484
4484
|
}
|
|
4485
4485
|
return s && !this.poseWeightOnLeft && s.isQuaternion && (s.x *= -1, s.w *= -1), s;
|
|
4486
4486
|
}
|
|
@@ -4492,8 +4492,8 @@ class Ee {
|
|
|
4492
4492
|
*/
|
|
4493
4493
|
mirrorPose(t) {
|
|
4494
4494
|
const e = {};
|
|
4495
|
-
for (let [
|
|
4496
|
-
|
|
4495
|
+
for (let [n, i] of Object.entries(t))
|
|
4496
|
+
i.isQuaternion && (n.startsWith("Left") ? n = "Right" + n.substring(4) : n.startsWith("Right") && (n = "Left" + n.substring(5)), i.x *= -1, i.w *= -1), e[n] = i.clone(), e[n].t = i.t, e[n].d = i.d;
|
|
4497
4497
|
return e;
|
|
4498
4498
|
}
|
|
4499
4499
|
/**
|
|
@@ -4503,18 +4503,18 @@ class Ee {
|
|
|
4503
4503
|
* @return {Object} A new pose object.
|
|
4504
4504
|
*/
|
|
4505
4505
|
poseFactory(t, e = 2e3) {
|
|
4506
|
-
const
|
|
4506
|
+
const n = {
|
|
4507
4507
|
template: t,
|
|
4508
4508
|
props: this.propsToThreeObjects(t.props)
|
|
4509
4509
|
};
|
|
4510
|
-
for (const [
|
|
4511
|
-
if (this.opt.modelMovementFactor < 1 && t.standing && (
|
|
4512
|
-
const o = this.poseStraight[
|
|
4510
|
+
for (const [i, s] of Object.entries(n.props)) {
|
|
4511
|
+
if (this.opt.modelMovementFactor < 1 && t.standing && (i === "Hips.quaternion" || i === "Spine.quaternion" || i === "Spine1.quaternion" || i === "Spine2.quaternion" || i === "Neck.quaternion" || i === "LeftUpLeg.quaternion" || i === "LeftLeg.quaternion" || i === "RightUpLeg.quaternion" || i === "RightLeg.quaternion")) {
|
|
4512
|
+
const o = this.poseStraight[i], l = s.angleTo(o);
|
|
4513
4513
|
s.rotateTowards(o, (1 - this.opt.modelMovementFactor) * l);
|
|
4514
4514
|
}
|
|
4515
4515
|
s.t = this.animClock, s.d = e;
|
|
4516
4516
|
}
|
|
4517
|
-
return
|
|
4517
|
+
return n;
|
|
4518
4518
|
}
|
|
4519
4519
|
/**
|
|
4520
4520
|
* Set a new pose and start transition timer.
|
|
@@ -4522,11 +4522,11 @@ class Ee {
|
|
|
4522
4522
|
* @param {number} [ms=2000] Transition time in milliseconds
|
|
4523
4523
|
*/
|
|
4524
4524
|
setPoseFromTemplate(t, e = 2e3) {
|
|
4525
|
-
const
|
|
4526
|
-
let o =
|
|
4527
|
-
if (
|
|
4525
|
+
const n = t && this.poseTarget && this.poseTarget.template && (this.poseTarget.template.standing && t.lying || this.poseTarget.template.lying && t.standing), i = t && t === this.poseCurrentTemplate, s = this.poseWeightOnLeft;
|
|
4526
|
+
let o = n ? 1e3 : e;
|
|
4527
|
+
if (n ? (this.poseCurrentTemplate = this.poseTemplates.oneknee, setTimeout(() => {
|
|
4528
4528
|
this.setPoseFromTemplate(t, e);
|
|
4529
|
-
}, o)) : this.poseCurrentTemplate = t || this.poseCurrentTemplate, this.poseTarget = this.poseFactory(this.poseCurrentTemplate, o), this.poseWeightOnLeft = !0, (!
|
|
4529
|
+
}, 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)
|
|
4530
4530
|
for (let [l, u] of Object.entries(this.gesture))
|
|
4531
4531
|
this.poseTarget.props.hasOwnProperty(l) && (this.poseTarget.props[l].copy(u), this.poseTarget.props[l].t = u.t, this.poseTarget.props[l].d = u.d);
|
|
4532
4532
|
Object.keys(this.poseDelta.props).forEach((l) => {
|
|
@@ -4547,8 +4547,8 @@ class Ee {
|
|
|
4547
4547
|
* @param {number} val Value
|
|
4548
4548
|
* @param {number} [ms=null] Transition time in milliseconds.
|
|
4549
4549
|
*/
|
|
4550
|
-
setValue(t, e,
|
|
4551
|
-
this.mtAvatar.hasOwnProperty(t) && Object.assign(this.mtAvatar[t], { system: e, systemd:
|
|
4550
|
+
setValue(t, e, n = null) {
|
|
4551
|
+
this.mtAvatar.hasOwnProperty(t) && Object.assign(this.mtAvatar[t], { system: e, systemd: n, needsUpdate: !0 });
|
|
4552
4552
|
}
|
|
4553
4553
|
/**
|
|
4554
4554
|
* Get mood names.
|
|
@@ -4572,12 +4572,12 @@ class Ee {
|
|
|
4572
4572
|
if (t = (t || "").trim().toLowerCase(), !this.animMoods.hasOwnProperty(t)) throw new Error("Unknown mood.");
|
|
4573
4573
|
this.moodName = t, this.mood = this.animMoods[this.moodName];
|
|
4574
4574
|
for (let e of Object.keys(this.mtAvatar)) {
|
|
4575
|
-
let
|
|
4576
|
-
this.mood.baseline.hasOwnProperty(e) ?
|
|
4575
|
+
let n = this.mtBaselineExceptions.hasOwnProperty(e) ? this.mtBaselineExceptions[e] : this.mtBaselineDefault;
|
|
4576
|
+
this.mood.baseline.hasOwnProperty(e) ? n = this.mood.baseline[e] : this.avatar.baseline?.hasOwnProperty(e) && (n = this.avatar.baseline[e]), this.setBaselineValue(e, n);
|
|
4577
4577
|
}
|
|
4578
4578
|
this.mood.anims.forEach((e) => {
|
|
4579
|
-
let
|
|
4580
|
-
|
|
4579
|
+
let n = this.animQueue.findIndex((i) => i.template.name === e.name);
|
|
4580
|
+
n !== -1 && this.animQueue.splice(n, 1), this.animQueue.push(this.animFactory(e, -1));
|
|
4581
4581
|
});
|
|
4582
4582
|
}
|
|
4583
4583
|
/**
|
|
@@ -4608,7 +4608,7 @@ class Ee {
|
|
|
4608
4608
|
}
|
|
4609
4609
|
console.log("Avatar is running:", this.isRunning), console.log("Animation queue exists:", !!this.animQueue);
|
|
4610
4610
|
const t = this.animQueue.length;
|
|
4611
|
-
this.animQueue = this.animQueue.filter((
|
|
4611
|
+
this.animQueue = this.animQueue.filter((i) => !i.template.name.startsWith("bodyMovement"));
|
|
4612
4612
|
const e = this.animQueue.length;
|
|
4613
4613
|
if (console.log(`Filtered animation queue: ${t} -> ${e} animations`), this.bodyMovement === "idle") {
|
|
4614
4614
|
this.fbxAnimationLoader && this.fbxAnimationLoader.stopCurrentAnimation();
|
|
@@ -4618,16 +4618,16 @@ class Ee {
|
|
|
4618
4618
|
try {
|
|
4619
4619
|
await this.fbxAnimationLoader.playGestureAnimation(this.bodyMovement, this.movementIntensity), console.log("Applied FBX body movement animation:", this.bodyMovement);
|
|
4620
4620
|
return;
|
|
4621
|
-
} catch (
|
|
4622
|
-
console.warn("FBX animation failed, falling back to code animation:",
|
|
4621
|
+
} catch (i) {
|
|
4622
|
+
console.warn("FBX animation failed, falling back to code animation:", i);
|
|
4623
4623
|
}
|
|
4624
|
-
const
|
|
4625
|
-
if (console.log("Created movement animation:",
|
|
4624
|
+
const n = this.createBodyMovementAnimation(this.bodyMovement);
|
|
4625
|
+
if (console.log("Created movement animation:", n), n)
|
|
4626
4626
|
try {
|
|
4627
|
-
const
|
|
4628
|
-
|
|
4629
|
-
} catch (
|
|
4630
|
-
console.error("Error creating body movement animation:",
|
|
4627
|
+
const i = this.animFactory(n, !0);
|
|
4628
|
+
i && i.ts && i.ts.length > 0 ? (this.animQueue.push(i), console.log("Applied code-based body movement animation:", this.bodyMovement), console.log("Animation queue length:", this.animQueue.length), console.log("Animation object:", i)) : (console.error("Invalid animation object created for:", this.bodyMovement), console.error("Animation object:", i));
|
|
4629
|
+
} catch (i) {
|
|
4630
|
+
console.error("Error creating body movement animation:", i);
|
|
4631
4631
|
}
|
|
4632
4632
|
}
|
|
4633
4633
|
/**
|
|
@@ -4668,14 +4668,14 @@ class Ee {
|
|
|
4668
4668
|
*/
|
|
4669
4669
|
maintainLockedPosition() {
|
|
4670
4670
|
if (this.lockedPosition && this.armature) {
|
|
4671
|
-
const t = this.armature.position.y, e = this.lockedPosition.y - 2,
|
|
4671
|
+
const t = this.armature.position.y, e = this.lockedPosition.y - 2, n = this.lockedPosition.y + 0.1;
|
|
4672
4672
|
t < e ? this.armature.position.set(
|
|
4673
4673
|
this.lockedPosition.x,
|
|
4674
4674
|
e,
|
|
4675
4675
|
this.lockedPosition.z
|
|
4676
|
-
) : t >
|
|
4676
|
+
) : t > n && this.armature.position.set(
|
|
4677
4677
|
this.lockedPosition.x,
|
|
4678
|
-
|
|
4678
|
+
n,
|
|
4679
4679
|
this.lockedPosition.z
|
|
4680
4680
|
), this.armature.position.x = this.lockedPosition.x, this.armature.position.z = this.lockedPosition.z;
|
|
4681
4681
|
}
|
|
@@ -4686,7 +4686,7 @@ class Ee {
|
|
|
4686
4686
|
* @returns {Object} Animation object.
|
|
4687
4687
|
*/
|
|
4688
4688
|
createBodyMovementAnimation(t) {
|
|
4689
|
-
const e = this.movementIntensity || 0.5,
|
|
4689
|
+
const e = this.movementIntensity || 0.5, n = {
|
|
4690
4690
|
walking: {
|
|
4691
4691
|
name: "bodyMovement_walking",
|
|
4692
4692
|
delay: [500, 2e3],
|
|
@@ -4843,10 +4843,10 @@ class Ee {
|
|
|
4843
4843
|
}
|
|
4844
4844
|
};
|
|
4845
4845
|
if (t === "dancing") {
|
|
4846
|
-
const
|
|
4847
|
-
return
|
|
4846
|
+
const i = ["dancing", "dancing2", "dancing3"], s = i[Math.floor(Math.random() * i.length)];
|
|
4847
|
+
return n[s] || n.dancing;
|
|
4848
4848
|
}
|
|
4849
|
-
return
|
|
4849
|
+
return n[t] || null;
|
|
4850
4850
|
}
|
|
4851
4851
|
/**
|
|
4852
4852
|
* Play a random dance animation
|
|
@@ -4902,13 +4902,13 @@ class Ee {
|
|
|
4902
4902
|
if (t === "eyesRotateY") {
|
|
4903
4903
|
const e = this.getBaselineValue("eyeLookOutLeft");
|
|
4904
4904
|
if (e === void 0) return;
|
|
4905
|
-
const
|
|
4906
|
-
return
|
|
4905
|
+
const n = this.getBaselineValue("eyeLookInLeft");
|
|
4906
|
+
return n === void 0 || this.getBaselineValue("eyeLookOutRight") === void 0 || this.getBaselineValue("eyeLookInRight") === void 0 ? void 0 : e - n;
|
|
4907
4907
|
} else if (t === "eyesRotateX") {
|
|
4908
4908
|
const e = this.getBaselineValue("eyesLookDown");
|
|
4909
4909
|
if (e === void 0) return;
|
|
4910
|
-
const
|
|
4911
|
-
return
|
|
4910
|
+
const n = this.getBaselineValue("eyesLookUp");
|
|
4911
|
+
return n === void 0 ? void 0 : e - n;
|
|
4912
4912
|
} else
|
|
4913
4913
|
return this.mtAvatar[t]?.baseline;
|
|
4914
4914
|
}
|
|
@@ -4929,13 +4929,13 @@ class Ee {
|
|
|
4929
4929
|
if (t === "eyesRotateY") {
|
|
4930
4930
|
const e = this.getFixedValue("eyeLookOutLeft");
|
|
4931
4931
|
if (e === null) return null;
|
|
4932
|
-
const
|
|
4933
|
-
return
|
|
4932
|
+
const n = this.getFixedValue("eyeLookInLeft");
|
|
4933
|
+
return n === null || this.getFixedValue("eyeLookOutRight") === null || this.getFixedValue("eyeLookInRight") === null ? null : e - n;
|
|
4934
4934
|
} else if (t === "eyesRotateX") {
|
|
4935
4935
|
const e = this.getFixedValue("eyesLookDown");
|
|
4936
4936
|
if (e === null) return null;
|
|
4937
|
-
const
|
|
4938
|
-
return
|
|
4937
|
+
const n = this.getFixedValue("eyesLookUp");
|
|
4938
|
+
return n === null ? null : e - n;
|
|
4939
4939
|
} else
|
|
4940
4940
|
return this.mtAvatar[t]?.fixed;
|
|
4941
4941
|
}
|
|
@@ -4944,8 +4944,8 @@ class Ee {
|
|
|
4944
4944
|
* @param {string} mt Morph target name
|
|
4945
4945
|
* @param {number} val Value, null if to be removed
|
|
4946
4946
|
*/
|
|
4947
|
-
setFixedValue(t, e,
|
|
4948
|
-
t === "eyesRotateY" ? (this.setFixedValue("eyeLookOutLeft", e === null ? null : e > 0 ? e : 0,
|
|
4947
|
+
setFixedValue(t, e, n = null) {
|
|
4948
|
+
t === "eyesRotateY" ? (this.setFixedValue("eyeLookOutLeft", e === null ? null : e > 0 ? e : 0, n), this.setFixedValue("eyeLookInLeft", e === null ? null : e > 0 ? 0 : -e, n), this.setFixedValue("eyeLookOutRight", e === null ? null : e > 0 ? 0 : -e, n), this.setFixedValue("eyeLookInRight", e === null ? null : e > 0 ? e : 0, n)) : t === "eyesRotateX" ? (this.setFixedValue("eyesLookDown", e === null ? null : e > 0 ? e : 0, n), this.setFixedValue("eyesLookUp", e === null ? null : e > 0 ? 0 : -e, n)) : this.mtAvatar.hasOwnProperty(t) && Object.assign(this.mtAvatar[t], { fixed: e, needsUpdate: !0 });
|
|
4949
4949
|
}
|
|
4950
4950
|
/**
|
|
4951
4951
|
* Create a new animation based on an animation template.
|
|
@@ -4956,7 +4956,7 @@ class Ee {
|
|
|
4956
4956
|
* @param {boolean} [noClockOffset=false] Do not apply clock offset
|
|
4957
4957
|
* @return {Object} New animation object.
|
|
4958
4958
|
*/
|
|
4959
|
-
animFactory(t, e = !1,
|
|
4959
|
+
animFactory(t, e = !1, n = 1, i = 1, s = !1) {
|
|
4960
4960
|
const o = { template: t, ts: [0], vs: {} };
|
|
4961
4961
|
let l = t;
|
|
4962
4962
|
for (; ; )
|
|
@@ -4996,9 +4996,9 @@ class Ee {
|
|
|
4996
4996
|
let a = Object.values(l.vs).reduce((h, r) => r.length > h ? r.length : h, 0);
|
|
4997
4997
|
o.ts = Array(a + 1).fill(0);
|
|
4998
4998
|
}
|
|
4999
|
-
s ? o.ts = o.ts.map((a) => u + a *
|
|
4999
|
+
s ? o.ts = o.ts.map((a) => u + a * n) : o.ts = o.ts.map((a) => this.animClock + u + a * n);
|
|
5000
5000
|
for (let [a, h] of Object.entries(l.vs)) {
|
|
5001
|
-
const r = this.getBaselineValue(a), c = h.map((d) => (d = this.valueFn(d), d === null ? null : typeof d == "function" ? d : typeof d == "string" || d instanceof String ? d.slice() : Array.isArray(d) ? a === "gesture" ? d.slice() : (r === void 0 ? 0 : r) +
|
|
5001
|
+
const r = this.getBaselineValue(a), c = h.map((d) => (d = this.valueFn(d), d === null ? null : typeof d == "function" ? d : typeof d == "string" || d instanceof String ? d.slice() : Array.isArray(d) ? a === "gesture" ? d.slice() : (r === void 0 ? 0 : r) + i * this.gaussianRandom(...d) : typeof d == "boolean" ? d : d instanceof Object && d.constructor === Object ? Object.assign({}, d) : (r === void 0 ? 0 : r) + i * d));
|
|
5002
5002
|
a === "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)]) : a === "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[a] = [null, ...c];
|
|
5003
5003
|
}
|
|
5004
5004
|
for (let a of Object.keys(o.vs))
|
|
@@ -5015,10 +5015,10 @@ class Ee {
|
|
|
5015
5015
|
* @param {function} [fun=null] Ease in/out function, null = linear
|
|
5016
5016
|
* @return {number} Value based on the given time.
|
|
5017
5017
|
*/
|
|
5018
|
-
valueAnimationSeq(t, e,
|
|
5019
|
-
t = this.valueFn(t), e = this.valueFn(e), s <
|
|
5020
|
-
let l = (e - t) / (
|
|
5021
|
-
return o && (l *= o((s -
|
|
5018
|
+
valueAnimationSeq(t, e, n, i, s, o = null) {
|
|
5019
|
+
t = this.valueFn(t), e = this.valueFn(e), s < n && (s = n), s > i && (s = i);
|
|
5020
|
+
let l = (e - t) / (i - n);
|
|
5021
|
+
return o && (l *= o((s - n) / (i - n))), l * s + (t - l * n);
|
|
5022
5022
|
}
|
|
5023
5023
|
/**
|
|
5024
5024
|
* Return gaussian distributed random value between start and end with skew.
|
|
@@ -5028,10 +5028,10 @@ class Ee {
|
|
|
5028
5028
|
* @param {number} [samples=5] Number of samples, 1 = uniform distribution.
|
|
5029
5029
|
* @return {number} Gaussian random value.
|
|
5030
5030
|
*/
|
|
5031
|
-
gaussianRandom(t, e,
|
|
5031
|
+
gaussianRandom(t, e, n = 1, i = 5) {
|
|
5032
5032
|
let s = 0;
|
|
5033
|
-
for (let o = 0; o <
|
|
5034
|
-
return t + Math.pow(s /
|
|
5033
|
+
for (let o = 0; o < i; o++) s += Math.random();
|
|
5034
|
+
return t + Math.pow(s / i, n) * (e - t);
|
|
5035
5035
|
}
|
|
5036
5036
|
/**
|
|
5037
5037
|
* Create a sigmoid function.
|
|
@@ -5039,12 +5039,12 @@ class Ee {
|
|
|
5039
5039
|
* @return {function} Sigmoid function.
|
|
5040
5040
|
*/
|
|
5041
5041
|
sigmoidFactory(t) {
|
|
5042
|
-
function e(
|
|
5043
|
-
return 1 / (1 + Math.exp(-t *
|
|
5042
|
+
function e(i) {
|
|
5043
|
+
return 1 / (1 + Math.exp(-t * i)) - 0.5;
|
|
5044
5044
|
}
|
|
5045
|
-
var
|
|
5046
|
-
return function(
|
|
5047
|
-
return
|
|
5045
|
+
var n = 0.5 / e(1);
|
|
5046
|
+
return function(i) {
|
|
5047
|
+
return n * e(2 * Math.max(Math.min(i, 1), 0) - 1) + 0.5;
|
|
5048
5048
|
};
|
|
5049
5049
|
}
|
|
5050
5050
|
/**
|
|
@@ -5054,8 +5054,8 @@ class Ee {
|
|
|
5054
5054
|
* @param {number[]} r2 Target range
|
|
5055
5055
|
* @return {number} Scaled value
|
|
5056
5056
|
*/
|
|
5057
|
-
convertRange(t, e,
|
|
5058
|
-
return (t - e[0]) * (
|
|
5057
|
+
convertRange(t, e, n) {
|
|
5058
|
+
return (t - e[0]) * (n[1] - n[0]) / (e[1] - e[0]) + n[0];
|
|
5059
5059
|
}
|
|
5060
5060
|
/**
|
|
5061
5061
|
* Animate the avatar.
|
|
@@ -5071,32 +5071,32 @@ class Ee {
|
|
|
5071
5071
|
this.animTimeLast = t;
|
|
5072
5072
|
}
|
|
5073
5073
|
e = e / this.animSlowdownRate, this.animClock += e, this.maintainLockedPosition();
|
|
5074
|
-
let
|
|
5074
|
+
let n, i, s, o, l = 0;
|
|
5075
5075
|
if (this.stats && this.stats.begin(), this.isListening) {
|
|
5076
|
-
for (this.listeningAnalyzer.getByteFrequencyData(this.volumeFrequencyData),
|
|
5077
|
-
this.volumeFrequencyData[
|
|
5076
|
+
for (this.listeningAnalyzer.getByteFrequencyData(this.volumeFrequencyData), n = 2, s = 10; n < s; n++)
|
|
5077
|
+
this.volumeFrequencyData[n] > l && (l = this.volumeFrequencyData[n]);
|
|
5078
5078
|
this.listeningVolume = (this.listeningVolume + l) / 2, this.listeningActive ? (this.listeningTimerTotal += e, this.listeningVolume < this.listeningSilenceThresholdLevel ? (this.listeningTimer += e, this.listeningTimer > this.listeningSilenceThresholdMs && (this.listeningOnchange && this.listeningOnchange("stop", this.listeningTimer), this.listeningActive = !1, this.listeningTimer = 0, this.listeningTimerTotal = 0)) : this.listeningTimer *= 0.5, this.listeningTimerTotal > this.listeningActiveDurationMax && (this.listeningOnchange && this.listeningOnchange("maxactive"), this.listeningTimerTotal = 0)) : (this.listeningTimerTotal += e, this.listeningVolume > this.listeningActiveThresholdLevel ? (this.listeningTimer += e, this.listeningTimer > this.listeningActiveThresholdMs && (this.listeningOnchange && this.listeningOnchange("start"), this.listeningActive = !0, this.listeningTimer = 0, this.listeningTimerTotal = 0)) : this.listeningTimer *= 0.5, this.listeningTimerTotal > this.listeningSilenceDurationMax && (this.listeningOnchange && this.listeningOnchange("maxsilence"), this.listeningTimerTotal = 0));
|
|
5079
5079
|
}
|
|
5080
5080
|
if (this.isSpeaking)
|
|
5081
|
-
for (l = 0, this.audioAnalyzerNode.getByteFrequencyData(this.volumeFrequencyData),
|
|
5082
|
-
this.volumeFrequencyData[
|
|
5081
|
+
for (l = 0, this.audioAnalyzerNode.getByteFrequencyData(this.volumeFrequencyData), n = 2, s = 10; n < s; n++)
|
|
5082
|
+
this.volumeFrequencyData[n] > l && (l = this.volumeFrequencyData[n]);
|
|
5083
5083
|
let u = null, a = null;
|
|
5084
5084
|
const h = [];
|
|
5085
|
-
for (
|
|
5086
|
-
const r = this.animQueue[
|
|
5085
|
+
for (n = 0, s = this.animQueue.length; n < s; n++) {
|
|
5086
|
+
const r = this.animQueue[n];
|
|
5087
5087
|
if (!(!r || !r.ts || !r.ts.length || this.animClock < r.ts[0])) {
|
|
5088
|
-
for (
|
|
5088
|
+
for (i = r.ndx || 0, o = r.ts.length; i < o && !(this.animClock < r.ts[i]); i++)
|
|
5089
5089
|
for (let [c, d] of Object.entries(r.vs))
|
|
5090
5090
|
if (this.mtAvatar.hasOwnProperty(c)) {
|
|
5091
|
-
if (d[
|
|
5091
|
+
if (d[i + 1] === null) continue;
|
|
5092
5092
|
const g = this.mtAvatar[c];
|
|
5093
|
-
if (d[
|
|
5094
|
-
g.newvalue = d[
|
|
5093
|
+
if (d[i] === null && (d[i] = g.value), i === o - 1)
|
|
5094
|
+
g.newvalue = d[i];
|
|
5095
5095
|
else {
|
|
5096
|
-
g.newvalue = d[
|
|
5097
|
-
const y = r.ts[
|
|
5096
|
+
g.newvalue = d[i + 1];
|
|
5097
|
+
const y = r.ts[i + 1] - r.ts[i];
|
|
5098
5098
|
let x = 1;
|
|
5099
|
-
y > 1e-4 && (x = (this.animClock - r.ts[
|
|
5099
|
+
y > 1e-4 && (x = (this.animClock - r.ts[i]) / y), x < 1 && (g.easing && (x = g.easing(x)), g.newvalue = (1 - x) * d[i] + x * g.newvalue), g.ref && g.ref !== r.vs && g.ref.hasOwnProperty(c) && delete g.ref[c], g.ref = r.vs;
|
|
5100
5100
|
}
|
|
5101
5101
|
if (l)
|
|
5102
5102
|
switch (c) {
|
|
@@ -5108,29 +5108,29 @@ class Ee {
|
|
|
5108
5108
|
g.newvalue *= 1 + l / 255 - 0.5;
|
|
5109
5109
|
}
|
|
5110
5110
|
g.needsUpdate = !0;
|
|
5111
|
-
} else c === "eyeContact" && d[
|
|
5112
|
-
|
|
5111
|
+
} else c === "eyeContact" && d[i] !== null && u !== !1 ? u = !!d[i] : c === "headMove" && d[i] !== null && a !== !1 ? d[i] === 0 ? a = !1 : (Math.random() < d[i] && (a = !0), d[i] = null) : d[i] !== null && (h.push({ mt: c, val: d[i] }), d[i] = null);
|
|
5112
|
+
i === o ? (r.hasOwnProperty("mood") && this.setMood(r.mood), r.loop ? (o = this.isSpeaking && (r.template.name === "head" || r.template.name === "eyes") ? 4 : 1, this.animQueue[n] = this.animFactory(r.template, r.loop > 0 ? r.loop - 1 : r.loop, 1, 1 / o)) : (this.animQueue.splice(n--, 1), s--)) : r.ndx = i - 1;
|
|
5113
5113
|
}
|
|
5114
5114
|
}
|
|
5115
5115
|
for (let r = 0, c = h.length; r < c; r++)
|
|
5116
|
-
switch (
|
|
5116
|
+
switch (i = h[r].val, h[r].mt) {
|
|
5117
5117
|
case "speak":
|
|
5118
|
-
this.speakText(
|
|
5118
|
+
this.speakText(i);
|
|
5119
5119
|
break;
|
|
5120
5120
|
case "subtitles":
|
|
5121
|
-
this.onSubtitles && typeof this.onSubtitles == "function" && this.onSubtitles(
|
|
5121
|
+
this.onSubtitles && typeof this.onSubtitles == "function" && this.onSubtitles(i);
|
|
5122
5122
|
break;
|
|
5123
5123
|
case "pose":
|
|
5124
|
-
this.poseName =
|
|
5124
|
+
this.poseName = i, this.setPoseFromTemplate(this.poseTemplates[this.poseName]);
|
|
5125
5125
|
break;
|
|
5126
5126
|
case "gesture":
|
|
5127
|
-
this.playGesture(...
|
|
5127
|
+
this.playGesture(...i);
|
|
5128
5128
|
break;
|
|
5129
5129
|
case "function":
|
|
5130
|
-
|
|
5130
|
+
i && typeof i == "function" && i();
|
|
5131
5131
|
break;
|
|
5132
5132
|
case "moveto":
|
|
5133
|
-
Object.entries(
|
|
5133
|
+
Object.entries(i.props).forEach((d) => {
|
|
5134
5134
|
d[1] ? this.poseTarget.props[d[0]].copy(d[1]) : this.poseTarget.props[d[0]].copy(this.getPoseTemplateProp(d[0])), this.poseTarget.props[d[0]].t = this.animClock, this.poseTarget.props[d[0]].d = d[1] && d[1].d ? d[1].d : d.duration || 2e3;
|
|
5135
5135
|
});
|
|
5136
5136
|
break;
|
|
@@ -5144,7 +5144,7 @@ class Ee {
|
|
|
5144
5144
|
{ link: "LeftForeArm", minx: -0.5, maxx: 1.5, miny: -1.5, maxy: 1.5, minz: -0.5, maxz: 3 },
|
|
5145
5145
|
{ link: "LeftArm", minx: -1.5, maxx: 1.5, miny: 0, maxy: 0, minz: -1, maxz: 3 }
|
|
5146
5146
|
]
|
|
5147
|
-
},
|
|
5147
|
+
}, i.x ? new f.Vector3(i.x, i.y, i.z) : null, !0, i.d);
|
|
5148
5148
|
break;
|
|
5149
5149
|
case "handRight":
|
|
5150
5150
|
this.ikSolve({
|
|
@@ -5156,31 +5156,31 @@ class Ee {
|
|
|
5156
5156
|
{ link: "RightForeArm", minx: -0.5, maxx: 1.5, miny: -1.5, maxy: 1.5, minz: -3, maxz: 0.5, maxAngle: 0.2 },
|
|
5157
5157
|
{ link: "RightArm", minx: -1.5, maxx: 1.5, miny: 0, maxy: 0, minz: -1, maxz: 3 }
|
|
5158
5158
|
]
|
|
5159
|
-
},
|
|
5159
|
+
}, i.x ? new f.Vector3(i.x, i.y, i.z) : null, !0, i.d);
|
|
5160
5160
|
break;
|
|
5161
5161
|
}
|
|
5162
|
-
if ((u || a) && (
|
|
5162
|
+
if ((u || a) && (F.setFromQuaternion(this.poseAvatar.props["Head.quaternion"]), F.x = Math.max(-0.9, Math.min(0.9, 2 * F.x - 0.5)), F.y = Math.max(-0.9, Math.min(0.9, -2.5 * F.y)), u ? (Object.assign(this.mtAvatar.eyesLookDown, { system: F.x < 0 ? -F.x : 0, needsUpdate: !0 }), Object.assign(this.mtAvatar.eyesLookUp, { system: F.x < 0 ? 0 : F.x, needsUpdate: !0 }), Object.assign(this.mtAvatar.eyeLookInLeft, { system: F.y < 0 ? -F.y : 0, needsUpdate: !0 }), Object.assign(this.mtAvatar.eyeLookOutLeft, { system: F.y < 0 ? 0 : F.y, needsUpdate: !0 }), Object.assign(this.mtAvatar.eyeLookInRight, { system: F.y < 0 ? 0 : F.y, needsUpdate: !0 }), Object.assign(this.mtAvatar.eyeLookOutRight, { system: F.y < 0 ? -F.y : 0, needsUpdate: !0 }), a && (n = -this.mtAvatar.bodyRotateY.value, i = this.gaussianRandom(-0.2, 0.2), this.animQueue.push(this.animFactory({
|
|
5163
5163
|
name: "headmove",
|
|
5164
5164
|
dt: [[1e3, 2e3], [1e3, 2e3, 1, 2], [1e3, 2e3], [1e3, 2e3, 1, 2]],
|
|
5165
5165
|
vs: {
|
|
5166
|
-
headRotateY: [
|
|
5167
|
-
headRotateX: [
|
|
5168
|
-
headRotateZ: [-
|
|
5166
|
+
headRotateY: [n, n, 0],
|
|
5167
|
+
headRotateX: [i, i, 0],
|
|
5168
|
+
headRotateZ: [-n / 4, -n / 4, 0]
|
|
5169
5169
|
}
|
|
5170
|
-
})))) : (
|
|
5170
|
+
})))) : (n = this.mtAvatar.eyeLookInLeft.value - this.mtAvatar.eyeLookOutLeft.value, i = this.gaussianRandom(-0.2, 0.2), this.animQueue.push(this.animFactory({
|
|
5171
5171
|
name: "headmove",
|
|
5172
5172
|
dt: [[1e3, 2e3], [1e3, 2e3, 1, 2], [1e3, 2e3], [1e3, 2e3, 1, 2]],
|
|
5173
5173
|
vs: {
|
|
5174
|
-
headRotateY: [null,
|
|
5175
|
-
headRotateX: [null,
|
|
5176
|
-
headRotateZ: [null, -
|
|
5174
|
+
headRotateY: [null, n, n, 0],
|
|
5175
|
+
headRotateX: [null, i, i, 0],
|
|
5176
|
+
headRotateZ: [null, -n / 4, -n / 4, 0],
|
|
5177
5177
|
eyeLookInLeft: [null, 0],
|
|
5178
5178
|
eyeLookOutLeft: [null, 0],
|
|
5179
5179
|
eyeLookInRight: [null, 0],
|
|
5180
5180
|
eyeLookOutRight: [null, 0],
|
|
5181
5181
|
eyeContact: [0]
|
|
5182
5182
|
}
|
|
5183
|
-
})))), e > 2 * this.animFrameDur && (e = 2 * this.animFrameDur), (this.viewName !== "full" || this.isAvatarOnly) && (
|
|
5183
|
+
})))), 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) && u ? 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 && (W.setFromAxisAngle(ht, this.volumeHeadCurrent), this.objectNeck.quaternion.multiply(W)), Te.setFromObject(this.armature), this.objectLeftToeBase.getWorldPosition(le), le.sub(this.armature.position), this.objectRightToeBase.getWorldPosition(he), he.sub(this.armature.position), this.objectHips.position.y -= Te.min.y / 2, this.objectHips.position.x -= (le.x + he.x) / 4, this.objectHips.position.z -= (le.z + he.z) / 2, this.dynamicbones.update(e), this.fbxAnimationLoader && this.fbxAnimationLoader.update(), this.opt.update && this.opt.update(e), this.updateMorphTargets(e), this.isAvatarOnly)
|
|
5184
5184
|
this.stats && this.stats.end();
|
|
5185
5185
|
else {
|
|
5186
5186
|
if (this.cameraClock !== null && this.cameraClock < 1e3) {
|
|
@@ -5197,8 +5197,8 @@ class Ee {
|
|
|
5197
5197
|
resetLips() {
|
|
5198
5198
|
this.visemeNames.forEach((t) => {
|
|
5199
5199
|
this.morphs.forEach((e) => {
|
|
5200
|
-
const
|
|
5201
|
-
|
|
5200
|
+
const n = e.morphTargetDictionary["viseme_" + t];
|
|
5201
|
+
n !== void 0 && (e.morphTargetInfluences[n] = 0);
|
|
5202
5202
|
});
|
|
5203
5203
|
});
|
|
5204
5204
|
}
|
|
@@ -5209,10 +5209,10 @@ class Ee {
|
|
|
5209
5209
|
*/
|
|
5210
5210
|
lipsyncGetProcessor(t, e = "./") {
|
|
5211
5211
|
if (!this.lipsync.hasOwnProperty(t)) {
|
|
5212
|
-
const
|
|
5212
|
+
const n = t.toLowerCase(), i = "Lipsync" + t.charAt(0).toUpperCase() + t.slice(1);
|
|
5213
5213
|
try {
|
|
5214
|
-
const s =
|
|
5215
|
-
s && s[
|
|
5214
|
+
const s = He[n];
|
|
5215
|
+
s && s[i] ? (this.lipsync[t] = new s[i](), console.log(`Loaded lip-sync module for ${t}`)) : console.warn(`Lip-sync module for ${t} not found. Available modules:`, Object.keys(He));
|
|
5216
5216
|
} catch (s) {
|
|
5217
5217
|
console.warn(`Failed to load lip-sync module for ${t}:`, s);
|
|
5218
5218
|
}
|
|
@@ -5245,16 +5245,16 @@ class Ee {
|
|
|
5245
5245
|
* @param {subtitlesfn} [onsubtitles=null] Callback when a subtitle is written
|
|
5246
5246
|
* @param {number[][]} [excludes=null] Array of [start, end] index arrays to not speak
|
|
5247
5247
|
*/
|
|
5248
|
-
speakText(t, e = null,
|
|
5248
|
+
speakText(t, e = null, n = null, i = null) {
|
|
5249
5249
|
e = e || {};
|
|
5250
5250
|
const s = /[!\.\?\n\p{Extended_Pictographic}]/ug, o = /[ ]/ug, l = /[\p{L}\p{N},\.\p{Quotation_Mark}!€\$\+\p{Dash_Punctuation}%&\?]/ug, u = /[\p{Extended_Pictographic}]/ug, a = e.lipsyncLang || this.avatar.lipsyncLang || this.opt.lipsyncLang;
|
|
5251
5251
|
let h = "", r = "", c = 0, d = [], g = [];
|
|
5252
5252
|
const y = Array.from(this.segmenter.segment(t), (x) => x.segment);
|
|
5253
5253
|
for (let x = 0; x < y.length; x++) {
|
|
5254
|
-
const I = x === y.length - 1,
|
|
5254
|
+
const I = x === y.length - 1, D = y[x].match(l);
|
|
5255
5255
|
let p = y[x].match(s);
|
|
5256
5256
|
const H = y[x].match(u), z = y[x].match(o);
|
|
5257
|
-
if (p && !I && !H && y[x + 1].match(s) && (p = !1),
|
|
5257
|
+
if (p && !I && !H && y[x + 1].match(s) && (p = !1), n && (h += y[x]), D && (!i || i.every((R) => x < R[0] || x > R[1])) && (r += y[x]), (z || p || I) && (r.length && (r = this.lipsyncPreProcessText(r, a), r.length && d.push({
|
|
5258
5258
|
mark: c,
|
|
5259
5259
|
word: r
|
|
5260
5260
|
})), h.length && (g.push({
|
|
@@ -5265,16 +5265,16 @@ class Ee {
|
|
|
5265
5265
|
subtitles: [h]
|
|
5266
5266
|
}
|
|
5267
5267
|
}), h = ""), r.length)) {
|
|
5268
|
-
const
|
|
5269
|
-
if (
|
|
5270
|
-
const
|
|
5271
|
-
for (let
|
|
5268
|
+
const R = this.lipsyncWordsToVisemes(r, a);
|
|
5269
|
+
if (R && R.visemes && R.visemes.length) {
|
|
5270
|
+
const M = R.times[R.visemes.length - 1] + R.durations[R.visemes.length - 1];
|
|
5271
|
+
for (let P = 0; P < R.visemes.length; P++)
|
|
5272
5272
|
g.push({
|
|
5273
5273
|
mark: c,
|
|
5274
5274
|
template: { name: "viseme" },
|
|
5275
|
-
ts: [(
|
|
5275
|
+
ts: [(R.times[P] - 0.6) / M, (R.times[P] + 0.5) / M, (R.times[P] + R.durations[P] + 0.5) / M],
|
|
5276
5276
|
vs: {
|
|
5277
|
-
["viseme_" +
|
|
5277
|
+
["viseme_" + R.visemes[P]]: [null, R.visemes[P] === "PP" || R.visemes[P] === "FF" ? 0.9 : 0.6, 0]
|
|
5278
5278
|
}
|
|
5279
5279
|
});
|
|
5280
5280
|
}
|
|
@@ -5282,14 +5282,14 @@ class Ee {
|
|
|
5282
5282
|
}
|
|
5283
5283
|
if (p || I) {
|
|
5284
5284
|
if (d.length || I && g.length) {
|
|
5285
|
-
const
|
|
5285
|
+
const R = {
|
|
5286
5286
|
anim: g
|
|
5287
5287
|
};
|
|
5288
|
-
|
|
5288
|
+
n && (R.onSubtitles = n), d.length && !e.avatarMute && (R.text = d, e.avatarMood && (R.mood = e.avatarMood), e.ttsLang && (R.lang = e.ttsLang), e.ttsVoice && (R.voice = e.ttsVoice), e.ttsRate && (R.rate = e.ttsRate), e.ttsVoice && (R.pitch = e.ttsPitch), e.ttsVolume && (R.volume = e.ttsVolume)), this.speechQueue.push(R), d = [], r = "", c = 0, g = [];
|
|
5289
5289
|
}
|
|
5290
5290
|
if (H) {
|
|
5291
|
-
let
|
|
5292
|
-
|
|
5291
|
+
let R = this.animEmojis[y[x]];
|
|
5292
|
+
R && R.link && (R = this.animEmojis[R.link]), R && this.speechQueue.push({ emoji: R });
|
|
5293
5293
|
}
|
|
5294
5294
|
this.speechQueue.push({ break: 100 });
|
|
5295
5295
|
}
|
|
@@ -5323,8 +5323,8 @@ class Ee {
|
|
|
5323
5323
|
* @param {string} url URL for the audio, stop if null.
|
|
5324
5324
|
*/
|
|
5325
5325
|
async playBackgroundAudio(t) {
|
|
5326
|
-
let
|
|
5327
|
-
this.stopBackgroundAudio(), this.audioBackgroundSource = this.audioCtx.createBufferSource(), this.audioBackgroundSource.loop = !0, this.audioBackgroundSource.buffer = await this.audioCtx.decodeAudioData(
|
|
5326
|
+
let n = await (await fetch(t)).arrayBuffer();
|
|
5327
|
+
this.stopBackgroundAudio(), this.audioBackgroundSource = this.audioCtx.createBufferSource(), this.audioBackgroundSource.loop = !0, this.audioBackgroundSource.buffer = await this.audioCtx.decodeAudioData(n), this.audioBackgroundSource.playbackRate.value = 1 / this.animSlowdownRate, this.audioBackgroundSource.connect(this.audioBackgroundGainNode), this.audioBackgroundSource.start(0);
|
|
5328
5328
|
}
|
|
5329
5329
|
/**
|
|
5330
5330
|
* Stop background audio.
|
|
@@ -5342,11 +5342,11 @@ class Ee {
|
|
|
5342
5342
|
*/
|
|
5343
5343
|
async setReverb(t = null) {
|
|
5344
5344
|
if (t) {
|
|
5345
|
-
let
|
|
5346
|
-
this.audioReverbNode.buffer = await this.audioCtx.decodeAudioData(
|
|
5345
|
+
let n = await (await fetch(t)).arrayBuffer();
|
|
5346
|
+
this.audioReverbNode.buffer = await this.audioCtx.decodeAudioData(n);
|
|
5347
5347
|
} else {
|
|
5348
|
-
const e = this.audioCtx.sampleRate,
|
|
5349
|
-
|
|
5348
|
+
const e = this.audioCtx.sampleRate, n = this.audioCtx.createBuffer(2, e, e);
|
|
5349
|
+
n.getChannelData(0)[0] = 1, n.getChannelData(1)[0] = 1, this.audioReverbNode.buffer = n;
|
|
5350
5350
|
}
|
|
5351
5351
|
}
|
|
5352
5352
|
/**
|
|
@@ -5355,8 +5355,8 @@ class Ee {
|
|
|
5355
5355
|
* @param {number} [background=null] Gain for background audio, if null do not change
|
|
5356
5356
|
* @param {number} [fadeSecs=0] Gradual exponential fade in/out time in seconds
|
|
5357
5357
|
*/
|
|
5358
|
-
setMixerGain(t, e = null,
|
|
5359
|
-
t !== null && (this.audioSpeechGainNode.gain.cancelScheduledValues(this.audioCtx.currentTime),
|
|
5358
|
+
setMixerGain(t, e = null, n = 0) {
|
|
5359
|
+
t !== null && (this.audioSpeechGainNode.gain.cancelScheduledValues(this.audioCtx.currentTime), n ? (this.audioSpeechGainNode.gain.setValueAtTime(Math.max(this.audioSpeechGainNode.gain.value, 1e-4), this.audioCtx.currentTime), this.audioSpeechGainNode.gain.exponentialRampToValueAtTime(Math.max(t, 1e-4), this.audioCtx.currentTime + n)) : this.audioSpeechGainNode.gain.setValueAtTime(t, this.audioCtx.currentTime)), e !== null && (this.audioBackgroundGainNode.gain.cancelScheduledValues(this.audioCtx.currentTime), n ? (this.audioBackgroundGainNode.gain.setValueAtTime(Math.max(this.audioBackgroundGainNode.gain.value, 1e-4), this.audioCtx.currentTime), this.audioBackgroundGainNode.gain.exponentialRampToValueAtTime(Math.max(e, 1e-4), this.audioCtx.currentTime + n)) : this.audioBackgroundGainNode.gain.setValueAtTime(e, this.audioCtx.currentTime));
|
|
5360
5360
|
}
|
|
5361
5361
|
/**
|
|
5362
5362
|
* Add audio to the speech queue.
|
|
@@ -5364,31 +5364,31 @@ class Ee {
|
|
|
5364
5364
|
* @param {Options} [opt=null] Text-specific options for lipsyncLang
|
|
5365
5365
|
* @param {subtitlesfn} [onsubtitles=null] Callback when a subtitle is written
|
|
5366
5366
|
*/
|
|
5367
|
-
speakAudio(t, e = null,
|
|
5367
|
+
speakAudio(t, e = null, n = null) {
|
|
5368
5368
|
e = e || {};
|
|
5369
|
-
const
|
|
5369
|
+
const i = e.lipsyncLang || this.avatar.lipsyncLang || this.opt.lipsyncLang, s = {};
|
|
5370
5370
|
if (t.words) {
|
|
5371
5371
|
let o = [];
|
|
5372
5372
|
for (let l = 0; l < t.words.length; l++) {
|
|
5373
5373
|
const u = t.words[l], a = t.wtimes[l];
|
|
5374
5374
|
let h = t.wdurations[l];
|
|
5375
|
-
if (u.length && (
|
|
5375
|
+
if (u.length && (n && o.push({
|
|
5376
5376
|
template: { name: "subtitles" },
|
|
5377
5377
|
ts: [a],
|
|
5378
5378
|
vs: {
|
|
5379
5379
|
subtitles: [" " + u]
|
|
5380
5380
|
}
|
|
5381
5381
|
}), !t.visemes)) {
|
|
5382
|
-
const r = this.lipsyncPreProcessText(u,
|
|
5382
|
+
const r = this.lipsyncPreProcessText(u, i), c = this.lipsyncWordsToVisemes(r, i);
|
|
5383
5383
|
if (c && c.visemes && c.visemes.length) {
|
|
5384
5384
|
const d = c.times[c.visemes.length - 1] + c.durations[c.visemes.length - 1], g = Math.min(h, Math.max(0, h - c.visemes.length * 150));
|
|
5385
5385
|
let y = 0.6 + this.convertRange(g, [0, h], [0, 0.4]);
|
|
5386
5386
|
if (h = Math.min(h, c.visemes.length * 200), d > 0)
|
|
5387
5387
|
for (let x = 0; x < c.visemes.length; x++) {
|
|
5388
|
-
const I = a + c.times[x] / d * h,
|
|
5388
|
+
const I = a + c.times[x] / d * h, D = c.durations[x] / d * h;
|
|
5389
5389
|
o.push({
|
|
5390
5390
|
template: { name: "viseme" },
|
|
5391
|
-
ts: [I - Math.min(60, 2 *
|
|
5391
|
+
ts: [I - Math.min(60, 2 * D / 3), I + Math.min(25, D / 2), I + D + Math.min(60, D / 2)],
|
|
5392
5392
|
vs: {
|
|
5393
5393
|
["viseme_" + c.visemes[x]]: [null, c.visemes[x] === "PP" || c.visemes[x] === "FF" ? 0.9 : y, 0]
|
|
5394
5394
|
}
|
|
@@ -5423,7 +5423,7 @@ class Ee {
|
|
|
5423
5423
|
let o = this.animFactory(t.anim, !1, 1, 1, !0);
|
|
5424
5424
|
s.anim ? s.anim.push(o) : s.anim = [o];
|
|
5425
5425
|
}
|
|
5426
|
-
|
|
5426
|
+
n && (s.onSubtitles = n), e.isRaw && (s.isRaw = !0), Object.keys(s).length && (this.speechQueue.push(s), s.isRaw || this.speechQueue.push({ break: 300 }), this.startSpeaking());
|
|
5427
5427
|
}
|
|
5428
5428
|
/**
|
|
5429
5429
|
* Play audio playlist using Web Audio API.
|
|
@@ -5442,21 +5442,21 @@ class Ee {
|
|
|
5442
5442
|
return;
|
|
5443
5443
|
}
|
|
5444
5444
|
}
|
|
5445
|
-
let
|
|
5445
|
+
let n;
|
|
5446
5446
|
if (Array.isArray(e.audio)) {
|
|
5447
5447
|
let s = this.concatArrayBuffers(e.audio);
|
|
5448
|
-
|
|
5448
|
+
n = this.pcmToAudioBuffer(s);
|
|
5449
5449
|
} else
|
|
5450
|
-
|
|
5451
|
-
this.audioSpeechSource = this.audioCtx.createBufferSource(), this.audioSpeechSource.buffer =
|
|
5450
|
+
n = e.audio;
|
|
5451
|
+
this.audioSpeechSource = this.audioCtx.createBufferSource(), this.audioSpeechSource.buffer = n, this.audioSpeechSource.playbackRate.value = 1 / this.animSlowdownRate, this.audioSpeechSource.connect(this.audioAnalyzerNode), this.audioSpeechSource.addEventListener("ended", () => {
|
|
5452
5452
|
this.audioSpeechSource.disconnect(), this.playAudio(!0);
|
|
5453
5453
|
}, { once: !0 });
|
|
5454
|
-
let
|
|
5455
|
-
e.anim && (e.isRaw || (
|
|
5454
|
+
let i = 0;
|
|
5455
|
+
e.anim && (e.isRaw || (i = Math.abs(Math.min(0, ...e.anim.map((s) => Math.min(...s.ts))))), e.anim.forEach((s) => {
|
|
5456
5456
|
for (let o = 0; o < s.ts.length; o++)
|
|
5457
|
-
s.ts[o] = this.animClock + s.ts[o] +
|
|
5457
|
+
s.ts[o] = this.animClock + s.ts[o] + i;
|
|
5458
5458
|
this.animQueue.push(s);
|
|
5459
|
-
})), this.audioSpeechSource.start(
|
|
5459
|
+
})), this.audioSpeechSource.start(i / 1e3);
|
|
5460
5460
|
} else
|
|
5461
5461
|
this.isAudioPlaying = !1, this.startSpeaking(!0);
|
|
5462
5462
|
}
|
|
@@ -5465,17 +5465,17 @@ class Ee {
|
|
|
5465
5465
|
* @param {Object} line Speech line object
|
|
5466
5466
|
*/
|
|
5467
5467
|
async synthesizeWithBrowserTTS(t) {
|
|
5468
|
-
return new Promise((e,
|
|
5469
|
-
const
|
|
5468
|
+
return new Promise((e, n) => {
|
|
5469
|
+
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, u = (t.pitch || this.avatar.ttsPitch || this.opt.ttsPitch || 1) + this.mood.speech.deltaPitch, a = (t.volume || this.avatar.ttsVolume || this.opt.ttsVolume || 1) + this.mood.speech.deltaVolume;
|
|
5470
5470
|
s.lang = o, s.rate = Math.max(0.1, Math.min(10, l)), s.pitch = Math.max(0, Math.min(2, u)), s.volume = Math.max(0, Math.min(1, a));
|
|
5471
5471
|
const h = speechSynthesis.getVoices(), r = t.voice || this.avatar.ttsVoice || this.opt.ttsVoice;
|
|
5472
5472
|
if (r && h.length > 0) {
|
|
5473
5473
|
const p = h.find((H) => H.name.includes(r) || H.lang === o);
|
|
5474
5474
|
p && (s.voice = p);
|
|
5475
5475
|
}
|
|
5476
|
-
const c =
|
|
5476
|
+
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", y = this.lipsyncPreProcessText(i, g), x = this.lipsyncWordsToVisemes(y, g);
|
|
5477
5477
|
console.log("Browser TTS Lip-sync Debug:", {
|
|
5478
|
-
text:
|
|
5478
|
+
text: i,
|
|
5479
5479
|
lipsyncLang: g,
|
|
5480
5480
|
processedText: y,
|
|
5481
5481
|
lipsyncData: x,
|
|
@@ -5486,21 +5486,21 @@ class Ee {
|
|
|
5486
5486
|
if (x && x.visemes && x.visemes.length > 0) {
|
|
5487
5487
|
const p = x.times[x.visemes.length - 1] + x.durations[x.visemes.length - 1];
|
|
5488
5488
|
for (let H = 0; H < x.visemes.length; H++) {
|
|
5489
|
-
const z = x.visemes[H],
|
|
5489
|
+
const z = x.visemes[H], R = x.times[H] / p, M = x.durations[H] / p, P = R * c, ee = M * c;
|
|
5490
5490
|
I.push({
|
|
5491
5491
|
template: { name: "viseme" },
|
|
5492
|
-
ts: [
|
|
5492
|
+
ts: [P - Math.min(60, 2 * ee / 3), P + Math.min(25, ee / 2), P + ee + Math.min(60, ee / 2)],
|
|
5493
5493
|
vs: {
|
|
5494
5494
|
["viseme_" + z]: [null, z === "PP" || z === "FF" ? 0.9 : 0.6, 0]
|
|
5495
5495
|
}
|
|
5496
5496
|
});
|
|
5497
5497
|
}
|
|
5498
5498
|
}
|
|
5499
|
-
const
|
|
5500
|
-
this.audioPlaylist.push({ anim:
|
|
5499
|
+
const D = [...t.anim, ...I];
|
|
5500
|
+
this.audioPlaylist.push({ anim: D, audio: d }), this.onSubtitles = t.onSubtitles || null, this.resetLips(), t.mood && this.setMood(t.mood), this.playAudio(), s.onend = () => {
|
|
5501
5501
|
e();
|
|
5502
5502
|
}, s.onerror = (p) => {
|
|
5503
|
-
console.error("Speech synthesis error:", p.error),
|
|
5503
|
+
console.error("Speech synthesis error:", p.error), n(p.error);
|
|
5504
5504
|
}, speechSynthesis.speak(s);
|
|
5505
5505
|
});
|
|
5506
5506
|
}
|
|
@@ -5509,7 +5509,7 @@ class Ee {
|
|
|
5509
5509
|
* @param {Object} line Speech line object
|
|
5510
5510
|
*/
|
|
5511
5511
|
async synthesizeWithElevenLabsTTS(t) {
|
|
5512
|
-
const e = t.text.map((c) => c.word).join(" "),
|
|
5512
|
+
const e = t.text.map((c) => c.word).join(" "), n = t.voice || this.avatar.ttsVoice || this.opt.ttsVoice || "21m00Tcm4TlvDq8ikWAM", i = {
|
|
5513
5513
|
text: e,
|
|
5514
5514
|
model_id: "eleven_monolingual_v1",
|
|
5515
5515
|
voice_settings: {
|
|
@@ -5518,14 +5518,14 @@ class Ee {
|
|
|
5518
5518
|
style: 0,
|
|
5519
5519
|
use_speaker_boost: !0
|
|
5520
5520
|
}
|
|
5521
|
-
}, s = await fetch(`${this.opt.ttsEndpoint}/${
|
|
5521
|
+
}, s = await fetch(`${this.opt.ttsEndpoint}/${n}`, {
|
|
5522
5522
|
method: "POST",
|
|
5523
5523
|
headers: {
|
|
5524
5524
|
Accept: "audio/mpeg",
|
|
5525
5525
|
"Content-Type": "application/json",
|
|
5526
5526
|
"xi-api-key": this.opt.ttsApikey
|
|
5527
5527
|
},
|
|
5528
|
-
body: JSON.stringify(
|
|
5528
|
+
body: JSON.stringify(i)
|
|
5529
5529
|
});
|
|
5530
5530
|
if (!s.ok)
|
|
5531
5531
|
throw new Error(`ElevenLabs TTS error: ${s.status} ${s.statusText}`);
|
|
@@ -5616,7 +5616,7 @@ class Ee {
|
|
|
5616
5616
|
* @param {Object} line Speech line object
|
|
5617
5617
|
*/
|
|
5618
5618
|
async synthesizeWithDeepgramTTS(t) {
|
|
5619
|
-
const e = t.text.map((c) => c.word).join(" "),
|
|
5619
|
+
const e = t.text.map((c) => c.word).join(" "), n = t.voice || this.avatar.ttsVoice || this.opt.ttsVoice || "aura-2-thalia-en", i = `${this.opt.ttsEndpoint}?model=${n}`, s = await fetch(i, {
|
|
5620
5620
|
method: "POST",
|
|
5621
5621
|
headers: {
|
|
5622
5622
|
Authorization: `Token ${this.opt.ttsApikey}`,
|
|
@@ -5714,7 +5714,7 @@ class Ee {
|
|
|
5714
5714
|
* @param {Object} line Speech line object
|
|
5715
5715
|
*/
|
|
5716
5716
|
async synthesizeWithAzureTTS(t) {
|
|
5717
|
-
const e = t.text.map((r) => r.word).join(" "),
|
|
5717
|
+
const e = t.text.map((r) => r.word).join(" "), i = `
|
|
5718
5718
|
<speak version="1.0" xmlns="http://www.w3.org/2001/10/synthesis" xml:lang="en-US">
|
|
5719
5719
|
<voice name="${t.voice || this.avatar.ttsVoice || this.opt.ttsVoice || "en-US-AriaNeural"}">
|
|
5720
5720
|
${e}
|
|
@@ -5727,7 +5727,7 @@ class Ee {
|
|
|
5727
5727
|
"Content-Type": "application/ssml+xml",
|
|
5728
5728
|
"X-Microsoft-OutputFormat": "audio-16khz-128kbitrate-mono-mp3"
|
|
5729
5729
|
},
|
|
5730
|
-
body:
|
|
5730
|
+
body: i
|
|
5731
5731
|
});
|
|
5732
5732
|
if (!s.ok)
|
|
5733
5733
|
throw new Error(`Azure TTS error: ${s.status} ${s.statusText}`);
|
|
@@ -5767,7 +5767,7 @@ class Ee {
|
|
|
5767
5767
|
t.text.forEach((o, l) => {
|
|
5768
5768
|
l > 0 && (e += " <mark name='" + o.mark + "'/>"), e += o.word.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'").replace(new RegExp("^\\p{Dash_Punctuation}$", "ug"), '<break time="750ms"/>');
|
|
5769
5769
|
}), e += "</speak>";
|
|
5770
|
-
const
|
|
5770
|
+
const n = {
|
|
5771
5771
|
method: "POST",
|
|
5772
5772
|
headers: {
|
|
5773
5773
|
"Content-Type": "application/json; charset=utf-8"
|
|
@@ -5790,9 +5790,9 @@ class Ee {
|
|
|
5790
5790
|
// Timepoint information for mark tags
|
|
5791
5791
|
})
|
|
5792
5792
|
};
|
|
5793
|
-
this.opt.jwtGet && typeof this.opt.jwtGet == "function" && (
|
|
5794
|
-
const
|
|
5795
|
-
if (
|
|
5793
|
+
this.opt.jwtGet && typeof this.opt.jwtGet == "function" && (n.headers.Authorization = "Bearer " + await this.opt.jwtGet());
|
|
5794
|
+
const i = await fetch(this.opt.ttsEndpoint + (this.opt.ttsApikey ? "?key=" + this.opt.ttsApikey : ""), n), s = await i.json();
|
|
5795
|
+
if (i.status === 200 && s && s.audioContent) {
|
|
5796
5796
|
const o = this.b64ToArrayBuffer(s.audioContent), l = await this.audioCtx.decodeAudioData(o);
|
|
5797
5797
|
this.speakWithHands();
|
|
5798
5798
|
const u = [0];
|
|
@@ -5831,8 +5831,8 @@ class Ee {
|
|
|
5831
5831
|
let e = this.speechQueue.shift();
|
|
5832
5832
|
if (e.emoji) {
|
|
5833
5833
|
this.lookAtCamera(500);
|
|
5834
|
-
let
|
|
5835
|
-
this.animQueue.push(this.animFactory(e.emoji)), setTimeout(this.startSpeaking.bind(this),
|
|
5834
|
+
let n = e.emoji.dt.reduce((i, s) => i + s, 0);
|
|
5835
|
+
this.animQueue.push(this.animFactory(e.emoji)), setTimeout(this.startSpeaking.bind(this), n, !0);
|
|
5836
5836
|
} else if (e.break)
|
|
5837
5837
|
setTimeout(this.startSpeaking.bind(this), e.break, !0);
|
|
5838
5838
|
else if (e.audio)
|
|
@@ -5841,13 +5841,13 @@ class Ee {
|
|
|
5841
5841
|
this.lookAtCamera(500);
|
|
5842
5842
|
try {
|
|
5843
5843
|
!this.opt.ttsEndpoint || this.opt.ttsEndpoint === "" ? await this.synthesizeWithBrowserTTS(e) : this.opt.ttsService === "elevenlabs" ? await this.synthesizeWithElevenLabsTTS(e) : this.opt.ttsService === "deepgram" ? await this.synthesizeWithDeepgramTTS(e) : this.opt.ttsService === "azure" ? await this.synthesizeWithAzureTTS(e) : await this.synthesizeWithExternalTTS(e);
|
|
5844
|
-
} catch (
|
|
5845
|
-
console.error("Error:",
|
|
5844
|
+
} catch (n) {
|
|
5845
|
+
console.error("Error:", n), this.startSpeaking(!0);
|
|
5846
5846
|
}
|
|
5847
|
-
} else e.anim ? (this.onSubtitles = e.onSubtitles || null, this.resetLips(), e.mood && this.setMood(e.mood), e.anim.forEach((
|
|
5848
|
-
for (let s = 0; s <
|
|
5849
|
-
|
|
5850
|
-
this.animQueue.push(
|
|
5847
|
+
} else e.anim ? (this.onSubtitles = e.onSubtitles || null, this.resetLips(), e.mood && this.setMood(e.mood), e.anim.forEach((n, i) => {
|
|
5848
|
+
for (let s = 0; s < n.ts.length; s++)
|
|
5849
|
+
n.ts[s] = this.animClock + 10 * i;
|
|
5850
|
+
this.animQueue.push(n);
|
|
5851
5851
|
}), setTimeout(this.startSpeaking.bind(this), 10 * e.anim.length, !0)) : e.marker ? (typeof e.marker == "function" && e.marker(), this.startSpeaking(!0)) : this.startSpeaking(!0);
|
|
5852
5852
|
} else
|
|
5853
5853
|
this.stateName = "idle", this.isSpeaking = !1;
|
|
@@ -5880,8 +5880,8 @@ class Ee {
|
|
|
5880
5880
|
* @param {function} [onSubtitles=null] Optional callback to play subtitles
|
|
5881
5881
|
* @param {function} [onMetrics=null] Optional callback to receive metrics data during streaming
|
|
5882
5882
|
*/
|
|
5883
|
-
async streamStart(t = {}, e = null,
|
|
5884
|
-
if (this.stopSpeaking(), this.isStreaming = !0, t.waitForAudioChunks !== void 0 && (this.streamWaitForAudioChunks = t.waitForAudioChunks), this.streamWaitForAudioChunks || (this.streamAudioStartTime = this.animClock), this.streamLipsyncQueue = [], this.streamLipsyncType = t.lipsyncType || this.streamLipsyncType || "visemes", this.streamLipsyncLang = t.lipsyncLang || this.streamLipsyncLang || this.avatar.lipsyncLang || this.opt.lipsyncLang, this.onAudioStart = e, this.onAudioEnd =
|
|
5883
|
+
async streamStart(t = {}, e = null, n = null, i = null, s = null) {
|
|
5884
|
+
if (this.stopSpeaking(), this.isStreaming = !0, t.waitForAudioChunks !== void 0 && (this.streamWaitForAudioChunks = t.waitForAudioChunks), this.streamWaitForAudioChunks || (this.streamAudioStartTime = this.animClock), this.streamLipsyncQueue = [], this.streamLipsyncType = t.lipsyncType || this.streamLipsyncType || "visemes", this.streamLipsyncLang = t.lipsyncLang || this.streamLipsyncLang || this.avatar.lipsyncLang || this.opt.lipsyncLang, this.onAudioStart = e, this.onAudioEnd = n, this.onMetrics = s, t.sampleRate !== void 0) {
|
|
5885
5885
|
const l = t.sampleRate;
|
|
5886
5886
|
typeof l == "number" && l >= 8e3 && l <= 96e3 ? l !== this.audioCtx.sampleRate && this.initAudioGraph(l) : console.warn(
|
|
5887
5887
|
"Invalid sampleRate provided. It must be a number between 8000 and 96000 Hz."
|
|
@@ -5895,7 +5895,7 @@ class Ee {
|
|
|
5895
5895
|
}
|
|
5896
5896
|
if (!this.workletLoaded)
|
|
5897
5897
|
try {
|
|
5898
|
-
const l = this.audioCtx.audioWorklet.addModule(
|
|
5898
|
+
const l = this.audioCtx.audioWorklet.addModule(lt.href), u = new Promise(
|
|
5899
5899
|
(a, h) => setTimeout(() => h(new Error("Worklet loading timed out")), 5e3)
|
|
5900
5900
|
);
|
|
5901
5901
|
await Promise.race([l, u]), this.workletLoaded = !0;
|
|
@@ -5931,7 +5931,7 @@ class Ee {
|
|
|
5931
5931
|
this.streamWorkletNode.port.postMessage({ type: "config-metrics", data: t.metrics });
|
|
5932
5932
|
} catch {
|
|
5933
5933
|
}
|
|
5934
|
-
if (this.resetLips(), this.lookAtCamera(500), t.mood && this.setMood(t.mood), this.onSubtitles =
|
|
5934
|
+
if (this.resetLips(), this.lookAtCamera(500), t.mood && this.setMood(t.mood), this.onSubtitles = i || null, this.audioCtx.state === "suspended" || this.audioCtx.state === "interrupted") {
|
|
5935
5935
|
const l = this.audioCtx.resume(), u = new Promise((a, h) => setTimeout(() => h("p2"), 1e3));
|
|
5936
5936
|
try {
|
|
5937
5937
|
await Promise.race([l, u]);
|
|
@@ -6010,28 +6010,28 @@ class Ee {
|
|
|
6010
6010
|
_processLipsyncData(t, e) {
|
|
6011
6011
|
if (this.isStreaming) {
|
|
6012
6012
|
if (t.visemes && this.streamLipsyncType == "visemes")
|
|
6013
|
-
for (let
|
|
6014
|
-
const
|
|
6013
|
+
for (let n = 0; n < t.visemes.length; n++) {
|
|
6014
|
+
const i = t.visemes[n], s = e + t.vtimes[n], o = t.vdurations[n], l = {
|
|
6015
6015
|
template: { name: "viseme" },
|
|
6016
6016
|
ts: [s - 2 * o / 3, s + o / 2, s + o + o / 2],
|
|
6017
6017
|
vs: {
|
|
6018
|
-
["viseme_" +
|
|
6018
|
+
["viseme_" + i]: [null, i === "PP" || i === "FF" ? 0.9 : 0.6, 0]
|
|
6019
6019
|
}
|
|
6020
6020
|
};
|
|
6021
6021
|
this.animQueue.push(l);
|
|
6022
6022
|
}
|
|
6023
6023
|
if (t.words && (this.onSubtitles || this.streamLipsyncType == "words"))
|
|
6024
|
-
for (let
|
|
6025
|
-
const
|
|
6026
|
-
let o = t.wdurations[
|
|
6027
|
-
if (
|
|
6024
|
+
for (let n = 0; n < t.words.length; n++) {
|
|
6025
|
+
const i = t.words[n], s = t.wtimes[n];
|
|
6026
|
+
let o = t.wdurations[n];
|
|
6027
|
+
if (i.length && (this.onSubtitles && this.animQueue.push({
|
|
6028
6028
|
template: { name: "subtitles" },
|
|
6029
6029
|
ts: [e + s],
|
|
6030
6030
|
vs: {
|
|
6031
|
-
subtitles: [" " +
|
|
6031
|
+
subtitles: [" " + i]
|
|
6032
6032
|
}
|
|
6033
6033
|
}), this.streamLipsyncType == "words")) {
|
|
6034
|
-
const l = this.streamLipsyncLang || this.avatar.lipsyncLang || this.opt.lipsyncLang, u = this.lipsyncPreProcessText(
|
|
6034
|
+
const l = this.streamLipsyncLang || this.avatar.lipsyncLang || this.opt.lipsyncLang, u = this.lipsyncPreProcessText(i, l), a = this.lipsyncWordsToVisemes(u, l);
|
|
6035
6035
|
if (a && a.visemes && a.visemes.length) {
|
|
6036
6036
|
const h = a.times[a.visemes.length - 1] + a.durations[a.visemes.length - 1], r = Math.min(o, Math.max(0, o - a.visemes.length * 150));
|
|
6037
6037
|
let c = 0.6 + this.convertRange(r, [0, o], [0, 0.4]);
|
|
@@ -6050,10 +6050,10 @@ class Ee {
|
|
|
6050
6050
|
}
|
|
6051
6051
|
}
|
|
6052
6052
|
if (t.anims && this.streamLipsyncType == "blendshapes")
|
|
6053
|
-
for (let
|
|
6054
|
-
let
|
|
6055
|
-
|
|
6056
|
-
let s = this.animFactory(
|
|
6053
|
+
for (let n = 0; n < t.anims.length; n++) {
|
|
6054
|
+
let i = t.anims[n];
|
|
6055
|
+
i.delay += e;
|
|
6056
|
+
let s = this.animFactory(i, !1, 1, 1, !0);
|
|
6057
6057
|
this.animQueue.push(s);
|
|
6058
6058
|
}
|
|
6059
6059
|
}
|
|
@@ -6069,15 +6069,15 @@ class Ee {
|
|
|
6069
6069
|
if (t.audio instanceof ArrayBuffer)
|
|
6070
6070
|
e.data = t.audio, this.streamWorkletNode.port.postMessage(e, [e.data]);
|
|
6071
6071
|
else if (t.audio instanceof Int16Array || t.audio instanceof Uint8Array) {
|
|
6072
|
-
const
|
|
6073
|
-
e.data =
|
|
6072
|
+
const n = t.audio.buffer.slice(t.audio.byteOffset, t.audio.byteOffset + t.audio.byteLength);
|
|
6073
|
+
e.data = n, this.streamWorkletNode.port.postMessage(e, [e.data]);
|
|
6074
6074
|
} else if (t.audio instanceof Float32Array) {
|
|
6075
|
-
const
|
|
6076
|
-
for (let
|
|
6077
|
-
let s = Math.max(-1, Math.min(1, t.audio[
|
|
6078
|
-
i
|
|
6075
|
+
const n = new Int16Array(t.audio.length);
|
|
6076
|
+
for (let i = 0; i < t.audio.length; i++) {
|
|
6077
|
+
let s = Math.max(-1, Math.min(1, t.audio[i]));
|
|
6078
|
+
n[i] = s < 0 ? s * 32768 : s * 32767;
|
|
6079
6079
|
}
|
|
6080
|
-
e.data =
|
|
6080
|
+
e.data = n.buffer, this.streamWorkletNode.port.postMessage(e, [e.data]);
|
|
6081
6081
|
} else
|
|
6082
6082
|
console.error("r.audio is not a supported type. Must be ArrayBuffer, Int16Array, Uint8Array, or Float32Array:", t.audio);
|
|
6083
6083
|
}
|
|
@@ -6107,16 +6107,16 @@ class Ee {
|
|
|
6107
6107
|
*/
|
|
6108
6108
|
lookAhead(t) {
|
|
6109
6109
|
if (t) {
|
|
6110
|
-
let e = (Math.random() - 0.5) / 4,
|
|
6111
|
-
|
|
6110
|
+
let e = (Math.random() - 0.5) / 4, n = (Math.random() - 0.5) / 4, i = this.animQueue.findIndex((o) => o.template.name === "lookat");
|
|
6111
|
+
i !== -1 && this.animQueue.splice(i, 1);
|
|
6112
6112
|
const s = {
|
|
6113
6113
|
name: "lookat",
|
|
6114
6114
|
dt: [750, t],
|
|
6115
6115
|
vs: {
|
|
6116
6116
|
bodyRotateX: [e],
|
|
6117
|
-
bodyRotateY: [
|
|
6117
|
+
bodyRotateY: [n],
|
|
6118
6118
|
eyesRotateX: [-3 * e + 0.1],
|
|
6119
|
-
eyesRotateY: [-5 *
|
|
6119
|
+
eyesRotateY: [-5 * n],
|
|
6120
6120
|
browInnerUp: [[0, 0.7]],
|
|
6121
6121
|
mouthLeft: [[0, 0.7]],
|
|
6122
6122
|
mouthRight: [[0, 0.7]],
|
|
@@ -6133,7 +6133,7 @@ class Ee {
|
|
|
6133
6133
|
*/
|
|
6134
6134
|
lookAtCamera(t) {
|
|
6135
6135
|
let e;
|
|
6136
|
-
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),
|
|
6136
|
+
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), le.setFromMatrixPosition(this.speakTo.objectLeftEye.matrixWorld), he.setFromMatrixPosition(this.speakTo.objectRightEye.matrixWorld), e.addVectors(le, he).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) {
|
|
6137
6137
|
if (this.avatar.hasOwnProperty("avatarIgnoreCamera")) {
|
|
6138
6138
|
if (this.avatar.avatarIgnoreCamera) {
|
|
6139
6139
|
this.lookAhead(t);
|
|
@@ -6146,12 +6146,12 @@ class Ee {
|
|
|
6146
6146
|
this.lookAt(null, null, t);
|
|
6147
6147
|
return;
|
|
6148
6148
|
}
|
|
6149
|
-
this.objectLeftEye.updateMatrixWorld(!0), this.objectRightEye.updateMatrixWorld(!0),
|
|
6150
|
-
const
|
|
6151
|
-
|
|
6152
|
-
const l = new f.Quaternion().setFromEuler(
|
|
6153
|
-
|
|
6154
|
-
let a =
|
|
6149
|
+
this.objectLeftEye.updateMatrixWorld(!0), this.objectRightEye.updateMatrixWorld(!0), le.setFromMatrixPosition(this.objectLeftEye.matrixWorld), he.setFromMatrixPosition(this.objectRightEye.matrixWorld), le.add(he).divideScalar(2), W.copy(this.armature.quaternion), W.multiply(this.poseTarget.props["Hips.quaternion"]), W.multiply(this.poseTarget.props["Spine.quaternion"]), W.multiply(this.poseTarget.props["Spine1.quaternion"]), W.multiply(this.poseTarget.props["Spine2.quaternion"]), W.multiply(this.poseTarget.props["Neck.quaternion"]), W.multiply(this.poseTarget.props["Head.quaternion"]);
|
|
6150
|
+
const n = new f.Vector3().subVectors(e, le).normalize(), i = Math.atan2(n.x, n.z), s = Math.asin(-n.y);
|
|
6151
|
+
F.set(s, i, 0, "YXZ");
|
|
6152
|
+
const l = new f.Quaternion().setFromEuler(F), u = new f.Quaternion().copy(l).multiply(W.clone().invert());
|
|
6153
|
+
F.setFromQuaternion(u, "YXZ");
|
|
6154
|
+
let a = F.x / (40 / 24) + 0.2, h = F.y / (9 / 4), r = Math.min(0.6, Math.max(-0.3, a)), c = Math.min(0.8, Math.max(-0.8, h)), d = (Math.random() - 0.5) / 4, g = (Math.random() - 0.5) / 4;
|
|
6155
6155
|
if (t) {
|
|
6156
6156
|
let y = this.animQueue.findIndex((I) => I.template.name === "lookat");
|
|
6157
6157
|
y !== -1 && this.animQueue.splice(y, 1);
|
|
@@ -6179,27 +6179,27 @@ class Ee {
|
|
|
6179
6179
|
* @param {number} y Y-coordinate relative to visual viewport
|
|
6180
6180
|
* @param {number} t Time in milliseconds
|
|
6181
6181
|
*/
|
|
6182
|
-
lookAt(t, e,
|
|
6182
|
+
lookAt(t, e, n) {
|
|
6183
6183
|
if (!this.camera) return;
|
|
6184
|
-
const
|
|
6184
|
+
const i = this.nodeAvatar.getBoundingClientRect();
|
|
6185
6185
|
this.objectLeftEye.updateMatrixWorld(!0), this.objectRightEye.updateMatrixWorld(!0);
|
|
6186
6186
|
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);
|
|
6187
6187
|
l.project(this.camera);
|
|
6188
|
-
let u = (l.x + 1) / 2 *
|
|
6189
|
-
t === null && (t = u), e === null && (e = a), W.copy(this.armature.quaternion), W.multiply(this.poseTarget.props["Hips.quaternion"]), W.multiply(this.poseTarget.props["Spine.quaternion"]), W.multiply(this.poseTarget.props["Spine1.quaternion"]), W.multiply(this.poseTarget.props["Spine2.quaternion"]), W.multiply(this.poseTarget.props["Neck.quaternion"]), W.multiply(this.poseTarget.props["Head.quaternion"]),
|
|
6190
|
-
let h =
|
|
6188
|
+
let u = (l.x + 1) / 2 * i.width + i.left, a = -(l.y - 1) / 2 * i.height + i.top;
|
|
6189
|
+
t === null && (t = u), e === null && (e = a), W.copy(this.armature.quaternion), W.multiply(this.poseTarget.props["Hips.quaternion"]), W.multiply(this.poseTarget.props["Spine.quaternion"]), W.multiply(this.poseTarget.props["Spine1.quaternion"]), W.multiply(this.poseTarget.props["Spine2.quaternion"]), W.multiply(this.poseTarget.props["Neck.quaternion"]), W.multiply(this.poseTarget.props["Head.quaternion"]), F.setFromQuaternion(W);
|
|
6190
|
+
let h = F.x / (40 / 24), r = F.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 - u, u), y = Math.max(window.innerHeight - a, a), x = this.convertRange(e, [a - y, a + y], [-0.3, 0.6]) - h + c, I = this.convertRange(t, [u - g, u + g], [-0.8, 0.8]) - r + d;
|
|
6191
6191
|
x = Math.min(0.6, Math.max(-0.3, x)), I = Math.min(0.8, Math.max(-0.8, I));
|
|
6192
|
-
let
|
|
6193
|
-
if (
|
|
6194
|
-
let H = this.animQueue.findIndex((
|
|
6192
|
+
let D = (Math.random() - 0.5) / 4, p = (Math.random() - 0.5) / 4;
|
|
6193
|
+
if (n) {
|
|
6194
|
+
let H = this.animQueue.findIndex((R) => R.template.name === "lookat");
|
|
6195
6195
|
H !== -1 && this.animQueue.splice(H, 1);
|
|
6196
6196
|
const z = {
|
|
6197
6197
|
name: "lookat",
|
|
6198
|
-
dt: [750,
|
|
6198
|
+
dt: [750, n],
|
|
6199
6199
|
vs: {
|
|
6200
|
-
bodyRotateX: [x +
|
|
6200
|
+
bodyRotateX: [x + D],
|
|
6201
6201
|
bodyRotateY: [I + p],
|
|
6202
|
-
eyesRotateX: [-3 *
|
|
6202
|
+
eyesRotateX: [-3 * D + 0.1],
|
|
6203
6203
|
eyesRotateY: [-5 * p],
|
|
6204
6204
|
browInnerUp: [[0, 0.7]],
|
|
6205
6205
|
mouthLeft: [[0, 0.7]],
|
|
@@ -6219,11 +6219,11 @@ class Ee {
|
|
|
6219
6219
|
*/
|
|
6220
6220
|
touchAt(t, e) {
|
|
6221
6221
|
if (!this.camera) return;
|
|
6222
|
-
const
|
|
6223
|
-
(t -
|
|
6224
|
-
-((e -
|
|
6222
|
+
const n = this.nodeAvatar.getBoundingClientRect(), i = new f.Vector2(
|
|
6223
|
+
(t - n.left) / n.width * 2 - 1,
|
|
6224
|
+
-((e - n.top) / n.height) * 2 + 1
|
|
6225
6225
|
), s = new f.Raycaster();
|
|
6226
|
-
s.setFromCamera(
|
|
6226
|
+
s.setFromCamera(i, this.camera);
|
|
6227
6227
|
const o = s.intersectObject(this.armature);
|
|
6228
6228
|
if (o.length > 0) {
|
|
6229
6229
|
const l = o[0].point, u = new f.Vector3(), a = new f.Vector3();
|
|
@@ -6287,20 +6287,20 @@ class Ee {
|
|
|
6287
6287
|
this.gaussianRandom(-0.8, -0.2),
|
|
6288
6288
|
this.gaussianRandom(0, 0.5)
|
|
6289
6289
|
), !0);
|
|
6290
|
-
const
|
|
6291
|
-
|
|
6290
|
+
const n = [], i = [];
|
|
6291
|
+
n.push(100 + Math.round(Math.random() * 500)), i.push({ duration: 1e3, props: {
|
|
6292
6292
|
"LeftHand.quaternion": new f.Quaternion().setFromEuler(new f.Euler(0, -1 - Math.random(), 0)),
|
|
6293
6293
|
"RightHand.quaternion": new f.Quaternion().setFromEuler(new f.Euler(0, 1 + Math.random(), 0))
|
|
6294
6294
|
} }), ["LeftArm", "LeftForeArm", "RightArm", "RightForeArm"].forEach((o) => {
|
|
6295
|
-
|
|
6296
|
-
}),
|
|
6297
|
-
|
|
6295
|
+
i[0].props[o + ".quaternion"] = this.ikMesh.getObjectByName(o).quaternion.clone();
|
|
6296
|
+
}), n.push(1e3 + Math.round(Math.random() * 500)), i.push({ duration: 2e3, props: {} }), ["LeftArm", "LeftForeArm", "RightArm", "RightForeArm", "LeftHand", "RightHand"].forEach((o) => {
|
|
6297
|
+
i[1].props[o + ".quaternion"] = null;
|
|
6298
6298
|
});
|
|
6299
6299
|
const s = this.animFactory({
|
|
6300
6300
|
name: "talkinghands",
|
|
6301
6301
|
delay: t,
|
|
6302
|
-
dt:
|
|
6303
|
-
vs: { moveto:
|
|
6302
|
+
dt: n,
|
|
6303
|
+
vs: { moveto: i }
|
|
6304
6304
|
});
|
|
6305
6305
|
this.animQueue.push(s);
|
|
6306
6306
|
}
|
|
@@ -6350,8 +6350,8 @@ class Ee {
|
|
|
6350
6350
|
* @param {Object} [opt={}] Options
|
|
6351
6351
|
* @param {function} [onchange=null] Callback function for start
|
|
6352
6352
|
*/
|
|
6353
|
-
startListening(t, e = {},
|
|
6354
|
-
this.listeningAnalyzer = t, this.listeningAnalyzer.fftSize = 256, this.listeningAnalyzer.smoothingTimeConstant = 0.1, this.listeningAnalyzer.minDecibels = -70, this.listeningAnalyzer.maxDecibels = -10, this.listeningOnchange =
|
|
6353
|
+
startListening(t, e = {}, n = null) {
|
|
6354
|
+
this.listeningAnalyzer = t, this.listeningAnalyzer.fftSize = 256, this.listeningAnalyzer.smoothingTimeConstant = 0.1, this.listeningAnalyzer.minDecibels = -70, this.listeningAnalyzer.maxDecibels = -10, this.listeningOnchange = n && typeof n == "function" ? n : null, this.listeningSilenceThresholdLevel = e?.hasOwnProperty("listeningSilenceThresholdLevel") ? e.listeningSilenceThresholdLevel : this.opt.listeningSilenceThresholdLevel, this.listeningSilenceThresholdMs = e?.hasOwnProperty("listeningSilenceThresholdMs") ? e.listeningSilenceThresholdMs : this.opt.listeningSilenceThresholdMs, this.listeningSilenceDurationMax = e?.hasOwnProperty("listeningSilenceDurationMax") ? e.listeningSilenceDurationMax : this.opt.listeningSilenceDurationMax, this.listeningActiveThresholdLevel = e?.hasOwnProperty("listeningActiveThresholdLevel") ? e.listeningActiveThresholdLevel : this.opt.listeningActiveThresholdLevel, this.listeningActiveThresholdMs = e?.hasOwnProperty("listeningActiveThresholdMs") ? e.listeningActiveThresholdMs : this.opt.listeningActiveThresholdMs, this.listeningActiveDurationMax = e?.hasOwnProperty("listeningActiveDurationMax") ? e.listeningActiveDurationMax : this.opt.listeningActiveDurationMax, this.listeningActive = !1, this.listeningVolume = 0, this.listeningTimer = 0, this.listeningTimerTotal = 0, this.isListening = !0;
|
|
6355
6355
|
}
|
|
6356
6356
|
/**
|
|
6357
6357
|
* Stop animation cycle.
|
|
@@ -6367,16 +6367,16 @@ class Ee {
|
|
|
6367
6367
|
* @param {number} [ndx=0] Index of the clip
|
|
6368
6368
|
* @param {number} [scale=0.01] Position scale factor
|
|
6369
6369
|
*/
|
|
6370
|
-
async playAnimation(t, e = null,
|
|
6370
|
+
async playAnimation(t, e = null, n = 10, i = 0, s = 0.01, o = !1) {
|
|
6371
6371
|
if (!this.armature) return;
|
|
6372
6372
|
this.positionWasLocked = !o, o ? console.log("Position locking disabled for FBX animation:", t) : (this.lockAvatarPosition(), console.log("Position locked immediately before FBX animation:", t));
|
|
6373
|
-
let l = this.animClips.find((u) => u.url === t + "-" +
|
|
6373
|
+
let l = this.animClips.find((u) => u.url === t + "-" + i);
|
|
6374
6374
|
if (l) {
|
|
6375
6375
|
let u = this.animQueue.find((r) => r.template.name === "pose");
|
|
6376
6376
|
u && (u.ts[0] = 1 / 0), Object.entries(l.pose.props).forEach((r) => {
|
|
6377
6377
|
this.poseBase.props[r[0]] = r[1].clone(), this.poseTarget.props[r[0]] = r[1].clone(), this.poseTarget.props[r[0]].t = 0, this.poseTarget.props[r[0]].d = 1e3;
|
|
6378
6378
|
}), 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 });
|
|
6379
|
-
const a = Math.ceil(
|
|
6379
|
+
const a = Math.ceil(n / l.clip.duration), h = this.mixer.clipAction(l.clip);
|
|
6380
6380
|
h.setLoop(f.LoopRepeat, a), h.clampWhenFinished = !0, this.currentFBXAction = h;
|
|
6381
6381
|
try {
|
|
6382
6382
|
h.fadeIn(0.5).play(), console.log("FBX animation started successfully:", t);
|
|
@@ -6403,7 +6403,7 @@ class Ee {
|
|
|
6403
6403
|
} catch (c) {
|
|
6404
6404
|
console.warn(`Could not verify file existence for ${t}, attempting to load anyway:`, c);
|
|
6405
6405
|
}
|
|
6406
|
-
const h = new
|
|
6406
|
+
const h = new ze();
|
|
6407
6407
|
let r;
|
|
6408
6408
|
try {
|
|
6409
6409
|
r = await h.loadAsync(t, e);
|
|
@@ -6426,8 +6426,8 @@ class Ee {
|
|
|
6426
6426
|
}
|
|
6427
6427
|
return;
|
|
6428
6428
|
}
|
|
6429
|
-
if (r && r.animations && r.animations[
|
|
6430
|
-
let c = r.animations[
|
|
6429
|
+
if (r && r.animations && r.animations[i]) {
|
|
6430
|
+
let c = r.animations[i];
|
|
6431
6431
|
const d = {};
|
|
6432
6432
|
c.tracks.forEach((y) => {
|
|
6433
6433
|
y.name = y.name.replaceAll("mixamorig", "");
|
|
@@ -6440,13 +6440,13 @@ class Ee {
|
|
|
6440
6440
|
});
|
|
6441
6441
|
const g = { props: d };
|
|
6442
6442
|
d["Hips.position"] && (d["Hips.position"].y < 0.5 ? g.lying = !0 : g.standing = !0), this.animClips.push({
|
|
6443
|
-
url: t + "-" +
|
|
6443
|
+
url: t + "-" + i,
|
|
6444
6444
|
clip: c,
|
|
6445
6445
|
pose: g
|
|
6446
|
-
}), this.playAnimation(t, e,
|
|
6446
|
+
}), this.playAnimation(t, e, n, i, s);
|
|
6447
6447
|
} else {
|
|
6448
|
-
const c = "Animation " + t + " (ndx=" +
|
|
6449
|
-
console.error(c), r && r.animations ? console.error(`FBX file loaded but has ${r.animations.length} animation(s), requested index ${
|
|
6448
|
+
const c = "Animation " + t + " (ndx=" + i + ") not found";
|
|
6449
|
+
console.error(c), r && r.animations ? console.error(`FBX file loaded but has ${r.animations.length} animation(s), requested index ${i}`) : console.error(r ? "FBX file loaded but contains no animations" : "FBX file failed to load or is invalid");
|
|
6450
6450
|
}
|
|
6451
6451
|
}
|
|
6452
6452
|
}
|
|
@@ -6455,8 +6455,8 @@ class Ee {
|
|
|
6455
6455
|
*/
|
|
6456
6456
|
stopAnimation() {
|
|
6457
6457
|
if (this.currentFBXAction && (this.currentFBXAction.stop(), this.currentFBXAction = null, console.log("FBX animation action stopped, mixer preserved for lip-sync")), this.mixer && this.mixer._actions.length === 0 && (this.mixer = null, console.log("Mixer destroyed as no actions remain")), this.positionWasLocked ? (this.unlockAvatarPosition(), console.log("Position unlocked after FBX animation stopped")) : console.log("Position was not locked, no unlock needed"), this.gesture)
|
|
6458
|
-
for (let [e,
|
|
6459
|
-
|
|
6458
|
+
for (let [e, n] of Object.entries(this.gesture))
|
|
6459
|
+
n.t = this.animClock, n.d = 1e3, this.poseTarget.props.hasOwnProperty(e) && (this.poseTarget.props[e].copy(n), this.poseTarget.props[e].t = this.animClock, this.poseTarget.props[e].d = 1e3);
|
|
6460
6460
|
let t = this.animQueue.find((e) => e.template.name === "pose");
|
|
6461
6461
|
t && (t.ts[0] = this.animClock), this.setPoseFromTemplate(null);
|
|
6462
6462
|
}
|
|
@@ -6468,21 +6468,21 @@ class Ee {
|
|
|
6468
6468
|
* @param {number} [ndx=0] Index of the clip
|
|
6469
6469
|
* @param {number} [scale=0.01] Position scale factor
|
|
6470
6470
|
*/
|
|
6471
|
-
async playPose(t, e = null,
|
|
6471
|
+
async playPose(t, e = null, n = 5, i = 0, s = 0.01) {
|
|
6472
6472
|
if (!this.armature) return;
|
|
6473
6473
|
let o = this.poseTemplates[t];
|
|
6474
6474
|
if (!o) {
|
|
6475
|
-
const l = this.animPoses.find((u) => u.url === t + "-" +
|
|
6475
|
+
const l = this.animPoses.find((u) => u.url === t + "-" + i);
|
|
6476
6476
|
l && (o = l.pose);
|
|
6477
6477
|
}
|
|
6478
6478
|
if (o) {
|
|
6479
6479
|
this.poseName = t, this.mixer = null;
|
|
6480
6480
|
let l = this.animQueue.find((u) => u.template.name === "pose");
|
|
6481
|
-
l && (l.ts[0] = this.animClock +
|
|
6481
|
+
l && (l.ts[0] = this.animClock + n * 1e3 + 2e3), this.setPoseFromTemplate(o);
|
|
6482
6482
|
} else {
|
|
6483
|
-
let u = await new
|
|
6484
|
-
if (u && u.animations && u.animations[
|
|
6485
|
-
let a = u.animations[
|
|
6483
|
+
let u = await new ze().loadAsync(t, e);
|
|
6484
|
+
if (u && u.animations && u.animations[i]) {
|
|
6485
|
+
let a = u.animations[i];
|
|
6486
6486
|
const h = {};
|
|
6487
6487
|
a.tracks.forEach((c) => {
|
|
6488
6488
|
c.name = c.name.replaceAll("mixamorig", "");
|
|
@@ -6491,11 +6491,11 @@ class Ee {
|
|
|
6491
6491
|
});
|
|
6492
6492
|
const r = { props: h };
|
|
6493
6493
|
h["Hips.position"] && (h["Hips.position"].y < 0.5 ? r.lying = !0 : r.standing = !0), this.animPoses.push({
|
|
6494
|
-
url: t + "-" +
|
|
6494
|
+
url: t + "-" + i,
|
|
6495
6495
|
pose: r
|
|
6496
|
-
}), this.playPose(t, e,
|
|
6496
|
+
}), this.playPose(t, e, n, i, s);
|
|
6497
6497
|
} else {
|
|
6498
|
-
const a = "Pose " + t + " (ndx=" +
|
|
6498
|
+
const a = "Pose " + t + " (ndx=" + i + ") not found";
|
|
6499
6499
|
console.error(a);
|
|
6500
6500
|
}
|
|
6501
6501
|
}
|
|
@@ -6514,16 +6514,16 @@ class Ee {
|
|
|
6514
6514
|
* @param {boolean} [mirror=false] Mirror gesture
|
|
6515
6515
|
* @param {number} [ms=1000] Transition time in milliseconds
|
|
6516
6516
|
*/
|
|
6517
|
-
playGesture(t, e = 3,
|
|
6517
|
+
playGesture(t, e = 3, n = !1, i = 1e3) {
|
|
6518
6518
|
if (!this.armature) return;
|
|
6519
6519
|
let s = this.gestureTemplates[t];
|
|
6520
6520
|
if (s) {
|
|
6521
6521
|
this.gestureTimeout && (clearTimeout(this.gestureTimeout), this.gestureTimeout = null);
|
|
6522
6522
|
let l = this.animQueue.findIndex((u) => u.template.name === "talkinghands");
|
|
6523
|
-
l !== -1 && (this.animQueue[l].ts = this.animQueue[l].ts.map((u) => 0)), this.gesture = this.propsToThreeObjects(s),
|
|
6523
|
+
l !== -1 && (this.animQueue[l].ts = this.animQueue[l].ts.map((u) => 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));
|
|
6524
6524
|
for (let [u, a] of Object.entries(this.gesture))
|
|
6525
|
-
a.t = this.animClock, a.d =
|
|
6526
|
-
e && Number.isFinite(e) && (this.gestureTimeout = setTimeout(this.stopGesture.bind(this,
|
|
6525
|
+
a.t = this.animClock, a.d = i, this.poseTarget.props.hasOwnProperty(u) && (this.poseTarget.props[u].copy(a), this.poseTarget.props[u].t = this.animClock, this.poseTarget.props[u].d = i);
|
|
6526
|
+
e && Number.isFinite(e) && (this.gestureTimeout = setTimeout(this.stopGesture.bind(this, i), 1e3 * e));
|
|
6527
6527
|
}
|
|
6528
6528
|
let o = this.animEmojis[t];
|
|
6529
6529
|
if (o && (o && o.link && (o = this.animEmojis[o.link]), o)) {
|
|
@@ -6550,12 +6550,12 @@ class Ee {
|
|
|
6550
6550
|
*/
|
|
6551
6551
|
stopGesture(t = 1e3) {
|
|
6552
6552
|
if (this.gestureTimeout && (clearTimeout(this.gestureTimeout), this.gestureTimeout = null), this.gesture) {
|
|
6553
|
-
const
|
|
6553
|
+
const n = Object.entries(this.gesture);
|
|
6554
6554
|
this.gesture = null;
|
|
6555
|
-
for (const [
|
|
6556
|
-
this.poseTarget.props.hasOwnProperty(
|
|
6555
|
+
for (const [i, s] of n)
|
|
6556
|
+
this.poseTarget.props.hasOwnProperty(i) && (this.poseTarget.props[i].copy(this.getPoseTemplateProp(i)), this.poseTarget.props[i].t = this.animClock, this.poseTarget.props[i].d = t);
|
|
6557
6557
|
}
|
|
6558
|
-
let e = this.animQueue.findIndex((
|
|
6558
|
+
let e = this.animQueue.findIndex((n) => n.gesture);
|
|
6559
6559
|
e !== -1 && this.animQueue.splice(e, 1);
|
|
6560
6560
|
}
|
|
6561
6561
|
/**
|
|
@@ -6567,9 +6567,9 @@ class Ee {
|
|
|
6567
6567
|
* @param {Boolean} [relative=false] If true, target is relative to root
|
|
6568
6568
|
* @param {numeric} [d=null] If set, apply in d milliseconds
|
|
6569
6569
|
*/
|
|
6570
|
-
ikSolve(t, e = null,
|
|
6570
|
+
ikSolve(t, e = null, n = !1, i = null) {
|
|
6571
6571
|
const s = new f.Vector3(), o = new f.Vector3(), l = new f.Vector3(), u = new f.Vector3(), a = new f.Quaternion(), h = new f.Vector3(), r = new f.Vector3(), c = new f.Vector3(), d = this.ikMesh.getObjectByName(t.root);
|
|
6572
|
-
d.position.setFromMatrixPosition(this.armature.getObjectByName(t.root).matrixWorld), d.quaternion.setFromRotationMatrix(this.armature.getObjectByName(t.root).matrixWorld), e &&
|
|
6572
|
+
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);
|
|
6573
6573
|
const g = this.ikMesh.getObjectByName(t.effector), y = t.links;
|
|
6574
6574
|
y.forEach((I) => {
|
|
6575
6575
|
I.bone = this.ikMesh.getObjectByName(I.link), I.bone.quaternion.copy(this.getPoseTemplateProp(I.link + ".quaternion"));
|
|
@@ -6577,12 +6577,12 @@ class Ee {
|
|
|
6577
6577
|
const x = t.iterations || 10;
|
|
6578
6578
|
if (e)
|
|
6579
6579
|
for (let I = 0; I < x; I++) {
|
|
6580
|
-
let
|
|
6580
|
+
let D = !1;
|
|
6581
6581
|
for (let p = 0, H = y.length; p < H; p++) {
|
|
6582
6582
|
const z = y[p].bone;
|
|
6583
6583
|
z.matrixWorld.decompose(u, a, h), a.invert(), o.setFromMatrixPosition(g.matrixWorld), l.subVectors(o, u), l.applyQuaternion(a), l.normalize(), s.subVectors(e, u), s.applyQuaternion(a), s.normalize();
|
|
6584
|
-
let
|
|
6585
|
-
|
|
6584
|
+
let R = s.dot(l);
|
|
6585
|
+
R > 1 ? R = 1 : R < -1 && (R = -1), R = Math.acos(R), !(R < 1e-5) && (y[p].minAngle !== void 0 && R < y[p].minAngle && (R = y[p].minAngle), y[p].maxAngle !== void 0 && R > y[p].maxAngle && (R = y[p].maxAngle), r.crossVectors(l, s), r.normalize(), W.setFromAxisAngle(r, R), z.quaternion.multiply(W), z.rotation.setFromVector3(c.setFromEuler(z.rotation).clamp(new f.Vector3(
|
|
6586
6586
|
y[p].minx !== void 0 ? y[p].minx : -1 / 0,
|
|
6587
6587
|
y[p].miny !== void 0 ? y[p].miny : -1 / 0,
|
|
6588
6588
|
y[p].minz !== void 0 ? y[p].minz : -1 / 0
|
|
@@ -6590,12 +6590,12 @@ class Ee {
|
|
|
6590
6590
|
y[p].maxx !== void 0 ? y[p].maxx : 1 / 0,
|
|
6591
6591
|
y[p].maxy !== void 0 ? y[p].maxy : 1 / 0,
|
|
6592
6592
|
y[p].maxz !== void 0 ? y[p].maxz : 1 / 0
|
|
6593
|
-
))), z.updateMatrixWorld(!0),
|
|
6593
|
+
))), z.updateMatrixWorld(!0), D = !0);
|
|
6594
6594
|
}
|
|
6595
|
-
if (!
|
|
6595
|
+
if (!D) break;
|
|
6596
6596
|
}
|
|
6597
|
-
|
|
6598
|
-
this.poseTarget.props[I.link + ".quaternion"].copy(I.bone.quaternion), this.poseTarget.props[I.link + ".quaternion"].t = this.animClock, this.poseTarget.props[I.link + ".quaternion"].d =
|
|
6597
|
+
i && y.forEach((I) => {
|
|
6598
|
+
this.poseTarget.props[I.link + ".quaternion"].copy(I.bone.quaternion), this.poseTarget.props[I.link + ".quaternion"].t = this.animClock, this.poseTarget.props[I.link + ".quaternion"].d = i;
|
|
6599
6599
|
});
|
|
6600
6600
|
}
|
|
6601
6601
|
/**
|
|
@@ -6605,7 +6605,7 @@ class Ee {
|
|
|
6605
6605
|
this.isRunning = !1, this.stop(), this.stopSpeaking(), this.streamStop(), this.isAvatarOnly ? this.armature && (this.armature.parent && this.armature.parent.remove(this.armature), this.clearThree(this.armature)) : (this.clearThree(this.scene), this.resizeobserver.disconnect(), this.renderer && (this.renderer.dispose(), this.renderer.domElement && this.renderer.domElement.parentNode && this.renderer.domElement.parentNode.removeChild(this.renderer.domElement), this.renderer = null)), this.clearThree(this.ikMesh), this.dynamicbones.dispose();
|
|
6606
6606
|
}
|
|
6607
6607
|
}
|
|
6608
|
-
const
|
|
6608
|
+
const ye = {
|
|
6609
6609
|
apiKey: "sk_ace57ef3ef65a92b9d3bee2a00183b78ca790bc3e10964f2",
|
|
6610
6610
|
// Replace with your actual API key (should start with sk_)
|
|
6611
6611
|
endpoint: "https://api.elevenlabs.io/v1/text-to-speech",
|
|
@@ -6625,7 +6625,7 @@ const me = {
|
|
|
6625
6625
|
josh: "VR6AewLTigWG4xSOukaG"
|
|
6626
6626
|
// Male, American
|
|
6627
6627
|
}
|
|
6628
|
-
},
|
|
6628
|
+
}, Me = {
|
|
6629
6629
|
defaultVoice: "aura-2-thalia-en",
|
|
6630
6630
|
// Thalia (Female, English)
|
|
6631
6631
|
voices: {
|
|
@@ -6648,27 +6648,27 @@ const me = {
|
|
|
6648
6648
|
function Ae() {
|
|
6649
6649
|
return {
|
|
6650
6650
|
service: "elevenlabs",
|
|
6651
|
-
endpoint:
|
|
6652
|
-
apiKey:
|
|
6653
|
-
defaultVoice:
|
|
6654
|
-
voices:
|
|
6651
|
+
endpoint: ye.endpoint,
|
|
6652
|
+
apiKey: ye.apiKey,
|
|
6653
|
+
defaultVoice: ye.defaultVoice,
|
|
6654
|
+
voices: ye.voices
|
|
6655
6655
|
};
|
|
6656
6656
|
}
|
|
6657
|
-
function
|
|
6657
|
+
function Rt() {
|
|
6658
6658
|
const O = Ae(), t = [];
|
|
6659
|
-
return Object.entries(O.voices).forEach(([e,
|
|
6659
|
+
return Object.entries(O.voices).forEach(([e, n]) => {
|
|
6660
6660
|
t.push({
|
|
6661
|
-
value:
|
|
6661
|
+
value: n,
|
|
6662
6662
|
label: `${e.charAt(0).toUpperCase() + e.slice(1)} (${O.service})`
|
|
6663
6663
|
});
|
|
6664
6664
|
}), t;
|
|
6665
6665
|
}
|
|
6666
|
-
const
|
|
6666
|
+
const Pe = Ie(({
|
|
6667
6667
|
avatarUrl: O = "/avatars/brunette.glb",
|
|
6668
6668
|
avatarBody: t = "F",
|
|
6669
6669
|
mood: e = "neutral",
|
|
6670
|
-
ttsLang:
|
|
6671
|
-
ttsService:
|
|
6670
|
+
ttsLang: n = "en",
|
|
6671
|
+
ttsService: i = null,
|
|
6672
6672
|
ttsVoice: s = null,
|
|
6673
6673
|
ttsApiKey: o = null,
|
|
6674
6674
|
bodyMovement: l = "idle",
|
|
@@ -6685,282 +6685,302 @@ const Fe = Ie(({
|
|
|
6685
6685
|
style: y = {},
|
|
6686
6686
|
animations: x = {}
|
|
6687
6687
|
}, I) => {
|
|
6688
|
-
const
|
|
6689
|
-
|
|
6688
|
+
const D = G(null), p = G(null), H = G(a), z = G(null), R = G(null), M = G(!1), P = G({ remainingText: null, originalText: null, options: null }), [ee, re] = de(!0), [S, N] = de(null), [Z, X] = de(!1), [j, K] = de(!1);
|
|
6689
|
+
me(() => {
|
|
6690
|
+
M.current = j;
|
|
6691
|
+
}, [j]), me(() => {
|
|
6690
6692
|
H.current = a;
|
|
6691
6693
|
}, [a]);
|
|
6692
|
-
const
|
|
6693
|
-
let
|
|
6694
|
-
|
|
6694
|
+
const te = Ae(), ce = i || te.service;
|
|
6695
|
+
let oe;
|
|
6696
|
+
ce === "browser" ? oe = {
|
|
6695
6697
|
service: "browser",
|
|
6696
6698
|
endpoint: "",
|
|
6697
6699
|
apiKey: null,
|
|
6698
6700
|
defaultVoice: "Google US English"
|
|
6699
|
-
} :
|
|
6701
|
+
} : ce === "elevenlabs" ? oe = {
|
|
6700
6702
|
service: "elevenlabs",
|
|
6701
6703
|
endpoint: "https://api.elevenlabs.io/v1/text-to-speech",
|
|
6702
|
-
apiKey: o ||
|
|
6703
|
-
defaultVoice: s ||
|
|
6704
|
-
voices:
|
|
6705
|
-
} :
|
|
6704
|
+
apiKey: o || te.apiKey,
|
|
6705
|
+
defaultVoice: s || te.defaultVoice || ye.defaultVoice,
|
|
6706
|
+
voices: te.voices || ye.voices
|
|
6707
|
+
} : ce === "deepgram" ? oe = {
|
|
6706
6708
|
service: "deepgram",
|
|
6707
6709
|
endpoint: "https://api.deepgram.com/v1/speak",
|
|
6708
|
-
apiKey: o ||
|
|
6709
|
-
defaultVoice: s ||
|
|
6710
|
-
voices:
|
|
6711
|
-
} :
|
|
6712
|
-
...
|
|
6710
|
+
apiKey: o || te.apiKey,
|
|
6711
|
+
defaultVoice: s || te.defaultVoice || Me.defaultVoice,
|
|
6712
|
+
voices: te.voices || Me.voices
|
|
6713
|
+
} : oe = {
|
|
6714
|
+
...te,
|
|
6713
6715
|
// Override API key if provided via props
|
|
6714
|
-
apiKey: o !== null ? o :
|
|
6716
|
+
apiKey: o !== null ? o : te.apiKey
|
|
6715
6717
|
};
|
|
6716
|
-
const
|
|
6718
|
+
const pe = {
|
|
6717
6719
|
url: O,
|
|
6718
6720
|
body: t,
|
|
6719
6721
|
avatarMood: e,
|
|
6720
|
-
ttsLang:
|
|
6721
|
-
ttsVoice: s ||
|
|
6722
|
+
ttsLang: ce === "browser" ? "en-US" : n,
|
|
6723
|
+
ttsVoice: s || oe.defaultVoice,
|
|
6722
6724
|
lipsyncLang: "en",
|
|
6723
6725
|
showFullAvatar: a,
|
|
6724
6726
|
bodyMovement: l,
|
|
6725
6727
|
movementIntensity: u
|
|
6726
|
-
},
|
|
6727
|
-
ttsEndpoint:
|
|
6728
|
-
ttsApikey:
|
|
6729
|
-
ttsService:
|
|
6728
|
+
}, J = {
|
|
6729
|
+
ttsEndpoint: oe.endpoint,
|
|
6730
|
+
ttsApikey: oe.apiKey,
|
|
6731
|
+
ttsService: ce,
|
|
6730
6732
|
lipsyncModules: ["en"],
|
|
6731
6733
|
cameraView: h
|
|
6732
|
-
},
|
|
6733
|
-
if (!(!
|
|
6734
|
+
}, b = T(async () => {
|
|
6735
|
+
if (!(!D.current || p.current))
|
|
6734
6736
|
try {
|
|
6735
|
-
if (
|
|
6736
|
-
if (
|
|
6737
|
-
const
|
|
6738
|
-
c(
|
|
6737
|
+
if (re(!0), N(null), p.current = new Fe(D.current, J), 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(pe, (U) => {
|
|
6738
|
+
if (U.lengthComputable) {
|
|
6739
|
+
const E = Math.min(100, Math.round(U.loaded / U.total * 100));
|
|
6740
|
+
c(E);
|
|
6739
6741
|
}
|
|
6740
|
-
}), await new Promise((
|
|
6741
|
-
const
|
|
6742
|
-
p.current.lipsync && Object.keys(p.current.lipsync).length > 0 ?
|
|
6742
|
+
}), await new Promise((U) => {
|
|
6743
|
+
const E = () => {
|
|
6744
|
+
p.current.lipsync && Object.keys(p.current.lipsync).length > 0 ? U() : setTimeout(E, 100);
|
|
6743
6745
|
};
|
|
6744
|
-
|
|
6746
|
+
E();
|
|
6745
6747
|
}), p.current && p.current.setShowFullAvatar)
|
|
6746
6748
|
try {
|
|
6747
6749
|
p.current.setShowFullAvatar(a);
|
|
6748
|
-
} catch (
|
|
6749
|
-
console.warn("Error setting full body mode on initialization:",
|
|
6750
|
+
} catch (U) {
|
|
6751
|
+
console.warn("Error setting full body mode on initialization:", U);
|
|
6750
6752
|
}
|
|
6751
|
-
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()),
|
|
6752
|
-
const
|
|
6753
|
+
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()), re(!1), X(!0), r(p.current);
|
|
6754
|
+
const B = () => {
|
|
6753
6755
|
document.visibilityState === "visible" ? p.current?.start() : p.current?.stop();
|
|
6754
6756
|
};
|
|
6755
|
-
return document.addEventListener("visibilitychange",
|
|
6756
|
-
document.removeEventListener("visibilitychange",
|
|
6757
|
+
return document.addEventListener("visibilitychange", B), () => {
|
|
6758
|
+
document.removeEventListener("visibilitychange", B);
|
|
6757
6759
|
};
|
|
6758
|
-
} catch (
|
|
6759
|
-
console.error("Error initializing TalkingHead:",
|
|
6760
|
+
} catch (L) {
|
|
6761
|
+
console.error("Error initializing TalkingHead:", L), N(L.message || "Failed to initialize avatar"), re(!1), d(L);
|
|
6760
6762
|
}
|
|
6761
|
-
}, [O, t, e,
|
|
6762
|
-
|
|
6763
|
+
}, [O, t, e, n, i, s, o, a, l, u, h]);
|
|
6764
|
+
me(() => (b(), () => {
|
|
6763
6765
|
p.current && (p.current.stop(), p.current.dispose(), p.current = null);
|
|
6764
|
-
}), [
|
|
6765
|
-
if (!
|
|
6766
|
-
const
|
|
6767
|
-
for (const
|
|
6766
|
+
}), [b]), me(() => {
|
|
6767
|
+
if (!D.current || !p.current) return;
|
|
6768
|
+
const L = new ResizeObserver((U) => {
|
|
6769
|
+
for (const E of U)
|
|
6768
6770
|
p.current && p.current.onResize && p.current.onResize();
|
|
6769
6771
|
});
|
|
6770
|
-
|
|
6771
|
-
const
|
|
6772
|
+
L.observe(D.current);
|
|
6773
|
+
const B = () => {
|
|
6772
6774
|
p.current && p.current.onResize && p.current.onResize();
|
|
6773
6775
|
};
|
|
6774
|
-
return window.addEventListener("resize",
|
|
6775
|
-
|
|
6776
|
+
return window.addEventListener("resize", B), () => {
|
|
6777
|
+
L.disconnect(), window.removeEventListener("resize", B);
|
|
6776
6778
|
};
|
|
6777
|
-
}, [
|
|
6778
|
-
const
|
|
6779
|
+
}, [Z]);
|
|
6780
|
+
const v = T(async () => {
|
|
6779
6781
|
if (p.current && p.current.audioCtx)
|
|
6780
6782
|
try {
|
|
6781
6783
|
(p.current.audioCtx.state === "suspended" || p.current.audioCtx.state === "interrupted") && (await p.current.audioCtx.resume(), console.log("Audio context resumed"));
|
|
6782
|
-
} catch (
|
|
6783
|
-
console.warn("Failed to resume audio context:",
|
|
6784
|
+
} catch (L) {
|
|
6785
|
+
console.warn("Failed to resume audio context:", L);
|
|
6784
6786
|
}
|
|
6785
|
-
}, []),
|
|
6786
|
-
if (p.current &&
|
|
6787
|
+
}, []), w = T(async (L, B = {}) => {
|
|
6788
|
+
if (p.current && Z)
|
|
6787
6789
|
try {
|
|
6788
|
-
|
|
6789
|
-
const
|
|
6790
|
-
...
|
|
6791
|
-
lipsyncLang:
|
|
6790
|
+
R.current && (clearInterval(R.current), R.current = null), z.current = { text: L, options: B }, P.current = { remainingText: null, originalText: null, options: null }, K(!1), M.current = !1, await v();
|
|
6791
|
+
const U = {
|
|
6792
|
+
...B,
|
|
6793
|
+
lipsyncLang: B.lipsyncLang || pe.lipsyncLang || "en"
|
|
6792
6794
|
};
|
|
6793
|
-
if (
|
|
6794
|
-
const
|
|
6795
|
-
let
|
|
6796
|
-
const
|
|
6797
|
-
let
|
|
6798
|
-
|
|
6799
|
-
if (
|
|
6795
|
+
if (B.onSpeechEnd && p.current) {
|
|
6796
|
+
const E = p.current;
|
|
6797
|
+
let Y = null, ge = 0;
|
|
6798
|
+
const ke = 1200;
|
|
6799
|
+
let xe = !1;
|
|
6800
|
+
Y = setInterval(() => {
|
|
6801
|
+
if (ge++, M.current)
|
|
6800
6802
|
return;
|
|
6801
|
-
if (
|
|
6802
|
-
if (
|
|
6803
|
-
|
|
6803
|
+
if (ge > ke) {
|
|
6804
|
+
if (Y && (clearInterval(Y), Y = null, R.current = null), !xe && !M.current) {
|
|
6805
|
+
xe = !0;
|
|
6804
6806
|
try {
|
|
6805
|
-
|
|
6806
|
-
} catch (
|
|
6807
|
-
console.error("Error in onSpeechEnd callback (timeout):",
|
|
6807
|
+
B.onSpeechEnd();
|
|
6808
|
+
} catch (we) {
|
|
6809
|
+
console.error("Error in onSpeechEnd callback (timeout):", we);
|
|
6808
6810
|
}
|
|
6809
6811
|
}
|
|
6810
6812
|
return;
|
|
6811
6813
|
}
|
|
6812
|
-
const
|
|
6813
|
-
|
|
6814
|
-
if (
|
|
6815
|
-
|
|
6814
|
+
const Oe = !E.speechQueue || E.speechQueue.length === 0, Ne = !E.audioPlaylist || E.audioPlaylist.length === 0;
|
|
6815
|
+
E && E.isSpeaking === !1 && Oe && Ne && E.isAudioPlaying === !1 && !xe && !M.current && setTimeout(() => {
|
|
6816
|
+
if (E && !M.current && E.isSpeaking === !1 && (!E.speechQueue || E.speechQueue.length === 0) && (!E.audioPlaylist || E.audioPlaylist.length === 0) && E.isAudioPlaying === !1 && !xe && !M.current) {
|
|
6817
|
+
xe = !0, Y && (clearInterval(Y), Y = null, R.current = null);
|
|
6816
6818
|
try {
|
|
6817
|
-
|
|
6818
|
-
} catch (
|
|
6819
|
-
console.error("Error in onSpeechEnd callback:",
|
|
6819
|
+
B.onSpeechEnd();
|
|
6820
|
+
} catch (Ue) {
|
|
6821
|
+
console.error("Error in onSpeechEnd callback:", Ue);
|
|
6820
6822
|
}
|
|
6821
6823
|
}
|
|
6822
6824
|
}, 100);
|
|
6823
|
-
}, 100),
|
|
6825
|
+
}, 100), R.current = Y;
|
|
6824
6826
|
}
|
|
6825
|
-
p.current.lipsync && Object.keys(p.current.lipsync).length > 0 ? (p.current.setSlowdownRate && p.current.setSlowdownRate(1.05), p.current.speakText(
|
|
6826
|
-
await
|
|
6827
|
+
p.current.lipsync && Object.keys(p.current.lipsync).length > 0 ? (p.current.setSlowdownRate && p.current.setSlowdownRate(1.05), p.current.speakText(L, U)) : setTimeout(async () => {
|
|
6828
|
+
await v(), p.current && p.current.lipsync && (p.current.setSlowdownRate && p.current.setSlowdownRate(1.05), p.current.speakText(L, U));
|
|
6827
6829
|
}, 100);
|
|
6828
|
-
} catch (
|
|
6829
|
-
console.error("Error speaking text:",
|
|
6830
|
+
} catch (U) {
|
|
6831
|
+
console.error("Error speaking text:", U), N(U.message || "Failed to speak text");
|
|
6830
6832
|
}
|
|
6831
|
-
}, [
|
|
6832
|
-
p.current && (p.current.stopSpeaking(), p.current.setSlowdownRate && p.current.setSlowdownRate(1), z.current = null,
|
|
6833
|
-
}, []),
|
|
6833
|
+
}, [Z, v, pe.lipsyncLang]), C = T(() => {
|
|
6834
|
+
p.current && (p.current.stopSpeaking(), p.current.setSlowdownRate && p.current.setSlowdownRate(1), z.current = null, K(!1));
|
|
6835
|
+
}, []), V = T(() => {
|
|
6834
6836
|
if (p.current && p.current.pauseSpeaking) {
|
|
6835
|
-
const
|
|
6836
|
-
(
|
|
6837
|
+
const L = p.current;
|
|
6838
|
+
if (L.isSpeaking || L.audioPlaylist && L.audioPlaylist.length > 0 || L.speechQueue && L.speechQueue.length > 0) {
|
|
6839
|
+
R.current && (clearInterval(R.current), R.current = null);
|
|
6840
|
+
let U = "";
|
|
6841
|
+
if (L.speechQueue && L.speechQueue.length > 0) {
|
|
6842
|
+
const E = L.speechQueue.filter((Y) => Y.text).map((Y) => Y.text).join(" ");
|
|
6843
|
+
E && (U = E.trim());
|
|
6844
|
+
}
|
|
6845
|
+
U && z.current && (P.current = {
|
|
6846
|
+
remainingText: U,
|
|
6847
|
+
originalText: z.current.text,
|
|
6848
|
+
options: z.current.options
|
|
6849
|
+
}), L.speechQueue && (L.speechQueue.length = 0), p.current.pauseSpeaking(), M.current = !0, K(!0);
|
|
6850
|
+
}
|
|
6837
6851
|
}
|
|
6838
|
-
}, []),
|
|
6839
|
-
if (p.current &&
|
|
6840
|
-
|
|
6841
|
-
|
|
6842
|
-
|
|
6843
|
-
|
|
6844
|
-
|
|
6852
|
+
}, []), ne = T(async () => {
|
|
6853
|
+
if (p.current && j) {
|
|
6854
|
+
K(!1), M.current = !1, await v();
|
|
6855
|
+
let L = "", B = {};
|
|
6856
|
+
if (P.current && P.current.remainingText)
|
|
6857
|
+
L = P.current.remainingText, B = P.current.options || {}, P.current = { remainingText: null, originalText: null, options: null };
|
|
6858
|
+
else if (z.current && z.current.text)
|
|
6859
|
+
L = z.current.text, B = z.current.options || {};
|
|
6860
|
+
else
|
|
6861
|
+
return;
|
|
6862
|
+
const U = {
|
|
6863
|
+
...B,
|
|
6864
|
+
lipsyncLang: B.lipsyncLang || pe.lipsyncLang || "en"
|
|
6845
6865
|
};
|
|
6846
|
-
p.current.lipsync && Object.keys(p.current.lipsync).length > 0 && (p.current.setSlowdownRate && p.current.setSlowdownRate(1.05), await
|
|
6866
|
+
p.current.lipsync && Object.keys(p.current.lipsync).length > 0 && (p.current.setSlowdownRate && p.current.setSlowdownRate(1.05), await w(L, U));
|
|
6847
6867
|
}
|
|
6848
|
-
}, [
|
|
6849
|
-
p.current && p.current.setMood(
|
|
6850
|
-
}, []),
|
|
6851
|
-
p.current && p.current.setSlowdownRate && p.current.setSlowdownRate(
|
|
6852
|
-
}, []),
|
|
6868
|
+
}, [v, j, w]), ie = T((L) => {
|
|
6869
|
+
p.current && p.current.setMood(L);
|
|
6870
|
+
}, []), fe = T((L) => {
|
|
6871
|
+
p.current && p.current.setSlowdownRate && p.current.setSlowdownRate(L);
|
|
6872
|
+
}, []), Se = T((L, B = !1) => {
|
|
6853
6873
|
if (p.current && p.current.playAnimation) {
|
|
6854
|
-
if (x && x[
|
|
6874
|
+
if (x && x[L] && (L = x[L]), p.current.setShowFullAvatar)
|
|
6855
6875
|
try {
|
|
6856
6876
|
p.current.setShowFullAvatar(H.current);
|
|
6857
|
-
} catch (
|
|
6858
|
-
console.warn("Error setting full body mode:",
|
|
6877
|
+
} catch (E) {
|
|
6878
|
+
console.warn("Error setting full body mode:", E);
|
|
6859
6879
|
}
|
|
6860
|
-
if (
|
|
6880
|
+
if (L.includes("."))
|
|
6861
6881
|
try {
|
|
6862
|
-
p.current.playAnimation(
|
|
6863
|
-
} catch (
|
|
6864
|
-
console.warn(`Failed to play ${
|
|
6882
|
+
p.current.playAnimation(L, null, 10, 0, 0.01, B);
|
|
6883
|
+
} catch (E) {
|
|
6884
|
+
console.warn(`Failed to play ${L}:`, E);
|
|
6865
6885
|
try {
|
|
6866
6886
|
p.current.setBodyMovement("idle");
|
|
6867
|
-
} catch (
|
|
6868
|
-
console.warn("Fallback animation also failed:",
|
|
6887
|
+
} catch (Y) {
|
|
6888
|
+
console.warn("Fallback animation also failed:", Y);
|
|
6869
6889
|
}
|
|
6870
6890
|
}
|
|
6871
6891
|
else {
|
|
6872
|
-
const
|
|
6873
|
-
let
|
|
6874
|
-
for (const
|
|
6892
|
+
const E = [".fbx", ".glb", ".gltf"];
|
|
6893
|
+
let Y = !1;
|
|
6894
|
+
for (const ge of E)
|
|
6875
6895
|
try {
|
|
6876
|
-
p.current.playAnimation(
|
|
6896
|
+
p.current.playAnimation(L + ge, null, 10, 0, 0.01, B), Y = !0;
|
|
6877
6897
|
break;
|
|
6878
6898
|
} catch {
|
|
6879
6899
|
}
|
|
6880
|
-
if (
|
|
6881
|
-
console.warn("Animation not found:",
|
|
6900
|
+
if (!Y) {
|
|
6901
|
+
console.warn("Animation not found:", L);
|
|
6882
6902
|
try {
|
|
6883
6903
|
p.current.setBodyMovement("idle");
|
|
6884
|
-
} catch (
|
|
6885
|
-
console.warn("Fallback animation also failed:",
|
|
6904
|
+
} catch (ge) {
|
|
6905
|
+
console.warn("Fallback animation also failed:", ge);
|
|
6886
6906
|
}
|
|
6887
6907
|
}
|
|
6888
6908
|
}
|
|
6889
6909
|
}
|
|
6890
|
-
}, [x]),
|
|
6910
|
+
}, [x]), De = T(() => {
|
|
6891
6911
|
p.current && p.current.onResize && p.current.onResize();
|
|
6892
6912
|
}, []);
|
|
6893
6913
|
return Le(I, () => ({
|
|
6894
|
-
speakText:
|
|
6895
|
-
stopSpeaking:
|
|
6896
|
-
pauseSpeaking:
|
|
6897
|
-
resumeSpeaking:
|
|
6898
|
-
resumeAudioContext:
|
|
6899
|
-
setMood:
|
|
6900
|
-
setTimingAdjustment:
|
|
6901
|
-
playAnimation:
|
|
6902
|
-
isReady:
|
|
6903
|
-
isPaused:
|
|
6914
|
+
speakText: w,
|
|
6915
|
+
stopSpeaking: C,
|
|
6916
|
+
pauseSpeaking: V,
|
|
6917
|
+
resumeSpeaking: ne,
|
|
6918
|
+
resumeAudioContext: v,
|
|
6919
|
+
setMood: ie,
|
|
6920
|
+
setTimingAdjustment: fe,
|
|
6921
|
+
playAnimation: Se,
|
|
6922
|
+
isReady: Z,
|
|
6923
|
+
isPaused: j,
|
|
6904
6924
|
talkingHead: p.current,
|
|
6905
|
-
handleResize:
|
|
6906
|
-
setBodyMovement: (
|
|
6925
|
+
handleResize: De,
|
|
6926
|
+
setBodyMovement: (L) => {
|
|
6907
6927
|
if (p.current && p.current.setShowFullAvatar && p.current.setBodyMovement)
|
|
6908
6928
|
try {
|
|
6909
|
-
p.current.setShowFullAvatar(H.current), p.current.setBodyMovement(
|
|
6910
|
-
} catch (
|
|
6911
|
-
console.warn("Error setting body movement:",
|
|
6929
|
+
p.current.setShowFullAvatar(H.current), p.current.setBodyMovement(L);
|
|
6930
|
+
} catch (B) {
|
|
6931
|
+
console.warn("Error setting body movement:", B);
|
|
6912
6932
|
}
|
|
6913
6933
|
},
|
|
6914
|
-
setMovementIntensity: (
|
|
6934
|
+
setMovementIntensity: (L) => p.current?.setMovementIntensity(L),
|
|
6915
6935
|
playRandomDance: () => {
|
|
6916
6936
|
if (p.current && p.current.setShowFullAvatar && p.current.playRandomDance)
|
|
6917
6937
|
try {
|
|
6918
6938
|
p.current.setShowFullAvatar(H.current), p.current.playRandomDance();
|
|
6919
|
-
} catch (
|
|
6920
|
-
console.warn("Error playing random dance:",
|
|
6939
|
+
} catch (L) {
|
|
6940
|
+
console.warn("Error playing random dance:", L);
|
|
6921
6941
|
}
|
|
6922
6942
|
},
|
|
6923
|
-
playReaction: (
|
|
6943
|
+
playReaction: (L) => {
|
|
6924
6944
|
if (p.current && p.current.setShowFullAvatar && p.current.playReaction)
|
|
6925
6945
|
try {
|
|
6926
|
-
p.current.setShowFullAvatar(H.current), p.current.playReaction(
|
|
6927
|
-
} catch (
|
|
6928
|
-
console.warn("Error playing reaction:",
|
|
6946
|
+
p.current.setShowFullAvatar(H.current), p.current.playReaction(L);
|
|
6947
|
+
} catch (B) {
|
|
6948
|
+
console.warn("Error playing reaction:", B);
|
|
6929
6949
|
}
|
|
6930
6950
|
},
|
|
6931
6951
|
playCelebration: () => {
|
|
6932
6952
|
if (p.current && p.current.setShowFullAvatar && p.current.playCelebration)
|
|
6933
6953
|
try {
|
|
6934
6954
|
p.current.setShowFullAvatar(H.current), p.current.playCelebration();
|
|
6935
|
-
} catch (
|
|
6936
|
-
console.warn("Error playing celebration:",
|
|
6955
|
+
} catch (L) {
|
|
6956
|
+
console.warn("Error playing celebration:", L);
|
|
6937
6957
|
}
|
|
6938
6958
|
},
|
|
6939
|
-
setShowFullAvatar: (
|
|
6959
|
+
setShowFullAvatar: (L) => {
|
|
6940
6960
|
if (p.current && p.current.setShowFullAvatar)
|
|
6941
6961
|
try {
|
|
6942
|
-
H.current =
|
|
6943
|
-
} catch (
|
|
6944
|
-
console.warn("Error setting showFullAvatar:",
|
|
6962
|
+
H.current = L, p.current.setShowFullAvatar(L);
|
|
6963
|
+
} catch (B) {
|
|
6964
|
+
console.warn("Error setting showFullAvatar:", B);
|
|
6945
6965
|
}
|
|
6946
6966
|
},
|
|
6947
6967
|
lockAvatarPosition: () => {
|
|
6948
6968
|
if (p.current && p.current.lockAvatarPosition)
|
|
6949
6969
|
try {
|
|
6950
6970
|
p.current.lockAvatarPosition();
|
|
6951
|
-
} catch (
|
|
6952
|
-
console.warn("Error locking avatar position:",
|
|
6971
|
+
} catch (L) {
|
|
6972
|
+
console.warn("Error locking avatar position:", L);
|
|
6953
6973
|
}
|
|
6954
6974
|
},
|
|
6955
6975
|
unlockAvatarPosition: () => {
|
|
6956
6976
|
if (p.current && p.current.unlockAvatarPosition)
|
|
6957
6977
|
try {
|
|
6958
6978
|
p.current.unlockAvatarPosition();
|
|
6959
|
-
} catch (
|
|
6960
|
-
console.warn("Error unlocking avatar position:",
|
|
6979
|
+
} catch (L) {
|
|
6980
|
+
console.warn("Error unlocking avatar position:", L);
|
|
6961
6981
|
}
|
|
6962
6982
|
}
|
|
6963
|
-
})), /* @__PURE__ */
|
|
6983
|
+
})), /* @__PURE__ */ Ee(
|
|
6964
6984
|
"div",
|
|
6965
6985
|
{
|
|
6966
6986
|
className: `talking-head-avatar ${g}`,
|
|
@@ -6971,10 +6991,10 @@ const Fe = Ie(({
|
|
|
6971
6991
|
...y
|
|
6972
6992
|
},
|
|
6973
6993
|
children: [
|
|
6974
|
-
/* @__PURE__ */
|
|
6994
|
+
/* @__PURE__ */ ue(
|
|
6975
6995
|
"div",
|
|
6976
6996
|
{
|
|
6977
|
-
ref:
|
|
6997
|
+
ref: D,
|
|
6978
6998
|
className: "talking-head-viewer",
|
|
6979
6999
|
style: {
|
|
6980
7000
|
width: "100%",
|
|
@@ -6983,7 +7003,7 @@ const Fe = Ie(({
|
|
|
6983
7003
|
}
|
|
6984
7004
|
}
|
|
6985
7005
|
),
|
|
6986
|
-
|
|
7006
|
+
ee && /* @__PURE__ */ ue("div", { className: "loading-overlay", style: {
|
|
6987
7007
|
position: "absolute",
|
|
6988
7008
|
top: "50%",
|
|
6989
7009
|
left: "50%",
|
|
@@ -6992,7 +7012,7 @@ const Fe = Ie(({
|
|
|
6992
7012
|
fontSize: "18px",
|
|
6993
7013
|
zIndex: 10
|
|
6994
7014
|
}, children: "Loading avatar..." }),
|
|
6995
|
-
|
|
7015
|
+
S && /* @__PURE__ */ ue("div", { className: "error-overlay", style: {
|
|
6996
7016
|
position: "absolute",
|
|
6997
7017
|
top: "50%",
|
|
6998
7018
|
left: "50%",
|
|
@@ -7003,25 +7023,25 @@ const Fe = Ie(({
|
|
|
7003
7023
|
zIndex: 10,
|
|
7004
7024
|
padding: "20px",
|
|
7005
7025
|
borderRadius: "8px"
|
|
7006
|
-
}, children:
|
|
7026
|
+
}, children: S })
|
|
7007
7027
|
]
|
|
7008
7028
|
}
|
|
7009
7029
|
);
|
|
7010
7030
|
});
|
|
7011
|
-
|
|
7012
|
-
const
|
|
7031
|
+
Pe.displayName = "TalkingHeadAvatar";
|
|
7032
|
+
const ut = Ie(({
|
|
7013
7033
|
text: O = "Hello! I'm a talking avatar. How are you today?",
|
|
7014
7034
|
onLoading: t = () => {
|
|
7015
7035
|
},
|
|
7016
7036
|
onError: e = () => {
|
|
7017
7037
|
},
|
|
7018
|
-
onReady:
|
|
7038
|
+
onReady: n = () => {
|
|
7019
7039
|
},
|
|
7020
|
-
className:
|
|
7040
|
+
className: i = "",
|
|
7021
7041
|
style: s = {},
|
|
7022
7042
|
avatarConfig: o = {}
|
|
7023
7043
|
}, l) => {
|
|
7024
|
-
const u =
|
|
7044
|
+
const u = G(null), a = G(null), [h, r] = de(!0), [c, d] = de(null), [g, y] = de(!1), x = Ae(), I = o.ttsService || x.service, D = I === "browser" ? {
|
|
7025
7045
|
endpoint: "",
|
|
7026
7046
|
apiKey: null,
|
|
7027
7047
|
defaultVoice: "Google US English"
|
|
@@ -7037,7 +7057,7 @@ const lt = Ie(({
|
|
|
7037
7057
|
body: "F",
|
|
7038
7058
|
avatarMood: "neutral",
|
|
7039
7059
|
ttsLang: I === "browser" ? "en-US" : "en",
|
|
7040
|
-
ttsVoice: o.ttsVoice ||
|
|
7060
|
+
ttsVoice: o.ttsVoice || D.defaultVoice,
|
|
7041
7061
|
lipsyncLang: "en",
|
|
7042
7062
|
// English lip-sync
|
|
7043
7063
|
showFullAvatar: !0,
|
|
@@ -7046,102 +7066,102 @@ const lt = Ie(({
|
|
|
7046
7066
|
movementIntensity: 0.5,
|
|
7047
7067
|
...o
|
|
7048
7068
|
}, H = {
|
|
7049
|
-
ttsEndpoint:
|
|
7050
|
-
ttsApikey:
|
|
7069
|
+
ttsEndpoint: D.endpoint,
|
|
7070
|
+
ttsApikey: D.apiKey,
|
|
7051
7071
|
ttsService: I,
|
|
7052
7072
|
lipsyncModules: ["en"],
|
|
7053
7073
|
cameraView: "upper"
|
|
7054
7074
|
}, z = T(async () => {
|
|
7055
7075
|
if (!(!u.current || a.current))
|
|
7056
7076
|
try {
|
|
7057
|
-
if (r(!0), d(null), a.current = new
|
|
7058
|
-
if (
|
|
7059
|
-
const
|
|
7060
|
-
t(
|
|
7077
|
+
if (r(!0), d(null), a.current = new Fe(u.current, H), await a.current.showAvatar(p, (Z) => {
|
|
7078
|
+
if (Z.lengthComputable) {
|
|
7079
|
+
const X = Math.min(100, Math.round(Z.loaded / Z.total * 100));
|
|
7080
|
+
t(X);
|
|
7061
7081
|
}
|
|
7062
7082
|
}), a.current.morphs && a.current.morphs.length > 0) {
|
|
7063
|
-
const
|
|
7064
|
-
console.log("Available morph targets:", Object.keys(
|
|
7065
|
-
const
|
|
7066
|
-
console.log("Viseme morph targets found:",
|
|
7083
|
+
const Z = a.current.morphs[0].morphTargetDictionary;
|
|
7084
|
+
console.log("Available morph targets:", Object.keys(Z));
|
|
7085
|
+
const X = Object.keys(Z).filter((j) => j.startsWith("viseme_"));
|
|
7086
|
+
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"));
|
|
7067
7087
|
}
|
|
7068
|
-
if (await new Promise((
|
|
7069
|
-
const
|
|
7070
|
-
a.current.lipsync && Object.keys(a.current.lipsync).length > 0 ? (console.log("Lip-sync modules loaded:", Object.keys(a.current.lipsync)),
|
|
7088
|
+
if (await new Promise((Z) => {
|
|
7089
|
+
const X = () => {
|
|
7090
|
+
a.current.lipsync && Object.keys(a.current.lipsync).length > 0 ? (console.log("Lip-sync modules loaded:", Object.keys(a.current.lipsync)), Z()) : (console.log("Waiting for lip-sync modules to load..."), setTimeout(X, 100));
|
|
7071
7091
|
};
|
|
7072
|
-
|
|
7092
|
+
X();
|
|
7073
7093
|
}), a.current && a.current.setShowFullAvatar)
|
|
7074
7094
|
try {
|
|
7075
7095
|
a.current.setShowFullAvatar(!0), console.log("Avatar initialized in full body mode");
|
|
7076
|
-
} catch (
|
|
7077
|
-
console.warn("Error setting full body mode on initialization:",
|
|
7096
|
+
} catch (Z) {
|
|
7097
|
+
console.warn("Error setting full body mode on initialization:", Z);
|
|
7078
7098
|
}
|
|
7079
|
-
r(!1), y(!0),
|
|
7080
|
-
const
|
|
7099
|
+
r(!1), y(!0), n(a.current);
|
|
7100
|
+
const N = () => {
|
|
7081
7101
|
document.visibilityState === "visible" ? a.current?.start() : a.current?.stop();
|
|
7082
7102
|
};
|
|
7083
|
-
return document.addEventListener("visibilitychange",
|
|
7084
|
-
document.removeEventListener("visibilitychange",
|
|
7103
|
+
return document.addEventListener("visibilitychange", N), () => {
|
|
7104
|
+
document.removeEventListener("visibilitychange", N);
|
|
7085
7105
|
};
|
|
7086
7106
|
} catch (S) {
|
|
7087
7107
|
console.error("Error initializing TalkingHead:", S), d(S.message || "Failed to initialize avatar"), r(!1), e(S);
|
|
7088
7108
|
}
|
|
7089
7109
|
}, []);
|
|
7090
|
-
|
|
7110
|
+
me(() => (z(), () => {
|
|
7091
7111
|
a.current && (a.current.stop(), a.current.dispose(), a.current = null);
|
|
7092
7112
|
}), [z]);
|
|
7093
|
-
const
|
|
7113
|
+
const R = T((S) => {
|
|
7094
7114
|
if (a.current && g)
|
|
7095
7115
|
try {
|
|
7096
7116
|
console.log("Speaking text:", S), console.log("Avatar config:", p), console.log("TalkingHead instance:", a.current), a.current.lipsync && Object.keys(a.current.lipsync).length > 0 ? (console.log("Lip-sync modules loaded:", Object.keys(a.current.lipsync)), a.current.setSlowdownRate && (a.current.setSlowdownRate(1.05), console.log("Applied timing adjustment for better lip-sync")), a.current.speakText(S)) : (console.warn("Lip-sync modules not ready, waiting..."), setTimeout(() => {
|
|
7097
7117
|
a.current && a.current.lipsync ? (console.log("Lip-sync now ready, speaking..."), a.current.setSlowdownRate && (a.current.setSlowdownRate(1.05), console.log("Applied timing adjustment for better lip-sync")), a.current.speakText(S)) : console.error("Lip-sync still not ready after waiting");
|
|
7098
7118
|
}, 500));
|
|
7099
|
-
} catch (
|
|
7100
|
-
console.error("Error speaking text:",
|
|
7119
|
+
} catch (N) {
|
|
7120
|
+
console.error("Error speaking text:", N), d(N.message || "Failed to speak text");
|
|
7101
7121
|
}
|
|
7102
7122
|
else
|
|
7103
7123
|
console.warn("Avatar not ready for speaking. isReady:", g, "talkingHeadRef:", !!a.current);
|
|
7104
|
-
}, [g, p]),
|
|
7124
|
+
}, [g, p]), M = T(() => {
|
|
7105
7125
|
a.current && (a.current.stopSpeaking(), a.current.setSlowdownRate && (a.current.setSlowdownRate(1), console.log("Reset timing to normal")));
|
|
7106
|
-
}, []),
|
|
7126
|
+
}, []), P = T((S) => {
|
|
7107
7127
|
a.current && a.current.setMood(S);
|
|
7108
|
-
}, []),
|
|
7128
|
+
}, []), ee = T((S) => {
|
|
7109
7129
|
a.current && a.current.setSlowdownRate && (a.current.setSlowdownRate(S), console.log("Timing adjustment set to:", S));
|
|
7110
|
-
}, []),
|
|
7130
|
+
}, []), re = T((S, N = !1) => {
|
|
7111
7131
|
if (a.current && a.current.playAnimation) {
|
|
7112
7132
|
if (a.current.setShowFullAvatar)
|
|
7113
7133
|
try {
|
|
7114
7134
|
a.current.setShowFullAvatar(!0);
|
|
7115
|
-
} catch (
|
|
7116
|
-
console.warn("Error setting full body mode:",
|
|
7135
|
+
} catch (X) {
|
|
7136
|
+
console.warn("Error setting full body mode:", X);
|
|
7117
7137
|
}
|
|
7118
7138
|
if (S.includes("."))
|
|
7119
7139
|
try {
|
|
7120
|
-
a.current.playAnimation(S, null, 10, 0, 0.01,
|
|
7121
|
-
} catch (
|
|
7122
|
-
console.log(`Failed to play ${S}:`,
|
|
7140
|
+
a.current.playAnimation(S, null, 10, 0, 0.01, N), console.log("Playing animation:", S);
|
|
7141
|
+
} catch (X) {
|
|
7142
|
+
console.log(`Failed to play ${S}:`, X);
|
|
7123
7143
|
try {
|
|
7124
7144
|
a.current.setBodyMovement("idle"), console.log("Fallback to idle animation");
|
|
7125
|
-
} catch (
|
|
7126
|
-
console.warn("Fallback animation also failed:",
|
|
7145
|
+
} catch (j) {
|
|
7146
|
+
console.warn("Fallback animation also failed:", j);
|
|
7127
7147
|
}
|
|
7128
7148
|
}
|
|
7129
7149
|
else {
|
|
7130
|
-
const
|
|
7131
|
-
let
|
|
7132
|
-
for (const
|
|
7150
|
+
const X = [".fbx", ".glb", ".gltf"];
|
|
7151
|
+
let j = !1;
|
|
7152
|
+
for (const K of X)
|
|
7133
7153
|
try {
|
|
7134
|
-
a.current.playAnimation(S +
|
|
7154
|
+
a.current.playAnimation(S + K, null, 10, 0, 0.01, N), console.log("Playing animation:", S + K), j = !0;
|
|
7135
7155
|
break;
|
|
7136
7156
|
} catch {
|
|
7137
|
-
console.log(`Failed to play ${S}${
|
|
7157
|
+
console.log(`Failed to play ${S}${K}, trying next format...`);
|
|
7138
7158
|
}
|
|
7139
|
-
if (!
|
|
7159
|
+
if (!j) {
|
|
7140
7160
|
console.warn("Animation system not available or animation not found:", S);
|
|
7141
7161
|
try {
|
|
7142
7162
|
a.current.setBodyMovement("idle"), console.log("Fallback to idle animation");
|
|
7143
|
-
} catch (
|
|
7144
|
-
console.warn("Fallback animation also failed:",
|
|
7163
|
+
} catch (K) {
|
|
7164
|
+
console.warn("Fallback animation also failed:", K);
|
|
7145
7165
|
}
|
|
7146
7166
|
}
|
|
7147
7167
|
}
|
|
@@ -7149,19 +7169,19 @@ const lt = Ie(({
|
|
|
7149
7169
|
console.warn("Animation system not available or animation not found:", S);
|
|
7150
7170
|
}, []);
|
|
7151
7171
|
return Le(l, () => ({
|
|
7152
|
-
speakText:
|
|
7153
|
-
stopSpeaking:
|
|
7154
|
-
setMood:
|
|
7155
|
-
setTimingAdjustment:
|
|
7156
|
-
playAnimation:
|
|
7172
|
+
speakText: R,
|
|
7173
|
+
stopSpeaking: M,
|
|
7174
|
+
setMood: P,
|
|
7175
|
+
setTimingAdjustment: ee,
|
|
7176
|
+
playAnimation: re,
|
|
7157
7177
|
isReady: g,
|
|
7158
7178
|
talkingHead: a.current,
|
|
7159
7179
|
setBodyMovement: (S) => {
|
|
7160
7180
|
if (a.current && a.current.setShowFullAvatar && a.current.setBodyMovement)
|
|
7161
7181
|
try {
|
|
7162
7182
|
a.current.setShowFullAvatar(!0), a.current.setBodyMovement(S), console.log("Body movement set with full body mode:", S);
|
|
7163
|
-
} catch (
|
|
7164
|
-
console.warn("Error setting body movement:",
|
|
7183
|
+
} catch (N) {
|
|
7184
|
+
console.warn("Error setting body movement:", N);
|
|
7165
7185
|
}
|
|
7166
7186
|
},
|
|
7167
7187
|
setMovementIntensity: (S) => a.current?.setMovementIntensity(S),
|
|
@@ -7177,8 +7197,8 @@ const lt = Ie(({
|
|
|
7177
7197
|
if (a.current && a.current.setShowFullAvatar && a.current.playReaction)
|
|
7178
7198
|
try {
|
|
7179
7199
|
a.current.setShowFullAvatar(!0), a.current.playReaction(S), console.log("Reaction played with full body mode:", S);
|
|
7180
|
-
} catch (
|
|
7181
|
-
console.warn("Error playing reaction:",
|
|
7200
|
+
} catch (N) {
|
|
7201
|
+
console.warn("Error playing reaction:", N);
|
|
7182
7202
|
}
|
|
7183
7203
|
},
|
|
7184
7204
|
playCelebration: () => {
|
|
@@ -7193,8 +7213,8 @@ const lt = Ie(({
|
|
|
7193
7213
|
if (a.current && a.current.setShowFullAvatar)
|
|
7194
7214
|
try {
|
|
7195
7215
|
a.current.setShowFullAvatar(S), console.log("Show full avatar set to:", S);
|
|
7196
|
-
} catch (
|
|
7197
|
-
console.warn("Error setting showFullAvatar:",
|
|
7216
|
+
} catch (N) {
|
|
7217
|
+
console.warn("Error setting showFullAvatar:", N);
|
|
7198
7218
|
}
|
|
7199
7219
|
},
|
|
7200
7220
|
lockAvatarPosition: () => {
|
|
@@ -7213,8 +7233,8 @@ const lt = Ie(({
|
|
|
7213
7233
|
console.warn("Error unlocking avatar position:", S);
|
|
7214
7234
|
}
|
|
7215
7235
|
}
|
|
7216
|
-
})), /* @__PURE__ */
|
|
7217
|
-
/* @__PURE__ */
|
|
7236
|
+
})), /* @__PURE__ */ Ee("div", { className: `talking-head-container ${i}`, style: s, children: [
|
|
7237
|
+
/* @__PURE__ */ ue(
|
|
7218
7238
|
"div",
|
|
7219
7239
|
{
|
|
7220
7240
|
ref: u,
|
|
@@ -7226,7 +7246,7 @@ const lt = Ie(({
|
|
|
7226
7246
|
}
|
|
7227
7247
|
}
|
|
7228
7248
|
),
|
|
7229
|
-
h && /* @__PURE__ */
|
|
7249
|
+
h && /* @__PURE__ */ ue("div", { className: "loading-overlay", style: {
|
|
7230
7250
|
position: "absolute",
|
|
7231
7251
|
top: "50%",
|
|
7232
7252
|
left: "50%",
|
|
@@ -7235,7 +7255,7 @@ const lt = Ie(({
|
|
|
7235
7255
|
fontSize: "18px",
|
|
7236
7256
|
zIndex: 10
|
|
7237
7257
|
}, children: "Loading avatar..." }),
|
|
7238
|
-
c && /* @__PURE__ */
|
|
7258
|
+
c && /* @__PURE__ */ ue("div", { className: "error-overlay", style: {
|
|
7239
7259
|
position: "absolute",
|
|
7240
7260
|
top: "50%",
|
|
7241
7261
|
left: "50%",
|
|
@@ -7249,14 +7269,14 @@ const lt = Ie(({
|
|
|
7249
7269
|
}, children: c })
|
|
7250
7270
|
] });
|
|
7251
7271
|
});
|
|
7252
|
-
|
|
7253
|
-
const
|
|
7272
|
+
ut.displayName = "TalkingHeadComponent";
|
|
7273
|
+
const ct = Ie(({
|
|
7254
7274
|
curriculumData: O = null,
|
|
7255
7275
|
avatarConfig: t = {},
|
|
7256
7276
|
animations: e = {},
|
|
7257
|
-
onLessonStart:
|
|
7277
|
+
onLessonStart: n = () => {
|
|
7258
7278
|
},
|
|
7259
|
-
onLessonComplete:
|
|
7279
|
+
onLessonComplete: i = () => {
|
|
7260
7280
|
},
|
|
7261
7281
|
onQuestionAnswer: s = () => {
|
|
7262
7282
|
},
|
|
@@ -7266,7 +7286,7 @@ const ht = Ie(({
|
|
|
7266
7286
|
},
|
|
7267
7287
|
autoStart: u = !1
|
|
7268
7288
|
}, a) => {
|
|
7269
|
-
const h =
|
|
7289
|
+
const h = G(null), r = G({
|
|
7270
7290
|
currentModuleIndex: 0,
|
|
7271
7291
|
currentLessonIndex: 0,
|
|
7272
7292
|
currentQuestionIndex: 0,
|
|
@@ -7276,18 +7296,18 @@ const ht = Ie(({
|
|
|
7276
7296
|
curriculumCompleted: !1,
|
|
7277
7297
|
score: 0,
|
|
7278
7298
|
totalQuestions: 0
|
|
7279
|
-
}), c =
|
|
7280
|
-
onLessonStart:
|
|
7281
|
-
onLessonComplete:
|
|
7299
|
+
}), c = G({
|
|
7300
|
+
onLessonStart: n,
|
|
7301
|
+
onLessonComplete: i,
|
|
7282
7302
|
onQuestionAnswer: s,
|
|
7283
7303
|
onCurriculumComplete: o,
|
|
7284
7304
|
onCustomAction: l
|
|
7285
|
-
}), d =
|
|
7305
|
+
}), d = G(null), g = G(null), y = G(null), x = G(null), I = G(null), D = G(null), p = G(null), H = G(O?.curriculum || {
|
|
7286
7306
|
title: "Default Curriculum",
|
|
7287
7307
|
description: "No curriculum data provided",
|
|
7288
7308
|
language: "en",
|
|
7289
7309
|
modules: []
|
|
7290
|
-
}), z =
|
|
7310
|
+
}), z = G({
|
|
7291
7311
|
avatarUrl: t.avatarUrl || "/avatars/brunette.glb",
|
|
7292
7312
|
avatarBody: t.avatarBody || "F",
|
|
7293
7313
|
mood: t.mood || "happy",
|
|
@@ -7301,15 +7321,15 @@ const ht = Ie(({
|
|
|
7301
7321
|
animations: e,
|
|
7302
7322
|
lipsyncLang: "en"
|
|
7303
7323
|
});
|
|
7304
|
-
|
|
7324
|
+
me(() => {
|
|
7305
7325
|
c.current = {
|
|
7306
|
-
onLessonStart:
|
|
7307
|
-
onLessonComplete:
|
|
7326
|
+
onLessonStart: n,
|
|
7327
|
+
onLessonComplete: i,
|
|
7308
7328
|
onQuestionAnswer: s,
|
|
7309
7329
|
onCurriculumComplete: o,
|
|
7310
7330
|
onCustomAction: l
|
|
7311
7331
|
};
|
|
7312
|
-
}, [
|
|
7332
|
+
}, [n, i, s, o, l]), me(() => {
|
|
7313
7333
|
H.current = O?.curriculum || {
|
|
7314
7334
|
title: "Default Curriculum",
|
|
7315
7335
|
description: "No curriculum data provided",
|
|
@@ -7330,11 +7350,11 @@ const ht = Ie(({
|
|
|
7330
7350
|
lipsyncLang: "en"
|
|
7331
7351
|
};
|
|
7332
7352
|
}, [O, t, e]);
|
|
7333
|
-
const
|
|
7353
|
+
const R = T(() => (H.current || { modules: [] }).modules[r.current.currentModuleIndex]?.lessons[r.current.currentLessonIndex], []), M = T(() => R()?.questions[r.current.currentQuestionIndex], [R]), P = T((b, v) => v.type === "multiple_choice" || v.type === "true_false" ? b === v.answer : v.type === "code_test" && typeof b == "object" && b !== null ? b.passed === !0 : !1, []), ee = T(() => {
|
|
7334
7354
|
r.current.lessonCompleted = !0, r.current.isQuestionMode = !1;
|
|
7335
7355
|
const b = r.current.totalQuestions > 0 ? Math.round(r.current.score / r.current.totalQuestions * 100) : 100;
|
|
7336
|
-
let
|
|
7337
|
-
if (r.current.totalQuestions > 0 ?
|
|
7356
|
+
let v = "Congratulations! You've completed this lesson";
|
|
7357
|
+
if (r.current.totalQuestions > 0 ? v += ` You got ${r.current.score} correct out of ${r.current.totalQuestions} question${r.current.totalQuestions === 1 ? "" : "s"}, achieving a score of ${b} percent. ` : v += "! ", b >= 80 ? v += "Excellent work! You have a great understanding of this topic." : b >= 60 ? v += "Good job! You understand most of the concepts." : v += "Keep practicing! You're making progress.", c.current.onLessonComplete({
|
|
7338
7358
|
moduleIndex: r.current.currentModuleIndex,
|
|
7339
7359
|
lessonIndex: r.current.currentLessonIndex,
|
|
7340
7360
|
score: r.current.score,
|
|
@@ -7354,9 +7374,9 @@ const ht = Ie(({
|
|
|
7354
7374
|
} catch {
|
|
7355
7375
|
h.current.playCelebration();
|
|
7356
7376
|
}
|
|
7357
|
-
const w = H.current || { modules: [] }, C = w.modules[r.current.currentModuleIndex], V = r.current.currentLessonIndex < (C?.lessons?.length || 0) - 1,
|
|
7358
|
-
h.current.speakText(
|
|
7359
|
-
lipsyncLang:
|
|
7377
|
+
const w = H.current || { modules: [] }, C = w.modules[r.current.currentModuleIndex], V = r.current.currentLessonIndex < (C?.lessons?.length || 0) - 1, ne = r.current.currentModuleIndex < (w.modules?.length || 0) - 1, ie = V || ne, fe = z.current || { lipsyncLang: "en" };
|
|
7378
|
+
h.current.speakText(v, {
|
|
7379
|
+
lipsyncLang: fe.lipsyncLang,
|
|
7360
7380
|
onSpeechEnd: () => {
|
|
7361
7381
|
c.current.onCustomAction({
|
|
7362
7382
|
type: "lessonCompleteFeedbackDone",
|
|
@@ -7370,12 +7390,12 @@ const ht = Ie(({
|
|
|
7370
7390
|
}
|
|
7371
7391
|
});
|
|
7372
7392
|
}
|
|
7373
|
-
}, [e.lessonComplete]),
|
|
7393
|
+
}, [e.lessonComplete]), re = T(() => {
|
|
7374
7394
|
r.current.curriculumCompleted = !0;
|
|
7375
7395
|
const b = H.current || { modules: [] };
|
|
7376
7396
|
if (c.current.onCurriculumComplete({
|
|
7377
7397
|
modules: b.modules.length,
|
|
7378
|
-
totalLessons: b.modules.reduce((
|
|
7398
|
+
totalLessons: b.modules.reduce((v, w) => v + w.lessons.length, 0)
|
|
7379
7399
|
}), h.current) {
|
|
7380
7400
|
if (h.current.setMood("celebrating"), e.curriculumComplete)
|
|
7381
7401
|
try {
|
|
@@ -7383,24 +7403,24 @@ const ht = Ie(({
|
|
|
7383
7403
|
} catch {
|
|
7384
7404
|
h.current.playCelebration();
|
|
7385
7405
|
}
|
|
7386
|
-
const
|
|
7387
|
-
h.current.speakText("Amazing! You've completed the entire curriculum! You're now ready to move on to more advanced topics. Well done!", { lipsyncLang:
|
|
7406
|
+
const v = z.current || { lipsyncLang: "en" };
|
|
7407
|
+
h.current.speakText("Amazing! You've completed the entire curriculum! You're now ready to move on to more advanced topics. Well done!", { lipsyncLang: v.lipsyncLang });
|
|
7388
7408
|
}
|
|
7389
7409
|
}, [e.curriculumComplete]), S = T(() => {
|
|
7390
|
-
const b =
|
|
7410
|
+
const b = R();
|
|
7391
7411
|
r.current.isQuestionMode = !0, r.current.currentQuestionIndex = 0, r.current.totalQuestions = b?.questions?.length || 0, r.current.score = 0;
|
|
7392
|
-
const
|
|
7393
|
-
|
|
7412
|
+
const v = M();
|
|
7413
|
+
v && c.current.onCustomAction({
|
|
7394
7414
|
type: "questionStart",
|
|
7395
7415
|
moduleIndex: r.current.currentModuleIndex,
|
|
7396
7416
|
lessonIndex: r.current.currentLessonIndex,
|
|
7397
7417
|
questionIndex: r.current.currentQuestionIndex,
|
|
7398
7418
|
totalQuestions: r.current.totalQuestions,
|
|
7399
|
-
question:
|
|
7419
|
+
question: v,
|
|
7400
7420
|
score: r.current.score
|
|
7401
7421
|
});
|
|
7402
7422
|
const w = () => {
|
|
7403
|
-
if (!h.current || !
|
|
7423
|
+
if (!h.current || !v) return;
|
|
7404
7424
|
if (h.current.setMood("happy"), e.questionStart)
|
|
7405
7425
|
try {
|
|
7406
7426
|
h.current.playAnimation(e.questionStart, !0);
|
|
@@ -7408,37 +7428,37 @@ const ht = Ie(({
|
|
|
7408
7428
|
console.warn("Failed to play questionStart animation:", V);
|
|
7409
7429
|
}
|
|
7410
7430
|
const C = z.current || { lipsyncLang: "en" };
|
|
7411
|
-
|
|
7431
|
+
v.type === "code_test" ? h.current.speakText(`Let's test your coding skills! Here's your first challenge: ${v.question}`, { lipsyncLang: C.lipsyncLang }) : v.type === "multiple_choice" ? h.current.speakText(`Now let me ask you some questions. Here's the first one: ${v.question}`, { lipsyncLang: C.lipsyncLang }) : v.type === "true_false" ? h.current.speakText(`Let's start with some true or false questions. First question: ${v.question}`, { lipsyncLang: C.lipsyncLang }) : h.current.speakText(`Now let me ask you some questions. Here's the first one: ${v.question}`, { lipsyncLang: C.lipsyncLang });
|
|
7412
7432
|
};
|
|
7413
|
-
if (h.current && h.current.isReady &&
|
|
7433
|
+
if (h.current && h.current.isReady && v)
|
|
7414
7434
|
w();
|
|
7415
7435
|
else if (h.current && h.current.isReady) {
|
|
7416
7436
|
const C = z.current || { lipsyncLang: "en" };
|
|
7417
7437
|
h.current.speakText("Now let me ask you some questions to test your understanding.", { lipsyncLang: C.lipsyncLang });
|
|
7418
7438
|
} else {
|
|
7419
7439
|
const C = setInterval(() => {
|
|
7420
|
-
h.current && h.current.isReady && (clearInterval(C),
|
|
7440
|
+
h.current && h.current.isReady && (clearInterval(C), v && w());
|
|
7421
7441
|
}, 100);
|
|
7422
7442
|
setTimeout(() => {
|
|
7423
7443
|
clearInterval(C);
|
|
7424
7444
|
}, 5e3);
|
|
7425
7445
|
}
|
|
7426
|
-
}, [e.questionStart,
|
|
7427
|
-
const b =
|
|
7446
|
+
}, [e.questionStart, R, M]), N = T(() => {
|
|
7447
|
+
const b = R();
|
|
7428
7448
|
if (r.current.currentQuestionIndex < (b?.questions?.length || 0) - 1) {
|
|
7429
7449
|
h.current && h.current.stopSpeaking && h.current.stopSpeaking(), r.current.currentQuestionIndex += 1;
|
|
7430
|
-
const
|
|
7431
|
-
|
|
7450
|
+
const v = M();
|
|
7451
|
+
v && c.current.onCustomAction({
|
|
7432
7452
|
type: "nextQuestion",
|
|
7433
7453
|
moduleIndex: r.current.currentModuleIndex,
|
|
7434
7454
|
lessonIndex: r.current.currentLessonIndex,
|
|
7435
7455
|
questionIndex: r.current.currentQuestionIndex,
|
|
7436
7456
|
totalQuestions: r.current.totalQuestions,
|
|
7437
|
-
question:
|
|
7457
|
+
question: v,
|
|
7438
7458
|
score: r.current.score
|
|
7439
7459
|
});
|
|
7440
7460
|
const w = () => {
|
|
7441
|
-
if (!h.current || !
|
|
7461
|
+
if (!h.current || !v) return;
|
|
7442
7462
|
if (h.current.setMood("happy"), h.current.setBodyMovement("idle"), e.nextQuestion)
|
|
7443
7463
|
try {
|
|
7444
7464
|
h.current.playAnimation(e.nextQuestion, !0);
|
|
@@ -7446,19 +7466,19 @@ const ht = Ie(({
|
|
|
7446
7466
|
console.warn("Failed to play nextQuestion animation:", V);
|
|
7447
7467
|
}
|
|
7448
7468
|
const C = z.current || { lipsyncLang: "en" };
|
|
7449
|
-
|
|
7469
|
+
v.type === "code_test" ? h.current.speakText(`Great! Now let's move on to your next coding challenge: ${v.question}`, {
|
|
7450
7470
|
lipsyncLang: C.lipsyncLang
|
|
7451
|
-
}) :
|
|
7471
|
+
}) : v.type === "multiple_choice" ? h.current.speakText(`Alright! Here's your next question: ${v.question}`, {
|
|
7452
7472
|
lipsyncLang: C.lipsyncLang
|
|
7453
|
-
}) :
|
|
7473
|
+
}) : v.type === "true_false" ? h.current.speakText(`Now let's try this one: ${v.question}`, {
|
|
7454
7474
|
lipsyncLang: C.lipsyncLang
|
|
7455
|
-
}) : h.current.speakText(`Here's the next question: ${
|
|
7475
|
+
}) : h.current.speakText(`Here's the next question: ${v.question}`, {
|
|
7456
7476
|
lipsyncLang: C.lipsyncLang
|
|
7457
7477
|
});
|
|
7458
7478
|
};
|
|
7459
|
-
if (h.current && h.current.isReady &&
|
|
7479
|
+
if (h.current && h.current.isReady && v)
|
|
7460
7480
|
w();
|
|
7461
|
-
else if (
|
|
7481
|
+
else if (v) {
|
|
7462
7482
|
const C = setInterval(() => {
|
|
7463
7483
|
h.current && h.current.isReady && (clearInterval(C), w());
|
|
7464
7484
|
}, 100);
|
|
@@ -7474,11 +7494,11 @@ const ht = Ie(({
|
|
|
7474
7494
|
totalQuestions: r.current.totalQuestions,
|
|
7475
7495
|
score: r.current.score
|
|
7476
7496
|
});
|
|
7477
|
-
}, [e.nextQuestion,
|
|
7478
|
-
const b = H.current || { modules: [] },
|
|
7479
|
-
if (r.current.currentLessonIndex < (
|
|
7497
|
+
}, [e.nextQuestion, R, M]), Z = T(() => {
|
|
7498
|
+
const b = H.current || { modules: [] }, v = b.modules[r.current.currentModuleIndex];
|
|
7499
|
+
if (r.current.currentLessonIndex < (v?.lessons?.length || 0) - 1) {
|
|
7480
7500
|
r.current.currentLessonIndex += 1, r.current.currentQuestionIndex = 0, r.current.lessonCompleted = !1, r.current.isQuestionMode = !1, r.current.isTeaching = !1, r.current.score = 0, r.current.totalQuestions = 0;
|
|
7481
|
-
const C = b.modules[r.current.currentModuleIndex], V = r.current.currentLessonIndex < (C?.lessons?.length || 0) - 1,
|
|
7501
|
+
const C = b.modules[r.current.currentModuleIndex], V = r.current.currentLessonIndex < (C?.lessons?.length || 0) - 1, ne = r.current.currentModuleIndex < (b.modules?.length || 0) - 1, ie = V || ne;
|
|
7482
7502
|
c.current.onCustomAction({
|
|
7483
7503
|
type: "lessonStart",
|
|
7484
7504
|
moduleIndex: r.current.currentModuleIndex,
|
|
@@ -7487,32 +7507,32 @@ const ht = Ie(({
|
|
|
7487
7507
|
}), c.current.onLessonStart({
|
|
7488
7508
|
moduleIndex: r.current.currentModuleIndex,
|
|
7489
7509
|
lessonIndex: r.current.currentLessonIndex,
|
|
7490
|
-
lesson:
|
|
7510
|
+
lesson: R()
|
|
7491
7511
|
}), h.current && (h.current.setMood("happy"), h.current.setBodyMovement("idle"));
|
|
7492
7512
|
} else if (r.current.currentModuleIndex < (b.modules?.length || 0) - 1) {
|
|
7493
7513
|
r.current.currentModuleIndex += 1, r.current.currentLessonIndex = 0, r.current.currentQuestionIndex = 0, r.current.lessonCompleted = !1, r.current.isQuestionMode = !1, r.current.isTeaching = !1, r.current.score = 0, r.current.totalQuestions = 0;
|
|
7494
|
-
const V = b.modules[r.current.currentModuleIndex],
|
|
7514
|
+
const V = b.modules[r.current.currentModuleIndex], ne = r.current.currentLessonIndex < (V?.lessons?.length || 0) - 1, ie = r.current.currentModuleIndex < (b.modules?.length || 0) - 1, fe = ne || ie;
|
|
7495
7515
|
c.current.onCustomAction({
|
|
7496
7516
|
type: "lessonStart",
|
|
7497
7517
|
moduleIndex: r.current.currentModuleIndex,
|
|
7498
7518
|
lessonIndex: r.current.currentLessonIndex,
|
|
7499
|
-
hasNextLesson:
|
|
7519
|
+
hasNextLesson: fe
|
|
7500
7520
|
}), c.current.onLessonStart({
|
|
7501
7521
|
moduleIndex: r.current.currentModuleIndex,
|
|
7502
7522
|
lessonIndex: r.current.currentLessonIndex,
|
|
7503
|
-
lesson:
|
|
7523
|
+
lesson: R()
|
|
7504
7524
|
}), h.current && (h.current.setMood("happy"), h.current.setBodyMovement("idle"));
|
|
7505
7525
|
} else
|
|
7506
7526
|
I.current && I.current();
|
|
7507
|
-
}, []),
|
|
7508
|
-
const b =
|
|
7509
|
-
let
|
|
7527
|
+
}, []), X = T(() => {
|
|
7528
|
+
const b = R();
|
|
7529
|
+
let v = null;
|
|
7510
7530
|
if (b?.avatar_script && b?.body) {
|
|
7511
7531
|
const w = b.avatar_script.trim(), C = b.body.trim(), V = w.match(/[.!?]$/) ? " " : ". ";
|
|
7512
|
-
|
|
7532
|
+
v = `${w}${V}${C}`;
|
|
7513
7533
|
} else
|
|
7514
|
-
|
|
7515
|
-
if (h.current && h.current.isReady &&
|
|
7534
|
+
v = b?.avatar_script || b?.body || null;
|
|
7535
|
+
if (h.current && h.current.isReady && v) {
|
|
7516
7536
|
r.current.isTeaching = !0, r.current.isQuestionMode = !1, r.current.score = 0, r.current.totalQuestions = 0, h.current.setMood("happy");
|
|
7517
7537
|
let w = !1;
|
|
7518
7538
|
if (e.teaching)
|
|
@@ -7532,7 +7552,7 @@ const ht = Ie(({
|
|
|
7532
7552
|
moduleIndex: r.current.currentModuleIndex,
|
|
7533
7553
|
lessonIndex: r.current.currentLessonIndex,
|
|
7534
7554
|
lesson: b
|
|
7535
|
-
}), h.current.speakText(
|
|
7555
|
+
}), h.current.speakText(v, {
|
|
7536
7556
|
lipsyncLang: C.lipsyncLang,
|
|
7537
7557
|
onSpeechEnd: () => {
|
|
7538
7558
|
r.current.isTeaching = !1, c.current.onCustomAction({
|
|
@@ -7545,15 +7565,15 @@ const ht = Ie(({
|
|
|
7545
7565
|
}
|
|
7546
7566
|
});
|
|
7547
7567
|
}
|
|
7548
|
-
}, [e.teaching,
|
|
7549
|
-
const
|
|
7568
|
+
}, [e.teaching, R]), j = T((b) => {
|
|
7569
|
+
const v = M(), w = P(b, v);
|
|
7550
7570
|
if (w && (r.current.score += 1), c.current.onQuestionAnswer({
|
|
7551
7571
|
moduleIndex: r.current.currentModuleIndex,
|
|
7552
7572
|
lessonIndex: r.current.currentLessonIndex,
|
|
7553
7573
|
questionIndex: r.current.currentQuestionIndex,
|
|
7554
7574
|
answer: b,
|
|
7555
7575
|
isCorrect: w,
|
|
7556
|
-
question:
|
|
7576
|
+
question: v
|
|
7557
7577
|
}), h.current)
|
|
7558
7578
|
if (w) {
|
|
7559
7579
|
if (h.current.setMood("happy"), e.correct)
|
|
@@ -7563,11 +7583,11 @@ const ht = Ie(({
|
|
|
7563
7583
|
h.current.setBodyMovement("happy");
|
|
7564
7584
|
}
|
|
7565
7585
|
h.current.setBodyMovement("gesturing");
|
|
7566
|
-
const C =
|
|
7586
|
+
const C = v.type === "code_test" ? `Great job! Your code passed all the tests! ${v.explanation || ""}` : `Excellent! That's correct! ${v.explanation || ""}`, V = z.current || { lipsyncLang: "en" };
|
|
7567
7587
|
h.current.speakText(C, {
|
|
7568
7588
|
lipsyncLang: V.lipsyncLang,
|
|
7569
7589
|
onSpeechEnd: () => {
|
|
7570
|
-
const ie =
|
|
7590
|
+
const ie = R()?.questions?.length || 0;
|
|
7571
7591
|
c.current.onCustomAction({
|
|
7572
7592
|
type: "answerFeedbackComplete",
|
|
7573
7593
|
moduleIndex: r.current.currentModuleIndex,
|
|
@@ -7588,11 +7608,11 @@ const ht = Ie(({
|
|
|
7588
7608
|
h.current.setBodyMovement("idle");
|
|
7589
7609
|
}
|
|
7590
7610
|
h.current.setBodyMovement("gesturing");
|
|
7591
|
-
const C =
|
|
7611
|
+
const C = v.type === "code_test" ? `Your code didn't pass all the tests. ${v.explanation || "Try again!"}` : `Not quite right, but don't worry! ${v.explanation || ""} Let's move on to the next question.`, V = z.current || { lipsyncLang: "en" };
|
|
7592
7612
|
h.current.speakText(C, {
|
|
7593
7613
|
lipsyncLang: V.lipsyncLang,
|
|
7594
7614
|
onSpeechEnd: () => {
|
|
7595
|
-
const ie =
|
|
7615
|
+
const ie = R()?.questions?.length || 0;
|
|
7596
7616
|
c.current.onCustomAction({
|
|
7597
7617
|
type: "answerFeedbackComplete",
|
|
7598
7618
|
moduleIndex: r.current.currentModuleIndex,
|
|
@@ -7607,7 +7627,7 @@ const ht = Ie(({
|
|
|
7607
7627
|
});
|
|
7608
7628
|
}
|
|
7609
7629
|
else {
|
|
7610
|
-
const V =
|
|
7630
|
+
const V = R()?.questions?.length || 0;
|
|
7611
7631
|
c.current.onCustomAction({
|
|
7612
7632
|
type: "answerFeedbackComplete",
|
|
7613
7633
|
moduleIndex: r.current.currentModuleIndex,
|
|
@@ -7620,13 +7640,13 @@ const ht = Ie(({
|
|
|
7620
7640
|
avatarNotReady: !0
|
|
7621
7641
|
});
|
|
7622
7642
|
}
|
|
7623
|
-
}, [e.correct, e.incorrect,
|
|
7624
|
-
const
|
|
7643
|
+
}, [e.correct, e.incorrect, M, R, P]), K = T((b) => {
|
|
7644
|
+
const v = M();
|
|
7625
7645
|
if (!b || typeof b != "object") {
|
|
7626
7646
|
console.error("Invalid code test result format. Expected object with {passed: boolean, ...}");
|
|
7627
7647
|
return;
|
|
7628
7648
|
}
|
|
7629
|
-
if (
|
|
7649
|
+
if (v?.type !== "code_test") {
|
|
7630
7650
|
console.warn("Current question is not a code test. Use handleAnswerSelect for other question types.");
|
|
7631
7651
|
return;
|
|
7632
7652
|
}
|
|
@@ -7646,12 +7666,12 @@ const ht = Ie(({
|
|
|
7646
7666
|
lessonIndex: r.current.currentLessonIndex,
|
|
7647
7667
|
questionIndex: r.current.currentQuestionIndex,
|
|
7648
7668
|
testResult: w,
|
|
7649
|
-
question:
|
|
7669
|
+
question: v
|
|
7650
7670
|
}), p.current && p.current(w);
|
|
7651
|
-
}, [
|
|
7671
|
+
}, [M, P]), te = T(() => {
|
|
7652
7672
|
if (r.current.currentQuestionIndex > 0) {
|
|
7653
7673
|
r.current.currentQuestionIndex -= 1;
|
|
7654
|
-
const b =
|
|
7674
|
+
const b = M();
|
|
7655
7675
|
b && c.current.onCustomAction({
|
|
7656
7676
|
type: "questionStart",
|
|
7657
7677
|
moduleIndex: r.current.currentModuleIndex,
|
|
@@ -7661,7 +7681,7 @@ const ht = Ie(({
|
|
|
7661
7681
|
question: b,
|
|
7662
7682
|
score: r.current.score
|
|
7663
7683
|
});
|
|
7664
|
-
const
|
|
7684
|
+
const v = () => {
|
|
7665
7685
|
if (!h.current || !b) return;
|
|
7666
7686
|
h.current.setMood("happy"), h.current.setBodyMovement("idle");
|
|
7667
7687
|
const w = z.current || { lipsyncLang: "en" };
|
|
@@ -7672,17 +7692,17 @@ const ht = Ie(({
|
|
|
7672
7692
|
});
|
|
7673
7693
|
};
|
|
7674
7694
|
if (h.current && h.current.isReady && b)
|
|
7675
|
-
|
|
7695
|
+
v();
|
|
7676
7696
|
else if (b) {
|
|
7677
7697
|
const w = setInterval(() => {
|
|
7678
|
-
h.current && h.current.isReady && (clearInterval(w),
|
|
7698
|
+
h.current && h.current.isReady && (clearInterval(w), v());
|
|
7679
7699
|
}, 100);
|
|
7680
7700
|
setTimeout(() => {
|
|
7681
7701
|
clearInterval(w);
|
|
7682
7702
|
}, 5e3);
|
|
7683
7703
|
}
|
|
7684
7704
|
}
|
|
7685
|
-
}, [
|
|
7705
|
+
}, [M]), ce = T(() => {
|
|
7686
7706
|
const b = H.current || { modules: [] };
|
|
7687
7707
|
if (b.modules[r.current.currentModuleIndex], r.current.currentLessonIndex > 0)
|
|
7688
7708
|
r.current.currentLessonIndex -= 1, r.current.currentQuestionIndex = 0, r.current.lessonCompleted = !1, r.current.isQuestionMode = !1, r.current.isTeaching = !1, r.current.score = 0, r.current.totalQuestions = 0, c.current.onCustomAction({
|
|
@@ -7692,7 +7712,7 @@ const ht = Ie(({
|
|
|
7692
7712
|
}), c.current.onLessonStart({
|
|
7693
7713
|
moduleIndex: r.current.currentModuleIndex,
|
|
7694
7714
|
lessonIndex: r.current.currentLessonIndex,
|
|
7695
|
-
lesson:
|
|
7715
|
+
lesson: R()
|
|
7696
7716
|
}), h.current && (h.current.setMood("happy"), h.current.setBodyMovement("idle"));
|
|
7697
7717
|
else if (r.current.currentModuleIndex > 0) {
|
|
7698
7718
|
const C = b.modules[r.current.currentModuleIndex - 1];
|
|
@@ -7703,53 +7723,53 @@ const ht = Ie(({
|
|
|
7703
7723
|
}), c.current.onLessonStart({
|
|
7704
7724
|
moduleIndex: r.current.currentModuleIndex,
|
|
7705
7725
|
lessonIndex: r.current.currentLessonIndex,
|
|
7706
|
-
lesson:
|
|
7726
|
+
lesson: R()
|
|
7707
7727
|
}), h.current && (h.current.setMood("happy"), h.current.setBodyMovement("idle"));
|
|
7708
7728
|
}
|
|
7709
|
-
}, [
|
|
7729
|
+
}, [R]), oe = T(() => {
|
|
7710
7730
|
r.current.currentModuleIndex = 0, r.current.currentLessonIndex = 0, r.current.currentQuestionIndex = 0, r.current.isTeaching = !1, r.current.isQuestionMode = !1, r.current.lessonCompleted = !1, r.current.curriculumCompleted = !1, r.current.score = 0, r.current.totalQuestions = 0;
|
|
7711
|
-
}, []),
|
|
7731
|
+
}, []), pe = T((b) => {
|
|
7712
7732
|
console.log("Avatar is ready!", b);
|
|
7713
|
-
const
|
|
7733
|
+
const v = R(), w = v?.avatar_script || v?.body;
|
|
7714
7734
|
u && w && setTimeout(() => {
|
|
7715
7735
|
d.current && d.current();
|
|
7716
7736
|
}, 10);
|
|
7717
|
-
}, [u,
|
|
7718
|
-
|
|
7719
|
-
d.current =
|
|
7737
|
+
}, [u, R]);
|
|
7738
|
+
We(() => {
|
|
7739
|
+
d.current = X, g.current = Z, y.current = ee, x.current = N, I.current = re, D.current = S, p.current = j;
|
|
7720
7740
|
}), Le(a, () => ({
|
|
7721
7741
|
// Curriculum control methods
|
|
7722
|
-
startTeaching:
|
|
7742
|
+
startTeaching: X,
|
|
7723
7743
|
startQuestions: S,
|
|
7724
|
-
handleAnswerSelect:
|
|
7725
|
-
handleCodeTestResult:
|
|
7726
|
-
nextQuestion:
|
|
7727
|
-
previousQuestion:
|
|
7728
|
-
nextLesson:
|
|
7744
|
+
handleAnswerSelect: j,
|
|
7745
|
+
handleCodeTestResult: K,
|
|
7746
|
+
nextQuestion: N,
|
|
7747
|
+
previousQuestion: te,
|
|
7748
|
+
nextLesson: Z,
|
|
7729
7749
|
previousLesson: ce,
|
|
7730
|
-
completeLesson:
|
|
7731
|
-
completeCurriculum:
|
|
7732
|
-
resetCurriculum:
|
|
7750
|
+
completeLesson: ee,
|
|
7751
|
+
completeCurriculum: re,
|
|
7752
|
+
resetCurriculum: oe,
|
|
7733
7753
|
getState: () => ({ ...r.current }),
|
|
7734
|
-
getCurrentQuestion: () =>
|
|
7735
|
-
getCurrentLesson: () =>
|
|
7754
|
+
getCurrentQuestion: () => M(),
|
|
7755
|
+
getCurrentLesson: () => R(),
|
|
7736
7756
|
// Direct access to avatar ref (always returns current value)
|
|
7737
7757
|
getAvatarRef: () => h.current,
|
|
7738
7758
|
// Convenience methods that delegate to avatar (always check current ref)
|
|
7739
|
-
speakText: async (b,
|
|
7759
|
+
speakText: async (b, v = {}) => {
|
|
7740
7760
|
await h.current?.resumeAudioContext?.();
|
|
7741
7761
|
const w = z.current || { lipsyncLang: "en" };
|
|
7742
|
-
h.current?.speakText(b, { ...
|
|
7762
|
+
h.current?.speakText(b, { ...v, lipsyncLang: v.lipsyncLang || w.lipsyncLang });
|
|
7743
7763
|
},
|
|
7744
7764
|
resumeAudioContext: async () => {
|
|
7745
7765
|
if (h.current?.resumeAudioContext)
|
|
7746
7766
|
return await h.current.resumeAudioContext();
|
|
7747
7767
|
const b = h.current?.talkingHead;
|
|
7748
7768
|
if (b?.audioCtx) {
|
|
7749
|
-
const
|
|
7750
|
-
if (
|
|
7769
|
+
const v = b.audioCtx;
|
|
7770
|
+
if (v.state === "suspended" || v.state === "interrupted")
|
|
7751
7771
|
try {
|
|
7752
|
-
await
|
|
7772
|
+
await v.resume(), console.log("Audio context resumed via talkingHead");
|
|
7753
7773
|
} catch (w) {
|
|
7754
7774
|
console.warn("Failed to resume audio context:", w);
|
|
7755
7775
|
}
|
|
@@ -7761,7 +7781,7 @@ const ht = Ie(({
|
|
|
7761
7781
|
resumeSpeaking: async () => await h.current?.resumeSpeaking(),
|
|
7762
7782
|
isPaused: () => h.current && typeof h.current.isPaused < "u" ? h.current.isPaused : !1,
|
|
7763
7783
|
setMood: (b) => h.current?.setMood(b),
|
|
7764
|
-
playAnimation: (b,
|
|
7784
|
+
playAnimation: (b, v) => h.current?.playAnimation(b, v),
|
|
7765
7785
|
setBodyMovement: (b) => h.current?.setBodyMovement(b),
|
|
7766
7786
|
setMovementIntensity: (b) => h.current?.setMovementIntensity(b),
|
|
7767
7787
|
playRandomDance: () => h.current?.playRandomDance(),
|
|
@@ -7772,10 +7792,10 @@ const ht = Ie(({
|
|
|
7772
7792
|
lockAvatarPosition: () => h.current?.lockAvatarPosition(),
|
|
7773
7793
|
unlockAvatarPosition: () => h.current?.unlockAvatarPosition(),
|
|
7774
7794
|
// Custom action trigger
|
|
7775
|
-
triggerCustomAction: (b,
|
|
7795
|
+
triggerCustomAction: (b, v) => {
|
|
7776
7796
|
c.current.onCustomAction({
|
|
7777
7797
|
type: b,
|
|
7778
|
-
...
|
|
7798
|
+
...v,
|
|
7779
7799
|
state: { ...r.current }
|
|
7780
7800
|
});
|
|
7781
7801
|
},
|
|
@@ -7783,8 +7803,8 @@ const ht = Ie(({
|
|
|
7783
7803
|
handleResize: () => h.current?.handleResize(),
|
|
7784
7804
|
// Avatar readiness check (always returns current value)
|
|
7785
7805
|
isAvatarReady: () => h.current?.isReady || !1
|
|
7786
|
-
}), [
|
|
7787
|
-
const
|
|
7806
|
+
}), [X, S, j, K, N, Z, ee, re, oe, M, R]);
|
|
7807
|
+
const J = z.current || {
|
|
7788
7808
|
avatarUrl: "/avatars/brunette.glb",
|
|
7789
7809
|
avatarBody: "F",
|
|
7790
7810
|
mood: "happy",
|
|
@@ -7797,23 +7817,23 @@ const ht = Ie(({
|
|
|
7797
7817
|
showFullAvatar: !1,
|
|
7798
7818
|
animations: e
|
|
7799
7819
|
};
|
|
7800
|
-
return /* @__PURE__ */
|
|
7801
|
-
|
|
7820
|
+
return /* @__PURE__ */ ue("div", { style: { width: "100%", height: "100%" }, children: /* @__PURE__ */ ue(
|
|
7821
|
+
Pe,
|
|
7802
7822
|
{
|
|
7803
7823
|
ref: h,
|
|
7804
|
-
avatarUrl:
|
|
7805
|
-
avatarBody:
|
|
7806
|
-
mood:
|
|
7807
|
-
ttsLang:
|
|
7808
|
-
ttsService:
|
|
7809
|
-
ttsVoice:
|
|
7810
|
-
ttsApiKey:
|
|
7811
|
-
bodyMovement:
|
|
7812
|
-
movementIntensity:
|
|
7813
|
-
showFullAvatar:
|
|
7824
|
+
avatarUrl: J.avatarUrl,
|
|
7825
|
+
avatarBody: J.avatarBody,
|
|
7826
|
+
mood: J.mood,
|
|
7827
|
+
ttsLang: J.ttsLang,
|
|
7828
|
+
ttsService: J.ttsService,
|
|
7829
|
+
ttsVoice: J.ttsVoice,
|
|
7830
|
+
ttsApiKey: J.ttsApiKey,
|
|
7831
|
+
bodyMovement: J.bodyMovement,
|
|
7832
|
+
movementIntensity: J.movementIntensity,
|
|
7833
|
+
showFullAvatar: J.showFullAvatar,
|
|
7814
7834
|
cameraView: "upper",
|
|
7815
|
-
animations:
|
|
7816
|
-
onReady:
|
|
7835
|
+
animations: J.animations,
|
|
7836
|
+
onReady: pe,
|
|
7817
7837
|
onLoading: () => {
|
|
7818
7838
|
},
|
|
7819
7839
|
onError: (b) => {
|
|
@@ -7822,8 +7842,8 @@ const ht = Ie(({
|
|
|
7822
7842
|
}
|
|
7823
7843
|
) });
|
|
7824
7844
|
});
|
|
7825
|
-
|
|
7826
|
-
const
|
|
7845
|
+
ct.displayName = "CurriculumLearning";
|
|
7846
|
+
const Be = {
|
|
7827
7847
|
// Code-based dance animations (no FBX required)
|
|
7828
7848
|
dance: {
|
|
7829
7849
|
name: "dance",
|
|
@@ -7926,14 +7946,14 @@ const Pe = {
|
|
|
7926
7946
|
duration: 5e3,
|
|
7927
7947
|
description: "Excited, energetic movement"
|
|
7928
7948
|
}
|
|
7929
|
-
},
|
|
7949
|
+
}, It = (O) => Be[O] || null, Lt = (O) => Be.hasOwnProperty(O);
|
|
7930
7950
|
export {
|
|
7931
|
-
|
|
7932
|
-
|
|
7933
|
-
|
|
7934
|
-
|
|
7951
|
+
ct as CurriculumLearning,
|
|
7952
|
+
Pe as TalkingHeadAvatar,
|
|
7953
|
+
ut as TalkingHeadComponent,
|
|
7954
|
+
Be as animations,
|
|
7935
7955
|
Ae as getActiveTTSConfig,
|
|
7936
|
-
|
|
7937
|
-
|
|
7938
|
-
|
|
7956
|
+
It as getAnimation,
|
|
7957
|
+
Rt as getVoiceOptions,
|
|
7958
|
+
Lt as hasAnimation
|
|
7939
7959
|
};
|