roavatar-renderer 1.6.0 → 1.6.2

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.
Files changed (3) hide show
  1. package/dist/index.d.ts +126 -8
  2. package/dist/index.js +865 -304
  3. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -30279,6 +30279,16 @@ class RBXSimpleView {
30279
30279
  }
30280
30280
  const magic = "<roblox!";
30281
30281
  const xmlMagic = "<roblox ";
30282
+ const CameraType = {
30283
+ "Fixed": 0,
30284
+ "Attach": 1,
30285
+ "Watch": 2,
30286
+ "Track": 3,
30287
+ "Follow": 4,
30288
+ "Custom": 5,
30289
+ "Scriptable": 6,
30290
+ "Orbital": 7
30291
+ };
30282
30292
  const ParticleFlipbookLayout = {
30283
30293
  "None": 0,
30284
30294
  "Grid2x2": 1,
@@ -30436,6 +30446,24 @@ const BodyPartNameToEnum = {
30436
30446
  "UpperTorso": BodyPart.Torso,
30437
30447
  "LowerTorso": BodyPart.Torso
30438
30448
  };
30449
+ const R6BodyPartNames = ["Head", "Torso", "Left Arm", "Right Arm", "Left Leg", "Right Leg"];
30450
+ const R15BodyPartNames = [
30451
+ "Head",
30452
+ "UpperTorso",
30453
+ "LowerTorso",
30454
+ "LeftUpperArm",
30455
+ "LeftLowerArm",
30456
+ "LeftHand",
30457
+ "RightUpperArm",
30458
+ "RightLowerArm",
30459
+ "RightHand",
30460
+ "LeftUpperLeg",
30461
+ "LeftLowerLeg",
30462
+ "LeftFoot",
30463
+ "RightUpperLeg",
30464
+ "RightLowerLeg",
30465
+ "RightFoot"
30466
+ ];
30439
30467
  const BodyPartEnumToNames = {
30440
30468
  [BodyPart.Head]: ["Head"],
30441
30469
  [BodyPart.Torso]: ["Torso", "UpperTorso", "LowerTorso"],
@@ -32744,6 +32772,9 @@ class InstanceWrapper {
32744
32772
  }
32745
32773
  }
32746
32774
  }
32775
+ addProp(name, type, value) {
32776
+ if (!this.instance.HasProperty(name)) this.instance.addProperty(new Property(name, type), value);
32777
+ }
32747
32778
  setup() {
32748
32779
  throw new Error("Virtual method setup() called");
32749
32780
  }
@@ -32783,7 +32814,7 @@ class InstanceWrapper {
32783
32814
  preRender() {
32784
32815
  }
32785
32816
  }
32786
- const __vite_glob_0_13 = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
32817
+ const __vite_glob_0_14 = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
32787
32818
  __proto__: null,
32788
32819
  GetWrapperForInstance,
32789
32820
  InstanceWrapper
