fragment-tools 0.1.13 → 0.1.15

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 (184) hide show
  1. package/.prettierignore +1 -2
  2. package/.prettierrc +23 -7
  3. package/README.md +28 -9
  4. package/bin/index.js +70 -10
  5. package/package.json +14 -6
  6. package/src/cli/build.js +125 -0
  7. package/src/cli/create.js +238 -0
  8. package/src/cli/createConfig.js +82 -0
  9. package/src/cli/createFragmentFile.js +70 -0
  10. package/src/cli/getEntries.js +85 -0
  11. package/src/cli/log.js +36 -24
  12. package/src/cli/plugins/check-dependencies.js +88 -42
  13. package/src/cli/plugins/hot-shader-replacement.js +408 -0
  14. package/src/cli/plugins/hot-sketch-reload.js +21 -25
  15. package/src/cli/plugins/save.js +101 -0
  16. package/src/cli/preview.js +55 -0
  17. package/src/cli/prompts.js +260 -0
  18. package/src/cli/run.js +131 -0
  19. package/src/cli/templates/blank/index.js +33 -0
  20. package/src/cli/templates/blank/meta.json +4 -0
  21. package/src/cli/templates/default/index.js +39 -0
  22. package/src/cli/templates/default/meta.json +5 -0
  23. package/src/cli/templates/fragment-gl/index.js +37 -0
  24. package/src/cli/templates/fragment-gl/meta.json +4 -0
  25. package/src/cli/templates/p5/index.js +32 -0
  26. package/src/cli/templates/p5/meta.json +5 -0
  27. package/src/cli/templates/p5-webgl/fragment.fs +14 -0
  28. package/src/cli/templates/p5-webgl/index.js +67 -0
  29. package/src/cli/templates/p5-webgl/meta.json +5 -0
  30. package/src/cli/templates/three-fragment/fragment.fs +10 -0
  31. package/src/cli/templates/three-fragment/index.js +95 -0
  32. package/src/cli/templates/three-fragment/meta.json +5 -0
  33. package/src/cli/templates/three-orthographic/index.js +55 -0
  34. package/src/cli/templates/three-orthographic/meta.json +5 -0
  35. package/src/cli/templates/three-perspective/index.js +52 -0
  36. package/src/cli/templates/three-perspective/meta.json +5 -0
  37. package/src/cli/utils.js +70 -0
  38. package/src/cli/ws.js +87 -78
  39. package/src/client/app/App.svelte +3 -3
  40. package/src/client/app/client.js +55 -39
  41. package/src/client/app/components/IconCross.svelte +18 -18
  42. package/src/client/app/components/Init.svelte +40 -8
  43. package/src/client/app/components/KeyBinding.svelte +22 -22
  44. package/src/client/app/helpers.js +42 -0
  45. package/src/client/app/hooks.js +20 -0
  46. package/src/client/app/inputs/Input.js +9 -9
  47. package/src/client/app/inputs/Keyboard.js +13 -15
  48. package/src/client/app/inputs/MIDI.js +14 -15
  49. package/src/client/app/inputs/Mouse.js +1 -1
  50. package/src/client/app/inputs/Webcam.js +89 -88
  51. package/src/client/app/lib/canvas-recorder/CanvasRecorder.js +41 -21
  52. package/src/client/app/lib/canvas-recorder/FrameRecorder.js +7 -6
  53. package/src/client/app/lib/canvas-recorder/H264Recorder.js +45 -0
  54. package/src/client/app/lib/canvas-recorder/MP4Recorder.js +7 -9
  55. package/src/client/app/lib/canvas-recorder/WebMRecorder.js +3 -4
  56. package/src/client/app/lib/canvas-recorder/mp4.js +1649 -15
  57. package/src/client/app/lib/canvas-recorder/utils.js +33 -17
  58. package/src/client/app/lib/gl/Geometry.js +11 -8
  59. package/src/client/app/lib/gl/Program.js +38 -19
  60. package/src/client/app/lib/gl/Renderer.js +163 -156
  61. package/src/client/app/lib/gl/Texture.js +113 -85
  62. package/src/client/app/lib/gl/index.js +12 -12
  63. package/src/client/app/lib/gl/utils.js +1 -3
  64. package/src/client/app/lib/helpers/frameDebounce.js +30 -30
  65. package/src/client/app/lib/loader/index.js +10 -10
  66. package/src/client/app/lib/loader/loadImage.js +15 -15
  67. package/src/client/app/lib/loader/loadScript.js +1 -1
  68. package/src/client/app/lib/paper-sizes.js +75 -76
  69. package/src/client/app/lib/presets.js +25 -5
  70. package/src/client/app/lib/tempo/Analyser.js +18 -17
  71. package/src/client/app/lib/tempo/Range.js +15 -12
  72. package/src/client/app/lib/tempo/index.js +34 -27
  73. package/src/client/app/modules/AudioAnalyser/Range.svelte +69 -72
  74. package/src/client/app/modules/AudioAnalyser/Spectrum.svelte +20 -19
  75. package/src/client/app/modules/AudioAnalyser.svelte +52 -35
  76. package/src/client/app/modules/Console/ConsoleLine.svelte +193 -172
  77. package/src/client/app/modules/Console.svelte +76 -74
  78. package/src/client/app/modules/Exports.svelte +62 -43
  79. package/src/client/app/modules/MidiPanel.svelte +100 -101
  80. package/src/client/app/modules/Monitor.svelte +57 -57
  81. package/src/client/app/modules/Params.svelte +128 -103
  82. package/src/client/app/renderers/2DRenderer.js +3 -3
  83. package/src/client/app/renderers/FragmentRenderer.js +30 -23
  84. package/src/client/app/renderers/P5GLRenderer.js +144 -0
  85. package/src/client/app/renderers/P5Renderer.js +10 -7
  86. package/src/client/app/renderers/THREERenderer.js +136 -94
  87. package/src/client/app/stores/audioAnalysis.js +3 -4
  88. package/src/client/app/stores/console.js +9 -10
  89. package/src/client/app/stores/errors.js +1 -1
  90. package/src/client/app/stores/exports.js +36 -20
  91. package/src/client/app/stores/index.js +2 -2
  92. package/src/client/app/stores/layout.js +143 -138
  93. package/src/client/app/stores/multisampling.js +4 -4
  94. package/src/client/app/stores/props.js +76 -13
  95. package/src/client/app/stores/renderers.js +26 -15
  96. package/src/client/app/stores/rendering.js +108 -89
  97. package/src/client/app/stores/sketches.js +7 -9
  98. package/src/client/app/stores/time.js +18 -18
  99. package/src/client/app/stores/utils.js +95 -38
  100. package/src/client/app/transitions/fade.js +3 -3
  101. package/src/client/app/transitions/index.js +6 -7
  102. package/src/client/app/transitions/splitX.js +2 -2
  103. package/src/client/app/transitions/splitY.js +2 -2
  104. package/src/client/app/triggers/Keyboard.js +88 -79
  105. package/src/client/app/triggers/MIDI.js +110 -84
  106. package/src/client/app/triggers/Mouse.js +73 -65
  107. package/src/client/app/triggers/Trigger.js +59 -58
  108. package/src/client/app/triggers/index.js +7 -7
  109. package/src/client/app/triggers/shared.js +5 -5
  110. package/src/client/app/ui/Build.svelte +70 -71
  111. package/src/client/app/ui/ErrorOverlay.svelte +118 -104
  112. package/src/client/app/ui/Field.svelte +393 -258
  113. package/src/client/app/ui/FieldGroup.svelte +106 -94
  114. package/src/client/app/ui/FieldSection.svelte +127 -116
  115. package/src/client/app/ui/FieldSpace.svelte +29 -30
  116. package/src/client/app/ui/FieldTrigger.svelte +256 -244
  117. package/src/client/app/ui/FieldTriggers.svelte +46 -46
  118. package/src/client/app/ui/FloatingParams.svelte +29 -30
  119. package/src/client/app/ui/Layout.svelte +31 -32
  120. package/src/client/app/ui/LayoutColumn.svelte +4 -4
  121. package/src/client/app/ui/LayoutComponent.svelte +239 -225
  122. package/src/client/app/ui/LayoutResizer.svelte +195 -176
  123. package/src/client/app/ui/LayoutRoot.svelte +6 -6
  124. package/src/client/app/ui/LayoutRow.svelte +4 -4
  125. package/src/client/app/ui/LayoutToolbar.svelte +191 -194
  126. package/src/client/app/ui/Module.svelte +134 -135
  127. package/src/client/app/ui/ModuleHeaderAction.svelte +81 -78
  128. package/src/client/app/ui/ModuleHeaderButton.svelte +12 -12
  129. package/src/client/app/ui/ModuleHeaderSelect.svelte +47 -37
  130. package/src/client/app/ui/ModuleRenderer.svelte +26 -27
  131. package/src/client/app/ui/OutputRenderer.svelte +112 -105
  132. package/src/client/app/ui/ParamsMultisampling.svelte +96 -95
  133. package/src/client/app/ui/ParamsOutput.svelte +130 -113
  134. package/src/client/app/ui/Preview.svelte +7 -8
  135. package/src/client/app/ui/SelectChevrons.svelte +27 -15
  136. package/src/client/app/ui/SketchRenderer.svelte +780 -667
  137. package/src/client/app/ui/SketchSelect.svelte +50 -44
  138. package/src/client/app/ui/fields/ButtonInput.svelte +61 -48
  139. package/src/client/app/ui/fields/CheckboxInput.svelte +67 -61
  140. package/src/client/app/ui/fields/ColorInput.svelte +294 -238
  141. package/src/client/app/ui/fields/FieldInputRow.svelte +8 -8
  142. package/src/client/app/ui/fields/ImageInput.svelte +123 -121
  143. package/src/client/app/ui/fields/Input.svelte +100 -111
  144. package/src/client/app/ui/fields/IntervalInput.svelte +268 -0
  145. package/src/client/app/ui/fields/ListInput.svelte +96 -96
  146. package/src/client/app/ui/fields/NumberInput.svelte +120 -116
  147. package/src/client/app/ui/fields/ProgressInput.svelte +99 -73
  148. package/src/client/app/ui/fields/Select.svelte +137 -124
  149. package/src/client/app/ui/fields/TextInput.svelte +10 -11
  150. package/src/client/app/ui/fields/VectorInput.svelte +86 -82
  151. package/src/client/app/utils/canvas.utils.js +189 -208
  152. package/src/client/app/utils/color.utils.js +138 -101
  153. package/src/client/app/utils/fields.utils.js +131 -0
  154. package/src/client/app/utils/file.utils.js +209 -37
  155. package/src/client/app/utils/glsl.utils.js +2 -2
  156. package/src/client/app/utils/glslErrors.js +49 -31
  157. package/src/client/app/utils/index.js +32 -29
  158. package/src/client/app/utils/math.utils.js +14 -10
  159. package/src/client/index.html +16 -16
  160. package/src/client/main.js +4 -4
  161. package/src/client/public/css/global.css +26 -16
  162. package/src/cli/db.js +0 -17
  163. package/src/cli/index.js +0 -198
  164. package/src/cli/plugins/db.js +0 -12
  165. package/src/cli/plugins/hot-shader-reload.js +0 -86
  166. package/src/cli/plugins/screenshot.js +0 -46
  167. package/src/cli/server.js +0 -153
  168. package/src/cli/templates/2d.js +0 -15
  169. package/src/cli/templates/blank.js +0 -13
  170. package/src/cli/templates/fragment.js +0 -18
  171. package/src/cli/templates/index.js +0 -27
  172. package/src/cli/templates/p5.js +0 -13
  173. package/src/cli/templates/three-fragment.js +0 -53
  174. package/src/cli/templates/three-orthographic.js +0 -23
  175. package/src/cli/templates/three-perspective.js +0 -20
  176. package/src/client/app/lib/canvas-recorder/FFMPEGRecorder.js +0 -56
  177. package/src/client/app/utils/props.utils.js +0 -51
  178. package/src/client/public/fonts/Inter-Bold.woff2 +0 -0
  179. package/src/client/public/fonts/Inter-Italic.woff2 +0 -0
  180. package/src/client/public/fonts/Inter-Regular.woff2 +0 -0
  181. package/src/client/public/fonts/Inter-SemiBold.woff2 +0 -0
  182. package/src/client/public/js/ffmpeg.min.js +0 -2
  183. package/src/client/public/js/ffmpeg.min.js.map +0 -1
  184. /package/src/cli/templates/{fragment.fs → fragment-gl/fragment.fs} +0 -0
