roavatar-renderer 1.5.4 → 1.5.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
@@ -1530,7 +1530,7 @@ export declare function getOriginalAttachmentPosition(attachment: Instance): Vec
1530
1530
 
1531
1531
  export declare function getOriginalSize(part: Instance): Vector3;
1532
1532
 
1533
- export declare function getRandomBetweenInclusive(min: number, max: number): number;
1533
+ export declare function getRandomBetweenInclusive(min: number, max: number, randomVal?: number): number;
1534
1534
 
1535
1535
  export declare function getRigExtentsWorld(rig: Instance): [Vector3, Vector3];
1536
1536
 
@@ -2187,7 +2187,7 @@ export declare type Mat3x3 = [number, number, number, number, number, number, nu
2187
2187
  /** @category Mesh */
2188
2188
  export declare type Mat4x4 = [number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number];
2189
2189
 
2190
- export declare function mathRandom(min: number, max: number): number;
2190
+ export declare function mathRandom(min: number, max: number, randomVal?: number): number;
2191
2191
 
2192
2192
  /** @category Outfit */
2193
2193
  export declare const MaxOneOfAssetTypes: string[];
@@ -2637,6 +2637,23 @@ export declare const ParticleEmitterShapeInOut: {
2637
2637
  InAndOut: number;
2638
2638
  };
2639
2639
 
2640
+ /**@category DataModelEnum */
2641
+ export declare const ParticleFlipbookLayout: {
2642
+ None: number;
2643
+ Grid2x2: number;
2644
+ Grid4x4: number;
2645
+ Grid8x8: number;
2646
+ Custom: number;
2647
+ };
2648
+
2649
+ /**@category DataModelEnum */
2650
+ export declare const ParticleFlipbookMode: {
2651
+ Loop: number;
2652
+ OneShot: number;
2653
+ PingPong: number;
2654
+ Random: number;
2655
+ };
2656
+
2640
2657
  /**@category DataModelEnum */
2641
2658
  export declare const ParticleOrientation: {
2642
2659
  FacingCamera: number;
package/dist/index.js CHANGED
@@ -27478,6 +27478,19 @@ class RBXSimpleView {
27478
27478
  }
27479
27479
  const magic = "<roblox!";
27480
27480
  const xmlMagic = "<roblox ";
27481
+ const ParticleFlipbookLayout = {
27482
+ "None": 0,
27483
+ "Grid2x2": 1,
27484
+ "Grid4x4": 2,
27485
+ "Grid8x8": 3,
27486
+ "Custom": 4
27487
+ };
27488
+ const ParticleFlipbookMode = {
27489
+ "Loop": 0,
27490
+ "OneShot": 1,
27491
+ "PingPong": 2,
27492
+ "Random": 3
27493
+ };
27481
27494
  const PartType = {
27482
27495
  "Ball": 0,
27483
27496
  "Block": 1,
@@ -29886,7 +29899,7 @@ const FLAGS = {
29886
29899
  ENABLE_API_RBX_CACHE: true,
29887
29900
  ROAVATAR_DATA_URL: "rbxassetid://102463700065175",
29888
29901
  //url of model to load that lists issues with specific versions
29889
- ROAVATAR_TRYON_PLACE: 135979364355750,
29902
+ ROAVATAR_TRYON_PLACE: 122920847927474,
29890
29903
  ASSETDELIVERY_V2: true,
29891
29904
  ASSET_REQUEST_PRIORITY: "high",
29892
29905
  API_DOMAIN: "roblox.com",
@@ -32164,11 +32177,11 @@ async function Wait(time2) {
32164
32177
  }, time2 * 1e3);
32165
32178
  });
32166
32179
  }
