roavatar-renderer 1.3.4 → 1.3.6

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
@@ -1044,6 +1044,7 @@ export declare const FLAGS: {
1044
1044
  AUDIO_ENABLED: boolean;
1045
1045
  LEGACY_WELD_BEHAVIOR: boolean;
1046
1046
  USE_RENDERTARGET: boolean;
1047
+ AUTO_RESTORE_CONTEXT: boolean;
1047
1048
  SHOW_SKELETON_HELPER: boolean;
1048
1049
  UPDATE_SKELETON: boolean;
1049
1050
  ANIMATE_SKELETON: boolean;
@@ -2195,7 +2196,8 @@ export declare class RBXRenderer {
2195
2196
  /**Creates canvasContainer */
2196
2197
  static createContainer(): void;
2197
2198
  /**Sets up the THREE.js renderer */
2198
- static create(): void;
2199
+ static create(canvas?: HTMLCanvasElement): void;
2200
+ static setupLostContextHandler(): void;
2199
2201
  /**Sets up a basic scene with lighting
2200
2202
  * @param lightingType "WellLit" is the default lighting for RoAvatar, "Thumbnail" tries to match the Roblox thumbnail lighting
2201
2203
  * @param backgroundColorHex is the hex code for the background color, for example 0x2b2d33
package/dist/index.js CHANGED
@@ -29523,6 +29523,7 @@ const FLAGS = {
29523
29523
  AUDIO_ENABLED: true,
29524
29524
  LEGACY_WELD_BEHAVIOR: false,
29525
29525
  USE_RENDERTARGET: true,
29526
+ AUTO_RESTORE_CONTEXT: true,
29526
29527
  //skeleton
29527
29528
  SHOW_SKELETON_HELPER: false,
29528
29529
  UPDATE_SKELETON: true,
@@ -41942,18 +41943,21 @@ class HSRDesc {
41942
41943
  if (this.layers.length !== other.layers.length) return false;
41943
41944
  if (this.layerTransparent.length !== other.layerTransparent.length) return false;
41944
41945
  for (const layer of this.layers) {
41945
- layerLoop: {
41946
- const selfIndex = this.layers.indexOf(layer);
41947
- for (const otherLayer of other.layers) {
41948
- const otherIndex = other.layers.indexOf(otherLayer);
41949
- if (layer.isSame(otherLayer)) {
41950
- if (this.layerTransparent[selfIndex] !== other.layerTransparent[otherIndex]) {
41951
- return false;
41952
- }
41953
- break layerLoop;
41946
+ let foundLayer = false;
41947
+ const selfIndex = this.layers.indexOf(layer);
41948
+ for (const otherLayer of other.layers) {
41949
+ const otherIndex = other.layers.indexOf(otherLayer);
41950
+ if (layer.isSame(otherLayer)) {
41951
+ foundLayer = true;
41952
+ if (this.layerTransparent[selfIndex] !== other.layerTransparent[otherIndex]) {
41953
+ return false;
41954
41954
  }
41955
+ break;
41955
41956
  }
41956
41957
  }
41958
+ if (!foundLayer) {
41959
+ return false;
41960
+ }
41957
41961
  }
41958
41962
  }
41959
41963
  return true;
@@ -43166,9 +43170,11 @@ class MaterialDesc {
43166
43170
  bodyPart;
43167
43171
  //should only be accounted for if uvType != Normal in TextureLayer
43168
43172
  avatarType;
43173
+ dirty = false;
43169
43174
  //result
43170
43175
  createdTextures = [];
43171
43176
  isSame(other) {
43177
+ if (this.dirty || other.dirty) return false;
43172
43178
  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;
43173
43179
  let layersSame = true;
43174
43180
  if (this.layers.length !== other.layers.length) {
@@ -43546,7 +43552,32 @@ class MaterialDesc {
43546
43552
  texture.needsUpdate = true;
43547
43553
  return [texture, hasTransparency];
43548
43554
  }
43549
- async compileTexture(textureType, meshDesc) {
43555
+ async compileTexture_DirectCompose(textureType) {
43556
+ let textureUrl = void 0;
43557
+ for (const layer of this.layers) {
43558
+ if (layer instanceof TextureLayer) {
43559
+ if (layer[textureType]) {
43560
+ textureUrl = layer[textureType];
43561
+ }
43562
+ }
43563
+ }
43564
+ if (textureUrl) {
43565
+ const image = await API.Generic.LoadImage(textureUrl);
43566
+ if (image) {
43567
+ let hasTransparency = true;
43568
+ if (!this.transparent) {
43569
+ hasTransparency = false;
43570
+ }
43571
+ const texture = new Texture(image);
43572
+ texture.wrapS = RepeatWrapping;
43573
+ texture.wrapT = RepeatWrapping;
43574
+ texture.colorSpace = textureType === "color" ? SRGBColorSpace : NoColorSpace;
43575
+ texture.needsUpdate = true;
43576
+ return [texture, hasTransparency];
43577
+ }
43578
+ }
43579
+ }
43580
+ getComposeType(textureType) {
43550
43581
  let hasSpecialUVType = false;
43551
43582
  let hasColorLayer = false;
43552
43583
  let hasLayerOfType = false;
@@ -43568,33 +43599,23 @@ class MaterialDesc {
43568
43599
  }
43569
43600
  if (!hasLayerOfType) return;
43570
43601
  if ((hasSpecialUVType || this.bodyPart !== void 0) && FLAGS.USE_RENDERTARGET) {
43571
- return this.compileTexture_FullCompose(textureType, meshDesc);
43602
+ return "full";
43572
43603
  } else if (this.layers.length > 1 || hasColorLayer && FLAGS.USE_RENDERTARGET) {
43573
- return this.compileTexture_SimpleCompose(textureType);
43604
+ return "simple";
43574
43605
  } else {
43575
- let textureUrl = void 0;
43576
- for (const layer of this.layers) {
43577
- if (layer instanceof TextureLayer) {
43578
- if (layer[textureType]) {
43579
- textureUrl = layer[textureType];
43580
- }
43581
- }
43582
- }
43583
- if (textureUrl) {
43584
- const image = await API.Generic.LoadImage(textureUrl);
43585
- if (image) {
43586
- let hasTransparency = true;
43587
- if (!this.transparent) {
43588
- hasTransparency = false;
43589
- }
43590
- const texture = new Texture(image);
43591
- texture.wrapS = RepeatWrapping;
43592
- texture.wrapT = RepeatWrapping;
43593
- texture.colorSpace = textureType === "color" ? SRGBColorSpace : NoColorSpace;
43594
- texture.needsUpdate = true;
43595
- return [texture, hasTransparency];
43596
- }
43597
- }
43606
+ return "direct";
43607
+ }
43608
+ }
43609
+ async compileTexture(textureType, meshDesc) {
43610
+ const composeType = this.getComposeType(textureType);
43611
+ if (!composeType) return;
43612
+ switch (composeType) {
43613
+ case "full":
43614
+ return this.compileTexture_FullCompose(textureType, meshDesc);
43615
+ case "simple":
43616
+ return this.compileTexture_SimpleCompose(textureType);
43617
+ case "direct":
43618
+ return this.compileTexture_DirectCompose(textureType);
43598
43619
  }
43599
43620
  }
43600
43621
  async compileMaterial(meshDesc) {
@@ -49197,8 +49218,8 @@ class RBXRenderer {
49197
49218
  RBXRenderer.canvasContainer.style.height = `${RBXRenderer.resolution[1]}px`;
49198
49219
  }
49199
49220
  /**Sets up the THREE.js renderer */
49200
- static create() {
49201
- RBXRenderer.renderer = new WebGLRenderer({ antialias: true, alpha: true });
49221
+ static create(canvas) {
49222
+ RBXRenderer.renderer = new WebGLRenderer({ antialias: true, alpha: true, canvas });
49202
49223
  RBXRenderer.renderer.setClearColor(new Color(1, 0, 1), 0);
49203
49224
  RBXRenderer.renderer.outputColorSpace = SRGBColorSpace;
49204
49225
  RBXRenderer.renderer.shadowMap.enabled = true;
@@ -49210,12 +49231,45 @@ class RBXRenderer {
49210
49231
  }
49211
49232
  RBXRenderer.renderer.domElement.setAttribute("id", "OutfitInfo-outfit-image-3d");
49212
49233
  RBXRenderer.canvasContainer.appendChild(RBXRenderer.renderer.domElement);
49213
- if (RBXRenderer.createLoadingIcon) {
49234
+ if (RBXRenderer.createLoadingIcon && !RBXRenderer.loadingIcon) {
49214
49235
  RBXRenderer.createLoadingIconHTML();
49215
49236
  }
49216
49237
  if (FLAGS.USE_POST_PROCESSING) {
49217
49238
  RBXRenderer._createEffectComposer();
49218
49239
  }
49240
+ RBXRenderer.setupLostContextHandler();
49241
+ }
49242
+ static setupLostContextHandler() {
49243
+ if (!RBXRenderer.renderer) return;
49244
+ RBXRenderer.renderer.domElement.addEventListener("webglcontextlost", (e) => {
49245
+ e.preventDefault();
49246
+ error(true, "RBXRenderer's WebGL2 context was lost, consider optimizing your WebGL usage");
49247
+ if (FLAGS.AUTO_RESTORE_CONTEXT) {
49248
+ const newCanvas = document.createElement("canvas");
49249
+ if (RBXRenderer.renderer?.domElement) {
49250
+ RBXRenderer.canvasContainer.replaceChild(newCanvas, RBXRenderer.renderer.domElement);
49251
+ }
49252
+ RBXRenderer.renderer?.dispose();
49253
+ RBXRenderer.create(newCanvas);
49254
+ for (const renderScene of RBXRenderer.scenes) {
49255
+ const controls = renderScene.controls;
49256
+ if (controls) {
49257
+ controls.dispose();
49258
+ controls.domElement = newCanvas;
49259
+ controls.connect(newCanvas);
49260
+ }
49261
+ for (const renderDesc of renderScene.renderDescs.values()) {
49262
+ if (renderDesc instanceof ObjectDesc) {
49263
+ const materialDesc = renderDesc.materialDesc;
49264
+ const composeType = materialDesc.getComposeType("color");
49265
+ if (composeType === "full" || composeType === "simple") {
49266
+ materialDesc.dirty = true;
49267
+ }
49268
+ }
49269
+ }
49270
+ }
49271
+ }
49272
+ });
49219
49273
  }
49220
49274
  /**Sets up a basic scene with lighting
49221
49275
  * @param lightingType "WellLit" is the default lighting for RoAvatar, "Thumbnail" tries to match the Roblox thumbnail lighting
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "roavatar-renderer",
3
- "version": "1.3.4",
3
+ "version": "1.3.6",
4
4
  "description": "A renderer for Roblox avatars, used by the RoAvatar extension.",
5
5
  "author": "steinan",
6
6
  "type": "module",