@stevejtrettel/shader-sandbox 0.1.2 → 0.1.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (113) hide show
  1. package/README.md +259 -235
  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 +16 -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
package/src/app/app.css CHANGED
@@ -1,45 +1,190 @@
1
1
  /**
2
- * App Styles - FPS counter and shader error overlay
2
+ * App Styles - Floating overlays on shader canvas
3
+ *
4
+ * All floating elements use consistent "liquid glass" styling:
5
+ * - Semi-transparent background with blur
6
+ * - Subtle border and shadow
7
+ * - 6px corner radius (smaller than canvas container's 8px per concentric radius rule)
3
8
  */
4
9
 
5
- /* ===== FPS Counter ===== */
6
- .fps-counter {
10
+ /* ===== Shared Glass Overlay Variables ===== */
11
+ :root {
12
+ --glass-bg: rgba(30, 30, 35, 0.65);
13
+ --glass-bg-hover: rgba(30, 30, 35, 0.8);
14
+ --glass-border: 1px solid rgba(255, 255, 255, 0.1);
15
+ --glass-shadow:
16
+ 0 4px 16px rgba(0, 0, 0, 0.25),
17
+ 0 2px 4px rgba(0, 0, 0, 0.15),
18
+ inset 0 1px 0 rgba(255, 255, 255, 0.1);
19
+ --glass-shadow-sm:
20
+ 0 2px 8px rgba(0, 0, 0, 0.25),
21
+ inset 0 1px 0 rgba(255, 255, 255, 0.08);
22
+ --glass-blur: blur(20px);
23
+ --glass-radius: 6px; /* all overlays use same radius, smaller than canvas (8px) */
24
+ --glass-radius-sm: 6px; /* same as above for consistency */
25
+ --glass-text: rgba(255, 255, 255, 0.9);
26
+ --glass-text-muted: rgba(255, 255, 255, 0.6);
27
+ }
28
+
29
+ /* ===== Stats Container (FPS + expandable stats) ===== */
30
+ .stats-container {
7
31
  position: absolute;
8
- bottom: 8px;
9
- left: 8px;
32
+ bottom: 12px;
33
+ left: 12px;
34
+ z-index: 1000;
35
+ display: flex;
36
+ flex-direction: column;
37
+ align-items: flex-start;
38
+ gap: 6px;
39
+ }
40
+
41
+ /* FPS Counter (clickable button) */
42
+ .fps-counter {
10
43
  padding: 6px 10px;
11
- background: rgba(0, 0, 0, 0.75);
12
- color: white;
44
+ background: var(--glass-bg);
45
+ color: var(--glass-text);
13
46
  font-family: 'Monaco', 'Menlo', 'Courier New', monospace;
14
- font-size: 12px;
47
+ font-size: 11px;
15
48
  font-weight: 500;
16
- border-radius: 4px;
17
- pointer-events: none;
49
+ border-radius: var(--glass-radius-sm);
50
+ border: var(--glass-border);
51
+ cursor: pointer;
18
52
  user-select: none;
19
- z-index: 1000;
20
- backdrop-filter: blur(4px);
21
- box-shadow: 0 2px 8px rgba(0, 0, 0, 0.3);
53
+ backdrop-filter: var(--glass-blur);
54
+ -webkit-backdrop-filter: var(--glass-blur);
55
+ box-shadow: var(--glass-shadow-sm);
56
+ transition: all 0.2s ease;
57
+ }
58
+
59
+ .fps-counter:hover {
60
+ background: var(--glass-bg-hover);
61
+ }
62
+
63
+ /* Stats Grid (expandable) */
64
+ .stats-grid {
65
+ display: flex;
66
+ flex-direction: row;
67
+ gap: 6px;
68
+ opacity: 0;
69
+ visibility: hidden;
70
+ transform: translateY(8px);
71
+ transition: opacity 0.2s ease, transform 0.2s ease, visibility 0.2s;
72
+ pointer-events: none;
73
+ }
74
+
75
+ .stats-grid.open {
76
+ opacity: 1;
77
+ visibility: visible;
78
+ transform: translateY(0);
79
+ pointer-events: auto;
80
+ }
81
+
82
+ /* Individual stat item */
83
+ .stat-item {
84
+ padding: 6px 10px;
85
+ background: var(--glass-bg);
86
+ border-radius: var(--glass-radius-sm);
87
+ border: var(--glass-border);
88
+ backdrop-filter: var(--glass-blur);
89
+ -webkit-backdrop-filter: var(--glass-blur);
90
+ box-shadow: var(--glass-shadow-sm);
91
+ display: flex;
92
+ flex-direction: column;
93
+ align-items: center;
94
+ gap: 2px;
95
+ min-width: 48px;
96
+ }
97
+
98
+ .stat-value {
99
+ color: var(--glass-text);
100
+ font-family: 'Monaco', 'Menlo', 'Courier New', monospace;
101
+ font-size: 11px;
102
+ font-weight: 600;
103
+ white-space: nowrap;
104
+ }
105
+
106
+ .stat-label {
107
+ color: var(--glass-text-muted);
108
+ font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
109
+ font-size: 9px;
110
+ font-weight: 500;
111
+ text-transform: uppercase;
112
+ letter-spacing: 0.5px;
22
113
  }
23
114
 
24
115
  /* ===== Playback Controls ===== */
25
116
  .playback-controls {
26
117
  position: absolute;
27
- bottom: 8px;
28
- right: 8px;
29
- display: flex;
30
- gap: 8px;
118
+ bottom: 12px;
119
+ right: 12px;
31
120
  z-index: 1000;
32
121
  }
33
122
 
123
+ /* Menu toggle button (+ / -) */
124
+ .controls-menu-button {
125
+ padding: 6px 8px;
126
+ background: var(--glass-bg);
127
+ color: var(--glass-text);
128
+ border: var(--glass-border);
129
+ border-radius: var(--glass-radius-sm);
130
+ cursor: pointer;
131
+ backdrop-filter: var(--glass-blur);
132
+ -webkit-backdrop-filter: var(--glass-blur);
133
+ box-shadow: var(--glass-shadow-sm);
134
+ transition: all 0.2s ease;
135
+ display: flex;
136
+ align-items: center;
137
+ justify-content: center;
138
+ width: 32px;
139
+ height: 32px;
140
+ font-size: 20px;
141
+ font-weight: 300;
142
+ line-height: 1;
143
+ }
144
+
145
+ .controls-menu-button:hover {
146
+ background: var(--glass-bg-hover);
147
+ transform: scale(1.05);
148
+ }
149
+
150
+ .controls-menu-button:active {
151
+ transform: scale(0.95);
152
+ }
153
+
154
+ /* Control buttons grid - 2x3 with menu button as last cell */
155
+ .controls-grid {
156
+ position: absolute;
157
+ bottom: 0;
158
+ right: 0;
159
+ display: grid;
160
+ grid-template-columns: 32px 32px 32px;
161
+ grid-template-rows: 32px 32px;
162
+ gap: 6px;
163
+ opacity: 0;
164
+ visibility: hidden;
165
+ transform: scale(0.8);
166
+ transform-origin: bottom right;
167
+ transition: opacity 0.2s ease, transform 0.2s ease, visibility 0.2s;
168
+ pointer-events: none;
169
+ }
170
+
171
+ .controls-grid.open {
172
+ opacity: 1;
173
+ visibility: visible;
174
+ transform: scale(1);
175
+ pointer-events: auto;
176
+ }
177
+
34
178
  .control-button {
35
179
  padding: 6px 8px;
36
- background: rgba(0, 0, 0, 0.75);
37
- color: white;
38
- border: none;
39
- border-radius: 4px;
180
+ background: var(--glass-bg);
181
+ color: var(--glass-text);
182
+ border: var(--glass-border);
183
+ border-radius: var(--glass-radius-sm);
40
184
  cursor: pointer;
41
- backdrop-filter: blur(4px);
42
- box-shadow: 0 2px 8px rgba(0, 0, 0, 0.3);
185
+ backdrop-filter: var(--glass-blur);
186
+ -webkit-backdrop-filter: var(--glass-blur);
187
+ box-shadow: var(--glass-shadow-sm);
43
188
  transition: all 0.2s ease;
44
189
  display: flex;
45
190
  align-items: center;
@@ -49,7 +194,7 @@
49
194
  }
50
195
 
51
196
  .control-button:hover {
52
- background: rgba(0, 0, 0, 0.85);
197
+ background: var(--glass-bg-hover);
53
198
  transform: scale(1.05);
54
199
  }
55
200
 
@@ -63,6 +208,18 @@
63
208
  fill: currentColor;
64
209
  }