@@ -32899,6 +32930,13 @@ class Vector3 {
32899
32930
  isSame(other) {
32900
32931
  return isSameFloat(this.X, other.X) && isSameFloat(this.Y, other.Y) && isSameFloat(this.Z, other.Z);
32901
32932
  }
32933
+ lerp(other, t) {
32934
+ return new Vector3(
32935
+ lerp(this.X, other.X, t),
32936
+ lerp(this.Y, other.Y, t),
32937
+ lerp(this.Z, other.Z, t)
32938
+ );
32939
+ }
32902
32940
  static new(X, Y, Z) {
32903
32941
  return new Vector3(X, Y, Z);
32904
32942
  }
@@ -33128,6 +33166,11 @@ class CFrame {
33128
33166
  constructor(x = 0, y = 0, z = 0) {
33129
33167
  this.Position = [x, y, z];
33130
33168
  }
33169
+ static Angles(x, y, z) {
33170
+ const cf = new CFrame();
33171
+ cf.Orientation = [x, y, z];
33172
+ return cf;
33173
+ }
33131
33174
  clone() {
33132
33175
  const cloneCF = new CFrame(this.Position[0], this.Position[1], this.Position[2]);
33133
33176
  cloneCF.Orientation = [this.Orientation[0], this.Orientation[1], this.Orientation[2]];
@@ -33198,6 +33241,17 @@ class CFrame {
33198
33241
  const matrix = new Matrix4().makeRotationFromEuler(new Euler(rx, ry, rz, order));
33199
33242
  return new CFrame().fromMatrix(matrix.elements);
33200
33243
  }
33244
+ rotationOnly() {
33245
+ const copy = this.clone();
33246
+ copy.Position = [0, 0, 0];
33247
+ return copy;
33248
+ }
33249
+ toEulerAngles(order = "XYZ") {
33250
+ const [rx, ry, rz] = this.Orientation;
33251
+ let euler = new Euler(rad(rx), rad(ry), rad(rz), "YXZ");
33252
+ euler = euler.reorder(order);
33253
+ return euler.toArray();
33254
+ }
33201
33255
  inverse() {
33202
33256
  const thisM = new Matrix4().fromArray(this.getMatrix());
33203
33257
  const inverse = thisM.clone();
@@ -33211,6 +33265,26 @@ class CFrame {
33211
33265
  const newCf = new CFrame().fromMatrix(newM.elements);
33212
33266
  return newCf;
33213
33267
  }
33268
+ multiplyVector(vector) {
33269
+ const vectorCF = new CFrame(...vector.toVec3());
33270
+ const resultCF = this.multiply(vectorCF);
33271
+ const resultVector = new Vector3(...resultCF.Position);
33272
+ return resultVector;
33273
+ }
33274
+ removeNaN(newValue = 0) {
33275
+ const newCF = new CFrame();
33276
+ newCF.Position = [
33277
+ isNaN(this.Position[0]) ? newValue : this.Position[0],
33278
+ isNaN(this.Position[1]) ? newValue : this.Position[1],
33279
+ isNaN(this.Position[2]) ? newValue : this.Position[2]
33280
+ ];
33281
+ newCF.Orientation = [
33282
+ isNaN(this.Orientation[0]) ? newValue : this.Orientation[0],
33283
+ isNaN(this.Orientation[1]) ? newValue : this.Orientation[1],
33284
+ isNaN(this.Orientation[2]) ? newValue : this.Orientation[2]
33285
+ ];
33286
+ return newCF;
33287
+ }
33214
33288
  isSame(other) {
33215
33289
  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]);
33216
33290
  }
@@ -36917,8 +36991,10 @@ class LocalOutfit {
36917
36991
  this.bg = data.bg || 0;
36918
36992
  return this;
36919
36993
  }
36920
- update(outfit) {
36994
+ update(outfitModel) {
36995
+ const outfit = outfitModel instanceof OutfitModel ? outfitModel.outfit : outfitModel;
36921
36996
  this.buffer = arrayBufferToBase64(outfit.toBuffer());
36997
+ if (outfitModel instanceof OutfitModel) this.bg = outfitModel.background?.id || 0;
36922
36998
  this.image = void 0;
36923
36999
  }
36924
37000
  /**
@@ -39122,8 +39198,15 @@ const API = {
39122
39198
  return response;
39123
39199
  }
39124
39200
  },
39201
+ GetUserAvatarModel: async function(userId) {
39202
+ const response = await RBLXGet(`https://avatar.roblox.com/v4/avatar/users/${userId}?selectionTypes=0&selectionTypes=1&selectionTypes=2&selectionTypes=3&selectionTypes=4&selectionTypes=5&selectionTypes=6`);
39203
+ if (response.status !== 200) return response;
39204
+ const body = await response.json();
39205
+ const outfitModel = new OutfitModel().fromJson(body);
39206
+ return outfitModel;
39207
+ },
39125
39208
  GetAvatarModel: async function() {
39126
- const response = await RBLXGet("https://avatar.roblox.com/v4/avatar?selectionTypes=0&selectionTypes=1&selectionTypes=2&selectionTypes=3&selectionTypes=4&selectionTypes=5");
39209
+ const response = await RBLXGet("https://avatar.roblox.com/v4/avatar?selectionTypes=0&selectionTypes=1&selectionTypes=2&selectionTypes=3&selectionTypes=4&selectionTypes=5&selectionTypes=6");
39127
39210
  if (response.status !== 200) return response;
39128
39211
  const body = await response.json();
39129
39212
  const outfitModel = new OutfitModel().fromJson(body);
@@ -43484,7 +43567,7 @@ class ConstraintWrapper extends InstanceWrapper {
43484
43567
  if (!this.instance.HasProperty("Attachment1")) this.instance.addProperty(new Property("Attachment1", DataType.Referent), void 0);
43485
43568
  }
43486
43569
  }
43487
- const __vite_glob_0_9 = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
43570
+ const __vite_glob_0_10 = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
43488
43571
  __proto__: null,
43489
43572
  ConstraintWrapper
43490
43573
  }, Symbol.toStringTag, { value: "Module" }));
@@ -45902,7 +45985,7 @@ class MeshDesc {
45902
45985
  const wrapTarget = child.parent?.parent?.FindFirstChildOfClass("WrapTarget");
45903
45986
  if (wrapTarget) {
45904
45987
  this.wrapTextureTarget = wrapTarget.Prop("CageMeshId");
45905
- this.wrapTextureTargetOrigin = wrapTarget.Prop("CageOrigin");
45988
+ this.wrapTextureTargetOrigin = wrapTarget.Prop("CageOrigin").removeNaN();
45906
45989
  }
45907
45990
  }
45908
45991
  }
@@ -47330,7 +47413,7 @@ class FaceControlsWrapper extends InstanceWrapper {
47330
47413
  }
47331
47414
  }
47332
47415
  }
47333
- const __vite_glob_0_11 = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
47416
+ const __vite_glob_0_12 = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
47334
47417
  __proto__: null,
47335
47418
  FaceControlsWrapper
47336
47419
  }, Symbol.toStringTag, { value: "Module" }));
@@ -47778,51 +47861,54 @@ class ObjectDesc extends RenderDesc {
47778
47861
  async compileResults(renderer, scene) {
47779
47862
  const loadingLabel = this.instance ? this.instance.GetFullName() : "unknown";
47780
47863
  API.Misc.startCurrentlyLoadingAssets(loadingLabel);
47781
- const originalResult = this.results;
47782
- const originalSkeletonDesc = this.skeletonDesc;
47783
- this.results = void 0;
47784
- this.skeletonDesc = void 0;
47785
- const promises = [
47786
- this.meshDesc.compileMesh(),
47787
- this.materialDesc.compileMaterial(this.meshDesc)
47788
- ];
47789
- const [threeMesh, threeMaterial] = await Promise.all(promises);
47790
- if (!(threeMesh instanceof Mesh)) {
47791
- warn(true, "Failed to get mesh for objectDesc", this.instance ? this.instance.GetFullName() : "unknown");
47864
+ try {
47865
+ const originalResult = this.results;
47866
+ const originalSkeletonDesc = this.skeletonDesc;
47867
+ this.results = void 0;
47868
+ this.skeletonDesc = void 0;
47869
+ const promises = [
47870
+ this.meshDesc.compileMesh(),
47871
+ this.materialDesc.compileMaterial(this.meshDesc)
47872
+ ];
47873
+ const [threeMesh, threeMaterial] = await Promise.all(promises);
47874
+ if (!(threeMesh instanceof Mesh)) {
47875
+ warn(true, "Failed to get mesh for objectDesc", this.instance ? this.instance.GetFullName() : "unknown");
47876
+ API.Misc.stopCurrentlyLoadingAssets(loadingLabel);
47877
+ return threeMesh;
47878
+ }
47879
+ if (threeMesh instanceof SkinnedMesh) {
47880
+ threeMaterial.skinning = true;
47881
+ this.isSkinned = true;
47882
+ }
47883
+ threeMesh.material = threeMaterial;
47884
+ threeMesh.receiveShadow = true;
47885
+ threeMaterial.needsUpdate = true;
47886
+ threeMesh.visible = threeMaterial.visible;
47887
+ this.results = [threeMesh];
47888
+ this.originalScale = threeMesh.scale.clone();
47889
+ if (!this.meshDesc.scaleIsRelative) {
47890
+ threeMesh.scale.set(this.size.X, this.size.Y, this.size.Z);
47891
+ } else {
47892
+ const oldSize = this.originalScale;
47893
+ threeMesh.scale.set(this.size.X / oldSize.x, this.size.Y / oldSize.y, this.size.Z / oldSize.z);
47894
+ }
47895
+ if (SkeletonDesc.descNeedsSkeleton(this.meshDesc)) {
47896
+ this.skeletonDesc = new SkeletonDesc(this, this.meshDesc, scene);
47897
+ } else {
47898
+ this.meshDesc.fileMesh = void 0;
47899
+ }
47900
+ if (originalResult) {
47901
+ this.disposeMeshes(scene, originalResult);
47902
+ }
47903
+ if (originalSkeletonDesc) {
47904
+ this.disposeSkeleton(scene, originalSkeletonDesc);
47905
+ }
47906
+ if (originalResult) {
47907
+ this.disposeRenderLists(renderer);
47908
+ }
47909
+ } finally {
47792
47910
  API.Misc.stopCurrentlyLoadingAssets(loadingLabel);
47793
- return threeMesh;
47794
- }
47795
- if (threeMesh instanceof SkinnedMesh) {
47796
- threeMaterial.skinning = true;
47797
- this.isSkinned = true;
47798
- }
47799
- threeMesh.material = threeMaterial;
47800
- threeMesh.receiveShadow = true;
47801
- threeMaterial.needsUpdate = true;
47802
- threeMesh.visible = threeMaterial.visible;
47803
- this.results = [threeMesh];
47804
- this.originalScale = threeMesh.scale.clone();
47805
- if (!this.meshDesc.scaleIsRelative) {
47806
- threeMesh.scale.set(this.size.X, this.size.Y, this.size.Z);
47807
- } else {
47808
- const oldSize = this.originalScale;
47809
- threeMesh.scale.set(this.size.X / oldSize.x, this.size.Y / oldSize.y, this.size.Z / oldSize.z);
47810
- }
47811
- if (SkeletonDesc.descNeedsSkeleton(this.meshDesc)) {
47812
- this.skeletonDesc = new SkeletonDesc(this, this.meshDesc, scene);
47813
- } else {
47814
- this.meshDesc.fileMesh = void 0;
47815
- }
47816
- if (originalResult) {
47817
- this.disposeMeshes(scene, originalResult);
47818
- }
47819
- if (originalSkeletonDesc) {
47820
- this.disposeSkeleton(scene, originalSkeletonDesc);
47821
- }
47822
- if (originalResult) {
47823
- this.disposeRenderLists(renderer);
47824
47911
  }
47825
- API.Misc.stopCurrentlyLoadingAssets(loadingLabel);
47826
47912
  return this.results;
47827
47913
  }
47828
47914
  getScale() {
@@ -48746,7 +48832,7 @@ class AnimationTrack {
48746
48832
  tick(deltaTime = 1 / 60) {
48747
48833
  const addTime = deltaTime * this.pSpeed;
48748
48834
  this.pFadedTime += addTime;
48749
- const newWeight = lerp(this.pOriginalWeight, this.pTargetWeight, specialClamp(this.pFadedTime / this.pFadeTime, 0, 1));
48835
+ const newWeight = this.pFadeTime === 0 ? this.pTargetWeight : lerp(this.pOriginalWeight, this.pTargetWeight, specialClamp(this.pFadedTime / this.pFadeTime, 0, 1));
48750
48836
  this.weight = newWeight;
48751
48837
  const ogTime = this.timePosition;
48752
48838
  if (this.weight >= 0.01) {
@@ -48769,6 +48855,7 @@ class AnimatorWrapperData {
48769
48855
  toolTracks = [];
48770
48856
  toolAddedConnection;
48771
48857
  toolRemovedConnection;
48858
+ forceTransitionTime;
48772
48859
  }
48773
48860
  class AnimatorWrapper extends InstanceWrapper {
48774
48861
  static className = "Animator";
@@ -48838,7 +48925,7 @@ class AnimatorWrapper extends InstanceWrapper {
48838
48925
  const realId = BigInt(API.Misc.idFromStr(id));
48839
48926
  return this.data.animationTracks.get(realId);
48840
48927
  }
48841
- _switchAnimation(name) {
48928
+ _switchAnimation(name, subAnimSpecifier) {
48842
48929
  let transitionTime = 0.2;
48843
48930
  if (name === this.data.currentAnimation) {
48844
48931
  transitionTime = 0.15;
@@ -48851,7 +48938,8 @@ class AnimatorWrapper extends InstanceWrapper {
48851
48938
  if (!name.startsWith("emote.") && !name.startsWith("id.")) {
48852
48939
  const entries = this.data.animationSet[name];
48853
48940
  if (entries && entries.length > 0) {
48854
- const entry = this._pickRandom(entries);
48941
+ const isSpecificSub = subAnimSpecifier !== void 0 && subAnimSpecifier >= 0;
48942
+ const entry = (isSpecificSub ? entries[subAnimSpecifier] : this._pickRandom(entries)) || entries[0];
48855
48943
  if (entry) {
48856
48944
  toPlayTrack = this._getTrack(entry.id);
48857
48945
  }
@@ -48877,7 +48965,7 @@ class AnimatorWrapper extends InstanceWrapper {
48877
48965
  this.data.currentAnimationTrack = void 0;
48878
48966
  this.data.currentAnimationTrack = toPlayTrack;
48879
48967
  if (toPlayTrack) {
48880
- toPlayTrack.Play(transitionTime);
48968
+ toPlayTrack.Play(this.data.forceTransitionTime === void 0 ? transitionTime : this.data.forceTransitionTime);
48881
48969
  }
48882
48970
  }
48883
48971
  }
@@ -48915,7 +49003,7 @@ class AnimatorWrapper extends InstanceWrapper {
48915
49003
  this.data.moodTracks.push(toPlayTrack);
48916
49004
  }
48917
49005
  this.data.currentMoodAnimationTrack = toPlayTrack;
48918
- toPlayTrack.Play(transitionTime);
49006
+ toPlayTrack.Play(this.data.forceTransitionTime === void 0 ? transitionTime : this.data.forceTransitionTime);
48919
49007
  }
48920
49008
  }
48921
49009
  return !!toPlayTrack;
@@ -48952,7 +49040,7 @@ class AnimatorWrapper extends InstanceWrapper {
48952
49040
  this.data.toolTracks.push(toPlayTrack);
48953
49041
  }
48954
49042
  this.data.currentToolAnimationTrack = toPlayTrack;
48955
- toPlayTrack.Play(transitionTime);
49043
+ toPlayTrack.Play(this.data.forceTransitionTime === void 0 ? transitionTime : this.data.forceTransitionTime);
48956
49044
  }
48957
49045
  }
48958
49046
  return !!toPlayTrack;
@@ -49158,27 +49246,20 @@ class AnimatorWrapper extends InstanceWrapper {
49158
49246
  if (subAnimIdStr.length > 0) {
49159
49247
  const subAnimId = BigInt(API.Misc.idFromStr(subAnimIdStr));
49160
49248
  const foundAnimTrack = this.data.animationTracks.get(subAnimId);
49249
+ if (!this.data.animationSet[animName]) {
49250
+ this.data.animationSet[animName] = [];
49251
+ }
49252
+ this.data.animationSet[animName].push({
49253
+ id: `rbxassetid://${subAnimId}`,
49254
+ weight: subWeight
49255
+ });
49161
49256
  if (foundAnimTrack) {
49162
49257
  if (forceLoop) {
49163
49258
  foundAnimTrack.looped = true;
49164
49259
  }
49165
- if (!this.data.animationSet[animName]) {
49166
- this.data.animationSet[animName] = [];
49167
- }
49168
- this.data.animationSet[animName].push({
49169
- id: `rbxassetid://${subAnimId}`,
49170
- weight: subWeight
49171
- });
49172
49260
  } else {
49173
49261
  promises.push(new Promise((resolve) => {
49174
49262
  this.loadAnimation(subAnimId, forceLoop).then((result) => {
49175
- if (!this.data.animationSet[animName]) {
49176
- this.data.animationSet[animName] = [];
49177
- }
49178
- this.data.animationSet[animName].push({
49179
- id: `rbxassetid://${subAnimId}`,
49180
- weight: subWeight
49181
- });
49182
49263
  resolve(result instanceof Response ? result : void 0);
49183
49264
  });
49184
49265
  }));
@@ -49217,7 +49298,7 @@ class AnimatorWrapper extends InstanceWrapper {
49217
49298
  }
49218
49299
  /**
49219
49300
  * Switches to new animation
49220
- * @param name Animation name, such as "idle", "walk", "emote.1234" or "id.1234"
49301
+ * @param name Animation name, such as "idle", "walk", "emote.1234" or "id.1234", can also specify sub animation like "idle:0"
49221
49302
  * @param type
49222
49303
  * @returns If animation sucessfully played
49223
49304
  */
@@ -49234,16 +49315,23 @@ class AnimatorWrapper extends InstanceWrapper {
49234
49315
  this.restPose(false, true);
49235
49316
  }
49236
49317
  }
49318
+ let subAnimSpecifier = -1;
49319
+ if (name.includes(":")) {
49320
+ const splitName = name.split(":");
49321
+ name = splitName[0];
49322
+ subAnimSpecifier = Number(splitName[1]);
49323
+ }
49237
49324
  switch (type) {
49238
49325
  case "main":
49239
- if (this.data.currentAnimation !== name) {
49326
+ if (this.data.currentAnimation !== name || subAnimSpecifier !== -1) {
49240
49327
  if (!name.startsWith("emote.") || staticFacialAnimation) {
49241
49328
  this.playAnimation("mood", "mood");
49242
49329
  } else {
49243
49330
  this.stopMoodAnimation();
49244
49331
  }
49245
49332
  log(false, "playing", name);
49246
- return this._switchAnimation(name);
49333
+ log(false, this.data.forceTransitionTime);
49334
+ return this._switchAnimation(name, subAnimSpecifier);
49247
49335
  } else {
49248
49336
  return true;
49249
49337
  }
@@ -49392,6 +49480,25 @@ const __vite_glob_0_8 = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.def
49392
49480
  __proto__: null,
49393
49481
  BoneWrapper
49394
49482
  }, Symbol.toStringTag, { value: "Module" }));
49483
+ class CameraWrapper extends InstanceWrapper {
49484
+ static className = "Camera";
49485
+ static requiredProperties = [
49486
+ "Name",
49487
+ "CFrame",
49488
+ "CameraType",
49489
+ "FieldOfView"
49490
+ ];
49491
+ setup() {
49492
+ this.addProp("Name", DataType.String, this.instance.className);
49493
+ this.addProp("CFrame", DataType.CFrame, new CFrame());
49494
+ this.addProp("CameraType", DataType.Enum, CameraType.Fixed);
49495
+ this.addProp("FieldOfView", DataType.Float32, 70);
49496
+ }
49497
+ }
49498
+ const __vite_glob_0_9 = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
49499
+ __proto__: null,
49500
+ CameraWrapper
49501
+ }, Symbol.toStringTag, { value: "Module" }));
49395
49502
  class DecalWrapper extends InstanceWrapper {
49396
49503
  static className = "Decal";
49397
49504
  static requiredProperties = [
@@ -49413,7 +49520,7 @@ class DecalWrapper extends InstanceWrapper {
49413
49520
  if (!this.instance.HasProperty("UVScale")) this.instance.addProperty(new Property("UVScale", DataType.Vector2), new Vector2());
49414
49521
  }
49415
49522
  }
49416
- const __vite_glob_0_10 = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
49523
+ const __vite_glob_0_11 = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
49417
49524
  __proto__: null,
49418
49525
  DecalWrapper
49419
49526
  }, Symbol.toStringTag, { value: "Module" }));
@@ -49557,7 +49664,7 @@ class MakeupDescriptionWrapper extends InstanceWrapper {
49557
49664
  if (!this.instance.HasProperty("Instance")) this.instance.addProperty(new Property("Instance", DataType.Referent), void 0);
49558
49665
  }
49559
49666
  }
49560
- const __vite_glob_0_15 = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
49667
+ const __vite_glob_0_16 = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
49561
49668
  __proto__: null,
49562
49669
  MakeupDescriptionWrapper
49563
49670
  }, Symbol.toStringTag, { value: "Module" }));
