@stevejtrettel/shader-sandbox 0.1.3 → 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.
Files changed (113) hide show
  1. package/README.md +220 -23
  2. package/bin/cli.js +106 -14
  3. package/dist-lib/app/App.d.ts +143 -15
  4. package/dist-lib/app/App.d.ts.map +1 -1
  5. package/dist-lib/app/App.js +1343 -108
  6. package/dist-lib/app/app.css +349 -24
  7. package/dist-lib/app/types.d.ts +48 -5
  8. package/dist-lib/app/types.d.ts.map +1 -1
  9. package/dist-lib/editor/EditorPanel.d.ts +2 -2
  10. package/dist-lib/editor/EditorPanel.d.ts.map +1 -1
  11. package/dist-lib/editor/EditorPanel.js +1 -1
  12. package/dist-lib/editor/editor-panel.css +55 -32
  13. package/dist-lib/editor/prism-editor.css +16 -16
  14. package/dist-lib/embed.js +1 -1
  15. package/dist-lib/engine/{ShadertoyEngine.d.ts → ShaderEngine.d.ts} +134 -10
  16. package/dist-lib/engine/ShaderEngine.d.ts.map +1 -0
  17. package/dist-lib/engine/ShaderEngine.js +1523 -0
  18. package/dist-lib/engine/glHelpers.d.ts +24 -0
  19. package/dist-lib/engine/glHelpers.d.ts.map +1 -1
  20. package/dist-lib/engine/glHelpers.js +88 -0
  21. package/dist-lib/engine/std140.d.ts +47 -0
  22. package/dist-lib/engine/std140.d.ts.map +1 -0
  23. package/dist-lib/engine/std140.js +119 -0
  24. package/dist-lib/engine/types.d.ts +55 -5
  25. package/dist-lib/engine/types.d.ts.map +1 -1
  26. package/dist-lib/engine/types.js +1 -1
  27. package/dist-lib/index.d.ts +4 -3
  28. package/dist-lib/index.d.ts.map +1 -1
  29. package/dist-lib/index.js +2 -1
  30. package/dist-lib/layouts/SplitLayout.d.ts +2 -1
  31. package/dist-lib/layouts/SplitLayout.d.ts.map +1 -1
  32. package/dist-lib/layouts/SplitLayout.js +3 -0
  33. package/dist-lib/layouts/TabbedLayout.d.ts.map +1 -1
  34. package/dist-lib/layouts/UILayout.d.ts +55 -0
  35. package/dist-lib/layouts/UILayout.d.ts.map +1 -0
  36. package/dist-lib/layouts/UILayout.js +147 -0
  37. package/dist-lib/layouts/default.css +2 -2
  38. package/dist-lib/layouts/index.d.ts +11 -1
  39. package/dist-lib/layouts/index.d.ts.map +1 -1
  40. package/dist-lib/layouts/index.js +17 -1
  41. package/dist-lib/layouts/split.css +33 -31
  42. package/dist-lib/layouts/tabbed.css +127 -74
  43. package/dist-lib/layouts/types.d.ts +14 -3
  44. package/dist-lib/layouts/types.d.ts.map +1 -1
  45. package/dist-lib/main.js +33 -0
  46. package/dist-lib/project/configHelpers.d.ts +45 -0
  47. package/dist-lib/project/configHelpers.d.ts.map +1 -0
  48. package/dist-lib/project/configHelpers.js +196 -0
  49. package/dist-lib/project/generatedLoader.d.ts +2 -2
  50. package/dist-lib/project/generatedLoader.d.ts.map +1 -1
  51. package/dist-lib/project/generatedLoader.js +23 -5
  52. package/dist-lib/project/loadProject.d.ts +6 -6
  53. package/dist-lib/project/loadProject.d.ts.map +1 -1
  54. package/dist-lib/project/loadProject.js +396 -144
  55. package/dist-lib/project/loaderHelper.d.ts +4 -4
  56. package/dist-lib/project/loaderHelper.d.ts.map +1 -1
  57. package/dist-lib/project/loaderHelper.js +278 -116
  58. package/dist-lib/project/types.d.ts +292 -13
  59. package/dist-lib/project/types.d.ts.map +1 -1
  60. package/dist-lib/project/types.js +13 -1
  61. package/dist-lib/styles/base.css +5 -1
  62. package/dist-lib/uniforms/UniformControls.d.ts +60 -0
  63. package/dist-lib/uniforms/UniformControls.d.ts.map +1 -0
  64. package/dist-lib/uniforms/UniformControls.js +518 -0
  65. package/dist-lib/uniforms/UniformStore.d.ts +74 -0
  66. package/dist-lib/uniforms/UniformStore.d.ts.map +1 -0
  67. package/dist-lib/uniforms/UniformStore.js +145 -0
  68. package/dist-lib/uniforms/UniformsPanel.d.ts +53 -0
  69. package/dist-lib/uniforms/UniformsPanel.d.ts.map +1 -0
  70. package/dist-lib/uniforms/UniformsPanel.js +124 -0
  71. package/dist-lib/uniforms/index.d.ts +11 -0
  72. package/dist-lib/uniforms/index.d.ts.map +1 -0
  73. package/dist-lib/uniforms/index.js +8 -0
  74. package/package.json +1 -1
  75. package/src/app/App.ts +1469 -126
  76. package/src/app/app.css +349 -24
  77. package/src/app/types.ts +53 -5
  78. package/src/editor/EditorPanel.ts +5 -5
  79. package/src/editor/editor-panel.css +55 -32
  80. package/src/editor/prism-editor.css +16 -16
  81. package/src/embed.ts +1 -1
  82. package/src/engine/ShaderEngine.ts +1934 -0
  83. package/src/engine/glHelpers.ts +117 -0
  84. package/src/engine/std140.ts +136 -0
  85. package/src/engine/types.ts +69 -5
  86. package/src/index.ts +4 -3
  87. package/src/layouts/SplitLayout.ts +8 -3
  88. package/src/layouts/TabbedLayout.ts +3 -3
  89. package/src/layouts/UILayout.ts +185 -0
  90. package/src/layouts/default.css +2 -2
  91. package/src/layouts/index.ts +20 -1
  92. package/src/layouts/split.css +33 -31
  93. package/src/layouts/tabbed.css +127 -74
  94. package/src/layouts/types.ts +19 -3
  95. package/src/layouts/ui.css +289 -0
  96. package/src/main.ts +39 -1
  97. package/src/project/configHelpers.ts +225 -0
  98. package/src/project/generatedLoader.ts +27 -6
  99. package/src/project/loadProject.ts +459 -173
  100. package/src/project/loaderHelper.ts +377 -130
  101. package/src/project/types.ts +360 -14
  102. package/src/styles/base.css +5 -1
  103. package/src/styles/theme.css +292 -0
  104. package/src/uniforms/UniformControls.ts +660 -0
  105. package/src/uniforms/UniformStore.ts +166 -0
  106. package/src/uniforms/UniformsPanel.ts +163 -0
  107. package/src/uniforms/index.ts +13 -0
  108. package/src/uniforms/uniform-controls.css +342 -0
  109. package/src/uniforms/uniforms-panel.css +277 -0
  110. package/templates/shaders/example-buffer/config.json +1 -0
  111. package/dist-lib/engine/ShadertoyEngine.d.ts.map +0 -1
  112. package/dist-lib/engine/ShadertoyEngine.js +0 -704
  113. package/src/engine/ShadertoyEngine.ts +0 -929
