r3f-vfx 0.0.5 → 0.0.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.ts +208 -32
- package/dist/index.js +55 -36
- package/package.json +1 -1
package/dist/index.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import * as react from 'react';
|
|
2
|
+
import { RefObject, ReactNode } from 'react';
|
|
2
3
|
import * as THREE from 'three/webgpu';
|
|
3
4
|
import { CoreState } from 'core-vfx';
|
|
4
5
|
|
|
@@ -36,39 +37,185 @@ declare const Lighting: Readonly<{
|
|
|
36
37
|
STANDARD: "standard";
|
|
37
38
|
PHYSICAL: "physical";
|
|
38
39
|
}>;
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
*/
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
start
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
40
|
+
type CurvePoint = {
|
|
41
|
+
pos: [number, number];
|
|
42
|
+
handleIn?: [number, number];
|
|
43
|
+
handleOut?: [number, number];
|
|
44
|
+
};
|
|
45
|
+
type CurveData = {
|
|
46
|
+
points: CurvePoint[];
|
|
47
|
+
} | null;
|
|
48
|
+
declare const bakeCurveToArray: (curveData: CurveData, resolution?: number) => Float32Array;
|
|
49
|
+
declare const createCombinedCurveTexture: (sizeCurve: CurveData, opacityCurve: CurveData, velocityCurve: CurveData, rotationSpeedCurve: CurveData) => THREE.DataTexture;
|
|
50
|
+
type Rotation3DInput = number | [number, number] | [[number, number], [number, number], [number, number]] | null | undefined;
|
|
51
|
+
type ParticleData = Record<string, any>;
|
|
52
|
+
type VFXParticlesProps = {
|
|
53
|
+
/** Optional name for registering with useVFXStore (enables VFXEmitter linking) */
|
|
54
|
+
name?: string;
|
|
55
|
+
/** Maximum number of particles */
|
|
56
|
+
maxParticles?: number;
|
|
57
|
+
/** Particle size [min, max] or single value */
|
|
58
|
+
size?: number | [number, number];
|
|
59
|
+
/** Array of hex color strings for start color */
|
|
60
|
+
colorStart?: string[];
|
|
61
|
+
/** Array of hex color strings for end color (null = use colorStart) */
|
|
62
|
+
colorEnd?: string[] | null;
|
|
63
|
+
/** Fade size [start, end] multiplier over lifetime */
|
|
64
|
+
fadeSize?: number | [number, number];
|
|
65
|
+
/** Curve data for size over lifetime */
|
|
66
|
+
fadeSizeCurve?: CurveData;
|
|
67
|
+
/** Fade opacity [start, end] multiplier over lifetime */
|
|
68
|
+
fadeOpacity?: number | [number, number];
|
|
69
|
+
/** Curve data for opacity over lifetime */
|
|
70
|
+
fadeOpacityCurve?: CurveData;
|
|
71
|
+
/** Curve data for velocity over lifetime */
|
|
72
|
+
velocityCurve?: CurveData;
|
|
73
|
+
/** Gravity vector [x, y, z] */
|
|
74
|
+
gravity?: [number, number, number];
|
|
75
|
+
/** Particle lifetime in seconds [min, max] or single value */
|
|
76
|
+
lifetime?: number | [number, number];
|
|
77
|
+
/** Direction ranges for velocity */
|
|
78
|
+
direction?: Rotation3DInput;
|
|
79
|
+
/** Start position offset ranges */
|
|
80
|
+
startPosition?: Rotation3DInput;
|
|
81
|
+
/** Speed [min, max] or single value */
|
|
82
|
+
speed?: number | [number, number];
|
|
83
|
+
/** Friction settings */
|
|
84
|
+
friction?: {
|
|
85
|
+
intensity?: number | [number, number];
|
|
86
|
+
easing?: string;
|
|
87
|
+
};
|
|
88
|
+
/** Particle appearance type */
|
|
89
|
+
appearance?: (typeof Appearance)[keyof typeof Appearance];
|
|
90
|
+
/** Alpha map texture */
|
|
91
|
+
alphaMap?: THREE.Texture | null;
|
|
92
|
+
/** Flipbook animation settings */
|
|
93
|
+
flipbook?: {
|
|
94
|
+
rows: number;
|
|
95
|
+
columns: number;
|
|
96
|
+
} | null;
|
|
97
|
+
/** Rotation [min, max] in radians or 3D rotation ranges */
|
|
98
|
+
rotation?: Rotation3DInput;
|
|
99
|
+
/** Rotation speed [min, max] in radians/second or 3D ranges */
|
|
100
|
+
rotationSpeed?: Rotation3DInput;
|
|
101
|
+
/** Curve data for rotation speed over lifetime */
|
|
102
|
+
rotationSpeedCurve?: CurveData;
|
|
103
|
+
/** Custom geometry for 3D particles */
|
|
104
|
+
geometry?: THREE.BufferGeometry | null;
|
|
105
|
+
/** Rotate geometry to face velocity direction */
|
|
106
|
+
orientToDirection?: boolean;
|
|
107
|
+
/** Which local axis aligns with velocity */
|
|
108
|
+
orientAxis?: string;
|
|
109
|
+
/** Stretch particles based on speed */
|
|
110
|
+
stretchBySpeed?: {
|
|
111
|
+
factor: number;
|
|
112
|
+
maxStretch: number;
|
|
113
|
+
} | null;
|
|
114
|
+
/** Material lighting type for geometry mode */
|
|
115
|
+
lighting?: (typeof Lighting)[keyof typeof Lighting];
|
|
116
|
+
/** Enable shadows on geometry instances */
|
|
117
|
+
shadow?: boolean;
|
|
118
|
+
/** Blending mode */
|
|
119
|
+
blending?: THREE.Blending;
|
|
120
|
+
/** Color intensity multiplier */
|
|
121
|
+
intensity?: number;
|
|
122
|
+
/** Emitter position [x, y, z] */
|
|
123
|
+
position?: [number, number, number];
|
|
124
|
+
/** Start emitting automatically */
|
|
125
|
+
autoStart?: boolean;
|
|
126
|
+
/** Delay between emissions in seconds */
|
|
127
|
+
delay?: number;
|
|
128
|
+
/** TSL node or function for backdrop sampling */
|
|
129
|
+
backdropNode?: any | ((data: ParticleData) => any) | null;
|
|
130
|
+
/** TSL node or function for custom opacity */
|
|
131
|
+
opacityNode?: any | ((data: ParticleData) => any) | null;
|
|
132
|
+
/** TSL node or function to override color */
|
|
133
|
+
colorNode?: any | ((data: ParticleData, defaultColor: any) => any) | null;
|
|
134
|
+
/** TSL node or function for alpha test/discard */
|
|
135
|
+
alphaTestNode?: any | ((data: ParticleData) => any) | null;
|
|
136
|
+
/** TSL node or function for shadow map output */
|
|
137
|
+
castShadowNode?: any | ((data: ParticleData) => any) | null;
|
|
138
|
+
/** Number of particles to emit per frame */
|
|
139
|
+
emitCount?: number;
|
|
140
|
+
/** Emitter shape type */
|
|
141
|
+
emitterShape?: (typeof EmitterShape)[keyof typeof EmitterShape];
|
|
142
|
+
/** Emitter radius [inner, outer] */
|
|
143
|
+
emitterRadius?: number | [number, number];
|
|
144
|
+
/** Cone angle in radians */
|
|
145
|
+
emitterAngle?: number;
|
|
146
|
+
/** Cone height [min, max] */
|
|
147
|
+
emitterHeight?: number | [number, number];
|
|
148
|
+
/** Emit from surface only */
|
|
149
|
+
emitterSurfaceOnly?: boolean;
|
|
150
|
+
/** Direction for cone/disk normal */
|
|
151
|
+
emitterDirection?: [number, number, number];
|
|
152
|
+
/** Turbulence settings */
|
|
153
|
+
turbulence?: {
|
|
154
|
+
intensity: number;
|
|
155
|
+
frequency?: number;
|
|
156
|
+
speed?: number;
|
|
70
157
|
} | null;
|
|
158
|
+
/** Array of attractors (max 4) */
|
|
159
|
+
attractors?: Array<{
|
|
160
|
+
position?: [number, number, number];
|
|
161
|
+
strength?: number;
|
|
162
|
+
radius?: number;
|
|
163
|
+
type?: 'point' | 'vortex';
|
|
164
|
+
axis?: [number, number, number];
|
|
165
|
+
}> | null;
|
|
166
|
+
/** Particles move from spawn position to center over lifetime */
|
|
167
|
+
attractToCenter?: boolean;
|
|
168
|
+
/** Use start position offset as direction */
|
|
169
|
+
startPositionAsDirection?: boolean;
|
|
170
|
+
/** Fade particles when intersecting scene geometry */
|
|
171
|
+
softParticles?: boolean;
|
|
172
|
+
/** Distance over which to fade soft particles */
|
|
173
|
+
softDistance?: number;
|
|
174
|
+
/** Plane collision settings */
|
|
175
|
+
collision?: {
|
|
176
|
+
plane?: {
|
|
177
|
+
y: number;
|
|
178
|
+
};
|
|
179
|
+
bounce?: number;
|
|
180
|
+
friction?: number;
|
|
181
|
+
die?: boolean;
|
|
182
|
+
sizeBasedGravity?: number;
|
|
183
|
+
} | null;
|
|
184
|
+
/** Show debug control panel */
|
|
185
|
+
debug?: boolean;
|
|
71
186
|
};
|
|
187
|
+
declare const VFXParticles: react.ForwardRefExoticComponent<VFXParticlesProps & react.RefAttributes<unknown>>;
|
|
188
|
+
|
|
189
|
+
interface VFXEmitterProps {
|
|
190
|
+
/** Name of the registered VFXParticles system */
|
|
191
|
+
name?: string;
|
|
192
|
+
/** Direct ref to VFXParticles (alternative to name) */
|
|
193
|
+
particlesRef?: RefObject<any> | any;
|
|
194
|
+
/** Local position offset */
|
|
195
|
+
position?: [number, number, number];
|
|
196
|
+
/** Particles to emit per burst */
|
|
197
|
+
emitCount?: number;
|
|
198
|
+
/** Seconds between emissions (0 = every frame) */
|
|
199
|
+
delay?: number;
|
|
200
|
+
/** Start emitting automatically */
|
|
201
|
+
autoStart?: boolean;
|
|
202
|
+
/** Keep emitting (false = emit once) */
|
|
203
|
+
loop?: boolean;
|
|
204
|
+
/** Transform direction by parent's world rotation */
|
|
205
|
+
localDirection?: boolean;
|
|
206
|
+
/** Direction override [[minX,maxX],[minY,maxY],[minZ,maxZ]] */
|
|
207
|
+
direction?: [[number, number], [number, number], [number, number]];
|
|
208
|
+
/** Per-spawn overrides (size, speed, colors, etc.) */
|
|
209
|
+
overrides?: Record<string, any> | null;
|
|
210
|
+
/** Callback fired after each emission */
|
|
211
|
+
onEmit?: (params: {
|
|
212
|
+
position: [number, number, number] | number[];
|
|
213
|
+
count: number;
|
|
214
|
+
direction: any;
|
|
215
|
+
}) => void;
|
|
216
|
+
/** Children elements */
|
|
217
|
+
children?: ReactNode;
|
|
218
|
+
}
|
|
72
219
|
/**
|
|
73
220
|
* VFXEmitter - A reusable emitter component that links to a VFXParticles system
|
|
74
221
|
*
|
|
@@ -113,7 +260,36 @@ declare function useVFXEmitter(name: any): {
|
|
|
113
260
|
* @param {object} [props.overrides] - Per-spawn overrides (size, speed, colors, etc.)
|
|
114
261
|
* @param {function} [props.onEmit] - Callback fired after each emission
|
|
115
262
|
*/
|
|
116
|
-
declare const VFXEmitter: react.ForwardRefExoticComponent<react.RefAttributes<
|
|
263
|
+
declare const VFXEmitter: react.ForwardRefExoticComponent<VFXEmitterProps & react.RefAttributes<unknown>>;
|
|
264
|
+
/**
|
|
265
|
+
* Higher-order hook for programmatic emitter control
|
|
266
|
+
*
|
|
267
|
+
* Usage:
|
|
268
|
+
* const { emit, burst, start, stop } = useVFXEmitter("sparks");
|
|
269
|
+
*
|
|
270
|
+
* // Emit at a position
|
|
271
|
+
* emit([1, 2, 3], 50);
|
|
272
|
+
*
|
|
273
|
+
* // Burst with overrides
|
|
274
|
+
* burst([0, 0, 0], 100, { colorStart: ["#ff0000"] });
|
|
275
|
+
*/
|
|
276
|
+
declare function useVFXEmitter(name: string): {
|
|
277
|
+
emit: (position?: number[], count?: number, overrides?: null) => boolean;
|
|
278
|
+
burst: (position?: number[], count?: number, overrides?: null) => boolean;
|
|
279
|
+
start: () => boolean;
|
|
280
|
+
stop: () => boolean;
|
|
281
|
+
clear: () => boolean;
|
|
282
|
+
isEmitting: () => boolean;
|
|
283
|
+
getUniforms: () => Record<string, unknown> | null;
|
|
284
|
+
getParticles: () => {
|
|
285
|
+
spawn: (x: number, y: number, z: number, count: number, overrides?: Record<string, unknown> | null) => void;
|
|
286
|
+
start: () => void;
|
|
287
|
+
stop: () => void;
|
|
288
|
+
clear: () => void;
|
|
289
|
+
isEmitting: boolean;
|
|
290
|
+
uniforms: Record<string, unknown>;
|
|
291
|
+
} | null;
|
|
292
|
+
};
|
|
117
293
|
|
|
118
294
|
declare function useVFXStore(): CoreState;
|
|
119
295
|
declare function useVFXStore<T>(selector: (state: CoreState) => T): T;
|
package/dist/index.js
CHANGED
|
@@ -5117,7 +5117,7 @@ ${" ".repeat(indent - 2)}}`;
|
|
|
5117
5117
|
}
|
|
5118
5118
|
});
|
|
5119
5119
|
|
|
5120
|
-
// src/VFXParticles.
|
|
5120
|
+
// src/VFXParticles.tsx
|
|
5121
5121
|
import {
|
|
5122
5122
|
forwardRef,
|
|
5123
5123
|
useImperativeHandle,
|
|
@@ -5149,7 +5149,6 @@ import {
|
|
|
5149
5149
|
positionLocal,
|
|
5150
5150
|
cos,
|
|
5151
5151
|
sin,
|
|
5152
|
-
atan,
|
|
5153
5152
|
sqrt,
|
|
5154
5153
|
acos,
|
|
5155
5154
|
PI,
|
|
@@ -5164,7 +5163,7 @@ import {
|
|
|
5164
5163
|
import { jsx as jsx2 } from "react/jsx-runtime";
|
|
5165
5164
|
var Appearance, Blending, EmitterShape, AttractorType, Easing, Lighting, MAX_ATTRACTORS, hexToRgb, toRange, easingToType, axisToNumber, CURVE_RESOLUTION, evaluateBezierSegment, sampleCurveAtX, bakeCurveToArray, createCombinedCurveTexture, toRotation3D, VFXParticles;
|
|
5166
5165
|
var init_VFXParticles = __esm({
|
|
5167
|
-
"src/VFXParticles.
|
|
5166
|
+
"src/VFXParticles.tsx"() {
|
|
5168
5167
|
"use strict";
|
|
5169
5168
|
init_react_store();
|
|
5170
5169
|
Appearance = Object.freeze({
|
|
@@ -5388,10 +5387,11 @@ var init_VFXParticles = __esm({
|
|
|
5388
5387
|
];
|
|
5389
5388
|
if (Array.isArray(value)) {
|
|
5390
5389
|
if (Array.isArray(value[0])) {
|
|
5390
|
+
const nested = value;
|
|
5391
5391
|
return [
|
|
5392
|
-
toRange(
|
|
5393
|
-
toRange(
|
|
5394
|
-
toRange(
|
|
5392
|
+
toRange(nested[0], [0, 0]),
|
|
5393
|
+
toRange(nested[1], [0, 0]),
|
|
5394
|
+
toRange(nested[2], [0, 0])
|
|
5395
5395
|
];
|
|
5396
5396
|
}
|
|
5397
5397
|
const range = toRange(value, [0, 0]);
|
|
@@ -5510,7 +5510,7 @@ var init_VFXParticles = __esm({
|
|
|
5510
5510
|
debug = false
|
|
5511
5511
|
}, ref) {
|
|
5512
5512
|
const { gl: renderer } = useThree();
|
|
5513
|
-
const spriteRef = useRef2();
|
|
5513
|
+
const spriteRef = useRef2(null);
|
|
5514
5514
|
const initialized = useRef2(false);
|
|
5515
5515
|
const nextIndex = useRef2(0);
|
|
5516
5516
|
const [emitting, setEmitting] = useState2(autoStart);
|
|
@@ -5618,8 +5618,9 @@ var init_VFXParticles = __esm({
|
|
|
5618
5618
|
return [0, 0];
|
|
5619
5619
|
}, [friction]);
|
|
5620
5620
|
const frictionEasingType = useMemo(() => {
|
|
5621
|
+
var _a;
|
|
5621
5622
|
if (typeof friction === "object" && friction !== null && "easing" in friction) {
|
|
5622
|
-
return easingToType(friction.easing);
|
|
5623
|
+
return easingToType((_a = friction.easing) != null ? _a : "linear");
|
|
5623
5624
|
}
|
|
5624
5625
|
return 0;
|
|
5625
5626
|
}, [friction]);
|
|
@@ -5850,14 +5851,15 @@ var init_VFXParticles = __esm({
|
|
|
5850
5851
|
);
|
|
5851
5852
|
for (let i = 0; i < MAX_ATTRACTORS; i++) {
|
|
5852
5853
|
const a = attractorList[i];
|
|
5854
|
+
const u = uniforms;
|
|
5853
5855
|
if (a) {
|
|
5854
|
-
|
|
5855
|
-
|
|
5856
|
-
|
|
5857
|
-
|
|
5858
|
-
|
|
5856
|
+
u[`attractor${i}Pos`].value.set(...(_d = a.position) != null ? _d : [0, 0, 0]);
|
|
5857
|
+
u[`attractor${i}Strength`].value = (_e = a.strength) != null ? _e : 1;
|
|
5858
|
+
u[`attractor${i}Radius`].value = (_f = a.radius) != null ? _f : 0;
|
|
5859
|
+
u[`attractor${i}Type`].value = a.type === "vortex" ? 1 : 0;
|
|
5860
|
+
u[`attractor${i}Axis`].value.set(...(_g = a.axis) != null ? _g : [0, 1, 0]).normalize();
|
|
5859
5861
|
} else {
|
|
5860
|
-
|
|
5862
|
+
u[`attractor${i}Strength`].value = 0;
|
|
5861
5863
|
}
|
|
5862
5864
|
}
|
|
5863
5865
|
uniforms.attractToCenter.value = attractToCenter ? 1 : 0;
|
|
@@ -6729,6 +6731,7 @@ var init_VFXParticles = __esm({
|
|
|
6729
6731
|
});
|
|
6730
6732
|
}, [renderer, computeInit]);
|
|
6731
6733
|
const applySpawnOverrides = useCallback2(
|
|
6734
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
6732
6735
|
(overrides) => {
|
|
6733
6736
|
if (!overrides) return null;
|
|
6734
6737
|
const saved = {};
|
|
@@ -6775,15 +6778,16 @@ var init_VFXParticles = __esm({
|
|
|
6775
6778
|
saved.gravity = uniforms.gravity.value.clone();
|
|
6776
6779
|
uniforms.gravity.value.set(...overrides.gravity);
|
|
6777
6780
|
}
|
|
6781
|
+
const u = uniforms;
|
|
6778
6782
|
if (overrides.colorStart !== void 0) {
|
|
6779
6783
|
const colors = overrides.colorStart.slice(0, 8).map(hexToRgb);
|
|
6780
6784
|
while (colors.length < 8)
|
|
6781
6785
|
colors.push(colors[colors.length - 1] || [1, 1, 1]);
|
|
6782
6786
|
setUniform("colorStartCount", overrides.colorStart.length);
|
|
6783
6787
|
colors.forEach((c, i) => {
|
|
6784
|
-
if (
|
|
6785
|
-
saved[`colorStart${i}`] =
|
|
6786
|
-
|
|
6788
|
+
if (u[`colorStart${i}`]) {
|
|
6789
|
+
saved[`colorStart${i}`] = u[`colorStart${i}`].value.clone();
|
|
6790
|
+
u[`colorStart${i}`].value.setRGB(...c);
|
|
6787
6791
|
}
|
|
6788
6792
|
});
|
|
6789
6793
|
}
|
|
@@ -6793,9 +6797,9 @@ var init_VFXParticles = __esm({
|
|
|
6793
6797
|
colors.push(colors[colors.length - 1] || [1, 1, 1]);
|
|
6794
6798
|
setUniform("colorEndCount", overrides.colorEnd.length);
|
|
6795
6799
|
colors.forEach((c, i) => {
|
|
6796
|
-
if (
|
|
6797
|
-
saved[`colorEnd${i}`] =
|
|
6798
|
-
|
|
6800
|
+
if (u[`colorEnd${i}`]) {
|
|
6801
|
+
saved[`colorEnd${i}`] = u[`colorEnd${i}`].value.clone();
|
|
6802
|
+
u[`colorEnd${i}`].value.setRGB(...c);
|
|
6799
6803
|
}
|
|
6800
6804
|
});
|
|
6801
6805
|
}
|
|
@@ -6836,7 +6840,8 @@ var init_VFXParticles = __esm({
|
|
|
6836
6840
|
);
|
|
6837
6841
|
const spawn = useCallback2(
|
|
6838
6842
|
(x = 0, y = 0, z = 0, count = 20, overrides = null) => {
|
|
6839
|
-
|
|
6843
|
+
var _a;
|
|
6844
|
+
const [px, py, pz] = (_a = positionRef.current) != null ? _a : [0, 0, 0];
|
|
6840
6845
|
spawnInternal(px + x, py + y, pz + z, count, overrides);
|
|
6841
6846
|
},
|
|
6842
6847
|
[spawnInternal]
|
|
@@ -6935,6 +6940,7 @@ var init_VFXParticles = __esm({
|
|
|
6935
6940
|
const prevGeometryTypeRef = useRef2(null);
|
|
6936
6941
|
const prevGeometryArgsRef = useRef2(null);
|
|
6937
6942
|
const handleDebugUpdate = useCallback2(
|
|
6943
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
6938
6944
|
(newValues) => {
|
|
6939
6945
|
var _a, _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;
|
|
6940
6946
|
debugValuesRef.current = __spreadValues(__spreadValues({}, debugValuesRef.current), newValues);
|
|
@@ -7407,7 +7413,7 @@ var init_VFXParticles = __esm({
|
|
|
7407
7413
|
// src/index.ts
|
|
7408
7414
|
init_VFXParticles();
|
|
7409
7415
|
|
|
7410
|
-
// src/VFXEmitter.
|
|
7416
|
+
// src/VFXEmitter.tsx
|
|
7411
7417
|
init_react_store();
|
|
7412
7418
|
import {
|
|
7413
7419
|
useRef as useRef3,
|
|
@@ -7436,7 +7442,7 @@ var VFXEmitter = forwardRef2(function VFXEmitter2({
|
|
|
7436
7442
|
onEmit,
|
|
7437
7443
|
children
|
|
7438
7444
|
}, ref) {
|
|
7439
|
-
const groupRef = useRef3();
|
|
7445
|
+
const groupRef = useRef3(null);
|
|
7440
7446
|
const emitAccumulator = useRef3(0);
|
|
7441
7447
|
const emitting = useRef3(autoStart);
|
|
7442
7448
|
const hasEmittedOnce = useRef3(false);
|
|
@@ -7446,18 +7452,28 @@ var VFXEmitter = forwardRef2(function VFXEmitter2({
|
|
|
7446
7452
|
}
|
|
7447
7453
|
return useVFXStore.getState().getParticles(name);
|
|
7448
7454
|
}, [name, particlesRef]);
|
|
7449
|
-
const transformDirectionByQuat = useCallback3(
|
|
7450
|
-
|
|
7451
|
-
|
|
7452
|
-
|
|
7453
|
-
|
|
7454
|
-
|
|
7455
|
-
|
|
7456
|
-
|
|
7457
|
-
|
|
7458
|
-
|
|
7459
|
-
|
|
7460
|
-
|
|
7455
|
+
const transformDirectionByQuat = useCallback3(
|
|
7456
|
+
(dirRange, quat) => {
|
|
7457
|
+
const minDir = _tempVec.set(
|
|
7458
|
+
dirRange[0][0],
|
|
7459
|
+
dirRange[1][0],
|
|
7460
|
+
dirRange[2][0]
|
|
7461
|
+
);
|
|
7462
|
+
minDir.applyQuaternion(quat);
|
|
7463
|
+
const maxDir = new Vector32(
|
|
7464
|
+
dirRange[0][1],
|
|
7465
|
+
dirRange[1][1],
|
|
7466
|
+
dirRange[2][1]
|
|
7467
|
+
);
|
|
7468
|
+
maxDir.applyQuaternion(quat);
|
|
7469
|
+
return [
|
|
7470
|
+
[Math.min(minDir.x, maxDir.x), Math.max(minDir.x, maxDir.x)],
|
|
7471
|
+
[Math.min(minDir.y, maxDir.y), Math.max(minDir.y, maxDir.y)],
|
|
7472
|
+
[Math.min(minDir.z, maxDir.z), Math.max(minDir.z, maxDir.z)]
|
|
7473
|
+
];
|
|
7474
|
+
},
|
|
7475
|
+
[]
|
|
7476
|
+
);
|
|
7461
7477
|
const getEmitParams = useCallback3(() => {
|
|
7462
7478
|
if (!groupRef.current) {
|
|
7463
7479
|
return { position, direction };
|
|
@@ -7563,7 +7579,10 @@ var VFXEmitter = forwardRef2(function VFXEmitter2({
|
|
|
7563
7579
|
}),
|
|
7564
7580
|
[emit, burst, start, stop, getParticleSystem]
|
|
7565
7581
|
);
|
|
7566
|
-
return
|
|
7582
|
+
return (
|
|
7583
|
+
// @ts-expect-error
|
|
7584
|
+
/* @__PURE__ */ jsx3("group", { ref: groupRef, position, children })
|
|
7585
|
+
);
|
|
7567
7586
|
});
|
|
7568
7587
|
function useVFXEmitter(name) {
|
|
7569
7588
|
const getParticles = useVFXStore((s) => s.getParticles);
|