r3f-vfx 0.1.9 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.ts +25 -233
- package/dist/index.js +451 -1410
- package/package.json +3 -3
package/dist/index.js
CHANGED
|
@@ -34,14 +34,13 @@ var __objRest = (source, exclude) => {
|
|
|
34
34
|
import {
|
|
35
35
|
forwardRef,
|
|
36
36
|
useImperativeHandle,
|
|
37
|
-
useEffect
|
|
38
|
-
useRef
|
|
39
|
-
useMemo
|
|
37
|
+
useEffect,
|
|
38
|
+
useRef,
|
|
39
|
+
useMemo,
|
|
40
40
|
useCallback,
|
|
41
|
-
useState
|
|
41
|
+
useState
|
|
42
42
|
} from "react";
|
|
43
43
|
import { useFrame, useThree } from "@react-three/fiber";
|
|
44
|
-
import * as THREE from "three/webgpu";
|
|
45
44
|
|
|
46
45
|
// src/react-store.ts
|
|
47
46
|
import { coreStore } from "core-vfx";
|
|
@@ -56,163 +55,45 @@ var useVFXStore = Object.assign(useVFXStoreImpl, {
|
|
|
56
55
|
getInitialState: coreStore.getInitialState
|
|
57
56
|
});
|
|
58
57
|
|
|
59
|
-
// src/useCurveTextureAsync.ts
|
|
60
|
-
import { useRef, useEffect, useMemo, useState } from "react";
|
|
61
|
-
import {
|
|
62
|
-
createDefaultCurveTexture,
|
|
63
|
-
createCombinedCurveTexture,
|
|
64
|
-
loadCurveTextureFromPath,
|
|
65
|
-
CurveChannel
|
|
66
|
-
} from "core-vfx";
|
|
67
|
-
var useCurveTextureAsync = (sizeCurve, opacityCurve, velocityCurve, rotationSpeedCurve, curveTexturePath = null) => {
|
|
68
|
-
const hasAnyCurve = sizeCurve || opacityCurve || velocityCurve || rotationSpeedCurve;
|
|
69
|
-
const texture = useMemo(() => {
|
|
70
|
-
if (!curveTexturePath && hasAnyCurve) {
|
|
71
|
-
return createCombinedCurveTexture(
|
|
72
|
-
sizeCurve,
|
|
73
|
-
opacityCurve,
|
|
74
|
-
velocityCurve,
|
|
75
|
-
rotationSpeedCurve
|
|
76
|
-
);
|
|
77
|
-
}
|
|
78
|
-
return createDefaultCurveTexture();
|
|
79
|
-
}, [
|
|
80
|
-
sizeCurve,
|
|
81
|
-
opacityCurve,
|
|
82
|
-
velocityCurve,
|
|
83
|
-
rotationSpeedCurve,
|
|
84
|
-
curveTexturePath,
|
|
85
|
-
hasAnyCurve
|
|
86
|
-
]);
|
|
87
|
-
const [loadedTexture, setLoadedTexture] = useState(
|
|
88
|
-
null
|
|
89
|
-
);
|
|
90
|
-
const [loadedChannels, setLoadedChannels] = useState(0);
|
|
91
|
-
useEffect(() => {
|
|
92
|
-
if (!curveTexturePath) {
|
|
93
|
-
setLoadedTexture(null);
|
|
94
|
-
setLoadedChannels(0);
|
|
95
|
-
return;
|
|
96
|
-
}
|
|
97
|
-
let cancelled = false;
|
|
98
|
-
loadCurveTextureFromPath(curveTexturePath).then((result) => {
|
|
99
|
-
if (!cancelled) {
|
|
100
|
-
setLoadedTexture(result.texture);
|
|
101
|
-
setLoadedChannels(result.activeChannels);
|
|
102
|
-
} else {
|
|
103
|
-
result.texture.dispose();
|
|
104
|
-
}
|
|
105
|
-
}).catch((err) => {
|
|
106
|
-
console.warn(
|
|
107
|
-
`Failed to load curve texture: ${curveTexturePath}, falling back to baking`,
|
|
108
|
-
err
|
|
109
|
-
);
|
|
110
|
-
if (!cancelled && hasAnyCurve) {
|
|
111
|
-
setLoadedTexture(
|
|
112
|
-
createCombinedCurveTexture(
|
|
113
|
-
sizeCurve,
|
|
114
|
-
opacityCurve,
|
|
115
|
-
velocityCurve,
|
|
116
|
-
rotationSpeedCurve
|
|
117
|
-
)
|
|
118
|
-
);
|
|
119
|
-
let mask = 0;
|
|
120
|
-
if (sizeCurve) mask |= CurveChannel.SIZE;
|
|
121
|
-
if (opacityCurve) mask |= CurveChannel.OPACITY;
|
|
122
|
-
if (velocityCurve) mask |= CurveChannel.VELOCITY;
|
|
123
|
-
if (rotationSpeedCurve) mask |= CurveChannel.ROTATION_SPEED;
|
|
124
|
-
setLoadedChannels(mask);
|
|
125
|
-
}
|
|
126
|
-
});
|
|
127
|
-
return () => {
|
|
128
|
-
cancelled = true;
|
|
129
|
-
};
|
|
130
|
-
}, [
|
|
131
|
-
curveTexturePath,
|
|
132
|
-
sizeCurve,
|
|
133
|
-
opacityCurve,
|
|
134
|
-
velocityCurve,
|
|
135
|
-
rotationSpeedCurve,
|
|
136
|
-
hasAnyCurve
|
|
137
|
-
]);
|
|
138
|
-
const activeTexture = loadedTexture != null ? loadedTexture : texture;
|
|
139
|
-
const sizeEnabled = loadedTexture ? !!(loadedChannels & CurveChannel.SIZE) : !!sizeCurve;
|
|
140
|
-
const opacityEnabled = loadedTexture ? !!(loadedChannels & CurveChannel.OPACITY) : !!opacityCurve;
|
|
141
|
-
const velocityEnabled = loadedTexture ? !!(loadedChannels & CurveChannel.VELOCITY) : !!velocityCurve;
|
|
142
|
-
const rotationSpeedEnabled = loadedTexture ? !!(loadedChannels & CurveChannel.ROTATION_SPEED) : !!rotationSpeedCurve;
|
|
143
|
-
const prevTextureRef = useRef(null);
|
|
144
|
-
useEffect(() => {
|
|
145
|
-
const prev = prevTextureRef.current;
|
|
146
|
-
if (prev && prev !== activeTexture) {
|
|
147
|
-
prev.dispose();
|
|
148
|
-
}
|
|
149
|
-
prevTextureRef.current = activeTexture;
|
|
150
|
-
}, [activeTexture]);
|
|
151
|
-
useEffect(() => {
|
|
152
|
-
return () => {
|
|
153
|
-
var _a;
|
|
154
|
-
(_a = prevTextureRef.current) == null ? void 0 : _a.dispose();
|
|
155
|
-
prevTextureRef.current = null;
|
|
156
|
-
};
|
|
157
|
-
}, []);
|
|
158
|
-
return {
|
|
159
|
-
texture: activeTexture,
|
|
160
|
-
sizeEnabled,
|
|
161
|
-
opacityEnabled,
|
|
162
|
-
velocityEnabled,
|
|
163
|
-
rotationSpeedEnabled
|
|
164
|
-
};
|
|
165
|
-
};
|
|
166
|
-
|
|
167
58
|
// src/VFXParticles.tsx
|
|
168
|
-
import { uniform, instancedArray } from "three/tsl";
|
|
169
59
|
import {
|
|
170
60
|
Appearance,
|
|
171
61
|
Blending,
|
|
172
62
|
EmitterShape,
|
|
173
63
|
Lighting,
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
createInitCompute,
|
|
182
|
-
createSpawnCompute,
|
|
183
|
-
createUpdateCompute,
|
|
184
|
-
createParticleMaterial
|
|
64
|
+
VFXParticleSystem,
|
|
65
|
+
isWebGPUBackend,
|
|
66
|
+
isNonDefaultRotation,
|
|
67
|
+
normalizeProps,
|
|
68
|
+
updateUniforms,
|
|
69
|
+
updateUniformsPartial,
|
|
70
|
+
resolveFeatures
|
|
185
71
|
} from "core-vfx";
|
|
186
72
|
import {
|
|
187
73
|
Appearance as Appearance2,
|
|
188
74
|
Blending as Blending2,
|
|
189
75
|
EmitterShape as EmitterShape2,
|
|
190
|
-
AttractorType
|
|
191
|
-
Easing
|
|
76
|
+
AttractorType,
|
|
77
|
+
Easing,
|
|
192
78
|
Lighting as Lighting2,
|
|
193
79
|
bakeCurveToArray,
|
|
194
|
-
createCombinedCurveTexture
|
|
80
|
+
createCombinedCurveTexture,
|
|
195
81
|
buildCurveTextureBin,
|
|
196
|
-
CurveChannel
|
|
82
|
+
CurveChannel
|
|
197
83
|
} from "core-vfx";
|
|
198
|
-
import { jsx } from "react/jsx-runtime";
|
|
199
|
-
var
|
|
200
|
-
function
|
|
84
|
+
import { Fragment, jsx } from "react/jsx-runtime";
|
|
85
|
+
var VFXParticlesImpl = forwardRef(
|
|
86
|
+
function VFXParticlesImpl2({
|
|
201
87
|
name,
|
|
202
|
-
// Optional name for registering with useVFXStore (enables VFXEmitter linking)
|
|
203
88
|
maxParticles = 1e4,
|
|
204
89
|
size = [0.1, 0.3],
|
|
205
90
|
colorStart = ["#ffffff"],
|
|
206
91
|
colorEnd = null,
|
|
207
|
-
// If null, uses colorStart (no color transition)
|
|
208
92
|
fadeSize = [1, 0],
|
|
209
93
|
fadeSizeCurve = null,
|
|
210
|
-
// Curve data { points: [...] } - controls fadeSize over lifetime (overrides fadeSize if set)
|
|
211
94
|
fadeOpacity = [1, 0],
|
|
212
95
|
fadeOpacityCurve = null,
|
|
213
|
-
// Curve data { points: [...] } - controls fadeOpacity over lifetime (overrides fadeOpacity if set)
|
|
214
96
|
velocityCurve = null,
|
|
215
|
-
// Curve data { points: [...] } - controls velocity/speed over lifetime (overrides friction if set)
|
|
216
97
|
gravity = [0, 0, 0],
|
|
217
98
|
lifetime = [1, 2],
|
|
218
99
|
direction = [
|
|
@@ -220,144 +101,81 @@ var VFXParticles = forwardRef(
|
|
|
220
101
|
[0, 1],
|
|
221
102
|
[-1, 1]
|
|
222
103
|
],
|
|
223
|
-
// [[minX, maxX], [minY, maxY], [minZ, maxZ]] or [min, max] for all axes
|
|
224
104
|
startPosition = [
|
|
225
105
|
[0, 0],
|
|
226
106
|
[0, 0],
|
|
227
107
|
[0, 0]
|
|
228
108
|
],
|
|
229
|
-
// [[minX, maxX], [minY, maxY], [minZ, maxZ]] offset from spawn position
|
|
230
109
|
speed = [0.1, 0.1],
|
|
231
110
|
friction = { intensity: 0, easing: "linear" },
|
|
232
|
-
// { intensity: [start, end] or single value, easing: string }
|
|
233
|
-
// intensity: 1 = max friction (almost stopped), 0 = no friction (normal), negative = boost/acceleration
|
|
234
111
|
appearance = Appearance.GRADIENT,
|
|
235
112
|
alphaMap = null,
|
|
236
113
|
flipbook = null,
|
|
237
|
-
// { rows: 4, columns: 8 }
|
|
238
114
|
rotation = [0, 0],
|
|
239
|
-
// [min, max] in radians
|
|
240
115
|
rotationSpeed = [0, 0],
|
|
241
|
-
// [min, max] rotation speed in radians/second
|
|
242
116
|
rotationSpeedCurve = null,
|
|
243
|
-
// Curve data { points: [...] } - controls rotation speed over lifetime
|
|
244
117
|
geometry = null,
|
|
245
|
-
// Custom geometry (e.g. new THREE.SphereGeometry(0.5, 8, 8))
|
|
246
118
|
orientToDirection = false,
|
|
247
|
-
// Rotate geometry to face velocity direction (geometry mode only)
|
|
248
119
|
orientAxis = "z",
|
|
249
|
-
// Which local axis aligns with velocity: "x", "y", "z", "-x", "-y", "-z"
|
|
250
120
|
stretchBySpeed = null,
|
|
251
|
-
// { factor: 2, maxStretch: 5 } - stretch particles in velocity direction based on effective speed
|
|
252
121
|
lighting = Lighting.STANDARD,
|
|
253
|
-
// 'basic' | 'standard' | 'physical' - material type for geometry mode
|
|
254
122
|
shadow = false,
|
|
255
|
-
// Enable both castShadow and receiveShadow on geometry instances
|
|
256
123
|
blending = Blending.NORMAL,
|
|
257
124
|
intensity = 1,
|
|
258
125
|
position = [0, 0, 0],
|
|
259
126
|
autoStart = true,
|
|
260
127
|
delay = 0,
|
|
261
128
|
backdropNode = null,
|
|
262
|
-
// TSL node or function for backdrop sampling
|
|
263
129
|
opacityNode = null,
|
|
264
|
-
// TSL node or function for custom opacity control
|
|
265
130
|
colorNode = null,
|
|
266
|
-
// TSL node or function to override color (receives particleData, should return vec4)
|
|
267
131
|
alphaTestNode = null,
|
|
268
|
-
// TSL node or function for custom alpha test/discard (return true to discard fragment)
|
|
269
132
|
castShadowNode = null,
|
|
270
|
-
// TSL node or function for shadow map output (what shadow the particle casts)
|
|
271
133
|
emitCount = 1,
|
|
272
|
-
// Emitter shape props
|
|
273
134
|
emitterShape = EmitterShape.BOX,
|
|
274
|
-
// Emission shape type
|
|
275
135
|
emitterRadius = [0, 1],
|
|
276
|
-
// [inner, outer] radius for sphere/cone/disk (inner=0 for solid)
|
|
277
136
|
emitterAngle = Math.PI / 4,
|
|
278
|
-
// Cone angle in radians (0 = line, PI/2 = hemisphere)
|
|
279
137
|
emitterHeight = [0, 1],
|
|
280
|
-
// [min, max] height for cone
|
|
281
138
|
emitterSurfaceOnly = false,
|
|
282
|
-
// Emit from surface only (sphere/disk)
|
|
283
139
|
emitterDirection = [0, 1, 0],
|
|
284
|
-
// Direction for cone/disk normal
|
|
285
|
-
// Turbulence (curl noise)
|
|
286
140
|
turbulence = null,
|
|
287
|
-
// { intensity: 0.5, frequency: 1, speed: 1 }
|
|
288
|
-
// Attractors - array of up to 4 attractors
|
|
289
|
-
// { position: [x,y,z], strength: 1, radius: 3, type: 'point'|'vortex', axis?: [x,y,z] }
|
|
290
141
|
attractors = null,
|
|
291
|
-
// Simple attract to center - particles move from spawn position to center over lifetime
|
|
292
|
-
// Overrides speed/direction - lifetime controls how long it takes to reach center
|
|
293
142
|
attractToCenter = false,
|
|
294
|
-
// Use start position offset as direction - particles move in the direction of their spawn offset
|
|
295
143
|
startPositionAsDirection = false,
|
|
296
|
-
// Soft particles - fade when intersecting scene geometry
|
|
297
144
|
softParticles = false,
|
|
298
145
|
softDistance = 0.5,
|
|
299
|
-
// Distance in world units over which to fade
|
|
300
|
-
// Plane collision - particles bounce or die when hitting a plane
|
|
301
|
-
// { plane: { y: 0 }, bounce: 0.3, friction: 0.8, die: false, sizeBasedGravity: 0 }
|
|
302
146
|
collision = null,
|
|
303
|
-
// Debug mode - shows tweakable control panel
|
|
304
147
|
debug = false,
|
|
305
|
-
// Path to pre-baked curve texture (skips runtime baking for faster load)
|
|
306
148
|
curveTexturePath = null,
|
|
307
|
-
// Depth test
|
|
308
149
|
depthTest = true,
|
|
309
|
-
// Render order
|
|
310
150
|
renderOrder = 0
|
|
311
151
|
}, ref) {
|
|
312
152
|
var _a;
|
|
313
153
|
const { gl: renderer } = useThree();
|
|
314
|
-
const spriteRef =
|
|
315
|
-
const
|
|
316
|
-
const
|
|
317
|
-
const [
|
|
318
|
-
const
|
|
319
|
-
const
|
|
320
|
-
const
|
|
321
|
-
const
|
|
322
|
-
const [
|
|
323
|
-
const [
|
|
324
|
-
const [
|
|
325
|
-
const [
|
|
326
|
-
const [
|
|
327
|
-
const [
|
|
328
|
-
const [activeFadeSizeCurve, setActiveFadeSizeCurve] = useState2(fadeSizeCurve);
|
|
329
|
-
const [activeFadeOpacityCurve, setActiveFadeOpacityCurve] = useState2(fadeOpacityCurve);
|
|
330
|
-
const [activeVelocityCurve, setActiveVelocityCurve] = useState2(velocityCurve);
|
|
331
|
-
const [activeRotationSpeedCurve, setActiveRotationSpeedCurve] = useState2(rotationSpeedCurve);
|
|
332
|
-
const [activeTurbulence, setActiveTurbulence] = useState2(
|
|
154
|
+
const spriteRef = useRef(null);
|
|
155
|
+
const [emitting, setEmitting] = useState(autoStart);
|
|
156
|
+
const debugValuesRef = useRef(null);
|
|
157
|
+
const [activeMaxParticles, setActiveMaxParticles] = useState(maxParticles);
|
|
158
|
+
const [activeLighting, setActiveLighting] = useState(lighting);
|
|
159
|
+
const [activeAppearance, setActiveAppearance] = useState(appearance);
|
|
160
|
+
const [activeOrientToDirection, setActiveOrientToDirection] = useState(orientToDirection);
|
|
161
|
+
const [activeGeometry, setActiveGeometry] = useState(geometry);
|
|
162
|
+
const [activeShadow, setActiveShadow] = useState(shadow);
|
|
163
|
+
const [activeFadeSizeCurve, setActiveFadeSizeCurve] = useState(fadeSizeCurve);
|
|
164
|
+
const [activeFadeOpacityCurve, setActiveFadeOpacityCurve] = useState(fadeOpacityCurve);
|
|
165
|
+
const [activeVelocityCurve, setActiveVelocityCurve] = useState(velocityCurve);
|
|
166
|
+
const [activeRotationSpeedCurve, setActiveRotationSpeedCurve] = useState(rotationSpeedCurve);
|
|
167
|
+
const [activeTurbulence, setActiveTurbulence] = useState(
|
|
333
168
|
turbulence !== null && ((_a = turbulence == null ? void 0 : turbulence.intensity) != null ? _a : 0) > 0
|
|
334
169
|
);
|
|
335
|
-
const [activeAttractors, setActiveAttractors] =
|
|
170
|
+
const [activeAttractors, setActiveAttractors] = useState(
|
|
336
171
|
attractors !== null && attractors.length > 0
|
|
337
172
|
);
|
|
338
|
-
const [activeCollision, setActiveCollision] =
|
|
339
|
-
const [activeNeedsPerParticleColor, setActiveNeedsPerParticleColor] =
|
|
340
|
-
const
|
|
341
|
-
if (typeof r === "number") return r !== 0;
|
|
342
|
-
if (Array.isArray(r) && r.length === 2 && typeof r[0] === "number") {
|
|
343
|
-
return r[0] !== 0 || r[1] !== 0;
|
|
344
|
-
}
|
|
345
|
-
if (Array.isArray(r)) {
|
|
346
|
-
return r.some(
|
|
347
|
-
(axis) => Array.isArray(axis) && (axis[0] !== 0 || axis[1] !== 0)
|
|
348
|
-
);
|
|
349
|
-
}
|
|
350
|
-
return false;
|
|
351
|
-
};
|
|
352
|
-
const [activeNeedsRotation, setActiveNeedsRotation] = useState2(
|
|
173
|
+
const [activeCollision, setActiveCollision] = useState(collision !== null);
|
|
174
|
+
const [activeNeedsPerParticleColor, setActiveNeedsPerParticleColor] = useState(colorStart.length > 1 || colorEnd !== null);
|
|
175
|
+
const [activeNeedsRotation, setActiveNeedsRotation] = useState(
|
|
353
176
|
isNonDefaultRotation(rotation) || isNonDefaultRotation(rotationSpeed)
|
|
354
177
|
);
|
|
355
|
-
|
|
356
|
-
delayRef.current = delay;
|
|
357
|
-
emitCountRef.current = emitCount;
|
|
358
|
-
turbulenceRef.current = turbulence;
|
|
359
|
-
}, [delay, emitCount, turbulence]);
|
|
360
|
-
useEffect2(() => {
|
|
178
|
+
useEffect(() => {
|
|
361
179
|
var _a2;
|
|
362
180
|
if (!debug) {
|
|
363
181
|
setActiveMaxParticles(maxParticles);
|
|
@@ -402,699 +220,221 @@ var VFXParticles = forwardRef(
|
|
|
402
220
|
attractors,
|
|
403
221
|
collision
|
|
404
222
|
]);
|
|
405
|
-
const
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
223
|
+
const system = useMemo(
|
|
224
|
+
() => {
|
|
225
|
+
var _a2, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n, _o, _p, _q, _r, _s, _t, _u, _v, _w, _x, _y, _z, _A, _B, _C, _D, _E, _F, _G, _H, _I;
|
|
226
|
+
const dbg = debug ? debugValuesRef.current : null;
|
|
227
|
+
return new VFXParticleSystem(
|
|
228
|
+
renderer,
|
|
229
|
+
{
|
|
230
|
+
maxParticles: activeMaxParticles,
|
|
231
|
+
size: (_a2 = dbg == null ? void 0 : dbg.size) != null ? _a2 : size,
|
|
232
|
+
colorStart: (_b = dbg == null ? void 0 : dbg.colorStart) != null ? _b : colorStart,
|
|
233
|
+
colorEnd: (dbg == null ? void 0 : dbg.colorEnd) !== void 0 ? dbg.colorEnd : colorEnd,
|
|
234
|
+
fadeSize: (_c = dbg == null ? void 0 : dbg.fadeSize) != null ? _c : fadeSize,
|
|
235
|
+
fadeSizeCurve: activeFadeSizeCurve,
|
|
236
|
+
fadeOpacity: (_d = dbg == null ? void 0 : dbg.fadeOpacity) != null ? _d : fadeOpacity,
|
|
237
|
+
fadeOpacityCurve: activeFadeOpacityCurve,
|
|
238
|
+
velocityCurve: activeVelocityCurve,
|
|
239
|
+
gravity: (_e = dbg == null ? void 0 : dbg.gravity) != null ? _e : gravity,
|
|
240
|
+
lifetime: (_f = dbg == null ? void 0 : dbg.lifetime) != null ? _f : lifetime,
|
|
241
|
+
direction: (_g = dbg == null ? void 0 : dbg.direction) != null ? _g : direction,
|
|
242
|
+
startPosition: (_h = dbg == null ? void 0 : dbg.startPosition) != null ? _h : startPosition,
|
|
243
|
+
speed: (_i = dbg == null ? void 0 : dbg.speed) != null ? _i : speed,
|
|
244
|
+
friction: (_j = dbg == null ? void 0 : dbg.friction) != null ? _j : friction,
|
|
245
|
+
appearance: activeAppearance,
|
|
246
|
+
alphaMap,
|
|
247
|
+
flipbook,
|
|
248
|
+
rotation: (_k = dbg == null ? void 0 : dbg.rotation) != null ? _k : rotation,
|
|
249
|
+
rotationSpeed: (_l = dbg == null ? void 0 : dbg.rotationSpeed) != null ? _l : rotationSpeed,
|
|
250
|
+
rotationSpeedCurve: activeRotationSpeedCurve,
|
|
251
|
+
geometry: activeGeometry,
|
|
252
|
+
orientToDirection: activeOrientToDirection,
|
|
253
|
+
orientAxis: (_m = dbg == null ? void 0 : dbg.orientAxis) != null ? _m : orientAxis,
|
|
254
|
+
stretchBySpeed: (_n = dbg == null ? void 0 : dbg.stretchBySpeed) != null ? _n : stretchBySpeed,
|
|
255
|
+
lighting: activeLighting,
|
|
256
|
+
shadow: activeShadow,
|
|
257
|
+
blending: (_o = dbg == null ? void 0 : dbg.blending) != null ? _o : blending,
|
|
258
|
+
intensity: (_p = dbg == null ? void 0 : dbg.intensity) != null ? _p : intensity,
|
|
259
|
+
position: (_q = dbg == null ? void 0 : dbg.position) != null ? _q : position,
|
|
260
|
+
autoStart: (_r = dbg == null ? void 0 : dbg.autoStart) != null ? _r : autoStart,
|
|
261
|
+
delay: (_s = dbg == null ? void 0 : dbg.delay) != null ? _s : delay,
|
|
262
|
+
emitCount: (_t = dbg == null ? void 0 : dbg.emitCount) != null ? _t : emitCount,
|
|
263
|
+
emitterShape: (_u = dbg == null ? void 0 : dbg.emitterShape) != null ? _u : emitterShape,
|
|
264
|
+
emitterRadius: (_v = dbg == null ? void 0 : dbg.emitterRadius) != null ? _v : emitterRadius,
|
|
265
|
+
emitterAngle: (_w = dbg == null ? void 0 : dbg.emitterAngle) != null ? _w : emitterAngle,
|
|
266
|
+
emitterHeight: (_x = dbg == null ? void 0 : dbg.emitterHeight) != null ? _x : emitterHeight,
|
|
267
|
+
emitterSurfaceOnly: (_y = dbg == null ? void 0 : dbg.emitterSurfaceOnly) != null ? _y : emitterSurfaceOnly,
|
|
268
|
+
emitterDirection: (_z = dbg == null ? void 0 : dbg.emitterDirection) != null ? _z : emitterDirection,
|
|
269
|
+
turbulence: (_A = dbg == null ? void 0 : dbg.turbulence) != null ? _A : turbulence,
|
|
270
|
+
attractors: (_B = dbg == null ? void 0 : dbg.attractors) != null ? _B : attractors,
|
|
271
|
+
attractToCenter: (_C = dbg == null ? void 0 : dbg.attractToCenter) != null ? _C : attractToCenter,
|
|
272
|
+
startPositionAsDirection: (_D = dbg == null ? void 0 : dbg.startPositionAsDirection) != null ? _D : startPositionAsDirection,
|
|
273
|
+
softParticles: (_E = dbg == null ? void 0 : dbg.softParticles) != null ? _E : softParticles,
|
|
274
|
+
softDistance: (_F = dbg == null ? void 0 : dbg.softDistance) != null ? _F : softDistance,
|
|
275
|
+
collision: (_G = dbg == null ? void 0 : dbg.collision) != null ? _G : collision,
|
|
276
|
+
backdropNode,
|
|
277
|
+
opacityNode,
|
|
278
|
+
colorNode,
|
|
279
|
+
alphaTestNode,
|
|
280
|
+
castShadowNode,
|
|
281
|
+
depthTest: (_H = dbg == null ? void 0 : dbg.depthTest) != null ? _H : depthTest,
|
|
282
|
+
renderOrder: (_I = dbg == null ? void 0 : dbg.renderOrder) != null ? _I : renderOrder,
|
|
283
|
+
curveTexturePath
|
|
284
|
+
}
|
|
285
|
+
);
|
|
286
|
+
},
|
|
287
|
+
// Only recreate when structural props change (features, maxParticles, etc.)
|
|
288
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
456
289
|
[
|
|
290
|
+
renderer,
|
|
291
|
+
activeMaxParticles,
|
|
292
|
+
activeLighting,
|
|
293
|
+
activeAppearance,
|
|
294
|
+
activeOrientToDirection,
|
|
295
|
+
activeGeometry,
|
|
296
|
+
activeShadow,
|
|
457
297
|
activeNeedsPerParticleColor,
|
|
458
298
|
activeNeedsRotation,
|
|
459
299
|
activeTurbulence,
|
|
460
300
|
activeAttractors,
|
|
461
|
-
activeCollision
|
|
301
|
+
activeCollision,
|
|
302
|
+
activeFadeSizeCurve,
|
|
303
|
+
activeFadeOpacityCurve,
|
|
304
|
+
activeVelocityCurve,
|
|
305
|
+
activeRotationSpeedCurve,
|
|
306
|
+
alphaMap,
|
|
307
|
+
flipbook,
|
|
308
|
+
blending,
|
|
309
|
+
backdropNode,
|
|
310
|
+
opacityNode,
|
|
311
|
+
colorNode,
|
|
312
|
+
alphaTestNode,
|
|
313
|
+
castShadowNode,
|
|
314
|
+
softParticles,
|
|
315
|
+
curveTexturePath
|
|
462
316
|
]
|
|
463
317
|
);
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
return [0, 0];
|
|
469
|
-
}, [friction]);
|
|
470
|
-
const frictionEasingType = useMemo2(() => {
|
|
318
|
+
useEffect(() => {
|
|
319
|
+
system.init();
|
|
320
|
+
}, [system]);
|
|
321
|
+
useEffect(() => {
|
|
471
322
|
var _a2;
|
|
472
|
-
if (typeof friction === "object" && friction !== null && "easing" in friction) {
|
|
473
|
-
return easingToType((_a2 = friction.easing) != null ? _a2 : "linear");
|
|
474
|
-
}
|
|
475
|
-
return 0;
|
|
476
|
-
}, [friction]);
|
|
477
|
-
const startColors = useMemo2(() => {
|
|
478
|
-
const colors = colorStart.slice(0, 8).map(hexToRgb);
|
|
479
|
-
while (colors.length < 8)
|
|
480
|
-
colors.push(colors[colors.length - 1] || [1, 1, 1]);
|
|
481
|
-
return colors;
|
|
482
|
-
}, [colorStart]);
|
|
483
|
-
const effectiveColorEnd = colorEnd != null ? colorEnd : colorStart;
|
|
484
|
-
const endColors = useMemo2(() => {
|
|
485
|
-
const colors = effectiveColorEnd.slice(0, 8).map(hexToRgb);
|
|
486
|
-
while (colors.length < 8)
|
|
487
|
-
colors.push(colors[colors.length - 1] || [1, 1, 1]);
|
|
488
|
-
return colors;
|
|
489
|
-
}, [effectiveColorEnd]);
|
|
490
|
-
const uniforms = useMemo2(
|
|
491
|
-
() => {
|
|
492
|
-
var _a2, _b, _c, _d, _e, _f, _g, _h, _i, _j;
|
|
493
|
-
return {
|
|
494
|
-
sizeMin: uniform(sizeRange[0]),
|
|
495
|
-
sizeMax: uniform(sizeRange[1]),
|
|
496
|
-
fadeSizeStart: uniform(fadeSizeRange[0]),
|
|
497
|
-
fadeSizeEnd: uniform(fadeSizeRange[1]),
|
|
498
|
-
fadeOpacityStart: uniform(fadeOpacityRange[0]),
|
|
499
|
-
fadeOpacityEnd: uniform(fadeOpacityRange[1]),
|
|
500
|
-
gravity: uniform(new THREE.Vector3(...gravity)),
|
|
501
|
-
frictionIntensityStart: uniform(frictionIntensityRange[0]),
|
|
502
|
-
frictionIntensityEnd: uniform(frictionIntensityRange[1]),
|
|
503
|
-
frictionEasingType: uniform(frictionEasingType),
|
|
504
|
-
speedMin: uniform(speedRange[0]),
|
|
505
|
-
speedMax: uniform(speedRange[1]),
|
|
506
|
-
lifetimeMin: uniform(lifetimeToFadeRate(lifetimeRange[1])),
|
|
507
|
-
lifetimeMax: uniform(lifetimeToFadeRate(lifetimeRange[0])),
|
|
508
|
-
deltaTime: uniform(0.016),
|
|
509
|
-
// Will be updated each frame
|
|
510
|
-
// 3D direction ranges
|
|
511
|
-
dirMinX: uniform(direction3D[0][0]),
|
|
512
|
-
dirMaxX: uniform(direction3D[0][1]),
|
|
513
|
-
dirMinY: uniform(direction3D[1][0]),
|
|
514
|
-
dirMaxY: uniform(direction3D[1][1]),
|
|
515
|
-
dirMinZ: uniform(direction3D[2][0]),
|
|
516
|
-
dirMaxZ: uniform(direction3D[2][1]),
|
|
517
|
-
// 3D start position offset ranges
|
|
518
|
-
startPosMinX: uniform(startPosition3D[0][0]),
|
|
519
|
-
startPosMaxX: uniform(startPosition3D[0][1]),
|
|
520
|
-
startPosMinY: uniform(startPosition3D[1][0]),
|
|
521
|
-
startPosMaxY: uniform(startPosition3D[1][1]),
|
|
522
|
-
startPosMinZ: uniform(startPosition3D[2][0]),
|
|
523
|
-
startPosMaxZ: uniform(startPosition3D[2][1]),
|
|
524
|
-
spawnPosition: uniform(new THREE.Vector3(...position)),
|
|
525
|
-
spawnIndexStart: uniform(0),
|
|
526
|
-
spawnIndexEnd: uniform(0),
|
|
527
|
-
spawnSeed: uniform(0),
|
|
528
|
-
intensity: uniform(intensity),
|
|
529
|
-
// 3D rotation ranges
|
|
530
|
-
rotationMinX: uniform(rotation3D[0][0]),
|
|
531
|
-
rotationMaxX: uniform(rotation3D[0][1]),
|
|
532
|
-
rotationMinY: uniform(rotation3D[1][0]),
|
|
533
|
-
rotationMaxY: uniform(rotation3D[1][1]),
|
|
534
|
-
rotationMinZ: uniform(rotation3D[2][0]),
|
|
535
|
-
rotationMaxZ: uniform(rotation3D[2][1]),
|
|
536
|
-
// 3D rotation speed ranges (radians/second)
|
|
537
|
-
rotationSpeedMinX: uniform(rotationSpeed3D[0][0]),
|
|
538
|
-
rotationSpeedMaxX: uniform(rotationSpeed3D[0][1]),
|
|
539
|
-
rotationSpeedMinY: uniform(rotationSpeed3D[1][0]),
|
|
540
|
-
rotationSpeedMaxY: uniform(rotationSpeed3D[1][1]),
|
|
541
|
-
rotationSpeedMinZ: uniform(rotationSpeed3D[2][0]),
|
|
542
|
-
rotationSpeedMaxZ: uniform(rotationSpeed3D[2][1]),
|
|
543
|
-
// Color arrays (8 colors max each)
|
|
544
|
-
colorStartCount: uniform(colorStart.length),
|
|
545
|
-
colorEndCount: uniform(effectiveColorEnd.length),
|
|
546
|
-
colorStart0: uniform(new THREE.Color(...startColors[0])),
|
|
547
|
-
colorStart1: uniform(new THREE.Color(...startColors[1])),
|
|
548
|
-
colorStart2: uniform(new THREE.Color(...startColors[2])),
|
|
549
|
-
colorStart3: uniform(new THREE.Color(...startColors[3])),
|
|
550
|
-
colorStart4: uniform(new THREE.Color(...startColors[4])),
|
|
551
|
-
colorStart5: uniform(new THREE.Color(...startColors[5])),
|
|
552
|
-
colorStart6: uniform(new THREE.Color(...startColors[6])),
|
|
553
|
-
colorStart7: uniform(new THREE.Color(...startColors[7])),
|
|
554
|
-
colorEnd0: uniform(new THREE.Color(...endColors[0])),
|
|
555
|
-
colorEnd1: uniform(new THREE.Color(...endColors[1])),
|
|
556
|
-
colorEnd2: uniform(new THREE.Color(...endColors[2])),
|
|
557
|
-
colorEnd3: uniform(new THREE.Color(...endColors[3])),
|
|
558
|
-
colorEnd4: uniform(new THREE.Color(...endColors[4])),
|
|
559
|
-
colorEnd5: uniform(new THREE.Color(...endColors[5])),
|
|
560
|
-
colorEnd6: uniform(new THREE.Color(...endColors[6])),
|
|
561
|
-
colorEnd7: uniform(new THREE.Color(...endColors[7])),
|
|
562
|
-
// Emitter shape uniforms
|
|
563
|
-
emitterShapeType: uniform(emitterShape),
|
|
564
|
-
emitterRadiusInner: uniform(emitterRadiusRange[0]),
|
|
565
|
-
emitterRadiusOuter: uniform(emitterRadiusRange[1]),
|
|
566
|
-
emitterAngle: uniform(emitterAngle),
|
|
567
|
-
emitterHeightMin: uniform(emitterHeightRange[0]),
|
|
568
|
-
emitterHeightMax: uniform(emitterHeightRange[1]),
|
|
569
|
-
emitterSurfaceOnly: uniform(emitterSurfaceOnly ? 1 : 0),
|
|
570
|
-
emitterDir: uniform(new THREE.Vector3(...emitterDirection).normalize()),
|
|
571
|
-
// Turbulence uniforms
|
|
572
|
-
turbulenceIntensity: uniform((_a2 = turbulence == null ? void 0 : turbulence.intensity) != null ? _a2 : 0),
|
|
573
|
-
turbulenceFrequency: uniform((_b = turbulence == null ? void 0 : turbulence.frequency) != null ? _b : 1),
|
|
574
|
-
turbulenceSpeed: uniform((_c = turbulence == null ? void 0 : turbulence.speed) != null ? _c : 1),
|
|
575
|
-
turbulenceTime: uniform(0),
|
|
576
|
-
// Updated each frame
|
|
577
|
-
// Attractor uniforms (up to 4)
|
|
578
|
-
attractorCount: uniform(0),
|
|
579
|
-
attractor0Pos: uniform(new THREE.Vector3(0, 0, 0)),
|
|
580
|
-
attractor0Strength: uniform(0),
|
|
581
|
-
attractor0Radius: uniform(1),
|
|
582
|
-
attractor0Type: uniform(0),
|
|
583
|
-
attractor0Axis: uniform(new THREE.Vector3(0, 1, 0)),
|
|
584
|
-
attractor1Pos: uniform(new THREE.Vector3(0, 0, 0)),
|
|
585
|
-
attractor1Strength: uniform(0),
|
|
586
|
-
attractor1Radius: uniform(1),
|
|
587
|
-
attractor1Type: uniform(0),
|
|
588
|
-
attractor1Axis: uniform(new THREE.Vector3(0, 1, 0)),
|
|
589
|
-
attractor2Pos: uniform(new THREE.Vector3(0, 0, 0)),
|
|
590
|
-
attractor2Strength: uniform(0),
|
|
591
|
-
attractor2Radius: uniform(1),
|
|
592
|
-
attractor2Type: uniform(0),
|
|
593
|
-
attractor2Axis: uniform(new THREE.Vector3(0, 1, 0)),
|
|
594
|
-
attractor3Pos: uniform(new THREE.Vector3(0, 0, 0)),
|
|
595
|
-
attractor3Strength: uniform(0),
|
|
596
|
-
attractor3Radius: uniform(1),
|
|
597
|
-
attractor3Type: uniform(0),
|
|
598
|
-
attractor3Axis: uniform(new THREE.Vector3(0, 1, 0)),
|
|
599
|
-
// Simple attract to center
|
|
600
|
-
attractToCenter: uniform(attractToCenter ? 1 : 0),
|
|
601
|
-
// Use start position as direction
|
|
602
|
-
startPositionAsDirection: uniform(startPositionAsDirection ? 1 : 0),
|
|
603
|
-
// Soft particles
|
|
604
|
-
softParticlesEnabled: uniform(softParticles ? 1 : 0),
|
|
605
|
-
softDistance: uniform(softDistance),
|
|
606
|
-
// Curve enabled flags (set by useCurveTextureAsync per-channel info)
|
|
607
|
-
velocityCurveEnabled: uniform(0),
|
|
608
|
-
rotationSpeedCurveEnabled: uniform(0),
|
|
609
|
-
fadeSizeCurveEnabled: uniform(0),
|
|
610
|
-
fadeOpacityCurveEnabled: uniform(0),
|
|
611
|
-
// Orient axis: 0=+X, 1=+Y, 2=+Z, 3=-X, 4=-Y, 5=-Z
|
|
612
|
-
orientAxisType: uniform(axisToNumber(orientAxis)),
|
|
613
|
-
// Stretch by speed (uses effective velocity after curve modifier)
|
|
614
|
-
stretchEnabled: uniform(stretchBySpeed ? 1 : 0),
|
|
615
|
-
stretchFactor: uniform((_d = stretchBySpeed == null ? void 0 : stretchBySpeed.factor) != null ? _d : 1),
|
|
616
|
-
stretchMax: uniform((_e = stretchBySpeed == null ? void 0 : stretchBySpeed.maxStretch) != null ? _e : 5),
|
|
617
|
-
// Collision uniforms
|
|
618
|
-
collisionEnabled: uniform(collision ? 1 : 0),
|
|
619
|
-
collisionPlaneY: uniform((_g = (_f = collision == null ? void 0 : collision.plane) == null ? void 0 : _f.y) != null ? _g : 0),
|
|
620
|
-
collisionBounce: uniform((_h = collision == null ? void 0 : collision.bounce) != null ? _h : 0.3),
|
|
621
|
-
collisionFriction: uniform((_i = collision == null ? void 0 : collision.friction) != null ? _i : 0.8),
|
|
622
|
-
collisionDie: uniform((collision == null ? void 0 : collision.die) ? 1 : 0),
|
|
623
|
-
// Size-based gravity (inside collision object)
|
|
624
|
-
sizeBasedGravity: uniform((_j = collision == null ? void 0 : collision.sizeBasedGravity) != null ? _j : 0)
|
|
625
|
-
};
|
|
626
|
-
},
|
|
627
|
-
[]
|
|
628
|
-
);
|
|
629
|
-
const positionRef = useRef2(position);
|
|
630
|
-
useEffect2(() => {
|
|
631
|
-
var _a2, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n;
|
|
632
323
|
if (debug) return;
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
uniforms.rotationSpeedMaxX.value = rotationSpeed3D[0][1];
|
|
668
|
-
uniforms.rotationSpeedMinY.value = rotationSpeed3D[1][0];
|
|
669
|
-
uniforms.rotationSpeedMaxY.value = rotationSpeed3D[1][1];
|
|
670
|
-
uniforms.rotationSpeedMinZ.value = rotationSpeed3D[2][0];
|
|
671
|
-
uniforms.rotationSpeedMaxZ.value = rotationSpeed3D[2][1];
|
|
672
|
-
uniforms.intensity.value = intensity;
|
|
673
|
-
uniforms.colorStartCount.value = colorStart.length;
|
|
674
|
-
uniforms.colorEndCount.value = effectiveColorEnd.length;
|
|
675
|
-
startColors.forEach((c, i) => {
|
|
676
|
-
var _a3;
|
|
677
|
-
;
|
|
678
|
-
(_a3 = uniforms[`colorStart${i}`]) == null ? void 0 : _a3.value.setRGB(...c);
|
|
679
|
-
});
|
|
680
|
-
endColors.forEach((c, i) => {
|
|
681
|
-
var _a3;
|
|
682
|
-
;
|
|
683
|
-
(_a3 = uniforms[`colorEnd${i}`]) == null ? void 0 : _a3.value.setRGB(...c);
|
|
324
|
+
system.setPosition(position);
|
|
325
|
+
system.setDelay(delay);
|
|
326
|
+
system.setEmitCount(emitCount);
|
|
327
|
+
system.setTurbulenceSpeed((_a2 = turbulence == null ? void 0 : turbulence.speed) != null ? _a2 : 1);
|
|
328
|
+
const normalized = normalizeProps({
|
|
329
|
+
size,
|
|
330
|
+
speed,
|
|
331
|
+
fadeSize,
|
|
332
|
+
fadeOpacity,
|
|
333
|
+
lifetime,
|
|
334
|
+
gravity,
|
|
335
|
+
direction,
|
|
336
|
+
startPosition,
|
|
337
|
+
rotation,
|
|
338
|
+
rotationSpeed,
|
|
339
|
+
friction,
|
|
340
|
+
intensity,
|
|
341
|
+
colorStart,
|
|
342
|
+
colorEnd,
|
|
343
|
+
emitterShape,
|
|
344
|
+
emitterRadius,
|
|
345
|
+
emitterAngle,
|
|
346
|
+
emitterHeight,
|
|
347
|
+
emitterSurfaceOnly,
|
|
348
|
+
emitterDirection,
|
|
349
|
+
turbulence,
|
|
350
|
+
attractors,
|
|
351
|
+
attractToCenter,
|
|
352
|
+
startPositionAsDirection,
|
|
353
|
+
softParticles,
|
|
354
|
+
softDistance,
|
|
355
|
+
collision,
|
|
356
|
+
orientAxis,
|
|
357
|
+
stretchBySpeed
|
|
684
358
|
});
|
|
685
|
-
uniforms
|
|
686
|
-
uniforms.emitterRadiusInner.value = emitterRadiusRange[0];
|
|
687
|
-
uniforms.emitterRadiusOuter.value = emitterRadiusRange[1];
|
|
688
|
-
uniforms.emitterAngle.value = emitterAngle;
|
|
689
|
-
uniforms.emitterHeightMin.value = emitterHeightRange[0];
|
|
690
|
-
uniforms.emitterHeightMax.value = emitterHeightRange[1];
|
|
691
|
-
uniforms.emitterSurfaceOnly.value = emitterSurfaceOnly ? 1 : 0;
|
|
692
|
-
uniforms.emitterDir.value.set(...emitterDirection).normalize();
|
|
693
|
-
uniforms.turbulenceIntensity.value = (_a2 = turbulence == null ? void 0 : turbulence.intensity) != null ? _a2 : 0;
|
|
694
|
-
uniforms.turbulenceFrequency.value = (_b = turbulence == null ? void 0 : turbulence.frequency) != null ? _b : 1;
|
|
695
|
-
uniforms.turbulenceSpeed.value = (_c = turbulence == null ? void 0 : turbulence.speed) != null ? _c : 1;
|
|
696
|
-
const attractorList = attractors != null ? attractors : [];
|
|
697
|
-
uniforms.attractorCount.value = Math.min(
|
|
698
|
-
attractorList.length,
|
|
699
|
-
MAX_ATTRACTORS
|
|
700
|
-
);
|
|
701
|
-
for (let i = 0; i < MAX_ATTRACTORS; i++) {
|
|
702
|
-
const a = attractorList[i];
|
|
703
|
-
const u = uniforms;
|
|
704
|
-
if (a) {
|
|
705
|
-
;
|
|
706
|
-
u[`attractor${i}Pos`].value.set(
|
|
707
|
-
...(_d = a.position) != null ? _d : [0, 0, 0]
|
|
708
|
-
);
|
|
709
|
-
u[`attractor${i}Strength`].value = (_e = a.strength) != null ? _e : 1;
|
|
710
|
-
u[`attractor${i}Radius`].value = (_f = a.radius) != null ? _f : 0;
|
|
711
|
-
u[`attractor${i}Type`].value = a.type === "vortex" ? 1 : 0;
|
|
712
|
-
u[`attractor${i}Axis`].value.set(...(_g = a.axis) != null ? _g : [0, 1, 0]).normalize();
|
|
713
|
-
} else {
|
|
714
|
-
u[`attractor${i}Strength`].value = 0;
|
|
715
|
-
}
|
|
716
|
-
}
|
|
717
|
-
uniforms.attractToCenter.value = attractToCenter ? 1 : 0;
|
|
718
|
-
uniforms.startPositionAsDirection.value = startPositionAsDirection ? 1 : 0;
|
|
719
|
-
uniforms.softParticlesEnabled.value = softParticles ? 1 : 0;
|
|
720
|
-
uniforms.softDistance.value = softDistance;
|
|
721
|
-
uniforms.velocityCurveEnabled.value = curveTextureVelocityEnabled ? 1 : 0;
|
|
722
|
-
uniforms.rotationSpeedCurveEnabled.value = curveTextureRotationSpeedEnabled ? 1 : 0;
|
|
723
|
-
uniforms.fadeSizeCurveEnabled.value = curveTextureSizeEnabled ? 1 : 0;
|
|
724
|
-
uniforms.fadeOpacityCurveEnabled.value = curveTextureOpacityEnabled ? 1 : 0;
|
|
725
|
-
uniforms.orientAxisType.value = axisToNumber(orientAxis);
|
|
726
|
-
uniforms.stretchEnabled.value = stretchBySpeed ? 1 : 0;
|
|
727
|
-
uniforms.stretchFactor.value = (_h = stretchBySpeed == null ? void 0 : stretchBySpeed.factor) != null ? _h : 1;
|
|
728
|
-
uniforms.stretchMax.value = (_i = stretchBySpeed == null ? void 0 : stretchBySpeed.maxStretch) != null ? _i : 5;
|
|
729
|
-
uniforms.collisionEnabled.value = collision ? 1 : 0;
|
|
730
|
-
uniforms.collisionPlaneY.value = (_k = (_j = collision == null ? void 0 : collision.plane) == null ? void 0 : _j.y) != null ? _k : 0;
|
|
731
|
-
uniforms.collisionBounce.value = (_l = collision == null ? void 0 : collision.bounce) != null ? _l : 0.3;
|
|
732
|
-
uniforms.collisionFriction.value = (_m = collision == null ? void 0 : collision.friction) != null ? _m : 0.8;
|
|
733
|
-
uniforms.collisionDie.value = (collision == null ? void 0 : collision.die) ? 1 : 0;
|
|
734
|
-
uniforms.sizeBasedGravity.value = (_n = collision == null ? void 0 : collision.sizeBasedGravity) != null ? _n : 0;
|
|
359
|
+
updateUniforms(system.uniforms, normalized);
|
|
735
360
|
}, [
|
|
736
361
|
debug,
|
|
362
|
+
system,
|
|
737
363
|
position,
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
364
|
+
size,
|
|
365
|
+
fadeSize,
|
|
366
|
+
fadeOpacity,
|
|
741
367
|
gravity,
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
rotationSpeed3D,
|
|
368
|
+
friction,
|
|
369
|
+
speed,
|
|
370
|
+
lifetime,
|
|
371
|
+
direction,
|
|
372
|
+
rotation,
|
|
373
|
+
rotationSpeed,
|
|
749
374
|
intensity,
|
|
750
375
|
colorStart,
|
|
751
|
-
|
|
752
|
-
startColors,
|
|
753
|
-
endColors,
|
|
754
|
-
uniforms,
|
|
376
|
+
colorEnd,
|
|
755
377
|
collision,
|
|
756
378
|
emitterShape,
|
|
757
|
-
|
|
379
|
+
emitterRadius,
|
|
758
380
|
emitterAngle,
|
|
759
|
-
|
|
381
|
+
emitterHeight,
|
|
760
382
|
emitterSurfaceOnly,
|
|
761
383
|
emitterDirection,
|
|
762
384
|
turbulence,
|
|
763
|
-
|
|
385
|
+
startPosition,
|
|
764
386
|
attractors,
|
|
765
387
|
attractToCenter,
|
|
766
388
|
startPositionAsDirection,
|
|
767
389
|
softParticles,
|
|
768
390
|
softDistance,
|
|
769
|
-
curveTextureVelocityEnabled,
|
|
770
|
-
curveTextureRotationSpeedEnabled,
|
|
771
|
-
curveTextureSizeEnabled,
|
|
772
|
-
curveTextureOpacityEnabled,
|
|
773
391
|
orientAxis,
|
|
774
|
-
stretchBySpeed
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
const arrays = {
|
|
778
|
-
positions: instancedArray(activeMaxParticles, "vec3"),
|
|
779
|
-
velocities: instancedArray(activeMaxParticles, "vec3"),
|
|
780
|
-
lifetimes: instancedArray(activeMaxParticles, "float"),
|
|
781
|
-
fadeRates: instancedArray(activeMaxParticles, "float"),
|
|
782
|
-
particleSizes: instancedArray(activeMaxParticles, "float"),
|
|
783
|
-
// Optional arrays - null when feature unused (saves GPU memory)
|
|
784
|
-
particleRotations: null,
|
|
785
|
-
particleColorStarts: null,
|
|
786
|
-
particleColorEnds: null
|
|
787
|
-
};
|
|
788
|
-
if (activeFeatures.needsRotation) {
|
|
789
|
-
arrays.particleRotations = instancedArray(activeMaxParticles, "vec3");
|
|
790
|
-
}
|
|
791
|
-
if (activeFeatures.needsPerParticleColor) {
|
|
792
|
-
arrays.particleColorStarts = instancedArray(activeMaxParticles, "vec3");
|
|
793
|
-
arrays.particleColorEnds = instancedArray(activeMaxParticles, "vec3");
|
|
794
|
-
}
|
|
795
|
-
return arrays;
|
|
796
|
-
}, [
|
|
797
|
-
activeMaxParticles,
|
|
798
|
-
activeFeatures.needsRotation,
|
|
799
|
-
activeFeatures.needsPerParticleColor
|
|
392
|
+
stretchBySpeed,
|
|
393
|
+
delay,
|
|
394
|
+
emitCount
|
|
800
395
|
]);
|
|
801
|
-
const computeInit = useMemo2(
|
|
802
|
-
() => createInitCompute(storage, activeMaxParticles),
|
|
803
|
-
[storage, activeMaxParticles]
|
|
804
|
-
);
|
|
805
|
-
const computeSpawn = useMemo2(
|
|
806
|
-
() => createSpawnCompute(storage, uniforms, activeMaxParticles),
|
|
807
|
-
[storage, uniforms, activeMaxParticles]
|
|
808
|
-
);
|
|
809
|
-
const computeUpdate = useMemo2(
|
|
810
|
-
() => createUpdateCompute(
|
|
811
|
-
storage,
|
|
812
|
-
uniforms,
|
|
813
|
-
curveTexture,
|
|
814
|
-
activeMaxParticles,
|
|
815
|
-
{
|
|
816
|
-
turbulence: activeFeatures.turbulence,
|
|
817
|
-
attractors: activeFeatures.attractors,
|
|
818
|
-
collision: activeFeatures.collision,
|
|
819
|
-
rotation: activeFeatures.rotation,
|
|
820
|
-
perParticleColor: activeFeatures.perParticleColor
|
|
821
|
-
}
|
|
822
|
-
),
|
|
823
|
-
[storage, uniforms, curveTexture, activeMaxParticles, activeFeatures]
|
|
824
|
-
);
|
|
825
|
-
const material = useMemo2(
|
|
826
|
-
() => createParticleMaterial(storage, uniforms, curveTexture, {
|
|
827
|
-
alphaMap,
|
|
828
|
-
flipbook,
|
|
829
|
-
appearance: activeAppearance,
|
|
830
|
-
lighting: activeLighting,
|
|
831
|
-
softParticles,
|
|
832
|
-
geometry: activeGeometry,
|
|
833
|
-
orientToDirection: activeOrientToDirection,
|
|
834
|
-
shadow: activeShadow,
|
|
835
|
-
blending,
|
|
836
|
-
opacityNode,
|
|
837
|
-
colorNode,
|
|
838
|
-
backdropNode,
|
|
839
|
-
alphaTestNode,
|
|
840
|
-
castShadowNode
|
|
841
|
-
}),
|
|
842
|
-
[
|
|
843
|
-
storage,
|
|
844
|
-
uniforms,
|
|
845
|
-
curveTexture,
|
|
846
|
-
activeAppearance,
|
|
847
|
-
alphaMap,
|
|
848
|
-
flipbook,
|
|
849
|
-
blending,
|
|
850
|
-
activeGeometry,
|
|
851
|
-
activeOrientToDirection,
|
|
852
|
-
activeLighting,
|
|
853
|
-
backdropNode,
|
|
854
|
-
opacityNode,
|
|
855
|
-
colorNode,
|
|
856
|
-
alphaTestNode,
|
|
857
|
-
castShadowNode,
|
|
858
|
-
softParticles,
|
|
859
|
-
activeShadow
|
|
860
|
-
]
|
|
861
|
-
);
|
|
862
|
-
const renderObject = useMemo2(() => {
|
|
863
|
-
if (activeGeometry) {
|
|
864
|
-
const mesh = new THREE.InstancedMesh(
|
|
865
|
-
activeGeometry,
|
|
866
|
-
material,
|
|
867
|
-
activeMaxParticles
|
|
868
|
-
);
|
|
869
|
-
mesh.frustumCulled = false;
|
|
870
|
-
mesh.castShadow = activeShadow;
|
|
871
|
-
mesh.receiveShadow = activeShadow;
|
|
872
|
-
return mesh;
|
|
873
|
-
} else {
|
|
874
|
-
const s = new THREE.Sprite(material);
|
|
875
|
-
s.count = activeMaxParticles;
|
|
876
|
-
s.frustumCulled = false;
|
|
877
|
-
return s;
|
|
878
|
-
}
|
|
879
|
-
}, [material, activeMaxParticles, activeGeometry, activeShadow]);
|
|
880
|
-
useEffect2(() => {
|
|
881
|
-
if (!renderer || initialized.current) return;
|
|
882
|
-
renderer.computeAsync(computeInit).then(() => {
|
|
883
|
-
initialized.current = true;
|
|
884
|
-
});
|
|
885
|
-
}, [renderer, computeInit]);
|
|
886
|
-
const applySpawnOverrides = useCallback(
|
|
887
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
888
|
-
(overrides) => {
|
|
889
|
-
if (!overrides) return null;
|
|
890
|
-
const saved = {};
|
|
891
|
-
const setUniform = (key, value) => {
|
|
892
|
-
if (uniforms[key]) {
|
|
893
|
-
saved[key] = uniforms[key].value;
|
|
894
|
-
uniforms[key].value = value;
|
|
895
|
-
}
|
|
896
|
-
};
|
|
897
|
-
if (overrides.size !== void 0) {
|
|
898
|
-
const range = toRange(overrides.size, [0.1, 0.3]);
|
|
899
|
-
setUniform("sizeMin", range[0]);
|
|
900
|
-
setUniform("sizeMax", range[1]);
|
|
901
|
-
}
|
|
902
|
-
if (overrides.speed !== void 0) {
|
|
903
|
-
const range = toRange(overrides.speed, [0.1, 0.1]);
|
|
904
|
-
setUniform("speedMin", range[0]);
|
|
905
|
-
setUniform("speedMax", range[1]);
|
|
906
|
-
}
|
|
907
|
-
if (overrides.lifetime !== void 0) {
|
|
908
|
-
const range = toRange(overrides.lifetime, [1, 2]);
|
|
909
|
-
setUniform("lifetimeMin", 1 / range[1]);
|
|
910
|
-
setUniform("lifetimeMax", 1 / range[0]);
|
|
911
|
-
}
|
|
912
|
-
if (overrides.direction !== void 0) {
|
|
913
|
-
const dir3D = toRotation3D(overrides.direction);
|
|
914
|
-
setUniform("dirMinX", dir3D[0][0]);
|
|
915
|
-
setUniform("dirMaxX", dir3D[0][1]);
|
|
916
|
-
setUniform("dirMinY", dir3D[1][0]);
|
|
917
|
-
setUniform("dirMaxY", dir3D[1][1]);
|
|
918
|
-
setUniform("dirMinZ", dir3D[2][0]);
|
|
919
|
-
setUniform("dirMaxZ", dir3D[2][1]);
|
|
920
|
-
}
|
|
921
|
-
if (overrides.startPosition !== void 0) {
|
|
922
|
-
const pos3D = toRotation3D(overrides.startPosition);
|
|
923
|
-
setUniform("startPosMinX", pos3D[0][0]);
|
|
924
|
-
setUniform("startPosMaxX", pos3D[0][1]);
|
|
925
|
-
setUniform("startPosMinY", pos3D[1][0]);
|
|
926
|
-
setUniform("startPosMaxY", pos3D[1][1]);
|
|
927
|
-
setUniform("startPosMinZ", pos3D[2][0]);
|
|
928
|
-
setUniform("startPosMaxZ", pos3D[2][1]);
|
|
929
|
-
}
|
|
930
|
-
if (overrides.gravity !== void 0) {
|
|
931
|
-
saved.gravity = uniforms.gravity.value.clone();
|
|
932
|
-
uniforms.gravity.value.set(
|
|
933
|
-
...overrides.gravity
|
|
934
|
-
);
|
|
935
|
-
}
|
|
936
|
-
const u = uniforms;
|
|
937
|
-
if (overrides.colorStart !== void 0) {
|
|
938
|
-
const colors = overrides.colorStart.slice(0, 8).map(hexToRgb);
|
|
939
|
-
while (colors.length < 8)
|
|
940
|
-
colors.push(colors[colors.length - 1] || [1, 1, 1]);
|
|
941
|
-
setUniform("colorStartCount", overrides.colorStart.length);
|
|
942
|
-
colors.forEach((c, i) => {
|
|
943
|
-
if (u[`colorStart${i}`]) {
|
|
944
|
-
saved[`colorStart${i}`] = u[`colorStart${i}`].value.clone();
|
|
945
|
-
u[`colorStart${i}`].value.setRGB(...c);
|
|
946
|
-
}
|
|
947
|
-
});
|
|
948
|
-
}
|
|
949
|
-
if (overrides.colorEnd !== void 0) {
|
|
950
|
-
const colors = overrides.colorEnd.slice(0, 8).map(hexToRgb);
|
|
951
|
-
while (colors.length < 8)
|
|
952
|
-
colors.push(colors[colors.length - 1] || [1, 1, 1]);
|
|
953
|
-
setUniform("colorEndCount", overrides.colorEnd.length);
|
|
954
|
-
colors.forEach((c, i) => {
|
|
955
|
-
if (u[`colorEnd${i}`]) {
|
|
956
|
-
saved[`colorEnd${i}`] = u[`colorEnd${i}`].value.clone();
|
|
957
|
-
u[`colorEnd${i}`].value.setRGB(...c);
|
|
958
|
-
}
|
|
959
|
-
});
|
|
960
|
-
}
|
|
961
|
-
if (overrides.rotation !== void 0) {
|
|
962
|
-
const rot3D = toRotation3D(overrides.rotation);
|
|
963
|
-
setUniform("rotationMinX", rot3D[0][0]);
|
|
964
|
-
setUniform("rotationMaxX", rot3D[0][1]);
|
|
965
|
-
setUniform("rotationMinY", rot3D[1][0]);
|
|
966
|
-
setUniform("rotationMaxY", rot3D[1][1]);
|
|
967
|
-
setUniform("rotationMinZ", rot3D[2][0]);
|
|
968
|
-
setUniform("rotationMaxZ", rot3D[2][1]);
|
|
969
|
-
}
|
|
970
|
-
if (overrides.emitterShape !== void 0) {
|
|
971
|
-
setUniform("emitterShapeType", overrides.emitterShape);
|
|
972
|
-
}
|
|
973
|
-
if (overrides.emitterRadius !== void 0) {
|
|
974
|
-
const range = toRange(overrides.emitterRadius, [0, 1]);
|
|
975
|
-
setUniform("emitterRadiusInner", range[0]);
|
|
976
|
-
setUniform("emitterRadiusOuter", range[1]);
|
|
977
|
-
}
|
|
978
|
-
if (overrides.emitterAngle !== void 0) {
|
|
979
|
-
setUniform("emitterAngle", overrides.emitterAngle);
|
|
980
|
-
}
|
|
981
|
-
if (overrides.emitterHeight !== void 0) {
|
|
982
|
-
const range = toRange(overrides.emitterHeight, [0, 1]);
|
|
983
|
-
setUniform("emitterHeightMin", range[0]);
|
|
984
|
-
setUniform("emitterHeightMax", range[1]);
|
|
985
|
-
}
|
|
986
|
-
if (overrides.emitterSurfaceOnly !== void 0) {
|
|
987
|
-
setUniform("emitterSurfaceOnly", overrides.emitterSurfaceOnly ? 1 : 0);
|
|
988
|
-
}
|
|
989
|
-
if (overrides.emitterDirection !== void 0) {
|
|
990
|
-
saved.emitterDir = uniforms.emitterDir.value.clone();
|
|
991
|
-
uniforms.emitterDir.value.set(...overrides.emitterDirection).normalize();
|
|
992
|
-
}
|
|
993
|
-
return () => {
|
|
994
|
-
Object.entries(saved).forEach(([key, value]) => {
|
|
995
|
-
if (uniforms[key]) {
|
|
996
|
-
uniforms[key].value = value;
|
|
997
|
-
}
|
|
998
|
-
});
|
|
999
|
-
};
|
|
1000
|
-
},
|
|
1001
|
-
[uniforms]
|
|
1002
|
-
);
|
|
1003
|
-
const spawnInternal = useCallback(
|
|
1004
|
-
(x, y, z, count = 20, overrides = null) => {
|
|
1005
|
-
if (!initialized.current || !renderer) return;
|
|
1006
|
-
const restore = applySpawnOverrides(overrides);
|
|
1007
|
-
const startIdx = nextIndex.current;
|
|
1008
|
-
const endIdx = (startIdx + count) % activeMaxParticles;
|
|
1009
|
-
uniforms.spawnPosition.value.set(x, y, z);
|
|
1010
|
-
uniforms.spawnIndexStart.value = startIdx;
|
|
1011
|
-
uniforms.spawnIndexEnd.value = endIdx;
|
|
1012
|
-
uniforms.spawnSeed.value = Math.random() * 1e4;
|
|
1013
|
-
nextIndex.current = endIdx;
|
|
1014
|
-
renderer.computeAsync(computeSpawn);
|
|
1015
|
-
if (restore) restore();
|
|
1016
|
-
},
|
|
1017
|
-
[
|
|
1018
|
-
renderer,
|
|
1019
|
-
computeSpawn,
|
|
1020
|
-
uniforms,
|
|
1021
|
-
activeMaxParticles,
|
|
1022
|
-
applySpawnOverrides
|
|
1023
|
-
]
|
|
1024
|
-
);
|
|
1025
396
|
const spawn = useCallback(
|
|
1026
397
|
(x = 0, y = 0, z = 0, count = 20, overrides = null) => {
|
|
1027
|
-
|
|
1028
|
-
|
|
1029
|
-
spawnInternal(px + x, py + y, pz + z, count, overrides);
|
|
398
|
+
const [px, py, pz] = system.position;
|
|
399
|
+
system.spawn(px + x, py + y, pz + z, count, overrides);
|
|
1030
400
|
},
|
|
1031
|
-
[
|
|
401
|
+
[system]
|
|
1032
402
|
);
|
|
1033
|
-
|
|
1034
|
-
|
|
1035
|
-
|
|
1036
|
-
}, [computeUpdate]);
|
|
1037
|
-
useFrame(async (state, delta) => {
|
|
1038
|
-
var _a2, _b;
|
|
1039
|
-
if (!initialized.current || !renderer) return;
|
|
1040
|
-
uniforms.deltaTime.value = delta;
|
|
1041
|
-
const turbSpeed = (_b = (_a2 = turbulenceRef.current) == null ? void 0 : _a2.speed) != null ? _b : 1;
|
|
1042
|
-
uniforms.turbulenceTime.value += delta * turbSpeed;
|
|
1043
|
-
await renderer.computeAsync(computeUpdateRef.current);
|
|
403
|
+
useFrame(async (_state, delta) => {
|
|
404
|
+
if (!system.initialized) return;
|
|
405
|
+
await system.update(delta);
|
|
1044
406
|
if (emitting) {
|
|
1045
|
-
|
|
1046
|
-
const currentDelay = delayRef.current;
|
|
1047
|
-
const currentEmitCount = emitCountRef.current;
|
|
1048
|
-
if (!currentDelay) {
|
|
1049
|
-
spawnInternal(px, py, pz, currentEmitCount);
|
|
1050
|
-
} else {
|
|
1051
|
-
emitAccumulator.current += delta;
|
|
1052
|
-
if (emitAccumulator.current >= currentDelay) {
|
|
1053
|
-
emitAccumulator.current -= currentDelay;
|
|
1054
|
-
spawnInternal(px, py, pz, currentEmitCount);
|
|
1055
|
-
}
|
|
1056
|
-
}
|
|
407
|
+
system.autoEmit(delta);
|
|
1057
408
|
}
|
|
1058
409
|
});
|
|
1059
410
|
const start = useCallback(() => {
|
|
411
|
+
system.start();
|
|
1060
412
|
setEmitting(true);
|
|
1061
|
-
|
|
1062
|
-
}, []);
|
|
413
|
+
}, [system]);
|
|
1063
414
|
const stop = useCallback(() => {
|
|
415
|
+
system.stop();
|
|
1064
416
|
setEmitting(false);
|
|
1065
|
-
}, []);
|
|
1066
|
-
const prevMaterialRef =
|
|
1067
|
-
const prevRenderObjectRef =
|
|
1068
|
-
|
|
1069
|
-
if (prevMaterialRef.current && prevMaterialRef.current !== material) {
|
|
417
|
+
}, [system]);
|
|
418
|
+
const prevMaterialRef = useRef(null);
|
|
419
|
+
const prevRenderObjectRef = useRef(null);
|
|
420
|
+
useEffect(() => {
|
|
421
|
+
if (prevMaterialRef.current && prevMaterialRef.current !== system.material) {
|
|
1070
422
|
prevMaterialRef.current.dispose();
|
|
1071
423
|
}
|
|
1072
|
-
prevMaterialRef.current = material;
|
|
1073
|
-
if (prevRenderObjectRef.current && prevRenderObjectRef.current !== renderObject) {
|
|
424
|
+
prevMaterialRef.current = system.material;
|
|
425
|
+
if (prevRenderObjectRef.current && prevRenderObjectRef.current !== system.renderObject) {
|
|
1074
426
|
if (prevRenderObjectRef.current.material) {
|
|
1075
427
|
prevRenderObjectRef.current.material.dispose();
|
|
1076
428
|
}
|
|
1077
429
|
}
|
|
1078
|
-
prevRenderObjectRef.current = renderObject;
|
|
1079
|
-
}, [material, renderObject]);
|
|
1080
|
-
|
|
430
|
+
prevRenderObjectRef.current = system.renderObject;
|
|
431
|
+
}, [system.material, system.renderObject]);
|
|
432
|
+
useEffect(() => {
|
|
1081
433
|
return () => {
|
|
1082
|
-
|
|
1083
|
-
material.dispose();
|
|
1084
|
-
}
|
|
1085
|
-
if (renderObject) {
|
|
1086
|
-
if (renderObject.geometry && !geometry) {
|
|
1087
|
-
renderObject.geometry.dispose();
|
|
1088
|
-
}
|
|
1089
|
-
if (renderObject.material) {
|
|
1090
|
-
renderObject.material.dispose();
|
|
1091
|
-
}
|
|
1092
|
-
}
|
|
1093
|
-
initialized.current = false;
|
|
1094
|
-
nextIndex.current = 0;
|
|
434
|
+
system.dispose();
|
|
1095
435
|
};
|
|
1096
436
|
}, []);
|
|
1097
|
-
const particleAPI =
|
|
437
|
+
const particleAPI = useMemo(
|
|
1098
438
|
() => ({
|
|
1099
439
|
spawn,
|
|
1100
440
|
start,
|
|
@@ -1103,266 +443,93 @@ var VFXParticles = forwardRef(
|
|
|
1103
443
|
return emitting;
|
|
1104
444
|
},
|
|
1105
445
|
clear() {
|
|
1106
|
-
|
|
1107
|
-
nextIndex.current = 0;
|
|
446
|
+
system.clear();
|
|
1108
447
|
},
|
|
1109
|
-
uniforms
|
|
448
|
+
uniforms: system.uniforms
|
|
1110
449
|
}),
|
|
1111
|
-
[spawn, start, stop, emitting,
|
|
450
|
+
[spawn, start, stop, emitting, system]
|
|
1112
451
|
);
|
|
1113
452
|
useImperativeHandle(ref, () => particleAPI, [particleAPI]);
|
|
1114
453
|
const registerParticles = useVFXStore((s) => s.registerParticles);
|
|
1115
454
|
const unregisterParticles = useVFXStore((s) => s.unregisterParticles);
|
|
1116
|
-
|
|
455
|
+
useEffect(() => {
|
|
1117
456
|
if (!name) return;
|
|
1118
457
|
registerParticles(name, particleAPI);
|
|
1119
458
|
return () => {
|
|
1120
459
|
unregisterParticles(name);
|
|
1121
460
|
};
|
|
1122
461
|
}, [name, particleAPI, registerParticles, unregisterParticles]);
|
|
1123
|
-
const
|
|
1124
|
-
const
|
|
1125
|
-
const prevGeometryArgsRef = useRef2(null);
|
|
462
|
+
const prevGeometryTypeRef = useRef(null);
|
|
463
|
+
const prevGeometryArgsRef = useRef(null);
|
|
1126
464
|
const handleDebugUpdate = useCallback(
|
|
1127
465
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
1128
466
|
(newValues) => {
|
|
1129
|
-
var _a2, _b, _c, _d, _e, _f, _g, _h, _i, _j
|
|
467
|
+
var _a2, _b, _c, _d, _e, _f, _g, _h, _i, _j;
|
|
1130
468
|
debugValuesRef.current = __spreadValues(__spreadValues({}, debugValuesRef.current), newValues);
|
|
1131
|
-
if ("
|
|
1132
|
-
const
|
|
1133
|
-
|
|
1134
|
-
|
|
1135
|
-
|
|
1136
|
-
|
|
1137
|
-
|
|
1138
|
-
uniforms.fadeSizeStart.value = fadeSizeR[0];
|
|
1139
|
-
uniforms.fadeSizeEnd.value = fadeSizeR[1];
|
|
469
|
+
if ("colorStart" in newValues && newValues.colorStart) {
|
|
470
|
+
const currentColorEnd = (_a2 = debugValuesRef.current) == null ? void 0 : _a2.colorEnd;
|
|
471
|
+
if (!currentColorEnd) {
|
|
472
|
+
newValues = __spreadProps(__spreadValues({}, newValues), {
|
|
473
|
+
colorEnd: null
|
|
474
|
+
});
|
|
475
|
+
}
|
|
1140
476
|
}
|
|
1141
|
-
if ("
|
|
1142
|
-
|
|
1143
|
-
|
|
1144
|
-
|
|
477
|
+
if ("colorEnd" in newValues && !newValues.colorEnd) {
|
|
478
|
+
newValues = __spreadProps(__spreadValues({}, newValues), {
|
|
479
|
+
colorEnd: null,
|
|
480
|
+
// Ensure updateUniformsPartial gets the right fallback
|
|
481
|
+
colorStart: (_d = (_c = newValues.colorStart) != null ? _c : (_b = debugValuesRef.current) == null ? void 0 : _b.colorStart) != null ? _d : ["#ffffff"]
|
|
482
|
+
});
|
|
1145
483
|
}
|
|
484
|
+
updateUniformsPartial(system.uniforms, newValues);
|
|
1146
485
|
if ("fadeSizeCurve" in newValues) {
|
|
1147
486
|
setActiveFadeSizeCurve(newValues.fadeSizeCurve);
|
|
1148
|
-
uniforms.fadeSizeCurveEnabled.value = newValues.fadeSizeCurve ? 1 : 0;
|
|
1149
487
|
}
|
|
1150
488
|
if ("fadeOpacityCurve" in newValues) {
|
|
1151
489
|
setActiveFadeOpacityCurve(newValues.fadeOpacityCurve);
|
|
1152
|
-
uniforms.fadeOpacityCurveEnabled.value = newValues.fadeOpacityCurve ? 1 : 0;
|
|
1153
490
|
}
|
|
1154
491
|
if ("velocityCurve" in newValues) {
|
|
1155
492
|
setActiveVelocityCurve(newValues.velocityCurve);
|
|
1156
|
-
uniforms.velocityCurveEnabled.value = newValues.velocityCurve ? 1 : 0;
|
|
1157
493
|
}
|
|
1158
494
|
if ("rotationSpeedCurve" in newValues) {
|
|
1159
495
|
setActiveRotationSpeedCurve(newValues.rotationSpeedCurve);
|
|
1160
|
-
uniforms.rotationSpeedCurveEnabled.value = newValues.rotationSpeedCurve ? 1 : 0;
|
|
1161
|
-
}
|
|
1162
|
-
if ("orientAxis" in newValues) {
|
|
1163
|
-
uniforms.orientAxisType.value = axisToNumber(newValues.orientAxis);
|
|
1164
|
-
}
|
|
1165
|
-
if ("stretchBySpeed" in newValues) {
|
|
1166
|
-
uniforms.stretchEnabled.value = newValues.stretchBySpeed ? 1 : 0;
|
|
1167
|
-
uniforms.stretchFactor.value = (_b = (_a2 = newValues.stretchBySpeed) == null ? void 0 : _a2.factor) != null ? _b : 1;
|
|
1168
|
-
uniforms.stretchMax.value = (_d = (_c = newValues.stretchBySpeed) == null ? void 0 : _c.maxStretch) != null ? _d : 5;
|
|
1169
|
-
}
|
|
1170
|
-
if (newValues.gravity && Array.isArray(newValues.gravity)) {
|
|
1171
|
-
uniforms.gravity.value.x = newValues.gravity[0];
|
|
1172
|
-
uniforms.gravity.value.y = newValues.gravity[1];
|
|
1173
|
-
uniforms.gravity.value.z = newValues.gravity[2];
|
|
1174
|
-
}
|
|
1175
|
-
if ("speed" in newValues) {
|
|
1176
|
-
const speedR = toRange(newValues.speed, [0.1, 0.1]);
|
|
1177
|
-
uniforms.speedMin.value = speedR[0];
|
|
1178
|
-
uniforms.speedMax.value = speedR[1];
|
|
1179
|
-
}
|
|
1180
|
-
if ("lifetime" in newValues) {
|
|
1181
|
-
const lifetimeR = toRange(newValues.lifetime, [1, 2]);
|
|
1182
|
-
uniforms.lifetimeMin.value = 1 / lifetimeR[1];
|
|
1183
|
-
uniforms.lifetimeMax.value = 1 / lifetimeR[0];
|
|
1184
|
-
}
|
|
1185
|
-
if ("friction" in newValues && newValues.friction) {
|
|
1186
|
-
const frictionR = toRange(newValues.friction.intensity, [0, 0]);
|
|
1187
|
-
uniforms.frictionIntensityStart.value = frictionR[0];
|
|
1188
|
-
uniforms.frictionIntensityEnd.value = frictionR[1];
|
|
1189
|
-
uniforms.frictionEasingType.value = easingToType(
|
|
1190
|
-
newValues.friction.easing
|
|
1191
|
-
);
|
|
1192
|
-
}
|
|
1193
|
-
if ("direction" in newValues) {
|
|
1194
|
-
const dir3D = toRotation3D(newValues.direction);
|
|
1195
|
-
uniforms.dirMinX.value = dir3D[0][0];
|
|
1196
|
-
uniforms.dirMaxX.value = dir3D[0][1];
|
|
1197
|
-
uniforms.dirMinY.value = dir3D[1][0];
|
|
1198
|
-
uniforms.dirMaxY.value = dir3D[1][1];
|
|
1199
|
-
uniforms.dirMinZ.value = dir3D[2][0];
|
|
1200
|
-
uniforms.dirMaxZ.value = dir3D[2][1];
|
|
1201
|
-
}
|
|
1202
|
-
if ("startPosition" in newValues) {
|
|
1203
|
-
const startPos3D = toRotation3D(newValues.startPosition);
|
|
1204
|
-
uniforms.startPosMinX.value = startPos3D[0][0];
|
|
1205
|
-
uniforms.startPosMaxX.value = startPos3D[0][1];
|
|
1206
|
-
uniforms.startPosMinY.value = startPos3D[1][0];
|
|
1207
|
-
uniforms.startPosMaxY.value = startPos3D[1][1];
|
|
1208
|
-
uniforms.startPosMinZ.value = startPos3D[2][0];
|
|
1209
|
-
uniforms.startPosMaxZ.value = startPos3D[2][1];
|
|
1210
|
-
}
|
|
1211
|
-
if ("rotation" in newValues) {
|
|
1212
|
-
const rot3D = toRotation3D(newValues.rotation);
|
|
1213
|
-
uniforms.rotationMinX.value = rot3D[0][0];
|
|
1214
|
-
uniforms.rotationMaxX.value = rot3D[0][1];
|
|
1215
|
-
uniforms.rotationMinY.value = rot3D[1][0];
|
|
1216
|
-
uniforms.rotationMaxY.value = rot3D[1][1];
|
|
1217
|
-
uniforms.rotationMinZ.value = rot3D[2][0];
|
|
1218
|
-
uniforms.rotationMaxZ.value = rot3D[2][1];
|
|
1219
|
-
}
|
|
1220
|
-
if ("rotationSpeed" in newValues) {
|
|
1221
|
-
const rotSpeed3D = toRotation3D(newValues.rotationSpeed);
|
|
1222
|
-
uniforms.rotationSpeedMinX.value = rotSpeed3D[0][0];
|
|
1223
|
-
uniforms.rotationSpeedMaxX.value = rotSpeed3D[0][1];
|
|
1224
|
-
uniforms.rotationSpeedMinY.value = rotSpeed3D[1][0];
|
|
1225
|
-
uniforms.rotationSpeedMaxY.value = rotSpeed3D[1][1];
|
|
1226
|
-
uniforms.rotationSpeedMinZ.value = rotSpeed3D[2][0];
|
|
1227
|
-
uniforms.rotationSpeedMaxZ.value = rotSpeed3D[2][1];
|
|
1228
|
-
}
|
|
1229
|
-
if ("rotation" in newValues || "rotationSpeed" in newValues) {
|
|
1230
|
-
const rot = (_g = (_f = newValues.rotation) != null ? _f : (_e = debugValuesRef.current) == null ? void 0 : _e.rotation) != null ? _g : [0, 0];
|
|
1231
|
-
const rotSpeed = (_j = (_i = newValues.rotationSpeed) != null ? _i : (_h = debugValuesRef.current) == null ? void 0 : _h.rotationSpeed) != null ? _j : [0, 0];
|
|
1232
|
-
const needsRotation = isNonDefaultRotation(rot) || isNonDefaultRotation(rotSpeed);
|
|
1233
|
-
if (needsRotation !== activeNeedsRotation) {
|
|
1234
|
-
setActiveNeedsRotation(needsRotation);
|
|
1235
|
-
}
|
|
1236
|
-
}
|
|
1237
|
-
if ("intensity" in newValues) {
|
|
1238
|
-
uniforms.intensity.value = newValues.intensity || 1;
|
|
1239
|
-
}
|
|
1240
|
-
if ("colorStart" in newValues && newValues.colorStart) {
|
|
1241
|
-
const startColors2 = newValues.colorStart.slice(0, 8).map(hexToRgb);
|
|
1242
|
-
while (startColors2.length < 8)
|
|
1243
|
-
startColors2.push(startColors2[startColors2.length - 1] || [1, 1, 1]);
|
|
1244
|
-
uniforms.colorStartCount.value = newValues.colorStart.length;
|
|
1245
|
-
startColors2.forEach((c, i) => {
|
|
1246
|
-
if (uniforms[`colorStart${i}`]) {
|
|
1247
|
-
uniforms[`colorStart${i}`].value.setRGB(...c);
|
|
1248
|
-
}
|
|
1249
|
-
});
|
|
1250
|
-
const currentColorEnd = (_k = debugValuesRef.current) == null ? void 0 : _k.colorEnd;
|
|
1251
|
-
if (!currentColorEnd) {
|
|
1252
|
-
uniforms.colorEndCount.value = newValues.colorStart.length;
|
|
1253
|
-
startColors2.forEach((c, i) => {
|
|
1254
|
-
if (uniforms[`colorEnd${i}`]) {
|
|
1255
|
-
uniforms[`colorEnd${i}`].value.setRGB(...c);
|
|
1256
|
-
}
|
|
1257
|
-
});
|
|
1258
|
-
}
|
|
1259
|
-
}
|
|
1260
|
-
if ("colorEnd" in newValues) {
|
|
1261
|
-
const effectiveEndColors = newValues.colorEnd || newValues.colorStart || ((_l = debugValuesRef.current) == null ? void 0 : _l.colorStart) || ["#ffffff"];
|
|
1262
|
-
if (effectiveEndColors) {
|
|
1263
|
-
const endColors2 = effectiveEndColors.slice(0, 8).map(hexToRgb);
|
|
1264
|
-
while (endColors2.length < 8)
|
|
1265
|
-
endColors2.push(endColors2[endColors2.length - 1] || [1, 1, 1]);
|
|
1266
|
-
uniforms.colorEndCount.value = effectiveEndColors.length;
|
|
1267
|
-
endColors2.forEach((c, i) => {
|
|
1268
|
-
if (uniforms[`colorEnd${i}`]) {
|
|
1269
|
-
uniforms[`colorEnd${i}`].value.setRGB(...c);
|
|
1270
|
-
}
|
|
1271
|
-
});
|
|
1272
|
-
}
|
|
1273
|
-
}
|
|
1274
|
-
if ("colorStart" in newValues || "colorEnd" in newValues) {
|
|
1275
|
-
const startLen = (_q = (_p = (_m = newValues.colorStart) == null ? void 0 : _m.length) != null ? _p : (_o = (_n = debugValuesRef.current) == null ? void 0 : _n.colorStart) == null ? void 0 : _o.length) != null ? _q : 1;
|
|
1276
|
-
const hasColorEnd = "colorEnd" in newValues ? newValues.colorEnd !== null : ((_r = debugValuesRef.current) == null ? void 0 : _r.colorEnd) !== null;
|
|
1277
|
-
const needsPerParticle = startLen > 1 || hasColorEnd;
|
|
1278
|
-
if (needsPerParticle !== activeNeedsPerParticleColor) {
|
|
1279
|
-
setActiveNeedsPerParticleColor(needsPerParticle);
|
|
1280
|
-
}
|
|
1281
|
-
}
|
|
1282
|
-
if ("emitterShape" in newValues) {
|
|
1283
|
-
uniforms.emitterShapeType.value = (_s = newValues.emitterShape) != null ? _s : EmitterShape.BOX;
|
|
1284
|
-
}
|
|
1285
|
-
if ("emitterRadius" in newValues) {
|
|
1286
|
-
const emitterRadiusR = toRange(newValues.emitterRadius, [0, 1]);
|
|
1287
|
-
uniforms.emitterRadiusInner.value = emitterRadiusR[0];
|
|
1288
|
-
uniforms.emitterRadiusOuter.value = emitterRadiusR[1];
|
|
1289
|
-
}
|
|
1290
|
-
if ("emitterAngle" in newValues) {
|
|
1291
|
-
uniforms.emitterAngle.value = (_t = newValues.emitterAngle) != null ? _t : Math.PI / 4;
|
|
1292
|
-
}
|
|
1293
|
-
if ("emitterHeight" in newValues) {
|
|
1294
|
-
const emitterHeightR = toRange(newValues.emitterHeight, [0, 1]);
|
|
1295
|
-
uniforms.emitterHeightMin.value = emitterHeightR[0];
|
|
1296
|
-
uniforms.emitterHeightMax.value = emitterHeightR[1];
|
|
1297
|
-
}
|
|
1298
|
-
if ("emitterSurfaceOnly" in newValues) {
|
|
1299
|
-
uniforms.emitterSurfaceOnly.value = newValues.emitterSurfaceOnly ? 1 : 0;
|
|
1300
|
-
}
|
|
1301
|
-
if ("emitterDirection" in newValues && newValues.emitterDirection && Array.isArray(newValues.emitterDirection)) {
|
|
1302
|
-
const dir = new THREE.Vector3(
|
|
1303
|
-
...newValues.emitterDirection
|
|
1304
|
-
).normalize();
|
|
1305
|
-
uniforms.emitterDir.value.x = dir.x;
|
|
1306
|
-
uniforms.emitterDir.value.y = dir.y;
|
|
1307
|
-
uniforms.emitterDir.value.z = dir.z;
|
|
1308
496
|
}
|
|
1309
497
|
if ("turbulence" in newValues) {
|
|
1310
|
-
|
|
1311
|
-
uniforms.turbulenceFrequency.value = (_x = (_w = newValues.turbulence) == null ? void 0 : _w.frequency) != null ? _x : 1;
|
|
1312
|
-
uniforms.turbulenceSpeed.value = (_z = (_y = newValues.turbulence) == null ? void 0 : _y.speed) != null ? _z : 1;
|
|
1313
|
-
turbulenceRef.current = newValues.turbulence;
|
|
1314
|
-
const needsTurbulence = newValues.turbulence !== null && ((_B = (_A = newValues.turbulence) == null ? void 0 : _A.intensity) != null ? _B : 0) > 0;
|
|
1315
|
-
if (needsTurbulence !== activeTurbulence) {
|
|
1316
|
-
setActiveTurbulence(needsTurbulence);
|
|
1317
|
-
}
|
|
498
|
+
system.setTurbulenceSpeed((_f = (_e = newValues.turbulence) == null ? void 0 : _e.speed) != null ? _f : 1);
|
|
1318
499
|
}
|
|
1319
|
-
|
|
1320
|
-
|
|
500
|
+
const newFeatures = resolveFeatures(debugValuesRef.current);
|
|
501
|
+
if (newFeatures.needsRotation !== activeNeedsRotation) {
|
|
502
|
+
setActiveNeedsRotation(newFeatures.needsRotation);
|
|
1321
503
|
}
|
|
1322
|
-
if (
|
|
1323
|
-
|
|
504
|
+
if (newFeatures.needsPerParticleColor !== activeNeedsPerParticleColor) {
|
|
505
|
+
setActiveNeedsPerParticleColor(newFeatures.needsPerParticleColor);
|
|
1324
506
|
}
|
|
1325
|
-
if (
|
|
1326
|
-
|
|
507
|
+
if (newFeatures.turbulence !== activeTurbulence) {
|
|
508
|
+
setActiveTurbulence(newFeatures.turbulence);
|
|
1327
509
|
}
|
|
1328
|
-
if (
|
|
1329
|
-
|
|
510
|
+
if (newFeatures.attractors !== activeAttractors) {
|
|
511
|
+
setActiveAttractors(newFeatures.attractors);
|
|
1330
512
|
}
|
|
1331
|
-
if (
|
|
1332
|
-
|
|
1333
|
-
uniforms.collisionPlaneY.value = (_F = (_E = (_D = newValues.collision) == null ? void 0 : _D.plane) == null ? void 0 : _E.y) != null ? _F : 0;
|
|
1334
|
-
uniforms.collisionBounce.value = (_H = (_G = newValues.collision) == null ? void 0 : _G.bounce) != null ? _H : 0.3;
|
|
1335
|
-
uniforms.collisionFriction.value = (_J = (_I = newValues.collision) == null ? void 0 : _I.friction) != null ? _J : 0.8;
|
|
1336
|
-
uniforms.collisionDie.value = ((_K = newValues.collision) == null ? void 0 : _K.die) ? 1 : 0;
|
|
1337
|
-
uniforms.sizeBasedGravity.value = (_M = (_L = newValues.collision) == null ? void 0 : _L.sizeBasedGravity) != null ? _M : 0;
|
|
1338
|
-
const needsCollision = newValues.collision !== null && newValues.collision !== void 0;
|
|
1339
|
-
if (needsCollision !== activeCollision) {
|
|
1340
|
-
setActiveCollision(needsCollision);
|
|
1341
|
-
}
|
|
1342
|
-
}
|
|
1343
|
-
if ("attractors" in newValues) {
|
|
1344
|
-
const needsAttractors = newValues.attractors !== null && ((_N = newValues.attractors) == null ? void 0 : _N.length) > 0;
|
|
1345
|
-
if (needsAttractors !== activeAttractors) {
|
|
1346
|
-
setActiveAttractors(needsAttractors);
|
|
1347
|
-
}
|
|
513
|
+
if (newFeatures.collision !== activeCollision) {
|
|
514
|
+
setActiveCollision(newFeatures.collision);
|
|
1348
515
|
}
|
|
1349
516
|
if (newValues.position) {
|
|
1350
|
-
|
|
517
|
+
system.setPosition(newValues.position);
|
|
1351
518
|
}
|
|
1352
|
-
if ("delay" in newValues)
|
|
519
|
+
if ("delay" in newValues) system.setDelay((_g = newValues.delay) != null ? _g : 0);
|
|
1353
520
|
if ("emitCount" in newValues)
|
|
1354
|
-
|
|
521
|
+
system.setEmitCount((_h = newValues.emitCount) != null ? _h : 1);
|
|
1355
522
|
if (newValues.autoStart !== void 0) {
|
|
1356
523
|
setEmitting(newValues.autoStart);
|
|
1357
524
|
}
|
|
1358
|
-
if (material && newValues.blending !== void 0) {
|
|
1359
|
-
material.blending = newValues.blending;
|
|
1360
|
-
material.needsUpdate = true;
|
|
525
|
+
if (system.material && newValues.blending !== void 0) {
|
|
526
|
+
system.material.blending = newValues.blending;
|
|
527
|
+
system.material.needsUpdate = true;
|
|
1361
528
|
}
|
|
1362
529
|
if (newValues.maxParticles !== void 0 && newValues.maxParticles !== activeMaxParticles) {
|
|
1363
530
|
setActiveMaxParticles(newValues.maxParticles);
|
|
1364
|
-
initialized
|
|
1365
|
-
nextIndex
|
|
531
|
+
system.initialized = false;
|
|
532
|
+
system.nextIndex = 0;
|
|
1366
533
|
}
|
|
1367
534
|
if (newValues.lighting !== void 0 && newValues.lighting !== activeLighting) {
|
|
1368
535
|
setActiveLighting(newValues.lighting);
|
|
@@ -1377,8 +544,8 @@ var VFXParticles = forwardRef(
|
|
|
1377
544
|
setActiveShadow(newValues.shadow);
|
|
1378
545
|
}
|
|
1379
546
|
if ("geometryType" in newValues || "geometryArgs" in newValues) {
|
|
1380
|
-
const geoType = (
|
|
1381
|
-
const geoArgs = (
|
|
547
|
+
const geoType = (_i = newValues.geometryType) != null ? _i : prevGeometryTypeRef.current;
|
|
548
|
+
const geoArgs = (_j = newValues.geometryArgs) != null ? _j : prevGeometryArgsRef.current;
|
|
1382
549
|
const geoTypeChanged = "geometryType" in newValues && geoType !== prevGeometryTypeRef.current;
|
|
1383
550
|
const geoArgsChanged = "geometryArgs" in newValues && JSON.stringify(geoArgs) !== JSON.stringify(prevGeometryArgsRef.current);
|
|
1384
551
|
if (geoTypeChanged || geoArgsChanged) {
|
|
@@ -1404,9 +571,7 @@ var VFXParticles = forwardRef(
|
|
|
1404
571
|
}
|
|
1405
572
|
},
|
|
1406
573
|
[
|
|
1407
|
-
|
|
1408
|
-
material,
|
|
1409
|
-
renderObject,
|
|
574
|
+
system,
|
|
1410
575
|
activeMaxParticles,
|
|
1411
576
|
activeLighting,
|
|
1412
577
|
activeAppearance,
|
|
@@ -1421,202 +586,68 @@ var VFXParticles = forwardRef(
|
|
|
1421
586
|
geometry
|
|
1422
587
|
]
|
|
1423
588
|
);
|
|
1424
|
-
|
|
589
|
+
useEffect(() => {
|
|
1425
590
|
if (!debug) return;
|
|
1426
|
-
|
|
1427
|
-
|
|
1428
|
-
|
|
1429
|
-
|
|
1430
|
-
|
|
1431
|
-
|
|
1432
|
-
|
|
1433
|
-
|
|
1434
|
-
|
|
1435
|
-
|
|
1436
|
-
|
|
1437
|
-
|
|
1438
|
-
|
|
1439
|
-
|
|
1440
|
-
|
|
1441
|
-
|
|
1442
|
-
|
|
1443
|
-
|
|
1444
|
-
|
|
1445
|
-
|
|
1446
|
-
|
|
1447
|
-
|
|
1448
|
-
|
|
1449
|
-
|
|
1450
|
-
|
|
1451
|
-
|
|
1452
|
-
|
|
1453
|
-
|
|
1454
|
-
|
|
1455
|
-
|
|
1456
|
-
|
|
1457
|
-
|
|
1458
|
-
|
|
1459
|
-
|
|
1460
|
-
|
|
1461
|
-
|
|
1462
|
-
|
|
1463
|
-
|
|
1464
|
-
|
|
1465
|
-
|
|
1466
|
-
|
|
1467
|
-
|
|
1468
|
-
|
|
1469
|
-
|
|
1470
|
-
|
|
1471
|
-
|
|
1472
|
-
|
|
1473
|
-
|
|
1474
|
-
|
|
1475
|
-
|
|
1476
|
-
|
|
1477
|
-
var _a2, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n, _o, _p, _q, _r, _s, _t, _u, _v, _w, _x, _y, _z, _A, _B, _C, _D, _E, _F, _G, _H, _I, _J, _K, _L, _M, _N, _O, _P, _Q;
|
|
1478
|
-
if (!geo) return { geometryType: "none", geometryArgs: null };
|
|
1479
|
-
const name2 = geo.constructor.name;
|
|
1480
|
-
const params = geo.parameters || {};
|
|
1481
|
-
switch (name2) {
|
|
1482
|
-
case "BoxGeometry":
|
|
1483
|
-
return {
|
|
1484
|
-
geometryType: "box",
|
|
1485
|
-
geometryArgs: {
|
|
1486
|
-
width: (_a2 = params.width) != null ? _a2 : 1,
|
|
1487
|
-
height: (_b = params.height) != null ? _b : 1,
|
|
1488
|
-
depth: (_c = params.depth) != null ? _c : 1,
|
|
1489
|
-
widthSegments: (_d = params.widthSegments) != null ? _d : 1,
|
|
1490
|
-
heightSegments: (_e = params.heightSegments) != null ? _e : 1,
|
|
1491
|
-
depthSegments: (_f = params.depthSegments) != null ? _f : 1
|
|
1492
|
-
}
|
|
1493
|
-
};
|
|
1494
|
-
case "SphereGeometry":
|
|
1495
|
-
return {
|
|
1496
|
-
geometryType: "sphere",
|
|
1497
|
-
geometryArgs: {
|
|
1498
|
-
radius: (_g = params.radius) != null ? _g : 0.5,
|
|
1499
|
-
widthSegments: (_h = params.widthSegments) != null ? _h : 16,
|
|
1500
|
-
heightSegments: (_i = params.heightSegments) != null ? _i : 12
|
|
1501
|
-
}
|
|
1502
|
-
};
|
|
1503
|
-
case "CylinderGeometry":
|
|
1504
|
-
return {
|
|
1505
|
-
geometryType: "cylinder",
|
|
1506
|
-
geometryArgs: {
|
|
1507
|
-
radiusTop: (_j = params.radiusTop) != null ? _j : 0.5,
|
|
1508
|
-
radiusBottom: (_k = params.radiusBottom) != null ? _k : 0.5,
|
|
1509
|
-
height: (_l = params.height) != null ? _l : 1,
|
|
1510
|
-
radialSegments: (_m = params.radialSegments) != null ? _m : 16,
|
|
1511
|
-
heightSegments: (_n = params.heightSegments) != null ? _n : 1
|
|
1512
|
-
}
|
|
1513
|
-
};
|
|
1514
|
-
case "ConeGeometry":
|
|
1515
|
-
return {
|
|
1516
|
-
geometryType: "cone",
|
|
1517
|
-
geometryArgs: {
|
|
1518
|
-
radius: (_o = params.radius) != null ? _o : 0.5,
|
|
1519
|
-
height: (_p = params.height) != null ? _p : 1,
|
|
1520
|
-
radialSegments: (_q = params.radialSegments) != null ? _q : 16,
|
|
1521
|
-
heightSegments: (_r = params.heightSegments) != null ? _r : 1
|
|
1522
|
-
}
|
|
1523
|
-
};
|
|
1524
|
-
case "TorusGeometry":
|
|
1525
|
-
return {
|
|
1526
|
-
geometryType: "torus",
|
|
1527
|
-
geometryArgs: {
|
|
1528
|
-
radius: (_s = params.radius) != null ? _s : 0.5,
|
|
1529
|
-
tube: (_t = params.tube) != null ? _t : 0.2,
|
|
1530
|
-
radialSegments: (_u = params.radialSegments) != null ? _u : 12,
|
|
1531
|
-
tubularSegments: (_v = params.tubularSegments) != null ? _v : 24
|
|
1532
|
-
}
|
|
1533
|
-
};
|
|
1534
|
-
case "PlaneGeometry":
|
|
1535
|
-
return {
|
|
1536
|
-
geometryType: "plane",
|
|
1537
|
-
geometryArgs: {
|
|
1538
|
-
width: (_w = params.width) != null ? _w : 1,
|
|
1539
|
-
height: (_x = params.height) != null ? _x : 1,
|
|
1540
|
-
widthSegments: (_y = params.widthSegments) != null ? _y : 1,
|
|
1541
|
-
heightSegments: (_z = params.heightSegments) != null ? _z : 1
|
|
1542
|
-
}
|
|
1543
|
-
};
|
|
1544
|
-
case "CircleGeometry":
|
|
1545
|
-
return {
|
|
1546
|
-
geometryType: "circle",
|
|
1547
|
-
geometryArgs: {
|
|
1548
|
-
radius: (_A = params.radius) != null ? _A : 0.5,
|
|
1549
|
-
segments: (_B = params.segments) != null ? _B : 16
|
|
1550
|
-
}
|
|
1551
|
-
};
|
|
1552
|
-
case "RingGeometry":
|
|
1553
|
-
return {
|
|
1554
|
-
geometryType: "ring",
|
|
1555
|
-
geometryArgs: {
|
|
1556
|
-
innerRadius: (_C = params.innerRadius) != null ? _C : 0.25,
|
|
1557
|
-
outerRadius: (_D = params.outerRadius) != null ? _D : 0.5,
|
|
1558
|
-
thetaSegments: (_E = params.thetaSegments) != null ? _E : 16
|
|
1559
|
-
}
|
|
1560
|
-
};
|
|
1561
|
-
case "DodecahedronGeometry":
|
|
1562
|
-
return {
|
|
1563
|
-
geometryType: "dodecahedron",
|
|
1564
|
-
geometryArgs: {
|
|
1565
|
-
radius: (_F = params.radius) != null ? _F : 0.5,
|
|
1566
|
-
detail: (_G = params.detail) != null ? _G : 0
|
|
1567
|
-
}
|
|
1568
|
-
};
|
|
1569
|
-
case "IcosahedronGeometry":
|
|
1570
|
-
return {
|
|
1571
|
-
geometryType: "icosahedron",
|
|
1572
|
-
geometryArgs: {
|
|
1573
|
-
radius: (_H = params.radius) != null ? _H : 0.5,
|
|
1574
|
-
detail: (_I = params.detail) != null ? _I : 0
|
|
1575
|
-
}
|
|
1576
|
-
};
|
|
1577
|
-
case "OctahedronGeometry":
|
|
1578
|
-
return {
|
|
1579
|
-
geometryType: "octahedron",
|
|
1580
|
-
geometryArgs: {
|
|
1581
|
-
radius: (_J = params.radius) != null ? _J : 0.5,
|
|
1582
|
-
detail: (_K = params.detail) != null ? _K : 0
|
|
1583
|
-
}
|
|
1584
|
-
};
|
|
1585
|
-
case "TetrahedronGeometry":
|
|
1586
|
-
return {
|
|
1587
|
-
geometryType: "tetrahedron",
|
|
1588
|
-
geometryArgs: {
|
|
1589
|
-
radius: (_L = params.radius) != null ? _L : 0.5,
|
|
1590
|
-
detail: (_M = params.detail) != null ? _M : 0
|
|
1591
|
-
}
|
|
1592
|
-
};
|
|
1593
|
-
case "CapsuleGeometry":
|
|
1594
|
-
return {
|
|
1595
|
-
geometryType: "capsule",
|
|
1596
|
-
geometryArgs: {
|
|
1597
|
-
radius: (_N = params.radius) != null ? _N : 0.25,
|
|
1598
|
-
length: (_O = params.length) != null ? _O : 0.5,
|
|
1599
|
-
capSegments: (_P = params.capSegments) != null ? _P : 4,
|
|
1600
|
-
radialSegments: (_Q = params.radialSegments) != null ? _Q : 8
|
|
1601
|
-
}
|
|
1602
|
-
};
|
|
1603
|
-
default:
|
|
1604
|
-
return { geometryType: "none", geometryArgs: null };
|
|
591
|
+
import("debug-vfx").then(
|
|
592
|
+
({ renderDebugPanel, detectGeometryTypeAndArgs }) => {
|
|
593
|
+
const initialValues = __spreadValues({
|
|
594
|
+
name,
|
|
595
|
+
maxParticles,
|
|
596
|
+
size,
|
|
597
|
+
colorStart,
|
|
598
|
+
colorEnd,
|
|
599
|
+
fadeSize,
|
|
600
|
+
fadeSizeCurve: fadeSizeCurve || null,
|
|
601
|
+
fadeOpacity,
|
|
602
|
+
fadeOpacityCurve: fadeOpacityCurve || null,
|
|
603
|
+
velocityCurve: velocityCurve || null,
|
|
604
|
+
gravity,
|
|
605
|
+
lifetime,
|
|
606
|
+
direction,
|
|
607
|
+
startPosition,
|
|
608
|
+
startPositionAsDirection,
|
|
609
|
+
speed,
|
|
610
|
+
friction,
|
|
611
|
+
appearance,
|
|
612
|
+
rotation,
|
|
613
|
+
rotationSpeed,
|
|
614
|
+
rotationSpeedCurve: rotationSpeedCurve || null,
|
|
615
|
+
orientToDirection,
|
|
616
|
+
orientAxis,
|
|
617
|
+
stretchBySpeed: stretchBySpeed || null,
|
|
618
|
+
lighting,
|
|
619
|
+
shadow,
|
|
620
|
+
blending,
|
|
621
|
+
intensity,
|
|
622
|
+
position,
|
|
623
|
+
autoStart,
|
|
624
|
+
delay,
|
|
625
|
+
emitCount,
|
|
626
|
+
emitterShape,
|
|
627
|
+
emitterRadius,
|
|
628
|
+
emitterAngle,
|
|
629
|
+
emitterHeight,
|
|
630
|
+
emitterSurfaceOnly,
|
|
631
|
+
emitterDirection,
|
|
632
|
+
turbulence,
|
|
633
|
+
attractToCenter,
|
|
634
|
+
softParticles,
|
|
635
|
+
softDistance,
|
|
636
|
+
collision
|
|
637
|
+
}, detectGeometryTypeAndArgs(geometry));
|
|
638
|
+
debugValuesRef.current = initialValues;
|
|
639
|
+
prevGeometryTypeRef.current = initialValues.geometryType;
|
|
640
|
+
prevGeometryArgsRef.current = initialValues.geometryArgs;
|
|
641
|
+
renderDebugPanel(initialValues, handleDebugUpdate);
|
|
1605
642
|
}
|
|
1606
|
-
|
|
1607
|
-
debugValuesRef.current = initialValues;
|
|
1608
|
-
prevGeometryTypeRef.current = initialValues.geometryType;
|
|
1609
|
-
prevGeometryArgsRef.current = initialValues.geometryArgs;
|
|
1610
|
-
import("debug-vfx").then(({ renderDebugPanel }) => {
|
|
1611
|
-
renderDebugPanel(initialValues, handleDebugUpdate);
|
|
1612
|
-
});
|
|
643
|
+
);
|
|
1613
644
|
return () => {
|
|
1614
645
|
import("debug-vfx").then(({ destroyDebugPanel }) => {
|
|
1615
646
|
destroyDebugPanel();
|
|
1616
647
|
});
|
|
1617
648
|
};
|
|
1618
649
|
}, [debug, geometry]);
|
|
1619
|
-
|
|
650
|
+
useEffect(() => {
|
|
1620
651
|
if (!debug) return;
|
|
1621
652
|
import("debug-vfx").then(({ updateDebugPanel }) => {
|
|
1622
653
|
if (debugValuesRef.current) {
|
|
@@ -1624,24 +655,46 @@ var VFXParticles = forwardRef(
|
|
|
1624
655
|
}
|
|
1625
656
|
});
|
|
1626
657
|
}, [debug, handleDebugUpdate]);
|
|
1627
|
-
return /* @__PURE__ */ jsx("primitive", { ref: spriteRef, object: renderObject });
|
|
658
|
+
return /* @__PURE__ */ jsx("primitive", { ref: spriteRef, object: system.renderObject });
|
|
659
|
+
}
|
|
660
|
+
);
|
|
661
|
+
var warnedWebGL = false;
|
|
662
|
+
var VFXParticles = forwardRef(
|
|
663
|
+
function VFXParticles2(_a, ref) {
|
|
664
|
+
var _b = _a, { fallback } = _b, props = __objRest(_b, ["fallback"]);
|
|
665
|
+
const { gl } = useThree();
|
|
666
|
+
const isWebGPU = useMemo(() => isWebGPUBackend(gl), [gl]);
|
|
667
|
+
if (!isWebGPU) {
|
|
668
|
+
if (!warnedWebGL) {
|
|
669
|
+
warnedWebGL = true;
|
|
670
|
+
console.warn(
|
|
671
|
+
"r3f-vfx: WebGPU backend not detected. Particle system disabled."
|
|
672
|
+
);
|
|
673
|
+
}
|
|
674
|
+
return /* @__PURE__ */ jsx(Fragment, { children: fallback != null ? fallback : null });
|
|
675
|
+
}
|
|
676
|
+
return /* @__PURE__ */ jsx(VFXParticlesImpl, __spreadValues({ ref }, props));
|
|
1628
677
|
}
|
|
1629
678
|
);
|
|
1630
679
|
|
|
1631
680
|
// src/VFXEmitter.tsx
|
|
1632
681
|
import {
|
|
1633
|
-
useRef as
|
|
1634
|
-
useEffect as
|
|
682
|
+
useRef as useRef2,
|
|
683
|
+
useEffect as useEffect2,
|
|
1635
684
|
useCallback as useCallback2,
|
|
685
|
+
useMemo as useMemo2,
|
|
1636
686
|
forwardRef as forwardRef2,
|
|
1637
687
|
useImperativeHandle as useImperativeHandle2
|
|
1638
688
|
} from "react";
|
|
1639
|
-
import { useFrame as useFrame2 } from "@react-three/fiber";
|
|
1640
|
-
import { Vector3
|
|
689
|
+
import { useFrame as useFrame2, useThree as useThree2 } from "@react-three/fiber";
|
|
690
|
+
import { Vector3, Quaternion } from "three/webgpu";
|
|
691
|
+
import {
|
|
692
|
+
EmitterController,
|
|
693
|
+
isWebGPUBackend as isWebGPUBackend2
|
|
694
|
+
} from "core-vfx";
|
|
1641
695
|
import { jsx as jsx2 } from "react/jsx-runtime";
|
|
1642
|
-
var
|
|
1643
|
-
var
|
|
1644
|
-
var _tempVec = new Vector32();
|
|
696
|
+
var worldPos = new Vector3();
|
|
697
|
+
var worldQuat = new Quaternion();
|
|
1645
698
|
var VFXEmitter = forwardRef2(function VFXEmitter2({
|
|
1646
699
|
name,
|
|
1647
700
|
particlesRef,
|
|
@@ -1656,51 +709,75 @@ var VFXEmitter = forwardRef2(function VFXEmitter2({
|
|
|
1656
709
|
onEmit,
|
|
1657
710
|
children
|
|
1658
711
|
}, ref) {
|
|
1659
|
-
const
|
|
1660
|
-
const
|
|
1661
|
-
const
|
|
1662
|
-
const
|
|
712
|
+
const { gl } = useThree2();
|
|
713
|
+
const isWebGPU = useMemo2(() => isWebGPUBackend2(gl), [gl]);
|
|
714
|
+
const groupRef = useRef2(null);
|
|
715
|
+
const controllerRef = useRef2(null);
|
|
716
|
+
if (!controllerRef.current) {
|
|
717
|
+
controllerRef.current = new EmitterController({
|
|
718
|
+
emitCount,
|
|
719
|
+
delay,
|
|
720
|
+
autoStart,
|
|
721
|
+
loop,
|
|
722
|
+
localDirection,
|
|
723
|
+
direction,
|
|
724
|
+
overrides,
|
|
725
|
+
onEmit
|
|
726
|
+
});
|
|
727
|
+
}
|
|
728
|
+
const controller = controllerRef.current;
|
|
1663
729
|
const getParticleSystem = useCallback2(() => {
|
|
1664
730
|
if (particlesRef) {
|
|
1665
731
|
return particlesRef.current || particlesRef;
|
|
1666
732
|
}
|
|
1667
733
|
return useVFXStore.getState().getParticles(name);
|
|
1668
734
|
}, [name, particlesRef]);
|
|
1669
|
-
|
|
1670
|
-
(
|
|
1671
|
-
|
|
1672
|
-
|
|
1673
|
-
|
|
1674
|
-
|
|
1675
|
-
|
|
1676
|
-
|
|
1677
|
-
|
|
1678
|
-
|
|
1679
|
-
|
|
1680
|
-
|
|
1681
|
-
|
|
1682
|
-
|
|
1683
|
-
|
|
1684
|
-
}
|
|
1685
|
-
|
|
1686
|
-
|
|
1687
|
-
|
|
1688
|
-
|
|
1689
|
-
|
|
1690
|
-
|
|
1691
|
-
|
|
1692
|
-
|
|
1693
|
-
|
|
1694
|
-
|
|
1695
|
-
|
|
1696
|
-
|
|
735
|
+
useEffect2(() => {
|
|
736
|
+
if (!isWebGPU) return;
|
|
737
|
+
const system = getParticleSystem();
|
|
738
|
+
controller.setSystem(system);
|
|
739
|
+
}, [isWebGPU, getParticleSystem, controller]);
|
|
740
|
+
useEffect2(() => {
|
|
741
|
+
controller.updateOptions({
|
|
742
|
+
emitCount,
|
|
743
|
+
delay,
|
|
744
|
+
autoStart,
|
|
745
|
+
loop,
|
|
746
|
+
localDirection,
|
|
747
|
+
direction,
|
|
748
|
+
overrides,
|
|
749
|
+
onEmit
|
|
750
|
+
});
|
|
751
|
+
}, [
|
|
752
|
+
controller,
|
|
753
|
+
emitCount,
|
|
754
|
+
delay,
|
|
755
|
+
autoStart,
|
|
756
|
+
loop,
|
|
757
|
+
localDirection,
|
|
758
|
+
direction,
|
|
759
|
+
overrides,
|
|
760
|
+
onEmit
|
|
761
|
+
]);
|
|
762
|
+
useFrame2((_, delta) => {
|
|
763
|
+
if (!isWebGPU) return;
|
|
764
|
+
if (!controller.getSystem()) {
|
|
765
|
+
const system = getParticleSystem();
|
|
766
|
+
if (system) controller.setSystem(system);
|
|
1697
767
|
}
|
|
1698
|
-
|
|
1699
|
-
|
|
768
|
+
if (!groupRef.current) return;
|
|
769
|
+
groupRef.current.getWorldPosition(worldPos);
|
|
770
|
+
groupRef.current.getWorldQuaternion(worldQuat);
|
|
771
|
+
controller.update(delta, worldPos, worldQuat);
|
|
772
|
+
});
|
|
1700
773
|
const emit = useCallback2(
|
|
1701
774
|
(emitOverrides = null) => {
|
|
1702
|
-
|
|
1703
|
-
if (!(
|
|
775
|
+
if (!groupRef.current) return false;
|
|
776
|
+
if (!controller.getSystem()) {
|
|
777
|
+
const system = getParticleSystem();
|
|
778
|
+
if (system) controller.setSystem(system);
|
|
779
|
+
}
|
|
780
|
+
if (!controller.getSystem()) {
|
|
1704
781
|
if (name) {
|
|
1705
782
|
console.warn(
|
|
1706
783
|
`VFXEmitter: No particle system found for name "${name}"`
|
|
@@ -1708,110 +785,44 @@ var VFXEmitter = forwardRef2(function VFXEmitter2({
|
|
|
1708
785
|
}
|
|
1709
786
|
return false;
|
|
1710
787
|
}
|
|
1711
|
-
|
|
1712
|
-
|
|
1713
|
-
|
|
1714
|
-
let finalDir = emitDir;
|
|
1715
|
-
if (emitTimeDirection && localDirection && groupRef.current) {
|
|
1716
|
-
groupRef.current.getWorldQuaternion(_worldQuat);
|
|
1717
|
-
finalDir = transformDirectionByQuat(emitTimeDirection, _worldQuat);
|
|
1718
|
-
} else if (emitTimeDirection) {
|
|
1719
|
-
finalDir = emitTimeDirection;
|
|
1720
|
-
}
|
|
1721
|
-
const _a = emitOverrides || {}, { direction: _ } = _a, emitOverridesWithoutDir = __objRest(_a, ["direction"]);
|
|
1722
|
-
const mergedOverrides = __spreadValues(__spreadValues({}, overrides), emitOverridesWithoutDir);
|
|
1723
|
-
const finalOverrides = finalDir ? __spreadProps(__spreadValues({}, mergedOverrides), { direction: finalDir }) : mergedOverrides;
|
|
1724
|
-
particles.spawn(x, y, z, emitCount, finalOverrides);
|
|
1725
|
-
if (onEmit) {
|
|
1726
|
-
onEmit({ position: emitPos, count: emitCount, direction: finalDir });
|
|
1727
|
-
}
|
|
1728
|
-
return true;
|
|
788
|
+
groupRef.current.getWorldPosition(worldPos);
|
|
789
|
+
groupRef.current.getWorldQuaternion(worldQuat);
|
|
790
|
+
return controller.emitAtPosition(worldPos, worldQuat, emitOverrides);
|
|
1729
791
|
},
|
|
1730
|
-
[
|
|
1731
|
-
getParticleSystem,
|
|
1732
|
-
getEmitParams,
|
|
1733
|
-
name,
|
|
1734
|
-
emitCount,
|
|
1735
|
-
overrides,
|
|
1736
|
-
onEmit,
|
|
1737
|
-
localDirection,
|
|
1738
|
-
transformDirectionByQuat
|
|
1739
|
-
]
|
|
792
|
+
[controller, getParticleSystem, name]
|
|
1740
793
|
);
|
|
1741
|
-
useFrame2((_, delta) => {
|
|
1742
|
-
if (!emitting.current) return;
|
|
1743
|
-
if (!loop && hasEmittedOnce.current) {
|
|
1744
|
-
return;
|
|
1745
|
-
}
|
|
1746
|
-
if (delay <= 0) {
|
|
1747
|
-
const success = emit();
|
|
1748
|
-
if (success) hasEmittedOnce.current = true;
|
|
1749
|
-
} else {
|
|
1750
|
-
emitAccumulator.current += delta;
|
|
1751
|
-
if (emitAccumulator.current >= delay) {
|
|
1752
|
-
emitAccumulator.current -= delay;
|
|
1753
|
-
const success = emit();
|
|
1754
|
-
if (success) hasEmittedOnce.current = true;
|
|
1755
|
-
}
|
|
1756
|
-
}
|
|
1757
|
-
});
|
|
1758
|
-
const start = useCallback2(() => {
|
|
1759
|
-
emitting.current = true;
|
|
1760
|
-
hasEmittedOnce.current = false;
|
|
1761
|
-
emitAccumulator.current = 0;
|
|
1762
|
-
}, []);
|
|
1763
|
-
const stop = useCallback2(() => {
|
|
1764
|
-
emitting.current = false;
|
|
1765
|
-
}, []);
|
|
1766
794
|
const burst = useCallback2(
|
|
1767
795
|
(count) => {
|
|
1768
|
-
|
|
1769
|
-
if (!(
|
|
1770
|
-
|
|
1771
|
-
|
|
1772
|
-
const finalOverrides = emitDir ? __spreadProps(__spreadValues({}, overrides), { direction: emitDir }) : overrides;
|
|
1773
|
-
particles.spawn(x, y, z, count != null ? count : emitCount, finalOverrides);
|
|
1774
|
-
if (onEmit) {
|
|
1775
|
-
onEmit({
|
|
1776
|
-
position: emitPos,
|
|
1777
|
-
count: count != null ? count : emitCount,
|
|
1778
|
-
direction: emitDir
|
|
1779
|
-
});
|
|
796
|
+
if (!groupRef.current) return false;
|
|
797
|
+
if (!controller.getSystem()) {
|
|
798
|
+
const system = getParticleSystem();
|
|
799
|
+
if (system) controller.setSystem(system);
|
|
1780
800
|
}
|
|
1781
|
-
return
|
|
801
|
+
if (!controller.getSystem()) return false;
|
|
802
|
+
groupRef.current.getWorldPosition(worldPos);
|
|
803
|
+
groupRef.current.getWorldQuaternion(worldQuat);
|
|
804
|
+
return controller.burst(count, worldPos, worldQuat);
|
|
1782
805
|
},
|
|
1783
|
-
[
|
|
806
|
+
[controller, getParticleSystem]
|
|
1784
807
|
);
|
|
1785
|
-
|
|
1786
|
-
|
|
1787
|
-
if (autoStart) {
|
|
1788
|
-
hasEmittedOnce.current = false;
|
|
1789
|
-
emitAccumulator.current = 0;
|
|
1790
|
-
}
|
|
1791
|
-
}, [autoStart]);
|
|
808
|
+
const start = useCallback2(() => controller.start(), [controller]);
|
|
809
|
+
const stop = useCallback2(() => controller.stop(), [controller]);
|
|
1792
810
|
useImperativeHandle2(
|
|
1793
811
|
ref,
|
|
1794
812
|
() => ({
|
|
1795
|
-
/** Emit particles at current position */
|
|
1796
813
|
emit,
|
|
1797
|
-
/** Burst emit - emit immediately regardless of autoStart */
|
|
1798
814
|
burst,
|
|
1799
|
-
/** Start auto-emission */
|
|
1800
815
|
start,
|
|
1801
|
-
/** Stop auto-emission */
|
|
1802
816
|
stop,
|
|
1803
|
-
/** Check if currently emitting */
|
|
1804
817
|
get isEmitting() {
|
|
1805
|
-
return
|
|
818
|
+
return controller.isEmitting;
|
|
1806
819
|
},
|
|
1807
|
-
/** Get the linked particle system */
|
|
1808
820
|
getParticleSystem,
|
|
1809
|
-
/** Get the group ref for direct access */
|
|
1810
821
|
get group() {
|
|
1811
822
|
return groupRef.current;
|
|
1812
823
|
}
|
|
1813
824
|
}),
|
|
1814
|
-
[emit, burst, start, stop, getParticleSystem]
|
|
825
|
+
[emit, burst, start, stop, controller, getParticleSystem]
|
|
1815
826
|
);
|
|
1816
827
|
return (
|
|
1817
828
|
// @ts-expect-error
|
|
@@ -1819,6 +830,8 @@ var VFXEmitter = forwardRef2(function VFXEmitter2({
|
|
|
1819
830
|
);
|
|
1820
831
|
});
|
|
1821
832
|
function useVFXEmitter(name) {
|
|
833
|
+
const { gl } = useThree2();
|
|
834
|
+
const isWebGPU = useMemo2(() => isWebGPUBackend2(gl), [gl]);
|
|
1822
835
|
const getParticles = useVFXStore((s) => s.getParticles);
|
|
1823
836
|
const storeEmit = useVFXStore((s) => s.emit);
|
|
1824
837
|
const storeStart = useVFXStore((s) => s.start);
|
|
@@ -1826,31 +839,44 @@ function useVFXEmitter(name) {
|
|
|
1826
839
|
const storeClear = useVFXStore((s) => s.clear);
|
|
1827
840
|
const emit = useCallback2(
|
|
1828
841
|
(position = [0, 0, 0], count = 20, overrides = null) => {
|
|
842
|
+
if (!isWebGPU) return false;
|
|
1829
843
|
const [x, y, z] = position;
|
|
1830
844
|
return storeEmit(name, { x, y, z, count, overrides });
|
|
1831
845
|
},
|
|
1832
|
-
[name, storeEmit]
|
|
846
|
+
[isWebGPU, name, storeEmit]
|
|
1833
847
|
);
|
|
1834
848
|
const burst = useCallback2(
|
|
1835
849
|
(position = [0, 0, 0], count = 50, overrides = null) => {
|
|
850
|
+
if (!isWebGPU) return false;
|
|
1836
851
|
const [x, y, z] = position;
|
|
1837
852
|
return storeEmit(name, { x, y, z, count, overrides });
|
|
1838
853
|
},
|
|
1839
|
-
[name, storeEmit]
|
|
854
|
+
[isWebGPU, name, storeEmit]
|
|
1840
855
|
);
|
|
1841
|
-
const start = useCallback2(() =>
|
|
1842
|
-
|
|
1843
|
-
|
|
856
|
+
const start = useCallback2(() => {
|
|
857
|
+
if (!isWebGPU) return false;
|
|
858
|
+
return storeStart(name);
|
|
859
|
+
}, [isWebGPU, name, storeStart]);
|
|
860
|
+
const stop = useCallback2(() => {
|
|
861
|
+
if (!isWebGPU) return false;
|
|
862
|
+
return storeStop(name);
|
|
863
|
+
}, [isWebGPU, name, storeStop]);
|
|
864
|
+
const clear = useCallback2(() => {
|
|
865
|
+
if (!isWebGPU) return false;
|
|
866
|
+
return storeClear(name);
|
|
867
|
+
}, [isWebGPU, name, storeClear]);
|
|
1844
868
|
const isEmitting = useCallback2(() => {
|
|
1845
869
|
var _a;
|
|
870
|
+
if (!isWebGPU) return false;
|
|
1846
871
|
const particles = getParticles(name);
|
|
1847
872
|
return (_a = particles == null ? void 0 : particles.isEmitting) != null ? _a : false;
|
|
1848
|
-
}, [name, getParticles]);
|
|
873
|
+
}, [isWebGPU, name, getParticles]);
|
|
1849
874
|
const getUniforms = useCallback2(() => {
|
|
1850
875
|
var _a;
|
|
876
|
+
if (!isWebGPU) return null;
|
|
1851
877
|
const particles = getParticles(name);
|
|
1852
878
|
return (_a = particles == null ? void 0 : particles.uniforms) != null ? _a : null;
|
|
1853
|
-
}, [name, getParticles]);
|
|
879
|
+
}, [isWebGPU, name, getParticles]);
|
|
1854
880
|
return {
|
|
1855
881
|
emit,
|
|
1856
882
|
burst,
|
|
@@ -1859,23 +885,38 @@ function useVFXEmitter(name) {
|
|
|
1859
885
|
clear,
|
|
1860
886
|
isEmitting,
|
|
1861
887
|
getUniforms,
|
|
1862
|
-
getParticles: () => getParticles(name)
|
|
888
|
+
getParticles: () => isWebGPU ? getParticles(name) : null
|
|
1863
889
|
};
|
|
1864
890
|
}
|
|
891
|
+
|
|
892
|
+
// src/index.ts
|
|
893
|
+
import {
|
|
894
|
+
VFXParticleSystem as VFXParticleSystem2,
|
|
895
|
+
EmitterController as EmitterController2,
|
|
896
|
+
isWebGPUBackend as isWebGPUBackend3,
|
|
897
|
+
isNonDefaultRotation as isNonDefaultRotation2,
|
|
898
|
+
normalizeProps as normalizeProps2,
|
|
899
|
+
resolveCurveTexture
|
|
900
|
+
} from "core-vfx";
|
|
1865
901
|
export {
|
|
1866
902
|
Appearance2 as Appearance,
|
|
1867
|
-
|
|
903
|
+
AttractorType,
|
|
1868
904
|
Blending2 as Blending,
|
|
1869
|
-
|
|
1870
|
-
|
|
905
|
+
CurveChannel,
|
|
906
|
+
Easing,
|
|
907
|
+
EmitterController2 as EmitterController,
|
|
1871
908
|
EmitterShape2 as EmitterShape,
|
|
1872
909
|
Lighting2 as Lighting,
|
|
1873
910
|
VFXEmitter,
|
|
911
|
+
VFXParticleSystem2 as VFXParticleSystem,
|
|
1874
912
|
VFXParticles,
|
|
1875
913
|
bakeCurveToArray,
|
|
1876
914
|
buildCurveTextureBin,
|
|
1877
|
-
|
|
1878
|
-
|
|
915
|
+
createCombinedCurveTexture,
|
|
916
|
+
isNonDefaultRotation2 as isNonDefaultRotation,
|
|
917
|
+
isWebGPUBackend3 as isWebGPUBackend,
|
|
918
|
+
normalizeProps2 as normalizeProps,
|
|
919
|
+
resolveCurveTexture,
|
|
1879
920
|
useVFXEmitter,
|
|
1880
921
|
useVFXStore
|
|
1881
922
|
};
|