@zylem/behaviors 0.2.0 → 0.3.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/dist/chunk-7JJEIADR.js +2631 -0
- package/dist/chunk-7JJEIADR.js.map +1 -0
- package/dist/{chunk-POZER3MQ.js → chunk-ZPSAXX73.js} +100 -94
- package/dist/chunk-ZPSAXX73.js.map +1 -0
- package/dist/index.d.ts +2 -2
- package/dist/index.js +2 -2
- package/dist/particle-emitter/presets.d.ts +2 -2
- package/dist/particle-emitter/presets.js +1 -1
- package/dist/particle-emitter.d.ts +9 -4
- package/dist/particle-emitter.js +2 -2
- package/dist/spark-Dx3cJbTW.d.ts +356 -0
- package/package.json +159 -159
- package/dist/chunk-GYURWCIQ.js +0 -1985
- package/dist/chunk-GYURWCIQ.js.map +0 -1
- package/dist/chunk-POZER3MQ.js.map +0 -1
- package/dist/spark-DDlIg1nM.d.ts +0 -148
|
@@ -0,0 +1,2631 @@
|
|
|
1
|
+
// src/lib/behaviors/particle-emitter/preset-builder.ts
|
|
2
|
+
import {
|
|
3
|
+
AdditiveBlending as AdditiveBlending2,
|
|
4
|
+
Color
|
|
5
|
+
} from "three";
|
|
6
|
+
|
|
7
|
+
// src/lib/behaviors/particle-emitter/gpu/particles.ts
|
|
8
|
+
import * as THREE3 from "three/webgpu";
|
|
9
|
+
import { texture as texture2, uniform, instancedArray } from "three/tsl";
|
|
10
|
+
|
|
11
|
+
// src/lib/behaviors/particle-emitter/gpu/types.ts
|
|
12
|
+
var EASE_FUNCTIONS = [
|
|
13
|
+
"easeLinear",
|
|
14
|
+
"easeInPower1",
|
|
15
|
+
"easeOutPower1",
|
|
16
|
+
"easeInOutPower1",
|
|
17
|
+
"easeInPower2",
|
|
18
|
+
"easeOutPower2",
|
|
19
|
+
"easeInOutPower2",
|
|
20
|
+
"easeInPower3",
|
|
21
|
+
"easeOutPower3",
|
|
22
|
+
"easeInOutPower3",
|
|
23
|
+
"easeInPower4",
|
|
24
|
+
"easeOutPower4",
|
|
25
|
+
"easeInOutPower4",
|
|
26
|
+
"easeInQuad",
|
|
27
|
+
"easeOutQuad",
|
|
28
|
+
"easeInOutQuad",
|
|
29
|
+
"easeInCubic",
|
|
30
|
+
"easeOutCubic",
|
|
31
|
+
"easeInOutCubic",
|
|
32
|
+
"easeInQuart",
|
|
33
|
+
"easeOutQuart",
|
|
34
|
+
"easeInOutQuart",
|
|
35
|
+
"easeInQuint",
|
|
36
|
+
"easeOutQuint",
|
|
37
|
+
"easeInOutQuint",
|
|
38
|
+
"easeInSine",
|
|
39
|
+
"easeOutSine",
|
|
40
|
+
"easeInOutSine",
|
|
41
|
+
"easeInExpo",
|
|
42
|
+
"easeOutExpo",
|
|
43
|
+
"easeInOutExpo",
|
|
44
|
+
"easeInCirc",
|
|
45
|
+
"easeOutCirc",
|
|
46
|
+
"easeInOutCirc",
|
|
47
|
+
"easeInElastic",
|
|
48
|
+
"easeOutElastic",
|
|
49
|
+
"easeInOutElastic",
|
|
50
|
+
"easeInBack",
|
|
51
|
+
"easeOutBack",
|
|
52
|
+
"easeInOutBack"
|
|
53
|
+
];
|
|
54
|
+
|
|
55
|
+
// src/lib/behaviors/particle-emitter/gpu/textures.ts
|
|
56
|
+
import * as THREE from "three/webgpu";
|
|
57
|
+
function createTextureAtlas(textures, onLoad, size = 512, filter) {
|
|
58
|
+
if (!textures || textures.length === 0) return null;
|
|
59
|
+
const canvas = document.createElement("canvas");
|
|
60
|
+
const ctx = canvas.getContext("2d");
|
|
61
|
+
const count = textures.length;
|
|
62
|
+
canvas.width = size * count;
|
|
63
|
+
canvas.height = size;
|
|
64
|
+
let loadedCount = 0;
|
|
65
|
+
let imagesLoaded = 0;
|
|
66
|
+
textures.forEach((texture3, i) => {
|
|
67
|
+
const img = texture3.image;
|
|
68
|
+
if (img && img.complete && img.width > 0) {
|
|
69
|
+
ctx.drawImage(img, i * size, 0, size, size);
|
|
70
|
+
imagesLoaded++;
|
|
71
|
+
} else {
|
|
72
|
+
const checkAndDraw = () => {
|
|
73
|
+
const ready = texture3.image;
|
|
74
|
+
if (ready && ready.complete && ready.width > 0) {
|
|
75
|
+
ctx.drawImage(ready, i * size, 0, size, size);
|
|
76
|
+
loadedCount++;
|
|
77
|
+
if (loadedCount === count - imagesLoaded) {
|
|
78
|
+
atlasTexture.needsUpdate = true;
|
|
79
|
+
if (onLoad) onLoad();
|
|
80
|
+
}
|
|
81
|
+
} else {
|
|
82
|
+
setTimeout(checkAndDraw, 100);
|
|
83
|
+
}
|
|
84
|
+
};
|
|
85
|
+
checkAndDraw();
|
|
86
|
+
}
|
|
87
|
+
});
|
|
88
|
+
const atlasTexture = new THREE.CanvasTexture(canvas);
|
|
89
|
+
if (filter !== void 0) {
|
|
90
|
+
atlasTexture.minFilter = filter;
|
|
91
|
+
atlasTexture.magFilter = filter;
|
|
92
|
+
}
|
|
93
|
+
atlasTexture.needsUpdate = true;
|
|
94
|
+
return atlasTexture;
|
|
95
|
+
}
|
|
96
|
+
function createColorGradientTexture(rows, width = 512) {
|
|
97
|
+
let safeRows = rows;
|
|
98
|
+
if (!safeRows || safeRows.length === 0) safeRows = [[{ color: "white", stop: 0 }]];
|
|
99
|
+
const normalized = safeRows.map((row) => {
|
|
100
|
+
const sorted = [...row].sort((a, b) => a.stop - b.stop);
|
|
101
|
+
if (sorted[0].stop > 0) sorted.unshift({ color: sorted[0].color, stop: 0 });
|
|
102
|
+
if (sorted[sorted.length - 1].stop < 1)
|
|
103
|
+
sorted.push({ color: sorted[sorted.length - 1].color, stop: 1 });
|
|
104
|
+
return sorted;
|
|
105
|
+
});
|
|
106
|
+
const canvas = document.createElement("canvas");
|
|
107
|
+
const ctx = canvas.getContext("2d");
|
|
108
|
+
canvas.width = width;
|
|
109
|
+
canvas.height = normalized.length;
|
|
110
|
+
for (let y = 0; y < normalized.length; y++) {
|
|
111
|
+
const stops = normalized[y];
|
|
112
|
+
const g = ctx.createLinearGradient(0, 0, width, 0);
|
|
113
|
+
for (const s of stops) g.addColorStop(THREE.MathUtils.clamp(s.stop, 0, 1), s.color);
|
|
114
|
+
ctx.fillStyle = g;
|
|
115
|
+
ctx.fillRect(0, y, width, 1);
|
|
116
|
+
}
|
|
117
|
+
const tex = new THREE.CanvasTexture(canvas);
|
|
118
|
+
tex.minFilter = THREE.LinearFilter;
|
|
119
|
+
tex.magFilter = THREE.LinearFilter;
|
|
120
|
+
tex.wrapS = THREE.ClampToEdgeWrapping;
|
|
121
|
+
tex.wrapT = THREE.ClampToEdgeWrapping;
|
|
122
|
+
tex.needsUpdate = true;
|
|
123
|
+
return tex;
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
// src/lib/behaviors/particle-emitter/gpu/nodes.ts
|
|
127
|
+
import * as THREE2 from "three/webgpu";
|
|
128
|
+
import {
|
|
129
|
+
normalize,
|
|
130
|
+
max,
|
|
131
|
+
varying,
|
|
132
|
+
If as If2,
|
|
133
|
+
distance,
|
|
134
|
+
Discard,
|
|
135
|
+
select as select2,
|
|
136
|
+
length,
|
|
137
|
+
range,
|
|
138
|
+
instanceIndex,
|
|
139
|
+
vec3,
|
|
140
|
+
float as float2,
|
|
141
|
+
mix,
|
|
142
|
+
vec4,
|
|
143
|
+
Fn as Fn2,
|
|
144
|
+
vec2,
|
|
145
|
+
smoothstep,
|
|
146
|
+
uv,
|
|
147
|
+
uint,
|
|
148
|
+
modelWorldMatrix,
|
|
149
|
+
transpose,
|
|
150
|
+
mat3,
|
|
151
|
+
bool
|
|
152
|
+
} from "three/tsl";
|
|
153
|
+
|
|
154
|
+
// src/lib/behaviors/particle-emitter/gpu/easing.ts
|
|
155
|
+
import { PI, float, mul, sub, pow, add, cos, sin, sqrt, select, Fn, If, Switch } from "three/tsl";
|
|
156
|
+
var easeLinear = /* @__PURE__ */ Fn(([t]) => t, { t: "float", return: "float" });
|
|
157
|
+
var easeInPower1 = /* @__PURE__ */ Fn(([t]) => t, { t: "float", return: "float" });
|
|
158
|
+
var easeOutPower1 = /* @__PURE__ */ Fn(([t]) => sub(1, sub(1, t)), {
|
|
159
|
+
t: "float",
|
|
160
|
+
return: "float"
|
|
161
|
+
});
|
|
162
|
+
var easeInOutPower1 = /* @__PURE__ */ Fn(([t]) => t, { t: "float", return: "float" });
|
|
163
|
+
var easeInPower2 = /* @__PURE__ */ Fn(([t]) => t.mul(t), { t: "float", return: "float" });
|
|
164
|
+
var easeOutPower2 = /* @__PURE__ */ Fn(([t]) => sub(1, pow(sub(1, t), 2)), {
|
|
165
|
+
t: "float",
|
|
166
|
+
return: "float"
|
|
167
|
+
});
|
|
168
|
+
var easeInOutPower2 = /* @__PURE__ */ Fn(
|
|
169
|
+
([t]) => select(
|
|
170
|
+
t.lessThan(0.5),
|
|
171
|
+
mul(2, t).mul(t),
|
|
172
|
+
sub(1, pow(float(-2).mul(t).add(2), 2).div(2))
|
|
173
|
+
),
|
|
174
|
+
{ t: "float", return: "float" }
|
|
175
|
+
);
|
|
176
|
+
var easeInPower3 = /* @__PURE__ */ Fn(([t]) => t.mul(t).mul(t), {
|
|
177
|
+
t: "float",
|
|
178
|
+
return: "float"
|
|
179
|
+
});
|
|
180
|
+
var easeOutPower3 = /* @__PURE__ */ Fn(([t]) => sub(1, pow(sub(1, t), 3)), {
|
|
181
|
+
t: "float",
|
|
182
|
+
return: "float"
|
|
183
|
+
});
|
|
184
|
+
var easeInOutPower3 = /* @__PURE__ */ Fn(
|
|
185
|
+
([t]) => select(
|
|
186
|
+
t.lessThan(0.5),
|
|
187
|
+
mul(4, t).mul(t).mul(t),
|
|
188
|
+
sub(1, pow(float(-2).mul(t).add(2), 3).div(2))
|
|
189
|
+
),
|
|
190
|
+
{ t: "float", return: "float" }
|
|
191
|
+
);
|
|
192
|
+
var easeInPower4 = /* @__PURE__ */ Fn(([t]) => t.mul(t).mul(t).mul(t), {
|
|
193
|
+
t: "float",
|
|
194
|
+
return: "float"
|
|
195
|
+
});
|
|
196
|
+
var easeOutPower4 = /* @__PURE__ */ Fn(([t]) => sub(1, pow(sub(1, t), 4)), {
|
|
197
|
+
t: "float",
|
|
198
|
+
return: "float"
|
|
199
|
+
});
|
|
200
|
+
var easeInOutPower4 = /* @__PURE__ */ Fn(
|
|
201
|
+
([t]) => select(
|
|
202
|
+
t.lessThan(0.5),
|
|
203
|
+
mul(8, t).mul(t).mul(t).mul(t),
|
|
204
|
+
sub(1, pow(float(-2).mul(t).add(2), 4).div(2))
|
|
205
|
+
),
|
|
206
|
+
{ t: "float", return: "float" }
|
|
207
|
+
);
|
|
208
|
+
var easeInQuad = /* @__PURE__ */ Fn(([t]) => t.mul(t), { t: "float", return: "float" });
|
|
209
|
+
var easeOutQuad = /* @__PURE__ */ Fn(([t]) => t.mul(sub(2, t)), {
|
|
210
|
+
t: "float",
|
|
211
|
+
return: "float"
|
|
212
|
+
});
|
|
213
|
+
var easeInOutQuad = /* @__PURE__ */ Fn(
|
|
214
|
+
([t]) => select(t.lessThan(0.5), mul(2, t).mul(t), float(-1).add(sub(4, mul(2, t)).mul(t))),
|
|
215
|
+
{ t: "float", return: "float" }
|
|
216
|
+
);
|
|
217
|
+
var easeInCubic = /* @__PURE__ */ Fn(([t]) => t.mul(t).mul(t), {
|
|
218
|
+
t: "float",
|
|
219
|
+
return: "float"
|
|
220
|
+
});
|
|
221
|
+
var easeOutCubic = /* @__PURE__ */ Fn(
|
|
222
|
+
([t]) => {
|
|
223
|
+
const t1 = t.sub(1);
|
|
224
|
+
return add(1, t1.mul(t1).mul(t1));
|
|
225
|
+
},
|
|
226
|
+
{ t: "float", return: "float" }
|
|
227
|
+
);
|
|
228
|
+
var easeInOutCubic = /* @__PURE__ */ Fn(
|
|
229
|
+
([t]) => select(
|
|
230
|
+
t.lessThan(0.5),
|
|
231
|
+
mul(4, t).mul(t).mul(t),
|
|
232
|
+
t.sub(1).mul(mul(2, t).sub(2)).mul(mul(2, t).sub(2)).add(1)
|
|
233
|
+
),
|
|
234
|
+
{ t: "float", return: "float" }
|
|
235
|
+
);
|
|
236
|
+
var easeInQuart = /* @__PURE__ */ Fn(([t]) => t.mul(t).mul(t).mul(t), {
|
|
237
|
+
t: "float",
|
|
238
|
+
return: "float"
|
|
239
|
+
});
|
|
240
|
+
var easeOutQuart = /* @__PURE__ */ Fn(
|
|
241
|
+
([t]) => {
|
|
242
|
+
const t1 = t.sub(1);
|
|
243
|
+
return sub(1, t1.mul(t1).mul(t1).mul(t1));
|
|
244
|
+
},
|
|
245
|
+
{ t: "float", return: "float" }
|
|
246
|
+
);
|
|
247
|
+
var easeInOutQuart = /* @__PURE__ */ Fn(
|
|
248
|
+
([t]) => {
|
|
249
|
+
const t1 = t.sub(1);
|
|
250
|
+
return select(
|
|
251
|
+
t.lessThan(0.5),
|
|
252
|
+
mul(8, t).mul(t).mul(t).mul(t),
|
|
253
|
+
sub(1, mul(8, t1).mul(t1).mul(t1).mul(t1))
|
|
254
|
+
);
|
|
255
|
+
},
|
|
256
|
+
{ t: "float", return: "float" }
|
|
257
|
+
);
|
|
258
|
+
var easeInQuint = /* @__PURE__ */ Fn(([t]) => t.mul(t).mul(t).mul(t).mul(t), {
|
|
259
|
+
t: "float",
|
|
260
|
+
return: "float"
|
|
261
|
+
});
|
|
262
|
+
var easeOutQuint = /* @__PURE__ */ Fn(
|
|
263
|
+
([t]) => {
|
|
264
|
+
const t1 = t.sub(1);
|
|
265
|
+
return add(1, t1.mul(t1).mul(t1).mul(t1).mul(t1));
|
|
266
|
+
},
|
|
267
|
+
{ t: "float", return: "float" }
|
|
268
|
+
);
|
|
269
|
+
var easeInOutQuint = /* @__PURE__ */ Fn(
|
|
270
|
+
([t]) => {
|
|
271
|
+
const t1 = t.sub(1);
|
|
272
|
+
return select(
|
|
273
|
+
t.lessThan(0.5),
|
|
274
|
+
mul(16, t).mul(t).mul(t).mul(t).mul(t),
|
|
275
|
+
add(1, mul(16, t1).mul(t1).mul(t1).mul(t1).mul(t1))
|
|
276
|
+
);
|
|
277
|
+
},
|
|
278
|
+
{ t: "float", return: "float" }
|
|
279
|
+
);
|
|
280
|
+
var easeInSine = /* @__PURE__ */ Fn(
|
|
281
|
+
([t]) => float(-1).mul(cos(t.mul(PI).mul(0.5))).add(1),
|
|
282
|
+
{ t: "float", return: "float" }
|
|
283
|
+
);
|
|
284
|
+
var easeOutSine = /* @__PURE__ */ Fn(([t]) => sin(t.mul(PI).mul(0.5)), {
|
|
285
|
+
t: "float",
|
|
286
|
+
return: "float"
|
|
287
|
+
});
|
|
288
|
+
var easeInOutSine = /* @__PURE__ */ Fn(([t]) => float(-0.5).mul(cos(PI.mul(t)).sub(1)), {
|
|
289
|
+
t: "float",
|
|
290
|
+
return: "float"
|
|
291
|
+
});
|
|
292
|
+
var easeInExpo = /* @__PURE__ */ Fn(
|
|
293
|
+
([t]) => select(t.equal(0), 0, pow(2, mul(10, t.sub(1)))),
|
|
294
|
+
{ t: "float", return: "float" }
|
|
295
|
+
);
|
|
296
|
+
var easeOutExpo = /* @__PURE__ */ Fn(
|
|
297
|
+
([t]) => select(t.equal(1), 1, sub(1, pow(2, float(-10).mul(t)))),
|
|
298
|
+
{ t: "float", return: "float" }
|
|
299
|
+
);
|
|
300
|
+
var easeInOutExpo = /* @__PURE__ */ Fn(
|
|
301
|
+
([t]) => {
|
|
302
|
+
If(t.equal(0).or(t.equal(1)), () => t);
|
|
303
|
+
return select(
|
|
304
|
+
t.lessThan(0.5),
|
|
305
|
+
mul(0.5, pow(2, mul(20, t).sub(10))),
|
|
306
|
+
mul(0.5, pow(2, float(-20).mul(t).add(10)).negate().add(2))
|
|
307
|
+
);
|
|
308
|
+
},
|
|
309
|
+
{ t: "float", return: "float" }
|
|
310
|
+
);
|
|
311
|
+
var easeInCirc = /* @__PURE__ */ Fn(
|
|
312
|
+
([t]) => float(-1).mul(sqrt(sub(1, t.mul(t))).sub(1)),
|
|
313
|
+
{ t: "float", return: "float" }
|
|
314
|
+
);
|
|
315
|
+
var easeOutCirc = /* @__PURE__ */ Fn(
|
|
316
|
+
([t]) => {
|
|
317
|
+
const t1 = t.sub(1);
|
|
318
|
+
return sqrt(sub(1, t1.mul(t1)));
|
|
319
|
+
},
|
|
320
|
+
{ t: "float", return: "float" }
|
|
321
|
+
);
|
|
322
|
+
var easeInOutCirc = /* @__PURE__ */ Fn(
|
|
323
|
+
([t]) => {
|
|
324
|
+
const t1 = mul(2, t);
|
|
325
|
+
const t2 = t1.sub(2);
|
|
326
|
+
return select(
|
|
327
|
+
t.lessThan(0.5),
|
|
328
|
+
float(-0.5).mul(sqrt(sub(1, t1.mul(t1))).sub(1)),
|
|
329
|
+
mul(0.5, sqrt(sub(1, t2.mul(t2))).add(1))
|
|
330
|
+
);
|
|
331
|
+
},
|
|
332
|
+
{ t: "float", return: "float" }
|
|
333
|
+
);
|
|
334
|
+
var easeInElastic = /* @__PURE__ */ Fn(
|
|
335
|
+
([t]) => {
|
|
336
|
+
If(t.equal(0).or(t.equal(1)), () => t);
|
|
337
|
+
return pow(2, mul(10, t.sub(1))).negate().mul(sin(t.sub(1.075).mul(mul(2, PI)).div(0.3)));
|
|
338
|
+
},
|
|
339
|
+
{ t: "float", return: "float" }
|
|
340
|
+
);
|
|
341
|
+
var easeOutElastic = /* @__PURE__ */ Fn(
|
|
342
|
+
([t]) => {
|
|
343
|
+
If(t.equal(0).or(t.equal(1)), () => t);
|
|
344
|
+
return pow(2, float(-10).mul(t)).mul(sin(t.sub(0.075).mul(mul(2, PI)).div(0.3))).add(1);
|
|
345
|
+
},
|
|
346
|
+
{ t: "float", return: "float" }
|
|
347
|
+
);
|
|
348
|
+
var easeInOutElastic = /* @__PURE__ */ Fn(
|
|
349
|
+
([t]) => {
|
|
350
|
+
If(
|
|
351
|
+
t.lessThan(0.5),
|
|
352
|
+
() => float(-0.5).mul(pow(2, mul(20, t).sub(10))).mul(sin(mul(20, t).sub(11.125).mul(mul(2, PI)).div(4.5)))
|
|
353
|
+
);
|
|
354
|
+
return pow(2, float(-20).mul(t).add(10)).mul(sin(mul(20, t).sub(11.125).mul(mul(2, PI)).div(4.5))).mul(0.5).add(1);
|
|
355
|
+
},
|
|
356
|
+
{ t: "float", return: "float" }
|
|
357
|
+
);
|
|
358
|
+
var easeInBack = /* @__PURE__ */ Fn(
|
|
359
|
+
([t]) => {
|
|
360
|
+
const s = float(1.70158);
|
|
361
|
+
return t.mul(t).mul(s.add(1).mul(t).sub(s));
|
|
362
|
+
},
|
|
363
|
+
{ t: "float", return: "float" }
|
|
364
|
+
);
|
|
365
|
+
var easeOutBack = /* @__PURE__ */ Fn(
|
|
366
|
+
([t]) => {
|
|
367
|
+
const s = float(1.70158);
|
|
368
|
+
const t1 = t.sub(1);
|
|
369
|
+
return t1.mul(t1).mul(s.add(1).mul(t1).add(s)).add(1);
|
|
370
|
+
},
|
|
371
|
+
{ t: "float", return: "float" }
|
|
372
|
+
);
|
|
373
|
+
var easeInOutBack = /* @__PURE__ */ Fn(
|
|
374
|
+
([t_immutable]) => {
|
|
375
|
+
const t = t_immutable.toVar();
|
|
376
|
+
const s = float(1.70158 * 1.525);
|
|
377
|
+
t.mulAssign(2);
|
|
378
|
+
If(t.lessThan(1), () => mul(0.5, t.mul(t).mul(s.add(1).mul(t).sub(s))));
|
|
379
|
+
t.subAssign(2);
|
|
380
|
+
return mul(0.5, t.mul(t).mul(s.add(1).mul(t).add(s)).add(2));
|
|
381
|
+
},
|
|
382
|
+
{ t: "float", return: "float" }
|
|
383
|
+
);
|
|
384
|
+
var applyEasing = /* @__PURE__ */ Fn(
|
|
385
|
+
([t, easingId]) => {
|
|
386
|
+
Switch(easingId).Case(0, () => easeLinear(t)).Case(1, () => easeInPower1(t)).Case(2, () => easeOutPower1(t)).Case(3, () => easeInOutPower1(t)).Case(4, () => easeInPower2(t)).Case(5, () => easeOutPower2(t)).Case(6, () => easeInOutPower2(t)).Case(7, () => easeInPower3(t)).Case(8, () => easeOutPower3(t)).Case(9, () => easeInOutPower3(t)).Case(10, () => easeInPower4(t)).Case(11, () => easeOutPower4(t)).Case(12, () => easeInOutPower4(t)).Case(13, () => easeInQuad(t)).Case(14, () => easeOutQuad(t)).Case(15, () => easeInOutQuad(t)).Case(16, () => easeInCubic(t)).Case(17, () => easeOutCubic(t)).Case(18, () => easeInOutCubic(t)).Case(19, () => easeInQuart(t)).Case(20, () => easeOutQuart(t)).Case(21, () => easeInOutQuart(t)).Case(22, () => easeInQuint(t)).Case(23, () => easeOutQuint(t)).Case(24, () => easeInOutQuint(t)).Case(25, () => easeInSine(t)).Case(26, () => easeOutSine(t)).Case(27, () => easeInOutSine(t)).Case(28, () => easeInExpo(t)).Case(29, () => easeOutExpo(t)).Case(30, () => easeInOutExpo(t)).Case(31, () => easeInCirc(t)).Case(32, () => easeOutCirc(t)).Case(33, () => easeInOutCirc(t)).Case(34, () => easeInElastic(t)).Case(35, () => easeOutElastic(t)).Case(36, () => easeInOutElastic(t)).Case(37, () => easeInBack(t)).Case(38, () => easeOutBack(t)).Case(39, () => easeInOutBack(t));
|
|
387
|
+
return t;
|
|
388
|
+
},
|
|
389
|
+
{ t: "float", easingId: "int", return: "float" }
|
|
390
|
+
);
|
|
391
|
+
|
|
392
|
+
// src/lib/behaviors/particle-emitter/gpu/nodes.ts
|
|
393
|
+
var idx7 = instanceIndex.mul(7);
|
|
394
|
+
var idx3 = instanceIndex.mul(3);
|
|
395
|
+
var idx2 = instanceIndex.mul(2);
|
|
396
|
+
var vProgress = varying(float2(0), "vProgress");
|
|
397
|
+
var positionNode = /* @__PURE__ */ Fn2(
|
|
398
|
+
([pos, age, duration, vProgress2, uGravity, dir, speed, worldUpRight, easingIndex]) => {
|
|
399
|
+
const progress = age.div(duration);
|
|
400
|
+
const _pos = vec3(pos);
|
|
401
|
+
If2(progress.lessThan(0).or(progress.greaterThan(1)), () => {
|
|
402
|
+
vProgress2.assign(1);
|
|
403
|
+
_pos.assign(vec3(0, 9999, 0));
|
|
404
|
+
}).Else(() => {
|
|
405
|
+
vProgress2.assign(applyEasing(progress, easingIndex));
|
|
406
|
+
const normalizedDirection = select2(length(dir).greaterThan(0), normalize(dir), vec3(0));
|
|
407
|
+
const gravityForce = uGravity.mul(0.5).mul(age.mul(age));
|
|
408
|
+
const easedAge = vProgress2.mul(duration);
|
|
409
|
+
const offset = normalizedDirection.mul(easedAge).mul(speed).add(gravityForce);
|
|
410
|
+
If2(worldUpRight, () => {
|
|
411
|
+
const m = mat3(modelWorldMatrix);
|
|
412
|
+
const rot = mat3(normalize(m[0]), normalize(m[1]), normalize(m[2]));
|
|
413
|
+
const inverseRotation = transpose(rot);
|
|
414
|
+
const worldOffset = inverseRotation.mul(offset);
|
|
415
|
+
const blendedOffset = mix(offset, worldOffset, vProgress2);
|
|
416
|
+
_pos.addAssign(blendedOffset);
|
|
417
|
+
}).Else(() => {
|
|
418
|
+
_pos.addAssign(offset);
|
|
419
|
+
});
|
|
420
|
+
});
|
|
421
|
+
return _pos;
|
|
422
|
+
}
|
|
423
|
+
);
|
|
424
|
+
var rotationNode = /* @__PURE__ */ Fn2(([rot, rotSpeed, age]) => {
|
|
425
|
+
const tau = float2(Math.PI * 2).toConst();
|
|
426
|
+
const init = rot.z.add(1).mul(0.5).mul(tau);
|
|
427
|
+
const angle = init.add(rotSpeed.z.mul(age));
|
|
428
|
+
const wrapped = angle.mod(tau);
|
|
429
|
+
return wrapped.add(tau).mod(tau);
|
|
430
|
+
});
|
|
431
|
+
var scaleNode = /* @__PURE__ */ Fn2(([fadeSize, scale, vProgress2]) => {
|
|
432
|
+
const uFadeSize = vec2(fadeSize[0], fadeSize[1]).toVar();
|
|
433
|
+
return smoothstep(0, uFadeSize.x, vProgress2).mul(smoothstep(1.01, uFadeSize.y, vProgress2)).mul(scale);
|
|
434
|
+
});
|
|
435
|
+
var colorNode = /* @__PURE__ */ Fn2(
|
|
436
|
+
([
|
|
437
|
+
colors,
|
|
438
|
+
intensity,
|
|
439
|
+
fadeAlpha,
|
|
440
|
+
fadeAlphaMap,
|
|
441
|
+
vProgress2,
|
|
442
|
+
uColorGradient,
|
|
443
|
+
uAlphaMapCount,
|
|
444
|
+
vAlphaMapUVOffsetX,
|
|
445
|
+
vAlphaMapUVOffsetY,
|
|
446
|
+
alphaMap
|
|
447
|
+
]) => {
|
|
448
|
+
const vColorGradientRow = range(0, colors.length - 1).toVar();
|
|
449
|
+
const uColorGradientRows = float2(colors.length).toVar();
|
|
450
|
+
const uIntensity = float2(intensity).toVar();
|
|
451
|
+
const uFadeAlpha = vec2(fadeAlpha[0], fadeAlpha[1]).toVar();
|
|
452
|
+
const uFadeAlphaMap = vec2(fadeAlphaMap[0], fadeAlphaMap[1]).toVar();
|
|
453
|
+
const u = vProgress2;
|
|
454
|
+
const v = vColorGradientRow.add(0.5).div(max(uColorGradientRows, 1));
|
|
455
|
+
const finalColor = uColorGradient.sample(vec2(u, v)).rgb;
|
|
456
|
+
finalColor.mulAssign(uIntensity);
|
|
457
|
+
const alpha = smoothstep(0, uFadeAlpha.x, vProgress2).mul(
|
|
458
|
+
smoothstep(1.01, uFadeAlpha.y, vProgress2)
|
|
459
|
+
);
|
|
460
|
+
const vUv = uv();
|
|
461
|
+
If2(uAlphaMapCount.equal(0), () => {
|
|
462
|
+
const center = vec2(0.5).toVar();
|
|
463
|
+
const dist = distance(vUv, center);
|
|
464
|
+
const radius = float2(0.5);
|
|
465
|
+
const feather = float2(0.98);
|
|
466
|
+
const _alpha = float2(1).sub(smoothstep(radius.sub(feather), radius, dist));
|
|
467
|
+
alpha.assign(_alpha.mul(alpha));
|
|
468
|
+
If2(_alpha.lessThan(0.01), () => Discard());
|
|
469
|
+
}).ElseIf(uAlphaMapCount.greaterThan(0), () => {
|
|
470
|
+
const startU = vAlphaMapUVOffsetX.add(vUv.x).div(uAlphaMapCount);
|
|
471
|
+
const startUV = vec2(startU, vUv.y);
|
|
472
|
+
const startAlpha = alphaMap.sample(startUV).a;
|
|
473
|
+
If2(uAlphaMapCount.greaterThan(1), () => {
|
|
474
|
+
const endU = vAlphaMapUVOffsetY.add(vUv.x).div(uAlphaMapCount);
|
|
475
|
+
const endUV = vec2(endU, vUv.y);
|
|
476
|
+
const endAlpha = alphaMap.sample(endUV).a;
|
|
477
|
+
const morphProgress = smoothstep(uFadeAlphaMap.x, uFadeAlphaMap.y, vProgress2);
|
|
478
|
+
const morphedAlpha = mix(startAlpha, endAlpha, morphProgress);
|
|
479
|
+
alpha.assign(morphedAlpha.mul(alpha));
|
|
480
|
+
}).Else(() => {
|
|
481
|
+
alpha.assign(startAlpha.mul(alpha));
|
|
482
|
+
});
|
|
483
|
+
});
|
|
484
|
+
return vec4(finalColor, alpha);
|
|
485
|
+
}
|
|
486
|
+
);
|
|
487
|
+
var InstancePositionNode = class extends THREE2.Node {
|
|
488
|
+
constructor() {
|
|
489
|
+
super("vec3");
|
|
490
|
+
this.updateType = THREE2.NodeUpdateType.OBJECT;
|
|
491
|
+
}
|
|
492
|
+
setup(frame) {
|
|
493
|
+
const mesh = frame.object;
|
|
494
|
+
const { attributes, uniforms, config, easingIndex } = mesh.userData;
|
|
495
|
+
const uPosition = uniforms.uPosition;
|
|
496
|
+
const _static = float2(config.emitter.static).toVar();
|
|
497
|
+
const posX = attributes.instance.element(idx7.add(0));
|
|
498
|
+
const posY = attributes.instance.element(idx7.add(1));
|
|
499
|
+
const posZ = attributes.instance.element(idx7.add(2));
|
|
500
|
+
const pos = vec3(posX, posY, posZ).add(uPosition.mul(_static));
|
|
501
|
+
const dirX = attributes.instanceDirection.element(idx3.add(0));
|
|
502
|
+
const dirY = attributes.instanceDirection.element(idx3.add(1));
|
|
503
|
+
const dirZ = attributes.instanceDirection.element(idx3.add(2));
|
|
504
|
+
const dir = vec3(dirX, dirY, dirZ);
|
|
505
|
+
const time = uniforms.uTime;
|
|
506
|
+
const uGravity = vec3(...config.particles.gravity);
|
|
507
|
+
const worldUpRight = bool(config.emitter.worldUpRight);
|
|
508
|
+
const startTime = attributes.instanceLifetime.element(idx2.add(0));
|
|
509
|
+
const duration = attributes.instanceLifetime.element(idx2.add(1));
|
|
510
|
+
const speed = attributes.instanceSpeed.element(instanceIndex).toVar();
|
|
511
|
+
const age = select2(speed.lessThan(0), duration.sub(time.sub(startTime)), time.sub(startTime));
|
|
512
|
+
return positionNode(pos, age, duration, vProgress, uGravity, dir, speed, worldUpRight, easingIndex);
|
|
513
|
+
}
|
|
514
|
+
};
|
|
515
|
+
var InstanceRotationNode = class extends THREE2.Node {
|
|
516
|
+
constructor() {
|
|
517
|
+
super("vec3");
|
|
518
|
+
this.updateType = THREE2.NodeUpdateType.OBJECT;
|
|
519
|
+
}
|
|
520
|
+
setup(frame) {
|
|
521
|
+
const mesh = frame.object;
|
|
522
|
+
const { attributes, uniforms } = mesh.userData;
|
|
523
|
+
const rotX = attributes.instance.element(idx7.add(3));
|
|
524
|
+
const rotY = attributes.instance.element(idx7.add(4));
|
|
525
|
+
const rotZ = attributes.instance.element(idx7.add(5));
|
|
526
|
+
const rot = vec3(rotX, rotY, rotZ);
|
|
527
|
+
const rotSpeedX = attributes.instanceRotationSpeed.element(idx3.add(0));
|
|
528
|
+
const rotSpeedY = attributes.instanceRotationSpeed.element(idx3.add(1));
|
|
529
|
+
const rotSpeedZ = attributes.instanceRotationSpeed.element(idx3.add(2));
|
|
530
|
+
const rotSpeed = vec3(rotSpeedX, rotSpeedY, rotSpeedZ);
|
|
531
|
+
const time = uniforms.uTime;
|
|
532
|
+
const startTime = attributes.instanceLifetime.element(idx2.add(0));
|
|
533
|
+
const duration = attributes.instanceLifetime.element(idx2.add(1));
|
|
534
|
+
const speed = attributes.instanceSpeed.element(instanceIndex).toVar();
|
|
535
|
+
const age = select2(speed.lessThan(0), duration.sub(time.sub(startTime)), time.sub(startTime));
|
|
536
|
+
return rotationNode(rot, rotSpeed, age);
|
|
537
|
+
}
|
|
538
|
+
};
|
|
539
|
+
var InstanceScaleNode = class extends THREE2.Node {
|
|
540
|
+
constructor() {
|
|
541
|
+
super("vec3");
|
|
542
|
+
this.updateType = THREE2.NodeUpdateType.OBJECT;
|
|
543
|
+
}
|
|
544
|
+
setup(frame) {
|
|
545
|
+
const mesh = frame.object;
|
|
546
|
+
const { attributes, config } = mesh.userData;
|
|
547
|
+
const scale = attributes.instance.element(idx7.add(6));
|
|
548
|
+
return scaleNode(config.particles.fadeSize, scale, vProgress);
|
|
549
|
+
}
|
|
550
|
+
};
|
|
551
|
+
var InstanceColorNode = class extends THREE2.Node {
|
|
552
|
+
constructor() {
|
|
553
|
+
super("vec3");
|
|
554
|
+
this.updateType = THREE2.NodeUpdateType.OBJECT;
|
|
555
|
+
}
|
|
556
|
+
setup(frame) {
|
|
557
|
+
const mesh = frame.object;
|
|
558
|
+
const { attributes, uniforms, config, alphaMapCount } = mesh.userData;
|
|
559
|
+
const uAlphaMapCount = uint(alphaMapCount).toVar();
|
|
560
|
+
const vAlphaMapUVOffsetX = attributes.instanceAlphaMapUVOffset.element(idx2.add(0));
|
|
561
|
+
const vAlphaMapUVOffsetY = attributes.instanceAlphaMapUVOffset.element(idx2.add(1));
|
|
562
|
+
return colorNode(
|
|
563
|
+
config.particles.colors,
|
|
564
|
+
config.particles.intensity,
|
|
565
|
+
config.particles.fadeAlpha,
|
|
566
|
+
config.particles.fadeAlphaMap,
|
|
567
|
+
vProgress,
|
|
568
|
+
uniforms.uColorGradient,
|
|
569
|
+
uAlphaMapCount,
|
|
570
|
+
vAlphaMapUVOffsetX,
|
|
571
|
+
vAlphaMapUVOffsetY,
|
|
572
|
+
uniforms.alphaMap
|
|
573
|
+
);
|
|
574
|
+
}
|
|
575
|
+
};
|
|
576
|
+
function createParticleMaterialTemplate() {
|
|
577
|
+
const mat = new THREE2.SpriteNodeMaterial();
|
|
578
|
+
mat.positionNode = new InstancePositionNode();
|
|
579
|
+
mat.rotationNode = new InstanceRotationNode();
|
|
580
|
+
mat.scaleNode = new InstanceScaleNode();
|
|
581
|
+
mat.colorNode = new InstanceColorNode();
|
|
582
|
+
return mat;
|
|
583
|
+
}
|
|
584
|
+
|
|
585
|
+
// src/lib/behaviors/particle-emitter/gpu/utils.ts
|
|
586
|
+
function randFloat(min, max2) {
|
|
587
|
+
return Math.random() * (max2 - min) + min;
|
|
588
|
+
}
|
|
589
|
+
function randInt(min, max2) {
|
|
590
|
+
return Math.floor(Math.random() * (max2 - min + 1)) + min;
|
|
591
|
+
}
|
|
592
|
+
|
|
593
|
+
// src/lib/behaviors/particle-emitter/gpu/particles.ts
|
|
594
|
+
var Particles = class extends THREE3.Object3D {
|
|
595
|
+
mesh;
|
|
596
|
+
/** Base object for positioning the emitter. */
|
|
597
|
+
base;
|
|
598
|
+
debugMesh;
|
|
599
|
+
material;
|
|
600
|
+
config;
|
|
601
|
+
uniforms;
|
|
602
|
+
buffers;
|
|
603
|
+
attributes;
|
|
604
|
+
easingIndex = 0;
|
|
605
|
+
alphaMapCount = 0;
|
|
606
|
+
emitted = 0;
|
|
607
|
+
cursor = 0;
|
|
608
|
+
/** Whether the particle system is currently running. */
|
|
609
|
+
running = false;
|
|
610
|
+
constructor(config, geometry) {
|
|
611
|
+
super();
|
|
612
|
+
this.name = "Particles";
|
|
613
|
+
this.type = "Particles";
|
|
614
|
+
this.base = new THREE3.Object3D();
|
|
615
|
+
this.base.name = "Base";
|
|
616
|
+
this.add(this.base);
|
|
617
|
+
this.debugMesh = new THREE3.Mesh(
|
|
618
|
+
new THREE3.BoxGeometry(0.2, 0.2, 0.2),
|
|
619
|
+
new THREE3.MeshBasicMaterial({ color: 16777215, wireframe: true })
|
|
620
|
+
);
|
|
621
|
+
this.debugMesh.name = "Debug";
|
|
622
|
+
this.base.add(this.debugMesh);
|
|
623
|
+
const p = config.particles;
|
|
624
|
+
const r = config.render ?? {};
|
|
625
|
+
const e = config.emitter ?? {};
|
|
626
|
+
this.config = {
|
|
627
|
+
particles: {
|
|
628
|
+
count: p.count ?? 1e3,
|
|
629
|
+
intensity: p.intensity ?? 1,
|
|
630
|
+
fadeSize: p.fadeSize ?? [0.1, 0.9],
|
|
631
|
+
fadeAlpha: p.fadeAlpha ?? [0, 1],
|
|
632
|
+
fadeAlphaMap: p.fadeAlphaMap ?? [0, 1],
|
|
633
|
+
gravity: p.gravity ?? [0, 0, 0],
|
|
634
|
+
alphaMapsStart: p.alphaMapsStart ?? [],
|
|
635
|
+
alphaMapsEnd: p.alphaMapsEnd ?? [],
|
|
636
|
+
colors: p.colors ?? [[{ color: "#ffffff", stop: 0 }]],
|
|
637
|
+
appearance: p.appearance ?? 0,
|
|
638
|
+
easeFunction: p.easeFunction ?? "easeLinear"
|
|
639
|
+
},
|
|
640
|
+
render: {
|
|
641
|
+
alphaMapSize: r.alphaMapSize ?? 256,
|
|
642
|
+
alphaMapFilter: r.alphaMapFilter ?? THREE3.LinearFilter,
|
|
643
|
+
frustumCulled: r.frustumCulled ?? true,
|
|
644
|
+
blendingMode: r.blendingMode ?? THREE3.AdditiveBlending,
|
|
645
|
+
side: r.side ?? THREE3.FrontSide,
|
|
646
|
+
depthTest: r.depthTest ?? true
|
|
647
|
+
},
|
|
648
|
+
emitter: {
|
|
649
|
+
duration: e.duration ?? 1,
|
|
650
|
+
rate: e.rate ?? 1e3,
|
|
651
|
+
spawnMode: e.spawnMode ?? "time",
|
|
652
|
+
static: e.static ?? 0,
|
|
653
|
+
worldUpRight: e.worldUpRight ?? false,
|
|
654
|
+
loop: e.loop ?? false,
|
|
655
|
+
delay: e.delay ?? 0,
|
|
656
|
+
debug: e.debug ?? false,
|
|
657
|
+
lifetime: e.lifetime ?? [0.1, 1],
|
|
658
|
+
speed: e.speed ?? [5, 20],
|
|
659
|
+
size: e.size ?? [0.1, 1],
|
|
660
|
+
startPositionMin: e.startPositionMin ?? [0, 0, 0],
|
|
661
|
+
startPositionMax: e.startPositionMax ?? [0, 0, 0],
|
|
662
|
+
startRotationMin: e.startRotationMin ?? [0, 0, 0],
|
|
663
|
+
startRotationMax: e.startRotationMax ?? [0, 0, 0],
|
|
664
|
+
rotationSpeedMin: e.rotationSpeedMin ?? [0, 0, 0],
|
|
665
|
+
rotationSpeedMax: e.rotationSpeedMax ?? [0, 0, 0],
|
|
666
|
+
directionMin: e.directionMin ?? [0, 0, 0],
|
|
667
|
+
directionMax: e.directionMax ?? [0, 0, 0]
|
|
668
|
+
}
|
|
669
|
+
};
|
|
670
|
+
this.debugMesh.visible = this.config.emitter.debug;
|
|
671
|
+
this.easingIndex = EASE_FUNCTIONS.indexOf(this.config.particles.easeFunction);
|
|
672
|
+
if (this.easingIndex < 0) this.easingIndex = 0;
|
|
673
|
+
const alphaMaps = [
|
|
674
|
+
...this.config.particles.alphaMapsStart ?? [],
|
|
675
|
+
...this.config.particles.alphaMapsEnd ?? []
|
|
676
|
+
];
|
|
677
|
+
this.alphaMapCount = alphaMaps.length;
|
|
678
|
+
let atlas = null;
|
|
679
|
+
if (alphaMaps.length > 0) {
|
|
680
|
+
atlas = createTextureAtlas(
|
|
681
|
+
alphaMaps,
|
|
682
|
+
void 0,
|
|
683
|
+
this.config.render.alphaMapSize,
|
|
684
|
+
this.config.render.alphaMapFilter
|
|
685
|
+
);
|
|
686
|
+
} else {
|
|
687
|
+
const canvas = document.createElement("canvas");
|
|
688
|
+
atlas = new THREE3.CanvasTexture(canvas);
|
|
689
|
+
}
|
|
690
|
+
const colorGradientTexture = createColorGradientTexture(this.config.particles.colors, 128);
|
|
691
|
+
this.uniforms = {
|
|
692
|
+
cursor: uniform(0),
|
|
693
|
+
rate: uniform(0),
|
|
694
|
+
uTime: uniform(0),
|
|
695
|
+
uPosition: uniform(this.base.position),
|
|
696
|
+
alphaMap: texture2(atlas),
|
|
697
|
+
uColorGradient: texture2(colorGradientTexture)
|
|
698
|
+
};
|
|
699
|
+
const defaultGeometry = geometry ?? new THREE3.PlaneGeometry(0.5, 0.5);
|
|
700
|
+
const count = this.config.particles.count;
|
|
701
|
+
this.buffers = {
|
|
702
|
+
instanceLifetime: new Float32Array(count * 2),
|
|
703
|
+
instance: new Float32Array(count * 7),
|
|
704
|
+
instanceDirection: new Float32Array(count * 3),
|
|
705
|
+
instanceRotationSpeed: new Float32Array(count * 3),
|
|
706
|
+
instanceAlphaMapUVOffset: new Float32Array(count * 2),
|
|
707
|
+
instanceSpeed: new Float32Array(count)
|
|
708
|
+
};
|
|
709
|
+
this.attributes = {
|
|
710
|
+
instanceLifetime: instancedArray(this.buffers.instanceLifetime, "float"),
|
|
711
|
+
instance: instancedArray(this.buffers.instance, "float"),
|
|
712
|
+
instanceDirection: instancedArray(this.buffers.instanceDirection, "float"),
|
|
713
|
+
instanceRotationSpeed: instancedArray(this.buffers.instanceRotationSpeed, "float"),
|
|
714
|
+
instanceAlphaMapUVOffset: instancedArray(this.buffers.instanceAlphaMapUVOffset, "float"),
|
|
715
|
+
instanceSpeed: instancedArray(this.buffers.instanceSpeed, "float")
|
|
716
|
+
};
|
|
717
|
+
this.material = this.createMaterial();
|
|
718
|
+
this.mesh = new THREE3.InstancedMesh(defaultGeometry, this.material, count);
|
|
719
|
+
this.mesh.userData = {
|
|
720
|
+
attributes: this.attributes,
|
|
721
|
+
uniforms: this.uniforms,
|
|
722
|
+
config: this.config,
|
|
723
|
+
alphaMapCount: this.alphaMapCount,
|
|
724
|
+
easingIndex: this.easingIndex
|
|
725
|
+
};
|
|
726
|
+
this.add(this.mesh);
|
|
727
|
+
this.mesh.frustumCulled = this.config.render.frustumCulled ?? false;
|
|
728
|
+
}
|
|
729
|
+
createMaterial() {
|
|
730
|
+
const _mat = createParticleMaterialTemplate();
|
|
731
|
+
_mat.blending = this.config.render.blendingMode;
|
|
732
|
+
_mat.premultipliedAlpha = this.config.render.blendingMode === THREE3.SubtractiveBlending || this.config.render.blendingMode === THREE3.MultiplyBlending;
|
|
733
|
+
_mat.depthWrite = false;
|
|
734
|
+
_mat.side = this.config.render.side;
|
|
735
|
+
_mat.depthTest = this.config.render.depthTest;
|
|
736
|
+
_mat.transparent = true;
|
|
737
|
+
return _mat;
|
|
738
|
+
}
|
|
739
|
+
/** Starts the particle system from the beginning. */
|
|
740
|
+
start() {
|
|
741
|
+
this.running = true;
|
|
742
|
+
this.uniforms.uTime.value = 0;
|
|
743
|
+
this.cursor = 0;
|
|
744
|
+
this.emitted = 0;
|
|
745
|
+
this.visible = true;
|
|
746
|
+
this.mesh.visible = true;
|
|
747
|
+
this.attributes.instanceLifetime.value.array.fill(0);
|
|
748
|
+
}
|
|
749
|
+
/** Restarts (alias for start). */
|
|
750
|
+
restart() {
|
|
751
|
+
this.start();
|
|
752
|
+
}
|
|
753
|
+
/** Pauses the particle system, keeping current state. */
|
|
754
|
+
pause() {
|
|
755
|
+
this.running = false;
|
|
756
|
+
}
|
|
757
|
+
/** Resumes a paused system without resetting its state. */
|
|
758
|
+
resume() {
|
|
759
|
+
this.running = true;
|
|
760
|
+
this.visible = true;
|
|
761
|
+
this.mesh.visible = true;
|
|
762
|
+
}
|
|
763
|
+
/** Stops the particle system and hides it. */
|
|
764
|
+
stop() {
|
|
765
|
+
this.running = false;
|
|
766
|
+
this.visible = false;
|
|
767
|
+
this.mesh.visible = false;
|
|
768
|
+
}
|
|
769
|
+
/** Whether emission loops continuously. */
|
|
770
|
+
get looping() {
|
|
771
|
+
return this.config.emitter.loop;
|
|
772
|
+
}
|
|
773
|
+
/**
|
|
774
|
+
* For non-looping systems, whether all emitted particles have aged past
|
|
775
|
+
* their maximum lifetime (so the effect is visually finished).
|
|
776
|
+
*/
|
|
777
|
+
isComplete() {
|
|
778
|
+
if (this.config.emitter.loop) return false;
|
|
779
|
+
const e = this.config.emitter;
|
|
780
|
+
const maxLifetime = e.lifetime[1];
|
|
781
|
+
const endTime = e.delay + e.duration + maxLifetime;
|
|
782
|
+
return this.emitted >= e.rate && this.uniforms.uTime.value > endTime;
|
|
783
|
+
}
|
|
784
|
+
/** Updates the particle system. Call each frame. */
|
|
785
|
+
update(delta) {
|
|
786
|
+
this.mesh.visible = this.visible;
|
|
787
|
+
if (!this.running) return;
|
|
788
|
+
this._update();
|
|
789
|
+
this.uniforms.uTime.value += delta;
|
|
790
|
+
}
|
|
791
|
+
_compute(i) {
|
|
792
|
+
const { emitter } = this.config;
|
|
793
|
+
const pos = this.uniforms.uPosition.value;
|
|
794
|
+
const dynamicFactor = 1 - emitter.static;
|
|
795
|
+
const inst = this.attributes.instance.value.array;
|
|
796
|
+
const i7 = i * 7;
|
|
797
|
+
inst[i7 + 0] = randFloat(emitter.startPositionMin[0], emitter.startPositionMax[0]) + pos.x * dynamicFactor;
|
|
798
|
+
inst[i7 + 1] = randFloat(emitter.startPositionMin[1], emitter.startPositionMax[1]) + pos.y * dynamicFactor;
|
|
799
|
+
inst[i7 + 2] = randFloat(emitter.startPositionMin[2], emitter.startPositionMax[2]) + pos.z * dynamicFactor;
|
|
800
|
+
inst[i7 + 3] = randFloat(emitter.startRotationMin[0], emitter.startRotationMax[0]);
|
|
801
|
+
inst[i7 + 4] = randFloat(emitter.startRotationMin[1], emitter.startRotationMax[1]);
|
|
802
|
+
inst[i7 + 5] = randFloat(emitter.startRotationMin[2], emitter.startRotationMax[2]);
|
|
803
|
+
inst[i7 + 6] = randFloat(emitter.size[0], emitter.size[1]);
|
|
804
|
+
const i3 = i * 3;
|
|
805
|
+
const dir = this.attributes.instanceDirection.value.array;
|
|
806
|
+
dir[i3 + 0] = randFloat(emitter.directionMin[0], emitter.directionMax[0]);
|
|
807
|
+
dir[i3 + 1] = randFloat(emitter.directionMin[1], emitter.directionMax[1]);
|
|
808
|
+
dir[i3 + 2] = randFloat(emitter.directionMin[2], emitter.directionMax[2]);
|
|
809
|
+
const rotSpeed = this.attributes.instanceRotationSpeed.value.array;
|
|
810
|
+
rotSpeed[i3 + 0] = randFloat(emitter.rotationSpeedMin[0], emitter.rotationSpeedMax[0]);
|
|
811
|
+
rotSpeed[i3 + 1] = randFloat(emitter.rotationSpeedMin[1], emitter.rotationSpeedMax[1]);
|
|
812
|
+
rotSpeed[i3 + 2] = randFloat(emitter.rotationSpeedMin[2], emitter.rotationSpeedMax[2]);
|
|
813
|
+
const i2 = i * 2;
|
|
814
|
+
const lifetime = this.attributes.instanceLifetime.value.array;
|
|
815
|
+
lifetime[i2 + 0] = this.uniforms.uTime.value;
|
|
816
|
+
lifetime[i2 + 1] = randFloat(emitter.lifetime[0], emitter.lifetime[1]);
|
|
817
|
+
const startCount = this.config.particles.alphaMapsStart?.length ?? 0;
|
|
818
|
+
const endCount = this.config.particles.alphaMapsEnd?.length ?? 0;
|
|
819
|
+
const startIdx = startCount > 0 ? randInt(0, startCount - 1) : 0;
|
|
820
|
+
let endIdx = 0;
|
|
821
|
+
if (endCount > 0) {
|
|
822
|
+
endIdx = startCount + randInt(0, endCount - 1);
|
|
823
|
+
} else if (startCount > 0) {
|
|
824
|
+
endIdx = randInt(0, startCount - 1);
|
|
825
|
+
}
|
|
826
|
+
const alphaOffset = this.attributes.instanceAlphaMapUVOffset.value.array;
|
|
827
|
+
alphaOffset[i2 + 0] = startIdx;
|
|
828
|
+
alphaOffset[i2 + 1] = endIdx;
|
|
829
|
+
this.attributes.instanceSpeed.value.array[i] = randFloat(emitter.speed[0], emitter.speed[1]);
|
|
830
|
+
}
|
|
831
|
+
_update() {
|
|
832
|
+
const loop = this.config.emitter.loop;
|
|
833
|
+
const spawnMode = this.config.emitter.spawnMode;
|
|
834
|
+
const maxParticlesTotal = this.config.particles.count;
|
|
835
|
+
const maxParticles = this.config.emitter.rate;
|
|
836
|
+
const duration = this.config.emitter.duration;
|
|
837
|
+
const delay = this.config.emitter.delay;
|
|
838
|
+
const amount = spawnMode === "burst" ? maxParticles : Math.max(
|
|
839
|
+
0,
|
|
840
|
+
Math.floor((this.uniforms.uTime.value - delay) / duration * maxParticles)
|
|
841
|
+
);
|
|
842
|
+
const rate = amount - this.emitted;
|
|
843
|
+
if (this.emitted >= maxParticles && !loop) return;
|
|
844
|
+
if (spawnMode === "time") {
|
|
845
|
+
if (this.cursor >= maxParticlesTotal) this.cursor = 0;
|
|
846
|
+
this.uniforms.cursor.value = this.cursor;
|
|
847
|
+
this.uniforms.rate.value = rate;
|
|
848
|
+
}
|
|
849
|
+
for (let _i = this.cursor; _i < this.cursor + rate; _i++) {
|
|
850
|
+
this._compute(_i % maxParticlesTotal);
|
|
851
|
+
}
|
|
852
|
+
this.attributes.instance.value.needsUpdate = true;
|
|
853
|
+
this.attributes.instanceDirection.value.needsUpdate = true;
|
|
854
|
+
this.attributes.instanceRotationSpeed.value.needsUpdate = true;
|
|
855
|
+
this.attributes.instanceLifetime.value.needsUpdate = true;
|
|
856
|
+
this.attributes.instanceAlphaMapUVOffset.value.needsUpdate = true;
|
|
857
|
+
this.attributes.instanceSpeed.value.needsUpdate = true;
|
|
858
|
+
if (spawnMode === "time") {
|
|
859
|
+
this.cursor += rate;
|
|
860
|
+
this.cursor = this.cursor % maxParticlesTotal;
|
|
861
|
+
}
|
|
862
|
+
this.emitted += rate;
|
|
863
|
+
}
|
|
864
|
+
/** Updates configuration at runtime (shallow per-section merge). */
|
|
865
|
+
updateConfig(config) {
|
|
866
|
+
if (config.particles) Object.assign(this.config.particles, config.particles);
|
|
867
|
+
if (config.render) Object.assign(this.config.render, config.render);
|
|
868
|
+
if (config.emitter) Object.assign(this.config.emitter, config.emitter);
|
|
869
|
+
}
|
|
870
|
+
/** Disposes of all resources used by the particle system. */
|
|
871
|
+
dispose() {
|
|
872
|
+
this.stop();
|
|
873
|
+
this.mesh.geometry.dispose();
|
|
874
|
+
this.material.dispose();
|
|
875
|
+
}
|
|
876
|
+
};
|
|
877
|
+
|
|
878
|
+
// src/lib/behaviors/particle-emitter/preset-builder.ts
|
|
879
|
+
var DEFAULT_MAGIC_BEHAVIOR_BY_ALIGNMENT = {
|
|
880
|
+
arcane: {
|
|
881
|
+
temperament: "regal",
|
|
882
|
+
agency: "reactive",
|
|
883
|
+
order: "geometric",
|
|
884
|
+
realityEffect: "warping",
|
|
885
|
+
intensity: 1
|
|
886
|
+
},
|
|
887
|
+
holy: {
|
|
888
|
+
temperament: "calm",
|
|
889
|
+
agency: "passive",
|
|
890
|
+
order: "geometric",
|
|
891
|
+
realityEffect: "illuminating",
|
|
892
|
+
intensity: 1
|
|
893
|
+
},
|
|
894
|
+
corrupted: {
|
|
895
|
+
temperament: "ominous",
|
|
896
|
+
agency: "seeking",
|
|
897
|
+
order: "chaotic",
|
|
898
|
+
realityEffect: "decaying",
|
|
899
|
+
intensity: 1.05
|
|
900
|
+
},
|
|
901
|
+
nature: {
|
|
902
|
+
temperament: "calm",
|
|
903
|
+
agency: "reactive",
|
|
904
|
+
order: "organic",
|
|
905
|
+
realityEffect: "healing",
|
|
906
|
+
intensity: 0.9
|
|
907
|
+
},
|
|
908
|
+
void: {
|
|
909
|
+
temperament: "ominous",
|
|
910
|
+
agency: "seeking",
|
|
911
|
+
order: "chaotic",
|
|
912
|
+
realityEffect: "warping",
|
|
913
|
+
intensity: 1.15
|
|
914
|
+
},
|
|
915
|
+
psychic: {
|
|
916
|
+
temperament: "predatory",
|
|
917
|
+
agency: "sentient-feeling",
|
|
918
|
+
order: "organic",
|
|
919
|
+
realityEffect: "binding",
|
|
920
|
+
intensity: 1
|
|
921
|
+
}
|
|
922
|
+
};
|
|
923
|
+
var MAGIC_PALETTES = {
|
|
924
|
+
arcane: { start: "#dbeafe", mid: "#60a5fa", end: "#1d4ed8" },
|
|
925
|
+
holy: { start: "#fff7d1", mid: "#fde68a", end: "#f59e0b" },
|
|
926
|
+
corrupted: { start: "#bef264", mid: "#84cc16", end: "#4d7c0f" },
|
|
927
|
+
nature: { start: "#dcfce7", mid: "#4ade80", end: "#15803d" },
|
|
928
|
+
void: { start: "#c4b5fd", mid: "#475569", end: "#0f172a" },
|
|
929
|
+
psychic: { start: "#fce7f3", mid: "#f472b6", end: "#db2777" }
|
|
930
|
+
};
|
|
931
|
+
function particleEffect(create) {
|
|
932
|
+
return { create };
|
|
933
|
+
}
|
|
934
|
+
function defineSemanticParticlePreset(preset) {
|
|
935
|
+
return preset;
|
|
936
|
+
}
|
|
937
|
+
function createMagicModifier(alignment, overrides = {}) {
|
|
938
|
+
return {
|
|
939
|
+
alignment,
|
|
940
|
+
...DEFAULT_MAGIC_BEHAVIOR_BY_ALIGNMENT[alignment],
|
|
941
|
+
...overrides
|
|
942
|
+
};
|
|
943
|
+
}
|
|
944
|
+
function createSemanticParticleEffect(preset, options = {}) {
|
|
945
|
+
const config = buildParticlesConfig(preset, options);
|
|
946
|
+
return particleEffect(() => new Particles(config));
|
|
947
|
+
}
|
|
948
|
+
function buildParticlesConfig(preset, options = {}) {
|
|
949
|
+
const defaults = preset.system.defaults;
|
|
950
|
+
const magic = normalizeMagicModifier(options.magic);
|
|
951
|
+
const resolvedShape = mergeShapeConfig(preset.system.shape, options.shape);
|
|
952
|
+
const baseBehaviors = mergeBehaviorConfig(preset.system.behaviors, options.behaviors);
|
|
953
|
+
const baseColor = options.color ?? defaults.color;
|
|
954
|
+
const resolvedColor = magic ? mixColors(baseColor, MAGIC_PALETTES[magic.alignment].start, 0.2) : baseColor;
|
|
955
|
+
const behaviors = magic ? applyMagicBehaviors(baseBehaviors, resolvedColor, magic) : baseBehaviors;
|
|
956
|
+
const duration = options.duration ?? defaults.duration;
|
|
957
|
+
const looping = options.looping ?? defaults.looping ?? preset.system.emission.type === "rate";
|
|
958
|
+
const life = toRange(options.life ?? defaults.life);
|
|
959
|
+
const size = toRange(options.size ?? defaults.size);
|
|
960
|
+
const baseSpeed = toRange(options.speed ?? defaults.speed);
|
|
961
|
+
const shapeSpeed = resolvedShape && "speed" in resolvedShape ? resolvedShape.speed : void 0;
|
|
962
|
+
const speed = shapeSpeed !== void 0 ? toRange(addRanges(baseSpeed, shapeSpeed)) : baseSpeed;
|
|
963
|
+
const intensity = magic ? clamp(magic.intensity ?? 1, 0.5, 1.5) : defaults.opacity ?? 1;
|
|
964
|
+
const colors = behaviors?.colorOverLife ? [behaviors.colorOverLife.colors.map(([color, stop]) => toGpuColorStop(color, stop))] : [
|
|
965
|
+
[
|
|
966
|
+
{ color: toHexColor(resolvedColor), stop: 0 },
|
|
967
|
+
{ color: toHexColor(resolvedColor), stop: 1 }
|
|
968
|
+
]
|
|
969
|
+
];
|
|
970
|
+
const fadeAlpha = behaviors?.colorOverLife ? deriveFadeFromAlpha(behaviors.colorOverLife.alpha) : [0.1, 0.85];
|
|
971
|
+
const fadeSize = behaviors?.sizeOverLife ? deriveFadeFromSizeCurve(behaviors.sizeOverLife) : [0.15, 0.9];
|
|
972
|
+
const gravity = behaviors?.forceOverLife ? forceToGravity(behaviors.forceOverLife) : [0, 0, 0];
|
|
973
|
+
const easeFunction = behaviors?.speedOverLife ? speedCurveToEase(behaviors.speedOverLife) : "easeLinear";
|
|
974
|
+
const emission = resolveEmission(preset.system.emission, options, duration, life[1]);
|
|
975
|
+
const direction = shapeToDirection(resolvedShape);
|
|
976
|
+
const startPosition = shapeToStartPosition(resolvedShape);
|
|
977
|
+
const startRotation = rotationToStart(options.rotation ?? defaults.rotation);
|
|
978
|
+
const rotationSpeed = behaviors?.rotationOverLife ? rangeToRotationSpeedZ(behaviors.rotationOverLife) : { min: [0, 0, 0], max: [0, 0, 0] };
|
|
979
|
+
const blending = options.blending ?? AdditiveBlending2;
|
|
980
|
+
const particles = {
|
|
981
|
+
count: emission.count,
|
|
982
|
+
intensity,
|
|
983
|
+
fadeSize,
|
|
984
|
+
fadeAlpha,
|
|
985
|
+
gravity,
|
|
986
|
+
colors,
|
|
987
|
+
easeFunction
|
|
988
|
+
};
|
|
989
|
+
if (options.texture) {
|
|
990
|
+
particles.alphaMapsStart = [options.texture];
|
|
991
|
+
}
|
|
992
|
+
const emitter = {
|
|
993
|
+
duration,
|
|
994
|
+
rate: emission.rate,
|
|
995
|
+
spawnMode: emission.spawnMode,
|
|
996
|
+
loop: looping,
|
|
997
|
+
static: 0,
|
|
998
|
+
worldUpRight: false,
|
|
999
|
+
lifetime: life,
|
|
1000
|
+
speed,
|
|
1001
|
+
size,
|
|
1002
|
+
directionMin: direction.min,
|
|
1003
|
+
directionMax: direction.max,
|
|
1004
|
+
startPositionMin: startPosition.min,
|
|
1005
|
+
startPositionMax: startPosition.max,
|
|
1006
|
+
startRotationMin: startRotation.min,
|
|
1007
|
+
startRotationMax: startRotation.max,
|
|
1008
|
+
rotationSpeedMin: rotationSpeed.min,
|
|
1009
|
+
rotationSpeedMax: rotationSpeed.max
|
|
1010
|
+
};
|
|
1011
|
+
return {
|
|
1012
|
+
particles,
|
|
1013
|
+
emitter,
|
|
1014
|
+
render: { blendingMode: blending }
|
|
1015
|
+
};
|
|
1016
|
+
}
|
|
1017
|
+
function resolveEmission(emission, options, duration, maxLifetime) {
|
|
1018
|
+
if (emission.type === "burst") {
|
|
1019
|
+
const count2 = Math.max(1, Math.round(options.count ?? emission.count));
|
|
1020
|
+
return { spawnMode: "burst", rate: count2, count: count2 };
|
|
1021
|
+
}
|
|
1022
|
+
const perSecond = Math.max(0, options.emissionRate ?? emission.rate);
|
|
1023
|
+
const rate = Math.max(1, Math.round(perSecond * Math.max(duration, 1e-4)));
|
|
1024
|
+
const simultaneous = Math.ceil(perSecond * Math.max(maxLifetime, 1e-4) * 1.5);
|
|
1025
|
+
const count = Math.min(2e5, Math.max(rate, simultaneous, 8));
|
|
1026
|
+
return { spawnMode: "time", rate, count };
|
|
1027
|
+
}
|
|
1028
|
+
function deriveFadeFromAlpha(alpha) {
|
|
1029
|
+
if (!alpha || alpha.length === 0) return [0.1, 0.85];
|
|
1030
|
+
const sorted = [...alpha].sort((a, b) => a[1] - b[1]);
|
|
1031
|
+
const maxAlpha = Math.max(...sorted.map(([value]) => value), 1e-4);
|
|
1032
|
+
let fadeIn = 0.15;
|
|
1033
|
+
for (const [value, stop] of sorted) {
|
|
1034
|
+
if (value >= maxAlpha * 0.6) {
|
|
1035
|
+
fadeIn = stop;
|
|
1036
|
+
break;
|
|
1037
|
+
}
|
|
1038
|
+
}
|
|
1039
|
+
let fadeOut = 0.85;
|
|
1040
|
+
for (const [value, stop] of sorted) {
|
|
1041
|
+
if (value >= maxAlpha * 0.4) fadeOut = stop;
|
|
1042
|
+
}
|
|
1043
|
+
fadeIn = clamp(fadeIn, 0.02, 0.45);
|
|
1044
|
+
fadeOut = clamp(fadeOut, 0.55, 0.99);
|
|
1045
|
+
if (fadeOut <= fadeIn) fadeOut = Math.min(0.99, fadeIn + 0.3);
|
|
1046
|
+
return [fadeIn, fadeOut];
|
|
1047
|
+
}
|
|
1048
|
+
function deriveFadeFromSizeCurve(points) {
|
|
1049
|
+
const start = points[0];
|
|
1050
|
+
const end = points[3];
|
|
1051
|
+
const fadeIn = start < 0.5 ? 0.25 : 0.02;
|
|
1052
|
+
const fadeOut = end < 0.5 ? 0.75 : 0.98;
|
|
1053
|
+
return [fadeIn, fadeOut];
|
|
1054
|
+
}
|
|
1055
|
+
function forceToGravity(force) {
|
|
1056
|
+
const mid = (range2) => {
|
|
1057
|
+
if (range2 === void 0) return 0;
|
|
1058
|
+
const [min, max2] = toRange(range2);
|
|
1059
|
+
return (min + max2) * 0.5;
|
|
1060
|
+
};
|
|
1061
|
+
return [mid(force.x), mid(force.y), mid(force.z)];
|
|
1062
|
+
}
|
|
1063
|
+
function speedCurveToEase(points) {
|
|
1064
|
+
const start = points[0];
|
|
1065
|
+
const end = points[3];
|
|
1066
|
+
if (end < start - 0.05) return "easeOutCubic";
|
|
1067
|
+
if (end > start + 0.05) return "easeInCubic";
|
|
1068
|
+
return "easeLinear";
|
|
1069
|
+
}
|
|
1070
|
+
function shapeToDirection(shape) {
|
|
1071
|
+
if (!shape || shape.type === "point" || shape.type === "sphere") {
|
|
1072
|
+
return { min: [-1, -1, -1], max: [1, 1, 1] };
|
|
1073
|
+
}
|
|
1074
|
+
const angle = shape.angle ?? 0.3;
|
|
1075
|
+
const spread = Math.tan(clamp(angle, 0, 1.4));
|
|
1076
|
+
return { min: [-spread, 1, -spread], max: [spread, 1, spread] };
|
|
1077
|
+
}
|
|
1078
|
+
function shapeToStartPosition(shape) {
|
|
1079
|
+
if (!shape || shape.type === "point") {
|
|
1080
|
+
return { min: [0, 0, 0], max: [0, 0, 0] };
|
|
1081
|
+
}
|
|
1082
|
+
const r = shape.radius ?? 0;
|
|
1083
|
+
if (shape.type === "sphere") {
|
|
1084
|
+
return { min: [-r, -r, -r], max: [r, r, r] };
|
|
1085
|
+
}
|
|
1086
|
+
return { min: [-r, 0, -r], max: [r, 0, r] };
|
|
1087
|
+
}
|
|
1088
|
+
function rotationToStart(rotation) {
|
|
1089
|
+
if (rotation === void 0) {
|
|
1090
|
+
return { min: [0, 0, 0], max: [0, 0, 0] };
|
|
1091
|
+
}
|
|
1092
|
+
const [min, max2] = toRange(rotation);
|
|
1093
|
+
const norm = (theta) => theta / Math.PI - 1;
|
|
1094
|
+
return { min: [0, 0, norm(min)], max: [0, 0, norm(max2)] };
|
|
1095
|
+
}
|
|
1096
|
+
function rangeToRotationSpeedZ(rotation) {
|
|
1097
|
+
const [min, max2] = toRange(rotation);
|
|
1098
|
+
return { min: [0, 0, min], max: [0, 0, max2] };
|
|
1099
|
+
}
|
|
1100
|
+
function toGpuColorStop(color, stop) {
|
|
1101
|
+
return { color: toHexColor(color), stop };
|
|
1102
|
+
}
|
|
1103
|
+
function normalizeMagicModifier(input) {
|
|
1104
|
+
if (!input) return null;
|
|
1105
|
+
if (typeof input === "string") return createMagicModifier(input);
|
|
1106
|
+
return createMagicModifier(input.alignment, input);
|
|
1107
|
+
}
|
|
1108
|
+
function applyMagicBehaviors(base, baseColor, magic) {
|
|
1109
|
+
const intensity = clamp(magic.intensity ?? 1, 0.25, 1.5);
|
|
1110
|
+
const palette = MAGIC_PALETTES[magic.alignment];
|
|
1111
|
+
return {
|
|
1112
|
+
...base,
|
|
1113
|
+
colorOverLife: tintColorOverLife(base?.colorOverLife, baseColor, palette, intensity),
|
|
1114
|
+
rotationOverLife: addRanges(base?.rotationOverLife, resolveMagicRotation(magic, intensity)),
|
|
1115
|
+
forceOverLife: mergeForce(base?.forceOverLife, resolveMagicForce(magic, intensity)),
|
|
1116
|
+
noise: mergeNoise(base?.noise, resolveMagicNoise(magic, intensity)),
|
|
1117
|
+
orbitOverLife: resolveMagicOrbit(magic, intensity) ?? base?.orbitOverLife
|
|
1118
|
+
};
|
|
1119
|
+
}
|
|
1120
|
+
function resolveMagicRotation(magic, intensity) {
|
|
1121
|
+
const amount = 0.7 + intensity * 1.4;
|
|
1122
|
+
switch (magic.order) {
|
|
1123
|
+
case "geometric":
|
|
1124
|
+
return [amount * 0.45, amount];
|
|
1125
|
+
case "organic":
|
|
1126
|
+
return [-amount * 0.55, amount * 0.55];
|
|
1127
|
+
case "chaotic":
|
|
1128
|
+
return [-amount * 2.4, amount * 2.4];
|
|
1129
|
+
default:
|
|
1130
|
+
return void 0;
|
|
1131
|
+
}
|
|
1132
|
+
}
|
|
1133
|
+
function resolveMagicForce(magic, intensity) {
|
|
1134
|
+
const amount = 0.2 + intensity * 0.55;
|
|
1135
|
+
switch (magic.realityEffect) {
|
|
1136
|
+
case "illuminating":
|
|
1137
|
+
case "healing":
|
|
1138
|
+
return { y: [amount * 0.6, amount] };
|
|
1139
|
+
case "decaying":
|
|
1140
|
+
return { y: [-amount, -amount * 0.5] };
|
|
1141
|
+
case "binding":
|
|
1142
|
+
return { y: [-amount * 0.35, amount * 0.15] };
|
|
1143
|
+
case "warping":
|
|
1144
|
+
return { x: [-amount * 0.35, amount * 0.35], z: [-amount * 0.35, amount * 0.35] };
|
|
1145
|
+
default:
|
|
1146
|
+
return void 0;
|
|
1147
|
+
}
|
|
1148
|
+
}
|
|
1149
|
+
function resolveMagicNoise(magic, intensity) {
|
|
1150
|
+
const calmMultiplier = magic.temperament === "calm" ? 0.6 : 1;
|
|
1151
|
+
const ominousBoost = magic.temperament === "ominous" ? 1.25 : 1;
|
|
1152
|
+
const basePower = (0.08 + intensity * 0.1) * calmMultiplier * ominousBoost;
|
|
1153
|
+
switch (magic.order) {
|
|
1154
|
+
case "geometric":
|
|
1155
|
+
return {
|
|
1156
|
+
frequency: [1.5, 3.5],
|
|
1157
|
+
power: [basePower * 0.4, basePower * 0.8],
|
|
1158
|
+
positionAmount: [0.08, 0.2],
|
|
1159
|
+
rotationAmount: [0.1, 0.2]
|
|
1160
|
+
};
|
|
1161
|
+
case "organic":
|
|
1162
|
+
return {
|
|
1163
|
+
frequency: [2.5, 5.5],
|
|
1164
|
+
power: [basePower * 0.7, basePower * 1.2],
|
|
1165
|
+
positionAmount: [0.12, 0.3],
|
|
1166
|
+
rotationAmount: [0.14, 0.26]
|
|
1167
|
+
};
|
|
1168
|
+
case "chaotic":
|
|
1169
|
+
default:
|
|
1170
|
+
return {
|
|
1171
|
+
frequency: [4, 8],
|
|
1172
|
+
power: [basePower, basePower * 1.7],
|
|
1173
|
+
positionAmount: [0.18, 0.38],
|
|
1174
|
+
rotationAmount: [0.18, 0.34]
|
|
1175
|
+
};
|
|
1176
|
+
}
|
|
1177
|
+
}
|
|
1178
|
+
function resolveMagicOrbit(magic, intensity) {
|
|
1179
|
+
if (magic.order === "geometric") {
|
|
1180
|
+
return { speed: [3 + intensity * 2, 6 + intensity * 3], axis: [0, 1, 0] };
|
|
1181
|
+
}
|
|
1182
|
+
if (magic.agency === "sentient-feeling") {
|
|
1183
|
+
return { speed: [1 + intensity, 2.5 + intensity * 1.2], axis: [0, 1, 0] };
|
|
1184
|
+
}
|
|
1185
|
+
return void 0;
|
|
1186
|
+
}
|
|
1187
|
+
function tintColorOverLife(base, baseColor, palette, intensity) {
|
|
1188
|
+
if (!base) {
|
|
1189
|
+
return {
|
|
1190
|
+
colors: [
|
|
1191
|
+
[mixColors(baseColor, palette.start, 0.25), 0],
|
|
1192
|
+
[mixColors(baseColor, palette.mid, 0.55), 0.45],
|
|
1193
|
+
[mixColors(baseColor, palette.end, 0.75), 1]
|
|
1194
|
+
],
|
|
1195
|
+
alpha: [
|
|
1196
|
+
[0.22, 0],
|
|
1197
|
+
[1, 0.12],
|
|
1198
|
+
[0.52 + intensity * 0.08, 0.64],
|
|
1199
|
+
[0, 1]
|
|
1200
|
+
]
|
|
1201
|
+
};
|
|
1202
|
+
}
|
|
1203
|
+
return {
|
|
1204
|
+
colors: base.colors.map(([color, stop], index) => {
|
|
1205
|
+
const target = index === 0 ? palette.start : index === base.colors.length - 1 ? palette.end : palette.mid;
|
|
1206
|
+
const amount = index === 0 ? 0.18 : 0.3 + intensity * 0.15;
|
|
1207
|
+
return [mixColors(color, target, amount), stop];
|
|
1208
|
+
}),
|
|
1209
|
+
alpha: base.alpha
|
|
1210
|
+
};
|
|
1211
|
+
}
|
|
1212
|
+
function mergeNoise(base, overlay) {
|
|
1213
|
+
if (!base) return overlay;
|
|
1214
|
+
if (!overlay) return base;
|
|
1215
|
+
return {
|
|
1216
|
+
frequency: addRanges(base.frequency, overlay.frequency) ?? base.frequency,
|
|
1217
|
+
power: addRanges(base.power, overlay.power) ?? base.power,
|
|
1218
|
+
positionAmount: addRanges(base.positionAmount, overlay.positionAmount),
|
|
1219
|
+
rotationAmount: addRanges(base.rotationAmount, overlay.rotationAmount)
|
|
1220
|
+
};
|
|
1221
|
+
}
|
|
1222
|
+
function mergeForce(base, overlay) {
|
|
1223
|
+
if (!base) return overlay;
|
|
1224
|
+
if (!overlay) return base;
|
|
1225
|
+
return {
|
|
1226
|
+
x: addRanges(base.x, overlay.x),
|
|
1227
|
+
y: addRanges(base.y, overlay.y),
|
|
1228
|
+
z: addRanges(base.z, overlay.z)
|
|
1229
|
+
};
|
|
1230
|
+
}
|
|
1231
|
+
function mergeBehaviorConfig(base, overrides) {
|
|
1232
|
+
if (!base && !overrides) return void 0;
|
|
1233
|
+
const merged = {};
|
|
1234
|
+
assignIfDefined(merged, "colorOverLife", resolveOverrideValue(base?.colorOverLife, overrides?.colorOverLife));
|
|
1235
|
+
assignIfDefined(merged, "sizeOverLife", resolveOverrideValue(base?.sizeOverLife, overrides?.sizeOverLife));
|
|
1236
|
+
assignIfDefined(merged, "speedOverLife", resolveOverrideValue(base?.speedOverLife, overrides?.speedOverLife));
|
|
1237
|
+
assignIfDefined(merged, "rotationOverLife", resolveOverrideValue(base?.rotationOverLife, overrides?.rotationOverLife));
|
|
1238
|
+
assignIfDefined(merged, "forceOverLife", resolvePartialOverride(base?.forceOverLife, overrides?.forceOverLife));
|
|
1239
|
+
assignIfDefined(merged, "noise", resolveNoiseOverride(base?.noise, overrides?.noise));
|
|
1240
|
+
assignIfDefined(merged, "orbitOverLife", resolveOrbitOverride(base?.orbitOverLife, overrides?.orbitOverLife));
|
|
1241
|
+
return Object.keys(merged).length > 0 ? merged : void 0;
|
|
1242
|
+
}
|
|
1243
|
+
function mergeShapeConfig(base, override) {
|
|
1244
|
+
if (!override) return base;
|
|
1245
|
+
if (!base || override.type !== base.type) return override;
|
|
1246
|
+
if (override.type === "point") return override;
|
|
1247
|
+
if (override.type === "cone" && base.type === "cone") return { ...base, ...override };
|
|
1248
|
+
if (override.type === "sphere" && base.type === "sphere") return { ...base, ...override };
|
|
1249
|
+
return override;
|
|
1250
|
+
}
|
|
1251
|
+
function addRanges(base, overlay) {
|
|
1252
|
+
if (base === void 0) return overlay;
|
|
1253
|
+
if (overlay === void 0) return base;
|
|
1254
|
+
const [baseMin, baseMax] = toRange(base);
|
|
1255
|
+
const [overlayMin, overlayMax] = toRange(overlay);
|
|
1256
|
+
return [baseMin + overlayMin, baseMax + overlayMax];
|
|
1257
|
+
}
|
|
1258
|
+
function resolveOverrideValue(base, override) {
|
|
1259
|
+
if (override === null) return void 0;
|
|
1260
|
+
return override ?? base;
|
|
1261
|
+
}
|
|
1262
|
+
function resolvePartialOverride(base, override) {
|
|
1263
|
+
if (override === null) return void 0;
|
|
1264
|
+
if (!override) return base;
|
|
1265
|
+
const resolved = { ...base, ...override };
|
|
1266
|
+
return Object.keys(resolved).length > 0 ? resolved : void 0;
|
|
1267
|
+
}
|
|
1268
|
+
function resolveNoiseOverride(base, override) {
|
|
1269
|
+
if (override === null) return void 0;
|
|
1270
|
+
if (!override) return base;
|
|
1271
|
+
const frequency = override.frequency ?? base?.frequency;
|
|
1272
|
+
const power = override.power ?? base?.power;
|
|
1273
|
+
if (frequency === void 0 || power === void 0) return void 0;
|
|
1274
|
+
return { ...base, ...override, frequency, power };
|
|
1275
|
+
}
|
|
1276
|
+
function resolveOrbitOverride(base, override) {
|
|
1277
|
+
if (override === null) return void 0;
|
|
1278
|
+
if (!override) return base;
|
|
1279
|
+
const speed = override.speed ?? base?.speed;
|
|
1280
|
+
if (speed === void 0) return void 0;
|
|
1281
|
+
return { ...base, ...override, speed };
|
|
1282
|
+
}
|
|
1283
|
+
function assignIfDefined(target, key, value) {
|
|
1284
|
+
if (value !== void 0) target[key] = value;
|
|
1285
|
+
}
|
|
1286
|
+
function toHexColor(color) {
|
|
1287
|
+
return `#${new Color(color).getHexString()}`;
|
|
1288
|
+
}
|
|
1289
|
+
function toRange(value) {
|
|
1290
|
+
if (Array.isArray(value)) {
|
|
1291
|
+
return [value[0] ?? 0, value[1] ?? value[0] ?? 0];
|
|
1292
|
+
}
|
|
1293
|
+
return [value, value];
|
|
1294
|
+
}
|
|
1295
|
+
function mixColors(base, overlay, amount) {
|
|
1296
|
+
const color = new Color(base);
|
|
1297
|
+
color.lerp(new Color(overlay), clamp(amount, 0, 1));
|
|
1298
|
+
return `#${color.getHexString()}`;
|
|
1299
|
+
}
|
|
1300
|
+
function clamp(value, min, max2) {
|
|
1301
|
+
return Math.min(Math.max(value, min), max2);
|
|
1302
|
+
}
|
|
1303
|
+
|
|
1304
|
+
// src/lib/behaviors/particle-emitter/presets/electricity/arc.ts
|
|
1305
|
+
var electricityArcPreset = defineSemanticParticlePreset({
|
|
1306
|
+
family: "electricity",
|
|
1307
|
+
variant: "arc",
|
|
1308
|
+
description: "directed snapping bridge of charge",
|
|
1309
|
+
axes: {
|
|
1310
|
+
"continuity vs discontinuity": "semi-continuous",
|
|
1311
|
+
"branching tendency": "medium",
|
|
1312
|
+
"snap/crackle quality": "high",
|
|
1313
|
+
"seeking behavior": "medium",
|
|
1314
|
+
"charge buildup": "medium",
|
|
1315
|
+
"rhythmic pulsing": "low"
|
|
1316
|
+
},
|
|
1317
|
+
system: {
|
|
1318
|
+
defaults: {
|
|
1319
|
+
duration: 0.7,
|
|
1320
|
+
looping: true,
|
|
1321
|
+
color: "#60a5fa",
|
|
1322
|
+
life: [0.12, 0.26],
|
|
1323
|
+
size: [0.06, 0.14],
|
|
1324
|
+
speed: [2.4, 4],
|
|
1325
|
+
rotation: [-0.3, 0.3],
|
|
1326
|
+
opacity: 0.96,
|
|
1327
|
+
renderMode: 1 /* StretchedBillBoard */
|
|
1328
|
+
},
|
|
1329
|
+
emission: { type: "rate", rate: 28 },
|
|
1330
|
+
shape: {
|
|
1331
|
+
type: "cone",
|
|
1332
|
+
radius: 0.06,
|
|
1333
|
+
thickness: 1,
|
|
1334
|
+
angle: 0.05,
|
|
1335
|
+
speed: [1.2, 2.4]
|
|
1336
|
+
},
|
|
1337
|
+
behaviors: {
|
|
1338
|
+
colorOverLife: {
|
|
1339
|
+
colors: [
|
|
1340
|
+
["#ffffff", 0],
|
|
1341
|
+
["#7dd3fc", 0.3],
|
|
1342
|
+
["#2563eb", 1]
|
|
1343
|
+
],
|
|
1344
|
+
alpha: [
|
|
1345
|
+
[0.2, 0],
|
|
1346
|
+
[1, 0.05],
|
|
1347
|
+
[0.46, 0.5],
|
|
1348
|
+
[0, 1]
|
|
1349
|
+
]
|
|
1350
|
+
},
|
|
1351
|
+
sizeOverLife: [0.7, 0.96, 0.82, 0.26],
|
|
1352
|
+
speedOverLife: [1.08, 0.94, 0.7, 0.38],
|
|
1353
|
+
noise: {
|
|
1354
|
+
frequency: [2.4, 4.8],
|
|
1355
|
+
power: [0.05, 0.12],
|
|
1356
|
+
positionAmount: [0.14, 0.28],
|
|
1357
|
+
rotationAmount: [0.04, 0.12]
|
|
1358
|
+
}
|
|
1359
|
+
},
|
|
1360
|
+
rendererEmitterSettings: {
|
|
1361
|
+
speedFactor: 0.62,
|
|
1362
|
+
lengthFactor: 1.16
|
|
1363
|
+
}
|
|
1364
|
+
}
|
|
1365
|
+
});
|
|
1366
|
+
function arc(options = {}) {
|
|
1367
|
+
return createSemanticParticleEffect(electricityArcPreset, options);
|
|
1368
|
+
}
|
|
1369
|
+
|
|
1370
|
+
// src/lib/behaviors/particle-emitter/presets/electricity/pulse.ts
|
|
1371
|
+
var electricityPulsePreset = defineSemanticParticlePreset({
|
|
1372
|
+
family: "electricity",
|
|
1373
|
+
variant: "pulse",
|
|
1374
|
+
description: "rhythmic swelling packet of charge",
|
|
1375
|
+
axes: {
|
|
1376
|
+
"continuity vs discontinuity": "discrete rhythmic",
|
|
1377
|
+
"branching tendency": "low",
|
|
1378
|
+
"snap/crackle quality": "medium",
|
|
1379
|
+
"seeking behavior": "low",
|
|
1380
|
+
"charge buildup": "medium",
|
|
1381
|
+
"rhythmic pulsing": "high"
|
|
1382
|
+
},
|
|
1383
|
+
system: {
|
|
1384
|
+
defaults: {
|
|
1385
|
+
duration: 0.28,
|
|
1386
|
+
color: "#a5f3fc",
|
|
1387
|
+
life: [0.14, 0.3],
|
|
1388
|
+
size: [0.18, 0.34],
|
|
1389
|
+
speed: [0.18, 0.42],
|
|
1390
|
+
opacity: 0.88
|
|
1391
|
+
},
|
|
1392
|
+
emission: { type: "burst", count: 10 },
|
|
1393
|
+
shape: {
|
|
1394
|
+
type: "sphere",
|
|
1395
|
+
radius: 0.04,
|
|
1396
|
+
thickness: 0.5,
|
|
1397
|
+
speed: [0.02, 0.08]
|
|
1398
|
+
},
|
|
1399
|
+
behaviors: {
|
|
1400
|
+
colorOverLife: {
|
|
1401
|
+
colors: [
|
|
1402
|
+
["#ffffff", 0],
|
|
1403
|
+
["#a5f3fc", 0.4],
|
|
1404
|
+
["#0891b2", 1]
|
|
1405
|
+
],
|
|
1406
|
+
alpha: [
|
|
1407
|
+
[0.14, 0],
|
|
1408
|
+
[0.92, 0.08],
|
|
1409
|
+
[0.42, 0.54],
|
|
1410
|
+
[0, 1]
|
|
1411
|
+
]
|
|
1412
|
+
},
|
|
1413
|
+
sizeOverLife: [0.2, 0.92, 1.26, 0.18]
|
|
1414
|
+
}
|
|
1415
|
+
}
|
|
1416
|
+
});
|
|
1417
|
+
function pulse(options = {}) {
|
|
1418
|
+
return createSemanticParticleEffect(electricityPulsePreset, options);
|
|
1419
|
+
}
|
|
1420
|
+
|
|
1421
|
+
// src/lib/behaviors/particle-emitter/presets/electricity/spark.ts
|
|
1422
|
+
var electricitySparkPreset = defineSemanticParticlePreset({
|
|
1423
|
+
family: "electricity",
|
|
1424
|
+
variant: "spark",
|
|
1425
|
+
description: "tiny discontinuous discharge",
|
|
1426
|
+
axes: {
|
|
1427
|
+
"continuity vs discontinuity": "highly discontinuous",
|
|
1428
|
+
"branching tendency": "low",
|
|
1429
|
+
"snap/crackle quality": "high",
|
|
1430
|
+
"seeking behavior": "low",
|
|
1431
|
+
"charge buildup": "low",
|
|
1432
|
+
"rhythmic pulsing": "low"
|
|
1433
|
+
},
|
|
1434
|
+
system: {
|
|
1435
|
+
defaults: {
|
|
1436
|
+
duration: 0.2,
|
|
1437
|
+
color: "#7dd3fc",
|
|
1438
|
+
life: [0.08, 0.18],
|
|
1439
|
+
size: [0.08, 0.16],
|
|
1440
|
+
speed: [2.2, 4.2],
|
|
1441
|
+
rotation: [-Math.PI, Math.PI],
|
|
1442
|
+
opacity: 0.92,
|
|
1443
|
+
renderMode: 1 /* StretchedBillBoard */
|
|
1444
|
+
},
|
|
1445
|
+
emission: { type: "burst", count: 12 },
|
|
1446
|
+
shape: {
|
|
1447
|
+
type: "sphere",
|
|
1448
|
+
radius: 0.06,
|
|
1449
|
+
thickness: 0.95,
|
|
1450
|
+
speed: [0.8, 1.6]
|
|
1451
|
+
},
|
|
1452
|
+
behaviors: {
|
|
1453
|
+
colorOverLife: {
|
|
1454
|
+
colors: [
|
|
1455
|
+
["#ffffff", 0],
|
|
1456
|
+
["#bae6fd", 0.3],
|
|
1457
|
+
["#38bdf8", 1]
|
|
1458
|
+
],
|
|
1459
|
+
alpha: [
|
|
1460
|
+
[0.22, 0],
|
|
1461
|
+
[1, 0.06],
|
|
1462
|
+
[0.48, 0.4],
|
|
1463
|
+
[0, 1]
|
|
1464
|
+
]
|
|
1465
|
+
},
|
|
1466
|
+
sizeOverLife: [0.44, 0.98, 0.7, 0.04],
|
|
1467
|
+
speedOverLife: [1.24, 0.9, 0.36, 0.04]
|
|
1468
|
+
},
|
|
1469
|
+
rendererEmitterSettings: {
|
|
1470
|
+
speedFactor: 0.46,
|
|
1471
|
+
lengthFactor: 1.02
|
|
1472
|
+
}
|
|
1473
|
+
}
|
|
1474
|
+
});
|
|
1475
|
+
function spark(options = {}) {
|
|
1476
|
+
return createSemanticParticleEffect(electricitySparkPreset, options);
|
|
1477
|
+
}
|
|
1478
|
+
|
|
1479
|
+
// src/lib/behaviors/particle-emitter/presets/electricity/storm.ts
|
|
1480
|
+
var electricityStormPreset = defineSemanticParticlePreset({
|
|
1481
|
+
family: "electricity",
|
|
1482
|
+
variant: "storm",
|
|
1483
|
+
description: "restless volume of crackling atmospheric charge",
|
|
1484
|
+
axes: {
|
|
1485
|
+
"continuity vs discontinuity": "mixed",
|
|
1486
|
+
"branching tendency": "high",
|
|
1487
|
+
"snap/crackle quality": "high",
|
|
1488
|
+
"seeking behavior": "medium-high",
|
|
1489
|
+
"charge buildup": "high",
|
|
1490
|
+
"rhythmic pulsing": "medium"
|
|
1491
|
+
},
|
|
1492
|
+
system: {
|
|
1493
|
+
defaults: {
|
|
1494
|
+
duration: 1.2,
|
|
1495
|
+
looping: true,
|
|
1496
|
+
color: "#38bdf8",
|
|
1497
|
+
life: [0.32, 0.82],
|
|
1498
|
+
size: [0.08, 0.2],
|
|
1499
|
+
speed: [2.2, 4.8],
|
|
1500
|
+
rotation: [-Math.PI, Math.PI],
|
|
1501
|
+
opacity: 0.94,
|
|
1502
|
+
renderMode: 1 /* StretchedBillBoard */
|
|
1503
|
+
},
|
|
1504
|
+
emission: { type: "rate", rate: 34 },
|
|
1505
|
+
shape: {
|
|
1506
|
+
type: "sphere",
|
|
1507
|
+
radius: 0.16,
|
|
1508
|
+
thickness: 0.98,
|
|
1509
|
+
speed: [1, 2]
|
|
1510
|
+
},
|
|
1511
|
+
behaviors: {
|
|
1512
|
+
colorOverLife: {
|
|
1513
|
+
colors: [
|
|
1514
|
+
["#ffffff", 0],
|
|
1515
|
+
["#67e8f9", 0.25],
|
|
1516
|
+
["#2563eb", 1]
|
|
1517
|
+
],
|
|
1518
|
+
alpha: [
|
|
1519
|
+
[0.18, 0],
|
|
1520
|
+
[0.98, 0.06],
|
|
1521
|
+
[0.5, 0.5],
|
|
1522
|
+
[0, 1]
|
|
1523
|
+
]
|
|
1524
|
+
},
|
|
1525
|
+
sizeOverLife: [0.62, 0.96, 0.84, 0.26],
|
|
1526
|
+
speedOverLife: [1.18, 0.94, 0.66, 0.32],
|
|
1527
|
+
noise: {
|
|
1528
|
+
frequency: [4.8, 8.4],
|
|
1529
|
+
power: [0.08, 0.18],
|
|
1530
|
+
positionAmount: [0.18, 0.38],
|
|
1531
|
+
rotationAmount: [0.08, 0.18]
|
|
1532
|
+
}
|
|
1533
|
+
},
|
|
1534
|
+
rendererEmitterSettings: {
|
|
1535
|
+
speedFactor: 0.66,
|
|
1536
|
+
lengthFactor: 1.18
|
|
1537
|
+
}
|
|
1538
|
+
}
|
|
1539
|
+
});
|
|
1540
|
+
function storm(options = {}) {
|
|
1541
|
+
return createSemanticParticleEffect(electricityStormPreset, options);
|
|
1542
|
+
}
|
|
1543
|
+
|
|
1544
|
+
// src/lib/behaviors/particle-emitter/presets/electricity/surge.ts
|
|
1545
|
+
var electricitySurgePreset = defineSemanticParticlePreset({
|
|
1546
|
+
family: "electricity",
|
|
1547
|
+
variant: "surge",
|
|
1548
|
+
description: "charge-rich spike that overwhelms the space",
|
|
1549
|
+
axes: {
|
|
1550
|
+
"continuity vs discontinuity": "bursting",
|
|
1551
|
+
"branching tendency": "medium",
|
|
1552
|
+
"snap/crackle quality": "high",
|
|
1553
|
+
"seeking behavior": "medium",
|
|
1554
|
+
"charge buildup": "high",
|
|
1555
|
+
"rhythmic pulsing": "medium"
|
|
1556
|
+
},
|
|
1557
|
+
system: {
|
|
1558
|
+
defaults: {
|
|
1559
|
+
duration: 0.34,
|
|
1560
|
+
color: "#38bdf8",
|
|
1561
|
+
life: [0.18, 0.36],
|
|
1562
|
+
size: [0.12, 0.26],
|
|
1563
|
+
speed: [2.8, 5.2],
|
|
1564
|
+
rotation: [-Math.PI, Math.PI],
|
|
1565
|
+
opacity: 0.98,
|
|
1566
|
+
renderMode: 1 /* StretchedBillBoard */
|
|
1567
|
+
},
|
|
1568
|
+
emission: { type: "burst", count: 24 },
|
|
1569
|
+
shape: {
|
|
1570
|
+
type: "sphere",
|
|
1571
|
+
radius: 0.08,
|
|
1572
|
+
thickness: 0.98,
|
|
1573
|
+
speed: [1.1, 2.2]
|
|
1574
|
+
},
|
|
1575
|
+
behaviors: {
|
|
1576
|
+
colorOverLife: {
|
|
1577
|
+
colors: [
|
|
1578
|
+
["#ffffff", 0],
|
|
1579
|
+
["#67e8f9", 0.22],
|
|
1580
|
+
["#0ea5e9", 1]
|
|
1581
|
+
],
|
|
1582
|
+
alpha: [
|
|
1583
|
+
[0.22, 0],
|
|
1584
|
+
[1, 0.04],
|
|
1585
|
+
[0.52, 0.44],
|
|
1586
|
+
[0, 1]
|
|
1587
|
+
]
|
|
1588
|
+
},
|
|
1589
|
+
sizeOverLife: [0.32, 0.9, 0.84, 0.08],
|
|
1590
|
+
speedOverLife: [1.22, 0.88, 0.42, 0.06],
|
|
1591
|
+
noise: {
|
|
1592
|
+
frequency: [4.5, 8],
|
|
1593
|
+
power: [0.08, 0.18],
|
|
1594
|
+
positionAmount: [0.22, 0.42],
|
|
1595
|
+
rotationAmount: [0.08, 0.16]
|
|
1596
|
+
}
|
|
1597
|
+
},
|
|
1598
|
+
rendererEmitterSettings: {
|
|
1599
|
+
speedFactor: 0.68,
|
|
1600
|
+
lengthFactor: 1.2
|
|
1601
|
+
}
|
|
1602
|
+
}
|
|
1603
|
+
});
|
|
1604
|
+
function surge(options = {}) {
|
|
1605
|
+
return createSemanticParticleEffect(electricitySurgePreset, options);
|
|
1606
|
+
}
|
|
1607
|
+
|
|
1608
|
+
// src/lib/behaviors/particle-emitter/presets/electricity/index.ts
|
|
1609
|
+
var electricityPresets = {
|
|
1610
|
+
spark,
|
|
1611
|
+
arc,
|
|
1612
|
+
surge,
|
|
1613
|
+
pulse,
|
|
1614
|
+
storm
|
|
1615
|
+
};
|
|
1616
|
+
|
|
1617
|
+
// src/lib/behaviors/particle-emitter/presets/fire/blaze.ts
|
|
1618
|
+
var fireBlazePreset = defineSemanticParticlePreset({
|
|
1619
|
+
family: "fire",
|
|
1620
|
+
variant: "blaze",
|
|
1621
|
+
description: "sustained, strong open burning",
|
|
1622
|
+
axes: {
|
|
1623
|
+
"heat feel": "intense",
|
|
1624
|
+
"hunger/spread tendency": "high",
|
|
1625
|
+
"smoke affinity": "medium",
|
|
1626
|
+
turbulence: "high",
|
|
1627
|
+
residuality: "medium"
|
|
1628
|
+
},
|
|
1629
|
+
system: {
|
|
1630
|
+
defaults: {
|
|
1631
|
+
duration: 1.8,
|
|
1632
|
+
looping: true,
|
|
1633
|
+
color: "#f97316",
|
|
1634
|
+
life: [0.55, 1.1],
|
|
1635
|
+
size: [0.32, 0.62],
|
|
1636
|
+
speed: [0.55, 1.4],
|
|
1637
|
+
rotation: [-0.24, 0.24],
|
|
1638
|
+
opacity: 0.96,
|
|
1639
|
+
renderMode: 3 /* VerticalBillBoard */
|
|
1640
|
+
},
|
|
1641
|
+
emission: { type: "rate", rate: 42 },
|
|
1642
|
+
shape: {
|
|
1643
|
+
type: "cone",
|
|
1644
|
+
radius: 0.18,
|
|
1645
|
+
thickness: 1,
|
|
1646
|
+
angle: 0.28,
|
|
1647
|
+
speed: [0.35, 0.95]
|
|
1648
|
+
},
|
|
1649
|
+
behaviors: {
|
|
1650
|
+
colorOverLife: {
|
|
1651
|
+
colors: [
|
|
1652
|
+
["#ffffff", 0],
|
|
1653
|
+
["#fde68a", 0.18],
|
|
1654
|
+
["#fb923c", 0.5],
|
|
1655
|
+
["#ef4444", 1]
|
|
1656
|
+
],
|
|
1657
|
+
alpha: [
|
|
1658
|
+
[0.18, 0],
|
|
1659
|
+
[1, 0.08],
|
|
1660
|
+
[0.56, 0.54],
|
|
1661
|
+
[0, 1]
|
|
1662
|
+
]
|
|
1663
|
+
},
|
|
1664
|
+
sizeOverLife: [0.45, 0.92, 1.14, 0.22],
|
|
1665
|
+
speedOverLife: [1.08, 0.96, 0.62, 0.16],
|
|
1666
|
+
forceOverLife: {
|
|
1667
|
+
y: [0.38, 0.72]
|
|
1668
|
+
},
|
|
1669
|
+
noise: {
|
|
1670
|
+
frequency: [4.5, 6.5],
|
|
1671
|
+
power: [0.1, 0.18],
|
|
1672
|
+
positionAmount: [0.32, 0.55],
|
|
1673
|
+
rotationAmount: [0.18, 0.3]
|
|
1674
|
+
}
|
|
1675
|
+
}
|
|
1676
|
+
}
|
|
1677
|
+
});
|
|
1678
|
+
function blaze(options = {}) {
|
|
1679
|
+
return createSemanticParticleEffect(fireBlazePreset, options);
|
|
1680
|
+
}
|
|
1681
|
+
|
|
1682
|
+
// src/lib/behaviors/particle-emitter/presets/fire/ember.ts
|
|
1683
|
+
var fireEmberPreset = defineSemanticParticlePreset({
|
|
1684
|
+
family: "fire",
|
|
1685
|
+
variant: "ember",
|
|
1686
|
+
description: "lingering, warm, residual, drifting",
|
|
1687
|
+
axes: {
|
|
1688
|
+
"heat feel": "warm",
|
|
1689
|
+
"hunger/spread tendency": "low",
|
|
1690
|
+
"smoke affinity": "medium",
|
|
1691
|
+
turbulence: "low",
|
|
1692
|
+
residuality: "high"
|
|
1693
|
+
},
|
|
1694
|
+
system: {
|
|
1695
|
+
defaults: {
|
|
1696
|
+
duration: 2.2,
|
|
1697
|
+
looping: true,
|
|
1698
|
+
color: "#fb923c",
|
|
1699
|
+
life: [1.1, 2.2],
|
|
1700
|
+
size: [0.05, 0.14],
|
|
1701
|
+
speed: [0.08, 0.32],
|
|
1702
|
+
rotation: [-0.45, 0.45],
|
|
1703
|
+
opacity: 0.9
|
|
1704
|
+
},
|
|
1705
|
+
emission: { type: "rate", rate: 8 },
|
|
1706
|
+
shape: {
|
|
1707
|
+
type: "cone",
|
|
1708
|
+
radius: 0.12,
|
|
1709
|
+
thickness: 1,
|
|
1710
|
+
angle: 0.22,
|
|
1711
|
+
speed: [0.08, 0.26]
|
|
1712
|
+
},
|
|
1713
|
+
behaviors: {
|
|
1714
|
+
colorOverLife: {
|
|
1715
|
+
colors: [
|
|
1716
|
+
["#fff7d1", 0],
|
|
1717
|
+
["#fb923c", 0.35],
|
|
1718
|
+
["#b45309", 1]
|
|
1719
|
+
],
|
|
1720
|
+
alpha: [
|
|
1721
|
+
[0.12, 0],
|
|
1722
|
+
[0.9, 0.12],
|
|
1723
|
+
[0.42, 0.7],
|
|
1724
|
+
[0, 1]
|
|
1725
|
+
]
|
|
1726
|
+
},
|
|
1727
|
+
sizeOverLife: [0.42, 0.9, 0.72, 0.18],
|
|
1728
|
+
forceOverLife: {
|
|
1729
|
+
y: [0.18, 0.42]
|
|
1730
|
+
},
|
|
1731
|
+
noise: {
|
|
1732
|
+
frequency: [1.2, 2.6],
|
|
1733
|
+
power: [0.02, 0.08],
|
|
1734
|
+
positionAmount: [0.06, 0.14],
|
|
1735
|
+
rotationAmount: [0.04, 0.1]
|
|
1736
|
+
}
|
|
1737
|
+
}
|
|
1738
|
+
}
|
|
1739
|
+
});
|
|
1740
|
+
function ember(options = {}) {
|
|
1741
|
+
return createSemanticParticleEffect(fireEmberPreset, options);
|
|
1742
|
+
}
|
|
1743
|
+
|
|
1744
|
+
// src/lib/behaviors/particle-emitter/presets/fire/flamelet.ts
|
|
1745
|
+
var fireFlameletPreset = defineSemanticParticlePreset({
|
|
1746
|
+
family: "fire",
|
|
1747
|
+
variant: "flamelet",
|
|
1748
|
+
description: "small coherent tongue of flame",
|
|
1749
|
+
axes: {
|
|
1750
|
+
"heat feel": "hot",
|
|
1751
|
+
"hunger/spread tendency": "medium",
|
|
1752
|
+
"smoke affinity": "low",
|
|
1753
|
+
turbulence: "medium",
|
|
1754
|
+
residuality: "low"
|
|
1755
|
+
},
|
|
1756
|
+
system: {
|
|
1757
|
+
defaults: {
|
|
1758
|
+
duration: 1.2,
|
|
1759
|
+
looping: true,
|
|
1760
|
+
color: "#fb923c",
|
|
1761
|
+
life: [0.48, 0.9],
|
|
1762
|
+
size: [0.2, 0.38],
|
|
1763
|
+
speed: [0.35, 0.9],
|
|
1764
|
+
rotation: [-0.18, 0.18],
|
|
1765
|
+
opacity: 0.94,
|
|
1766
|
+
renderMode: 3 /* VerticalBillBoard */
|
|
1767
|
+
},
|
|
1768
|
+
emission: { type: "rate", rate: 22 },
|
|
1769
|
+
shape: {
|
|
1770
|
+
type: "cone",
|
|
1771
|
+
radius: 0.1,
|
|
1772
|
+
thickness: 1,
|
|
1773
|
+
angle: 0.18,
|
|
1774
|
+
speed: [0.3, 0.72]
|
|
1775
|
+
},
|
|
1776
|
+
behaviors: {
|
|
1777
|
+
colorOverLife: {
|
|
1778
|
+
colors: [
|
|
1779
|
+
["#fff7d1", 0],
|
|
1780
|
+
["#fbbf24", 0.24],
|
|
1781
|
+
["#fb923c", 0.62],
|
|
1782
|
+
["#ef4444", 1]
|
|
1783
|
+
],
|
|
1784
|
+
alpha: [
|
|
1785
|
+
[0.16, 0],
|
|
1786
|
+
[0.94, 0.1],
|
|
1787
|
+
[0.48, 0.58],
|
|
1788
|
+
[0, 1]
|
|
1789
|
+
]
|
|
1790
|
+
},
|
|
1791
|
+
sizeOverLife: [0.44, 0.92, 1.08, 0.16],
|
|
1792
|
+
speedOverLife: [1.08, 0.95, 0.62, 0.18],
|
|
1793
|
+
forceOverLife: {
|
|
1794
|
+
y: [0.3, 0.55]
|
|
1795
|
+
},
|
|
1796
|
+
noise: {
|
|
1797
|
+
frequency: [3, 5],
|
|
1798
|
+
power: [0.08, 0.14],
|
|
1799
|
+
positionAmount: [0.24, 0.42],
|
|
1800
|
+
rotationAmount: [0.16, 0.24]
|
|
1801
|
+
}
|
|
1802
|
+
}
|
|
1803
|
+
}
|
|
1804
|
+
});
|
|
1805
|
+
function flamelet(options = {}) {
|
|
1806
|
+
return createSemanticParticleEffect(fireFlameletPreset, options);
|
|
1807
|
+
}
|
|
1808
|
+
|
|
1809
|
+
// src/lib/behaviors/particle-emitter/presets/fire/smolder.ts
|
|
1810
|
+
var fireSmolderPreset = defineSemanticParticlePreset({
|
|
1811
|
+
family: "fire",
|
|
1812
|
+
variant: "smolder",
|
|
1813
|
+
description: "low-oxygen, persistent, smoky heat",
|
|
1814
|
+
axes: {
|
|
1815
|
+
"heat feel": "buried-hot",
|
|
1816
|
+
"hunger/spread tendency": "low",
|
|
1817
|
+
"smoke affinity": "high",
|
|
1818
|
+
turbulence: "low",
|
|
1819
|
+
residuality: "high"
|
|
1820
|
+
},
|
|
1821
|
+
system: {
|
|
1822
|
+
defaults: {
|
|
1823
|
+
duration: 2.6,
|
|
1824
|
+
looping: true,
|
|
1825
|
+
color: "#c2410c",
|
|
1826
|
+
life: [1.4, 2.8],
|
|
1827
|
+
size: [0.28, 0.58],
|
|
1828
|
+
speed: [0.06, 0.22],
|
|
1829
|
+
rotation: [-0.35, 0.35],
|
|
1830
|
+
opacity: 0.76
|
|
1831
|
+
},
|
|
1832
|
+
emission: { type: "rate", rate: 14 },
|
|
1833
|
+
shape: {
|
|
1834
|
+
type: "cone",
|
|
1835
|
+
radius: 0.16,
|
|
1836
|
+
thickness: 1,
|
|
1837
|
+
angle: 0.12,
|
|
1838
|
+
speed: [0.04, 0.16]
|
|
1839
|
+
},
|
|
1840
|
+
behaviors: {
|
|
1841
|
+
colorOverLife: {
|
|
1842
|
+
colors: [
|
|
1843
|
+
["#fed7aa", 0],
|
|
1844
|
+
["#c2410c", 0.28],
|
|
1845
|
+
["#525252", 1]
|
|
1846
|
+
],
|
|
1847
|
+
alpha: [
|
|
1848
|
+
[0.14, 0],
|
|
1849
|
+
[0.76, 0.12],
|
|
1850
|
+
[0.4, 0.68],
|
|
1851
|
+
[0, 1]
|
|
1852
|
+
]
|
|
1853
|
+
},
|
|
1854
|
+
sizeOverLife: [0.34, 0.86, 1.08, 0.46],
|
|
1855
|
+
forceOverLife: {
|
|
1856
|
+
y: [0.08, 0.2]
|
|
1857
|
+
},
|
|
1858
|
+
noise: {
|
|
1859
|
+
frequency: [1.6, 3.1],
|
|
1860
|
+
power: [0.04, 0.12],
|
|
1861
|
+
positionAmount: [0.12, 0.26],
|
|
1862
|
+
rotationAmount: [0.06, 0.14]
|
|
1863
|
+
}
|
|
1864
|
+
}
|
|
1865
|
+
}
|
|
1866
|
+
});
|
|
1867
|
+
function smolder(options = {}) {
|
|
1868
|
+
return createSemanticParticleEffect(fireSmolderPreset, options);
|
|
1869
|
+
}
|
|
1870
|
+
|
|
1871
|
+
// src/lib/behaviors/particle-emitter/presets/fire/spark.ts
|
|
1872
|
+
var fireSparkPreset = defineSemanticParticlePreset({
|
|
1873
|
+
family: "fire",
|
|
1874
|
+
variant: "spark",
|
|
1875
|
+
description: "tiny, sudden, energetic, fleeting",
|
|
1876
|
+
axes: {
|
|
1877
|
+
"heat feel": "sharp-hot",
|
|
1878
|
+
"hunger/spread tendency": "low",
|
|
1879
|
+
"smoke affinity": "low",
|
|
1880
|
+
turbulence: "high",
|
|
1881
|
+
residuality: "low"
|
|
1882
|
+
},
|
|
1883
|
+
system: {
|
|
1884
|
+
defaults: {
|
|
1885
|
+
duration: 0.24,
|
|
1886
|
+
color: "#ffd166",
|
|
1887
|
+
life: [0.12, 0.24],
|
|
1888
|
+
size: [0.08, 0.16],
|
|
1889
|
+
speed: [1.8, 4.6],
|
|
1890
|
+
rotation: [-Math.PI, Math.PI],
|
|
1891
|
+
renderMode: 1 /* StretchedBillBoard */
|
|
1892
|
+
},
|
|
1893
|
+
emission: { type: "burst", count: 10 },
|
|
1894
|
+
shape: {
|
|
1895
|
+
type: "sphere",
|
|
1896
|
+
radius: 0.05,
|
|
1897
|
+
thickness: 0.92,
|
|
1898
|
+
speed: [0.45, 1.2]
|
|
1899
|
+
},
|
|
1900
|
+
behaviors: {
|
|
1901
|
+
colorOverLife: {
|
|
1902
|
+
colors: [
|
|
1903
|
+
["#ffffff", 0],
|
|
1904
|
+
["#fde68a", 0.2],
|
|
1905
|
+
["#fb923c", 0.62],
|
|
1906
|
+
["#ef4444", 1]
|
|
1907
|
+
],
|
|
1908
|
+
alpha: [
|
|
1909
|
+
[0.18, 0],
|
|
1910
|
+
[1, 0.08],
|
|
1911
|
+
[0.52, 0.5],
|
|
1912
|
+
[0, 1]
|
|
1913
|
+
]
|
|
1914
|
+
},
|
|
1915
|
+
sizeOverLife: [0.48, 1.08, 0.88, 0.06],
|
|
1916
|
+
speedOverLife: [1.18, 0.88, 0.42, 0.04]
|
|
1917
|
+
},
|
|
1918
|
+
rendererEmitterSettings: {
|
|
1919
|
+
speedFactor: 0.55,
|
|
1920
|
+
lengthFactor: 1.08
|
|
1921
|
+
}
|
|
1922
|
+
}
|
|
1923
|
+
});
|
|
1924
|
+
function spark2(options = {}) {
|
|
1925
|
+
return createSemanticParticleEffect(fireSparkPreset, options);
|
|
1926
|
+
}
|
|
1927
|
+
|
|
1928
|
+
// src/lib/behaviors/particle-emitter/presets/fire/index.ts
|
|
1929
|
+
var firePresets = {
|
|
1930
|
+
spark: spark2,
|
|
1931
|
+
ember,
|
|
1932
|
+
flamelet,
|
|
1933
|
+
blaze,
|
|
1934
|
+
smolder
|
|
1935
|
+
};
|
|
1936
|
+
|
|
1937
|
+
// src/lib/behaviors/particle-emitter/presets/gas/haze.ts
|
|
1938
|
+
var gasHazePreset = defineSemanticParticlePreset({
|
|
1939
|
+
family: "gas",
|
|
1940
|
+
variant: "haze",
|
|
1941
|
+
description: "broad, thin atmospheric contamination",
|
|
1942
|
+
axes: {
|
|
1943
|
+
"opacity feel": "low",
|
|
1944
|
+
toxicity: "low-medium",
|
|
1945
|
+
buoyancy: "neutral",
|
|
1946
|
+
"spread tendency": "high",
|
|
1947
|
+
thickness: "thin",
|
|
1948
|
+
"staining / contaminating character": "low"
|
|
1949
|
+
},
|
|
1950
|
+
system: {
|
|
1951
|
+
defaults: {
|
|
1952
|
+
duration: 4.4,
|
|
1953
|
+
looping: true,
|
|
1954
|
+
color: "#cbd5e1",
|
|
1955
|
+
life: [3.4, 5.4],
|
|
1956
|
+
size: [0.9, 1.7],
|
|
1957
|
+
speed: [0.02, 0.08],
|
|
1958
|
+
rotation: [-Math.PI, Math.PI],
|
|
1959
|
+
opacity: 0.18
|
|
1960
|
+
},
|
|
1961
|
+
emission: { type: "rate", rate: 10 },
|
|
1962
|
+
shape: {
|
|
1963
|
+
type: "cone",
|
|
1964
|
+
radius: 0.64,
|
|
1965
|
+
thickness: 1,
|
|
1966
|
+
angle: 0.5,
|
|
1967
|
+
speed: [0.01, 0.04]
|
|
1968
|
+
},
|
|
1969
|
+
behaviors: {
|
|
1970
|
+
colorOverLife: {
|
|
1971
|
+
colors: [
|
|
1972
|
+
["#f8fafc", 0],
|
|
1973
|
+
["#cbd5e1", 0.4],
|
|
1974
|
+
["#94a3b8", 1]
|
|
1975
|
+
],
|
|
1976
|
+
alpha: [
|
|
1977
|
+
[0.04, 0],
|
|
1978
|
+
[0.2, 0.24],
|
|
1979
|
+
[0.08, 0.88],
|
|
1980
|
+
[0, 1]
|
|
1981
|
+
]
|
|
1982
|
+
},
|
|
1983
|
+
sizeOverLife: [0.88, 1.08, 1.28, 1.42],
|
|
1984
|
+
noise: {
|
|
1985
|
+
frequency: [0.6, 1.4],
|
|
1986
|
+
power: [0.02, 0.06],
|
|
1987
|
+
positionAmount: [0.08, 0.16],
|
|
1988
|
+
rotationAmount: [0.06, 0.1]
|
|
1989
|
+
}
|
|
1990
|
+
}
|
|
1991
|
+
}
|
|
1992
|
+
});
|
|
1993
|
+
function haze(options = {}) {
|
|
1994
|
+
return createSemanticParticleEffect(gasHazePreset, options);
|
|
1995
|
+
}
|
|
1996
|
+
|
|
1997
|
+
// src/lib/behaviors/particle-emitter/presets/gas/miasma.ts
|
|
1998
|
+
var gasMiasmaPreset = defineSemanticParticlePreset({
|
|
1999
|
+
family: "gas",
|
|
2000
|
+
variant: "miasma",
|
|
2001
|
+
description: "thick, toxic, contaminating exhalation",
|
|
2002
|
+
axes: {
|
|
2003
|
+
"opacity feel": "medium",
|
|
2004
|
+
toxicity: "high",
|
|
2005
|
+
buoyancy: "low-medium",
|
|
2006
|
+
"spread tendency": "high",
|
|
2007
|
+
thickness: "sticky",
|
|
2008
|
+
"staining / contaminating character": "high"
|
|
2009
|
+
},
|
|
2010
|
+
system: {
|
|
2011
|
+
defaults: {
|
|
2012
|
+
duration: 3.8,
|
|
2013
|
+
looping: true,
|
|
2014
|
+
color: "#84cc16",
|
|
2015
|
+
life: [2.8, 4.6],
|
|
2016
|
+
size: [0.52, 1.08],
|
|
2017
|
+
speed: [0.03, 0.16],
|
|
2018
|
+
rotation: [-Math.PI, Math.PI],
|
|
2019
|
+
opacity: 0.5
|
|
2020
|
+
},
|
|
2021
|
+
emission: { type: "rate", rate: 16 },
|
|
2022
|
+
shape: {
|
|
2023
|
+
type: "cone",
|
|
2024
|
+
radius: 0.3,
|
|
2025
|
+
thickness: 1,
|
|
2026
|
+
angle: 0.3,
|
|
2027
|
+
speed: [0.02, 0.08]
|
|
2028
|
+
},
|
|
2029
|
+
behaviors: {
|
|
2030
|
+
colorOverLife: {
|
|
2031
|
+
colors: [
|
|
2032
|
+
["#ecfccb", 0],
|
|
2033
|
+
["#84cc16", 0.4],
|
|
2034
|
+
["#3f6212", 1]
|
|
2035
|
+
],
|
|
2036
|
+
alpha: [
|
|
2037
|
+
[0.08, 0],
|
|
2038
|
+
[0.58, 0.14],
|
|
2039
|
+
[0.24, 0.8],
|
|
2040
|
+
[0, 1]
|
|
2041
|
+
]
|
|
2042
|
+
},
|
|
2043
|
+
sizeOverLife: [0.4, 0.92, 1.3, 1.9],
|
|
2044
|
+
noise: {
|
|
2045
|
+
frequency: [1.8, 3.8],
|
|
2046
|
+
power: [0.08, 0.18],
|
|
2047
|
+
positionAmount: [0.16, 0.34],
|
|
2048
|
+
rotationAmount: [0.08, 0.18]
|
|
2049
|
+
}
|
|
2050
|
+
}
|
|
2051
|
+
}
|
|
2052
|
+
});
|
|
2053
|
+
function miasma(options = {}) {
|
|
2054
|
+
return createSemanticParticleEffect(gasMiasmaPreset, options);
|
|
2055
|
+
}
|
|
2056
|
+
|
|
2057
|
+
// src/lib/behaviors/particle-emitter/presets/gas/plume.ts
|
|
2058
|
+
var gasPlumePreset = defineSemanticParticlePreset({
|
|
2059
|
+
family: "gas",
|
|
2060
|
+
variant: "plume",
|
|
2061
|
+
description: "columnar rising release with strong lift",
|
|
2062
|
+
axes: {
|
|
2063
|
+
"opacity feel": "medium",
|
|
2064
|
+
toxicity: "medium",
|
|
2065
|
+
buoyancy: "very-high",
|
|
2066
|
+
"spread tendency": "medium",
|
|
2067
|
+
thickness: "medium",
|
|
2068
|
+
"staining / contaminating character": "medium"
|
|
2069
|
+
},
|
|
2070
|
+
system: {
|
|
2071
|
+
defaults: {
|
|
2072
|
+
duration: 2.8,
|
|
2073
|
+
looping: true,
|
|
2074
|
+
color: "#94a3b8",
|
|
2075
|
+
life: [1.8, 3.2],
|
|
2076
|
+
size: [0.32, 0.72],
|
|
2077
|
+
speed: [0.16, 0.52],
|
|
2078
|
+
rotation: [-Math.PI, Math.PI],
|
|
2079
|
+
opacity: 0.48
|
|
2080
|
+
},
|
|
2081
|
+
emission: { type: "rate", rate: 22 },
|
|
2082
|
+
shape: {
|
|
2083
|
+
type: "cone",
|
|
2084
|
+
radius: 0.18,
|
|
2085
|
+
thickness: 1,
|
|
2086
|
+
angle: 0.18,
|
|
2087
|
+
speed: [0.08, 0.24]
|
|
2088
|
+
},
|
|
2089
|
+
behaviors: {
|
|
2090
|
+
colorOverLife: {
|
|
2091
|
+
colors: [
|
|
2092
|
+
["#e2e8f0", 0],
|
|
2093
|
+
["#94a3b8", 0.36],
|
|
2094
|
+
["#475569", 1]
|
|
2095
|
+
],
|
|
2096
|
+
alpha: [
|
|
2097
|
+
[0.06, 0],
|
|
2098
|
+
[0.54, 0.14],
|
|
2099
|
+
[0.2, 0.84],
|
|
2100
|
+
[0, 1]
|
|
2101
|
+
]
|
|
2102
|
+
},
|
|
2103
|
+
sizeOverLife: [0.42, 0.92, 1.36, 1.84],
|
|
2104
|
+
forceOverLife: {
|
|
2105
|
+
y: [0.28, 0.6]
|
|
2106
|
+
},
|
|
2107
|
+
noise: {
|
|
2108
|
+
frequency: [1.6, 3.4],
|
|
2109
|
+
power: [0.08, 0.14],
|
|
2110
|
+
positionAmount: [0.14, 0.28],
|
|
2111
|
+
rotationAmount: [0.08, 0.16]
|
|
2112
|
+
}
|
|
2113
|
+
}
|
|
2114
|
+
}
|
|
2115
|
+
});
|
|
2116
|
+
function plume(options = {}) {
|
|
2117
|
+
return createSemanticParticleEffect(gasPlumePreset, options);
|
|
2118
|
+
}
|
|
2119
|
+
|
|
2120
|
+
// src/lib/behaviors/particle-emitter/presets/gas/smoke.ts
|
|
2121
|
+
var gasSmokePreset = defineSemanticParticlePreset({
|
|
2122
|
+
family: "gas",
|
|
2123
|
+
variant: "smoke",
|
|
2124
|
+
description: "opaque, buoyant, lingering combustion residue",
|
|
2125
|
+
axes: {
|
|
2126
|
+
"opacity feel": "medium-high",
|
|
2127
|
+
toxicity: "medium",
|
|
2128
|
+
buoyancy: "high",
|
|
2129
|
+
"spread tendency": "medium",
|
|
2130
|
+
thickness: "medium",
|
|
2131
|
+
"staining / contaminating character": "medium"
|
|
2132
|
+
},
|
|
2133
|
+
system: {
|
|
2134
|
+
defaults: {
|
|
2135
|
+
duration: 3.2,
|
|
2136
|
+
looping: true,
|
|
2137
|
+
color: "#737373",
|
|
2138
|
+
life: [2.4, 4.2],
|
|
2139
|
+
size: [0.45, 0.92],
|
|
2140
|
+
speed: [0.08, 0.3],
|
|
2141
|
+
rotation: [-Math.PI, Math.PI],
|
|
2142
|
+
opacity: 0.58
|
|
2143
|
+
},
|
|
2144
|
+
emission: { type: "rate", rate: 14 },
|
|
2145
|
+
shape: {
|
|
2146
|
+
type: "cone",
|
|
2147
|
+
radius: 0.24,
|
|
2148
|
+
thickness: 1,
|
|
2149
|
+
angle: 0.28,
|
|
2150
|
+
speed: [0.04, 0.14]
|
|
2151
|
+
},
|
|
2152
|
+
behaviors: {
|
|
2153
|
+
colorOverLife: {
|
|
2154
|
+
colors: [
|
|
2155
|
+
["#d4d4d8", 0],
|
|
2156
|
+
["#737373", 0.4],
|
|
2157
|
+
["#404040", 1]
|
|
2158
|
+
],
|
|
2159
|
+
alpha: [
|
|
2160
|
+
[0.08, 0],
|
|
2161
|
+
[0.68, 0.14],
|
|
2162
|
+
[0.24, 0.84],
|
|
2163
|
+
[0, 1]
|
|
2164
|
+
]
|
|
2165
|
+
},
|
|
2166
|
+
sizeOverLife: [0.38, 0.88, 1.4, 2.08],
|
|
2167
|
+
forceOverLife: {
|
|
2168
|
+
y: [0.12, 0.28]
|
|
2169
|
+
},
|
|
2170
|
+
noise: {
|
|
2171
|
+
frequency: [1.2, 2.8],
|
|
2172
|
+
power: [0.08, 0.16],
|
|
2173
|
+
positionAmount: [0.12, 0.26],
|
|
2174
|
+
rotationAmount: [0.08, 0.18]
|
|
2175
|
+
}
|
|
2176
|
+
}
|
|
2177
|
+
}
|
|
2178
|
+
});
|
|
2179
|
+
function smoke(options = {}) {
|
|
2180
|
+
return createSemanticParticleEffect(gasSmokePreset, options);
|
|
2181
|
+
}
|
|
2182
|
+
|
|
2183
|
+
// src/lib/behaviors/particle-emitter/presets/gas/vapor.ts
|
|
2184
|
+
var gasVaporPreset = defineSemanticParticlePreset({
|
|
2185
|
+
family: "gas",
|
|
2186
|
+
variant: "vapor",
|
|
2187
|
+
description: "visible gaseous release with light buoyancy",
|
|
2188
|
+
axes: {
|
|
2189
|
+
"opacity feel": "light",
|
|
2190
|
+
toxicity: "neutral",
|
|
2191
|
+
buoyancy: "high",
|
|
2192
|
+
"spread tendency": "medium",
|
|
2193
|
+
thickness: "thin",
|
|
2194
|
+
"staining / contaminating character": "low"
|
|
2195
|
+
},
|
|
2196
|
+
system: {
|
|
2197
|
+
defaults: {
|
|
2198
|
+
duration: 3,
|
|
2199
|
+
looping: true,
|
|
2200
|
+
color: "#e2e8f0",
|
|
2201
|
+
life: [2.2, 3.6],
|
|
2202
|
+
size: [0.38, 0.78],
|
|
2203
|
+
speed: [0.04, 0.18],
|
|
2204
|
+
rotation: [-Math.PI, Math.PI],
|
|
2205
|
+
opacity: 0.28
|
|
2206
|
+
},
|
|
2207
|
+
emission: { type: "rate", rate: 18 },
|
|
2208
|
+
shape: {
|
|
2209
|
+
type: "cone",
|
|
2210
|
+
radius: 0.28,
|
|
2211
|
+
thickness: 1,
|
|
2212
|
+
angle: 0.36,
|
|
2213
|
+
speed: [0.02, 0.08]
|
|
2214
|
+
},
|
|
2215
|
+
behaviors: {
|
|
2216
|
+
colorOverLife: {
|
|
2217
|
+
colors: [
|
|
2218
|
+
["#f8fafc", 0],
|
|
2219
|
+
["#e2e8f0", 0.36],
|
|
2220
|
+
["#cbd5e1", 1]
|
|
2221
|
+
],
|
|
2222
|
+
alpha: [
|
|
2223
|
+
[0.06, 0],
|
|
2224
|
+
[0.34, 0.22],
|
|
2225
|
+
[0.12, 0.84],
|
|
2226
|
+
[0, 1]
|
|
2227
|
+
]
|
|
2228
|
+
},
|
|
2229
|
+
sizeOverLife: [0.42, 0.9, 1.38, 1.98],
|
|
2230
|
+
forceOverLife: {
|
|
2231
|
+
y: [0.06, 0.18]
|
|
2232
|
+
},
|
|
2233
|
+
noise: {
|
|
2234
|
+
frequency: [1, 2],
|
|
2235
|
+
power: [0.04, 0.08],
|
|
2236
|
+
positionAmount: [0.1, 0.2],
|
|
2237
|
+
rotationAmount: [0.08, 0.14]
|
|
2238
|
+
}
|
|
2239
|
+
}
|
|
2240
|
+
}
|
|
2241
|
+
});
|
|
2242
|
+
function vapor(options = {}) {
|
|
2243
|
+
return createSemanticParticleEffect(gasVaporPreset, options);
|
|
2244
|
+
}
|
|
2245
|
+
|
|
2246
|
+
// src/lib/behaviors/particle-emitter/presets/gas/index.ts
|
|
2247
|
+
var gasPresets = {
|
|
2248
|
+
vapor,
|
|
2249
|
+
smoke,
|
|
2250
|
+
haze,
|
|
2251
|
+
plume,
|
|
2252
|
+
miasma
|
|
2253
|
+
};
|
|
2254
|
+
|
|
2255
|
+
// src/lib/behaviors/particle-emitter/presets/magic/arcane.ts
|
|
2256
|
+
function arcane(options = {}) {
|
|
2257
|
+
return createMagicModifier("arcane", options);
|
|
2258
|
+
}
|
|
2259
|
+
|
|
2260
|
+
// src/lib/behaviors/particle-emitter/presets/magic/corrupted.ts
|
|
2261
|
+
function corrupted(options = {}) {
|
|
2262
|
+
return createMagicModifier("corrupted", options);
|
|
2263
|
+
}
|
|
2264
|
+
|
|
2265
|
+
// src/lib/behaviors/particle-emitter/presets/magic/holy.ts
|
|
2266
|
+
function holy(options = {}) {
|
|
2267
|
+
return createMagicModifier("holy", options);
|
|
2268
|
+
}
|
|
2269
|
+
|
|
2270
|
+
// src/lib/behaviors/particle-emitter/presets/magic/nature.ts
|
|
2271
|
+
function nature(options = {}) {
|
|
2272
|
+
return createMagicModifier("nature", options);
|
|
2273
|
+
}
|
|
2274
|
+
|
|
2275
|
+
// src/lib/behaviors/particle-emitter/presets/magic/psychic.ts
|
|
2276
|
+
function psychic(options = {}) {
|
|
2277
|
+
return createMagicModifier("psychic", options);
|
|
2278
|
+
}
|
|
2279
|
+
|
|
2280
|
+
// src/lib/behaviors/particle-emitter/presets/magic/void.ts
|
|
2281
|
+
function voidMagic(options = {}) {
|
|
2282
|
+
return createMagicModifier("void", options);
|
|
2283
|
+
}
|
|
2284
|
+
|
|
2285
|
+
// src/lib/behaviors/particle-emitter/presets/magic/index.ts
|
|
2286
|
+
var magicPresets = {
|
|
2287
|
+
arcane,
|
|
2288
|
+
holy,
|
|
2289
|
+
corrupted,
|
|
2290
|
+
nature,
|
|
2291
|
+
void: voidMagic,
|
|
2292
|
+
psychic
|
|
2293
|
+
};
|
|
2294
|
+
|
|
2295
|
+
// src/lib/behaviors/particle-emitter/presets/water/drizzle.ts
|
|
2296
|
+
var waterDrizzlePreset = defineSemanticParticlePreset({
|
|
2297
|
+
family: "water",
|
|
2298
|
+
variant: "drizzle",
|
|
2299
|
+
description: "soft, continuous, light fall",
|
|
2300
|
+
axes: {
|
|
2301
|
+
pressure: "low",
|
|
2302
|
+
"surface tension feel": "light",
|
|
2303
|
+
aeration: "low",
|
|
2304
|
+
coherence: "discrete",
|
|
2305
|
+
"gravitational obedience": "very-high"
|
|
2306
|
+
},
|
|
2307
|
+
system: {
|
|
2308
|
+
defaults: {
|
|
2309
|
+
duration: 1.4,
|
|
2310
|
+
looping: true,
|
|
2311
|
+
color: "#e0f2fe",
|
|
2312
|
+
life: [0.6, 1.05],
|
|
2313
|
+
size: [0.05, 0.1],
|
|
2314
|
+
speed: [2.8, 4.4],
|
|
2315
|
+
opacity: 0.62,
|
|
2316
|
+
renderMode: 1 /* StretchedBillBoard */
|
|
2317
|
+
},
|
|
2318
|
+
emission: { type: "rate", rate: 26 },
|
|
2319
|
+
shape: {
|
|
2320
|
+
type: "cone",
|
|
2321
|
+
radius: 0.46,
|
|
2322
|
+
thickness: 1,
|
|
2323
|
+
angle: 0.04,
|
|
2324
|
+
speed: [1.8, 2.6]
|
|
2325
|
+
},
|
|
2326
|
+
behaviors: {
|
|
2327
|
+
colorOverLife: {
|
|
2328
|
+
colors: [
|
|
2329
|
+
["#f8fafc", 0],
|
|
2330
|
+
["#e0f2fe", 0.45],
|
|
2331
|
+
["#7dd3fc", 1]
|
|
2332
|
+
],
|
|
2333
|
+
alpha: [
|
|
2334
|
+
[0.12, 0],
|
|
2335
|
+
[0.78, 0.08],
|
|
2336
|
+
[0.52, 0.58],
|
|
2337
|
+
[0, 1]
|
|
2338
|
+
]
|
|
2339
|
+
},
|
|
2340
|
+
speedOverLife: [1.02, 1, 0.94, 0.88],
|
|
2341
|
+
forceOverLife: {
|
|
2342
|
+
y: [-8.2, -6.4]
|
|
2343
|
+
}
|
|
2344
|
+
},
|
|
2345
|
+
rendererEmitterSettings: {
|
|
2346
|
+
speedFactor: 0.42,
|
|
2347
|
+
lengthFactor: 1.24
|
|
2348
|
+
}
|
|
2349
|
+
}
|
|
2350
|
+
});
|
|
2351
|
+
function drizzle(options = {}) {
|
|
2352
|
+
return createSemanticParticleEffect(waterDrizzlePreset, options);
|
|
2353
|
+
}
|
|
2354
|
+
|
|
2355
|
+
// src/lib/behaviors/particle-emitter/presets/water/mist.ts
|
|
2356
|
+
var waterMistPreset = defineSemanticParticlePreset({
|
|
2357
|
+
family: "water",
|
|
2358
|
+
variant: "mist",
|
|
2359
|
+
description: "diffuse suspended moisture",
|
|
2360
|
+
axes: {
|
|
2361
|
+
pressure: "low",
|
|
2362
|
+
"surface tension feel": "soft",
|
|
2363
|
+
aeration: "low",
|
|
2364
|
+
coherence: "diffuse",
|
|
2365
|
+
"gravitational obedience": "low"
|
|
2366
|
+
},
|
|
2367
|
+
system: {
|
|
2368
|
+
defaults: {
|
|
2369
|
+
duration: 3.2,
|
|
2370
|
+
looping: true,
|
|
2371
|
+
color: "#dbeafe",
|
|
2372
|
+
life: [2.4, 3.8],
|
|
2373
|
+
size: [0.4, 0.82],
|
|
2374
|
+
speed: [0.05, 0.2],
|
|
2375
|
+
rotation: [-Math.PI, Math.PI],
|
|
2376
|
+
opacity: 0.36
|
|
2377
|
+
},
|
|
2378
|
+
emission: { type: "rate", rate: 16 },
|
|
2379
|
+
shape: {
|
|
2380
|
+
type: "cone",
|
|
2381
|
+
radius: 0.32,
|
|
2382
|
+
thickness: 1,
|
|
2383
|
+
angle: 0.42,
|
|
2384
|
+
speed: [0.02, 0.08]
|
|
2385
|
+
},
|
|
2386
|
+
behaviors: {
|
|
2387
|
+
colorOverLife: {
|
|
2388
|
+
colors: [
|
|
2389
|
+
["#f8fafc", 0],
|
|
2390
|
+
["#dbeafe", 0.35],
|
|
2391
|
+
["#bfdbfe", 1]
|
|
2392
|
+
],
|
|
2393
|
+
alpha: [
|
|
2394
|
+
[0.08, 0],
|
|
2395
|
+
[0.44, 0.2],
|
|
2396
|
+
[0.18, 0.82],
|
|
2397
|
+
[0, 1]
|
|
2398
|
+
]
|
|
2399
|
+
},
|
|
2400
|
+
sizeOverLife: [0.38, 0.86, 1.42, 2.02],
|
|
2401
|
+
forceOverLife: {
|
|
2402
|
+
y: [0.02, 0.12]
|
|
2403
|
+
},
|
|
2404
|
+
noise: {
|
|
2405
|
+
frequency: [0.8, 1.8],
|
|
2406
|
+
power: [0.04, 0.1],
|
|
2407
|
+
positionAmount: [0.1, 0.18],
|
|
2408
|
+
rotationAmount: [0.08, 0.14]
|
|
2409
|
+
}
|
|
2410
|
+
}
|
|
2411
|
+
}
|
|
2412
|
+
});
|
|
2413
|
+
function mist(options = {}) {
|
|
2414
|
+
return createSemanticParticleEffect(waterMistPreset, options);
|
|
2415
|
+
}
|
|
2416
|
+
|
|
2417
|
+
// src/lib/behaviors/particle-emitter/presets/water/splash.ts
|
|
2418
|
+
var waterSplashPreset = defineSemanticParticlePreset({
|
|
2419
|
+
family: "water",
|
|
2420
|
+
variant: "splash",
|
|
2421
|
+
description: "sudden impact-driven burst",
|
|
2422
|
+
axes: {
|
|
2423
|
+
pressure: "impact-driven",
|
|
2424
|
+
"surface tension feel": "beaded",
|
|
2425
|
+
aeration: "medium",
|
|
2426
|
+
coherence: "shattering",
|
|
2427
|
+
"gravitational obedience": "high"
|
|
2428
|
+
},
|
|
2429
|
+
system: {
|
|
2430
|
+
defaults: {
|
|
2431
|
+
duration: 0.34,
|
|
2432
|
+
color: "#7dd3fc",
|
|
2433
|
+
life: [0.26, 0.55],
|
|
2434
|
+
size: [0.1, 0.22],
|
|
2435
|
+
speed: [1.4, 3.1],
|
|
2436
|
+
rotation: [-Math.PI, Math.PI],
|
|
2437
|
+
opacity: 0.82,
|
|
2438
|
+
renderMode: 1 /* StretchedBillBoard */
|
|
2439
|
+
},
|
|
2440
|
+
emission: { type: "burst", count: 18 },
|
|
2441
|
+
shape: {
|
|
2442
|
+
type: "sphere",
|
|
2443
|
+
radius: 0.08,
|
|
2444
|
+
thickness: 0.96,
|
|
2445
|
+
speed: [0.7, 1.4]
|
|
2446
|
+
},
|
|
2447
|
+
behaviors: {
|
|
2448
|
+
colorOverLife: {
|
|
2449
|
+
colors: [
|
|
2450
|
+
["#ffffff", 0],
|
|
2451
|
+
["#bae6fd", 0.4],
|
|
2452
|
+
["#38bdf8", 1]
|
|
2453
|
+
],
|
|
2454
|
+
alpha: [
|
|
2455
|
+
[0.18, 0],
|
|
2456
|
+
[0.88, 0.08],
|
|
2457
|
+
[0.42, 0.54],
|
|
2458
|
+
[0, 1]
|
|
2459
|
+
]
|
|
2460
|
+
},
|
|
2461
|
+
sizeOverLife: [0.32, 0.86, 0.92, 0.08],
|
|
2462
|
+
speedOverLife: [1.12, 0.88, 0.46, 0.08],
|
|
2463
|
+
forceOverLife: {
|
|
2464
|
+
y: [-4.4, -2.6]
|
|
2465
|
+
}
|
|
2466
|
+
},
|
|
2467
|
+
rendererEmitterSettings: {
|
|
2468
|
+
speedFactor: 0.36,
|
|
2469
|
+
lengthFactor: 0.88
|
|
2470
|
+
}
|
|
2471
|
+
}
|
|
2472
|
+
});
|
|
2473
|
+
function splash(options = {}) {
|
|
2474
|
+
return createSemanticParticleEffect(waterSplashPreset, options);
|
|
2475
|
+
}
|
|
2476
|
+
|
|
2477
|
+
// src/lib/behaviors/particle-emitter/presets/water/spray.ts
|
|
2478
|
+
var waterSprayPreset = defineSemanticParticlePreset({
|
|
2479
|
+
family: "water",
|
|
2480
|
+
variant: "spray",
|
|
2481
|
+
description: "fine ejected droplets",
|
|
2482
|
+
axes: {
|
|
2483
|
+
pressure: "medium-high",
|
|
2484
|
+
"surface tension feel": "light",
|
|
2485
|
+
aeration: "medium",
|
|
2486
|
+
coherence: "broken",
|
|
2487
|
+
"gravitational obedience": "high"
|
|
2488
|
+
},
|
|
2489
|
+
system: {
|
|
2490
|
+
defaults: {
|
|
2491
|
+
duration: 1,
|
|
2492
|
+
looping: true,
|
|
2493
|
+
color: "#93c5fd",
|
|
2494
|
+
life: [0.45, 0.9],
|
|
2495
|
+
size: [0.08, 0.16],
|
|
2496
|
+
speed: [1.1, 2.3],
|
|
2497
|
+
rotation: [-Math.PI, Math.PI],
|
|
2498
|
+
opacity: 0.72,
|
|
2499
|
+
renderMode: 1 /* StretchedBillBoard */
|
|
2500
|
+
},
|
|
2501
|
+
emission: { type: "rate", rate: 38 },
|
|
2502
|
+
shape: {
|
|
2503
|
+
type: "cone",
|
|
2504
|
+
radius: 0.12,
|
|
2505
|
+
thickness: 1,
|
|
2506
|
+
angle: 0.24,
|
|
2507
|
+
speed: [0.85, 1.8]
|
|
2508
|
+
},
|
|
2509
|
+
behaviors: {
|
|
2510
|
+
colorOverLife: {
|
|
2511
|
+
colors: [
|
|
2512
|
+
["#eff6ff", 0],
|
|
2513
|
+
["#93c5fd", 0.45],
|
|
2514
|
+
["#60a5fa", 1]
|
|
2515
|
+
],
|
|
2516
|
+
alpha: [
|
|
2517
|
+
[0.16, 0],
|
|
2518
|
+
[0.82, 0.08],
|
|
2519
|
+
[0.52, 0.58],
|
|
2520
|
+
[0, 1]
|
|
2521
|
+
]
|
|
2522
|
+
},
|
|
2523
|
+
sizeOverLife: [0.72, 0.96, 0.82, 0.28],
|
|
2524
|
+
speedOverLife: [1.04, 0.92, 0.68, 0.38],
|
|
2525
|
+
forceOverLife: {
|
|
2526
|
+
y: [-5.8, -3.8]
|
|
2527
|
+
},
|
|
2528
|
+
noise: {
|
|
2529
|
+
frequency: [1.2, 2.2],
|
|
2530
|
+
power: [0.04, 0.08],
|
|
2531
|
+
positionAmount: [0.08, 0.16],
|
|
2532
|
+
rotationAmount: [0.04, 0.08]
|
|
2533
|
+
}
|
|
2534
|
+
},
|
|
2535
|
+
rendererEmitterSettings: {
|
|
2536
|
+
speedFactor: 0.5,
|
|
2537
|
+
lengthFactor: 0.95
|
|
2538
|
+
}
|
|
2539
|
+
}
|
|
2540
|
+
});
|
|
2541
|
+
function spray(options = {}) {
|
|
2542
|
+
return createSemanticParticleEffect(waterSprayPreset, options);
|
|
2543
|
+
}
|
|
2544
|
+
|
|
2545
|
+
// src/lib/behaviors/particle-emitter/presets/water/torrent.ts
|
|
2546
|
+
var waterTorrentPreset = defineSemanticParticlePreset({
|
|
2547
|
+
family: "water",
|
|
2548
|
+
variant: "torrent",
|
|
2549
|
+
description: "strong, forceful, dense flow",
|
|
2550
|
+
axes: {
|
|
2551
|
+
pressure: "high",
|
|
2552
|
+
"surface tension feel": "driven",
|
|
2553
|
+
aeration: "medium",
|
|
2554
|
+
coherence: "strong",
|
|
2555
|
+
"gravitational obedience": "high"
|
|
2556
|
+
},
|
|
2557
|
+
system: {
|
|
2558
|
+
defaults: {
|
|
2559
|
+
duration: 1,
|
|
2560
|
+
looping: true,
|
|
2561
|
+
color: "#38bdf8",
|
|
2562
|
+
life: [0.35, 0.75],
|
|
2563
|
+
size: [0.1, 0.22],
|
|
2564
|
+
speed: [2.6, 4.9],
|
|
2565
|
+
rotation: [-0.3, 0.3],
|
|
2566
|
+
opacity: 0.84,
|
|
2567
|
+
renderMode: 1 /* StretchedBillBoard */
|
|
2568
|
+
},
|
|
2569
|
+
emission: { type: "rate", rate: 60 },
|
|
2570
|
+
shape: {
|
|
2571
|
+
type: "cone",
|
|
2572
|
+
radius: 0.18,
|
|
2573
|
+
thickness: 1,
|
|
2574
|
+
angle: 0.12,
|
|
2575
|
+
speed: [1.8, 3.1]
|
|
2576
|
+
},
|
|
2577
|
+
behaviors: {
|
|
2578
|
+
colorOverLife: {
|
|
2579
|
+
colors: [
|
|
2580
|
+
["#f0f9ff", 0],
|
|
2581
|
+
["#7dd3fc", 0.35],
|
|
2582
|
+
["#0ea5e9", 1]
|
|
2583
|
+
],
|
|
2584
|
+
alpha: [
|
|
2585
|
+
[0.18, 0],
|
|
2586
|
+
[0.92, 0.08],
|
|
2587
|
+
[0.56, 0.52],
|
|
2588
|
+
[0, 1]
|
|
2589
|
+
]
|
|
2590
|
+
},
|
|
2591
|
+
sizeOverLife: [0.72, 0.94, 0.84, 0.28],
|
|
2592
|
+
speedOverLife: [1.04, 0.92, 0.68, 0.34],
|
|
2593
|
+
forceOverLife: {
|
|
2594
|
+
y: [-6.8, -4.8]
|
|
2595
|
+
},
|
|
2596
|
+
noise: {
|
|
2597
|
+
frequency: [1.4, 2.6],
|
|
2598
|
+
power: [0.04, 0.09],
|
|
2599
|
+
positionAmount: [0.08, 0.14],
|
|
2600
|
+
rotationAmount: [0.06, 0.1]
|
|
2601
|
+
}
|
|
2602
|
+
},
|
|
2603
|
+
rendererEmitterSettings: {
|
|
2604
|
+
speedFactor: 0.56,
|
|
2605
|
+
lengthFactor: 1.08
|
|
2606
|
+
}
|
|
2607
|
+
}
|
|
2608
|
+
});
|
|
2609
|
+
function torrent(options = {}) {
|
|
2610
|
+
return createSemanticParticleEffect(waterTorrentPreset, options);
|
|
2611
|
+
}
|
|
2612
|
+
|
|
2613
|
+
// src/lib/behaviors/particle-emitter/presets/water/index.ts
|
|
2614
|
+
var waterPresets = {
|
|
2615
|
+
mist,
|
|
2616
|
+
spray,
|
|
2617
|
+
splash,
|
|
2618
|
+
drizzle,
|
|
2619
|
+
torrent
|
|
2620
|
+
};
|
|
2621
|
+
|
|
2622
|
+
export {
|
|
2623
|
+
Particles,
|
|
2624
|
+
particleEffect,
|
|
2625
|
+
electricityPresets,
|
|
2626
|
+
firePresets,
|
|
2627
|
+
gasPresets,
|
|
2628
|
+
magicPresets,
|
|
2629
|
+
waterPresets
|
|
2630
|
+
};
|
|
2631
|
+
//# sourceMappingURL=chunk-7JJEIADR.js.map
|