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,112 +1,137 @@
1
1
  <script context="module">
2
- import { writable } from "svelte/store";
2
+ import { writable } from 'svelte/store';
3
3
 
4
- export const params = writable([]);
5
-
6
- let ID = 0;
4
+ export const params = writable([]);
7
5
 
6
+ let ID = 0;
8
7
  </script>
9
8
 
10
9
  <script>
11
- import { onMount, onDestroy } from "svelte";
12
- import { props } from "../stores";
13
- import { sketches } from "../stores/sketches.js";
14
- import { monitors } from "../stores/rendering";
15
- import Module from "../ui/Module.svelte";
16
- import Field from "../ui/Field.svelte";
17
- import OutputParams from "../ui/ParamsOutput.svelte";
18
- import ModuleHeaderAction from "../ui/ModuleHeaderAction.svelte";
19
-
20
- export let mID;
21
- export let hasHeader = true;
22
- export let output = true;
23
-
24
- let id = ID++;
25
- let selected = id;
26
- let sketch, sketchKey, sketchProps = {};
27
- let monitor, showOutputParams;
28
-
29
- onMount(() => {
30
- $params = [
31
- ...$params,
32
- {
33
- id,
34
- }
35
- ];
36
- });
37
-
38
- onDestroy(() => {
39
- $params = $params.filter((p) => p.id !== id);
40
- });
41
-
42
- $: options = [
43
- ...$monitors.map((monitor, index) => {
44
- return { value: index, label: `monitor ${index + 1}`}
45
- }),
46
- ...$params.length > 1 ? [{ value: "output", label: "output"}] : [],
47
- ];
48
-
49
- monitors.subscribe((value) => {
50
- monitor = $monitors[Math.min(selected, $monitors.length - 1)];
51
- sketchKey = monitor ? monitor.selected : undefined;
52
- });
53
-
54
- $: {
55
- sketch = $sketches[sketchKey];
56
- sketchProps = $props[sketchKey];
57
- }
58
-
59
- $: showOutputParams = (monitor && monitor.selected === "output") ||
60
- ($params.length === 1) ||
61
- (selected === "output");
62
-
10
+ import { onMount, onDestroy } from 'svelte';
11
+ import { sketches } from '../stores/sketches.js';
12
+ import { monitors, rendering } from '../stores/rendering';
13
+ import Module from '../ui/Module.svelte';
14
+ import Field from '../ui/Field.svelte';
15
+ import OutputParams from '../ui/ParamsOutput.svelte';
16
+ import ModuleHeaderAction from '../ui/ModuleHeaderAction.svelte';
17
+ import { updateProp, props } from '../stores/props';
18
+
19
+ export let mID;
20
+ export let hasHeader = true;
21
+ export let output = true;
22
+
23
+ let id = ID++;
24
+ let selected = id;
25
+ let sketch,
26
+ sketchKey,
27
+ sketchProps = {};
28
+ let monitor, showOutputParams;
29
+
30
+ onMount(() => {
31
+ $params = [
32
+ ...$params,
33
+ {
34
+ id,
35
+ },
36
+ ];
37
+ });
38
+
39
+ onDestroy(() => {
40
+ $params = $params.filter((p) => p.id !== id);
41
+ });
42
+
43
+ $: options = [
44
+ ...$monitors.map((monitor, index) => {
45
+ return { value: index, label: `monitor ${index + 1}` };
46
+ }),
47
+ ...($params.length > 1 ? [{ value: 'output', label: 'output' }] : []),
48
+ ];
49
+
50
+ monitors.subscribe((value) => {
51
+ monitor = $monitors[Math.min(selected, $monitors.length - 1)];
52
+ sketchKey = monitor ? monitor.selected : undefined;
53
+ });
54
+
55
+ $: {
56
+ sketch = $sketches[sketchKey];
57
+ sketchProps = $props[sketchKey];
58
+ }
59
+
60
+ $: showOutputParams =
61
+ (monitor && monitor.selected === 'output') ||
62
+ $params.length === 1 ||
63
+ selected === 'output';
63
64
  </script>
64
65
 
