@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.
- package/README.md +220 -23
- package/bin/cli.js +106 -14
- package/dist-lib/app/App.d.ts +143 -15
- package/dist-lib/app/App.d.ts.map +1 -1
- package/dist-lib/app/App.js +1343 -108
- package/dist-lib/app/app.css +349 -24
- package/dist-lib/app/types.d.ts +48 -5
- package/dist-lib/app/types.d.ts.map +1 -1
- package/dist-lib/editor/EditorPanel.d.ts +2 -2
- package/dist-lib/editor/EditorPanel.d.ts.map +1 -1
- package/dist-lib/editor/EditorPanel.js +1 -1
- package/dist-lib/editor/editor-panel.css +55 -32
- package/dist-lib/editor/prism-editor.css +16 -16
- package/dist-lib/embed.js +1 -1
- package/dist-lib/engine/{ShadertoyEngine.d.ts → ShaderEngine.d.ts} +134 -10
- package/dist-lib/engine/ShaderEngine.d.ts.map +1 -0
- package/dist-lib/engine/ShaderEngine.js +1523 -0
- package/dist-lib/engine/glHelpers.d.ts +24 -0
- package/dist-lib/engine/glHelpers.d.ts.map +1 -1
- package/dist-lib/engine/glHelpers.js +88 -0
- package/dist-lib/engine/std140.d.ts +47 -0
- package/dist-lib/engine/std140.d.ts.map +1 -0
- package/dist-lib/engine/std140.js +119 -0
- package/dist-lib/engine/types.d.ts +55 -5
- package/dist-lib/engine/types.d.ts.map +1 -1
- package/dist-lib/engine/types.js +1 -1
- package/dist-lib/index.d.ts +4 -3
- package/dist-lib/index.d.ts.map +1 -1
- package/dist-lib/index.js +2 -1
- package/dist-lib/layouts/SplitLayout.d.ts +2 -1
- package/dist-lib/layouts/SplitLayout.d.ts.map +1 -1
- package/dist-lib/layouts/SplitLayout.js +3 -0
- package/dist-lib/layouts/TabbedLayout.d.ts.map +1 -1
- package/dist-lib/layouts/UILayout.d.ts +55 -0
- package/dist-lib/layouts/UILayout.d.ts.map +1 -0
- package/dist-lib/layouts/UILayout.js +147 -0
- package/dist-lib/layouts/default.css +2 -2
- package/dist-lib/layouts/index.d.ts +11 -1
- package/dist-lib/layouts/index.d.ts.map +1 -1
- package/dist-lib/layouts/index.js +17 -1
- package/dist-lib/layouts/split.css +33 -31
- package/dist-lib/layouts/tabbed.css +127 -74
- package/dist-lib/layouts/types.d.ts +14 -3
- package/dist-lib/layouts/types.d.ts.map +1 -1
- package/dist-lib/main.js +33 -0
- package/dist-lib/project/configHelpers.d.ts +45 -0
- package/dist-lib/project/configHelpers.d.ts.map +1 -0
- package/dist-lib/project/configHelpers.js +196 -0
- package/dist-lib/project/generatedLoader.d.ts +2 -2
- package/dist-lib/project/generatedLoader.d.ts.map +1 -1
- package/dist-lib/project/generatedLoader.js +23 -5
- package/dist-lib/project/loadProject.d.ts +6 -6
- package/dist-lib/project/loadProject.d.ts.map +1 -1
- package/dist-lib/project/loadProject.js +396 -144
- package/dist-lib/project/loaderHelper.d.ts +4 -4
- package/dist-lib/project/loaderHelper.d.ts.map +1 -1
- package/dist-lib/project/loaderHelper.js +278 -116
- package/dist-lib/project/types.d.ts +292 -13
- package/dist-lib/project/types.d.ts.map +1 -1
- package/dist-lib/project/types.js +13 -1
- package/dist-lib/styles/base.css +5 -1
- package/dist-lib/uniforms/UniformControls.d.ts +60 -0
- package/dist-lib/uniforms/UniformControls.d.ts.map +1 -0
- package/dist-lib/uniforms/UniformControls.js +518 -0
- package/dist-lib/uniforms/UniformStore.d.ts +74 -0
- package/dist-lib/uniforms/UniformStore.d.ts.map +1 -0
- package/dist-lib/uniforms/UniformStore.js +145 -0
- package/dist-lib/uniforms/UniformsPanel.d.ts +53 -0
- package/dist-lib/uniforms/UniformsPanel.d.ts.map +1 -0
- package/dist-lib/uniforms/UniformsPanel.js +124 -0
- package/dist-lib/uniforms/index.d.ts +11 -0
- package/dist-lib/uniforms/index.d.ts.map +1 -0
- package/dist-lib/uniforms/index.js +8 -0
- package/package.json +1 -1
- package/src/app/App.ts +1469 -126
- package/src/app/app.css +349 -24
- package/src/app/types.ts +53 -5
- package/src/editor/EditorPanel.ts +5 -5
- package/src/editor/editor-panel.css +55 -32
- package/src/editor/prism-editor.css +16 -16
- package/src/embed.ts +1 -1
- package/src/engine/ShaderEngine.ts +1934 -0
- package/src/engine/glHelpers.ts +117 -0
- package/src/engine/std140.ts +136 -0
- package/src/engine/types.ts +69 -5
- package/src/index.ts +4 -3
- package/src/layouts/SplitLayout.ts +8 -3
- package/src/layouts/TabbedLayout.ts +3 -3
- package/src/layouts/UILayout.ts +185 -0
- package/src/layouts/default.css +2 -2
- package/src/layouts/index.ts +20 -1
- package/src/layouts/split.css +33 -31
- package/src/layouts/tabbed.css +127 -74
- package/src/layouts/types.ts +19 -3
- package/src/layouts/ui.css +289 -0
- package/src/main.ts +39 -1
- package/src/project/configHelpers.ts +225 -0
- package/src/project/generatedLoader.ts +27 -6
- package/src/project/loadProject.ts +459 -173
- package/src/project/loaderHelper.ts +377 -130
- package/src/project/types.ts +360 -14
- package/src/styles/base.css +5 -1
- package/src/styles/theme.css +292 -0
- package/src/uniforms/UniformControls.ts +660 -0
- package/src/uniforms/UniformStore.ts +166 -0
- package/src/uniforms/UniformsPanel.ts +163 -0
- package/src/uniforms/index.ts +13 -0
- package/src/uniforms/uniform-controls.css +342 -0
- package/src/uniforms/uniforms-panel.css +277 -0
- package/templates/shaders/example-buffer/config.json +1 -0
- package/dist-lib/engine/ShadertoyEngine.d.ts.map +0 -1
- package/dist-lib/engine/ShadertoyEngine.js +0 -704
- 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:
|
|
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:
|
|
43
|
-
border-bottom: 1px solid
|
|
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:
|
|
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:
|
|
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:
|
|
74
|
+
color: var(--tab-text-hover);
|
|
83
75
|
}
|
|
84
76
|
|
|
85
77
|
.tabbed-tab-button.active {
|
|
86
|
-
color:
|
|
87
|
-
border-bottom-color:
|
|
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:
|
|
87
|
+
color: var(--accent-secondary);
|
|
96
88
|
}
|
|
97
89
|
|
|
98
90
|
.tabbed-tab-button.image-tab.active {
|
|
99
|
-
color:
|
|
100
|
-
border-bottom-color:
|
|
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:
|
|
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(--
|
|
153
|
-
color: var(--line-number
|
|
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:
|
|
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:
|
|
185
|
-
}
|
|
186
|
-
|
|
187
|
-
/* ===== Prism Theme (
|
|
188
|
-
.tabbed-code-viewer .token.comment { color:
|
|
189
|
-
.tabbed-code-viewer .token.keyword { color:
|
|
190
|
-
.tabbed-code-viewer .token.string { color:
|
|
191
|
-
.tabbed-code-viewer .token.number { color:
|
|
192
|
-
.tabbed-code-viewer .token.operator { color:
|
|
193
|
-
.tabbed-code-viewer .token.function { color:
|
|
194
|
-
.tabbed-code-viewer .token.class-name { color:
|
|
195
|
-
.tabbed-code-viewer .token.punctuation { color:
|
|
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:
|
|
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:
|
|
264
|
-
border: 1px solid
|
|
265
|
-
color:
|
|
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:
|
|
275
|
-
border-color:
|
|
276
|
-
color:
|
|
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:
|
|
270
|
+
background: var(--button-bg-hover);
|
|
281
271
|
}
|
|
282
272
|
|
|
283
273
|
.tabbed-copy-button.copied {
|
|
284
|
-
background:
|
|
285
|
-
border-color:
|
|
286
|
-
color:
|
|
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:
|
|
283
|
+
background: var(--recompile-bg);
|
|
294
284
|
border: none;
|
|
295
|
-
color:
|
|
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:
|
|
296
|
+
background: var(--recompile-bg-hover);
|
|
307
297
|
}
|
|
308
298
|
|
|
309
299
|
.tabbed-recompile-button:active {
|
|
310
|
-
background:
|
|
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:
|
|
323
|
-
color:
|
|
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
|
|
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:
|
|
338
|
-
color:
|
|
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 {
|
|
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:
|
|
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,
|
|
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"}
|