65
210
 
211
+ /* Menu button - standalone when closed, part of grid when open */
212
+ .playback-controls .controls-menu-button {
213
+ position: relative;
214
+ z-index: 1;
215
+ }
216
+
217
+ /* When open, hide standalone button (it's now in the grid) */
218
+ .playback-controls.open > .controls-menu-button {
219
+ opacity: 0;
220
+ pointer-events: none;
221
+ }
222
+
66
223
  /* ===== Shader Error Overlay ===== */
67
224
  .shader-error-overlay {
68
225
  position: absolute;
@@ -206,3 +363,171 @@
206
363
  margin-left: -16px;
207
364
  padding-left: 13px;
208
365
  }
366
+
367
+ /* ===== WebGL Context Lost Overlay ===== */
368
+ .context-lost-overlay {
369
+ position: absolute;
370
+ top: 0;
371
+ left: 0;
372
+ right: 0;
373
+ bottom: 0;
374
+ background: rgba(0, 0, 0, 0.9);
375
+ backdrop-filter: blur(8px);
376
+ display: flex;
377
+ align-items: center;
378
+ justify-content: center;
379
+ z-index: 3000;
380
+ }
381
+
382
+ .context-lost-content {
383
+ text-align: center;
384
+ color: white;
385
+ padding: 40px;
386
+ }
387
+
388
+ .context-lost-icon {
389
+ margin-bottom: 16px;
390
+ opacity: 0.8;
391
+ }
392
+
393
+ .context-lost-spinner {
394
+ width: 48px;
395
+ height: 48px;
396
+ border: 3px solid rgba(255, 255, 255, 0.2);
397
+ border-top-color: white;
398
+ border-radius: 50%;
399
+ margin: 0 auto 16px;
400
+ animation: context-lost-spin 1s linear infinite;
401
+ }
402
+
403
+ @keyframes context-lost-spin {
404
+ to { transform: rotate(360deg); }
405
+ }
406
+
407
+ .context-lost-title {
408
+ font-size: 18px;
409
+ font-weight: 600;
410
+ margin-bottom: 8px;
411
+ font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
412
+ }
413
+
414
+ .context-lost-message {
415
+ font-size: 14px;
416
+ opacity: 0.7;
417
+ margin-bottom: 20px;
418
+ font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
419
+ }
420
+
421
+ .context-lost-reload {
422
+ background: white;
423
+ color: #000;
424
+ border: none;
425
+ padding: 10px 24px;
426
+ border-radius: 6px;
427
+ font-size: 14px;
428
+ font-weight: 500;
429
+ cursor: pointer;
430
+ transition: transform 0.2s, box-shadow 0.2s;
431
+ font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
432
+ }
433
+
434
+ .context-lost-reload:hover {
435
+ transform: scale(1.02);
436
+ box-shadow: 0 4px 12px rgba(255, 255, 255, 0.2);
437
+ }
438
+
439
+ .context-lost-reload:active {
440
+ transform: scale(0.98);
441
+ }
442
+
443
+ /* ===== Recording Indicator ===== */
444
+ .recording-indicator {
445
+ position: absolute;
446
+ top: 12px;
447
+ right: 12px;
448
+ z-index: 1000;
449
+ display: flex;
450
+ align-items: center;
451
+ gap: 6px;
452
+ padding: 6px 10px;
453
+ background: rgba(220, 38, 38, 0.85);
454
+ border-radius: var(--glass-radius-sm);
455
+ border: 1px solid rgba(255, 100, 100, 0.3);
456
+ backdrop-filter: var(--glass-blur);
457
+ -webkit-backdrop-filter: var(--glass-blur);
458
+ box-shadow: var(--glass-shadow-sm);
459
+ }
460
+
461
+ .recording-dot {
462
+ width: 8px;
463
+ height: 8px;
464
+ background: white;
465
+ border-radius: 50%;
466
+ animation: recording-pulse 1s ease-in-out infinite;
467
+ }
468
+
469
+ @keyframes recording-pulse {
470
+ 0%, 100% { opacity: 1; }
471
+ 50% { opacity: 0.4; }
472
+ }
473
+
474
+ .recording-text {
475
+ color: white;
476
+ font-family: 'Monaco', 'Menlo', 'Courier New', monospace;
477
+ font-size: 11px;
478
+ font-weight: 600;
479
+ letter-spacing: 0.5px;
480
+ }
481
+
482
+ /* Record button recording state */
483
+ .control-button.recording {
484
+ background: rgba(220, 38, 38, 0.7);
485
+ border-color: rgba(255, 100, 100, 0.3);
486
+ }
487
+
488
+ .control-button.recording:hover {
489
+ background: rgba(220, 38, 38, 0.85);
490
+ }
491
+
492
+ .control-button.recording svg {
493
+ fill: white;
494
+ }
495
+
496
+ /* ===== Media Permission Banner ===== */
497
+
498
+ .media-permission-banner {
499
+ position: absolute;
500
+ bottom: 48px;
501
+ left: 50%;
502
+ transform: translateX(-50%);
503
+ background: var(--glass-bg);
504
+ backdrop-filter: blur(12px);
505
+ -webkit-backdrop-filter: blur(12px);
506
+ border: var(--glass-border);
507
+ box-shadow: var(--glass-shadow);
508
+ color: rgba(255, 255, 255, 0.9);
509
+ padding: 8px 16px;
510
+ border-radius: 6px;
511
+ font-size: 13px;
512
+ font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
513
+ display: flex;
514
+ align-items: center;
515
+ gap: 12px;
516
+ z-index: 100;
517
+ white-space: nowrap;
518
+ }
519
+
520
+ .media-banner-button {
521
+ background: rgba(74, 158, 255, 0.8);
522
+ color: #fff;
523
+ border: none;
524
+ padding: 4px 12px;
525
+ border-radius: 4px;
526
+ cursor: pointer;
527
+ font-size: 13px;
528
+ font-family: inherit;
529
+ }
530
+
531
+ .media-banner-button:hover {
532
+ background: rgba(74, 158, 255, 1);
533
+ }
package/src/app/types.ts CHANGED
@@ -4,7 +4,7 @@
4
4
  * Types for the browser runtime coordinator.
