@newkrok/three-particles 2.2.0 → 2.3.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.
package/README.md CHANGED
@@ -66,3 +66,53 @@ updateParticleSystems({now, delta, elapsed});
66
66
  # Documentation
67
67
 
68
68
  Automatically generated TypeDoc: [https://newkrok.github.io/three-particles/](https://newkrok.github.io/three-particles/)
69
+
70
+ ## Important Notes
71
+
72
+ ### Color Over Lifetime
73
+
74
+ The `colorOverLifetime` feature uses a **multiplier-based approach** (similar to Unity's particle system), where each RGB channel curve acts as a multiplier applied to the particle's `startColor`.
75
+
76
+ **Formula:** `finalColor = startColor * colorOverLifetime`
77
+
78
+ **⚠️ Important:** To achieve full color transitions, set `startColor` to white `{ r: 1, g: 1, b: 1 }`. If any channel in `startColor` is set to 0, that channel cannot be modified by `colorOverLifetime`.
79
+
80
+ **Example - Rainbow effect:**
81
+ ```javascript
82
+ {
83
+ startColor: {
84
+ min: { r: 1, g: 1, b: 1 }, // White - allows full color range
85
+ max: { r: 1, g: 1, b: 1 }
86
+ },
87
+ colorOverLifetime: {
88
+ isActive: true,
89
+ r: { // Red: full → half → off
90
+ type: 'BEZIER',
91
+ scale: 1,
92
+ bezierPoints: [
93
+ { x: 0, y: 1, percentage: 0 },
94
+ { x: 0.5, y: 0.5, percentage: 0.5 },
95
+ { x: 1, y: 0, percentage: 1 }
96
+ ]
97
+ },
98
+ g: { // Green: off → full → off
99
+ type: 'BEZIER',
100
+ scale: 1,
101
+ bezierPoints: [
102
+ { x: 0, y: 0, percentage: 0 },
103
+ { x: 0.5, y: 1, percentage: 0.5 },
104
+ { x: 1, y: 0, percentage: 1 }
105
+ ]
106
+ },
107
+ b: { // Blue: off → half → full
108
+ type: 'BEZIER',
109
+ scale: 1,
110
+ bezierPoints: [
111
+ { x: 0, y: 0, percentage: 0 },
112
+ { x: 0.5, y: 0.5, percentage: 0.5 },
113
+ { x: 1, y: 1, percentage: 1 }
114
+ ]
115
+ }
116
+ }
117
+ }
118
+ ```
@@ -1 +1 @@
1
- [{"label":"three-particles.min.js","isAsset":true,"statSize":466107,"groups":[{"label":"dist","path":"./dist","statSize":456242,"groups":[{"id":706,"label":"index.js + 26 modules (concatenated)","path":"./dist/index.js + 26 modules (concatenated)","statSize":456242,"parsedSize":0,"gzipSize":0,"concatenated":true,"groups":[{"label":"dist","path":"./dist/index.js + 26 modules (concatenated)/dist","statSize":52974,"groups":[{"id":null,"label":"index.js","path":"./dist/index.js + 26 modules (concatenated)/dist/index.js","statSize":426,"parsedSize":0,"gzipSize":0,"inaccurateSizes":true},{"label":"js/effects/three-particles","path":"./dist/index.js + 26 modules (concatenated)/dist/js/effects/three-particles","statSize":52548,"groups":[{"id":null,"label":"three-particles-bezier.js","path":"./dist/index.js + 26 modules (concatenated)/dist/js/effects/three-particles/three-particles-bezier.js","statSize":2350,"parsedSize":0,"gzipSize":0,"inaccurateSizes":true},{"id":null,"label":"three-particles-curves.js","path":"./dist/index.js + 26 modules (concatenated)/dist/js/effects/three-particles/three-particles-curves.js","statSize":2628,"parsedSize":0,"gzipSize":0,"inaccurateSizes":true},{"id":null,"label":"three-particles-modifiers.js","path":"./dist/index.js + 26 modules (concatenated)/dist/js/effects/three-particles/three-particles-modifiers.js","statSize":4748,"parsedSize":0,"gzipSize":0,"inaccurateSizes":true},{"id":null,"label":"three-particles-utils.js","path":"./dist/index.js + 26 modules (concatenated)/dist/js/effects/three-particles/three-particles-utils.js","statSize":8634,"parsedSize":0,"gzipSize":0,"inaccurateSizes":true},{"id":null,"label":"three-particles.js","path":"./dist/index.js + 26 modules (concatenated)/dist/js/effects/three-particles/three-particles.js","statSize":31198,"parsedSize":0,"gzipSize":0,"inaccurateSizes":true},{"label":"shaders","path":"./dist/index.js + 26 modules (concatenated)/dist/js/effects/three-particles/shaders","statSize":2990,"groups":[{"id":null,"label":"particle-system-fragment-shader.glsl.js","path":"./dist/index.js + 26 modules (concatenated)/dist/js/effects/three-particles/shaders/particle-system-fragment-shader.glsl.js","statSize":2039,"parsedSize":0,"gzipSize":0,"inaccurateSizes":true},{"id":null,"label":"particle-system-vertex-shader.glsl.js","path":"./dist/index.js + 26 modules (concatenated)/dist/js/effects/three-particles/shaders/particle-system-vertex-shader.glsl.js","statSize":951,"parsedSize":0,"gzipSize":0,"inaccurateSizes":true}],"parsedSize":0,"gzipSize":0,"inaccurateSizes":true}],"parsedSize":0,"gzipSize":0,"inaccurateSizes":true}],"parsedSize":0,"gzipSize":0,"inaccurateSizes":true},{"label":"node_modules","path":"./dist/index.js + 26 modules (concatenated)/node_modules","statSize":403226,"groups":[{"label":"@newkrok/three-utils/dist","path":"./dist/index.js + 26 modules (concatenated)/node_modules/@newkrok/three-utils/dist","statSize":25076,"groups":[{"id":null,"label":"index.js","path":"./dist/index.js + 26 modules (concatenated)/node_modules/@newkrok/three-utils/dist/index.js","statSize":411,"parsedSize":0,"gzipSize":0,"inaccurateSizes":true},{"id":null,"label":"callback-utils.js","path":"./dist/index.js + 26 modules (concatenated)/node_modules/@newkrok/three-utils/dist/callback-utils.js","statSize":1408,"parsedSize":0,"gzipSize":0,"inaccurateSizes":true},{"id":null,"label":"object-utils.js","path":"./dist/index.js + 26 modules (concatenated)/node_modules/@newkrok/three-utils/dist/object-utils.js","statSize":2889,"parsedSize":0,"gzipSize":0,"inaccurateSizes":true},{"id":null,"label":"time-utils.js","path":"./dist/index.js + 26 modules (concatenated)/node_modules/@newkrok/three-utils/dist/time-utils.js","statSize":1037,"parsedSize":0,"gzipSize":0,"inaccurateSizes":true},{"label":"assets","path":"./dist/index.js + 26 modules (concatenated)/node_modules/@newkrok/three-utils/dist/assets","statSize":15614,"groups":[{"id":null,"label":"index.js","path":"./dist/index.js + 26 modules (concatenated)/node_modules/@newkrok/three-utils/dist/assets/index.js","statSize":44,"parsedSize":0,"gzipSize":0,"inaccurateSizes":true},{"id":null,"label":"assets.js","path":"./dist/index.js + 26 modules (concatenated)/node_modules/@newkrok/three-utils/dist/assets/assets.js","statSize":9027,"parsedSize":0,"gzipSize":0,"inaccurateSizes":true},{"id":null,"label":"loaders.js","path":"./dist/index.js + 26 modules (concatenated)/node_modules/@newkrok/three-utils/dist/assets/loaders.js","statSize":6543,"parsedSize":0,"gzipSize":0,"inaccurateSizes":true}],"parsedSize":0,"gzipSize":0,"inaccurateSizes":true},{"label":"audio","path":"./dist/index.js + 26 modules (concatenated)/node_modules/@newkrok/three-utils/dist/audio","statSize":3717,"groups":[{"id":null,"label":"index.js","path":"./dist/index.js + 26 modules (concatenated)/node_modules/@newkrok/three-utils/dist/audio/index.js","statSize":42,"parsedSize":0,"gzipSize":0,"inaccurateSizes":true},{"id":null,"label":"audio.js","path":"./dist/index.js + 26 modules (concatenated)/node_modules/@newkrok/three-utils/dist/audio/audio.js","statSize":3675,"parsedSize":0,"gzipSize":0,"inaccurateSizes":true}],"parsedSize":0,"gzipSize":0,"inaccurateSizes":true}],"parsedSize":0,"gzipSize":0,"inaccurateSizes":true},{"label":"three/examples/jsm","path":"./dist/index.js + 26 modules (concatenated)/node_modules/three/examples/jsm","statSize":365229,"groups":[{"label":"misc","path":"./dist/index.js + 26 modules (concatenated)/node_modules/three/examples/jsm/misc","statSize":1617,"groups":[{"id":null,"label":"Gyroscope.js","path":"./dist/index.js + 26 modules (concatenated)/node_modules/three/examples/jsm/misc/Gyroscope.js","statSize":1617,"parsedSize":0,"gzipSize":0,"inaccurateSizes":true}],"parsedSize":0,"gzipSize":0,"inaccurateSizes":true},{"label":"helpers","path":"./dist/index.js + 26 modules (concatenated)/node_modules/three/examples/jsm/helpers","statSize":4384,"groups":[{"id":null,"label":"PositionalAudioHelper.js","path":"./dist/index.js + 26 modules (concatenated)/node_modules/three/examples/jsm/helpers/PositionalAudioHelper.js","statSize":4384,"parsedSize":0,"gzipSize":0,"inaccurateSizes":true}],"parsedSize":0,"gzipSize":0,"inaccurateSizes":true},{"label":"loaders","path":"./dist/index.js + 26 modules (concatenated)/node_modules/three/examples/jsm/loaders","statSize":219615,"groups":[{"id":null,"label":"FBXLoader.js","path":"./dist/index.js + 26 modules (concatenated)/node_modules/three/examples/jsm/loaders/FBXLoader.js","statSize":104876,"parsedSize":0,"gzipSize":0,"inaccurateSizes":true},{"id":null,"label":"GLTFLoader.js","path":"./dist/index.js + 26 modules (concatenated)/node_modules/three/examples/jsm/loaders/GLTFLoader.js","statSize":114739,"parsedSize":0,"gzipSize":0,"inaccurateSizes":true}],"parsedSize":0,"gzipSize":0,"inaccurateSizes":true},{"label":"libs","path":"./dist/index.js + 26 modules (concatenated)/node_modules/three/examples/jsm/libs","statSize":89384,"groups":[{"id":null,"label":"fflate.module.js","path":"./dist/index.js + 26 modules (concatenated)/node_modules/three/examples/jsm/libs/fflate.module.js","statSize":89384,"parsedSize":0,"gzipSize":0,"inaccurateSizes":true}],"parsedSize":0,"gzipSize":0,"inaccurateSizes":true},{"label":"curves","path":"./dist/index.js + 26 modules (concatenated)/node_modules/three/examples/jsm/curves","statSize":14690,"groups":[{"id":null,"label":"NURBSCurve.js","path":"./dist/index.js + 26 modules (concatenated)/node_modules/three/examples/jsm/curves/NURBSCurve.js","statSize":3888,"parsedSize":0,"gzipSize":0,"inaccurateSizes":true},{"id":null,"label":"NURBSUtils.js","path":"./dist/index.js + 26 modules (concatenated)/node_modules/three/examples/jsm/curves/NURBSUtils.js","statSize":10802,"parsedSize":0,"gzipSize":0,"inaccurateSizes":true}],"parsedSize":0,"gzipSize":0,"inaccurateSizes":true},{"label":"utils","path":"./dist/index.js + 26 modules (concatenated)/node_modules/three/examples/jsm/utils","statSize":35539,"groups":[{"id":null,"label":"BufferGeometryUtils.js","path":"./dist/index.js + 26 modules (concatenated)/node_modules/three/examples/jsm/utils/BufferGeometryUtils.js","statSize":35539,"parsedSize":0,"gzipSize":0,"inaccurateSizes":true}],"parsedSize":0,"gzipSize":0,"inaccurateSizes":true}],"parsedSize":0,"gzipSize":0,"inaccurateSizes":true},{"label":"three-noise/build","path":"./dist/index.js + 26 modules (concatenated)/node_modules/three-noise/build","statSize":12921,"groups":[{"id":null,"label":"three-noise.module.js","path":"./dist/index.js + 26 modules (concatenated)/node_modules/three-noise/build/three-noise.module.js","statSize":12921,"parsedSize":0,"gzipSize":0,"inaccurateSizes":true}],"parsedSize":0,"gzipSize":0,"inaccurateSizes":true}],"parsedSize":0,"gzipSize":0,"inaccurateSizes":true}]}],"parsedSize":0,"gzipSize":0},{"label":"node_modules/easing-functions","path":"./node_modules/easing-functions","statSize":9865,"groups":[{"id":300,"label":"index.js","path":"./node_modules/easing-functions/index.js","statSize":9865}],"parsedSize":0,"gzipSize":0}],"isInitialByEntrypoint":{"main":true}}]
1
+ [{"label":"three-particles.min.js","isAsset":true,"statSize":483424,"parsedSize":123254,"gzipSize":37926,"groups":[{"label":"dist","path":"./dist","statSize":473559,"groups":[{"id":706,"label":"index.js + 26 modules (concatenated)","path":"./dist/index.js + 26 modules (concatenated)","statSize":473559,"parsedSize":123254,"gzipSize":37926,"concatenated":true,"groups":[{"label":"dist","path":"./dist/index.js + 26 modules (concatenated)/dist","statSize":70181,"groups":[{"id":null,"label":"index.js","path":"./dist/index.js + 26 modules (concatenated)/dist/index.js","statSize":426,"parsedSize":110,"gzipSize":34,"inaccurateSizes":true},{"label":"js/effects/three-particles","path":"./dist/index.js + 26 modules (concatenated)/dist/js/effects/three-particles","statSize":69755,"groups":[{"id":null,"label":"three-particles-bezier.js","path":"./dist/index.js + 26 modules (concatenated)/dist/js/effects/three-particles/three-particles-bezier.js","statSize":2350,"parsedSize":611,"gzipSize":188,"inaccurateSizes":true},{"id":null,"label":"three-particles-curves.js","path":"./dist/index.js + 26 modules (concatenated)/dist/js/effects/three-particles/three-particles-curves.js","statSize":3617,"parsedSize":941,"gzipSize":289,"inaccurateSizes":true},{"id":null,"label":"three-particles-modifiers.js","path":"./dist/index.js + 26 modules (concatenated)/dist/js/effects/three-particles/three-particles-modifiers.js","statSize":8644,"parsedSize":2249,"gzipSize":692,"inaccurateSizes":true},{"id":null,"label":"three-particles-utils.js","path":"./dist/index.js + 26 modules (concatenated)/dist/js/effects/three-particles/three-particles-utils.js","statSize":14332,"parsedSize":3730,"gzipSize":1147,"inaccurateSizes":true},{"id":null,"label":"three-particles.js","path":"./dist/index.js + 26 modules (concatenated)/dist/js/effects/three-particles/three-particles.js","statSize":37822,"parsedSize":9843,"gzipSize":3029,"inaccurateSizes":true},{"label":"shaders","path":"./dist/index.js + 26 modules (concatenated)/dist/js/effects/three-particles/shaders","statSize":2990,"groups":[{"id":null,"label":"particle-system-fragment-shader.glsl.js","path":"./dist/index.js + 26 modules (concatenated)/dist/js/effects/three-particles/shaders/particle-system-fragment-shader.glsl.js","statSize":2039,"parsedSize":530,"gzipSize":163,"inaccurateSizes":true},{"id":null,"label":"particle-system-vertex-shader.glsl.js","path":"./dist/index.js + 26 modules (concatenated)/dist/js/effects/three-particles/shaders/particle-system-vertex-shader.glsl.js","statSize":951,"parsedSize":247,"gzipSize":76,"inaccurateSizes":true}],"parsedSize":778,"gzipSize":239,"inaccurateSizes":true}],"parsedSize":18155,"gzipSize":5586,"inaccurateSizes":true}],"parsedSize":18266,"gzipSize":5620,"inaccurateSizes":true},{"label":"node_modules","path":"./dist/index.js + 26 modules (concatenated)/node_modules","statSize":403336,"groups":[{"label":"@newkrok/three-utils/dist","path":"./dist/index.js + 26 modules (concatenated)/node_modules/@newkrok/three-utils/dist","statSize":25076,"groups":[{"id":null,"label":"index.js","path":"./dist/index.js + 26 modules (concatenated)/node_modules/@newkrok/three-utils/dist/index.js","statSize":411,"parsedSize":106,"gzipSize":32,"inaccurateSizes":true},{"id":null,"label":"callback-utils.js","path":"./dist/index.js + 26 modules (concatenated)/node_modules/@newkrok/three-utils/dist/callback-utils.js","statSize":1408,"parsedSize":366,"gzipSize":112,"inaccurateSizes":true},{"id":null,"label":"object-utils.js","path":"./dist/index.js + 26 modules (concatenated)/node_modules/@newkrok/three-utils/dist/object-utils.js","statSize":2889,"parsedSize":751,"gzipSize":231,"inaccurateSizes":true},{"id":null,"label":"time-utils.js","path":"./dist/index.js + 26 modules (concatenated)/node_modules/@newkrok/three-utils/dist/time-utils.js","statSize":1037,"parsedSize":269,"gzipSize":83,"inaccurateSizes":true},{"label":"assets","path":"./dist/index.js + 26 modules (concatenated)/node_modules/@newkrok/three-utils/dist/assets","statSize":15614,"groups":[{"id":null,"label":"index.js","path":"./dist/index.js + 26 modules (concatenated)/node_modules/@newkrok/three-utils/dist/assets/index.js","statSize":44,"parsedSize":11,"gzipSize":3,"inaccurateSizes":true},{"id":null,"label":"assets.js","path":"./dist/index.js + 26 modules (concatenated)/node_modules/@newkrok/three-utils/dist/assets/assets.js","statSize":9027,"parsedSize":2349,"gzipSize":722,"inaccurateSizes":true},{"id":null,"label":"loaders.js","path":"./dist/index.js + 26 modules (concatenated)/node_modules/@newkrok/three-utils/dist/assets/loaders.js","statSize":6543,"parsedSize":1702,"gzipSize":524,"inaccurateSizes":true}],"parsedSize":4063,"gzipSize":1250,"inaccurateSizes":true},{"label":"audio","path":"./dist/index.js + 26 modules (concatenated)/node_modules/@newkrok/three-utils/dist/audio","statSize":3717,"groups":[{"id":null,"label":"index.js","path":"./dist/index.js + 26 modules (concatenated)/node_modules/@newkrok/three-utils/dist/audio/index.js","statSize":42,"parsedSize":10,"gzipSize":3,"inaccurateSizes":true},{"id":null,"label":"audio.js","path":"./dist/index.js + 26 modules (concatenated)/node_modules/@newkrok/three-utils/dist/audio/audio.js","statSize":3675,"parsedSize":956,"gzipSize":294,"inaccurateSizes":true}],"parsedSize":967,"gzipSize":297,"inaccurateSizes":true}],"parsedSize":6526,"gzipSize":2008,"inaccurateSizes":true},{"label":"three/examples/jsm","path":"./dist/index.js + 26 modules (concatenated)/node_modules/three/examples/jsm","statSize":365339,"groups":[{"label":"misc","path":"./dist/index.js + 26 modules (concatenated)/node_modules/three/examples/jsm/misc","statSize":1617,"groups":[{"id":null,"label":"Gyroscope.js","path":"./dist/index.js + 26 modules (concatenated)/node_modules/three/examples/jsm/misc/Gyroscope.js","statSize":1617,"parsedSize":420,"gzipSize":129,"inaccurateSizes":true}],"parsedSize":420,"gzipSize":129,"inaccurateSizes":true},{"label":"helpers","path":"./dist/index.js + 26 modules (concatenated)/node_modules/three/examples/jsm/helpers","statSize":4384,"groups":[{"id":null,"label":"PositionalAudioHelper.js","path":"./dist/index.js + 26 modules (concatenated)/node_modules/three/examples/jsm/helpers/PositionalAudioHelper.js","statSize":4384,"parsedSize":1141,"gzipSize":351,"inaccurateSizes":true}],"parsedSize":1141,"gzipSize":351,"inaccurateSizes":true},{"label":"loaders","path":"./dist/index.js + 26 modules (concatenated)/node_modules/three/examples/jsm/loaders","statSize":219725,"groups":[{"id":null,"label":"FBXLoader.js","path":"./dist/index.js + 26 modules (concatenated)/node_modules/three/examples/jsm/loaders/FBXLoader.js","statSize":104842,"parsedSize":27287,"gzipSize":8396,"inaccurateSizes":true},{"id":null,"label":"GLTFLoader.js","path":"./dist/index.js + 26 modules (concatenated)/node_modules/three/examples/jsm/loaders/GLTFLoader.js","statSize":114883,"parsedSize":29900,"gzipSize":9200,"inaccurateSizes":true}],"parsedSize":57188,"gzipSize":17597,"inaccurateSizes":true},{"label":"libs","path":"./dist/index.js + 26 modules (concatenated)/node_modules/three/examples/jsm/libs","statSize":89384,"groups":[{"id":null,"label":"fflate.module.js","path":"./dist/index.js + 26 modules (concatenated)/node_modules/three/examples/jsm/libs/fflate.module.js","statSize":89384,"parsedSize":23264,"gzipSize":7158,"inaccurateSizes":true}],"parsedSize":23264,"gzipSize":7158,"inaccurateSizes":true},{"label":"curves","path":"./dist/index.js + 26 modules (concatenated)/node_modules/three/examples/jsm/curves","statSize":14690,"groups":[{"id":null,"label":"NURBSCurve.js","path":"./dist/index.js + 26 modules (concatenated)/node_modules/three/examples/jsm/curves/NURBSCurve.js","statSize":3888,"parsedSize":1011,"gzipSize":311,"inaccurateSizes":true},{"id":null,"label":"NURBSUtils.js","path":"./dist/index.js + 26 modules (concatenated)/node_modules/three/examples/jsm/curves/NURBSUtils.js","statSize":10802,"parsedSize":2811,"gzipSize":865,"inaccurateSizes":true}],"parsedSize":3823,"gzipSize":1176,"inaccurateSizes":true},{"label":"utils","path":"./dist/index.js + 26 modules (concatenated)/node_modules/three/examples/jsm/utils","statSize":35539,"groups":[{"id":null,"label":"BufferGeometryUtils.js","path":"./dist/index.js + 26 modules (concatenated)/node_modules/three/examples/jsm/utils/BufferGeometryUtils.js","statSize":35539,"parsedSize":9249,"gzipSize":2846,"inaccurateSizes":true}],"parsedSize":9249,"gzipSize":2846,"inaccurateSizes":true}],"parsedSize":95087,"gzipSize":29258,"inaccurateSizes":true},{"label":"three-noise/build","path":"./dist/index.js + 26 modules (concatenated)/node_modules/three-noise/build","statSize":12921,"groups":[{"id":null,"label":"three-noise.module.js","path":"./dist/index.js + 26 modules (concatenated)/node_modules/three-noise/build/three-noise.module.js","statSize":12921,"parsedSize":3362,"gzipSize":1034,"inaccurateSizes":true}],"parsedSize":3362,"gzipSize":1034,"inaccurateSizes":true}],"parsedSize":104976,"gzipSize":32302,"inaccurateSizes":true}]}],"parsedSize":123254,"gzipSize":37926},{"label":"node_modules/easing-functions","path":"./node_modules/easing-functions","statSize":9865,"groups":[{"id":300,"label":"index.js","path":"./node_modules/easing-functions/index.js","statSize":9865}],"parsedSize":0,"gzipSize":0}],"isInitialByEntrypoint":{"main":true}}]
@@ -1,37 +1,108 @@
1
1
  import { CurveFunction } from './types.js';
2
+ /**
3
+ * Predefined easing function identifiers for animating particle properties
4
+ * over their lifetime.
5
+ *
6
+ * These functions control the rate of change and create different animation
7
+ * feels. Each type has three variants:
8
+ * - **IN**: Starts slow, accelerates toward the end
9
+ * - **OUT**: Starts fast, decelerates toward the end
10
+ * - **IN_OUT**: Combines both, slow at start and end, fast in middle
11
+ *
12
+ * @enum {string}
13
+ *
14
+ * @see {@link https://easings.net/} - Visual reference for easing functions
15
+ */
2
16
  export declare const enum CurveFunctionId {
17
+ /** Use custom Bezier curve (not an easing function) */
3
18
  BEZIER = "BEZIER",
19
+ /** Linear interpolation with constant rate of change */
4
20
  LINEAR = "LINEAR",
21
+ /** Quadratic (t²) easing - gentle acceleration */
5
22
  QUADRATIC_IN = "QUADRATIC_IN",
23
+ /** Quadratic (t²) easing - gentle deceleration */
6
24
  QUADRATIC_OUT = "QUADRATIC_OUT",
25
+ /** Quadratic (t²) easing - gentle acceleration then deceleration */
7
26
  QUADRATIC_IN_OUT = "QUADRATIC_IN_OUT",
27
+ /** Cubic (t³) easing - moderate acceleration */
8
28
  CUBIC_IN = "CUBIC_IN",
29
+ /** Cubic (t³) easing - moderate deceleration */
9
30
  CUBIC_OUT = "CUBIC_OUT",
31
+ /** Cubic (t³) easing - moderate acceleration then deceleration */
10
32
  CUBIC_IN_OUT = "CUBIC_IN_OUT",
33
+ /** Quartic (t⁴) easing - strong acceleration */
11
34
  QUARTIC_IN = "QUARTIC_IN",
35
+ /** Quartic (t⁴) easing - strong deceleration */
12
36
  QUARTIC_OUT = "QUARTIC_OUT",
37
+ /** Quartic (t⁴) easing - strong acceleration then deceleration */
13
38
  QUARTIC_IN_OUT = "QUARTIC_IN_OUT",
39
+ /** Quintic (t⁵) easing - very strong acceleration */
14
40
  QUINTIC_IN = "QUINTIC_IN",
41
+ /** Quintic (t⁵) easing - very strong deceleration */
15
42
  QUINTIC_OUT = "QUINTIC_OUT",
43
+ /** Quintic (t⁵) easing - very strong acceleration then deceleration */
16
44
  QUINTIC_IN_OUT = "QUINTIC_IN_OUT",
45
+ /** Sinusoidal easing - smooth, natural acceleration */
17
46
  SINUSOIDAL_IN = "SINUSOIDAL_IN",
47
+ /** Sinusoidal easing - smooth, natural deceleration */
18
48
  SINUSOIDAL_OUT = "SINUSOIDAL_OUT",
49
+ /** Sinusoidal easing - smooth acceleration then deceleration */
19
50
  SINUSOIDAL_IN_OUT = "SINUSOIDAL_IN_OUT",
51
+ /** Exponential easing - dramatic, explosive acceleration */
20
52
  EXPONENTIAL_IN = "EXPONENTIAL_IN",
53
+ /** Exponential easing - dramatic, explosive deceleration */
21
54
  EXPONENTIAL_OUT = "EXPONENTIAL_OUT",
55
+ /** Exponential easing - dramatic acceleration then deceleration */
22
56
  EXPONENTIAL_IN_OUT = "EXPONENTIAL_IN_OUT",
57
+ /** Circular easing - sharp acceleration with curved trajectory */
23
58
  CIRCULAR_IN = "CIRCULAR_IN",
59
+ /** Circular easing - sharp deceleration with curved trajectory */
24
60
  CIRCULAR_OUT = "CIRCULAR_OUT",
61
+ /** Circular easing - sharp acceleration then deceleration */
25
62
  CIRCULAR_IN_OUT = "CIRCULAR_IN_OUT",
63
+ /** Elastic easing - oscillates back before accelerating (spring-like) */
26
64
  ELASTIC_IN = "ELASTIC_IN",
65
+ /** Elastic easing - overshoots then oscillates back (spring-like) */
27
66
  ELASTIC_OUT = "ELASTIC_OUT",
67
+ /** Elastic easing - oscillates at both ends (spring-like) */
28
68
  ELASTIC_IN_OUT = "ELASTIC_IN_OUT",
69
+ /** Back easing - pulls back before accelerating forward */
29
70
  BACK_IN = "BACK_IN",
71
+ /** Back easing - overshoots forward then pulls back */
30
72
  BACK_OUT = "BACK_OUT",
73
+ /** Back easing - pulls back, overshoots, then settles */
31
74
  BACK_IN_OUT = "BACK_IN_OUT",
75
+ /** Bounce easing - bounces at the start */
32
76
  BOUNCE_IN = "BOUNCE_IN",
77
+ /** Bounce easing - bounces at the end (like a ball landing) */
33
78
  BOUNCE_OUT = "BOUNCE_OUT",
79
+ /** Bounce easing - bounces at both start and end */
34
80
  BOUNCE_IN_OUT = "BOUNCE_IN_OUT"
35
81
  }
82
+ /**
83
+ * Resolves a curve function from an identifier or returns the function itself.
84
+ *
85
+ * This utility function allows you to use either a {@link CurveFunctionId} string
86
+ * identifier or a custom function directly.
87
+ *
88
+ * @param curveFunctionId - Either a {@link CurveFunctionId} enum value or a
89
+ * custom {@link CurveFunction} implementation
90
+ * @returns The actual easing function that takes a normalized time value (0-1)
91
+ * and returns the eased value
92
+ *
93
+ * @example
94
+ * ```typescript
95
+ * import { getCurveFunction, CurveFunctionId } from '@newkrok/three-particles';
96
+ *
97
+ * // Using a predefined easing function
98
+ * const easingFunc = getCurveFunction(CurveFunctionId.CUBIC_OUT);
99
+ * console.log(easingFunc(0.5)); // Returns eased value at 50% progress
100
+ *
101
+ * // Using a custom function
102
+ * const customEasing = (t: number) => t * t; // Quadratic
103
+ * const customFunc = getCurveFunction(customEasing);
104
+ * console.log(customFunc(0.5)); // Returns 0.25
105
+ * ```
106
+ */
36
107
  export declare const getCurveFunction: (curveFunctionId: CurveFunctionId | CurveFunction) => CurveFunction;
37
108
  //# sourceMappingURL=three-particles-curves.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"three-particles-curves.d.ts","sourceRoot":"","sources":["../../../../src/js/effects/three-particles/three-particles-curves.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAE3C,0BAAkB,eAAe;IAC/B,MAAM,WAAW;IACjB,MAAM,WAAW;IACjB,YAAY,iBAAiB;IAC7B,aAAa,kBAAkB;IAC/B,gBAAgB,qBAAqB;IACrC,QAAQ,aAAa;IACrB,SAAS,cAAc;IACvB,YAAY,iBAAiB;IAC7B,UAAU,eAAe;IACzB,WAAW,gBAAgB;IAC3B,cAAc,mBAAmB;IACjC,UAAU,eAAe;IACzB,WAAW,gBAAgB;IAC3B,cAAc,mBAAmB;IACjC,aAAa,kBAAkB;IAC/B,cAAc,mBAAmB;IACjC,iBAAiB,sBAAsB;IACvC,cAAc,mBAAmB;IACjC,eAAe,oBAAoB;IACnC,kBAAkB,uBAAuB;IACzC,WAAW,gBAAgB;IAC3B,YAAY,iBAAiB;IAC7B,eAAe,oBAAoB;IACnC,UAAU,eAAe;IACzB,WAAW,gBAAgB;IAC3B,cAAc,mBAAmB;IACjC,OAAO,YAAY;IACnB,QAAQ,aAAa;IACrB,WAAW,gBAAgB;IAC3B,SAAS,cAAc;IACvB,UAAU,eAAe;IACzB,aAAa,kBAAkB;CAChC;AAoCD,eAAO,MAAM,gBAAgB,GAC3B,iBAAiB,eAAe,GAAG,aAAa,KAC/C,aAGuC,CAAC"}
1
+ {"version":3,"file":"three-particles-curves.d.ts","sourceRoot":"","sources":["../../../../src/js/effects/three-particles/three-particles-curves.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAE3C;;;;;;;;;;;;;GAaG;AACH,0BAAkB,eAAe;IAC/B,uDAAuD;IACvD,MAAM,WAAW;IAEjB,wDAAwD;IACxD,MAAM,WAAW;IAEjB,kDAAkD;IAClD,YAAY,iBAAiB;IAC7B,kDAAkD;IAClD,aAAa,kBAAkB;IAC/B,oEAAoE;IACpE,gBAAgB,qBAAqB;IAErC,gDAAgD;IAChD,QAAQ,aAAa;IACrB,gDAAgD;IAChD,SAAS,cAAc;IACvB,kEAAkE;IAClE,YAAY,iBAAiB;IAE7B,gDAAgD;IAChD,UAAU,eAAe;IACzB,gDAAgD;IAChD,WAAW,gBAAgB;IAC3B,kEAAkE;IAClE,cAAc,mBAAmB;IAEjC,qDAAqD;IACrD,UAAU,eAAe;IACzB,qDAAqD;IACrD,WAAW,gBAAgB;IAC3B,uEAAuE;IACvE,cAAc,mBAAmB;IAEjC,uDAAuD;IACvD,aAAa,kBAAkB;IAC/B,uDAAuD;IACvD,cAAc,mBAAmB;IACjC,gEAAgE;IAChE,iBAAiB,sBAAsB;IAEvC,4DAA4D;IAC5D,cAAc,mBAAmB;IACjC,4DAA4D;IAC5D,eAAe,oBAAoB;IACnC,mEAAmE;IACnE,kBAAkB,uBAAuB;IAEzC,kEAAkE;IAClE,WAAW,gBAAgB;IAC3B,kEAAkE;IAClE,YAAY,iBAAiB;IAC7B,6DAA6D;IAC7D,eAAe,oBAAoB;IAEnC,yEAAyE;IACzE,UAAU,eAAe;IACzB,qEAAqE;IACrE,WAAW,gBAAgB;IAC3B,6DAA6D;IAC7D,cAAc,mBAAmB;IAEjC,2DAA2D;IAC3D,OAAO,YAAY;IACnB,uDAAuD;IACvD,QAAQ,aAAa;IACrB,yDAAyD;IACzD,WAAW,gBAAgB;IAE3B,2CAA2C;IAC3C,SAAS,cAAc;IACvB,+DAA+D;IAC/D,UAAU,eAAe;IACzB,oDAAoD;IACpD,aAAa,kBAAkB;CAChC;AAoCD;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,eAAO,MAAM,gBAAgB,GAC3B,iBAAiB,eAAe,GAAG,aAAa,KAC/C,aAGuC,CAAC"}
@@ -32,6 +32,31 @@ const CurveFunctionIdMap = {
32
32
  ["BOUNCE_OUT" /* CurveFunctionId.BOUNCE_OUT */]: Easing.Bounce.Out,
33
33
  ["BOUNCE_IN_OUT" /* CurveFunctionId.BOUNCE_IN_OUT */]: Easing.Bounce.InOut,
34
34
  };
35
+ /**
36
+ * Resolves a curve function from an identifier or returns the function itself.
37
+ *
38
+ * This utility function allows you to use either a {@link CurveFunctionId} string
39
+ * identifier or a custom function directly.
40
+ *
41
+ * @param curveFunctionId - Either a {@link CurveFunctionId} enum value or a
42
+ * custom {@link CurveFunction} implementation
43
+ * @returns The actual easing function that takes a normalized time value (0-1)
44
+ * and returns the eased value
45
+ *
46
+ * @example
47
+ * ```typescript
48
+ * import { getCurveFunction, CurveFunctionId } from '@newkrok/three-particles';
49
+ *
50
+ * // Using a predefined easing function
51
+ * const easingFunc = getCurveFunction(CurveFunctionId.CUBIC_OUT);
52
+ * console.log(easingFunc(0.5)); // Returns eased value at 50% progress
53
+ *
54
+ * // Using a custom function
55
+ * const customEasing = (t: number) => t * t; // Quadratic
56
+ * const customFunc = getCurveFunction(customEasing);
57
+ * console.log(customFunc(0.5)); // Returns 0.25
58
+ * ```
59
+ */
35
60
  export const getCurveFunction = (curveFunctionId) => typeof curveFunctionId === 'function'
36
61
  ? curveFunctionId
37
62
  : CurveFunctionIdMap[curveFunctionId];
@@ -1,25 +1,115 @@
1
+ /**
2
+ * Defines the coordinate space in which particles are simulated.
3
+ *
4
+ * @enum {string}
5
+ */
1
6
  export declare const enum SimulationSpace {
7
+ /**
8
+ * Particles move relative to the emitter's local coordinate system.
9
+ * When the emitter moves or rotates, particles move with it.
10
+ * Ideal for effects attached to moving objects (e.g., engine trails, character auras).
11
+ */
2
12
  LOCAL = "LOCAL",
13
+ /**
14
+ * Particles move in world space and are independent of the emitter's transform.
15
+ * Once emitted, particles remain stationary or move according to their velocity in world coordinates.
16
+ * Ideal for environmental effects (e.g., smoke, explosions, ambient particles).
17
+ */
3
18
  WORLD = "WORLD"
4
19
  }
20
+ /**
21
+ * Defines the geometric shape from which particles are emitted.
22
+ *
23
+ * @enum {string}
24
+ */
5
25
  export declare const enum Shape {
26
+ /**
27
+ * Emit particles from a spherical volume or shell.
28
+ * Configure with {@link Sphere} properties (radius, arc, radiusThickness).
29
+ */
6
30
  SPHERE = "SPHERE",
31
+ /**
32
+ * Emit particles from a conical volume or shell.
33
+ * Configure with {@link Cone} properties (angle, radius, arc, radiusThickness).
34
+ * Useful for directional effects like fire, smoke plumes, or spray effects.
35
+ */
7
36
  CONE = "CONE",
37
+ /**
38
+ * Emit particles from a box volume, shell, or edges.
39
+ * Configure with {@link Box} properties (scale, emitFrom).
40
+ * Useful for area-based effects like dust clouds or rain.
41
+ */
8
42
  BOX = "BOX",
43
+ /**
44
+ * Emit particles from a circular area or edge.
45
+ * Configure with {@link Circle} properties (radius, arc, radiusThickness).
46
+ * Useful for ground impacts, rings, or radial effects.
47
+ */
9
48
  CIRCLE = "CIRCLE",
49
+ /**
50
+ * Emit particles from a rectangular area.
51
+ * Configure with {@link Rectangle} properties (scale, rotation).
52
+ * Useful for planar effects like rain on a surface or screen effects.
53
+ */
10
54
  RECTANGLE = "RECTANGLE"
11
55
  }
56
+ /**
57
+ * Defines where on a shape particles are emitted from.
58
+ * Not all shapes support all emit modes.
59
+ *
60
+ * @enum {string}
61
+ */
12
62
  export declare const enum EmitFrom {
63
+ /**
64
+ * Emit particles from random positions within the entire volume of the shape.
65
+ * Supported by: SPHERE, CONE, BOX.
66
+ */
13
67
  VOLUME = "VOLUME",
68
+ /**
69
+ * Emit particles from the surface/shell of the shape.
70
+ * Supported by: SPHERE, CONE, BOX.
71
+ */
14
72
  SHELL = "SHELL",
73
+ /**
74
+ * Emit particles from the edges of the shape.
75
+ * Supported by: BOX.
76
+ */
15
77
  EDGE = "EDGE"
16
78
  }
79
+ /**
80
+ * Defines how texture sheet animation is timed.
81
+ *
82
+ * @enum {string}
83
+ */
17
84
  export declare const enum TimeMode {
85
+ /**
86
+ * Animation frames are based on the particle's lifetime percentage.
87
+ * The animation completes once over the particle's lifetime.
88
+ */
18
89
  LIFETIME = "LIFETIME",
90
+ /**
91
+ * Animation frames are based on frames per second (FPS).
92
+ * The animation runs at a fixed speed regardless of particle lifetime.
93
+ */
19
94
  FPS = "FPS"
20
95
  }
96
+ /**
97
+ * Defines the type of curve function used for animating values over a particle's lifetime.
98
+ *
99
+ * @enum {string}
100
+ */
21
101
  export declare const enum LifeTimeCurve {
102
+ /**
103
+ * Use custom Bezier curves with control points.
104
+ * Provides maximum control over the animation curve shape.
105
+ * See {@link BezierCurve} for configuration.
106
+ */
22
107
  BEZIER = "BEZIER",
108
+ /**
109
+ * Use predefined easing functions (e.g., easeInQuad, easeOutCubic).
110
+ * Convenient for common animation patterns.
111
+ * See {@link EasingCurve} and {@link CurveFunctionId} for available functions.
112
+ */
23
113
  EASING = "EASING"
24
114
  }
25
115
  //# sourceMappingURL=three-particles-enums.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"three-particles-enums.d.ts","sourceRoot":"","sources":["../../../../src/js/effects/three-particles/three-particles-enums.ts"],"names":[],"mappings":"AAAA,0BAAkB,eAAe;IAC/B,KAAK,UAAU;IACf,KAAK,UAAU;CAChB;AAED,0BAAkB,KAAK;IACrB,MAAM,WAAW;IACjB,IAAI,SAAS;IACb,GAAG,QAAQ;IACX,MAAM,WAAW;IACjB,SAAS,cAAc;CACxB;AAED,0BAAkB,QAAQ;IACxB,MAAM,WAAW;IACjB,KAAK,UAAU;IACf,IAAI,SAAS;CACd;AAED,0BAAkB,QAAQ;IACxB,QAAQ,aAAa;IACrB,GAAG,QAAQ;CACZ;AAED,0BAAkB,aAAa;IAC7B,MAAM,WAAW;IACjB,MAAM,WAAW;CAClB"}
1
+ {"version":3,"file":"three-particles-enums.d.ts","sourceRoot":"","sources":["../../../../src/js/effects/three-particles/three-particles-enums.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,0BAAkB,eAAe;IAC/B;;;;OAIG;IACH,KAAK,UAAU;IAEf;;;;OAIG;IACH,KAAK,UAAU;CAChB;AAED;;;;GAIG;AACH,0BAAkB,KAAK;IACrB;;;OAGG;IACH,MAAM,WAAW;IAEjB;;;;OAIG;IACH,IAAI,SAAS;IAEb;;;;OAIG;IACH,GAAG,QAAQ;IAEX;;;;OAIG;IACH,MAAM,WAAW;IAEjB;;;;OAIG;IACH,SAAS,cAAc;CACxB;AAED;;;;;GAKG;AACH,0BAAkB,QAAQ;IACxB;;;OAGG;IACH,MAAM,WAAW;IAEjB;;;OAGG;IACH,KAAK,UAAU;IAEf;;;OAGG;IACH,IAAI,SAAS;CACd;AAED;;;;GAIG;AACH,0BAAkB,QAAQ;IACxB;;;OAGG;IACH,QAAQ,aAAa;IAErB;;;OAGG;IACH,GAAG,QAAQ;CACZ;AAED;;;;GAIG;AACH,0BAAkB,aAAa;IAC7B;;;;OAIG;IACH,MAAM,WAAW;IAEjB;;;;OAIG;IACH,MAAM,WAAW;CAClB"}
@@ -1,5 +1,67 @@
1
1
  import * as THREE from 'three';
2
2
  import { GeneralData, NormalizedParticleSystemConfig } from './types.js';
3
+ /**
4
+ * Applies all active modifiers to a single particle during the update cycle.
5
+ *
6
+ * This function handles the animation and modification of particle properties over its lifetime,
7
+ * including velocity (linear and orbital), size, opacity, color, rotation, and noise-based effects.
8
+ * It is called once per particle per frame by the {@link updateParticleSystems} function.
9
+ *
10
+ * @param params - Configuration object containing:
11
+ * @param params.delta - Time elapsed since the last frame in seconds. Used for velocity and rotation calculations.
12
+ * @param params.generalData - Internal particle system state and cached values.
13
+ * @param params.normalizedConfig - The normalized particle system configuration with all modifiers.
14
+ * @param params.attributes - Three.js buffer attributes for position, size, rotation, and color.
15
+ * @param params.particleLifetimePercentage - Normalized lifetime of the particle (0.0 to 1.0).
16
+ * - 0.0 = particle just born
17
+ * - 1.0 = particle at end of life
18
+ * @param params.particleIndex - Index of the particle in the buffer arrays.
19
+ *
20
+ * @remarks
21
+ * The function modifies the following particle properties based on configuration:
22
+ *
23
+ * - **Linear Velocity**: Moves particles in a straight line (velocityOverLifetime.linear)
24
+ * - **Orbital Velocity**: Rotates particles around their emission point (velocityOverLifetime.orbital)
25
+ * - **Size Over Lifetime**: Scales particle size based on lifetime curve (sizeOverLifetime)
26
+ * - **Opacity Over Lifetime**: Fades particles in/out based on lifetime curve (opacityOverLifetime)
27
+ * - **Color Over Lifetime**: Animates RGB channels independently based on lifetime curves (colorOverLifetime)
28
+ * - **Rotation Over Lifetime**: Rotates particles around their center (rotationOverLifetime)
29
+ * - **Noise**: Adds organic, turbulent motion to position, rotation, and size (noise)
30
+ *
31
+ * Each modifier only runs if it's active in the configuration, optimizing performance for simple effects.
32
+ *
33
+ * @example
34
+ * ```typescript
35
+ * // This function is called internally by updateParticleSystems
36
+ * // You typically don't need to call it directly
37
+ *
38
+ * // However, understanding its behavior helps configure particle systems:
39
+ * const config = {
40
+ * sizeOverLifetime: {
41
+ * isActive: true,
42
+ * lifetimeCurve: {
43
+ * type: 'BEZIER',
44
+ * bezierPoints: [
45
+ * { x: 0, y: 0, percentage: 0 }, // Start at 0% size
46
+ * { x: 0.5, y: 1, percentage: 0.5 }, // Grow to 100% at midlife
47
+ * { x: 1, y: 0, percentage: 1 } // Shrink to 0% at end
48
+ * ]
49
+ * }
50
+ * },
51
+ * opacityOverLifetime: {
52
+ * isActive: true,
53
+ * lifetimeCurve: {
54
+ * type: 'EASING',
55
+ * curveFunction: 'easeOutQuad'
56
+ * }
57
+ * }
58
+ * };
59
+ * ```
60
+ *
61
+ * @see {@link updateParticleSystems} - Calls this function for each active particle
62
+ * @see {@link VelocityOverLifetime} - Configuration for velocity modifiers
63
+ * @see {@link NoiseConfig} - Configuration for noise-based effects
64
+ */
3
65
  export declare const applyModifiers: ({ delta, generalData, normalizedConfig, attributes, particleLifetimePercentage, particleIndex, }: {
4
66
  delta: number;
5
67
  generalData: GeneralData;
@@ -1 +1 @@
1
- {"version":3,"file":"three-particles-modifiers.d.ts","sourceRoot":"","sources":["../../../../src/js/effects/three-particles/three-particles-modifiers.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAG/B,OAAO,EAAE,WAAW,EAAE,8BAA8B,EAAE,MAAM,YAAY,CAAC;AAKzE,eAAO,MAAM,cAAc,GAAI,kGAO5B;IACD,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,EAAE,WAAW,CAAC;IACzB,gBAAgB,EAAE,8BAA8B,CAAC;IACjD,UAAU,EAAE,KAAK,CAAC,sBAAsB,CAAC;IACzC,0BAA0B,EAAE,MAAM,CAAC;IACnC,aAAa,EAAE,MAAM,CAAC;CACvB,SA8IA,CAAC"}
1
+ {"version":3,"file":"three-particles-modifiers.d.ts","sourceRoot":"","sources":["../../../../src/js/effects/three-particles/three-particles-modifiers.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAG/B,OAAO,EAAE,WAAW,EAAE,8BAA8B,EAAE,MAAM,YAAY,CAAC;AAKzE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6DG;AACH,eAAO,MAAM,cAAc,GAAI,kGAO5B;IACD,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,EAAE,WAAW,CAAC;IACzB,gBAAgB,EAAE,8BAA8B,CAAC;IACjD,UAAU,EAAE,KAAK,CAAC,sBAAsB,CAAC;IACzC,0BAA0B,EAAE,MAAM,CAAC;IACnC,aAAa,EAAE,MAAM,CAAC;CACvB,SA2KA,CAAC"}
@@ -2,6 +2,68 @@ import * as THREE from 'three';
2
2
  import { calculateValue } from './three-particles-utils.js';
3
3
  const noiseInput = new THREE.Vector3(0, 0, 0);
4
4
  const orbitalEuler = new THREE.Euler();
5
+ /**
6
+ * Applies all active modifiers to a single particle during the update cycle.
7
+ *
8
+ * This function handles the animation and modification of particle properties over its lifetime,
9
+ * including velocity (linear and orbital), size, opacity, color, rotation, and noise-based effects.
10
+ * It is called once per particle per frame by the {@link updateParticleSystems} function.
11
+ *
12
+ * @param params - Configuration object containing:
13
+ * @param params.delta - Time elapsed since the last frame in seconds. Used for velocity and rotation calculations.
14
+ * @param params.generalData - Internal particle system state and cached values.
15
+ * @param params.normalizedConfig - The normalized particle system configuration with all modifiers.
16
+ * @param params.attributes - Three.js buffer attributes for position, size, rotation, and color.
17
+ * @param params.particleLifetimePercentage - Normalized lifetime of the particle (0.0 to 1.0).
18
+ * - 0.0 = particle just born
19
+ * - 1.0 = particle at end of life
20
+ * @param params.particleIndex - Index of the particle in the buffer arrays.
21
+ *
22
+ * @remarks
23
+ * The function modifies the following particle properties based on configuration:
24
+ *
25
+ * - **Linear Velocity**: Moves particles in a straight line (velocityOverLifetime.linear)
26
+ * - **Orbital Velocity**: Rotates particles around their emission point (velocityOverLifetime.orbital)
27
+ * - **Size Over Lifetime**: Scales particle size based on lifetime curve (sizeOverLifetime)
28
+ * - **Opacity Over Lifetime**: Fades particles in/out based on lifetime curve (opacityOverLifetime)
29
+ * - **Color Over Lifetime**: Animates RGB channels independently based on lifetime curves (colorOverLifetime)
30
+ * - **Rotation Over Lifetime**: Rotates particles around their center (rotationOverLifetime)
31
+ * - **Noise**: Adds organic, turbulent motion to position, rotation, and size (noise)
32
+ *
33
+ * Each modifier only runs if it's active in the configuration, optimizing performance for simple effects.
34
+ *
35
+ * @example
36
+ * ```typescript
37
+ * // This function is called internally by updateParticleSystems
38
+ * // You typically don't need to call it directly
39
+ *
40
+ * // However, understanding its behavior helps configure particle systems:
41
+ * const config = {
42
+ * sizeOverLifetime: {
43
+ * isActive: true,
44
+ * lifetimeCurve: {
45
+ * type: 'BEZIER',
46
+ * bezierPoints: [
47
+ * { x: 0, y: 0, percentage: 0 }, // Start at 0% size
48
+ * { x: 0.5, y: 1, percentage: 0.5 }, // Grow to 100% at midlife
49
+ * { x: 1, y: 0, percentage: 1 } // Shrink to 0% at end
50
+ * ]
51
+ * }
52
+ * },
53
+ * opacityOverLifetime: {
54
+ * isActive: true,
55
+ * lifetimeCurve: {
56
+ * type: 'EASING',
57
+ * curveFunction: 'easeOutQuad'
58
+ * }
59
+ * }
60
+ * };
61
+ * ```
62
+ *
63
+ * @see {@link updateParticleSystems} - Calls this function for each active particle
64
+ * @see {@link VelocityOverLifetime} - Configuration for velocity modifiers
65
+ * @see {@link NoiseConfig} - Configuration for noise-based effects
66
+ */
5
67
  export const applyModifiers = ({ delta, generalData, normalizedConfig, attributes, particleLifetimePercentage, particleIndex, }) => {
6
68
  const { particleSystemId, startValues, lifetimeValues, linearVelocityData, orbitalVelocityData, noise, } = generalData;
7
69
  const positionIndex = particleIndex * 3;
@@ -55,6 +117,20 @@ export const applyModifiers = ({ delta, generalData, normalizedConfig, attribute
55
117
  startValues.startOpacity[particleIndex] * multiplier;
56
118
  attributes.colorA.needsUpdate = true;
57
119
  }
120
+ if (normalizedConfig.colorOverLifetime.isActive) {
121
+ const rMultiplier = calculateValue(particleSystemId, normalizedConfig.colorOverLifetime.r, particleLifetimePercentage);
122
+ const gMultiplier = calculateValue(particleSystemId, normalizedConfig.colorOverLifetime.g, particleLifetimePercentage);
123
+ const bMultiplier = calculateValue(particleSystemId, normalizedConfig.colorOverLifetime.b, particleLifetimePercentage);
124
+ attributes.colorR.array[particleIndex] =
125
+ startValues.startColorR[particleIndex] * rMultiplier;
126
+ attributes.colorG.array[particleIndex] =
127
+ startValues.startColorG[particleIndex] * gMultiplier;
128
+ attributes.colorB.array[particleIndex] =
129
+ startValues.startColorB[particleIndex] * bMultiplier;
130
+ attributes.colorR.needsUpdate = true;
131
+ attributes.colorG.needsUpdate = true;
132
+ attributes.colorB.needsUpdate = true;
133
+ }
58
134
  if (lifetimeValues.rotationOverLifetime) {
59
135
  attributes.rotation.array[particleIndex] +=
60
136
  lifetimeValues.rotationOverLifetime[particleIndex] * delta * 0.02;