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.
- package/LICENSE.md +21 -0
- package/README.md +101 -0
- package/bin/index.js +19 -0
- package/docs/README.md +18 -0
- package/docs/api/CLI.md +44 -0
- package/docs/api/renderers.md +80 -0
- package/docs/api/sketch.md +216 -0
- package/docs/api/triggers.md +101 -0
- package/docs/guide/about.md +16 -0
- package/docs/guide/exports.md +86 -0
- package/docs/guide/external-dependencies.md +22 -0
- package/docs/guide/getting-started.md +113 -0
- package/docs/guide/hot-shader-reloading.md +20 -0
- package/docs/guide/shortcuts.md +12 -0
- package/docs/guide/triggers.png +0 -0
- package/docs/guide/using-triggers.md +39 -0
- package/examples/cube-three.js +34 -0
- package/examples/ellipse-p5.js +26 -0
- package/examples/icon.fs +96 -0
- package/examples/icon.js +63 -0
- package/examples/icon.png +0 -0
- package/examples/icon.transparent.png +0 -0
- package/examples/package-lock.json +40 -0
- package/examples/package.json +15 -0
- package/examples/shape-2d.js +45 -0
- package/examples/shape-three.js +49 -0
- package/examples/shape-tree.fs +3 -0
- package/package.json +37 -0
- package/screenshot.png +0 -0
- package/src/cli/db.js +17 -0
- package/src/cli/index.js +198 -0
- package/src/cli/log.js +26 -0
- package/src/cli/plugins/check-dependencies.js +77 -0
- package/src/cli/plugins/db.js +12 -0
- package/src/cli/plugins/hot-shader-reload.js +86 -0
- package/src/cli/plugins/hot-sketch-reload.js +39 -0
- package/src/cli/plugins/screenshot.js +31 -0
- package/src/cli/server.js +140 -0
- package/src/cli/templates/2d.js +15 -0
- package/src/cli/templates/fragment.fs +10 -0
- package/src/cli/templates/fragment.js +18 -0
- package/src/cli/templates/index.js +24 -0
- package/src/cli/templates/p5.js +13 -0
- package/src/cli/templates/three-fragment.js +53 -0
- package/src/cli/templates/three-orthographic.js +23 -0
- package/src/cli/templates/three-perspective.js +20 -0
- package/src/cli/ws.js +92 -0
- package/src/client/app/App.svelte +8 -0
- package/src/client/app/client.js +68 -0
- package/src/client/app/components/IconCross.svelte +29 -0
- package/src/client/app/components/Init.svelte +13 -0
- package/src/client/app/components/KeyBinding.svelte +32 -0
- package/src/client/app/inputs/Input.js +15 -0
- package/src/client/app/inputs/Keyboard.js +21 -0
- package/src/client/app/inputs/MIDI.js +144 -0
- package/src/client/app/inputs/Mouse.js +5 -0
- package/src/client/app/inputs/Webcam.js +98 -0
- package/src/client/app/lib/canvas-recorder/CanvasRecorder.js +88 -0
- package/src/client/app/lib/canvas-recorder/FFMPEGRecorder.js +56 -0
- package/src/client/app/lib/canvas-recorder/FrameRecorder.js +40 -0
- package/src/client/app/lib/canvas-recorder/GIFRecorder.js +52 -0
- package/src/client/app/lib/canvas-recorder/MP4Recorder.js +46 -0
- package/src/client/app/lib/canvas-recorder/WebMRecorder.js +30 -0
- package/src/client/app/lib/canvas-recorder/mp4.js +20 -0
- package/src/client/app/lib/canvas-recorder/mp4.wasm +0 -0
- package/src/client/app/lib/canvas-recorder/utils.js +22 -0
- package/src/client/app/lib/gl/Geometry.js +39 -0
- package/src/client/app/lib/gl/Program.js +130 -0
- package/src/client/app/lib/gl/Renderer.js +148 -0
- package/src/client/app/lib/gl/Texture.js +114 -0
- package/src/client/app/lib/gl/index.js +109 -0
- package/src/client/app/lib/gl/utils.js +5 -0
- package/src/client/app/lib/helpers/frameDebounce.js +40 -0
- package/src/client/app/lib/loader/index.js +20 -0
- package/src/client/app/lib/loader/loadImage.js +19 -0
- package/src/client/app/lib/loader/loadScript.js +14 -0
- package/src/client/app/lib/paper-sizes.js +104 -0
- package/src/client/app/lib/presets.js +12 -0
- package/src/client/app/lib/tempo/Analyser.js +165 -0
- package/src/client/app/lib/tempo/Range.js +97 -0
- package/src/client/app/lib/tempo/index.js +138 -0
- package/src/client/app/modules/AudioAnalyser/Range.svelte +93 -0
- package/src/client/app/modules/AudioAnalyser/Spectrum.svelte +31 -0
- package/src/client/app/modules/AudioAnalyser.svelte +70 -0
- package/src/client/app/modules/Console/ConsoleLine.svelte +254 -0
- package/src/client/app/modules/Console.svelte +82 -0
- package/src/client/app/modules/Exports.svelte +105 -0
- package/src/client/app/modules/MidiPanel.svelte +106 -0
- package/src/client/app/modules/Monitor.svelte +62 -0
- package/src/client/app/modules/Params.svelte +112 -0
- package/src/client/app/renderers/2DRenderer.js +5 -0
- package/src/client/app/renderers/FragmentRenderer.js +62 -0
- package/src/client/app/renderers/OGLRenderer.js +0 -0
- package/src/client/app/renderers/P5Renderer.js +39 -0
- package/src/client/app/renderers/THREERenderer.js +128 -0
- package/src/client/app/stores/audioAnalysis.js +10 -0
- package/src/client/app/stores/console.js +76 -0
- package/src/client/app/stores/errors.js +25 -0
- package/src/client/app/stores/exports.js +28 -0
- package/src/client/app/stores/index.js +2 -0
- package/src/client/app/stores/layout.js +187 -0
- package/src/client/app/stores/multisampling.js +16 -0
- package/src/client/app/stores/props.js +44 -0
- package/src/client/app/stores/renderers.js +60 -0
- package/src/client/app/stores/rendering.js +111 -0
- package/src/client/app/stores/sketches.js +40 -0
- package/src/client/app/stores/time.js +27 -0
- package/src/client/app/stores/utils.js +66 -0
- package/src/client/app/transitions/fade.js +17 -0
- package/src/client/app/transitions/index.js +12 -0
- package/src/client/app/transitions/splitX.js +16 -0
- package/src/client/app/transitions/splitY.js +16 -0
- package/src/client/app/triggers/Keyboard.js +95 -0
- package/src/client/app/triggers/MIDI.js +122 -0
- package/src/client/app/triggers/Mouse.js +96 -0
- package/src/client/app/triggers/Trigger.js +71 -0
- package/src/client/app/triggers/index.js +19 -0
- package/src/client/app/triggers/shared.js +37 -0
- package/src/client/app/ui/Build.svelte +96 -0
- package/src/client/app/ui/ErrorOverlay.svelte +130 -0
- package/src/client/app/ui/Field.svelte +262 -0
- package/src/client/app/ui/FieldGroup.svelte +103 -0
- package/src/client/app/ui/FieldSection.svelte +123 -0
- package/src/client/app/ui/FieldSpace.svelte +37 -0
- package/src/client/app/ui/FieldTrigger.svelte +263 -0
- package/src/client/app/ui/FieldTriggers.svelte +58 -0
- package/src/client/app/ui/FloatingParams.svelte +49 -0
- package/src/client/app/ui/Layout.svelte +50 -0
- package/src/client/app/ui/LayoutColumn.svelte +9 -0
- package/src/client/app/ui/LayoutComponent.svelte +279 -0
- package/src/client/app/ui/LayoutResizer.svelte +218 -0
- package/src/client/app/ui/LayoutRoot.svelte +11 -0
- package/src/client/app/ui/LayoutRow.svelte +9 -0
- package/src/client/app/ui/LayoutToolbar.svelte +264 -0
- package/src/client/app/ui/Module.svelte +154 -0
- package/src/client/app/ui/ModuleHeaderAction.svelte +87 -0
- package/src/client/app/ui/ModuleHeaderButton.svelte +21 -0
- package/src/client/app/ui/ModuleHeaderSelect.svelte +50 -0
- package/src/client/app/ui/ModuleRenderer.svelte +38 -0
- package/src/client/app/ui/OutputRenderer.svelte +149 -0
- package/src/client/app/ui/ParamsMultisampling.svelte +109 -0
- package/src/client/app/ui/ParamsOutput.svelte +139 -0
- package/src/client/app/ui/Preview.svelte +15 -0
- package/src/client/app/ui/SelectChevrons.svelte +25 -0
- package/src/client/app/ui/SketchRenderer.svelte +672 -0
- package/src/client/app/ui/SketchSelect.svelte +49 -0
- package/src/client/app/ui/fields/ButtonInput.svelte +54 -0
- package/src/client/app/ui/fields/CheckboxInput.svelte +70 -0
- package/src/client/app/ui/fields/ColorInput.svelte +187 -0
- package/src/client/app/ui/fields/FieldInputRow.svelte +13 -0
- package/src/client/app/ui/fields/ImageInput.svelte +145 -0
- package/src/client/app/ui/fields/Input.svelte +120 -0
- package/src/client/app/ui/fields/ListInput.svelte +106 -0
- package/src/client/app/ui/fields/NumberInput.svelte +114 -0
- package/src/client/app/ui/fields/ProgressInput.svelte +90 -0
- package/src/client/app/ui/fields/Select.svelte +116 -0
- package/src/client/app/ui/fields/TextInput.svelte +18 -0
- package/src/client/app/ui/fields/Vec2Input.svelte +5 -0
- package/src/client/app/ui/fields/Vec3Input.svelte +6 -0
- package/src/client/app/ui/fields/VectorInput.svelte +102 -0
- package/src/client/app/utils/canvas.utils.js +229 -0
- package/src/client/app/utils/color.utils.js +427 -0
- package/src/client/app/utils/file.utils.js +77 -0
- package/src/client/app/utils/glsl.utils.js +14 -0
- package/src/client/app/utils/glslErrors.js +154 -0
- package/src/client/app/utils/index.js +39 -0
- package/src/client/app/utils/math.utils.js +23 -0
- package/src/client/app/utils/props.utils.js +53 -0
- package/src/client/index.html +18 -0
- package/src/client/main.js +9 -0
- package/src/client/public/css/global.css +115 -0
- package/src/client/public/favicon.ico +0 -0
- package/src/client/public/fonts/Inter-Bold.woff2 +0 -0
- package/src/client/public/fonts/Inter-Italic.woff2 +0 -0
- package/src/client/public/fonts/Inter-Regular.woff2 +0 -0
- package/src/client/public/fonts/Inter-SemiBold.woff2 +0 -0
- package/src/client/public/fonts/JetBrainsMono-Regular.woff2 +0 -0
- package/src/client/public/icons/chevron-bottom.svg +3 -0
- package/src/client/public/icons/chevron-right.svg +3 -0
- package/src/client/public/icons/chevron-top.svg +3 -0
- package/src/client/public/icons/columns-horizontal.svg +4 -0
- package/src/client/public/icons/columns-vertical.svg +4 -0
- package/src/client/public/icons/folder-plus.svg +6 -0
- package/src/client/public/icons/lock.svg +4 -0
- package/src/client/public/icons/picture-in-picture.svg +4 -0
- package/src/client/public/icons/trash.svg +5 -0
- package/src/client/public/icons/trigger.svg +8 -0
- package/src/client/public/icons/unlock.svg +4 -0
- package/src/client/public/js/ffmpeg.min.js +2 -0
- package/src/client/public/js/ffmpeg.min.js.map +1 -0
- package/src/client/public/js/gif.js +2 -0
- package/src/client/public/js/gif.worker.js +2 -0
package/LICENSE.md
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2022 Raphaël Améaume
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
<h1 align="center">Fragment</h1>
|
|
2
|
+
<div align="center">A web development environment for creative coding</div>
|
|
3
|
+
<br/>
|
|
4
|
+
|
|
5
|
+