@@ -3,14 +3,6 @@
3
3
  * Single window with tabs switching between shader and code views
4
4
  */
5
5
 
6
- /* ===== Theme Variables (for code viewer) ===== */
7
- .layout-tabbed {
8
- --tab-border: #e0e0e0;
9
- --code-bg: white;
10
- --code-text: #000;
11
- --line-number-text: #999;
12
- }
13
-
14
6
  .layout-tabbed {
15
7
  width: 100%;
16
8
  height: 100%;
@@ -30,7 +22,7 @@
30
22
  height: 650px; /* 600px content + ~50px tabs */
31
23
  max-height: 100%;
32
24
  border-radius: 8px;
33
- box-shadow: 0 20px 60px rgba(0, 0, 0, 0.25), 0 5px 15px rgba(0, 0, 0, 0.15);
25
+ box-shadow: var(--shadow-lg), var(--shadow-sm);
34
26
  overflow: hidden;
35
27
  }
36
28
 
@@ -39,8 +31,8 @@
39
31
  display: flex;
40
32
  align-items: center;
41
33
  flex-shrink: 0;
42
- background: #f8f8f8;
43
- border-bottom: 1px solid #e0e0e0;
34
+ background: var(--tab-bg);
35
+ border-bottom: 1px solid var(--border-primary);
44
36
  padding-right: 8px;