@@ -1,587 +1,700 @@
1
1
  <script>
2
- import { onMount, onDestroy } from "svelte";
3
- import { derived } from "svelte/store";
4
- import KeyBinding from "../components/KeyBinding.svelte";
5
- import { sketches, sketchesKeys } from "../stores/sketches.js";
6
- import { layout } from "../stores/layout.js";
7
- import { rendering, SIZES, sync, monitors } from "../stores/rendering.js";
8
- import { current as currentTime } from "../stores/time.js";
9
- import { errors, displayError, clearError } from "../stores/errors.js";
10
- import { exports, props } from "../stores/index.js";
11
- import { findRenderer } from "../stores/renderers";
12
- import { recording, capturing } from "../stores/exports.js";
13
- import { removeHotListeners } from "../triggers/index.js";
14
- import { checkForTriggersDown, checkForTriggersMove, checkForTriggersUp, checkForTriggersClick } from "../triggers/Mouse.js";
15
- import { client } from "../client";
16
- import { recordCanvas, screenshotCanvas } from "../utils/canvas.utils.js";
17
- import ErrorOverlay from "./ErrorOverlay.svelte";
18
-
19
- export let key;
20
- export let id = 0;
21
- export let paused = false;
22
- export let visible = true;
23
-
24
- let node, container;
25
- let framerate = 60;
26
- let elapsed = 0;
27
- let elapsedRenderingTime = 0;
28
- let now = performance.now(), then = performance.now(), dt = 0, lastTime = performance.now();
29
- let canvas;
30
- let _raf;
31
- let _key = key;
32
-
33
- let sketch;
34
- let _created = false, _errored = false;
35
- let renderer;
36
- let noop = () => {};
37
- let _renderSketch = noop;
38
- let backgroundColor = "inherit";
39
-
40
- function checkForResize() {
41
- if (!node) return;
42
-
43
- let needsUpdate = $rendering.resizing === SIZES.WINDOW || $rendering.resizing === SIZES.ASPECT_RATIO;
44
-
45
- let newWidth, newHeight;
46
-
47
- if ($rendering.resizing === SIZES.WINDOW) {
48
- newWidth = node.offsetWidth;
49
- newHeight = node.offsetHeight;
50
- } else if ($rendering.resizing === SIZES.ASPECT_RATIO) {
51
- const { offsetWidth, offsetHeight } = node;
52
- const aspectRatio = $rendering.aspectRatio;
53
- const monitorRatio = offsetWidth / offsetHeight;
54
-
55
- if (aspectRatio < monitorRatio) {
56
- newHeight = offsetHeight;
57
- newWidth = newHeight * aspectRatio;
58
- } else {
59
- newWidth = offsetWidth;
60
- newHeight = newWidth / aspectRatio;
61
- }
62
- }
63
-
64
- needsUpdate = needsUpdate && (newWidth !== $rendering.width || newHeight !== $rendering.height);
65
-
66
- if (needsUpdate) {
67
- rendering.update(curr => {
68
- return {
69
- ...curr,
70
- width: newWidth,
71
- height: newHeight,
72
- }
73
- });
74
- }
75
- }
76
-
77
- let resizeObserver = new ResizeObserver(() => {
78
- checkForResize();
79
- });
80
-
81
- let params = {};
82
-
83
- let sketchProps = derived(props, () => {
84
- return $props[key];
85
- });
86
-
87
- let needsRender = false;
88
-
89
- sketchProps.subscribe(() => {
90
- if (framerate === 0) {
91
- // ensure we don't double render from createSketch
92
- requestAnimationFrame(() => {
93
- needsRender = true;
94
- })
95
- }
96
- });
97
-
98
- layout.subscribe(() => {
99
- setBackgroundColor();
100
- });
101
-
102
- function createCanvas(canvas = document.createElement('canvas')) {
103
- canvas.width = $rendering.width * $rendering.pixelRatio;
104
- canvas.height = $rendering.height * $rendering.pixelRatio;
105
-
106
- canvas.onmousedown = (event) => checkForTriggersDown(event, key);
107
- canvas.onmousemove = (event) => checkForTriggersMove(event, key);
108
- canvas.onmouseup = (event) => checkForTriggersUp(event, key);
109
- canvas.onclick = (event) => checkForTriggersClick(event, key);
110
-
111
- container.appendChild(canvas);
112
-
113
- $monitors = $monitors.map((monitor) => {
114
- if (monitor.id === id) {
115
- return {...monitor, canvas };
116
- }
117
-
118
- return monitor;
119
- })
120
-
121
- return canvas;
122
- }
123
-
124
- function destroyCanvas(canvas) {
125
- canvas.onmousedown = null;
126
- canvas.onmousemove = null;
127
- canvas.onmouseup = null;
128
- canvas.onclick = null;
129
-
130
- if (canvas.parentNode === container) {
131
- canvas.parentNode.removeChild(canvas);
132
- }
133
-
134
- canvas = null;
135
- }
136
-
137
- function setBackgroundColor() {
138
- if (sketch) {
139
- if (($layout.previewing || __BUILD__) && sketch.buildConfig && sketch.buildConfig.backgroundColor) {
140
- backgroundColor = sketch.buildConfig.backgroundColor;
141
- } else if (!$layout.previewing && sketch.backgroundColor) {
142
- backgroundColor = sketch.backgroundColor;
143
- } else {
144
- backgroundColor = "inherit";
145
- }
146
- } else {
147
- backgroundColor = "inherit";
148
- }
149
- }
150
-
151
- async function createSketch(key) {
152
- _created = false;
153
-
154
- sketch = $sketches[key];
155
-
156
- if (!key || !sketch) {
157
- _errored = true;
158
-
159
- if (_raf) {
160
- cancelAnimationFrame(_raf);
161
- _raf = null;
162
- }
163
-
164
- return;
165
- }
166
-
167
- clearError(key);
168
- setBackgroundColor();
169
-
170
- if (canvas) {
171
- if (renderer && typeof renderer.onDestroyPreview === "function") {
172
- renderer.onDestroyPreview({ id, canvas });
173
- }
174
-
175
- destroyCanvas(canvas);
176
- }
177
-
178
- renderer = await findRenderer(sketch.rendering);
179
-
180
- if (!container) return;
181
-
182
- canvas = createCanvas();
183
-
184
- if ($rendering.resizing === SIZES.SCALE) {
185
- canvas.style.transform = `scale(${$rendering.scale})`;
186
- } else {
187
- canvas.style.transform = null;
188
- }
189
-
190
- removeHotListeners(key);
191
-
192
- let mountParams = {};
193
-
194
- if (renderer && typeof renderer.onMountPreview === "function") {
195
- mountParams = renderer.onMountPreview({
196
- id,
197
- canvas,
198
- width: $rendering.width,
199
- height: $rendering.height,
200
- pixelRatio: $rendering.pixelRatio,
201
- });
202
- }
203
-
204
- if (mountParams.canvas && mountParams.canvas !== canvas) {
205
- destroyCanvas(canvas);
206
- canvas = createCanvas(mountParams.canvas);
207
- }
208
-
209
- params = {
210
- ...mountParams,
211
- canvas,
212
- };
213
-
214
- framerate = isFinite(sketch.fps) ? sketch.fps : 60;
215
-
216
- const init = sketch.setup || sketch.init || noop;
217
- const resize = sketch.resize || noop;
218
- const { width, height, pixelRatio } = $rendering;
219
-
220
- try {
221
-
222
- elapsedRenderingTime = 0;
223
-
224
- if (sketch.load) {
225
- await sketch.load();
226
- }
227
-
228
- init({
229
- width,
230
- height,
231
- pixelRatio,
232
- props,
233
- ...params,
234
- });
235
-
236
- resize({
237
- canvas,
238
- width,
239
- height,
240
- pixelRatio,
241
- props,
242
- ...params,
243
- });
244
-
245
- _created = true;
246
- _errored = false;
247
-
248
- _renderSketch = createRenderLoop();
249
-
250
- requestAnimationFrame(() => {
251
- needsRender = true;
252
-
253
- if (!_raf) {
254
- render();
255
- }
256
- });
257
-
258
-
259
- } catch(error) {
260
- onError(error);
261
- }
262
- }
263
-
264
- /**
265
- *
266
- * @param {Error} error
267
- */
268
- function onError(error) {
269
- _errored = true;
270
- console.error(error);
271
-
272
- displayError(error, key);
273
-
274
- cancelAnimationFrame(_raf);
275
- _raf = null;
276
- }
277
-
278
- let record = $recording;
279
- let capture = $capturing;
280
-
281
- $: {
282
- if ($recording && !record) {
283
- let recordOptions = {
284
- onTick: _renderSketch,
285
- framerate: $exports.framerate,
286
- filename: key,
287
- pattern: sketch?.filenamePattern,
288
- format: $exports.videoFormat,
289
- imageEncoding: $exports.imageEncoding,
290
- quality: $exports.videoQuality,
291
- params: {
292
- props: sketch.props,
293
- },
294
- onStart: () => {
295
- elapsedRenderingTime = 0;
296
- paused = true;
297
- },
298
- onComplete: () => {
299
- $recording = false;
300
- record = null;
301
- paused = false;
302
- }
303
- };
304
-
305
- if ($exports.useDuration) {
306
- recordOptions.duration = sketch.duration * $exports.loopCount;
307
- }
308
-
309
- record = recordCanvas(canvas, recordOptions);
310
- }
311
-
312
- if (record && !$recording) {
313
- record.stop();
314
- record = false;
315
- }
316
- }
317
-
318
- $: {
319
- if (!capture && $capturing) {
320
- save();
321
- }
322
- }
323
-
324
- function createRenderLoop() {
325
- const { width, height, pixelRatio } = $rendering;
326
- const draw = sketch.draw || sketch.update;
327
- const { duration } = sketch;
328
-
329
- let playhead = 0;
330
- let playcount = 0;
331
- let hasDuration = isFinite(duration);
332
-
333
- let onBeforeUpdatePreview = (renderer && renderer.onBeforeUpdatePreview) || noop;
334
- let onAfterUpdatePreview = (renderer && renderer.onAfterUpdatePreview) || noop;
335
-
336
- let frameLength = 1000 / framerate;
337
- let frameCount = framerate * duration;
338
- let interval = 1 / frameCount;
339
-
340
- return ({ time = performance.now(), deltaTime = time - lastTime } = {}) => {
341
- needsRender = false;
342
- lastTime = time;
343
-
344
- try {
345
- onBeforeUpdatePreview({ id, canvas });
346
-
347
- let t = !$sync ? elapsedRenderingTime : Math.floor(time / frameLength) * frameLength;
348
-
349
- if (hasDuration && framerate > 0) {
350
- playhead = (t / 1000) / duration;
351
- playhead %= 1;
352
- playhead = Math.floor(playhead / interval) * interval;
353
- playcount = Math.floor(elapsedRenderingTime / 1000 / duration);
354
- }
355
-
356
- draw({
357
- ...renderer,
358
- ...params,
359
- props: sketch.props,
360
- playhead,
361
- playcount,
362
- width,
363
- height,
364
- pixelRatio,
365
- time: t,
366
- deltaTime,
367
- });
368
- onAfterUpdatePreview({ id, canvas });
369
-
370
- elapsedRenderingTime += deltaTime;
371
- } catch(error) {
372
- onError(error);
373
- }
374
- };
375
- }
376
-
377
- function render() {
378
- _raf = requestAnimationFrame(render);
379
-
380
- now = performance.now();
381
- dt = now - then;
382
- then = now;
383
-
384
- if (!paused) {
385
- elapsed += dt;
386
-
387
- if (!$sync) {
388
- if ((elapsed) >= ((1 / framerate) * 1000)) {
389
- elapsed = 0;
390
- _renderSketch();
391
- }
392
- } else {
393
- _renderSketch();
394
- }
395
- } else {
396
- lastTime = now;
397
- }
398
-
399
- if (needsRender) {
400
- _renderSketch();
401
- }
402
- }
403
-
404
- $: {
405
- if (canvas && _key !== key) {
406
- if (_created) {
407
- clearError(_key);
408
- }
409
-
410
- _key = key;
411
- createSketch(key);
412
- }
413
- }
414
-
415
- rendering.subscribe((current) => {
416
- if (canvas && _created) {
417
- if (current.resizing === SIZES.SCALE) {
418
- canvas.style.transform = `scale(${current.scale})`;
419
- } else {
420
- canvas.style.transform = null;
421
- }
422
-
423
- const { width, height, pixelRatio } = current;
424
- const resize = sketch.resize || noop;
425
-
426
- resize({
427
- canvas,
428
- width,
429
- height,
430
- pixelRatio,
431
- ...params,
432
- });
433
-
434
- _renderSketch = createRenderLoop();
435
- needsRender = true;
436
- }
437
- });
438
-
439
- async function save() {
440
- paused = true;
441
-
442
- _renderSketch();
443
-
444
- await screenshotCanvas(canvas, {
445
- filename: key,
446
- pattern: sketch?.filenamePattern,
447
- params: {
448
- props: sketch.props,
449
- }
450
- });
451
- paused = false;
452
- $capturing = false;
453
- }
454
-
455
- sketches.subscribe(() => {
456
- if (_created || _errored) {
457
- createSketch(key);
458
- }
459
- });
460
-
461
- sync.subscribe(() => {
462
- if (_created) {
463
- _renderSketch = createRenderLoop();
464
- }
465
- });
466
-
467
- onMount(() => {
468
- createSketch(key);
469
-
470
- client.on('shader-update', () => {
471
- if (framerate === 0) {
472
- needsRender = true;
473
- }
474
- });
475
-
476
- resizeObserver.observe(node);
477
- })
478
-
479
- function checkForPause(event) {
480
- const keyboardEvent = event.detail;
481
-
482
- if (!keyboardEvent.metaKey || !keyboardEvent.ctrlKey) {
483
- keyboardEvent.preventDefault();
484
-
485
- if (!$recording) {
486
- then = performance.now();
487
- paused = !paused;
488
- } else {
489
- console.warn(`Cannot pause while recording.`);
490
- }
491
- }
492
- }
493
-
494
- function checkForSave(event) {
495
- const keyboardEvent = event.detail;
496
-
497
- if (keyboardEvent.metaKey || keyboardEvent.ctrlKey) {
498
- keyboardEvent.preventDefault();
499
-
500
- if (!$recording) {
501
- save();
502
- } else {
503
- console.warn(`Cannot save while recording.`);
504
- }
505
- }
506
- }
507
-
508
- function checkForRecord(event) {
509
- const keyboardEvent = event.detail;
510
- keyboardEvent.preventDefault();
511
-
512
- $recording = !$recording;
513
- }
514
-
515
- function checkForRefresh(event) {
516
- const keyboardEvent = event.detail;
517
- if (!keyboardEvent.metaKey && !keyboardEvent.ctrlKey) {
518
- keyboardEvent.preventDefault();
519
- console.log(`[fragment] ${key} reloaded.`);
520
- createSketch(key);
521
- }
522
- }
523
-
524
- onDestroy(() => {
525
- resizeObserver.unobserve(node);
526
- cancelAnimationFrame(_raf);
527
-
528
- if (renderer && typeof renderer.onDestroyPreview === "function") {
529
- renderer.onDestroyPreview({ id, canvas });
530
- }
531
-
532
- renderer = null;
533
-
534
- if (canvas) {
535
- destroyCanvas(canvas);
536
- }
537
-
538
- _created = false;
539
- });
540
-
541
- $: {
542
- checkForResize();
543
-
544
- if (renderer && typeof renderer.onResizePreview === "function") {
545
- renderer.onResizePreview({
546
- id,
547
- width: $rendering.width,
548
- height: $rendering.height,
549
- pixelRatio: $rendering.pixelRatio,
550
- });
551
- }
552
-
553
- if (canvas) {
554
- const pixelRatio = $rendering.pixelRatio;
555
-
556
- canvas.width = $rendering.width * pixelRatio;
557
- canvas.height = $rendering.height * pixelRatio;
558
- }
559
- }
560
-
561
- $: error = (key && $errors.has(key)) ? $errors.get(key) : // display error if error context match current key
562
- $errors.size === 1 &&
563
- ![...$errors.keys()].some((key) => $sketchesKeys.includes(key)) &&
564
- (
565
- $monitors.length === 1 || // if there's only one monitor
566
- !$monitors.some(m => m.selected === $errors.keys().next().value) // if none of current monitors match the key
567
- ) ? $errors.get($errors.keys().next().value) : null;
2
+ import { onMount, onDestroy } from 'svelte';
3
+ import { derived } from 'svelte/store';
4
+ import KeyBinding from '../components/KeyBinding.svelte';
5
+ import { sketches, sketchesKeys } from '../stores/sketches.js';
6
+ import { layout } from '../stores/layout.js';
7
+ import { rendering, SIZES, sync, monitors } from '../stores/rendering.js';
8
+ import { errors, displayError, clearError } from '../stores/errors.js';
9
+ import { exports, props } from '../stores/index.js';
10
+ import { findRenderer } from '../stores/renderers';
11
+ import { map } from '../utils/math.utils';
12
+ import {
13
+ recording,
14
+ capturing,
15
+ beforeCapture,
16
+ afterCapture,
17
+ beforeRecord,
18
+ afterRecord,
19
+ } from '../stores/exports.js';
20
+ import { removeHotListeners } from '../triggers/index.js';
21
+ import { removeHooksFrom } from '../hooks';
22
+ import {
23
+ checkForTriggersDown,
24
+ checkForTriggersMove,
25
+ checkForTriggersUp,
26
+ checkForTriggersClick,
27
+ } from '../triggers/Mouse.js';
28
+ import { client } from '../client';
29
+ import { recordCanvas, screenshotCanvas } from '../utils/canvas.utils.js';
30
+ import ErrorOverlay from './ErrorOverlay.svelte';
31
+ import { resetProps } from '../stores/props';
32
+
33
+ export let key;
34
+ export let id = 0;
35
+ export let paused = false;
36
+ export let visible = true;
37
+
38
+ let node, container;
39
+ let framerate = 60;
40
+ let elapsed = 0;
41
+ let elapsedRenderingTime = 0;
42
+ let now = performance.now(),
43
+ then = performance.now(),
44
+ dt = 0,
45
+ lastTime = performance.now();
46
+ let canvas;
47
+ let _raf;
48
+ let _key = key;
49
+
50
+ let sketch;
51
+ let _created = false,
52
+ _errored = false;
53
+ let renderer;
54
+ let noop = () => {};
55
+ let _renderSketch = noop;
56
+ let backgroundColor = 'inherit';
57
+
58
+ $: beforeCaptureCallbacks = $beforeCapture.get(key) || [];
59
+ $: afterCaptureCallbacks = $afterCapture.get(key) || [];
60
+ $: beforeRecordCallbacks = $beforeRecord.get(key) || [];
61
+ $: afterRecordCallbacks = $afterRecord.get(key) || [];
62
+
63
+ function checkForResize() {
64
+ if (!node) return;
65
+
66
+ let needsUpdate =
67
+ $rendering.resizing === SIZES.WINDOW ||
68
+ $rendering.resizing === SIZES.ASPECT_RATIO;
69
+
70
+ let newWidth, newHeight;
71
+
72
+ if ($rendering.resizing === SIZES.WINDOW) {
73
+ newWidth = node.offsetWidth;
74
+ newHeight = node.offsetHeight;
75
+ } else if ($rendering.resizing === SIZES.ASPECT_RATIO) {
76
+ const { offsetWidth, offsetHeight } = node;
77
+ const aspectRatio = $rendering.aspectRatio;
78
+ const monitorRatio = offsetWidth / offsetHeight;
79
+
80
+ if (aspectRatio < monitorRatio) {
81
+ newHeight = offsetHeight;
82
+ newWidth = newHeight * aspectRatio;
83
+ } else {
84
+ newWidth = offsetWidth;
85
+ newHeight = newWidth / aspectRatio;
86
+ }
87
+ }
88
+
89
+ needsUpdate =
90
+ needsUpdate &&
91
+ (newWidth !== $rendering.width || newHeight !== $rendering.height);
92
+
93
+ if (needsUpdate) {
94
+ rendering.update((curr) => {
95
+ return {
96
+ ...curr,
97
+ width: newWidth,
98
+ height: newHeight,
99
+ };
100
+ });
101
+ }
102
+ }
103
+
104
+ let resizeObserver = new ResizeObserver(() => {
105
+ checkForResize();
106
+ });
107
+
108
+ let params = {};
109
+
110
+ let sketchProps = derived(props, () => {
111
+ return $props[key];
112
+ });
113
+
114
+ let needsRender = false;
115
+
116
+ sketchProps.subscribe(() => {
117
+ if (framerate === 0) {
118
+ // ensure we don't double render from createSketch
119
+ requestAnimationFrame(() => {
120
+ needsRender = true;
121
+ });
122
+ }
123
+ });
124
+
125
+ layout.subscribe(() => {
126
+ setBackgroundColor();
127
+ });
128
+
129
+ function createCanvas(canvas = document.createElement('canvas')) {
130
+ canvas.width = $rendering.width * $rendering.pixelRatio;
131
+ canvas.height = $rendering.height * $rendering.pixelRatio;
132
+
133
+ canvas.onmousedown = (event) => checkForTriggersDown(event, key);
134
+ canvas.onmousemove = (event) => checkForTriggersMove(event, key);
135
+ canvas.onmouseup = (event) => checkForTriggersUp(event, key);
136
+ canvas.onclick = (event) => checkForTriggersClick(event, key);
137
+
138
+ container.appendChild(canvas);
139
+
140
+ $monitors = $monitors.map((monitor) => {
141
+ if (monitor.id === id) {
142
+ return { ...monitor, canvas };
143
+ }
144
+
145
+ return monitor;
146
+ });
147
+
148
+ return canvas;
149
+ }
150
+
151
+ function destroyCanvas(canvas) {
152
+ canvas.onmousedown = null;
153
+ canvas.onmousemove = null;
154
+ canvas.onmouseup = null;
155
+ canvas.onclick = null;
156
+
157
+ if (canvas.parentNode === container) {
158
+ canvas.parentNode.removeChild(canvas);
159
+ }
160
+
161
+ canvas = null;
162
+ }
163
+
164
+ function setBackgroundColor() {
165
+ if (sketch) {
166
+ if (
167
+ ($layout.previewing || __BUILD__) &&
168
+ sketch.buildConfig &&
169
+ sketch.buildConfig.backgroundColor
170
+ ) {
171
+ backgroundColor = sketch.buildConfig.backgroundColor;
172
+ } else if (!$layout.previewing && sketch.backgroundColor) {
173
+ backgroundColor = sketch.backgroundColor;
174
+ } else {
175
+ backgroundColor = 'inherit';
176
+ }
177
+ } else {
178
+ backgroundColor = 'inherit';
179
+ }
180
+ }
181
+
182
+ async function createSketch(key) {
183
+ _created = false;
184
+
185
+ sketch = $sketches[key];
186
+
187
+ if (!key || !sketch) {
188
+ _errored = true;
189
+
190
+ if (_raf) {
191
+ cancelAnimationFrame(_raf);
192
+ _raf = null;
193
+ }
194
+
195
+ return;
196
+ }
197
+
198
+ clearError(key);
199
+ setBackgroundColor();
200
+
201
+ if (canvas) {
202
+ if (renderer && typeof renderer.onDestroyPreview === 'function') {
203
+ renderer.onDestroyPreview({ id, canvas });
204
+ }
205
+
206
+ destroyCanvas(canvas);
207
+ }
208
+
209
+ renderer = await findRenderer({
210
+ rendering: sketch.rendering,
211
+ renderer: sketch.renderer,
212
+ });
213
+
214
+ if (!container) return;
215
+
216
+ canvas = createCanvas();
217
+
218
+ if ($rendering.resizing === SIZES.SCALE) {
219
+ canvas.style.transform = `scale(${$rendering.scale})`;
220
+ } else {
221
+ canvas.style.transform = null;
222
+ }
223
+
224
+ removeHotListeners(key);
225
+ removeHooksFrom(key);
226
+
227
+ let mountParams = {};
228
+
229
+ if (renderer && typeof renderer.onMountPreview === 'function') {
230
+ mountParams = renderer.onMountPreview({
231
+ id,
232
+ canvas,
233
+ container,
234
+ width: $rendering.width,
235
+ height: $rendering.height,
236
+ pixelRatio: $rendering.pixelRatio,
237
+ });
238
+ }
239
+
240
+ if (mountParams.canvas && mountParams.canvas !== canvas) {
241
+ destroyCanvas(canvas);
242
+ canvas = createCanvas(mountParams.canvas);
243
+ }
244
+
245
+ params = {
246
+ ...mountParams,
247
+ canvas,
248
+ publicPath: `@fs${__CWD__}`,
249
+ };
250
+
251
+ framerate = isFinite(sketch.fps) ? sketch.fps : 60;
252
+
253
+ const init = sketch.setup || sketch.init || noop;
254
+ const resize = sketch.resize || noop;
255
+ const { width, height, pixelRatio } = $rendering;
256
+
257
+ try {
258
+ elapsedRenderingTime = 0;
259
+
260
+ if (sketch.load) {
261
+ await sketch.load({
262
+ width,
263
+ height,
264
+ pixelRatio,
265
+ props: $sketchProps,
266
+ ...params,
267
+ });
268
+ }
269
+
270
+ init({
271
+ width,
272
+ height,
273
+ pixelRatio,
274
+ props: $sketchProps,
275
+ ...params,
276
+ });
277
+
278
+ resize({
279
+ canvas,
280
+ width,
281
+ height,
282
+ pixelRatio,
283
+ props: $sketchProps,
284
+ ...params,
285
+ });
286
+
287
+ _created = true;
288
+ _errored = false;
289
+
290
+ _renderSketch = createRenderLoop();
291
+
292
+ requestAnimationFrame(() => {
293
+ needsRender = true;
294
+
295
+ if (!_raf) {
296
+ render();
297
+ }
298
+ });
299
+ } catch (error) {
300
+ onError(error);
301
+ }
302
+ }
303
+
304
+ /**
305
+ *
306
+ * @param {Error} error
307
+ */
308
+ function onError(error) {
309
+ _errored = true;
310
+ console.error(error);
311
+
312
+ displayError(error, key);
313
+
314
+ cancelAnimationFrame(_raf);
315
+ _raf = null;
316
+ }
317
+
318
+ let record = $recording;
319
+ let capture = $capturing;
320
+
321
+ $: {
322
+ const recordArgs = {
323
+ encoding: $exports.videoFormat,
324
+ quality: $exports.videoQuality,
325
+ framerate: $exports.framerate,
326
+ };
327
+
328
+ function onRecordEnd() {
329
+ record = null;
330
+ paused = false;
331
+
332
+ afterRecordCallbacks.forEach((callback) => {
333
+ callback(recordArgs);
334
+ });
335
+
336
+ _renderSketch();
337
+ }
338
+
339
+ if ($recording && !record) {
340
+ let recordOptions = {
341
+ onTick: _renderSketch,
342
+ framerate: $exports.framerate,
343
+ filename: key,
344
+ exportDir: sketch?.exportDir,
345
+ pattern: sketch?.filenamePattern,
346
+ format: $exports.videoFormat,
347
+ imageEncoding: $exports.imageEncoding,
348
+ quality: $exports.videoQuality,
349
+ params: {
350
+ props: sketch?.props,
351
+ },
352
+ onStart: () => {
353
+ beforeRecordCallbacks.forEach((callback) => {
354
+ callback(recordArgs);
355
+ });
356
+
357
+ elapsedRenderingTime = 0;
358
+ paused = true;
359
+ },
360
+ onComplete: () => {
361
+ $recording = false;
362
+ onRecordEnd();
363
+ },
364
+ };
365
+
366
+ if ($exports.useDuration) {
367
+ recordOptions.duration = sketch.duration * $exports.loopCount;
368
+ }
369
+
370
+ record = recordCanvas(canvas, recordOptions);
371
+ }
372
+
373
+ if (record && !$recording) {
374
+ record.stop();
375
+ }
376
+ }
377
+
378
+ $: {
379
+ if (!capture && $capturing) {
380
+ save();
381
+ }
382
+ }
383
+
384
+ function createRenderLoop() {
385
+ const { width, height, pixelRatio } = $rendering;
386
+ const draw = sketch.draw || sketch.update;
387
+ const { duration } = sketch;
388
+
389
+ let playhead = NaN;
390
+ let playcount = NaN;
391
+ let frame = NaN;
392
+ let hasDuration = isFinite(duration);
393
+
394
+ let onBeforeUpdatePreview =
395
+ (renderer && renderer.onBeforeUpdatePreview) || noop;
396
+ let onAfterUpdatePreview =
397
+ (renderer && renderer.onAfterUpdatePreview) || noop;
398
+
399
+ let frameLength = 1000 / framerate;
400
+ let frameCount = framerate * duration;
401
+ let interval = 1 / frameCount;
402
+
403
+ return ({
404
+ time = performance.now(),
405
+ deltaTime = time - lastTime,
406
+ } = {}) => {
407
+ needsRender = false;
408
+ lastTime = time;
409
+
410
+ try {
411
+ onBeforeUpdatePreview({ id, canvas, container });
412
+
413
+ let t = !$sync
414
+ ? elapsedRenderingTime
415
+ : Math.floor(time / frameLength) * frameLength;
416
+
417
+ if (hasDuration && framerate > 0) {
418
+ playhead = t / 1000 / duration;
419
+ playhead %= 1;
420
+ playhead = Math.floor(playhead / interval) * interval;
421
+ playcount = Math.floor(
422
+ elapsedRenderingTime / 1000 / duration,
423
+ );
424
+
425
+ frame = Math.floor(map(playhead, 0, 1, 1, frameCount + 1));
426
+ }
427
+
428
+ draw({
429
+ ...renderer,
430
+ ...params,
431
+ props: $sketchProps,
432
+ playhead,
433
+ playcount,
434
+ frame,
435
+ width,
436
+ height,
437
+ pixelRatio,
438
+ time: t,
439
+ deltaTime,
440
+ });
441
+ onAfterUpdatePreview({ id, canvas, container });
442
+
443
+ elapsedRenderingTime += deltaTime;
444
+ } catch (error) {
445
+ onError(error);
446
+ }
447
+ };
448
+ }
449
+
450
+ function render() {
451
+ _raf = requestAnimationFrame(render);
452
+
453
+ now = performance.now();
454
+ dt = now - then;
455
+ then = now;
456
+
457
+ if (!paused) {
458
+ elapsed += dt;
459
+
460
+ if (!$sync) {
461
+ if (elapsed >= (1 / framerate) * 1000) {
462
+ elapsed = 0;
463
+ _renderSketch();
464
+ }
465
+ } else {
466
+ _renderSketch();
467
+ }
468
+ } else {
469
+ lastTime = now;
470
+ }
471
+
472
+ if (needsRender && _created) {
473
+ _renderSketch();
474
+ }
475
+ }
476
+
477
+ $: {
478
+ if (canvas && _key !== key) {
479
+ if (_created) {
480
+ clearError(_key);
481
+ }
482
+
483
+ _key = key;
484
+ createSketch(key);
485
+ }
486
+ }
487
+
488
+ rendering.subscribe((current) => {
489
+ if (canvas && _created) {
490
+ if (current.resizing === SIZES.SCALE) {
491
+ canvas.style.transform = `scale(${current.scale})`;
492
+ } else {
493
+ canvas.style.transform = null;
494
+ }
495
+
496
+ const { width, height, pixelRatio } = current;
497
+ const resize = sketch.resize || noop;
498
+
499
+ resize({
500
+ canvas,
501
+ width,
502
+ height,
503
+ pixelRatio,
504
+ ...params,
505
+ });
506
+
507
+ _renderSketch = createRenderLoop();
508
+ needsRender = true;
509
+ }
510
+ });
511
+
512
+ async function save() {
513
+ paused = true;
514
+
515
+ const {
516
+ imageCount = 1,
517
+ imageEncoding,
518
+ imageQuality,
519
+ pixelsPerInch,
520
+ } = $exports;
521
+
522
+ const captureArgs = {
523
+ encoding: imageEncoding,
524
+ quality: imageQuality,
525
+ pixelsPerInch,
526
+ count: imageCount,
527
+ };
528
+
529
+ for (let i = 0; i < imageCount; i++) {
530
+ beforeCaptureCallbacks.forEach((callback) => {
531
+ callback({ ...captureArgs, index: i });
532
+ });
533
+
534
+ _renderSketch();
535
+
536
+ await screenshotCanvas(canvas, {
537
+ filename: key,
538
+ pattern: sketch?.filenamePattern,
539
+ exportDir: sketch?.exportDir,
540
+ index: imageCount > 1 ? i : undefined,
541
+ params: {
542
+ props: sketch?.props,
543
+ },
544
+ });
545
+ paused = false;
546
+ $capturing = false;
547
+
548
+ afterCaptureCallbacks.forEach((callback) => {
549
+ callback({ ...captureArgs, index: i });
550
+ });
551
+
552
+ _renderSketch();
553
+ }
554
+ }
555
+
556
+ sync.subscribe(() => {
557
+ if (_created) {
558
+ _renderSketch = createRenderLoop();
559
+ }
560
+ });
561
+
562
+ onMount(() => {
563
+ createSketch(key);
564
+
565
+ sketches.subscribe(() => {
566
+ if (_created || _errored) {
567
+ createSketch(key);
568
+ }
569
+ });
570
+
571
+ client.on('shader-update', () => {
572
+ if (framerate === 0) {
573
+ needsRender = true;
574
+ }
575
+ });
576
+
577
+ resizeObserver.observe(node);
578
+ });
579
+
580
+ function checkForPause(event) {
581
+ const keyboardEvent = event.detail;
582
+
583
+ if (!keyboardEvent.metaKey || !keyboardEvent.ctrlKey) {
584
+ keyboardEvent.preventDefault();
585
+
586
+ if (!$recording) {
587
+ then = performance.now();
588
+ paused = !paused;
589
+ } else {
590
+ console.warn(`Cannot pause while recording.`);
591
+ }
592
+ }
593
+ }
594
+
595
+ function checkForSave(event) {
596
+ const keyboardEvent = event.detail;
597
+
598
+ if (keyboardEvent.metaKey || keyboardEvent.ctrlKey) {
599
+ keyboardEvent.preventDefault();
600
+
601
+ if (!$recording) {
602
+ save();
603
+ } else {
604
+ console.warn(`Cannot save while recording.`);
605
+ }
606
+ }
607
+ }
608
+
609
+ function checkForRecord(event) {
610
+ const keyboardEvent = event.detail;
611
+ keyboardEvent.preventDefault();
612
+
613
+ $recording = !$recording;
614
+ }
615
+
616
+ function checkForRefresh(event) {
617
+ const keyboardEvent = event.detail;
618
+ if (!keyboardEvent.metaKey && !keyboardEvent.ctrlKey) {
619
+ keyboardEvent.preventDefault();
620
+ resetProps(key, {
621
+ width: $rendering.width,
622
+ height: $rendering.height,
623
+ pixelRatio: $rendering.pixelRatio,
624
+ });
625
+ console.log(`[fragment] ${key} reloaded.`);
626
+ createSketch(key);
627
+ }
628
+ }
629
+
630
+ onDestroy(() => {
631
+ resizeObserver.unobserve(node);
632
+ cancelAnimationFrame(_raf);
633
+
634
+ if (renderer && typeof renderer.onDestroyPreview === 'function') {
635
+ renderer.onDestroyPreview({ id, canvas, container });
636
+ }
637
+
638
+ renderer = null;
639
+
640
+ if (canvas) {
641
+ destroyCanvas(canvas);
642
+ }
643
+
644
+ _created = false;
645
+ });
646
+
647
+ $: {
648
+ checkForResize();
649
+
650
+ if (renderer && typeof renderer.onResizePreview === 'function') {
651
+ renderer.onResizePreview({
652
+ id,
653
+ container,
654
+ width: $rendering.width,
655
+ height: $rendering.height,
656
+ pixelRatio: $rendering.pixelRatio,
657
+ });
658
+ }
659
+
660
+ if (canvas) {
661
+ const pixelRatio = $rendering.pixelRatio;
662
+
663
+ canvas.width = $rendering.width * pixelRatio;
664
+ canvas.height = $rendering.height * pixelRatio;
665
+ }
666
+ }
667
+
668
+ $: error =
669
+ key && $errors.has(key)
670
+ ? $errors.get(key) // display error if error context match current key
671
+ : $errors.size === 1 &&
672
+ ![...$errors.keys()].some((key) =>
673
+ $sketchesKeys.includes(key),
674
+ ) &&
675
+ ($monitors.length === 1 || // if there's only one monitor
676
+ !$monitors.some(
677
+ (m) => m.selected === $errors.keys().next().value,
678
+ )) // if none of current monitors match the key
679
+ ? $errors.get($errors.keys().next().value)
680
+ : null;
568
681
  </script>
