babylon.quarks-editor 0.26.0 → 0.28.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.
Files changed (211) hide show
  1. package/CHANGELOG.md +134 -0
  2. package/README.md +69 -9
  3. package/dist/core/assetDragSession.d.ts +1 -1
  4. package/dist/core/assetTree.d.ts +6 -1
  5. package/dist/core/assets.d.ts +7 -0
  6. package/dist/core/assets.js +11 -7
  7. package/dist/core/binding.d.ts +11 -2
  8. package/dist/core/binding.js +9 -1
  9. package/dist/core/collision.d.ts +4 -0
  10. package/dist/core/collision.js +4 -0
  11. package/dist/core/colors.d.ts +16 -0
  12. package/dist/core/colors.js +8 -0
  13. package/dist/core/defaultEffect.d.ts +5 -4
  14. package/dist/core/defaultEffect.js +4 -4
  15. package/dist/core/editorScene.d.ts +1 -1
  16. package/dist/core/editorSession.d.ts +229 -0
  17. package/dist/core/editorSession.js +983 -0
  18. package/dist/core/effectTree.d.ts +6 -1
  19. package/dist/core/effectTree.js +13 -88
  20. package/dist/core/emitterShapeWireframe.d.ts +2 -2
  21. package/dist/core/emitterShapeWireframe.js +45 -13
  22. package/dist/core/galleryDropMarker.d.ts +2 -2
  23. package/dist/core/galleryDropMarker.js +6 -6
  24. package/dist/core/galleryLayout.d.ts +3 -3
  25. package/dist/core/galleryLayout.js +1 -1
  26. package/dist/core/galleryPlayback.d.ts +1 -1
  27. package/dist/core/galleryPlayback.js +2 -1
  28. package/dist/core/galleryScene.d.ts +4 -4
  29. package/dist/core/galleryScene.js +3 -3
  30. package/dist/core/gallerySelectionMarker.d.ts +4 -4
  31. package/dist/core/gallerySelectionMarker.js +5 -5
  32. package/dist/core/groups.d.ts +1 -1
  33. package/dist/core/groups.js +1 -1
  34. package/dist/core/history.d.ts +7 -1
  35. package/dist/core/history.js +4 -0
  36. package/dist/core/indexedDbProjectStore.d.ts +14 -1
  37. package/dist/core/indexedDbProjectStore.js +13 -0
  38. package/dist/core/lineShaders.d.ts +2 -2
  39. package/dist/core/lineShaders.js +2 -2
  40. package/dist/core/loadEffect.d.ts +2 -2
  41. package/dist/core/loadEffect.js +1 -1
  42. package/dist/core/material.d.ts +12 -2
  43. package/dist/core/pickAssetFiles.js +1 -1
  44. package/dist/core/playback.d.ts +6 -0
  45. package/dist/core/projectStore.d.ts +26 -0
  46. package/dist/core/projectStore.js +1 -0
  47. package/dist/core/sceneEntries.d.ts +7 -4
  48. package/dist/core/sceneEntries.js +2 -2
  49. package/dist/core/scrub.d.ts +2 -2
  50. package/dist/core/scrub.js +2 -2
  51. package/dist/core/shapes.d.ts +25 -1
  52. package/dist/core/shapes.js +5 -0
  53. package/dist/core/systems.d.ts +4 -2
  54. package/dist/core/systems.js +3 -1
  55. package/dist/core/textureExport.d.ts +1 -1
  56. package/dist/core/timeline.d.ts +25 -5
  57. package/dist/core/transport.d.ts +3 -3
  58. package/dist/core/transport.js +2 -2
  59. package/dist/core/values.d.ts +21 -4
  60. package/dist/core/values.js +5 -0
  61. package/dist/core/viewportPicker.d.ts +4 -4
  62. package/dist/core/viewportPicker.js +8 -7
  63. package/dist/index.d.ts +25 -21
  64. package/dist/index.js +12 -12
  65. package/dist/react/AssetsPanel.d.ts +9 -2
  66. package/dist/react/AssetsPanel.js +6 -6
  67. package/dist/react/ChoiceDialog.d.ts +7 -0
  68. package/dist/react/ChoiceDialog.js +1 -1
  69. package/dist/react/ContextMenu.d.ts +10 -1
  70. package/dist/react/ContextMenu.js +1 -1
  71. package/dist/react/CurveEditor.d.ts +1 -1
  72. package/dist/react/CurveEditor.js +2 -2
  73. package/dist/react/EditorWorkspace.d.ts +9 -2
  74. package/dist/react/EditorWorkspace.js +10 -7
  75. package/dist/react/EffectEditor.d.ts +11 -5
  76. package/dist/react/EffectEditor.js +7 -7
  77. package/dist/react/EffectEditorHost.d.ts +33 -29
  78. package/dist/react/EffectEditorHost.js +247 -1674
  79. package/dist/react/EffectTreeView.d.ts +4 -1
  80. package/dist/react/EffectTreeView.js +3 -3
  81. package/dist/react/GradientEditor.d.ts +1 -1
  82. package/dist/react/GradientEditor.js +3 -3
  83. package/dist/react/InspectorInfoIcon.js +3 -3
  84. package/dist/react/InspectorLabel.js +3 -3
  85. package/dist/react/MessageDialog.d.ts +5 -0
  86. package/dist/react/MessageDialog.js +1 -1
  87. package/dist/react/ModuleSection.d.ts +10 -0
  88. package/dist/react/ModuleSection.js +8 -5
  89. package/dist/react/ObjectModule.d.ts +1 -1
  90. package/dist/react/ObjectModule.js +4 -4
  91. package/dist/react/ProjectsPage.d.ts +7 -1
  92. package/dist/react/ProjectsPage.js +33 -17
  93. package/dist/react/PromptDialog.d.ts +7 -0
  94. package/dist/react/PromptDialog.js +1 -1
  95. package/dist/react/ScenePanel.d.ts +9 -2
  96. package/dist/react/ScenePanel.js +12 -10
  97. package/dist/react/SubEmittersModule.d.ts +1 -1
  98. package/dist/react/SubEmittersModule.js +5 -5
  99. package/dist/react/TextureSelect.d.ts +24 -0
  100. package/dist/react/TextureSelect.js +74 -0
  101. package/dist/react/TextureUVField.d.ts +14 -0
  102. package/dist/react/TextureUVField.js +23 -0
  103. package/dist/react/TimelinePanel.d.ts +20 -7
  104. package/dist/react/TimelinePanel.js +21 -15
  105. package/dist/react/TimelineTrackRow.d.ts +13 -3
  106. package/dist/react/TimelineTrackRow.js +6 -6
  107. package/dist/react/TransportBar.d.ts +13 -4
  108. package/dist/react/TransportBar.js +3 -3
  109. package/dist/react/ValueField.d.ts +32 -5
  110. package/dist/react/ValueField.js +22 -11
  111. package/dist/react/behaviorModules.d.ts +19 -6
  112. package/dist/react/behaviorModules.js +68 -17
  113. package/dist/react/fields.d.ts +9 -0
  114. package/dist/react/fields.js +6 -3
  115. package/dist/react/host/BottomDocks.d.ts +36 -0
  116. package/dist/react/host/BottomDocks.js +63 -0
  117. package/dist/react/host/HostDialogs.d.ts +50 -0
  118. package/dist/react/host/HostDialogs.js +113 -0
  119. package/dist/react/host/InspectorSidebar.d.ts +32 -0
  120. package/dist/react/host/InspectorSidebar.js +59 -0
  121. package/dist/react/host/SceneSidebar.d.ts +53 -0
  122. package/dist/react/host/SceneSidebar.js +62 -0
  123. package/dist/react/host/ViewportPane.d.ts +56 -0
  124. package/dist/react/host/ViewportPane.js +91 -0
  125. package/dist/react/host/hostHooks.d.ts +44 -0
  126. package/dist/react/host/hostHooks.js +164 -0
  127. package/dist/react/host/hostStyles.d.ts +21 -0
  128. package/dist/react/host/hostStyles.js +57 -0
  129. package/dist/react/index.d.ts +42 -38
  130. package/dist/react/index.js +25 -23
  131. package/dist/react/inspectorHints.js +31 -0
  132. package/dist/react/modules.d.ts +19 -6
  133. package/dist/react/modules.js +134 -117
  134. package/dist/react/theme.d.ts +15 -0
  135. package/dist/react/theme.js +15 -0
  136. package/dist/session.d.ts +9 -0
  137. package/dist/session.js +8 -0
  138. package/package.json +18 -11
  139. package/src/core/assetDragSession.ts +1 -1
  140. package/src/core/assetTree.ts +15 -2
  141. package/src/core/assets.ts +25 -10
  142. package/src/core/binding.ts +12 -3
  143. package/src/core/collision.ts +4 -0
  144. package/src/core/colors.ts +21 -1
  145. package/src/core/defaultEffect.ts +8 -7
  146. package/src/core/editorScene.ts +1 -1
  147. package/src/core/editorSession.ts +1299 -0
  148. package/src/core/effectTree.ts +18 -101
  149. package/src/core/emitterShapeWireframe.ts +48 -16
  150. package/src/core/galleryDropMarker.ts +8 -8
  151. package/src/core/galleryLayout.ts +4 -4
  152. package/src/core/galleryPlayback.ts +3 -2
  153. package/src/core/galleryScene.ts +5 -5
  154. package/src/core/gallerySelectionMarker.ts +7 -7
  155. package/src/core/groups.ts +1 -1
  156. package/src/core/history.ts +7 -1
  157. package/src/core/indexedDbProjectStore.ts +14 -1
  158. package/src/core/lineShaders.ts +2 -2
  159. package/src/core/loadEffect.ts +4 -4
  160. package/src/core/material.ts +14 -4
  161. package/src/core/pickAssetFiles.ts +2 -2
  162. package/src/core/playback.ts +6 -0
  163. package/src/core/projectStore.ts +26 -0
  164. package/src/core/sceneEntries.ts +8 -5
  165. package/src/core/scrub.ts +3 -3
  166. package/src/core/shapes.ts +29 -2
  167. package/src/core/systems.ts +11 -4
  168. package/src/core/textureExport.ts +1 -1
  169. package/src/core/timeline.ts +43 -18
  170. package/src/core/transport.ts +4 -4
  171. package/src/core/values.ts +20 -4
  172. package/src/core/viewportPicker.ts +12 -11
  173. package/src/index.ts +25 -21
  174. package/src/react/AssetsPanel.tsx +13 -6
  175. package/src/react/ChoiceDialog.tsx +8 -1
  176. package/src/react/ContextMenu.tsx +11 -2
  177. package/src/react/CurveEditor.tsx +2 -2
  178. package/src/react/EditorWorkspace.tsx +16 -10
  179. package/src/react/EffectEditor.tsx +17 -9
  180. package/src/react/EffectEditorHost.tsx +415 -2354
  181. package/src/react/EffectTreeView.tsx +7 -4
  182. package/src/react/GradientEditor.tsx +3 -3
  183. package/src/react/InspectorInfoIcon.tsx +3 -3
  184. package/src/react/InspectorLabel.tsx +3 -3
  185. package/src/react/MessageDialog.tsx +6 -1
  186. package/src/react/ModuleSection.tsx +15 -4
  187. package/src/react/ObjectModule.tsx +5 -5
  188. package/src/react/ProjectsPage.tsx +44 -17
  189. package/src/react/PromptDialog.tsx +8 -1
  190. package/src/react/ScenePanel.tsx +21 -12
  191. package/src/react/SubEmittersModule.tsx +6 -6
  192. package/src/react/TextureSelect.tsx +118 -0
  193. package/src/react/TextureUVField.tsx +62 -0
  194. package/src/react/TimelinePanel.tsx +40 -21
  195. package/src/react/TimelineTrackRow.tsx +19 -9
  196. package/src/react/TransportBar.tsx +16 -7
  197. package/src/react/ValueField.tsx +60 -16
  198. package/src/react/behaviorModules.tsx +240 -55
  199. package/src/react/fields.tsx +22 -4
  200. package/src/react/host/BottomDocks.tsx +178 -0
  201. package/src/react/host/HostDialogs.tsx +228 -0
  202. package/src/react/host/InspectorSidebar.tsx +147 -0
  203. package/src/react/host/SceneSidebar.tsx +227 -0
  204. package/src/react/host/ViewportPane.tsx +300 -0
  205. package/src/react/host/hostHooks.ts +198 -0
  206. package/src/react/host/hostStyles.ts +65 -0
  207. package/src/react/index.ts +43 -38
  208. package/src/react/inspectorHints.ts +40 -0
  209. package/src/react/modules.tsx +440 -170
  210. package/src/react/theme.ts +15 -0
  211. package/src/session.ts +17 -0
