@codexo/exojs-particles 0.15.3 → 0.16.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (211) hide show
  1. package/README.md +21 -43
  2. package/dist/esm/ParticleStorage.d.ts +188 -0
  3. package/dist/esm/ParticleStorage.d.ts.map +1 -0
  4. package/dist/esm/ParticleStorage.js +208 -0
  5. package/dist/esm/ParticleStorage.js.map +1 -0
  6. package/dist/esm/ParticleSystem.d.ts +189 -60
  7. package/dist/esm/ParticleSystem.d.ts.map +1 -0
  8. package/dist/esm/ParticleSystem.js +660 -560
  9. package/dist/esm/ParticleSystem.js.map +1 -1
  10. package/dist/esm/distributions/BoxArea.d.ts +1 -0
  11. package/dist/esm/distributions/BoxArea.d.ts.map +1 -0
  12. package/dist/esm/distributions/BoxArea.js +38 -44
  13. package/dist/esm/distributions/BoxArea.js.map +1 -1
  14. package/dist/esm/distributions/CircleArea.d.ts +1 -0
  15. package/dist/esm/distributions/CircleArea.d.ts.map +1 -0
  16. package/dist/esm/distributions/CircleArea.js +30 -28
  17. package/dist/esm/distributions/CircleArea.js.map +1 -1
  18. package/dist/esm/distributions/ColorGradient.d.ts +3 -2
  19. package/dist/esm/distributions/ColorGradient.d.ts.map +1 -0
  20. package/dist/esm/distributions/ColorGradient.js +70 -75
  21. package/dist/esm/distributions/ColorGradient.js.map +1 -1
  22. package/dist/esm/distributions/ConeDirection.d.ts +2 -1
  23. package/dist/esm/distributions/ConeDirection.d.ts.map +1 -0
  24. package/dist/esm/distributions/ConeDirection.js +41 -39
  25. package/dist/esm/distributions/ConeDirection.js.map +1 -1
  26. package/dist/esm/distributions/Constant.d.ts +1 -0
  27. package/dist/esm/distributions/Constant.d.ts.map +1 -0
  28. package/dist/esm/distributions/Constant.js +32 -32
  29. package/dist/esm/distributions/Constant.js.map +1 -1
  30. package/dist/esm/distributions/Curve.d.ts +2 -1
  31. package/dist/esm/distributions/Curve.d.ts.map +1 -0
  32. package/dist/esm/distributions/Curve.js +46 -55
  33. package/dist/esm/distributions/Curve.js.map +1 -1
  34. package/dist/esm/distributions/Distribution.d.ts +4 -3
  35. package/dist/esm/distributions/Distribution.d.ts.map +1 -0
  36. package/dist/esm/distributions/LineSegment.d.ts +1 -0
  37. package/dist/esm/distributions/LineSegment.d.ts.map +1 -0
  38. package/dist/esm/distributions/LineSegment.js +25 -23
  39. package/dist/esm/distributions/LineSegment.js.map +1 -1
  40. package/dist/esm/distributions/Range.d.ts +1 -0
  41. package/dist/esm/distributions/Range.d.ts.map +1 -0
  42. package/dist/esm/distributions/Range.js +18 -16
  43. package/dist/esm/distributions/Range.js.map +1 -1
  44. package/dist/esm/distributions/VectorRange.d.ts +1 -0
  45. package/dist/esm/distributions/VectorRange.d.ts.map +1 -0
  46. package/dist/esm/distributions/VectorRange.js +29 -27
  47. package/dist/esm/distributions/VectorRange.js.map +1 -1
  48. package/dist/esm/distributions/index.d.ts +1 -0
  49. package/dist/esm/distributions/index.d.ts.map +1 -0
  50. package/dist/esm/gpu/ParticleGpuState.d.ts +143 -18
  51. package/dist/esm/gpu/ParticleGpuState.d.ts.map +1 -0
  52. package/dist/esm/gpu/ParticleGpuState.js +655 -497
  53. package/dist/esm/gpu/ParticleGpuState.js.map +1 -1
  54. package/dist/esm/gpu/shaders/particle-simulate.wgsl.js +6 -0
  55. package/dist/esm/gpu/shaders/particle-simulate.wgsl.js.map +1 -0
  56. package/dist/esm/index.d.ts +1 -0
  57. package/dist/esm/index.d.ts.map +1 -0
  58. package/dist/esm/index.js +39 -32
  59. package/dist/esm/modules/AlphaFadeOverLifetime.d.ts +4 -3
  60. package/dist/esm/modules/AlphaFadeOverLifetime.d.ts.map +1 -0
  61. package/dist/esm/modules/AlphaFadeOverLifetime.js +68 -55
  62. package/dist/esm/modules/AlphaFadeOverLifetime.js.map +1 -1
  63. package/dist/esm/modules/ApplyForce.d.ts +4 -3
  64. package/dist/esm/modules/ApplyForce.d.ts.map +1 -0
  65. package/dist/esm/modules/ApplyForce.js +49 -43
  66. package/dist/esm/modules/ApplyForce.js.map +1 -1
  67. package/dist/esm/modules/AttractToPoint.d.ts +4 -3
  68. package/dist/esm/modules/AttractToPoint.d.ts.map +1 -0
  69. package/dist/esm/modules/AttractToPoint.js +73 -62
  70. package/dist/esm/modules/AttractToPoint.js.map +1 -1
  71. package/dist/esm/modules/BurstSpawn.d.ts +6 -18
  72. package/dist/esm/modules/BurstSpawn.d.ts.map +1 -0
  73. package/dist/esm/modules/BurstSpawn.js +56 -91
  74. package/dist/esm/modules/BurstSpawn.js.map +1 -1
  75. package/dist/esm/modules/ColorOverLifetime.d.ts +4 -3
  76. package/dist/esm/modules/ColorOverLifetime.d.ts.map +1 -0
  77. package/dist/esm/modules/ColorOverLifetime.js +65 -53
  78. package/dist/esm/modules/ColorOverLifetime.js.map +1 -1
  79. package/dist/esm/modules/ColorOverSpeed.d.ts +5 -4
  80. package/dist/esm/modules/ColorOverSpeed.d.ts.map +1 -0
  81. package/dist/esm/modules/ColorOverSpeed.js +90 -75
  82. package/dist/esm/modules/ColorOverSpeed.js.map +1 -1
  83. package/dist/esm/modules/DeathModule.d.ts +26 -10
  84. package/dist/esm/modules/DeathModule.d.ts.map +1 -0
  85. package/dist/esm/modules/DeathModule.js +38 -22
  86. package/dist/esm/modules/DeathModule.js.map +1 -1
  87. package/dist/esm/modules/Drag.d.ts +3 -2
  88. package/dist/esm/modules/Drag.d.ts.map +1 -0
  89. package/dist/esm/modules/Drag.js +43 -37
  90. package/dist/esm/modules/Drag.js.map +1 -1
  91. package/dist/esm/modules/OrbitalForce.d.ts +4 -3
  92. package/dist/esm/modules/OrbitalForce.d.ts.map +1 -0
  93. package/dist/esm/modules/OrbitalForce.js +70 -58
  94. package/dist/esm/modules/OrbitalForce.js.map +1 -1
  95. package/dist/esm/modules/RateSpawn.d.ts +7 -22
  96. package/dist/esm/modules/RateSpawn.d.ts.map +1 -0
  97. package/dist/esm/modules/RateSpawn.js +39 -71
  98. package/dist/esm/modules/RateSpawn.js.map +1 -1
  99. package/dist/esm/modules/RepelFromPoint.d.ts +4 -3
  100. package/dist/esm/modules/RepelFromPoint.d.ts.map +1 -0
  101. package/dist/esm/modules/RepelFromPoint.js +72 -62
  102. package/dist/esm/modules/RepelFromPoint.js.map +1 -1
  103. package/dist/esm/modules/RotateOverLifetime.d.ts +3 -2
  104. package/dist/esm/modules/RotateOverLifetime.d.ts.map +1 -0
  105. package/dist/esm/modules/RotateOverLifetime.js +40 -36
  106. package/dist/esm/modules/RotateOverLifetime.js.map +1 -1
  107. package/dist/esm/modules/ScaleOverLifetime.d.ts +5 -4
  108. package/dist/esm/modules/ScaleOverLifetime.d.ts.map +1 -0
  109. package/dist/esm/modules/ScaleOverLifetime.js +60 -50
  110. package/dist/esm/modules/ScaleOverLifetime.js.map +1 -1
  111. package/dist/esm/modules/SpawnModule.d.ts +15 -12
  112. package/dist/esm/modules/SpawnModule.d.ts.map +1 -0
  113. package/dist/esm/modules/SpawnModule.js +32 -28
  114. package/dist/esm/modules/SpawnModule.js.map +1 -1
  115. package/dist/esm/modules/SpawnOnDeath.d.ts +13 -9
  116. package/dist/esm/modules/SpawnOnDeath.d.ts.map +1 -0
  117. package/dist/esm/modules/SpawnOnDeath.js +41 -43
  118. package/dist/esm/modules/SpawnOnDeath.js.map +1 -1
  119. package/dist/esm/modules/Turbulence.d.ts +4 -3
  120. package/dist/esm/modules/Turbulence.d.ts.map +1 -0
  121. package/dist/esm/modules/Turbulence.js +101 -89
  122. package/dist/esm/modules/Turbulence.js.map +1 -1
  123. package/dist/esm/modules/UpdateModule.d.ts +21 -13
  124. package/dist/esm/modules/UpdateModule.d.ts.map +1 -0
  125. package/dist/esm/modules/UpdateModule.js +65 -63
  126. package/dist/esm/modules/UpdateModule.js.map +1 -1
  127. package/dist/esm/modules/VelocityOverLifetime.d.ts +7 -6
  128. package/dist/esm/modules/VelocityOverLifetime.d.ts.map +1 -0
  129. package/dist/esm/modules/VelocityOverLifetime.js +75 -73
  130. package/dist/esm/modules/VelocityOverLifetime.js.map +1 -1
  131. package/dist/esm/modules/WgslContribution.d.ts +16 -15
  132. package/dist/esm/modules/WgslContribution.d.ts.map +1 -0
  133. package/dist/esm/modules/WgslContribution.js +37 -29
  134. package/dist/esm/modules/WgslContribution.js.map +1 -1
  135. package/dist/esm/modules/index.d.ts +3 -1
  136. package/dist/esm/modules/index.d.ts.map +1 -0
  137. package/dist/esm/modules/spawnFields.d.ts +32 -0
  138. package/dist/esm/modules/spawnFields.d.ts.map +1 -0
  139. package/dist/esm/modules/spawnFields.js +31 -0
  140. package/dist/esm/modules/spawnFields.js.map +1 -0
  141. package/dist/esm/particlesBuildInfo.d.ts +1 -0
  142. package/dist/esm/particlesBuildInfo.d.ts.map +1 -0
  143. package/dist/esm/particlesBuildInfo.js +6 -4
  144. package/dist/esm/particlesBuildInfo.js.map +1 -1
  145. package/dist/esm/particlesExtension.d.ts +13 -5
  146. package/dist/esm/particlesExtension.d.ts.map +1 -0
  147. package/dist/esm/particlesExtension.js +38 -42
  148. package/dist/esm/particlesExtension.js.map +1 -1
  149. package/dist/esm/public.d.ts +11 -0
  150. package/dist/esm/public.d.ts.map +1 -0
  151. package/dist/esm/renderModes/MeshParticles.d.ts +128 -0
  152. package/dist/esm/renderModes/MeshParticles.d.ts.map +1 -0
  153. package/dist/esm/renderModes/MeshParticles.js +263 -0
  154. package/dist/esm/renderModes/MeshParticles.js.map +1 -0
  155. package/dist/esm/renderModes/ParticleBufferLayout.d.ts +59 -0
  156. package/dist/esm/renderModes/ParticleBufferLayout.d.ts.map +1 -0
  157. package/dist/esm/renderModes/ParticleBufferLayout.js +99 -0
  158. package/dist/esm/renderModes/ParticleBufferLayout.js.map +1 -0
  159. package/dist/esm/renderModes/ParticleInstanceWriter.d.ts +58 -0
  160. package/dist/esm/renderModes/ParticleInstanceWriter.d.ts.map +1 -0
  161. package/dist/esm/renderModes/ParticleInstanceWriter.js +173 -0
  162. package/dist/esm/renderModes/ParticleInstanceWriter.js.map +1 -0
  163. package/dist/esm/renderModes/ParticleMaterial.d.ts +18 -0
  164. package/dist/esm/renderModes/ParticleMaterial.d.ts.map +1 -0
  165. package/dist/esm/renderModes/ParticleMaterial.js +24 -0
  166. package/dist/esm/renderModes/ParticleMaterial.js.map +1 -0
  167. package/dist/esm/renderModes/ParticleRenderMode.d.ts +114 -0
  168. package/dist/esm/renderModes/ParticleRenderMode.d.ts.map +1 -0
  169. package/dist/esm/renderModes/ParticleRenderMode.js +99 -0
  170. package/dist/esm/renderModes/ParticleRenderMode.js.map +1 -0
  171. package/dist/esm/renderModes/QuadParticles.d.ts +55 -0
  172. package/dist/esm/renderModes/QuadParticles.d.ts.map +1 -0
  173. package/dist/esm/renderModes/QuadParticles.js +95 -0
  174. package/dist/esm/renderModes/QuadParticles.js.map +1 -0
  175. package/dist/esm/renderModes/RibbonParticles.d.ts +96 -0
  176. package/dist/esm/renderModes/RibbonParticles.d.ts.map +1 -0
  177. package/dist/esm/renderModes/RibbonParticles.js +202 -0
  178. package/dist/esm/renderModes/RibbonParticles.js.map +1 -0
  179. package/dist/esm/renderModes/shaders/mesh-particles.wgsl.js +6 -0
  180. package/dist/esm/renderModes/shaders/mesh-particles.wgsl.js.map +1 -0
  181. package/dist/esm/renderModes/shaders/mesh.vert.js +6 -0
  182. package/dist/esm/renderModes/shaders/mesh.vert.js.map +1 -0
  183. package/dist/esm/renderModes/shaders/quad-particles.wgsl.js +6 -0
  184. package/dist/esm/renderModes/shaders/quad-particles.wgsl.js.map +1 -0
  185. package/dist/esm/renderModes/shaders/ribbon-particles.wgsl.js +6 -0
  186. package/dist/esm/renderModes/shaders/ribbon-particles.wgsl.js.map +1 -0
  187. package/dist/esm/renderModes/shaders/ribbon.frag.js +6 -0
  188. package/dist/esm/renderModes/shaders/ribbon.frag.js.map +1 -0
  189. package/dist/esm/renderModes/shaders/ribbon.vert.js +6 -0
  190. package/dist/esm/renderModes/shaders/ribbon.vert.js.map +1 -0
  191. package/dist/esm/renderers/WebGl2ParticleRenderer.d.ts +48 -20
  192. package/dist/esm/renderers/WebGl2ParticleRenderer.d.ts.map +1 -0
  193. package/dist/esm/renderers/WebGl2ParticleRenderer.js +317 -321
  194. package/dist/esm/renderers/WebGl2ParticleRenderer.js.map +1 -1
  195. package/dist/esm/renderers/WebGpuParticleRenderer.d.ts +99 -18
  196. package/dist/esm/renderers/WebGpuParticleRenderer.d.ts.map +1 -0
  197. package/dist/esm/renderers/WebGpuParticleRenderer.js +542 -551
  198. package/dist/esm/renderers/WebGpuParticleRenderer.js.map +1 -1
  199. package/dist/esm/renderers/shaders/particle.frag.js +6 -0
  200. package/dist/esm/renderers/shaders/particle.frag.js.map +1 -0
  201. package/dist/esm/renderers/shaders/particle.vert.js +6 -0
  202. package/dist/esm/renderers/shaders/particle.vert.js.map +1 -0
  203. package/package.json +8 -15
  204. package/dist/esm/index.js.map +0 -1
  205. package/dist/esm/register.d.ts +0 -1
  206. package/dist/esm/register.js +0 -43
  207. package/dist/esm/register.js.map +0 -1
  208. package/dist/esm/renderers/glsl/particle.frag.js +0 -4
  209. package/dist/esm/renderers/glsl/particle.frag.js.map +0 -1
  210. package/dist/esm/renderers/glsl/particle.vert.js +0 -4
  211. package/dist/esm/renderers/glsl/particle.vert.js.map +0 -1