5
5
  */
6
6
 
7
- import type { ShadertoyProject } from '../project/types';
7
+ import type { ShaderProject } from '../project/types';
8
8
 
9
9
  /**
10
10
  * Options for creating the App.
@@ -18,19 +18,67 @@ export interface AppOptions {
18
18
  /**
19
19
  * Loaded Shadertoy project.
20
20
  */
21
- project: ShadertoyProject;
21
+ project: ShaderProject;
22
22
 
23
23
  /**
24
24
  * Canvas pixel ratio (default: window.devicePixelRatio).
25
25
  * Set to 1 for performance, or higher for retina displays.
26
26
  */
27
27
  pixelRatio?: number;
28
+
29
+ /**
30
+ * Skip creating the floating uniforms panel.
31
+ * Used by 'ui' layout which has its own uniforms panel.
32
+ */
33
+ skipUniformsPanel?: boolean;
34
+
35
+ /**
36
+ * Skip creating the playback controls overlay.
37
+ * Used by 'ui' layout which has its own playback controls.
38
+ */
39
+ skipPlaybackControls?: boolean;
28
40
  }
29
41
 
30
42
  /**
31
- * Mouse state for iMouse uniform.
43
+ * Mouse state for iMouse uniform (Shadertoy spec).
32
44
  * Format: [x, y, clickX, clickY]
33
- * - x, y: current mouse position in pixels
34
- * - clickX, clickY: position of last click (or -1, -1 if no click)
45
+ * - x, y: mouse position while button is held (freezes on release)
46
+ * - clickX, clickY: click origin position (positive while held, negated on release)
47
+ * The sign of clickX serves as a "mouse is down" signal (z > 0.0 = pressed).
35
48
  */
