roavatar-renderer 1.6.1 → 1.6.3

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
@@ -695,9 +695,11 @@ export declare class BackgroundRenderer {
695
695
  hasNewUpdate: boolean;
696
696
  affectSceneAppearance: boolean;
697
697
  cameraAffectsTransparency: boolean;
698
+ cameraAffectsRotation: boolean;
698
699
  lastFrameTime: number;
699
700
  animationInterval?: NodeJS.Timeout;
700
701
  animationFPS: number;
702
+ originalPartCFrames: Map<Instance, CFrame>;
701
703
  renderScene: RBXRendererScene;
702
704
  private _renderSceneCompiledConnection?;
703
705
  private _renderSceneFailedConnection?;
@@ -733,6 +735,7 @@ export declare class BackgroundRenderer {
733
735
  _loadBackgroundData(): Promise<void>;
734
736
  _loadAvatarCyclorama(): Promise<void>;
735
737
  _applyBackgroundData(): void;
738
+ _applyBackgroundRotation(): void;
736
739
  /**
737
740
  * Starts updating the animation of the background per frame
738
741
  */
@@ -3671,6 +3674,12 @@ declare class RenderDesc extends DisposableDesc {
3671
3674
 
3672
3675
  export declare function replaceBodyPart(rig: Instance, child: Instance): void;
3673
3676
 
3677
+ /**@category DataModelEnum */
3678
+ export declare const ResamplerMode: {
3679
+ Default: number;
3680
+ Pixelated: number;
3681
+ };
3682
+
3674
3683
  export declare function rgbToHex(r: number, g: number, b: number): string;
3675
3684
 
3676
3685
  export declare type RigData = {
package/dist/index.js CHANGED
@@ -30279,6 +30279,10 @@ class RBXSimpleView {
30279
30279
  }
30280
30280
  const magic = "<roblox!";
30281
30281
  const xmlMagic = "<roblox ";
30282
+ const ResamplerMode = {
30283
+ "Default": 0,
30284
+ "Pixelated": 1
30285
+ };
30282
30286
  const CameraType = {
30283
30287
  "Fixed": 0,
30284
30288
  "Attach": 1,
@@ -33167,9 +33171,7 @@ class CFrame {
33167
33171
  this.Position = [x, y, z];
33168
33172
  }
33169
33173
  static Angles(x, y, z) {
33170
- const cf = new CFrame();
33171
- cf.Orientation = [x, y, z];
33172
- return cf;
33174
+ return CFrame.fromEulerAngles(x, y, z, "XYZ");
33173
33175
  }
33174
33176
  clone() {
33175
33177
  const cloneCF = new CFrame(this.Position[0], this.Position[1], this.Position[2]);
@@ -38944,6 +38946,7 @@ function createContentMap() {
38944
38946
  ContentMap.set("roavatar://AvatarCyclorama.rbxm", "79116945688799");
38945
38947
  }
38946
38948
  let CachedRoAvatarData = void 0;
38949
+ const thumbnailTypesWithBackground = ["Outfit", "Avatar", "AvatarHeadshot"];
38947
38950
  let ThumbnailsToBatch = [];
38948
38951
  const API = {
38949
38952
  "Misc": {
@@ -39492,7 +39495,7 @@ const API = {
39492
39495
  try {
39493
39496
  await mesh.fromBuffer(buffer2);
39494
39497
  if (FLAGS.ENABLE_API_CACHE && FLAGS.ENABLE_API_MESH_CACHE) {
39495
- CACHE.Mesh.set(cacheStr, mesh.clone());
39498
+ CACHE.Mesh.set(cacheStr, readOnly ? mesh : mesh.clone());
39496
39499
  }
39497
39500
  return mesh;
39498
39501
  } catch {
@@ -39717,7 +39720,7 @@ const API = {
39717
39720
  id,
39718
39721
  size,
39719
39722
  headShape,
39720
- includeBackground: type === "Outfit"
39723
+ includeBackground: thumbnailTypesWithBackground.includes(type)
39721
39724
  };
39722
39725
  const cachedThumbnail = CACHE.Thumbnails.get(requestIdFromThumbnailInfo(thisThumbnailInfo));
39723
39726
  if (CACHE.Thumbnails.has(requestIdFromThumbnailInfo(thisThumbnailInfo))) {
@@ -39742,7 +39745,7 @@ const API = {
39742
39745
  attempt: 0,
39743
39746
  lastTryTimestamp: 0,
39744
39747
  headShape,
39745
- includeBackground: type === "Outfit"
39748
+ includeBackground: thumbnailTypesWithBackground.includes(type)
39746
39749
  });
39747
39750
  });
39748
39751
  },
@@ -39752,7 +39755,7 @@ const API = {
39752
39755
  id,
39753
39756
  size,
39754
39757
  headShape,
39755
- includeBackground: type === "Outfit"
39758
+ includeBackground: thumbnailTypesWithBackground.includes(type)
39756
39759
  };
39757
39760
  CACHE.Thumbnails.delete(requestIdFromThumbnailInfo(thisThumbnailInfo));
39758
39761
  },
@@ -46469,6 +46472,7 @@ class MaterialDesc {
46469
46472
  transparency = 0;
46470
46473
  doubleSided = false;
46471
46474
  visible = true;
46475
+ resampleMode = ResamplerMode.Default;
46472
46476
  emissiveStrength = 1;
46473
46477
  emissiveTint = new Color3(1, 1, 1);
46474
46478
  bodyPart;
@@ -46481,7 +46485,7 @@ class MaterialDesc {
46481
46485
  result;
46482
46486
  isSame(other) {
46483
46487
  if (this.dirty || other.dirty) return false;
46484
- const propertiesSame = this.isDecal === other.isDecal && this.transparent === other.transparent && Math.round(this.transparency * 100) === Math.round(other.transparency * 100) && this.doubleSided === other.doubleSided && this.visible === other.visible && this.canHaveMipmaps === other.canHaveMipmaps;
46488
+ const propertiesSame = this.isDecal === other.isDecal && this.transparent === other.transparent && Math.round(this.transparency * 100) === Math.round(other.transparency * 100) && this.doubleSided === other.doubleSided && this.visible === other.visible && this.canHaveMipmaps === other.canHaveMipmaps && this.resampleMode === other.resampleMode;
46485
46489
  let layersSame = true;
46486
46490
  if (this.layers.length !== other.layers.length) {
46487
46491
  layersSame = false;
@@ -46496,7 +46500,7 @@ class MaterialDesc {
46496
46500
  }
46497
46501
  needsRegeneration(other) {
46498
46502
  if (this.dirty || other.dirty) return true;
46499
- const propertiesSame = this.isDecal === other.isDecal && this.doubleSided === other.doubleSided && this.visible === other.visible && this.canHaveMipmaps === other.canHaveMipmaps;
46503
+ const propertiesSame = this.isDecal === other.isDecal && this.doubleSided === other.doubleSided && this.visible === other.visible && this.canHaveMipmaps === other.canHaveMipmaps && this.resampleMode === other.resampleMode;
46500
46504
  let layersSame = true;
46501
46505
  if (this.layers.length !== other.layers.length) {
46502
46506
  layersSame = false;
@@ -46795,6 +46799,7 @@ class MaterialDesc {
46795
46799
  if (texture !== lineartexture) {
46796
46800
  lineartexture.dispose();
46797
46801
  }
46802
+ texture.magFilter = this.resampleMode === ResamplerMode.Default ? LinearFilter : NearestFilter;
46798
46803
  let hasTransparency = false;
46799
46804
  const rbxRenderer = RBXRenderer.getRenderer();
46800
46805
  if (!hasColorLayer && rbxRenderer || FLAGS.RENDERTARGET_TO_CANVASTEXTURE && rbxRenderer) {
@@ -46815,6 +46820,7 @@ class MaterialDesc {
46815
46820
  texture.minFilter = ogTexture.minFilter;
46816
46821
  texture.magFilter = ogTexture.magFilter;
46817
46822
  texture.generateMipmaps = ogTexture.generateMipmaps;
46823
+ ogTexture.dispose();
46818
46824
  }
46819
46825
  }
46820
46826
  if (!this.transparent) {
@@ -46880,6 +46886,7 @@ class MaterialDesc {
46880
46886
  } else {
46881
46887
  hasTransparency = false;
46882
46888
  }
46889
+ texture.magFilter = this.resampleMode === ResamplerMode.Default ? LinearFilter : NearestFilter;
46883
46890
  texture.needsUpdate = true;
46884
46891
  return [texture, hasTransparency];
46885
46892
  }
@@ -46904,6 +46911,7 @@ class MaterialDesc {
46904
46911
  texture.wrapT = RepeatWrapping;
46905
46912
  texture.colorSpace = textureType === "color" ? SRGBColorSpace : NoColorSpace;
46906
46913
  texture.generateMipmaps = this.canHaveMipmaps;
46914
+ texture.magFilter = this.resampleMode === ResamplerMode.Default ? LinearFilter : NearestFilter;
46907
46915
  texture.needsUpdate = true;
46908
46916
  return [texture, hasTransparency];
46909
46917
  }
@@ -47294,6 +47302,7 @@ class MaterialDesc {
47294
47302
  if (surfaceAppearance.Prop("AlphaMode") === AlphaMode.Transparency) {
47295
47303
  this.transparent = true;
47296
47304
  }
47305
+ this.resampleMode = surfaceAppearance.PropOrDefault("ResampleMode", this.resampleMode);
47297
47306
  affectedByHumanoid = false;
47298
47307
  }
47299
47308
  if (affectedByHumanoid && child.parent && !surfaceAppearance) {
@@ -48939,7 +48948,7 @@ class AnimatorWrapper extends InstanceWrapper {
48939
48948
  const entries = this.data.animationSet[name];
48940
48949
  if (entries && entries.length > 0) {
48941
48950
  const isSpecificSub = subAnimSpecifier !== void 0 && subAnimSpecifier >= 0;
48942
- const entry = isSpecificSub ? entries[subAnimSpecifier] : this._pickRandom(entries);
48951
+ const entry = (isSpecificSub ? entries[subAnimSpecifier] : this._pickRandom(entries)) || entries[0];
48943
48952
  if (entry) {
48944
48953
  toPlayTrack = this._getTrack(entry.id);
48945
48954
  }
@@ -49246,27 +49255,20 @@ class AnimatorWrapper extends InstanceWrapper {
49246
49255
  if (subAnimIdStr.length > 0) {
49247
49256
  const subAnimId = BigInt(API.Misc.idFromStr(subAnimIdStr));
49248
49257
  const foundAnimTrack = this.data.animationTracks.get(subAnimId);
49258
+ if (!this.data.animationSet[animName]) {
49259
+ this.data.animationSet[animName] = [];
49260
+ }
49261
+ this.data.animationSet[animName].push({
49262
+ id: `rbxassetid://${subAnimId}`,
49263
+ weight: subWeight
49264
+ });
49249
49265
  if (foundAnimTrack) {
49250
49266
  if (forceLoop) {
49251
49267
  foundAnimTrack.looped = true;
49252
49268
  }
49253
- if (!this.data.animationSet[animName]) {
49254
- this.data.animationSet[animName] = [];
49255
- }
49256
- this.data.animationSet[animName].push({
49257
- id: `rbxassetid://${subAnimId}`,
49258
- weight: subWeight
49259
- });
49260
49269
  } else {
49261
49270
  promises.push(new Promise((resolve) => {
49262
49271
  this.loadAnimation(subAnimId, forceLoop).then((result) => {
49263
- if (!this.data.animationSet[animName]) {
49264
- this.data.animationSet[animName] = [];
49265
- }
49266
- this.data.animationSet[animName].push({
49267
- id: `rbxassetid://${subAnimId}`,
49268
- weight: subWeight
49269
- });
49270
49272
  resolve(result instanceof Response ? result : void 0);
49271
49273
  });
49272
49274
  }));
@@ -49330,7 +49332,7 @@ class AnimatorWrapper extends InstanceWrapper {
49330
49332
  }
49331
49333
  switch (type) {
49332
49334
  case "main":
49333
- if (this.data.currentAnimation !== name) {
49335
+ if (this.data.currentAnimation !== name || subAnimSpecifier !== -1) {
49334
49336
  if (!name.startsWith("emote.") || staticFacialAnimation) {
49335
49337
  this.playAnimation("mood", "mood");
49336
49338
  } else {
@@ -50876,18 +50878,13 @@ class HumanoidDescriptionWrapper extends InstanceWrapper {
50876
50878
  if (animationSetEntries) {
50877
50879
  for (const subAnim of animationSetEntries) {
50878
50880
  const subAnimId = BigInt(API.Misc.idFromStr(subAnim.id));
50881
+ animatorW.data.animationSet[animName].push(subAnim);
50879
50882
  if (!animatorW.data.animationTracks.has(subAnimId)) {
50880
50883
  promises.push(new Promise((resolve) => {
50881
50884
  animatorW.loadAnimation(subAnimId, true).then((result) => {
50882
- if (!animatorW.data.animationSet[animName]) {
50883
- animatorW.data.animationSet[animName] = [];
50884
- }
50885
- animatorW.data.animationSet[animName].push(subAnim);
50886
50885
  resolve(result instanceof Response ? result : void 0);
50887
50886
  });
50888
50887
  }));
50889
- } else {
50890
- animatorW.data.animationSet[animName].push(subAnim);
50891
50888
  }
50892
50889
  }
50893
50890
  } else {
@@ -57702,7 +57699,7 @@ class RBXRenderer {
57702
57699
  if (RBXRenderer.renderer) RBXRenderer.renderer.setClearColor(new Color(0, 0, 0), 0);
57703
57700
  RBXRenderer.renderer.outputColorSpace = SRGBColorSpace;
57704
57701
  RBXRenderer.renderer.shadowMap.enabled = true;
57705
- RBXRenderer.renderer.shadowMap.type = PCFSoftShadowMap;
57702
+ RBXRenderer.renderer.shadowMap.type = PCFShadowMap;
57706
57703
  RBXRenderer.renderer.setPixelRatio(globalThis.devicePixelRatio * 1 || 1);
57707
57704
  RBXRenderer.renderer.setSize(...RBXRenderer.resolution);
57708
57705
  if (FLAGS.USE_POST_PROCESSING && FLAGS.POST_PROCESSING_IS_DOUBLE_SIZE) {
@@ -57798,7 +57795,11 @@ class RBXRenderer {
57798
57795
  directionalLight.shadow.camera.bottom = -shadowPhysicalSize + bottomOffset;
57799
57796
  directionalLight.shadow.camera.near = 0.5;
57800
57797
  directionalLight.shadow.camera.far = 25;
57801
- directionalLight.shadow.intensity = 0.5;
57798
+ if (lightingType === "WellLit") directionalLight.shadow.intensity = 0.5;
57799
+ if (lightingType === "Thumbnail") {
57800
+ directionalLight.shadow.radius = 4;
57801
+ directionalLight.shadow.bias = 5e-4;
57802
+ }
57802
57803
  directionalLight.target.position.set(0, 0, 0);
57803
57804
  renderScene.scene.add(directionalLight);
57804
57805
  renderScene.directionalLight = directionalLight;
@@ -58815,9 +58816,11 @@ class BackgroundRenderer {
58815
58816
  hasNewUpdate = false;
58816
58817
  affectSceneAppearance = true;
58817
58818
  cameraAffectsTransparency = true;
58819
+ cameraAffectsRotation = false;
58818
58820
  lastFrameTime = Date.now() / 1e3;
58819
58821
  animationInterval;
58820
58822
  animationFPS = 60;
58823
+ originalPartCFrames = /* @__PURE__ */ new Map();
58821
58824
  renderScene = RBXRenderer.firstScene;
58822
58825
  _renderSceneCompiledConnection;
58823
58826
  _renderSceneFailedConnection;
@@ -58906,6 +58909,12 @@ class BackgroundRenderer {
58906
58909
  const root = rbx.generateTree();
58907
58910
  this.avatarCyclorama = root.GetChildren()[0];
58908
58911
  this.avatarCyclorama.setParent(null);
58912
+ for (const child of this.avatarCyclorama.GetChildren()) {
58913
+ if (child.IsA("BasePart")) {
58914
+ const childCF = child.Prop("CFrame");
58915
+ this.originalPartCFrames.set(child, childCF);
58916
+ }
58917
+ }
58909
58918
  root.Destroy();
58910
58919
  } else {
58911
58920
  this.onError.Fire("avatarCyclorama");
@@ -58947,6 +58956,25 @@ class BackgroundRenderer {
58947
58956
  }
58948
58957
  this.fireFullyRenderedIfNeeded();
58949
58958
  }
58959
+ _applyBackgroundRotation() {
58960
+ if (this.avatarCyclorama && this.cameraAffectsRotation) {
58961
+ const cameraCF = RBXRenderer.getCameraCFrame(this.renderScene);
58962
+ const cameraLook = cameraCF.lookVector();
58963
+ cameraLook[0] = -cameraLook[0];
58964
+ cameraLook[1] = 0;
58965
+ cameraLook[2] = -cameraLook[2];
58966
+ const cameraAngle = CFrame.lookAt([0, 0, 0], cameraLook);
58967
+ for (const child of this.avatarCyclorama.GetChildren()) {
58968
+ if (child.IsA("BasePart")) {
58969
+ const ogChildCF = this.originalPartCFrames.get(child);
58970
+ if (ogChildCF) {
58971
+ const newChildCF = cameraAngle.multiply(ogChildCF);
58972
+ child.setProperty("CFrame", newChildCF);
58973
+ }
58974
+ }
58975
+ }
58976
+ }
58977
+ }
58950
58978
  /**
58951
58979
  * Starts updating the animation of the background per frame
58952
58980
  */
@@ -58961,6 +58989,7 @@ class BackgroundRenderer {
58961
58989
  * Updates the animation once
58962
58990
  */
58963
58991
  animateOnce() {
58992
+ this._applyBackgroundRotation();
58964
58993
  this._applyBackgroundData();
58965
58994
  }
58966
58995
  /**
@@ -59346,6 +59375,7 @@ class OutfitRenderer {
59346
59375
  this.doAddInstance = false;
59347
59376
  this.backgroundRenderer.affectSceneAppearance = false;
59348
59377
  this.backgroundRenderer.cameraAffectsTransparency = false;
59378
+ this.backgroundRenderer.cameraAffectsRotation = true;
59349
59379
  if (this.outfit.playerAvatarType === AvatarType.R6) this.deltaTimeMultiplier = 0;
59350
59380
  await new Promise((resolve) => {
59351
59381
  this.onSuccess.Connect(() => {
@@ -59521,6 +59551,18 @@ async function generateOutfitThumbnail(auth, outfit, size = [150, 150], type = "
59521
59551
  renderScene.destroy();
59522
59552
  return void 0;
59523
59553
  }
59554
+ if (thumbnailCameraType === "default" && outfitRenderer.backgroundRenderer.backgroundId) {
59555
+ thumbnailCameraType = "avatarFullbody";
59556
+ }
59557
+ if (outfitRenderer.backgroundRenderer.backgroundId) {
59558
+ renderScene.directionalLight.castShadow = true;
59559
+ renderScene.directionalLight.position.set(...renderScene.directionalLight.position.toArray().map((v, i) => {
59560
+ return i === 2 ? -v : v;
59561
+ }));
59562
+ renderScene.directionalLight2.position.set(...renderScene.directionalLight2.position.toArray().map((v, i) => {
59563
+ return i === 2 ? -v : v;
59564
+ }));
59565
+ }
59524
59566
  if (outfitRenderer.currentRig) {
59525
59567
  let cameraCFrame = new CFrame();
59526
59568
  switch (thumbnailCameraType) {
@@ -59528,10 +59570,10 @@ async function generateOutfitThumbnail(auth, outfit, size = [150, 150], type = "
59528
59570
  cameraCFrame = getThumbnailCameraCFrame(outfitRenderer.currentRig, renderScene.camera.fov) || cameraCFrame;
59529
59571
  break;
59530
59572
  case "avatarHeadshot":
59531
- cameraCFrame = getCameraCFrameForHeadshotCustomized(outfitRenderer.currentRig, 28, 0, 1) || cameraCFrame;
59573
+ cameraCFrame = getCameraCFrameForHeadshotCustomized(outfitRenderer.currentRig, 30, 0, 1) || cameraCFrame;
59532
59574
  break;
59533
59575
  case "avatarFullbody":
59534
- cameraCFrame = getCameraCFrameForAvatarCustomized(outfitRenderer.currentRig, 28, 0) || cameraCFrame;
59576
+ cameraCFrame = getCameraCFrameForAvatarCustomized(outfitRenderer.currentRig, 30, 0) || cameraCFrame;
59535
59577
  break;
59536
59578
  case "fullbody":
59537
59579
  cameraCFrame = getFullBodyCameraCFrame(outfitRenderer.currentRig) || cameraCFrame;
@@ -59539,10 +59581,11 @@ async function generateOutfitThumbnail(auth, outfit, size = [150, 150], type = "
59539
59581
  }
59540
59582
  if (cameraCFrame) {
59541
59583
  RBXRenderer.setCameraCFrame(cameraCFrame, renderScene);
59542
- RBXRenderer.setCameraFov(thumbnailCameraType === "default" ? 70 : thumbnailCameraType === "fullbody" ? 56 : 28, renderScene);
59584
+ RBXRenderer.setCameraFov(thumbnailCameraType === "default" ? 70 : thumbnailCameraType === "fullbody" ? 56 : 30, renderScene);
59543
59585
  renderScene.camera.updateProjectionMatrix();
59544
59586
  }
59545
59587
  outfitRenderer.updateParticleMatrix();
59588
+ outfitRenderer.backgroundRenderer.animateOnce();
59546
59589
  const result = type === "gltf" || type === "glb" ? await modelThumbnailClick(renderScene, type, {
59547
59590
  includeAnimations
59548
59591
  }) : await imageThumbnailClick(renderScene, size[0], size[1], type, {
@@ -59791,6 +59834,7 @@ export {
59791
59834
  Ray3 as Ray,
59792
59835
  RegisterWrappers,
59793
59836
  RegularBodyColors,
59837
+ ResamplerMode,
59794
59838
  RoAvatarData,
59795
59839
  RoAvatarDataError,
59796
59840
  RoAvatarVersions,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "roavatar-renderer",
3
- "version": "1.6.1",
3
+ "version": "1.6.3",
4
4
  "description": "A renderer for Roblox avatars, used by the RoAvatar extension.",
5
5
  "author": "steinan",
6
6
  "type": "module",