fragment-tools 0.1.0

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 (192) hide show
  1. package/LICENSE.md +21 -0
  2. package/README.md +101 -0
  3. package/bin/index.js +19 -0
  4. package/docs/README.md +18 -0
  5. package/docs/api/CLI.md +44 -0
  6. package/docs/api/renderers.md +80 -0
  7. package/docs/api/sketch.md +216 -0
  8. package/docs/api/triggers.md +101 -0
  9. package/docs/guide/about.md +16 -0
  10. package/docs/guide/exports.md +86 -0
  11. package/docs/guide/external-dependencies.md +22 -0
  12. package/docs/guide/getting-started.md +113 -0
  13. package/docs/guide/hot-shader-reloading.md +20 -0
  14. package/docs/guide/shortcuts.md +12 -0
  15. package/docs/guide/triggers.png +0 -0
  16. package/docs/guide/using-triggers.md +39 -0
  17. package/examples/cube-three.js +34 -0
  18. package/examples/ellipse-p5.js +26 -0
  19. package/examples/icon.fs +96 -0
  20. package/examples/icon.js +63 -0
  21. package/examples/icon.png +0 -0
  22. package/examples/icon.transparent.png +0 -0
  23. package/examples/package-lock.json +40 -0
  24. package/examples/package.json +15 -0
  25. package/examples/shape-2d.js +45 -0
  26. package/examples/shape-three.js +49 -0
  27. package/examples/shape-tree.fs +3 -0
  28. package/package.json +37 -0
  29. package/screenshot.png +0 -0
  30. package/src/cli/db.js +17 -0
  31. package/src/cli/index.js +198 -0
  32. package/src/cli/log.js +26 -0
  33. package/src/cli/plugins/check-dependencies.js +77 -0
  34. package/src/cli/plugins/db.js +12 -0
  35. package/src/cli/plugins/hot-shader-reload.js +86 -0
  36. package/src/cli/plugins/hot-sketch-reload.js +39 -0
  37. package/src/cli/plugins/screenshot.js +31 -0
  38. package/src/cli/server.js +140 -0
  39. package/src/cli/templates/2d.js +15 -0
  40. package/src/cli/templates/fragment.fs +10 -0
  41. package/src/cli/templates/fragment.js +18 -0
  42. package/src/cli/templates/index.js +24 -0
  43. package/src/cli/templates/p5.js +13 -0
  44. package/src/cli/templates/three-fragment.js +53 -0
  45. package/src/cli/templates/three-orthographic.js +23 -0
  46. package/src/cli/templates/three-perspective.js +20 -0
  47. package/src/cli/ws.js +92 -0
  48. package/src/client/app/App.svelte +8 -0
  49. package/src/client/app/client.js +68 -0
  50. package/src/client/app/components/IconCross.svelte +29 -0
  51. package/src/client/app/components/Init.svelte +13 -0
  52. package/src/client/app/components/KeyBinding.svelte +32 -0
  53. package/src/client/app/inputs/Input.js +15 -0
  54. package/src/client/app/inputs/Keyboard.js +21 -0
  55. package/src/client/app/inputs/MIDI.js +144 -0
  56. package/src/client/app/inputs/Mouse.js +5 -0
  57. package/src/client/app/inputs/Webcam.js +98 -0
  58. package/src/client/app/lib/canvas-recorder/CanvasRecorder.js +88 -0
  59. package/src/client/app/lib/canvas-recorder/FFMPEGRecorder.js +56 -0
  60. package/src/client/app/lib/canvas-recorder/FrameRecorder.js +40 -0
  61. package/src/client/app/lib/canvas-recorder/GIFRecorder.js +52 -0
  62. package/src/client/app/lib/canvas-recorder/MP4Recorder.js +46 -0
  63. package/src/client/app/lib/canvas-recorder/WebMRecorder.js +30 -0
  64. package/src/client/app/lib/canvas-recorder/mp4.js +20 -0
  65. package/src/client/app/lib/canvas-recorder/mp4.wasm +0 -0
  66. package/src/client/app/lib/canvas-recorder/utils.js +22 -0
  67. package/src/client/app/lib/gl/Geometry.js +39 -0
  68. package/src/client/app/lib/gl/Program.js +130 -0
  69. package/src/client/app/lib/gl/Renderer.js +148 -0
  70. package/src/client/app/lib/gl/Texture.js +114 -0
  71. package/src/client/app/lib/gl/index.js +109 -0
  72. package/src/client/app/lib/gl/utils.js +5 -0
  73. package/src/client/app/lib/helpers/frameDebounce.js +40 -0
  74. package/src/client/app/lib/loader/index.js +20 -0
  75. package/src/client/app/lib/loader/loadImage.js +19 -0
  76. package/src/client/app/lib/loader/loadScript.js +14 -0
  77. package/src/client/app/lib/paper-sizes.js +104 -0
  78. package/src/client/app/lib/presets.js +12 -0
  79. package/src/client/app/lib/tempo/Analyser.js +165 -0
  80. package/src/client/app/lib/tempo/Range.js +97 -0
  81. package/src/client/app/lib/tempo/index.js +138 -0
  82. package/src/client/app/modules/AudioAnalyser/Range.svelte +93 -0
  83. package/src/client/app/modules/AudioAnalyser/Spectrum.svelte +31 -0
  84. package/src/client/app/modules/AudioAnalyser.svelte +70 -0
  85. package/src/client/app/modules/Console/ConsoleLine.svelte +254 -0
  86. package/src/client/app/modules/Console.svelte +82 -0
  87. package/src/client/app/modules/Exports.svelte +105 -0
  88. package/src/client/app/modules/MidiPanel.svelte +106 -0
  89. package/src/client/app/modules/Monitor.svelte +62 -0
  90. package/src/client/app/modules/Params.svelte +112 -0
  91. package/src/client/app/renderers/2DRenderer.js +5 -0
  92. package/src/client/app/renderers/FragmentRenderer.js +62 -0
  93. package/src/client/app/renderers/OGLRenderer.js +0 -0
  94. package/src/client/app/renderers/P5Renderer.js +39 -0
  95. package/src/client/app/renderers/THREERenderer.js +128 -0
  96. package/src/client/app/stores/audioAnalysis.js +10 -0
  97. package/src/client/app/stores/console.js +76 -0
  98. package/src/client/app/stores/errors.js +25 -0
  99. package/src/client/app/stores/exports.js +28 -0
  100. package/src/client/app/stores/index.js +2 -0
  101. package/src/client/app/stores/layout.js +187 -0
  102. package/src/client/app/stores/multisampling.js +16 -0
  103. package/src/client/app/stores/props.js +44 -0
  104. package/src/client/app/stores/renderers.js +60 -0
  105. package/src/client/app/stores/rendering.js +111 -0
  106. package/src/client/app/stores/sketches.js +40 -0
  107. package/src/client/app/stores/time.js +27 -0
  108. package/src/client/app/stores/utils.js +66 -0
  109. package/src/client/app/transitions/fade.js +17 -0
  110. package/src/client/app/transitions/index.js +12 -0
  111. package/src/client/app/transitions/splitX.js +16 -0
  112. package/src/client/app/transitions/splitY.js +16 -0
  113. package/src/client/app/triggers/Keyboard.js +95 -0
  114. package/src/client/app/triggers/MIDI.js +122 -0
  115. package/src/client/app/triggers/Mouse.js +96 -0
  116. package/src/client/app/triggers/Trigger.js +71 -0
  117. package/src/client/app/triggers/index.js +19 -0
  118. package/src/client/app/triggers/shared.js +37 -0
  119. package/src/client/app/ui/Build.svelte +96 -0
  120. package/src/client/app/ui/ErrorOverlay.svelte +130 -0
  121. package/src/client/app/ui/Field.svelte +262 -0
  122. package/src/client/app/ui/FieldGroup.svelte +103 -0
  123. package/src/client/app/ui/FieldSection.svelte +123 -0
  124. package/src/client/app/ui/FieldSpace.svelte +37 -0
  125. package/src/client/app/ui/FieldTrigger.svelte +263 -0
  126. package/src/client/app/ui/FieldTriggers.svelte +58 -0
  127. package/src/client/app/ui/FloatingParams.svelte +49 -0
  128. package/src/client/app/ui/Layout.svelte +50 -0
  129. package/src/client/app/ui/LayoutColumn.svelte +9 -0
  130. package/src/client/app/ui/LayoutComponent.svelte +279 -0
  131. package/src/client/app/ui/LayoutResizer.svelte +218 -0
  132. package/src/client/app/ui/LayoutRoot.svelte +11 -0
  133. package/src/client/app/ui/LayoutRow.svelte +9 -0
  134. package/src/client/app/ui/LayoutToolbar.svelte +264 -0
  135. package/src/client/app/ui/Module.svelte +154 -0
  136. package/src/client/app/ui/ModuleHeaderAction.svelte +87 -0
  137. package/src/client/app/ui/ModuleHeaderButton.svelte +21 -0
  138. package/src/client/app/ui/ModuleHeaderSelect.svelte +50 -0
  139. package/src/client/app/ui/ModuleRenderer.svelte +38 -0
  140. package/src/client/app/ui/OutputRenderer.svelte +149 -0
  141. package/src/client/app/ui/ParamsMultisampling.svelte +109 -0
  142. package/src/client/app/ui/ParamsOutput.svelte +139 -0
  143. package/src/client/app/ui/Preview.svelte +15 -0
  144. package/src/client/app/ui/SelectChevrons.svelte +25 -0
  145. package/src/client/app/ui/SketchRenderer.svelte +672 -0
  146. package/src/client/app/ui/SketchSelect.svelte +49 -0
  147. package/src/client/app/ui/fields/ButtonInput.svelte +54 -0
  148. package/src/client/app/ui/fields/CheckboxInput.svelte +70 -0
  149. package/src/client/app/ui/fields/ColorInput.svelte +187 -0
  150. package/src/client/app/ui/fields/FieldInputRow.svelte +13 -0
  151. package/src/client/app/ui/fields/ImageInput.svelte +145 -0
  152. package/src/client/app/ui/fields/Input.svelte +120 -0
  153. package/src/client/app/ui/fields/ListInput.svelte +106 -0
  154. package/src/client/app/ui/fields/NumberInput.svelte +114 -0
  155. package/src/client/app/ui/fields/ProgressInput.svelte +90 -0
  156. package/src/client/app/ui/fields/Select.svelte +116 -0
  157. package/src/client/app/ui/fields/TextInput.svelte +18 -0
  158. package/src/client/app/ui/fields/Vec2Input.svelte +5 -0
  159. package/src/client/app/ui/fields/Vec3Input.svelte +6 -0
  160. package/src/client/app/ui/fields/VectorInput.svelte +102 -0
  161. package/src/client/app/utils/canvas.utils.js +229 -0
  162. package/src/client/app/utils/color.utils.js +427 -0
  163. package/src/client/app/utils/file.utils.js +77 -0
  164. package/src/client/app/utils/glsl.utils.js +14 -0
  165. package/src/client/app/utils/glslErrors.js +154 -0
  166. package/src/client/app/utils/index.js +39 -0
  167. package/src/client/app/utils/math.utils.js +23 -0
  168. package/src/client/app/utils/props.utils.js +53 -0
  169. package/src/client/index.html +18 -0
  170. package/src/client/main.js +9 -0
  171. package/src/client/public/css/global.css +115 -0
  172. package/src/client/public/favicon.ico +0 -0
  173. package/src/client/public/fonts/Inter-Bold.woff2 +0 -0
  174. package/src/client/public/fonts/Inter-Italic.woff2 +0 -0
  175. package/src/client/public/fonts/Inter-Regular.woff2 +0 -0
  176. package/src/client/public/fonts/Inter-SemiBold.woff2 +0 -0
  177. package/src/client/public/fonts/JetBrainsMono-Regular.woff2 +0 -0
  178. package/src/client/public/icons/chevron-bottom.svg +3 -0
  179. package/src/client/public/icons/chevron-right.svg +3 -0
  180. package/src/client/public/icons/chevron-top.svg +3 -0
  181. package/src/client/public/icons/columns-horizontal.svg +4 -0
  182. package/src/client/public/icons/columns-vertical.svg +4 -0
  183. package/src/client/public/icons/folder-plus.svg +6 -0
  184. package/src/client/public/icons/lock.svg +4 -0
  185. package/src/client/public/icons/picture-in-picture.svg +4 -0
  186. package/src/client/public/icons/trash.svg +5 -0
  187. package/src/client/public/icons/trigger.svg +8 -0
  188. package/src/client/public/icons/unlock.svg +4 -0
  189. package/src/client/public/js/ffmpeg.min.js +2 -0
  190. package/src/client/public/js/ffmpeg.min.js.map +1 -0
  191. package/src/client/public/js/gif.js +2 -0
  192. package/src/client/public/js/gif.worker.js +2 -0