32167
- function getRandomBetweenInclusive(min, max) {
32168
- return Math.random() * (max + 1 - min) + min;
32180
+ function getRandomBetweenInclusive(min, max, randomVal = Math.random()) {
32181
+ return randomVal * (max + 1 - min) + min;
32169
32182
  }
32170
- function mathRandom(min, max) {
32171
- return Math.floor(getRandomBetweenInclusive(min, max));
32183
+ function mathRandom(min, max, randomVal = Math.random()) {
32184
+ return Math.floor(getRandomBetweenInclusive(min, max, randomVal));
32172
32185
  }
32173
32186
  async function imageUrlToDataUrl(imageUrl) {
32174
32187
  const response = await fetch(imageUrl);
@@ -42574,12 +42587,12 @@ class ModelLayersDesc {
42574
42587
  }
42575
42588
  for (const deformer of this.targetDeformers) {
42576
42589
  if (deformer) {
42577
- meshPromises.push(promiseForMesh(deformer.targetCage));
42590
+ meshPromises.push(promiseForMesh(deformer.targetCage, true));
42578
42591
  }
42579
42592
  }
42580
42593
  for (const enclosedLayer of this.layers) {
42581
- meshPromises.push(promiseForMesh(enclosedLayer.cage));
42582
- meshPromises.push(promiseForMesh(enclosedLayer.reference));
42594
+ meshPromises.push(promiseForMesh(enclosedLayer.cage, true));
42595
+ meshPromises.push(promiseForMesh(enclosedLayer.reference, true));
42583
42596
  if (enclosedLayer.mesh) meshPromises.push(promiseForMesh(enclosedLayer.mesh, true));
42584
42597
  }
42585
42598
  const values = await Promise.all(meshPromises);
@@ -42600,14 +42613,14 @@ class ModelLayersDesc {
42600
42613
  inheritSkeleton(targetCage, targetMesh);
42601
42614
  }
42602
42615
  const distDeformer = this.targetDeformers[0];
42603
- const dist_mesh = distDeformer ? meshMap.get(distDeformer.targetCage).clone() : meshMap.get(this.targetCages[0]);
42616
+ const dist_mesh = distDeformer ? meshMap.get(distDeformer.targetCage).clone() : meshMap.get(this.targetCages[0]).clone();
42604
42617
  const dist_mesh_mesh = meshMap.get(this.targetMeshes[0]);
42605
42618
  offsetMesh(dist_mesh, this.targetOffsets[0]);
42606
42619
  scaleMesh(dist_mesh, this.targetSizes[0].divide(new Vector32().fromVec3(dist_mesh_mesh.size)));
42607
42620
  offsetMesh(dist_mesh, this.targetCFrames[0]);
42608
42621
  for (let i = 1; i < this.targetCages.length; i++) {
42609
42622
  const deformer = this.targetDeformers[i];
42610
- const targetCage = deformer ? meshMap.get(deformer.targetCage).clone() : meshMap.get(this.targetCages[i]);
42623
+ const targetCage = deformer ? meshMap.get(deformer.targetCage).clone() : meshMap.get(this.targetCages[i]).clone();
42611
42624
  const targetMesh = meshMap.get(this.targetMeshes[i]);
42612
42625
  offsetMesh(targetCage, this.targetOffsets[i]);
42613
42626
  scaleMesh(targetCage, this.targetSizes[i].divide(new Vector32().fromVec3(targetMesh.size)));
@@ -42619,8 +42632,8 @@ class ModelLayersDesc {
42619
42632
  targetMeshes.push(dist_mesh.clone());
42620
42633
  const uvToHits = [];
42621
42634
  for (const layer of this.layers) {
42622
- const cage = meshMap.get(layer.cage);
42623
- const reference = meshMap.get(layer.reference);
42635
+ const cage = meshMap.get(layer.cage)?.clone();
42636
+ const reference = meshMap.get(layer.reference)?.clone();
42624
42637
  if (!cage || !reference) {
42625
42638
  throw new Error("this isnt possible, shut up typescript");
42626
42639
  }
@@ -42795,8 +42808,8 @@ class HSRDesc {
42795
42808
  const cacheId = `${layer.mesh}-${layer.reference}-${layer.cage}`;
42796
42809
  const cacheEntry = FLAGS.CACHE_HSR_HITS ? CACHE_uvToHits.get(cacheId) : void 0;
42797
42810
  if (!cacheEntry) {
42798
- meshPromises.push(promiseForMesh(enclosedLayer.cage));
42799
- meshPromises.push(promiseForMesh(enclosedLayer.reference));
42811
+ meshPromises.push(promiseForMesh(enclosedLayer.cage, true));
42812
+ meshPromises.push(promiseForMesh(enclosedLayer.reference, true));
42800
42813
  if (enclosedLayer.mesh) meshPromises.push(promiseForMesh(enclosedLayer.mesh, true));
42801
42814
  }
42802
42815
  }
@@ -42816,8 +42829,8 @@ class HSRDesc {
42816
42829
  const cacheEntry = FLAGS.CACHE_HSR_HITS ? CACHE_uvToHits.get(cacheId) : void 0;
42817
42830
  const latestUvToHitsMap = cacheEntry ? cacheEntry : /* @__PURE__ */ new Map();
42818
42831
  if (!cacheEntry && !isTransparent) {
42819
- const cage = meshMap.get(layer.cage);
42820
- const reference = meshMap.get(layer.reference);
42832
+ const cage = meshMap.get(layer.cage)?.clone();
42833
+ const reference = meshMap.get(layer.reference)?.clone();
42821
42834
  const mesh = layer.mesh ? meshMap.get(layer.mesh) : void 0;
42822
42835
  if (!cage || !reference) {
42823
42836
  throw new Error("this isnt possible, shut up typescript");
@@ -48262,6 +48275,11 @@ class HumanoidDescriptionWrapper extends InstanceWrapper {
48262
48275
  } else {
48263
48276
  const head2 = dataModel.FindFirstChildOfClass("MeshPart");
48264
48277
  if (head2) {
48278
+ for (const childChild of head2.GetChildren()) {
48279
+ if (childChild.w?.IsA("Weld") || childChild.w?.IsA("AnimationConstraint")) {
48280
+ childChild.Destroy();
48281
+ }
48282
+ }
48265
48283
  replaceBodyPart(rig, head2);
48266
48284
  }
48267
48285
  }
@@ -49365,13 +49383,16 @@ const __vite_glob_0_0 = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.def
49365
49383
  }, Symbol.toStringTag, { value: "Module" }));
49366
49384
  const particle_vertexShader = `
49367
49385
  attribute vec3 instanceColor;
49368
- attribute vec2 instanceSeedTime;
49386
+ attribute vec3 instanceSeedTime;
49369
49387
  attribute float instanceOpacity;
49388
+ attribute vec4 instanceFlipbook;
49370
49389
 
49371
49390
  varying vec2 vUv;
49372
49391
  varying vec3 vInstanceColor;
49373
49392
  varying float vInstanceOpacity;
49374
- varying vec2 vInstanceSeedTime;
49393
+ varying vec3 vInstanceSeedTime;
49394
+ varying vec2 vFlipbookUv0;
49395
+ varying vec2 vFlipbookUv1;
49375
49396
 
49376
49397
  uniform float uZOffset;
49377
49398
 
@@ -49380,6 +49401,8 @@ void main() {
49380
49401
  vInstanceColor = instanceColor;
49381
49402
  vInstanceOpacity = instanceOpacity;
49382
49403
  vInstanceSeedTime = instanceSeedTime;
49404
+ vFlipbookUv0 = instanceFlipbook.xy;
49405
+ vFlipbookUv1 = instanceFlipbook.zw;
49383
49406
 
49384
49407
  vec4 modelViewPosition = modelViewMatrix * instanceMatrix * vec4(position, 1.0);
49385
49408
 
@@ -49393,19 +49416,28 @@ const particle_fragmentShader = `
49393
49416
  varying vec2 vUv;
49394
49417
  varying vec3 vInstanceColor;
49395
49418
  varying float vInstanceOpacity;
49396
- varying vec2 vInstanceSeedTime;
49419
+ varying vec3 vInstanceSeedTime;
49420
+ varying vec2 vFlipbookUv0;
49421
+ varying vec2 vFlipbookUv1;
49397
49422
 
49398
49423
  uniform sampler2D uColorMap;
49399
49424
  uniform sampler2D uAlphaMap;
49400
49425
  uniform sampler2D uMap;
49401
49426
  uniform float uOpacity;
49427
+ uniform vec2 uFlipbookSize;
49402
49428
 
49403
49429
  void main() {
49404
49430
  float seed = vInstanceSeedTime.x;
49405
49431
  float time = vInstanceSeedTime.y;
49432
+ float flipbookFrameTime = vInstanceSeedTime.z;
49433
+
49434
+ // Sample the texture using the UV coordinates (for both frames)
49435
+ vec4 texColor0 = texture2D(uMap, vUv * uFlipbookSize + vFlipbookUv0);
49436
+ vec4 texColor1 = texture2D(uMap, vUv * uFlipbookSize + vFlipbookUv1);
49437
+
49438
+ float frameTransition = mod(time, flipbookFrameTime) / flipbookFrameTime;
49439
+ vec4 texColor = texColor0 * (1.0 - frameTransition) + texColor1 * frameTransition;
49406
49440
 
49407
- // Sample the texture using the UV coordinates
49408
- vec4 texColor = texture2D(uMap, vUv);
49409
49441
  vec4 alphaTex = texture2D(uAlphaMap, vec2(time, seed));
49410
49442
  vec4 colorTex = texture2D(uColorMap, vec2(time, seed));
49411
49443
 
@@ -49415,6 +49447,8 @@ void main() {
49415
49447
  // Apply opacity to the texture alpha
49416
49448
  vec4 opacityColor = tintedColor * vec4(1.0, 1.0, 1.0, uOpacity * vInstanceOpacity) * alphaTex.r;
49417
49449
 
49450
+ //#ADDITIVE_INSERT
49451
+
49418
49452
  // Apply that weird color things sparkles have
49419
49453
  vec4 finalColor = opacityColor;
49420
49454
  finalColor.rgb = mix(opacityColor.rgb, opacityColor.rgb * colorTex.rgb, colorTex.a);
@@ -49422,6 +49456,12 @@ void main() {
49422
49456
  gl_FragColor = finalColor;
49423
49457
  }
49424
49458
  `;
49459
+ const particle_fragmentShader_additive = particle_fragmentShader.replace(
49460
+ "//#ADDITIVE_INSERT",
49461
+ `if (opacityColor.r + opacityColor.g + opacityColor.b <= 0.05) {
49462
+ discard;
49463
+ }`
49464
+ );
49425
49465
  function randomBetween(min, max) {
49426
49466
  return Math.random() * (max - min) + min;
49427
49467
  }
@@ -49450,17 +49490,22 @@ class Particle {
49450
49490
  this.velocity = velocity;
49451
49491
  this.rotationSpeed = rotationSpeed;
49452
49492
  }
49493
+ get intSeed() {
49494
+ return Math.floor(this.seed * 1e6);
49495
+ }
49453
49496
  camDistance(renderScene) {
49454
49497
  const cameraPos = new Vector32(...renderScene.camera.position.toArray());
49455
49498
  const particlePos = this.position;
49456
49499
  const distance2 = cameraPos.minus(particlePos).magnitude();
49457
49500
  return distance2;
49458
49501
  }
49459
- getMatrix(renderScene, size, orientation) {
49502
+ getMatrix(renderScene, size, orientation, squash) {
49460
49503
  const camera = renderScene.camera;
49461
49504
  const particlePos = new Vector3$1(...this.position.toVec3());
49462
49505
  const translation = new Matrix4().makeTranslation(particlePos);
49463
- const scale = new Matrix4().makeScale(size, size, 1);
49506
+ const sizeX = squash > 0 ? size / (1 + squash) : size * (1 - squash);
49507
+ const sizeY = squash > 0 ? size * (1 + squash) : size / (1 - squash);
49508
+ const scale = new Matrix4().makeScale(sizeX, sizeY, 1);
49464
49509
  switch (orientation) {
49465
49510
  case ParticleOrientation.FacingCameraWorldUp: {
49466
49511
  const cameraLookVector = new Vector3$1();
@@ -49490,13 +49535,29 @@ class Particle {
49490
49535
  return final;
49491
49536
  }
49492
49537
  case ParticleOrientation.VelocityParallel: {
49493
- const normalizedVelocity = new Vector3$1(...this.velocity.normalize().toVec3());
49494
- const rotationParticlePosMatrix = new Matrix4().lookAt(particlePos, camera.position, normalizedVelocity);
49495
- const _pos = new Vector3$1();
49496
- const _scale = new Vector3$1();
49497
- const rotationQuat = new Quaternion();
49498
- rotationParticlePosMatrix.decompose(_pos, rotationQuat, _scale);
49499
- const rotation = new Matrix4().makeRotationFromQuaternion(rotationQuat);
49538
+ const toCamera = new Vector3$1(0, 0, -1).applyQuaternion(camera.quaternion);
49539
+ const velocityVector = new Vector3$1(...this.velocity.toVec3());
49540
+ const vY = velocityVector.normalize();
49541
+ const vX = new Vector3$1().crossVectors(toCamera.normalize(), vY).normalize();
49542
+ const vZ = new Vector3$1().crossVectors(vX, vY).normalize();
49543
+ const rotation = new Matrix4().set(
49544
+ vX.x,
49545
+ vY.x,
49546
+ vZ.x,
49547
+ 0,
49548
+ vX.y,
49549
+ vY.y,
49550
+ vZ.y,
49551
+ 0,
49552
+ vX.z,
49553
+ vY.z,
49554
+ vZ.z,
49555
+ 0,
49556
+ 0,
49557
+ 0,
49558
+ 0,
49559
+ 1
49560
+ );
49500
49561
  const flatRotation = new Matrix4().makeRotationAxis(new Vector3$1(0, 0, 1), rad(this.rotation + 90));
49501
49562
  const final = translation.multiply(rotation).multiply(flatRotation).multiply(scale);
49502
49563
  return final;
@@ -49510,6 +49571,30 @@ class Particle {
49510
49571
  }
49511
49572
  }
49512
49573
  }
49574
+ getFlipbookIndex(total, isNext, framerate, mode, startRandom) {
49575
+ const rng = new RNG(this.intSeed + 324);
49576
+ const randomVal = rng.nextFloat();
49577
+ let offset = startRandom ? mathRandom(0, total - 1, randomVal) : 0;
49578
+ switch (mode) {
49579
+ case ParticleFlipbookMode.Loop:
49580
+ offset += Math.floor(this.time * framerate);
49581
+ break;
49582
+ case ParticleFlipbookMode.OneShot:
49583
+ offset += Math.round(this.time * total);
49584
+ break;
49585
+ case ParticleFlipbookMode.PingPong:
49586
+ offset += Math.floor(this.time * framerate);
49587
+ break;
49588
+ case ParticleFlipbookMode.Random:
49589
+ offset += mathRandom(0, total - 1, new RNG(this.intSeed + 334 + Math.floor(this.time * framerate)).nextFloat());
49590
+ break;
49591
+ }
49592
+ if (isNext) offset += 1;
49593
+ if (offset >= total) {
49594
+ offset %= total;
49595
+ }
49596
+ return offset;
49597
+ }
49513
49598
  tick(dt, drag, acceleration) {
49514
49599
  this.time += specialClamp(dt, 0, this.lifetime);
49515
49600
  this.position = this.position.add(this.velocity.multiply(new Vector32(dt, dt, dt)));
@@ -49542,8 +49627,16 @@ class EmitterDesc extends DisposableDesc {
49542
49627
  blending = AdditiveBlending;
49543
49628
  color = new ColorSequence();
49544
49629
  size = new NumberSequence();
49630
+ squash = new NumberSequence([new NumberSequenceKeypoint(0, 0, 0)]);
49545
49631
  transparency = new NumberSequence([new NumberSequenceKeypoint(0, 0, 0)]);
49546
49632
  normalizeSizeKeypointTime = true;
49633
+ flipbookLayout = ParticleFlipbookLayout.None;
49634
+ flipbookBlendFrames = true;
49635
+ flipbookFramerate = new NumberRange(1, 1);
49636
+ flipbookMode = ParticleFlipbookMode.Loop;
49637
+ flipbookSizeX = 1;
49638
+ flipbookSizeY = 1;
49639
+ flipbookStartRandom = false;
49547
49640
  //requires recompilation
49548
49641
  rate = 10;
49549
49642
  colorTexture;
@@ -49553,7 +49646,9 @@ class EmitterDesc extends DisposableDesc {
49553
49646
  instanceOpacityBuffer;
49554
49647
  instanceColorBuffer;
49555
49648
  instanceSeedTimeBuffer;
49649
+ instanceFlipbookBuffer;
49556
49650
  result;
49651
+ resultMaterial;
49557
49652
  particles = [];
49558
49653
  initialParticleCount = 0;
49559
49654
  get maxCount() {
@@ -49565,7 +49660,7 @@ class EmitterDesc extends DisposableDesc {
49565
49660
  return this.texture === other.texture && this.alphaTexture === other.alphaTexture && this.colorTexture === other.colorTexture && this.rate === other.rate;
49566
49661
  }
49567
49662
  isSame(other) {
49568
- return !this.needsRegeneration(other) && this.lockedToPart === other.lockedToPart && this.lifetime.isSame(other.lifetime) && this.spreadAngle.isSame(other.spreadAngle) && this.speed.isSame(other.speed) && this.rotation.isSame(other.rotation) && this.rotationSpeed.isSame(other.rotationSpeed) && this.localAcceleration.isSame(other.localAcceleration) && this.acceleration.isSame(other.acceleration) && this.drag === other.drag && this.timeScale === other.timeScale && this.orientation === other.orientation && this.zOffset === other.zOffset && this.offset.isSame(other.offset) && this.shapeInOut === other.shapeInOut && this.opacity === other.opacity && this.lightEmission === other.lightEmission && this.blending === other.blending && this.color.isSame(other.color) && this.size.isSame(other.size) && this.transparency.isSame(other.transparency) && this.normalizeSizeKeypointTime === other.normalizeSizeKeypointTime;
49663
+ return !this.needsRegeneration(other) && this.lockedToPart === other.lockedToPart && this.lifetime.isSame(other.lifetime) && this.spreadAngle.isSame(other.spreadAngle) && this.speed.isSame(other.speed) && this.rotation.isSame(other.rotation) && this.rotationSpeed.isSame(other.rotationSpeed) && this.localAcceleration.isSame(other.localAcceleration) && this.acceleration.isSame(other.acceleration) && this.drag === other.drag && this.timeScale === other.timeScale && this.orientation === other.orientation && this.zOffset === other.zOffset && this.offset.isSame(other.offset) && this.shapeInOut === other.shapeInOut && this.opacity === other.opacity && this.lightEmission === other.lightEmission && this.blending === other.blending && this.color.isSame(other.color) && this.size.isSame(other.size) && this.squash.isSame(other.squash) && this.transparency.isSame(other.transparency) && this.normalizeSizeKeypointTime === other.normalizeSizeKeypointTime && this.flipbookLayout === other.flipbookLayout && this.flipbookBlendFrames === other.flipbookBlendFrames && this.flipbookFramerate.isSame(other.flipbookFramerate) && this.flipbookMode === other.flipbookMode && this.flipbookSizeX === other.flipbookSizeX && this.flipbookSizeY === other.flipbookSizeY && this.flipbookStartRandom === other.flipbookStartRandom;
49569
49664
  }
49570
49665
  fromEmitterDesc(other) {
49571
49666
  this.lockedToPart = other.lockedToPart;
@@ -49588,8 +49683,16 @@ class EmitterDesc extends DisposableDesc {
49588
49683
  this.blending = other.blending;
49589
49684
  this.color = other.color.clone();
49590
49685
  this.size = other.size.clone();
49686
+ this.squash = other.squash.clone();
49591
49687
  this.transparency = other.transparency.clone();
49592
49688
  this.normalizeSizeKeypointTime = other.normalizeSizeKeypointTime;
49689
+ this.flipbookLayout = other.flipbookLayout;
49690
+ this.flipbookBlendFrames = other.flipbookBlendFrames;
49691
+ this.flipbookFramerate = other.flipbookFramerate.clone();
49692
+ this.flipbookMode = other.flipbookMode;
49693
+ this.flipbookSizeX = other.flipbookSizeX;
49694
+ this.flipbookSizeY = other.flipbookSizeY;
49695
+ this.flipbookStartRandom = other.flipbookStartRandom;
49593
49696
  }
49594
49697
  dispose(renderer, scene) {
49595
49698
  const mesh = this.result;
@@ -49613,6 +49716,31 @@ class EmitterDesc extends DisposableDesc {
49613
49716
  }
49614
49717
  return void 0;
49615
49718
  }
49719
+ getFlipbookSize() {
49720
+ let flipbookSizeX = this.flipbookSizeX;
49721
+ let flipbookSizeY = this.flipbookSizeY;
49722
+ switch (this.flipbookLayout) {
49723
+ case ParticleFlipbookLayout.None:
49724
+ flipbookSizeX = 1;
49725
+ flipbookSizeY = 1;
49726
+ break;
49727
+ case ParticleFlipbookLayout.Grid2x2:
49728
+ flipbookSizeX = 2;
49729
+ flipbookSizeY = 2;
49730
+ break;
49731
+ case ParticleFlipbookLayout.Grid4x4:
49732
+ flipbookSizeX = 4;
49733
+ flipbookSizeY = 4;
49734
+ break;
49735
+ case ParticleFlipbookLayout.Grid8x8:
49736
+ flipbookSizeX = 8;
49737
+ flipbookSizeY = 8;
49738
+ break;
49739
+ case ParticleFlipbookLayout.Custom:
49740
+ break;
49741
+ }
49742
+ return [flipbookSizeX, flipbookSizeY];
49743
+ }
49616
49744
  async compileResult(renderer, scene) {
49617
49745
  const originalResult = this.result;
49618
49746
  const texturePromises = [
@@ -49638,8 +49766,11 @@ class EmitterDesc extends DisposableDesc {
49638
49766
  geometry.setAttribute("instanceColor", this.instanceColorBuffer);
49639
49767
  this.instanceOpacityBuffer = new InstancedBufferAttribute(new Float32Array(this.maxCount), 1);
49640
49768
  geometry.setAttribute("instanceOpacity", this.instanceOpacityBuffer);
49641
- this.instanceSeedTimeBuffer = new InstancedBufferAttribute(new Float32Array(this.maxCount), 2);
49769
+ this.instanceSeedTimeBuffer = new InstancedBufferAttribute(new Float32Array(this.maxCount * 3), 3);
49642
49770
  geometry.setAttribute("instanceSeedTime", this.instanceSeedTimeBuffer);
49771
+ this.instanceFlipbookBuffer = new InstancedBufferAttribute(new Float32Array(this.maxCount * 4), 4);
49772
+ geometry.setAttribute("instanceFlipbook", this.instanceFlipbookBuffer);
49773
+ const [flipbookSizeX, flipbookSizeY] = this.getFlipbookSize();
49643
49774
  const material = new ShaderMaterial({
49644
49775
  transparent: true,
49645
49776
  depthWrite: false,
@@ -49647,15 +49778,17 @@ class EmitterDesc extends DisposableDesc {
49647
49778
  blending: this.blending,
49648
49779
  opacity: this.opacity,
49649
49780
  vertexShader: particle_vertexShader,
49650
- fragmentShader: particle_fragmentShader,
49781
+ fragmentShader: this.blending === AdditiveBlending ? particle_fragmentShader_additive : particle_fragmentShader,
49651
49782
  uniforms: {
49652
49783
  uMap: { value: mapToUse },
49653
49784
  uAlphaMap: { value: alphaMapToUse },
49654
49785
  uColorMap: { value: colorMapToUse },
49655
49786
  uOpacity: { value: this.opacity },
49656
- uZOffset: { value: this.zOffset }
49787
+ uZOffset: { value: this.zOffset },
49788
+ uFlipbookSize: { value: new Vector2$1(1 / flipbookSizeX, 1 / flipbookSizeY) }
49657
49789
  }
49658
49790
  });
49791
+ this.resultMaterial = material;
49659
49792
  this.result = new InstancedMesh(geometry, material, this.maxCount);
49660
49793
  this.result.name = "Particles";
49661
49794
  this.result.frustumCulled = false;
@@ -49739,24 +49872,47 @@ class EmitterDesc extends DisposableDesc {
49739
49872
  }
49740
49873
  }
49741
49874
  updateResult(renderScene) {
49742
- if (!this.result || !this.instanceColorBuffer || !this.instanceOpacityBuffer || !this.instanceSeedTimeBuffer) return;
49875
+ if (!this.result || !this.instanceColorBuffer || !this.instanceOpacityBuffer || !this.instanceSeedTimeBuffer || !this.instanceFlipbookBuffer) return;
49743
49876
  this.result.count = this.particles.length;
49877
+ const [flipbookSizeX, flipbookSizeY] = this.getFlipbookSize();
49878
+ const flipbookTotal = flipbookSizeX * flipbookSizeY;
49879
+ if (this.resultMaterial) {
49880
+ this.resultMaterial.uniforms.uOpacity.value = this.opacity;
49881
+ this.resultMaterial.uniforms.uZOffset.value = this.zOffset;
49882
+ this.resultMaterial.uniforms.uFlipbookSize.value.set(1 / flipbookSizeX, 1 / flipbookSizeY);
49883
+ }
49744
49884
  for (let i = 0; i < this.result.count; i++) {
49745
49885
  const particle = this.particles[i];
49746
49886
  const time2 = particle.time;
49747
49887
  const normalizedTime = particle.time / particle.lifetime;
49748
49888
  const color = this.color.getValue(normalizedTime);
49749
49889
  const size = this.size.getValue(this.normalizeSizeKeypointTime ? normalizedTime : time2, particle.seed + 0);
49890
+ const squash = this.squash.getValue(this.normalizeSizeKeypointTime ? normalizedTime : time2, particle.seed + 2);
49750
49891
  const opacity = 1 - this.transparency.getValue(normalizedTime, particle.seed + 1);
49751
- this.result.setMatrixAt(i, particle.getMatrix(renderScene, size, this.orientation));
49892
+ const flipbookFramerate = mathRandom(this.flipbookFramerate.Min, this.flipbookFramerate.Max, new RNG(particle.seed + 67).nextFloat());
49893
+ let flipbookFrameTime = this.flipbookMode === ParticleFlipbookMode.OneShot ? particle.lifetime / flipbookTotal : 1 / flipbookFramerate;
49894
+ if (!this.flipbookBlendFrames) flipbookFrameTime = 1e6;
49895
+ this.result.setMatrixAt(i, particle.getMatrix(renderScene, size, this.orientation, squash));
49752
49896
  this.instanceColorBuffer.setXYZ(i, color.R, color.G, color.B);
49753
49897
  this.instanceOpacityBuffer.setX(i, opacity);
49754
- this.instanceSeedTimeBuffer.setXY(i, particle.seed, normalizedTime);
49898
+ this.instanceSeedTimeBuffer.setXYZ(i, particle.seed, normalizedTime, flipbookFrameTime);
49899
+ const flipbookFrame0 = particle.getFlipbookIndex(flipbookTotal, false, flipbookFramerate, this.flipbookMode, this.flipbookStartRandom);
49900
+ const flipbookFrame1 = this.flipbookBlendFrames ? particle.getFlipbookIndex(flipbookTotal, true, flipbookFramerate, this.flipbookMode, this.flipbookStartRandom) : flipbookFrame0;
49901
+ const column0 = flipbookFrame0 % flipbookSizeX;
49902
+ const row0 = Math.floor(flipbookFrame0 / flipbookSizeX);
49903
+ const column1 = flipbookFrame1 % flipbookSizeX;
49904
+ const row1 = Math.floor(flipbookFrame1 / flipbookSizeX);
49905
+ const u0 = column0 * 1 / flipbookSizeX;
49906
+ const v0 = (flipbookSizeY - 1 - row0) * 1 / flipbookSizeY;
49907
+ const u1 = column1 * 1 / flipbookSizeX;
49908
+ const v1 = (flipbookSizeY - 1 - row1) * 1 / flipbookSizeY;
49909
+ this.instanceFlipbookBuffer.setXYZW(i, u0, v0, u1, v1);
49755
49910
  }
49756
49911
  this.result.instanceMatrix.needsUpdate = true;
49757
49912
  this.instanceColorBuffer.needsUpdate = true;
49758
49913
  this.instanceOpacityBuffer.needsUpdate = true;
49759
49914
  this.instanceSeedTimeBuffer.needsUpdate = true;
49915
+ this.instanceFlipbookBuffer.needsUpdate = true;
49760
49916
  }
49761
49917
  }
49762
49918
  class EmitterGroupDesc extends RenderDesc {
@@ -49899,6 +50055,7 @@ class EmitterGroupDesc extends RenderDesc {
49899
50055
  if (child.HasProperty("Drag")) emitterDesc.drag = child.Prop("Drag");
49900
50056
  if (child.HasProperty("TimeScale")) emitterDesc.timeScale = child.Prop("TimeScale");
49901
50057
  if (child.HasProperty("Size")) emitterDesc.size = child.Prop("Size");
50058
+ if (child.HasProperty("Squash")) emitterDesc.squash = child.Prop("Squash");
49902
50059
  if (child.HasProperty("Color")) emitterDesc.color = child.Prop("Color");
49903
50060
  if (child.HasProperty("Texture")) emitterDesc.texture = child.Prop("Texture");
49904
50061
  if (child.HasProperty("Transparency")) emitterDesc.transparency = child.Prop("Transparency");
@@ -49907,6 +50064,13 @@ class EmitterGroupDesc extends RenderDesc {
49907
50064
  if (child.HasProperty("ZOffset")) emitterDesc.zOffset = child.Prop("ZOffset");
49908
50065
  if (child.HasProperty("Orientation")) emitterDesc.orientation = child.Prop("Orientation");
49909
50066
  if (child.HasProperty("LockedToPart")) emitterDesc.lockedToPart = child.Prop("LockedToPart");
50067
+ emitterDesc.flipbookLayout = child.PropOrDefault("FlipbookLayout", emitterDesc.flipbookLayout);
50068
+ emitterDesc.flipbookBlendFrames = child.PropOrDefault("FlipbookBlendFrames", emitterDesc.flipbookBlendFrames);
50069
+ emitterDesc.flipbookFramerate = child.PropOrDefault("FlipbookFramerate", emitterDesc.flipbookFramerate);
50070
+ emitterDesc.flipbookMode = child.PropOrDefault("FlipbookMode", emitterDesc.flipbookMode);
50071
+ emitterDesc.flipbookSizeX = child.PropOrDefault("FlipbookSizeX", emitterDesc.flipbookSizeX);
50072
+ emitterDesc.flipbookSizeY = child.PropOrDefault("FlipbookSizeY", emitterDesc.flipbookSizeY);
50073
+ emitterDesc.flipbookStartRandom = child.PropOrDefault("FlipbookStartRandom", emitterDesc.flipbookStartRandom);
49910
50074
  this.emitterDescs.push(emitterDesc);
49911
50075
  }
49912
50076
  fromSparkles(child) {
@@ -50522,8 +50686,8 @@ class RBXRenderer {
50522
50686
  }
50523
50687
  /**Sets up the THREE.js renderer */
50524
50688
  static create(canvas) {
50525
- RBXRenderer.renderer = new WebGLRenderer({ antialias: true, alpha: true, canvas });
50526
- RBXRenderer.renderer.setClearColor(new Color(1, 0, 1), 0);
50689
+ RBXRenderer.renderer = new WebGLRenderer({ antialias: true, alpha: true, premultipliedAlpha: false, canvas });
50690
+ if (RBXRenderer.renderer) RBXRenderer.renderer.setClearColor(new Color(0, 0, 0), 0);
50527
50691
  RBXRenderer.renderer.outputColorSpace = SRGBColorSpace;
50528
50692
  RBXRenderer.renderer.shadowMap.enabled = true;
50529
50693
  RBXRenderer.renderer.shadowMap.type = PCFSoftShadowMap;
@@ -50693,6 +50857,7 @@ class RBXRenderer {
50693
50857
  */
50694
50858
  static setBackgroundTransparent(transparent) {
50695
50859
  RBXRenderer.backgroundTransparent = transparent;
50860
+ if (RBXRenderer.renderer) RBXRenderer.renderer.setClearColor(new Color(0, 0, 0), 0);
50696
50861
  for (const renderScene of RBXRenderer.scenes) {
50697
50862
  if (RBXRenderer.backgroundTransparent) {
50698
50863
  renderScene.scene.background = null;
@@ -51682,6 +51847,8 @@ export {
51682
51847
  OutfitRenderer,
51683
51848
  PartType,
51684
51849
  ParticleEmitterShapeInOut,
51850
+ ParticleFlipbookLayout,
51851
+ ParticleFlipbookMode,
51685
51852
  ParticleOrientation,
51686
51853
  Property,
51687
51854
  PropertyTypeInfo,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "roavatar-renderer",
3
- "version": "1.5.4",
3
+ "version": "1.5.6",
4
4
  "description": "A renderer for Roblox avatars, used by the RoAvatar extension.",
5
5
  "author": "steinan",
6
6
  "type": "module",