45
37
  }
46
38
 
@@ -60,7 +52,7 @@
60
52
  }
61
53
 
62
54
  .tabbed-tab-bar::-webkit-scrollbar-thumb {
63
- background: #ccc;
55
+ background: var(--border-secondary);
64
56
  border-radius: 2px;
65
57
  }
66
58
 
@@ -73,18 +65,18 @@
73
65
  font-family: 'Monaco', 'Menlo', 'Courier New', monospace;
74
66
  cursor: pointer;
75
67
  transition: color 0.15s, border-color 0.15s;
76
- color: #666;
68
+ color: var(--tab-text);
77
69
  white-space: nowrap;
78
70
  flex-shrink: 0;
79
71
  }
80
72
 
81
73
  .tabbed-tab-button:hover {
82
- color: #333;
74
+ color: var(--tab-text-hover);
83
75
  }
84
76
 
85
77
  .tabbed-tab-button.active {
86
- color: #000;
87
- border-bottom-color: #4a9eff;
78
+ color: var(--tab-text-active);
79
+ border-bottom-color: var(--tab-border-active);
88
80
  }
89
81
 
90
82
  .tabbed-tab-button.shader-tab {
@@ -92,12 +84,28 @@
92
84
  }
93
85
 
94
86
  .tabbed-tab-button.image-tab {
95
- color: #7c4dff;
87
+ color: var(--accent-secondary);
96
88
  }
97
89
 
98
90
  .tabbed-tab-button.image-tab.active {
99
- color: #7c4dff;
100
- border-bottom-color: #7c4dff;
91
+ color: var(--accent-secondary);
92
+ border-bottom-color: var(--accent-secondary);
93
+ }
94
+
95
+ .tabbed-tab-button.uniforms-tab {
96
+ color: var(--accent-tertiary, var(--accent-primary));
97
+ padding: 8px 12px;
98
+ }
99
+
100
+ .tabbed-tab-button.uniforms-tab.active {
101
+ color: var(--accent-tertiary, var(--accent-primary));
102
+ border-bottom-color: var(--accent-tertiary, var(--accent-primary));
103
+ }
104
+
105
+ .tabbed-tab-button .uniforms-icon {
106
+ width: 18px;
107
+ height: 18px;
108
+ display: block;
101
109
  }
102
110
 
103
111
  /* ===== Content Area ===== */
@@ -105,7 +113,7 @@
105
113
  flex: 1;
106
114
  min-height: 0; /* Critical for flexbox scrolling */
107
115
  position: relative;
108
- background: #000;
116
+ background: var(--bg-canvas);
109
117
  overflow: hidden;
110
118
  }
111
119
 
@@ -149,8 +157,8 @@
149
157
  text-align: right;
150
158
  padding-right: 16px;
151
159
  margin-right: 16px;
152
- border-right: 1px solid var(--tab-border);
153
- color: var(--line-number-text);
160
+ border-right: 1px solid var(--code-line-border);
161
+ color: var(--code-line-number);
154
162
  user-select: none;
155
163
  flex-shrink: 0;
156
164
  padding-left: 16px;
@@ -171,7 +179,7 @@
171
179
  display: flex;
172
180
  align-items: center;
173
181
  justify-content: center;
174
- background: #f5f5f5;
182
+ background: var(--image-viewer-bg);
175
183
  padding: 20px;
176
184
  box-sizing: border-box;
177
185
  }
@@ -181,36 +189,18 @@
181
189
  max-height: 100%;
182
190
  object-fit: contain;
183
191
  border-radius: 4px;