569
682
 
570
683
  <div
571
- bind:this={node}
572
- class="sketch-renderer"
573
- class:visible={visible}
574
- class:recording={$recording}
575
- style={`--background-color: ${backgroundColor}`}
684
+ bind:this={node}
685
+ class="sketch-renderer"
686
+ class:visible
687
+ class:recording={$recording}
688
+ style={`--background-color: ${backgroundColor}`}
576
689
  >
577
- <div
578
- class="canvas-container"
579
- style="max-width: {$rendering.width}px; max-height: {$rendering.height}px;"
580
- bind:this={container}>
581
- </div>
582
- {#if $recording}
583
- <span class="record">REC</span>
584
- {/if}
690
+ <div
691
+ class="canvas-container"
692
+ style="max-width: {$rendering.width}px; max-height: {$rendering.height}px;"
693
+ bind:this={container}
694
+ />
695
+ {#if $recording}
696
+ <span class="record">REC</span>
697
+ {/if}
585
698
  </div>
586
699
  <KeyBinding type="down" key=" " on:trigger={checkForPause} />
587
700
  <KeyBinding type="down" key="r" on:trigger={checkForRefresh} />
@@ -589,95 +702,95 @@ $: error = (key && $errors.has(key)) ? $errors.get(key) : // display error if er
589
702
  <KeyBinding type="down" key="S" on:trigger={checkForRecord} />
590
703
 
591
704
  {#if error}
592
- <ErrorOverlay {error} />
705
+ <ErrorOverlay {error} />
593
706
  {/if}
594
707
 
595
708
  <style>
596
- .sketch-renderer {
597
- position: absolute;
598
- display: flex;
599
- width: 100%;
600
- height: 100%;
601
- justify-content: center;
602
- align-items: center;
603
-
604
- background-color: var(--background-color, var(--color-lightblack));
605
- }
606
-
607
- .sketch-renderer:not(.visible) {
608
- display: none;
609
- }
610
-
611
- .canvas-container {
612
- position: relative;
613
- display: flex;
614
- flex-direction: column;
615
- justify-content: center;
616
- align-items: center;
617
- height: 100%;
618
- max-height: 100%;
619
- }
620
-
621
- .sketch-renderer.recording .canvas-container {
622
- opacity: 0.5;
623
- }
624
-
625
- .record {
626
- position: absolute;
627
- top: 4px;
628
- right: 4px;
629
- z-index: 2;
630
-
631
- display: flex;
632
- place-items: center;
633
-
634
- height: 16px;
635
- padding: 0 2px;
636
-
637
- color: var(--color-red);
638
- font-size: 10px;
639
-
640
- border: 1px solid var(--color-red);
641
- border-radius: 2px;
642
- }
643
-
644
- .record:before {
645
- --size: 6px;
646
- content: '';
647
-
648
- width: var(--size);
649
- height: var(--size);
650
- margin: 0 3px 0 1px;
651
-
652
- background-color: var(--color-red);
653
- border-radius: 50%;
654
-
655
- animation: fade 1s ease-in-out infinite;
656
- }
657
-
658
- @keyframes fade {
659
- 0% {
660
- opacity: 0;
661
- }
662
-
663
- 50% {
664
- opacity: 1;
665
- }
666
-
667
- 100% {
668
- opacity: 0;
669
- }
670
- }
671
-
672
- :global(.canvas-container canvas){
673
- max-width: 100%;
674
- max-height: 100%;
675
-
676
- flex: none;
677
-
678
- width: auto !important;
679
- height: auto !important;
680
-
681
- background-color: var(--background-color, #000000);
682
- }
709
+ .sketch-renderer {
710
+ position: absolute;
711
+ display: flex;
712
+ width: 100%;
713
+ height: 100%;
714
+ justify-content: center;
715
+ align-items: center;
716
+
717
+ background-color: var(--background-color, var(--color-lightblack));
718
+ }
719
+
720
+ .sketch-renderer:not(.visible) {
721
+ display: none;
722
+ }
723
+
724
+ .canvas-container {
725
+ position: relative;
726
+ display: flex;
727
+ flex-direction: column;
728
+ justify-content: center;
729
+ align-items: center;
730
+ height: 100%;
731
+ max-height: 100%;
732
+ }
733
+
734
+ .sketch-renderer.recording .canvas-container {
735
+ opacity: 0.5;
736
+ }
737
+
738
+ .record {
739
+ position: absolute;
740
+ top: 4px;
741
+ right: 4px;
742
+ z-index: 2;
743
+
744
+ display: flex;
745
+ place-items: center;
746
+
747
+ height: 16px;
748
+ padding: 0 2px;
749
+
750
+ color: var(--color-red);
751
+ font-size: 10px;
752
+
753
+ border: 1px solid var(--color-red);
754
+ border-radius: 2px;
755
+ }
756
+
757
+ .record:before {
758
+ --size: 6px;
759
+ content: '';
760
+
761
+ width: var(--size);
762
+ height: var(--size);
763
+ margin: 0 3px 0 1px;
764
+
765
+ background-color: var(--color-red);
766
+ border-radius: 50%;
767
+
768
+ animation: fade 1s ease-in-out infinite;
769
+ }
770
+
771
+ @keyframes fade {
772
+ 0% {
773
+ opacity: 0;
774
+ }
775
+
776
+ 50% {
777
+ opacity: 1;
778
+ }
779
+
780
+ 100% {
781
+ opacity: 0;
782
+ }
783
+ }
784
+
785
+ :global(.canvas-container canvas) {
786
+ max-width: 100%;
787
+ max-height: 100%;
788
+
789
+ flex: none;
790
+
791
+ width: auto !important;
792
+ height: auto !important;
793
+
794
+ background-color: var(--background-color, #000000);
795
+ }
683
796
  </style>