roavatar-renderer 1.2.15 → 1.2.16

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.d.ts CHANGED
@@ -295,6 +295,10 @@ export declare const API: {
295
295
  PremiumFeatures: {
296
296
  GetSubscription: (userId: number) => Promise<Response | GetSubscription_Result>;
297
297
  };
298
+ RBLXGet: typeof RBLXGet;
299
+ RBLXPost: typeof RBLXPost;
300
+ RBLXDelete: typeof RBLXDelete;
301
+ RBLXPatch: typeof RBLXPatch;
298
302
  };
299
303
 
300
304
  export declare function arrayBufferToBase64(buffer: ArrayBuffer): string;
@@ -1545,6 +1549,8 @@ export declare const magic = "<roblox!";
1545
1549
 
1546
1550
  export declare function magnitude(v: Vec3): number;
1547
1551
 
1552
+ export declare const MakeupAssetTypes: string[];
1553
+
1548
1554
  export declare class MakeupDescriptionWrapper extends InstanceWrapper {
1549
1555
  static className: string;
1550
1556
  static requiredProperties: string[];
@@ -2060,6 +2066,14 @@ export declare class RBFDeformerPatch {
2060
2066
  deformMesh(): void;
2061
2067
  }
2062
2068
 
2069
+ declare function RBLXDelete(url: string, auth: Authentication, body: any, attempt?: number): Promise<Response>;
2070
+
2071
+ declare function RBLXGet(url: string, headers?: any, includeCredentials?: boolean): Promise<Response>;
2072
+
2073
+ declare function RBLXPatch(url: string, auth: Authentication, body: any, attempt?: number): Promise<Response>;
2074
+
2075
+ declare function RBLXPost(url: string, auth: Authentication | undefined, body: any, attempt?: number, method?: string): Promise<Response>;
2076
+
2063
2077
  export declare class RBX {
2064
2078
  classCount: number;
2065
2079
  instanceCount: number;
@@ -2610,7 +2624,7 @@ declare type ValidationIssue = {
2610
2624
  assetIndex?: number;
2611
2625
  };
2612
2626
 
2613
- declare type ValidationIssueType = "AccessoryLimit" | "LayeredLimit" | "OneOfTypeLimit" | "DuplicateId" | "NotWearable" | "MissingLayeredMeta" | "InvalidAsset";
2627
+ declare type ValidationIssueType = "AccessoryLimit" | "LayeredLimit" | "OneOfTypeLimit" | "DuplicateId" | "NotWearable" | "MissingLayeredMeta" | "InvalidAsset" | "MakeupLimit";
2614
2628
 
2615
2629
  export declare type Vec2 = [number, number];
2616
2630
 
package/dist/index.js CHANGED
@@ -287,6 +287,11 @@ const LayeredClothingAssetOrder = {
287
287
  90: 16
288
288
  // EyeMakeup
289
289
  };
290
+ const MakeupAssetTypes = [
291
+ "FaceMakeup",
292
+ "LipMakeup",
293
+ "EyeMakeup"
294
+ ];
290
295
  const MaxPerAsset = {
291
296
  "Head": 1,
292
297
  "TShirt": 1,
@@ -26700,6 +26705,7 @@ class WebGLRenderer {
26700
26705
  gl.unpackColorSpace = ColorManagement._getUnpackColorSpace();
26701
26706
  }
26702
26707
  }
26708
+ const textDecoder$1 = new TextDecoder();
26703
26709
  class SimpleView {
26704
26710
  view;
26705
26711
  viewOffset;
@@ -26757,7 +26763,7 @@ class SimpleView {
26757
26763
  if (!stringLength) {
26758
26764
  stringLength = this.readUint32();
26759
26765
  }
26760
- const string = new TextDecoder().decode(new Uint8Array(this.view.buffer).subarray(this.viewOffset, this.viewOffset + stringLength));
26766
+ const string = textDecoder$1.decode(new Uint8Array(this.view.buffer).subarray(this.viewOffset, this.viewOffset + stringLength));
26761
26767
  this.viewOffset += stringLength;
26762
26768
  return string;
26763
26769
  }
@@ -26889,6 +26895,7 @@ function intToRgb(colorInt) {
26889
26895
  const B = colorInt & 255;
26890
26896
  return { R, G, B };
26891
26897
  }
26898
+ const textDecoder = new TextDecoder();
26892
26899
  class RBXSimpleView {
26893
26900
  view;
26894
26901
  viewOffset;
@@ -26926,7 +26933,7 @@ class RBXSimpleView {
26926
26933
  if (!stringLength) {
26927
26934
  stringLength = this.readUint32();
26928
26935
  }
26929
- const string = new TextDecoder().decode(new Uint8Array(this.view.buffer).subarray(this.viewOffset, this.viewOffset + stringLength));
26936
+ const string = textDecoder.decode(new Uint8Array(this.view.buffer).subarray(this.viewOffset, this.viewOffset + stringLength));
26930
26937
  this.viewOffset += stringLength;
26931
26938
  return string;
26932
26939
  }
@@ -29238,7 +29245,7 @@ function nearestSearch(node, target, best = { dist: Infinity, index: -1 }) {
29238
29245
  }
29239
29246
  return best;
29240
29247
  }
29241
- const jsContent = '(function() {\n "use strict";\n const FullBodyColorPalette = [\n {\n "brickColorId": 361,\n "hexColor": "#564236",\n "name": "Dirt brown"\n },\n {\n "brickColorId": 192,\n "hexColor": "#694028",\n "name": "Reddish brown"\n },\n {\n "brickColorId": 217,\n "hexColor": "#7C5C46",\n "name": "Brown"\n },\n {\n "brickColorId": 153,\n "hexColor": "#957977",\n "name": "Sand red"\n },\n {\n "brickColorId": 359,\n "hexColor": "#AF9483",\n "name": "Linen"\n },\n {\n "brickColorId": 352,\n "hexColor": "#C7AC78",\n "name": "Burlap"\n },\n {\n "brickColorId": 5,\n "hexColor": "#D7C59A",\n "name": "Brick yellow"\n },\n {\n "brickColorId": 101,\n "hexColor": "#DA867A",\n "name": "Medium red"\n },\n {\n "brickColorId": 1007,\n "hexColor": "#A34B4B",\n "name": "Dusty Rose"\n },\n {\n "brickColorId": 1014,\n "hexColor": "#AA5500",\n "name": "CGA brown"\n },\n {\n "brickColorId": 38,\n "hexColor": "#A05F35",\n "name": "Dark orange"\n },\n {\n "brickColorId": 18,\n "hexColor": "#CC8E69",\n "name": "Nougat"\n },\n {\n "brickColorId": 125,\n "hexColor": "#EAB892",\n "name": "Light orange"\n },\n {\n "brickColorId": 1030,\n "hexColor": "#FFCC99",\n "name": "Pastel brown"\n },\n {\n "brickColorId": 133,\n "hexColor": "#D5733D",\n "name": "Neon orange"\n },\n {\n "brickColorId": 106,\n "hexColor": "#DA8541",\n "name": "Bright orange"\n },\n {\n "brickColorId": 105,\n "hexColor": "#E29B40",\n "name": "Br. yellowish orange"\n },\n {\n "brickColorId": 1017,\n "hexColor": "#FFAF00",\n "name": "Deep orange"\n },\n {\n "brickColorId": 24,\n "hexColor": "#F5CD30",\n "name": "Bright yellow"\n },\n {\n "brickColorId": 334,\n "hexColor": "#F8D96D",\n "name": "Daisy orange"\n },\n {\n "brickColorId": 226,\n "hexColor": "#FDEA8D",\n "name": "Cool yellow"\n },\n {\n "brickColorId": 141,\n "hexColor": "#27462D",\n "name": "Earth green"\n },\n {\n "brickColorId": 1021,\n "hexColor": "#3A7D15",\n "name": "Camo"\n },\n {\n "brickColorId": 28,\n "hexColor": "#287F47",\n "name": "Dark green"\n },\n {\n "brickColorId": 37,\n "hexColor": "#4B974B",\n "name": "Bright green"\n },\n {\n "brickColorId": 310,\n "hexColor": "#5B9A4C",\n "name": "Shamrock"\n },\n {\n "brickColorId": 317,\n "hexColor": "#7C9C6B",\n "name": "Moss"\n },\n {\n "brickColorId": 119,\n "hexColor": "#A4BD47",\n "name": "Br. yellowish green"\n },\n {\n "brickColorId": 1011,\n "hexColor": "#002060",\n "name": "Navy blue"\n },\n {\n "brickColorId": 1012,\n "hexColor": "#2154B9",\n "name": "Deep blue"\n },\n {\n "brickColorId": 1010,\n "hexColor": "#0000FF",\n "name": "Really blue"\n },\n {\n "brickColorId": 23,\n "hexColor": "#0D69AC",\n "name": "Bright blue"\n },\n {\n "brickColorId": 305,\n "hexColor": "#527CAE",\n "name": "Steel blue"\n },\n {\n "brickColorId": 102,\n "hexColor": "#6E99CA",\n "name": "Medium blue"\n },\n {\n "brickColorId": 45,\n "hexColor": "#B4D2E4",\n "name": "Light blue"\n },\n {\n "brickColorId": 107,\n "hexColor": "#008F9C",\n "name": "Bright bluish green"\n },\n {\n "brickColorId": 1018,\n "hexColor": "#12EED4",\n "name": "Teal"\n },\n {\n "brickColorId": 1027,\n "hexColor": "#9FF3E9",\n "name": "Pastel blue-green"\n },\n {\n "brickColorId": 1019,\n "hexColor": "#00FFFF",\n "name": "Toothpaste"\n },\n {\n "brickColorId": 1013,\n "hexColor": "#04AFEC",\n "name": "Cyan"\n },\n {\n "brickColorId": 11,\n "hexColor": "#80BBDC",\n "name": "Pastel Blue"\n },\n {\n "brickColorId": 1024,\n "hexColor": "#AFDDFF",\n "name": "Pastel light blue"\n },\n {\n "brickColorId": 104,\n "hexColor": "#6B327C",\n "name": "Bright violet"\n },\n {\n "brickColorId": 1023,\n "hexColor": "#8C5B9F",\n "name": "Lavender"\n },\n {\n "brickColorId": 321,\n "hexColor": "#A75E9B",\n "name": "Lilac"\n },\n {\n "brickColorId": 1015,\n "hexColor": "#AA00AA",\n "name": "Magenta"\n },\n {\n "brickColorId": 1031,\n "hexColor": "#6225D1",\n "name": "Royal purple"\n },\n {\n "brickColorId": 1006,\n "hexColor": "#B480FF",\n "name": "Alder"\n },\n {\n "brickColorId": 1026,\n "hexColor": "#B1A7FF",\n "name": "Pastel violet"\n },\n {\n "brickColorId": 21,\n "hexColor": "#C4281C",\n "name": "Bright red"\n },\n {\n "brickColorId": 1004,\n "hexColor": "#FF0000",\n "name": "Really red"\n },\n {\n "brickColorId": 1032,\n "hexColor": "#FF00BF",\n "name": "Hot pink"\n },\n {\n "brickColorId": 1016,\n "hexColor": "#FF66CC",\n "name": "Pink"\n },\n {\n "brickColorId": 330,\n "hexColor": "#FF98DC",\n "name": "Carnation pink"\n },\n {\n "brickColorId": 9,\n "hexColor": "#E8BAC8",\n "name": "Light reddish violet"\n },\n {\n "brickColorId": 1025,\n "hexColor": "#FFC9C9",\n "name": "Pastel orange"\n },\n {\n "brickColorId": 364,\n "hexColor": "#5A4C42",\n "name": "Dark taupe"\n },\n {\n "brickColorId": 351,\n "hexColor": "#BC9B5D",\n "name": "Cork"\n },\n {\n "brickColorId": 1008,\n "hexColor": "#C1BE42",\n "name": "Olive"\n },\n {\n "brickColorId": 29,\n "hexColor": "#A1C48C",\n "name": "Medium green"\n },\n {\n "brickColorId": 1022,\n "hexColor": "#7F8E64",\n "name": "Grime"\n },\n {\n "brickColorId": 151,\n "hexColor": "#789082",\n "name": "Sand green"\n },\n {\n "brickColorId": 135,\n "hexColor": "#74869D",\n "name": "Sand blue"\n },\n {\n "brickColorId": 1020,\n "hexColor": "#00FF00",\n "name": "Lime green"\n },\n {\n "brickColorId": 1028,\n "hexColor": "#CCFFCC",\n "name": "Pastel green"\n },\n {\n "brickColorId": 1009,\n "hexColor": "#FFFF00",\n "name": "New Yeller"\n },\n {\n "brickColorId": 1029,\n "hexColor": "#FFFFCC",\n "name": "Pastel yellow"\n },\n {\n "brickColorId": 1003,\n "hexColor": "#111111",\n "name": "Really black"\n },\n {\n "brickColorId": 26,\n "hexColor": "#1B2A35",\n "name": "Black"\n },\n {\n "brickColorId": 199,\n "hexColor": "#635F62",\n "name": "Dark stone grey"\n },\n {\n "brickColorId": 194,\n "hexColor": "#A3A2A5",\n "name": "Medium stone grey"\n },\n {\n "brickColorId": 1002,\n "hexColor": "#CDCDCD",\n "name": "Mid gray"\n },\n {\n "brickColorId": 208,\n "hexColor": "#E5E4DF",\n "name": "Light stone grey"\n },\n {\n "brickColorId": 1,\n "hexColor": "#F2F3F3",\n "name": "White"\n },\n {\n "brickColorId": 1001,\n "hexColor": "#F8F8F8",\n "name": "Institutional white"\n }\n ];\n const RegularBodyColors = [\n "5A4C42",\n "7C5C46",\n "AF9483",\n "CC8E69",\n "EAB892",\n "564236",\n "694028",\n "BC9B5D",\n "c7ac78",\n "d7c59a",\n "957977",\n "a34b4b",\n "da867a",\n "ffc9c9",\n "ff98dc",\n "74869d",\n "527cae",\n "80bbdc",\n "b1a7ff",\n "a75e9b",\n "008f9c",\n "5b9a4c",\n "7c9c6b",\n "a1c48c",\n "e29b40",\n "f5cd30",\n "f8d96d",\n "635f62",\n "cdcdcd",\n "f8f8f8"\n ];\n for (let i = 0; i < RegularBodyColors.length; i++) {\n const color = RegularBodyColors[i];\n RegularBodyColors[i] = color.toUpperCase();\n }\n const FullBodyColors = [];\n for (const colorDetails of FullBodyColorPalette) {\n FullBodyColors.push(colorDetails.hexColor.substring(1));\n }\n function calculateMagnitude3D(x, y, z) {\n return Math.sqrt(x * x + y * y + z * z);\n }\n function magnitude(v) {\n return calculateMagnitude3D(v[0], v[1], v[2]);\n }\n function minus(v0, v1) {\n return [v0[0] - v1[0], v0[1] - v1[1], v0[2] - v1[2]];\n }\n function distance(v0, v1) {\n return magnitude(minus(v1, v0));\n }\n class KDNode {\n point;\n index;\n axis;\n left = null;\n right = null;\n constructor(point, index, axis) {\n this.point = point;\n this.index = index;\n this.axis = axis;\n }\n }\n function buildKDTree(points, indices, depth = 0) {\n if (points.length === 0) return null;\n const axis = depth % 3;\n const sorted = points.map((p, i) => ({ p, index: indices[i] })).sort((a, b) => a.p[axis] - b.p[axis]);\n const mid = Math.floor(sorted.length / 2);\n const node = new KDNode(sorted[mid].p, sorted[mid].index, axis);\n const leftPoints = sorted.slice(0, mid).map((x) => x.p);\n const leftIndices = sorted.slice(0, mid).map((x) => x.index);\n const rightPoints = sorted.slice(mid + 1).map((x) => x.p);\n const rightIndices = sorted.slice(mid + 1).map((x) => x.index);\n node.left = buildKDTree(leftPoints, leftIndices, depth + 1);\n node.right = buildKDTree(rightPoints, rightIndices, depth + 1);\n return node;\n }\n function siftUp(heap, i) {\n while (i > 0) {\n const p = i - 1 >> 1;\n if (heap[p].dist >= heap[i].dist) break;\n const tmp = heap[p];\n heap[p] = heap[i];\n heap[i] = tmp;\n i = p;\n }\n }\n function siftDown(heap, i) {\n const n = heap.length;\n while (true) {\n let largest = i;\n const l = (i << 1) + 1;\n const r = l + 1;\n if (l < n && heap[l].dist > heap[largest].dist) largest = l;\n if (r < n && heap[r].dist > heap[largest].dist) largest = r;\n if (largest === i) break;\n const tmp = heap[i];\n heap[i] = heap[largest];\n heap[largest] = tmp;\n i = largest;\n }\n }\n function heapPushMax(heap, item, k) {\n if (heap.length < k) {\n heap.push(item);\n siftUp(heap, heap.length - 1);\n return;\n }\n if (item.dist >= heap[0].dist) return;\n heap[0] = item;\n siftDown(heap, 0);\n }\n function distSq(a, b) {\n const dx = a[0] - b[0];\n const dy = a[1] - b[1];\n const dz = a[2] - b[2];\n return dx * dx + dy * dy + dz * dz;\n }\n function knnSearch(node, target, k, heap = []) {\n if (!node) return heap;\n const axis = node.axis;\n const dist = distSq(target, node.point);\n heapPushMax(heap, { dist, index: node.index }, k);\n const diff = target[axis] - node.point[axis];\n const primary = diff < 0 ? node.left : node.right;\n const secondary = diff < 0 ? node.right : node.left;\n knnSearch(primary, target, k, heap);\n const worstDist = heap.length < k ? Infinity : heap[0].dist;\n if (diff * diff < worstDist) {\n knnSearch(secondary, target, k, heap);\n }\n if (node === null) {\n heap.sort((a, b) => a.dist - b.dist);\n }\n return heap;\n }\n function nearestSearch(node, target, best = { dist: Infinity, index: -1 }) {\n if (!node) return best;\n const dist = distance(target, node.point);\n if (dist < best.dist) {\n best = { dist, index: node.index };\n }\n const axis = node.axis;\n const diff = target[axis] - node.point[axis];\n const primary = diff < 0 ? node.left : node.right;\n const secondary = diff < 0 ? node.right : node.left;\n best = nearestSearch(primary, target, best);\n if (Math.abs(diff) < best.dist) {\n best = nearestSearch(secondary, target, best);\n }\n return best;\n }\n function luDecompose(A) {\n const n = A.length;\n const LU = A;\n const P = new Int32Array(n);\n for (let i = 0; i < n; i++) P[i] = i;\n for (let k = 0; k < n; k++) {\n let pivot = k;\n for (let i = k + 1; i < n; i++) {\n if (Math.abs(LU[i][k]) > Math.abs(LU[pivot][k])) {\n pivot = i;\n }\n }\n if (pivot !== k) {\n const tmpRow = LU[k];\n LU[k] = LU[pivot];\n LU[pivot] = tmpRow;\n const tmpP = P[k];\n P[k] = P[pivot];\n P[pivot] = tmpP;\n }\n const pivotVal = LU[k][k];\n for (let i = k + 1; i < n; i++) {\n LU[i][k] /= pivotVal;\n const mult = LU[i][k];\n const rowI = LU[i];\n const rowK = LU[k];\n for (let j = k + 1; j < n; j++) {\n rowI[j] -= mult * rowK[j];\n }\n }\n }\n return { LU, P };\n }\n function luSolve({ LU, P }, b) {\n const n = LU.length;\n const x = new Float32Array(n);\n for (let i = 0; i < n; i++) {\n x[i] = b[P[i]];\n }\n for (let i = 0; i < n; i++) {\n const row = LU[i];\n let sum = x[i];\n for (let j = 0; j < i; j++) {\n sum -= row[j] * x[j];\n }\n x[i] = sum;\n }\n for (let i = n - 1; i >= 0; i--) {\n const row = LU[i];\n let sum = x[i];\n for (let j = i + 1; j < n; j++) {\n sum -= row[j] * x[j];\n }\n x[i] = sum / row[i];\n }\n return x;\n }\n function patchRBFWorkerFunc([_A, _bx, _by, _bz]) {\n const A = _A.map((r) => new Float32Array(r));\n const bx = new Float32Array(_bx);\n const by = new Float32Array(_by);\n const bz = new Float32Array(_bz);\n const LU = luDecompose(A);\n const wx = luSolve(LU, bx);\n const wy = luSolve(LU, by);\n const wz = luSolve(LU, bz);\n const n = wx.length;\n const result = new Float32Array(n * 3);\n for (let i = 0; i < n; i++) {\n result[i * 3 + 0] = wx[i];\n result[i * 3 + 1] = wy[i];\n result[i * 3 + 2] = wz[i];\n }\n return result.buffer;\n }\n function RBFDeformerSolveAsync([patchCount, detailsCount, epsilon, importantIndicesBuf, refVertsBuf, distVertsBuf, meshVertsBuf, meshBonesBuf]) {\n const importantIndices = new Uint16Array(importantIndicesBuf);\n const refVerts = new Float32Array(refVertsBuf);\n const distVerts = new Float32Array(distVertsBuf);\n const meshVerts = new Float32Array(meshVertsBuf);\n const meshBones = new Float32Array(meshBonesBuf);\n const refCount = refVerts.length / 3;\n const meshVertCount = meshVerts.length / 3;\n const meshBoneCount = meshBones.length / 3;\n const points = new Array(refCount);\n const indices = new Array(refCount);\n for (let i = 0; i < refCount; i++) {\n const refPos = [refVerts[i * 3 + 0], refVerts[i * 3 + 1], refVerts[i * 3 + 2]];\n points[i] = refPos;\n indices[i] = i;\n }\n const controlKD = buildKDTree(points, indices);\n const step = Math.max(1, Math.floor(refCount / patchCount));\n const patchCenters = [];\n for (let i = 0; i < refCount; i += step) {\n const refPos = [refVerts[i * 3 + 0], refVerts[i * 3 + 1], refVerts[i * 3 + 2]];\n patchCenters.push(refPos);\n if (patchCenters.length >= patchCount) break;\n }\n const neighborIndices = new Array(patchCenters.length);\n const weights = new Array(patchCenters.length);\n const patchIndices = patchCenters.map((_, i) => i);\n const patchKD = buildKDTree(patchCenters, patchIndices);\n const isUsedArr = new Array(patchCenters.length).fill(false);\n const nearestPatch = new Uint16Array(meshVertCount + meshBoneCount);\n for (let i = 0; i < meshVertCount; i++) {\n const vec = [meshVerts[i * 3 + 0], meshVerts[i * 3 + 1], meshVerts[i * 3 + 2]];\n const nearestPatchNode = nearestSearch(patchKD, vec);\n isUsedArr[nearestPatchNode.index] = true;\n nearestPatch[i] = nearestPatchNode.index;\n }\n for (let i = 0; i < meshBoneCount; i++) {\n const vec = [meshBones[i * 3 + 0], meshBones[i * 3 + 1], meshBones[i * 3 + 2]];\n const nearestPatchNode = nearestSearch(patchKD, vec);\n isUsedArr[nearestPatchNode.index] = true;\n nearestPatch[i + meshVertCount] = nearestPatchNode.index;\n }\n for (let i = 0; i < patchCenters.length; i++) {\n if (!isUsedArr[i]) {\n continue;\n }\n const centerPos = patchCenters[i];\n const neighbors = knnSearch(controlKD, centerPos, detailsCount);\n const foundNeighborIndices = neighbors.map((n) => n.index);\n for (const important of importantIndices) {\n if (!foundNeighborIndices.includes(important)) {\n foundNeighborIndices.push(important);\n }\n }\n neighborIndices[i] = new Uint16Array(foundNeighborIndices);\n }\n const A_array = new Array(patchCenters.length);\n for (let p = 0; p < patchCenters.length; p++) {\n const patchNeighborIndices = neighborIndices[p];\n if (!patchNeighborIndices) continue;\n const K = patchNeighborIndices.length;\n const positions = new Array(patchNeighborIndices.length);\n for (let i = 0; i < patchNeighborIndices.length; i++) {\n const j = patchNeighborIndices[i];\n const refPos = [refVerts[j * 3 + 0], refVerts[j * 3 + 1], refVerts[j * 3 + 2]];\n positions[i] = refPos;\n }\n const A = new Array(K);\n for (let i = 0; i < K; i++) {\n A[i] = new Float32Array(K);\n }\n for (let i = 0; i < K; i++) {\n const [pix, piy, piz] = positions[i];\n for (let j = i + 1; j < K; j++) {\n const [pjx, pjy, pjz] = positions[j];\n const dist = Math.sqrt((pix - pjx) * (pix - pjx) + (piy - pjy) * (piy - pjy) + (piz - pjz) * (piz - pjz));\n A[i][j] = dist;\n A[j][i] = dist;\n }\n A[i][i] = epsilon;\n }\n A_array[p] = A;\n }\n for (let p = 0; p < patchCenters.length; p++) {\n if (!isUsedArr[p]) {\n continue;\n }\n const patchNeighborIndices = neighborIndices[p];\n const K = patchNeighborIndices.length;\n const usedRef = new Array(K);\n const usedDist = new Array(K);\n for (let i = 0; i < K; i++) {\n const idx = patchNeighborIndices[i];\n const j = idx;\n const refPos = [refVerts[j * 3 + 0], refVerts[j * 3 + 1], refVerts[j * 3 + 2]];\n const distPos = [distVerts[j * 3 + 0], distVerts[j * 3 + 1], distVerts[j * 3 + 2]];\n usedRef[i] = refPos;\n usedDist[i] = distPos;\n }\n const A = A_array[p];\n const bx = new Float32Array(K);\n const by = new Float32Array(K);\n const bz = new Float32Array(K);\n for (let i = 0; i < K; i++) {\n const dr = usedDist[i];\n const rr = usedRef[i];\n bx[i] = dr[0] - rr[0];\n by[i] = dr[1] - rr[1];\n bz[i] = dr[2] - rr[2];\n }\n const Abuffers = A.map((r) => r.buffer);\n weights[p] = new Float32Array(patchRBFWorkerFunc([Abuffers, bx.buffer, by.buffer, bz.buffer]));\n }\n const neighborIndicesBuf = neighborIndices.map((a) => {\n return a.buffer;\n });\n const weightsBuf = weights.map((a) => {\n return a.buffer;\n });\n return [neighborIndicesBuf, weightsBuf, nearestPatch.buffer];\n }\n const WorkerTypeToFunction = {\n "patchRBF": patchRBFWorkerFunc,\n "RBFDeformerSolveAsync": RBFDeformerSolveAsync\n };\n function getWorkerOnMessage() {\n return function(event) {\n const [id, type, data] = event.data;\n const func = WorkerTypeToFunction[type];\n self.postMessage([id, func(data)]);\n };\n }\n onmessage = getWorkerOnMessage();\n})();\n';
29248
+ const jsContent = '(function() {\n "use strict";\n new TextDecoder();\n new TextDecoder();\n const FullBodyColorPalette = [\n {\n "brickColorId": 361,\n "hexColor": "#564236",\n "name": "Dirt brown"\n },\n {\n "brickColorId": 192,\n "hexColor": "#694028",\n "name": "Reddish brown"\n },\n {\n "brickColorId": 217,\n "hexColor": "#7C5C46",\n "name": "Brown"\n },\n {\n "brickColorId": 153,\n "hexColor": "#957977",\n "name": "Sand red"\n },\n {\n "brickColorId": 359,\n "hexColor": "#AF9483",\n "name": "Linen"\n },\n {\n "brickColorId": 352,\n "hexColor": "#C7AC78",\n "name": "Burlap"\n },\n {\n "brickColorId": 5,\n "hexColor": "#D7C59A",\n "name": "Brick yellow"\n },\n {\n "brickColorId": 101,\n "hexColor": "#DA867A",\n "name": "Medium red"\n },\n {\n "brickColorId": 1007,\n "hexColor": "#A34B4B",\n "name": "Dusty Rose"\n },\n {\n "brickColorId": 1014,\n "hexColor": "#AA5500",\n "name": "CGA brown"\n },\n {\n "brickColorId": 38,\n "hexColor": "#A05F35",\n "name": "Dark orange"\n },\n {\n "brickColorId": 18,\n "hexColor": "#CC8E69",\n "name": "Nougat"\n },\n {\n "brickColorId": 125,\n "hexColor": "#EAB892",\n "name": "Light orange"\n },\n {\n "brickColorId": 1030,\n "hexColor": "#FFCC99",\n "name": "Pastel brown"\n },\n {\n "brickColorId": 133,\n "hexColor": "#D5733D",\n "name": "Neon orange"\n },\n {\n "brickColorId": 106,\n "hexColor": "#DA8541",\n "name": "Bright orange"\n },\n {\n "brickColorId": 105,\n "hexColor": "#E29B40",\n "name": "Br. yellowish orange"\n },\n {\n "brickColorId": 1017,\n "hexColor": "#FFAF00",\n "name": "Deep orange"\n },\n {\n "brickColorId": 24,\n "hexColor": "#F5CD30",\n "name": "Bright yellow"\n },\n {\n "brickColorId": 334,\n "hexColor": "#F8D96D",\n "name": "Daisy orange"\n },\n {\n "brickColorId": 226,\n "hexColor": "#FDEA8D",\n "name": "Cool yellow"\n },\n {\n "brickColorId": 141,\n "hexColor": "#27462D",\n "name": "Earth green"\n },\n {\n "brickColorId": 1021,\n "hexColor": "#3A7D15",\n "name": "Camo"\n },\n {\n "brickColorId": 28,\n "hexColor": "#287F47",\n "name": "Dark green"\n },\n {\n "brickColorId": 37,\n "hexColor": "#4B974B",\n "name": "Bright green"\n },\n {\n "brickColorId": 310,\n "hexColor": "#5B9A4C",\n "name": "Shamrock"\n },\n {\n "brickColorId": 317,\n "hexColor": "#7C9C6B",\n "name": "Moss"\n },\n {\n "brickColorId": 119,\n "hexColor": "#A4BD47",\n "name": "Br. yellowish green"\n },\n {\n "brickColorId": 1011,\n "hexColor": "#002060",\n "name": "Navy blue"\n },\n {\n "brickColorId": 1012,\n "hexColor": "#2154B9",\n "name": "Deep blue"\n },\n {\n "brickColorId": 1010,\n "hexColor": "#0000FF",\n "name": "Really blue"\n },\n {\n "brickColorId": 23,\n "hexColor": "#0D69AC",\n "name": "Bright blue"\n },\n {\n "brickColorId": 305,\n "hexColor": "#527CAE",\n "name": "Steel blue"\n },\n {\n "brickColorId": 102,\n "hexColor": "#6E99CA",\n "name": "Medium blue"\n },\n {\n "brickColorId": 45,\n "hexColor": "#B4D2E4",\n "name": "Light blue"\n },\n {\n "brickColorId": 107,\n "hexColor": "#008F9C",\n "name": "Bright bluish green"\n },\n {\n "brickColorId": 1018,\n "hexColor": "#12EED4",\n "name": "Teal"\n },\n {\n "brickColorId": 1027,\n "hexColor": "#9FF3E9",\n "name": "Pastel blue-green"\n },\n {\n "brickColorId": 1019,\n "hexColor": "#00FFFF",\n "name": "Toothpaste"\n },\n {\n "brickColorId": 1013,\n "hexColor": "#04AFEC",\n "name": "Cyan"\n },\n {\n "brickColorId": 11,\n "hexColor": "#80BBDC",\n "name": "Pastel Blue"\n },\n {\n "brickColorId": 1024,\n "hexColor": "#AFDDFF",\n "name": "Pastel light blue"\n },\n {\n "brickColorId": 104,\n "hexColor": "#6B327C",\n "name": "Bright violet"\n },\n {\n "brickColorId": 1023,\n "hexColor": "#8C5B9F",\n "name": "Lavender"\n },\n {\n "brickColorId": 321,\n "hexColor": "#A75E9B",\n "name": "Lilac"\n },\n {\n "brickColorId": 1015,\n "hexColor": "#AA00AA",\n "name": "Magenta"\n },\n {\n "brickColorId": 1031,\n "hexColor": "#6225D1",\n "name": "Royal purple"\n },\n {\n "brickColorId": 1006,\n "hexColor": "#B480FF",\n "name": "Alder"\n },\n {\n "brickColorId": 1026,\n "hexColor": "#B1A7FF",\n "name": "Pastel violet"\n },\n {\n "brickColorId": 21,\n "hexColor": "#C4281C",\n "name": "Bright red"\n },\n {\n "brickColorId": 1004,\n "hexColor": "#FF0000",\n "name": "Really red"\n },\n {\n "brickColorId": 1032,\n "hexColor": "#FF00BF",\n "name": "Hot pink"\n },\n {\n "brickColorId": 1016,\n "hexColor": "#FF66CC",\n "name": "Pink"\n },\n {\n "brickColorId": 330,\n "hexColor": "#FF98DC",\n "name": "Carnation pink"\n },\n {\n "brickColorId": 9,\n "hexColor": "#E8BAC8",\n "name": "Light reddish violet"\n },\n {\n "brickColorId": 1025,\n "hexColor": "#FFC9C9",\n "name": "Pastel orange"\n },\n {\n "brickColorId": 364,\n "hexColor": "#5A4C42",\n "name": "Dark taupe"\n },\n {\n "brickColorId": 351,\n "hexColor": "#BC9B5D",\n "name": "Cork"\n },\n {\n "brickColorId": 1008,\n "hexColor": "#C1BE42",\n "name": "Olive"\n },\n {\n "brickColorId": 29,\n "hexColor": "#A1C48C",\n "name": "Medium green"\n },\n {\n "brickColorId": 1022,\n "hexColor": "#7F8E64",\n "name": "Grime"\n },\n {\n "brickColorId": 151,\n "hexColor": "#789082",\n "name": "Sand green"\n },\n {\n "brickColorId": 135,\n "hexColor": "#74869D",\n "name": "Sand blue"\n },\n {\n "brickColorId": 1020,\n "hexColor": "#00FF00",\n "name": "Lime green"\n },\n {\n "brickColorId": 1028,\n "hexColor": "#CCFFCC",\n "name": "Pastel green"\n },\n {\n "brickColorId": 1009,\n "hexColor": "#FFFF00",\n "name": "New Yeller"\n },\n {\n "brickColorId": 1029,\n "hexColor": "#FFFFCC",\n "name": "Pastel yellow"\n },\n {\n "brickColorId": 1003,\n "hexColor": "#111111",\n "name": "Really black"\n },\n {\n "brickColorId": 26,\n "hexColor": "#1B2A35",\n "name": "Black"\n },\n {\n "brickColorId": 199,\n "hexColor": "#635F62",\n "name": "Dark stone grey"\n },\n {\n "brickColorId": 194,\n "hexColor": "#A3A2A5",\n "name": "Medium stone grey"\n },\n {\n "brickColorId": 1002,\n "hexColor": "#CDCDCD",\n "name": "Mid gray"\n },\n {\n "brickColorId": 208,\n "hexColor": "#E5E4DF",\n "name": "Light stone grey"\n },\n {\n "brickColorId": 1,\n "hexColor": "#F2F3F3",\n "name": "White"\n },\n {\n "brickColorId": 1001,\n "hexColor": "#F8F8F8",\n "name": "Institutional white"\n }\n ];\n const RegularBodyColors = [\n "5A4C42",\n "7C5C46",\n "AF9483",\n "CC8E69",\n "EAB892",\n "564236",\n "694028",\n "BC9B5D",\n "c7ac78",\n "d7c59a",\n "957977",\n "a34b4b",\n "da867a",\n "ffc9c9",\n "ff98dc",\n "74869d",\n "527cae",\n "80bbdc",\n "b1a7ff",\n "a75e9b",\n "008f9c",\n "5b9a4c",\n "7c9c6b",\n "a1c48c",\n "e29b40",\n "f5cd30",\n "f8d96d",\n "635f62",\n "cdcdcd",\n "f8f8f8"\n ];\n for (let i = 0; i < RegularBodyColors.length; i++) {\n const color = RegularBodyColors[i];\n RegularBodyColors[i] = color.toUpperCase();\n }\n const FullBodyColors = [];\n for (const colorDetails of FullBodyColorPalette) {\n FullBodyColors.push(colorDetails.hexColor.substring(1));\n }\n function calculateMagnitude3D(x, y, z) {\n return Math.sqrt(x * x + y * y + z * z);\n }\n function magnitude(v) {\n return calculateMagnitude3D(v[0], v[1], v[2]);\n }\n function minus(v0, v1) {\n return [v0[0] - v1[0], v0[1] - v1[1], v0[2] - v1[2]];\n }\n function distance(v0, v1) {\n return magnitude(minus(v1, v0));\n }\n class KDNode {\n point;\n index;\n axis;\n left = null;\n right = null;\n constructor(point, index, axis) {\n this.point = point;\n this.index = index;\n this.axis = axis;\n }\n }\n function buildKDTree(points, indices, depth = 0) {\n if (points.length === 0) return null;\n const axis = depth % 3;\n const sorted = points.map((p, i) => ({ p, index: indices[i] })).sort((a, b) => a.p[axis] - b.p[axis]);\n const mid = Math.floor(sorted.length / 2);\n const node = new KDNode(sorted[mid].p, sorted[mid].index, axis);\n const leftPoints = sorted.slice(0, mid).map((x) => x.p);\n const leftIndices = sorted.slice(0, mid).map((x) => x.index);\n const rightPoints = sorted.slice(mid + 1).map((x) => x.p);\n const rightIndices = sorted.slice(mid + 1).map((x) => x.index);\n node.left = buildKDTree(leftPoints, leftIndices, depth + 1);\n node.right = buildKDTree(rightPoints, rightIndices, depth + 1);\n return node;\n }\n function siftUp(heap, i) {\n while (i > 0) {\n const p = i - 1 >> 1;\n if (heap[p].dist >= heap[i].dist) break;\n const tmp = heap[p];\n heap[p] = heap[i];\n heap[i] = tmp;\n i = p;\n }\n }\n function siftDown(heap, i) {\n const n = heap.length;\n while (true) {\n let largest = i;\n const l = (i << 1) + 1;\n const r = l + 1;\n if (l < n && heap[l].dist > heap[largest].dist) largest = l;\n if (r < n && heap[r].dist > heap[largest].dist) largest = r;\n if (largest === i) break;\n const tmp = heap[i];\n heap[i] = heap[largest];\n heap[largest] = tmp;\n i = largest;\n }\n }\n function heapPushMax(heap, item, k) {\n if (heap.length < k) {\n heap.push(item);\n siftUp(heap, heap.length - 1);\n return;\n }\n if (item.dist >= heap[0].dist) return;\n heap[0] = item;\n siftDown(heap, 0);\n }\n function distSq(a, b) {\n const dx = a[0] - b[0];\n const dy = a[1] - b[1];\n const dz = a[2] - b[2];\n return dx * dx + dy * dy + dz * dz;\n }\n function knnSearch(node, target, k, heap = []) {\n if (!node) return heap;\n const axis = node.axis;\n const dist = distSq(target, node.point);\n heapPushMax(heap, { dist, index: node.index }, k);\n const diff = target[axis] - node.point[axis];\n const primary = diff < 0 ? node.left : node.right;\n const secondary = diff < 0 ? node.right : node.left;\n knnSearch(primary, target, k, heap);\n const worstDist = heap.length < k ? Infinity : heap[0].dist;\n if (diff * diff < worstDist) {\n knnSearch(secondary, target, k, heap);\n }\n if (node === null) {\n heap.sort((a, b) => a.dist - b.dist);\n }\n return heap;\n }\n function nearestSearch(node, target, best = { dist: Infinity, index: -1 }) {\n if (!node) return best;\n const dist = distance(target, node.point);\n if (dist < best.dist) {\n best = { dist, index: node.index };\n }\n const axis = node.axis;\n const diff = target[axis] - node.point[axis];\n const primary = diff < 0 ? node.left : node.right;\n const secondary = diff < 0 ? node.right : node.left;\n best = nearestSearch(primary, target, best);\n if (Math.abs(diff) < best.dist) {\n best = nearestSearch(secondary, target, best);\n }\n return best;\n }\n function luDecompose(A) {\n const n = A.length;\n const LU = A;\n const P = new Int32Array(n);\n for (let i = 0; i < n; i++) P[i] = i;\n for (let k = 0; k < n; k++) {\n let pivot = k;\n for (let i = k + 1; i < n; i++) {\n if (Math.abs(LU[i][k]) > Math.abs(LU[pivot][k])) {\n pivot = i;\n }\n }\n if (pivot !== k) {\n const tmpRow = LU[k];\n LU[k] = LU[pivot];\n LU[pivot] = tmpRow;\n const tmpP = P[k];\n P[k] = P[pivot];\n P[pivot] = tmpP;\n }\n const pivotVal = LU[k][k];\n for (let i = k + 1; i < n; i++) {\n LU[i][k] /= pivotVal;\n const mult = LU[i][k];\n const rowI = LU[i];\n const rowK = LU[k];\n for (let j = k + 1; j < n; j++) {\n rowI[j] -= mult * rowK[j];\n }\n }\n }\n return { LU, P };\n }\n function luSolve({ LU, P }, b) {\n const n = LU.length;\n const x = new Float32Array(n);\n for (let i = 0; i < n; i++) {\n x[i] = b[P[i]];\n }\n for (let i = 0; i < n; i++) {\n const row = LU[i];\n let sum = x[i];\n for (let j = 0; j < i; j++) {\n sum -= row[j] * x[j];\n }\n x[i] = sum;\n }\n for (let i = n - 1; i >= 0; i--) {\n const row = LU[i];\n let sum = x[i];\n for (let j = i + 1; j < n; j++) {\n sum -= row[j] * x[j];\n }\n x[i] = sum / row[i];\n }\n return x;\n }\n function patchRBFWorkerFunc([_A, _bx, _by, _bz]) {\n const A = _A.map((r) => new Float32Array(r));\n const bx = new Float32Array(_bx);\n const by = new Float32Array(_by);\n const bz = new Float32Array(_bz);\n const LU = luDecompose(A);\n const wx = luSolve(LU, bx);\n const wy = luSolve(LU, by);\n const wz = luSolve(LU, bz);\n const n = wx.length;\n const result = new Float32Array(n * 3);\n for (let i = 0; i < n; i++) {\n result[i * 3 + 0] = wx[i];\n result[i * 3 + 1] = wy[i];\n result[i * 3 + 2] = wz[i];\n }\n return result.buffer;\n }\n function RBFDeformerSolveAsync([patchCount, detailsCount, epsilon, importantIndicesBuf, refVertsBuf, distVertsBuf, meshVertsBuf, meshBonesBuf]) {\n const importantIndices = new Uint16Array(importantIndicesBuf);\n const refVerts = new Float32Array(refVertsBuf);\n const distVerts = new Float32Array(distVertsBuf);\n const meshVerts = new Float32Array(meshVertsBuf);\n const meshBones = new Float32Array(meshBonesBuf);\n const refCount = refVerts.length / 3;\n const meshVertCount = meshVerts.length / 3;\n const meshBoneCount = meshBones.length / 3;\n const points = new Array(refCount);\n const indices = new Array(refCount);\n for (let i = 0; i < refCount; i++) {\n const refPos = [refVerts[i * 3 + 0], refVerts[i * 3 + 1], refVerts[i * 3 + 2]];\n points[i] = refPos;\n indices[i] = i;\n }\n const controlKD = buildKDTree(points, indices);\n const step = Math.max(1, Math.floor(refCount / patchCount));\n const patchCenters = [];\n for (let i = 0; i < refCount; i += step) {\n const refPos = [refVerts[i * 3 + 0], refVerts[i * 3 + 1], refVerts[i * 3 + 2]];\n patchCenters.push(refPos);\n if (patchCenters.length >= patchCount) break;\n }\n const neighborIndices = new Array(patchCenters.length);\n const weights = new Array(patchCenters.length);\n const patchIndices = patchCenters.map((_, i) => i);\n const patchKD = buildKDTree(patchCenters, patchIndices);\n const isUsedArr = new Array(patchCenters.length).fill(false);\n const nearestPatch = new Uint16Array(meshVertCount + meshBoneCount);\n for (let i = 0; i < meshVertCount; i++) {\n const vec = [meshVerts[i * 3 + 0], meshVerts[i * 3 + 1], meshVerts[i * 3 + 2]];\n const nearestPatchNode = nearestSearch(patchKD, vec);\n isUsedArr[nearestPatchNode.index] = true;\n nearestPatch[i] = nearestPatchNode.index;\n }\n for (let i = 0; i < meshBoneCount; i++) {\n const vec = [meshBones[i * 3 + 0], meshBones[i * 3 + 1], meshBones[i * 3 + 2]];\n const nearestPatchNode = nearestSearch(patchKD, vec);\n isUsedArr[nearestPatchNode.index] = true;\n nearestPatch[i + meshVertCount] = nearestPatchNode.index;\n }\n for (let i = 0; i < patchCenters.length; i++) {\n if (!isUsedArr[i]) {\n continue;\n }\n const centerPos = patchCenters[i];\n const neighbors = knnSearch(controlKD, centerPos, detailsCount);\n const foundNeighborIndices = neighbors.map((n) => n.index);\n for (const important of importantIndices) {\n if (!foundNeighborIndices.includes(important)) {\n foundNeighborIndices.push(important);\n }\n }\n neighborIndices[i] = new Uint16Array(foundNeighborIndices);\n }\n const A_array = new Array(patchCenters.length);\n for (let p = 0; p < patchCenters.length; p++) {\n const patchNeighborIndices = neighborIndices[p];\n if (!patchNeighborIndices) continue;\n const K = patchNeighborIndices.length;\n const positions = new Array(patchNeighborIndices.length);\n for (let i = 0; i < patchNeighborIndices.length; i++) {\n const j = patchNeighborIndices[i];\n const refPos = [refVerts[j * 3 + 0], refVerts[j * 3 + 1], refVerts[j * 3 + 2]];\n positions[i] = refPos;\n }\n const A = new Array(K);\n for (let i = 0; i < K; i++) {\n A[i] = new Float32Array(K);\n }\n for (let i = 0; i < K; i++) {\n const [pix, piy, piz] = positions[i];\n for (let j = i + 1; j < K; j++) {\n const [pjx, pjy, pjz] = positions[j];\n const dist = Math.sqrt((pix - pjx) * (pix - pjx) + (piy - pjy) * (piy - pjy) + (piz - pjz) * (piz - pjz));\n A[i][j] = dist;\n A[j][i] = dist;\n }\n A[i][i] = epsilon;\n }\n A_array[p] = A;\n }\n for (let p = 0; p < patchCenters.length; p++) {\n if (!isUsedArr[p]) {\n continue;\n }\n const patchNeighborIndices = neighborIndices[p];\n const K = patchNeighborIndices.length;\n const usedRef = new Array(K);\n const usedDist = new Array(K);\n for (let i = 0; i < K; i++) {\n const idx = patchNeighborIndices[i];\n const j = idx;\n const refPos = [refVerts[j * 3 + 0], refVerts[j * 3 + 1], refVerts[j * 3 + 2]];\n const distPos = [distVerts[j * 3 + 0], distVerts[j * 3 + 1], distVerts[j * 3 + 2]];\n usedRef[i] = refPos;\n usedDist[i] = distPos;\n }\n const A = A_array[p];\n const bx = new Float32Array(K);\n const by = new Float32Array(K);\n const bz = new Float32Array(K);\n for (let i = 0; i < K; i++) {\n const dr = usedDist[i];\n const rr = usedRef[i];\n bx[i] = dr[0] - rr[0];\n by[i] = dr[1] - rr[1];\n bz[i] = dr[2] - rr[2];\n }\n const Abuffers = A.map((r) => r.buffer);\n weights[p] = new Float32Array(patchRBFWorkerFunc([Abuffers, bx.buffer, by.buffer, bz.buffer]));\n }\n const neighborIndicesBuf = neighborIndices.map((a) => {\n return a.buffer;\n });\n const weightsBuf = weights.map((a) => {\n return a.buffer;\n });\n return [neighborIndicesBuf, weightsBuf, nearestPatch.buffer];\n }\n const WorkerTypeToFunction = {\n "patchRBF": patchRBFWorkerFunc,\n "RBFDeformerSolveAsync": RBFDeformerSolveAsync\n };\n function getWorkerOnMessage() {\n return function(event) {\n const [id, type, data] = event.data;\n const func = WorkerTypeToFunction[type];\n self.postMessage([id, func(data)]);\n };\n }\n onmessage = getWorkerOnMessage();\n})();\n';
29242
29249
  const blob = typeof self !== "undefined" && self.Blob && new Blob(["(self.URL || self.webkitURL).revokeObjectURL(self.location.href);", jsContent], { type: "text/javascript;charset=utf-8" });
29243
29250
  function WorkerWrapper(options) {
29244
29251
  let objURL;
@@ -32588,6 +32595,7 @@ class Outfit {
32588
32595
  const usedIds = [];
32589
32596
  let totalAccessories = 0;
32590
32597
  let totalLayered = 0;
32598
+ let totalMakeup = 0;
32591
32599
  for (let i = 0; i < this.assets.length; i++) {
32592
32600
  const asset = this.assets[i];
32593
32601
  if (!(asset instanceof Asset)) {
@@ -32628,7 +32636,7 @@ class Outfit {
32628
32636
  });
32629
32637
  }
32630
32638
  }
32631
- if (LayeredAssetTypes.includes(asset.assetType.name)) {
32639
+ if (LayeredAssetTypes.includes(asset.assetType.name) && !MakeupAssetTypes.includes(asset.assetType.name)) {
32632
32640
  totalLayered += 1;
32633
32641
  if (totalLayered > 10) {
32634
32642
  issues.push({
@@ -32638,6 +32646,16 @@ class Outfit {
32638
32646
  });
32639
32647
  }
32640
32648
  }
32649
+ if (MakeupAssetTypes.includes(asset.assetType.name)) {
32650
+ totalMakeup += 1;
32651
+ if (totalMakeup > 6) {
32652
+ issues.push({
32653
+ "type": "MakeupLimit",
32654
+ "text": "Too much makeup",
32655
+ assetIndex: i
32656
+ });
32657
+ }
32658
+ }
32641
32659
  if (MaxOneOfAssetTypes.includes(asset.assetType.name)) {
32642
32660
  for (let j = 0; j < this.assets.length; j++) {
32643
32661
  const otherAsset = this.assets[j];
@@ -34532,7 +34550,7 @@ class FileMesh {
34532
34550
  decoderModule.destroy(faceArray);
34533
34551
  decoderModule.destroy(mesh);
34534
34552
  decoderModule.destroy(decoder);
34535
- console.log(this.coreMesh);
34553
+ log(false, this.coreMesh);
34536
34554
  }
34537
34555
  }
34538
34556
  readChunkFACS(view, version) {
@@ -36074,7 +36092,11 @@ const API = {
36074
36092
  }
36075
36093
  return await response.json();
36076
36094
  }
36077
- }
36095
+ },
36096
+ "RBLXGet": RBLXGet,
36097
+ "RBLXPost": RBLXPost,
36098
+ "RBLXDelete": RBLXDelete,
36099
+ "RBLXPatch": RBLXPatch
36078
36100
  };
36079
36101
  let currentLoadingThumbnails = false;
36080
36102
  function requestIdFromThumbnailInfo(thumbnailInfo) {
@@ -46174,7 +46196,6 @@ class AnimationTrack {
46174
46196
  partKeyframe.easingStyle = pose.Prop("EasingStyle");
46175
46197
  }
46176
46198
  } else {
46177
- warn(false, `Missing either part0 or part1 with names: ${part0Name} ${part1Name}`);
46178
46199
  return [void 0, void 0, void 0];
46179
46200
  }
46180
46201
  if (!motorName || !motorParentName || !partKeyframe) {
@@ -49913,6 +49934,7 @@ export {
49913
49934
  LayeredAssetTypes,
49914
49935
  LayeredClothingAssetOrder,
49915
49936
  LocalOutfit,
49937
+ MakeupAssetTypes,
49916
49938
  MakeupDescriptionWrapper,
49917
49939
  MakeupType,
49918
49940
  MaxOneOfAssetTypes,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "roavatar-renderer",
3
- "version": "1.2.15",
3
+ "version": "1.2.16",
4
4
  "description": "A renderer for Roblox avatars, used by the RoAvatar extension.",
5
5
  "author": "steinan",
6
6
  "type": "module",