babylon.quarks-editor 0.18.1 → 0.20.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/CHANGELOG.md +28 -0
- package/README.md +6 -6
- package/dist/core/assetDragSession.d.ts +4 -0
- package/dist/core/assetDragSession.js +8 -0
- package/dist/core/assetTree.d.ts +39 -0
- package/dist/core/assetTree.js +112 -0
- package/dist/core/assets.d.ts +56 -0
- package/dist/core/assets.js +207 -0
- package/dist/core/binding.d.ts +6 -1
- package/dist/core/binding.js +7 -0
- package/dist/core/collision.d.ts +4 -5
- package/dist/core/collision.js +4 -5
- package/dist/core/colors.d.ts +1 -1
- package/dist/core/defaultEffect.d.ts +4 -5
- package/dist/core/defaultEffect.js +5 -14
- package/dist/core/effectTree.d.ts +1 -1
- package/dist/core/effectTree.js +18 -4
- package/dist/core/emitterShapeWireframe.d.ts +2 -1
- package/dist/core/emitterShapeWireframe.js +2 -1
- package/dist/core/galleryDropMarker.js +1 -1
- package/dist/core/galleryPlayback.d.ts +7 -7
- package/dist/core/galleryPlayback.js +2 -2
- package/dist/core/galleryScene.d.ts +8 -13
- package/dist/core/galleryScene.js +14 -42
- package/dist/core/gallerySelectionMarker.d.ts +1 -0
- package/dist/core/gallerySelectionMarker.js +1 -0
- package/dist/core/history.d.ts +12 -1
- package/dist/core/history.js +16 -3
- package/dist/core/indexedDbProjectStore.d.ts +35 -0
- package/dist/core/indexedDbProjectStore.js +299 -0
- package/dist/core/lineShaders.d.ts +2 -0
- package/dist/core/lineShaders.js +7 -0
- package/dist/core/loadEffect.d.ts +2 -2
- package/dist/core/loadEffect.js +1 -1
- package/dist/core/pickAssetFiles.d.ts +6 -0
- package/dist/core/{pickGalleryFiles.js → pickAssetFiles.js} +13 -8
- package/dist/core/projectStore.d.ts +61 -0
- package/dist/core/projectStore.js +14 -0
- package/dist/core/sceneEntries.d.ts +35 -0
- package/dist/core/sceneEntries.js +62 -0
- package/dist/core/shapes.d.ts +1 -1
- package/dist/core/shapes.js +35 -8
- package/dist/core/systems.d.ts +1 -1
- package/dist/core/systems.js +3 -1
- package/dist/core/timeline.d.ts +1 -2
- package/dist/core/transport.d.ts +12 -0
- package/dist/core/transport.js +36 -0
- package/dist/core/values.d.ts +1 -1
- package/dist/core/viewportPicker.d.ts +4 -4
- package/dist/core/viewportPicker.js +3 -3
- package/dist/index.d.ts +15 -11
- package/dist/index.js +8 -6
- package/dist/react/AssetsPanel.d.ts +22 -0
- package/dist/react/AssetsPanel.js +252 -0
- package/dist/react/ChoiceDialog.d.ts +18 -0
- package/dist/react/ChoiceDialog.js +48 -0
- package/dist/react/ContextMenu.d.ts +16 -0
- package/dist/react/ContextMenu.js +70 -0
- package/dist/react/CurveEditor.d.ts +1 -2
- package/dist/react/CurveEditor.js +14 -3
- package/dist/react/EditorWorkspace.d.ts +21 -0
- package/dist/react/EditorWorkspace.js +63 -0
- package/dist/react/EffectEditor.d.ts +3 -3
- package/dist/react/EffectEditor.js +9 -6
- package/dist/react/EffectEditorHost.d.ts +20 -3
- package/dist/react/EffectEditorHost.js +1426 -558
- package/dist/react/EffectTreeView.d.ts +17 -0
- package/dist/react/EffectTreeView.js +52 -0
- package/dist/react/GradientEditor.d.ts +1 -2
- package/dist/react/GradientEditor.js +8 -1
- package/dist/react/MessageDialog.js +7 -1
- package/dist/react/ModuleSection.js +10 -3
- package/dist/react/ObjectModule.d.ts +5 -2
- package/dist/react/ObjectModule.js +8 -11
- package/dist/react/ProjectsPage.d.ts +9 -0
- package/dist/react/ProjectsPage.js +140 -0
- package/dist/react/ScenePanel.d.ts +26 -0
- package/dist/react/ScenePanel.js +134 -0
- package/dist/react/SubEmittersModule.d.ts +1 -2
- package/dist/react/TimelinePanel.d.ts +11 -4
- package/dist/react/TimelinePanel.js +65 -40
- package/dist/react/TimelineTrackRow.d.ts +1 -1
- package/dist/react/TimelineTrackRow.js +20 -6
- package/dist/react/TransportBar.d.ts +24 -0
- package/dist/react/TransportBar.js +43 -0
- package/dist/react/ValueField.d.ts +1 -2
- package/dist/react/behaviorModules.js +24 -12
- package/dist/react/index.d.ts +31 -17
- package/dist/react/index.js +18 -11
- package/dist/react/inspectorHints.js +1 -2
- package/dist/react/modules.js +55 -25
- package/package.json +68 -68
- package/src/core/assetDragSession.ts +12 -0
- package/src/core/assetTree.ts +148 -0
- package/src/core/assets.ts +262 -0
- package/src/core/binding.ts +10 -2
- package/src/core/collision.ts +4 -5
- package/src/core/colors.ts +1 -1
- package/src/core/defaultEffect.ts +10 -23
- package/src/core/effectTree.ts +22 -7
- package/src/core/emitterShapeWireframe.ts +9 -4
- package/src/core/galleryDropMarker.ts +6 -2
- package/src/core/galleryPlayback.ts +9 -9
- package/src/core/galleryScene.ts +15 -63
- package/src/core/gallerySelectionMarker.ts +6 -1
- package/src/core/history.ts +24 -3
- package/src/core/indexedDbProjectStore.ts +357 -0
- package/src/core/lineShaders.ts +7 -0
- package/src/core/loadEffect.ts +3 -3
- package/src/core/{pickGalleryFiles.ts → pickAssetFiles.ts} +16 -8
- package/src/core/projectStore.ts +81 -0
- package/src/core/sceneEntries.ts +96 -0
- package/src/core/shapes.ts +48 -10
- package/src/core/systems.ts +9 -3
- package/src/core/timeline.ts +8 -8
- package/src/core/transport.ts +53 -0
- package/src/core/values.ts +1 -1
- package/src/core/viewportPicker.ts +5 -5
- package/src/index.ts +29 -18
- package/src/react/AssetsPanel.tsx +559 -0
- package/src/react/ChoiceDialog.tsx +93 -0
- package/src/react/ContextMenu.tsx +107 -0
- package/src/react/CurveEditor.tsx +40 -10
- package/src/react/EditorWorkspace.tsx +95 -0
- package/src/react/EffectEditor.tsx +28 -16
- package/src/react/EffectEditorHost.tsx +2005 -721
- package/src/react/EffectTreeView.tsx +117 -0
- package/src/react/GradientEditor.tsx +21 -4
- package/src/react/InspectorInfoIcon.tsx +6 -2
- package/src/react/MessageDialog.tsx +9 -1
- package/src/react/ModuleSection.tsx +12 -3
- package/src/react/ObjectModule.tsx +41 -16
- package/src/react/ProjectsPage.tsx +306 -0
- package/src/react/PromptDialog.tsx +5 -1
- package/src/react/ScenePanel.tsx +318 -0
- package/src/react/SubEmittersModule.tsx +1 -2
- package/src/react/TimelinePanel.tsx +171 -99
- package/src/react/TimelineTrackRow.tsx +71 -18
- package/src/react/TransportBar.tsx +114 -0
- package/src/react/ValueField.tsx +0 -1
- package/src/react/behaviorModules.tsx +148 -42
- package/src/react/index.ts +47 -33
- package/src/react/inspectorHints.ts +1 -2
- package/src/react/modules.tsx +173 -57
- package/dist/core/galleryDragSession.d.ts +0 -4
- package/dist/core/galleryDragSession.js +0 -8
- package/dist/core/galleryTree.d.ts +0 -49
- package/dist/core/galleryTree.js +0 -138
- package/dist/core/loadEffectGallery.d.ts +0 -36
- package/dist/core/loadEffectGallery.js +0 -97
- package/dist/core/pickGalleryFiles.d.ts +0 -5
- package/dist/react/GalleryPanel.d.ts +0 -20
- package/dist/react/GalleryPanel.js +0 -246
- package/src/core/galleryDragSession.ts +0 -12
- package/src/core/galleryTree.ts +0 -187
- package/src/core/loadEffectGallery.ts +0 -146
- package/src/react/GalleryPanel.tsx +0 -517
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
2
|
+
import { ArrowPathIcon, ForwardIcon, PauseIcon, PlayIcon, RectangleGroupIcon } from '@heroicons/react/24/solid';
|
|
2
3
|
import React, { useMemo, useRef, useState } from 'react';
|
|
3
|
-
import { ArrowPathIcon, ForwardIcon, PauseIcon, PlayIcon, RectangleGroupIcon, } from '@heroicons/react/24/solid';
|
|
4
|
-
import { clearFocusFinished, getFocusElapsed, isFocusFinished, markFocusFinished, setFocusElapsed, } from '../core/playback';
|
|
5
4
|
import { groupNodes } from '../core/groups';
|
|
5
|
+
import { clearFocusFinished, getFocusElapsed, isFocusFinished, markFocusFinished, setFocusElapsed, } from '../core/playback';
|
|
6
6
|
import { pauseFocus, playFocus, scrubFocusTo, scrubFocusToSettled } from '../core/scrub';
|
|
7
7
|
import { computeTimelineRows, computeTimelineSpan } from '../core/timeline';
|
|
8
|
+
import { PLAYBACK_SPEEDS, restartFocusPlayback, toggleStagePlayback } from '../core/transport';
|
|
8
9
|
import { TimelineTrackRow } from './TimelineTrackRow';
|
|
9
10
|
import { iconStyle } from './icons';
|
|
10
11
|
import { buttonStyle, theme } from './theme';
|
|
@@ -29,7 +30,7 @@ function pickTickInterval(pxPerSecond) {
|
|
|
29
30
|
* apply only to the focused effect without stopping other previews.
|
|
30
31
|
*/
|
|
31
32
|
export function TimelinePanel(props) {
|
|
32
|
-
const { binding, selectedNode, onSelectNode, scene, renderer, playbackRef, playheadRef, counterRef, stagePlaying, setStagePlaying, speed, setSpeed, playbackEnabled = true } = props;
|
|
33
|
+
const { binding, selectedNode, onSelectNode, scene, renderer, playbackRef, playheadRef, counterRef, stagePlaying, setStagePlaying, speed, setSpeed, playbackEnabled = true, docked = false, showTransport = true, } = props;
|
|
33
34
|
const [bodyWidthPx, setBodyWidthPx] = useState(600);
|
|
34
35
|
const [collapsedGroups, setCollapsedGroups] = useState(() => new Set());
|
|
35
36
|
const [hiddenSystems, setHiddenSystems] = useState(() => new Set());
|
|
@@ -129,7 +130,18 @@ export function TimelinePanel(props) {
|
|
|
129
130
|
};
|
|
130
131
|
raf = requestAnimationFrame(tick);
|
|
131
132
|
return () => cancelAnimationFrame(raf);
|
|
132
|
-
}, [
|
|
133
|
+
}, [
|
|
134
|
+
pxPerSecond,
|
|
135
|
+
timelineSpan,
|
|
136
|
+
anyLooping,
|
|
137
|
+
playbackRef,
|
|
138
|
+
playheadRef,
|
|
139
|
+
focusRootId,
|
|
140
|
+
playbackEnabled,
|
|
141
|
+
binding,
|
|
142
|
+
scene,
|
|
143
|
+
renderer,
|
|
144
|
+
]);
|
|
133
145
|
const visibleRows = useMemo(() => {
|
|
134
146
|
let hideUntilDepth = null;
|
|
135
147
|
const visible = rows.filter((row) => {
|
|
@@ -196,34 +208,12 @@ export function TimelinePanel(props) {
|
|
|
196
208
|
}
|
|
197
209
|
};
|
|
198
210
|
const restartFocus = () => {
|
|
199
|
-
|
|
200
|
-
const state = playbackRef.current;
|
|
201
|
-
setFocusElapsed(state, focusRootId, 0);
|
|
202
|
-
clearFocusFinished(state, focusRootId);
|
|
203
|
-
if (stagePlaying) {
|
|
204
|
-
playFocus(binding);
|
|
205
|
-
}
|
|
211
|
+
restartFocusPlayback(binding, renderer, scene, playbackRef.current);
|
|
206
212
|
if (playheadRef.current) {
|
|
207
213
|
playheadRef.current.style.left = `${LABEL_WIDTH + TIMELINE_INSET}px`;
|
|
208
214
|
}
|
|
209
|
-
scene.render();
|
|
210
|
-
};
|
|
211
|
-
const handleStagePlayPause = () => {
|
|
212
|
-
const state = playbackRef.current;
|
|
213
|
-
if (!stagePlaying) {
|
|
214
|
-
if (isFocusFinished(state, focusRootId)) {
|
|
215
|
-
binding.restart();
|
|
216
|
-
clearFocusFinished(state, focusRootId);
|
|
217
|
-
setFocusElapsed(state, focusRootId, 0);
|
|
218
|
-
scene.render();
|
|
219
|
-
}
|
|
220
|
-
state.stagePlaying = true;
|
|
221
|
-
setStagePlaying(true);
|
|
222
|
-
return;
|
|
223
|
-
}
|
|
224
|
-
state.stagePlaying = false;
|
|
225
|
-
setStagePlaying(false);
|
|
226
215
|
};
|
|
216
|
+
const handleStagePlayPause = () => toggleStagePlayback(binding, scene, playbackRef.current, stagePlaying, setStagePlaying);
|
|
227
217
|
const ticks = [];
|
|
228
218
|
for (let t = 0; t <= timelineSpan; t += pickTickInterval(pxPerSecond)) {
|
|
229
219
|
ticks.push(t);
|
|
@@ -238,19 +228,31 @@ export function TimelinePanel(props) {
|
|
|
238
228
|
gap: 6,
|
|
239
229
|
};
|
|
240
230
|
return (_jsxs("div", { style: {
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
231
|
+
...(docked
|
|
232
|
+
? { flex: 1, minHeight: 0 }
|
|
233
|
+
: { flexShrink: 0, height: PANEL_HEIGHT, borderTop: `1px solid ${theme.border}` }),
|
|
244
234
|
background: theme.panelBg,
|
|
245
235
|
display: 'flex',
|
|
246
236
|
flexDirection: 'column',
|
|
247
237
|
fontFamily: theme.font,
|
|
248
238
|
color: theme.text,
|
|
249
|
-
}, children: [
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
239
|
+
}, children: [(showTransport || groupSelection.size >= 2) && (_jsxs("div", { style: {
|
|
240
|
+
display: 'flex',
|
|
241
|
+
alignItems: 'center',
|
|
242
|
+
gap: 6,
|
|
243
|
+
padding: '6px 10px',
|
|
244
|
+
borderBottom: `1px solid ${theme.border}`,
|
|
245
|
+
}, children: [showTransport && (_jsxs(_Fragment, { children: [_jsx("button", { className: "qe-hover", style: { ...overlayButton, opacity: playbackEnabled ? 1 : 0.45 }, title: stagePlaying ? 'Pause stage preview' : 'Play stage preview', disabled: !playbackEnabled, onClick: handleStagePlayPause, children: stagePlaying ? (_jsx(PauseIcon, { style: iconStyle(14) })) : (_jsx(PlayIcon, { style: iconStyle(14) })) }), _jsx("button", { className: "qe-hover", style: { ...overlayButton, opacity: playbackEnabled ? 1 : 0.45 }, title: "Step one frame (stage)", disabled: !playbackEnabled || stagePlaying, onClick: () => (playbackRef.current.stepQueued = true), children: _jsx(ForwardIcon, { style: iconStyle(14) }) }), _jsx("button", { className: "qe-hover", style: { ...overlayButton, opacity: playbackEnabled ? 1 : 0.45 }, title: "Restart focused effect only", disabled: !playbackEnabled, onClick: restartFocus, children: _jsx(ArrowPathIcon, { style: iconStyle(14) }) }), _jsx("select", { className: "qe-hover", style: { ...overlayButton, padding: '5px 4px', opacity: playbackEnabled ? 1 : 0.45 }, title: "Playback speed", value: speed, disabled: !playbackEnabled, onChange: (e) => {
|
|
246
|
+
const next = Number(e.target.value);
|
|
247
|
+
playbackRef.current.speed = next;
|
|
248
|
+
setSpeed(next);
|
|
249
|
+
}, children: PLAYBACK_SPEEDS.map((s) => (_jsxs("option", { value: s, children: ["\u00D7", s] }, s))) }), _jsx("span", { ref: counterRef, style: {
|
|
250
|
+
fontSize: 12,
|
|
251
|
+
color: theme.textDim,
|
|
252
|
+
fontVariantNumeric: 'tabular-nums',
|
|
253
|
+
paddingLeft: 4,
|
|
254
|
+
minWidth: 120,
|
|
255
|
+
} })] })), groupSelection.size >= 2 && (_jsxs("button", { className: "qe-hover", style: overlayButton, title: "Group the checked rows", onClick: groupSelectedNodes, children: [_jsx(RectangleGroupIcon, { style: iconStyle(14) }), "Group (", groupSelection.size, ")"] }))] })), _jsx("div", { ref: bodyRef, style: { position: 'relative', flex: 1, minHeight: 0 }, children: !playbackEnabled ? (_jsx("div", { style: {
|
|
254
256
|
position: 'absolute',
|
|
255
257
|
inset: 0,
|
|
256
258
|
display: 'flex',
|
|
@@ -261,7 +263,7 @@ export function TimelinePanel(props) {
|
|
|
261
263
|
fontSize: 13,
|
|
262
264
|
color: theme.textDim,
|
|
263
265
|
lineHeight: 1.5,
|
|
264
|
-
}, children: "
|
|
266
|
+
}, children: "The focused effect is hidden. Show it in the Scene list to preview playback." })) : (_jsxs(_Fragment, { children: [_jsxs("div", { style: {
|
|
265
267
|
position: 'absolute',
|
|
266
268
|
top: 0,
|
|
267
269
|
left: 0,
|
|
@@ -271,7 +273,12 @@ export function TimelinePanel(props) {
|
|
|
271
273
|
gridTemplateColumns: `${LABEL_WIDTH}px 1fr`,
|
|
272
274
|
background: theme.panelBg,
|
|
273
275
|
zIndex: 2,
|
|
274
|
-
}, children: [_jsx("div", { style: { height: RULER_HEIGHT } }), _jsx("div", { className: "qe-hover-bg", style: {
|
|
276
|
+
}, children: [_jsx("div", { style: { height: RULER_HEIGHT } }), _jsx("div", { className: "qe-hover-bg", style: {
|
|
277
|
+
position: 'relative',
|
|
278
|
+
height: RULER_HEIGHT,
|
|
279
|
+
cursor: 'ew-resize',
|
|
280
|
+
overflow: 'hidden',
|
|
281
|
+
}, onPointerDown: (e) => {
|
|
275
282
|
playbackRef.current.scrubbing = true;
|
|
276
283
|
e.target.setPointerCapture(e.pointerId);
|
|
277
284
|
queueScrub(e.clientX);
|
|
@@ -281,7 +288,16 @@ export function TimelinePanel(props) {
|
|
|
281
288
|
}, onPointerUp: (e) => {
|
|
282
289
|
playbackRef.current.scrubbing = false;
|
|
283
290
|
e.target.releasePointerCapture?.(e.pointerId);
|
|
284
|
-
}, children: ticks.map((t) => (_jsxs("div", { style: {
|
|
291
|
+
}, children: ticks.map((t) => (_jsxs("div", { style: {
|
|
292
|
+
position: 'absolute',
|
|
293
|
+
left: TIMELINE_INSET + t * pxPerSecond,
|
|
294
|
+
top: 0,
|
|
295
|
+
bottom: 0,
|
|
296
|
+
borderLeft: `1px solid ${theme.border}`,
|
|
297
|
+
fontSize: 10,
|
|
298
|
+
color: theme.textDim,
|
|
299
|
+
paddingLeft: 3,
|
|
300
|
+
}, children: [t, "s"] }, t))) })] }), _jsx("div", { style: {
|
|
285
301
|
position: 'absolute',
|
|
286
302
|
top: RULER_HEIGHT,
|
|
287
303
|
left: 0,
|
|
@@ -293,7 +309,16 @@ export function TimelinePanel(props) {
|
|
|
293
309
|
display: 'grid',
|
|
294
310
|
gridTemplateColumns: `${LABEL_WIDTH}px 1fr`,
|
|
295
311
|
gridAutoRows: 'min-content',
|
|
296
|
-
}, children: visibleRows.map((row) => (_jsx(TimelineTrackRow, { row: row, binding: binding, selected: row.node === selectedNode, onSelectNode: onSelectNode, pxPerSecond: pxPerSecond, offsetPx: TIMELINE_INSET, collapsed: row.kind === 'group' && collapsedGroups.has(row.node), onToggleCollapse: row.kind === 'group' ? () => toggleCollapse(row.node) : undefined, hidden: row.kind === 'track' && hiddenSystems.has(row.system), onToggleVisible: row.kind === 'track' ? () => toggleVisible(row.system) : undefined, groupSelected: groupSelection.has(row.node), onToggleGroupSelect: () => toggleGroupSelect(row.node) }, row.node.uniqueId))) }) }), _jsx("div", { style: {
|
|
312
|
+
}, children: visibleRows.map((row) => (_jsx(TimelineTrackRow, { row: row, binding: binding, selected: row.node === selectedNode, onSelectNode: onSelectNode, pxPerSecond: pxPerSecond, offsetPx: TIMELINE_INSET, collapsed: row.kind === 'group' && collapsedGroups.has(row.node), onToggleCollapse: row.kind === 'group' ? () => toggleCollapse(row.node) : undefined, hidden: row.kind === 'track' && hiddenSystems.has(row.system), onToggleVisible: row.kind === 'track' ? () => toggleVisible(row.system) : undefined, groupSelected: groupSelection.has(row.node), onToggleGroupSelect: () => toggleGroupSelect(row.node) }, row.node.uniqueId))) }) }), _jsx("div", { style: {
|
|
313
|
+
position: 'absolute',
|
|
314
|
+
top: 0,
|
|
315
|
+
bottom: 0,
|
|
316
|
+
left: LABEL_WIDTH,
|
|
317
|
+
width: 1,
|
|
318
|
+
background: theme.border,
|
|
319
|
+
pointerEvents: 'none',
|
|
320
|
+
zIndex: 3,
|
|
321
|
+
} }), _jsx("div", { ref: playheadRef, style: {
|
|
297
322
|
position: 'absolute',
|
|
298
323
|
top: 0,
|
|
299
324
|
bottom: 0,
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import React from 'react';
|
|
2
1
|
import type { TransformNode } from '@babylonjs/core/Meshes/transformNode';
|
|
2
|
+
import React from 'react';
|
|
3
3
|
import type { EffectBinding } from '../core/binding';
|
|
4
4
|
import type { TimelineRow } from '../core/timeline';
|
|
5
5
|
export interface TimelineTrackRowProps {
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
2
|
-
import { useState } from 'react';
|
|
3
2
|
import { CheckIcon, ChevronDownIcon, ChevronRightIcon, EyeIcon, EyeSlashIcon, PencilSquareIcon, PlusIcon, SparklesIcon, SquaresPlusIcon, XMarkIcon, } from '@heroicons/react/24/solid';
|
|
3
|
+
import { useState } from 'react';
|
|
4
4
|
import { buildEffectTree, collectSystems } from '../core/effectTree';
|
|
5
|
-
import { createChildSystem, removeSystems } from '../core/systems';
|
|
6
5
|
import { ungroupNode } from '../core/groups';
|
|
6
|
+
import { createChildSystem, removeSystems } from '../core/systems';
|
|
7
7
|
import { PromptDialog } from './PromptDialog';
|
|
8
8
|
import { iconStyle } from './icons';
|
|
9
9
|
import { theme } from './theme';
|
|
@@ -20,7 +20,7 @@ const ROW_HEIGHT = 28;
|
|
|
20
20
|
const checkboxButton = { ...iconButton, width: 12, height: 12 };
|
|
21
21
|
/** One row of the timeline: a label cell (name + actions) and, for tracks, a bar cell. */
|
|
22
22
|
export function TimelineTrackRow(props) {
|
|
23
|
-
const { row, binding, selected, onSelectNode, pxPerSecond, offsetPx, collapsed, onToggleCollapse, hidden, onToggleVisible, groupSelected, onToggleGroupSelect } = props;
|
|
23
|
+
const { row, binding, selected, onSelectNode, pxPerSecond, offsetPx, collapsed, onToggleCollapse, hidden, onToggleVisible, groupSelected, onToggleGroupSelect, } = props;
|
|
24
24
|
const [renaming, setRenaming] = useState(false);
|
|
25
25
|
const isRoot = row.node === binding.root;
|
|
26
26
|
const labelStyle = {
|
|
@@ -44,10 +44,17 @@ export function TimelineTrackRow(props) {
|
|
|
44
44
|
return (_jsxs(_Fragment, { children: [_jsxs("div", { className: "qe-hover-bg", style: { ...labelStyle, borderTop: `1px solid ${theme.border}` }, onClick: () => onSelectNode(row.node), children: [!isRoot && (_jsx("button", { className: "qe-hover", title: groupSelected ? 'Remove from group selection' : 'Select for grouping', style: { ...checkboxButton, color: groupSelected ? theme.accent : theme.textDim }, onClick: (e) => {
|
|
45
45
|
e.stopPropagation();
|
|
46
46
|
onToggleGroupSelect();
|
|
47
|
-
}, children: groupSelected ? (_jsx(CheckIcon, { style: iconStyle(12) })) : (_jsx("span", { style: {
|
|
47
|
+
}, children: groupSelected ? (_jsx(CheckIcon, { style: iconStyle(12) })) : (_jsx("span", { style: {
|
|
48
|
+
width: 10,
|
|
49
|
+
height: 10,
|
|
50
|
+
border: `1px solid currentColor`,
|
|
51
|
+
borderRadius: 2,
|
|
52
|
+
display: 'block',
|
|
53
|
+
boxSizing: 'border-box',
|
|
54
|
+
} })) })), _jsx("span", { className: "qe-hover", title: collapsed ? 'Expand' : 'Collapse', style: { color: theme.textDim, width: 12, cursor: 'pointer', display: 'inline-flex' }, onClick: (e) => {
|
|
48
55
|
e.stopPropagation();
|
|
49
56
|
onToggleCollapse?.();
|
|
50
|
-
}, children: collapsed ? _jsx(ChevronRightIcon, { style: iconStyle(12) }) : _jsx(ChevronDownIcon, { style: iconStyle(12) }) }), _jsx("span", { style: { flex: 1, overflow: 'hidden', textOverflow: 'ellipsis' }, children: row.name }), _jsx("button", { className: "qe-hover", title: "Add system to this group", style: { ...iconButton, color: theme.accent }, onClick: (e) => {
|
|
57
|
+
}, children: collapsed ? (_jsx(ChevronRightIcon, { style: iconStyle(12) })) : (_jsx(ChevronDownIcon, { style: iconStyle(12) })) }), _jsx("span", { style: { flex: 1, overflow: 'hidden', textOverflow: 'ellipsis' }, children: row.name }), _jsx("button", { className: "qe-hover", title: "Add system to this group", style: { ...iconButton, color: theme.accent }, onClick: (e) => {
|
|
51
58
|
e.stopPropagation();
|
|
52
59
|
let created;
|
|
53
60
|
binding.apply(() => {
|
|
@@ -82,7 +89,14 @@ export function TimelineTrackRow(props) {
|
|
|
82
89
|
return (_jsxs(_Fragment, { children: [_jsxs("div", { className: "qe-hover-bg", style: { ...labelStyle, opacity: hidden ? 0.5 : 1 }, onClick: () => onSelectNode(row.node), children: [!isRoot && (_jsx("button", { className: "qe-hover", title: groupSelected ? 'Remove from group selection' : 'Select for grouping', style: { ...checkboxButton, color: groupSelected ? theme.accent : theme.textDim }, onClick: (e) => {
|
|
83
90
|
e.stopPropagation();
|
|
84
91
|
onToggleGroupSelect();
|
|
85
|
-
}, children: groupSelected ? (_jsx(CheckIcon, { style: iconStyle(12) })) : (_jsx("span", { style: {
|
|
92
|
+
}, children: groupSelected ? (_jsx(CheckIcon, { style: iconStyle(12) })) : (_jsx("span", { style: {
|
|
93
|
+
width: 10,
|
|
94
|
+
height: 10,
|
|
95
|
+
border: `1px solid currentColor`,
|
|
96
|
+
borderRadius: 2,
|
|
97
|
+
display: 'block',
|
|
98
|
+
boxSizing: 'border-box',
|
|
99
|
+
} })) })), _jsx("button", { className: "qe-hover", title: hidden ? 'Show in viewport' : 'Hide in viewport', style: { ...iconButton, color: hidden ? theme.textDim : theme.accent }, onClick: (e) => {
|
|
86
100
|
e.stopPropagation();
|
|
87
101
|
onToggleVisible?.();
|
|
88
102
|
}, children: hidden ? _jsx(EyeSlashIcon, { style: iconStyle(12) }) : _jsx(EyeIcon, { style: iconStyle(12) }) }), _jsx("span", { style: { color: theme.accent, display: 'inline-flex' }, children: _jsx(SparklesIcon, { style: iconStyle(11) }) }), _jsxs("span", { style: { flex: 1, overflow: 'hidden', textOverflow: 'ellipsis' }, children: [row.name, system.onlyUsedByOther ? ' (sub)' : ''] }), !isRoot && (_jsx("button", { className: "qe-hover", title: "Rename", style: { ...iconButton, color: theme.textDim }, onClick: (e) => {
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import type { Scene } from '@babylonjs/core/scene';
|
|
2
|
+
import type { BatchedRenderer } from 'babylon.quarks';
|
|
3
|
+
import React from 'react';
|
|
4
|
+
import type { EffectBinding } from '../core/binding';
|
|
5
|
+
import type { PlaybackState } from '../core/playback';
|
|
6
|
+
export interface TransportBarProps {
|
|
7
|
+
binding: EffectBinding | null;
|
|
8
|
+
scene: Scene;
|
|
9
|
+
renderer: BatchedRenderer;
|
|
10
|
+
playbackRef: React.MutableRefObject<PlaybackState>;
|
|
11
|
+
/** The host's render loop writes time and particle count here. */
|
|
12
|
+
counterRef: React.RefObject<HTMLSpanElement>;
|
|
13
|
+
stagePlaying: boolean;
|
|
14
|
+
setStagePlaying: (playing: boolean) => void;
|
|
15
|
+
speed: number;
|
|
16
|
+
setSpeed: (speed: number) => void;
|
|
17
|
+
/** False when the focused effect is hidden. */
|
|
18
|
+
enabled: boolean;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Floating playback controls in the viewport (like Unity's Particle Effect overlay), so playing
|
|
22
|
+
* and restarting never needs the timeline open.
|
|
23
|
+
*/
|
|
24
|
+
export declare function TransportBar(props: TransportBarProps): React.ReactElement;
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { ArrowPathIcon, ForwardIcon, PauseIcon, PlayIcon } from '@heroicons/react/24/solid';
|
|
3
|
+
import { PLAYBACK_SPEEDS, restartFocusPlayback, toggleStagePlayback } from '../core/transport';
|
|
4
|
+
import { iconStyle } from './icons';
|
|
5
|
+
import { buttonStyle, theme } from './theme';
|
|
6
|
+
const barButton = {
|
|
7
|
+
...buttonStyle,
|
|
8
|
+
width: 28,
|
|
9
|
+
height: 26,
|
|
10
|
+
padding: 0,
|
|
11
|
+
display: 'inline-flex',
|
|
12
|
+
alignItems: 'center',
|
|
13
|
+
justifyContent: 'center',
|
|
14
|
+
};
|
|
15
|
+
/**
|
|
16
|
+
* Floating playback controls in the viewport (like Unity's Particle Effect overlay), so playing
|
|
17
|
+
* and restarting never needs the timeline open.
|
|
18
|
+
*/
|
|
19
|
+
export function TransportBar(props) {
|
|
20
|
+
const { binding, scene, renderer, playbackRef, counterRef, stagePlaying, setStagePlaying, speed, setSpeed } = props;
|
|
21
|
+
const enabled = props.enabled && binding !== null;
|
|
22
|
+
return (_jsxs("div", { style: {
|
|
23
|
+
display: 'flex',
|
|
24
|
+
alignItems: 'center',
|
|
25
|
+
gap: 4,
|
|
26
|
+
padding: 4,
|
|
27
|
+
background: theme.panelBg,
|
|
28
|
+
border: `1px solid ${theme.border}`,
|
|
29
|
+
borderRadius: 8,
|
|
30
|
+
fontFamily: theme.font,
|
|
31
|
+
}, children: [_jsx("button", { className: "qe-hover", style: barButton, title: stagePlaying ? 'Pause (Space)' : 'Play (Space)', disabled: !enabled, onClick: () => toggleStagePlayback(binding, scene, playbackRef.current, stagePlaying, setStagePlaying), children: stagePlaying ? _jsx(PauseIcon, { style: iconStyle(14) }) : _jsx(PlayIcon, { style: iconStyle(14) }) }), _jsx("button", { className: "qe-hover", style: barButton, title: "Step one frame", disabled: !enabled || stagePlaying, onClick: () => (playbackRef.current.stepQueued = true), children: _jsx(ForwardIcon, { style: iconStyle(14) }) }), _jsx("button", { className: "qe-hover", style: barButton, title: "Restart the focused effect", disabled: !enabled, onClick: () => binding && restartFocusPlayback(binding, renderer, scene, playbackRef.current), children: _jsx(ArrowPathIcon, { style: iconStyle(14) }) }), _jsx("select", { className: "qe-hover", style: { ...barButton, width: 'auto', padding: '0 4px' }, title: "Playback speed", value: speed, disabled: !enabled, onChange: (e) => {
|
|
32
|
+
const next = Number(e.target.value);
|
|
33
|
+
playbackRef.current.speed = next;
|
|
34
|
+
setSpeed(next);
|
|
35
|
+
}, children: PLAYBACK_SPEEDS.map((s) => (_jsxs("option", { value: s, children: ["\u00D7", s] }, s))) }), _jsx("span", { ref: counterRef, style: {
|
|
36
|
+
fontSize: 12,
|
|
37
|
+
color: theme.textDim,
|
|
38
|
+
fontVariantNumeric: 'tabular-nums',
|
|
39
|
+
padding: '0 6px',
|
|
40
|
+
minWidth: 150,
|
|
41
|
+
whiteSpace: 'nowrap',
|
|
42
|
+
} })] }));
|
|
43
|
+
}
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import React from 'react';
|
|
2
1
|
import { ScalarGenerator } from '../core/values';
|
|
3
2
|
/**
|
|
4
3
|
* Unity-like value field: Constant | Random Between Two Constants | Curve,
|
|
@@ -12,4 +11,4 @@ export declare function ValueField(props: {
|
|
|
12
11
|
onChange: (generator: ScalarGenerator) => void;
|
|
13
12
|
min?: number;
|
|
14
13
|
curveMax?: number;
|
|
15
|
-
}):
|
|
14
|
+
}): import("react").JSX.Element;
|
|
@@ -1,12 +1,11 @@
|
|
|
1
1
|
import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
-
import { ApplyCollision, ApplyForce, ChangeEmitDirection, ColorBySpeed, ConstantValue, ForceOverLife, FrameOverLife, Gradient, InheritVelocity, IntervalValue, LimitSpeedOverLife, Noise, OrbitOverLife, RotationBySpeed, RotationOverLife, SizeBySpeed, SpeedOverLife, TurbulenceField, Vector3, VelocityOverLife, WidthOverLength, } from 'babylon.quarks';
|
|
3
|
-
import {
|
|
4
|
-
import { DEFAULT_GRADIENT_STOPS, buildGradient, findBehavior, readGradientStops } from '../core/colors';
|
|
2
|
+
import { ApplyCollision, ApplyForce, ChangeEmitDirection, ColorBySpeed, ConstantValue, ForceOverLife, FrameOverLife, getPhysicsResolver, Gradient, InheritVelocity, IntervalValue, LimitSpeedOverLife, Noise, OrbitOverLife, RotationBySpeed, RotationOverLife, SizeBySpeed, SpeedOverLife, TurbulenceField, Vector3, VelocityOverLife, WidthOverLength, } from 'babylon.quarks';
|
|
3
|
+
import { buildGradient, DEFAULT_GRADIENT_STOPS, findBehavior, readGradientStops } from '../core/colors';
|
|
5
4
|
import { buildCurve, buildScalar, readPieces, readScalar } from '../core/values';
|
|
6
|
-
import { GradientEditor } from './GradientEditor';
|
|
7
5
|
import { CurveEditor } from './CurveEditor';
|
|
8
|
-
import { ModuleSection } from './ModuleSection';
|
|
9
6
|
import { NumberField, Row, SelectField } from './fields';
|
|
7
|
+
import { GradientEditor } from './GradientEditor';
|
|
8
|
+
import { ModuleSection } from './ModuleSection';
|
|
10
9
|
import { ValueField } from './ValueField';
|
|
11
10
|
function removeBehaviorOfType(behaviors, type) {
|
|
12
11
|
for (let i = behaviors.length - 1; i >= 0; i--) {
|
|
@@ -71,17 +70,18 @@ export function EmitDirectionModule({ binding }) {
|
|
|
71
70
|
return (_jsx(BehaviorModule, { binding: binding, title: "Randomize Direction", type: "ChangeEmitDirection", create: () => new ChangeEmitDirection(new IntervalValue(0, Math.PI / 6)), children: (behavior) => (_jsx(ValueField, { label: "Angle (rad)", generator: behavior.angle, min: 0, curveMax: Math.PI, onChange: (g) => binding.apply(() => (behavior.angle = g)) })) }));
|
|
72
71
|
}
|
|
73
72
|
export function CollisionModule({ binding }) {
|
|
74
|
-
//
|
|
75
|
-
//
|
|
76
|
-
|
|
77
|
-
return (_jsx(BehaviorModule, { binding: binding, title: "Collision", type: "ApplyCollision", create: () => new ApplyCollision(ensureGroundResolver(), 0.5), children: (behavior) => (_jsxs(_Fragment, { children: [_jsx(Row, { label: "Bounce", children: _jsx(NumberField, { value: behavior.bounce, min: 0, step: 0.05, onChange: (v) => binding.apply(() => (behavior.bounce = v)) }) }), _jsx(Row, { label: "Floor Y", children: _jsx(NumberField, { value: resolver.y, step: 0.1, onChange: (v) => binding.apply(() => (resolver.y = v)) }) }), _jsx("div", { style: { fontSize: 11, opacity: 0.6, marginTop: 4 }, children: "Collides against a ground plane. Bounce is saved with the effect; Floor Y is an editor preview aid (a host can register its own colliders)." })] })) }));
|
|
73
|
+
// Like Unity: Collision stores bounce only. Colliders are host-provided via
|
|
74
|
+
// setPhysicsResolver — the editor never invents a ground plane.
|
|
75
|
+
return (_jsx(BehaviorModule, { binding: binding, title: "Collision", type: "ApplyCollision", create: () => new ApplyCollision(getPhysicsResolver(), 0.5), children: (behavior) => (_jsxs(_Fragment, { children: [_jsx(Row, { label: "Bounce", children: _jsx(NumberField, { value: behavior.bounce, min: 0, step: 0.05, onChange: (v) => binding.apply(() => (behavior.bounce = v)) }) }), _jsx("div", { style: { fontSize: 11, opacity: 0.6, marginTop: 4 }, children: "Bounce is saved with the effect. Colliders come from the host (setPhysicsResolver) \u2014 without one, Collision is inert." })] })) }));
|
|
78
76
|
}
|
|
79
77
|
/** Shared speed-range rows for the "by Speed" trio. */
|
|
80
78
|
function SpeedRangeRows({ binding, behavior }) {
|
|
81
79
|
return (_jsx(Row, { label: "Speed range", children: _jsxs("div", { style: { display: 'flex', gap: 6 }, children: [_jsx(NumberField, { value: behavior.speedRange.a, min: 0, onChange: (v) => binding.apply(() => (behavior.speedRange = new IntervalValue(v, behavior.speedRange.b))) }), _jsx(NumberField, { value: behavior.speedRange.b, min: 0, onChange: (v) => binding.apply(() => (behavior.speedRange = new IntervalValue(behavior.speedRange.a, v))) })] }) }));
|
|
82
80
|
}
|
|
83
81
|
export function ColorBySpeedModule({ binding }) {
|
|
84
|
-
return (_jsx(BehaviorModule, { binding: binding, title: "Color by Speed", type: "ColorBySpeed", create: () => new ColorBySpeed(buildGradient(DEFAULT_GRADIENT_STOPS), new IntervalValue(0, 5)), children: (behavior) => (_jsxs(_Fragment, { children: [_jsx("div", { style: { marginTop: 6 }, children: _jsx(GradientEditor, { stops: behavior.color instanceof Gradient
|
|
82
|
+
return (_jsx(BehaviorModule, { binding: binding, title: "Color by Speed", type: "ColorBySpeed", create: () => new ColorBySpeed(buildGradient(DEFAULT_GRADIENT_STOPS), new IntervalValue(0, 5)), children: (behavior) => (_jsxs(_Fragment, { children: [_jsx("div", { style: { marginTop: 6 }, children: _jsx(GradientEditor, { stops: behavior.color instanceof Gradient
|
|
83
|
+
? readGradientStops(behavior.color)
|
|
84
|
+
: DEFAULT_GRADIENT_STOPS, onChange: (stops) => binding.apply(() => (behavior.color = buildGradient(stops))) }) }), _jsx(SpeedRangeRows, { binding: binding, behavior: behavior })] })) }));
|
|
85
85
|
}
|
|
86
86
|
export function SizeBySpeedModule({ binding }) {
|
|
87
87
|
return (_jsx(BehaviorModule, { binding: binding, title: "Size by Speed", type: "SizeBySpeed", create: () => new SizeBySpeed(buildScalar({ mode: 'curve', value: 1, min: 0, max: 1, curve: [0.5, 0.8, 1.2, 1.5] }), new IntervalValue(0, 5)), children: (behavior) => (_jsxs(_Fragment, { children: [_jsx("div", { style: { marginTop: 6 }, children: _jsx(CurveEditor, { pieces: readPieces(behavior.size), maxValue: 2, onChange: (pieces) => binding.apply(() => (behavior.size = buildCurve(pieces))) }) }), _jsx(SpeedRangeRows, { binding: binding, behavior: behavior })] })) }));
|
|
@@ -106,7 +106,13 @@ export function TextureSheetModule({ binding }) {
|
|
|
106
106
|
const startIdx = Math.min(Math.max(0, Math.round(readScalar(system.startTileIndex).value)), tiles - 1);
|
|
107
107
|
const startCol = startIdx % u;
|
|
108
108
|
const startRow = Math.floor(startIdx / u);
|
|
109
|
-
return (_jsxs(ModuleSection, { title: "Texture Sheet Animation", defaultOpen: false, children: [textureUrl && (_jsxs("div", { style: { marginTop: 6 }, children: [_jsxs("div", { style: {
|
|
109
|
+
return (_jsxs(ModuleSection, { title: "Texture Sheet Animation", defaultOpen: false, children: [textureUrl && (_jsxs("div", { style: { marginTop: 6 }, children: [_jsxs("div", { style: {
|
|
110
|
+
position: 'relative',
|
|
111
|
+
width: 218,
|
|
112
|
+
border: '1px solid #2b3761',
|
|
113
|
+
borderRadius: 6,
|
|
114
|
+
overflow: 'hidden',
|
|
115
|
+
}, children: [_jsx("img", { src: textureUrl, alt: "texture atlas", style: { width: '100%', display: 'block' } }), _jsx("div", { style: {
|
|
110
116
|
position: 'absolute',
|
|
111
117
|
inset: 0,
|
|
112
118
|
pointerEvents: 'none',
|
|
@@ -133,7 +139,13 @@ export function TextureSheetModule({ binding }) {
|
|
|
133
139
|
}, children: startIdx }) })] }), _jsxs("div", { style: { fontSize: 11, color: '#b7c6ea', marginTop: 3 }, children: [u, " \u00D7 ", v, " = ", tiles, " tiles; frame indices 0\u2013", tiles - 1, "; start tile", ' ', _jsx("span", { style: { color: '#ffce6b', fontWeight: 600 }, children: startIdx })] })] })), _jsx(Row, { label: "Tiles U", children: _jsx(NumberField, { value: system.uTileCount, min: 1, step: 1, onChange: (v) => binding.apply((s) => (s.uTileCount = Math.round(v))) }) }), _jsx(Row, { label: "Tiles V", children: _jsx(NumberField, { value: system.vTileCount, min: 1, step: 1, onChange: (v) => binding.apply((s) => (s.vTileCount = Math.round(v))) }) }), _jsx(Row, { label: "Blend tiles", children: _jsx("input", { type: "checkbox", className: "qe-hover", checked: system.blendTiles, style: { justifySelf: 'start', width: 15, height: 15, accentColor: '#78a5ff', cursor: 'pointer' }, onChange: (e) => binding.apply((s) => (s.blendTiles = e.target.checked)) }) }), _jsx(Row, { label: "Start tile", children: _jsx(NumberField, { value: readScalar(system.startTileIndex).value, min: 0, step: 1, onChange: (v) => binding.apply((s) => (s.startTileIndex = new ConstantValue(Math.round(v)))) }) }), _jsx(Row, { label: "Animate frames", children: _jsx("input", { type: "checkbox", className: "qe-hover", checked: !!frameBehavior, style: { justifySelf: 'start', width: 15, height: 15, accentColor: '#78a5ff', cursor: 'pointer' }, onChange: (e) => binding.apply((s) => {
|
|
134
140
|
removeBehaviorOfType(s.behaviors, 'FrameOverLife');
|
|
135
141
|
if (e.target.checked) {
|
|
136
|
-
s.addBehavior(new FrameOverLife(buildScalar({
|
|
142
|
+
s.addBehavior(new FrameOverLife(buildScalar({
|
|
143
|
+
mode: 'curve',
|
|
144
|
+
value: 0,
|
|
145
|
+
min: 0,
|
|
146
|
+
max: tiles - 1,
|
|
147
|
+
curve: [0, (tiles - 1) / 3, (2 * (tiles - 1)) / 3, tiles - 1],
|
|
148
|
+
})));
|
|
137
149
|
}
|
|
138
150
|
}) }) }), frameBehavior && (_jsx("div", { style: { marginTop: 6 }, children: _jsx(CurveEditor, { pieces: readPieces(frameBehavior.frame), maxValue: Math.max(1, tiles - 1), onChange: (pieces) => binding.apply(() => (frameBehavior.frame = buildCurve(pieces))) }) }))] }));
|
|
139
151
|
}
|
package/dist/react/index.d.ts
CHANGED
|
@@ -1,24 +1,38 @@
|
|
|
1
|
+
export { AssetsPanel } from './AssetsPanel';
|
|
2
|
+
export type { AssetsPanelProps } from './AssetsPanel';
|
|
3
|
+
export { CollisionModule, ColorBySpeedModule, EmitDirectionModule, ForceOverLifeModule, GravityModule, LimitSpeedOverLifeModule, NoiseModule, OrbitOverLifeModule, RotationBySpeedModule, RotationOverLifeModule, SizeBySpeedModule, SpeedOverLifeModule, TextureSheetModule, TurbulenceModule, WidthOverTrailModule, } from './behaviorModules';
|
|
4
|
+
export { ChoiceDialog } from './ChoiceDialog';
|
|
5
|
+
export type { ChoiceDialogAction, ChoiceDialogProps } from './ChoiceDialog';
|
|
6
|
+
export { ContextMenu } from './ContextMenu';
|
|
7
|
+
export type { ContextMenuItem, ContextMenuProps } from './ContextMenu';
|
|
8
|
+
export { CurveEditor } from './CurveEditor';
|
|
9
|
+
export { EditorWorkspace, QuarksEditorWorkspace } from './EditorWorkspace';
|
|
10
|
+
export type { EditorWorkspaceProps } from './EditorWorkspace';
|
|
1
11
|
export { EffectEditor } from './EffectEditor';
|
|
2
12
|
export type { EffectEditorProps } from './EffectEditor';
|
|
3
|
-
export {
|
|
4
|
-
export type {
|
|
13
|
+
export { EffectEditorHost, QuarksEffectEditor } from './EffectEditorHost';
|
|
14
|
+
export type { EffectEditorHostHandle, EffectEditorHostProps } from './EffectEditorHost';
|
|
15
|
+
export { EffectTreeView } from './EffectTreeView';
|
|
16
|
+
export type { EffectTreeViewProps } from './EffectTreeView';
|
|
17
|
+
export { CheckboxField, NumberField, Row, SelectField } from './fields';
|
|
18
|
+
export { GradientEditor } from './GradientEditor';
|
|
19
|
+
export { MessageDialog } from './MessageDialog';
|
|
20
|
+
export type { MessageDialogProps } from './MessageDialog';
|
|
21
|
+
export { ColorOverLifeModule, EmissionModule, MainModule, RendererModule, ShapeModule, SizeOverLifeModule, } from './modules';
|
|
22
|
+
export type { GeometryData, GeometryOption, TextureOption } from './modules';
|
|
23
|
+
export { ModuleSection } from './ModuleSection';
|
|
24
|
+
export { ProjectsPage } from './ProjectsPage';
|
|
25
|
+
export type { ProjectsPageProps } from './ProjectsPage';
|
|
26
|
+
export { PromptDialog } from './PromptDialog';
|
|
27
|
+
export type { PromptDialogProps } from './PromptDialog';
|
|
28
|
+
export { ScenePanel } from './ScenePanel';
|
|
29
|
+
export type { ScenePanelProps } from './ScenePanel';
|
|
5
30
|
export { SubEmittersModule } from './SubEmittersModule';
|
|
31
|
+
export { buttonStyle, inputStyle, labelStyle, rowStyle, theme } from './theme';
|
|
6
32
|
export { TimelinePanel } from './TimelinePanel';
|
|
7
|
-
export type {
|
|
33
|
+
export type { PlaybackState, TimelinePanelProps } from './TimelinePanel';
|
|
8
34
|
export { TimelineTrackRow } from './TimelineTrackRow';
|
|
9
35
|
export type { TimelineTrackRowProps } from './TimelineTrackRow';
|
|
10
|
-
export {
|
|
11
|
-
export {
|
|
12
|
-
export type { PromptDialogProps } from './PromptDialog';
|
|
13
|
-
export { CurveEditor } from './CurveEditor';
|
|
14
|
-
export { GradientEditor } from './GradientEditor';
|
|
36
|
+
export { TransportBar } from './TransportBar';
|
|
37
|
+
export type { TransportBarProps } from './TransportBar';
|
|
15
38
|
export { ValueField } from './ValueField';
|
|
16
|
-
export { Row, NumberField, CheckboxField, SelectField } from './fields';
|
|
17
|
-
export { MainModule, EmissionModule, ShapeModule, SizeOverLifeModule, ColorOverLifeModule, RendererModule, } from './modules';
|
|
18
|
-
export { theme, inputStyle, rowStyle, labelStyle, buttonStyle } from './theme';
|
|
19
|
-
export { MessageDialog } from './MessageDialog';
|
|
20
|
-
export type { MessageDialogProps } from './MessageDialog';
|
|
21
|
-
export { GalleryPanel } from './GalleryPanel';
|
|
22
|
-
export type { GalleryPanelProps } from './GalleryPanel';
|
|
23
|
-
export { EffectEditorHost, QuarksEffectEditor } from './EffectEditorHost';
|
|
24
|
-
export type { EffectEditorHostProps, EffectEditorHostHandle } from './EffectEditorHost';
|
package/dist/react/index.js
CHANGED
|
@@ -1,16 +1,23 @@
|
|
|
1
|
+
export { AssetsPanel } from './AssetsPanel';
|
|
2
|
+
export { CollisionModule, ColorBySpeedModule, EmitDirectionModule, ForceOverLifeModule, GravityModule, LimitSpeedOverLifeModule, NoiseModule, OrbitOverLifeModule, RotationBySpeedModule, RotationOverLifeModule, SizeBySpeedModule, SpeedOverLifeModule, TextureSheetModule, TurbulenceModule, WidthOverTrailModule, } from './behaviorModules';
|
|
3
|
+
export { ChoiceDialog } from './ChoiceDialog';
|
|
4
|
+
export { ContextMenu } from './ContextMenu';
|
|
5
|
+
export { CurveEditor } from './CurveEditor';
|
|
6
|
+
export { EditorWorkspace, QuarksEditorWorkspace } from './EditorWorkspace';
|
|
1
7
|
export { EffectEditor } from './EffectEditor';
|
|
2
|
-
export {
|
|
8
|
+
export { EffectEditorHost, QuarksEffectEditor } from './EffectEditorHost';
|
|
9
|
+
export { EffectTreeView } from './EffectTreeView';
|
|
10
|
+
export { CheckboxField, NumberField, Row, SelectField } from './fields';
|
|
11
|
+
export { GradientEditor } from './GradientEditor';
|
|
12
|
+
export { MessageDialog } from './MessageDialog';
|
|
13
|
+
export { ColorOverLifeModule, EmissionModule, MainModule, RendererModule, ShapeModule, SizeOverLifeModule, } from './modules';
|
|
14
|
+
export { ModuleSection } from './ModuleSection';
|
|
15
|
+
export { ProjectsPage } from './ProjectsPage';
|
|
16
|
+
export { PromptDialog } from './PromptDialog';
|
|
17
|
+
export { ScenePanel } from './ScenePanel';
|
|
3
18
|
export { SubEmittersModule } from './SubEmittersModule';
|
|
19
|
+
export { buttonStyle, inputStyle, labelStyle, rowStyle, theme } from './theme';
|
|
4
20
|
export { TimelinePanel } from './TimelinePanel';
|
|
5
21
|
export { TimelineTrackRow } from './TimelineTrackRow';
|
|
6
|
-
export {
|
|
7
|
-
export { PromptDialog } from './PromptDialog';
|
|
8
|
-
export { CurveEditor } from './CurveEditor';
|
|
9
|
-
export { GradientEditor } from './GradientEditor';
|
|
22
|
+
export { TransportBar } from './TransportBar';
|
|
10
23
|
export { ValueField } from './ValueField';
|
|
11
|
-
export { Row, NumberField, CheckboxField, SelectField } from './fields';
|
|
12
|
-
export { MainModule, EmissionModule, ShapeModule, SizeOverLifeModule, ColorOverLifeModule, RendererModule, } from './modules';
|
|
13
|
-
export { theme, inputStyle, rowStyle, labelStyle, buttonStyle } from './theme';
|
|
14
|
-
export { MessageDialog } from './MessageDialog';
|
|
15
|
-
export { GalleryPanel } from './GalleryPanel';
|
|
16
|
-
export { EffectEditorHost, QuarksEffectEditor } from './EffectEditorHost';
|
|
@@ -117,8 +117,7 @@ const INSPECTOR_HINTS = {
|
|
|
117
117
|
'turbulence.strength': 'Per-axis multiplier for turbulent velocity.',
|
|
118
118
|
'Time scale': 'How fast the turbulence field evolves over time (per axis).',
|
|
119
119
|
'Angle (rad)': 'Maximum random deflection from the base emit direction, in radians.',
|
|
120
|
-
Bounce: 'Energy retained after
|
|
121
|
-
'Floor Y': 'World-space Y height of the preview ground plane used for collision.',
|
|
120
|
+
Bounce: 'Energy retained after a collision (0 = stick, 1 = full bounce). Colliders are host-provided.',
|
|
122
121
|
'Speed range': 'Particle speed range (min, max) that maps to the color/size/rotation curve.',
|
|
123
122
|
'Orbit speed': 'Angular speed of orbit around the configured axis over lifetime.',
|
|
124
123
|
'rotationOverLife.velocity': 'Angular velocity applied over normalized lifetime (rad/s).',
|