@@ -50762,18 +50869,13 @@ class HumanoidDescriptionWrapper extends InstanceWrapper {
50762
50869
  if (animationSetEntries) {
50763
50870
  for (const subAnim of animationSetEntries) {
50764
50871
  const subAnimId = BigInt(API.Misc.idFromStr(subAnim.id));
50872
+ animatorW.data.animationSet[animName].push(subAnim);
50765
50873
  if (!animatorW.data.animationTracks.has(subAnimId)) {
50766
50874
  promises.push(new Promise((resolve) => {
50767
50875
  animatorW.loadAnimation(subAnimId, true).then((result) => {
50768
- if (!animatorW.data.animationSet[animName]) {
50769
- animatorW.data.animationSet[animName] = [];
50770
- }
50771
- animatorW.data.animationSet[animName].push(subAnim);
50772
50876
  resolve(result instanceof Response ? result : void 0);
50773
50877
  });
50774
50878
  }));
50775
- } else {
50776
- animatorW.data.animationSet[animName].push(subAnim);
50777
50879
  }
50778
50880
  }
50779
50881
  } else {
@@ -50795,12 +50897,16 @@ class HumanoidDescriptionWrapper extends InstanceWrapper {
50795
50897
  if (this.instance.PropOrDefault(animationProp, 0n) > 0n && avatarType === AvatarType.R15) {
50796
50898
  const id = this.instance.Prop(animationProp);
50797
50899
  promises.push(new Promise((resolve) => {
50900
+ if (animationProp === "IdleAnimation") {
50901
+ delete animatorW.data.animationSet["pose"];
50902
+ }
50798
50903
  animatorW.loadAvatarAnimation(id, false, true).then((result) => {
50799
50904
  resolve(result);
50800
50905
  });
50801
50906
  }));
50802
50907
  } else {
50803
50908
  this._loadDefaultAnimation(animationProp, avatarType, animatorW, promises);
50909
+ if (animationProp === "IdleAnimation" && !toChange.includes("pose")) this._loadDefaultAnimation("pose", avatarType, animatorW, promises);
50804
50910
  }
50805
50911
  }
50806
50912
  const values = await Promise.all(promises);
@@ -50935,7 +51041,7 @@ class HumanoidDescriptionWrapper extends InstanceWrapper {
50935
51041
  return this.instance;
50936
51042
  }
50937
51043
  }
50938
- const __vite_glob_0_12 = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
51044
+ const __vite_glob_0_13 = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
50939
51045
  __proto__: null,
50940
51046
  HumanoidDescriptionWrapper
50941
51047
  }, Symbol.toStringTag, { value: "Module" }));
@@ -51070,14 +51176,14 @@ class JointInstanceWrapper extends InstanceWrapper {
51070
51176
  }
51071
51177
  }
51072
51178
  }
51073
- const __vite_glob_0_14 = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
51179
+ const __vite_glob_0_15 = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
51074
51180
  __proto__: null,
51075
51181
  JointInstanceWrapper
51076
51182
  }, Symbol.toStringTag, { value: "Module" }));
51077
51183
  class ManualWeldWrapper extends JointInstanceWrapper {
51078
51184
  static className = "ManualWeld";
51079
51185
  }
51080
- const __vite_glob_0_16 = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
51186
+ const __vite_glob_0_17 = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
51081
51187
  __proto__: null,
51082
51188
  ManualWeldWrapper
51083
51189
  }, Symbol.toStringTag, { value: "Module" }));
@@ -51092,7 +51198,7 @@ class MeshPartWrapper extends BasePartWrapper {
51092
51198
  if (!this.instance.HasProperty("DoubleSided")) this.instance.addProperty(new Property("DoubleSided", DataType.Bool), false);
51093
51199
  }
51094
51200
  }
51095
- const __vite_glob_0_17 = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
51201
+ const __vite_glob_0_18 = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
51096
51202
  __proto__: null,
51097
51203
  MeshPartWrapper
51098
51204
  }, Symbol.toStringTag, { value: "Module" }));
@@ -51111,7 +51217,7 @@ class ModelWrapper extends InstanceWrapper {
51111
51217
  throw new Error("Model has no PrimaryPart");
51112
51218
  }
51113
51219
  }
51114
- const __vite_glob_0_18 = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
51220
+ const __vite_glob_0_19 = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
51115
51221
  __proto__: null,
51116
51222
  ModelWrapper
51117
51223
  }, Symbol.toStringTag, { value: "Module" }));
@@ -51126,7 +51232,7 @@ class Motor6DWrapper extends JointInstanceWrapper {
51126
51232
  if (!this.instance.HasProperty("Transform")) this.instance.addProperty(new Property("Transform", DataType.CFrame), new CFrame());
51127
51233
  }
51128
51234
  }
51129
- const __vite_glob_0_19 = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
51235
+ const __vite_glob_0_20 = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
51130
51236
  __proto__: null,
51131
51237
  Motor6DWrapper
51132
51238
  }, Symbol.toStringTag, { value: "Module" }));
@@ -51141,7 +51247,7 @@ class PartWrapper extends BasePartWrapper {
51141
51247
  if (!this.instance.HasProperty("shape")) this.instance.addProperty(new Property("shape", DataType.Enum), PartType.Block);
51142
51248
  }
51143
51249
  }
51144
- const __vite_glob_0_20 = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
51250
+ const __vite_glob_0_21 = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
51145
51251
  __proto__: null,
51146
51252
  PartWrapper
51147
51253
  }, Symbol.toStringTag, { value: "Module" }));
@@ -52066,7 +52172,7 @@ class ParticleEmitterWrapper extends InstanceWrapper {
52066
52172
  }
52067
52173
  }
52068
52174
  }
52069
- const __vite_glob_0_21 = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
52175
+ const __vite_glob_0_22 = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
52070
52176
  __proto__: null,
52071
52177
  ParticleEmitterWrapper
52072
52178
  }, Symbol.toStringTag, { value: "Module" }));
@@ -52172,7 +52278,7 @@ class SoundWrapper extends InstanceWrapper {
52172
52278
  }
52173
52279
  }
52174
52280
  }
52175
- const __vite_glob_0_23 = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
52281
+ const __vite_glob_0_24 = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
52176
52282
  __proto__: null,
52177
52283
  SoundWrapper
52178
52284
  }, Symbol.toStringTag, { value: "Module" }));
@@ -52426,7 +52532,7 @@ class ScriptWrapper extends InstanceWrapper {
52426
52532
  }
52427
52533
  }
52428
52534
  }
52429
- const __vite_glob_0_22 = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
52535
+ const __vite_glob_0_23 = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
52430
52536
  __proto__: null,
52431
52537
  ScriptWrapper
52432
52538
  }, Symbol.toStringTag, { value: "Module" }));
@@ -52483,25 +52589,25 @@ class ToolWrapper extends InstanceWrapper {
52483
52589
  }
52484
52590
  }
52485
52591
  }
52486
- const __vite_glob_0_24 = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
52592
+ const __vite_glob_0_25 = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
52487
52593
  __proto__: null,
52488
52594
  ToolWrapper
52489
52595
  }, Symbol.toStringTag, { value: "Module" }));
52490
52596
  class WedgePartWrapper extends BasePartWrapper {
52491
52597
  static className = "WedgePart";
52492
52598
  }
52493
- const __vite_glob_0_25 = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
52599
+ const __vite_glob_0_26 = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
52494
52600
  __proto__: null,
52495
52601
  WedgePartWrapper
52496
52602
  }, Symbol.toStringTag, { value: "Module" }));
52497
52603
  class WeldWrapper extends JointInstanceWrapper {
52498
52604
  static className = "Weld";
52499
52605
  }
52500
- const __vite_glob_0_26 = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
52606
+ const __vite_glob_0_27 = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
52501
52607
  __proto__: null,
52502
52608
  WeldWrapper
52503
52609
  }, Symbol.toStringTag, { value: "Module" }));
