roavatar-renderer 1.2.16 → 1.3.1

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/README.md CHANGED
@@ -44,7 +44,7 @@ Basic example on how to load an avatar using OutfitRenderer (to make it simpler)
44
44
  document.body.appendChild(RBXRenderer.getRendererElement())
45
45
 
46
46
  //get avatar data for the user with id 1
47
- const outfit = API.Avatar.GetAvatarDetails(1)
47
+ const outfit = await API.Avatar.GetAvatarDetails(1)
48
48
  if (!(outfit instanceof Outfit)) throw new Error("Failed to get outfit")
49
49
 
50
50
  //create renderer for outfit
package/dist/index.d.ts CHANGED
@@ -55,6 +55,14 @@ export declare const AccessoryType: {
55
55
  Eyelash: number;
56
56
  };
57
57
 
58
+ export declare class AccessoryWrapper extends InstanceWrapper {
59
+ static className: string;
60
+ static requiredProperties: string[];
61
+ setup(): void;
62
+ created(): void;
63
+ AccessoryBuildWeld(): void;
64
+ }
65
+
58
66
  export declare const ActualBundleTypes: string[];
59
67
 
60
68
  export declare function add(v0: Vec3, v1: Vec3): Vec3;
@@ -83,6 +91,12 @@ export declare const AlphaMode: {
83
91
  TintMask: number;
84
92
  };
85
93
 
94
+ export declare class AnimationConstraintWrapper extends InstanceWrapper {
95
+ static className: string;
96
+ static requiredProperties: string[];
97
+ setup(): void;
98
+ }
99
+
86
100
  export declare type AnimationProp = "ClimbAnimation" | "FallAnimation" | "IdleAnimation" | "JumpAnimation" | "MoodAnimation" | "RunAnimation" | "SwimAnimation" | "WalkAnimation" | "dance1" | "dance2" | "dance3" | "toolnone";
87
101
 
