r3f-vfx 0.1.2 → 0.1.4
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 +18 -8
- package/dist/index.js +147 -214
- package/package.json +2 -2
package/dist/index.d.ts
CHANGED
|
@@ -2,7 +2,7 @@ import * as react from 'react';
|
|
|
2
2
|
import { RefObject, ReactNode } from 'react';
|
|
3
3
|
import * as THREE from 'three/webgpu';
|
|
4
4
|
import { CurveData, Rotation3DInput, Appearance, Lighting, ParticleData, EmitterShape, CoreState } from 'core-vfx';
|
|
5
|
-
export { Appearance, AttractorConfig, AttractorType, BaseParticleProps, Blending, CollisionConfig, CurveData, CurvePoint, Easing, EmitterShape, FlipbookConfig, FrictionConfig, Lighting, ParticleData, Rotation3DInput, StretchConfig, TurbulenceConfig, bakeCurveToArray, createCombinedCurveTexture } from 'core-vfx';
|
|
5
|
+
export { Appearance, AttractorConfig, AttractorType, BaseParticleProps, Blending, CollisionConfig, CurveChannel, CurveData, CurvePoint, CurveTextureResult, Easing, EmitterShape, FlipbookConfig, FrictionConfig, Lighting, ParticleData, Rotation3DInput, StretchConfig, TurbulenceConfig, bakeCurveToArray, buildCurveTextureBin, createCombinedCurveTexture } from 'core-vfx';
|
|
6
6
|
|
|
7
7
|
type VFXParticlesProps = {
|
|
8
8
|
/** Optional name for registering with useVFXStore (enables VFXEmitter linking) */
|
|
@@ -264,14 +264,24 @@ declare const useVFXStore: typeof useVFXStoreImpl & {
|
|
|
264
264
|
getInitialState: () => CoreState;
|
|
265
265
|
};
|
|
266
266
|
|
|
267
|
+
type CurveTextureHookResult = {
|
|
268
|
+
texture: THREE.DataTexture;
|
|
269
|
+
/** Per-channel enabled state, combining curve props and loaded .bin channels */
|
|
270
|
+
sizeEnabled: boolean;
|
|
271
|
+
opacityEnabled: boolean;
|
|
272
|
+
velocityEnabled: boolean;
|
|
273
|
+
rotationSpeedEnabled: boolean;
|
|
274
|
+
};
|
|
267
275
|
/**
|
|
268
|
-
* Hook for curve texture loading/baking
|
|
269
|
-
*
|
|
276
|
+
* Hook for curve texture loading/baking.
|
|
277
|
+
*
|
|
278
|
+
* If curveTexturePath is provided, loads pre-baked texture from file.
|
|
279
|
+
* The .bin file contains a header with a bitmask of which channels are active.
|
|
280
|
+
* Only those channels override the curve props; the rest use curve props or defaults.
|
|
270
281
|
*
|
|
271
|
-
* If
|
|
272
|
-
* If curves
|
|
273
|
-
* If no curves AND no path, returns default texture (no baking needed)
|
|
282
|
+
* If curves are defined (no path), bakes them synchronously on the main thread.
|
|
283
|
+
* If no curves AND no path, returns default texture (no baking needed).
|
|
274
284
|
*/
|
|
275
|
-
declare const useCurveTextureAsync: (sizeCurve: CurveData | null, opacityCurve: CurveData | null, velocityCurve: CurveData | null, rotationSpeedCurve: CurveData | null, curveTexturePath?: string | null) =>
|
|
285
|
+
declare const useCurveTextureAsync: (sizeCurve: CurveData | null, opacityCurve: CurveData | null, velocityCurve: CurveData | null, rotationSpeedCurve: CurveData | null, curveTexturePath?: string | null) => CurveTextureHookResult;
|
|
276
286
|
|
|
277
|
-
export { VFXEmitter, VFXParticles, useCurveTextureAsync, useVFXEmitter, useVFXStore };
|
|
287
|
+
export { type CurveTextureHookResult, VFXEmitter, VFXParticles, useCurveTextureAsync, useVFXEmitter, useVFXStore };
|
package/dist/index.js
CHANGED
|
@@ -58,38 +58,29 @@ var init_react_store = __esm({
|
|
|
58
58
|
});
|
|
59
59
|
|
|
60
60
|
// src/useCurveTextureAsync.ts
|
|
61
|
-
import { useRef, useEffect, useMemo } from "react";
|
|
61
|
+
import { useRef, useEffect, useMemo, useState } from "react";
|
|
62
62
|
import {
|
|
63
63
|
createDefaultCurveTexture,
|
|
64
64
|
createCombinedCurveTexture,
|
|
65
|
-
loadCurveTextureFromPath
|
|
65
|
+
loadCurveTextureFromPath,
|
|
66
|
+
CurveChannel
|
|
66
67
|
} from "core-vfx";
|
|
67
68
|
var useCurveTextureAsync;
|
|
68
69
|
var init_useCurveTextureAsync = __esm({
|
|
69
70
|
"src/useCurveTextureAsync.ts"() {
|
|
70
71
|
"use strict";
|
|
71
72
|
useCurveTextureAsync = (sizeCurve, opacityCurve, velocityCurve, rotationSpeedCurve, curveTexturePath = null) => {
|
|
72
|
-
const textureRef = useRef(null);
|
|
73
|
-
if (!textureRef.current) {
|
|
74
|
-
textureRef.current = createDefaultCurveTexture();
|
|
75
|
-
}
|
|
76
73
|
const hasAnyCurve = sizeCurve || opacityCurve || velocityCurve || rotationSpeedCurve;
|
|
77
|
-
useMemo(() => {
|
|
78
|
-
if (!curveTexturePath && hasAnyCurve
|
|
79
|
-
|
|
74
|
+
const texture = useMemo(() => {
|
|
75
|
+
if (!curveTexturePath && hasAnyCurve) {
|
|
76
|
+
return createCombinedCurveTexture(
|
|
80
77
|
sizeCurve,
|
|
81
78
|
opacityCurve,
|
|
82
79
|
velocityCurve,
|
|
83
80
|
rotationSpeedCurve
|
|
84
81
|
);
|
|
85
|
-
const srcData = bakedTexture.image.data;
|
|
86
|
-
const dstData = textureRef.current.image.data;
|
|
87
|
-
if (srcData && dstData) {
|
|
88
|
-
dstData.set(srcData);
|
|
89
|
-
textureRef.current.needsUpdate = true;
|
|
90
|
-
}
|
|
91
|
-
bakedTexture.dispose();
|
|
92
82
|
}
|
|
83
|
+
return createDefaultCurveTexture();
|
|
93
84
|
}, [
|
|
94
85
|
sizeCurve,
|
|
95
86
|
opacityCurve,
|
|
@@ -98,32 +89,49 @@ var init_useCurveTextureAsync = __esm({
|
|
|
98
89
|
curveTexturePath,
|
|
99
90
|
hasAnyCurve
|
|
100
91
|
]);
|
|
92
|
+
const [loadedTexture, setLoadedTexture] = useState(
|
|
93
|
+
null
|
|
94
|
+
);
|
|
95
|
+
const [loadedChannels, setLoadedChannels] = useState(0);
|
|
101
96
|
useEffect(() => {
|
|
102
|
-
if (curveTexturePath
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
`Failed to load curve texture: ${curveTexturePath}, falling back to baking`,
|
|
107
|
-
err
|
|
108
|
-
);
|
|
109
|
-
if (hasAnyCurve && textureRef.current) {
|
|
110
|
-
const bakedTexture = createCombinedCurveTexture(
|
|
111
|
-
sizeCurve,
|
|
112
|
-
opacityCurve,
|
|
113
|
-
velocityCurve,
|
|
114
|
-
rotationSpeedCurve
|
|
115
|
-
);
|
|
116
|
-
const srcData = bakedTexture.image.data;
|
|
117
|
-
const dstData = textureRef.current.image.data;
|
|
118
|
-
if (srcData && dstData) {
|
|
119
|
-
dstData.set(srcData);
|
|
120
|
-
textureRef.current.needsUpdate = true;
|
|
121
|
-
}
|
|
122
|
-
bakedTexture.dispose();
|
|
123
|
-
}
|
|
124
|
-
}
|
|
125
|
-
);
|
|
97
|
+
if (!curveTexturePath) {
|
|
98
|
+
setLoadedTexture(null);
|
|
99
|
+
setLoadedChannels(0);
|
|
100
|
+
return;
|
|
126
101
|
}
|
|
102
|
+
let cancelled = false;
|
|
103
|
+
loadCurveTextureFromPath(curveTexturePath).then((result) => {
|
|
104
|
+
if (!cancelled) {
|
|
105
|
+
setLoadedTexture(result.texture);
|
|
106
|
+
setLoadedChannels(result.activeChannels);
|
|
107
|
+
} else {
|
|
108
|
+
result.texture.dispose();
|
|
109
|
+
}
|
|
110
|
+
}).catch((err) => {
|
|
111
|
+
console.warn(
|
|
112
|
+
`Failed to load curve texture: ${curveTexturePath}, falling back to baking`,
|
|
113
|
+
err
|
|
114
|
+
);
|
|
115
|
+
if (!cancelled && hasAnyCurve) {
|
|
116
|
+
setLoadedTexture(
|
|
117
|
+
createCombinedCurveTexture(
|
|
118
|
+
sizeCurve,
|
|
119
|
+
opacityCurve,
|
|
120
|
+
velocityCurve,
|
|
121
|
+
rotationSpeedCurve
|
|
122
|
+
)
|
|
123
|
+
);
|
|
124
|
+
let mask = 0;
|
|
125
|
+
if (sizeCurve) mask |= CurveChannel.SIZE;
|
|
126
|
+
if (opacityCurve) mask |= CurveChannel.OPACITY;
|
|
127
|
+
if (velocityCurve) mask |= CurveChannel.VELOCITY;
|
|
128
|
+
if (rotationSpeedCurve) mask |= CurveChannel.ROTATION_SPEED;
|
|
129
|
+
setLoadedChannels(mask);
|
|
130
|
+
}
|
|
131
|
+
});
|
|
132
|
+
return () => {
|
|
133
|
+
cancelled = true;
|
|
134
|
+
};
|
|
127
135
|
}, [
|
|
128
136
|
curveTexturePath,
|
|
129
137
|
sizeCurve,
|
|
@@ -132,14 +140,33 @@ var init_useCurveTextureAsync = __esm({
|
|
|
132
140
|
rotationSpeedCurve,
|
|
133
141
|
hasAnyCurve
|
|
134
142
|
]);
|
|
143
|
+
const activeTexture = loadedTexture != null ? loadedTexture : texture;
|
|
144
|
+
const sizeEnabled = loadedTexture ? !!(loadedChannels & CurveChannel.SIZE) : !!sizeCurve;
|
|
145
|
+
const opacityEnabled = loadedTexture ? !!(loadedChannels & CurveChannel.OPACITY) : !!opacityCurve;
|
|
146
|
+
const velocityEnabled = loadedTexture ? !!(loadedChannels & CurveChannel.VELOCITY) : !!velocityCurve;
|
|
147
|
+
const rotationSpeedEnabled = loadedTexture ? !!(loadedChannels & CurveChannel.ROTATION_SPEED) : !!rotationSpeedCurve;
|
|
148
|
+
const prevTextureRef = useRef(null);
|
|
149
|
+
useEffect(() => {
|
|
150
|
+
const prev = prevTextureRef.current;
|
|
151
|
+
if (prev && prev !== activeTexture) {
|
|
152
|
+
prev.dispose();
|
|
153
|
+
}
|
|
154
|
+
prevTextureRef.current = activeTexture;
|
|
155
|
+
}, [activeTexture]);
|
|
135
156
|
useEffect(() => {
|
|
136
157
|
return () => {
|
|
137
158
|
var _a;
|
|
138
|
-
(_a =
|
|
139
|
-
|
|
159
|
+
(_a = prevTextureRef.current) == null ? void 0 : _a.dispose();
|
|
160
|
+
prevTextureRef.current = null;
|
|
140
161
|
};
|
|
141
162
|
}, []);
|
|
142
|
-
return
|
|
163
|
+
return {
|
|
164
|
+
texture: activeTexture,
|
|
165
|
+
sizeEnabled,
|
|
166
|
+
opacityEnabled,
|
|
167
|
+
velocityEnabled,
|
|
168
|
+
rotationSpeedEnabled
|
|
169
|
+
};
|
|
143
170
|
};
|
|
144
171
|
}
|
|
145
172
|
});
|
|
@@ -156,7 +183,8 @@ __export(VFXParticlesDebugPanel_exports, {
|
|
|
156
183
|
updateDebugPanel: () => updateDebugPanel
|
|
157
184
|
});
|
|
158
185
|
import { createRoot } from "react-dom/client";
|
|
159
|
-
import { useState, useCallback, useRef as useRef2, useEffect as useEffect2 } from "react";
|
|
186
|
+
import { useState as useState2, useCallback, useRef as useRef2, useEffect as useEffect2 } from "react";
|
|
187
|
+
import { buildCurveTextureBin } from "core-vfx";
|
|
160
188
|
import * as THREE from "three";
|
|
161
189
|
import { create } from "zustand";
|
|
162
190
|
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
@@ -1220,10 +1248,10 @@ ${" ".repeat(indent - 2)}}`;
|
|
|
1220
1248
|
onToggleEnabled,
|
|
1221
1249
|
hidden = false
|
|
1222
1250
|
}) => {
|
|
1223
|
-
const [isOpen, setIsOpen] =
|
|
1224
|
-
const [isHovered, setIsHovered] =
|
|
1251
|
+
const [isOpen, setIsOpen] = useState2(defaultOpen);
|
|
1252
|
+
const [isHovered, setIsHovered] = useState2(false);
|
|
1225
1253
|
const contentRef = useRef2(null);
|
|
1226
|
-
const [contentHeight, setContentHeight] =
|
|
1254
|
+
const [contentHeight, setContentHeight] = useState2(defaultOpen ? "auto" : 0);
|
|
1227
1255
|
useEffect2(() => {
|
|
1228
1256
|
if (contentRef.current) {
|
|
1229
1257
|
if (isOpen) {
|
|
@@ -1305,7 +1333,7 @@ ${" ".repeat(indent - 2)}}`;
|
|
|
1305
1333
|
const hasMoved = useRef2(false);
|
|
1306
1334
|
const startX = useRef2(0);
|
|
1307
1335
|
const startValue = useRef2(0);
|
|
1308
|
-
const [isDragging, setIsDragging] =
|
|
1336
|
+
const [isDragging, setIsDragging] = useState2(false);
|
|
1309
1337
|
const handleMouseDown = useCallback(
|
|
1310
1338
|
(e) => {
|
|
1311
1339
|
if (e.button !== 0) return;
|
|
@@ -1363,8 +1391,8 @@ ${" ".repeat(indent - 2)}}`;
|
|
|
1363
1391
|
placeholder
|
|
1364
1392
|
}) => {
|
|
1365
1393
|
const inputRef = useRef2(null);
|
|
1366
|
-
const [localValue, setLocalValue] =
|
|
1367
|
-
const [isFocused, setIsFocused] =
|
|
1394
|
+
const [localValue, setLocalValue] = useState2(String(value));
|
|
1395
|
+
const [isFocused, setIsFocused] = useState2(false);
|
|
1368
1396
|
const { handleMouseDown, hasMoved, isDragging } = useScrubber(
|
|
1369
1397
|
value,
|
|
1370
1398
|
onChange,
|
|
@@ -1491,7 +1519,7 @@ ${" ".repeat(indent - 2)}}`;
|
|
|
1491
1519
|
step = 0.01
|
|
1492
1520
|
}) => {
|
|
1493
1521
|
const [minVal, maxVal] = parseRange(value, [0, 0]);
|
|
1494
|
-
const [linked, setLinked] =
|
|
1522
|
+
const [linked, setLinked] = useState2(false);
|
|
1495
1523
|
const handleMinChange = useCallback(
|
|
1496
1524
|
(v) => {
|
|
1497
1525
|
if (linked) {
|
|
@@ -1742,8 +1770,8 @@ ${" ".repeat(indent - 2)}}`;
|
|
|
1742
1770
|
label
|
|
1743
1771
|
] }) });
|
|
1744
1772
|
CustomColorPicker = ({ color, onChange }) => {
|
|
1745
|
-
const [isOpen, setIsOpen] =
|
|
1746
|
-
const [hexInput, setHexInput] =
|
|
1773
|
+
const [isOpen, setIsOpen] = useState2(false);
|
|
1774
|
+
const [hexInput, setHexInput] = useState2(color);
|
|
1747
1775
|
const pickerRef = useRef2(null);
|
|
1748
1776
|
const gradientRef = useRef2(null);
|
|
1749
1777
|
const isDraggingGradient = useRef2(false);
|
|
@@ -1839,7 +1867,7 @@ ${" ".repeat(indent - 2)}}`;
|
|
|
1839
1867
|
const toHex = (x) => Math.round(x * 255).toString(16).padStart(2, "0");
|
|
1840
1868
|
return `#${toHex(r)}${toHex(g)}${toHex(b)}`;
|
|
1841
1869
|
};
|
|
1842
|
-
const [hsv, setHsv] =
|
|
1870
|
+
const [hsv, setHsv] = useState2(() => hexToHsv(color));
|
|
1843
1871
|
useEffect2(() => {
|
|
1844
1872
|
if (!isOpen) {
|
|
1845
1873
|
setHsv(hexToHsv(color));
|
|
@@ -2180,12 +2208,12 @@ ${" ".repeat(indent - 2)}}`;
|
|
|
2180
2208
|
const containerRef = useRef2(null);
|
|
2181
2209
|
const draggingRef = useRef2(null);
|
|
2182
2210
|
const localDataRef = useRef2((value == null ? void 0 : value.points) || defaultValue.points);
|
|
2183
|
-
const [, forceUpdate] =
|
|
2184
|
-
const [hoverItem, setHoverItem] =
|
|
2185
|
-
const [selectedPoint, setSelectedPoint] =
|
|
2186
|
-
const [isScaling, setIsScaling] =
|
|
2211
|
+
const [, forceUpdate] = useState2(0);
|
|
2212
|
+
const [hoverItem, setHoverItem] = useState2(null);
|
|
2213
|
+
const [selectedPoint, setSelectedPoint] = useState2(null);
|
|
2214
|
+
const [isScaling, setIsScaling] = useState2(false);
|
|
2187
2215
|
const scaleStartRef = useRef2(null);
|
|
2188
|
-
const [isRotating, setIsRotating] =
|
|
2216
|
+
const [isRotating, setIsRotating] = useState2(false);
|
|
2189
2217
|
const rotateStartRef = useRef2(null);
|
|
2190
2218
|
const SIZE = 260;
|
|
2191
2219
|
const PADDING = 30;
|
|
@@ -2815,8 +2843,8 @@ ${" ".repeat(indent - 2)}}`;
|
|
|
2815
2843
|
]
|
|
2816
2844
|
}
|
|
2817
2845
|
];
|
|
2818
|
-
const [easingIntensity, setEasingIntensity] =
|
|
2819
|
-
const [easingFrequency, setEasingFrequency] =
|
|
2846
|
+
const [easingIntensity, setEasingIntensity] = useState2(1);
|
|
2847
|
+
const [easingFrequency, setEasingFrequency] = useState2(3);
|
|
2820
2848
|
const generateBounce = useCallback((intensity, frequency) => {
|
|
2821
2849
|
const points2 = [{ pos: [0, 0], handleOut: [0.1, 0] }];
|
|
2822
2850
|
const bounces = Math.max(1, Math.round(frequency));
|
|
@@ -3525,22 +3553,22 @@ ${" ".repeat(indent - 2)}}`;
|
|
|
3525
3553
|
);
|
|
3526
3554
|
DebugPanelContent = ({ initialValues, onUpdate }) => {
|
|
3527
3555
|
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, _D, _E, _F, _G, _H, _I, _J, _K, _L, _M, _N, _O, _P, _Q, _R, _S, _T, _U, _V, _W, _X;
|
|
3528
|
-
const [isMinimized, setIsMinimized] =
|
|
3529
|
-
const [panelSize, setPanelSize] =
|
|
3530
|
-
const [copySuccess, setCopySuccess] =
|
|
3531
|
-
const [bakeSuccess, setBakeSuccess] =
|
|
3532
|
-
const [hasPendingChanges, setHasPendingChanges] =
|
|
3556
|
+
const [isMinimized, setIsMinimized] = useState2(false);
|
|
3557
|
+
const [panelSize, setPanelSize] = useState2({ width: 380, height: null });
|
|
3558
|
+
const [copySuccess, setCopySuccess] = useState2(false);
|
|
3559
|
+
const [bakeSuccess, setBakeSuccess] = useState2(false);
|
|
3560
|
+
const [hasPendingChanges, setHasPendingChanges] = useState2(false);
|
|
3533
3561
|
const valuesRef = useRef2(initialValues);
|
|
3534
3562
|
const dirtyKeysRef = useRef2(/* @__PURE__ */ new Set());
|
|
3535
|
-
const [, forceUpdate] =
|
|
3563
|
+
const [, forceUpdate] = useState2(0);
|
|
3536
3564
|
const isResizing = useRef2(false);
|
|
3537
3565
|
const resizeType = useRef2(null);
|
|
3538
3566
|
const debounceTimerRef = useRef2(null);
|
|
3539
3567
|
const DEBOUNCE_DELAY = 500;
|
|
3540
|
-
const [searchQuery, setSearchQuery] =
|
|
3568
|
+
const [searchQuery, setSearchQuery] = useState2("");
|
|
3541
3569
|
const historyRef = useRef2([JSON.parse(JSON.stringify(initialValues))]);
|
|
3542
|
-
const [historyIndex, setHistoryIndex] =
|
|
3543
|
-
const [historyLength, setHistoryLength] =
|
|
3570
|
+
const [historyIndex, setHistoryIndex] = useState2(0);
|
|
3571
|
+
const [historyLength, setHistoryLength] = useState2(1);
|
|
3544
3572
|
const MAX_HISTORY = 50;
|
|
3545
3573
|
const isUndoingRef = useRef2(false);
|
|
3546
3574
|
const prevInitialValuesRef = useRef2(initialValues);
|
|
@@ -3606,98 +3634,15 @@ ${" ".repeat(indent - 2)}}`;
|
|
|
3606
3634
|
flushChanges();
|
|
3607
3635
|
}
|
|
3608
3636
|
const values2 = valuesRef.current;
|
|
3609
|
-
const
|
|
3610
|
-
|
|
3611
|
-
|
|
3612
|
-
|
|
3613
|
-
|
|
3614
|
-
|
|
3615
|
-
const mt = 1 - t;
|
|
3616
|
-
const mt2 = mt * mt;
|
|
3617
|
-
const mt3 = mt2 * mt;
|
|
3618
|
-
const t2 = t * t;
|
|
3619
|
-
const t3 = t2 * t;
|
|
3620
|
-
return [
|
|
3621
|
-
mt3 * cp0[0] + 3 * mt2 * t * cp1[0] + 3 * mt * t2 * cp2[0] + t3 * cp3[0],
|
|
3622
|
-
mt3 * cp0[1] + 3 * mt2 * t * cp1[1] + 3 * mt * t2 * cp2[1] + t3 * cp3[1]
|
|
3623
|
-
];
|
|
3624
|
-
};
|
|
3625
|
-
const sampleCurveAtX = (x, points) => {
|
|
3626
|
-
var _a2, _b2, _c2, _d2;
|
|
3627
|
-
if (!points || points.length < 2) return x;
|
|
3628
|
-
if (!((_a2 = points[0]) == null ? void 0 : _a2.pos) || !((_b2 = points[points.length - 1]) == null ? void 0 : _b2.pos)) return x;
|
|
3629
|
-
let segmentIdx = 0;
|
|
3630
|
-
for (let i = 0; i < points.length - 1; i++) {
|
|
3631
|
-
if (((_c2 = points[i]) == null ? void 0 : _c2.pos) && ((_d2 = points[i + 1]) == null ? void 0 : _d2.pos) && x >= points[i].pos[0] && x <= points[i + 1].pos[0]) {
|
|
3632
|
-
segmentIdx = i;
|
|
3633
|
-
break;
|
|
3634
|
-
}
|
|
3635
|
-
}
|
|
3636
|
-
const p0 = points[segmentIdx];
|
|
3637
|
-
const p1 = points[segmentIdx + 1];
|
|
3638
|
-
if (!(p0 == null ? void 0 : p0.pos) || !(p1 == null ? void 0 : p1.pos)) return x;
|
|
3639
|
-
let tLow = 0, tHigh = 1, t = 0.5;
|
|
3640
|
-
for (let iter = 0; iter < 20; iter++) {
|
|
3641
|
-
const [px] = evaluateBezierSegment(
|
|
3642
|
-
t,
|
|
3643
|
-
p0.pos,
|
|
3644
|
-
p1.pos,
|
|
3645
|
-
p0.handleOut,
|
|
3646
|
-
p1.handleIn
|
|
3647
|
-
);
|
|
3648
|
-
if (Math.abs(px - x) < 1e-4) break;
|
|
3649
|
-
if (px < x) {
|
|
3650
|
-
tLow = t;
|
|
3651
|
-
} else {
|
|
3652
|
-
tHigh = t;
|
|
3653
|
-
}
|
|
3654
|
-
t = (tLow + tHigh) / 2;
|
|
3655
|
-
}
|
|
3656
|
-
const [, py] = evaluateBezierSegment(
|
|
3657
|
-
t,
|
|
3658
|
-
p0.pos,
|
|
3659
|
-
p1.pos,
|
|
3660
|
-
p0.handleOut,
|
|
3661
|
-
p1.handleIn
|
|
3662
|
-
);
|
|
3663
|
-
return Math.max(-0.5, Math.min(1.5, py));
|
|
3664
|
-
};
|
|
3665
|
-
const bakeCurveToArray2 = (curveData) => {
|
|
3666
|
-
const data = new Float32Array(CURVE_RESOLUTION);
|
|
3667
|
-
if (!(curveData == null ? void 0 : curveData.points) || !Array.isArray(curveData.points) || curveData.points.length < 2) {
|
|
3668
|
-
for (let i = 0; i < CURVE_RESOLUTION; i++) {
|
|
3669
|
-
data[i] = 1 - i / (CURVE_RESOLUTION - 1);
|
|
3670
|
-
}
|
|
3671
|
-
return data;
|
|
3672
|
-
}
|
|
3673
|
-
const firstPoint = curveData.points[0];
|
|
3674
|
-
const lastPoint = curveData.points[curveData.points.length - 1];
|
|
3675
|
-
if (!(firstPoint == null ? void 0 : firstPoint.pos) || !(lastPoint == null ? void 0 : lastPoint.pos) || !Array.isArray(firstPoint.pos) || !Array.isArray(lastPoint.pos)) {
|
|
3676
|
-
for (let i = 0; i < CURVE_RESOLUTION; i++) {
|
|
3677
|
-
data[i] = 1 - i / (CURVE_RESOLUTION - 1);
|
|
3678
|
-
}
|
|
3679
|
-
return data;
|
|
3680
|
-
}
|
|
3681
|
-
for (let i = 0; i < CURVE_RESOLUTION; i++) {
|
|
3682
|
-
const x = i / (CURVE_RESOLUTION - 1);
|
|
3683
|
-
data[i] = sampleCurveAtX(x, curveData.points);
|
|
3684
|
-
}
|
|
3685
|
-
return data;
|
|
3686
|
-
};
|
|
3687
|
-
const sizeData = bakeCurveToArray2(values2.fadeSizeCurve);
|
|
3688
|
-
const opacityData = bakeCurveToArray2(values2.fadeOpacityCurve);
|
|
3689
|
-
const velocityData = bakeCurveToArray2(values2.velocityCurve);
|
|
3690
|
-
const rotationSpeedData = bakeCurveToArray2(values2.rotationSpeedCurve);
|
|
3691
|
-
const rgba = new Float32Array(CURVE_RESOLUTION * 4);
|
|
3692
|
-
for (let i = 0; i < CURVE_RESOLUTION; i++) {
|
|
3693
|
-
rgba[i * 4] = sizeData[i];
|
|
3694
|
-
rgba[i * 4 + 1] = opacityData[i];
|
|
3695
|
-
rgba[i * 4 + 2] = velocityData[i];
|
|
3696
|
-
rgba[i * 4 + 3] = rotationSpeedData[i];
|
|
3697
|
-
}
|
|
3637
|
+
const binBuffer = buildCurveTextureBin(
|
|
3638
|
+
values2.fadeSizeCurve || null,
|
|
3639
|
+
values2.fadeOpacityCurve || null,
|
|
3640
|
+
values2.velocityCurve || null,
|
|
3641
|
+
values2.rotationSpeedCurve || null
|
|
3642
|
+
);
|
|
3698
3643
|
const vfxName = values2.name || `vfx-curves-${Date.now()}`;
|
|
3699
3644
|
const filename = `${vfxName.replace(/[^a-zA-Z0-9-_]/g, "-")}.bin`;
|
|
3700
|
-
const blob = new Blob([
|
|
3645
|
+
const blob = new Blob([binBuffer], { type: "application/octet-stream" });
|
|
3701
3646
|
const link = document.createElement("a");
|
|
3702
3647
|
link.download = filename;
|
|
3703
3648
|
link.href = URL.createObjectURL(blob);
|
|
@@ -5404,7 +5349,7 @@ import {
|
|
|
5404
5349
|
useRef as useRef3,
|
|
5405
5350
|
useMemo as useMemo2,
|
|
5406
5351
|
useCallback as useCallback2,
|
|
5407
|
-
useState as
|
|
5352
|
+
useState as useState3
|
|
5408
5353
|
} from "react";
|
|
5409
5354
|
import { useFrame, useThree } from "@react-three/fiber";
|
|
5410
5355
|
import * as THREE2 from "three/webgpu";
|
|
@@ -5434,7 +5379,9 @@ import {
|
|
|
5434
5379
|
Easing as Easing2,
|
|
5435
5380
|
Lighting,
|
|
5436
5381
|
bakeCurveToArray,
|
|
5437
|
-
createCombinedCurveTexture as createCombinedCurveTexture3
|
|
5382
|
+
createCombinedCurveTexture as createCombinedCurveTexture3,
|
|
5383
|
+
buildCurveTextureBin as buildCurveTextureBin2,
|
|
5384
|
+
CurveChannel as CurveChannel2
|
|
5438
5385
|
} from "core-vfx";
|
|
5439
5386
|
import { jsx as jsx2 } from "react/jsx-runtime";
|
|
5440
5387
|
var VFXParticles;
|
|
@@ -5561,29 +5508,29 @@ var init_VFXParticles = __esm({
|
|
|
5561
5508
|
const spriteRef = useRef3(null);
|
|
5562
5509
|
const initialized = useRef3(false);
|
|
5563
5510
|
const nextIndex = useRef3(0);
|
|
5564
|
-
const [emitting, setEmitting] =
|
|
5511
|
+
const [emitting, setEmitting] = useState3(autoStart);
|
|
5565
5512
|
const emitAccumulator = useRef3(0);
|
|
5566
5513
|
const delayRef = useRef3(delay);
|
|
5567
5514
|
const emitCountRef = useRef3(emitCount);
|
|
5568
5515
|
const turbulenceRef = useRef3(turbulence);
|
|
5569
|
-
const [activeMaxParticles, setActiveMaxParticles] =
|
|
5570
|
-
const [activeLighting, setActiveLighting] =
|
|
5571
|
-
const [activeAppearance, setActiveAppearance] =
|
|
5572
|
-
const [activeOrientToDirection, setActiveOrientToDirection] =
|
|
5573
|
-
const [activeGeometry, setActiveGeometry] =
|
|
5574
|
-
const [activeShadow, setActiveShadow] =
|
|
5575
|
-
const [activeFadeSizeCurve, setActiveFadeSizeCurve] =
|
|
5576
|
-
const [activeFadeOpacityCurve, setActiveFadeOpacityCurve] =
|
|
5577
|
-
const [activeVelocityCurve, setActiveVelocityCurve] =
|
|
5578
|
-
const [activeRotationSpeedCurve, setActiveRotationSpeedCurve] =
|
|
5579
|
-
const [activeTurbulence, setActiveTurbulence] =
|
|
5516
|
+
const [activeMaxParticles, setActiveMaxParticles] = useState3(maxParticles);
|
|
5517
|
+
const [activeLighting, setActiveLighting] = useState3(lighting);
|
|
5518
|
+
const [activeAppearance, setActiveAppearance] = useState3(appearance);
|
|
5519
|
+
const [activeOrientToDirection, setActiveOrientToDirection] = useState3(orientToDirection);
|
|
5520
|
+
const [activeGeometry, setActiveGeometry] = useState3(geometry);
|
|
5521
|
+
const [activeShadow, setActiveShadow] = useState3(shadow);
|
|
5522
|
+
const [activeFadeSizeCurve, setActiveFadeSizeCurve] = useState3(fadeSizeCurve);
|
|
5523
|
+
const [activeFadeOpacityCurve, setActiveFadeOpacityCurve] = useState3(fadeOpacityCurve);
|
|
5524
|
+
const [activeVelocityCurve, setActiveVelocityCurve] = useState3(velocityCurve);
|
|
5525
|
+
const [activeRotationSpeedCurve, setActiveRotationSpeedCurve] = useState3(rotationSpeedCurve);
|
|
5526
|
+
const [activeTurbulence, setActiveTurbulence] = useState3(
|
|
5580
5527
|
turbulence !== null && ((_a = turbulence == null ? void 0 : turbulence.intensity) != null ? _a : 0) > 0
|
|
5581
5528
|
);
|
|
5582
|
-
const [activeAttractors, setActiveAttractors] =
|
|
5529
|
+
const [activeAttractors, setActiveAttractors] = useState3(
|
|
5583
5530
|
attractors !== null && attractors.length > 0
|
|
5584
5531
|
);
|
|
5585
|
-
const [activeCollision, setActiveCollision] =
|
|
5586
|
-
const [activeNeedsPerParticleColor, setActiveNeedsPerParticleColor] =
|
|
5532
|
+
const [activeCollision, setActiveCollision] = useState3(collision !== null);
|
|
5533
|
+
const [activeNeedsPerParticleColor, setActiveNeedsPerParticleColor] = useState3(colorStart.length > 1 || colorEnd !== null);
|
|
5587
5534
|
const isNonDefaultRotation = (r) => {
|
|
5588
5535
|
if (typeof r === "number") return r !== 0;
|
|
5589
5536
|
if (Array.isArray(r) && r.length === 2 && typeof r[0] === "number") {
|
|
@@ -5596,7 +5543,7 @@ var init_VFXParticles = __esm({
|
|
|
5596
5543
|
}
|
|
5597
5544
|
return false;
|
|
5598
5545
|
};
|
|
5599
|
-
const [activeNeedsRotation, setActiveNeedsRotation] =
|
|
5546
|
+
const [activeNeedsRotation, setActiveNeedsRotation] = useState3(
|
|
5600
5547
|
isNonDefaultRotation(rotation) || isNonDefaultRotation(rotationSpeed)
|
|
5601
5548
|
);
|
|
5602
5549
|
useEffect3(() => {
|
|
@@ -5656,22 +5603,19 @@ var init_VFXParticles = __esm({
|
|
|
5656
5603
|
() => toRange(fadeOpacity, [1, 0]),
|
|
5657
5604
|
[fadeOpacity]
|
|
5658
5605
|
);
|
|
5659
|
-
const
|
|
5606
|
+
const {
|
|
5607
|
+
texture: curveTexture,
|
|
5608
|
+
sizeEnabled: curveTextureSizeEnabled,
|
|
5609
|
+
opacityEnabled: curveTextureOpacityEnabled,
|
|
5610
|
+
velocityEnabled: curveTextureVelocityEnabled,
|
|
5611
|
+
rotationSpeedEnabled: curveTextureRotationSpeedEnabled
|
|
5612
|
+
} = useCurveTextureAsync(
|
|
5660
5613
|
activeFadeSizeCurve,
|
|
5661
5614
|
activeFadeOpacityCurve,
|
|
5662
5615
|
activeVelocityCurve,
|
|
5663
5616
|
activeRotationSpeedCurve,
|
|
5664
5617
|
curveTexturePath
|
|
5665
5618
|
);
|
|
5666
|
-
const prevCurveTextureRef = useRef3(null);
|
|
5667
|
-
useEffect3(() => {
|
|
5668
|
-
prevCurveTextureRef.current = curveTexture;
|
|
5669
|
-
return () => {
|
|
5670
|
-
if (curveTexture) {
|
|
5671
|
-
curveTexture.dispose();
|
|
5672
|
-
}
|
|
5673
|
-
};
|
|
5674
|
-
}, [curveTexture]);
|
|
5675
5619
|
const lifetimeRange = useMemo2(() => toRange(lifetime, [1, 2]), [lifetime]);
|
|
5676
5620
|
const rotation3D = useMemo2(() => toRotation3D(rotation), [rotation]);
|
|
5677
5621
|
const rotationSpeed3D = useMemo2(
|
|
@@ -5853,23 +5797,11 @@ var init_VFXParticles = __esm({
|
|
|
5853
5797
|
// Soft particles
|
|
5854
5798
|
softParticlesEnabled: uniform(softParticles ? 1 : 0),
|
|
5855
5799
|
softDistance: uniform(softDistance),
|
|
5856
|
-
//
|
|
5857
|
-
|
|
5858
|
-
|
|
5859
|
-
|
|
5860
|
-
),
|
|
5861
|
-
// Rotation speed curve (modulates rotation speed over lifetime)
|
|
5862
|
-
rotationSpeedCurveEnabled: uniform(
|
|
5863
|
-
rotationSpeedCurve || curveTexturePath ? 1 : 0
|
|
5864
|
-
),
|
|
5865
|
-
// Fade size curve (when disabled, uses fadeSize prop interpolation)
|
|
5866
|
-
fadeSizeCurveEnabled: uniform(
|
|
5867
|
-
fadeSizeCurve || curveTexturePath ? 1 : 0
|
|
5868
|
-
),
|
|
5869
|
-
// Fade opacity curve (when disabled, uses fadeOpacity prop interpolation)
|
|
5870
|
-
fadeOpacityCurveEnabled: uniform(
|
|
5871
|
-
fadeOpacityCurve || curveTexturePath ? 1 : 0
|
|
5872
|
-
),
|
|
5800
|
+
// Curve enabled flags (set by useCurveTextureAsync per-channel info)
|
|
5801
|
+
velocityCurveEnabled: uniform(0),
|
|
5802
|
+
rotationSpeedCurveEnabled: uniform(0),
|
|
5803
|
+
fadeSizeCurveEnabled: uniform(0),
|
|
5804
|
+
fadeOpacityCurveEnabled: uniform(0),
|
|
5873
5805
|
// Orient axis: 0=+X, 1=+Y, 2=+Z, 3=-X, 4=-Y, 5=-Z
|
|
5874
5806
|
orientAxisType: uniform(axisToNumber(orientAxis)),
|
|
5875
5807
|
// Stretch by speed (uses effective velocity after curve modifier)
|
|
@@ -5980,10 +5912,10 @@ var init_VFXParticles = __esm({
|
|
|
5980
5912
|
uniforms.startPositionAsDirection.value = startPositionAsDirection ? 1 : 0;
|
|
5981
5913
|
uniforms.softParticlesEnabled.value = softParticles ? 1 : 0;
|
|
5982
5914
|
uniforms.softDistance.value = softDistance;
|
|
5983
|
-
uniforms.velocityCurveEnabled.value =
|
|
5984
|
-
uniforms.rotationSpeedCurveEnabled.value =
|
|
5985
|
-
uniforms.fadeSizeCurveEnabled.value =
|
|
5986
|
-
uniforms.fadeOpacityCurveEnabled.value =
|
|
5915
|
+
uniforms.velocityCurveEnabled.value = curveTextureVelocityEnabled ? 1 : 0;
|
|
5916
|
+
uniforms.rotationSpeedCurveEnabled.value = curveTextureRotationSpeedEnabled ? 1 : 0;
|
|
5917
|
+
uniforms.fadeSizeCurveEnabled.value = curveTextureSizeEnabled ? 1 : 0;
|
|
5918
|
+
uniforms.fadeOpacityCurveEnabled.value = curveTextureOpacityEnabled ? 1 : 0;
|
|
5987
5919
|
uniforms.orientAxisType.value = axisToNumber(orientAxis);
|
|
5988
5920
|
uniforms.stretchEnabled.value = stretchBySpeed ? 1 : 0;
|
|
5989
5921
|
uniforms.stretchFactor.value = (_h = stretchBySpeed == null ? void 0 : stretchBySpeed.factor) != null ? _h : 1;
|
|
@@ -6028,11 +5960,10 @@ var init_VFXParticles = __esm({
|
|
|
6028
5960
|
startPositionAsDirection,
|
|
6029
5961
|
softParticles,
|
|
6030
5962
|
softDistance,
|
|
6031
|
-
|
|
6032
|
-
|
|
6033
|
-
|
|
6034
|
-
|
|
6035
|
-
curveTexturePath,
|
|
5963
|
+
curveTextureVelocityEnabled,
|
|
5964
|
+
curveTextureRotationSpeedEnabled,
|
|
5965
|
+
curveTextureSizeEnabled,
|
|
5966
|
+
curveTextureOpacityEnabled,
|
|
6036
5967
|
orientAxis,
|
|
6037
5968
|
stretchBySpeed
|
|
6038
5969
|
]);
|
|
@@ -7118,12 +7049,14 @@ export {
|
|
|
7118
7049
|
Appearance,
|
|
7119
7050
|
AttractorType2 as AttractorType,
|
|
7120
7051
|
Blending,
|
|
7052
|
+
CurveChannel2 as CurveChannel,
|
|
7121
7053
|
Easing2 as Easing,
|
|
7122
7054
|
EmitterShape,
|
|
7123
7055
|
Lighting,
|
|
7124
7056
|
VFXEmitter,
|
|
7125
7057
|
VFXParticles,
|
|
7126
7058
|
bakeCurveToArray,
|
|
7059
|
+
buildCurveTextureBin2 as buildCurveTextureBin,
|
|
7127
7060
|
createCombinedCurveTexture3 as createCombinedCurveTexture,
|
|
7128
7061
|
useCurveTextureAsync,
|
|
7129
7062
|
useVFXEmitter,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "r3f-vfx",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.4",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"repository": {
|
|
@@ -24,7 +24,7 @@
|
|
|
24
24
|
"prepublishOnly": "bun run copy-readme"
|
|
25
25
|
},
|
|
26
26
|
"dependencies": {
|
|
27
|
-
"core-vfx": "0.0.
|
|
27
|
+
"core-vfx": "0.0.7",
|
|
28
28
|
"zustand": "5.0.10"
|
|
29
29
|
},
|
|
30
30
|
"devDependencies": {
|