|
|
6
|
+
|
|
7
|
+
`fragment` provides a simple API to work with `<canvas>`.
|
|
8
|
+
|
|
9
|
+
## Features
|
|
10
|
+
|
|
11
|
+
- Multiple rendering modes: [Canvas 2D](https://developer.mozilla.org/en-US/docs/Web/API/Canvas_API), [p5.js](https://github.com/processing/p5.js/), [three.js](https://github.com/mrdoob/three.js/), [WebGL fragment shaders](https://developer.mozilla.org/en-US/docs/Web/API/WebGLShader)
|
|
12
|
+
- Built-in GUI from sketch files
|
|
13
|
+
- Export `<canvas>` to images (.png, .webm, .jpg) or videos (.mp4, .webm, .gif) on the fly
|
|
14
|
+
- Hot shader reloading & [glslify](https://github.com/glslify/glslify) support
|
|
15
|
+
- Interactive sketches using *triggers*
|
|
16
|
+
- Static build for production deployment
|
|
17
|
+
|
|
18
|
+
## Installation
|
|
19
|
+
|
|
20
|
+
`fragment` is not yet available on [npmjs.com](npmjs.com) so you need to clone and link the project in order to use it. It's only a few steps.
|
|
21
|
+
|
|
22
|
+
```
|
|
23
|
+
# clone the project
|
|
24
|
+
git clone https://github.com/raphaelameaume/fragment
|
|
25
|
+
|
|
26
|
+
# move to the project directory
|
|
27
|
+
cd fragment
|
|
28
|
+
|
|
29
|
+
# link the project
|
|
30
|
+
npm link
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
You should now be able to run `fragment` from your command line. If you encounter any issues, you can read more about linking on [npmjs.com](https://docs.npmjs.com/cli/v8/commands/npm-link).
|
|
34
|
+
|
|
35
|
+
## Usage
|
|
36
|
+
|
|
37
|
+
```
|
|
38
|
+
# create a new directory for your sketches
|
|
39
|
+
mkdir ../sketches
|
|
40
|
+
|
|
41
|
+
# move into that folder
|
|
42
|
+
cd sketches
|
|
43
|
+
|
|
44
|
+
# initialize npm for linking to work
|
|
45
|
+
npm init
|
|
46
|
+
|
|
47
|
+
# create a sketch from a template
|
|
48
|
+
fragment ./sketch.js --new --template=2d
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
Learn more about the available flag options in the [CLI docs](./docs/api/CLI.md).
|
|
52
|
+
|
|
53
|
+
## Example
|
|
54
|
+
|
|
55
|
+
This is an example of a sketch drawing a blue circle on a black background with a custom control for the radius of the circle.
|
|
56
|
+
|
|
57
|
+
```js
|
|
58
|
+
export let props = {
|
|
59
|
+
radius: {
|
|
60
|
+
value: 10,
|
|
61
|
+
params: {
|
|
62
|
+
min: 4,
|
|
63
|
+
max: 30
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
};
|
|
67
|
+
|
|
68
|
+
export let update = ({ context, width, height }) => {
|
|
69
|
+
// draw background
|
|
70
|
+
context.fillStyle = '#000000';
|
|
71
|
+
context.fillRect(0, 0, width, height);
|
|
72
|
+
|
|
73
|
+
// draw circle
|
|
74
|
+
const radius = props.radius.value;
|
|
75
|
+
|
|
76
|
+
context.fillStyle = '#0000ff';
|
|
77
|
+
context.beginPath();
|
|
78
|
+
context.arc(width * 0.5, height * 0.5, radius, 0, 2 * Math.PI, false);
|
|
79
|
+
context.fill();
|
|
80
|
+
};
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
Learn how to write your own sketch in the [API docs](./docs/api/sketch.md) or read the [examples](./examples/).
|
|
84
|
+
|
|
85
|
+
## Contributing
|
|
86
|
+
|
|
87
|
+
If you find issues, please [file one](https://github.com/raphaelameaume/fragment/issues) with details on how to reproduce it.
|
|
88
|
+
|
|
89
|
+
Feel free to reach out on [Twitter](https://twitter.com/raphaelameaume) if you want to discuss the project.
|
|
90
|
+
|
|
91
|
+
## Credits
|
|
92
|
+
|
|
93
|
+
- [Vite](https://vitejs.dev/)
|
|
94
|
+
- [Svelte](https://svelte.dev/)
|
|
95
|
+
- The font used for display is the [JetBrains Mono](https://www.jetbrains.com/lp/mono/).
|
|
96
|
+
- Icons are from [Iconic](https://iconic.app/)
|
|
97
|
+
- A special thanks to [Matt Deslauriers](https://www.mattdesl.com/) for [canvas-sketch](https://github.com/mattdesl/canvas-sketch) and his multiple projects around generative-art tools.
|
|
98
|
+
|
|
99
|
+
## License
|
|
100
|
+
|
|
101
|
+
See [LICENSE.md](./LICENSE.md) for details.
|
package/bin/index.js
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
import sade from "sade";
|
|
4
|
+
import { run } from "../src/cli/index.js";
|
|
5
|
+
|
|
6
|
+
sade('fragment [entry]')
|
|
7
|
+
.version('0.1.0')
|
|
8
|
+
.describe('Run a dev environment for fragment')
|
|
9
|
+
.option('-n, --new', 'Create file if it does not exist', false)
|
|
10
|
+
.option('-t, --template', 'Specify template to create the file from', '2d')
|
|
11
|
+
.option('-p, --port', 'Port to bind', 3000)
|
|
12
|
+
.option('-dev, --development', 'Enable development mode', false)
|
|
13
|
+
.option('-b, --build', 'Build sketch for production', false)
|
|
14
|
+
.option('--outDir', 'Directory used for static build', null)
|
|
15
|
+
.option('--emptyOutDir', "Empty outDir before static build", false)
|
|
16
|
+
.action((entry, options) => {
|
|
17
|
+
run(entry, options);
|
|
18
|
+
})
|
|
19
|
+
.parse(process.argv);
|
package/docs/README.md
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
#### <sup>[fragment](../README.md) → [Documentation](./README.md)</sup>
|
|
2
|
+
<br>
|
|
3
|
+
|
|
4
|
+
## Guide
|
|
5
|
+
- [About](./guide/about.md)
|
|
6
|
+
- [Getting started](./guide/getting-started.md)
|
|
7
|
+
- [Export a sketch](./guide/exports.md)
|
|
8
|
+
- [Using external dependencies](./guide/external-dependencies.md)
|
|
9
|
+
- [Using triggers](./guide/using-triggers.md)
|
|
10
|
+
- [Hot Shader Reloading](./guide/hot-shader-reloading.md)
|
|
11
|
+
- [Shortcuts](./guide/shortcuts.md)
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
## APIs
|
|
15
|
+
- [CLI](./api/CLI.md)
|
|
16
|
+
- [Sketch](./api/sketch.md)
|
|
17
|
+
- [Renderers](./api/renderers.md)
|
|
18
|
+
- [Triggers](./api/triggers.md)
|
package/docs/api/CLI.md
ADDED
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
#### <sup>[fragment](../../README.md) → [Documentation](../README.md) → [API](../README.md#apis) → CLI</sup>
|
|
2
|
+
<br>
|
|
3
|
+
|
|
4
|
+
# CLI
|
|
5
|
+
|
|
6
|
+
Once `fragment` is properly [installed](../../README.md#installation), you can launch it and create sketches from the command line.
|
|
7
|
+
|
|
8
|
+
## Usage
|
|
9
|
+
|
|
10
|
+
`fragment [file] [opts]`
|
|
11
|
+
|
|
12
|
+
## Examples
|
|
13
|
+
|
|
14
|
+
```
|
|
15
|
+
# Start fragment with an existing sketch
|
|
16
|
+
fragment ./sketch.js
|
|
17
|
+
|
|
18
|
+
# Create a new file on disk and start
|
|
19
|
+
fragment ./sketch.js --new
|
|
20
|
+
|
|
21
|
+
# Create a new file from a pre-defined template
|
|
22
|
+
fragment ./sketch.js --new --template=three/orthographic
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
## Options
|
|
26
|
+
|
|
27
|
+
| Flag | Shortcut | Description | Default |
|
|
28
|
+
|---|---|---|---|
|
|
29
|
+
|`--new`| `-n` | Create a new file and start | `false` |
|
|
30
|
+
|`--template`| `-t` | Specify the type of template to use as source | `2d` |
|
|
31
|
+
|`--port`| `-p` | Specify the server port. | `3000` |
|
|
32
|
+
|`--build`| `-b` | Build sketch for production | `false` |
|
|
33
|
+
|`--outDir`| `none` | Change directory used for production build | `[/[sketch-name]` |
|
|
34
|
+
|`--emptyOutDir`| `none` | Empty outDir before static build | `false` |
|
|
35
|
+
|
|
36
|
+
## Templates
|
|
37
|
+
|
|
38
|
+
`fragment` currently supports the following templates:
|
|
39
|
+
- [2d](../../src/cli/templates/2d.js)
|
|
40
|
+
- [fragment](../../src/cli/templates/fragment.js)
|
|
41
|
+
- [three/fragment](../../src/cli/templates/three-fragment.js)
|
|
42
|
+
- [three/orthographic](../../src/cli/templates/three-orthographic.js)
|
|
43
|
+
- [three/perspective](../../src/cli/templates/three-perspective.js)
|
|
44
|
+
- [p5](../../src/cli/templates/p5.js)
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
#### <sup>[fragment](../../README.md) → [Documentation](../README.md) → [API](../README.md#apis) → Renderers</sup>
|
|
2
|
+
<br>
|
|
3
|
+
|
|
4
|
+
# Renderers
|
|
5
|
+
|
|
6
|
+
They described systems that take *sketchs* as input and output their results to a canvas. A renderer should be capable of displaying multiple skeches of the same *rendering* at the same time in the most efficient way possible, meaning it should share ressources between sketches whenever possible.
|
|
7
|
+
|
|
8
|
+
A renderer can implement the [*hooks*](#hooks) described here in order to match requirements described above.
|
|
9
|
+
|
|
10
|
+
## Hooks
|
|
11
|
+
|
|
12
|
+
#### `init`
|
|
13
|
+
- Type: `() => InitParams`
|
|
14
|
+
|
|
15
|
+
Called once on the first time a sketch with matching rendering is mounted. Useful to create and save ressources that will be shared across sketches. The object returned from this function will spread as params and made available to sketch hooks.
|
|
16
|
+
|
|
17
|
+
Example:
|
|
18
|
+
```js
|
|
19
|
+
// renderer.js
|
|
20
|
+
export let init = () => {
|
|
21
|
+
let renderer = createRenderer();
|
|
22
|
+
let value = true;
|
|
23
|
+
|
|
24
|
+
return {
|
|
25
|
+
renderer,
|
|
26
|
+
value,
|
|
27
|
+
}
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
// sketch.js
|
|
31
|
+
export let init = ({ renderer, value }) => {
|
|
32
|
+
console.log(value); // true
|
|
33
|
+
};
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
#### `onMountPreview`
|
|
37
|
+
- Type: `({ index: number, canvas: HTMLCanvasElement }) => MountParams`
|
|
38
|
+
|
|
39
|
+
Called everytime a sketch is mounted or hot reloaded. The object returned from this function will spread as params and made available to sketch hooks.
|
|
40
|
+
|
|
41
|
+
```js
|
|
42
|
+
// renderer.js
|
|
43
|
+
export let onMountPreview = ({ index }) => {
|
|
44
|
+
return {
|
|
45
|
+
previewIndex: index,
|
|
46
|
+
};
|
|
47
|
+
};
|
|
48
|
+
|
|
49
|
+
// sketch.js
|
|
50
|
+
export let update = ({ previewIndex }) => {
|
|
51
|
+
console.log(previewIndex); // 0
|
|
52
|
+
};
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
> ⚠️ InitParams and MountParams are both spread at the same level and in this order, so if you export an object key from `init()` and the same key for a different value from `onMountPreview`, `onMountPreview` value will take over as the spread happen {...InitParams, ...MountParams }.
|
|
56
|
+
|
|
57
|
+
#### `onBeforeUpdatePreview`
|
|
58
|
+
- Type: `({ index: number, canvas: HTMLCanvasElement }) => void`
|
|
59
|
+
|
|
60
|
+
Called on each frame before `sketch.update()`.
|
|
61
|
+
|
|
62
|
+
#### `onAfterUpdatePreview`
|
|
63
|
+
- Type: `({ index: number, canvas: HTMLCanvasElement }) => void`
|
|
64
|
+
|
|
65
|
+
Called on each frame after `sketch.update()`.
|
|
66
|
+
|
|
67
|
+
#### `onResizePreview`
|
|
68
|
+
- Type: `({ index: number, canvas: HTMLCanvasElement, width: number, height: number }) => void`
|
|
69
|
+
|
|
70
|
+
Called for each preview when OutputParams.canvasSize or OutputParams.dimensions change.
|
|
71
|
+
|
|
72
|
+
#### `onDestroyPreview`
|
|
73
|
+
- Type: `({ index: number, canvas: HTMLCanvasElement }) => void`
|
|
74
|
+
|
|
75
|
+
Called when a sketch is unmounted or hot reloaded.
|
|
76
|
+
|
|
77
|
+
#### `resize`
|
|
78
|
+
- Type: `({ width: number, height: number, pixelRatio: number }) => void`
|
|
79
|
+
|
|
80
|
+
Called once when OutputParams.canvasSize or OutputParams.dimensions change.
|
|
@@ -0,0 +1,216 @@
|
|
|
1
|
+
#### <sup>[fragment](../../README.md) → [Documentation](../README.md) → [API](../README.md#apis) → Sketch</sup>
|
|
2
|
+
<br>
|
|
3
|
+
|
|
4
|
+
# Sketch
|
|
5
|
+
|
|
6
|
+
A sketch in `fragment` is the entry point of your project. Its API is fairly simple, supports different types of renderings and can grow in complexity.
|
|
7
|
+
|
|
8
|
+
## Lifecycle
|
|
9
|
+
|
|
10
|
+
Each time your sketch is saved, the previous one is destroyed and a new *lifecycle* is called. Internally, `fragment` will call available [exports](./#exports) from your sketch in this specific order.
|
|
11
|
+
|
|
12
|
+
```js
|
|
13
|
+
sketch.init();
|
|
14
|
+
sketch.resize();
|
|
15
|
+
sketch.update();
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
## Exports
|
|
19
|
+
|
|
20
|
+
`fragment` leverages the power of [named ESM exports](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/export), meaning that you can export various properties from your sketch entry point and they will be picked up on runtime.
|
|
21
|
+
|
|
22
|
+
#### `init`
|
|
23
|
+
- Type: `({ canvas: HTMLCanvasElement, width: number, height: number, pixelRatio, ...params: {...InitParams, ...MountParams }}) => void`
|
|
24
|
+
|
|
25
|
+
| name | type | description |
|
|
26
|
+
|---|---|---|
|
|
27
|
+
| canvas | `HTMLCanvasElement` | The canvas element used for drawing |
|
|
28
|
+
| width | `number` | Width of the canvas |
|
|
29
|
+
| height | `number` | Height of the canvas |
|
|
30
|
+
| pixelRatio | `number` | PixelRatio of the canvas |
|
|
31
|
+
|
|
32
|
+
Depending on the rendering context, params can contain different things.
|
|
33
|
+
|
|
34
|
+
> ⚠ Notice the spread operator `...` before `params`, this means that the rest of the object will be "collected" into a single object called `params`. The values defined here are available directly if you want:
|
|
35
|
+
|
|
36
|
+
##### `rendering = "2d"`
|
|
37
|
+
| name | type | description |
|
|
38
|
+
|---|---|---|
|
|
39
|
+
| `context` | `CanvasRenderingContext2D` | The context of the canvas |
|
|
40
|
+
##### `rendering = "p5"`
|
|
41
|
+
| name | type | description |
|
|
42
|
+
|---|---|---|
|
|
43
|
+
| `p` | `p5Instance` | The p5 instance |
|
|
44
|
+
##### `rendering = "three"`
|
|
45
|
+
| name | type | description |
|
|
46
|
+
|---|---|---|
|
|
47
|
+
| `renderer` | `THREE.WebGLRenderer` | The three.js WebGLRenderer |
|
|
48
|
+
| `scene` | `THREE.Scene` | A instance of THREE.Scene |
|
|
49
|
+
##### `rendering = "fragment"`
|
|
50
|
+
| name | type | description |
|
|
51
|
+
|---|---|---|
|
|
52
|
+
| `frag` | `fragmentInstance` | The fragment instance |
|
|
53
|
+
|
|
54
|
+
```js
|
|
55
|
+
export let rendering = "2d";
|
|
56
|
+
|
|
57
|
+
export let init = ({ context, width, height }) => {
|
|
58
|
+
context.fillStyle = '#ff0000';
|
|
59
|
+
};
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
#### `update`
|
|
63
|
+
- Type: `({ time: number, deltaTime: number, playhead?: number, playcount?: number }) => void`
|
|
64
|
+
|
|
65
|
+
| name | type | description |
|
|
66
|
+
|---|---|---|
|
|
67
|
+
| time | `number` | Amount of time ellapsed since the start of fragment. In milliseconds |
|
|
68
|
+
| deltaTime | `number` | Amount of time ellapsed since the last frame. In milliseconds |
|
|
69
|
+
| playhead | `number` | If [`duration`](#duration) is defined, playhead will go from 0 to 1 every specified duration |
|
|
70
|
+
| playcount | `number` | If [`duration`](#duration) is defined, playcount will increase of 1 every loop |
|
|
71
|
+
|
|
72
|
+
#### `resize`
|
|
73
|
+
- Type: `({ width: number, height: number, pixelRatio: number }) => void`
|
|
74
|
+
|
|
75
|
+
| name | type | description |
|
|
76
|
+
|---|---|---|
|
|
77
|
+
| width | `number` | Width of the canvas |
|
|
78
|
+
| height | `number` | Height of the canvas |
|
|
79
|
+
| pixelRatio | `number` | PixelRatio of the canvas |
|
|
80
|
+
|
|
81
|
+
#### `props`
|
|
82
|
+
- Type: `SketchProps`
|
|
83
|
+
|
|
84
|
+
See [SketchProps](#sketchprops) for details.
|
|
85
|
+
|
|
86
|
+
#### `rendering`
|
|
87
|
+
- Type: `string`
|
|
88
|
+
- Values: `2d`, `three`, `p5`, `fragment`
|
|
89
|
+
- Default: `2d`
|
|
90
|
+
|
|
91
|
+
> ⚠ If you used either `three` or `p5` rendering, you'll need to install them from your project root directory in order to make it work.
|
|
92
|
+
|
|
93
|
+
```
|
|
94
|
+
npm install three --save
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
#### `duration`
|
|
98
|
+
- Type: `number`
|
|
99
|
+
- Default: `undefined`
|
|
100
|
+
|
|
101
|
+
Setting a duration to a sketch will compute correct values for `playhead` and `playcount` in [`update`](#update) callback params.
|
|
102
|
+
|
|
103
|
+
#### `fps`
|
|
104
|
+
- Type: `number`
|
|
105
|
+
- Default: `60`
|
|
106
|
+
|
|
107
|
+
Change how many times `update()` is called in 1 second. Py default, the value is 60, meaning `update()` will be called on every *requestAnimationFrame*.
|
|
108
|
+
If you set it to `0`, `fragment` will only call `update()` once at the end of the *lifecycle* and when `props` change.
|
|
109
|
+
|
|
110
|
+
#### `name`
|
|
111
|
+
- Type: `string`
|
|
112
|
+
- Default: `[filename]`
|
|
113
|
+
|
|
114
|
+
Change the value used for display in the monitor dropdown.
|
|
115
|
+
|
|
116
|
+
#### `filenamePattern`
|
|
117
|
+
- Type: `({ filename: string, suffix: string, year:string, month:string, day:string, hours:string, minutes:string, seconds:string, props: SketchProps }) => string`
|
|
118
|
+
- Default: `({ filename, suffix }) => ${filename}.${suffix}`
|
|
119
|
+
|
|
120
|
+
Change the filename pattern when exporting a file. By default, `fragment` will use the sketch filename and a timestamp to name your export like `sketch.js.2022.05.27-08.30.00.[extension]`.
|
|
121
|
+
|
|
122
|
+
In order to reuse the timestamp in your own pattern, `suffix` is available as a parameter within the callback, but you can also deconstruct `{ year, month, day, hours, minutes, seconds}` to make up your own.
|
|
123
|
+
|
|
124
|
+
> ⚠️ You don't need to specify the extension since this is handled internally by the [Exports](./modules.md#exports) module.
|
|
125
|
+
|
|
126
|
+
The callback is also returning the sketch current props so you can use their values in your export name.
|
|
127
|
+
|
|
128
|
+
Example:
|
|
129
|
+
|
|
130
|
+
```js
|
|
131
|
+
export let filenamePattern = ({ filename, suffix, props }) => {
|
|
132
|
+
return `${filename}.${suffix}.radius=${props.radius.value}`;
|
|
133
|
+
}
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
## SketchProps
|
|
137
|
+
|
|
138
|
+
You can define `props` in your sketch files in order to create GUI elements and use their values directly in your code. `fragment` will attempt to infer the type of field you want based on values and params of the props.
|
|
139
|
+
|
|
140
|
+
| value type | params | field |
|
|
141
|
+
|---|---|---|
|
|
142
|
+
| `number` | { disabled?: `boolean`, step?: `number` } | `<NumberInput>` |
|
|
143
|
+
| `number` | { min:`number`, max: `number` } | `<ProgressInput>` + `<NumberInput>` |
|
|
144
|
+
| `number` | { options?: `number[] \| object[{label?: string, value:number}]`} | `<SelectInput>`|
|
|
145
|
+
| `string` | { disabled?: `boolean`} | `<TextInput>`|
|
|
146
|
+
| `string` | { options?: `string[] \| object[{label?: string, value:string}]`} | `<SelectInput>`|
|
|
147
|
+
| `function` | { disabled?: `boolean`, label?: `string` } | `<ButtonInput>`|
|
|
148
|
+
| `number[](2)` | { locked?: `boolean` } | `<Vec2Input>`|
|
|
149
|
+
| `number[](3)` | { locked?: `boolean` } | `<Vec3Input>`|
|
|
150
|
+
|
|
151
|
+
Example:
|
|
152
|
+
```js
|
|
153
|
+
export let props = {
|
|
154
|
+
radius: {
|
|
155
|
+
value: 10,
|
|
156
|
+
params: {
|
|
157
|
+
min: 1,
|
|
158
|
+
max: 30,
|
|
159
|
+
step: 0.1
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
};
|
|
163
|
+
|
|
164
|
+
// use props.radius.value
|
|
165
|
+
export let update = ({ context }) => {
|
|
166
|
+
const radius = props.radius.value;
|
|
167
|
+
|
|
168
|
+
context.arc(x, y, radius, 0, 2 * Math.PI);
|
|
169
|
+
};
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
You can force a type on a prop by assigning a `type` to your object like so:
|
|
173
|
+
|
|
174
|
+
```js
|
|
175
|
+
export let props = {
|
|
176
|
+
color: {
|
|
177
|
+
value: [255, 0, 255],
|
|
178
|
+
type: "color",
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
```
|
|
182
|
+
|
|
183
|
+
You can also add a listener if you want to trigger a function when the prop value changes.
|
|
184
|
+
|
|
185
|
+
```js
|
|
186
|
+
function onColorChange({ value }) {
|
|
187
|
+
console.log("color has changed!", value);
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
export let props = {
|
|
191
|
+
color: {
|
|
192
|
+
value: [255, 0, 255],
|
|
193
|
+
type: "color",
|
|
194
|
+
onChange: onColorChange,
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
```
|
|
198
|
+
|
|
199
|
+
A prop can be `hidden` so it doesn't show up in the Parameters module or in `build` mode.
|
|
200
|
+
|
|
201
|
+
```js
|
|
202
|
+
export let props = {
|
|
203
|
+
color: {
|
|
204
|
+
value: [255, 0, 255],
|
|
205
|
+
hidden: __PRODUCTION__,
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
```
|
|
209
|
+
|
|
210
|
+
## Templates
|
|
211
|
+
|
|
212
|
+
`fragment` comes with a bunch of pre-defined templates. See [CLI docs](./CLI.md#templates) for details.
|
|
213
|
+
|
|
214
|
+
## Interactivity
|
|
215
|
+
|
|
216
|
+
You can set up *triggers* in your sketch files to make them **interactive**. See [Triggers docs](./triggers.md) for details.
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
#### <sup>[fragment](../../README.md) → [Documentation](../README.md) → [API](../README.md#apis) → Triggers</sup>
|
|
2
|
+
<br>
|
|
3
|
+
|
|
4
|
+
# Triggers
|
|
5
|
+
|
|
6
|
+
## Mouse
|
|
7
|
+
|
|
8
|
+
Mouse triggers are called when the event happens on the `<canvas>` used for your sketch.
|
|
9
|
+
|
|
10
|
+
#### `onClick`
|
|
11
|
+
- Type: `(listener(event:MouseEvent): function) => void`
|
|
12
|
+
|
|
13
|
+
Register a `click` listener on the `<canvas>`.
|
|
14
|
+
|
|
15
|
+
#### `onMouseDown`
|
|
16
|
+
- Type: `(listener(event:MouseEvent): function) => void`
|
|
17
|
+
|
|
18
|
+
Register a `mousedown` listener on the `<canvas>`.
|
|
19
|
+
|
|
20
|
+
#### `onMouseUp`
|
|
21
|
+
- Type: `(listener(event:MouseEvent): function) => void`
|
|
22
|
+
|
|
23
|
+
Register a `mouseup` listener on the `<canvas>`.
|
|
24
|
+
|
|
25
|
+
#### `onMouseMove`
|
|
26
|
+
- Type: `(listener(event:MouseEvent): function) => void`
|
|
27
|
+
|
|
28
|
+
Register a `mousemove` listener on the `<canvas>`.
|
|
29
|
+
|
|
30
|
+
## Keyboard
|
|
31
|
+
|
|
32
|
+
Keyboard triggers are called when the event happens on `window`.
|
|
33
|
+
A `key` argument can be optionnaly passed to call the listener only when a specific key is typed. If a single function is provided, the listener will be called for every key typed. The `key` argument can also be an array, in this case it will be called for every key typed in the array.
|
|
34
|
+
|
|
35
|
+
> ⚠ The `key` argument is case sensitive, so `onKeyPress('a', () =>)` and `onKeyPress('A', () =>)` is not the same thing
|
|
36
|
+
|
|
37
|
+
```js
|
|
38
|
+
import { onKeyPress } from "@fragment/triggers";
|
|
39
|
+
|
|
40
|
+
export let init = () => {
|
|
41
|
+
onKeyPress(() => {
|
|
42
|
+
console.log("called for every keypress");
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
onKeyPress('a', () => {
|
|
46
|
+
console.log("called when 'a' is pressed");
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
onKeyPress('A', () => {
|
|
50
|
+
console.log("called when 'A' is pressed");
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
onKeyPress(['a', 'A'], () => {
|
|
54
|
+
console.log("called when 'a' or 'A' is pressed");
|
|
55
|
+
});
|
|
56
|
+
};
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
#### `onKeyPress`
|
|
60
|
+
- Type: `(key?: (string|string[]), listener(event:KeyboardEvent): function) => void`
|
|
61
|
+
|
|
62
|
+
Register a `keypress` listener for `key` on `window`.
|
|
63
|
+
|
|
64
|
+
#### `onKeyDown`
|
|
65
|
+
- Type: `(key?: (string|string[]), listener(event:KeyboardEvent): function) => void`
|
|
66
|
+
|
|
67
|
+
Register a `keydown` listener for `key` on `window`.
|
|
68
|
+
|
|
69
|
+
#### `onKeyUp`
|
|
70
|
+
- Type: `(key?: (string|string[]), listener(event:KeyboardEvent): function) => void`
|
|
71
|
+
|
|
72
|
+
Register a `keyup` listener for `key` on `window`.
|
|
73
|
+
|
|
74
|
+
## MIDI
|
|
75
|
+
|
|
76
|
+
MIDI triggers are called when using a MIDI device after authorizing usage of the [Web MIDI API](https://developer.mozilla.org/en-US/docs/Web/API/Web_MIDI_API).
|
|
77
|
+
|
|
78
|
+
#### `onNoteOn`
|
|
79
|
+
- Type: `(note?:(string|string[]), listener(event:MIDIEvent): function) => void`
|
|
80
|
+
|
|
81
|
+
Register a listener called when `note` is played on. Notes: `["C", "C#", "D", "D#", "E", "F", "F#", "G", "G#", "A", "A#", "B"]`.
|
|
82
|
+
|
|
83
|
+
#### `onNoteOff`
|
|
84
|
+
- Type: `(note?:(string|string[]), listener(event:MIDIEvent): function) => void`
|
|
85
|
+
|
|
86
|
+
Register a listener called when `note` is played off. Notes: `["C", "C#", "D", "D#", "E", "F", "F#", "G", "G#", "A", "A#", "B"]`.
|
|
87
|
+
|
|
88
|
+
#### `onNumberOn`
|
|
89
|
+
- Type: `(noteNumber?:(number|number[], listener(event:MIDIEvent): function) => void`
|
|
90
|
+
|
|
91
|
+
Register a listener called when `noteNumber` is played on.
|
|
92
|
+
|
|
93
|
+
#### `onNumberOff`
|
|
94
|
+
- Type: `(noteNumber?:(number|number[], listener(event:MIDIEvent): function) => void`
|
|
95
|
+
|
|
96
|
+
Register a listener called when `noteNumber` is played off.
|
|
97
|
+
|
|
98
|
+
#### `onControlChange`
|
|
99
|
+
- Type: `(control?:(number|number[]), listener(event:MIDIEvent): function) => void`
|
|
100
|
+
|
|
101
|
+
Register a listener called when `control` changes.
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
#### <sup>[fragment](../../README.md) → [Documentation](../README.md) → [Guide](../README.md#guide) → About</sup>
|
|
2
|
+
<br>
|
|
3
|
+
|
|
4
|
+
# About
|
|
5
|
+
|
|
6
|
+
`fragment` started as an idea in 2017 when I did a VJ performance based on [three.js](https://threejs.org/) visuals with a friend. We had a couple of different scenes that could react to audio beats and MIDI inputs. All scenes were made at different times, with different stacks and MIDI inputs had to be programmed and reminded beforehand.
|
|
7
|
+
|
|
8
|
+
In 2018, we did a projection mapping for MAPP Montreal, also made with [three.js](https://threejs.org/). Visuals were still reacting to the soundtrack but it was not live, we needed to export a video of the whole thing. As we were lacking time to find better solutions, we ended up using a computer capable of capturing the screen while still rendering at 60fps. Not ideal.
|
|
9
|
+
|
|
10
|
+
In 2019, I became a freelance creative developer and extended the variety of my practices: web development, real-time graphics, and generative art. I felt the need of a sketching environment, who could support the range of needs of my previous and future projects:
|
|
11
|
+
- programmable interface
|
|
12
|
+
- reactive to different kinds of inputs (GUIS, keyboard, MIDI, mouse, sound...) from the code and the UI
|
|
13
|
+
- fast as possible
|
|
14
|
+
- images, videos or live exports
|
|
15
|
+
|
|
16
|
+
So I spent the last 3 years building my own tool.
|