tres-vfx 0.1.0 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -1,2 +1,1019 @@
1
+ var __defProp = Object.defineProperty;
2
+ var __defProps = Object.defineProperties;
3
+ var __getOwnPropDescs = Object.getOwnPropertyDescriptors;
4
+ var __getOwnPropSymbols = Object.getOwnPropertySymbols;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __propIsEnum = Object.prototype.propertyIsEnumerable;
7
+ var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
8
+ var __spreadValues = (a, b) => {
9
+ for (var prop in b || (b = {}))
10
+ if (__hasOwnProp.call(b, prop))
11
+ __defNormalProp(a, prop, b[prop]);
12
+ if (__getOwnPropSymbols)
13
+ for (var prop of __getOwnPropSymbols(b)) {
14
+ if (__propIsEnum.call(b, prop))
15
+ __defNormalProp(a, prop, b[prop]);
16
+ }
17
+ return a;
18
+ };
19
+ var __spreadProps = (a, b) => __defProps(a, __getOwnPropDescs(b));
20
+
21
+ // src/VFXParticles.ts
22
+ import {
23
+ defineComponent,
24
+ ref,
25
+ watch,
26
+ onMounted,
27
+ onUnmounted,
28
+ h,
29
+ shallowRef
30
+ } from "vue";
31
+ import { useLoop, useTresContext } from "@tresjs/core";
32
+ import { coreStore } from "core-vfx";
33
+ import {
34
+ Appearance,
35
+ Blending,
36
+ EmitterShape,
37
+ Lighting,
38
+ VFXParticleSystem,
39
+ isNonDefaultRotation,
40
+ normalizeProps,
41
+ updateUniforms,
42
+ updateUniformsPartial,
43
+ resolveFeatures
44
+ } from "core-vfx";
45
+ var VFXParticles = defineComponent({
46
+ name: "VFXParticles",
47
+ props: {
48
+ name: { type: String, default: void 0 },
49
+ debug: { type: Boolean, default: false },
50
+ maxParticles: { type: Number, default: 1e4 },
51
+ size: {
52
+ type: null,
53
+ default: () => [0.1, 0.3]
54
+ },
55
+ colorStart: {
56
+ type: Array,
57
+ default: () => ["#ffffff"]
58
+ },
59
+ colorEnd: {
60
+ type: null,
61
+ default: null
62
+ },
63
+ fadeSize: {
64
+ type: null,
65
+ default: () => [1, 0]
66
+ },
67
+ fadeSizeCurve: {
68
+ type: null,
69
+ default: null
70
+ },
71
+ fadeOpacity: {
72
+ type: null,
73
+ default: () => [1, 0]
74
+ },
75
+ fadeOpacityCurve: {
76
+ type: null,
77
+ default: null
78
+ },
79
+ velocityCurve: {
80
+ type: null,
81
+ default: null
82
+ },
83
+ gravity: {
84
+ type: null,
85
+ default: () => [0, 0, 0]
86
+ },
87
+ lifetime: {
88
+ type: null,
89
+ default: () => [1, 2]
90
+ },
91
+ direction: {
92
+ type: null,
93
+ default: () => [
94
+ [-1, 1],
95
+ [0, 1],
96
+ [-1, 1]
97
+ ]
98
+ },
99
+ startPosition: {
100
+ type: null,
101
+ default: () => [
102
+ [0, 0],
103
+ [0, 0],
104
+ [0, 0]
105
+ ]
106
+ },
107
+ speed: {
108
+ type: null,
109
+ default: () => [0.1, 0.1]
110
+ },
111
+ friction: {
112
+ type: Object,
113
+ default: () => ({ intensity: 0, easing: "linear" })
114
+ },
115
+ appearance: {
116
+ type: null,
117
+ default: Appearance.GRADIENT
118
+ },
119
+ alphaMap: { type: Object, default: null },
120
+ flipbook: {
121
+ type: Object,
122
+ default: null
123
+ },
124
+ rotation: {
125
+ type: null,
126
+ default: () => [0, 0]
127
+ },
128
+ rotationSpeed: {
129
+ type: null,
130
+ default: () => [0, 0]
131
+ },
132
+ rotationSpeedCurve: {
133
+ type: null,
134
+ default: null
135
+ },
136
+ geometry: {
137
+ type: Object,
138
+ default: null
139
+ },
140
+ orientToDirection: { type: Boolean, default: false },
141
+ orientAxis: { type: String, default: "z" },
142
+ stretchBySpeed: {
143
+ type: Object,
144
+ default: null
145
+ },
146
+ lighting: {
147
+ type: null,
148
+ default: Lighting.STANDARD
149
+ },
150
+ shadow: { type: Boolean, default: false },
151
+ blending: {
152
+ type: null,
153
+ default: Blending.NORMAL
154
+ },
155
+ intensity: { type: Number, default: 1 },
156
+ position: {
157
+ type: null,
158
+ default: () => [0, 0, 0]
159
+ },
160
+ autoStart: { type: Boolean, default: true },
161
+ delay: { type: Number, default: 0 },
162
+ backdropNode: { type: null, default: null },
163
+ opacityNode: { type: null, default: null },
164
+ colorNode: { type: null, default: null },
165
+ alphaTestNode: {
166
+ type: null,
167
+ default: null
168
+ },
169
+ castShadowNode: {
170
+ type: null,
171
+ default: null
172
+ },
173
+ emitCount: { type: Number, default: 1 },
174
+ emitterShape: {
175
+ type: null,
176
+ default: EmitterShape.BOX
177
+ },
178
+ emitterRadius: {
179
+ type: null,
180
+ default: () => [0, 1]
181
+ },
182
+ emitterAngle: { type: Number, default: Math.PI / 4 },
183
+ emitterHeight: {
184
+ type: null,
185
+ default: () => [0, 1]
186
+ },
187
+ emitterSurfaceOnly: { type: Boolean, default: false },
188
+ emitterDirection: {
189
+ type: null,
190
+ default: () => [0, 1, 0]
191
+ },
192
+ turbulence: {
193
+ type: Object,
194
+ default: null
195
+ },
196
+ attractors: {
197
+ type: null,
198
+ default: null
199
+ },
200
+ attractToCenter: { type: Boolean, default: false },
201
+ startPositionAsDirection: { type: Boolean, default: false },
202
+ softParticles: { type: Boolean, default: false },
203
+ softDistance: { type: Number, default: 0.5 },
204
+ collision: {
205
+ type: Object,
206
+ default: null
207
+ },
208
+ curveTexturePath: {
209
+ type: null,
210
+ default: null
211
+ },
212
+ depthTest: { type: Boolean, default: true },
213
+ renderOrder: { type: Number, default: 0 }
214
+ },
215
+ setup(props, { expose }) {
216
+ var _a, _b, _c, _d;
217
+ const { renderer: rendererCtx } = useTresContext();
218
+ const { onBeforeRender } = useLoop();
219
+ const systemRef = shallowRef(null);
220
+ const renderObjectRef = shallowRef(null);
221
+ const emitting = ref(props.autoStart);
222
+ const debugValuesRef = ref(null);
223
+ const activeMaxParticles = ref(props.maxParticles);
224
+ const activeLighting = ref(props.lighting);
225
+ const activeAppearance = ref(props.appearance);
226
+ const activeOrientToDirection = ref(props.orientToDirection);
227
+ const activeGeometry = shallowRef(props.geometry);
228
+ const activeShadow = ref(props.shadow);
229
+ const activeFadeSizeCurve = shallowRef(props.fadeSizeCurve);
230
+ const activeFadeOpacityCurve = shallowRef(props.fadeOpacityCurve);
231
+ const activeVelocityCurve = shallowRef(props.velocityCurve);
232
+ const activeRotationSpeedCurve = shallowRef(props.rotationSpeedCurve);
233
+ const activeTurbulence = ref(
234
+ props.turbulence !== null && ((_b = (_a = props.turbulence) == null ? void 0 : _a.intensity) != null ? _b : 0) > 0
235
+ );
236
+ const activeAttractors = ref(
237
+ props.attractors !== null && ((_d = (_c = props.attractors) == null ? void 0 : _c.length) != null ? _d : 0) > 0
238
+ );
239
+ const activeCollision = ref(props.collision !== null);
240
+ const activeNeedsPerParticleColor = ref(
241
+ props.colorStart.length > 1 || props.colorEnd !== null
242
+ );
243
+ const activeNeedsRotation = ref(
244
+ isNonDefaultRotation(props.rotation) || isNonDefaultRotation(props.rotationSpeed)
245
+ );
246
+ const prevGeometryTypeRef = ref(null);
247
+ const prevGeometryArgsRef = ref(null);
248
+ function buildOptions() {
249
+ var _a2, _b2, _c2, _d2, _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;
250
+ const dbg = props.debug ? debugValuesRef.value : null;
251
+ return {
252
+ maxParticles: activeMaxParticles.value,
253
+ size: (_a2 = dbg == null ? void 0 : dbg.size) != null ? _a2 : props.size,
254
+ colorStart: (_b2 = dbg == null ? void 0 : dbg.colorStart) != null ? _b2 : props.colorStart,
255
+ colorEnd: (dbg == null ? void 0 : dbg.colorEnd) !== void 0 ? dbg.colorEnd : props.colorEnd,
256
+ fadeSize: (_c2 = dbg == null ? void 0 : dbg.fadeSize) != null ? _c2 : props.fadeSize,
257
+ fadeSizeCurve: activeFadeSizeCurve.value,
258
+ fadeOpacity: (_d2 = dbg == null ? void 0 : dbg.fadeOpacity) != null ? _d2 : props.fadeOpacity,
259
+ fadeOpacityCurve: activeFadeOpacityCurve.value,
260
+ velocityCurve: activeVelocityCurve.value,
261
+ gravity: (_e = dbg == null ? void 0 : dbg.gravity) != null ? _e : props.gravity,
262
+ lifetime: (_f = dbg == null ? void 0 : dbg.lifetime) != null ? _f : props.lifetime,
263
+ direction: (_g = dbg == null ? void 0 : dbg.direction) != null ? _g : props.direction,
264
+ startPosition: (_h = dbg == null ? void 0 : dbg.startPosition) != null ? _h : props.startPosition,
265
+ speed: (_i = dbg == null ? void 0 : dbg.speed) != null ? _i : props.speed,
266
+ friction: (_j = dbg == null ? void 0 : dbg.friction) != null ? _j : props.friction,
267
+ appearance: activeAppearance.value,
268
+ alphaMap: props.alphaMap,
269
+ flipbook: props.flipbook,
270
+ rotation: (_k = dbg == null ? void 0 : dbg.rotation) != null ? _k : props.rotation,
271
+ rotationSpeed: (_l = dbg == null ? void 0 : dbg.rotationSpeed) != null ? _l : props.rotationSpeed,
272
+ rotationSpeedCurve: activeRotationSpeedCurve.value,
273
+ geometry: activeGeometry.value,
274
+ orientToDirection: activeOrientToDirection.value,
275
+ orientAxis: (_m = dbg == null ? void 0 : dbg.orientAxis) != null ? _m : props.orientAxis,
276
+ stretchBySpeed: (_n = dbg == null ? void 0 : dbg.stretchBySpeed) != null ? _n : props.stretchBySpeed,
277
+ lighting: activeLighting.value,
278
+ shadow: activeShadow.value,
279
+ blending: (_o = dbg == null ? void 0 : dbg.blending) != null ? _o : props.blending,
280
+ intensity: (_p = dbg == null ? void 0 : dbg.intensity) != null ? _p : props.intensity,
281
+ position: (_q = dbg == null ? void 0 : dbg.position) != null ? _q : props.position,
282
+ autoStart: (_r = dbg == null ? void 0 : dbg.autoStart) != null ? _r : props.autoStart,
283
+ delay: (_s = dbg == null ? void 0 : dbg.delay) != null ? _s : props.delay,
284
+ emitCount: (_t = dbg == null ? void 0 : dbg.emitCount) != null ? _t : props.emitCount,
285
+ emitterShape: (_u = dbg == null ? void 0 : dbg.emitterShape) != null ? _u : props.emitterShape,
286
+ emitterRadius: (_v = dbg == null ? void 0 : dbg.emitterRadius) != null ? _v : props.emitterRadius,
287
+ emitterAngle: (_w = dbg == null ? void 0 : dbg.emitterAngle) != null ? _w : props.emitterAngle,
288
+ emitterHeight: (_x = dbg == null ? void 0 : dbg.emitterHeight) != null ? _x : props.emitterHeight,
289
+ emitterSurfaceOnly: (_y = dbg == null ? void 0 : dbg.emitterSurfaceOnly) != null ? _y : props.emitterSurfaceOnly,
290
+ emitterDirection: (_z = dbg == null ? void 0 : dbg.emitterDirection) != null ? _z : props.emitterDirection,
291
+ turbulence: (_A = dbg == null ? void 0 : dbg.turbulence) != null ? _A : props.turbulence,
292
+ attractors: (_B = dbg == null ? void 0 : dbg.attractors) != null ? _B : props.attractors,
293
+ attractToCenter: (_C = dbg == null ? void 0 : dbg.attractToCenter) != null ? _C : props.attractToCenter,
294
+ startPositionAsDirection: (_D = dbg == null ? void 0 : dbg.startPositionAsDirection) != null ? _D : props.startPositionAsDirection,
295
+ softParticles: (_E = dbg == null ? void 0 : dbg.softParticles) != null ? _E : props.softParticles,
296
+ softDistance: (_F = dbg == null ? void 0 : dbg.softDistance) != null ? _F : props.softDistance,
297
+ collision: (_G = dbg == null ? void 0 : dbg.collision) != null ? _G : props.collision,
298
+ backdropNode: props.backdropNode,
299
+ opacityNode: props.opacityNode,
300
+ colorNode: props.colorNode,
301
+ alphaTestNode: props.alphaTestNode,
302
+ castShadowNode: props.castShadowNode,
303
+ depthTest: (_H = dbg == null ? void 0 : dbg.depthTest) != null ? _H : props.depthTest,
304
+ renderOrder: (_I = dbg == null ? void 0 : dbg.renderOrder) != null ? _I : props.renderOrder,
305
+ curveTexturePath: props.curveTexturePath
306
+ };
307
+ }
308
+ function createSystem() {
309
+ const renderer = rendererCtx.instance;
310
+ if (!renderer) return null;
311
+ const system = new VFXParticleSystem(renderer, buildOptions());
312
+ return system;
313
+ }
314
+ function destroySystem() {
315
+ const system = systemRef.value;
316
+ if (!system) return;
317
+ if (props.name) {
318
+ coreStore.getState().unregisterParticles(props.name);
319
+ }
320
+ system.dispose();
321
+ systemRef.value = null;
322
+ renderObjectRef.value = null;
323
+ }
324
+ function initSystem() {
325
+ const oldSystem = systemRef.value;
326
+ if (oldSystem) {
327
+ oldSystem.initialized = false;
328
+ if (props.name) {
329
+ coreStore.getState().unregisterParticles(props.name);
330
+ }
331
+ }
332
+ systemRef.value = null;
333
+ renderObjectRef.value = null;
334
+ const renderer = rendererCtx.instance;
335
+ if (!renderer) {
336
+ console.warn("tres-vfx: No renderer instance available");
337
+ return;
338
+ }
339
+ const system = createSystem();
340
+ if (!system) return;
341
+ systemRef.value = system;
342
+ renderObjectRef.value = system.renderObject;
343
+ system.init();
344
+ if (props.name) {
345
+ coreStore.getState().registerParticles(props.name, {
346
+ spawn: (x = 0, y = 0, z = 0, count = 20, overrides = null) => {
347
+ const [px, py, pz] = system.position;
348
+ system.spawn(px + x, py + y, pz + z, count, overrides);
349
+ },
350
+ start: () => {
351
+ system.start();
352
+ emitting.value = true;
353
+ },
354
+ stop: () => {
355
+ system.stop();
356
+ emitting.value = false;
357
+ },
358
+ get isEmitting() {
359
+ return emitting.value;
360
+ },
361
+ clear: () => system.clear(),
362
+ uniforms: system.uniforms
363
+ });
364
+ }
365
+ if (props.debug) {
366
+ initDebugPanel();
367
+ }
368
+ }
369
+ function handleDebugUpdate(newValues) {
370
+ var _a2, _b2, _c2, _d2, _e, _f, _g, _h, _i, _j;
371
+ debugValuesRef.value = __spreadValues(__spreadValues({}, debugValuesRef.value), newValues);
372
+ const system = systemRef.value;
373
+ if (!system) return;
374
+ if ("colorStart" in newValues && newValues.colorStart) {
375
+ const currentColorEnd = (_a2 = debugValuesRef.value) == null ? void 0 : _a2.colorEnd;
376
+ if (!currentColorEnd) {
377
+ newValues = __spreadProps(__spreadValues({}, newValues), { colorEnd: null });
378
+ }
379
+ }
380
+ if ("colorEnd" in newValues && !newValues.colorEnd) {
381
+ newValues = __spreadProps(__spreadValues({}, newValues), {
382
+ colorEnd: null,
383
+ colorStart: (_d2 = (_c2 = newValues.colorStart) != null ? _c2 : (_b2 = debugValuesRef.value) == null ? void 0 : _b2.colorStart) != null ? _d2 : ["#ffffff"]
384
+ });
385
+ }
386
+ updateUniformsPartial(system.uniforms, newValues);
387
+ if ("fadeSizeCurve" in newValues) {
388
+ activeFadeSizeCurve.value = newValues.fadeSizeCurve;
389
+ }
390
+ if ("fadeOpacityCurve" in newValues) {
391
+ activeFadeOpacityCurve.value = newValues.fadeOpacityCurve;
392
+ }
393
+ if ("velocityCurve" in newValues) {
394
+ activeVelocityCurve.value = newValues.velocityCurve;
395
+ }
396
+ if ("rotationSpeedCurve" in newValues) {
397
+ activeRotationSpeedCurve.value = newValues.rotationSpeedCurve;
398
+ }
399
+ if ("turbulence" in newValues) {
400
+ system.setTurbulenceSpeed(
401
+ (_f = (_e = newValues.turbulence) == null ? void 0 : _e.speed) != null ? _f : 1
402
+ );
403
+ }
404
+ const newFeatures = resolveFeatures(
405
+ debugValuesRef.value
406
+ );
407
+ if (newFeatures.needsRotation !== activeNeedsRotation.value) {
408
+ activeNeedsRotation.value = newFeatures.needsRotation;
409
+ }
410
+ if (newFeatures.needsPerParticleColor !== activeNeedsPerParticleColor.value) {
411
+ activeNeedsPerParticleColor.value = newFeatures.needsPerParticleColor;
412
+ }
413
+ if (newFeatures.turbulence !== activeTurbulence.value) {
414
+ activeTurbulence.value = newFeatures.turbulence;
415
+ }
416
+ if (newFeatures.attractors !== activeAttractors.value) {
417
+ activeAttractors.value = newFeatures.attractors;
418
+ }
419
+ if (newFeatures.collision !== activeCollision.value) {
420
+ activeCollision.value = newFeatures.collision;
421
+ }
422
+ if (newValues.position) {
423
+ system.setPosition(newValues.position);
424
+ }
425
+ if ("delay" in newValues)
426
+ system.setDelay((_g = newValues.delay) != null ? _g : 0);
427
+ if ("emitCount" in newValues)
428
+ system.setEmitCount((_h = newValues.emitCount) != null ? _h : 1);
429
+ if (newValues.autoStart !== void 0) {
430
+ emitting.value = newValues.autoStart;
431
+ }
432
+ if (system.material && newValues.blending !== void 0) {
433
+ ;
434
+ system.material.blending = newValues.blending;
435
+ system.material.needsUpdate = true;
436
+ }
437
+ if (newValues.maxParticles !== void 0 && newValues.maxParticles !== activeMaxParticles.value) {
438
+ activeMaxParticles.value = newValues.maxParticles;
439
+ system.initialized = false;
440
+ system.nextIndex = 0;
441
+ }
442
+ if (newValues.lighting !== void 0 && newValues.lighting !== activeLighting.value) {
443
+ activeLighting.value = newValues.lighting;
444
+ }
445
+ if (newValues.appearance !== void 0 && newValues.appearance !== activeAppearance.value) {
446
+ activeAppearance.value = newValues.appearance;
447
+ }
448
+ if (newValues.orientToDirection !== void 0 && newValues.orientToDirection !== activeOrientToDirection.value) {
449
+ activeOrientToDirection.value = newValues.orientToDirection;
450
+ }
451
+ if (newValues.shadow !== void 0 && newValues.shadow !== activeShadow.value) {
452
+ activeShadow.value = newValues.shadow;
453
+ }
454
+ if ("geometryType" in newValues || "geometryArgs" in newValues) {
455
+ const geoType = (_i = newValues.geometryType) != null ? _i : prevGeometryTypeRef.value;
456
+ const geoArgs = (_j = newValues.geometryArgs) != null ? _j : prevGeometryArgsRef.value;
457
+ const geoTypeChanged = "geometryType" in newValues && geoType !== prevGeometryTypeRef.value;
458
+ const geoArgsChanged = "geometryArgs" in newValues && JSON.stringify(geoArgs) !== JSON.stringify(prevGeometryArgsRef.value);
459
+ if (geoTypeChanged || geoArgsChanged) {
460
+ prevGeometryTypeRef.value = geoType;
461
+ prevGeometryArgsRef.value = geoArgs;
462
+ import("debug-vfx").then((mod) => {
463
+ const { createGeometry, GeometryType } = mod;
464
+ if (geoType === GeometryType.NONE || !geoType) {
465
+ if (activeGeometry.value !== null && !props.geometry) {
466
+ activeGeometry.value.dispose();
467
+ }
468
+ activeGeometry.value = null;
469
+ } else {
470
+ const newGeometry = createGeometry(
471
+ geoType,
472
+ geoArgs
473
+ );
474
+ if (newGeometry) {
475
+ if (activeGeometry.value !== null && activeGeometry.value !== props.geometry) {
476
+ activeGeometry.value.dispose();
477
+ }
478
+ activeGeometry.value = newGeometry;
479
+ }
480
+ }
481
+ });
482
+ }
483
+ }
484
+ }
485
+ function initDebugPanel() {
486
+ import("debug-vfx").then((mod) => {
487
+ const { renderDebugPanel, detectGeometryTypeAndArgs } = mod;
488
+ if (!debugValuesRef.value) {
489
+ const initialValues = __spreadValues({
490
+ name: props.name,
491
+ maxParticles: props.maxParticles,
492
+ size: props.size,
493
+ colorStart: props.colorStart,
494
+ colorEnd: props.colorEnd,
495
+ fadeSize: props.fadeSize,
496
+ fadeSizeCurve: props.fadeSizeCurve || null,
497
+ fadeOpacity: props.fadeOpacity,
498
+ fadeOpacityCurve: props.fadeOpacityCurve || null,
499
+ velocityCurve: props.velocityCurve || null,
500
+ gravity: props.gravity,
501
+ lifetime: props.lifetime,
502
+ direction: props.direction,
503
+ startPosition: props.startPosition,
504
+ startPositionAsDirection: props.startPositionAsDirection,
505
+ speed: props.speed,
506
+ friction: props.friction,
507
+ appearance: props.appearance,
508
+ rotation: props.rotation,
509
+ rotationSpeed: props.rotationSpeed,
510
+ rotationSpeedCurve: props.rotationSpeedCurve || null,
511
+ orientToDirection: props.orientToDirection,
512
+ orientAxis: props.orientAxis,
513
+ stretchBySpeed: props.stretchBySpeed || null,
514
+ lighting: props.lighting,
515
+ shadow: props.shadow,
516
+ blending: props.blending,
517
+ intensity: props.intensity,
518
+ position: props.position,
519
+ autoStart: props.autoStart,
520
+ delay: props.delay,
521
+ emitCount: props.emitCount,
522
+ emitterShape: props.emitterShape,
523
+ emitterRadius: props.emitterRadius,
524
+ emitterAngle: props.emitterAngle,
525
+ emitterHeight: props.emitterHeight,
526
+ emitterSurfaceOnly: props.emitterSurfaceOnly,
527
+ emitterDirection: props.emitterDirection,
528
+ turbulence: props.turbulence,
529
+ attractToCenter: props.attractToCenter,
530
+ softParticles: props.softParticles,
531
+ softDistance: props.softDistance,
532
+ collision: props.collision
533
+ }, detectGeometryTypeAndArgs(props.geometry));
534
+ debugValuesRef.value = initialValues;
535
+ prevGeometryTypeRef.value = initialValues.geometryType;
536
+ prevGeometryArgsRef.value = initialValues.geometryArgs;
537
+ }
538
+ renderDebugPanel(debugValuesRef.value, handleDebugUpdate, "tres");
539
+ });
540
+ }
541
+ watch(
542
+ () => [
543
+ props.maxParticles,
544
+ props.lighting,
545
+ props.appearance,
546
+ props.orientToDirection,
547
+ props.geometry,
548
+ props.shadow,
549
+ props.fadeSizeCurve,
550
+ props.fadeOpacityCurve,
551
+ props.velocityCurve,
552
+ props.rotationSpeedCurve,
553
+ props.colorStart.length,
554
+ props.colorEnd,
555
+ props.rotation,
556
+ props.rotationSpeed,
557
+ props.turbulence,
558
+ props.attractors,
559
+ props.collision
560
+ ],
561
+ () => {
562
+ var _a2, _b2, _c2, _d2;
563
+ if (props.debug) return;
564
+ activeMaxParticles.value = props.maxParticles;
565
+ activeLighting.value = props.lighting;
566
+ activeAppearance.value = props.appearance;
567
+ activeOrientToDirection.value = props.orientToDirection;
568
+ activeGeometry.value = props.geometry;
569
+ activeShadow.value = props.shadow;
570
+ activeFadeSizeCurve.value = props.fadeSizeCurve;
571
+ activeFadeOpacityCurve.value = props.fadeOpacityCurve;
572
+ activeVelocityCurve.value = props.velocityCurve;
573
+ activeRotationSpeedCurve.value = props.rotationSpeedCurve;
574
+ activeNeedsPerParticleColor.value = props.colorStart.length > 1 || props.colorEnd !== null;
575
+ activeNeedsRotation.value = isNonDefaultRotation(props.rotation) || isNonDefaultRotation(props.rotationSpeed);
576
+ activeTurbulence.value = props.turbulence !== null && ((_b2 = (_a2 = props.turbulence) == null ? void 0 : _a2.intensity) != null ? _b2 : 0) > 0;
577
+ activeAttractors.value = props.attractors !== null && ((_d2 = (_c2 = props.attractors) == null ? void 0 : _c2.length) != null ? _d2 : 0) > 0;
578
+ activeCollision.value = props.collision !== null;
579
+ }
580
+ );
581
+ watch(
582
+ [
583
+ activeMaxParticles,
584
+ activeLighting,
585
+ activeAppearance,
586
+ activeOrientToDirection,
587
+ activeGeometry,
588
+ activeShadow,
589
+ activeNeedsPerParticleColor,
590
+ activeNeedsRotation,
591
+ activeTurbulence,
592
+ activeAttractors,
593
+ activeCollision,
594
+ activeFadeSizeCurve,
595
+ activeFadeOpacityCurve,
596
+ activeVelocityCurve,
597
+ activeRotationSpeedCurve
598
+ ],
599
+ () => {
600
+ initSystem();
601
+ }
602
+ );
603
+ watch(
604
+ () => [
605
+ props.position,
606
+ props.size,
607
+ props.fadeSize,
608
+ props.fadeOpacity,
609
+ props.gravity,
610
+ props.friction,
611
+ props.speed,
612
+ props.lifetime,
613
+ props.direction,
614
+ props.rotation,
615
+ props.rotationSpeed,
616
+ props.intensity,
617
+ props.colorStart,
618
+ props.colorEnd,
619
+ props.collision,
620
+ props.emitterShape,
621
+ props.emitterRadius,
622
+ props.emitterAngle,
623
+ props.emitterHeight,
624
+ props.emitterSurfaceOnly,
625
+ props.emitterDirection,
626
+ props.turbulence,
627
+ props.startPosition,
628
+ props.attractors,
629
+ props.attractToCenter,
630
+ props.startPositionAsDirection,
631
+ props.softParticles,
632
+ props.softDistance,
633
+ props.orientAxis,
634
+ props.stretchBySpeed,
635
+ props.delay,
636
+ props.emitCount
637
+ ],
638
+ () => {
639
+ var _a2, _b2;
640
+ if (props.debug) return;
641
+ const system = systemRef.value;
642
+ if (!system) return;
643
+ system.setPosition(props.position);
644
+ system.setDelay(props.delay);
645
+ system.setEmitCount(props.emitCount);
646
+ system.setTurbulenceSpeed((_b2 = (_a2 = props.turbulence) == null ? void 0 : _a2.speed) != null ? _b2 : 1);
647
+ const normalized = normalizeProps({
648
+ size: props.size,
649
+ speed: props.speed,
650
+ fadeSize: props.fadeSize,
651
+ fadeOpacity: props.fadeOpacity,
652
+ lifetime: props.lifetime,
653
+ gravity: props.gravity,
654
+ direction: props.direction,
655
+ startPosition: props.startPosition,
656
+ rotation: props.rotation,
657
+ rotationSpeed: props.rotationSpeed,
658
+ friction: props.friction,
659
+ intensity: props.intensity,
660
+ colorStart: props.colorStart,
661
+ colorEnd: props.colorEnd,
662
+ emitterShape: props.emitterShape,
663
+ emitterRadius: props.emitterRadius,
664
+ emitterAngle: props.emitterAngle,
665
+ emitterHeight: props.emitterHeight,
666
+ emitterSurfaceOnly: props.emitterSurfaceOnly,
667
+ emitterDirection: props.emitterDirection,
668
+ turbulence: props.turbulence,
669
+ attractors: props.attractors,
670
+ attractToCenter: props.attractToCenter,
671
+ startPositionAsDirection: props.startPositionAsDirection,
672
+ softParticles: props.softParticles,
673
+ softDistance: props.softDistance,
674
+ collision: props.collision,
675
+ orientAxis: props.orientAxis,
676
+ stretchBySpeed: props.stretchBySpeed
677
+ });
678
+ updateUniforms(system.uniforms, normalized);
679
+ },
680
+ { deep: true }
681
+ );
682
+ onBeforeRender(({ delta }) => {
683
+ const system = systemRef.value;
684
+ if (!system || !system.initialized) return;
685
+ system.update(delta);
686
+ if (emitting.value) {
687
+ system.autoEmit(delta);
688
+ }
689
+ });
690
+ onMounted(() => {
691
+ var _a2;
692
+ const mgr = rendererCtx;
693
+ if ((_a2 = mgr.isInitialized) == null ? void 0 : _a2.value) {
694
+ initSystem();
695
+ } else if (mgr.onReady) {
696
+ mgr.onReady(() => {
697
+ initSystem();
698
+ });
699
+ } else {
700
+ initSystem();
701
+ }
702
+ });
703
+ onUnmounted(() => {
704
+ if (props.debug) {
705
+ import("debug-vfx").then((mod) => {
706
+ mod.destroyDebugPanel();
707
+ });
708
+ }
709
+ destroySystem();
710
+ });
711
+ const api = {
712
+ spawn: (x = 0, y = 0, z = 0, count = 20, overrides = null) => {
713
+ const system = systemRef.value;
714
+ if (!system) return;
715
+ const [px, py, pz] = system.position;
716
+ system.spawn(px + x, py + y, pz + z, count, overrides);
717
+ },
718
+ start: () => {
719
+ const system = systemRef.value;
720
+ if (!system) return;
721
+ system.start();
722
+ emitting.value = true;
723
+ },
724
+ stop: () => {
725
+ const system = systemRef.value;
726
+ if (!system) return;
727
+ system.stop();
728
+ emitting.value = false;
729
+ },
730
+ clear: () => {
731
+ var _a2;
732
+ (_a2 = systemRef.value) == null ? void 0 : _a2.clear();
733
+ },
734
+ get isEmitting() {
735
+ return emitting.value;
736
+ },
737
+ get uniforms() {
738
+ var _a2, _b2;
739
+ return (_b2 = (_a2 = systemRef.value) == null ? void 0 : _a2.uniforms) != null ? _b2 : null;
740
+ }
741
+ };
742
+ expose(api);
743
+ return () => {
744
+ const obj = renderObjectRef.value;
745
+ if (!obj) return null;
746
+ return h("primitive", { object: obj });
747
+ };
748
+ }
749
+ });
750
+
751
+ // src/VFXEmitter.ts
752
+ import { defineComponent as defineComponent2, ref as ref2, watch as watch2, onMounted as onMounted2, h as h2 } from "vue";
753
+ import { useLoop as useLoop2, useTresContext as useTresContext2 } from "@tresjs/core";
754
+ import { Vector3, Quaternion } from "three/webgpu";
755
+ import {
756
+ EmitterController,
757
+ coreStore as coreStore2
758
+ } from "core-vfx";
759
+ var worldPos = new Vector3();
760
+ var worldQuat = new Quaternion();
761
+ var VFXEmitter = defineComponent2({
762
+ name: "VFXEmitter",
763
+ props: {
764
+ name: { type: String, default: void 0 },
765
+ particlesRef: { type: Object, default: void 0 },
766
+ position: {
767
+ type: null,
768
+ default: () => [0, 0, 0]
769
+ },
770
+ emitCount: { type: Number, default: 10 },
771
+ delay: { type: Number, default: 0 },
772
+ autoStart: { type: Boolean, default: true },
773
+ loop: { type: Boolean, default: true },
774
+ localDirection: { type: Boolean, default: false },
775
+ direction: {
776
+ type: null,
777
+ default: void 0
778
+ },
779
+ overrides: {
780
+ type: Object,
781
+ default: null
782
+ },
783
+ onEmit: {
784
+ type: Function,
785
+ default: void 0
786
+ }
787
+ },
788
+ setup(props, { expose, slots }) {
789
+ const { renderer } = useTresContext2();
790
+ const { onBeforeRender } = useLoop2();
791
+ const groupRef = ref2(null);
792
+ const controller = new EmitterController({
793
+ emitCount: props.emitCount,
794
+ delay: props.delay,
795
+ autoStart: props.autoStart,
796
+ loop: props.loop,
797
+ localDirection: props.localDirection,
798
+ direction: props.direction,
799
+ overrides: props.overrides,
800
+ onEmit: props.onEmit
801
+ });
802
+ function getParticleSystem() {
803
+ if (props.particlesRef) {
804
+ return props.particlesRef.value || props.particlesRef;
805
+ }
806
+ return props.name ? coreStore2.getState().getParticles(props.name) : void 0;
807
+ }
808
+ watch2(
809
+ () => [
810
+ props.emitCount,
811
+ props.delay,
812
+ props.autoStart,
813
+ props.loop,
814
+ props.localDirection,
815
+ props.direction,
816
+ props.overrides,
817
+ props.onEmit
818
+ ],
819
+ () => {
820
+ controller.updateOptions({
821
+ emitCount: props.emitCount,
822
+ delay: props.delay,
823
+ autoStart: props.autoStart,
824
+ loop: props.loop,
825
+ localDirection: props.localDirection,
826
+ direction: props.direction,
827
+ overrides: props.overrides,
828
+ onEmit: props.onEmit
829
+ });
830
+ }
831
+ );
832
+ function linkSystem() {
833
+ const system = getParticleSystem();
834
+ if (system) controller.setSystem(system);
835
+ }
836
+ onMounted2(() => {
837
+ var _a;
838
+ const mgr = renderer;
839
+ if ((_a = mgr.isInitialized) == null ? void 0 : _a.value) {
840
+ linkSystem();
841
+ } else if (mgr.onReady) {
842
+ mgr.onReady(() => {
843
+ linkSystem();
844
+ });
845
+ } else {
846
+ linkSystem();
847
+ }
848
+ });
849
+ onBeforeRender(({ delta }) => {
850
+ if (!controller.getSystem()) {
851
+ const system = getParticleSystem();
852
+ if (system) controller.setSystem(system);
853
+ }
854
+ const group = groupRef.value;
855
+ if (!group) return;
856
+ group.getWorldPosition(worldPos);
857
+ group.getWorldQuaternion(worldQuat);
858
+ controller.update(delta, worldPos, worldQuat);
859
+ });
860
+ const emit = (emitOverrides = null) => {
861
+ const group = groupRef.value;
862
+ if (!group) return false;
863
+ if (!controller.getSystem()) {
864
+ const system = getParticleSystem();
865
+ if (system) controller.setSystem(system);
866
+ }
867
+ if (!controller.getSystem()) {
868
+ if (props.name) {
869
+ console.warn(
870
+ `VFXEmitter: No particle system found for name "${props.name}"`
871
+ );
872
+ }
873
+ return false;
874
+ }
875
+ group.getWorldPosition(worldPos);
876
+ group.getWorldQuaternion(worldQuat);
877
+ return controller.emitAtPosition(worldPos, worldQuat, emitOverrides);
878
+ };
879
+ const burst = (count) => {
880
+ const group = groupRef.value;
881
+ if (!group) return false;
882
+ if (!controller.getSystem()) {
883
+ const system = getParticleSystem();
884
+ if (system) controller.setSystem(system);
885
+ }
886
+ if (!controller.getSystem()) return false;
887
+ group.getWorldPosition(worldPos);
888
+ group.getWorldQuaternion(worldQuat);
889
+ return controller.burst(count, worldPos, worldQuat);
890
+ };
891
+ const start = () => controller.start();
892
+ const stop = () => controller.stop();
893
+ expose({
894
+ emit,
895
+ burst,
896
+ start,
897
+ stop,
898
+ get isEmitting() {
899
+ return controller.isEmitting;
900
+ },
901
+ getParticleSystem,
902
+ get group() {
903
+ return groupRef.value;
904
+ }
905
+ });
906
+ return () => {
907
+ return h2(
908
+ "TresGroup",
909
+ {
910
+ ref: (el) => {
911
+ groupRef.value = el;
912
+ },
913
+ position: props.position
914
+ },
915
+ slots.default ? slots.default() : void 0
916
+ );
917
+ };
918
+ }
919
+ });
920
+ function useVFXEmitter(name) {
921
+ const getParticles = () => coreStore2.getState().getParticles(name);
922
+ const emit = (position = [0, 0, 0], count = 20, overrides = null) => {
923
+ const [x, y, z] = position;
924
+ return coreStore2.getState().emit(name, { x, y, z, count, overrides });
925
+ };
926
+ const burst = (position = [0, 0, 0], count = 50, overrides = null) => {
927
+ const [x, y, z] = position;
928
+ return coreStore2.getState().emit(name, { x, y, z, count, overrides });
929
+ };
930
+ const start = () => {
931
+ return coreStore2.getState().start(name);
932
+ };
933
+ const stop = () => {
934
+ return coreStore2.getState().stop(name);
935
+ };
936
+ const clear = () => {
937
+ return coreStore2.getState().clear(name);
938
+ };
939
+ const isEmitting = () => {
940
+ var _a;
941
+ const particles = getParticles();
942
+ return (_a = particles == null ? void 0 : particles.isEmitting) != null ? _a : false;
943
+ };
944
+ const getUniforms = () => {
945
+ var _a;
946
+ const particles = getParticles();
947
+ return (_a = particles == null ? void 0 : particles.uniforms) != null ? _a : null;
948
+ };
949
+ return {
950
+ emit,
951
+ burst,
952
+ start,
953
+ stop,
954
+ clear,
955
+ isEmitting,
956
+ getUniforms,
957
+ getParticles
958
+ };
959
+ }
960
+
961
+ // src/vue-store.ts
962
+ import { ref as ref3, onUnmounted as onUnmounted2 } from "vue";
963
+ import { coreStore as coreStore3 } from "core-vfx";
964
+ function useVFXStore(selector) {
965
+ const pick = selector != null ? selector : ((s) => s);
966
+ const state = ref3(pick(coreStore3.getState()));
967
+ const unsubscribe = coreStore3.subscribe((s) => {
968
+ state.value = pick(s);
969
+ });
970
+ onUnmounted2(unsubscribe);
971
+ return state;
972
+ }
973
+ useVFXStore.getState = coreStore3.getState;
974
+ useVFXStore.setState = coreStore3.setState;
975
+ useVFXStore.subscribe = coreStore3.subscribe;
976
+
1
977
  // src/index.ts
