roavatar-renderer 1.9.2 → 1.9.4

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
@@ -1436,6 +1436,11 @@ export declare function exposeFLAGS(): void;
1436
1436
  */
1437
1437
  export declare function exposeMesh(): void;
1438
1438
 
1439
+ /**
1440
+ * @category Exposer
1441
+ */
1442
+ export declare function exposeTests(): void;
1443
+
1439
1444
  /**
1440
1445
  * @category Exposer
1441
1446
  */
@@ -1515,7 +1520,13 @@ export declare class FileMesh {
1515
1520
  setBoneSource(name: string): void;
1516
1521
  setBoneSourceSize(): void;
1517
1522
  combine(other: FileMesh): void;
1518
- removeDuplicateVertices(distance?: number): number;
1523
+ /**
1524
+ *
1525
+ * @param distance
1526
+ * @param updateFaces This also fixes the faces (but it doesnt actually since its broken)
1527
+ * @returns
1528
+ */
1529
+ removeDuplicateVertices(distance?: number, updateFaces?: boolean): number;
1519
1530
  removeFaces(indices: number[]): void;
1520
1531
  basicSkin(boneNames: string[]): void;
1521
1532
  getValidationIssue(): "subsetLengthMismatch" | undefined;
@@ -1695,6 +1706,8 @@ export declare const FLAGS: {
1695
1706
  SEARCH_FOR_STRING: string | undefined;
1696
1707
  /**only used by RoAvatar, set this to a string to load a place file, for example "../assets/UniversalApp.rbxm" */
1697
1708
  LOAD_TEST_PLACE: string | undefined;
1709
+ /**Used for autotests */
1710
+ AUTOTEST_MODEL: string;
1698
1711
  };
1699
1712
 
1700
1713
  declare class FloatCurve {
@@ -2233,6 +2246,10 @@ export declare class Instance {
2233
2246
  setParent(instance: Instance | undefined | null, fireEvents?: boolean): void;
2234
2247
  Destroy(): void;
2235
2248
  GetFullName(): string;
2249
+ /**
2250
+ * @returns A reference to Instance._children, dangerous since the array can be modified by the Instance due to setParent and similar
2251
+ */
2252
+ GetChildrenDangerous(): Instance[];
2236
2253
  GetChildren(): Instance[];
2237
2254
  GetDescendants(): Instance[];
2238
2255
  FindFirstChild(name: string): Instance | undefined;
package/dist/index.js CHANGED
@@ -32648,8 +32648,9 @@ const FLAGS = {
32648
32648
  VERBOSE_LOGGING: false,
32649
32649
  SEARCH_FOR_STRING: void 0,
32650
32650
  //"requestparams" //"looks/" //this is useful if you want to find api endpoints
32651
- LOAD_TEST_PLACE: void 0
32651
+ LOAD_TEST_PLACE: void 0,
32652
32652
  //"../assets/UniversalApp.rbxm" //"../assets/WrapDeformerTest.rbxm" //"../assets/DecalTest2.rbxm" //"../assets/TransparentDominus.rbxm" //"../assets/EmissiveTest.rbxm" //"../assets/Mesh Deformation Test.rbxl" //set this to a string to load a place file
32653
+ AUTOTEST_MODEL: "rbxassetid://138879899842500"
32653
32654
  };
32654
32655
  function log(critical, ...args) {
32655
32656
  if (critical || FLAGS.VERBOSE_LOGGING) {
@@ -33113,7 +33114,7 @@ class CFrame {
33113
33114
  return new Matrix4().compose(new Vector3$1(...this.Position), new Quaternion().setFromEuler(new Euler(rad(this.Orientation[0]), rad(this.Orientation[1]), rad(this.Orientation[2]), "YXZ")), new Vector3$1(1, 1, 1));
33114
33115
  }
33115
33116
  getMatrix() {
33116
- return this.getTHREEMatrix().toArray();
33117
+ return this.getTHREEMatrix().elements;
33117
33118
  }
33118
33119
  fromMatrix(m) {
33119
33120
  this.Orientation = rotationMatrixToEulerAngles([
@@ -33196,14 +33197,13 @@ class CFrame {
33196
33197
  return euler.toArray();
33197
33198
  }
33198
33199
  inverse() {
33199
- const thisM = new Matrix4().fromArray(this.getMatrix());
33200
- const inverse = thisM.clone();
33200
+ const inverse = this.getTHREEMatrix();
33201
33201
  inverse.invert();
33202
33202
  return new CFrame().fromMatrix(inverse.elements);
33203
33203
  }
33204
33204
  multiply(cf) {
33205
- const thisM = new Matrix4().fromArray(this.getMatrix());
33206
- const cfM = new Matrix4().fromArray(cf.getMatrix());
33205
+ const thisM = this.getTHREEMatrix();
33206
+ const cfM = cf.getTHREEMatrix();
33207
33207
  const newM = thisM.multiply(cfM);
33208
33208
  const newCf = new CFrame().fromMatrix(newM.elements);
33209
33209
  return newCf;
@@ -33229,7 +33229,13 @@ class CFrame {
33229
33229
  return newCF;
33230
33230
  }
33231
33231
  isSame(other) {
33232
- return isSameFloat(this.Position[0], other.Position[0]) && isSameFloat(this.Position[1], other.Position[1]) && isSameFloat(this.Position[2], other.Position[2]) && isSameFloat(this.Orientation[0], other.Orientation[0]) && isSameFloat(this.Orientation[1], other.Orientation[1]) && isSameFloat(this.Orientation[2], other.Orientation[2]);
33232
+ const so0 = Math.abs(this.Orientation[0]) > 179 ? Math.abs(this.Orientation[0]) : this.Orientation[0];
33233
+ const so1 = Math.abs(this.Orientation[1]) > 179 ? Math.abs(this.Orientation[1]) : this.Orientation[1];
33234
+ const so2 = Math.abs(this.Orientation[2]) > 179 ? Math.abs(this.Orientation[2]) : this.Orientation[2];
33235
+ const oo0 = Math.abs(other.Orientation[0]) > 179 ? Math.abs(other.Orientation[0]) : other.Orientation[0];
33236
+ const oo1 = Math.abs(other.Orientation[1]) > 179 ? Math.abs(other.Orientation[1]) : other.Orientation[1];
33237
+ const oo2 = Math.abs(other.Orientation[2]) > 179 ? Math.abs(other.Orientation[2]) : other.Orientation[2];
33238
+ return isSameFloat(this.Position[0], other.Position[0]) && isSameFloat(this.Position[1], other.Position[1]) && isSameFloat(this.Position[2], other.Position[2]) && isSameFloat(so0, oo0) && isSameFloat(so1, oo1) && isSameFloat(so2, oo2);
33233
33239
  }
33234
33240
  }
33235
33241
  class Connection {
@@ -33628,17 +33634,23 @@ class Instance {
33628
33634
  return this.name || "null";
33629
33635
  }
33630
33636
  }
33637
+ /**
33638
+ * @returns A reference to Instance._children, dangerous since the array can be modified by the Instance due to setParent and similar
33639
+ */
33640
+ GetChildrenDangerous() {
33641
+ return this._children;
33642
+ }
33631
33643
  GetChildren() {
33632
- const childrenList = [];
33633
- for (const child of this._children) {
33634
- childrenList.push(child);
33635
- }
33636
- return childrenList;
33644
+ return [...this._children];
33637
33645
  }
33638
33646
  GetDescendants() {
33639
- let descendants = this.GetChildren();
33640
- for (const child of this.GetChildren()) {
33641
- descendants = descendants.concat(child.GetDescendants());
33647
+ const toCheck = this.GetChildren();
33648
+ const descendants = [...toCheck];
33649
+ while (toCheck.length > 0) {
33650
+ const child = toCheck.pop();
33651
+ const children = child.GetChildrenDangerous();
33652
+ toCheck.push(...children);
33653
+ descendants.push(...children);
33642
33654
  }
33643
33655
  return descendants;
33644
33656
  }
@@ -39034,10 +39046,15 @@ class FileMesh {
39034
39046
  this.skinning.setWeight(ogSkinningsSize + i, other.skinning.getWeight(i));
39035
39047
  }
39036
39048
  }
39037
- removeDuplicateVertices(distance2 = 1e-4) {
39049
+ /**
39050
+ *
39051
+ * @param distance
39052
+ * @param updateFaces This also fixes the faces (but it doesnt actually since its broken)
39053
+ * @returns
39054
+ */
39055
+ removeDuplicateVertices(distance2 = 1e-4, updateFaces = false) {
39038
39056
  const posToIndex = /* @__PURE__ */ new Map();
39039
39057
  const remap = new Array(this.coreMesh.numverts).fill(-1);
39040
- const vertToSubset = new Array(this.coreMesh.numverts).fill(-1);
39041
39058
  for (let i = 0; i < this.coreMesh.numverts; i++) {
39042
39059
  const pos = this.coreMesh.getPos(i);
39043
39060
  const uv = this.coreMesh.getUV(i);
@@ -39054,27 +39071,26 @@ class FileMesh {
39054
39071
  remap[i] = i;
39055
39072
  }
39056
39073
  }
39057
- for (let i = 0; i < this.coreMesh.numfaces; i++) {
39058
- const remapFace = this.coreMesh.getFace(remap[i]);
39059
- this.coreMesh.setFace(i, clonePrimitiveArray(remapFace));
39060
- }
39061
39074
  const newVerts = [];
39062
39075
  const newSkinnings = [];
39063
- const newSubsetIndices = [];
39064
39076
  const newIndex = /* @__PURE__ */ new Map();
39065
39077
  for (let i = 0; i < this.coreMesh.numverts; i++) {
39066
39078
  const canonical = remap[i];
39067
39079
  if (!newIndex.has(canonical)) {
39068
39080
  newIndex.set(canonical, newVerts.length);
39069
39081
  newVerts.push(canonical);
39070
- newSubsetIndices.push(vertToSubset[i]);
39071
39082
  newSkinnings.push(canonical);
39072
39083
  }
39073
39084
  remap[i] = newIndex.get(canonical);
39074
39085
  }
39075
- for (let i = 0; i < this.coreMesh.numfaces; i++) {
39076
- const remapFace = this.coreMesh.getFace(remap[i]);
39077
- this.coreMesh.setFace(i, clonePrimitiveArray(remapFace));
39086
+ if (updateFaces) {
39087
+ for (let i = 0; i < this.coreMesh.numfaces; i++) {
39088
+ const face = this.coreMesh.getFace(i);
39089
+ face[0] = remap[face[0]];
39090
+ face[1] = remap[face[1]];
39091
+ face[2] = remap[face[2]];
39092
+ this.coreMesh.setFace(i, face);
39093
+ }
39078
39094
  }
39079
39095
  this.coreMesh.onlyVerts(newVerts);
39080
39096
  this.skinning.onlySkinnings(newSkinnings);
@@ -44174,21 +44190,20 @@ class AccessoryWrapper extends InstanceWrapper {
44174
44190
  if (humanoid) {
44175
44191
  const handle = this.instance.FindFirstChild("Handle");
44176
44192
  if (handle) {
44177
- let accessoryAttachment = null;
44178
- let bodyAttachment = null;
44179
- for (const child of handle.GetChildren()) {
44193
+ for (const child of handle.GetChildrenDangerous()) {
44180
44194
  if (child.className === "Attachment") {
44181
- const bodyDescendants = this.instance.parent.GetDescendants();
44182
- for (const bodyChild of bodyDescendants) {
44183
- if (bodyChild.className === "Attachment" && child && bodyChild.Property("Name") === child.Property("Name") && bodyChild.parent && bodyChild.parent.parent === this.instance.parent) {
44184
- bodyAttachment = bodyChild;
44185
- accessoryAttachment = child;
44186
- break;
44195
+ const bodyParts = this.instance.parent.GetChildrenDangerous();
44196
+ for (const bodyPart of bodyParts) {
44197
+ if (bodyPart.className !== "Part" && bodyPart.className !== "MeshPart") continue;
44198
+ const bodyPartChildren = bodyPart.GetChildrenDangerous();
44199
+ for (const bodyChild of bodyPartChildren) {
44200
+ if (bodyChild.className === "Attachment" && child && bodyChild.Property("Name") === child.Property("Name") && bodyChild.parent && bodyChild.parent.parent === this.instance.parent) {
44201
+ return [bodyChild, child];
44202
+ }
44187
44203
  }
44188
44204
  }
44189
44205
  }
44190
44206
  }
44191
- if (bodyAttachment && accessoryAttachment) return [bodyAttachment, accessoryAttachment];
44192
44207
  }
44193
44208
  }
44194
44209
  }
@@ -44201,12 +44216,9 @@ class AccessoryWrapper extends InstanceWrapper {
44201
44216
  if (handle) {
44202
44217
  const attachmentPair = this.getBodyAccessoryAttachmentPair();
44203
44218
  const oldAccessoryWeld = handle.FindFirstChild("AccessoryWeld");
44204
- if (oldAccessoryWeld) {
44205
- oldAccessoryWeld.Destroy();
44206
- }
44207
44219
  if (attachmentPair) {
44208
44220
  const [bodyAttachment, accessoryAttachment] = attachmentPair;
44209
- const weld = new Instance("Weld");
44221
+ const weld = oldAccessoryWeld || new Instance("Weld");
44210
44222
  weld.addProperty(new Property("Name", DataType.String), "AccessoryWeld");
44211
44223
  weld.addProperty(new Property("Archivable", DataType.Bool), true);
44212
44224
  weld.addProperty(new Property("C1", DataType.CFrame), accessoryAttachment.Property("CFrame").clone());
@@ -44221,7 +44233,7 @@ class AccessoryWrapper extends InstanceWrapper {
44221
44233
  const head = this.instance.parent.FindFirstChild("Head");
44222
44234
  if (!head) return;
44223
44235
  const attachmentPoint = this.instance.PropOrDefault("AttachmentPoint", new CFrame());
44224
- const weld = new Instance("Weld");
44236
+ const weld = oldAccessoryWeld || new Instance("Weld");
44225
44237
  weld.addProperty(new Property("Name", DataType.String), "AccessoryWeld");
44226
44238
  weld.addProperty(new Property("Archivable", DataType.Bool), true);
44227
44239
  weld.addProperty(new Property("C1", DataType.CFrame), attachmentPoint.clone());
@@ -44492,7 +44504,7 @@ function getOriginalSize(part) {
44492
44504
  }
44493
44505
  return originalSize;
44494
44506
  }
44495
- function scaleChildrenOfPart(part, scaleVector, alreadyScaledAttachment) {
44507
+ function scaleChildrenOfPart(part, scaleVector, adjustedScaleVector, alreadyScaledAttachment) {
44496
44508
  for (const child of part.GetDescendants()) {
44497
44509
  if (child.className === "Attachment" && child !== alreadyScaledAttachment) {
44498
44510
  let originalPosition = child.Prop("Position");
@@ -44503,7 +44515,7 @@ function scaleChildrenOfPart(part, scaleVector, alreadyScaledAttachment) {
44503
44515
  } else if (child.className === "SpecialMesh") {
44504
44516
  if (child.Prop("MeshType") !== MeshType.Head) {
44505
44517
  const orignalScale = child.Prop("Scale");
44506
- child.setProperty("Scale", orignalScale.multiply(scaleVector));
44518
+ child.setProperty("Scale", orignalScale.multiply(adjustedScaleVector));
44507
44519
  }
44508
44520
  }
44509
44521
  }
@@ -44632,7 +44644,7 @@ function ScaleAccessory(accessory, bodyScaleVector, headScaleVector, bodyTypeSca
44632
44644
  }
44633
44645
  }
44634
44646
  }
44635
- scaleChildrenOfPart(handle, beforeAdjustmentResultScale, hasAdjusted);
44647
+ scaleChildrenOfPart(handle, beforeAdjustmentResultScale, resultScale, hasAdjusted);
44636
44648
  handle.setProperty("Size", originalSize.multiply(resultScale));
44637
44649
  if (accessory.className === "Accessory") {
44638
44650
  const accessoryWrapper = new AccessoryWrapper(accessory);
@@ -48627,7 +48639,12 @@ class ObjectDesc extends RenderDesc {
48627
48639
  threeMesh.scale.set(this.size.X, this.size.Y, this.size.Z);
48628
48640
  } else {
48629
48641
  const oldSize = this.originalScale;
48630
- threeMesh.scale.set(this.size.X / oldSize.x, this.size.Y / oldSize.y, this.size.Z / oldSize.z);
48642
+ const [sX, sY, sZ] = [
48643
+ specialClamp(this.size.X / oldSize.x, 1e-5, 1e6),
48644
+ specialClamp(this.size.Y / oldSize.y, 1e-5, 1e6),
48645
+ specialClamp(this.size.Z / oldSize.z, 1e-5, 1e6)
48646
+ ];
48647
+ threeMesh.scale.set(sX, sY, sZ);
48631
48648
  }
48632
48649
  if (SkeletonDesc.descNeedsSkeleton(this.meshDesc)) {
48633
48650
  this.skeletonDesc = new SkeletonDesc(this, this.meshDesc, scene);
@@ -48656,7 +48673,12 @@ class ObjectDesc extends RenderDesc {
48656
48673
  return new Vector3(this.size.X, this.size.Y, this.size.Z);
48657
48674
  } else {
48658
48675
  const oldSize = this.originalScale;
48659
- return new Vector3(this.size.X / oldSize.x, this.size.Y / oldSize.y, this.size.Z / oldSize.z);
48676
+ const [sX, sY, sZ] = [
48677
+ specialClamp(this.size.X / oldSize.x, 1e-5, 1e6),
48678
+ specialClamp(this.size.Y / oldSize.y, 1e-5, 1e6),
48679
+ specialClamp(this.size.Z / oldSize.z, 1e-5, 1e6)
48680
+ ];
48681
+ return new Vector3(sX, sY, sZ);
48660
48682
  }
48661
48683
  }
48662
48684
  updateResults() {
@@ -62308,6 +62330,10 @@ class RBXRenderer {
62308
62330
  controls.domElement = newCanvas;
62309
62331
  controls.connect(newCanvas);
62310
62332
  }
62333
+ const effectComposer = renderScene.effectComposer;
62334
+ if (effectComposer) {
62335
+ RBXRenderer.createEffectComposer(renderScene);
62336
+ }
62311
62337
  for (const renderDesc of renderScene.renderDescs.values()) {
62312
62338
  if (renderDesc instanceof ObjectDesc) {
62313
62339
  const materialDesc = renderDesc.materialDesc;
@@ -64395,6 +64421,106 @@ async function generateOutfitModelThumbnail(auth, outfitModel, options) {
64395
64421
  Object.assign(defaultOptions, options);
64396
64422
  return generateOutfitThumbnail(auth, outfitModel, defaultOptions.size, defaultOptions.type, defaultOptions.quality, defaultOptions.gltfAutoDownload, defaultOptions.includeAnimations);
64397
64423
  }
64424
+ async function runTests() {
64425
+ const auth = new Authentication();
64426
+ const testModel = await API.Asset.GetRBX(FLAGS.AUTOTEST_MODEL);
64427
+ if (testModel instanceof Response) throw "FLAGS.AUTOTEST_MODEL request failed";
64428
+ const root = testModel.generateTree();
64429
+ const folder = root.Child("Tests");
64430
+ if (!folder) throw "FLAGS.AUTOTEST_MODEL is missing Tests folder";
64431
+ for (const test of folder.GetChildren()) {
64432
+ console.log(test);
64433
+ const outfitDataValue = test.Child("OutfitData");
64434
+ const typesValue = test.Child("Types");
64435
+ const avatar = test.Child("Player");
64436
+ if (!outfitDataValue || !typesValue || !avatar) throw "A test is missing OutfitData";
64437
+ const outfitData = outfitDataValue.Prop("Value");
64438
+ const types = typesValue.Prop("Value").split(",");
64439
+ const outfit = new Outfit();
64440
+ await outfit.fromBuffer(base64ToArrayBuffer(outfitData), auth);
64441
+ const outfitRenderer = new OutfitRenderer(auth, outfit);
64442
+ await new Promise((resolve) => {
64443
+ outfitRenderer.onSuccess.Connect(() => {
64444
+ for (const type of types) {
64445
+ switch (type) {
64446
+ case "scale":
64447
+ testScale(outfitRenderer, avatar);
64448
+ break;
64449
+ default:
64450
+ throw `Invalid test type found: ${type}`;
64451
+ }
64452
+ }
64453
+ resolve(null);
64454
+ });
64455
+ });
64456
+ outfitRenderer.onError.Connect(() => {
64457
+ throw "OutfitRenderer failed to load";
64458
+ });
64459
+ outfitRenderer.destroy();
64460
+ }
64461
+ console.log("TESTS COMPLETE!");
64462
+ }
64463
+ function getEquivalent(self2, otherParent) {
64464
+ const equivalent = otherParent.GetChildren().filter((v) => {
64465
+ return v.Prop("Name") === self2.Prop("Name") && v.className === self2.className;
64466
+ })[0];
64467
+ return equivalent;
64468
+ }
64469
+ function testScaleInstance(child, otherParent) {
64470
+ if (child.IsA("BasePart")) {
64471
+ const equivalent = getEquivalent(child, otherParent);
64472
+ if (!equivalent) throw `BasePart: No equivalent for ${child.GetFullName()}`;
64473
+ const equivalentSize = equivalent.Prop("size");
64474
+ const selfSize = child.Prop("size");
64475
+ if (!equivalentSize.isSame(selfSize)) throw `TEST FAIL: Part size for ${child.GetFullName()} is not the same`;
64476
+ const specialMesh = child.FindFirstChildOfClass("SpecialMesh");
64477
+ if (specialMesh) {
64478
+ testScaleInstance(specialMesh, equivalent);
64479
+ }
64480
+ const foundNames = [];
64481
+ for (const att of child.GetChildren()) {
64482
+ if (att.IsA("Attachment")) {
64483
+ foundNames.push(att.Prop("Name"));
64484
+ }
64485
+ }
64486
+ const newNames = foundNames.filter((v) => {
64487
+ return foundNames.filter((g) => {
64488
+ return g === v;
64489
+ }).length === 1;
64490
+ });
64491
+ for (const newName of newNames) {
64492
+ const att = child.Child(newName);
64493
+ if (!att) throw `Attachment somehow doesnt exist???`;
64494
+ testScaleInstance(att, equivalent);
64495
+ }
64496
+ } else if (child.IsA("Accessory")) {
64497
+ const equivalent = getEquivalent(child, otherParent);
64498
+ if (!equivalent) throw `Accessory: No equivalent for ${child.GetFullName()}`;
64499
+ const handle = child.Child("Handle");
64500
+ if (handle) {
64501
+ testScaleInstance(handle, equivalent);
64502
+ }
64503
+ } else if (child.className === "SpecialMesh") {
64504
+ const equivalent = getEquivalent(child, otherParent);
64505
+ if (!equivalent) throw `SpecialMesh: No equivalent for ${child.GetFullName()}`;
64506
+ const selfScale = child.Prop("Scale");
64507
+ const equivalentScale = equivalent.Prop("Scale");
64508
+ if (!selfScale.isSame(equivalentScale)) throw `TEST FAIL: SpecialMesh Scale for ${child.GetFullName()} is not the same`;
64509
+ } else if (child.IsA("Attachment")) {
64510
+ if (child.Prop("Name") === "RootRigAttachment") return;
64511
+ const equivalent = getEquivalent(child, otherParent);
64512
+ if (!equivalent) throw `Attachment: No equivalent for ${child.GetFullName()}`;
64513
+ const selfCF = child.Prop("CFrame");
64514
+ const equivalentCF = equivalent.Prop("CFrame");
64515
+ if (!selfCF.isSame(equivalentCF)) throw `TEST FAIL: Attachment CFrame for ${child.GetFullName()} is not the same`;
64516
+ }
64517
+ }
64518
+ function testScale(outfitRenderer, avatar) {
64519
+ const currentRig = outfitRenderer.currentRig;
64520
+ for (const child of currentRig.GetChildren()) {
64521
+ testScaleInstance(child, avatar);
64522
+ }
64523
+ }
64398
64524
  function renderToRenderTarget(width, height, renderScene) {
64399
64525
  const renderTarget = new WebGLRenderTarget(width, height, {
64400
64526
  colorSpace: SRGBColorSpace,
@@ -64476,6 +64602,9 @@ function exposeThumbnailGenerator() {
64476
64602
  globalThis.setupThumbnailScene = setupThumbnailScene;
64477
64603
  globalThis.getThumbnailCameraCFrame = getThumbnailCameraCFrame;
64478
64604
  }
64605
+ function exposeTests() {
64606
+ globalThis.runTests = runTests;
64607
+ }
64479
64608
  export {
64480
64609
  API,
64481
64610
  AbbreviationToFaceControlProperty,
@@ -64684,6 +64813,7 @@ export {
64684
64813
  exposeAPI,
64685
64814
  exposeFLAGS,
64686
64815
  exposeMesh,
64816
+ exposeTests,
64687
64817
  exposeThumbnailGenerator,
64688
64818
  fileMeshToTHREEGeometry,
64689
64819
  floor,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "roavatar-renderer",
3
- "version": "1.9.2",
3
+ "version": "1.9.4",
4
4
  "description": "A renderer for Roblox avatars, used by the RoAvatar extension.",
5
5
  "author": "steinan",
6
6
  "type": "module",