36
49
  export type MouseState = [number, number, number, number];
50
+
51
+ /**
52
+ * Single touch point state.
53
+ * Format: [x, y, startX, startY]
54
+ * - x, y: current touch position in pixels
55
+ * - startX, startY: position where touch started
56
+ */
57
+ export type TouchPoint = [number, number, number, number];
58
+
59
+ /**
60
+ * Touch state for touch uniforms.
61
+ */
62
+ export interface TouchState {
63
+ /** Number of active touches (0-10) */
64
+ count: number;
65
+ /** Up to 3 tracked touches for shader uniforms */
66
+ touches: [TouchPoint, TouchPoint, TouchPoint];
67
+ /** Pinch scale factor (1.0 = no pinch, >1 = zoom in, <1 = zoom out) */
68
+ pinch: number;
69
+ /** Pinch change since last frame */
70
+ pinchDelta: number;
71
+ /** Center point of pinch gesture [x, y] */
72
+ pinchCenter: [number, number];
73
+ }
74
+
75
+ /**
76
+ * Internal pointer tracking for gesture recognition.
77
+ */
78
+ export interface PointerData {
79
+ id: number;
80
+ x: number;
81
+ y: number;
82
+ startX: number;
83
+ startY: number;
84
+ }
@@ -8,7 +8,7 @@
8
8
  * - Tab management for multiple passes