52504
- const modules$1 = /* @__PURE__ */ Object.assign({ "./instance/Accessory.ts": __vite_glob_0_0$1, "./instance/AccessoryDescription.ts": __vite_glob_0_1$1, "./instance/AnimationConstraint.ts": __vite_glob_0_2$1, "./instance/Animator.ts": __vite_glob_0_3, "./instance/Attachment.ts": __vite_glob_0_4, "./instance/BasePart.ts": __vite_glob_0_5, "./instance/BodyColors.ts": __vite_glob_0_6, "./instance/BodyPartDescription.ts": __vite_glob_0_7, "./instance/Bone.ts": __vite_glob_0_8, "./instance/Constraint.ts": __vite_glob_0_9, "./instance/Decal.ts": __vite_glob_0_10, "./instance/FaceControls.ts": __vite_glob_0_11, "./instance/HumanoidDescription.ts": __vite_glob_0_12, "./instance/InstanceWrapper.ts": __vite_glob_0_13, "./instance/JointInstance.ts": __vite_glob_0_14, "./instance/MakeupDescription.ts": __vite_glob_0_15, "./instance/ManualWeld.ts": __vite_glob_0_16, "./instance/MeshPart.ts": __vite_glob_0_17, "./instance/Model.ts": __vite_glob_0_18, "./instance/Motor6D.ts": __vite_glob_0_19, "./instance/Part.ts": __vite_glob_0_20, "./instance/ParticleEmitter.ts": __vite_glob_0_21, "./instance/Script.ts": __vite_glob_0_22, "./instance/Sound.ts": __vite_glob_0_23, "./instance/Tool.ts": __vite_glob_0_24, "./instance/WedgePart.ts": __vite_glob_0_25, "./instance/Weld.ts": __vite_glob_0_26 });
52610
+ const modules$1 = /* @__PURE__ */ Object.assign({ "./instance/Accessory.ts": __vite_glob_0_0$1, "./instance/AccessoryDescription.ts": __vite_glob_0_1$1, "./instance/AnimationConstraint.ts": __vite_glob_0_2$1, "./instance/Animator.ts": __vite_glob_0_3, "./instance/Attachment.ts": __vite_glob_0_4, "./instance/BasePart.ts": __vite_glob_0_5, "./instance/BodyColors.ts": __vite_glob_0_6, "./instance/BodyPartDescription.ts": __vite_glob_0_7, "./instance/Bone.ts": __vite_glob_0_8, "./instance/Camera.ts": __vite_glob_0_9, "./instance/Constraint.ts": __vite_glob_0_10, "./instance/Decal.ts": __vite_glob_0_11, "./instance/FaceControls.ts": __vite_glob_0_12, "./instance/HumanoidDescription.ts": __vite_glob_0_13, "./instance/InstanceWrapper.ts": __vite_glob_0_14, "./instance/JointInstance.ts": __vite_glob_0_15, "./instance/MakeupDescription.ts": __vite_glob_0_16, "./instance/ManualWeld.ts": __vite_glob_0_17, "./instance/MeshPart.ts": __vite_glob_0_18, "./instance/Model.ts": __vite_glob_0_19, "./instance/Motor6D.ts": __vite_glob_0_20, "./instance/Part.ts": __vite_glob_0_21, "./instance/ParticleEmitter.ts": __vite_glob_0_22, "./instance/Script.ts": __vite_glob_0_23, "./instance/Sound.ts": __vite_glob_0_24, "./instance/Tool.ts": __vite_glob_0_25, "./instance/WedgePart.ts": __vite_glob_0_26, "./instance/Weld.ts": __vite_glob_0_27 });
52505
52611
  function RegisterWrappers() {
52506
52612
  for (const module of Object.values(modules$1)) {
52507
52613
  for (const exprt of Object.values(module)) {
@@ -57584,7 +57690,7 @@ class RBXRenderer {
57584
57690
  if (RBXRenderer.renderer) RBXRenderer.renderer.setClearColor(new Color(0, 0, 0), 0);
57585
57691
  RBXRenderer.renderer.outputColorSpace = SRGBColorSpace;
57586
57692
  RBXRenderer.renderer.shadowMap.enabled = true;
57587
- RBXRenderer.renderer.shadowMap.type = PCFSoftShadowMap;
57693
+ RBXRenderer.renderer.shadowMap.type = PCFShadowMap;
57588
57694
  RBXRenderer.renderer.setPixelRatio(globalThis.devicePixelRatio * 1 || 1);
57589
57695
  RBXRenderer.renderer.setSize(...RBXRenderer.resolution);
57590
57696
  if (FLAGS.USE_POST_PROCESSING && FLAGS.POST_PROCESSING_IS_DOUBLE_SIZE) {
@@ -58114,6 +58220,579 @@ class HSR {
58114
58220
  }
58115
58221
  }
58116
58222
  }
58223
+ function getHeadAttachments(rig) {
58224
+ const headAttachments = /* @__PURE__ */ new Map();
58225
+ const head = rig.Child("Head");
58226
+ if (head) {
58227
+ for (const child of head.GetDescendants()) {
58228
+ if (child.IsA("Attachment")) {
58229
+ headAttachments.set(child.Prop("Name"), true);
58230
+ }
58231
+ }
58232
+ }
58233
+ return headAttachments;
58234
+ }
58235
+ function makeRotatedCorner(x, y, z, halfSize, cFrame) {
58236
+ const corner = Vector3.new(x * halfSize.X, y * halfSize.Y, z * halfSize.Z);
58237
+ const newCF = cFrame.multiply(new CFrame(...corner.toVec3()));
58238
+ return Vector3.new(...newCF.Position);
58239
+ }
58240
+ function growExtentsToIncludePoint(minExtent, maxExtent, point) {
58241
+ minExtent = Vector3.new(Math.min(point.X, minExtent.X), Math.min(point.Y, minExtent.Y), Math.min(point.Z, minExtent.Z));
58242
+ maxExtent = Vector3.new(Math.max(point.X, maxExtent.X), Math.max(point.Y, maxExtent.Y), Math.max(point.Z, maxExtent.Z));
58243
+ return [minExtent, maxExtent];
58244
+ }
58245
+ function growExtentsToInclude(minExtent, maxExtent, part, cInverse, optYMinCFrame, optYMin) {
58246
+ const size = part.Prop("Size").divide(new Vector3(2, 2, 2));
58247
+ for (let x = -1; x <= 1; x += 2) {
58248
+ for (let y = -1; y <= 1; y += 2) {
58249
+ for (let z = -1; z <= 1; z += 2) {
58250
+ let corner = makeRotatedCorner(x, y, z, size, part.Prop("CFrame"));
58251
+ if (optYMinCFrame && optYMin !== void 0) {
58252
+ const transformedCorner = new Vector3(...optYMinCFrame.inverse().multiply(new CFrame(...corner.toVec3())).Position);
58253
+ const clampedTransformedCorner = Vector3.new(transformedCorner.X, Math.max(optYMin, transformedCorner.Y), transformedCorner.Z);
58254
+ corner = new Vector3(...optYMinCFrame.multiply(new CFrame(...clampedTransformedCorner.toVec3())).Position);
58255
+ }
58256
+ corner = new Vector3(...cInverse.multiply(new CFrame(...corner.toVec3())).Position);
58257
+ [minExtent, maxExtent] = growExtentsToIncludePoint(minExtent, maxExtent, corner);
58258
+ }
58259
+ }
58260
+ }
58261
+ return [minExtent, maxExtent];
58262
+ }
58263
+ function initExtents() {
58264
+ const minExtent = Vector3.new(Infinity, Infinity, Infinity);
58265
+ const maxExtent = Vector3.new(-Infinity, -Infinity, -Infinity);
58266
+ return [minExtent, maxExtent];
58267
+ }
58268
+ function recursiveCalculateExtents(minExtent, maxExtent, instance, cInverse, indent) {
58269
+ for (const child of instance.GetChildren()) {
58270
+ if (child.IsA("BasePart")) {
58271
+ [minExtent, maxExtent] = growExtentsToInclude(minExtent, maxExtent, child, cInverse);
58272
+ }
58273
+ [minExtent, maxExtent] = recursiveCalculateExtents(minExtent, maxExtent, child, cInverse);
58274
+ }
58275
+ return [minExtent, maxExtent];
58276
+ }
58277
+ function calculateModelExtents(model, targetCFrame) {
58278
+ let [minExtent, maxExtent] = initExtents();
58279
+ const cInverse = targetCFrame.inverse();
58280
+ [minExtent, maxExtent] = recursiveCalculateExtents(minExtent, maxExtent, model, cInverse);
58281
+ return [minExtent, maxExtent];
58282
+ }
58283
+ function calculateHeadExtents(character, targetCFrame) {
58284
+ let [minExtent, maxExtent] = initExtents();
58285
+ const head = character.FindFirstChild("Head");
58286
+ if (!head) {
58287
+ return [minExtent, maxExtent];
58288
+ }
58289
+ const cInverse = targetCFrame.inverse();
58290
+ const untransformedHeadYMin = -head.Prop("Size").Y / 2;
58291
+ [minExtent, maxExtent] = growExtentsToInclude(minExtent, maxExtent, head, cInverse);
58292
+ const headAttachments = getHeadAttachments(character);
58293
+ for (const child of character.GetChildren()) {
58294
+ if (child.IsA("Accessory")) {
58295
+ const handle = child.FindFirstChild("Handle");
58296
+ if (handle) {
58297
+ const attachment = handle.FindFirstChildOfClass("Attachment");
58298
+ if (!attachment || headAttachments.has(attachment.Prop("Name"))) {
58299
+ [minExtent, maxExtent] = growExtentsToInclude(minExtent, maxExtent, handle, cInverse, head.Prop("CFrame"), untransformedHeadYMin);
58300
+ }
58301
+ }
58302
+ }
58303
+ }
58304
+ return [minExtent, maxExtent];
58305
+ }
58306
+ function calculateBodyPartsExtents(targetCFrame, bodyParts) {
58307
+ let [minExtent, maxExtent] = initExtents();
58308
+ const cInverse = targetCFrame.inverse();
58309
+ for (const part of bodyParts) {
58310
+ [minExtent, maxExtent] = growExtentsToInclude(minExtent, maxExtent, part, cInverse, targetCFrame);
58311
+ }
58312
+ return [minExtent, maxExtent];
58313
+ }
58314
+ function calculateTargetCFrame(baseCFrame) {
58315
+ let targetLookVector = new Vector3();
58316
+ if (Math.abs(baseCFrame.lookVector()[1]) > 0.9) {
58317
+ targetLookVector = new Vector3().fromVec3(baseCFrame.upVector());
58318
+ } else {
58319
+ targetLookVector = new Vector3().fromVec3(baseCFrame.lookVector());
58320
+ }
58321
+ targetLookVector = Vector3.new(targetLookVector.X, 0, targetLookVector.Z).normalize();
58322
+ return CFrame.lookAt(baseCFrame.Position, new Vector3().fromVec3(baseCFrame.Position).add(targetLookVector).toVec3());
58323
+ }
58324
+ function adjustTargetCFrameWithExtents(targetCFrame, minExtent, maxExtent) {
58325
+ let adjustment = minExtent.add(maxExtent).divide(new Vector3(2, 2, 2));
58326
+ const tmpCFrame = targetCFrame.rotationOnly();
58327
+ adjustment = tmpCFrame.multiplyVector(adjustment);
58328
+ targetCFrame.Position = add(targetCFrame.Position, adjustment.toVec3());
58329
+ return targetCFrame;
58330
+ }
58331
+ function vector3FromXYRotPlusDistance(xAngleDeg, yAngleDeg, radius) {
58332
+ const cFrame = CFrame.fromEulerAngles(rad(xAngleDeg), rad(yAngleDeg), 0, "XYZ");
58333
+ return new Vector3(...cFrame.lookVector()).multiply(new Vector3(radius, radius, radius));
58334
+ }
58335
+ const CONSTANTS_CameraUtility = {
58336
+ //When generating a head thumbnail, how much 'margin' around extent of head + accoutrements?
58337
+ DefaultHeadMarginScale: 1.1,
58338
+ //When generating a full body thumbnail, how much 'margin' around whole body?
58339
+ DefaultBodyMarginScale: 1.1,
58340
+ //Amount of margin around a body part in a generated thumbnail
58341
+ DefaultBodyPartMarginScale: 1.2,
58342
+ XRotForFullBody: 15,
58343
+ XRotForCloseup: 0,
58344
+ DistanceScaleForFullBody: 1
58345
+ };
58346
+ const HEAD_MARGIN_SCALE = 1.1;
58347
+ const HEAD_X_ROTATION_RAD = rad(15);
58348
+ const HEAD_Y_ROTATION_RAD = rad(30);
58349
+ const FACE_LEFT_CFRAME = CFrame.fromEulerAngles(rad(-20), rad(20), 0, "YXZ");
58350
+ const FACE_RIGHT_CFRAME = CFrame.fromEulerAngles(rad(-20), rad(-20), 0, "YXZ");
58351
+ const HEAD_BODYPART_FIELD_OF_VIEW_DEG = 30;
58352
+ const ACCESSORY_DEFAULT_CFRAME = CFrame.Angles(rad(25), rad(25), rad(0));
58353
+ const ACCESSORY_FIELD_OF_VIEW_DEG = 20;
58354
+ const ACCESSORY_EXTENT_SCALE = 1.1;
58355
+ const LEFT_SHOE_CFRAME = CFrame.Angles(rad(0), rad(90), rad(0));
58356
+ const RIGHT_SHOE_CFRAME = CFrame.Angles(rad(0), rad(-90), rad(0));
58357
+ function getCameraCFrame(targetCFrame, relativePos) {
58358
+ const cameraPos = targetCFrame.multiplyVector(relativePos);
58359
+ return CFrame.lookAt(cameraPos.toVec3(), targetCFrame.Position);
58360
+ }
58361
+ function createThumbnailCamera() {
58362
+ const camera = new Instance("Camera");
58363
+ camera.setProperty("Name", "ThumbnailCamera");
58364
+ camera.setProperty("CameraType", CameraType.Scriptable);
58365
+ return camera;
58366
+ }
58367
+ function calculateBaseDistanceToCamera(fieldOfViewRad, minExtent, maxExtent, marginScale) {
58368
+ const offsetFromCenter = Math.max((maxExtent.X - minExtent.X) / 2, (maxExtent.Y - minExtent.Y) / 2);
58369
+ const t = Math.tan(fieldOfViewRad / 2);
58370
+ return offsetFromCenter * marginScale / t;
58371
+ }
58372
+ function setupCamera(camera, cameraOptions) {
58373
+ if (cameraOptions.optFieldOfView) {
58374
+ camera.setProperty("FieldOfView", cameraOptions.optFieldOfView);
58375
+ }
58376
+ const fieldOfViewForDistanceScale = cameraOptions.optFieldOfViewForDistanceScale || camera.Prop("FieldOfView");
58377
+ let distanceToCamera = calculateBaseDistanceToCamera(
58378
+ rad(fieldOfViewForDistanceScale),
58379
+ cameraOptions.minExtent,
58380
+ cameraOptions.maxExtent,
58381
+ cameraOptions.extentScale
58382
+ );
58383
+ if (cameraOptions.optCameraDistanceScale) {
58384
+ distanceToCamera = distanceToCamera * cameraOptions.optCameraDistanceScale;
58385
+ }
58386
+ const finalTargetCFrame = adjustTargetCFrameWithExtents(
58387
+ cameraOptions.targetCFrame,
58388
+ cameraOptions.minExtent,
58389
+ cameraOptions.maxExtent
58390
+ );
58391
+ const cameraXRotDeg = cameraOptions.optCameraXRot || 0;
58392
+ const cameraYRotDeg = cameraOptions.optCameraYRot || 0;
58393
+ const cPos = vector3FromXYRotPlusDistance(cameraXRotDeg, cameraYRotDeg, distanceToCamera);
58394
+ camera.setProperty("CFrame", getCameraCFrame(finalTargetCFrame, cPos));
58395
+ }
58396
+ function setupBodyPartCamera(mannequin, faceRight, focusPartNames, camera) {
58397
+ const mannequinFocusParts = [];
58398
+ for (const focusPartName of focusPartNames) {
58399
+ const focusPart = mannequin.FindFirstDescendant(focusPartName);
58400
+ if (focusPart) {
58401
+ mannequinFocusParts.push(focusPart);
58402
+ }
58403
+ }
58404
+ const humanoidRootPart = mannequin.FindFirstChild("HumanoidRootPart");
58405
+ if (humanoidRootPart) {
58406
+ let mannequinTargetCFrame = humanoidRootPart.Prop("CFrame");
58407
+ const adjustment = faceRight ? FACE_RIGHT_CFRAME : FACE_LEFT_CFRAME;
58408
+ mannequinTargetCFrame = adjustment.multiply(mannequinTargetCFrame);
58409
+ const [minPartsExtent, maxPartsExtent] = calculateBodyPartsExtents(mannequinTargetCFrame, mannequinFocusParts);
58410
+ const cameraOptions = {
58411
+ optFieldOfView: HEAD_BODYPART_FIELD_OF_VIEW_DEG,
58412
+ targetCFrame: mannequinTargetCFrame,
58413
+ minExtent: minPartsExtent,
58414
+ maxExtent: maxPartsExtent,
58415
+ extentScale: CONSTANTS_CameraUtility.DefaultBodyPartMarginScale
58416
+ };
58417
+ setupCamera(camera, cameraOptions);
58418
+ }
58419
+ }
58420
+ function setupHeadCamera(headModel, camera) {
58421
+ const head = headModel.FindFirstChild("Head");
58422
+ if (head) {
58423
+ let headTargetCFrame = calculateTargetCFrame(head.Prop("CFrame"));
58424
+ const adjustment = CFrame.fromEulerAngles(HEAD_X_ROTATION_RAD, HEAD_Y_ROTATION_RAD, 0, "YXZ");
58425
+ headTargetCFrame = adjustment.multiply(headTargetCFrame);
58426
+ const [minHeadExtent, maxHeadExtent] = calculateHeadExtents(headModel, headTargetCFrame);
58427
+ const cameraOptions = {
58428
+ optFieldOfView: HEAD_BODYPART_FIELD_OF_VIEW_DEG,
58429
+ targetCFrame: headTargetCFrame,
58430
+ minExtent: minHeadExtent,
58431
+ maxExtent: maxHeadExtent,
58432
+ extentScale: HEAD_MARGIN_SCALE
58433
+ };
58434
+ setupCamera(camera, cameraOptions);
58435
+ }
58436
+ }
58437
+ function isLeftShoe(acc) {
58438
+ const handle = acc.FindFirstChildOfClass("MeshPart");
58439
+ if (!handle) {
58440
+ return false;
58441
+ }
58442
+ return void 0 !== handle.FindFirstChild("LeftFootAttachment");
58443
+ }
58444
+ function isRightShoe(acc) {
58445
+ const handle = acc.FindFirstChildOfClass("MeshPart");
58446
+ if (!handle) {
58447
+ return false;
58448
+ }
58449
+ return void 0 !== handle.FindFirstChild("RightFootAttachment");
58450
+ }
58451
+ function getAccessoryAngle(acc) {
58452
+ if (isLeftShoe(acc)) {
58453
+ return LEFT_SHOE_CFRAME;
58454
+ } else if (isRightShoe(acc)) {
58455
+ return RIGHT_SHOE_CFRAME;
58456
+ }
58457
+ return ACCESSORY_DEFAULT_CFRAME;
58458
+ }
58459
+ function setupAccessoryCamera(accessoryModel, camera) {
58460
+ const modelChildren = accessoryModel.GetChildren();
58461
+ const accoutrement = modelChildren[0];
58462
+ const handle = accoutrement.FindFirstChild("Handle");
58463
+ if (handle) {
58464
+ handle.setProperty("CFrame", new CFrame());
58465
+ const targetCFrame = handle.Prop("CFrame").multiply(getAccessoryAngle(accoutrement));
58466
+ const [minPartsExtent, maxPartsExtent] = calculateModelExtents(accessoryModel, targetCFrame);
58467
+ const cameraOptions = {
58468
+ optFieldOfView: ACCESSORY_FIELD_OF_VIEW_DEG,
58469
+ targetCFrame,
58470
+ minExtent: minPartsExtent,
58471
+ maxExtent: maxPartsExtent,
58472
+ extentScale: ACCESSORY_EXTENT_SCALE
58473
+ };
58474
+ setupCamera(camera, cameraOptions);
58475
+ }
58476
+ }
58477
+ const FIntCameraPresetHeadshotExtentScaleHundredths = 110;
58478
+ const CONSTANTS_CameraPresetsUtility = {
58479
+ GOLDEN_RATIO: 600 / 1e3,
58480
+ //game:DefineFastInt("AvatarGoldenRatio", 618) / 1000 -- = 0.618
58481
+ UPVECTOR_ORENTATION_TRESHOLD: -60 / 100,
58482
+ //game:DefineFastInt("UpVectorOrentationThreshold1", -60) / 100 // = -0.6
58483
+ AVATAR_ROTATION_DEGREE: 15
58484
+ //game:DefineFastInt("LookAvatarRotationDegree1", 23)
58485
+ };
58486
+ function getTorsoOrUpperTorso(character) {
58487
+ return character.FindFirstChild("Torso") || character.FindFirstChild("UpperTorso");
58488
+ }
58489
+ function getMannequinBodyParts(character, humanoid) {
58490
+ const bodyParts = [];
58491
+ if (humanoid.Prop("RigType") === HumanoidRigType.R6) {
58492
+ for (const partName of R6BodyPartNames) {
58493
+ const bodyPart = character.FindFirstChild(partName);
58494
+ if (bodyPart) bodyParts.push(bodyPart);
58495
+ }
58496
+ } else if (humanoid.Prop("RigType") === HumanoidRigType.R15) {
58497
+ for (const partName of R15BodyPartNames) {
58498
+ const bodyPart = character.FindFirstChild(partName);
58499
+ if (bodyPart) bodyParts.push(bodyPart);
58500
+ }
58501
+ }
58502
+ return bodyParts;
58503
+ }
58504
+ function getCharacterTorsoCFrame(character) {
58505
+ const torso = getTorsoOrUpperTorso(character);
58506
+ return torso ? torso.Prop("CFrame") : new CFrame();
58507
+ }
58508
+ function getFullBodyCameraCFrame(character, applyEmote, isFallbackEmoteApplied = true, fieldOfViewDeg, characterInitialCFrame, autoZoom = true) {
58509
+ const fovAngle = fieldOfViewDeg || 56;
58510
+ const characterInitialPivotTo = characterInitialCFrame || getCharacterTorsoCFrame(character);
58511
+ const characterInitialLookVector = characterInitialPivotTo.lookVector();
58512
+ if (applyEmote) {
58513
+ applyEmote();
58514
+ }
58515
+ const humanoid = character.FindFirstChildOfClass("Humanoid");
58516
+ if (!humanoid) {
58517
+ return;
58518
+ }
58519
+ const bodyParts = getMannequinBodyParts(character, humanoid);
58520
+ const characterPivotToAuxiliaryCFrame = getCharacterTorsoCFrame(character);
58521
+ const characterAuxiliaryUpVector = characterPivotToAuxiliaryCFrame.upVector();
58522
+ const head = character.FindFirstChild("Head");
58523
+ if (!head) return;
58524
+ const [characterHeadRotationX, characterHeadRotationY, characterHeadRotationZ] = head.Prop("CFrame").toEulerAngles("XYZ");
58525
+ if (isFallbackEmoteApplied) {
58526
+ const rootAssembly = head.w.GetAssembly();
58527
+ const rootPart = rootAssembly.rootNode.part;
58528
+ rootPart.setProperty("CFrame", rootPart.Prop("CFrame").multiply(CFrame.Angles(0, rad(CONSTANTS_CameraPresetsUtility.AVATAR_ROTATION_DEGREE * -1), 0)));
58529
+ rootAssembly.traverseTree();
58530
+ }
58531
+ const [minPartsExtent, maxPartsExtent] = calculateBodyPartsExtents(characterPivotToAuxiliaryCFrame, bodyParts);
58532
+ const tanAlpha = Math.tan(rad(fovAngle / 2));
58533
+ const goldPositionOfExtent = minPartsExtent.lerp(maxPartsExtent, CONSTANTS_CameraPresetsUtility.GOLDEN_RATIO);
58534
+ const centerPositionOfExtent = minPartsExtent.lerp(maxPartsExtent, 0.5);
58535
+ const goldPosition = new Vector3(centerPositionOfExtent.X, goldPositionOfExtent.Y, centerPositionOfExtent.Z);
58536
+ const goldPositionWorldSpace = characterPivotToAuxiliaryCFrame.multiplyVector(goldPosition);
58537
+ let characterGoldenRatioPivotTo = characterPivotToAuxiliaryCFrame.rotationOnly();
58538
+ characterGoldenRatioPivotTo.Position = add(characterGoldenRatioPivotTo.Position, goldPositionWorldSpace.toVec3());
58539
+ if (!isFallbackEmoteApplied) {
58540
+ const headPivotTo = CFrame.fromEulerAngles(characterHeadRotationX, characterHeadRotationY, characterHeadRotationZ, "XYZ");
58541
+ characterGoldenRatioPivotTo = headPivotTo.rotationOnly();
58542
+ characterGoldenRatioPivotTo.Position = add(characterGoldenRatioPivotTo.Position, goldPositionWorldSpace.toVec3());
58543
+ }
58544
+ const distanceToLowerExtents = Math.max(goldPosition.X - minPartsExtent.X, goldPosition.Y - minPartsExtent.Y);
58545
+ const distanceToUpperExtents = Math.max(maxPartsExtent.X - goldPosition.X, maxPartsExtent.Y - goldPosition.Y);
58546
+ const dc1 = distanceToLowerExtents * CONSTANTS_CameraUtility.DefaultBodyMarginScale / tanAlpha;
58547
+ const dc1Option = distanceToUpperExtents * CONSTANTS_CameraUtility.DefaultBodyMarginScale / tanAlpha;
58548
+ let distanceToCameraOption = dc1;
58549
+ const isUpsideDown = characterAuxiliaryUpVector[1] < CONSTANTS_CameraPresetsUtility.UPVECTOR_ORENTATION_TRESHOLD;
58550
+ const isUpsideRight = characterAuxiliaryUpVector[0] < CONSTANTS_CameraPresetsUtility.UPVECTOR_ORENTATION_TRESHOLD;
58551
+ if (isUpsideDown || isUpsideRight) {
58552
+ distanceToCameraOption = Math.max(dc1, dc1Option);
58553
+ }
58554
+ let distanceToCamera = distanceToCameraOption * CONSTANTS_CameraUtility.DistanceScaleForFullBody;
58555
+ if (autoZoom) {
58556
+ const [minExtentWithAccessories, maxExtentWithAccessories] = calculateModelExtents(character, characterPivotToAuxiliaryCFrame);
58557
+ const dc2 = Math.max(maxExtentWithAccessories.X - minExtentWithAccessories.X, maxExtentWithAccessories.Y - minExtentWithAccessories.Y) * CONSTANTS_CameraUtility.DefaultBodyMarginScale / 2 / tanAlpha;
58558
+ distanceToCamera = Math.max(dc1, dc1Option) * Math.max(Math.min(dc2 / Math.max(dc1, dc1Option), 1.5), 1.1);
58559
+ }
58560
+ const relativePositionToCamera = new Vector3().fromVec3(multiply(characterInitialLookVector, [distanceToCamera, distanceToCamera, distanceToCamera]));
58561
+ return getCameraCFrame(characterGoldenRatioPivotTo, relativePositionToCamera);
58562
+ }
58563
+ function getHeadshotCameraCFrame(character, applyEmote, isFallbackEmoteApplied, fieldOfViewDeg, cameraOptionsOverride) {
58564
+ const fovAngle = fieldOfViewDeg || 30;
58565
+ if (applyEmote) {
58566
+ applyEmote();
58567
+ }
58568
+ const characterHead = character.FindFirstChild("Head");
58569
+ if (!characterHead) {
58570
+ return;
58571
+ }
58572
+ let targetCFrame = characterHead.Prop("CFrame");
58573
+ const faceFrontAttachment = characterHead.FindFirstChild("FaceFrontAttachment");
58574
+ if (faceFrontAttachment) {
58575
+ const faceFrontAttachmentW = faceFrontAttachment.w;
58576
+ if (faceFrontAttachmentW) {
58577
+ targetCFrame = faceFrontAttachmentW.getWorldCFrame();
58578
+ }
58579
+ }
58580
+ const headTargetCFrame = calculateTargetCFrame(targetCFrame);
58581
+ const [minHeadExtent, maxHeadExtent] = calculateHeadExtents(character, headTargetCFrame);
58582
+ const camera = createThumbnailCamera();
58583
+ const cameraOptions = {
58584
+ extentScale: FIntCameraPresetHeadshotExtentScaleHundredths / 100,
58585
+ maxExtent: maxHeadExtent,
58586
+ minExtent: minHeadExtent,
58587
+ optCameraXRot: CONSTANTS_CameraUtility.XRotForCloseup,
58588
+ optFieldOfView: fovAngle,
58589
+ targetCFrame: headTargetCFrame
58590
+ };
58591
+ Object.assign(cameraOptions, cameraOptionsOverride);
58592
+ setupCamera(camera, cameraOptions);
58593
+ return camera;
58594
+ }
58595
+ function getAvatarCameraCFrame(character, applyEmote, isFallbackEmoteApplied, fieldOfViewDeg, cameraOptionsOverride) {
58596
+ const fovAngle = fieldOfViewDeg || 30;
58597
+ if (applyEmote) {
58598
+ applyEmote();
58599
+ }
58600
+ const characterHead = character.FindFirstChild("Head");
58601
+ if (!characterHead) {
58602
+ return;
58603
+ }
58604
+ let targetCFrame = characterHead.Prop("CFrame");
58605
+ const faceFrontAttachment = characterHead.FindFirstChild("FaceFrontAttachment");
58606
+ if (faceFrontAttachment) {
58607
+ const faceFrontAttachmentW = faceFrontAttachment.w;
58608
+ if (faceFrontAttachmentW) {
58609
+ targetCFrame = faceFrontAttachmentW.getWorldCFrame();
58610
+ }
58611
+ }
58612
+ const torsoCFrame = getCharacterTorsoCFrame(character);
58613
+ targetCFrame.Position = torsoCFrame.Position;
58614
+ const headTargetCFrame = calculateTargetCFrame(targetCFrame);
58615
+ const [minHeadExtent, maxHeadExtent] = calculateModelExtents(character, headTargetCFrame);
58616
+ const camera = createThumbnailCamera();
58617
+ const cameraOptions = {
58618
+ extentScale: FIntCameraPresetHeadshotExtentScaleHundredths / 100,
58619
+ maxExtent: maxHeadExtent,
58620
+ minExtent: minHeadExtent,
58621
+ optCameraXRot: CONSTANTS_CameraUtility.XRotForFullBody,
58622
+ optFieldOfView: fovAngle,
58623
+ targetCFrame: headTargetCFrame
58624
+ };
58625
+ Object.assign(cameraOptions, cameraOptionsOverride);
58626
+ setupCamera(camera, cameraOptions);
58627
+ return camera;
58628
+ }
58629
+ function getCorners(cframe, size) {
58630
+ const halfX = size.X / 2;
58631
+ const halfY = size.Y / 2;
58632
+ const halfZ = size.Z / 2;
58633
+ return [
58634
+ cframe.multiply(new CFrame(halfX, halfY, halfZ)),
58635
+ cframe.multiply(new CFrame(halfX, halfY, -halfZ)),
58636
+ cframe.multiply(new CFrame(-halfX, halfY, halfZ)),
58637
+ cframe.multiply(new CFrame(-halfX, halfY, -halfZ)),
58638
+ cframe.multiply(new CFrame(halfX, -halfY, halfZ)),
58639
+ cframe.multiply(new CFrame(halfX, -halfY, -halfZ)),
58640
+ cframe.multiply(new CFrame(-halfX, -halfY, halfZ)),
58641
+ cframe.multiply(new CFrame(-halfX, -halfY, -halfZ))
58642
+ ];
58643
+ }
58644
+ function getLower(a, b) {
58645
+ return new Vector3(
58646
+ a.X < b.X ? a.X : b.X,
58647
+ a.Y < b.Y ? a.Y : b.Y,
58648
+ a.Z < b.Z ? a.Z : b.Z
58649
+ );
58650
+ }
58651
+ function getHigher(a, b) {
58652
+ return new Vector3(
58653
+ a.X > b.X ? a.X : b.X,
58654
+ a.Y > b.Y ? a.Y : b.Y,
58655
+ a.Z > b.Z ? a.Z : b.Z
58656
+ );
58657
+ }
58658
+ function getExtentsForParts(parts, includeTransform) {
58659
+ let lowerExtents = new Vector3(0, 0, 0);
58660
+ let higherExtents = new Vector3(0, 0, 0);
58661
+ for (const child of parts) {
58662
+ if (child.createWrapper()?.IsA("BasePart")) {
58663
+ const cframe = traverseRigCFrame(child, includeTransform, true);
58664
+ const size = child.Prop("Size");
58665
+ const corners = getCorners(cframe, size);
58666
+ for (const corner of corners) {
58667
+ lowerExtents = getLower(lowerExtents, new Vector3().fromVec3(corner.Position));
58668
+ higherExtents = getHigher(higherExtents, new Vector3().fromVec3(corner.Position));
58669
+ }
58670
+ }
58671
+ }
58672
+ return [lowerExtents, higherExtents];
58673
+ }
58674
+ function getExtents(cframe, parts) {
58675
+ const inverseCF = cframe.inverse();
58676
+ let lowerExtents = new Vector3(0, 0, 0);
58677
+ let higherExtents = new Vector3(0, 0, 0);
58678
+ for (const child of parts) {
58679
+ if (child.createWrapper()?.IsA("BasePart")) {
58680
+ const partCF = child.Prop("CFrame");
58681
+ const partSize = child.Prop("Size");
58682
+ const corners = getCorners(inverseCF.multiply(partCF), partSize);
58683
+ for (const corner of corners) {
58684
+ lowerExtents = getLower(lowerExtents, new Vector3().fromVec3(corner.Position));
58685
+ higherExtents = getHigher(higherExtents, new Vector3().fromVec3(corner.Position));
58686
+ }
58687
+ }
58688
+ }
58689
+ return [lowerExtents, higherExtents];
58690
+ }
58691
+ function getExtentsWorld(rig) {
58692
+ const rigParts = [];
58693
+ for (const child of rig.GetDescendants()) {
58694
+ if (child.createWrapper()?.IsA("BasePart")) {
58695
+ rigParts.push(child);
58696
+ }
58697
+ }
58698
+ const extents = getExtents(new CFrame(), rigParts);
58699
+ return extents;
58700
+ }
58701
+ function getExtentsCenter(extents) {
58702
+ return extents[1].minus(extents[0]).divide(new Vector3(2, 2, 2)).add(extents[0]);
58703
+ }
58704
+ function zoomExtents(cameraCFrame, modelCFrame, modelSize, targetFOV, distanceScale, sizeType = "calculate") {
58705
+ let largestSize = Math.max(modelSize.X, modelSize.Y, modelSize.Z);
58706
+ if (sizeType === "calculate") {
58707
+ largestSize = modelSize.magnitude() / 2 / Math.sin(rad(targetFOV / 2));
58708
+ }
58709
+ const fovMultiplier = sizeType === "largestAxis" ? 70 / targetFOV : 1;
58710
+ const lookDir = multiply(normalize(minus(cameraCFrame.Position, modelCFrame.Position)), [distanceScale, distanceScale, distanceScale]);
58711
+ cameraCFrame.Position = add(modelCFrame.Position, multiply(multiply(lookDir, [largestSize, largestSize, largestSize]), [fovMultiplier, fovMultiplier, fovMultiplier]));
58712
+ }
58713
+ function getCameraOffset(fov2, extentsSize) {
58714
+ const halfSize = extentsSize.magnitude() / 2;
58715
+ const fovDivisor = Math.tan(rad(fov2 / 2));
58716
+ return halfSize / fovDivisor;
58717
+ }
58718
+ function zoomToExtents(cameraCFrame, modelCFrame, modelSize, fov2 = 70) {
58719
+ const cameraOffset = getCameraOffset(fov2, modelSize);
58720
+ const cameraRotation = new CFrame();
58721
+ cameraRotation.Orientation = cameraCFrame.Orientation;
58722
+ const instancePosition = modelCFrame.Position;
58723
+ cameraCFrame.Position = add(instancePosition, multiply(minus([0, 0, 0], cameraRotation.lookVector()), [cameraOffset, cameraOffset, cameraOffset]));
58724
+ }
58725
+ function getHeadExtents(rig) {
58726
+ const head = rig.FindFirstChild("Head");
58727
+ if (!head) return;
58728
+ const headParts = [];
58729
+ for (const child of rig.GetDescendants()) {
58730
+ if (child === head) {
58731
+ headParts.push(head);
58732
+ } else {
58733
+ const weld = child.FindFirstChildOfClass("Weld");
58734
+ if (weld && child.parent && child.parent.className === "Accessory") {
58735
+ if (weld.Prop("Part0") === head || weld.Prop("Part1") === head) {
58736
+ headParts.push(child);
58737
+ }
58738
+ }
58739
+ }
58740
+ }
58741
+ const extents = getExtents(head.Prop("CFrame"), headParts);
58742
+ return extents;
58743
+ }
58744
+ function getCameraCFrameForHeadshotCustomized(rig, fov2, yRot, distance2) {
58745
+ const camera = getHeadshotCameraCFrame(rig, void 0, void 0, fov2, {
58746
+ optCameraYRot: yRot,
58747
+ optCameraDistanceScale: distance2,
58748
+ extentScale: 1.1
58749
+ });
58750
+ if (camera) {
58751
+ const cameraCF = camera.Prop("CFrame");
58752
+ camera.Destroy();
58753
+ return cameraCF;
58754
+ }
58755
+ }
58756
+ function getCameraCFrameForAvatarCustomized(rig, fov2, yRot) {
58757
+ const camera = getAvatarCameraCFrame(rig, void 0, void 0, fov2, {
58758
+ optCameraYRot: yRot,
58759
+ optCameraDistanceScale: 1,
58760
+ extentScale: 1.1
58761
+ });
58762
+ if (camera) {
58763
+ const cameraCF = camera.Prop("CFrame");
58764
+ camera.Destroy();
58765
+ return cameraCF;
58766
+ }
58767
+ }
58768
+ function getCameraCFrameForAvatarNonCustomized(rig) {
58769
+ const thumbnailCamera = rig.FindFirstChildOfClass("Camera");
58770
+ if (thumbnailCamera) return thumbnailCamera.PropOrDefault("CFrame", new CFrame());
58771
+ let rootPart = rig.PropOrDefault("PrimaryPart", void 0);
58772
+ if (!rootPart) rootPart = rig.FindFirstChildOfClass("Part");
58773
+ if (!rootPart) rootPart = rig.FindFirstChildOfClass("MeshPart");
58774
+ if (!rootPart) return;
58775
+ const rootPartCF = rootPart.PropOrDefault("CFrame", new CFrame()).clone();
58776
+ const worldExtents = getExtentsWorld(rig);
58777
+ if (!worldExtents) return;
58778
+ const extentsSize = worldExtents[1].minus(worldExtents[0]);
58779
+ rootPartCF.Position = getExtentsCenter(worldExtents).toVec3();
58780
+ let lookVector = rootPartCF.lookVector();
58781
+ if (Math.abs(lookVector[1]) > 0.95) {
58782
+ lookVector = [0, 0, -1];
58783
+ } else {
58784
+ lookVector[1] = 0;
58785
+ lookVector = normalize(lookVector);
58786
+ }
58787
+ let lookCF = CFrame.lookAt([0, 0, 0], lookVector);
58788
+ lookCF = lookCF.multiply(CFrame.fromEulerAngles(25 * Math.PI / 180, 27.5 * Math.PI / 180, 0, "ZXY"));
58789
+ lookVector = lookCF.lookVector();
58790
+ lookCF.Position = add(rootPartCF.Position, multiply([10, 10, 10], lookVector));
58791
+ lookCF = CFrame.lookAt(lookCF.Position, rootPartCF.Position);
58792
+ const cameraCF = lookCF.clone();
58793
+ zoomExtents(cameraCF, rootPartCF, extentsSize, 70, 1);
58794
+ return cameraCF;
58795
+ }
58117
58796
  class BackgroundRenderer {
58118
58797
  auth;
58119
58798
  avatarCyclorama;
@@ -58318,7 +58997,7 @@ class OutfitRenderer {
58318
58997
  doCameraUpdate = false;
58319
58998
  /**Does camera update every frame */
58320
58999
  doAddInstance = true;
58321
- /**If outfitRenderer should call RBXRenderer.addInstance() */
59000
+ /**If outfitRenderer should call RBXRenderer.addInstance(), setting this to false will make OutfitRenderer return success early */
58322
59001
  forceAnimationLoop = true;
58323
59002
  /**If future loaded animations should be set to loop */
58324
59003
  backgroundRenderer;
@@ -58360,6 +59039,16 @@ class OutfitRenderer {
58360
59039
  * @returns void
58361
59040
  */
58362
59041
  onRenderError = new Event();
59042
+ get humanoid() {
59043
+ return this.currentRig?.FindFirstChildOfClass("Humanoid");
59044
+ }
59045
+ get animator() {
59046
+ return this.humanoid?.FindFirstChildOfClass("Animator");
59047
+ }
59048
+ get animatorW() {
59049
+ const animator = this.animator;
59050
+ if (animator) return new AnimatorWrapper(animator);
59051
+ }
58363
59052
  /**
58364
59053
  * Creates a new OutfitRenderer which makes it easy to render outfits
58365
59054
  * @param auth The authentication object, you should have one you use for everything
@@ -58551,9 +59240,30 @@ class OutfitRenderer {
58551
59240
  this.animationInterval = void 0;
58552
59241
  }
58553
59242
  }
59243
+ /**
59244
+ * Checks if the provided animation set is loaded
59245
+ * @param name The name of the animation, for example "idle", "run", but NOT "emote.1234" or "id.1234" as they are not in the animation set
59246
+ * @returns If the animation is loaded
59247
+ */
59248
+ hasAnimationSetAnimation(name) {
59249
+ if (this.currentRig) {
59250
+ const humanoid = this.currentRig.FindFirstChildOfClass("Humanoid");
59251
+ if (humanoid) {
59252
+ const animator = humanoid.FindFirstChildOfClass("Animator");
59253
+ if (animator) {
59254
+ const animatorW = new AnimatorWrapper(animator);
59255
+ const entries = animatorW.data.animationSet[name];
59256
+ if (entries) {
59257
+ return entries.length > 0;
59258
+ }
59259
+ }
59260
+ }
59261
+ }
59262
+ return false;
59263
+ }
58554
59264
  /**
58555
59265
  * Sets the current animation being played
58556
- * @param name The name of the animation, for example "idle", "run", "emote.1234" or "anim.1234"
59266
+ * @param name The name of the animation, for example "idle", "run", "emote.1234" or "id.1234"
58557
59267
  * @returns If the animation started playing, it may start playing later if it has been queued despite returning false
58558
59268
  */
58559
59269
  setMainAnimation(name) {
@@ -58622,16 +59332,28 @@ class OutfitRenderer {
58622
59332
  }
58623
59333
  async _prepareForThumbnail() {
58624
59334
  this.doAddInstance = false;
59335
+ this.backgroundRenderer.affectSceneAppearance = false;
59336
+ this.backgroundRenderer.cameraAffectsTransparency = false;
58625
59337
  if (this.outfit.playerAvatarType === AvatarType.R6) this.deltaTimeMultiplier = 0;
58626
59338
  await new Promise((resolve) => {
58627
59339
  this.onSuccess.Connect(() => {
59340
+ const animatorW = this.animatorW;
59341
+ if (animatorW) {
59342
+ animatorW.data.forceTransitionTime = 0;
59343
+ }
58628
59344
  if (!this.outfit.containsAssetType("Gear")) {
58629
59345
  if (this.outfit.playerAvatarType === AvatarType.R15) {
58630
- this.setMainAnimation("pose").then(() => {
58631
- resolve(void 0);
58632
- });
59346
+ if (this.hasAnimationSetAnimation("pose")) {
59347
+ this.setMainAnimation("pose").then(() => {
59348
+ resolve(void 0);
59349
+ });
59350
+ } else {
59351
+ this.setMainAnimation("idle:0").then(() => {
59352
+ resolve(void 0);
59353
+ });
59354
+ }
58633
59355
  } else {
58634
- this.setMainAnimation("idle").then(() => {
59356
+ this.setMainAnimation("idle:0").then(() => {
58635
59357
  resolve(void 0);
58636
59358
  });
58637
59359
  }
@@ -58642,8 +59364,10 @@ class OutfitRenderer {
58642
59364
  }
58643
59365
  });
58644
59366
  });
58645
- this.animateOnce(!this.outfit.containsAssetType("Gear") && this.outfit.playerAvatarType === AvatarType.R6 ? 0 : 1);
59367
+ this.animateOnce(0);
59368
+ if (this.outfit.playerAvatarType !== AvatarType.R6 && this.animatorW?.data.currentAnimation === "idle") this.animateOnce((this.animatorW?.data.currentAnimationTrack?.length || 0) / 2);
58646
59369
  if (this.currentRig) RBXRenderer.addInstance(this.currentRig, this.auth, this.renderScene);
59370
+ this.hasFiredFullyRendered = false;
58647
59371
  await new Promise((resolve) => {
58648
59372
  const connection = this.onRenderSuccess.Connect(() => {
58649
59373
  resolve(void 0);
@@ -58727,102 +59451,6 @@ async function modelThumbnailClick(renderScene, format, options) {
58727
59451
  binary: format === "glb"
58728
59452
  });
58729
59453
  }
58730
- function getCorners(cframe, size) {
58731
- const halfX = size.X / 2;
58732
- const halfY = size.Y / 2;
58733
- const halfZ = size.Z / 2;
58734
- return [
58735
- cframe.multiply(new CFrame(halfX, halfY, halfZ)),
58736
- cframe.multiply(new CFrame(halfX, halfY, -halfZ)),
58737
- cframe.multiply(new CFrame(-halfX, halfY, halfZ)),
58738
- cframe.multiply(new CFrame(-halfX, halfY, -halfZ)),
58739
- cframe.multiply(new CFrame(halfX, -halfY, halfZ)),
58740
- cframe.multiply(new CFrame(halfX, -halfY, -halfZ)),
58741
- cframe.multiply(new CFrame(-halfX, -halfY, halfZ)),
58742
- cframe.multiply(new CFrame(-halfX, -halfY, -halfZ))
58743
- ];
58744
- }
58745
- function getLower(a, b) {
58746
- return new Vector3(
58747
- a.X < b.X ? a.X : b.X,
58748
- a.Y < b.Y ? a.Y : b.Y,
58749
- a.Z < b.Z ? a.Z : b.Z
58750
- );
58751
- }
58752
- function getHigher(a, b) {
58753
- return new Vector3(
58754
- a.X > b.X ? a.X : b.X,
58755
- a.Y > b.Y ? a.Y : b.Y,
58756
- a.Z > b.Z ? a.Z : b.Z
58757
- );
58758
- }
58759
- function getExtentsForParts(parts, includeTransform) {
58760
- let lowerExtents = new Vector3(0, 0, 0);
58761
- let higherExtents = new Vector3(0, 0, 0);
58762
- for (const child of parts) {
58763
- if (child.createWrapper()?.IsA("BasePart")) {
58764
- const cframe = traverseRigCFrame(child, includeTransform, true);
58765
- const size = child.Prop("Size");
58766
- const corners = getCorners(cframe, size);
58767
- for (const corner of corners) {
58768
- lowerExtents = getLower(lowerExtents, new Vector3().fromVec3(corner.Position));
58769
- higherExtents = getHigher(higherExtents, new Vector3().fromVec3(corner.Position));
58770
- }
58771
- }
58772
- }
58773
- return [lowerExtents, higherExtents];
58774
- }
58775
- function getExtents(cframe, parts) {
58776
- const inverseCF = cframe.inverse();
58777
- let lowerExtents = new Vector3(0, 0, 0);
58778
- let higherExtents = new Vector3(0, 0, 0);
58779
- for (const child of parts) {
58780
- if (child.createWrapper()?.IsA("BasePart")) {
58781
- const partCF = child.Prop("CFrame");
58782
- const partSize = child.Prop("Size");
58783
- const corners = getCorners(inverseCF.multiply(partCF), partSize);
58784
- for (const corner of corners) {
58785
- lowerExtents = getLower(lowerExtents, new Vector3().fromVec3(corner.Position));
58786
- higherExtents = getHigher(higherExtents, new Vector3().fromVec3(corner.Position));
58787
- }
58788
- }
58789
- }
58790
- return [lowerExtents, higherExtents];
58791
- }
58792
- function getExtentsWorld(rig) {
58793
- const rigParts = [];
58794
- for (const child of rig.GetDescendants()) {
58795
- if (child.createWrapper()?.IsA("BasePart")) {
58796
- rigParts.push(child);
58797
- }
58798
- }
58799
- const extents = getExtents(new CFrame(), rigParts);
58800
- return extents;
58801
- }
58802
- function getExtentsCenter(extents) {
58803
- return extents[1].minus(extents[0]).divide(new Vector3(2, 2, 2)).add(extents[0]);
58804
- }
58805
- function zoomExtents(cameraCFrame, modelCFrame, modelSize, targetFOV, distanceScale, sizeType = "calculate") {
58806
- let largestSize = Math.max(modelSize.X, modelSize.Y, modelSize.Z);
58807
- if (sizeType === "calculate") {
58808
- largestSize = modelSize.magnitude() / 2 / Math.sin(rad(targetFOV / 2));
58809
- }
58810
- const fovMultiplier = sizeType === "largestAxis" ? 70 / targetFOV : 1;
58811
- const lookDir = multiply(normalize(minus(cameraCFrame.Position, modelCFrame.Position)), [distanceScale, distanceScale, distanceScale]);
58812
- cameraCFrame.Position = add(modelCFrame.Position, multiply(multiply(lookDir, [largestSize, largestSize, largestSize]), [fovMultiplier, fovMultiplier, fovMultiplier]));
58813
- }
58814
- function getCameraOffset(fov2, extentsSize) {
58815
- const halfSize = extentsSize.magnitude() / 2;
58816
- const fovDivisor = Math.tan(rad(fov2 / 2));
58817
- return halfSize / fovDivisor;
58818
- }
58819
- function zoomToExtents(cameraCFrame, modelCFrame, modelSize, fov2 = 70) {
58820
- const cameraOffset = getCameraOffset(fov2, modelSize);
58821
- const cameraRotation = new CFrame();
58822
- cameraRotation.Orientation = cameraCFrame.Orientation;
58823
- const instancePosition = modelCFrame.Position;
58824
- cameraCFrame.Position = add(instancePosition, multiply(minus([0, 0, 0], cameraRotation.lookVector()), [cameraOffset, cameraOffset, cameraOffset]));
58825
- }
58826
59454
  function getThumbnailCameraCFrame(model, fov2, forceAngle) {
58827
59455
  const thumbnailCamera = model.FindFirstChildOfClass("Camera");
58828
59456
  if (thumbnailCamera) return thumbnailCamera.PropOrDefault("CFrame", new CFrame());
@@ -58869,7 +59497,7 @@ function setupThumbnailScene(renderScene) {
58869
59497
  if (renderScene.shadowPlane) renderScene.scene.remove(renderScene.shadowPlane);
58870
59498
  renderScene.scene.background = null;
58871
59499
  }
58872
- async function generateOutfitThumbnail(auth, outfit, size = [150, 150], type = "png", quality = 1, gltfAutoDownload = false, includeAnimations = false, renderSceneParam) {
59500
+ async function generateOutfitThumbnail(auth, outfit, size = [150, 150], type = "png", quality = 1, gltfAutoDownload = false, includeAnimations = false, renderSceneParam, thumbnailCameraType = "default") {
58873
59501
  const renderScene = renderSceneParam || RBXRenderer.addScene();
58874
59502
  if (renderScene !== renderSceneParam) {
58875
59503
  setupThumbnailScene(renderScene);
@@ -58882,9 +59510,25 @@ async function generateOutfitThumbnail(auth, outfit, size = [150, 150], type = "
58882
59510
  return void 0;
58883
59511
  }
58884
59512
  if (outfitRenderer.currentRig) {
58885
- const cameraCFrame = getThumbnailCameraCFrame(outfitRenderer.currentRig, renderScene.camera.fov);
59513
+ let cameraCFrame = new CFrame();
59514
+ switch (thumbnailCameraType) {
59515
+ case "default":
59516
+ cameraCFrame = getThumbnailCameraCFrame(outfitRenderer.currentRig, renderScene.camera.fov) || cameraCFrame;
59517
+ break;
59518
+ case "avatarHeadshot":
59519
+ cameraCFrame = getCameraCFrameForHeadshotCustomized(outfitRenderer.currentRig, 28, 0, 1) || cameraCFrame;
59520
+ break;
59521
+ case "avatarFullbody":
59522
+ cameraCFrame = getCameraCFrameForAvatarCustomized(outfitRenderer.currentRig, 28, 0) || cameraCFrame;
59523
+ break;
59524
+ case "fullbody":
59525
+ cameraCFrame = getFullBodyCameraCFrame(outfitRenderer.currentRig) || cameraCFrame;
59526
+ break;
59527
+ }
58886
59528
  if (cameraCFrame) {
58887
59529
  RBXRenderer.setCameraCFrame(cameraCFrame, renderScene);
59530
+ RBXRenderer.setCameraFov(thumbnailCameraType === "default" ? 70 : thumbnailCameraType === "fullbody" ? 56 : 28, renderScene);
59531
+ renderScene.camera.updateProjectionMatrix();
58888
59532
  }
58889
59533
  outfitRenderer.updateParticleMatrix();
58890
59534
  const result = type === "gltf" || type === "glb" ? await modelThumbnailClick(renderScene, type, {
@@ -58917,37 +59561,7 @@ async function generateOutfitModelThumbnail(auth, outfitModel, options) {
58917
59561
  includeAnimations: false
58918
59562
  };
58919
59563
  Object.assign(defaultOptions, options);
58920
- const renderScene = RBXRenderer.addScene();
58921
- setupThumbnailScene(renderScene);
58922
- if (outfitModel.background?.id) {
58923
- const avatarCycloramaRBX = await API.Asset.GetRBX("roavatar://AvatarCyclorama.rbxm");
58924
- if (avatarCycloramaRBX instanceof Response) return void 0;
58925
- const avatarCycloramaRoot = avatarCycloramaRBX.generateTree();
58926
- const avatarCyclorama = avatarCycloramaRoot.GetChildren()[0];
58927
- if (avatarCyclorama) {
58928
- const backgroundDataRBX = await API.Asset.GetRBX("rbxassetid://" + outfitModel.background.id);
58929
- if (backgroundDataRBX instanceof Response) return void 0;
58930
- const backgroundDataRoot = backgroundDataRBX.generateTree();
58931
- const backgroundData = backgroundDataRoot.GetChildren()[0];
58932
- if (backgroundData) {
58933
- if (backgroundData) {
58934
- const colorValue = backgroundData.Child("Color");
58935
- const imageIdValue = backgroundData.Child("ImageId");
58936
- if (colorValue && imageIdValue) {
58937
- const color2 = colorValue.Prop("Value");
58938
- const imageId = imageIdValue.Prop("Value");
58939
- avatarCyclorama.Child("color_mesh").setProperty("Color", color2.toColor3uint8());
58940
- avatarCyclorama.Child("texture_mesh").setProperty("TextureID", `rbxassetid://${imageId}`);
58941
- avatarCyclorama.preRender();
58942
- RBXRenderer.addInstance(avatarCyclorama, auth, renderScene);
58943
- renderScene.camera.fov = 30;
58944
- renderScene.camera.updateProjectionMatrix();
58945
- }
58946
- }
58947
- }
58948
- }
58949
- }
58950
- return generateOutfitThumbnail(auth, outfitModel.outfit, defaultOptions.size, defaultOptions.type, defaultOptions.quality, defaultOptions.gltfAutoDownload, defaultOptions.includeAnimations, renderScene);
59564
+ return generateOutfitThumbnail(auth, outfitModel, defaultOptions.size, defaultOptions.type, defaultOptions.quality, defaultOptions.gltfAutoDownload, defaultOptions.includeAnimations);
58951
59565
  }
58952
59566
  function renderToRenderTarget(width, height, renderScene) {
58953
59567
  const renderTarget = new WebGLRenderTarget(width, height, {
@@ -59030,79 +59644,6 @@ function exposeThumbnailGenerator() {
59030
59644
  globalThis.setupThumbnailScene = setupThumbnailScene;
59031
59645
  globalThis.getThumbnailCameraCFrame = getThumbnailCameraCFrame;
59032
59646
  }
59033
- function getHeadExtents(rig) {
59034
- const head = rig.FindFirstChild("Head");
59035
- if (!head) return;
59036
- const headParts = [];
59037
- for (const child of rig.GetDescendants()) {
59038
- if (child === head) {
59039
- headParts.push(head);
59040
- } else {
59041
- const weld = child.FindFirstChildOfClass("Weld");
59042
- if (weld && child.parent && child.parent.className === "Accessory") {
59043
- if (weld.Prop("Part0") === head || weld.Prop("Part1") === head) {
59044
- headParts.push(child);
59045
- }
59046
- }
59047
- }
59048
- }
59049
- const extents = getExtents(head.Prop("CFrame"), headParts);
59050
- return extents;
59051
- }
59052
- function getCameraCFrameForHeadshotCustomized(rig, fov2, yRot, distance2) {
59053
- const head = rig.FindFirstChild("Head");
59054
- if (!head) return;
59055
- const headCF = head.PropOrDefault("CFrame", new CFrame());
59056
- const headLocalExtents = getHeadExtents(rig);
59057
- if (!headLocalExtents) return;
59058
- const headCenterPosLocal = headLocalExtents[0].add(headLocalExtents[1].minus(headLocalExtents[0]).divide(new Vector3(2, 2, 2)));
59059
- const headCenterPos = new Vector3().fromVec3(headCF.multiply(new CFrame(...headCenterPosLocal.toVec3())).Position);
59060
- const headCenterCF = new CFrame(...headCenterPos.toVec3());
59061
- let lookVector = headCF.lookVector();
59062
- if (Math.abs(lookVector[1]) > 0.95) {
59063
- lookVector = [0, 0, -1];
59064
- } else {
59065
- lookVector[1] = 0;
59066
- lookVector = normalize(lookVector);
59067
- }
59068
- let lookCF = CFrame.lookAt([0, 0, 0], lookVector);
59069
- lookCF = lookCF.multiply(CFrame.fromEulerAngles(0, rad(yRot), 0, "ZXY"));
59070
- lookVector = lookCF.lookVector();
59071
- const fovMultiplier = 70 / fov2;
59072
- lookCF.Position = add(headCenterCF.Position, multiply(multiply([10, 10, 10], lookVector), [fovMultiplier, fovMultiplier, fovMultiplier]));
59073
- lookCF = CFrame.lookAt(lookCF.Position, headCenterCF.Position);
59074
- const cameraCF = lookCF.clone();
59075
- zoomExtents(cameraCF, headCenterCF, headLocalExtents[1].minus(headLocalExtents[0]), fov2, distance2, "largestAxis");
59076
- return cameraCF;
59077
- }
59078
- function getCameraCFrameForAvatarNonCustomized(rig) {
59079
- const thumbnailCamera = rig.FindFirstChildOfClass("Camera");
59080
- if (thumbnailCamera) return thumbnailCamera.PropOrDefault("CFrame", new CFrame());
59081
- let rootPart = rig.PropOrDefault("PrimaryPart", void 0);
59082
- if (!rootPart) rootPart = rig.FindFirstChildOfClass("Part");
59083
- if (!rootPart) rootPart = rig.FindFirstChildOfClass("MeshPart");
59084
- if (!rootPart) return;
59085
- const rootPartCF = rootPart.PropOrDefault("CFrame", new CFrame()).clone();
59086
- const worldExtents = getExtentsWorld(rig);
59087
- if (!worldExtents) return;
59088
- const extentsSize = worldExtents[1].minus(worldExtents[0]);
59089
- rootPartCF.Position = getExtentsCenter(worldExtents).toVec3();
59090
- let lookVector = rootPartCF.lookVector();
59091
- if (Math.abs(lookVector[1]) > 0.95) {
59092
- lookVector = [0, 0, -1];
59093
- } else {
59094
- lookVector[1] = 0;
59095
- lookVector = normalize(lookVector);
59096
- }
59097
- let lookCF = CFrame.lookAt([0, 0, 0], lookVector);
59098
- lookCF = lookCF.multiply(CFrame.fromEulerAngles(25 * Math.PI / 180, 27.5 * Math.PI / 180, 0, "ZXY"));
59099
- lookVector = lookCF.lookVector();
59100
- lookCF.Position = add(rootPartCF.Position, multiply([10, 10, 10], lookVector));
59101
- lookCF = CFrame.lookAt(lookCF.Position, rootPartCF.Position);
59102
- const cameraCF = lookCF.clone();
59103
- zoomExtents(cameraCF, rootPartCF, extentsSize, 70, 1);
59104
- return cameraCF;
59105
- }
59106
59647
  export {
59107
59648
  API,
59108
59649
  AbbreviationToFaceControlProperty,
@@ -59138,6 +59679,7 @@ export {
59138
59679
  AttachmentWrapper,
59139
59680
  Authentication,
59140
59681
  AvatarType,
59682
+ BackgroundRenderer,
59141
59683
  BasePartWrapper,
59142
59684
  BodyColor3s,
59143
59685
  BodyColors,
@@ -59152,8 +59694,12 @@ export {
59152
59694
  BundleTypes,
59153
59695
  CACHE,
59154
59696
  CFrame,
59697
+ CONSTANTS_CameraPresetsUtility,
59698
+ CONSTANTS_CameraUtility,
59155
59699
  COREMESH,
59156
59700
  Cache,
59701
+ CameraType,
59702
+ CameraWrapper,
59157
59703
  CatalogBundleTypes,
59158
59704
  CategoryDictionary,
59159
59705
  Color3,
@@ -59217,11 +59763,14 @@ export {
59217
59763
  PartType,
59218
59764
  PartWrapper,
59219
59765
  ParticleEmitterShapeInOut,
59766
+ ParticleEmitterWrapper,
59220
59767
  ParticleFlipbookLayout,
59221
59768
  ParticleFlipbookMode,
59222
59769
  ParticleOrientation,
59223
59770
  Property,
59224
59771
  PropertyTypeInfo,
59772
+ R15BodyPartNames,
59773
+ R6BodyPartNames,
59225
59774
  RBFDeformerPatch,
59226
59775
  RBX,
59227
59776
  RBXRenderer,
@@ -59275,6 +59824,7 @@ export {
59275
59824
  browserSendMessage,
59276
59825
  buildFaceKD,
59277
59826
  buildVertKD,
59827
+ calculateBaseDistanceToCamera,
59278
59828
  calculateMagnitude3D,
59279
59829
  calculateMotor6Doffset,
59280
59830
  clamp,
@@ -59283,6 +59833,7 @@ export {
59283
59833
  cloneSearch_Payload,
59284
59834
  closestPointTriangle,
59285
59835
  createContentMap,
59836
+ createThumbnailCamera,
59286
59837
  createWeightsForMeshChunked,
59287
59838
  cross,
59288
59839
  defaultPantAssetIds,
@@ -59307,14 +59858,20 @@ export {
59307
59858
  generateOutfitModelThumbnail,
59308
59859
  generateOutfitThumbnail,
59309
59860
  generateUUIDv4,
59861
+ getAvatarCameraCFrame,
59862
+ getCameraCFrame,
59863
+ getCameraCFrameForAvatarCustomized,
59310
59864
  getCameraCFrameForAvatarNonCustomized,
59311
59865
  getCameraCFrameForHeadshotCustomized,
59866
+ getCharacterTorsoCFrame,
59312
59867
  getDistIndexArray,
59313
59868
  getExtents,
59314
59869
  getExtentsCenter,
59315
59870
  getExtentsForParts,
59316
59871
  getExtentsWorld,
59872
+ getFullBodyCameraCFrame,
59317
59873
  getHeadExtents,
59874
+ getHeadshotCameraCFrame,
59318
59875
  getOffsetArray,
59319
59876
  getOriginalAttachmentOrientation,
59320
59877
  getOriginalAttachmentPosition,
@@ -59369,6 +59926,10 @@ export {
59369
59926
  rotationMatrixToEulerAngles,
59370
59927
  saveByteArray,
59371
59928
  scaleMesh,
59929
+ setupAccessoryCamera,
59930
+ setupBodyPartCamera,
59931
+ setupCamera,
59932
+ setupHeadCamera,
59372
59933
  setupThumbnailScene,
59373
59934
  snapToNumber,
59374
59935
  specialClamp,