threlte-vfx 0.2.0 → 0.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +70 -13
- package/dist/index.d.ts +92 -2
- package/dist/index.js +746 -35
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
|
-
#
|
|
1
|
+
# ✨ Three VFX ✨
|
|
2
2
|
|
|
3
|
-
High-performance GPU-accelerated particle system for Three.js WebGPU
|
|
3
|
+
High-performance GPU-accelerated particle system for Three.js WebGPU.
|
|
4
|
+
|
|
5
|
+
Available for React Three Fiber (R3F), and experimentally for vanilla Three.js, TresJS (Vue), and Threlte (Svelte).
|
|
4
6
|
|
|
5
7
|
## Features
|
|
6
8
|
|
|
@@ -12,24 +14,22 @@ High-performance GPU-accelerated particle system for Three.js WebGPU with React
|
|
|
12
14
|
- 🔗 **Emitter System** - Decoupled emitters that can share particle systems
|
|
13
15
|
- ⚡ **WebGPU Native** - Built specifically for Three.js WebGPU renderer
|
|
14
16
|
|
|
15
|
-
|
|
17
|
+
⚠️ Three VFX only supports WebGPU at the moment ([79% global support](https://caniuse.com/webgpu)). A `fallback` option is available to replace the particle systems by your own fallback objects.
|
|
16
18
|
|
|
17
|
-
```bash
|
|
18
|
-
npm install r3f-vfx
|
|
19
|
-
```
|
|
20
19
|
|
|
21
|
-
|
|
20
|
+
## Quick Start
|
|
21
|
+
|
|
22
|
+
### React Three Fiber
|
|
23
|
+
|
|
24
|
+
Add it to your React Three Fiber project with:
|
|
22
25
|
|
|
23
26
|
```bash
|
|
24
|
-
npm install
|
|
27
|
+
npm install r3f-vfx
|
|
25
28
|
```
|
|
26
29
|
|
|
27
|
-
## Quick Start
|
|
28
|
-
|
|
29
30
|
```tsx
|
|
30
31
|
import { Canvas } from '@react-three/fiber'
|
|
31
|
-
import { VFXParticles
|
|
32
|
-
import * as THREE from 'three/webgpu'
|
|
32
|
+
import { VFXParticles } from 'r3f-vfx'
|
|
33
33
|
|
|
34
34
|
function App() {
|
|
35
35
|
return (
|
|
@@ -40,7 +40,64 @@ function App() {
|
|
|
40
40
|
}
|
|
41
41
|
```
|
|
42
42
|
|
|
43
|
-
|
|
43
|
+
### Vanilla Three.js (Experimental)
|
|
44
|
+
|
|
45
|
+
Add it to your vanilla Three.js project with:
|
|
46
|
+
|
|
47
|
+
```bash
|
|
48
|
+
npm install vanilla-vfx
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
```ts
|
|
52
|
+
import { VFXParticles } from 'vanilla-vfx'
|
|
53
|
+
|
|
54
|
+
const particles = new VFXParticles(renderer, { debug: true })
|
|
55
|
+
scene.add(particles.renderObject)
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
### TresJS / Vue (Experimental)
|
|
59
|
+
|
|
60
|
+
Add it to your TresJS project with:
|
|
61
|
+
|
|
62
|
+
```bash
|
|
63
|
+
npm install tres-vfx
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
```vue
|
|
67
|
+
<script setup>
|
|
68
|
+
import { TresCanvas } from '@tresjs/core'
|
|
69
|
+
import { VFXParticles } from 'tres-vfx'
|
|
70
|
+
</script>
|
|
71
|
+
|
|
72
|
+
<template>
|
|
73
|
+
<TresCanvas>
|
|
74
|
+
<VFXParticles debug />
|
|
75
|
+
</TresCanvas>
|
|
76
|
+
</template>
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
### Threlte / Svelte (Experimental)
|
|
80
|
+
|
|
81
|
+
Add it to your Threlte project with:
|
|
82
|
+
|
|
83
|
+
```bash
|
|
84
|
+
npm install threlte-vfx
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
```svelte
|
|
88
|
+
<script>
|
|
89
|
+
import { Canvas } from '@threlte/core'
|
|
90
|
+
import VFXParticles from 'threlte-vfx/VFXParticles.svelte'
|
|
91
|
+
</script>
|
|
92
|
+
|
|
93
|
+
<Canvas>
|
|
94
|
+
<VFXParticles debug />
|
|
95
|
+
</Canvas>
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
## How to use
|
|
99
|
+
|
|
100
|
+
Use the debug panel to design your effect, then copy the generated code and replace it in your code.
|
|
44
101
|
|
|
45
102
|
## API Reference
|
|
46
103
|
|
package/dist/index.d.ts
CHANGED
|
@@ -1,8 +1,98 @@
|
|
|
1
|
+
import { SvelteComponent, Snippet } from 'svelte';
|
|
1
2
|
import * as core_vfx from 'core-vfx';
|
|
2
|
-
import { CoreState } from 'core-vfx';
|
|
3
|
+
import { VFXParticleSystemOptions, FrictionConfig, FlipbookConfig, Rotation3DInput, StretchConfig, TurbulenceConfig, AttractorConfig, CollisionConfig, EmitterControllerOptions, CoreState } from 'core-vfx';
|
|
3
4
|
export { Appearance, AttractorConfig, AttractorType, BaseParticleProps, Blending, CollisionConfig, CurveChannel, CurveData, CurvePoint, CurveTextureResolved, CurveTextureResult, Easing, EmitterController, EmitterControllerOptions, EmitterShape, FlipbookConfig, FrictionConfig, Lighting, NormalizedParticleProps, ParticleData, Rotation3DInput, StretchConfig, TurbulenceConfig, VFXParticleSystem, VFXParticleSystemOptions, bakeCurveToArray, buildCurveTextureBin, createCombinedCurveTexture, isNonDefaultRotation, isWebGPUBackend, normalizeProps, resolveCurveTexture } from 'core-vfx';
|
|
5
|
+
import { Texture, BufferGeometry } from 'three';
|
|
4
6
|
import { Readable } from 'svelte/store';
|
|
5
7
|
|
|
8
|
+
interface VFXParticlesProps {
|
|
9
|
+
name?: string
|
|
10
|
+
debug?: boolean
|
|
11
|
+
maxParticles?: number
|
|
12
|
+
size?: [number, number] | number
|
|
13
|
+
colorStart?: string[]
|
|
14
|
+
colorEnd?: string[] | null
|
|
15
|
+
fadeSize?: [number, number]
|
|
16
|
+
fadeSizeCurve?: unknown[] | null
|
|
17
|
+
fadeOpacity?: [number, number]
|
|
18
|
+
fadeOpacityCurve?: unknown[] | null
|
|
19
|
+
velocityCurve?: unknown[] | null
|
|
20
|
+
gravity?: [number, number, number]
|
|
21
|
+
lifetime?: [number, number]
|
|
22
|
+
direction?: VFXParticleSystemOptions['direction']
|
|
23
|
+
startPosition?: VFXParticleSystemOptions['startPosition']
|
|
24
|
+
speed?: [number, number] | number
|
|
25
|
+
friction?: FrictionConfig
|
|
26
|
+
appearance?: string | number
|
|
27
|
+
alphaMap?: Texture | null
|
|
28
|
+
flipbook?: FlipbookConfig | null
|
|
29
|
+
rotation?: Rotation3DInput
|
|
30
|
+
rotationSpeed?: Rotation3DInput
|
|
31
|
+
rotationSpeedCurve?: unknown[] | null
|
|
32
|
+
geometry?: BufferGeometry | null
|
|
33
|
+
orientToDirection?: boolean
|
|
34
|
+
orientAxis?: string
|
|
35
|
+
stretchBySpeed?: StretchConfig | null
|
|
36
|
+
lighting?: string | number
|
|
37
|
+
shadow?: boolean
|
|
38
|
+
blending?: string | number
|
|
39
|
+
intensity?: number
|
|
40
|
+
position?: [number, number, number]
|
|
41
|
+
autoStart?: boolean
|
|
42
|
+
delay?: number
|
|
43
|
+
backdropNode?: unknown
|
|
44
|
+
opacityNode?: unknown
|
|
45
|
+
colorNode?: unknown
|
|
46
|
+
alphaTestNode?: unknown
|
|
47
|
+
castShadowNode?: unknown
|
|
48
|
+
emitCount?: number
|
|
49
|
+
emitterShape?: string | number
|
|
50
|
+
emitterRadius?: [number, number]
|
|
51
|
+
emitterAngle?: number
|
|
52
|
+
emitterHeight?: [number, number]
|
|
53
|
+
emitterSurfaceOnly?: boolean
|
|
54
|
+
emitterDirection?: [number, number, number]
|
|
55
|
+
turbulence?: TurbulenceConfig | null
|
|
56
|
+
attractors?: AttractorConfig[] | null
|
|
57
|
+
attractToCenter?: boolean
|
|
58
|
+
startPositionAsDirection?: boolean
|
|
59
|
+
softParticles?: boolean
|
|
60
|
+
softDistance?: number
|
|
61
|
+
collision?: CollisionConfig | null
|
|
62
|
+
curveTexturePath?: string | null
|
|
63
|
+
depthTest?: boolean
|
|
64
|
+
renderOrder?: number
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
declare class VFXParticles extends SvelteComponent<VFXParticlesProps> {
|
|
68
|
+
spawn(x?: number, y?: number, z?: number, count?: number, overrides?: Record<string, unknown> | null): void
|
|
69
|
+
start(): void
|
|
70
|
+
stop(): void
|
|
71
|
+
clear(): void
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
interface VFXEmitterProps {
|
|
75
|
+
name?: string
|
|
76
|
+
particlesRef?: any
|
|
77
|
+
position?: [number, number, number]
|
|
78
|
+
emitCount?: number
|
|
79
|
+
delay?: number
|
|
80
|
+
autoStart?: boolean
|
|
81
|
+
loop?: boolean
|
|
82
|
+
localDirection?: boolean
|
|
83
|
+
direction?: EmitterControllerOptions['direction']
|
|
84
|
+
overrides?: Record<string, unknown> | null
|
|
85
|
+
onEmit?: EmitterControllerOptions['onEmit']
|
|
86
|
+
children?: Snippet
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
declare class VFXEmitter extends SvelteComponent<VFXEmitterProps> {
|
|
90
|
+
emit(emitOverrides?: Record<string, unknown> | null): boolean
|
|
91
|
+
burst(count: number): boolean
|
|
92
|
+
start(): void
|
|
93
|
+
stop(): void
|
|
94
|
+
}
|
|
95
|
+
|
|
6
96
|
declare function useVFXEmitter(name: string): {
|
|
7
97
|
emit: (position?: [number, number, number], count?: number, overrides?: Record<string, unknown> | null) => boolean;
|
|
8
98
|
burst: (position?: [number, number, number], count?: number, overrides?: Record<string, unknown> | null) => boolean;
|
|
@@ -25,4 +115,4 @@ declare namespace useVFXStore {
|
|
|
25
115
|
var subscribe: (listener: (state: CoreState, prevState: CoreState) => void) => () => void;
|
|
26
116
|
}
|
|
27
117
|
|
|
28
|
-
export { useVFXEmitter, useVFXStore };
|
|
118
|
+
export { VFXEmitter, VFXParticles, useVFXEmitter, useVFXStore };
|
package/dist/index.js
CHANGED
|
@@ -1,33 +1,742 @@
|
|
|
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 prop3 in b || (b = {}))
|
|
10
|
+
if (__hasOwnProp.call(b, prop3))
|
|
11
|
+
__defNormalProp(a, prop3, b[prop3]);
|
|
12
|
+
if (__getOwnPropSymbols)
|
|
13
|
+
for (var prop3 of __getOwnPropSymbols(b)) {
|
|
14
|
+
if (__propIsEnum.call(b, prop3))
|
|
15
|
+
__defNormalProp(a, prop3, b[prop3]);
|
|
16
|
+
}
|
|
17
|
+
return a;
|
|
18
|
+
};
|
|
19
|
+
var __spreadProps = (a, b) => __defProps(a, __getOwnPropDescs(b));
|
|
20
|
+
|
|
21
|
+
// src/VFXParticles.svelte
|
|
22
|
+
import "svelte/internal/disclose-version";
|
|
23
|
+
import * as $ from "svelte/internal/client";
|
|
24
|
+
import { T, useThrelte, useTask } from "@threlte/core";
|
|
25
|
+
import { onMount, onDestroy, untrack } from "svelte";
|
|
26
|
+
import * as THREE from "three/webgpu";
|
|
27
|
+
import { coreStore } from "core-vfx";
|
|
28
|
+
import {
|
|
29
|
+
Appearance,
|
|
30
|
+
Blending,
|
|
31
|
+
EmitterShape,
|
|
32
|
+
Lighting,
|
|
33
|
+
VFXParticleSystem,
|
|
34
|
+
isWebGPUBackend,
|
|
35
|
+
isNonDefaultRotation,
|
|
36
|
+
normalizeProps,
|
|
37
|
+
updateUniforms,
|
|
38
|
+
updateUniformsPartial,
|
|
39
|
+
resolveFeatures
|
|
40
|
+
} from "core-vfx";
|
|
41
|
+
function VFXParticles($$anchor, $$props) {
|
|
42
|
+
var _a, _b, _c, _d;
|
|
43
|
+
$.push($$props, true);
|
|
44
|
+
let name = $.prop($$props, "name", 19, () => void 0), debug = $.prop($$props, "debug", 3, false), maxParticles = $.prop($$props, "maxParticles", 3, 1e4), size = $.prop($$props, "size", 19, () => [0.1, 0.3]), colorStart = $.prop($$props, "colorStart", 19, () => ["#ffffff"]), colorEnd = $.prop($$props, "colorEnd", 3, null), fadeSize = $.prop($$props, "fadeSize", 19, () => [1, 0]), fadeSizeCurve = $.prop($$props, "fadeSizeCurve", 3, null), fadeOpacity = $.prop($$props, "fadeOpacity", 19, () => [1, 0]), fadeOpacityCurve = $.prop($$props, "fadeOpacityCurve", 3, null), velocityCurve = $.prop($$props, "velocityCurve", 3, null), gravity = $.prop($$props, "gravity", 19, () => [0, 0, 0]), lifetime = $.prop($$props, "lifetime", 19, () => [1, 2]), direction = $.prop($$props, "direction", 19, () => [[-1, 1], [0, 1], [-1, 1]]), startPosition = $.prop($$props, "startPosition", 19, () => [[0, 0], [0, 0], [0, 0]]), speed = $.prop($$props, "speed", 19, () => [0.1, 0.1]), friction = $.prop($$props, "friction", 19, () => ({ intensity: 0, easing: "linear" })), appearance = $.prop($$props, "appearance", 19, () => Appearance.GRADIENT), alphaMap = $.prop($$props, "alphaMap", 3, null), flipbook = $.prop($$props, "flipbook", 3, null), rotation = $.prop($$props, "rotation", 19, () => [0, 0]), rotationSpeed = $.prop($$props, "rotationSpeed", 19, () => [0, 0]), rotationSpeedCurve = $.prop($$props, "rotationSpeedCurve", 3, null), geometry = $.prop($$props, "geometry", 3, null), orientToDirection = $.prop($$props, "orientToDirection", 3, false), orientAxis = $.prop($$props, "orientAxis", 3, "z"), stretchBySpeed = $.prop($$props, "stretchBySpeed", 3, null), lighting = $.prop($$props, "lighting", 19, () => Lighting.STANDARD), shadow = $.prop($$props, "shadow", 3, false), blending = $.prop($$props, "blending", 19, () => Blending.NORMAL), intensity = $.prop($$props, "intensity", 3, 1), position = $.prop($$props, "position", 19, () => [0, 0, 0]), autoStart = $.prop($$props, "autoStart", 3, true), delay = $.prop($$props, "delay", 3, 0), backdropNode = $.prop($$props, "backdropNode", 3, null), opacityNode = $.prop($$props, "opacityNode", 3, null), colorNode = $.prop($$props, "colorNode", 3, null), alphaTestNode = $.prop($$props, "alphaTestNode", 3, null), castShadowNode = $.prop($$props, "castShadowNode", 3, null), emitCount = $.prop($$props, "emitCount", 3, 1), emitterShape = $.prop($$props, "emitterShape", 19, () => EmitterShape.BOX), emitterRadius = $.prop($$props, "emitterRadius", 19, () => [0, 1]), emitterAngle = $.prop($$props, "emitterAngle", 19, () => Math.PI / 4), emitterHeight = $.prop($$props, "emitterHeight", 19, () => [0, 1]), emitterSurfaceOnly = $.prop($$props, "emitterSurfaceOnly", 3, false), emitterDirection = $.prop($$props, "emitterDirection", 19, () => [0, 1, 0]), turbulence = $.prop($$props, "turbulence", 3, null), attractors = $.prop($$props, "attractors", 3, null), attractToCenter = $.prop($$props, "attractToCenter", 3, false), startPositionAsDirection = $.prop($$props, "startPositionAsDirection", 3, false), softParticles = $.prop($$props, "softParticles", 3, false), softDistance = $.prop($$props, "softDistance", 3, 0.5), collision = $.prop($$props, "collision", 3, null), curveTexturePath = $.prop($$props, "curveTexturePath", 3, null), depthTest = $.prop($$props, "depthTest", 3, true), renderOrder = $.prop($$props, "renderOrder", 3, 0);
|
|
45
|
+
const { renderer } = useThrelte();
|
|
46
|
+
let warnedWebGL = false;
|
|
47
|
+
let mounted = false;
|
|
48
|
+
let _system = null;
|
|
49
|
+
let _renderObject = null;
|
|
50
|
+
let _isWebGPU = false;
|
|
51
|
+
let _emitting = autoStart();
|
|
52
|
+
let renderObjectForTemplate = $.state(null);
|
|
53
|
+
let isWebGPUForTemplate = $.state(false);
|
|
54
|
+
let debugValues = null;
|
|
55
|
+
let activeMaxParticles = $.state($.proxy(maxParticles()));
|
|
56
|
+
let activeLighting = $.state($.proxy(lighting()));
|
|
57
|
+
let activeAppearance = $.state($.proxy(appearance()));
|
|
58
|
+
let activeOrientToDirection = $.state($.proxy(orientToDirection()));
|
|
59
|
+
let activeGeometry = $.state($.proxy(geometry()));
|
|
60
|
+
let activeShadow = $.state($.proxy(shadow()));
|
|
61
|
+
let activeFadeSizeCurve = $.state($.proxy(fadeSizeCurve()));
|
|
62
|
+
let activeFadeOpacityCurve = $.state($.proxy(fadeOpacityCurve()));
|
|
63
|
+
let activeVelocityCurve = $.state($.proxy(velocityCurve()));
|
|
64
|
+
let activeRotationSpeedCurve = $.state($.proxy(rotationSpeedCurve()));
|
|
65
|
+
let activeTurbulence = $.state($.proxy(turbulence() !== null && ((_b = (_a = turbulence()) == null ? void 0 : _a.intensity) != null ? _b : 0) > 0));
|
|
66
|
+
let activeAttractors = $.state($.proxy(attractors() !== null && ((_d = (_c = attractors()) == null ? void 0 : _c.length) != null ? _d : 0) > 0));
|
|
67
|
+
let activeCollision = $.state(collision() !== null);
|
|
68
|
+
let activeNeedsPerParticleColor = $.state($.proxy(colorStart().length > 1 || colorEnd() !== null));
|
|
69
|
+
let activeNeedsRotation = $.state($.proxy(isNonDefaultRotation(rotation()) || isNonDefaultRotation(rotationSpeed())));
|
|
70
|
+
let prevGeometryType = null;
|
|
71
|
+
let prevGeometryArgs = null;
|
|
72
|
+
function buildOptions() {
|
|
73
|
+
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;
|
|
74
|
+
const dbg = debug() ? debugValues : null;
|
|
75
|
+
return {
|
|
76
|
+
maxParticles: untrack(() => $.get(activeMaxParticles)),
|
|
77
|
+
size: (_a2 = dbg == null ? void 0 : dbg.size) != null ? _a2 : size(),
|
|
78
|
+
colorStart: (_b2 = dbg == null ? void 0 : dbg.colorStart) != null ? _b2 : colorStart(),
|
|
79
|
+
colorEnd: (dbg == null ? void 0 : dbg.colorEnd) !== void 0 ? dbg.colorEnd : colorEnd(),
|
|
80
|
+
fadeSize: (_c2 = dbg == null ? void 0 : dbg.fadeSize) != null ? _c2 : fadeSize(),
|
|
81
|
+
fadeSizeCurve: untrack(() => $.get(activeFadeSizeCurve)),
|
|
82
|
+
fadeOpacity: (_d2 = dbg == null ? void 0 : dbg.fadeOpacity) != null ? _d2 : fadeOpacity(),
|
|
83
|
+
fadeOpacityCurve: untrack(() => $.get(activeFadeOpacityCurve)),
|
|
84
|
+
velocityCurve: untrack(() => $.get(activeVelocityCurve)),
|
|
85
|
+
gravity: (_e = dbg == null ? void 0 : dbg.gravity) != null ? _e : gravity(),
|
|
86
|
+
lifetime: (_f = dbg == null ? void 0 : dbg.lifetime) != null ? _f : lifetime(),
|
|
87
|
+
direction: (_g = dbg == null ? void 0 : dbg.direction) != null ? _g : direction(),
|
|
88
|
+
startPosition: (_h = dbg == null ? void 0 : dbg.startPosition) != null ? _h : startPosition(),
|
|
89
|
+
speed: (_i = dbg == null ? void 0 : dbg.speed) != null ? _i : speed(),
|
|
90
|
+
friction: (_j = dbg == null ? void 0 : dbg.friction) != null ? _j : friction(),
|
|
91
|
+
appearance: untrack(() => $.get(activeAppearance)),
|
|
92
|
+
alphaMap: alphaMap(),
|
|
93
|
+
flipbook: flipbook(),
|
|
94
|
+
rotation: (_k = dbg == null ? void 0 : dbg.rotation) != null ? _k : rotation(),
|
|
95
|
+
rotationSpeed: (_l = dbg == null ? void 0 : dbg.rotationSpeed) != null ? _l : rotationSpeed(),
|
|
96
|
+
rotationSpeedCurve: untrack(() => $.get(activeRotationSpeedCurve)),
|
|
97
|
+
geometry: untrack(() => $.get(activeGeometry)),
|
|
98
|
+
orientToDirection: untrack(() => $.get(activeOrientToDirection)),
|
|
99
|
+
orientAxis: (_m = dbg == null ? void 0 : dbg.orientAxis) != null ? _m : orientAxis(),
|
|
100
|
+
stretchBySpeed: (_n = dbg == null ? void 0 : dbg.stretchBySpeed) != null ? _n : stretchBySpeed(),
|
|
101
|
+
lighting: untrack(() => $.get(activeLighting)),
|
|
102
|
+
shadow: untrack(() => $.get(activeShadow)),
|
|
103
|
+
blending: (_o = dbg == null ? void 0 : dbg.blending) != null ? _o : blending(),
|
|
104
|
+
intensity: (_p = dbg == null ? void 0 : dbg.intensity) != null ? _p : intensity(),
|
|
105
|
+
position: (_q = dbg == null ? void 0 : dbg.position) != null ? _q : position(),
|
|
106
|
+
autoStart: (_r = dbg == null ? void 0 : dbg.autoStart) != null ? _r : autoStart(),
|
|
107
|
+
delay: (_s = dbg == null ? void 0 : dbg.delay) != null ? _s : delay(),
|
|
108
|
+
emitCount: (_t = dbg == null ? void 0 : dbg.emitCount) != null ? _t : emitCount(),
|
|
109
|
+
emitterShape: (_u = dbg == null ? void 0 : dbg.emitterShape) != null ? _u : emitterShape(),
|
|
110
|
+
emitterRadius: (_v = dbg == null ? void 0 : dbg.emitterRadius) != null ? _v : emitterRadius(),
|
|
111
|
+
emitterAngle: (_w = dbg == null ? void 0 : dbg.emitterAngle) != null ? _w : emitterAngle(),
|
|
112
|
+
emitterHeight: (_x = dbg == null ? void 0 : dbg.emitterHeight) != null ? _x : emitterHeight(),
|
|
113
|
+
emitterSurfaceOnly: (_y = dbg == null ? void 0 : dbg.emitterSurfaceOnly) != null ? _y : emitterSurfaceOnly(),
|
|
114
|
+
emitterDirection: (_z = dbg == null ? void 0 : dbg.emitterDirection) != null ? _z : emitterDirection(),
|
|
115
|
+
turbulence: (_A = dbg == null ? void 0 : dbg.turbulence) != null ? _A : turbulence(),
|
|
116
|
+
attractors: (_B = dbg == null ? void 0 : dbg.attractors) != null ? _B : attractors(),
|
|
117
|
+
attractToCenter: (_C = dbg == null ? void 0 : dbg.attractToCenter) != null ? _C : attractToCenter(),
|
|
118
|
+
startPositionAsDirection: (_D = dbg == null ? void 0 : dbg.startPositionAsDirection) != null ? _D : startPositionAsDirection(),
|
|
119
|
+
softParticles: (_E = dbg == null ? void 0 : dbg.softParticles) != null ? _E : softParticles(),
|
|
120
|
+
softDistance: (_F = dbg == null ? void 0 : dbg.softDistance) != null ? _F : softDistance(),
|
|
121
|
+
collision: (_G = dbg == null ? void 0 : dbg.collision) != null ? _G : collision(),
|
|
122
|
+
backdropNode: backdropNode(),
|
|
123
|
+
opacityNode: opacityNode(),
|
|
124
|
+
colorNode: colorNode(),
|
|
125
|
+
alphaTestNode: alphaTestNode(),
|
|
126
|
+
castShadowNode: castShadowNode(),
|
|
127
|
+
depthTest: (_H = dbg == null ? void 0 : dbg.depthTest) != null ? _H : depthTest(),
|
|
128
|
+
renderOrder: (_I = dbg == null ? void 0 : dbg.renderOrder) != null ? _I : renderOrder(),
|
|
129
|
+
curveTexturePath: curveTexturePath()
|
|
130
|
+
};
|
|
131
|
+
}
|
|
132
|
+
function createSystem() {
|
|
133
|
+
const r = renderer;
|
|
134
|
+
if (!r) return null;
|
|
135
|
+
return new VFXParticleSystem(r, buildOptions());
|
|
136
|
+
}
|
|
137
|
+
function destroySystem() {
|
|
138
|
+
if (!_system) return;
|
|
139
|
+
if (name()) {
|
|
140
|
+
coreStore.getState().unregisterParticles(name());
|
|
141
|
+
}
|
|
142
|
+
_system.dispose();
|
|
143
|
+
_system = null;
|
|
144
|
+
_renderObject = null;
|
|
145
|
+
$.set(renderObjectForTemplate, null);
|
|
146
|
+
$.set(isWebGPUForTemplate, false);
|
|
147
|
+
}
|
|
148
|
+
function initSystem() {
|
|
149
|
+
const oldSystem = _system;
|
|
150
|
+
if (oldSystem) {
|
|
151
|
+
oldSystem.initialized = false;
|
|
152
|
+
if (name()) {
|
|
153
|
+
coreStore.getState().unregisterParticles(name());
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
_system = null;
|
|
157
|
+
_renderObject = null;
|
|
158
|
+
if (!renderer) {
|
|
159
|
+
console.warn("threlte-vfx: No renderer instance available");
|
|
160
|
+
return;
|
|
161
|
+
}
|
|
162
|
+
if (!isWebGPUBackend(renderer)) {
|
|
163
|
+
if (!warnedWebGL) {
|
|
164
|
+
warnedWebGL = true;
|
|
165
|
+
console.warn("threlte-vfx: WebGPU backend not detected. Particle system disabled.");
|
|
166
|
+
}
|
|
167
|
+
_isWebGPU = false;
|
|
168
|
+
$.set(isWebGPUForTemplate, false);
|
|
169
|
+
$.set(renderObjectForTemplate, null);
|
|
170
|
+
return;
|
|
171
|
+
}
|
|
172
|
+
_isWebGPU = true;
|
|
173
|
+
const newSystem = createSystem();
|
|
174
|
+
if (!newSystem) return;
|
|
175
|
+
_system = newSystem;
|
|
176
|
+
_renderObject = newSystem.renderObject;
|
|
177
|
+
newSystem.init();
|
|
178
|
+
if (name()) {
|
|
179
|
+
coreStore.getState().registerParticles(name(), {
|
|
180
|
+
spawn: (x = 0, y = 0, z = 0, count = 20, overrides = null) => {
|
|
181
|
+
const [px, py, pz] = newSystem.position;
|
|
182
|
+
newSystem.spawn(px + x, py + y, pz + z, count, overrides);
|
|
183
|
+
},
|
|
184
|
+
start: () => {
|
|
185
|
+
newSystem.start();
|
|
186
|
+
_emitting = true;
|
|
187
|
+
},
|
|
188
|
+
stop: () => {
|
|
189
|
+
newSystem.stop();
|
|
190
|
+
_emitting = false;
|
|
191
|
+
},
|
|
192
|
+
get isEmitting() {
|
|
193
|
+
return _emitting;
|
|
194
|
+
},
|
|
195
|
+
clear: () => newSystem.clear(),
|
|
196
|
+
uniforms: newSystem.uniforms
|
|
197
|
+
});
|
|
198
|
+
}
|
|
199
|
+
if (debug()) {
|
|
200
|
+
initDebugPanel();
|
|
201
|
+
}
|
|
202
|
+
$.set(isWebGPUForTemplate, true);
|
|
203
|
+
$.set(renderObjectForTemplate, newSystem.renderObject, true);
|
|
204
|
+
}
|
|
205
|
+
function handleDebugUpdate(newValues) {
|
|
206
|
+
var _a2, _b2, _c2, _d2, _e, _f, _g, _h;
|
|
207
|
+
debugValues = __spreadValues(__spreadValues({}, debugValues), newValues);
|
|
208
|
+
if (!_system) return;
|
|
209
|
+
if ("colorStart" in newValues && newValues.colorStart) {
|
|
210
|
+
const currentColorEnd = debugValues == null ? void 0 : debugValues.colorEnd;
|
|
211
|
+
if (!currentColorEnd) {
|
|
212
|
+
newValues = __spreadProps(__spreadValues({}, newValues), { colorEnd: null });
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
if ("colorEnd" in newValues && !newValues.colorEnd) {
|
|
216
|
+
newValues = __spreadProps(__spreadValues({}, newValues), {
|
|
217
|
+
colorEnd: null,
|
|
218
|
+
colorStart: (_b2 = (_a2 = newValues.colorStart) != null ? _a2 : debugValues == null ? void 0 : debugValues.colorStart) != null ? _b2 : ["#ffffff"]
|
|
219
|
+
});
|
|
220
|
+
}
|
|
221
|
+
updateUniformsPartial(_system.uniforms, newValues);
|
|
222
|
+
if ("fadeSizeCurve" in newValues) {
|
|
223
|
+
$.set(activeFadeSizeCurve, newValues.fadeSizeCurve, true);
|
|
224
|
+
}
|
|
225
|
+
if ("fadeOpacityCurve" in newValues) {
|
|
226
|
+
$.set(activeFadeOpacityCurve, newValues.fadeOpacityCurve, true);
|
|
227
|
+
}
|
|
228
|
+
if ("velocityCurve" in newValues) {
|
|
229
|
+
$.set(activeVelocityCurve, newValues.velocityCurve, true);
|
|
230
|
+
}
|
|
231
|
+
if ("rotationSpeedCurve" in newValues) {
|
|
232
|
+
$.set(activeRotationSpeedCurve, newValues.rotationSpeedCurve, true);
|
|
233
|
+
}
|
|
234
|
+
if ("turbulence" in newValues) {
|
|
235
|
+
_system.setTurbulenceSpeed((_d2 = (_c2 = newValues.turbulence) == null ? void 0 : _c2.speed) != null ? _d2 : 1);
|
|
236
|
+
}
|
|
237
|
+
const newFeatures = resolveFeatures(debugValues);
|
|
238
|
+
if (newFeatures.needsRotation !== $.get(activeNeedsRotation)) {
|
|
239
|
+
$.set(activeNeedsRotation, newFeatures.needsRotation, true);
|
|
240
|
+
}
|
|
241
|
+
if (newFeatures.needsPerParticleColor !== $.get(activeNeedsPerParticleColor)) {
|
|
242
|
+
$.set(activeNeedsPerParticleColor, newFeatures.needsPerParticleColor, true);
|
|
243
|
+
}
|
|
244
|
+
if (newFeatures.turbulence !== $.get(activeTurbulence)) {
|
|
245
|
+
$.set(activeTurbulence, newFeatures.turbulence, true);
|
|
246
|
+
}
|
|
247
|
+
if (newFeatures.attractors !== $.get(activeAttractors)) {
|
|
248
|
+
$.set(activeAttractors, newFeatures.attractors, true);
|
|
249
|
+
}
|
|
250
|
+
if (newFeatures.collision !== $.get(activeCollision)) {
|
|
251
|
+
$.set(activeCollision, newFeatures.collision, true);
|
|
252
|
+
}
|
|
253
|
+
if (newValues.position) {
|
|
254
|
+
_system.setPosition(newValues.position);
|
|
255
|
+
}
|
|
256
|
+
if ("delay" in newValues) _system.setDelay((_e = newValues.delay) != null ? _e : 0);
|
|
257
|
+
if ("emitCount" in newValues) _system.setEmitCount((_f = newValues.emitCount) != null ? _f : 1);
|
|
258
|
+
if (newValues.autoStart !== void 0) {
|
|
259
|
+
_emitting = newValues.autoStart;
|
|
260
|
+
}
|
|
261
|
+
if (_system.material && newValues.blending !== void 0) {
|
|
262
|
+
_system.material.blending = newValues.blending;
|
|
263
|
+
_system.material.needsUpdate = true;
|
|
264
|
+
}
|
|
265
|
+
if (newValues.maxParticles !== void 0 && newValues.maxParticles !== $.get(activeMaxParticles)) {
|
|
266
|
+
$.set(activeMaxParticles, newValues.maxParticles, true);
|
|
267
|
+
_system.initialized = false;
|
|
268
|
+
_system.nextIndex = 0;
|
|
269
|
+
}
|
|
270
|
+
if (newValues.lighting !== void 0 && newValues.lighting !== $.get(activeLighting)) {
|
|
271
|
+
$.set(activeLighting, newValues.lighting, true);
|
|
272
|
+
}
|
|
273
|
+
if (newValues.appearance !== void 0 && newValues.appearance !== $.get(activeAppearance)) {
|
|
274
|
+
$.set(activeAppearance, newValues.appearance, true);
|
|
275
|
+
}
|
|
276
|
+
if (newValues.orientToDirection !== void 0 && newValues.orientToDirection !== $.get(activeOrientToDirection)) {
|
|
277
|
+
$.set(activeOrientToDirection, newValues.orientToDirection, true);
|
|
278
|
+
}
|
|
279
|
+
if (newValues.shadow !== void 0 && newValues.shadow !== $.get(activeShadow)) {
|
|
280
|
+
$.set(activeShadow, newValues.shadow, true);
|
|
281
|
+
}
|
|
282
|
+
if ("geometryType" in newValues || "geometryArgs" in newValues) {
|
|
283
|
+
const geoType = (_g = newValues.geometryType) != null ? _g : prevGeometryType;
|
|
284
|
+
const geoArgs = (_h = newValues.geometryArgs) != null ? _h : prevGeometryArgs;
|
|
285
|
+
const geoTypeChanged = "geometryType" in newValues && geoType !== prevGeometryType;
|
|
286
|
+
const geoArgsChanged = "geometryArgs" in newValues && JSON.stringify(geoArgs) !== JSON.stringify(prevGeometryArgs);
|
|
287
|
+
if (geoTypeChanged || geoArgsChanged) {
|
|
288
|
+
prevGeometryType = geoType;
|
|
289
|
+
prevGeometryArgs = geoArgs;
|
|
290
|
+
import("debug-vfx").then((mod) => {
|
|
291
|
+
const { createGeometry, GeometryType } = mod;
|
|
292
|
+
if (geoType === GeometryType.NONE || !geoType) {
|
|
293
|
+
if ($.get(activeGeometry) !== null && !geometry()) {
|
|
294
|
+
$.get(activeGeometry).dispose();
|
|
295
|
+
}
|
|
296
|
+
$.set(activeGeometry, null);
|
|
297
|
+
} else {
|
|
298
|
+
const newGeometry = createGeometry(geoType, geoArgs);
|
|
299
|
+
if (newGeometry) {
|
|
300
|
+
if ($.get(activeGeometry) !== null && $.get(activeGeometry) !== geometry()) {
|
|
301
|
+
$.get(activeGeometry).dispose();
|
|
302
|
+
}
|
|
303
|
+
$.set(activeGeometry, newGeometry, true);
|
|
304
|
+
}
|
|
305
|
+
}
|
|
306
|
+
});
|
|
307
|
+
}
|
|
308
|
+
}
|
|
309
|
+
}
|
|
310
|
+
function initDebugPanel() {
|
|
311
|
+
import("debug-vfx").then((mod) => {
|
|
312
|
+
const { renderDebugPanel, detectGeometryTypeAndArgs } = mod;
|
|
313
|
+
if (!debugValues) {
|
|
314
|
+
const initialValues = __spreadValues({
|
|
315
|
+
name: name(),
|
|
316
|
+
maxParticles: maxParticles(),
|
|
317
|
+
size: size(),
|
|
318
|
+
colorStart: colorStart(),
|
|
319
|
+
colorEnd: colorEnd(),
|
|
320
|
+
fadeSize: fadeSize(),
|
|
321
|
+
fadeSizeCurve: fadeSizeCurve() || null,
|
|
322
|
+
fadeOpacity: fadeOpacity(),
|
|
323
|
+
fadeOpacityCurve: fadeOpacityCurve() || null,
|
|
324
|
+
velocityCurve: velocityCurve() || null,
|
|
325
|
+
gravity: gravity(),
|
|
326
|
+
lifetime: lifetime(),
|
|
327
|
+
direction: direction(),
|
|
328
|
+
startPosition: startPosition(),
|
|
329
|
+
startPositionAsDirection: startPositionAsDirection(),
|
|
330
|
+
speed: speed(),
|
|
331
|
+
friction: friction(),
|
|
332
|
+
appearance: appearance(),
|
|
333
|
+
rotation: rotation(),
|
|
334
|
+
rotationSpeed: rotationSpeed(),
|
|
335
|
+
rotationSpeedCurve: rotationSpeedCurve() || null,
|
|
336
|
+
orientToDirection: orientToDirection(),
|
|
337
|
+
orientAxis: orientAxis(),
|
|
338
|
+
stretchBySpeed: stretchBySpeed() || null,
|
|
339
|
+
lighting: lighting(),
|
|
340
|
+
shadow: shadow(),
|
|
341
|
+
blending: blending(),
|
|
342
|
+
intensity: intensity(),
|
|
343
|
+
position: position(),
|
|
344
|
+
autoStart: autoStart(),
|
|
345
|
+
delay: delay(),
|
|
346
|
+
emitCount: emitCount(),
|
|
347
|
+
emitterShape: emitterShape(),
|
|
348
|
+
emitterRadius: emitterRadius(),
|
|
349
|
+
emitterAngle: emitterAngle(),
|
|
350
|
+
emitterHeight: emitterHeight(),
|
|
351
|
+
emitterSurfaceOnly: emitterSurfaceOnly(),
|
|
352
|
+
emitterDirection: emitterDirection(),
|
|
353
|
+
turbulence: turbulence(),
|
|
354
|
+
attractToCenter: attractToCenter(),
|
|
355
|
+
softParticles: softParticles(),
|
|
356
|
+
softDistance: softDistance(),
|
|
357
|
+
collision: collision()
|
|
358
|
+
}, detectGeometryTypeAndArgs(geometry()));
|
|
359
|
+
debugValues = initialValues;
|
|
360
|
+
prevGeometryType = initialValues.geometryType;
|
|
361
|
+
prevGeometryArgs = initialValues.geometryArgs;
|
|
362
|
+
}
|
|
363
|
+
renderDebugPanel(debugValues, handleDebugUpdate, "threlte");
|
|
364
|
+
});
|
|
365
|
+
}
|
|
366
|
+
$.user_effect(() => {
|
|
367
|
+
const _deps = [
|
|
368
|
+
maxParticles(),
|
|
369
|
+
lighting(),
|
|
370
|
+
appearance(),
|
|
371
|
+
orientToDirection(),
|
|
372
|
+
geometry(),
|
|
373
|
+
shadow(),
|
|
374
|
+
fadeSizeCurve(),
|
|
375
|
+
fadeOpacityCurve(),
|
|
376
|
+
velocityCurve(),
|
|
377
|
+
rotationSpeedCurve(),
|
|
378
|
+
colorStart().length,
|
|
379
|
+
colorEnd(),
|
|
380
|
+
rotation(),
|
|
381
|
+
rotationSpeed(),
|
|
382
|
+
turbulence(),
|
|
383
|
+
attractors(),
|
|
384
|
+
collision()
|
|
385
|
+
];
|
|
386
|
+
if (debug()) return;
|
|
387
|
+
untrack(() => {
|
|
388
|
+
var _a2, _b2, _c2, _d2;
|
|
389
|
+
$.set(activeMaxParticles, maxParticles());
|
|
390
|
+
$.set(activeLighting, lighting(), true);
|
|
391
|
+
$.set(activeAppearance, appearance(), true);
|
|
392
|
+
$.set(activeOrientToDirection, orientToDirection());
|
|
393
|
+
$.set(activeGeometry, geometry());
|
|
394
|
+
$.set(activeShadow, shadow());
|
|
395
|
+
$.set(activeFadeSizeCurve, fadeSizeCurve());
|
|
396
|
+
$.set(activeFadeOpacityCurve, fadeOpacityCurve());
|
|
397
|
+
$.set(activeVelocityCurve, velocityCurve());
|
|
398
|
+
$.set(activeRotationSpeedCurve, rotationSpeedCurve());
|
|
399
|
+
$.set(activeNeedsPerParticleColor, colorStart().length > 1 || colorEnd() !== null, true);
|
|
400
|
+
$.set(activeNeedsRotation, isNonDefaultRotation(rotation()) || isNonDefaultRotation(rotationSpeed()), true);
|
|
401
|
+
$.set(activeTurbulence, turbulence() !== null && ((_b2 = (_a2 = turbulence()) == null ? void 0 : _a2.intensity) != null ? _b2 : 0) > 0, true);
|
|
402
|
+
$.set(activeAttractors, attractors() !== null && ((_d2 = (_c2 = attractors()) == null ? void 0 : _c2.length) != null ? _d2 : 0) > 0, true);
|
|
403
|
+
$.set(activeCollision, collision() !== null);
|
|
404
|
+
});
|
|
405
|
+
});
|
|
406
|
+
$.user_effect(() => {
|
|
407
|
+
const _deps = [
|
|
408
|
+
$.get(activeMaxParticles),
|
|
409
|
+
$.get(activeLighting),
|
|
410
|
+
$.get(activeAppearance),
|
|
411
|
+
$.get(activeOrientToDirection),
|
|
412
|
+
$.get(activeGeometry),
|
|
413
|
+
$.get(activeShadow),
|
|
414
|
+
$.get(activeNeedsPerParticleColor),
|
|
415
|
+
$.get(activeNeedsRotation),
|
|
416
|
+
$.get(activeTurbulence),
|
|
417
|
+
$.get(activeAttractors),
|
|
418
|
+
$.get(activeCollision),
|
|
419
|
+
$.get(activeFadeSizeCurve),
|
|
420
|
+
$.get(activeFadeOpacityCurve),
|
|
421
|
+
$.get(activeVelocityCurve),
|
|
422
|
+
$.get(activeRotationSpeedCurve)
|
|
423
|
+
];
|
|
424
|
+
if (!mounted) return;
|
|
425
|
+
untrack(() => {
|
|
426
|
+
if (!_isWebGPU) return;
|
|
427
|
+
initSystem();
|
|
428
|
+
});
|
|
429
|
+
});
|
|
430
|
+
$.user_effect(() => {
|
|
431
|
+
const _deps = [
|
|
432
|
+
position(),
|
|
433
|
+
size(),
|
|
434
|
+
fadeSize(),
|
|
435
|
+
fadeOpacity(),
|
|
436
|
+
gravity(),
|
|
437
|
+
friction(),
|
|
438
|
+
speed(),
|
|
439
|
+
lifetime(),
|
|
440
|
+
direction(),
|
|
441
|
+
rotation(),
|
|
442
|
+
rotationSpeed(),
|
|
443
|
+
intensity(),
|
|
444
|
+
colorStart(),
|
|
445
|
+
colorEnd(),
|
|
446
|
+
collision(),
|
|
447
|
+
emitterShape(),
|
|
448
|
+
emitterRadius(),
|
|
449
|
+
emitterAngle(),
|
|
450
|
+
emitterHeight(),
|
|
451
|
+
emitterSurfaceOnly(),
|
|
452
|
+
emitterDirection(),
|
|
453
|
+
turbulence(),
|
|
454
|
+
startPosition(),
|
|
455
|
+
attractors(),
|
|
456
|
+
attractToCenter(),
|
|
457
|
+
startPositionAsDirection(),
|
|
458
|
+
softParticles(),
|
|
459
|
+
softDistance(),
|
|
460
|
+
orientAxis(),
|
|
461
|
+
stretchBySpeed(),
|
|
462
|
+
delay(),
|
|
463
|
+
emitCount()
|
|
464
|
+
];
|
|
465
|
+
if (debug()) return;
|
|
466
|
+
untrack(() => {
|
|
467
|
+
var _a2, _b2;
|
|
468
|
+
if (!_system) return;
|
|
469
|
+
_system.setPosition(position());
|
|
470
|
+
_system.setDelay(delay());
|
|
471
|
+
_system.setEmitCount(emitCount());
|
|
472
|
+
_system.setTurbulenceSpeed((_b2 = (_a2 = turbulence()) == null ? void 0 : _a2.speed) != null ? _b2 : 1);
|
|
473
|
+
const normalized = normalizeProps({
|
|
474
|
+
size: size(),
|
|
475
|
+
speed: speed(),
|
|
476
|
+
fadeSize: fadeSize(),
|
|
477
|
+
fadeOpacity: fadeOpacity(),
|
|
478
|
+
lifetime: lifetime(),
|
|
479
|
+
gravity: gravity(),
|
|
480
|
+
direction: direction(),
|
|
481
|
+
startPosition: startPosition(),
|
|
482
|
+
rotation: rotation(),
|
|
483
|
+
rotationSpeed: rotationSpeed(),
|
|
484
|
+
friction: friction(),
|
|
485
|
+
intensity: intensity(),
|
|
486
|
+
colorStart: colorStart(),
|
|
487
|
+
colorEnd: colorEnd(),
|
|
488
|
+
emitterShape: emitterShape(),
|
|
489
|
+
emitterRadius: emitterRadius(),
|
|
490
|
+
emitterAngle: emitterAngle(),
|
|
491
|
+
emitterHeight: emitterHeight(),
|
|
492
|
+
emitterSurfaceOnly: emitterSurfaceOnly(),
|
|
493
|
+
emitterDirection: emitterDirection(),
|
|
494
|
+
turbulence: turbulence(),
|
|
495
|
+
attractors: attractors(),
|
|
496
|
+
attractToCenter: attractToCenter(),
|
|
497
|
+
startPositionAsDirection: startPositionAsDirection(),
|
|
498
|
+
softParticles: softParticles(),
|
|
499
|
+
softDistance: softDistance(),
|
|
500
|
+
collision: collision(),
|
|
501
|
+
orientAxis: orientAxis(),
|
|
502
|
+
stretchBySpeed: stretchBySpeed()
|
|
503
|
+
});
|
|
504
|
+
updateUniforms(_system.uniforms, normalized);
|
|
505
|
+
});
|
|
506
|
+
});
|
|
507
|
+
useTask((delta) => {
|
|
508
|
+
if (!_system || !_system.initialized) return;
|
|
509
|
+
_system.update(delta);
|
|
510
|
+
if (_emitting) {
|
|
511
|
+
_system.autoEmit(delta);
|
|
512
|
+
}
|
|
513
|
+
});
|
|
514
|
+
onMount(() => {
|
|
515
|
+
mounted = true;
|
|
516
|
+
initSystem();
|
|
517
|
+
});
|
|
518
|
+
onDestroy(() => {
|
|
519
|
+
mounted = false;
|
|
520
|
+
if (debug()) {
|
|
521
|
+
import("debug-vfx").then((mod) => {
|
|
522
|
+
mod.destroyDebugPanel();
|
|
523
|
+
});
|
|
524
|
+
}
|
|
525
|
+
destroySystem();
|
|
526
|
+
});
|
|
527
|
+
function spawn(x = 0, y = 0, z = 0, count = 20, overrides = null) {
|
|
528
|
+
if (!_system) return;
|
|
529
|
+
const [px, py, pz] = _system.position;
|
|
530
|
+
_system.spawn(px + x, py + y, pz + z, count, overrides);
|
|
531
|
+
}
|
|
532
|
+
function start() {
|
|
533
|
+
if (!_system) return;
|
|
534
|
+
_system.start();
|
|
535
|
+
_emitting = true;
|
|
536
|
+
}
|
|
537
|
+
function stop() {
|
|
538
|
+
if (!_system) return;
|
|
539
|
+
_system.stop();
|
|
540
|
+
_emitting = false;
|
|
541
|
+
}
|
|
542
|
+
function clear() {
|
|
543
|
+
_system == null ? void 0 : _system.clear();
|
|
544
|
+
}
|
|
545
|
+
var fragment = $.comment();
|
|
546
|
+
var node = $.first_child(fragment);
|
|
547
|
+
{
|
|
548
|
+
var consequent = ($$anchor2) => {
|
|
549
|
+
T($$anchor2, {
|
|
550
|
+
get is() {
|
|
551
|
+
return $.get(renderObjectForTemplate);
|
|
552
|
+
}
|
|
553
|
+
});
|
|
554
|
+
};
|
|
555
|
+
$.if(node, ($$render) => {
|
|
556
|
+
if ($.get(isWebGPUForTemplate) && $.get(renderObjectForTemplate)) $$render(consequent);
|
|
557
|
+
});
|
|
558
|
+
}
|
|
559
|
+
$.append($$anchor, fragment);
|
|
560
|
+
return $.pop({ spawn, start, stop, clear });
|
|
561
|
+
}
|
|
562
|
+
|
|
563
|
+
// src/VFXEmitter.svelte
|
|
564
|
+
import "svelte/internal/disclose-version";
|
|
565
|
+
import * as $2 from "svelte/internal/client";
|
|
566
|
+
import { T as T2, useThrelte as useThrelte2, useTask as useTask2 } from "@threlte/core";
|
|
567
|
+
import { onMount as onMount2 } from "svelte";
|
|
568
|
+
import { Vector3, Quaternion, Group } from "three/webgpu";
|
|
569
|
+
import {
|
|
570
|
+
EmitterController,
|
|
571
|
+
isWebGPUBackend as isWebGPUBackend2,
|
|
572
|
+
coreStore as coreStore2
|
|
573
|
+
} from "core-vfx";
|
|
574
|
+
function VFXEmitter($$anchor, $$props) {
|
|
575
|
+
$2.push($$props, true);
|
|
576
|
+
const worldPos = new Vector3();
|
|
577
|
+
const worldQuat = new Quaternion();
|
|
578
|
+
let name = $2.prop($$props, "name", 19, () => void 0), particlesRef = $2.prop($$props, "particlesRef", 19, () => void 0), position = $2.prop($$props, "position", 19, () => [0, 0, 0]), emitCount = $2.prop($$props, "emitCount", 3, 10), delay = $2.prop($$props, "delay", 3, 0), autoStart = $2.prop($$props, "autoStart", 3, true), loop = $2.prop($$props, "loop", 3, true), localDirection = $2.prop($$props, "localDirection", 3, false), direction = $2.prop($$props, "direction", 19, () => void 0), overrides = $2.prop($$props, "overrides", 3, null), onEmit = $2.prop($$props, "onEmit", 19, () => void 0);
|
|
579
|
+
const { renderer } = useThrelte2();
|
|
580
|
+
let groupRef = $2.state(null);
|
|
581
|
+
let isWebGPU = $2.state(false);
|
|
582
|
+
const controller = new EmitterController({
|
|
583
|
+
emitCount: emitCount(),
|
|
584
|
+
delay: delay(),
|
|
585
|
+
autoStart: autoStart(),
|
|
586
|
+
loop: loop(),
|
|
587
|
+
localDirection: localDirection(),
|
|
588
|
+
direction: direction(),
|
|
589
|
+
overrides: overrides(),
|
|
590
|
+
onEmit: onEmit()
|
|
591
|
+
});
|
|
592
|
+
function getParticleSystem() {
|
|
593
|
+
if (particlesRef()) {
|
|
594
|
+
return particlesRef().value || particlesRef();
|
|
595
|
+
}
|
|
596
|
+
return name() ? coreStore2.getState().getParticles(name()) : void 0;
|
|
597
|
+
}
|
|
598
|
+
$2.user_effect(() => {
|
|
599
|
+
const _deps = [
|
|
600
|
+
emitCount(),
|
|
601
|
+
delay(),
|
|
602
|
+
autoStart(),
|
|
603
|
+
loop(),
|
|
604
|
+
localDirection(),
|
|
605
|
+
direction(),
|
|
606
|
+
overrides(),
|
|
607
|
+
onEmit()
|
|
608
|
+
];
|
|
609
|
+
controller.updateOptions({
|
|
610
|
+
emitCount: emitCount(),
|
|
611
|
+
delay: delay(),
|
|
612
|
+
autoStart: autoStart(),
|
|
613
|
+
loop: loop(),
|
|
614
|
+
localDirection: localDirection(),
|
|
615
|
+
direction: direction(),
|
|
616
|
+
overrides: overrides(),
|
|
617
|
+
onEmit: onEmit()
|
|
618
|
+
});
|
|
619
|
+
});
|
|
620
|
+
function checkWebGPU() {
|
|
621
|
+
if (renderer && isWebGPUBackend2(renderer)) {
|
|
622
|
+
$2.set(isWebGPU, true);
|
|
623
|
+
const system = getParticleSystem();
|
|
624
|
+
if (system) controller.setSystem(system);
|
|
625
|
+
}
|
|
626
|
+
}
|
|
627
|
+
onMount2(() => {
|
|
628
|
+
checkWebGPU();
|
|
629
|
+
});
|
|
630
|
+
useTask2((delta) => {
|
|
631
|
+
if (!$2.get(isWebGPU)) return;
|
|
632
|
+
if (!controller.getSystem()) {
|
|
633
|
+
const system = getParticleSystem();
|
|
634
|
+
if (system) controller.setSystem(system);
|
|
635
|
+
}
|
|
636
|
+
if (!$2.get(groupRef)) return;
|
|
637
|
+
$2.get(groupRef).getWorldPosition(worldPos);
|
|
638
|
+
$2.get(groupRef).getWorldQuaternion(worldQuat);
|
|
639
|
+
controller.update(delta, worldPos, worldQuat);
|
|
640
|
+
});
|
|
641
|
+
function emit(emitOverrides = null) {
|
|
642
|
+
if (!$2.get(groupRef)) return false;
|
|
643
|
+
if (!controller.getSystem()) {
|
|
644
|
+
const system = getParticleSystem();
|
|
645
|
+
if (system) controller.setSystem(system);
|
|
646
|
+
}
|
|
647
|
+
if (!controller.getSystem()) {
|
|
648
|
+
if (name()) {
|
|
649
|
+
console.warn(`VFXEmitter: No particle system found for name "${name()}"`);
|
|
650
|
+
}
|
|
651
|
+
return false;
|
|
652
|
+
}
|
|
653
|
+
$2.get(groupRef).getWorldPosition(worldPos);
|
|
654
|
+
$2.get(groupRef).getWorldQuaternion(worldQuat);
|
|
655
|
+
return controller.emitAtPosition(worldPos, worldQuat, emitOverrides);
|
|
656
|
+
}
|
|
657
|
+
function burst(count) {
|
|
658
|
+
if (!$2.get(groupRef)) return false;
|
|
659
|
+
if (!controller.getSystem()) {
|
|
660
|
+
const system = getParticleSystem();
|
|
661
|
+
if (system) controller.setSystem(system);
|
|
662
|
+
}
|
|
663
|
+
if (!controller.getSystem()) return false;
|
|
664
|
+
$2.get(groupRef).getWorldPosition(worldPos);
|
|
665
|
+
$2.get(groupRef).getWorldQuaternion(worldQuat);
|
|
666
|
+
return controller.burst(count, worldPos, worldQuat);
|
|
667
|
+
}
|
|
668
|
+
function start() {
|
|
669
|
+
controller.start();
|
|
670
|
+
}
|
|
671
|
+
function stop() {
|
|
672
|
+
controller.stop();
|
|
673
|
+
}
|
|
674
|
+
var fragment = $2.comment();
|
|
675
|
+
var node = $2.first_child(fragment);
|
|
676
|
+
$2.component(node, () => T2.Group, ($$anchor2, $$component) => {
|
|
677
|
+
$$component($$anchor2, {
|
|
678
|
+
get position() {
|
|
679
|
+
return position();
|
|
680
|
+
},
|
|
681
|
+
get ref() {
|
|
682
|
+
return $2.get(groupRef);
|
|
683
|
+
},
|
|
684
|
+
set ref($$value) {
|
|
685
|
+
$2.set(groupRef, $$value, true);
|
|
686
|
+
},
|
|
687
|
+
children: ($$anchor3, $$slotProps) => {
|
|
688
|
+
var fragment_1 = $2.comment();
|
|
689
|
+
var node_1 = $2.first_child(fragment_1);
|
|
690
|
+
{
|
|
691
|
+
var consequent = ($$anchor4) => {
|
|
692
|
+
var fragment_2 = $2.comment();
|
|
693
|
+
var node_2 = $2.first_child(fragment_2);
|
|
694
|
+
$2.snippet(node_2, () => $$props.children);
|
|
695
|
+
$2.append($$anchor4, fragment_2);
|
|
696
|
+
};
|
|
697
|
+
$2.if(node_1, ($$render) => {
|
|
698
|
+
if ($$props.children) $$render(consequent);
|
|
699
|
+
});
|
|
700
|
+
}
|
|
701
|
+
$2.append($$anchor3, fragment_1);
|
|
702
|
+
},
|
|
703
|
+
$$slots: { default: true }
|
|
704
|
+
});
|
|
705
|
+
});
|
|
706
|
+
$2.append($$anchor, fragment);
|
|
707
|
+
return $2.pop({ emit, burst, start, stop });
|
|
708
|
+
}
|
|
709
|
+
|
|
1
710
|
// src/useVFXEmitter.ts
|
|
2
|
-
import { useThrelte } from "@threlte/core";
|
|
3
|
-
import { coreStore, isWebGPUBackend } from "core-vfx";
|
|
711
|
+
import { useThrelte as useThrelte3 } from "@threlte/core";
|
|
712
|
+
import { coreStore as coreStore3, isWebGPUBackend as isWebGPUBackend3 } from "core-vfx";
|
|
4
713
|
function useVFXEmitter(name) {
|
|
5
|
-
const { renderer } =
|
|
714
|
+
const { renderer } = useThrelte3();
|
|
6
715
|
const checkWebGPU = () => {
|
|
7
|
-
return renderer &&
|
|
716
|
+
return renderer && isWebGPUBackend3(renderer);
|
|
8
717
|
};
|
|
9
|
-
const getParticles = () =>
|
|
718
|
+
const getParticles = () => coreStore3.getState().getParticles(name);
|
|
10
719
|
const emit = (position = [0, 0, 0], count = 20, overrides = null) => {
|
|
11
720
|
if (!checkWebGPU()) return false;
|
|
12
721
|
const [x, y, z] = position;
|
|
13
|
-
return
|
|
722
|
+
return coreStore3.getState().emit(name, { x, y, z, count, overrides });
|
|
14
723
|
};
|
|
15
724
|
const burst = (position = [0, 0, 0], count = 50, overrides = null) => {
|
|
16
725
|
if (!checkWebGPU()) return false;
|
|
17
726
|
const [x, y, z] = position;
|
|
18
|
-
return
|
|
727
|
+
return coreStore3.getState().emit(name, { x, y, z, count, overrides });
|
|
19
728
|
};
|
|
20
729
|
const start = () => {
|
|
21
730
|
if (!checkWebGPU()) return false;
|
|
22
|
-
return
|
|
731
|
+
return coreStore3.getState().start(name);
|
|
23
732
|
};
|
|
24
733
|
const stop = () => {
|
|
25
734
|
if (!checkWebGPU()) return false;
|
|
26
|
-
return
|
|
735
|
+
return coreStore3.getState().stop(name);
|
|
27
736
|
};
|
|
28
737
|
const clear = () => {
|
|
29
738
|
if (!checkWebGPU()) return false;
|
|
30
|
-
return
|
|
739
|
+
return coreStore3.getState().clear(name);
|
|
31
740
|
};
|
|
32
741
|
const isEmitting = () => {
|
|
33
742
|
var _a;
|
|
@@ -54,60 +763,62 @@ function useVFXEmitter(name) {
|
|
|
54
763
|
}
|
|
55
764
|
|
|
56
765
|
// src/svelte-store.ts
|
|
57
|
-
import { coreStore as
|
|
766
|
+
import { coreStore as coreStore4 } from "core-vfx";
|
|
58
767
|
function useVFXStore(selector) {
|
|
59
768
|
const pick = selector != null ? selector : ((s) => s);
|
|
60
769
|
return {
|
|
61
770
|
subscribe(run) {
|
|
62
|
-
run(pick(
|
|
63
|
-
const unsubscribe =
|
|
64
|
-
run(pick(
|
|
771
|
+
run(pick(coreStore4.getState()));
|
|
772
|
+
const unsubscribe = coreStore4.subscribe((state3) => {
|
|
773
|
+
run(pick(state3));
|
|
65
774
|
});
|
|
66
775
|
return unsubscribe;
|
|
67
776
|
}
|
|
68
777
|
};
|
|
69
778
|
}
|
|
70
|
-
useVFXStore.getState =
|
|
71
|
-
useVFXStore.setState =
|
|
72
|
-
useVFXStore.subscribe =
|
|
779
|
+
useVFXStore.getState = coreStore4.getState;
|
|
780
|
+
useVFXStore.setState = coreStore4.setState;
|
|
781
|
+
useVFXStore.subscribe = coreStore4.subscribe;
|
|
73
782
|
|
|
74
783
|
// src/index.ts
|
|
75
784
|
import {
|
|
76
|
-
Appearance,
|
|
77
|
-
Blending,
|
|
78
|
-
EmitterShape,
|
|
785
|
+
Appearance as Appearance2,
|
|
786
|
+
Blending as Blending2,
|
|
787
|
+
EmitterShape as EmitterShape2,
|
|
79
788
|
AttractorType,
|
|
80
789
|
Easing,
|
|
81
|
-
Lighting,
|
|
790
|
+
Lighting as Lighting2,
|
|
82
791
|
bakeCurveToArray,
|
|
83
792
|
createCombinedCurveTexture,
|
|
84
793
|
buildCurveTextureBin,
|
|
85
794
|
CurveChannel
|
|
86
795
|
} from "core-vfx";
|
|
87
796
|
import {
|
|
88
|
-
VFXParticleSystem,
|
|
89
|
-
EmitterController,
|
|
90
|
-
isWebGPUBackend as
|
|
91
|
-
isNonDefaultRotation,
|
|
92
|
-
normalizeProps,
|
|
797
|
+
VFXParticleSystem as VFXParticleSystem2,
|
|
798
|
+
EmitterController as EmitterController2,
|
|
799
|
+
isWebGPUBackend as isWebGPUBackend4,
|
|
800
|
+
isNonDefaultRotation as isNonDefaultRotation2,
|
|
801
|
+
normalizeProps as normalizeProps2,
|
|
93
802
|
resolveCurveTexture
|
|
94
803
|
} from "core-vfx";
|
|
95
804
|
export {
|
|
96
|
-
Appearance,
|
|
805
|
+
Appearance2 as Appearance,
|
|
97
806
|
AttractorType,
|
|
98
|
-
Blending,
|
|
807
|
+
Blending2 as Blending,
|
|
99
808
|
CurveChannel,
|
|
100
809
|
Easing,
|
|
101
|
-
EmitterController,
|
|
102
|
-
EmitterShape,
|
|
103
|
-
Lighting,
|
|
104
|
-
|
|
810
|
+
EmitterController2 as EmitterController,
|
|
811
|
+
EmitterShape2 as EmitterShape,
|
|
812
|
+
Lighting2 as Lighting,
|
|
813
|
+
VFXEmitter,
|
|
814
|
+
VFXParticleSystem2 as VFXParticleSystem,
|
|
815
|
+
VFXParticles,
|
|
105
816
|
bakeCurveToArray,
|
|
106
817
|
buildCurveTextureBin,
|
|
107
818
|
createCombinedCurveTexture,
|
|
108
|
-
isNonDefaultRotation,
|
|
109
|
-
|
|
110
|
-
normalizeProps,
|
|
819
|
+
isNonDefaultRotation2 as isNonDefaultRotation,
|
|
820
|
+
isWebGPUBackend4 as isWebGPUBackend,
|
|
821
|
+
normalizeProps2 as normalizeProps,
|
|
111
822
|
resolveCurveTexture,
|
|
112
823
|
useVFXEmitter,
|
|
113
824
|
useVFXStore
|