9
9
  */
10
10
 
11
- import { ShadertoyProject, PassName } from '../project/types';
11
+ import { ShaderProject, PassName } from '../project/types';
12
12
  import { RecompileHandler } from '../layouts/types';
13
13
 
14
14
  import './editor-panel.css';
@@ -25,7 +25,7 @@ interface EditorInstance {
25
25
 
26
26
  export class EditorPanel {
27
27
  private container: HTMLElement;
28
- private project: ShadertoyProject;
28
+ private project: ShaderProject;
29
29
  private recompileHandler: RecompileHandler | null = null;
30
30
 
31
31
  private tabBar: HTMLElement;
@@ -43,7 +43,7 @@ export class EditorPanel {
43
43
  // Track modified sources (passName -> modified source)
44
44
  private modifiedSources: Map<string, string> = new Map();
45
45
 
46
- constructor(container: HTMLElement, project: ShadertoyProject) {
46
+ constructor(container: HTMLElement, project: ShaderProject) {
47
47
  this.container = container;
48
48
  this.project = project;
49
49
 
@@ -121,7 +121,7 @@ export class EditorPanel {
121
121
  private buildTabs(): void {
122
122
  this.tabs = [];
123
123
 
124
- // 1. Common first (if exists)
124
+ // 1. Common (if exists)
125
125
  if (this.project.commonSource) {
126
126
  this.tabs.push({
127
127
  kind: 'code',
@@ -247,7 +247,7 @@ export class EditorPanel {
247
247
  imgContainer.className = 'editor-image-viewer';
248
248
 
249
249
  const img = document.createElement('img');
250
- img.src = tab.url;
250
+ img.src = (tab as ImageTab).url;
251
251
  img.alt = tab.name;
252
252
 
253
253
  imgContainer.appendChild(img);