65
- <Module {mID} {hasHeader} name={`Parameters`} slug="params" >
66
- <div slot="header-right">
67
- {#if options.length > 1 }
68
- <ModuleHeaderAction
69
- value={selected}
70
- permanent
71
- border
72
- on:change={(event) => selected = event.detail}
73
- options={options}
74
- />
75
- {/if }
76
- </div>
77
- {#if showOutputParams && output }
78
- <OutputParams />
79
- {/if}
80
-
81
- {#if sketch }
82
- {#if typeof props === "object"}
83
- {#if output}
84
- <Field key="framerate" value={isFinite(sketch.fps) ? sketch.fps : 60} params={{disabled: true}}/>
85
- {/if}
86
- {#if sketch.duration && sketch.duration > 0 && output }
87
- <Field key="duration" value={sketch.duration} params={{disabled: true, suffix: "s"}}/>
88
- {/if }
89
- {#each Object.keys(sketchProps) as key, i}
90
- {#if !sketchProps[key].hidden}
91
- <Field
92
- context={sketchKey}
93
- key={key}
94
- value={sketchProps[key].value}
95
- type={sketchProps[key].type}
96
- bind:params={sketchProps[key].params}
97
- on:click={() => {
98
- $props[sketchKey][key].value._refresh = true;
99
- }}
100
- on:change={(event) => {
101
- $props[sketchKey][key].value = event.detail;
102
-
103
- if (typeof $props[sketchKey][key].onChange === 'function') {
104
- $props[sketchKey][key].onChange($props[sketchKey][key]);
105
- }
106
- }}
107
- />
108
- {/if}
109
- {/each}
110
- {/if}
111
- {/if}
66
+ <Module {mID} {hasHeader} name={`Parameters`} slug="params">
67
+ <div slot="header-right">
68
+ {#if options.length > 1}
69
+ <ModuleHeaderAction
70
+ value={selected}
71
+ permanent
72
+ border
73
+ on:change={(event) => (selected = event.detail)}
74
+ {options}
75
+ />
76
+ {/if}
77
+ </div>
78
+ {#if showOutputParams && output}
79
+ <OutputParams />
80
+ {/if}
81
+
82
+ {#if sketch}
83
+ {#if typeof props === 'object'}
84
+ {#if output}
85
+ <Field
86
+ key="framerate"
87
+ value={isFinite(sketch.fps) ? sketch.fps : 60}
88
+ disabled
89
+ />
90
+ {/if}
91
+ {#if sketch.duration && sketch.duration > 0 && output}
92
+ <Field
93
+ key="duration"
94
+ value={sketch.duration}
95
+ params={{ suffix: 's' }}
96
+ disabled
97
+ />
98
+ {/if}
99
+ {#each Object.keys(sketchProps) as key, index (key)}
100
+ {@const sketchProp = sketchProps[key]}
101
+ {@const {
102
+ hidden,
103
+ displayName,
104
+ value,
105
+ type,
106
+ disabled,
107
+ __initialValue: initialValue,
108
+ } = sketchProp}
109
+ {@const isDisabled =
110
+ typeof disabled === 'function' ? disabled() : disabled}
111
+ {#if typeof hidden === 'function' ? !hidden() : !hidden}
112
+ <Field
113
+ context={sketchKey}
114
+ {key}
115
+ {displayName}
116
+ {value}
117
+ {initialValue}
118
+ {type}
119
+ {index}
120
+ disabled={isDisabled}
121
+ bind:params={sketchProps[key].params}
122
+ on:click={() => {
123
+ $props[sketchKey][key].value._refresh = true;
124
+ }}
125
+ on:change={(event) => {
126
+ updateProp(sketchKey, key, event.detail, {
127
+ width: $rendering.width,
128
+ height: $rendering.height,
129
+ pixelRatio: $rendering.pixelRatio,
130
+ });
131
+ }}
132
+ />
133
+ {/if}
134
+ {/each}
135
+ {/if}
136
+ {/if}
112
137
  </Module>
@@ -1,5 +1,5 @@
1
1
  export let onMountPreview = ({ canvas }) => {
2
- return {
3
- context: canvas.getContext("2d"),
4
- }
2
+ return {
3
+ context: canvas.getContext('2d'),
4
+ };
5
5
  };
@@ -1,7 +1,7 @@
1
- import { fragment } from "../lib/gl";
2
- import { client } from "@fragment/client";
3
- import { getShaderPath } from "../utils/glsl.utils";
4
- import { clearError } from "../stores/errors";
1
+ import { fragment } from '../lib/gl';
2
+ import { client } from '@fragment/client';
3
+ import { getShaderPath } from '../utils/glsl.utils';
4
+ import { clearError } from '../stores/errors';
5
5
 
6
6
  let frags = [];
7
7
 
@@ -19,44 +19,51 @@ export let onMountPreview = ({ canvas, id }) => {
19
19
  };
20
20
 
21
21
  export let onResizePreview = ({ id, width, height, pixelRatio }) => {
22
- let { frag } = frags.find(f => f.id === id);
22
+ let { frag } = frags.find((f) => f.id === id);
23
23
 
24
24
  frag.resize({ width, height, pixelRatio });
25
25
  };
26
26
 
27
27
  export let onDestroyPreview = ({ canvas, id }) => {
28
- let fragIndex = frags.findIndex(f => f.id === id);
28
+ let fragIndex = frags.findIndex((f) => f.id === id);
29
29
  let { frag } = frags[fragIndex];
30
-
30
+
31
31
  clearError(frag.gl.__uuid);
32
32
 
33
33
  frag.destroy();
34
34
  frags.splice(fragIndex, 1);
35
35
  };
36
36
 
37
- client.on('shader-update', (data) => {
37
+ client.on('shader-update', (shaderUpdates) => {
38
38
  frags.forEach(({ frag }) => clearError(frag.gl.__uuid));
39
39
 
40
- const { filepath, source } = data;
40
+ shaderUpdates.forEach((shaderUpdate) => {
41
+ const { filepath, source } = shaderUpdate;
41
42
 
42
- const programs = frags.map(({ frag }) => frag.program);
43
+ const programs = frags.map(({ frag }) => frag.program);
43
44
 
44
- programs.forEach((program) => {
45
- const { fragment, vertex } = program;
45
+ programs.forEach((program) => {
46
+ const { fragment, vertex } = program;
46
47
 
47
- const shaders = {
48
- vertexShader: vertex,
49
- fragmentShader: fragment
50
- };
48
+ const shaders = {
49
+ vertexShader: vertex,
50
+ fragmentShader: fragment,
51
+ };
51
52
 
52
- Object.keys(shaders).forEach((key) => {
53
- const shaderPath = getShaderPath(shaders[key]);
53
+ Object.keys(shaders).forEach((key) => {
54
+ const shaderPath = getShaderPath(shaders[key]);
54
55
 
55
- if (shaderPath === filepath) {
56
- console.log(`[fragment] shader update ${shaderPath.replace(__CWD__, "")}`);
57
- program[key] = source;
58
- program.needsUpdate = true;
59
- }
56
+ if (shaderPath === filepath) {
57
+ console.log(
58
+ `[fragment-plugin-hsr] hsr update ${shaderPath.replace(
59
+ __CWD__,
60
+ '',
61
+ )}`,
62
+ );
63
+ program[key] = source;
64
+ program.needsUpdate = true;
65
+ }
66
+ });
60
67
  });
61
68
  });
62
69
  });
@@ -0,0 +1,144 @@
1
+ import p5 from 'p5';
2
+ import { client } from '@fragment/client';
3
+ import { getShaderPath } from '../utils/glsl.utils';
4
+ import { clearError } from '../stores/errors';
5
+
6
+ let previews = [];
7
+
8
+ export let onMountPreview = ({ id, width, height }) => {
9
+ const p = new p5((sketch) => {
10
+ sketch.setup = () => {
11
+ sketch.createCanvas(width, height, 'webgl');
12
+ };
13
+ });
14
+
15
+ const preview = {
16
+ id,
17
+ p,
18
+ };
19
+
20
+ previews.push(preview);
21
+
22
+ return {
23
+ canvas: p.canvas,
24
+ p,
25
+ };
26
+ };
27
+
28
+ export let onBeforeUpdatePreview = ({ id }) => {
29
+ const preview = previews.find((p) => p.id === id);
30
+
31
+ if (preview) {
32
+ preview.rendered = false;
33
+ }
34
+ };
35
+
36
+ export let onAfterUpdatePreview = ({ id }) => {
37
+ const preview = previews.find((p) => p.id === id);
38
+
39
+ if (preview) {
40
+ preview.rendered = true;
41
+ }
42
+
43
+ if (
44
+ previews.every((preview) => preview.rendered) &&
45
+ _shaderUpdates.length > 0
46
+ ) {
47
+ clearShaderUpdates();
48
+ }
49
+ };
50
+
51
+ export let onResizePreview = ({ id, width, height, pixelRatio }) => {
52
+ const preview = previews.find((p) => p.id === id);
53
+
54
+ if (preview) {
55
+ preview.p.resizeCanvas(width * pixelRatio, height * pixelRatio, false);
56
+ }
57
+ };
58
+
59
+ export let onDestroyPreview = ({ id }) => {
60
+ const previewIndex = previews.find((p) => p.id === id);
61
+ const preview = previews[previewIndex];
62
+
63
+ if (preview) {
64
+ preview.p.remove();
65
+ }
66
+
67
+ previews.splice(previewIndex, 1);
68
+ };
69
+
70
+ /* HOT SHADER RELOADING */
71
+ const { shader } = p5.prototype;
72
+ const { useProgram } = p5.Shader.prototype;
73
+
74
+ p5.Shader.prototype.useProgram = function () {
75
+ // avoid p5 throwing error covering shader syntax error overlay
76
+ if (this._glProgram !== 0) {
77
+ useProgram.call(this);
78
+ }
79
+ };
80
+
81
+ p5.prototype.shader = function (s) {
82
+ let needsUpdate = false;
83
+ ['_vertSrc', '_fragSrc'].forEach((key) => {
84
+ const shader = s[key];
85
+ const shaderPath = getShaderPath(shader);
86
+ const shaderUpdate = _shaderUpdates.find(
87
+ (shaderUpdate) => shaderUpdate.filepath === shaderPath,
88
+ );
89
+
90
+ if (shaderUpdate) {
91
+ console.log(
92
+ `[fragment-plugin-hsr] hsr update ${shaderPath.replace(
93
+ __CWD__,
94
+ '',
95
+ )}`,
96
+ );
97
+ needsUpdate = true;
98
+
99
+ s[key] = shaderUpdate.source;
100
+ }
101
+ });
102
+
103
+ if (needsUpdate) {
104
+ s.bindShader();
105
+ s.unbindShader();
106
+
107
+ // set it to undefined so it goes into useProgram when binded
108
+ // see useProgram
109
+ this._renderer._curShader = undefined;
110
+
111
+ // set _glProgram so it compiles the shader again
112
+ s._glProgram = 0;
113
+ // set to false so it caches attributes and uniforms
114
+ s._loadedAttributes = false;
115
+ s._loadedUniforms = false;
116
+ // empty samplers array because of samplers.push()
117
+ s.samplers = [];
118
+
119
+ // call s.init() and gl.useProgram
120
+ s.bindShader();
121
+ }
122
+
123
+ return shader.call(this, s);
124
+ };
125
+
126
+ let _shaderUpdates = [];
127
+
128
+ function clearShaderUpdates() {
129
+ _shaderUpdates = [];
130
+ }
131
+
132
+ if (import.meta.hot) {
133
+ import.meta.hot.on('sketch-update', (data) => {
134
+ clearShaderUpdates();
135
+ });
136
+ }
137
+
138
+ client.on('shader-update', (shaderUpdates) => {
139
+ previews.forEach(({ p }) => {
140
+ clearError(p._renderer.GL.__uuid);
141
+ });
142
+
143
+ _shaderUpdates = shaderUpdates;
144
+ });
@@ -1,4 +1,4 @@
1
- import p5 from "p5";
1
+ import p5 from 'p5';
2
2
 
3
3
  let previews = [];
4
4
 
@@ -6,7 +6,7 @@ export let onMountPreview = ({ id, width, height }) => {
6
6
  const p = new p5((sketch) => {
7
7
  sketch.setup = () => {
8
8
  sketch.createCanvas(width, height);
9
- }
9
+ };
10
10
  });
11
11
 
12
12
  const preview = {
@@ -15,15 +15,15 @@ export let onMountPreview = ({ id, width, height }) => {
15
15
  };
16
16
 
17
17
  previews.push(preview);
18
-
19
- return {
18
+
19
+ return {
20
20
  canvas: p.canvas,
21
21
  p,
22
- };
22
+ };
23
23
  };
24
24
 
25
25
  export let onResizePreview = ({ id, width, height, pixelRatio }) => {
26
- const preview = previews.find(p => p.id === id);
26
+ const preview = previews.find((p) => p.id === id);
27
27
 
28
28
  if (preview) {
29
29
  preview.p.resizeCanvas(width * pixelRatio, height * pixelRatio, false);
@@ -31,9 +31,12 @@ export let onResizePreview = ({ id, width, height, pixelRatio }) => {
31
31
  };
32
32
 
33
33
  export let onDestroyPreview = ({ id }) => {
34
- const preview = previews.find(p => p.id === id);
34
+ const previewIndex = previews.find((p) => p.id === id);
35
+ const preview = previews[previewIndex];
35
36
 
36
37
  if (preview) {
37
38
  preview.p.remove();
38
39
  }
40
+
41
+ previews.splice(previewIndex, 1);
39
42
  };