@@ -0,0 +1,87 @@
1
+ <script>
2
+ import ModuleHeaderSelect from "./ModuleHeaderSelect.svelte";
3
+ import ModuleHeaderButton from "./ModuleHeaderButton.svelte";
4
+
5
+ export let label = "";
6
+ export let permanent = false;
7
+ export let value = null;
8
+ export let border = false;
9
+ export let margin = true;
10
+ export let options = [];
11
+
12
+ $: disabled = options.length === 1;
13
+
14
+ </script>
15
+
16
+ <div class="module-header-action" class:permanent={permanent} class:border={border} class:no-margin={!margin} class:disabled={disabled}>
17
+ {#if options.length > 0}
18
+ <ModuleHeaderSelect {options} {value} {disabled} on:change/>
19
+ {:else}
20
+ <ModuleHeaderButton label={label} on:click>
21
+ <slot name="text">
22
+ <div class="text">
23
+ <slot></slot>
24
+ </div>
25
+ </slot>
26
+ <slot name="icon"></slot>
27
+ </ModuleHeaderButton>
28
+ {/if}
29
+ </div>
30
+
31
+
32
+ <style>
33
+ .module-header-action {
34
+ display: flex;
35
+ align-items: center;
36
+
37
+ color: rgba(255, 255, 255, 0.75);
38
+
39
+ margin: 0 2px;
40
+ }
41
+
42
+ .module-header-action:not(.disabled):hover {
43
+ color: rgba(255, 255, 255, 1);
44
+ }
45
+
46
+ .text:not(:empty) {
47
+ color: inherit;
48
+ background: transparent;
49
+ width: 100%;
50
+ font-size: 10px;
51
+
52
+ padding: 1px 3px 1px 3px;
53
+ }
54
+
55
+ .module-header-action.no-margin {
56
+ margin: 0;
57
+ }
58
+
59
+ .module-header-action.border {
60
+ border-radius: 2px;
61
+ border: 1px solid rgba(255, 255, 255, 0.25);
62
+ }
63
+
64
+ .module-header-action:not(.disabled).border:hover {
65
+ border: 1px solid rgba(255, 255, 255, 0.5);
66
+ }
67
+
68
+ .module-header-action:first-child {
69
+ margin-left: 0;
70
+ }
71
+
72
+ .module-header-action:last-child {
73
+ margin-right: 0;
74
+ }
75
+
76
+ .module-header-action:not(.permanent) {
77
+ opacity: 0;
78
+ transition: opacity 0.2s ease;
79
+ pointer-events: none;
80
+ }
81
+
82
+ :global(.module__header:hover .module-header-action:not(.permanent)) {
83
+ opacity: 1;
84
+ pointer-events: auto;
85
+ }
86
+
87
+ </style>
@@ -0,0 +1,21 @@
1
+ <script>
2
+ export let label;
3
+ </script>
4
+
5
+ <button class="module-header-action__button" aria-label={label} on:click>
6
+ <slot></slot>
7
+ </button>
8
+
9
+ <style>
10
+ .module-header-action__button {
11
+ color: inherit;
12
+ background: transparent;
13
+ /* opacity: 0.5; */
14
+ display: flex;
15
+ transition: opacity 0.2s ease;
16
+ }
17
+
18
+ .module-header-action__button:hover {
19
+ opacity: 1;
20
+ }
21
+ </style>
@@ -0,0 +1,50 @@
1
+ <script>
2
+ import { createEventDispatcher } from "svelte";
3
+
4
+ import SelectChevrons from "./SelectChevrons.svelte";
5
+
6
+ export let value;
7
+ export let options = [];
8
+ export let disabled = false;
9
+
10
+ const dispatch = createEventDispatcher();
11
+
12
+ function handleChange(event) {
13
+ dispatch("change", event.currentTarget.value);
14
+ }
15
+ </script>
16
+
17
+ <div class="module-header-select">
18
+ <select class="select" on:change={handleChange} class:single={options.length === 1} disabled={disabled}>
19
+ {#each options as option}
20
+ <option value={option.value} selected={value === option.value}>{option.label}</option>
21
+ {/each}
22
+ </select>
23
+ {#if options.length > 1 }
24
+ <SelectChevrons width={15} height={15} --color="rgba(255, 255, 255, 0.75)" />
25
+ {/if}
26
+ </div>
27
+
28
+ <style>
29
+ .module-header-select {
30
+ position: relative;
31
+
32
+ display: flex;
33
+ }
34
+
35
+ .select {
36
+ font-size: 10px;
37
+ padding: 1px 3px;
38
+
39
+ color: inherit;
40
+ background: transparent;
41
+
42
+ outline: 0;
43
+ user-select: none;
44
+ }
45
+
46
+ .select:not(.single) {
47
+ padding-right: 15px;
48
+ }
49
+
50
+ </style>
@@ -0,0 +1,38 @@
1
+ <script context="module">
2
+ export let moduleNames = [
3
+ "monitor",
4
+ "params",
5
+ "midi",
6
+ "console",
7
+ "exports",
8
+ ];
9
+ </script>
10
+
11
+ <script>
12
+ import Module from "./Module.svelte";
13
+
14
+ export let mID = undefined;
15
+ export let name;
16
+ export let hasHeader = true;
17
+
18
+ const moduleList = {
19
+ "monitor": () => import("../modules/Monitor.svelte"),
20
+ "params": () => import("../modules/Params.svelte"),
21
+ "midi": () => import("../modules/MidiPanel.svelte"),
22
+ "console": () => import("../modules/Console.svelte"),
23
+ "exports": () => import("../modules/Exports.svelte"),
24
+ };
25
+
26
+ </script>
27
+
28
+ {#if moduleList[name]}
29
+ {#await moduleList[name]()}
30
+ <Module {hasHeader} {mID} {name}/>
31
+ {:then value}
32
+ <svelte:component this={value.default} {mID} {hasHeader} />
33
+ {:catch error}
34
+ <p>Something went wrong: {error.message}</p>
35
+ {/await}
36
+ {:else}
37
+ <Module {hasHeader} {mID} {name}/>
38
+ {/if}
@@ -0,0 +1,149 @@
1
+ <script>
2
+ import { onDestroy, onMount } from "svelte";
3
+ import { fragment, Texture } from "../lib/gl";
4
+ import { transitions } from "../transitions/index.js";
5
+ import { rendering, monitors } from "../stores/rendering.js";
6
+ import { multisampling, threshold, transition } from "../stores/multisampling.js";
7
+
8
+ export let paused = false;
9
+
10
+ let _raf;
11
+ let canvas;
12
+ let output;
13
+ let _mounted;
14
+ let uniforms = {
15
+ threshold: { value: 0, type: "float" },
16
+ uSampler0: { value: null, type: "sampler2D" },
17
+ uSampler1: { value: null, type: "sampler2D" },
18
+ }
19
+
20
+ let defaultFragmentShader = /* glsl */`
21
+ precision highp float;
22
+
23
+ uniform float threshold;
24
+ uniform sampler2D uSampler0;
25
+ uniform sampler2D uSampler1;
26
+
27
+ varying vec2 vUv;
28
+
29
+ void main() {
30
+ vec4 mapTexel0 = texture2D(uSampler0, vUv);
31
+ vec4 mapTexel1 = texture2D(uSampler1, vUv);
32
+
33
+ vec3 color = mix(mapTexel0.rgb, mapTexel1.rgb, threshold);
34
+
35
+ gl_FragColor = vec4(color, 1.);
36
+ }
37
+ `;
38
+
39
+ $: t = transitions[$transition];
40
+ $: fragmentShader = t ? t.fragmentShader : defaultFragmentShader;
41
+ $: {
42
+ if (output) {
43
+ output.fragmentShader = fragmentShader;
44
+ }
45
+ }
46
+
47
+ onMount(() => {
48
+ output = fragment({
49
+ canvas,
50
+ shader: fragmentShader,
51
+ uniforms,
52
+ });
53
+
54
+ uniforms.uSampler0.value = new Texture(output.gl);
55
+ uniforms.uSampler1.value = new Texture(output.gl);
56
+
57
+ assignTextures();
58
+ resize();
59
+ render();
60
+
61
+ rendering.subscribe(() => {
62
+ resize();
63
+ });
64
+
65
+ _mounted = true;
66
+ });
67
+
68
+ onDestroy(() => {
69
+ cancelAnimationFrame(_raf);
70
+
71
+ output.destroy();
72
+ output = null;
73
+ });
74
+
75
+ function assignTextures([monitorID0, monitorID1] = $multisampling) {
76
+ if (!output) return;
77
+
78
+ if (monitorID0 >= 0) {
79
+ uniforms.uSampler0.value.image = $monitors.find((monitor) => monitor.id === monitorID0).canvas;
80
+ }
81
+
82
+ if (monitorID1 >= 0) {
83
+ uniforms.uSampler1.value.image = $monitors.find((monitor) => monitor.id === monitorID1).canvas;
84
+ }
85
+ }
86
+
87
+ multisampling.subscribe(assignTextures);
88
+
89
+ function render() {
90
+ uniforms.threshold.value = $threshold;
91
+
92
+ if (!paused) {
93
+ uniforms.uSampler0.value.needsUpdate = true;
94
+ uniforms.uSampler1.value.needsUpdate = true;
95
+
96
+ output.render();
97
+ }
98
+
99
+ _raf = requestAnimationFrame(render);
100
+ }
101
+
102
+ function resize() {
103
+ if (!output) return;
104
+
105
+ const { width, height, pixelRatio } = $rendering;
106
+
107
+ output.resize({
108
+ width,
109
+ height,
110
+ pixelRatio,
111
+ })
112
+ }
113
+
114
+ </script>
115
+
116
+ <div class="output-renderer">
117
+ <div class="canvas-container" style="max-width: {$rendering.width}px;">
118
+ <canvas bind:this={canvas}></canvas>
119
+ </div>
120
+ </div>
121
+
122
+ <style>
123
+ .output-renderer {
124
+ position: relative;
125
+ display: flex;
126
+ width: 100%;
127
+ height: 100%;
128
+ justify-content: center;
129
+
130
+ background-color: var(--background-color, var(--color-lightblack));
131
+ }
132
+
133
+ .output-renderer :global(canvas) {
134
+ max-width: 100%;
135
+ max-height: 100%;
136
+ background: black;
137
+
138
+ width: auto !important;
139
+ height: auto !important;
140
+ }
141
+
142
+ .canvas-container {
143
+ position: relative;
144
+ display: flex;
145
+ align-items: center;
146
+ height: 100%;
147
+ max-height: 100%;
148
+ }
149
+ </style>
@@ -0,0 +1,109 @@
1
+ <script>
2
+ import { multisampling, threshold, transition } from "../stores/multisampling.js";
3
+ import { monitors } from "../stores/rendering.js";
4
+ import { transitions } from "../transitions/index.js";
5
+ import Field from "./Field.svelte";
6
+ import FieldGroup from "./FieldGroup.svelte";
7
+
8
+ let monitorDisabled = false;
9
+ let sampler0 = -1;
10
+ let sampler1 = -1;
11
+
12
+ const transitionOptions = Object.keys(transitions).map((key) => {
13
+ const transition = transitions[key];
14
+ const label = transition.name ? transition.name : key;
15
+ return { value: key, label };
16
+ });
17
+
18
+ if (!$transition) {
19
+ $transition = transitionOptions[0].value;
20
+ }
21
+
22
+ $: samplerOptions = $monitors
23
+ .map((monitor, index) => ({ label: `monitor ${index+1}`, value: monitor.id })) // set index first so it matches <Monitor>
24
+ .filter((option) => {
25
+ const monitor = $monitors.find((m) => m.id === option.value);
26
+
27
+ return monitor.selected !== "output";
28
+ });
29
+ $: {
30
+ monitorDisabled = samplerOptions.length === 0;
31
+
32
+ if (samplerOptions.length === 0) {
33
+ samplerOptions = [
34
+ { label: `No monitor available.`, value: -1 }
35
+ ];
36
+ sampler0 = samplerOptions[0].value;
37
+ sampler1 = samplerOptions[0].value;
38
+ } else {
39
+ if (sampler0 < 0) {
40
+ sampler0 = samplerOptions[0].value;
41
+ }
42
+
43
+ if (sampler1 < 0) {
44
+ sampler1 = samplerOptions.length > 1 ? samplerOptions[1].value : -1;
45
+ }
46
+ }
47
+
48
+ $multisampling = [sampler0, sampler1];
49
+ }
50
+
51
+ </script>
52
+ <FieldGroup name="monitors">
53
+ <Field
54
+ key="sampler0"
55
+ value={sampler0}
56
+ on:change={event => {
57
+ sampler0 = Number(event.detail);
58
+ }}
59
+ params={
60
+ {
61
+ options: samplerOptions,
62
+ disabled: monitorDisabled
63
+ }
64
+ }
65
+ />
66
+ <Field
67
+ key="sampler1"
68
+ value={sampler1}
69
+ on:change={event => {
70
+ sampler1 = Number(event.detail);
71
+ }}
72
+ params={
73
+ {
74
+ options: samplerOptions,
75
+ disabled: monitorDisabled
76
+ }
77
+ }
78
+ />
79
+ </FieldGroup>
80
+ <FieldGroup name="transition">
81
+ <Field
82
+ key="type"
83
+ value={$transition}
84
+ on:change={(event) => {
85
+ $transition = event.detail;
86
+ }}
87
+ params={{
88
+ options: transitionOptions,
89
+ }}
90
+ />
91
+ <Field
92
+ key="threshold"
93
+ value={$threshold}
94
+ on:change={(event) => $threshold = event.detail }
95
+ params={{
96
+ step: 0.01,
97
+ min: 0,
98
+ max: 1,
99
+ }}
100
+ />
101
+ <Field
102
+ key="switch"
103
+ value={() => $threshold = 1 - Math.round($threshold)}
104
+ params={{
105
+ label: `switch ${Math.round($threshold) > 0 ? `<` : `>`}`
106
+ }}
107
+ />
108
+
109
+ </FieldGroup>
@@ -0,0 +1,139 @@
1
+ <script>
2
+ import { rendering, SIZES, monitors } from "../stores/rendering.js";
3
+ import { sketchesCount } from "../stores/sketches.js";
4
+ import Field from "./Field.svelte";
5
+ import presets, { getDimensionsForPreset } from "../lib/presets";
6
+ import { exports } from "../stores";
7
+ import ParamsMultisampling from "./ParamsMultisampling.svelte";
8
+
9
+ let canvasWidth = $rendering.width;
10
+ let canvasHeight = $rendering.height;
11
+
12
+ function handleChangeDimensions(event) {
13
+ const [width, height] = event.detail;
14
+ const needsUpdate = canvasWidth !== width || canvasHeight !== height;
15
+
16
+ if (needsUpdate) {
17
+ canvasWidth = width;
18
+ canvasHeight = height;
19
+
20
+ rendering.update((curr) => {
21
+ return {
22
+ ...curr,
23
+ width,
24
+ height
25
+ }
26
+ });
27
+ }
28
+ }
29
+
30
+ let sizes = Object.values(SIZES);
31
+ $: dimensionsEnabled = [SIZES.FIXED, SIZES.SCALE].includes($rendering.resizing);
32
+
33
+ $: {
34
+ if ($rendering.resizing === SIZES.PRESET) {
35
+ const { preset } = $rendering;
36
+ const [ width, height ] = getDimensionsForPreset(preset, { pixelsPerInch: 300 });
37
+
38
+ rendering.update((curr) => {
39
+ return {
40
+ ...curr,
41
+ width,
42
+ height,
43
+ };
44
+ });
45
+ }
46
+ }
47
+
48
+ </script>
49
+
50
+ <Field
51
+ key="dimensions"
52
+ value={[
53
+ $rendering.width,
54
+ $rendering.height,
55
+ ]}
56
+ on:change={handleChangeDimensions}
57
+ params={{
58
+ step: 1,
59
+ suffix: "px",
60
+ locked: false,
61
+ disabled: !dimensionsEnabled,
62
+ }}
63
+ />
64
+ <Field
65
+ key="canvasSize"
66
+ value={$rendering.resizing}
67
+ on:change={(event) => {
68
+ const resizing = event.detail;
69
+ let aspectRatio = 1;
70
+
71
+ if (resizing === SIZES.ASPECT_RATIO) {
72
+ // compute aspect ratio based on previous props
73
+ aspectRatio = $rendering.width / $rendering.height;
74
+ }
75
+
76
+ $exports.pixelsPerInch = resizing === SIZES.PRESET ? 300 : 72;
77
+
78
+ rendering.update((curr) => {
79
+ return {
80
+ ...curr,
81
+ resizing,
82
+ aspectRatio,
83
+ }
84
+ });
85
+ }}
86
+ params={{
87
+ options: sizes,
88
+ }}
89
+ />
90
+ {#if $rendering.resizing === SIZES.ASPECT_RATIO}
91
+ <Field
92
+ key="aspectRatio"
93
+ value={$rendering.aspectRatio}
94
+ on:change={(event) => {
95
+ $rendering.aspectRatio = event.detail;
96
+ }}
97
+ params={{
98
+ step: 0.01,
99
+ }}
100
+ />
101
+ {/if}
102
+ {#if $rendering.resizing === SIZES.SCALE}
103
+ <Field
104
+ key="zoom"
105
+ value={$rendering.scale}
106
+ on:change={(event) => {
107
+ $rendering.scale = event.detail;
108
+ }}
109
+ params={{
110
+ step: 0.01,
111
+ }}
112
+ />
113
+ {/if}
114
+ {#if $rendering.resizing === SIZES.PRESET}
115
+ <Field
116
+ key="preset"
117
+ value={$rendering.preset}
118
+ on:change={(event) => {
119
+ $rendering.preset = event.detail;
120
+ }}
121
+ params={{
122
+ options: presets,
123
+ }}
124
+ />
125
+ {/if}
126
+
127
+ {#if $rendering.resizing !== SIZES.PRESET }
128
+ <Field
129
+ key="pixelRatio"
130
+ value={Number($rendering.pixelRatio)}
131
+ on:change={(event) => $rendering.pixelRatio = event.detail }
132
+ params={{
133
+ step: 0.1,
134
+ }}
135
+ />
136
+ {/if}
137
+ {#if $sketchesCount > 1 && $monitors.length > 1 }
138
+ <ParamsMultisampling />
139
+ {/if}
@@ -0,0 +1,15 @@
1
+ <script>
2
+ import { onDestroy } from "svelte";
3
+
4
+ import { rendering } from "../stores/rendering";
5
+ import Build from "./Build.svelte";
6
+
7
+ let saved = $rendering;
8
+
9
+ onDestroy(() => {
10
+ $rendering = saved;
11
+ });
12
+
13
+ </script>
14
+
15
+ <Build />
@@ -0,0 +1,25 @@
1
+ <script>
2
+ export let width = 24;
3
+ export let height = 24;
4
+ </script>
5
+
6
+ <div class="chevrons" style={`width: ${width}px;`}>
7
+ <svg class="chevron chevron-bottom" width={width} height={height} fill="none" viewBox="0 0 24 24">
8
+ <path stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" d="M15.25 10.75L12 14.25L8.75 10.75"></path>
9
+ </svg>
10
+ </div>
11
+
12
+ <style>
13
+ .chevrons {
14
+ position: absolute;
15
+ top: 0;
16
+ right: 0;
17
+ bottom: 0;
18
+ display: flex;
19
+ align-items: center;
20
+ width: 15px;
21
+
22
+ color: var(--color, currentColor);
23
+ pointer-events: none;
24
+ }
25
+ </style>