@@ -1,65 +1,77 @@
1
- import { UpdateModule } from './UpdateModule.js';
1
+ import { UpdateModule } from "./UpdateModule.js";
2
2
 
3
+ //#region src/modules/OrbitalForce.ts
3
4
  /**
4
- * Applies a tangential acceleration around a center point perpendicular
5
- * to the radial vector `(particle − center)`. Combined with an attract /
6
- * repel module that controls the radial distance, this produces orbital,
7
- * spiral, or vortex motion.
8
- *
9
- * `angularSpeed` is the target angular velocity in radians/second. The
10
- * effective tangential acceleration scales with `radius * angularSpeed`,
11
- * so distant particles get pushed harder (matching uniform circular
12
- * motion). Positive values orbit counter-clockwise, negative clockwise.
13
- *
14
- * Use cases: galactic spirals, smoke vortices around an attractor, wind
15
- * eddies. Layer with {@link AttractToPoint} for stable orbits.
16
- *
17
- * GPU-eligible.
18
- */
19
- class OrbitalForce extends UpdateModule {
20
- x;
21
- y;
22
- angularSpeed;
23
- constructor(x, y, angularSpeed) {
24
- super();
25
- this.x = x;
26
- this.y = y;
27
- this.angularSpeed = angularSpeed;
28
- }
29
- apply(system, dt) {
30
- const { posX, posY, velX, velY, liveCount } = system;
31
- const { x, y, angularSpeed } = this;
32
- const omega = angularSpeed * dt;
33
- for (let i = 0; i < liveCount; i++) {
34
- const dx = (posX[i] ?? 0) - x;
35
- const dy = (posY[i] ?? 0) - y;
36
- // Perpendicular vector: (-dy, dx) for counter-clockwise.
37
- velX[i] = (velX[i] ?? 0) + -dy * omega;
38
- velY[i] = (velY[i] ?? 0) + dx * omega;
39
- }
40
- }
41
- wgsl() {
42
- return {
43
- key: 'OrbitalForce',
44
- uniforms: [
45
- { name: 'center', type: 'vec2<f32>' },
46
- { name: 'angularSpeed', type: 'f32' },
47
- { name: '_pad0', type: 'f32' },
48
- ],
49
- body: `
5
+ * Applies a tangential acceleration around a center point - perpendicular
6
+ * to the radial vector `(particle − center)`. Combined with an attract /
7
+ * repel module that controls the radial distance, this produces orbital,
8
+ * spiral, or vortex motion.
9
+ *
10
+ * `angularSpeed` is the target angular velocity in radians/second. The
11
+ * effective tangential acceleration scales with `radius * angularSpeed`,
12
+ * so distant particles get pushed harder (matching uniform circular
13
+ * motion). Positive values orbit counter-clockwise, negative clockwise.
14
+ *
15
+ * Use cases: galactic spirals, smoke vortices around an attractor, wind
16
+ * eddies. Layer with {@link AttractToPoint} for stable orbits.
17
+ *
18
+ * GPU-eligible.
19
+ */
20
+ var OrbitalForce = class extends UpdateModule {
21
+ x;
22
+ y;
23
+ angularSpeed;
24
+ constructor(x, y, angularSpeed) {
25
+ super();
26
+ this.x = x;
27
+ this.y = y;
28
+ this.angularSpeed = angularSpeed;
29
+ }
30
+ apply(particles, dt) {
31
+ const { x: posX, y: posY } = particles.position;
32
+ const { x: velX, y: velY } = particles.velocity;
33
+ const liveCount = particles.count;
34
+ const { x, y, angularSpeed } = this;
35
+ const omega = angularSpeed * dt;
36
+ for (let i = 0; i < liveCount; i++) {
37
+ const dx = (posX[i] ?? 0) - x;
38
+ const dy = (posY[i] ?? 0) - y;
39
+ velX[i] = (velX[i] ?? 0) + -dy * omega;
40
+ velY[i] = (velY[i] ?? 0) + dx * omega;
41
+ }
42
+ }
43
+ wgsl() {
44
+ return {
45
+ key: "OrbitalForce",
46
+ uniforms: [
47
+ {
48
+ name: "center",
49
+ type: "vec2<f32>"
50
+ },
51
+ {
52
+ name: "angularSpeed",
53
+ type: "f32"
54
+ },
55
+ {
56
+ name: "_pad0",
57
+ type: "f32"
58
+ }
59
+ ],
60
+ body: `
50
61
  let orbitDelta = positions[idx] - modules.u_OrbitalForce.center;
51
62
  let orbitOmega = modules.u_OrbitalForce.angularSpeed * dt;
52
63
  velocities[idx] = velocities[idx] + vec2<f32>(-orbitDelta.y, orbitDelta.x) * orbitOmega;
53
- `,
54
- };
55
- }
56
- writeUniforms(view, offset) {
57
- view.setFloat32(offset + 0, this.x, true);
58
- view.setFloat32(offset + 4, this.y, true);
59
- view.setFloat32(offset + 8, this.angularSpeed, true);
60
- view.setFloat32(offset + 12, 0, true);
61
- }
62
- }
64
+ `
65
+ };
66
+ }
67
+ writeUniforms(view, offset) {
68
+ view.setFloat32(offset + 0, this.x, true);
69
+ view.setFloat32(offset + 4, this.y, true);
70
+ view.setFloat32(offset + 8, this.angularSpeed, true);
71
+ view.setFloat32(offset + 12, 0, true);
72
+ }
73
+ };
63
74
 