184
- box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15);
185
- }
186
-
187
- /* ===== Prism Theme (Light) ===== */
188
- .tabbed-code-viewer .token.comment { color: #6a9955; }
189
- .tabbed-code-viewer .token.keyword { color: #0000ff; }
190
- .tabbed-code-viewer .token.string { color: #a31515; }
191
- .tabbed-code-viewer .token.number { color: #098658; }
192
- .tabbed-code-viewer .token.operator { color: #000000; }
193
- .tabbed-code-viewer .token.function { color: #795e26; }
194
- .tabbed-code-viewer .token.class-name { color: #267f99; }
195
- .tabbed-code-viewer .token.punctuation { color: #000000; }
196
-
197
- /* ===== Prism Theme (Dark) ===== */
198
- [data-bs-theme="dark"] .tabbed-code-viewer .token.comment,
199
- .dark .tabbed-code-viewer .token.comment { color: #6a9955; }
200
- [data-bs-theme="dark"] .tabbed-code-viewer .token.keyword,
201
- .dark .tabbed-code-viewer .token.keyword { color: #569cd6; }
202
- [data-bs-theme="dark"] .tabbed-code-viewer .token.string,
203
- .dark .tabbed-code-viewer .token.string { color: #ce9178; }
204
- [data-bs-theme="dark"] .tabbed-code-viewer .token.number,
205
- .dark .tabbed-code-viewer .token.number { color: #b5cea8; }
206
- [data-bs-theme="dark"] .tabbed-code-viewer .token.operator,
207
- .dark .tabbed-code-viewer .token.operator { color: #d4d4d4; }
208
- [data-bs-theme="dark"] .tabbed-code-viewer .token.function,
209
- .dark .tabbed-code-viewer .token.function { color: #dcdcaa; }
210
- [data-bs-theme="dark"] .tabbed-code-viewer .token.class-name,
211
- .dark .tabbed-code-viewer .token.class-name { color: #4ec9b0; }
212
- [data-bs-theme="dark"] .tabbed-code-viewer .token.punctuation,
213
- .dark .tabbed-code-viewer .token.punctuation { color: #d4d4d4; }
192
+ box-shadow: var(--shadow-sm);
193
+ }
194
+
195
+ /* ===== Prism Theme (uses CSS variables) ===== */
196
+ .tabbed-code-viewer .token.comment { color: var(--syntax-comment); }
197
+ .tabbed-code-viewer .token.keyword { color: var(--syntax-keyword); }
198
+ .tabbed-code-viewer .token.string { color: var(--syntax-string); }
199
+ .tabbed-code-viewer .token.number { color: var(--syntax-number); }
200
+ .tabbed-code-viewer .token.operator { color: var(--syntax-operator); }
201
+ .tabbed-code-viewer .token.function { color: var(--syntax-function); }
202
+ .tabbed-code-viewer .token.class-name { color: var(--syntax-class); }
203
+ .tabbed-code-viewer .token.punctuation { color: var(--syntax-punctuation); }
214
204
 
215
205
  /* ===== Responsive ===== */
216
206
  @media (max-width: 1200px) {
@@ -244,7 +234,7 @@
244
234
  width: 100%;
245
235
  height: 100%;
246
236
  overflow: hidden;
247
- background: #ffffff;
237
+ background: var(--code-bg);
248
238
  }
249
239
 
250
240
  /* Button container for copy and recompile (in toolbar) */
@@ -260,9 +250,9 @@
260
250
  display: flex;
261
251
  align-items: center;
262
252
  justify-content: center;
263
- background: transparent;
264
- border: 1px solid #ccc;
265
- color: #666;
253
+ background: var(--button-bg);
254
+ border: 1px solid var(--button-border);
255
+ color: var(--button-text);
266
256
  width: 32px;
267
257
  height: 32px;
268
258
  border-radius: 4px;
@@ -271,43 +261,43 @@
271
261
  }
272
262
 
273
263
  .tabbed-copy-button:hover {
274
- background: #f0f0f0;
275
- border-color: #999;
276
- color: #333;
264
+ background: var(--button-bg-hover);
265
+ border-color: var(--button-border-hover);
266
+ color: var(--button-text-hover);
277
267
  }
278
268
 
279
269
  .tabbed-copy-button:active {
280
- background: #e0e0e0;
270
+ background: var(--button-bg-hover);
281
271
  }
282
272
 
283
273
  .tabbed-copy-button.copied {
284
- background: #e8f5e9;
285
- border-color: #4caf50;
286
- color: #4caf50;
274
+ background: var(--success-bg);
275
+ border-color: var(--success-border);
276
+ color: var(--success-text);
287
277
  }
288
278
 
289
279
  .tabbed-recompile-button {
290
280
  display: flex;
291
281
  align-items: center;
292
282
  gap: 6px;
293
- background: #4a9eff;
283
+ background: var(--recompile-bg);
294
284
  border: none;
295
- color: #fff;
285
+ color: var(--recompile-text);
296
286
  padding: 6px 12px;
297
287
  border-radius: 4px;
298
288
  cursor: pointer;
299
289
  font-family: inherit;
300
290
  font-size: 12px;
301
291
  font-weight: 500;
302
- transition: background 0.15s;
292
+ transition: background 0.15s, color 0.15s;
303
293
  }
304
294
 
305
295
  .tabbed-recompile-button:hover {
306
- background: #3a8eef;
296
+ background: var(--recompile-bg-hover);
307
297
  }
308
298
 
309
299
  .tabbed-recompile-button:active {
310
- background: #2a7edf;
300
+ background: var(--recompile-bg-active);
311
301
  }
312
302
 
313
303
  .tabbed-recompile-button svg {
@@ -319,23 +309,23 @@
319
309
  bottom: 0;
320
310
  left: 0;
321
311
  right: 0;
322
- background: #fff0f0;
323
- color: #c00;
312
+ background: var(--error-bg);
313
+ color: var(--error-text);
324
314
  padding: 10px 14px;
325
315
  font-family: 'Monaco', 'Menlo', 'Courier New', monospace;
326
316
  font-size: 12px;
327
317
  white-space: pre-wrap;
328
318
  overflow: auto;
329
319
  max-height: 120px;
330
- border-top: 1px solid #fcc;
320
+ border-top: 1px solid var(--error-border);
331
321
  z-index: 10;
332
322
  }
333
323
 
334
324
  .tabbed-fallback-textarea {
335
325
  width: 100%;
336
326
  height: 100%;
337
- background: #ffffff;
338
- color: #000;
327
+ background: var(--code-bg);
328
+ color: var(--code-text);
339
329
  border: none;
340
330
  padding: 12px;
341
331
  font-family: 'Monaco', 'Menlo', 'Courier New', monospace;
@@ -343,3 +333,66 @@
343
333
  resize: none;
344
334
  outline: none;
345
335
  }
336
+
337
+ /* ===== Uniforms Container (semi-transparent overlay) ===== */
338
+ .tabbed-uniforms-container {
339
+ position: absolute;
340
+ top: 0;
341
+ left: 0;
342
+ width: 100%;
343
+ height: 100%;
344
+ overflow-y: auto;
345
+ background: rgba(0, 0, 0, 0.5);
346
+ backdrop-filter: blur(8px);
347
+ display: flex;
348
+ justify-content: center;
349
+ padding: 20px;
350
+ box-sizing: border-box;
351
+ }
352
+
353
+ /* Center the uniform controls and constrain width */
354
+ .tabbed-uniforms-container .uniform-controls {
355
+ max-width: 400px;
356
+ width: 100%;
357
+ background: rgba(30, 30, 35, 0.95);
358
+ border-radius: 12px;
359
+ padding: 20px;
360
+ box-shadow: 0 4px 20px rgba(0, 0, 0, 0.4);
361
+ height: fit-content;
362
+ }
363
+
364
+ /* Ensure text is visible in the overlay */
365
+ .tabbed-uniforms-container .uniform-control-label {
366
+ color: #e0e0e0;
367
+ }
368
+
369
+ .tabbed-uniforms-container .uniform-control-value {
370
+ color: #a0a0a0;
371
+ background: rgba(0, 0, 0, 0.3);
372
+ }
373
+
374
+ .tabbed-uniforms-container .uniform-controls-header {
375
+ color: #909090;
376
+ border-bottom-color: rgba(255, 255, 255, 0.1);
377
+ }
378
+
379
+ .tabbed-uniforms-container .uniform-control-slider {
380
+ background: rgba(255, 255, 255, 0.1);
381
+ }
382
+
383
+ .tabbed-uniforms-container .uniform-control-slider::-webkit-slider-thumb {
384
+ background: #ffffff;
385
+ }
386
+
387
+ .tabbed-uniforms-container .uniform-control-slider::-moz-range-thumb {
388
+ background: #ffffff;
389
+ }
390
+
391
+ .tabbed-uniforms-container .uniform-control-vec-component {
392
+ color: #909090;
393
+ }
394
+
395
+ .tabbed-uniforms-container .uniform-control-vec-value {
396
+ color: #a0a0a0;
397
+ background: rgba(0, 0, 0, 0.3);
398
+ }
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * Layout Types - Common interface for all layout modes
3
3
  */
4
- import { ShadertoyProject, PassName } from '../project/types';
4
+ import { ShaderProject, PassName, UniformValue } from '../project/types';
5
5
  /**
6
6
  * Result of a recompilation attempt.
7
7
  */
@@ -16,6 +16,12 @@ export interface RecompileResult {
16
16
  * @returns Result indicating success or failure with error message
17
17
  */
18
18
  export type RecompileHandler = (passName: 'common' | PassName, newSource: string) => RecompileResult;
19
+ /**
20
+ * Callback for uniform value changes.
21
+ * @param name - Uniform name
22
+ * @param value - New uniform value
23
+ */
24
+ export type UniformChangeHandler = (name: string, value: UniformValue) => void;
19
25
  /**
20
26
  * Base interface that all layouts must implement.
21
27
  */
@@ -29,6 +35,11 @@ export interface BaseLayout {
29
35
  * Called by App after initialization to wire up recompilation.
30
36
  */
31
37
  setRecompileHandler?(handler: RecompileHandler): void;
38
+ /**
39
+ * Set the uniform change handler for uniform controls.
40
+ * Called by App after initialization to wire up uniform changes.
41
+ */
42
+ setUniformHandler?(handler: UniformChangeHandler): void;
32
43
  /**
33
44
  * Clean up all DOM elements and resources.
34
45
  */
@@ -39,10 +50,10 @@ export interface BaseLayout {
39
50
  */
40
51
  export interface LayoutOptions {
41
52
  container: HTMLElement;
42
- project: ShadertoyProject;
53
+ project: ShaderProject;
43
54
  }
44
55
  /**
45
56
  * Available layout modes.
46
57
  */
47
- export type LayoutMode = 'fullscreen' | 'default' | 'split' | 'tabbed';
58
+ export type LayoutMode = 'fullscreen' | 'default' | 'split' | 'tabbed' | 'ui';
48
59
  //# sourceMappingURL=types.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/layouts/types.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,gBAAgB,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAE9D;;GAEG;AACH,MAAM,WAAW,eAAe;IAC9B,OAAO,EAAE,OAAO,CAAC;IACjB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED;;;;;GAKG;AACH,MAAM,MAAM,gBAAgB,GAAG,CAC7B,QAAQ,EAAE,QAAQ,GAAG,QAAQ,EAC7B,SAAS,EAAE,MAAM,KACd,eAAe,CAAC;AAErB;;GAEG;AACH,MAAM,WAAW,UAAU;IACzB;;OAEG;IACH,kBAAkB,IAAI,WAAW,CAAC;IAElC;;;OAGG;IACH,mBAAmB,CAAC,CAAC,OAAO,EAAE,gBAAgB,GAAG,IAAI,CAAC;IAEtD;;OAEG;IACH,OAAO,IAAI,IAAI,CAAC;CACjB;AAED;;GAEG;AACH,MAAM,WAAW,aAAa;IAC5B,SAAS,EAAE,WAAW,CAAC;IACvB,OAAO,EAAE,gBAAgB,CAAC;CAC3B;AAED;;GAEG;AACH,MAAM,MAAM,UAAU,GAAG,YAAY,GAAG,SAAS,GAAG,OAAO,GAAG,QAAQ,CAAC"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/layouts/types.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,aAAa,EAAE,QAAQ,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AAEzE;;GAEG;AACH,MAAM,WAAW,eAAe;IAC9B,OAAO,EAAE,OAAO,CAAC;IACjB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED;;;;;GAKG;AACH,MAAM,MAAM,gBAAgB,GAAG,CAC7B,QAAQ,EAAE,QAAQ,GAAG,QAAQ,EAC7B,SAAS,EAAE,MAAM,KACd,eAAe,CAAC;AAErB;;;;GAIG;AACH,MAAM,MAAM,oBAAoB,GAAG,CACjC,IAAI,EAAE,MAAM,EACZ,KAAK,EAAE,YAAY,KAChB,IAAI,CAAC;AAEV;;GAEG;AACH,MAAM,WAAW,UAAU;IACzB;;OAEG;IACH,kBAAkB,IAAI,WAAW,CAAC;IAElC;;;OAGG;IACH,mBAAmB,CAAC,CAAC,OAAO,EAAE,gBAAgB,GAAG,IAAI,CAAC;IAEtD;;;OAGG;IACH,iBAAiB,CAAC,CAAC,OAAO,EAAE,oBAAoB,GAAG,IAAI,CAAC;IAExD;;OAEG;IACH,OAAO,IAAI,IAAI,CAAC;CACjB;AAED;;GAEG;AACH,MAAM,WAAW,aAAa;IAC5B,SAAS,EAAE,WAAW,CAAC;IACvB,OAAO,EAAE,aAAa,CAAC;CACxB;AAED;;GAEG;AACH,MAAM,MAAM,UAAU,GAAG,YAAY,GAAG,SAAS,GAAG,OAAO,GAAG,QAAQ,GAAG,IAAI,CAAC"}
package/dist-lib/main.js CHANGED
@@ -14,6 +14,7 @@
14
14
  import './styles/base.css';
15
15
  import { App } from './app/App';
16
16
  import { createLayout } from './layouts';
17
+ import { UILayout } from './layouts/UILayout';
17
18
  import { loadDemoProject, DEMO_NAME } from './project/generatedLoader';
18
19
  async function main() {
19
20
  try {
@@ -35,11 +36,15 @@ async function main() {
35
36
  });
36
37
  // Get canvas container from layout
37
38
  const canvasContainer = layout.getCanvasContainer();
39
+ // Check if this is a UILayout (which has its own uniforms panel and playback controls)
40
+ const isUILayout = layout instanceof UILayout;
38
41
  // Create app
39
42
  const app = new App({
40
43
  container: canvasContainer,
41
44
  project,
42
45
  pixelRatio: window.devicePixelRatio,
46
+ skipUniformsPanel: isUILayout,
47
+ skipPlaybackControls: isUILayout,
43
48
  });
44
49
  // Wire up recompile handler for layouts that support it (split, tabbed)
45
50
  if (layout.setRecompileHandler) {
@@ -67,6 +72,34 @@ async function main() {
67
72
  }
68
73
  });
69
74
  }
75
+ // Wire up uniform change handler for layouts that support it (split, tabbed)
76
+ if (layout.setUniformHandler) {
77
+ layout.setUniformHandler((name, value) => {
78
+ const engine = app.getEngine();
79
+ if (engine) {
80
+ engine.setUniformValue(name, value);
81
+ }
82
+ });
83
+ }
84
+ // Wire up UILayout callbacks (playback controls and uniforms)
85
+ if (layout instanceof UILayout) {
86
+ layout.setPlaybackCallbacks({
87
+ onPlayPause: () => {
88
+ app.togglePlayPause();
89
+ layout.setPaused(app.getPaused());
90
+ },
91
+ onReset: () => app.reset(),
92
+ onScreenshot: () => app.screenshot(),
93
+ });
94
+ layout.setUniformCallback((name, value) => {
95
+ const engine = app.getEngine();
96
+ if (engine) {
97
+ engine.setUniformValue(name, value);
98
+ }
99
+ });
100
+ // Sync initial paused state (from project.startPaused)
101
+ layout.setPaused(app.getPaused());
102
+ }
70
103
  // Only start animation loop if there are no compilation errors
71
104
  // If there are errors, the error overlay is already shown by App constructor
72
105
  if (!app.hasErrors()) {
@@ -0,0 +1,45 @@
1
+ /**
2
+ * Shared helpers for config loading.
3
+ * Used by both the Node/CLI loader (loadProject.ts) and
4
+ * the browser/Vite loader (loaderHelper.ts).
5
+ */
6
+ import type { PassName, ChannelValue, ChannelJSONObject } from './types';
7
+ /**
8
+ * Type guard for PassName.
9
+ */
10
+ export declare function isPassName(s: string): s is PassName;
11
+ /**
12
+ * Get default source file name for a pass.
13
+ */
14
+ export declare function defaultSourceForPass(name: PassName): string;
15
+ /**
16
+ * Parse a channel value (string shorthand or object) into normalized ChannelJSONObject.
17
+ *
18
+ * String shortcuts:
19
+ * - "BufferA", "BufferB", etc. → buffer reference
20
+ * - "keyboard" → keyboard input
21
+ * - "audio" → microphone audio input
22
+ * - "webcam" → webcam video input
23
+ * - "photo.jpg" (with extension) → texture file
24
+ */
25
+ export declare function parseChannelValue(value: ChannelValue): ChannelJSONObject | null;
26
+ /** The ordered list of pass names for iteration. */
27
+ export declare const PASS_ORDER: readonly ["Image", "BufferA", "BufferB", "BufferC", "BufferD"];
28
+ /** The four buffer pass names (excludes Image). */
29
+ export declare const BUFFER_PASS_NAMES: PassName[];
30
+ /** The four channel keys. */
31
+ export declare const CHANNEL_KEYS: readonly ["iChannel0", "iChannel1", "iChannel2", "iChannel3"];
32
+ /** Default layout for projects. */
33
+ export declare const DEFAULT_LAYOUT: "default";
34
+ /** Default controls setting. */
35
+ export declare const DEFAULT_CONTROLS = false;
36
+ /** Default theme. */
37
+ export declare const DEFAULT_THEME: "light";
38
+ /** Check if a string is a valid GLSL identifier (not a reserved word). */
39
+ export declare function isValidGLSLIdentifier(name: string): boolean;
40
+ /**
41
+ * Validate a project config and throw on errors.
42
+ * Logs warnings for non-fatal issues.
43
+ */
44
+ export declare function validateConfig(config: Record<string, any>, root: string): void;
45
+ //# sourceMappingURL=configHelpers.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"configHelpers.d.ts","sourceRoot":"","sources":["../../src/project/configHelpers.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,QAAQ,EAAE,YAAY,EAAE,iBAAiB,EAAE,MAAM,SAAS,CAAC;AAEzE;;GAEG;AACH,wBAAgB,UAAU,CAAC,CAAC,EAAE,MAAM,GAAG,CAAC,IAAI,QAAQ,CAEnD;AAED;;GAEG;AACH,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,QAAQ,GAAG,MAAM,CAa3D;AAED;;;;;;;;;GASG;AACH,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,YAAY,GAAG,iBAAiB,GAAG,IAAI,CAmB/E;AAED,oDAAoD;AACpD,eAAO,MAAM,UAAU,gEAAiE,CAAC;AAEzF,mDAAmD;AACnD,eAAO,MAAM,iBAAiB,EAAE,QAAQ,EAAiD,CAAC;AAE1F,6BAA6B;AAC7B,eAAO,MAAM,YAAY,+DAAgE,CAAC;AAE1F,mCAAmC;AACnC,eAAO,MAAM,cAAc,EAAG,SAAkB,CAAC;AAEjD,gCAAgC;AAChC,eAAO,MAAM,gBAAgB,QAAQ,CAAC;AAEtC,qBAAqB;AACrB,eAAO,MAAM,aAAa,EAAG,OAAgB,CAAC;AA6B9C,0EAA0E;AAC1E,wBAAgB,qBAAqB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAE3D;AAeD;;;GAGG;AACH,wBAAgB,cAAc,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,EAAE,IAAI,EAAE,MAAM,GAAG,IAAI,CA6F9E"}