r3f-vfx 0.0.4 → 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 +213 -49
- package/dist/index.js +68 -181
- package/package.json +6 -2
package/dist/index.d.ts
CHANGED
|
@@ -1,4 +1,7 @@
|
|
|
1
|
-
import * as
|
|
1
|
+
import * as react from 'react';
|
|
2
|
+
import { RefObject, ReactNode } from 'react';
|
|
3
|
+
import * as THREE from 'three/webgpu';
|
|
4
|
+
import { CoreState } from 'core-vfx';
|
|
2
5
|
|
|
3
6
|
declare const Appearance: Readonly<{
|
|
4
7
|
DEFAULT: "default";
|
|
@@ -6,10 +9,10 @@ declare const Appearance: Readonly<{
|
|
|
6
9
|
CIRCULAR: "circular";
|
|
7
10
|
}>;
|
|
8
11
|
declare const Blending: Readonly<{
|
|
9
|
-
NORMAL:
|
|
10
|
-
ADDITIVE:
|
|
11
|
-
MULTIPLY:
|
|
12
|
-
SUBTRACTIVE:
|
|
12
|
+
NORMAL: 1;
|
|
13
|
+
ADDITIVE: 2;
|
|
14
|
+
MULTIPLY: 4;
|
|
15
|
+
SUBTRACTIVE: 3;
|
|
13
16
|
}>;
|
|
14
17
|
declare const EmitterShape: Readonly<{
|
|
15
18
|
POINT: 0;
|
|
@@ -34,32 +37,185 @@ declare const Lighting: Readonly<{
|
|
|
34
37
|
STANDARD: "standard";
|
|
35
38
|
PHYSICAL: "physical";
|
|
36
39
|
}>;
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
*/
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
start
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
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;
|
|
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;
|
|
62
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
|
+
}
|
|
63
219
|
/**
|
|
64
220
|
* VFXEmitter - A reusable emitter component that links to a VFXParticles system
|
|
65
221
|
*
|
|
@@ -104,30 +260,38 @@ declare function useVFXEmitter(name: any): {
|
|
|
104
260
|
* @param {object} [props.overrides] - Per-spawn overrides (size, speed, colors, etc.)
|
|
105
261
|
* @param {function} [props.onEmit] - Callback fired after each emission
|
|
106
262
|
*/
|
|
107
|
-
declare const VFXEmitter:
|
|
108
|
-
|
|
263
|
+
declare const VFXEmitter: react.ForwardRefExoticComponent<VFXEmitterProps & react.RefAttributes<unknown>>;
|
|
109
264
|
/**
|
|
110
|
-
*
|
|
111
|
-
*
|
|
112
|
-
* Allows multiple VFXEmitter components to share a single VFXParticles instance,
|
|
113
|
-
* avoiding extra draw calls while enabling emission from multiple positions.
|
|
265
|
+
* Higher-order hook for programmatic emitter control
|
|
114
266
|
*
|
|
115
267
|
* Usage:
|
|
268
|
+
* const { emit, burst, start, stop } = useVFXEmitter("sparks");
|
|
116
269
|
*
|
|
117
|
-
* //
|
|
118
|
-
*
|
|
119
|
-
*
|
|
120
|
-
* // Or use the VFXParticles name prop with auto-registration
|
|
121
|
-
* <VFXParticles name="sparks" ... />
|
|
122
|
-
*
|
|
123
|
-
* // Emit from anywhere using VFXEmitter (no extra draw calls!)
|
|
124
|
-
* <VFXEmitter name="sparks" position={[1, 0, 0]} emitCount={10} />
|
|
125
|
-
* <VFXEmitter name="sparks" position={[-1, 0, 0]} emitCount={5} />
|
|
270
|
+
* // Emit at a position
|
|
271
|
+
* emit([1, 2, 3], 50);
|
|
126
272
|
*
|
|
127
|
-
* //
|
|
128
|
-
*
|
|
129
|
-
* emit("sparks", { x: 0, y: 1, z: 0, count: 20 });
|
|
273
|
+
* // Burst with overrides
|
|
274
|
+
* burst([0, 0, 0], 100, { colorStart: ["#ff0000"] });
|
|
130
275
|
*/
|
|
131
|
-
declare
|
|
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
|
+
};
|
|
293
|
+
|
|
294
|
+
declare function useVFXStore(): CoreState;
|
|
295
|
+
declare function useVFXStore<T>(selector: (state: CoreState) => T): T;
|
|
132
296
|
|
|
133
297
|
export { Appearance, AttractorType, Blending, Easing, EmitterShape, Lighting, VFXEmitter, VFXParticles, bakeCurveToArray, createCombinedCurveTexture, useVFXEmitter, useVFXStore };
|
package/dist/index.js
CHANGED
|
@@ -18,19 +18,6 @@ var __spreadValues = (a, b) => {
|
|
|
18
18
|
return a;
|
|
19
19
|
};
|
|
20
20
|
var __spreadProps = (a, b) => __defProps(a, __getOwnPropDescs(b));
|
|
21
|
-
var __restKey = (key) => typeof key === "symbol" ? key : key + "";
|
|
22
|
-
var __objRest = (source, exclude) => {
|
|
23
|
-
var target = {};
|
|
24
|
-
for (var prop in source)
|
|
25
|
-
if (__hasOwnProp.call(source, prop) && exclude.indexOf(prop) < 0)
|
|
26
|
-
target[prop] = source[prop];
|
|
27
|
-
if (source != null && __getOwnPropSymbols)
|
|
28
|
-
for (var prop of __getOwnPropSymbols(source)) {
|
|
29
|
-
if (exclude.indexOf(prop) < 0 && __propIsEnum.call(source, prop))
|
|
30
|
-
target[prop] = source[prop];
|
|
31
|
-
}
|
|
32
|
-
return target;
|
|
33
|
-
};
|
|
34
21
|
var __esm = (fn, res) => function __init() {
|
|
35
22
|
return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
|
|
36
23
|
};
|
|
@@ -39,134 +26,15 @@ var __export = (target, all) => {
|
|
|
39
26
|
__defProp(target, name, { get: all[name], enumerable: true });
|
|
40
27
|
};
|
|
41
28
|
|
|
42
|
-
// src/
|
|
43
|
-
import {
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
29
|
+
// src/react-store.ts
|
|
30
|
+
import { coreStore } from "core-vfx";
|
|
31
|
+
import { useStore } from "zustand";
|
|
32
|
+
function useVFXStore(selector) {
|
|
33
|
+
return useStore(coreStore, selector);
|
|
34
|
+
}
|
|
35
|
+
var init_react_store = __esm({
|
|
36
|
+
"src/react-store.ts"() {
|
|
47
37
|
"use strict";
|
|
48
|
-
useVFXStore = create((set, get) => ({
|
|
49
|
-
// Registered particle systems: { name: ref }
|
|
50
|
-
particles: {},
|
|
51
|
-
/**
|
|
52
|
-
* Register a VFXParticles instance by name
|
|
53
|
-
* @param {string} name - Unique identifier for this particle system
|
|
54
|
-
* @param {object} ref - The ref object from VFXParticles (with spawn, start, stop methods)
|
|
55
|
-
*/
|
|
56
|
-
registerParticles: (name, ref) => {
|
|
57
|
-
if (!name || !ref) return;
|
|
58
|
-
set((state) => ({
|
|
59
|
-
particles: __spreadProps(__spreadValues({}, state.particles), { [name]: ref })
|
|
60
|
-
}));
|
|
61
|
-
},
|
|
62
|
-
/**
|
|
63
|
-
* Unregister a VFXParticles instance
|
|
64
|
-
* @param {string} name - Name of the particle system to unregister
|
|
65
|
-
*/
|
|
66
|
-
unregisterParticles: (name) => {
|
|
67
|
-
set((state) => {
|
|
68
|
-
const _a = state.particles, { [name]: _ } = _a, rest = __objRest(_a, [__restKey(name)]);
|
|
69
|
-
return { particles: rest };
|
|
70
|
-
});
|
|
71
|
-
},
|
|
72
|
-
/**
|
|
73
|
-
* Get a registered particle system by name
|
|
74
|
-
* @param {string} name - Name of the particle system
|
|
75
|
-
* @returns {object|null} The particle system ref or null
|
|
76
|
-
*/
|
|
77
|
-
getParticles: (name) => {
|
|
78
|
-
return get().particles[name] || null;
|
|
79
|
-
},
|
|
80
|
-
/**
|
|
81
|
-
* Emit particles from a registered system
|
|
82
|
-
* @param {string} name - Name of the particle system
|
|
83
|
-
* @param {object} options - Emission options
|
|
84
|
-
* @param {number} [options.x=0] - X position offset
|
|
85
|
-
* @param {number} [options.y=0] - Y position offset
|
|
86
|
-
* @param {number} [options.z=0] - Z position offset
|
|
87
|
-
* @param {number} [options.count=20] - Number of particles to emit
|
|
88
|
-
* @param {object} [options.overrides] - Spawn parameter overrides
|
|
89
|
-
* @returns {boolean} True if emission was successful
|
|
90
|
-
*/
|
|
91
|
-
emit: (name, { x = 0, y = 0, z = 0, count = 20, overrides = null } = {}) => {
|
|
92
|
-
const particles = get().particles[name];
|
|
93
|
-
if (!(particles == null ? void 0 : particles.spawn)) {
|
|
94
|
-
console.warn(
|
|
95
|
-
`VFXStore: No particle system registered with name "${name}"`
|
|
96
|
-
);
|
|
97
|
-
return false;
|
|
98
|
-
}
|
|
99
|
-
particles.spawn(x, y, z, count, overrides);
|
|
100
|
-
return true;
|
|
101
|
-
},
|
|
102
|
-
/**
|
|
103
|
-
* Start auto-emission on a registered particle system
|
|
104
|
-
* @param {string} name - Name of the particle system
|
|
105
|
-
* @returns {boolean} True if successful
|
|
106
|
-
*/
|
|
107
|
-
start: (name) => {
|
|
108
|
-
const particles = get().particles[name];
|
|
109
|
-
if (!(particles == null ? void 0 : particles.start)) {
|
|
110
|
-
console.warn(
|
|
111
|
-
`VFXStore: No particle system registered with name "${name}"`
|
|
112
|
-
);
|
|
113
|
-
return false;
|
|
114
|
-
}
|
|
115
|
-
particles.start();
|
|
116
|
-
return true;
|
|
117
|
-
},
|
|
118
|
-
/**
|
|
119
|
-
* Stop auto-emission on a registered particle system
|
|
120
|
-
* @param {string} name - Name of the particle system
|
|
121
|
-
* @returns {boolean} True if successful
|
|
122
|
-
*/
|
|
123
|
-
stop: (name) => {
|
|
124
|
-
const particles = get().particles[name];
|
|
125
|
-
if (!(particles == null ? void 0 : particles.stop)) {
|
|
126
|
-
console.warn(
|
|
127
|
-
`VFXStore: No particle system registered with name "${name}"`
|
|
128
|
-
);
|
|
129
|
-
return false;
|
|
130
|
-
}
|
|
131
|
-
particles.stop();
|
|
132
|
-
return true;
|
|
133
|
-
},
|
|
134
|
-
/**
|
|
135
|
-
* Clear all particles from a registered system
|
|
136
|
-
* @param {string} name - Name of the particle system
|
|
137
|
-
* @returns {boolean} True if successful
|
|
138
|
-
*/
|
|
139
|
-
clear: (name) => {
|
|
140
|
-
const particles = get().particles[name];
|
|
141
|
-
if (!(particles == null ? void 0 : particles.clear)) {
|
|
142
|
-
console.warn(
|
|
143
|
-
`VFXStore: No particle system registered with name "${name}"`
|
|
144
|
-
);
|
|
145
|
-
return false;
|
|
146
|
-
}
|
|
147
|
-
particles.clear();
|
|
148
|
-
return true;
|
|
149
|
-
},
|
|
150
|
-
/**
|
|
151
|
-
* Check if a particle system is currently emitting
|
|
152
|
-
* @param {string} name - Name of the particle system
|
|
153
|
-
* @returns {boolean} True if emitting
|
|
154
|
-
*/
|
|
155
|
-
isEmitting: (name) => {
|
|
156
|
-
var _a;
|
|
157
|
-
const particles = get().particles[name];
|
|
158
|
-
return (_a = particles == null ? void 0 : particles.isEmitting) != null ? _a : false;
|
|
159
|
-
},
|
|
160
|
-
/**
|
|
161
|
-
* Get the uniforms object for direct manipulation
|
|
162
|
-
* @param {string} name - Name of the particle system
|
|
163
|
-
* @returns {object|null} The uniforms object or null
|
|
164
|
-
*/
|
|
165
|
-
getUniforms: (name) => {
|
|
166
|
-
const particles = get().particles[name];
|
|
167
|
-
return (particles == null ? void 0 : particles.uniforms) || null;
|
|
168
|
-
}
|
|
169
|
-
}));
|
|
170
38
|
}
|
|
171
39
|
});
|
|
172
40
|
|
|
@@ -184,7 +52,7 @@ __export(VFXParticlesDebugPanel_exports, {
|
|
|
184
52
|
import { createRoot } from "react-dom/client";
|
|
185
53
|
import { useState, useCallback, useRef, useEffect } from "react";
|
|
186
54
|
import * as THREE from "three";
|
|
187
|
-
import { create
|
|
55
|
+
import { create } from "zustand";
|
|
188
56
|
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
189
57
|
function renderDebugPanel(values, onChange) {
|
|
190
58
|
currentValues = values;
|
|
@@ -355,7 +223,7 @@ var init_VFXParticlesDebugPanel = __esm({
|
|
|
355
223
|
"src/VFXParticlesDebugPanel.jsx"() {
|
|
356
224
|
"use strict";
|
|
357
225
|
init_VFXParticles();
|
|
358
|
-
useDebugPanelStore =
|
|
226
|
+
useDebugPanelStore = create(() => ({
|
|
359
227
|
flushChangesRef: { current: null }
|
|
360
228
|
}));
|
|
361
229
|
getFlushChanges = () => useDebugPanelStore.getState().flushChangesRef.current;
|
|
@@ -5249,7 +5117,7 @@ ${" ".repeat(indent - 2)}}`;
|
|
|
5249
5117
|
}
|
|
5250
5118
|
});
|
|
5251
5119
|
|
|
5252
|
-
// src/VFXParticles.
|
|
5120
|
+
// src/VFXParticles.tsx
|
|
5253
5121
|
import {
|
|
5254
5122
|
forwardRef,
|
|
5255
5123
|
useImperativeHandle,
|
|
@@ -5281,7 +5149,6 @@ import {
|
|
|
5281
5149
|
positionLocal,
|
|
5282
5150
|
cos,
|
|
5283
5151
|
sin,
|
|
5284
|
-
atan,
|
|
5285
5152
|
sqrt,
|
|
5286
5153
|
acos,
|
|
5287
5154
|
PI,
|
|
@@ -5296,9 +5163,9 @@ import {
|
|
|
5296
5163
|
import { jsx as jsx2 } from "react/jsx-runtime";
|
|
5297
5164
|
var Appearance, Blending, EmitterShape, AttractorType, Easing, Lighting, MAX_ATTRACTORS, hexToRgb, toRange, easingToType, axisToNumber, CURVE_RESOLUTION, evaluateBezierSegment, sampleCurveAtX, bakeCurveToArray, createCombinedCurveTexture, toRotation3D, VFXParticles;
|
|
5298
5165
|
var init_VFXParticles = __esm({
|
|
5299
|
-
"src/VFXParticles.
|
|
5166
|
+
"src/VFXParticles.tsx"() {
|
|
5300
5167
|
"use strict";
|
|
5301
|
-
|
|
5168
|
+
init_react_store();
|
|
5302
5169
|
Appearance = Object.freeze({
|
|
5303
5170
|
DEFAULT: "default",
|
|
5304
5171
|
GRADIENT: "gradient",
|
|
@@ -5520,10 +5387,11 @@ var init_VFXParticles = __esm({
|
|
|
5520
5387
|
];
|
|
5521
5388
|
if (Array.isArray(value)) {
|
|
5522
5389
|
if (Array.isArray(value[0])) {
|
|
5390
|
+
const nested = value;
|
|
5523
5391
|
return [
|
|
5524
|
-
toRange(
|
|
5525
|
-
toRange(
|
|
5526
|
-
toRange(
|
|
5392
|
+
toRange(nested[0], [0, 0]),
|
|
5393
|
+
toRange(nested[1], [0, 0]),
|
|
5394
|
+
toRange(nested[2], [0, 0])
|
|
5527
5395
|
];
|
|
5528
5396
|
}
|
|
5529
5397
|
const range = toRange(value, [0, 0]);
|
|
@@ -5642,7 +5510,7 @@ var init_VFXParticles = __esm({
|
|
|
5642
5510
|
debug = false
|
|
5643
5511
|
}, ref) {
|
|
5644
5512
|
const { gl: renderer } = useThree();
|
|
5645
|
-
const spriteRef = useRef2();
|
|
5513
|
+
const spriteRef = useRef2(null);
|
|
5646
5514
|
const initialized = useRef2(false);
|
|
5647
5515
|
const nextIndex = useRef2(0);
|
|
5648
5516
|
const [emitting, setEmitting] = useState2(autoStart);
|
|
@@ -5750,8 +5618,9 @@ var init_VFXParticles = __esm({
|
|
|
5750
5618
|
return [0, 0];
|
|
5751
5619
|
}, [friction]);
|
|
5752
5620
|
const frictionEasingType = useMemo(() => {
|
|
5621
|
+
var _a;
|
|
5753
5622
|
if (typeof friction === "object" && friction !== null && "easing" in friction) {
|
|
5754
|
-
return easingToType(friction.easing);
|
|
5623
|
+
return easingToType((_a = friction.easing) != null ? _a : "linear");
|
|
5755
5624
|
}
|
|
5756
5625
|
return 0;
|
|
5757
5626
|
}, [friction]);
|
|
@@ -5982,14 +5851,15 @@ var init_VFXParticles = __esm({
|
|
|
5982
5851
|
);
|
|
5983
5852
|
for (let i = 0; i < MAX_ATTRACTORS; i++) {
|
|
5984
5853
|
const a = attractorList[i];
|
|
5854
|
+
const u = uniforms;
|
|
5985
5855
|
if (a) {
|
|
5986
|
-
|
|
5987
|
-
|
|
5988
|
-
|
|
5989
|
-
|
|
5990
|
-
|
|
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();
|
|
5991
5861
|
} else {
|
|
5992
|
-
|
|
5862
|
+
u[`attractor${i}Strength`].value = 0;
|
|
5993
5863
|
}
|
|
5994
5864
|
}
|
|
5995
5865
|
uniforms.attractToCenter.value = attractToCenter ? 1 : 0;
|
|
@@ -6861,6 +6731,7 @@ var init_VFXParticles = __esm({
|
|
|
6861
6731
|
});
|
|
6862
6732
|
}, [renderer, computeInit]);
|
|
6863
6733
|
const applySpawnOverrides = useCallback2(
|
|
6734
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
6864
6735
|
(overrides) => {
|
|
6865
6736
|
if (!overrides) return null;
|
|
6866
6737
|
const saved = {};
|
|
@@ -6907,15 +6778,16 @@ var init_VFXParticles = __esm({
|
|
|
6907
6778
|
saved.gravity = uniforms.gravity.value.clone();
|
|
6908
6779
|
uniforms.gravity.value.set(...overrides.gravity);
|
|
6909
6780
|
}
|
|
6781
|
+
const u = uniforms;
|
|
6910
6782
|
if (overrides.colorStart !== void 0) {
|
|
6911
6783
|
const colors = overrides.colorStart.slice(0, 8).map(hexToRgb);
|
|
6912
6784
|
while (colors.length < 8)
|
|
6913
6785
|
colors.push(colors[colors.length - 1] || [1, 1, 1]);
|
|
6914
6786
|
setUniform("colorStartCount", overrides.colorStart.length);
|
|
6915
6787
|
colors.forEach((c, i) => {
|
|
6916
|
-
if (
|
|
6917
|
-
saved[`colorStart${i}`] =
|
|
6918
|
-
|
|
6788
|
+
if (u[`colorStart${i}`]) {
|
|
6789
|
+
saved[`colorStart${i}`] = u[`colorStart${i}`].value.clone();
|
|
6790
|
+
u[`colorStart${i}`].value.setRGB(...c);
|
|
6919
6791
|
}
|
|
6920
6792
|
});
|
|
6921
6793
|
}
|
|
@@ -6925,9 +6797,9 @@ var init_VFXParticles = __esm({
|
|
|
6925
6797
|
colors.push(colors[colors.length - 1] || [1, 1, 1]);
|
|
6926
6798
|
setUniform("colorEndCount", overrides.colorEnd.length);
|
|
6927
6799
|
colors.forEach((c, i) => {
|
|
6928
|
-
if (
|
|
6929
|
-
saved[`colorEnd${i}`] =
|
|
6930
|
-
|
|
6800
|
+
if (u[`colorEnd${i}`]) {
|
|
6801
|
+
saved[`colorEnd${i}`] = u[`colorEnd${i}`].value.clone();
|
|
6802
|
+
u[`colorEnd${i}`].value.setRGB(...c);
|
|
6931
6803
|
}
|
|
6932
6804
|
});
|
|
6933
6805
|
}
|
|
@@ -6968,7 +6840,8 @@ var init_VFXParticles = __esm({
|
|
|
6968
6840
|
);
|
|
6969
6841
|
const spawn = useCallback2(
|
|
6970
6842
|
(x = 0, y = 0, z = 0, count = 20, overrides = null) => {
|
|
6971
|
-
|
|
6843
|
+
var _a;
|
|
6844
|
+
const [px, py, pz] = (_a = positionRef.current) != null ? _a : [0, 0, 0];
|
|
6972
6845
|
spawnInternal(px + x, py + y, pz + z, count, overrides);
|
|
6973
6846
|
},
|
|
6974
6847
|
[spawnInternal]
|
|
@@ -7067,6 +6940,7 @@ var init_VFXParticles = __esm({
|
|
|
7067
6940
|
const prevGeometryTypeRef = useRef2(null);
|
|
7068
6941
|
const prevGeometryArgsRef = useRef2(null);
|
|
7069
6942
|
const handleDebugUpdate = useCallback2(
|
|
6943
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
7070
6944
|
(newValues) => {
|
|
7071
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;
|
|
7072
6946
|
debugValuesRef.current = __spreadValues(__spreadValues({}, debugValuesRef.current), newValues);
|
|
@@ -7539,8 +7413,8 @@ var init_VFXParticles = __esm({
|
|
|
7539
7413
|
// src/index.ts
|
|
7540
7414
|
init_VFXParticles();
|
|
7541
7415
|
|
|
7542
|
-
// src/VFXEmitter.
|
|
7543
|
-
|
|
7416
|
+
// src/VFXEmitter.tsx
|
|
7417
|
+
init_react_store();
|
|
7544
7418
|
import {
|
|
7545
7419
|
useRef as useRef3,
|
|
7546
7420
|
useEffect as useEffect3,
|
|
@@ -7568,7 +7442,7 @@ var VFXEmitter = forwardRef2(function VFXEmitter2({
|
|
|
7568
7442
|
onEmit,
|
|
7569
7443
|
children
|
|
7570
7444
|
}, ref) {
|
|
7571
|
-
const groupRef = useRef3();
|
|
7445
|
+
const groupRef = useRef3(null);
|
|
7572
7446
|
const emitAccumulator = useRef3(0);
|
|
7573
7447
|
const emitting = useRef3(autoStart);
|
|
7574
7448
|
const hasEmittedOnce = useRef3(false);
|
|
@@ -7578,18 +7452,28 @@ var VFXEmitter = forwardRef2(function VFXEmitter2({
|
|
|
7578
7452
|
}
|
|
7579
7453
|
return useVFXStore.getState().getParticles(name);
|
|
7580
7454
|
}, [name, particlesRef]);
|
|
7581
|
-
const transformDirectionByQuat = useCallback3(
|
|
7582
|
-
|
|
7583
|
-
|
|
7584
|
-
|
|
7585
|
-
|
|
7586
|
-
|
|
7587
|
-
|
|
7588
|
-
|
|
7589
|
-
|
|
7590
|
-
|
|
7591
|
-
|
|
7592
|
-
|
|
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
|
+
);
|
|
7593
7477
|
const getEmitParams = useCallback3(() => {
|
|
7594
7478
|
if (!groupRef.current) {
|
|
7595
7479
|
return { position, direction };
|
|
@@ -7695,7 +7579,10 @@ var VFXEmitter = forwardRef2(function VFXEmitter2({
|
|
|
7695
7579
|
}),
|
|
7696
7580
|
[emit, burst, start, stop, getParticleSystem]
|
|
7697
7581
|
);
|
|
7698
|
-
return
|
|
7582
|
+
return (
|
|
7583
|
+
// @ts-expect-error
|
|
7584
|
+
/* @__PURE__ */ jsx3("group", { ref: groupRef, position, children })
|
|
7585
|
+
);
|
|
7699
7586
|
});
|
|
7700
7587
|
function useVFXEmitter(name) {
|
|
7701
7588
|
const getParticles = useVFXStore((s) => s.getParticles);
|
|
@@ -7743,7 +7630,7 @@ function useVFXEmitter(name) {
|
|
|
7743
7630
|
}
|
|
7744
7631
|
|
|
7745
7632
|
// src/index.ts
|
|
7746
|
-
|
|
7633
|
+
init_react_store();
|
|
7747
7634
|
export {
|
|
7748
7635
|
Appearance,
|
|
7749
7636
|
AttractorType,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "r3f-vfx",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.6",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"repository": {
|
|
@@ -24,10 +24,14 @@
|
|
|
24
24
|
"prepublishOnly": "bun run typecheck && bun run build && bun run copy-readme"
|
|
25
25
|
},
|
|
26
26
|
"dependencies": {
|
|
27
|
-
"core-vfx": "0.0.
|
|
27
|
+
"core-vfx": "0.0.2",
|
|
28
28
|
"zustand": "5.0.10"
|
|
29
29
|
},
|
|
30
30
|
"devDependencies": {
|
|
31
|
+
"@react-three/fiber": "9.5.0",
|
|
32
|
+
"@types/react": "19.2.10",
|
|
33
|
+
"@types/three": "0.182.0",
|
|
34
|
+
"three": "0.182.0",
|
|
31
35
|
"tsup": "8.5.1",
|
|
32
36
|
"typescript": "5.9.3"
|
|
33
37
|
},
|