75
+ //#endregion
64
76
  export { OrbitalForce };
65
- //# sourceMappingURL=OrbitalForce.js.map
77
+ //# sourceMappingURL=OrbitalForce.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"OrbitalForce.js","sources":["../../../../src/modules/OrbitalForce.ts"],"sourcesContent":[null],"names":[],"mappings":";;AAKA;;;;;;;;;;;;;;;AAeG;AACG,MAAO,YAAa,SAAQ,YAAY,CAAA;AACrC,IAAA,CAAC;AACD,IAAA,CAAC;AACD,IAAA,YAAY;AAEnB,IAAA,WAAA,CAAmB,CAAS,EAAE,CAAS,EAAE,YAAoB,EAAA;AAC3D,QAAA,KAAK,EAAE;AACP,QAAA,IAAI,CAAC,CAAC,GAAG,CAAC;AACV,QAAA,IAAI,CAAC,CAAC,GAAG,CAAC;AACV,QAAA,IAAI,CAAC,YAAY,GAAG,YAAY;IAClC;IAEgB,KAAK,CAAC,MAAsB,EAAE,EAAU,EAAA;AACtD,QAAA,MAAM,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,SAAS,EAAE,GAAG,MAAM;QACpD,MAAM,EAAE,CAAC,EAAE,CAAC,EAAE,YAAY,EAAE,GAAG,IAAI;AACnC,QAAA,MAAM,KAAK,GAAG,YAAY,GAAG,EAAE;AAE/B,QAAA,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,SAAS,EAAE,CAAC,EAAE,EAAE;AAClC,YAAA,MAAM,EAAE,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC;AAC7B,YAAA,MAAM,EAAE,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC;;AAE7B,YAAA,IAAI,CAAC,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,GAAG,KAAK;AACtC,YAAA,IAAI,CAAC,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,EAAE,GAAG,KAAK;QACvC;IACF;IAEgB,IAAI,GAAA;QAClB,OAAO;AACL,YAAA,GAAG,EAAE,cAAc;AACnB,YAAA,QAAQ,EAAE;AACR,gBAAA,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,WAAW,EAAE;AACrC,gBAAA,EAAE,IAAI,EAAE,cAAc,EAAE,IAAI,EAAE,KAAK,EAAE;AACrC,gBAAA,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,KAAK,EAAE;AAC/B,aAAA;AACD,YAAA,IAAI,EAAE;;;;AAIC,YAAA,CAAA;SACR;IACH;IAEgB,aAAa,CAAC,IAAc,EAAE,MAAc,EAAA;AAC1D,QAAA,IAAI,CAAC,UAAU,CAAC,MAAM,GAAG,CAAC,EAAE,IAAI,CAAC,CAAC,EAAE,IAAI,CAAC;AACzC,QAAA,IAAI,CAAC,UAAU,CAAC,MAAM,GAAG,CAAC,EAAE,IAAI,CAAC,CAAC,EAAE,IAAI,CAAC;AACzC,QAAA,IAAI,CAAC,UAAU,CAAC,MAAM,GAAG,CAAC,EAAE,IAAI,CAAC,YAAY,EAAE,IAAI,CAAC;QACpD,IAAI,CAAC,UAAU,CAAC,MAAM,GAAG,EAAE,EAAE,CAAC,EAAE,IAAI,CAAC;IACvC;AACD;;;;"}
1
+ {"version":3,"file":"OrbitalForce.js","names":[],"sources":["../../../src/modules/OrbitalForce.ts"],"sourcesContent":["import type { ParticleBatch } from '#ParticleStorage';\n\nimport { UpdateModule } from './UpdateModule';\nimport type { WgslContribution } from './WgslContribution';\n\n/**\n * Applies a tangential acceleration around a center point - perpendicular\n * to the radial vector `(particle − center)`. Combined with an attract /\n * repel module that controls the radial distance, this produces orbital,\n * spiral, or vortex motion.\n *\n * `angularSpeed` is the target angular velocity in radians/second. The\n * effective tangential acceleration scales with `radius * angularSpeed`,\n * so distant particles get pushed harder (matching uniform circular\n * motion). Positive values orbit counter-clockwise, negative clockwise.\n *\n * Use cases: galactic spirals, smoke vortices around an attractor, wind\n * eddies. Layer with {@link AttractToPoint} for stable orbits.\n *\n * GPU-eligible.\n */\nexport class OrbitalForce extends UpdateModule {\n public x: number;\n public y: number;\n public angularSpeed: number;\n\n public constructor(x: number, y: number, angularSpeed: number) {\n super();\n this.x = x;\n this.y = y;\n this.angularSpeed = angularSpeed;\n }\n\n public override apply(particles: ParticleBatch, dt: number): void {\n const { x: posX, y: posY } = particles.position;\n const { x: velX, y: velY } = particles.velocity;\n const liveCount = particles.count;\n const { x, y, angularSpeed } = this;\n const omega = angularSpeed * dt;\n\n for (let i = 0; i < liveCount; i++) {\n const dx = (posX[i] ?? 0) - x;\n const dy = (posY[i] ?? 0) - y;\n // Perpendicular vector: (-dy, dx) for counter-clockwise.\n velX[i] = (velX[i] ?? 0) + -dy * omega;\n velY[i] = (velY[i] ?? 0) + dx * omega;\n }\n }\n\n public override wgsl(): WgslContribution {\n return {\n key: 'OrbitalForce',\n uniforms: [\n { name: 'center', type: 'vec2<f32>' },\n { name: 'angularSpeed', type: 'f32' },\n { name: '_pad0', type: 'f32' },\n ],\n body: `\n let orbitDelta = positions[idx] - modules.u_OrbitalForce.center;\n let orbitOmega = modules.u_OrbitalForce.angularSpeed * dt;\n velocities[idx] = velocities[idx] + vec2<f32>(-orbitDelta.y, orbitDelta.x) * orbitOmega;\n `,\n };\n }\n\n public override writeUniforms(view: DataView, offset: number): void {\n view.setFloat32(offset + 0, this.x, true);\n view.setFloat32(offset + 4, this.y, true);\n view.setFloat32(offset + 8, this.angularSpeed, true);\n view.setFloat32(offset + 12, 0, true);\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;AAqBA,IAAa,eAAb,cAAkC,aAAa;CAC7C,AAAO;CACP,AAAO;CACP,AAAO;CAEP,AAAO,YAAY,GAAW,GAAW,cAAsB;EAC7D,MAAM;EACN,KAAK,IAAI;EACT,KAAK,IAAI;EACT,KAAK,eAAe;CACtB;CAEA,AAAgB,MAAM,WAA0B,IAAkB;EAChE,MAAM,EAAE,GAAG,MAAM,GAAG,SAAS,UAAU;EACvC,MAAM,EAAE,GAAG,MAAM,GAAG,SAAS,UAAU;EACvC,MAAM,YAAY,UAAU;EAC5B,MAAM,EAAE,GAAG,GAAG,iBAAiB;EAC/B,MAAM,QAAQ,eAAe;EAE7B,KAAK,IAAI,IAAI,GAAG,IAAI,WAAW,KAAK;GAClC,MAAM,MAAM,KAAK,MAAM,KAAK;GAC5B,MAAM,MAAM,KAAK,MAAM,KAAK;GAE5B,KAAK,MAAM,KAAK,MAAM,KAAK,CAAC,KAAK;GACjC,KAAK,MAAM,KAAK,MAAM,KAAK,KAAK;EAClC;CACF;CAEA,AAAgB,OAAyB;EACvC,OAAO;GACL,KAAK;GACL,UAAU;IACR;KAAE,MAAM;KAAU,MAAM;IAAY;IACpC;KAAE,MAAM;KAAgB,MAAM;IAAM;IACpC;KAAE,MAAM;KAAS,MAAM;IAAM;GAC/B;GACA,MAAM;;;;;EAKR;CACF;CAEA,AAAgB,cAAc,MAAgB,QAAsB;EAClE,KAAK,WAAW,SAAS,GAAG,KAAK,GAAG,IAAI;EACxC,KAAK,WAAW,SAAS,GAAG,KAAK,GAAG,IAAI;EACxC,KAAK,WAAW,SAAS,GAAG,KAAK,cAAc,IAAI;EACnD,KAAK,WAAW,SAAS,IAAI,GAAG,IAAI;CACtC;AACF"}
@@ -1,27 +1,11 @@
1
- import { Color } from '@codexo/exojs';
2
- import { Vector } from '@codexo/exojs';
3
- import type { Distribution } from "#distributions/Distribution";
4
- import type { ParticleSystem } from "#ParticleSystem";
1
+ import type { Distribution } from '#distributions/Distribution';
2
+ import type { ParticleEmitter } from '#ParticleStorage';
3
+ import { type ParticleSpawnFields } from './spawnFields';
5
4
  import { SpawnModule } from './SpawnModule';
6
- /**
7
- * Per-property spawn configuration. Every entry is a {@link Distribution}
8
- * sampled once per spawned particle. Omitting an entry leaves the slot's
9
- * field at its zero/default value (zero position/velocity/rotation, unit
10
- * scale, opaque white, lifetime 1 s).
11
- */
12
- export interface RateSpawnConfig {
5
+ /** Spawn configuration for {@link RateSpawn}: the emission rate plus the shared per-property fields. */
6
+ export interface RateSpawnConfig extends ParticleSpawnFields {
13
7
  /** Particles emitted per second. Sampled each frame. */
14
8
  rate: Distribution<number>;
15
- /** Total lifetime in seconds. Required — drives expiry. Default 1. */
16
- lifetime?: Distribution<number>;
17
- position?: Distribution<Vector>;
18
- velocity?: Distribution<Vector>;
19
- scale?: Distribution<Vector>;
20
- rotation?: Distribution<number>;
21
- rotationSpeed?: Distribution<number>;
22
- /** Initial tint at spawn. For per-frame fade use a `ColorOverLifetime` update module. */
23
- tint?: Distribution<Color>;
24
- textureIndex?: Distribution<number>;
25
9
  }
26
10
  /**
27
11
  * Continuous, rate-based spawner. Emits a {@link RateSpawnConfig.rate}
@@ -37,5 +21,6 @@ export declare class RateSpawn extends SpawnModule {
37
21
  private readonly _vec;
38
22
  private readonly _color;
39
23
  constructor(config: RateSpawnConfig);
40
- apply(system: ParticleSystem, dt: number): void;
24
+ apply(emitter: ParticleEmitter, dt: number): void;
41
25
  }
26
+ //# sourceMappingURL=RateSpawn.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"RateSpawn.d.ts","sourceRoot":"","sources":["../../../src/modules/RateSpawn.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,6BAA6B,CAAC;AAChE,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAC;AAExD,OAAO,EAAgB,KAAK,mBAAmB,EAAE,MAAM,eAAe,CAAC;AACvE,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAE5C,wGAAwG;AACxG,MAAM,WAAW,eAAgB,SAAQ,mBAAmB;IAC1D,wDAAwD;IACxD,IAAI,EAAE,YAAY,CAAC,MAAM,CAAC,CAAC;CAC5B;AAED;;;;;;;GAOG;AACH,qBAAa,SAAU,SAAQ,WAAW;IACjC,MAAM,EAAE,eAAe,CAAC;IAE/B,OAAO,CAAC,YAAY,CAAK;IACzB,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAgB;IACrC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAe;gBAEnB,MAAM,EAAE,eAAe;IAK1B,KAAK,CAAC,OAAO,EAAE,eAAe,EAAE,EAAE,EAAE,MAAM,GAAG,IAAI;CA0BlE"}
@@ -1,75 +1,43 @@
1
- import { Vector, Color } from '@codexo/exojs';
2
- import { SpawnModule } from './SpawnModule.js';
1
+ import { fillParticle } from "./spawnFields.js";
2
+ import { SpawnModule } from "./SpawnModule.js";
3
+ import { Color, Vector } from "@codexo/exojs";
3
4
 
5
+ //#region src/modules/RateSpawn.ts
4
6
  /**
5
- * Continuous, rate-based spawner. Emits a {@link RateSpawnConfig.rate}
6
- * sample per second; sub-frame fractions accumulate so low rates (e.g.
7
- * 0.5 particles/s) remain accurate over time.
8
- *
9
- * Each property is independently randomised via its {@link Distribution}.
10
- * Every spawned particle gets a fresh sample for every configured field.
11
- */
12
- class RateSpawn extends SpawnModule {
13
- config;
14
- _accumulator = 0;
15
- _vec = new Vector();
16
- _color = new Color();
17
- constructor(config) {
18
- super();
19
- this.config = config;
20
- }
21
- apply(system, dt) {
22
- const cfg = this.config;
23
- const rate = cfg.rate.sample();
24
- this._accumulator += rate * dt;
25
- const count = this._accumulator | 0;
26
- if (count <= 0) {
27
- return;
28
- }
29
- this._accumulator -= count;
30
- const v = this._vec;
31
- const c = this._color;
32
- for (let i = 0; i < count; i++) {
33
- const slot = system.spawn();
34
- if (slot < 0) {
35
- this._accumulator = 0;
36
- return;
37
- }
38
- system.lifetime[slot] = cfg.lifetime ? cfg.lifetime.sample() : 1;
39
- if (cfg.position) {
40
- cfg.position.sample(v);
41
- system.posX[slot] = v.x;
42
- system.posY[slot] = v.y;
43
- }
44
- else {
45
- system.posX[slot] = 0;
46
- system.posY[slot] = 0;
47
- }
48
- if (cfg.velocity) {
49
- cfg.velocity.sample(v);
50
- system.velX[slot] = v.x;
51
- system.velY[slot] = v.y;
52
- }
53
- else {
54
- system.velX[slot] = 0;
55
- system.velY[slot] = 0;
56
- }
57
- if (cfg.scale) {
58
- cfg.scale.sample(v);
59
- system.scaleX[slot] = v.x;
60
- system.scaleY[slot] = v.y;
61
- }
62
- else {
63
- system.scaleX[slot] = 1;
64
- system.scaleY[slot] = 1;
65
- }
66
- system.rotations[slot] = cfg.rotation ? cfg.rotation.sample() : 0;
67
- system.rotationSpeeds[slot] = cfg.rotationSpeed ? cfg.rotationSpeed.sample() : 0;
68
- system.color[slot] = cfg.tint ? cfg.tint.sample(c).toRgba() : 0xffffffff;
69
- system.textureIndex[slot] = cfg.textureIndex ? cfg.textureIndex.sample() | 0 : 0;
70
- }
71
- }
72
- }
7
+ * Continuous, rate-based spawner. Emits a {@link RateSpawnConfig.rate}
8
+ * sample per second; sub-frame fractions accumulate so low rates (e.g.
9
+ * 0.5 particles/s) remain accurate over time.
10
+ *
11
+ * Each property is independently randomised via its {@link Distribution}.
12
+ * Every spawned particle gets a fresh sample for every configured field.
13
+ */
14
+ var RateSpawn = class extends SpawnModule {
15
+ config;
16
+ _accumulator = 0;
17
+ _vec = new Vector();
18
+ _color = new Color();
19
+ constructor(config) {
20
+ super();
21
+ this.config = config;
22
+ }
23
+ apply(emitter, dt) {
24
+ const cfg = this.config;
25
+ const rate = cfg.rate.sample();
26
+ this._accumulator += rate * dt;
27
+ const count = this._accumulator | 0;
28
+ if (count <= 0) return;
29
+ this._accumulator -= count;
30
+ for (let i = 0; i < count; i++) {
31
+ const particle = emitter.emit();
32
+ if (particle === null) {
33
+ this._accumulator = 0;
34
+ return;
35
+ }
36
+ fillParticle(particle, cfg, this._vec, this._color);
37
+ }
38
+ }
39
+ };
73
40
 
41
+ //#endregion
74
42
  export { RateSpawn };
75
- //# sourceMappingURL=RateSpawn.js.map
43
+ //# sourceMappingURL=RateSpawn.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"RateSpawn.js","sources":["../../../../src/modules/RateSpawn.ts"],"sourcesContent":[null],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"RateSpawn.js","names":[],"sources":["../../../src/modules/RateSpawn.ts"],"sourcesContent":["import { Color } from '@codexo/exojs';\nimport { Vector } from '@codexo/exojs';\n\nimport type { Distribution } from '#distributions/Distribution';\nimport type { ParticleEmitter } from '#ParticleStorage';\n\nimport { fillParticle, type ParticleSpawnFields } from './spawnFields';\nimport { SpawnModule } from './SpawnModule';\n\n/** Spawn configuration for {@link RateSpawn}: the emission rate plus the shared per-property fields. */\nexport interface RateSpawnConfig extends ParticleSpawnFields {\n /** Particles emitted per second. Sampled each frame. */\n rate: Distribution<number>;\n}\n\n/**\n * Continuous, rate-based spawner. Emits a {@link RateSpawnConfig.rate}\n * sample per second; sub-frame fractions accumulate so low rates (e.g.\n * 0.5 particles/s) remain accurate over time.\n *\n * Each property is independently randomised via its {@link Distribution}.\n * Every spawned particle gets a fresh sample for every configured field.\n */\nexport class RateSpawn extends SpawnModule {\n public config: RateSpawnConfig;\n\n private _accumulator = 0;\n private readonly _vec = new Vector();\n private readonly _color = new Color();\n\n public constructor(config: RateSpawnConfig) {\n super();\n this.config = config;\n }\n\n public override apply(emitter: ParticleEmitter, dt: number): void {\n const cfg = this.config;\n const rate = cfg.rate.sample();\n\n this._accumulator += rate * dt;\n\n const count = this._accumulator | 0;\n\n if (count <= 0) {\n return;\n }\n\n this._accumulator -= count;\n\n for (let i = 0; i < count; i++) {\n const particle = emitter.emit();\n\n if (particle === null) {\n this._accumulator = 0;\n\n return;\n }\n\n fillParticle(particle, cfg, this._vec, this._color);\n }\n }\n}\n"],"mappings":";;;;;;;;;;;;;AAuBA,IAAa,YAAb,cAA+B,YAAY;CACzC,AAAO;CAEP,AAAQ,eAAe;CACvB,AAAiB,OAAO,IAAI,OAAO;CACnC,AAAiB,SAAS,IAAI,MAAM;CAEpC,AAAO,YAAY,QAAyB;EAC1C,MAAM;EACN,KAAK,SAAS;CAChB;CAEA,AAAgB,MAAM,SAA0B,IAAkB;EAChE,MAAM,MAAM,KAAK;EACjB,MAAM,OAAO,IAAI,KAAK,OAAO;EAE7B,KAAK,gBAAgB,OAAO;EAE5B,MAAM,QAAQ,KAAK,eAAe;EAElC,IAAI,SAAS,GACX;EAGF,KAAK,gBAAgB;EAErB,KAAK,IAAI,IAAI,GAAG,IAAI,OAAO,KAAK;GAC9B,MAAM,WAAW,QAAQ,KAAK;GAE9B,IAAI,aAAa,MAAM;IACrB,KAAK,eAAe;IAEpB;GACF;GAEA,aAAa,UAAU,KAAK,KAAK,MAAM,KAAK,MAAM;EACpD;CACF;AACF"}
@@ -1,11 +1,11 @@
1
- import type { ParticleSystem } from "#ParticleSystem";
1
+ import type { ParticleBatch } from '#ParticleStorage';
2
2
  import { UpdateModule } from './UpdateModule';
3
3
  import type { WgslContribution } from './WgslContribution';
4
4
  /**
5
5
  * Pushes every live particle away from a fixed point in the system's local
6
6
  * coordinate space. Acceleration magnitude is `strength` (units / s²)
7
7
  * along the direction `(particle − point)`. The optional `radius` controls
8
- * the influence range particles farther than `radius` are unaffected.
8
+ * the influence range - particles farther than `radius` are unaffected.
9
9
  * Setting `radius = 0` (default) means infinite range with no falloff.
10
10
  *
11
11
  * Use cases: shockwaves, explosion blast, mouse-cursor repel field.
@@ -18,7 +18,8 @@ export declare class RepelFromPoint extends UpdateModule {
18
18
  strength: number;
19
19
  radius: number;
20
20
  constructor(x: number, y: number, strength: number, radius?: number);
21
- apply(system: ParticleSystem, dt: number): void;
21
+ apply(particles: ParticleBatch, dt: number): void;
22
22
  wgsl(): WgslContribution;
23
23
  writeUniforms(view: DataView, offset: number): void;
24
24
  }
25
+ //# sourceMappingURL=RepelFromPoint.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"RepelFromPoint.d.ts","sourceRoot":"","sources":["../../../src/modules/RepelFromPoint.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AAEtD,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAC9C,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AAE3D;;;;;;;;;;GAUG;AACH,qBAAa,cAAe,SAAQ,YAAY;IACvC,CAAC,EAAE,MAAM,CAAC;IACV,CAAC,EAAE,MAAM,CAAC;IACV,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;gBAEH,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,SAAI;IAQrD,KAAK,CAAC,SAAS,EAAE,aAAa,EAAE,EAAE,EAAE,MAAM,GAAG,IAAI;IAwBjD,IAAI,IAAI,gBAAgB;IAuBxB,aAAa,CAAC,IAAI,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,GAAG,IAAI;CAMpE"}
@@ -1,56 +1,65 @@
1
- import { UpdateModule } from './UpdateModule.js';
1
+ import { UpdateModule } from "./UpdateModule.js";
2
2
 
3
+ //#region src/modules/RepelFromPoint.ts
3
4
  /**
4
- * Pushes every live particle away from a fixed point in the system's local
5
- * coordinate space. Acceleration magnitude is `strength` (units / s²)
6
- * along the direction `(particle − point)`. The optional `radius` controls
7
- * the influence range particles farther than `radius` are unaffected.
8
- * Setting `radius = 0` (default) means infinite range with no falloff.
9
- *
10
- * Use cases: shockwaves, explosion blast, mouse-cursor repel field.
11
- *
12
- * GPU-eligible.
13
- */
14
- class RepelFromPoint extends UpdateModule {
15
- x;
16
- y;
17
- strength;
18
- radius;
19
- constructor(x, y, strength, radius = 0) {
20
- super();
21
- this.x = x;
22
- this.y = y;
23
- this.strength = strength;
24
- this.radius = radius;
25
- }
26
- apply(system, dt) {
27
- const { posX, posY, velX, velY, liveCount } = system;
28
- const { x, y, strength, radius } = this;
29
- const radiusSq = radius * radius;
30
- for (let i = 0; i < liveCount; i++) {
31
- const dx = (posX[i] ?? 0) - x;
32
- const dy = (posY[i] ?? 0) - y;
33
- const distSq = dx * dx + dy * dy;
34
- if (distSq < 1e-10)
35
- continue;
36
- if (radius > 0 && distSq > radiusSq)
37
- continue;
38
- const dist = Math.sqrt(distSq);
39
- const falloff = radius > 0 ? 1 - dist / radius : 1;
40
- const a = (strength * falloff * dt) / dist;
41
- velX[i] = (velX[i] ?? 0) + dx * a;
42
- velY[i] = (velY[i] ?? 0) + dy * a;
43
- }
44
- }
45
- wgsl() {
46
- return {
47
- key: 'RepelFromPoint',
48
- uniforms: [
49
- { name: 'point', type: 'vec2<f32>' },
50
- { name: 'strength', type: 'f32' },
51
- { name: 'radius', type: 'f32' },
52
- ],
53
- body: `
5
+ * Pushes every live particle away from a fixed point in the system's local
6
+ * coordinate space. Acceleration magnitude is `strength` (units / s²)
7
+ * along the direction `(particle − point)`. The optional `radius` controls
8
+ * the influence range - particles farther than `radius` are unaffected.
9
+ * Setting `radius = 0` (default) means infinite range with no falloff.
10
+ *
11
+ * Use cases: shockwaves, explosion blast, mouse-cursor repel field.
12
+ *
13
+ * GPU-eligible.
14
+ */
15
+ var RepelFromPoint = class extends UpdateModule {
16
+ x;
17
+ y;
18
+ strength;
19
+ radius;
20
+ constructor(x, y, strength, radius = 0) {
21
+ super();
22
+ this.x = x;
23
+ this.y = y;
24
+ this.strength = strength;
25
+ this.radius = radius;
26
+ }
27
+ apply(particles, dt) {
28
+ const { x: posX, y: posY } = particles.position;
29
+ const { x: velX, y: velY } = particles.velocity;
30
+ const liveCount = particles.count;
31
+ const { x, y, strength, radius } = this;
32
+ const radiusSq = radius * radius;
33
+ for (let i = 0; i < liveCount; i++) {
34
+ const dx = (posX[i] ?? 0) - x;
35
+ const dy = (posY[i] ?? 0) - y;
36
+ const distSq = dx * dx + dy * dy;
37
+ if (distSq < 1e-10) continue;
38
+ if (radius > 0 && distSq > radiusSq) continue;
39
+ const dist = Math.sqrt(distSq);
40
+ const a = strength * (radius > 0 ? 1 - dist / radius : 1) * dt / dist;
41
+ velX[i] = (velX[i] ?? 0) + dx * a;
42
+ velY[i] = (velY[i] ?? 0) + dy * a;
43
+ }
44
+ }
45
+ wgsl() {
46
+ return {
47
+ key: "RepelFromPoint",
48
+ uniforms: [
49
+ {
50
+ name: "point",
51
+ type: "vec2<f32>"
52
+ },
53
+ {
54
+ name: "strength",
55
+ type: "f32"
56
+ },
57
+ {
58
+ name: "radius",
59
+ type: "f32"
60
+ }
61
+ ],
62
+ body: `
54
63
  let repelDelta = positions[idx] - modules.u_RepelFromPoint.point;
55
64
  let repelDistSq = dot(repelDelta, repelDelta);
56
65
  let repelRadius = modules.u_RepelFromPoint.radius;
@@ -61,16 +70,17 @@ class RepelFromPoint extends UpdateModule {
61
70
  let repelAccel = (modules.u_RepelFromPoint.strength * repelFalloff * dt) / repelDist;
62
71
  velocities[idx] = velocities[idx] + repelDelta * repelAccel;
63
72
  }
64
- `,
65
- };
66
- }
67
- writeUniforms(view, offset) {
68
- view.setFloat32(offset + 0, this.x, true);
69
- view.setFloat32(offset + 4, this.y, true);
70
- view.setFloat32(offset + 8, this.strength, true);
71
- view.setFloat32(offset + 12, this.radius, true);
72
- }
73
- }
73
+ `
74
+ };
75
+ }
76
+ writeUniforms(view, offset) {
77
+ view.setFloat32(offset + 0, this.x, true);
78
+ view.setFloat32(offset + 4, this.y, true);
79
+ view.setFloat32(offset + 8, this.strength, true);
80
+ view.setFloat32(offset + 12, this.radius, true);
81
+ }
82
+ };
74
83
 
84
+ //#endregion
75
85
  export { RepelFromPoint };
76
- //# sourceMappingURL=RepelFromPoint.js.map
86
+ //# sourceMappingURL=RepelFromPoint.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"RepelFromPoint.js","sources":["../../../../src/modules/RepelFromPoint.ts"],"sourcesContent":[null],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"RepelFromPoint.js","names":[],"sources":["../../../src/modules/RepelFromPoint.ts"],"sourcesContent":["import type { ParticleBatch } from '#ParticleStorage';\n\nimport { UpdateModule } from './UpdateModule';\nimport type { WgslContribution } from './WgslContribution';\n\n/**\n * Pushes every live particle away from a fixed point in the system's local\n * coordinate space. Acceleration magnitude is `strength` (units / s²)\n * along the direction `(particle − point)`. The optional `radius` controls\n * the influence range - particles farther than `radius` are unaffected.\n * Setting `radius = 0` (default) means infinite range with no falloff.\n *\n * Use cases: shockwaves, explosion blast, mouse-cursor repel field.\n *\n * GPU-eligible.\n */\nexport class RepelFromPoint extends UpdateModule {\n public x: number;\n public y: number;\n public strength: number;\n public radius: number;\n\n public constructor(x: number, y: number, strength: number, radius = 0) {\n super();\n this.x = x;\n this.y = y;\n this.strength = strength;\n this.radius = radius;\n }\n\n public override apply(particles: ParticleBatch, dt: number): void {\n const { x: posX, y: posY } = particles.position;\n const { x: velX, y: velY } = particles.velocity;\n const liveCount = particles.count;\n const { x, y, strength, radius } = this;\n const radiusSq = radius * radius;\n\n for (let i = 0; i < liveCount; i++) {\n const dx = (posX[i] ?? 0) - x;\n const dy = (posY[i] ?? 0) - y;\n const distSq = dx * dx + dy * dy;\n\n if (distSq < 1e-10) continue;\n if (radius > 0 && distSq > radiusSq) continue;\n\n const dist = Math.sqrt(distSq);\n const falloff = radius > 0 ? 1 - dist / radius : 1;\n const a = (strength * falloff * dt) / dist;\n\n velX[i] = (velX[i] ?? 0) + dx * a;\n velY[i] = (velY[i] ?? 0) + dy * a;\n }\n }\n\n public override wgsl(): WgslContribution {\n return {\n key: 'RepelFromPoint',\n uniforms: [\n { name: 'point', type: 'vec2<f32>' },\n { name: 'strength', type: 'f32' },\n { name: 'radius', type: 'f32' },\n ],\n body: `\n let repelDelta = positions[idx] - modules.u_RepelFromPoint.point;\n let repelDistSq = dot(repelDelta, repelDelta);\n let repelRadius = modules.u_RepelFromPoint.radius;\n let repelInRange = (repelRadius <= 0.0) || (repelDistSq <= repelRadius * repelRadius);\n if (repelDistSq > 0.0000001 && repelInRange) {\n let repelDist = sqrt(repelDistSq);\n let repelFalloff = select(1.0, 1.0 - repelDist / max(repelRadius, 0.000001), repelRadius > 0.0);\n let repelAccel = (modules.u_RepelFromPoint.strength * repelFalloff * dt) / repelDist;\n velocities[idx] = velocities[idx] + repelDelta * repelAccel;\n }\n `,\n };\n }\n\n public override writeUniforms(view: DataView, offset: number): void {\n view.setFloat32(offset + 0, this.x, true);\n view.setFloat32(offset + 4, this.y, true);\n view.setFloat32(offset + 8, this.strength, true);\n view.setFloat32(offset + 12, this.radius, true);\n }\n}\n"],"mappings":";;;;;;;;;;;;;;AAgBA,IAAa,iBAAb,cAAoC,aAAa;CAC/C,AAAO;CACP,AAAO;CACP,AAAO;CACP,AAAO;CAEP,AAAO,YAAY,GAAW,GAAW,UAAkB,SAAS,GAAG;EACrE,MAAM;EACN,KAAK,IAAI;EACT,KAAK,IAAI;EACT,KAAK,WAAW;EAChB,KAAK,SAAS;CAChB;CAEA,AAAgB,MAAM,WAA0B,IAAkB;EAChE,MAAM,EAAE,GAAG,MAAM,GAAG,SAAS,UAAU;EACvC,MAAM,EAAE,GAAG,MAAM,GAAG,SAAS,UAAU;EACvC,MAAM,YAAY,UAAU;EAC5B,MAAM,EAAE,GAAG,GAAG,UAAU,WAAW;EACnC,MAAM,WAAW,SAAS;EAE1B,KAAK,IAAI,IAAI,GAAG,IAAI,WAAW,KAAK;GAClC,MAAM,MAAM,KAAK,MAAM,KAAK;GAC5B,MAAM,MAAM,KAAK,MAAM,KAAK;GAC5B,MAAM,SAAS,KAAK,KAAK,KAAK;GAE9B,IAAI,SAAS,OAAO;GACpB,IAAI,SAAS,KAAK,SAAS,UAAU;GAErC,MAAM,OAAO,KAAK,KAAK,MAAM;GAE7B,MAAM,IAAK,YADK,SAAS,IAAI,IAAI,OAAO,SAAS,KACjB,KAAM;GAEtC,KAAK,MAAM,KAAK,MAAM,KAAK,KAAK;GAChC,KAAK,MAAM,KAAK,MAAM,KAAK,KAAK;EAClC;CACF;CAEA,AAAgB,OAAyB;EACvC,OAAO;GACL,KAAK;GACL,UAAU;IACR;KAAE,MAAM;KAAS,MAAM;IAAY;IACnC;KAAE,MAAM;KAAY,MAAM;IAAM;IAChC;KAAE,MAAM;KAAU,MAAM;IAAM;GAChC;GACA,MAAM;;;;;;;;;;;;EAYR;CACF;CAEA,AAAgB,cAAc,MAAgB,QAAsB;EAClE,KAAK,WAAW,SAAS,GAAG,KAAK,GAAG,IAAI;EACxC,KAAK,WAAW,SAAS,GAAG,KAAK,GAAG,IAAI;EACxC,KAAK,WAAW,SAAS,GAAG,KAAK,UAAU,IAAI;EAC/C,KAAK,WAAW,SAAS,IAAI,KAAK,QAAQ,IAAI;CAChD;AACF"}
@@ -1,4 +1,4 @@
1
- import type { ParticleSystem } from "#ParticleSystem";
1
+ import type { ParticleBatch } from '#ParticleStorage';
2
2
  import { UpdateModule } from './UpdateModule';
3
3
  import type { WgslContribution } from './WgslContribution';
4
4
  /**
@@ -14,7 +14,8 @@ import type { WgslContribution } from './WgslContribution';
14
14
  export declare class RotateOverLifetime extends UpdateModule {
15
15
  angularAcceleration: number;
16
16
  constructor(angularAcceleration: number);
17
- apply(system: ParticleSystem, dt: number): void;
17
+ apply(particles: ParticleBatch, dt: number): void;
18
18
  wgsl(): WgslContribution;
19
19
  writeUniforms(view: DataView, offset: number): void;
20
20
  }
21
+ //# sourceMappingURL=RotateOverLifetime.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"RotateOverLifetime.d.ts","sourceRoot":"","sources":["../../../src/modules/RotateOverLifetime.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AAEtD,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAC9C,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AAE3D;;;;;;;;;GASG;AACH,qBAAa,kBAAmB,SAAQ,YAAY;IAC3C,mBAAmB,EAAE,MAAM,CAAC;gBAEhB,mBAAmB,EAAE,MAAM;IAK9B,KAAK,CAAC,SAAS,EAAE,aAAa,EAAE,EAAE,EAAE,MAAM,GAAG,IAAI;IAUjD,IAAI,IAAI,gBAAgB;IAUxB,aAAa,CAAC,IAAI,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,GAAG,IAAI;CAGpE"}