roavatar-renderer 1.2.15 → 1.3.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.
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) {
@@ -41198,7 +41220,6 @@ function TraverseRigFromAttachmentsInternal(self2, part, characterParts, buildJo
41198
41220
  if (part !== characterPart) {
41199
41221
  const matchingAttachment = characterPart.FindFirstChild(attachmentName);
41200
41222
  if (matchingAttachment && matchingAttachment.className === "Attachment") {
41201
- log(false, "matchingAtt", part, characterPart, attachmentName);
41202
41223
  AdjustRootRigAttachmentPosition(self2, part, characterPart, attachment, matchingAttachment);
41203
41224
  {
41204
41225
  createJoint(jointName, attachment, matchingAttachment);
@@ -44775,8 +44796,13 @@ class DisposableDesc {
44775
44796
  }
44776
44797
  }
44777
44798
  class RenderDesc extends DisposableDesc {
44799
+ renderScene;
44778
44800
  results;
44779
44801
  instance;
44802
+ constructor(renderScene) {
44803
+ super();
44804
+ this.renderScene = renderScene;
44805
+ }
44780
44806
  // eslint-disable-next-line @typescript-eslint/no-unused-vars
44781
44807
  isSame(_other) {
44782
44808
  throw new Error("Virtual method isSame called");
@@ -45121,14 +45147,14 @@ class Particle {
45121
45147
  this.velocity = velocity;
45122
45148
  this.rotationSpeed = rotationSpeed;
45123
45149
  }
45124
- camDistance() {
45125
- const cameraPos = new Vector32(...RBXRenderer.getRendererCamera().position.toArray());
45150
+ camDistance(renderScene) {
45151
+ const cameraPos = new Vector32(...renderScene.camera.position.toArray());
45126
45152
  const particlePos = this.position;
45127
45153
  const distance2 = cameraPos.minus(particlePos).magnitude();
45128
45154
  return distance2;
45129
45155
  }
45130
- getMatrix(size, orientation) {
45131
- const camera = RBXRenderer.getRendererCamera();
45156
+ getMatrix(renderScene, size, orientation) {
45157
+ const camera = renderScene.camera;
45132
45158
  const particlePos = new Vector3$1(...this.position.toVec3());
45133
45159
  const translation = new Matrix4().makeTranslation(particlePos);
45134
45160
  const scale = new Matrix4().makeScale(size, size, 1);
@@ -45373,7 +45399,7 @@ class EmitterDesc extends DisposableDesc {
45373
45399
  this.passedTime -= 1 / this.rate;
45374
45400
  }
45375
45401
  }
45376
- updateResult() {
45402
+ updateResult(renderScene) {
45377
45403
  if (!this.result || !this.instanceColorBuffer || !this.instanceOpacityBuffer || !this.instanceSeedTimeBuffer) return;
45378
45404
  this.result.count = this.particles.length;
45379
45405
  for (let i = 0; i < this.result.count; i++) {
@@ -45383,7 +45409,7 @@ class EmitterDesc extends DisposableDesc {
45383
45409
  const color = this.color.getValue(normalizedTime);
45384
45410
  const size = this.size.getValue(this.normalizeSizeKeypointTime ? normalizedTime : time2, particle.seed + 0);
45385
45411
  const opacity = 1 - this.transparency.getValue(normalizedTime, particle.seed + 1);
45386
- this.result.setMatrixAt(i, particle.getMatrix(size, this.orientation));
45412
+ this.result.setMatrixAt(i, particle.getMatrix(renderScene, size, this.orientation));
45387
45413
  this.instanceColorBuffer.setXYZ(i, color.R, color.G, color.B);
45388
45414
  this.instanceOpacityBuffer.setX(i, opacity);
45389
45415
  this.instanceSeedTimeBuffer.setXY(i, particle.seed, normalizedTime);
@@ -45681,7 +45707,7 @@ class EmitterGroupDesc extends RenderDesc {
45681
45707
  this.lastTime = this.time;
45682
45708
  for (const emitterDesc of this.emitterDescs) {
45683
45709
  emitterDesc.tick(dt, this);
45684
- emitterDesc.updateResult();
45710
+ emitterDesc.updateResult(this.renderScene);
45685
45711
  }
45686
45712
  this.lastCframe = this.cframe.clone();
45687
45713
  }
@@ -46174,7 +46200,6 @@ class AnimationTrack {
46174
46200
  partKeyframe.easingStyle = pose.Prop("EasingStyle");
46175
46201
  }
46176
46202
  } else {
46177
- warn(false, `Missing either part0 or part1 with names: ${part0Name} ${part1Name}`);
46178
46203
  return [void 0, void 0, void 0];
46179
46204
  }
46180
46205
  if (!motorName || !motorParentName || !partKeyframe) {
@@ -48941,42 +48966,104 @@ function RegisterWrappers() {
48941
48966
  BodyColorsWrapper.register();
48942
48967
  AccessoryWrapper.register();
48943
48968
  }
48969
+ class RBXRendererScene {
48970
+ //important scene components
48971
+ scene = new Scene();
48972
+ camera = new PerspectiveCamera(70, 1 / 1, 0.1, 100);
48973
+ controls;
48974
+ //renderer
48975
+ effectComposer;
48976
+ //viewport
48977
+ scissor;
48978
+ viewport;
48979
+ //renderables data
48980
+ isRenderingMesh = /* @__PURE__ */ new Map();
48981
+ renderDescs = /* @__PURE__ */ new Map();
48982
+ destroyConnections = /* @__PURE__ */ new Map();
48983
+ //scene appearance config
48984
+ lookAwayVector = [0.406, 0.306, -0.819];
48985
+ lookAwayDistance = 6;
48986
+ shadowEnabled = true;
48987
+ shadowResolution = [256, 256];
48988
+ _wellLitDirectionalLightIntensity = Math.PI / 2;
48989
+ set wellLitDirectionalLightIntensity(v) {
48990
+ this._wellLitDirectionalLightIntensity = v;
48991
+ if (this.directionalLight) {
48992
+ this.directionalLight.intensity = this._wellLitDirectionalLightIntensity;
48993
+ }
48994
+ }
48995
+ get wellLitDirectionalLightIntensity() {
48996
+ return this._wellLitDirectionalLightIntensity;
48997
+ }
48998
+ //scene appearance
48999
+ plane;
49000
+ shadowPlane;
49001
+ ambientLight;
49002
+ directionalLight;
49003
+ directionalLight2;
49004
+ setRect(bounds) {
49005
+ this.viewport = [bounds.left, document.body.clientHeight - bounds.bottom, bounds.width, bounds.height];
49006
+ this.scissor = [...this.viewport];
49007
+ }
49008
+ noRect() {
49009
+ this.viewport = [0, 0, 0, 0];
49010
+ this.scissor = [0, 0, 0, 0];
49011
+ }
49012
+ }
48944
49013
  class RBXRenderer {
48945
- static isRenderingMesh = /* @__PURE__ */ new Map();
48946
- static renderDescs = /* @__PURE__ */ new Map();
48947
- static destroyConnections = /* @__PURE__ */ new Map();
48948
- static lookAwayVector = [0.406, 0.306, -0.819];
48949
- static lookAwayDistance = 6;
48950
49014
  static orbitControlsTarget = [0, 3, 0];
48951
- static scene = new Scene();
48952
- static camera = new PerspectiveCamera(70, 1 / 1, 0.1, 100);
48953
- static controls;
49015
+ static scenes = [new RBXRendererScene()];
49016
+ static get firstScene() {
49017
+ return RBXRenderer.scenes[0];
49018
+ }
49019
+ /**@deprecated This can only get the first renderScene's scene */
49020
+ static get scene() {
49021
+ return RBXRenderer.firstScene.scene;
49022
+ }
49023
+ /**@deprecated This can only get the first renderScene's camera */
49024
+ static get camera() {
49025
+ return RBXRenderer.firstScene.camera;
49026
+ }
49027
+ /**@deprecated This can only get the first renderScene's controls */
49028
+ static get controls() {
49029
+ return RBXRenderer.firstScene.controls;
49030
+ }
48954
49031
  static renderer;
48955
- static effectComposer;
48956
- static shadowEnabled = true;
48957
- static shadowResolution = [256, 256];
48958
49032
  static resolution = [420, 420];
48959
49033
  static backgroundColorHex = 2829619;
48960
49034
  static backgroundTransparent = false;
48961
- static _wellLitDirectionalLightIntensity = Math.PI / 2;
48962
- static set wellLitDirectionalLightIntensity(v) {
48963
- RBXRenderer._wellLitDirectionalLightIntensity = v;
48964
- if (RBXRenderer.directionalLight) {
48965
- RBXRenderer.directionalLight.intensity = RBXRenderer._wellLitDirectionalLightIntensity;
48966
- }
48967
- }
48968
- static get wellLitDirectionalLightIntensity() {
48969
- return RBXRenderer._wellLitDirectionalLightIntensity;
48970
- }
48971
49035
  static createLoadingIcon = true;
48972
49036
  static canvasContainer;
48973
49037
  static loadingIcon;
48974
49038
  static loadingIconStyle;
48975
- static plane;
48976
- static shadowPlane;
48977
- static ambientLight;
48978
- static directionalLight;
48979
- static directionalLight2;
49039
+ /**@deprecated This can only get the first renderScene's plane */
49040
+ static get plane() {
49041
+ return RBXRenderer.firstScene.plane;
49042
+ }
49043
+ /**@deprecated This can only get the first renderScene's shadowPlane */
49044
+ static get shadowPlane() {
49045
+ return RBXRenderer.firstScene.shadowPlane;
49046
+ }
49047
+ /**@deprecated This can only get the first renderScene's ambientLight */
49048
+ static get ambientLight() {
49049
+ return RBXRenderer.firstScene.ambientLight;
49050
+ }
49051
+ /**@deprecated This can only get the first renderScene's directionalLight */
49052
+ static get directionalLight() {
49053
+ return RBXRenderer.firstScene.directionalLight;
49054
+ }
49055
+ /**@deprecated This can only get the first renderScene's directionalLight2 */
49056
+ static get directionalLight2() {
49057
+ return RBXRenderer.firstScene.directionalLight2;
49058
+ }
49059
+ /**@deprecated This can only set the first renderScene's wellLitDirectionalLightIntensity*/
49060
+ static set wellLitDirectionalLightIntensity(v) {
49061
+ RBXRenderer.firstScene.wellLitDirectionalLightIntensity = v;
49062
+ }
49063
+ /**@deprecated This can only gey the first renderScene's wellLitDirectionalLightIntensity*/
49064
+ static get wellLitDirectionalLightIntensity() {
49065
+ return RBXRenderer.firstScene.wellLitDirectionalLightIntensity;
49066
+ }
48980
49067
  static failedToCreate = false;
48981
49068
  static error;
48982
49069
  static async boilerplateSetup() {
@@ -49030,17 +49117,67 @@ class RBXRenderer {
49030
49117
  errorDiv.appendChild(errorLink);
49031
49118
  RBXRenderer.canvasContainer.append(errorDiv);
49032
49119
  }
49120
+ static createLoadingIconHTML() {
49121
+ RBXRenderer.loadingIcon = document.createElement("span");
49122
+ RBXRenderer.loadingIcon.className = "roavatar-loader";
49123
+ RBXRenderer.loadingIcon.style.opacity = "0";
49124
+ RBXRenderer.loadingIcon.style.position = "absolute";
49125
+ RBXRenderer.loadingIcon.style.bottom = "12px";
49126
+ RBXRenderer.loadingIcon.style.right = "12px";
49127
+ RBXRenderer.loadingIcon.style.width = "24px";
49128
+ RBXRenderer.loadingIcon.style.height = "24px";
49129
+ RBXRenderer.loadingIcon.style.transition = "0.1s";
49130
+ RBXRenderer.loadingIconStyle = document.createElement("style");
49131
+ RBXRenderer.loadingIconStyle.textContent = `
49132
+ /*Loader source: https://cssloaders.github.io/ */
49133
+ .roavatar-loader {
49134
+ width: 48px;
49135
+ height: 48px;
49136
+ display: inline-block;
49137
+ position: relative;
49138
+ background: #FFF;
49139
+ box-sizing: border-box;
49140
+ animation: rooavatarFlipX 1s linear infinite;
49141
+ }
49142
+
49143
+ @keyframes rooavatarFlipX {
49144
+ 0% {
49145
+ transform: perspective(200px) rotateX(0deg) rotateY(0deg);
49146
+ }
49147
+ 50% {
49148
+ transform: perspective(200px) rotateX(-180deg) rotateY(0deg);
49149
+ }
49150
+ 100% {
49151
+ transform: perspective(200px) rotateX(-180deg) rotateY(-180deg);
49152
+ }
49153
+ }
49154
+ `;
49155
+ document.head.appendChild(RBXRenderer.loadingIconStyle);
49156
+ RBXRenderer.canvasContainer.appendChild(RBXRenderer.loadingIcon);
49157
+ const onLoadConnection = API.Events.OnLoadingAssets.Connect((newIsLoading) => {
49158
+ if (RBXRenderer.loadingIcon) {
49159
+ RBXRenderer.loadingIcon.style.opacity = newIsLoading ? "1" : "0";
49160
+ } else {
49161
+ onLoadConnection.Disconnect();
49162
+ }
49163
+ });
49164
+ }
49165
+ static addScene() {
49166
+ const renderScene = new RBXRendererScene();
49167
+ RBXRenderer.scenes.push(renderScene);
49168
+ return renderScene;
49169
+ }
49033
49170
  /**Fully sets up renderer with scene, camera and frame rendering
49034
49171
  * @returns success
49035
49172
  */
49036
- static async fullSetup(includeScene = true, includeControls = true) {
49173
+ static async fullSetup(includeSceneAppearance = true, includeControls = true, includeAnimate = true) {
49037
49174
  try {
49038
49175
  RBXRenderer.createContainer();
49039
49176
  await RBXRenderer.boilerplateSetup();
49040
49177
  RBXRenderer.create();
49041
- if (includeScene) RBXRenderer.setupScene();
49178
+ if (includeSceneAppearance) RBXRenderer.setupScene();
49042
49179
  if (includeControls) RBXRenderer.setupControls();
49043
- RBXRenderer.animate();
49180
+ if (includeAnimate) RBXRenderer.animateAll();
49044
49181
  } catch (err2) {
49045
49182
  error(err2);
49046
49183
  RBXRenderer.failedToCreate = true;
@@ -49071,49 +49208,7 @@ class RBXRenderer {
49071
49208
  RBXRenderer.renderer.domElement.setAttribute("id", "OutfitInfo-outfit-image-3d");
49072
49209
  RBXRenderer.canvasContainer.appendChild(RBXRenderer.renderer.domElement);
49073
49210
  if (RBXRenderer.createLoadingIcon) {
49074
- RBXRenderer.loadingIcon = document.createElement("span");
49075
- RBXRenderer.loadingIcon.className = "roavatar-loader";
49076
- RBXRenderer.loadingIcon.style.opacity = "0";
49077
- RBXRenderer.loadingIcon.style.position = "absolute";
49078
- RBXRenderer.loadingIcon.style.bottom = "12px";
49079
- RBXRenderer.loadingIcon.style.right = "12px";
49080
- RBXRenderer.loadingIcon.style.width = "24px";
49081
- RBXRenderer.loadingIcon.style.height = "24px";
49082
- RBXRenderer.loadingIcon.style.transition = "0.1s";
49083
- RBXRenderer.loadingIconStyle = document.createElement("style");
49084
- RBXRenderer.loadingIconStyle.textContent = `
49085
- /*Loader source: https://cssloaders.github.io/ */
49086
- .roavatar-loader {
49087
- width: 48px;
49088
- height: 48px;
49089
- display: inline-block;
49090
- position: relative;
49091
- background: #FFF;
49092
- box-sizing: border-box;
49093
- animation: rooavatarFlipX 1s linear infinite;
49094
- }
49095
-
49096
- @keyframes rooavatarFlipX {
49097
- 0% {
49098
- transform: perspective(200px) rotateX(0deg) rotateY(0deg);
49099
- }
49100
- 50% {
49101
- transform: perspective(200px) rotateX(-180deg) rotateY(0deg);
49102
- }
49103
- 100% {
49104
- transform: perspective(200px) rotateX(-180deg) rotateY(-180deg);
49105
- }
49106
- }
49107
- `;
49108
- document.head.appendChild(RBXRenderer.loadingIconStyle);
49109
- RBXRenderer.canvasContainer.appendChild(RBXRenderer.loadingIcon);
49110
- const onLoadConnection = API.Events.OnLoadingAssets.Connect((newIsLoading) => {
49111
- if (RBXRenderer.loadingIcon) {
49112
- RBXRenderer.loadingIcon.style.opacity = newIsLoading ? "1" : "0";
49113
- } else {
49114
- onLoadConnection.Disconnect();
49115
- }
49116
- });
49211
+ RBXRenderer.createLoadingIconHTML();
49117
49212
  }
49118
49213
  if (FLAGS.USE_POST_PROCESSING) {
49119
49214
  RBXRenderer._createEffectComposer();
@@ -49123,10 +49218,10 @@ class RBXRenderer {
49123
49218
  * @param lightingType "WellLit" is the default lighting for RoAvatar, "Thumbnail" tries to match the Roblox thumbnail lighting
49124
49219
  * @param backgroundColorHex is the hex code for the background color, for example 0x2b2d33
49125
49220
  */
49126
- static setupScene(lightingType = "WellLit", backgroundColorHex = RBXRenderer.backgroundColorHex) {
49221
+ static setupScene(lightingType = "WellLit", backgroundColorHex = RBXRenderer.backgroundColorHex, renderScene = RBXRenderer.firstScene) {
49127
49222
  RBXRenderer.backgroundColorHex = backgroundColorHex;
49128
49223
  const backgroundColor = new Color(backgroundColorHex);
49129
- RBXRenderer.scene.background = backgroundColor;
49224
+ renderScene.scene.background = backgroundColor;
49130
49225
  let thumbnailAmbientVal = 138;
49131
49226
  thumbnailAmbientVal = 128;
49132
49227
  let ambientLightColor = void 0;
@@ -49136,8 +49231,8 @@ class RBXRenderer {
49136
49231
  ambientLightColor = new Color(100 / 255, 100 / 255, 100 / 255);
49137
49232
  }
49138
49233
  const ambientLight = new AmbientLight(ambientLightColor, Math.PI / 2);
49139
- RBXRenderer.scene.add(ambientLight);
49140
- RBXRenderer.ambientLight = ambientLight;
49234
+ renderScene.scene.add(ambientLight);
49235
+ renderScene.ambientLight = ambientLight;
49141
49236
  let directionalLightColor = void 0;
49142
49237
  const directionalLightVal = 0.7 * 0.9 * 2 * 0.4;
49143
49238
  if (lightingType === "Thumbnail") {
@@ -49147,7 +49242,7 @@ class RBXRenderer {
49147
49242
  }
49148
49243
  let directionalLightIntensity = 1;
49149
49244
  if (lightingType === "WellLit") {
49150
- directionalLightIntensity = this._wellLitDirectionalLightIntensity;
49245
+ directionalLightIntensity = renderScene._wellLitDirectionalLightIntensity;
49151
49246
  }
49152
49247
  const directionalLight = new DirectionalLight(directionalLightColor, directionalLightIntensity);
49153
49248
  if (lightingType === "WellLit") {
@@ -49156,10 +49251,10 @@ class RBXRenderer {
49156
49251
  directionalLight.position.set(-0.47489210963249207 * 10, 0.8225368857383728 * 10, 0.3129066228866577 * 10);
49157
49252
  }
49158
49253
  if (lightingType === "WellLit") {
49159
- directionalLight.castShadow = RBXRenderer.shadowEnabled;
49254
+ directionalLight.castShadow = renderScene.shadowEnabled;
49160
49255
  }
49161
- directionalLight.shadow.mapSize.width = RBXRenderer.shadowResolution[0];
49162
- directionalLight.shadow.mapSize.height = RBXRenderer.shadowResolution[1];
49256
+ directionalLight.shadow.mapSize.width = renderScene.shadowResolution[0];
49257
+ directionalLight.shadow.mapSize.height = renderScene.shadowResolution[1];
49163
49258
  const bottomOffset = 1.6;
49164
49259
  const shadowPhysicalSize = 5;
49165
49260
  directionalLight.shadow.camera.left = -shadowPhysicalSize;
@@ -49170,20 +49265,20 @@ class RBXRenderer {
49170
49265
  directionalLight.shadow.camera.far = 25;
49171
49266
  directionalLight.shadow.intensity = 0.5;
49172
49267
  directionalLight.target.position.set(0, 0, 0);
49173
- RBXRenderer.scene.add(directionalLight);
49174
- RBXRenderer.directionalLight = directionalLight;
49268
+ renderScene.scene.add(directionalLight);
49269
+ renderScene.directionalLight = directionalLight;
49175
49270
  if (lightingType === "WellLit") {
49176
49271
  const directionalLight2 = new DirectionalLight(16777215, 0.3);
49177
49272
  directionalLight2.position.set(5, -7, 5);
49178
49273
  directionalLight2.target.position.set(0, 0, 0);
49179
- RBXRenderer.scene.add(directionalLight2);
49180
- RBXRenderer.directionalLight2 = directionalLight2;
49274
+ renderScene.scene.add(directionalLight2);
49275
+ renderScene.directionalLight2 = directionalLight2;
49181
49276
  } else if (lightingType === "Thumbnail") {
49182
49277
  const directionalLight2 = new DirectionalLight(directionalLightColor, directionalLightIntensity * 0.5);
49183
49278
  directionalLight2.position.set(-0.47489210963249207 * -10, 0.8225368857383728 * -10, 0.3129066228866577 * -10);
49184
49279
  directionalLight2.target.position.set(0, 0, 0);
49185
- RBXRenderer.scene.add(directionalLight2);
49186
- RBXRenderer.directionalLight2 = directionalLight2;
49280
+ renderScene.scene.add(directionalLight2);
49281
+ renderScene.directionalLight2 = directionalLight2;
49187
49282
  }
49188
49283
  const planeGeometry = new PlaneGeometry(100, 100, 1, 1);
49189
49284
  const planeShadowMaterial = new ShadowMaterial({ opacity: 1 });
@@ -49191,27 +49286,27 @@ class RBXRenderer {
49191
49286
  shadowPlane.rotation.set(rad(-90), 0, 0);
49192
49287
  shadowPlane.position.set(0, 0, 0);
49193
49288
  shadowPlane.receiveShadow = true;
49194
- RBXRenderer.shadowPlane = shadowPlane;
49195
- RBXRenderer.scene.add(shadowPlane);
49289
+ renderScene.shadowPlane = shadowPlane;
49290
+ renderScene.scene.add(shadowPlane);
49196
49291
  const planeSolidColorMaterial = new MeshBasicMaterial({ color: backgroundColor });
49197
49292
  const plane = new Mesh(planeGeometry, planeSolidColorMaterial);
49198
49293
  plane.rotation.set(rad(-90), 0, 0);
49199
49294
  plane.position.set(0, 0, 0);
49200
49295
  plane.receiveShadow = false;
49201
- RBXRenderer.plane = plane;
49202
- RBXRenderer.scene.add(plane);
49296
+ renderScene.plane = plane;
49297
+ renderScene.scene.add(plane);
49203
49298
  }
49204
49299
  /**Sets up orbit controls */
49205
- static setupControls() {
49300
+ static setupControls(renderScene = RBXRenderer.firstScene) {
49206
49301
  if (!RBXRenderer.renderer) return;
49207
- const controls = new OrbitControls(RBXRenderer.camera, RBXRenderer.renderer.domElement);
49302
+ const controls = new OrbitControls(renderScene.camera, RBXRenderer.renderer.domElement);
49208
49303
  controls.maxDistance = 25;
49209
49304
  controls.zoomSpeed = 2;
49210
49305
  controls.target.set(...RBXRenderer.orbitControlsTarget);
49211
49306
  log(false, controls.target);
49212
- RBXRenderer.controls = controls;
49213
- RBXRenderer.camera.position.set(RBXRenderer.lookAwayVector[0] * RBXRenderer.lookAwayDistance, 3 + RBXRenderer.lookAwayVector[1] * RBXRenderer.lookAwayDistance, RBXRenderer.lookAwayVector[2] * RBXRenderer.lookAwayDistance);
49214
- RBXRenderer.camera.lookAt(new Vector3$1(...RBXRenderer.orbitControlsTarget));
49307
+ renderScene.controls = controls;
49308
+ renderScene.camera.position.set(renderScene.lookAwayVector[0] * renderScene.lookAwayDistance, 3 + renderScene.lookAwayVector[1] * renderScene.lookAwayDistance, renderScene.lookAwayVector[2] * renderScene.lookAwayDistance);
49309
+ renderScene.camera.lookAt(new Vector3$1(...RBXRenderer.orbitControlsTarget));
49215
49310
  controls.update();
49216
49311
  }
49217
49312
  /**
@@ -49219,16 +49314,18 @@ class RBXRenderer {
49219
49314
  */
49220
49315
  static setBackgroundColor(colorHex) {
49221
49316
  RBXRenderer.backgroundColorHex = colorHex;
49222
- if (RBXRenderer.backgroundTransparent) {
49223
- RBXRenderer.scene.background = null;
49224
- } else {
49225
- RBXRenderer.scene.background = new Color(RBXRenderer.backgroundColorHex);
49226
- }
49227
- if (RBXRenderer.plane) {
49228
- RBXRenderer.plane.visible = !RBXRenderer.backgroundTransparent;
49229
- }
49230
- if (RBXRenderer.plane) {
49231
- RBXRenderer.plane.material = new MeshBasicMaterial({ color: colorHex });
49317
+ for (const renderScene of RBXRenderer.scenes) {
49318
+ if (RBXRenderer.backgroundTransparent) {
49319
+ renderScene.scene.background = null;
49320
+ } else {
49321
+ renderScene.scene.background = new Color(RBXRenderer.backgroundColorHex);
49322
+ }
49323
+ if (renderScene.plane) {
49324
+ renderScene.plane.visible = !RBXRenderer.backgroundTransparent;
49325
+ }
49326
+ if (renderScene.plane) {
49327
+ renderScene.plane.material = new MeshBasicMaterial({ color: colorHex });
49328
+ }
49232
49329
  }
49233
49330
  }
49234
49331
  /**
@@ -49237,60 +49334,103 @@ class RBXRenderer {
49237
49334
  */
49238
49335
  static setBackgroundTransparent(transparent) {
49239
49336
  RBXRenderer.backgroundTransparent = transparent;
49240
- if (RBXRenderer.backgroundTransparent) {
49241
- RBXRenderer.scene.background = null;
49242
- } else {
49243
- RBXRenderer.scene.background = new Color(RBXRenderer.backgroundColorHex);
49244
- }
49245
- if (RBXRenderer.plane) {
49246
- RBXRenderer.plane.visible = !RBXRenderer.backgroundTransparent;
49337
+ for (const renderScene of RBXRenderer.scenes) {
49338
+ if (RBXRenderer.backgroundTransparent) {
49339
+ renderScene.scene.background = null;
49340
+ } else {
49341
+ renderScene.scene.background = new Color(RBXRenderer.backgroundColorHex);
49342
+ }
49343
+ if (renderScene.plane) {
49344
+ renderScene.plane.visible = !RBXRenderer.backgroundTransparent;
49345
+ }
49247
49346
  }
49248
49347
  }
49249
49348
  /**Makes the renderer render a new frame on every animationFrame */
49250
- static animate() {
49349
+ static animate(shouldRequestAnimationFrame = true) {
49350
+ if (!RBXRenderer.renderer) return;
49351
+ RBXRenderer.renderScene(RBXRenderer.firstScene);
49352
+ if (shouldRequestAnimationFrame) {
49353
+ requestAnimationFrame(() => {
49354
+ RBXRenderer.animate();
49355
+ });
49356
+ }
49357
+ }
49358
+ static animateAll(shouldRequestAnimationFrame = true) {
49359
+ if (!RBXRenderer.renderer) return;
49360
+ for (const renderScene of RBXRenderer.scenes) {
49361
+ RBXRenderer.renderScene(renderScene, renderScene === RBXRenderer.firstScene);
49362
+ }
49363
+ if (shouldRequestAnimationFrame) {
49364
+ requestAnimationFrame(() => {
49365
+ RBXRenderer.animateAll();
49366
+ });
49367
+ }
49368
+ }
49369
+ static renderScene(renderScene, autoClear = true) {
49251
49370
  if (!RBXRenderer.renderer) return;
49371
+ RBXRenderer.renderer.autoClear = autoClear;
49372
+ if (!autoClear) {
49373
+ RBXRenderer.renderer.clearDepth();
49374
+ }
49252
49375
  RBXRenderer.renderer.setRenderTarget(null);
49253
- if (RBXRenderer.effectComposer) {
49254
- RBXRenderer.effectComposer.render();
49376
+ let [x, y] = [0, 0];
49377
+ let [width, height] = RBXRenderer.resolution;
49378
+ if (renderScene.viewport) {
49379
+ x = renderScene.viewport[0];
49380
+ y = renderScene.viewport[1];
49381
+ width = renderScene.viewport[2];
49382
+ height = renderScene.viewport[3];
49383
+ }
49384
+ RBXRenderer.renderer.setViewport(x, y, width, height);
49385
+ if (renderScene.scissor) {
49386
+ RBXRenderer.renderer.setScissorTest(true);
49387
+ RBXRenderer.renderer.setScissor(...renderScene.scissor);
49255
49388
  } else {
49256
- RBXRenderer.renderer.render(RBXRenderer.scene, RBXRenderer.camera);
49389
+ RBXRenderer.renderer.setScissorTest(false);
49257
49390
  }
49258
- requestAnimationFrame(() => {
49259
- RBXRenderer.animate();
49260
- });
49391
+ renderScene.camera.aspect = width / height;
49392
+ renderScene.camera.updateProjectionMatrix();
49393
+ if (width > 0 && height > 0) {
49394
+ if (renderScene.effectComposer) {
49395
+ renderScene.effectComposer.render();
49396
+ } else {
49397
+ RBXRenderer.renderer.render(renderScene.scene, renderScene.camera);
49398
+ }
49399
+ }
49400
+ RBXRenderer.renderer.autoClear = true;
49261
49401
  }
49262
- static _createEffectComposer() {
49402
+ static _createEffectComposer(renderScene = RBXRenderer.firstScene) {
49263
49403
  if (!RBXRenderer.renderer) return;
49264
- RBXRenderer.effectComposer = new EffectComposer(RBXRenderer.renderer);
49265
- const renderPass = new RenderPass(RBXRenderer.scene, RBXRenderer.camera);
49266
- RBXRenderer.effectComposer.addPass(renderPass);
49404
+ renderScene.effectComposer = new EffectComposer(RBXRenderer.renderer);
49405
+ const renderPass = new RenderPass(renderScene.scene, renderScene.camera);
49406
+ renderScene.effectComposer.addPass(renderPass);
49267
49407
  const resolution = new Vector2$1(420, 420);
49268
49408
  const bloomPass = new UnrealBloomPass(resolution, 0.15, 1e-4, 0.9);
49269
- RBXRenderer.effectComposer.addPass(bloomPass);
49409
+ renderScene.effectComposer.addPass(bloomPass);
49270
49410
  if (!FLAGS.POST_PROCESSING_IS_DOUBLE_SIZE) {
49271
49411
  const fxaaPass = new FXAAPass();
49272
- RBXRenderer.effectComposer.addPass(fxaaPass);
49412
+ renderScene.effectComposer.addPass(fxaaPass);
49273
49413
  }
49274
49414
  const outputPass = new OutputPass();
49275
- RBXRenderer.effectComposer.addPass(outputPass);
49415
+ renderScene.effectComposer.addPass(outputPass);
49276
49416
  }
49277
49417
  /**Removes an instance from the renderer */
49278
- static removeInstance(instance) {
49418
+ static removeInstance(instance, renderScene = RBXRenderer.firstScene) {
49279
49419
  if (!RBXRenderer.renderer) return;
49280
- const desc = RBXRenderer.renderDescs.get(instance);
49420
+ const desc = renderScene.renderDescs.get(instance);
49281
49421
  if (desc) {
49282
- desc.dispose(RBXRenderer.renderer, RBXRenderer.scene);
49422
+ desc.dispose(RBXRenderer.renderer, renderScene.scene);
49283
49423
  }
49284
- RBXRenderer.renderDescs.delete(instance);
49285
- RBXRenderer.isRenderingMesh.delete(instance);
49424
+ renderScene.renderDescs.delete(instance);
49425
+ renderScene.isRenderingMesh.delete(instance);
49286
49426
  for (const child of instance.GetChildren()) {
49287
- RBXRenderer.removeInstance(child);
49427
+ RBXRenderer.removeInstance(child, renderScene);
49288
49428
  }
49289
49429
  }
49290
- static _addRenderDesc(instance, auth, DescClass) {
49430
+ static _addRenderDesc(instance, auth, DescClass, renderScene) {
49291
49431
  if (!RBXRenderer.renderer) return;
49292
- const oldDesc = RBXRenderer.renderDescs.get(instance);
49293
- const newDesc = new DescClass();
49432
+ const oldDesc = renderScene.renderDescs.get(instance);
49433
+ const newDesc = new DescClass(renderScene);
49294
49434
  newDesc.fromInstance(instance);
49295
49435
  if (oldDesc && !oldDesc.needsRegeneration(newDesc)) {
49296
49436
  if (!oldDesc.isSame(newDesc)) {
@@ -49298,15 +49438,15 @@ class RBXRenderer {
49298
49438
  oldDesc.updateResults();
49299
49439
  }
49300
49440
  } else {
49301
- if (!RBXRenderer.isRenderingMesh.get(instance)) {
49441
+ if (!renderScene.isRenderingMesh.get(instance)) {
49302
49442
  newDesc.results = oldDesc?.results;
49303
- RBXRenderer.renderDescs.set(instance, newDesc);
49304
- RBXRenderer.isRenderingMesh.set(instance, true);
49305
- newDesc.compileResults(RBXRenderer.renderer, RBXRenderer.scene).then((results) => {
49443
+ renderScene.renderDescs.set(instance, newDesc);
49444
+ renderScene.isRenderingMesh.set(instance, true);
49445
+ newDesc.compileResults(RBXRenderer.renderer, renderScene.scene).then((results) => {
49306
49446
  if (results && !(results instanceof Response)) {
49307
49447
  newDesc.updateResults();
49308
- if (RBXRenderer.renderDescs.get(instance) && RBXRenderer.renderer) {
49309
- oldDesc?.dispose(RBXRenderer.renderer, RBXRenderer.scene);
49448
+ if (renderScene.renderDescs.get(instance) && RBXRenderer.renderer) {
49449
+ oldDesc?.dispose(RBXRenderer.renderer, renderScene.scene);
49310
49450
  for (const result of results) {
49311
49451
  if (result instanceof SkinnedMesh && newDesc instanceof ObjectDesc) {
49312
49452
  const skeleton = newDesc.skeletonDesc?.skeleton;
@@ -49316,20 +49456,20 @@ class RBXRenderer {
49316
49456
  if (FLAGS.USE_LOCAL_SKELETONDESC) {
49317
49457
  result.add(newDesc.skeletonDesc.rootBone);
49318
49458
  } else {
49319
- RBXRenderer.scene.add(newDesc.skeletonDesc.rootBone);
49459
+ renderScene.scene.add(newDesc.skeletonDesc.rootBone);
49320
49460
  }
49321
49461
  }
49322
49462
  result.bind(skeleton);
49323
- RBXRenderer.scene.add(result);
49463
+ renderScene.scene.add(result);
49324
49464
  }
49325
49465
  } else {
49326
- RBXRenderer.scene.add(result);
49466
+ renderScene.scene.add(result);
49327
49467
  }
49328
49468
  }
49329
- RBXRenderer.isRenderingMesh.set(instance, false);
49330
- RBXRenderer.addInstance(instance, auth);
49469
+ renderScene.isRenderingMesh.set(instance, false);
49470
+ RBXRenderer.addInstance(instance, auth, renderScene);
49331
49471
  } else if (RBXRenderer.renderer) {
49332
- newDesc.dispose(RBXRenderer.renderer, RBXRenderer.scene);
49472
+ newDesc.dispose(RBXRenderer.renderer, renderScene.scene);
49333
49473
  }
49334
49474
  } else {
49335
49475
  warn(false, "Failed to compile mesh", this, results);
@@ -49337,17 +49477,17 @@ class RBXRenderer {
49337
49477
  });
49338
49478
  }
49339
49479
  }
49340
- if (!RBXRenderer.destroyConnections.get(instance)) {
49341
- RBXRenderer.destroyConnections.set(instance, instance.Destroying.Connect(() => {
49342
- RBXRenderer.removeInstance(instance);
49343
- const connection = RBXRenderer.destroyConnections.get(instance);
49480
+ if (!renderScene.destroyConnections.get(instance)) {
49481
+ renderScene.destroyConnections.set(instance, instance.Destroying.Connect(() => {
49482
+ RBXRenderer.removeInstance(instance, renderScene);
49483
+ const connection = renderScene.destroyConnections.get(instance);
49344
49484
  connection?.Disconnect();
49345
- RBXRenderer.destroyConnections.delete(instance);
49485
+ renderScene.destroyConnections.delete(instance);
49346
49486
  }));
49347
49487
  }
49348
49488
  }
49349
49489
  /**Adds an instance to the renderer or updates it */
49350
- static addInstance(instance, auth) {
49490
+ static addInstance(instance, auth, renderScene = RBXRenderer.firstScene) {
49351
49491
  const isDecal = instance.className === "Decal";
49352
49492
  const isBakedDecal = isDecal && !instance.FindFirstChildOfClass("WrapTextureTransfer");
49353
49493
  let isFirstDecal = true;
@@ -49360,12 +49500,12 @@ class RBXRenderer {
49360
49500
  }
49361
49501
  }
49362
49502
  if (ObjectDescClassTypes.includes(instance.className) && !isBakedDecal && (!isDecal || isFirstDecal)) {
49363
- RBXRenderer._addRenderDesc(instance, auth, ObjectDesc);
49503
+ RBXRenderer._addRenderDesc(instance, auth, ObjectDesc, renderScene);
49364
49504
  } else if (EmitterGroupDescClassTypes.includes(instance.className)) {
49365
- RBXRenderer._addRenderDesc(instance, auth, EmitterGroupDesc);
49505
+ RBXRenderer._addRenderDesc(instance, auth, EmitterGroupDesc, renderScene);
49366
49506
  }
49367
49507
  for (const child of instance.GetChildren()) {
49368
- RBXRenderer.addInstance(child, auth);
49508
+ RBXRenderer.addInstance(child, auth, renderScene);
49369
49509
  }
49370
49510
  }
49371
49511
  static setRendererSize(width, height) {
@@ -49378,8 +49518,6 @@ class RBXRenderer {
49378
49518
  if (FLAGS.USE_POST_PROCESSING && FLAGS.POST_PROCESSING_IS_DOUBLE_SIZE) {
49379
49519
  RBXRenderer.renderer.setSize(RBXRenderer.resolution[0] * 2, RBXRenderer.resolution[1] * 2);
49380
49520
  }
49381
- RBXRenderer.camera.aspect = width / height;
49382
- RBXRenderer.camera.updateProjectionMatrix();
49383
49521
  }
49384
49522
  /**
49385
49523
  * @deprecated Use getRendererElement instead which includes the loading icon
@@ -49395,11 +49533,12 @@ class RBXRenderer {
49395
49533
  static getRendererElement() {
49396
49534
  return RBXRenderer.canvasContainer;
49397
49535
  }
49536
+ /**@deprecated This can only get the first renderScene's camera */
49398
49537
  static getRendererCamera() {
49399
49538
  return RBXRenderer.camera;
49400
49539
  }
49401
- static getCameraCFrame() {
49402
- const camera = RBXRenderer.camera;
49540
+ static getCameraCFrame(renderScene = RBXRenderer.firstScene) {
49541
+ const camera = renderScene.camera;
49403
49542
  const pos = camera.position;
49404
49543
  let rot = camera.rotation.clone();
49405
49544
  rot = rot.reorder("YXZ");
@@ -49408,34 +49547,36 @@ class RBXRenderer {
49408
49547
  cf.Orientation = [deg(rot.x), deg(rot.y), deg(rot.z)];
49409
49548
  return cf;
49410
49549
  }
49411
- static setCameraCFrame(cameraCF) {
49550
+ static setCameraCFrame(cameraCF, renderScene = RBXRenderer.firstScene) {
49412
49551
  const camPos = new Vector3$1();
49413
49552
  const camQuat = new Quaternion();
49414
49553
  const camScale = new Vector3$1();
49415
49554
  const camMatrix = cameraCF.getTHREEMatrix();
49416
49555
  camMatrix.decompose(camPos, camQuat, camScale);
49417
- RBXRenderer.getRendererCamera().position.set(...camPos.toArray());
49418
- RBXRenderer.getRendererCamera().quaternion.set(...camQuat.toArray());
49419
- RBXRenderer.getRendererCamera().updateMatrixWorld();
49556
+ renderScene.camera.position.set(...camPos.toArray());
49557
+ renderScene.camera.quaternion.set(...camQuat.toArray());
49558
+ renderScene.camera.updateMatrixWorld();
49420
49559
  }
49421
- static setCameraFov(fov2) {
49422
- RBXRenderer.getRendererCamera().fov = fov2;
49560
+ static setCameraFov(fov2, renderScene = RBXRenderer.firstScene) {
49561
+ renderScene.camera.fov = fov2;
49423
49562
  }
49563
+ /**@deprecated This can only get the first renderScene's controls */
49424
49564
  static getRendererControls() {
49425
49565
  return RBXRenderer.controls;
49426
49566
  }
49427
49567
  static getRenderer() {
49428
49568
  return RBXRenderer.renderer;
49429
49569
  }
49570
+ /**@deprecated This can only get the first renderScene's scene */
49430
49571
  static getScene() {
49431
- return RBXRenderer.scene;
49572
+ return RBXRenderer.firstScene;
49432
49573
  }
49433
49574
  /**@deprecated
49434
49575
  * This function is unstable and can throw errors, but might work
49435
49576
  */
49436
- static exportScene() {
49577
+ static exportScene(renderScene = RBXRenderer.firstScene) {
49437
49578
  const exporter = new GLTFExporter();
49438
- exporter.parse(RBXRenderer.scene, (gltf) => {
49579
+ exporter.parse(renderScene.scene, (gltf) => {
49439
49580
  if (gltf instanceof ArrayBuffer) {
49440
49581
  saveByteArray([gltf], "scene.glb");
49441
49582
  } else {
@@ -49524,7 +49665,7 @@ class HSR {
49524
49665
  if (FLAGS.HSR_SHOW_RAY) {
49525
49666
  const geometry = new BufferGeometry().setFromPoints([new Vector3$1(...ray.origin), new Vector3$1(...ray.end)]);
49526
49667
  const line = new Line(geometry, rayHit ? hitMaterial : missMaterial);
49527
- RBXRenderer.getScene().add(line);
49668
+ RBXRenderer.scene.add(line);
49528
49669
  }
49529
49670
  }
49530
49671
  this.innerHits[i] = hits;
@@ -49584,6 +49725,22 @@ function getHigher(a, b) {
49584
49725
  a.Z > b.Z ? a.Z : b.Z
49585
49726
  );
49586
49727
  }
49728
+ function getExtentsForParts(parts, includeTransform) {
49729
+ let lowerExtents = new Vector32(0, 0, 0);
49730
+ let higherExtents = new Vector32(0, 0, 0);
49731
+ for (const child of parts) {
49732
+ if (child.className === "Part" || child.className === "MeshPart") {
49733
+ const cframe = traverseRigCFrame(child, includeTransform, true);
49734
+ const size = child.Prop("Size");
49735
+ const corners = getCorners(cframe, size);
49736
+ for (const corner of corners) {
49737
+ lowerExtents = getLower(lowerExtents, new Vector32().fromVec3(corner.Position));
49738
+ higherExtents = getHigher(higherExtents, new Vector32().fromVec3(corner.Position));
49739
+ }
49740
+ }
49741
+ }
49742
+ return [lowerExtents, higherExtents];
49743
+ }
49587
49744
  function getExtents(cframe, parts) {
49588
49745
  const inverseCF = cframe.inverse();
49589
49746
  let lowerExtents = new Vector32(0, 0, 0);
@@ -49658,7 +49815,6 @@ class OutfitRenderer {
49658
49815
  currentRig;
49659
49816
  /**Instance for the Model of the current outfit */
49660
49817
  currentRigType;
49661
- rigPath;
49662
49818
  doCameraUpdateOnLoad = true;
49663
49819
  /**Makes camera update when new avatar has loaded */
49664
49820
  doCameraUpdate = false;
@@ -49670,17 +49826,18 @@ class OutfitRenderer {
49670
49826
  animationInterval;
49671
49827
  animationFPS = 60;
49672
49828
  deltaTimeMultiplier = 1;
49829
+ renderScene = RBXRenderer.firstScene;
49673
49830
  /**
49674
49831
  * Creates a new OutfitRenderer which makes it easy to render outfits
49675
49832
  * @param auth The authentication object, you should have one you use for everything
49676
49833
  * @param outfit The outfit you want to render, it can be updated later by calling setOutfit()
49677
- * @param rigPath The path that contains RigR6.rbxm and RigR15.rbxm, should always be "roavatar://" as rig path is now controlled by FLAGS
49834
+ * @param renderScene The scene the outfit should be rendered in
49678
49835
  */
49679
- constructor(auth, outfit, rigPath = "roavatar://") {
49836
+ constructor(auth, outfit, renderScene = RBXRenderer.firstScene) {
49680
49837
  this.auth = auth;
49681
49838
  this.outfit = outfit;
49682
49839
  this.currentRigType = outfit.playerAvatarType;
49683
- this.rigPath = rigPath;
49840
+ this.renderScene = renderScene;
49684
49841
  this._updateOutfit();
49685
49842
  }
49686
49843
  /**
@@ -49695,12 +49852,12 @@ class OutfitRenderer {
49695
49852
  this.currentRig = void 0;
49696
49853
  }
49697
49854
  this.currentRigType = newRigType;
49698
- API.Asset.GetRBX(`${this.rigPath}Rig${this.currentRigType}.rbxm`, void 0).then((result) => {
49855
+ API.Asset.GetRBX(`roavatar://Rig${this.currentRigType}.rbxm`, void 0).then((result) => {
49699
49856
  if (result instanceof RBX) {
49700
49857
  const newRig = result.generateTree().GetChildren()[0];
49701
49858
  this.currentRig = newRig;
49702
49859
  this.currentlyChangingRig = false;
49703
- RBXRenderer.addInstance(this.currentRig, this.auth);
49860
+ RBXRenderer.addInstance(this.currentRig, this.auth, this.renderScene);
49704
49861
  resolve(newRig);
49705
49862
  } else {
49706
49863
  resolve(result);
@@ -49733,7 +49890,7 @@ class OutfitRenderer {
49733
49890
  hrpWrapper.applyDescription(humanoid).then((result) => {
49734
49891
  this.currentlyUpdating = false;
49735
49892
  if (this.currentRig) {
49736
- RBXRenderer.addInstance(this.currentRig, this.auth);
49893
+ RBXRenderer.addInstance(this.currentRig, this.auth, this.renderScene);
49737
49894
  if (this.doCameraUpdateOnLoad) {
49738
49895
  this.centerCamera();
49739
49896
  }
@@ -49770,8 +49927,8 @@ class OutfitRenderer {
49770
49927
  if (this.currentRig) {
49771
49928
  const upperTorso = this.currentRig.FindFirstChild("HumanoidRootPart");
49772
49929
  if (upperTorso) {
49773
- const controls = RBXRenderer.getRendererControls();
49774
- const camera = RBXRenderer.getRendererCamera();
49930
+ const controls = this.renderScene.controls;
49931
+ const camera = this.renderScene.camera;
49775
49932
  const pos = upperTorso.Prop("Position");
49776
49933
  if (controls) {
49777
49934
  const offset = new Vector3$1().subVectors(camera.position, controls.target);
@@ -49802,7 +49959,7 @@ class OutfitRenderer {
49802
49959
  const animatorW = new AnimatorWrapper(animator);
49803
49960
  animatorW.renderAnimation(deltaTime);
49804
49961
  this.currentRig.preRender();
49805
- RBXRenderer.addInstance(this.currentRig, this.auth);
49962
+ RBXRenderer.addInstance(this.currentRig, this.auth, this.renderScene);
49806
49963
  }
49807
49964
  }
49808
49965
  }
@@ -49846,6 +50003,7 @@ export {
49846
50003
  AccessoryAssetTypes,
49847
50004
  AccessoryDescriptionWrapper,
49848
50005
  AccessoryType,
50006
+ AccessoryWrapper,
49849
50007
  ActualBundleTypes,
49850
50008
  AllAccessorySorts,
49851
50009
  AllAnimationSorts,
@@ -49857,6 +50015,7 @@ export {
49857
50015
  AllHeadShapes,
49858
50016
  AllInstances,
49859
50017
  AlphaMode,
50018
+ AnimationConstraintWrapper,
49860
50019
  AnimationPropToName,
49861
50020
  AnimationTrack,
49862
50021
  AnimatorWrapper,
@@ -49871,6 +50030,7 @@ export {
49871
50030
  AvatarType,
49872
50031
  BodyColor3s,
49873
50032
  BodyColors,
50033
+ BodyColorsWrapper,
49874
50034
  BodyPart,
49875
50035
  BodyPartDescriptionWrapper,
49876
50036
  BodyPartEnumToNames,
@@ -49890,6 +50050,7 @@ export {
49890
50050
  Content,
49891
50051
  ContentMap,
49892
50052
  DataType,
50053
+ DecalWrapper,
49893
50054
  DefaultAnimations,
49894
50055
  DefaultAnimationsR6,
49895
50056
  DefaultGetWorkerFunc,
@@ -49913,12 +50074,15 @@ export {
49913
50074
  LayeredAssetTypes,
49914
50075
  LayeredClothingAssetOrder,
49915
50076
  LocalOutfit,
50077
+ MakeupAssetTypes,
49916
50078
  MakeupDescriptionWrapper,
49917
50079
  MakeupType,
50080
+ ManualWeldWrapper,
49918
50081
  MaxOneOfAssetTypes,
49919
50082
  MaxPerAsset,
49920
50083
  MeshType,
49921
50084
  ModelWrapper,
50085
+ Motor6DWrapper,
49922
50086
  NeverLayeredAccessoryTypes,
49923
50087
  NormalId,
49924
50088
  NumberRange,
@@ -49935,6 +50099,7 @@ export {
49935
50099
  RBFDeformerPatch,
49936
50100
  RBX,
49937
50101
  RBXRenderer,
50102
+ RBXRendererScene,
49938
50103
  RNG,
49939
50104
  Ray3 as Ray,
49940
50105
  RegisterWrappers,
@@ -49962,6 +50127,7 @@ export {
49962
50127
  Vector32 as Vector3,
49963
50128
  Wait,
49964
50129
  WearableAssetTypes,
50130
+ WeldWrapper,
49965
50131
  WorkerTypeToFunction,
49966
50132
  WrapLayerAutoSkin,
49967
50133
  accessoryRefinementLowerBounds,
@@ -50000,11 +50166,14 @@ export {
50000
50166
  download,
50001
50167
  exposeAPI,
50002
50168
  exposeMesh,
50169
+ fileMeshToTHREEGeometry,
50003
50170
  floor,
50004
50171
  gaussian_rbf,
50005
50172
  generateUUIDv4,
50006
50173
  getCameraCFrameForHeadshotCustomized,
50007
50174
  getDistIndexArray,
50175
+ getExtents,
50176
+ getExtentsForParts,
50008
50177
  getHeadExtents,
50009
50178
  getOffsetArray,
50010
50179
  getOriginalSize,
@@ -50060,5 +50229,6 @@ export {
50060
50229
  triangleNormal,
50061
50230
  versionToNumber,
50062
50231
  vertPosToChunkPos,
50063
- xmlMagic
50232
+ xmlMagic,
50233
+ zoomExtents
50064
50234
  };