2
- console.log("tres-vfx");
978
+ import {
979
+ Appearance as Appearance2,
980
+ Blending as Blending2,
981
+ EmitterShape as EmitterShape2,
982
+ AttractorType,
983
+ Easing,
984
+ Lighting as Lighting2,
985
+ bakeCurveToArray,
986
+ createCombinedCurveTexture,
987
+ buildCurveTextureBin,
988
+ CurveChannel
989
+ } from "core-vfx";
990
+ import {
991
+ VFXParticleSystem as VFXParticleSystem2,
992
+ EmitterController as EmitterController2,
993
+ isWebGPUBackend,
994
+ isNonDefaultRotation as isNonDefaultRotation2,
995
+ normalizeProps as normalizeProps2,
996
+ resolveCurveTexture
997
+ } from "core-vfx";
998
+ export {
999
+ Appearance2 as Appearance,
1000
+ AttractorType,
1001
+ Blending2 as Blending,
1002
+ CurveChannel,
1003
+ Easing,
1004
+ EmitterController2 as EmitterController,
1005
+ EmitterShape2 as EmitterShape,
1006
+ Lighting2 as Lighting,
1007
+ VFXEmitter,
1008
+ VFXParticleSystem2 as VFXParticleSystem,
1009
+ VFXParticles,
1010
+ bakeCurveToArray,
1011
+ buildCurveTextureBin,
1012
+ createCombinedCurveTexture,
1013
+ isNonDefaultRotation2 as isNonDefaultRotation,
1014
+ isWebGPUBackend,
1015
+ normalizeProps2 as normalizeProps,
1016
+ resolveCurveTexture,
1017
+ useVFXEmitter,
1018
+ useVFXStore
1019
+ };