@@ -0,0 +1,198 @@
1
+ import {Viewport} from '@babylonjs/core/Maths/math.viewport.js';
2
+ import type {TransformNode} from '@babylonjs/core/Meshes/transformNode.js';
3
+ import {useEffect, useRef, useState} from 'react';
4
+ import type {EditorSession} from '../../core/editorSession.js';
5
+ import {notifyTransformChanged} from '../../core/transformStore.js';
6
+ import {DRAWER_HEIGHT} from './hostStyles.js';
7
+ import type {GizmoMode} from './ViewportPane.js';
8
+
9
+ /** True for a field that takes typed text, where editor shortcuts stay out of the way. */
10
+ export function isTextInput(target: EventTarget | null): boolean {
11
+ const el = target as HTMLElement | null;
12
+ return !!el && (el.isContentEditable || ['INPUT', 'TEXTAREA', 'SELECT'].includes(el.tagName));
13
+ }
14
+
15
+ /**
16
+ * Inspector value controls (numbers, checkboxes, selects): Ctrl+Z there means the effect's undo,
17
+ * not the browser's per-field text undo. Free-text inputs (names, filters) keep the native one.
18
+ */
19
+ export function isInspectorValueControl(target: EventTarget | null): boolean {
20
+ const el = target as HTMLElement | null;
21
+ if (!el) return false;
22
+ if (el.tagName === 'SELECT') return true;
23
+ return el.tagName === 'INPUT' && ['number', 'checkbox', 'range', 'color'].includes((el as HTMLInputElement).type);
24
+ }
25
+
26
+ /** What the editor's keyboard shortcuts do. */
27
+ export interface HostShortcuts {
28
+ /** Ctrl+S: save the scene, or ask about the open prefab. */
29
+ save(): void;
30
+ /** Ctrl+Space: open or close the Assets drawer. */
31
+ toggleAssets(): void;
32
+ /** Space: play or pause the stage. */
33
+ togglePlayback(): void;
34
+ /** Escape: close the floating Assets drawer. */
35
+ closeDrawer(): void;
36
+ /** Ctrl+Z / Ctrl+Y / Ctrl+Shift+Z. */
37
+ historyStep(redo: boolean): void;
38
+ /** Delete: remove the focused effect; returns whether it did. */
39
+ deleteFocused(): boolean;
40
+ }
41
+
42
+ /** Handles a keydown on the editor's window; exported for tests. */
43
+ export function handleHostShortcut(e: KeyboardEvent, shortcuts: HostShortcuts): void {
44
+ const key = e.key.toLowerCase();
45
+ const command = e.ctrlKey || e.metaKey;
46
+ if (command && key === 's') {
47
+ e.preventDefault();
48
+ shortcuts.save();
49
+ return;
50
+ }
51
+ if (e.code === 'Space' && command) {
52
+ e.preventDefault();
53
+ shortcuts.toggleAssets();
54
+ return;
55
+ }
56
+ const target = e.target as HTMLElement | null;
57
+ if (e.code === 'Space' && !isTextInput(target) && target?.tagName !== 'BUTTON') {
58
+ e.preventDefault();
59
+ shortcuts.togglePlayback();
60
+ return;
61
+ }
62
+ if (e.key === 'Escape') {
63
+ shortcuts.closeDrawer();
64
+ }
65
+ if (command && (key === 'z' || key === 'y')) {
66
+ if (isTextInput(e.target) && !isInspectorValueControl(e.target)) {
67
+ return;
68
+ }
69
+ e.preventDefault();
70
+ // Leave the field first so it shows the restored value instead of its draft text.
71
+ (e.target as HTMLElement | null)?.blur?.();
72
+ shortcuts.historyStep(key === 'y' || e.shiftKey);
73
+ return;
74
+ }
75
+ if (e.key === 'Delete' && !isTextInput(e.target) && shortcuts.deleteFocused()) {
76
+ e.preventDefault();
77
+ }
78
+ }
79
+
80
+ /** Installs the editor's keyboard shortcuts on the window; the latest `shortcuts` are always used. */
81
+ export function useHostShortcuts(shortcuts: HostShortcuts): void {
82
+ const ref = useRef(shortcuts);
83
+ ref.current = shortcuts;
84
+ useEffect(() => {
85
+ const onKey = (e: KeyboardEvent) => handleHostShortcut(e, ref.current);
86
+ window.addEventListener('keydown', onKey);
87
+ return () => window.removeEventListener('keydown', onKey);
88
+ }, []);
89
+ }
90
+
91
+ /**
92
+ * Puts the stage gizmo in `mode` and attaches it to `target`, leaving it where it is while
93
+ * `paused`. One gizmo drag is one undo step: the binding snapshots at drag start, and the UI
94
+ * refreshes at most once a frame while dragging.
95
+ */
96
+ export function useStageGizmo(
97
+ session: EditorSession | null,
98
+ mode: GizmoMode,
99
+ target: TransformNode | null,
100
+ paused: boolean
101
+ ): void {
102
+ useEffect(() => {
103
+ const gm = session?.gizmoManager;
104
+ if (!gm) return;
105
+ gm.positionGizmoEnabled = mode === 'position';
106
+ gm.rotationGizmoEnabled = mode === 'rotation';
107
+ gm.scaleGizmoEnabled = mode === 'scale';
108
+ const activeGizmo =
109
+ mode === 'position'
110
+ ? gm.gizmos.positionGizmo
111
+ : mode === 'rotation'
112
+ ? gm.gizmos.rotationGizmo
113
+ : mode === 'scale'
114
+ ? gm.gizmos.scaleGizmo
115
+ : null;
116
+ let dragRaf = 0;
117
+ const scheduleTransformRefresh = () => {
118
+ if (dragRaf !== 0) {
119
+ return;
120
+ }
121
+ dragRaf = requestAnimationFrame(() => {
122
+ dragRaf = 0;
123
+ notifyTransformChanged();
124
+ });
125
+ };
126
+ const dragStartObserver = activeGizmo?.onDragStartObservable.add(() => session.binding?.onBeforeChange?.());
127
+ const dragObserver = activeGizmo?.onDragObservable.add(scheduleTransformRefresh);
128
+ const dragEndObserver = activeGizmo?.onDragEndObservable.add(() => {
129
+ notifyTransformChanged();
130
+ session.binding?.markChanged();
131
+ });
132
+ return () => {
133
+ if (dragRaf !== 0) {
134
+ cancelAnimationFrame(dragRaf);
135
+ }
136
+ if (activeGizmo) {
137
+ activeGizmo.onDragStartObservable.remove(dragStartObserver ?? null);
138
+ activeGizmo.onDragObservable.remove(dragObserver ?? null);
139
+ activeGizmo.onDragEndObservable.remove(dragEndObserver ?? null);
140
+ }
141
+ };
142
+ }, [session, mode]);
143
+
144
+ useEffect(() => {
145
+ if (!paused) {
146
+ session?.gizmoManager.attachToNode(target);
147
+ }
148
+ }, [session, target, paused]);
149
+ }
150
+
151
+ /**
152
+ * The floating drawer is opaque, so the scene renders only in the part of the viewport above it:
153
+ * the view, and every "frame this effect" camera move, re-centres on what is visible. Measured
154
+ * again when the drawer floats or docks and when the timeline collapses. Returns the pixels the
155
+ * drawer covers.
156
+ */
157
+ export function useViewportInset(
158
+ session: EditorSession | null,
159
+ canvasRef: React.RefObject<HTMLCanvasElement | null>,
160
+ areaRef: React.RefObject<HTMLDivElement | null>,
161
+ drawerFloating: boolean,
162
+ timelineCollapsed: boolean
163
+ ): number {
164
+ const [inset, setInset] = useState(0);
165
+ useEffect(() => {
166
+ const update = () => {
167
+ const camera = session?.camera;
168
+ const canvas = canvasRef.current;
169
+ const area = areaRef.current;
170
+ if (!camera || !canvas || !area) return;
171
+ const canvasRect = canvas.getBoundingClientRect();
172
+ const drawerTop = area.getBoundingClientRect().bottom - DRAWER_HEIGHT;
173
+ const covered = drawerFloating
174
+ ? Math.max(0, Math.min(canvasRect.height * 0.8, canvasRect.bottom - drawerTop))
175
+ : 0;
176
+ const fraction = canvasRect.height > 0 ? covered / canvasRect.height : 0;
177
+ camera.viewport = new Viewport(0, fraction, 1, 1 - fraction);
178
+ setInset(covered);
179
+ };
180
+ update();
181
+ window.addEventListener('resize', update);
182
+ return () => window.removeEventListener('resize', update);
183
+ }, [session, canvasRef, areaRef, drawerFloating, timelineCollapsed]);
184
+ return inset;
185
+ }
186
+
187
+ /** Asks before the page unloads while `dirty`. */
188
+ export function useUnsavedChangesGuard(dirty: boolean): void {
189
+ useEffect(() => {
190
+ if (!dirty) return;
191
+ const onBeforeUnload = (e: BeforeUnloadEvent) => {
192
+ e.preventDefault();
193
+ e.returnValue = '';
194
+ };
195
+ window.addEventListener('beforeunload', onBeforeUnload);
196
+ return () => window.removeEventListener('beforeunload', onBeforeUnload);
197
+ }, [dirty]);
198
+ }
@@ -0,0 +1,65 @@
1
+ import type React from 'react';
2
+ import {buttonStyle, theme} from '../theme.js';
3
+
4
+ /** Width of the Scene list on the left. */
5
+ export const SCENE_PANEL_WIDTH = 280;
6
+ /** Width of the inspector on the right. */
7
+ export const INSPECTOR_WIDTH = 340;
8
+ /** Height of the timeline dock when expanded. */
9
+ export const TIMELINE_HEIGHT = 200;
10
+ /** Height of the Assets drawer. */
11
+ export const DRAWER_HEIGHT = 280;
12
+
13
+ /** A square icon button of the viewport toolbars. */
14
+ export const squareButtonStyle: React.CSSProperties = {
15
+ ...buttonStyle,
16
+ width: 28,
17
+ height: 28,
18
+ padding: 0,
19
+ display: 'flex',
20
+ alignItems: 'center',
21
+ justifyContent: 'center',
22
+ fontWeight: 700,
23
+ };
24
+
25
+ /** Added to a toolbar button that is switched on. */
26
+ export const activeSquareButtonStyle: React.CSSProperties = {
27
+ border: `1px solid ${theme.borderActive}`,
28
+ background: 'rgba(120, 165, 255, 0.35)',
29
+ };
30
+
31
+ /** Title of a dock (Assets, Timeline). */
32
+ export const dockTitleStyle: React.CSSProperties = {
33
+ fontSize: 11,
34
+ fontWeight: 600,
35
+ letterSpacing: 0.4,
36
+ textTransform: 'uppercase',
37
+ color: theme.text,
38
+ };
39
+
40
+ /** A small icon button in a dock's header. */
41
+ export const dockIconButtonStyle: React.CSSProperties = {
42
+ ...buttonStyle,
43
+ width: 24,
44
+ height: 22,
45
+ padding: 0,
46
+ display: 'inline-flex',
47
+ alignItems: 'center',
48
+ justifyContent: 'center',
49
+ };
50
+
51
+ /** A floating panel over the viewport. */
52
+ export const floatingPanelStyle: React.CSSProperties = {
53
+ background: theme.panelBg,
54
+ border: `1px solid ${theme.border}`,
55
+ borderRadius: 8,
56
+ };
57
+
58
+ /** A Save button, highlighted while there is something to save. */
59
+ export function saveButtonStyle(pending: boolean, padding: string): React.CSSProperties {
60
+ return {
61
+ ...buttonStyle,
62
+ padding,
63
+ ...(pending ? {background: theme.accent, color: '#0a1128', border: `1px solid ${theme.accent}`} : {}),
64
+ };
65
+ }
@@ -1,6 +1,7 @@
1
- export {AssetsPanel} from './AssetsPanel';
2
- export type {AssetsPanelProps} from './AssetsPanel';
1
+ export {AssetsPanel} from './AssetsPanel.js';
2
+ export type {AssetsPanelProps} from './AssetsPanel.js';
3
3
  export {
4
+ AttractorModule,
4
5
  CollisionModule,
5
6
  ColorBySpeedModule,
6
7
  EmitDirectionModule,
@@ -16,24 +17,24 @@ export {
16
17
  TextureSheetModule,
17
18
  TurbulenceModule,
18
19
  WidthOverTrailModule,
19
- } from './behaviorModules';
20
- export {ChoiceDialog} from './ChoiceDialog';
21
- export type {ChoiceDialogAction, ChoiceDialogProps} from './ChoiceDialog';
22
- export {ContextMenu} from './ContextMenu';
23
- export type {ContextMenuItem, ContextMenuProps} from './ContextMenu';
24
- export {CurveEditor} from './CurveEditor';
25
- export {EditorWorkspace, QuarksEditorWorkspace} from './EditorWorkspace';
26
- export type {EditorWorkspaceProps} from './EditorWorkspace';
27
- export {EffectEditor} from './EffectEditor';
28
- export type {EffectEditorProps} from './EffectEditor';
29
- export {EffectEditorHost, QuarksEffectEditor} from './EffectEditorHost';
30
- export type {EffectEditorHostHandle, EffectEditorHostProps} from './EffectEditorHost';
31
- export {EffectTreeView} from './EffectTreeView';
32
- export type {EffectTreeViewProps} from './EffectTreeView';
33
- export {CheckboxField, NumberField, Row, SelectField} from './fields';
34
- export {GradientEditor} from './GradientEditor';
35
- export {MessageDialog} from './MessageDialog';
36
- export type {MessageDialogProps} from './MessageDialog';
20
+ } from './behaviorModules.js';
21
+ export {ChoiceDialog} from './ChoiceDialog.js';
22
+ export type {ChoiceDialogAction, ChoiceDialogProps} from './ChoiceDialog.js';
23
+ export {ContextMenu} from './ContextMenu.js';
24
+ export type {ContextMenuItem, ContextMenuProps} from './ContextMenu.js';
25
+ export {CurveEditor} from './CurveEditor.js';
26
+ export {EditorWorkspace, QuarksEditorWorkspace} from './EditorWorkspace.js';
27
+ export type {EditorWorkspaceProps} from './EditorWorkspace.js';
28
+ export {EffectEditor} from './EffectEditor.js';
29
+ export type {EffectEditorProps} from './EffectEditor.js';
30
+ export {EffectEditorHost, QuarksEffectEditor} from './EffectEditorHost.js';
31
+ export type {EditorProject, EffectEditorHostHandle, EffectEditorHostProps} from './EffectEditorHost.js';
32
+ export {EffectTreeView} from './EffectTreeView.js';
33
+ export type {EffectTreeViewProps} from './EffectTreeView.js';
34
+ export {CheckboxField, NumberField, Row, SelectField} from './fields.js';
35
+ export {GradientEditor} from './GradientEditor.js';
36
+ export {MessageDialog} from './MessageDialog.js';
37
+ export type {MessageDialogProps} from './MessageDialog.js';
37
38
  export {
38
39
  ColorOverLifeModule,
39
40
  EmissionModule,
@@ -41,21 +42,25 @@ export {
41
42
  RendererModule,
42
43
  ShapeModule,
43
44
  SizeOverLifeModule,
44
- } from './modules';
45
- export type {GeometryData, GeometryOption, TextureOption} from './modules';
46
- export {ModuleSection} from './ModuleSection';
47
- export {ProjectsPage} from './ProjectsPage';
48
- export type {ProjectsPageProps} from './ProjectsPage';
49
- export {PromptDialog} from './PromptDialog';
50
- export type {PromptDialogProps} from './PromptDialog';
51
- export {ScenePanel} from './ScenePanel';
52
- export type {ScenePanelProps} from './ScenePanel';
53
- export {SubEmittersModule} from './SubEmittersModule';
54
- export {buttonStyle, inputStyle, labelStyle, rowStyle, theme} from './theme';
55
- export {TimelinePanel} from './TimelinePanel';
56
- export type {PlaybackState, TimelinePanelProps} from './TimelinePanel';
57
- export {TimelineTrackRow} from './TimelineTrackRow';
58
- export type {TimelineTrackRowProps} from './TimelineTrackRow';
59
- export {TransportBar} from './TransportBar';
60
- export type {TransportBarProps} from './TransportBar';
61
- export {ValueField} from './ValueField';
45
+ } from './modules.js';
46
+ export type {GeometryData, GeometryOption, TextureOption} from './modules.js';
47
+ export {ModuleSection} from './ModuleSection.js';
48
+ export type {ModuleProps} from './ModuleSection.js';
49
+ export {ProjectsPage} from './ProjectsPage.js';
50
+ export type {ProjectsPageProps} from './ProjectsPage.js';
51
+ export {PromptDialog} from './PromptDialog.js';
52
+ export type {PromptDialogProps} from './PromptDialog.js';
53
+ export {ScenePanel} from './ScenePanel.js';
54
+ export type {ScenePanelProps} from './ScenePanel.js';
55
+ export {SubEmittersModule} from './SubEmittersModule.js';
56
+ export {TextureSelect, textureUrlOf} from './TextureSelect.js';
57
+ export {TextureUVField} from './TextureUVField.js';
58
+ export {buttonStyle, inputStyle, labelStyle, rowStyle, theme} from './theme.js';
59
+ export {TimelinePanel} from './TimelinePanel.js';
60
+ export type {PlaybackState, TimelinePanelProps} from './TimelinePanel.js';
61
+ export {TimelineTrackRow} from './TimelineTrackRow.js';
62
+ export type {TimelineTrackRowProps} from './TimelineTrackRow.js';
63
+ export {TransportBar} from './TransportBar.js';
64
+ export type {TransportBarProps} from './TransportBar.js';
65
+ export {ValueField} from './ValueField.js';
66
+ export type {ConstantValueFieldProps, CurveValueFieldProps} from './ValueField.js';
@@ -13,6 +13,7 @@ const INSPECTOR_HINTS: Record<string, string> = {
13
13
  'Velocity over Lifetime': 'Adds linear and orbital velocity each frame in local or world space.',
14
14
  'Inherit Velocity': 'Copies the emitter’s movement into new particle velocity.',
15
15
  Gravity: 'Applies a constant downward force (Earth-like gravity by default).',
16
+ Attractor: 'Pulls particles towards a point, harder the nearer they are (a point gravity).',
16
17
  'Rotation over Lifetime': 'Spins particles by setting angular velocity over lifetime.',
17
18
  Noise: 'Procedural noise that jitters particle position and rotation.',
18
19
  Turbulence: '3D turbulent velocity field that swirls particles through space.',
@@ -31,7 +32,11 @@ const INSPECTOR_HINTS: Record<string, string> = {
31
32
  Duration: 'How long the particle system runs before stopping (non-looping) or one loop cycle.',
32
33
  Looping: 'When enabled, the effect restarts from the beginning after duration ends.',
33
34
  'World space': 'Simulates in world coordinates so moving the emitter does not drag existing particles.',
35
+ 'Scaling mode':
36
+ 'What the emitter’s scale does to a world-space system: only the shape and sizes, or speeds and forces too (Unity’s Scaling Mode).',
34
37
  Prewarm: 'Simulates the effect once at start so it already looks mid-playback when play begins.',
38
+ 'Warm-up time':
39
+ 'Seconds of the cycle simulated before the first frame of a looping system (Niagara’s Warmup Time); 0 warms up a whole cycle, as Unity does.',
35
40
  'Start delay': 'Wait time before emission starts after play or restart.',
36
41
  'Start lifetime': 'How long each spawned particle lives before dying.',
37
42
  'Start speed': 'Initial speed along the emission direction when a particle is born.',
@@ -70,12 +75,37 @@ const INSPECTOR_HINTS: Record<string, string> = {
70
75
  'Render mode': 'Orientation and geometry used to draw each particle.',
71
76
  'Trail length': 'Maximum number of trail segments per particle (trail mode).',
72
77
  'Follow origin': 'Keeps the trail anchored to the emitter origin instead of the particle head.',
78
+ 'Texture mode':
79
+ 'How the texture runs along the ribbon: once by distance, once with each segment an equal share, repeated per world unit, or once per segment.',
80
+ 'Texture scale': 'Repeats of the texture: per world unit (tile), per segment (repeat), or over the ribbon.',
81
+ 'Min vertex distance':
82
+ 'The particle has to move this far before a new point is fixed; the last point follows it meanwhile. 0: a point every step.',
83
+ 'Trail time':
84
+ 'How long a point is kept, in seconds, within the trail length. 0: until the trail length is reached.',
73
85
  'Speed factor': 'How much particle speed stretches the billboard (stretched billboard mode).',
74
86
  'Length factor': 'Base stretch multiplier for stretched billboards.',
75
87
  Source: 'Material preset loaded from the effect JSON (read-only reference).',
76
88
  'Blend mode': 'How particle color is composited over the background.',
77
89
  Transparent: 'Enables alpha blending for soft edges and fade-outs.',
78
90
  Texture: 'Sprite or flipbook image applied to each particle.',
91
+ 'UV channel':
92
+ 'Which UV set the texture reads: the sprite or mesh UV, or a mesh’s second set / the length of a trail.',
93
+ Tiling: 'Repeats of the texture across the UV range, U and V (Unity’s material Tiling).',
94
+ Offset: 'Shift of the texture in UV units after tiling, U and V (Unity’s material Offset).',
95
+ Scroll: 'UV units per second the texture moves on the renderer’s clock (Unreal’s Panner).',
96
+ 'Flip U/V': 'Fraction of particles mirrored horizontally and vertically, picked at birth (Unity’s renderer Flip).',
97
+ Ramp: 'Colour ramp read left to right; without one there is no gradient map.',
98
+ 'Ramp channel':
99
+ 'Which value of the map texel picks the colour along the ramp: one channel of a packed texture, or luminance.',
100
+ Erosion: 'Lets alpha erode the shape through a mask instead of fading it.',
101
+ 'Erosion mask': 'Texture whose red channel orders what goes first; none uses the map’s own alpha.',
102
+ Softness: 'Width of the soft transition at the erosion cut, in mask units.',
103
+ 'Edge width': 'Width of the glowing band above the erosion cut; 0 draws none.',
104
+ 'Edge color': 'Linear RGB added in the edge band; may exceed 1 for a glow.',
105
+ 'Noise texture': 'Texture whose red and green channels push the map’s UV about; it should repeat.',
106
+ 'Distortion strength': 'How far the map’s UV is pushed at most, in UV units.',
107
+ 'Swept trail': 'Spans the ribbon along a fixed axis of the emitter instead of facing the camera (a weapon trail).',
108
+ 'Side axis': 'Local axis the swept trail spans its width along; give a unit vector.',
79
109
  'Alpha test': 'Pixels below this alpha are discarded (cutout/hard edges).',
80
110
  'Depth write': 'Writes to the depth buffer — usually off for additive particles.',
81
111
  'Depth test': 'Whether particles are occluded by scene geometry.',
@@ -90,6 +120,16 @@ const INSPECTOR_HINTS: Record<string, string> = {
90
120
  'Blend tiles': 'Smoothly blends between adjacent atlas tiles during animation.',
91
121
  'Start tile': 'Atlas cell index where playback begins (0 = top-left).',
92
122
  'Animate frames': 'Enables frame-over-lifetime curve to cycle through atlas tiles.',
123
+ 'Time mode':
124
+ 'Lifetime samples the curve over each particle’s life; FPS plays frames by age from the curve’s frame.',
125
+ FPS: 'Frames per second in FPS mode.',
126
+ Loop: 'In FPS mode, wrap back to the first frame of the segment, or hold the last.',
127
+ 'Random frame': 'In FPS mode, show a random frame of the segment every tick instead of the next one.',
128
+ 'Frame count': 'Frames in the segment that plays, from the first frame; 0 means no segment.',
129
+ 'Start frame':
130
+ 'Starts each particle on a random one of the first N frames (Unity’s Start Frame); editing sets a 0…N range.',
131
+ 'attractor.center': 'Point in the system’s space particles are pulled towards.',
132
+ 'attractor.magnitude': 'Pull strength, divided by the squared distance to the center.',
93
133
 
94
134
  // Sub emitters
95
135
  Trigger: 'When the child system is spawned: on particle birth, death, or every frame.',