88
102
  export declare const AnimationPropToName: {
@@ -552,6 +566,14 @@ declare type BodyColorsJson = {
552
566
  leftLegColorId?: number;
553
567
  };
554
568
 
569
+ export declare class BodyColorsWrapper extends InstanceWrapper {
570
+ static className: string;
571
+ static requiredProperties: string[];
572
+ setup(): void;
573
+ created(): void;
574
+ update(): void;
575
+ }
576
+
555
577
  export declare const BodyPart: {
556
578
  Head: number;
557
579
  Torso: number;
@@ -826,6 +848,12 @@ export declare const DataType: {
826
848
  NonSerializable: number;
827
849
  };
828
850
 
851
+ export declare class DecalWrapper extends InstanceWrapper {
852
+ static className: string;
853
+ static requiredProperties: string[];
854
+ setup(): void;
855
+ }
856
+
829
857
  /**
830
858
  * @deprecated
831
859
  */
@@ -982,6 +1010,8 @@ export declare class FileMeshSubset {
982
1010
  clone(): FileMeshSubset;
983
1011
  }
984
1012
 
1013
+ export declare function fileMeshToTHREEGeometry(mesh: FileMesh, canIncludeSkinning?: boolean, forceVertexColor?: Vector3): THREE.BufferGeometry<THREE.NormalBufferAttributes, THREE.BufferGeometryEventMap>;
1014
+
985
1015
  export declare const FLAGS: {
986
1016
  HAIR_IS_BODYPART: boolean;
987
1017
  AVATAR_JOINT_UPGRADE: boolean;
@@ -1061,6 +1091,11 @@ export declare function getCameraCFrameForHeadshotCustomized(rig: Instance, fov:
1061
1091
 
1062
1092
  export declare function getDistIndexArray(ref: FileMesh, dist: FileMesh): (number | undefined)[];
1063
1093
 
1094
+ export declare function getExtents(cframe: CFrame, parts: Instance[]): [Vector3, Vector3];
1095
+
1096
+ /**@deprecated this is SO broken */
1097
+ export declare function getExtentsForParts(parts: Instance[], includeTransform?: boolean): [Vector3, Vector3];
1098
+
1064
1099
  export declare function getHeadExtents(rig: Instance): [Vector3, Vector3] | undefined;
1065
1100
 
1066
1101
  export declare interface GetInfoForId_Result {
@@ -1563,6 +1598,10 @@ export declare const MakeupType: {
1563
1598
  Eye: number;
1564
1599
  };
1565
1600
 
1601
+ export declare class ManualWeldWrapper extends WeldWrapper {
1602
+ static className: string;
1603
+ }
1604
+
1566
1605
  export declare function mapNum(x: number, in_min: number, in_max: number, out_min: number, out_max: number): number;
1567
1606
 
1568
1607
  export declare interface MarketplaceWidget {
@@ -1645,6 +1684,12 @@ export declare class ModelWrapper extends InstanceWrapper {
1645
1684
  GetModelCFrame(): CFrame;
1646
1685
  }
1647
1686
 
1687
+ export declare class Motor6DWrapper extends WeldWrapper {
1688
+ static className: string;
1689
+ static requiredProperties: string[];
1690
+ setup(): void;
1691
+ }
1692
+
1648
1693
  /**
1649
1694
  * @deprecated Use mountElement instead
1650
1695
  * @param container
@@ -1884,7 +1929,6 @@ export declare class OutfitRenderer {
1884
1929
  outfit: Outfit;
1885
1930
  currentRig?: Instance; /**Instance for the Model of the current outfit */
1886
1931
  currentRigType: AvatarType;
1887
- rigPath: string;
1888
1932
  doCameraUpdateOnLoad: boolean; /**Makes camera update when new avatar has loaded */
1889
1933
  doCameraUpdate: boolean; /**Does camera update every frame */
1890
1934
  currentlyChangingRig: boolean;
@@ -1894,13 +1938,14 @@ export declare class OutfitRenderer {
1894
1938
  animationInterval?: NodeJS.Timeout;
1895
1939
  animationFPS: number;
1896
1940
  deltaTimeMultiplier: number;
1941
+ renderScene: RBXRendererScene;
1897
1942
  /**
1898
1943
  * Creates a new OutfitRenderer which makes it easy to render outfits
1899
1944
  * @param auth The authentication object, you should have one you use for everything
1900
1945
  * @param outfit The outfit you want to render, it can be updated later by calling setOutfit()
1901
- * @param rigPath The path that contains RigR6.rbxm and RigR15.rbxm, should always be "roavatar://" as rig path is now controlled by FLAGS
1946
+ * @param renderScene The scene the outfit should be rendered in
1902
1947
  */
1903
- constructor(auth: Authentication, outfit: Outfit, rigPath?: string);
1948
+ constructor(auth: Authentication, outfit: Outfit, renderScene?: RBXRendererScene);
1904
1949
  /**
1905
1950
  * Updates the current rig, called internally by _updateOutfit()
1906
1951
  */
@@ -2105,42 +2150,47 @@ export declare class RBX {
2105
2150
  }
2106
2151
 
2107
2152
  export declare class RBXRenderer {
2108
- static isRenderingMesh: Map<Instance, boolean>;
2109
- static renderDescs: Map<Instance, RenderDesc>;
2110
- static destroyConnections: Map<Instance, Connection>;
2111
- static lookAwayVector: Vec3;
2112
- static lookAwayDistance: number;
2113
2153
  static orbitControlsTarget: Vec3;
2114
- static scene: THREE.Scene;
2115
- static camera: THREE.PerspectiveCamera;
2116
- static controls: OrbitControls | undefined;
2154
+ static scenes: RBXRendererScene[];
2155
+ static get firstScene(): RBXRendererScene;
2156
+ /**@deprecated This can only get the first renderScene's scene */
2157
+ static get scene(): THREE.Scene;
2158
+ /**@deprecated This can only get the first renderScene's camera */
2159
+ static get camera(): THREE.PerspectiveCamera;
2160
+ /**@deprecated This can only get the first renderScene's controls */
2161
+ static get controls(): OrbitControls | undefined;
2117
2162
  static renderer?: THREE.WebGLRenderer;
2118
- static effectComposer: EffectComposer | undefined;
2119
- static shadowEnabled: boolean;
2120
- static shadowResolution: [number, number];
2121
2163
  static resolution: [number, number];
2122
2164
  static backgroundColorHex: number;
2123
2165
  static backgroundTransparent: boolean;
2124
- static _wellLitDirectionalLightIntensity: number;
2125
- static set wellLitDirectionalLightIntensity(v: number);
2126
- static get wellLitDirectionalLightIntensity(): number;
2127
2166
  static createLoadingIcon: boolean;
2128
2167
  static canvasContainer: HTMLDivElement;
2129
2168
  static loadingIcon?: HTMLSpanElement;
2130
2169
  static loadingIconStyle?: HTMLStyleElement;
2131
- static plane?: THREE.Mesh;
2132
- static shadowPlane?: THREE.Mesh;
2133
- static ambientLight?: THREE.AmbientLight;
2134
- static directionalLight?: THREE.DirectionalLight;
2135
- static directionalLight2?: THREE.DirectionalLight;
2170
+ /**@deprecated This can only get the first renderScene's plane */
2171
+ static get plane(): THREE.Mesh<THREE.BufferGeometry<THREE.NormalBufferAttributes, THREE.BufferGeometryEventMap>, THREE.Material | THREE.Material[], THREE.Object3DEventMap> | undefined;
2172
+ /**@deprecated This can only get the first renderScene's shadowPlane */
2173
+ static get shadowPlane(): THREE.Mesh<THREE.BufferGeometry<THREE.NormalBufferAttributes, THREE.BufferGeometryEventMap>, THREE.Material | THREE.Material[], THREE.Object3DEventMap> | undefined;
2174
+ /**@deprecated This can only get the first renderScene's ambientLight */
2175
+ static get ambientLight(): THREE.AmbientLight | undefined;
2176
+ /**@deprecated This can only get the first renderScene's directionalLight */
2177
+ static get directionalLight(): THREE.DirectionalLight | undefined;
2178
+ /**@deprecated This can only get the first renderScene's directionalLight2 */
2179
+ static get directionalLight2(): THREE.DirectionalLight | undefined;
2180
+ /**@deprecated This can only set the first renderScene's wellLitDirectionalLightIntensity*/
2181
+ static set wellLitDirectionalLightIntensity(v: number);
2182
+ /**@deprecated This can only gey the first renderScene's wellLitDirectionalLightIntensity*/
2183
+ static get wellLitDirectionalLightIntensity(): number;
2136
2184
  static failedToCreate: boolean;
2137
2185
  static error?: unknown;
2138
2186
  static boilerplateSetup(): Promise<void>;
2139
2187
  static showErrorHTML(): Promise<void>;
2188
+ static createLoadingIconHTML(): void;
2189
+ static addScene(): RBXRendererScene;
2140
2190
  /**Fully sets up renderer with scene, camera and frame rendering
2141
2191
  * @returns success
2142
2192
  */
2143
- static fullSetup(includeScene?: boolean, includeControls?: boolean): Promise<boolean>;
2193
+ static fullSetup(includeSceneAppearance?: boolean, includeControls?: boolean, includeAnimate?: boolean): Promise<boolean>;
2144
2194
  /**Creates canvasContainer */
2145
2195
  static createContainer(): void;
2146
2196
  /**Sets up the THREE.js renderer */
@@ -2149,9 +2199,9 @@ export declare class RBXRenderer {
2149
2199
  * @param lightingType "WellLit" is the default lighting for RoAvatar, "Thumbnail" tries to match the Roblox thumbnail lighting
2150
2200
  * @param backgroundColorHex is the hex code for the background color, for example 0x2b2d33
2151
2201
  */
2152
- static setupScene(lightingType?: "WellLit" | "Thumbnail", backgroundColorHex?: number): void;
2202
+ static setupScene(lightingType?: "WellLit" | "Thumbnail", backgroundColorHex?: number, renderScene?: RBXRendererScene): void;
2153
2203
  /**Sets up orbit controls */
2154
- static setupControls(): void;
2204
+ static setupControls(renderScene?: RBXRendererScene): void;
2155
2205
  /**
2156
2206
  * @param colorHex example: 0x2b2d33 which is the default
2157
2207
  */
@@ -2162,13 +2212,15 @@ export declare class RBXRenderer {
2162
2212
  */
2163
2213
  static setBackgroundTransparent(transparent: boolean): void;
2164
2214
  /**Makes the renderer render a new frame on every animationFrame */
2165
- static animate(): void;
2166
- static _createEffectComposer(): void;
2215
+ static animate(shouldRequestAnimationFrame?: boolean): void;
2216
+ static animateAll(shouldRequestAnimationFrame?: boolean): void;
2217
+ static renderScene(renderScene: RBXRendererScene, autoClear?: boolean): void;
2218
+ static _createEffectComposer(renderScene?: RBXRendererScene): void;
2167
2219
  /**Removes an instance from the renderer */
2168
- static removeInstance(instance: Instance): void;
2169
- static _addRenderDesc(instance: Instance, auth: Authentication, DescClass: typeof RenderDesc): void;
2220
+ static removeInstance(instance: Instance, renderScene?: RBXRendererScene): void;
2221
+ static _addRenderDesc(instance: Instance, auth: Authentication, DescClass: typeof RenderDesc, renderScene: RBXRendererScene): void;
2170
2222
  /**Adds an instance to the renderer or updates it */
2171
- static addInstance(instance: Instance, auth: Authentication): void;
2223
+ static addInstance(instance: Instance, auth: Authentication, renderScene?: RBXRendererScene): void;
2172
2224
  static setRendererSize(width: number, height: number): void;
2173
2225
  /**
2174
2226
  * @deprecated Use getRendererElement instead which includes the loading icon
@@ -2179,17 +2231,46 @@ export declare class RBXRenderer {
2179
2231
  * @returns An element containing the renderer canvas
2180
2232
  */
2181
2233
  static getRendererElement(): HTMLDivElement;
2234
+ /**@deprecated This can only get the first renderScene's camera */
2182
2235
  static getRendererCamera(): THREE.PerspectiveCamera;
2183
- static getCameraCFrame(): CFrame;
2184
- static setCameraCFrame(cameraCF: CFrame): void;
2185
- static setCameraFov(fov: number): void;
2236
+ static getCameraCFrame(renderScene?: RBXRendererScene): CFrame;
2237
+ static setCameraCFrame(cameraCF: CFrame, renderScene?: RBXRendererScene): void;
2238
+ static setCameraFov(fov: number, renderScene?: RBXRendererScene): void;
2239
+ /**@deprecated This can only get the first renderScene's controls */
2186
2240
  static getRendererControls(): OrbitControls | undefined;
2187
2241
  static getRenderer(): THREE.WebGLRenderer | undefined;
2188
- static getScene(): THREE.Scene;
2242
+ /**@deprecated This can only get the first renderScene's scene */
2243
+ static getScene(): RBXRendererScene;
2189
2244
  /**@deprecated
2190
2245
  * This function is unstable and can throw errors, but might work
2191
2246
  */
2192
- static exportScene(): void;
2247
+ static exportScene(renderScene?: RBXRendererScene): void;
2248
+ }
2249
+
2250
+ export declare class RBXRendererScene {
2251
+ scene: THREE.Scene;
2252
+ camera: THREE.PerspectiveCamera;
2253
+ controls: OrbitControls | undefined;
2254
+ effectComposer: EffectComposer | undefined;
2255
+ scissor?: [number, number, number, number];
2256
+ viewport?: [number, number, number, number];
2257
+ isRenderingMesh: Map<Instance, boolean>;
2258
+ renderDescs: Map<Instance, RenderDesc>;
2259
+ destroyConnections: Map<Instance, Connection>;
2260
+ lookAwayVector: Vec3;
2261
+ lookAwayDistance: number;
2262
+ shadowEnabled: boolean;
2263
+ shadowResolution: [number, number];
2264
+ _wellLitDirectionalLightIntensity: number;
2265
+ set wellLitDirectionalLightIntensity(v: number);
2266
+ get wellLitDirectionalLightIntensity(): number;
2267
+ plane?: THREE.Mesh;
2268
+ shadowPlane?: THREE.Mesh;
2269
+ ambientLight?: THREE.AmbientLight;
2270
+ directionalLight?: THREE.DirectionalLight;
2271
+ directionalLight2?: THREE.DirectionalLight;
2272
+ setRect(bounds: DOMRect): void;
2273
+ noRect(): void;
2193
2274
  }
2194
2275
 
2195
2276
  declare class RBXSimpleView {
@@ -2235,8 +2316,10 @@ export declare const RegularBodyColors: string[];
2235
2316
  * Abstract class used to describe all rendered instances
2236
2317
  */
2237
2318
  declare class RenderDesc extends DisposableDesc {
2319
+ renderScene: RBXRendererScene;
2238
2320
  results?: THREE.Mesh[];
2239
2321
  instance?: Instance;
2322
+ constructor(renderScene: RBXRendererScene);
2240
2323
  isSame(_other: RenderDesc): boolean;
2241
2324
  needsRegeneration(_other: RenderDesc): boolean;
2242
2325
  fromRenderDesc(other: RenderDesc): void;
@@ -2687,6 +2770,22 @@ export declare type WeightChunk3 = WeightChunk & {
2687
2770
  weights: Vec3[];
2688
2771
  };
2689
2772
 
2773
+ export declare class WeldWrapper extends InstanceWrapper {
2774
+ static className: string;
2775
+ static requiredProperties: string[];
2776
+ setup(): void;
2777
+ get data(): WeldWrapperData;
2778
+ created(): void;
2779
+ preRender(): void;
2780
+ update(affectedPart?: number): void;
2781
+ }
2782
+
2783
+ declare class WeldWrapperData {
2784
+ part0ChangedConnection?: Connection;
2785
+ lastUpdateTime: number;
2786
+ timeUpdates: number;
2787
+ }
2788
+
2690
2789
  export declare const WorkerTypeToFunction: {
2691
2790
  [K in string]: Function;
2692
2791
  };
@@ -2699,4 +2798,6 @@ export declare const WrapLayerAutoSkin: {
2699
2798
 
2700
2799
  export declare const xmlMagic = "<roblox ";
2701
2800
 
2801
+ export declare function zoomExtents(cameraCFrame: CFrame, modelCFrame: CFrame, modelSize: Vector3, targetFOV: number, distanceScale: number): void;
2802
+
2702
2803
  export { }
package/dist/index.js CHANGED
@@ -41220,7 +41220,6 @@ function TraverseRigFromAttachmentsInternal(self2, part, characterParts, buildJo
41220
41220
  if (part !== characterPart) {
41221
41221
  const matchingAttachment = characterPart.FindFirstChild(attachmentName);
41222
41222
  if (matchingAttachment && matchingAttachment.className === "Attachment") {
41223
- log(false, "matchingAtt", part, characterPart, attachmentName);
41224
41223
  AdjustRootRigAttachmentPosition(self2, part, characterPart, attachment, matchingAttachment);
41225
41224
  {
41226
41225
  createJoint(jointName, attachment, matchingAttachment);
@@ -44797,8 +44796,13 @@ class DisposableDesc {
44797
44796
  }
44798
44797
  }
44799
44798
  class RenderDesc extends DisposableDesc {
44799
+ renderScene;
44800
44800
  results;
44801
44801
  instance;
44802
+ constructor(renderScene) {
44803
+ super();
44804
+ this.renderScene = renderScene;
44805
+ }
44802
44806
  // eslint-disable-next-line @typescript-eslint/no-unused-vars
44803
44807
  isSame(_other) {
44804
44808
  throw new Error("Virtual method isSame called");
@@ -45143,14 +45147,14 @@ class Particle {
45143
45147
  this.velocity = velocity;
45144
45148
  this.rotationSpeed = rotationSpeed;
45145
45149
  }
45146
- camDistance() {
45147
- const cameraPos = new Vector32(...RBXRenderer.getRendererCamera().position.toArray());
45150
+ camDistance(renderScene) {
45151
+ const cameraPos = new Vector32(...renderScene.camera.position.toArray());
45148
45152
  const particlePos = this.position;
45149
45153
  const distance2 = cameraPos.minus(particlePos).magnitude();
45150
45154
  return distance2;
45151
45155
  }
45152
- getMatrix(size, orientation) {
45153
- const camera = RBXRenderer.getRendererCamera();
45156
+ getMatrix(renderScene, size, orientation) {
45157
+ const camera = renderScene.camera;
45154
45158
  const particlePos = new Vector3$1(...this.position.toVec3());
45155
45159
  const translation = new Matrix4().makeTranslation(particlePos);
45156
45160
  const scale = new Matrix4().makeScale(size, size, 1);
@@ -45395,7 +45399,7 @@ class EmitterDesc extends DisposableDesc {
45395
45399
  this.passedTime -= 1 / this.rate;
45396
45400
  }
45397
45401
  }
45398
- updateResult() {
45402
+ updateResult(renderScene) {
45399
45403
  if (!this.result || !this.instanceColorBuffer || !this.instanceOpacityBuffer || !this.instanceSeedTimeBuffer) return;
45400
45404
  this.result.count = this.particles.length;
45401
45405
  for (let i = 0; i < this.result.count; i++) {
@@ -45405,7 +45409,7 @@ class EmitterDesc extends DisposableDesc {
45405
45409
  const color = this.color.getValue(normalizedTime);
45406
45410
  const size = this.size.getValue(this.normalizeSizeKeypointTime ? normalizedTime : time2, particle.seed + 0);
45407
45411
  const opacity = 1 - this.transparency.getValue(normalizedTime, particle.seed + 1);
45408
- this.result.setMatrixAt(i, particle.getMatrix(size, this.orientation));
45412
+ this.result.setMatrixAt(i, particle.getMatrix(renderScene, size, this.orientation));
45409
45413
  this.instanceColorBuffer.setXYZ(i, color.R, color.G, color.B);
45410
45414
  this.instanceOpacityBuffer.setX(i, opacity);
45411
45415
  this.instanceSeedTimeBuffer.setXY(i, particle.seed, normalizedTime);
@@ -45703,7 +45707,7 @@ class EmitterGroupDesc extends RenderDesc {
45703
45707
  this.lastTime = this.time;
45704
45708
  for (const emitterDesc of this.emitterDescs) {
45705
45709
  emitterDesc.tick(dt, this);
45706
- emitterDesc.updateResult();
45710
+ emitterDesc.updateResult(this.renderScene);
45707
45711
  }
45708
45712
  this.lastCframe = this.cframe.clone();
45709
45713
  }
@@ -48962,42 +48966,104 @@ function RegisterWrappers() {
48962
48966
  BodyColorsWrapper.register();
48963
48967
  AccessoryWrapper.register();
48964
48968
  }
48969
+ class RBXRendererScene {
48970
+ //important scene components
48971
+ scene = new Scene();
48972
+ camera = new PerspectiveCamera(70, 1 / 1, 0.1, 100);
48973
+ controls;
48974
+ //renderer
48975
+ effectComposer;
48976
+ //viewport
48977
+ scissor;
48978
+ viewport;
48979
+ //renderables data
48980
+ isRenderingMesh = /* @__PURE__ */ new Map();
48981
+ renderDescs = /* @__PURE__ */ new Map();
48982
+ destroyConnections = /* @__PURE__ */ new Map();
48983
+ //scene appearance config
48984
+ lookAwayVector = [0.406, 0.306, -0.819];
48985
+ lookAwayDistance = 6;
48986
+ shadowEnabled = true;
48987
+ shadowResolution = [256, 256];
48988
+ _wellLitDirectionalLightIntensity = Math.PI / 2;
48989
+ set wellLitDirectionalLightIntensity(v) {
48990
+ this._wellLitDirectionalLightIntensity = v;
48991
+ if (this.directionalLight) {
48992
+ this.directionalLight.intensity = this._wellLitDirectionalLightIntensity;
48993
+ }
48994
+ }
48995
+ get wellLitDirectionalLightIntensity() {
48996
+ return this._wellLitDirectionalLightIntensity;
48997
+ }
48998
+ //scene appearance
48999
+ plane;
49000
+ shadowPlane;
49001
+ ambientLight;
49002
+ directionalLight;
49003
+ directionalLight2;
49004
+ setRect(bounds) {
49005
+ this.viewport = [bounds.left, window.innerHeight - bounds.bottom, bounds.width, bounds.height];
49006
+ this.scissor = [...this.viewport];
49007
+ }
49008
+ noRect() {
49009
+ this.viewport = [0, 0, 0, 0];
49010
+ this.scissor = [0, 0, 0, 0];
49011
+ }
49012
+ }
48965
49013
  class RBXRenderer {
48966
- static isRenderingMesh = /* @__PURE__ */ new Map();
48967
- static renderDescs = /* @__PURE__ */ new Map();
48968
- static destroyConnections = /* @__PURE__ */ new Map();
48969
- static lookAwayVector = [0.406, 0.306, -0.819];
48970
- static lookAwayDistance = 6;
48971
49014
  static orbitControlsTarget = [0, 3, 0];
48972
- static scene = new Scene();
48973
- static camera = new PerspectiveCamera(70, 1 / 1, 0.1, 100);
48974
- static controls;
49015
+ static scenes = [new RBXRendererScene()];
49016
+ static get firstScene() {
49017
+ return RBXRenderer.scenes[0];
49018
+ }
49019
+ /**@deprecated This can only get the first renderScene's scene */
49020
+ static get scene() {
49021
+ return RBXRenderer.firstScene.scene;
49022
+ }
49023
+ /**@deprecated This can only get the first renderScene's camera */
49024
+ static get camera() {
49025
+ return RBXRenderer.firstScene.camera;
49026
+ }
49027
+ /**@deprecated This can only get the first renderScene's controls */
49028
+ static get controls() {
49029
+ return RBXRenderer.firstScene.controls;
49030
+ }
48975
49031
  static renderer;
48976
- static effectComposer;
48977
- static shadowEnabled = true;
48978
- static shadowResolution = [256, 256];
48979
49032
  static resolution = [420, 420];
48980
49033
  static backgroundColorHex = 2829619;
48981
49034
  static backgroundTransparent = false;
48982
- static _wellLitDirectionalLightIntensity = Math.PI / 2;
48983
- static set wellLitDirectionalLightIntensity(v) {
48984
- RBXRenderer._wellLitDirectionalLightIntensity = v;
48985
- if (RBXRenderer.directionalLight) {
48986
- RBXRenderer.directionalLight.intensity = RBXRenderer._wellLitDirectionalLightIntensity;
48987
- }
48988
- }
48989
- static get wellLitDirectionalLightIntensity() {
48990
- return RBXRenderer._wellLitDirectionalLightIntensity;
48991
- }
48992
49035
  static createLoadingIcon = true;
48993
49036
  static canvasContainer;
48994
49037
  static loadingIcon;
48995
49038
  static loadingIconStyle;
48996
- static plane;
48997
- static shadowPlane;
48998
- static ambientLight;
48999
- static directionalLight;
49000
- static directionalLight2;
49039
+ /**@deprecated This can only get the first renderScene's plane */
49040
+ static get plane() {
49041
+ return RBXRenderer.firstScene.plane;
49042
+ }
49043
+ /**@deprecated This can only get the first renderScene's shadowPlane */
49044
+ static get shadowPlane() {
49045
+ return RBXRenderer.firstScene.shadowPlane;
49046
+ }
49047
+ /**@deprecated This can only get the first renderScene's ambientLight */
49048
+ static get ambientLight() {
49049
+ return RBXRenderer.firstScene.ambientLight;
49050
+ }
49051
+ /**@deprecated This can only get the first renderScene's directionalLight */
49052
+ static get directionalLight() {
49053
+ return RBXRenderer.firstScene.directionalLight;
49054
+ }
49055
+ /**@deprecated This can only get the first renderScene's directionalLight2 */
49056
+ static get directionalLight2() {
49057
+ return RBXRenderer.firstScene.directionalLight2;
49058
+ }
49059
+ /**@deprecated This can only set the first renderScene's wellLitDirectionalLightIntensity*/
49060
+ static set wellLitDirectionalLightIntensity(v) {
49061
+ RBXRenderer.firstScene.wellLitDirectionalLightIntensity = v;
49062
+ }
49063
+ /**@deprecated This can only gey the first renderScene's wellLitDirectionalLightIntensity*/
49064
+ static get wellLitDirectionalLightIntensity() {
49065
+ return RBXRenderer.firstScene.wellLitDirectionalLightIntensity;
49066
+ }
49001
49067
  static failedToCreate = false;
49002
49068
  static error;
49003
49069
  static async boilerplateSetup() {
@@ -49051,17 +49117,67 @@ class RBXRenderer {
49051
49117
  errorDiv.appendChild(errorLink);
49052
49118
  RBXRenderer.canvasContainer.append(errorDiv);
49053
49119
  }
49120
+ static createLoadingIconHTML() {
49121
+ RBXRenderer.loadingIcon = document.createElement("span");
49122
+ RBXRenderer.loadingIcon.className = "roavatar-loader";
49123
+ RBXRenderer.loadingIcon.style.opacity = "0";
49124
+ RBXRenderer.loadingIcon.style.position = "absolute";
49125
+ RBXRenderer.loadingIcon.style.bottom = "12px";
49126
+ RBXRenderer.loadingIcon.style.right = "12px";
49127
+ RBXRenderer.loadingIcon.style.width = "24px";
49128
+ RBXRenderer.loadingIcon.style.height = "24px";
49129
+ RBXRenderer.loadingIcon.style.transition = "0.1s";
49130
+ RBXRenderer.loadingIconStyle = document.createElement("style");
49131
+ RBXRenderer.loadingIconStyle.textContent = `
49132
+ /*Loader source: https://cssloaders.github.io/ */
49133
+ .roavatar-loader {
49134
+ width: 48px;
49135
+ height: 48px;
49136
+ display: inline-block;
49137
+ position: relative;
49138
+ background: #FFF;
49139
+ box-sizing: border-box;
49140
+ animation: rooavatarFlipX 1s linear infinite;
49141
+ }
49142
+
49143
+ @keyframes rooavatarFlipX {
49144
+ 0% {
49145
+ transform: perspective(200px) rotateX(0deg) rotateY(0deg);
49146
+ }
49147
+ 50% {
49148
+ transform: perspective(200px) rotateX(-180deg) rotateY(0deg);
49149
+ }
49150
+ 100% {
49151
+ transform: perspective(200px) rotateX(-180deg) rotateY(-180deg);
49152
+ }
49153
+ }
49154
+ `;
49155
+ document.head.appendChild(RBXRenderer.loadingIconStyle);
49156
+ RBXRenderer.canvasContainer.appendChild(RBXRenderer.loadingIcon);
49157
+ const onLoadConnection = API.Events.OnLoadingAssets.Connect((newIsLoading) => {
49158
+ if (RBXRenderer.loadingIcon) {
49159
+ RBXRenderer.loadingIcon.style.opacity = newIsLoading ? "1" : "0";
49160
+ } else {
49161
+ onLoadConnection.Disconnect();
49162
+ }
49163
+ });
49164
+ }
49165
+ static addScene() {
49166
+ const renderScene = new RBXRendererScene();
49167
+ RBXRenderer.scenes.push(renderScene);
49168
+ return renderScene;
49169
+ }
49054
49170
  /**Fully sets up renderer with scene, camera and frame rendering
49055
49171
  * @returns success
49056
49172
  */
49057
- static async fullSetup(includeScene = true, includeControls = true) {
49173
+ static async fullSetup(includeSceneAppearance = true, includeControls = true, includeAnimate = true) {
49058
49174
  try {
49059
49175
  RBXRenderer.createContainer();
49060
49176
  await RBXRenderer.boilerplateSetup();
49061
49177
  RBXRenderer.create();
49062
- if (includeScene) RBXRenderer.setupScene();
49178
+ if (includeSceneAppearance) RBXRenderer.setupScene();
49063
49179
  if (includeControls) RBXRenderer.setupControls();
49064
- RBXRenderer.animate();
49180
+ if (includeAnimate) RBXRenderer.animateAll();
49065
49181
  } catch (err2) {
49066
49182
  error(err2);
49067
49183
  RBXRenderer.failedToCreate = true;
@@ -49092,49 +49208,7 @@ class RBXRenderer {
49092
49208
  RBXRenderer.renderer.domElement.setAttribute("id", "OutfitInfo-outfit-image-3d");
49093
49209
  RBXRenderer.canvasContainer.appendChild(RBXRenderer.renderer.domElement);
49094
49210
  if (RBXRenderer.createLoadingIcon) {
49095
- RBXRenderer.loadingIcon = document.createElement("span");
49096
- RBXRenderer.loadingIcon.className = "roavatar-loader";
49097
- RBXRenderer.loadingIcon.style.opacity = "0";
49098
- RBXRenderer.loadingIcon.style.position = "absolute";
49099
- RBXRenderer.loadingIcon.style.bottom = "12px";
49100
- RBXRenderer.loadingIcon.style.right = "12px";
49101
- RBXRenderer.loadingIcon.style.width = "24px";
49102
- RBXRenderer.loadingIcon.style.height = "24px";
49103
- RBXRenderer.loadingIcon.style.transition = "0.1s";
49104
- RBXRenderer.loadingIconStyle = document.createElement("style");
49105
- RBXRenderer.loadingIconStyle.textContent = `
49106
- /*Loader source: https://cssloaders.github.io/ */
49107
- .roavatar-loader {
49108
- width: 48px;
49109
- height: 48px;
49110
- display: inline-block;
49111
- position: relative;
49112
- background: #FFF;
49113
- box-sizing: border-box;
49114
- animation: rooavatarFlipX 1s linear infinite;
49115
- }
49116
-
49117
- @keyframes rooavatarFlipX {
49118
- 0% {
49119
- transform: perspective(200px) rotateX(0deg) rotateY(0deg);
49120
- }
49121
- 50% {
49122
- transform: perspective(200px) rotateX(-180deg) rotateY(0deg);
49123
- }
49124
- 100% {
49125
- transform: perspective(200px) rotateX(-180deg) rotateY(-180deg);
49126
- }
49127
- }
49128
- `;
49129
- document.head.appendChild(RBXRenderer.loadingIconStyle);
49130
- RBXRenderer.canvasContainer.appendChild(RBXRenderer.loadingIcon);
49131
- const onLoadConnection = API.Events.OnLoadingAssets.Connect((newIsLoading) => {
49132
- if (RBXRenderer.loadingIcon) {
49133
- RBXRenderer.loadingIcon.style.opacity = newIsLoading ? "1" : "0";
49134
- } else {
49135
- onLoadConnection.Disconnect();
49136
- }
49137
- });
49211
+ RBXRenderer.createLoadingIconHTML();
49138
49212
  }
49139
49213
  if (FLAGS.USE_POST_PROCESSING) {
49140
49214
  RBXRenderer._createEffectComposer();
@@ -49144,10 +49218,10 @@ class RBXRenderer {
49144
49218
  * @param lightingType "WellLit" is the default lighting for RoAvatar, "Thumbnail" tries to match the Roblox thumbnail lighting
49145
49219
  * @param backgroundColorHex is the hex code for the background color, for example 0x2b2d33
49146
49220
  */
49147
- static setupScene(lightingType = "WellLit", backgroundColorHex = RBXRenderer.backgroundColorHex) {
49221
+ static setupScene(lightingType = "WellLit", backgroundColorHex = RBXRenderer.backgroundColorHex, renderScene = RBXRenderer.firstScene) {
49148
49222
  RBXRenderer.backgroundColorHex = backgroundColorHex;
49149
49223
  const backgroundColor = new Color(backgroundColorHex);
49150
- RBXRenderer.scene.background = backgroundColor;
49224
+ renderScene.scene.background = backgroundColor;
49151
49225
  let thumbnailAmbientVal = 138;
49152
49226
  thumbnailAmbientVal = 128;
49153
49227
  let ambientLightColor = void 0;
@@ -49157,8 +49231,8 @@ class RBXRenderer {
49157
49231
  ambientLightColor = new Color(100 / 255, 100 / 255, 100 / 255);
49158
49232
  }
49159
49233
  const ambientLight = new AmbientLight(ambientLightColor, Math.PI / 2);
49160
- RBXRenderer.scene.add(ambientLight);
49161
- RBXRenderer.ambientLight = ambientLight;
49234
+ renderScene.scene.add(ambientLight);
49235
+ renderScene.ambientLight = ambientLight;
49162
49236
  let directionalLightColor = void 0;
49163
49237
  const directionalLightVal = 0.7 * 0.9 * 2 * 0.4;
49164
49238
  if (lightingType === "Thumbnail") {
@@ -49168,7 +49242,7 @@ class RBXRenderer {
49168
49242
  }
49169
49243
  let directionalLightIntensity = 1;
49170
49244
  if (lightingType === "WellLit") {
49171
- directionalLightIntensity = this._wellLitDirectionalLightIntensity;
49245
+ directionalLightIntensity = renderScene._wellLitDirectionalLightIntensity;
49172
49246
  }
49173
49247
  const directionalLight = new DirectionalLight(directionalLightColor, directionalLightIntensity);
49174
49248
  if (lightingType === "WellLit") {
@@ -49177,10 +49251,10 @@ class RBXRenderer {
49177
49251
  directionalLight.position.set(-0.47489210963249207 * 10, 0.8225368857383728 * 10, 0.3129066228866577 * 10);
49178
49252
  }
49179
49253
  if (lightingType === "WellLit") {
49180
- directionalLight.castShadow = RBXRenderer.shadowEnabled;
49254
+ directionalLight.castShadow = renderScene.shadowEnabled;
49181
49255
  }
49182
- directionalLight.shadow.mapSize.width = RBXRenderer.shadowResolution[0];
49183
- directionalLight.shadow.mapSize.height = RBXRenderer.shadowResolution[1];
49256
+ directionalLight.shadow.mapSize.width = renderScene.shadowResolution[0];
49257
+ directionalLight.shadow.mapSize.height = renderScene.shadowResolution[1];
49184
49258
  const bottomOffset = 1.6;
49185
49259
  const shadowPhysicalSize = 5;
49186
49260
  directionalLight.shadow.camera.left = -shadowPhysicalSize;
@@ -49191,20 +49265,20 @@ class RBXRenderer {
49191
49265
  directionalLight.shadow.camera.far = 25;
49192
49266
  directionalLight.shadow.intensity = 0.5;
49193
49267
  directionalLight.target.position.set(0, 0, 0);
49194
- RBXRenderer.scene.add(directionalLight);
49195
- RBXRenderer.directionalLight = directionalLight;
49268
+ renderScene.scene.add(directionalLight);
49269
+ renderScene.directionalLight = directionalLight;
49196
49270
  if (lightingType === "WellLit") {
49197
49271
  const directionalLight2 = new DirectionalLight(16777215, 0.3);
49198
49272
  directionalLight2.position.set(5, -7, 5);
49199
49273
  directionalLight2.target.position.set(0, 0, 0);
49200
- RBXRenderer.scene.add(directionalLight2);
49201
- RBXRenderer.directionalLight2 = directionalLight2;
49274
+ renderScene.scene.add(directionalLight2);
49275
+ renderScene.directionalLight2 = directionalLight2;
49202
49276
  } else if (lightingType === "Thumbnail") {
49203
49277
  const directionalLight2 = new DirectionalLight(directionalLightColor, directionalLightIntensity * 0.5);
49204
49278
  directionalLight2.position.set(-0.47489210963249207 * -10, 0.8225368857383728 * -10, 0.3129066228866577 * -10);
49205
49279
  directionalLight2.target.position.set(0, 0, 0);
49206
- RBXRenderer.scene.add(directionalLight2);
49207
- RBXRenderer.directionalLight2 = directionalLight2;
49280
+ renderScene.scene.add(directionalLight2);
49281
+ renderScene.directionalLight2 = directionalLight2;
49208
49282
  }
49209
49283
  const planeGeometry = new PlaneGeometry(100, 100, 1, 1);
49210
49284
  const planeShadowMaterial = new ShadowMaterial({ opacity: 1 });
@@ -49212,27 +49286,27 @@ class RBXRenderer {
49212
49286
  shadowPlane.rotation.set(rad(-90), 0, 0);
49213
49287
  shadowPlane.position.set(0, 0, 0);
49214
49288
  shadowPlane.receiveShadow = true;
49215
- RBXRenderer.shadowPlane = shadowPlane;
49216
- RBXRenderer.scene.add(shadowPlane);
49289
+ renderScene.shadowPlane = shadowPlane;
49290
+ renderScene.scene.add(shadowPlane);
49217
49291
  const planeSolidColorMaterial = new MeshBasicMaterial({ color: backgroundColor });
49218
49292
  const plane = new Mesh(planeGeometry, planeSolidColorMaterial);
49219
49293
  plane.rotation.set(rad(-90), 0, 0);
49220
49294
  plane.position.set(0, 0, 0);
49221
49295
  plane.receiveShadow = false;
49222
- RBXRenderer.plane = plane;
49223
- RBXRenderer.scene.add(plane);
49296
+ renderScene.plane = plane;
49297
+ renderScene.scene.add(plane);
49224
49298
  }
49225
49299
  /**Sets up orbit controls */
49226
- static setupControls() {
49300
+ static setupControls(renderScene = RBXRenderer.firstScene) {
49227
49301
  if (!RBXRenderer.renderer) return;
49228
- const controls = new OrbitControls(RBXRenderer.camera, RBXRenderer.renderer.domElement);
49302
+ const controls = new OrbitControls(renderScene.camera, RBXRenderer.renderer.domElement);
49229
49303
  controls.maxDistance = 25;
49230
49304
  controls.zoomSpeed = 2;
49231
49305
  controls.target.set(...RBXRenderer.orbitControlsTarget);
49232
49306
  log(false, controls.target);
49233
- RBXRenderer.controls = controls;
49234
- RBXRenderer.camera.position.set(RBXRenderer.lookAwayVector[0] * RBXRenderer.lookAwayDistance, 3 + RBXRenderer.lookAwayVector[1] * RBXRenderer.lookAwayDistance, RBXRenderer.lookAwayVector[2] * RBXRenderer.lookAwayDistance);
49235
- RBXRenderer.camera.lookAt(new Vector3$1(...RBXRenderer.orbitControlsTarget));
49307
+ renderScene.controls = controls;
49308
+ renderScene.camera.position.set(renderScene.lookAwayVector[0] * renderScene.lookAwayDistance, 3 + renderScene.lookAwayVector[1] * renderScene.lookAwayDistance, renderScene.lookAwayVector[2] * renderScene.lookAwayDistance);
49309
+ renderScene.camera.lookAt(new Vector3$1(...RBXRenderer.orbitControlsTarget));
49236
49310
  controls.update();
49237
49311
  }
49238
49312
  /**
@@ -49240,16 +49314,18 @@ class RBXRenderer {
49240
49314
  */
49241
49315
  static setBackgroundColor(colorHex) {
49242
49316
  RBXRenderer.backgroundColorHex = colorHex;
49243
- if (RBXRenderer.backgroundTransparent) {
49244
- RBXRenderer.scene.background = null;
49245
- } else {
49246
- RBXRenderer.scene.background = new Color(RBXRenderer.backgroundColorHex);
49247
- }
49248
- if (RBXRenderer.plane) {
49249
- RBXRenderer.plane.visible = !RBXRenderer.backgroundTransparent;
49250
- }
49251
- if (RBXRenderer.plane) {
49252
- RBXRenderer.plane.material = new MeshBasicMaterial({ color: colorHex });
49317
+ for (const renderScene of RBXRenderer.scenes) {
49318
+ if (RBXRenderer.backgroundTransparent) {
49319
+ renderScene.scene.background = null;
49320
+ } else {
49321
+ renderScene.scene.background = new Color(RBXRenderer.backgroundColorHex);
49322
+ }
49323
+ if (renderScene.plane) {
49324
+ renderScene.plane.visible = !RBXRenderer.backgroundTransparent;
49325
+ }
49326
+ if (renderScene.plane) {
49327
+ renderScene.plane.material = new MeshBasicMaterial({ color: colorHex });
49328
+ }
49253
49329
  }
49254
49330
  }
49255
49331
  /**
@@ -49258,60 +49334,103 @@ class RBXRenderer {
49258
49334
  */
49259
49335
  static setBackgroundTransparent(transparent) {
49260
49336
  RBXRenderer.backgroundTransparent = transparent;
49261
- if (RBXRenderer.backgroundTransparent) {
49262
- RBXRenderer.scene.background = null;
49263
- } else {
49264
- RBXRenderer.scene.background = new Color(RBXRenderer.backgroundColorHex);
49265
- }
49266
- if (RBXRenderer.plane) {
49267
- RBXRenderer.plane.visible = !RBXRenderer.backgroundTransparent;
49337
+ for (const renderScene of RBXRenderer.scenes) {
49338
+ if (RBXRenderer.backgroundTransparent) {
49339
+ renderScene.scene.background = null;
49340
+ } else {
49341
+ renderScene.scene.background = new Color(RBXRenderer.backgroundColorHex);
49342
+ }
49343
+ if (renderScene.plane) {
49344
+ renderScene.plane.visible = !RBXRenderer.backgroundTransparent;
49345
+ }
49268
49346
  }
49269
49347
  }
49270
49348
  /**Makes the renderer render a new frame on every animationFrame */
49271
- static animate() {
49349
+ static animate(shouldRequestAnimationFrame = true) {
49350
+ if (!RBXRenderer.renderer) return;
49351
+ RBXRenderer.renderScene(RBXRenderer.firstScene);
49352
+ if (shouldRequestAnimationFrame) {
49353
+ requestAnimationFrame(() => {
49354
+ RBXRenderer.animate();
49355
+ });
49356
+ }
49357
+ }
49358
+ static animateAll(shouldRequestAnimationFrame = true) {
49359
+ if (!RBXRenderer.renderer) return;
49360
+ for (const renderScene of RBXRenderer.scenes) {
49361
+ RBXRenderer.renderScene(renderScene, renderScene === RBXRenderer.firstScene);
49362
+ }
49363
+ if (shouldRequestAnimationFrame) {
49364
+ requestAnimationFrame(() => {
49365
+ RBXRenderer.animateAll();
49366
+ });
49367
+ }
49368
+ }
49369
+ static renderScene(renderScene, autoClear = true) {
49272
49370
  if (!RBXRenderer.renderer) return;
49371
+ RBXRenderer.renderer.autoClear = autoClear;
49372
+ if (!autoClear) {
49373
+ RBXRenderer.renderer.clearDepth();
49374
+ }
49273
49375
  RBXRenderer.renderer.setRenderTarget(null);
49274
- if (RBXRenderer.effectComposer) {
49275
- RBXRenderer.effectComposer.render();
49376
+ let [x, y] = [0, 0];
49377
+ let [width, height] = RBXRenderer.resolution;
49378
+ if (renderScene.viewport) {
49379
+ x = renderScene.viewport[0];
49380
+ y = renderScene.viewport[1];
49381
+ width = renderScene.viewport[2];
49382
+ height = renderScene.viewport[3];
49383
+ }
49384
+ RBXRenderer.renderer.setViewport(x, y, width, height);
49385
+ if (renderScene.scissor) {
49386
+ RBXRenderer.renderer.setScissorTest(true);
49387
+ RBXRenderer.renderer.setScissor(...renderScene.scissor);
49276
49388
  } else {
49277
- RBXRenderer.renderer.render(RBXRenderer.scene, RBXRenderer.camera);
49389
+ RBXRenderer.renderer.setScissorTest(false);
49278
49390
  }
49279
- requestAnimationFrame(() => {
49280
- RBXRenderer.animate();
49281
- });
49391
+ renderScene.camera.aspect = width / height;
49392
+ renderScene.camera.updateProjectionMatrix();
49393
+ if (width > 0 && height > 0) {
49394
+ if (renderScene.effectComposer) {
49395
+ renderScene.effectComposer.render();
49396
+ } else {
49397
+ RBXRenderer.renderer.render(renderScene.scene, renderScene.camera);
49398
+ }
49399
+ }
49400
+ RBXRenderer.renderer.autoClear = true;
49282
49401
  }
49283
- static _createEffectComposer() {
49402
+ static _createEffectComposer(renderScene = RBXRenderer.firstScene) {
49284
49403
  if (!RBXRenderer.renderer) return;
49285
- RBXRenderer.effectComposer = new EffectComposer(RBXRenderer.renderer);
49286
- const renderPass = new RenderPass(RBXRenderer.scene, RBXRenderer.camera);
49287
- RBXRenderer.effectComposer.addPass(renderPass);
49404
+ renderScene.effectComposer = new EffectComposer(RBXRenderer.renderer);
49405
+ const renderPass = new RenderPass(renderScene.scene, renderScene.camera);
49406
+ renderScene.effectComposer.addPass(renderPass);
49288
49407
  const resolution = new Vector2$1(420, 420);
49289
49408
  const bloomPass = new UnrealBloomPass(resolution, 0.15, 1e-4, 0.9);
49290
- RBXRenderer.effectComposer.addPass(bloomPass);
49409
+ renderScene.effectComposer.addPass(bloomPass);
49291
49410
  if (!FLAGS.POST_PROCESSING_IS_DOUBLE_SIZE) {
49292
49411
  const fxaaPass = new FXAAPass();
49293
- RBXRenderer.effectComposer.addPass(fxaaPass);
49412
+ renderScene.effectComposer.addPass(fxaaPass);
49294
49413
  }
49295
49414
  const outputPass = new OutputPass();
49296
- RBXRenderer.effectComposer.addPass(outputPass);
49415
+ renderScene.effectComposer.addPass(outputPass);
49297
49416
  }
49298
49417
  /**Removes an instance from the renderer */
49299
- static removeInstance(instance) {
49418
+ static removeInstance(instance, renderScene = RBXRenderer.firstScene) {
49300
49419
  if (!RBXRenderer.renderer) return;
49301
- const desc = RBXRenderer.renderDescs.get(instance);
49420
+ const desc = renderScene.renderDescs.get(instance);
49302
49421
  if (desc) {
49303
- desc.dispose(RBXRenderer.renderer, RBXRenderer.scene);
49422
+ desc.dispose(RBXRenderer.renderer, renderScene.scene);
49304
49423
  }
49305
- RBXRenderer.renderDescs.delete(instance);
49306
- RBXRenderer.isRenderingMesh.delete(instance);
49424
+ renderScene.renderDescs.delete(instance);
49425
+ renderScene.isRenderingMesh.delete(instance);
49307
49426
  for (const child of instance.GetChildren()) {
49308
- RBXRenderer.removeInstance(child);
49427
+ RBXRenderer.removeInstance(child, renderScene);
49309
49428
  }
49310
49429
  }
49311
- static _addRenderDesc(instance, auth, DescClass) {
49430
+ static _addRenderDesc(instance, auth, DescClass, renderScene) {
49312
49431
  if (!RBXRenderer.renderer) return;
49313
- const oldDesc = RBXRenderer.renderDescs.get(instance);
49314
- const newDesc = new DescClass();
49432
+ const oldDesc = renderScene.renderDescs.get(instance);
49433
+ const newDesc = new DescClass(renderScene);
49315
49434
  newDesc.fromInstance(instance);
49316
49435
  if (oldDesc && !oldDesc.needsRegeneration(newDesc)) {
49317
49436
  if (!oldDesc.isSame(newDesc)) {
@@ -49319,15 +49438,15 @@ class RBXRenderer {
49319
49438
  oldDesc.updateResults();
49320
49439
  }
49321
49440
  } else {
49322
- if (!RBXRenderer.isRenderingMesh.get(instance)) {
49441
+ if (!renderScene.isRenderingMesh.get(instance)) {
49323
49442
  newDesc.results = oldDesc?.results;
49324
- RBXRenderer.renderDescs.set(instance, newDesc);
49325
- RBXRenderer.isRenderingMesh.set(instance, true);
49326
- newDesc.compileResults(RBXRenderer.renderer, RBXRenderer.scene).then((results) => {
49443
+ renderScene.renderDescs.set(instance, newDesc);
49444
+ renderScene.isRenderingMesh.set(instance, true);
49445
+ newDesc.compileResults(RBXRenderer.renderer, renderScene.scene).then((results) => {
49327
49446
  if (results && !(results instanceof Response)) {
49328
49447
  newDesc.updateResults();
49329
- if (RBXRenderer.renderDescs.get(instance) && RBXRenderer.renderer) {
49330
- oldDesc?.dispose(RBXRenderer.renderer, RBXRenderer.scene);
49448
+ if (renderScene.renderDescs.get(instance) && RBXRenderer.renderer) {
49449
+ oldDesc?.dispose(RBXRenderer.renderer, renderScene.scene);
49331
49450
  for (const result of results) {
49332
49451
  if (result instanceof SkinnedMesh && newDesc instanceof ObjectDesc) {
49333
49452
  const skeleton = newDesc.skeletonDesc?.skeleton;
@@ -49337,20 +49456,20 @@ class RBXRenderer {
49337
49456
  if (FLAGS.USE_LOCAL_SKELETONDESC) {
49338
49457
  result.add(newDesc.skeletonDesc.rootBone);
49339
49458
  } else {
49340
- RBXRenderer.scene.add(newDesc.skeletonDesc.rootBone);
49459
+ renderScene.scene.add(newDesc.skeletonDesc.rootBone);
49341
49460
  }
49342
49461
  }
49343
49462
  result.bind(skeleton);
49344
- RBXRenderer.scene.add(result);
49463
+ renderScene.scene.add(result);
49345
49464
  }
49346
49465
  } else {
49347
- RBXRenderer.scene.add(result);
49466
+ renderScene.scene.add(result);
49348
49467
  }
49349
49468
  }
49350
- RBXRenderer.isRenderingMesh.set(instance, false);
49351
- RBXRenderer.addInstance(instance, auth);
49469
+ renderScene.isRenderingMesh.set(instance, false);
49470
+ RBXRenderer.addInstance(instance, auth, renderScene);
49352
49471
  } else if (RBXRenderer.renderer) {
49353
- newDesc.dispose(RBXRenderer.renderer, RBXRenderer.scene);
49472
+ newDesc.dispose(RBXRenderer.renderer, renderScene.scene);
49354
49473
  }
49355
49474
  } else {
49356
49475
  warn(false, "Failed to compile mesh", this, results);
@@ -49358,17 +49477,17 @@ class RBXRenderer {
49358
49477
  });
49359
49478
  }
49360
49479
  }
49361
- if (!RBXRenderer.destroyConnections.get(instance)) {
49362
- RBXRenderer.destroyConnections.set(instance, instance.Destroying.Connect(() => {
49363
- RBXRenderer.removeInstance(instance);
49364
- const connection = RBXRenderer.destroyConnections.get(instance);
49480
+ if (!renderScene.destroyConnections.get(instance)) {
49481
+ renderScene.destroyConnections.set(instance, instance.Destroying.Connect(() => {
49482
+ RBXRenderer.removeInstance(instance, renderScene);
49483
+ const connection = renderScene.destroyConnections.get(instance);
49365
49484
  connection?.Disconnect();
49366
- RBXRenderer.destroyConnections.delete(instance);
49485
+ renderScene.destroyConnections.delete(instance);
49367
49486
  }));
49368
49487
  }
49369
49488
  }
49370
49489
  /**Adds an instance to the renderer or updates it */
49371
- static addInstance(instance, auth) {
49490
+ static addInstance(instance, auth, renderScene = RBXRenderer.firstScene) {
49372
49491
  const isDecal = instance.className === "Decal";
49373
49492
  const isBakedDecal = isDecal && !instance.FindFirstChildOfClass("WrapTextureTransfer");
49374
49493
  let isFirstDecal = true;
@@ -49381,12 +49500,12 @@ class RBXRenderer {
49381
49500
  }
49382
49501
  }
49383
49502
  if (ObjectDescClassTypes.includes(instance.className) && !isBakedDecal && (!isDecal || isFirstDecal)) {
49384
- RBXRenderer._addRenderDesc(instance, auth, ObjectDesc);
49503
+ RBXRenderer._addRenderDesc(instance, auth, ObjectDesc, renderScene);
49385
49504
  } else if (EmitterGroupDescClassTypes.includes(instance.className)) {
49386
- RBXRenderer._addRenderDesc(instance, auth, EmitterGroupDesc);
49505
+ RBXRenderer._addRenderDesc(instance, auth, EmitterGroupDesc, renderScene);
49387
49506
  }
49388
49507
  for (const child of instance.GetChildren()) {
49389
- RBXRenderer.addInstance(child, auth);
49508
+ RBXRenderer.addInstance(child, auth, renderScene);
49390
49509
  }
49391
49510
  }
49392
49511
  static setRendererSize(width, height) {
@@ -49399,8 +49518,6 @@ class RBXRenderer {
49399
49518
  if (FLAGS.USE_POST_PROCESSING && FLAGS.POST_PROCESSING_IS_DOUBLE_SIZE) {
49400
49519
  RBXRenderer.renderer.setSize(RBXRenderer.resolution[0] * 2, RBXRenderer.resolution[1] * 2);
49401
49520
  }
49402
- RBXRenderer.camera.aspect = width / height;
49403
- RBXRenderer.camera.updateProjectionMatrix();
49404
49521
  }
49405
49522
  /**
49406
49523
  * @deprecated Use getRendererElement instead which includes the loading icon
@@ -49416,11 +49533,12 @@ class RBXRenderer {
49416
49533
  static getRendererElement() {
49417
49534
  return RBXRenderer.canvasContainer;
49418
49535
  }
49536
+ /**@deprecated This can only get the first renderScene's camera */
49419
49537
  static getRendererCamera() {
49420
49538
  return RBXRenderer.camera;
49421
49539
  }
49422
- static getCameraCFrame() {
49423
- const camera = RBXRenderer.camera;
49540
+ static getCameraCFrame(renderScene = RBXRenderer.firstScene) {
49541
+ const camera = renderScene.camera;
49424
49542
  const pos = camera.position;
49425
49543
  let rot = camera.rotation.clone();
49426
49544
  rot = rot.reorder("YXZ");
@@ -49429,34 +49547,36 @@ class RBXRenderer {
49429
49547
  cf.Orientation = [deg(rot.x), deg(rot.y), deg(rot.z)];
49430
49548
  return cf;
49431
49549
  }
49432
- static setCameraCFrame(cameraCF) {
49550
+ static setCameraCFrame(cameraCF, renderScene = RBXRenderer.firstScene) {
49433
49551
  const camPos = new Vector3$1();
49434
49552
  const camQuat = new Quaternion();
49435
49553
  const camScale = new Vector3$1();
49436
49554
  const camMatrix = cameraCF.getTHREEMatrix();
49437
49555
  camMatrix.decompose(camPos, camQuat, camScale);
49438
- RBXRenderer.getRendererCamera().position.set(...camPos.toArray());
49439
- RBXRenderer.getRendererCamera().quaternion.set(...camQuat.toArray());
49440
- RBXRenderer.getRendererCamera().updateMatrixWorld();
49556
+ renderScene.camera.position.set(...camPos.toArray());
49557
+ renderScene.camera.quaternion.set(...camQuat.toArray());
49558
+ renderScene.camera.updateMatrixWorld();
49441
49559
  }
49442
- static setCameraFov(fov2) {
49443
- RBXRenderer.getRendererCamera().fov = fov2;
49560
+ static setCameraFov(fov2, renderScene = RBXRenderer.firstScene) {
49561
+ renderScene.camera.fov = fov2;
49444
49562
  }
49563
+ /**@deprecated This can only get the first renderScene's controls */
49445
49564
  static getRendererControls() {
49446
49565
  return RBXRenderer.controls;
49447
49566
  }
49448
49567
  static getRenderer() {
49449
49568
  return RBXRenderer.renderer;
49450
49569
  }
49570
+ /**@deprecated This can only get the first renderScene's scene */
49451
49571
  static getScene() {
49452
- return RBXRenderer.scene;
49572
+ return RBXRenderer.firstScene;
49453
49573
  }
49454
49574
  /**@deprecated
49455
49575
  * This function is unstable and can throw errors, but might work
49456
49576
  */
49457
- static exportScene() {
49577
+ static exportScene(renderScene = RBXRenderer.firstScene) {
49458
49578
  const exporter = new GLTFExporter();
49459
- exporter.parse(RBXRenderer.scene, (gltf) => {
49579
+ exporter.parse(renderScene.scene, (gltf) => {
49460
49580
  if (gltf instanceof ArrayBuffer) {
49461
49581
  saveByteArray([gltf], "scene.glb");
49462
49582
  } else {
@@ -49545,7 +49665,7 @@ class HSR {
49545
49665
  if (FLAGS.HSR_SHOW_RAY) {
49546
49666
  const geometry = new BufferGeometry().setFromPoints([new Vector3$1(...ray.origin), new Vector3$1(...ray.end)]);
49547
49667
  const line = new Line(geometry, rayHit ? hitMaterial : missMaterial);
49548
- RBXRenderer.getScene().add(line);
49668
+ RBXRenderer.scene.add(line);
49549
49669
  }
49550
49670
  }
49551
49671
  this.innerHits[i] = hits;
@@ -49605,6 +49725,22 @@ function getHigher(a, b) {
49605
49725
  a.Z > b.Z ? a.Z : b.Z
49606
49726
  );
49607
49727
  }
49728
+ function getExtentsForParts(parts, includeTransform) {
49729
+ let lowerExtents = new Vector32(0, 0, 0);
49730
+ let higherExtents = new Vector32(0, 0, 0);
49731
+ for (const child of parts) {
49732
+ if (child.className === "Part" || child.className === "MeshPart") {
49733
+ const cframe = traverseRigCFrame(child, includeTransform, true);
49734
+ const size = child.Prop("Size");
49735
+ const corners = getCorners(cframe, size);
49736
+ for (const corner of corners) {
49737
+ lowerExtents = getLower(lowerExtents, new Vector32().fromVec3(corner.Position));
49738
+ higherExtents = getHigher(higherExtents, new Vector32().fromVec3(corner.Position));
49739
+ }
49740
+ }
49741
+ }
49742
+ return [lowerExtents, higherExtents];
49743
+ }
49608
49744
  function getExtents(cframe, parts) {
49609
49745
  const inverseCF = cframe.inverse();
49610
49746
  let lowerExtents = new Vector32(0, 0, 0);
@@ -49679,7 +49815,6 @@ class OutfitRenderer {
49679
49815
  currentRig;
49680
49816
  /**Instance for the Model of the current outfit */
49681
49817
  currentRigType;
49682
- rigPath;
49683
49818
  doCameraUpdateOnLoad = true;
49684
49819
  /**Makes camera update when new avatar has loaded */
49685
49820
  doCameraUpdate = false;
@@ -49691,17 +49826,18 @@ class OutfitRenderer {
49691
49826
  animationInterval;
49692
49827
  animationFPS = 60;
49693
49828
  deltaTimeMultiplier = 1;
49829
+ renderScene = RBXRenderer.firstScene;
49694
49830
  /**
49695
49831
  * Creates a new OutfitRenderer which makes it easy to render outfits
49696
49832
  * @param auth The authentication object, you should have one you use for everything
49697
49833
  * @param outfit The outfit you want to render, it can be updated later by calling setOutfit()
49698
- * @param rigPath The path that contains RigR6.rbxm and RigR15.rbxm, should always be "roavatar://" as rig path is now controlled by FLAGS
49834
+ * @param renderScene The scene the outfit should be rendered in
49699
49835
  */
49700
- constructor(auth, outfit, rigPath = "roavatar://") {
49836
+ constructor(auth, outfit, renderScene = RBXRenderer.firstScene) {
49701
49837
  this.auth = auth;
49702
49838
  this.outfit = outfit;
49703
49839
  this.currentRigType = outfit.playerAvatarType;
49704
- this.rigPath = rigPath;
49840
+ this.renderScene = renderScene;
49705
49841
  this._updateOutfit();
49706
49842
  }
49707
49843
  /**
@@ -49716,12 +49852,12 @@ class OutfitRenderer {
49716
49852
  this.currentRig = void 0;
49717
49853
  }
49718
49854
  this.currentRigType = newRigType;
49719
- API.Asset.GetRBX(`${this.rigPath}Rig${this.currentRigType}.rbxm`, void 0).then((result) => {
49855
+ API.Asset.GetRBX(`roavatar://Rig${this.currentRigType}.rbxm`, void 0).then((result) => {
49720
49856
  if (result instanceof RBX) {
49721
49857
  const newRig = result.generateTree().GetChildren()[0];
49722
49858
  this.currentRig = newRig;
49723
49859
  this.currentlyChangingRig = false;
49724
- RBXRenderer.addInstance(this.currentRig, this.auth);
49860
+ RBXRenderer.addInstance(this.currentRig, this.auth, this.renderScene);
49725
49861
  resolve(newRig);
49726
49862
  } else {
49727
49863
  resolve(result);
@@ -49754,7 +49890,7 @@ class OutfitRenderer {
49754
49890
  hrpWrapper.applyDescription(humanoid).then((result) => {
49755
49891
  this.currentlyUpdating = false;
49756
49892
  if (this.currentRig) {
49757
- RBXRenderer.addInstance(this.currentRig, this.auth);
49893
+ RBXRenderer.addInstance(this.currentRig, this.auth, this.renderScene);
49758
49894
  if (this.doCameraUpdateOnLoad) {
49759
49895
  this.centerCamera();
49760
49896
  }
@@ -49791,8 +49927,8 @@ class OutfitRenderer {
49791
49927
  if (this.currentRig) {
49792
49928
  const upperTorso = this.currentRig.FindFirstChild("HumanoidRootPart");
49793
49929
  if (upperTorso) {
49794
- const controls = RBXRenderer.getRendererControls();
49795
- const camera = RBXRenderer.getRendererCamera();
49930
+ const controls = this.renderScene.controls;
49931
+ const camera = this.renderScene.camera;
49796
49932
  const pos = upperTorso.Prop("Position");
49797
49933
  if (controls) {
49798
49934
  const offset = new Vector3$1().subVectors(camera.position, controls.target);
@@ -49823,7 +49959,7 @@ class OutfitRenderer {
49823
49959
  const animatorW = new AnimatorWrapper(animator);
49824
49960
  animatorW.renderAnimation(deltaTime);
49825
49961
  this.currentRig.preRender();
49826
- RBXRenderer.addInstance(this.currentRig, this.auth);
49962
+ RBXRenderer.addInstance(this.currentRig, this.auth, this.renderScene);
49827
49963
  }
49828
49964
  }
49829
49965
  }
@@ -49867,6 +50003,7 @@ export {
49867
50003
  AccessoryAssetTypes,
49868
50004
  AccessoryDescriptionWrapper,
49869
50005
  AccessoryType,
50006
+ AccessoryWrapper,
49870
50007
  ActualBundleTypes,
49871
50008
  AllAccessorySorts,
49872
50009
  AllAnimationSorts,
@@ -49878,6 +50015,7 @@ export {
49878
50015
  AllHeadShapes,
49879
50016
  AllInstances,
49880
50017
  AlphaMode,
50018
+ AnimationConstraintWrapper,
49881
50019
  AnimationPropToName,
49882
50020
  AnimationTrack,
49883
50021
  AnimatorWrapper,
@@ -49892,6 +50030,7 @@ export {
49892
50030
  AvatarType,
49893
50031
  BodyColor3s,
49894
50032
  BodyColors,
50033
+ BodyColorsWrapper,
49895
50034
  BodyPart,
49896
50035
  BodyPartDescriptionWrapper,
49897
50036
  BodyPartEnumToNames,
@@ -49911,6 +50050,7 @@ export {
49911
50050
  Content,
49912
50051
  ContentMap,
49913
50052
  DataType,
50053
+ DecalWrapper,
49914
50054
  DefaultAnimations,
49915
50055
  DefaultAnimationsR6,
49916
50056
  DefaultGetWorkerFunc,
@@ -49937,10 +50077,12 @@ export {
49937
50077
  MakeupAssetTypes,
49938
50078
  MakeupDescriptionWrapper,
49939
50079
  MakeupType,
50080
+ ManualWeldWrapper,
49940
50081
  MaxOneOfAssetTypes,
49941
50082
  MaxPerAsset,
49942
50083
  MeshType,
49943
50084
  ModelWrapper,
50085
+ Motor6DWrapper,
49944
50086
  NeverLayeredAccessoryTypes,
49945
50087
  NormalId,
49946
50088
  NumberRange,
@@ -49957,6 +50099,7 @@ export {
49957
50099
  RBFDeformerPatch,
49958
50100
  RBX,
49959
50101
  RBXRenderer,
50102
+ RBXRendererScene,
49960
50103
  RNG,
49961
50104
  Ray3 as Ray,
49962
50105
  RegisterWrappers,
@@ -49984,6 +50127,7 @@ export {
49984
50127
  Vector32 as Vector3,
49985
50128
  Wait,
49986
50129
  WearableAssetTypes,
50130
+ WeldWrapper,
49987
50131
  WorkerTypeToFunction,
49988
50132
  WrapLayerAutoSkin,
49989
50133
  accessoryRefinementLowerBounds,
@@ -50022,11 +50166,14 @@ export {
50022
50166
  download,
50023
50167
  exposeAPI,
50024
50168
  exposeMesh,
50169
+ fileMeshToTHREEGeometry,
50025
50170
  floor,
50026
50171
  gaussian_rbf,
50027
50172
  generateUUIDv4,
50028
50173
  getCameraCFrameForHeadshotCustomized,
50029
50174
  getDistIndexArray,
50175
+ getExtents,
50176
+ getExtentsForParts,
50030
50177
  getHeadExtents,
50031
50178
  getOffsetArray,
50032
50179
  getOriginalSize,
@@ -50082,5 +50229,6 @@ export {
50082
50229
  triangleNormal,
50083
50230
  versionToNumber,
50084
50231
  vertPosToChunkPos,
50085
- xmlMagic
50232
+ xmlMagic,
50233
+ zoomExtents
50086
50234
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "roavatar-renderer",
3
- "version": "1.2.16",
3
+ "version": "1.3.1",
4
4
  "description": "A renderer for Roblox avatars, used by the RoAvatar extension.",
5
5
  "author": "steinan",
6
6
  "type": "module",