@mml-io/3d-web-avatar 0.12.1 → 0.13.0
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.
@@ -1,6 +1,7 @@
|
|
1
1
|
import { Object3D } from "three";
|
2
|
+
import { MMLCharacterDescriptionPart } from "../helpers/parseMMLDescription";
|
2
3
|
import { ModelLoader } from "./ModelLoader";
|
3
|
-
export declare class
|
4
|
+
export declare class MMLCharacter {
|
4
5
|
private modelLoader;
|
5
6
|
private skeletonHelpers;
|
6
7
|
private skinnedMeshesParent;
|
@@ -9,5 +10,5 @@ export declare class Character {
|
|
9
10
|
constructor(modelLoader: ModelLoader);
|
10
11
|
private createBoneIndexMap;
|
11
12
|
private remapBoneIndices;
|
12
|
-
mergeBodyParts(fullBodyURL: string, bodyParts: Array<
|
13
|
+
mergeBodyParts(fullBodyURL: string, bodyParts: Array<MMLCharacterDescriptionPart>): Promise<Object3D>;
|
13
14
|
}
|
@@ -1,6 +1,24 @@
|
|
1
1
|
export type MMLCharacterDescriptionPart = {
|
2
2
|
url: string;
|
3
3
|
type?: string;
|
4
|
+
socket?: {
|
5
|
+
socket: string;
|
6
|
+
position: {
|
7
|
+
x: number;
|
8
|
+
y: number;
|
9
|
+
z: number;
|
10
|
+
};
|
11
|
+
scale: {
|
12
|
+
x: number;
|
13
|
+
y: number;
|
14
|
+
z: number;
|
15
|
+
};
|
16
|
+
rotation: {
|
17
|
+
x: number;
|
18
|
+
y: number;
|
19
|
+
z: number;
|
20
|
+
};
|
21
|
+
};
|
4
22
|
};
|
5
23
|
export type MMLCharacterDescription = {
|
6
24
|
base: MMLCharacterDescriptionPart;
|
package/build/index.d.ts
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
export {
|
1
|
+
export { MMLCharacter } from "./character/MMLCharacter";
|
2
2
|
export { cloneModel } from "./helpers/SkeletonHelpers";
|
3
3
|
export { TimeManagerInterface } from "./character/types";
|
4
4
|
export { ModelLoader } from "./character/ModelLoader";
|
package/build/index.js
CHANGED
@@ -1,6 +1,9 @@
|
|
1
|
-
// src/character/
|
1
|
+
// src/character/MMLCharacter.ts
|
2
2
|
import {
|
3
|
-
BufferAttribute
|
3
|
+
BufferAttribute,
|
4
|
+
Euler,
|
5
|
+
MathUtils,
|
6
|
+
Vector3
|
4
7
|
} from "three";
|
5
8
|
|
6
9
|
// src/helpers/SkeletonHelpers.ts
|
@@ -121,6 +124,10 @@ var SkeletonHelpers = class {
|
|
121
124
|
const cloneSkinnedMeshes = {};
|
122
125
|
let hierarchyCheck = false;
|
123
126
|
clone2.scene.traverse((node) => {
|
127
|
+
if (node.isMesh || node.isSkinnedMesh) {
|
128
|
+
node.castShadow = true;
|
129
|
+
node.receiveShadow = true;
|
130
|
+
}
|
124
131
|
if (node.type === "Bone") {
|
125
132
|
if (hierarchyCheck === false) {
|
126
133
|
hierarchyCheck = true;
|
@@ -157,8 +164,8 @@ var SkeletonHelpers = class {
|
|
157
164
|
}
|
158
165
|
};
|
159
166
|
|
160
|
-
// src/character/
|
161
|
-
var
|
167
|
+
// src/character/MMLCharacter.ts
|
168
|
+
var MMLCharacter = class {
|
162
169
|
constructor(modelLoader) {
|
163
170
|
this.modelLoader = modelLoader;
|
164
171
|
this.skeletonHelpers = new SkeletonHelpers();
|
@@ -201,19 +208,22 @@ var Character = class {
|
|
201
208
|
async mergeBodyParts(fullBodyURL, bodyParts) {
|
202
209
|
const fullBodyAsset = await this.modelLoader.load(fullBodyURL);
|
203
210
|
const fullBodyGLTF = this.skeletonHelpers.cloneGLTF(fullBodyAsset, "fullBody");
|
204
|
-
const assetPromises = bodyParts.map(
|
205
|
-
(
|
206
|
-
|
207
|
-
|
208
|
-
resolve({ asset, partUrl });
|
209
|
-
});
|
211
|
+
const assetPromises = bodyParts.map((part) => {
|
212
|
+
return new Promise((resolve) => {
|
213
|
+
this.modelLoader.load(part.url).then((asset) => {
|
214
|
+
resolve({ asset, part });
|
210
215
|
});
|
211
|
-
}
|
212
|
-
);
|
216
|
+
});
|
217
|
+
});
|
213
218
|
const assets = await Promise.all(assetPromises);
|
214
219
|
const fullBodyModelGroup = fullBodyGLTF.gltf.scene;
|
215
220
|
this.skinnedMeshesParent = null;
|
221
|
+
const availableBones = /* @__PURE__ */ new Map();
|
216
222
|
fullBodyModelGroup.traverse((child) => {
|
223
|
+
const asBone = child;
|
224
|
+
if (asBone.isBone) {
|
225
|
+
availableBones.set(child.name, asBone);
|
226
|
+
}
|
217
227
|
const asSkinnedMesh = child;
|
218
228
|
if (asSkinnedMesh.isSkinnedMesh) {
|
219
229
|
asSkinnedMesh.castShadow = true;
|
@@ -226,20 +236,54 @@ var Character = class {
|
|
226
236
|
this.sharedSkeleton = fullBodyGLTF.sharedSkeleton;
|
227
237
|
this.sharedMatrixWorld = fullBodyGLTF.matrixWorld;
|
228
238
|
for (const loadingAsset of assets) {
|
229
|
-
const
|
239
|
+
const part = loadingAsset.part;
|
240
|
+
const gltf = this.skeletonHelpers.cloneGLTF(loadingAsset.asset, part.url);
|
230
241
|
const modelGroup = gltf.gltf.scene;
|
231
|
-
|
232
|
-
|
233
|
-
|
234
|
-
if (
|
235
|
-
|
236
|
-
|
237
|
-
|
238
|
-
|
239
|
-
|
240
|
-
(_a = this.skinnedMeshesParent) == null ? void 0 : _a.add(skinnedMeshClone);
|
242
|
+
if (part.socket) {
|
243
|
+
const socketName = part.socket.socket;
|
244
|
+
let bone = availableBones.get("root");
|
245
|
+
if (availableBones.has(socketName)) {
|
246
|
+
bone = availableBones.get(socketName);
|
247
|
+
} else {
|
248
|
+
console.warn(
|
249
|
+
`WARNING: no bone found for [${socketName}] socket. Attatching to Root bone`
|
250
|
+
);
|
241
251
|
}
|
242
|
-
|
252
|
+
if (bone) {
|
253
|
+
modelGroup.position.set(0, 0, 0);
|
254
|
+
modelGroup.rotation.set(0, 0, 0);
|
255
|
+
modelGroup.scale.set(1, 1, 1);
|
256
|
+
bone.add(modelGroup);
|
257
|
+
modelGroup.rotateZ(-Math.PI / 2);
|
258
|
+
const offsetPosition = new Vector3(
|
259
|
+
part.socket.position.x,
|
260
|
+
part.socket.position.y,
|
261
|
+
part.socket.position.z
|
262
|
+
);
|
263
|
+
modelGroup.position.copy(offsetPosition);
|
264
|
+
const offsetRotation = new Euler(
|
265
|
+
MathUtils.degToRad(part.socket.rotation.x),
|
266
|
+
MathUtils.degToRad(part.socket.rotation.y),
|
267
|
+
MathUtils.degToRad(part.socket.rotation.z)
|
268
|
+
);
|
269
|
+
modelGroup.setRotationFromEuler(offsetRotation);
|
270
|
+
modelGroup.scale.set(part.socket.scale.x, part.socket.scale.y, part.socket.scale.z);
|
271
|
+
}
|
272
|
+
} else {
|
273
|
+
modelGroup.traverse((child) => {
|
274
|
+
var _a;
|
275
|
+
const asSkinnedMesh = child;
|
276
|
+
if (asSkinnedMesh.isSkinnedMesh) {
|
277
|
+
const skinnedMeshClone = child.clone(true);
|
278
|
+
this.remapBoneIndices(skinnedMeshClone);
|
279
|
+
skinnedMeshClone.castShadow = true;
|
280
|
+
skinnedMeshClone.receiveShadow = true;
|
281
|
+
skinnedMeshClone.bind(this.sharedSkeleton, this.sharedMatrixWorld);
|
282
|
+
skinnedMeshClone.children = [];
|
283
|
+
(_a = this.skinnedMeshesParent) == null ? void 0 : _a.add(skinnedMeshClone);
|
284
|
+
}
|
285
|
+
});
|
286
|
+
}
|
243
287
|
}
|
244
288
|
return fullBodyGLTF.gltf.scene;
|
245
289
|
}
|
@@ -393,7 +437,24 @@ var parseMMLDescription = (mmlDescription) => {
|
|
393
437
|
);
|
394
438
|
parts = directModelChildren.map((model) => {
|
395
439
|
const partSrc = model.getAttribute("src") ?? "";
|
396
|
-
|
440
|
+
const socketAttr = model.getAttribute("socket");
|
441
|
+
const position = {
|
442
|
+
x: parseFloat(model.getAttribute("x") ?? "0") || 0,
|
443
|
+
y: parseFloat(model.getAttribute("y") ?? "0") || 0,
|
444
|
+
z: parseFloat(model.getAttribute("z") ?? "0") || 0
|
445
|
+
};
|
446
|
+
const scale = {
|
447
|
+
x: parseFloat(model.getAttribute("sx") ?? "1") || 1,
|
448
|
+
y: parseFloat(model.getAttribute("sy") ?? "1") || 1,
|
449
|
+
z: parseFloat(model.getAttribute("sz") ?? "1") || 1
|
450
|
+
};
|
451
|
+
const rotation = {
|
452
|
+
x: parseFloat(model.getAttribute("rx") ?? "0") || 0,
|
453
|
+
y: parseFloat(model.getAttribute("ry") ?? "0") || 0,
|
454
|
+
z: parseFloat(model.getAttribute("rz") ?? "0") || 0
|
455
|
+
};
|
456
|
+
const socketObj = socketAttr ? { socket: socketAttr, position, scale, rotation } : void 0;
|
457
|
+
return { url: partSrc, socket: socketObj };
|
397
458
|
});
|
398
459
|
const wrappedModelTags = Array.from(doc.querySelectorAll("m-character m-model")).filter(
|
399
460
|
(model) => !directModelChildren.includes(model)
|
@@ -425,7 +486,7 @@ var createMMLCharacterString = (characterDescription) => {
|
|
425
486
|
</m-character>`;
|
426
487
|
};
|
427
488
|
export {
|
428
|
-
|
489
|
+
MMLCharacter,
|
429
490
|
ModelLoader,
|
430
491
|
cloneModel,
|
431
492
|
createMMLCharacterString,
|
package/build/index.js.map
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
{
|
2
2
|
"version": 3,
|
3
|
-
"sources": ["../src/character/
|
4
|
-
"sourcesContent": ["import {\n BoxHelper,\n BufferAttribute,\n Group,\n Matrix4,\n MeshStandardMaterial,\n Object3D,\n Skeleton,\n SkinnedMesh,\n} from \"three\";\nimport { GLTF } from \"three/examples/jsm/loaders/GLTFLoader.js\";\n\nimport { SkeletonHelpers } from \"../helpers/SkeletonHelpers\";\n\nimport { ModelLoader } from \"./ModelLoader\";\n\nexport class Character {\n private skeletonHelpers: SkeletonHelpers = new SkeletonHelpers();\n private skinnedMeshesParent: Group | null = null;\n private sharedSkeleton: Skeleton | null = null;\n private sharedMatrixWorld: Matrix4 | null = null;\n\n constructor(private modelLoader: ModelLoader) {}\n\n private createBoneIndexMap(\n originSkeleton: Skeleton,\n targetSkeleton: Skeleton,\n ): Map<number, number> {\n const boneIndexMap = new Map<number, number>();\n\n for (let i = 0; i < originSkeleton.bones.length; i++) {\n const originBone = originSkeleton.bones[i];\n const targetBone = targetSkeleton.bones.find((bone) => bone.name === originBone.name);\n if (targetBone) {\n boneIndexMap.set(i, targetSkeleton.bones.indexOf(targetBone));\n }\n }\n return boneIndexMap;\n }\n\n private remapBoneIndices(skinnedMesh: SkinnedMesh): void {\n const targetSkeleton = this.sharedSkeleton!;\n const originSkeleton = skinnedMesh.skeleton;\n const originGeometry = skinnedMesh.geometry;\n\n const boneIndexMap = this.createBoneIndexMap(originSkeleton, targetSkeleton);\n\n const newSkinIndexArray = [];\n for (let i = 0; i < originGeometry.attributes.skinIndex.array.length; i++) {\n const originIndex = originGeometry.attributes.skinIndex.array[i];\n const targetIndex = boneIndexMap.get(originIndex);\n if (targetIndex !== undefined) {\n newSkinIndexArray.push(targetIndex);\n } else {\n console.error(\"Missing bone index\", originIndex);\n newSkinIndexArray.push(0);\n }\n }\n skinnedMesh.geometry.attributes.skinIndex = new BufferAttribute(\n new Uint8Array(newSkinIndexArray),\n 4,\n );\n }\n\n public async mergeBodyParts(fullBodyURL: string, bodyParts: Array<string>): Promise<Object3D> {\n const fullBodyAsset = await this.modelLoader.load(fullBodyURL);\n const fullBodyGLTF = this.skeletonHelpers.cloneGLTF(fullBodyAsset as GLTF, \"fullBody\");\n\n const assetPromises: Array<Promise<{ asset: GLTF; partUrl: string }>> = bodyParts.map(\n (partUrl) => {\n return new Promise((resolve) => {\n this.modelLoader.load(partUrl).then((asset) => {\n resolve({ asset: asset!, partUrl });\n });\n });\n },\n );\n const assets = await Promise.all(assetPromises);\n\n const fullBodyModelGroup = fullBodyGLTF.gltf.scene;\n\n this.skinnedMeshesParent = null;\n\n fullBodyModelGroup.traverse((child) => {\n const asSkinnedMesh = child as SkinnedMesh;\n if (asSkinnedMesh.isSkinnedMesh) {\n asSkinnedMesh.castShadow = true;\n asSkinnedMesh.receiveShadow = true;\n if (this.skinnedMeshesParent === null) {\n this.skinnedMeshesParent = asSkinnedMesh.parent as Group;\n }\n }\n });\n this.sharedSkeleton = fullBodyGLTF.sharedSkeleton;\n this.sharedMatrixWorld = fullBodyGLTF.matrixWorld;\n\n for (const loadingAsset of assets) {\n const gltf = this.skeletonHelpers.cloneGLTF(loadingAsset.asset, loadingAsset.partUrl);\n const modelGroup = gltf.gltf.scene;\n modelGroup.traverse((child) => {\n const asSkinnedMesh = child as SkinnedMesh;\n if (asSkinnedMesh.type === \"SkinnedMesh\") {\n const skinnedMeshClone = child.clone(true) as SkinnedMesh;\n this.remapBoneIndices(skinnedMeshClone);\n skinnedMeshClone.castShadow = true;\n skinnedMeshClone.receiveShadow = true;\n skinnedMeshClone.bind(this.sharedSkeleton!, this.sharedMatrixWorld!);\n this.skinnedMeshesParent?.add(skinnedMeshClone);\n }\n });\n }\n return fullBodyGLTF!.gltf.scene as Object3D;\n }\n}\n", "import { Bone, Group, Matrix4, Object3D, Skeleton, SkinnedMesh } from \"three\";\nimport { GLTF } from \"three/examples/jsm/loaders/GLTFLoader.js\";\nimport * as SkeletonUtils from \"three/examples/jsm/utils/SkeletonUtils.js\";\n\ntype ClonedGLTFParts = {\n gltf: GLTF;\n sharedSkeleton: Skeleton;\n matrixWorld: Matrix4;\n};\n\ntype BoneHierarchyMap = Map<string, BoneHierarchyMap>;\ntype DiffResult = {\n identical: boolean;\n differences: string[];\n};\n\nexport function cloneModel(model: Group) {\n const clone = SkeletonUtils.clone(model);\n return clone;\n}\n\nexport class SkeletonHelpers {\n private debug: boolean = false;\n private hierarchies: BoneHierarchyMap[] = [];\n private modelNames: string[] = [];\n\n private extractBoneHierarchy(node: Object3D): BoneHierarchyMap | null {\n if (node.type !== \"Bone\") return null;\n const boneMap: BoneHierarchyMap = new Map();\n node.children.forEach((child) => {\n const childHierarchy = this.extractBoneHierarchy(child);\n if (childHierarchy) boneMap.set(child.name, childHierarchy);\n });\n return boneMap;\n }\n\n private areBoneHierarchiesEqual(\n a: BoneHierarchyMap,\n b: BoneHierarchyMap,\n modelNameA: string,\n modelNameB: string,\n path: string[] = [],\n ): DiffResult {\n let identical = true;\n const differences: string[] = [];\n\n if (a.size !== b.size) {\n differences.push(\n `Different number of children at path: ${path.join(\n \" -> \",\n )} in models ${modelNameA} and ${modelNameB}.`,\n );\n identical = false;\n }\n\n for (const [key, value] of a) {\n if (!b.has(key)) {\n differences.push(\n `Bone \"${key}\" was found in model ${modelNameA} but not in model ${modelNameB} at path: ${path.join(\n \" -> \",\n )}.`,\n );\n identical = false;\n continue;\n }\n\n const newPath = [...path, key];\n const result = this.areBoneHierarchiesEqual(\n value,\n b.get(key)!,\n modelNameA,\n modelNameB,\n newPath,\n );\n\n if (!result.identical) {\n identical = false;\n differences.push(...result.differences);\n }\n }\n\n for (const key of b.keys()) {\n if (!a.has(key)) {\n differences.push(\n `Bone \"${key}\" was found in model ${modelNameB} but not in model ${modelNameA} at path: ${path.join(\n \" -> \",\n )}.`,\n );\n identical = false;\n }\n }\n\n return {\n identical,\n differences,\n };\n }\n\n public extractAndStoreBoneHierarchy(node: Object3D, modelName: string) {\n const newHierarchy = this.extractBoneHierarchy(node);\n\n if (!newHierarchy) {\n console.log(`No bone hierarchy found in the model: ${modelName}.`);\n return;\n }\n\n this.hierarchies.push(newHierarchy);\n this.modelNames.push(modelName);\n }\n\n public compareLatestHierarchies() {\n if (this.hierarchies.length < 2) return;\n\n const latestHierarchy = this.hierarchies[this.hierarchies.length - 1];\n const previousHierarchy = this.hierarchies[this.hierarchies.length - 2];\n\n const diff = this.areBoneHierarchiesEqual(\n previousHierarchy,\n latestHierarchy,\n this.modelNames[this.modelNames.length - 2],\n this.modelNames[this.modelNames.length - 1],\n [],\n );\n\n if (diff.identical) {\n if (this.debug) console.log(\"The skeletons are identical.\");\n } else {\n diff.differences.forEach((difference) => console.log(difference));\n }\n }\n\n public cloneGLTF(gltf: GLTF, modelName: string): ClonedGLTFParts {\n const clone: Partial<GLTF> = {\n animations: gltf.animations,\n scene: cloneModel(gltf.scene) as Group,\n };\n\n let sharedSkeleton: Skeleton | null = null;\n let matrixWorld: Matrix4 | null = null;\n\n const skinnedMeshes: Record<string, SkinnedMesh> = {};\n\n gltf.scene.traverse((node) => {\n if (node.type === \"SkinnedMesh\") {\n skinnedMeshes[node.name] = node as SkinnedMesh;\n }\n });\n\n const cloneBones: Record<string, Bone> = {};\n const cloneSkinnedMeshes: Record<string, SkinnedMesh> = {};\n\n let hierarchyCheck = false;\n clone.scene!.traverse((node) => {\n if (node.type === \"Bone\") {\n if (hierarchyCheck === false) {\n hierarchyCheck = true;\n this.extractAndStoreBoneHierarchy(node, modelName);\n }\n cloneBones[node.name] = node as Bone;\n }\n\n if (node.type === \"SkinnedMesh\") {\n cloneSkinnedMeshes[node.name] = node as SkinnedMesh;\n }\n });\n\n for (const name in skinnedMeshes) {\n const skinnedMesh = skinnedMeshes[name];\n const skeleton = skinnedMesh.skeleton;\n const cloneSkinnedMesh = cloneSkinnedMeshes[name];\n\n const orderedCloneBones = [];\n\n for (let i = 0; i < skeleton.bones.length; ++i) {\n const cloneBone = cloneBones[skeleton.bones[i].name];\n orderedCloneBones.push(cloneBone);\n }\n\n if (sharedSkeleton === null) {\n sharedSkeleton = new Skeleton(orderedCloneBones, skeleton.boneInverses);\n }\n\n if (matrixWorld === null) {\n matrixWorld = cloneSkinnedMesh.matrixWorld;\n }\n\n cloneSkinnedMesh.bind(sharedSkeleton, matrixWorld);\n }\n\n return {\n gltf: clone as GLTF,\n sharedSkeleton: sharedSkeleton as Skeleton,\n matrixWorld: matrixWorld as Matrix4,\n };\n }\n}\n", "import { LoadingManager } from \"three\";\nimport { GLTF, GLTFLoader as ThreeGLTFLoader } from \"three/examples/jsm/loaders/GLTFLoader.js\";\n\nclass CachedGLTFLoader extends ThreeGLTFLoader {\n private blobCache: Map<string, string>;\n\n constructor(manager?: LoadingManager) {\n super(manager);\n this.blobCache = new Map();\n }\n\n setBlobUrl(originalUrl: string, blobUrl: string) {\n this.blobCache.set(originalUrl, blobUrl);\n }\n\n getBlobUrl(originalUrl: string): string | undefined {\n return this.blobCache.get(originalUrl);\n }\n\n load(\n url: string,\n onLoad: (gltf: GLTF) => void,\n onProgress?: ((event: ProgressEvent<EventTarget>) => void) | undefined,\n onError?: ((event: ErrorEvent) => void) | undefined,\n ): void {\n const blobUrl = this.getBlobUrl(url);\n const effectiveUrl = blobUrl || url;\n super.load(effectiveUrl, onLoad, onProgress, onError);\n }\n}\n\nclass LRUCache<K, V> {\n private maxSize: number;\n private cache: Map<K, V>;\n\n constructor(maxSize: number = 100) {\n this.maxSize = maxSize;\n this.cache = new Map();\n }\n\n get(key: K): V | undefined {\n const item = this.cache.get(key);\n if (item) {\n this.cache.delete(key);\n this.cache.set(key, item);\n }\n return item;\n }\n\n set(key: K, value: V): void {\n if (this.cache.size >= this.maxSize) {\n const oldestKey = this.cache.keys().next().value;\n this.cache.delete(oldestKey);\n }\n this.cache.set(key, value);\n }\n}\n\ninterface CachedModel {\n blob: Blob;\n}\n\nexport class ModelLoader {\n private static instance: ModelLoader | null = null;\n\n private readonly loadingManager: LoadingManager;\n private readonly gltfLoader: CachedGLTFLoader;\n private modelCache: LRUCache<string, CachedModel>;\n private ongoingLoads: Map<string, Promise<GLTF | undefined>> = new Map();\n\n constructor(\n maxCacheSize: number = 100,\n private debug: boolean = false,\n ) {\n this.loadingManager = new LoadingManager();\n this.gltfLoader = new CachedGLTFLoader(this.loadingManager);\n this.modelCache = new LRUCache(maxCacheSize);\n }\n\n static getInstance(): ModelLoader {\n if (!ModelLoader.instance) {\n ModelLoader.instance = new ModelLoader();\n }\n return ModelLoader.instance;\n }\n\n async load(fileUrl: string): Promise<GLTF | undefined> {\n const cachedModel = this.modelCache.get(fileUrl);\n\n if (cachedModel) {\n if (this.debug === true) {\n console.log(`Loading ${fileUrl.split(\"/\").pop()} from cache`);\n }\n const blobURL = URL.createObjectURL(cachedModel.blob);\n this.gltfLoader.setBlobUrl(fileUrl, blobURL);\n return this.loadFromUrl(blobURL);\n } else {\n if (this.debug === true) {\n console.log(`Loading ${fileUrl} from server`);\n }\n const ongoingLoad = this.ongoingLoads.get(fileUrl);\n if (ongoingLoad) return ongoingLoad;\n\n const loadPromise = fetch(fileUrl)\n .then((response) => response.blob())\n .then((blob) => {\n this.modelCache.set(fileUrl, { blob });\n const blobURL = URL.createObjectURL(blob);\n this.ongoingLoads.delete(fileUrl);\n return this.loadFromUrl(blobURL);\n });\n\n this.ongoingLoads.set(fileUrl, loadPromise);\n return loadPromise;\n }\n }\n\n private async loadFromUrl(url: string): Promise<GLTF | undefined> {\n return new Promise((resolve, reject) => {\n this.gltfLoader.load(\n url,\n (object: GLTF) => {\n resolve(object);\n },\n undefined,\n (error) => {\n console.error(`Error loading model from ${url}: ${error}`);\n reject(error);\n },\n );\n });\n }\n}\n", "export type MMLCharacterDescriptionPart = {\n url: string;\n type?: string;\n};\n\nexport type MMLCharacterDescription = {\n base: MMLCharacterDescriptionPart;\n parts: MMLCharacterDescriptionPart[];\n};\n\nexport type LoadingErrors = string[];\n\nexport const parseMMLDescription = (\n mmlDescription: string,\n): [MMLCharacterDescription, LoadingErrors] => {\n const parser: DOMParser = new DOMParser();\n const doc = parser.parseFromString(mmlDescription, \"text/html\");\n\n const tag = (count: number) => {\n return count > 1 ? \"tags\" : \"tag\";\n };\n\n const errors: string[] = [];\n\n const warn = (errorMessage: string) => {\n errors.push(errorMessage);\n console.warn(errorMessage);\n };\n\n const characters = Array.from(doc.body.children).filter(\n (child) => child.tagName.toLowerCase() === \"m-character\",\n );\n const validCharacter = characters.shift();\n\n if (characters.length > 0) {\n const tagStr = tag(characters.length);\n warn(\n `ignoring ${characters.length} extra <m-character> ${tagStr} found in the root of the document (only the first one is valid).`,\n );\n }\n\n const nestedCharacters = doc.querySelectorAll(\"body * m-character\");\n if (nestedCharacters.length > 0) {\n const tagStr = tag(nestedCharacters.length);\n warn(\n `ignoring ${nestedCharacters.length} nested <m-character> ${tagStr} found within other tags. A valid <m-character> tag must be at the root of the document.`,\n );\n }\n\n const rootModels = Array.from(doc.body.children).filter(\n (child) => child.tagName.toLowerCase() === \"m-model\",\n );\n if (rootModels.length > 0) {\n const tagStr = tag(rootModels.length);\n warn(\n `ignoring ${rootModels.length} <m-model> ${tagStr} were found at the root of the document (<m-model> tags must be children of a valid <m-character> tag).`,\n );\n }\n\n let base: MMLCharacterDescriptionPart = { url: \"\" };\n let parts: MMLCharacterDescriptionPart[] = [];\n\n if (validCharacter) {\n const baseSrc = validCharacter.getAttribute(\"src\") ?? \"\";\n base = { url: baseSrc };\n\n const directModelChildren = Array.from(validCharacter.children).filter(\n (child) => child.tagName.toLowerCase() === \"m-model\",\n );\n parts = directModelChildren.map((model) => {\n const partSrc = model.getAttribute(\"src\") ?? \"\";\n return { url: partSrc };\n });\n\n const wrappedModelTags = Array.from(doc.querySelectorAll(\"m-character m-model\")).filter(\n (model) => !directModelChildren.includes(model),\n );\n if (wrappedModelTags.length > 0) {\n const tagStr = tag(wrappedModelTags.length);\n warn(\n `ignoring ${wrappedModelTags.length} <m-model> ${tagStr} that were found wrapped inside tags other than a valid <m-character> tag.`,\n );\n }\n } else {\n warn(`No valid <m-character> tag was found in the provided document.`);\n }\n\n const characterDescription: MMLCharacterDescription = {\n base: base,\n parts: parts,\n };\n\n return [characterDescription, errors];\n};\n", "import { MMLCharacterDescription } from \"./parseMMLDescription\";\n\nexport const createMMLCharacterString = (characterDescription: MMLCharacterDescription): string => {\n const base = characterDescription.base.url;\n\n const partsTags = characterDescription.parts.map(\n (part) => `<m-model src=\"${part.url}\"${part.type ? ` type=\"${part.type}\"` : \"\"}></m-model>`,\n );\n\n return `<m-character src=\"${base}\">\n ${partsTags.join(\"\\n \")}\n</m-character>`;\n};\n"],
|
5
|
-
"mappings": "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",
|
3
|
+
"sources": ["../src/character/MMLCharacter.ts", "../src/helpers/SkeletonHelpers.ts", "../src/character/ModelLoader.ts", "../src/helpers/parseMMLDescription.ts", "../src/helpers/createMMLCharacterString.ts"],
|
4
|
+
"sourcesContent": ["import {\n Bone,\n BufferAttribute,\n Euler,\n Group,\n MathUtils,\n Matrix4,\n MeshStandardMaterial,\n Object3D,\n Skeleton,\n SkinnedMesh,\n Vector3,\n} from \"three\";\nimport { GLTF } from \"three/examples/jsm/loaders/GLTFLoader.js\";\n\nimport { MMLCharacterDescriptionPart } from \"../helpers/parseMMLDescription\";\nimport { SkeletonHelpers } from \"../helpers/SkeletonHelpers\";\n\nimport { ModelLoader } from \"./ModelLoader\";\n\nexport class MMLCharacter {\n private skeletonHelpers: SkeletonHelpers = new SkeletonHelpers();\n private skinnedMeshesParent: Group | null = null;\n private sharedSkeleton: Skeleton | null = null;\n private sharedMatrixWorld: Matrix4 | null = null;\n\n constructor(private modelLoader: ModelLoader) {}\n\n private createBoneIndexMap(\n originSkeleton: Skeleton,\n targetSkeleton: Skeleton,\n ): Map<number, number> {\n const boneIndexMap = new Map<number, number>();\n\n for (let i = 0; i < originSkeleton.bones.length; i++) {\n const originBone = originSkeleton.bones[i];\n const targetBone = targetSkeleton.bones.find((bone) => bone.name === originBone.name);\n if (targetBone) {\n boneIndexMap.set(i, targetSkeleton.bones.indexOf(targetBone));\n }\n }\n return boneIndexMap;\n }\n\n private remapBoneIndices(skinnedMesh: SkinnedMesh): void {\n const targetSkeleton = this.sharedSkeleton!;\n const originSkeleton = skinnedMesh.skeleton;\n const originGeometry = skinnedMesh.geometry;\n\n const boneIndexMap = this.createBoneIndexMap(originSkeleton, targetSkeleton);\n\n const newSkinIndexArray = [];\n for (let i = 0; i < originGeometry.attributes.skinIndex.array.length; i++) {\n const originIndex = originGeometry.attributes.skinIndex.array[i];\n const targetIndex = boneIndexMap.get(originIndex);\n if (targetIndex !== undefined) {\n newSkinIndexArray.push(targetIndex);\n } else {\n console.error(\"Missing bone index\", originIndex);\n newSkinIndexArray.push(0);\n }\n }\n skinnedMesh.geometry.attributes.skinIndex = new BufferAttribute(\n new Uint8Array(newSkinIndexArray),\n 4,\n );\n }\n\n public async mergeBodyParts(\n fullBodyURL: string,\n bodyParts: Array<MMLCharacterDescriptionPart>,\n ): Promise<Object3D> {\n const fullBodyAsset = await this.modelLoader.load(fullBodyURL);\n const fullBodyGLTF = this.skeletonHelpers.cloneGLTF(fullBodyAsset as GLTF, \"fullBody\");\n const assetPromises: Array<Promise<{ asset: GLTF; part: MMLCharacterDescriptionPart }>> =\n bodyParts.map((part) => {\n return new Promise((resolve) => {\n this.modelLoader.load(part.url).then((asset) => {\n resolve({ asset: asset!, part });\n });\n });\n });\n const assets = await Promise.all(assetPromises);\n\n const fullBodyModelGroup = fullBodyGLTF.gltf.scene;\n\n this.skinnedMeshesParent = null;\n\n const availableBones = new Map<string, Bone>();\n fullBodyModelGroup.traverse((child) => {\n const asBone = child as Bone;\n if (asBone.isBone) {\n availableBones.set(child.name, asBone);\n }\n\n const asSkinnedMesh = child as SkinnedMesh;\n if (asSkinnedMesh.isSkinnedMesh) {\n asSkinnedMesh.castShadow = true;\n asSkinnedMesh.receiveShadow = true;\n if (this.skinnedMeshesParent === null) {\n this.skinnedMeshesParent = asSkinnedMesh.parent as Group;\n }\n }\n });\n this.sharedSkeleton = fullBodyGLTF.sharedSkeleton;\n this.sharedMatrixWorld = fullBodyGLTF.matrixWorld;\n\n for (const loadingAsset of assets) {\n const part = loadingAsset.part;\n const gltf = this.skeletonHelpers.cloneGLTF(loadingAsset.asset, part.url);\n const modelGroup = gltf.gltf.scene;\n if (part.socket) {\n const socketName = part.socket.socket;\n let bone = availableBones.get(\"root\");\n if (availableBones.has(socketName)) {\n bone = availableBones.get(socketName);\n } else {\n console.warn(\n `WARNING: no bone found for [${socketName}] socket. Attatching to Root bone`,\n );\n }\n if (bone) {\n modelGroup.position.set(0, 0, 0);\n modelGroup.rotation.set(0, 0, 0);\n modelGroup.scale.set(1, 1, 1);\n\n bone.add(modelGroup);\n\n modelGroup.rotateZ(-Math.PI / 2);\n\n const offsetPosition = new Vector3(\n part.socket.position.x,\n part.socket.position.y,\n part.socket.position.z,\n );\n modelGroup.position.copy(offsetPosition);\n\n const offsetRotation = new Euler(\n MathUtils.degToRad(part.socket.rotation.x),\n MathUtils.degToRad(part.socket.rotation.y),\n MathUtils.degToRad(part.socket.rotation.z),\n );\n modelGroup.setRotationFromEuler(offsetRotation);\n\n modelGroup.scale.set(part.socket.scale.x, part.socket.scale.y, part.socket.scale.z);\n }\n } else {\n modelGroup.traverse((child) => {\n const asSkinnedMesh = child as SkinnedMesh;\n if (asSkinnedMesh.isSkinnedMesh) {\n const skinnedMeshClone = child.clone(true) as SkinnedMesh;\n this.remapBoneIndices(skinnedMeshClone);\n skinnedMeshClone.castShadow = true;\n skinnedMeshClone.receiveShadow = true;\n skinnedMeshClone.bind(this.sharedSkeleton!, this.sharedMatrixWorld!);\n skinnedMeshClone.children = [];\n this.skinnedMeshesParent?.add(skinnedMeshClone);\n }\n });\n }\n }\n return fullBodyGLTF!.gltf.scene as Object3D;\n }\n}\n", "import { Bone, Group, Matrix4, Mesh, Object3D, Skeleton, SkinnedMesh } from \"three\";\nimport { GLTF } from \"three/examples/jsm/loaders/GLTFLoader.js\";\nimport * as SkeletonUtils from \"three/examples/jsm/utils/SkeletonUtils.js\";\n\ntype ClonedGLTFParts = {\n gltf: GLTF;\n sharedSkeleton: Skeleton;\n matrixWorld: Matrix4;\n};\n\ntype BoneHierarchyMap = Map<string, BoneHierarchyMap>;\ntype DiffResult = {\n identical: boolean;\n differences: string[];\n};\n\nexport function cloneModel(model: Group) {\n const clone = SkeletonUtils.clone(model);\n return clone;\n}\n\nexport class SkeletonHelpers {\n private debug: boolean = false;\n private hierarchies: BoneHierarchyMap[] = [];\n private modelNames: string[] = [];\n\n private extractBoneHierarchy(node: Object3D): BoneHierarchyMap | null {\n if (node.type !== \"Bone\") return null;\n const boneMap: BoneHierarchyMap = new Map();\n node.children.forEach((child) => {\n const childHierarchy = this.extractBoneHierarchy(child);\n if (childHierarchy) boneMap.set(child.name, childHierarchy);\n });\n return boneMap;\n }\n\n private areBoneHierarchiesEqual(\n a: BoneHierarchyMap,\n b: BoneHierarchyMap,\n modelNameA: string,\n modelNameB: string,\n path: string[] = [],\n ): DiffResult {\n let identical = true;\n const differences: string[] = [];\n\n if (a.size !== b.size) {\n differences.push(\n `Different number of children at path: ${path.join(\n \" -> \",\n )} in models ${modelNameA} and ${modelNameB}.`,\n );\n identical = false;\n }\n\n for (const [key, value] of a) {\n if (!b.has(key)) {\n differences.push(\n `Bone \"${key}\" was found in model ${modelNameA} but not in model ${modelNameB} at path: ${path.join(\n \" -> \",\n )}.`,\n );\n identical = false;\n continue;\n }\n\n const newPath = [...path, key];\n const result = this.areBoneHierarchiesEqual(\n value,\n b.get(key)!,\n modelNameA,\n modelNameB,\n newPath,\n );\n\n if (!result.identical) {\n identical = false;\n differences.push(...result.differences);\n }\n }\n\n for (const key of b.keys()) {\n if (!a.has(key)) {\n differences.push(\n `Bone \"${key}\" was found in model ${modelNameB} but not in model ${modelNameA} at path: ${path.join(\n \" -> \",\n )}.`,\n );\n identical = false;\n }\n }\n\n return {\n identical,\n differences,\n };\n }\n\n public extractAndStoreBoneHierarchy(node: Object3D, modelName: string) {\n const newHierarchy = this.extractBoneHierarchy(node);\n\n if (!newHierarchy) {\n console.log(`No bone hierarchy found in the model: ${modelName}.`);\n return;\n }\n\n this.hierarchies.push(newHierarchy);\n this.modelNames.push(modelName);\n }\n\n public compareLatestHierarchies() {\n if (this.hierarchies.length < 2) return;\n\n const latestHierarchy = this.hierarchies[this.hierarchies.length - 1];\n const previousHierarchy = this.hierarchies[this.hierarchies.length - 2];\n\n const diff = this.areBoneHierarchiesEqual(\n previousHierarchy,\n latestHierarchy,\n this.modelNames[this.modelNames.length - 2],\n this.modelNames[this.modelNames.length - 1],\n [],\n );\n\n if (diff.identical) {\n if (this.debug) console.log(\"The skeletons are identical.\");\n } else {\n diff.differences.forEach((difference) => console.log(difference));\n }\n }\n\n public cloneGLTF(gltf: GLTF, modelName: string): ClonedGLTFParts {\n const clone: Partial<GLTF> = {\n animations: gltf.animations,\n scene: cloneModel(gltf.scene) as Group,\n };\n\n let sharedSkeleton: Skeleton | null = null;\n let matrixWorld: Matrix4 | null = null;\n\n const skinnedMeshes: Record<string, SkinnedMesh> = {};\n\n gltf.scene.traverse((node) => {\n if (node.type === \"SkinnedMesh\") {\n skinnedMeshes[node.name] = node as SkinnedMesh;\n }\n });\n\n const cloneBones: Record<string, Bone> = {};\n const cloneSkinnedMeshes: Record<string, SkinnedMesh> = {};\n\n let hierarchyCheck = false;\n clone.scene!.traverse((node) => {\n if ((node as Mesh).isMesh || (node as SkinnedMesh).isSkinnedMesh) {\n node.castShadow = true;\n node.receiveShadow = true;\n }\n if (node.type === \"Bone\") {\n if (hierarchyCheck === false) {\n hierarchyCheck = true;\n this.extractAndStoreBoneHierarchy(node, modelName);\n }\n cloneBones[node.name] = node as Bone;\n }\n\n if (node.type === \"SkinnedMesh\") {\n cloneSkinnedMeshes[node.name] = node as SkinnedMesh;\n }\n });\n\n for (const name in skinnedMeshes) {\n const skinnedMesh = skinnedMeshes[name];\n const skeleton = skinnedMesh.skeleton;\n const cloneSkinnedMesh = cloneSkinnedMeshes[name];\n\n const orderedCloneBones = [];\n\n for (let i = 0; i < skeleton.bones.length; ++i) {\n const cloneBone = cloneBones[skeleton.bones[i].name];\n orderedCloneBones.push(cloneBone);\n }\n\n if (sharedSkeleton === null) {\n sharedSkeleton = new Skeleton(orderedCloneBones, skeleton.boneInverses);\n }\n\n if (matrixWorld === null) {\n matrixWorld = cloneSkinnedMesh.matrixWorld;\n }\n\n cloneSkinnedMesh.bind(sharedSkeleton, matrixWorld);\n }\n\n return {\n gltf: clone as GLTF,\n sharedSkeleton: sharedSkeleton as Skeleton,\n matrixWorld: matrixWorld as Matrix4,\n };\n }\n}\n", "import { LoadingManager } from \"three\";\nimport { GLTF, GLTFLoader as ThreeGLTFLoader } from \"three/examples/jsm/loaders/GLTFLoader.js\";\n\nclass CachedGLTFLoader extends ThreeGLTFLoader {\n private blobCache: Map<string, string>;\n\n constructor(manager?: LoadingManager) {\n super(manager);\n this.blobCache = new Map();\n }\n\n setBlobUrl(originalUrl: string, blobUrl: string) {\n this.blobCache.set(originalUrl, blobUrl);\n }\n\n getBlobUrl(originalUrl: string): string | undefined {\n return this.blobCache.get(originalUrl);\n }\n\n load(\n url: string,\n onLoad: (gltf: GLTF) => void,\n onProgress?: ((event: ProgressEvent<EventTarget>) => void) | undefined,\n onError?: ((event: ErrorEvent) => void) | undefined,\n ): void {\n const blobUrl = this.getBlobUrl(url);\n const effectiveUrl = blobUrl || url;\n super.load(effectiveUrl, onLoad, onProgress, onError);\n }\n}\n\nclass LRUCache<K, V> {\n private maxSize: number;\n private cache: Map<K, V>;\n\n constructor(maxSize: number = 100) {\n this.maxSize = maxSize;\n this.cache = new Map();\n }\n\n get(key: K): V | undefined {\n const item = this.cache.get(key);\n if (item) {\n this.cache.delete(key);\n this.cache.set(key, item);\n }\n return item;\n }\n\n set(key: K, value: V): void {\n if (this.cache.size >= this.maxSize) {\n const oldestKey = this.cache.keys().next().value;\n this.cache.delete(oldestKey);\n }\n this.cache.set(key, value);\n }\n}\n\ninterface CachedModel {\n blob: Blob;\n}\n\nexport class ModelLoader {\n private static instance: ModelLoader | null = null;\n\n private readonly loadingManager: LoadingManager;\n private readonly gltfLoader: CachedGLTFLoader;\n private modelCache: LRUCache<string, CachedModel>;\n private ongoingLoads: Map<string, Promise<GLTF | undefined>> = new Map();\n\n constructor(\n maxCacheSize: number = 100,\n private debug: boolean = false,\n ) {\n this.loadingManager = new LoadingManager();\n this.gltfLoader = new CachedGLTFLoader(this.loadingManager);\n this.modelCache = new LRUCache(maxCacheSize);\n }\n\n static getInstance(): ModelLoader {\n if (!ModelLoader.instance) {\n ModelLoader.instance = new ModelLoader();\n }\n return ModelLoader.instance;\n }\n\n async load(fileUrl: string): Promise<GLTF | undefined> {\n const cachedModel = this.modelCache.get(fileUrl);\n\n if (cachedModel) {\n if (this.debug === true) {\n console.log(`Loading ${fileUrl.split(\"/\").pop()} from cache`);\n }\n const blobURL = URL.createObjectURL(cachedModel.blob);\n this.gltfLoader.setBlobUrl(fileUrl, blobURL);\n return this.loadFromUrl(blobURL);\n } else {\n if (this.debug === true) {\n console.log(`Loading ${fileUrl} from server`);\n }\n const ongoingLoad = this.ongoingLoads.get(fileUrl);\n if (ongoingLoad) return ongoingLoad;\n\n const loadPromise = fetch(fileUrl)\n .then((response) => response.blob())\n .then((blob) => {\n this.modelCache.set(fileUrl, { blob });\n const blobURL = URL.createObjectURL(blob);\n this.ongoingLoads.delete(fileUrl);\n return this.loadFromUrl(blobURL);\n });\n\n this.ongoingLoads.set(fileUrl, loadPromise);\n return loadPromise;\n }\n }\n\n private async loadFromUrl(url: string): Promise<GLTF | undefined> {\n return new Promise((resolve, reject) => {\n this.gltfLoader.load(\n url,\n (object: GLTF) => {\n resolve(object);\n },\n undefined,\n (error) => {\n console.error(`Error loading model from ${url}: ${error}`);\n reject(error);\n },\n );\n });\n }\n}\n", "export type MMLCharacterDescriptionPart = {\n url: string;\n type?: string;\n socket?: {\n socket: string;\n position: { x: number; y: number; z: number };\n scale: { x: number; y: number; z: number };\n rotation: { x: number; y: number; z: number };\n };\n};\n\nexport type MMLCharacterDescription = {\n base: MMLCharacterDescriptionPart;\n parts: MMLCharacterDescriptionPart[];\n};\n\nexport type LoadingErrors = string[];\n\nexport const parseMMLDescription = (\n mmlDescription: string,\n): [MMLCharacterDescription, LoadingErrors] => {\n const parser: DOMParser = new DOMParser();\n const doc = parser.parseFromString(mmlDescription, \"text/html\");\n\n const tag = (count: number) => {\n return count > 1 ? \"tags\" : \"tag\";\n };\n\n const errors: string[] = [];\n\n const warn = (errorMessage: string) => {\n errors.push(errorMessage);\n console.warn(errorMessage);\n };\n\n const characters = Array.from(doc.body.children).filter(\n (child) => child.tagName.toLowerCase() === \"m-character\",\n );\n const validCharacter = characters.shift();\n\n if (characters.length > 0) {\n const tagStr = tag(characters.length);\n warn(\n `ignoring ${characters.length} extra <m-character> ${tagStr} found in the root of the document (only the first one is valid).`,\n );\n }\n\n const nestedCharacters = doc.querySelectorAll(\"body * m-character\");\n if (nestedCharacters.length > 0) {\n const tagStr = tag(nestedCharacters.length);\n warn(\n `ignoring ${nestedCharacters.length} nested <m-character> ${tagStr} found within other tags. A valid <m-character> tag must be at the root of the document.`,\n );\n }\n\n const rootModels = Array.from(doc.body.children).filter(\n (child) => child.tagName.toLowerCase() === \"m-model\",\n );\n if (rootModels.length > 0) {\n const tagStr = tag(rootModels.length);\n warn(\n `ignoring ${rootModels.length} <m-model> ${tagStr} were found at the root of the document (<m-model> tags must be children of a valid <m-character> tag).`,\n );\n }\n\n let base: MMLCharacterDescriptionPart = { url: \"\" };\n let parts: MMLCharacterDescriptionPart[] = [];\n\n if (validCharacter) {\n const baseSrc = validCharacter.getAttribute(\"src\") ?? \"\";\n base = { url: baseSrc };\n\n const directModelChildren = Array.from(validCharacter.children).filter(\n (child) => child.tagName.toLowerCase() === \"m-model\",\n );\n parts = directModelChildren.map((model) => {\n const partSrc = model.getAttribute(\"src\") ?? \"\";\n\n const socketAttr = model.getAttribute(\"socket\");\n const position = {\n x: parseFloat(model.getAttribute(\"x\") ?? \"0\") || 0,\n y: parseFloat(model.getAttribute(\"y\") ?? \"0\") || 0,\n z: parseFloat(model.getAttribute(\"z\") ?? \"0\") || 0,\n };\n const scale = {\n x: parseFloat(model.getAttribute(\"sx\") ?? \"1\") || 1,\n y: parseFloat(model.getAttribute(\"sy\") ?? \"1\") || 1,\n z: parseFloat(model.getAttribute(\"sz\") ?? \"1\") || 1,\n };\n const rotation = {\n x: parseFloat(model.getAttribute(\"rx\") ?? \"0\") || 0,\n y: parseFloat(model.getAttribute(\"ry\") ?? \"0\") || 0,\n z: parseFloat(model.getAttribute(\"rz\") ?? \"0\") || 0,\n };\n\n const socketObj = socketAttr ? { socket: socketAttr, position, scale, rotation } : undefined;\n\n return { url: partSrc, socket: socketObj };\n });\n\n const wrappedModelTags = Array.from(doc.querySelectorAll(\"m-character m-model\")).filter(\n (model) => !directModelChildren.includes(model),\n );\n if (wrappedModelTags.length > 0) {\n const tagStr = tag(wrappedModelTags.length);\n warn(\n `ignoring ${wrappedModelTags.length} <m-model> ${tagStr} that were found wrapped inside tags other than a valid <m-character> tag.`,\n );\n }\n } else {\n warn(`No valid <m-character> tag was found in the provided document.`);\n }\n\n const characterDescription: MMLCharacterDescription = {\n base: base,\n parts: parts,\n };\n\n return [characterDescription, errors];\n};\n", "import { MMLCharacterDescription } from \"./parseMMLDescription\";\n\nexport const createMMLCharacterString = (characterDescription: MMLCharacterDescription): string => {\n const base = characterDescription.base.url;\n\n const partsTags = characterDescription.parts.map(\n (part) => `<m-model src=\"${part.url}\"${part.type ? ` type=\"${part.type}\"` : \"\"}></m-model>`,\n );\n\n return `<m-character src=\"${base}\">\n ${partsTags.join(\"\\n \")}\n</m-character>`;\n};\n"],
|
5
|
+
"mappings": ";AAAA;AAAA,EAEE;AAAA,EACA;AAAA,EAEA;AAAA,EAMA;AAAA,OACK;;;ACZP,SAA+C,gBAA6B;AAE5E,YAAY,mBAAmB;AAcxB,SAAS,WAAW,OAAc;AACvC,QAAMA,SAAsB,oBAAM,KAAK;AACvC,SAAOA;AACT;AAEO,IAAM,kBAAN,MAAsB;AAAA,EAAtB;AACL,SAAQ,QAAiB;AACzB,SAAQ,cAAkC,CAAC;AAC3C,SAAQ,aAAuB,CAAC;AAAA;AAAA,EAExB,qBAAqB,MAAyC;AACpE,QAAI,KAAK,SAAS;AAAQ,aAAO;AACjC,UAAM,UAA4B,oBAAI,IAAI;AAC1C,SAAK,SAAS,QAAQ,CAAC,UAAU;AAC/B,YAAM,iBAAiB,KAAK,qBAAqB,KAAK;AACtD,UAAI;AAAgB,gBAAQ,IAAI,MAAM,MAAM,cAAc;AAAA,IAC5D,CAAC;AACD,WAAO;AAAA,EACT;AAAA,EAEQ,wBACN,GACA,GACA,YACA,YACA,OAAiB,CAAC,GACN;AACZ,QAAI,YAAY;AAChB,UAAM,cAAwB,CAAC;AAE/B,QAAI,EAAE,SAAS,EAAE,MAAM;AACrB,kBAAY;AAAA,QACV,yCAAyC,KAAK;AAAA,UAC5C;AAAA,QACF,CAAC,cAAc,UAAU,QAAQ,UAAU;AAAA,MAC7C;AACA,kBAAY;AAAA,IACd;AAEA,eAAW,CAAC,KAAK,KAAK,KAAK,GAAG;AAC5B,UAAI,CAAC,EAAE,IAAI,GAAG,GAAG;AACf,oBAAY;AAAA,UACV,SAAS,GAAG,wBAAwB,UAAU,qBAAqB,UAAU,aAAa,KAAK;AAAA,YAC7F;AAAA,UACF,CAAC;AAAA,QACH;AACA,oBAAY;AACZ;AAAA,MACF;AAEA,YAAM,UAAU,CAAC,GAAG,MAAM,GAAG;AAC7B,YAAM,SAAS,KAAK;AAAA,QAClB;AAAA,QACA,EAAE,IAAI,GAAG;AAAA,QACT;AAAA,QACA;AAAA,QACA;AAAA,MACF;AAEA,UAAI,CAAC,OAAO,WAAW;AACrB,oBAAY;AACZ,oBAAY,KAAK,GAAG,OAAO,WAAW;AAAA,MACxC;AAAA,IACF;AAEA,eAAW,OAAO,EAAE,KAAK,GAAG;AAC1B,UAAI,CAAC,EAAE,IAAI,GAAG,GAAG;AACf,oBAAY;AAAA,UACV,SAAS,GAAG,wBAAwB,UAAU,qBAAqB,UAAU,aAAa,KAAK;AAAA,YAC7F;AAAA,UACF,CAAC;AAAA,QACH;AACA,oBAAY;AAAA,MACd;AAAA,IACF;AAEA,WAAO;AAAA,MACL;AAAA,MACA;AAAA,IACF;AAAA,EACF;AAAA,EAEO,6BAA6B,MAAgB,WAAmB;AACrE,UAAM,eAAe,KAAK,qBAAqB,IAAI;AAEnD,QAAI,CAAC,cAAc;AACjB,cAAQ,IAAI,yCAAyC,SAAS,GAAG;AACjE;AAAA,IACF;AAEA,SAAK,YAAY,KAAK,YAAY;AAClC,SAAK,WAAW,KAAK,SAAS;AAAA,EAChC;AAAA,EAEO,2BAA2B;AAChC,QAAI,KAAK,YAAY,SAAS;AAAG;AAEjC,UAAM,kBAAkB,KAAK,YAAY,KAAK,YAAY,SAAS,CAAC;AACpE,UAAM,oBAAoB,KAAK,YAAY,KAAK,YAAY,SAAS,CAAC;AAEtE,UAAM,OAAO,KAAK;AAAA,MAChB;AAAA,MACA;AAAA,MACA,KAAK,WAAW,KAAK,WAAW,SAAS,CAAC;AAAA,MAC1C,KAAK,WAAW,KAAK,WAAW,SAAS,CAAC;AAAA,MAC1C,CAAC;AAAA,IACH;AAEA,QAAI,KAAK,WAAW;AAClB,UAAI,KAAK;AAAO,gBAAQ,IAAI,8BAA8B;AAAA,IAC5D,OAAO;AACL,WAAK,YAAY,QAAQ,CAAC,eAAe,QAAQ,IAAI,UAAU,CAAC;AAAA,IAClE;AAAA,EACF;AAAA,EAEO,UAAU,MAAY,WAAoC;AAC/D,UAAMA,SAAuB;AAAA,MAC3B,YAAY,KAAK;AAAA,MACjB,OAAO,WAAW,KAAK,KAAK;AAAA,IAC9B;AAEA,QAAI,iBAAkC;AACtC,QAAI,cAA8B;AAElC,UAAM,gBAA6C,CAAC;AAEpD,SAAK,MAAM,SAAS,CAAC,SAAS;AAC5B,UAAI,KAAK,SAAS,eAAe;AAC/B,sBAAc,KAAK,IAAI,IAAI;AAAA,MAC7B;AAAA,IACF,CAAC;AAED,UAAM,aAAmC,CAAC;AAC1C,UAAM,qBAAkD,CAAC;AAEzD,QAAI,iBAAiB;AACrB,IAAAA,OAAM,MAAO,SAAS,CAAC,SAAS;AAC9B,UAAK,KAAc,UAAW,KAAqB,eAAe;AAChE,aAAK,aAAa;AAClB,aAAK,gBAAgB;AAAA,MACvB;AACA,UAAI,KAAK,SAAS,QAAQ;AACxB,YAAI,mBAAmB,OAAO;AAC5B,2BAAiB;AACjB,eAAK,6BAA6B,MAAM,SAAS;AAAA,QACnD;AACA,mBAAW,KAAK,IAAI,IAAI;AAAA,MAC1B;AAEA,UAAI,KAAK,SAAS,eAAe;AAC/B,2BAAmB,KAAK,IAAI,IAAI;AAAA,MAClC;AAAA,IACF,CAAC;AAED,eAAW,QAAQ,eAAe;AAChC,YAAM,cAAc,cAAc,IAAI;AACtC,YAAM,WAAW,YAAY;AAC7B,YAAM,mBAAmB,mBAAmB,IAAI;AAEhD,YAAM,oBAAoB,CAAC;AAE3B,eAAS,IAAI,GAAG,IAAI,SAAS,MAAM,QAAQ,EAAE,GAAG;AAC9C,cAAM,YAAY,WAAW,SAAS,MAAM,CAAC,EAAE,IAAI;AACnD,0BAAkB,KAAK,SAAS;AAAA,MAClC;AAEA,UAAI,mBAAmB,MAAM;AAC3B,yBAAiB,IAAI,SAAS,mBAAmB,SAAS,YAAY;AAAA,MACxE;AAEA,UAAI,gBAAgB,MAAM;AACxB,sBAAc,iBAAiB;AAAA,MACjC;AAEA,uBAAiB,KAAK,gBAAgB,WAAW;AAAA,IACnD;AAEA,WAAO;AAAA,MACL,MAAMA;AAAA,MACN;AAAA,MACA;AAAA,IACF;AAAA,EACF;AACF;;;ADnLO,IAAM,eAAN,MAAmB;AAAA,EAMxB,YAAoB,aAA0B;AAA1B;AALpB,SAAQ,kBAAmC,IAAI,gBAAgB;AAC/D,SAAQ,sBAAoC;AAC5C,SAAQ,iBAAkC;AAC1C,SAAQ,oBAAoC;AAAA,EAEG;AAAA,EAEvC,mBACN,gBACA,gBACqB;AACrB,UAAM,eAAe,oBAAI,IAAoB;AAE7C,aAAS,IAAI,GAAG,IAAI,eAAe,MAAM,QAAQ,KAAK;AACpD,YAAM,aAAa,eAAe,MAAM,CAAC;AACzC,YAAM,aAAa,eAAe,MAAM,KAAK,CAAC,SAAS,KAAK,SAAS,WAAW,IAAI;AACpF,UAAI,YAAY;AACd,qBAAa,IAAI,GAAG,eAAe,MAAM,QAAQ,UAAU,CAAC;AAAA,MAC9D;AAAA,IACF;AACA,WAAO;AAAA,EACT;AAAA,EAEQ,iBAAiB,aAAgC;AACvD,UAAM,iBAAiB,KAAK;AAC5B,UAAM,iBAAiB,YAAY;AACnC,UAAM,iBAAiB,YAAY;AAEnC,UAAM,eAAe,KAAK,mBAAmB,gBAAgB,cAAc;AAE3E,UAAM,oBAAoB,CAAC;AAC3B,aAAS,IAAI,GAAG,IAAI,eAAe,WAAW,UAAU,MAAM,QAAQ,KAAK;AACzE,YAAM,cAAc,eAAe,WAAW,UAAU,MAAM,CAAC;AAC/D,YAAM,cAAc,aAAa,IAAI,WAAW;AAChD,UAAI,gBAAgB,QAAW;AAC7B,0BAAkB,KAAK,WAAW;AAAA,MACpC,OAAO;AACL,gBAAQ,MAAM,sBAAsB,WAAW;AAC/C,0BAAkB,KAAK,CAAC;AAAA,MAC1B;AAAA,IACF;AACA,gBAAY,SAAS,WAAW,YAAY,IAAI;AAAA,MAC9C,IAAI,WAAW,iBAAiB;AAAA,MAChC;AAAA,IACF;AAAA,EACF;AAAA,EAEA,MAAa,eACX,aACA,WACmB;AACnB,UAAM,gBAAgB,MAAM,KAAK,YAAY,KAAK,WAAW;AAC7D,UAAM,eAAe,KAAK,gBAAgB,UAAU,eAAuB,UAAU;AACrF,UAAM,gBACJ,UAAU,IAAI,CAAC,SAAS;AACtB,aAAO,IAAI,QAAQ,CAAC,YAAY;AAC9B,aAAK,YAAY,KAAK,KAAK,GAAG,EAAE,KAAK,CAAC,UAAU;AAC9C,kBAAQ,EAAE,OAAe,KAAK,CAAC;AAAA,QACjC,CAAC;AAAA,MACH,CAAC;AAAA,IACH,CAAC;AACH,UAAM,SAAS,MAAM,QAAQ,IAAI,aAAa;AAE9C,UAAM,qBAAqB,aAAa,KAAK;AAE7C,SAAK,sBAAsB;AAE3B,UAAM,iBAAiB,oBAAI,IAAkB;AAC7C,uBAAmB,SAAS,CAAC,UAAU;AACrC,YAAM,SAAS;AACf,UAAI,OAAO,QAAQ;AACjB,uBAAe,IAAI,MAAM,MAAM,MAAM;AAAA,MACvC;AAEA,YAAM,gBAAgB;AACtB,UAAI,cAAc,eAAe;AAC/B,sBAAc,aAAa;AAC3B,sBAAc,gBAAgB;AAC9B,YAAI,KAAK,wBAAwB,MAAM;AACrC,eAAK,sBAAsB,cAAc;AAAA,QAC3C;AAAA,MACF;AAAA,IACF,CAAC;AACD,SAAK,iBAAiB,aAAa;AACnC,SAAK,oBAAoB,aAAa;AAEtC,eAAW,gBAAgB,QAAQ;AACjC,YAAM,OAAO,aAAa;AAC1B,YAAM,OAAO,KAAK,gBAAgB,UAAU,aAAa,OAAO,KAAK,GAAG;AACxE,YAAM,aAAa,KAAK,KAAK;AAC7B,UAAI,KAAK,QAAQ;AACf,cAAM,aAAa,KAAK,OAAO;AAC/B,YAAI,OAAO,eAAe,IAAI,MAAM;AACpC,YAAI,eAAe,IAAI,UAAU,GAAG;AAClC,iBAAO,eAAe,IAAI,UAAU;AAAA,QACtC,OAAO;AACL,kBAAQ;AAAA,YACN,+BAA+B,UAAU;AAAA,UAC3C;AAAA,QACF;AACA,YAAI,MAAM;AACR,qBAAW,SAAS,IAAI,GAAG,GAAG,CAAC;AAC/B,qBAAW,SAAS,IAAI,GAAG,GAAG,CAAC;AAC/B,qBAAW,MAAM,IAAI,GAAG,GAAG,CAAC;AAE5B,eAAK,IAAI,UAAU;AAEnB,qBAAW,QAAQ,CAAC,KAAK,KAAK,CAAC;AAE/B,gBAAM,iBAAiB,IAAI;AAAA,YACzB,KAAK,OAAO,SAAS;AAAA,YACrB,KAAK,OAAO,SAAS;AAAA,YACrB,KAAK,OAAO,SAAS;AAAA,UACvB;AACA,qBAAW,SAAS,KAAK,cAAc;AAEvC,gBAAM,iBAAiB,IAAI;AAAA,YACzB,UAAU,SAAS,KAAK,OAAO,SAAS,CAAC;AAAA,YACzC,UAAU,SAAS,KAAK,OAAO,SAAS,CAAC;AAAA,YACzC,UAAU,SAAS,KAAK,OAAO,SAAS,CAAC;AAAA,UAC3C;AACA,qBAAW,qBAAqB,cAAc;AAE9C,qBAAW,MAAM,IAAI,KAAK,OAAO,MAAM,GAAG,KAAK,OAAO,MAAM,GAAG,KAAK,OAAO,MAAM,CAAC;AAAA,QACpF;AAAA,MACF,OAAO;AACL,mBAAW,SAAS,CAAC,UAAU;AAnJvC;AAoJU,gBAAM,gBAAgB;AACtB,cAAI,cAAc,eAAe;AAC/B,kBAAM,mBAAmB,MAAM,MAAM,IAAI;AACzC,iBAAK,iBAAiB,gBAAgB;AACtC,6BAAiB,aAAa;AAC9B,6BAAiB,gBAAgB;AACjC,6BAAiB,KAAK,KAAK,gBAAiB,KAAK,iBAAkB;AACnE,6BAAiB,WAAW,CAAC;AAC7B,uBAAK,wBAAL,mBAA0B,IAAI;AAAA,UAChC;AAAA,QACF,CAAC;AAAA,MACH;AAAA,IACF;AACA,WAAO,aAAc,KAAK;AAAA,EAC5B;AACF;;;AEnKA,SAAS,sBAAsB;AAC/B,SAAe,cAAc,uBAAuB;AAEpD,IAAM,mBAAN,cAA+B,gBAAgB;AAAA,EAG7C,YAAY,SAA0B;AACpC,UAAM,OAAO;AACb,SAAK,YAAY,oBAAI,IAAI;AAAA,EAC3B;AAAA,EAEA,WAAW,aAAqB,SAAiB;AAC/C,SAAK,UAAU,IAAI,aAAa,OAAO;AAAA,EACzC;AAAA,EAEA,WAAW,aAAyC;AAClD,WAAO,KAAK,UAAU,IAAI,WAAW;AAAA,EACvC;AAAA,EAEA,KACE,KACA,QACA,YACA,SACM;AACN,UAAM,UAAU,KAAK,WAAW,GAAG;AACnC,UAAM,eAAe,WAAW;AAChC,UAAM,KAAK,cAAc,QAAQ,YAAY,OAAO;AAAA,EACtD;AACF;AAEA,IAAM,WAAN,MAAqB;AAAA,EAInB,YAAY,UAAkB,KAAK;AACjC,SAAK,UAAU;AACf,SAAK,QAAQ,oBAAI,IAAI;AAAA,EACvB;AAAA,EAEA,IAAI,KAAuB;AACzB,UAAM,OAAO,KAAK,MAAM,IAAI,GAAG;AAC/B,QAAI,MAAM;AACR,WAAK,MAAM,OAAO,GAAG;AACrB,WAAK,MAAM,IAAI,KAAK,IAAI;AAAA,IAC1B;AACA,WAAO;AAAA,EACT;AAAA,EAEA,IAAI,KAAQ,OAAgB;AAC1B,QAAI,KAAK,MAAM,QAAQ,KAAK,SAAS;AACnC,YAAM,YAAY,KAAK,MAAM,KAAK,EAAE,KAAK,EAAE;AAC3C,WAAK,MAAM,OAAO,SAAS;AAAA,IAC7B;AACA,SAAK,MAAM,IAAI,KAAK,KAAK;AAAA,EAC3B;AACF;AAMO,IAAM,eAAN,MAAM,aAAY;AAAA,EAQvB,YACE,eAAuB,KACf,QAAiB,OACzB;AADQ;AAJV,SAAQ,eAAuD,oBAAI,IAAI;AAMrE,SAAK,iBAAiB,IAAI,eAAe;AACzC,SAAK,aAAa,IAAI,iBAAiB,KAAK,cAAc;AAC1D,SAAK,aAAa,IAAI,SAAS,YAAY;AAAA,EAC7C;AAAA,EAEA,OAAO,cAA2B;AAChC,QAAI,CAAC,aAAY,UAAU;AACzB,mBAAY,WAAW,IAAI,aAAY;AAAA,IACzC;AACA,WAAO,aAAY;AAAA,EACrB;AAAA,EAEA,MAAM,KAAK,SAA4C;AACrD,UAAM,cAAc,KAAK,WAAW,IAAI,OAAO;AAE/C,QAAI,aAAa;AACf,UAAI,KAAK,UAAU,MAAM;AACvB,gBAAQ,IAAI,WAAW,QAAQ,MAAM,GAAG,EAAE,IAAI,CAAC,aAAa;AAAA,MAC9D;AACA,YAAM,UAAU,IAAI,gBAAgB,YAAY,IAAI;AACpD,WAAK,WAAW,WAAW,SAAS,OAAO;AAC3C,aAAO,KAAK,YAAY,OAAO;AAAA,IACjC,OAAO;AACL,UAAI,KAAK,UAAU,MAAM;AACvB,gBAAQ,IAAI,WAAW,OAAO,cAAc;AAAA,MAC9C;AACA,YAAM,cAAc,KAAK,aAAa,IAAI,OAAO;AACjD,UAAI;AAAa,eAAO;AAExB,YAAM,cAAc,MAAM,OAAO,EAC9B,KAAK,CAAC,aAAa,SAAS,KAAK,CAAC,EAClC,KAAK,CAAC,SAAS;AACd,aAAK,WAAW,IAAI,SAAS,EAAE,KAAK,CAAC;AACrC,cAAM,UAAU,IAAI,gBAAgB,IAAI;AACxC,aAAK,aAAa,OAAO,OAAO;AAChC,eAAO,KAAK,YAAY,OAAO;AAAA,MACjC,CAAC;AAEH,WAAK,aAAa,IAAI,SAAS,WAAW;AAC1C,aAAO;AAAA,IACT;AAAA,EACF;AAAA,EAEA,MAAc,YAAY,KAAwC;AAChE,WAAO,IAAI,QAAQ,CAAC,SAAS,WAAW;AACtC,WAAK,WAAW;AAAA,QACd;AAAA,QACA,CAAC,WAAiB;AAChB,kBAAQ,MAAM;AAAA,QAChB;AAAA,QACA;AAAA,QACA,CAAC,UAAU;AACT,kBAAQ,MAAM,4BAA4B,GAAG,KAAK,KAAK,EAAE;AACzD,iBAAO,KAAK;AAAA,QACd;AAAA,MACF;AAAA,IACF,CAAC;AAAA,EACH;AACF;AAtEa,aACI,WAA+B;AADzC,IAAM,cAAN;;;AC5CA,IAAM,sBAAsB,CACjC,mBAC6C;AAC7C,QAAM,SAAoB,IAAI,UAAU;AACxC,QAAM,MAAM,OAAO,gBAAgB,gBAAgB,WAAW;AAE9D,QAAM,MAAM,CAAC,UAAkB;AAC7B,WAAO,QAAQ,IAAI,SAAS;AAAA,EAC9B;AAEA,QAAM,SAAmB,CAAC;AAE1B,QAAM,OAAO,CAAC,iBAAyB;AACrC,WAAO,KAAK,YAAY;AACxB,YAAQ,KAAK,YAAY;AAAA,EAC3B;AAEA,QAAM,aAAa,MAAM,KAAK,IAAI,KAAK,QAAQ,EAAE;AAAA,IAC/C,CAAC,UAAU,MAAM,QAAQ,YAAY,MAAM;AAAA,EAC7C;AACA,QAAM,iBAAiB,WAAW,MAAM;AAExC,MAAI,WAAW,SAAS,GAAG;AACzB,UAAM,SAAS,IAAI,WAAW,MAAM;AACpC;AAAA,MACE,YAAY,WAAW,MAAM,wBAAwB,MAAM;AAAA,IAC7D;AAAA,EACF;AAEA,QAAM,mBAAmB,IAAI,iBAAiB,oBAAoB;AAClE,MAAI,iBAAiB,SAAS,GAAG;AAC/B,UAAM,SAAS,IAAI,iBAAiB,MAAM;AAC1C;AAAA,MACE,YAAY,iBAAiB,MAAM,yBAAyB,MAAM;AAAA,IACpE;AAAA,EACF;AAEA,QAAM,aAAa,MAAM,KAAK,IAAI,KAAK,QAAQ,EAAE;AAAA,IAC/C,CAAC,UAAU,MAAM,QAAQ,YAAY,MAAM;AAAA,EAC7C;AACA,MAAI,WAAW,SAAS,GAAG;AACzB,UAAM,SAAS,IAAI,WAAW,MAAM;AACpC;AAAA,MACE,YAAY,WAAW,MAAM,cAAc,MAAM;AAAA,IACnD;AAAA,EACF;AAEA,MAAI,OAAoC,EAAE,KAAK,GAAG;AAClD,MAAI,QAAuC,CAAC;AAE5C,MAAI,gBAAgB;AAClB,UAAM,UAAU,eAAe,aAAa,KAAK,KAAK;AACtD,WAAO,EAAE,KAAK,QAAQ;AAEtB,UAAM,sBAAsB,MAAM,KAAK,eAAe,QAAQ,EAAE;AAAA,MAC9D,CAAC,UAAU,MAAM,QAAQ,YAAY,MAAM;AAAA,IAC7C;AACA,YAAQ,oBAAoB,IAAI,CAAC,UAAU;AACzC,YAAM,UAAU,MAAM,aAAa,KAAK,KAAK;AAE7C,YAAM,aAAa,MAAM,aAAa,QAAQ;AAC9C,YAAM,WAAW;AAAA,QACf,GAAG,WAAW,MAAM,aAAa,GAAG,KAAK,GAAG,KAAK;AAAA,QACjD,GAAG,WAAW,MAAM,aAAa,GAAG,KAAK,GAAG,KAAK;AAAA,QACjD,GAAG,WAAW,MAAM,aAAa,GAAG,KAAK,GAAG,KAAK;AAAA,MACnD;AACA,YAAM,QAAQ;AAAA,QACZ,GAAG,WAAW,MAAM,aAAa,IAAI,KAAK,GAAG,KAAK;AAAA,QAClD,GAAG,WAAW,MAAM,aAAa,IAAI,KAAK,GAAG,KAAK;AAAA,QAClD,GAAG,WAAW,MAAM,aAAa,IAAI,KAAK,GAAG,KAAK;AAAA,MACpD;AACA,YAAM,WAAW;AAAA,QACf,GAAG,WAAW,MAAM,aAAa,IAAI,KAAK,GAAG,KAAK;AAAA,QAClD,GAAG,WAAW,MAAM,aAAa,IAAI,KAAK,GAAG,KAAK;AAAA,QAClD,GAAG,WAAW,MAAM,aAAa,IAAI,KAAK,GAAG,KAAK;AAAA,MACpD;AAEA,YAAM,YAAY,aAAa,EAAE,QAAQ,YAAY,UAAU,OAAO,SAAS,IAAI;AAEnF,aAAO,EAAE,KAAK,SAAS,QAAQ,UAAU;AAAA,IAC3C,CAAC;AAED,UAAM,mBAAmB,MAAM,KAAK,IAAI,iBAAiB,qBAAqB,CAAC,EAAE;AAAA,MAC/E,CAAC,UAAU,CAAC,oBAAoB,SAAS,KAAK;AAAA,IAChD;AACA,QAAI,iBAAiB,SAAS,GAAG;AAC/B,YAAM,SAAS,IAAI,iBAAiB,MAAM;AAC1C;AAAA,QACE,YAAY,iBAAiB,MAAM,cAAc,MAAM;AAAA,MACzD;AAAA,IACF;AAAA,EACF,OAAO;AACL,SAAK,gEAAgE;AAAA,EACvE;AAEA,QAAM,uBAAgD;AAAA,IACpD;AAAA,IACA;AAAA,EACF;AAEA,SAAO,CAAC,sBAAsB,MAAM;AACtC;;;ACrHO,IAAM,2BAA2B,CAAC,yBAA0D;AACjG,QAAM,OAAO,qBAAqB,KAAK;AAEvC,QAAM,YAAY,qBAAqB,MAAM;AAAA,IAC3C,CAAC,SAAS,iBAAiB,KAAK,GAAG,IAAI,KAAK,OAAO,UAAU,KAAK,IAAI,MAAM,EAAE;AAAA,EAChF;AAEA,SAAO,qBAAqB,IAAI;AAAA,IAC9B,UAAU,KAAK,MAAM,CAAC;AAAA;AAE1B;",
|
6
6
|
"names": ["clone"]
|
7
7
|
}
|
package/package.json
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
{
|
2
2
|
"name": "@mml-io/3d-web-avatar",
|
3
|
-
"version": "0.
|
3
|
+
"version": "0.13.0",
|
4
4
|
"publishConfig": {
|
5
5
|
"access": "public"
|
6
6
|
},
|
@@ -16,7 +16,8 @@
|
|
16
16
|
"start": "NODE_ENV=production node build/index.js 2>error.log",
|
17
17
|
"type-check": "tsc --noEmit",
|
18
18
|
"lint": "eslint \"./{src,test}/**/*.{js,jsx,ts,tsx}\" --max-warnings 0",
|
19
|
-
"lint-fix": "eslint \"./{src,test}/**/*.{js,jsx,ts,tsx}\" --fix"
|
19
|
+
"lint-fix": "eslint \"./{src,test}/**/*.{js,jsx,ts,tsx}\" --fix",
|
20
|
+
"test": "jest"
|
20
21
|
},
|
21
22
|
"dependencies": {
|
22
23
|
"react": "^18.2.0",
|
@@ -28,7 +29,7 @@
|
|
28
29
|
"@types/react": "^18.2.48",
|
29
30
|
"@types/react-dom": "^18.2.18",
|
30
31
|
"@types/three": "0.153.0",
|
31
|
-
"esbuild-css-modules-plugin": "3.0
|
32
|
+
"esbuild-css-modules-plugin": "3.1.0"
|
32
33
|
},
|
33
|
-
"gitHead": "
|
34
|
+
"gitHead": "dd4ec3072e0fec33f7a885b4123636cbe0222fcd"
|
34
35
|
}
|