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.
- package/.prettierignore +1 -2
- package/.prettierrc +23 -7
- package/README.md +28 -9
- package/bin/index.js +70 -10
- package/package.json +14 -6
- package/src/cli/build.js +125 -0
- package/src/cli/create.js +238 -0
- package/src/cli/createConfig.js +82 -0
- package/src/cli/createFragmentFile.js +70 -0
- package/src/cli/getEntries.js +85 -0
- package/src/cli/log.js +36 -24
- package/src/cli/plugins/check-dependencies.js +88 -42
- package/src/cli/plugins/hot-shader-replacement.js +408 -0
- package/src/cli/plugins/hot-sketch-reload.js +21 -25
- package/src/cli/plugins/save.js +101 -0
- package/src/cli/preview.js +55 -0
- package/src/cli/prompts.js +260 -0
- package/src/cli/run.js +131 -0
- package/src/cli/templates/blank/index.js +33 -0
- package/src/cli/templates/blank/meta.json +4 -0
- package/src/cli/templates/default/index.js +39 -0
- package/src/cli/templates/default/meta.json +5 -0
- package/src/cli/templates/fragment-gl/index.js +37 -0
- package/src/cli/templates/fragment-gl/meta.json +4 -0
- package/src/cli/templates/p5/index.js +32 -0
- package/src/cli/templates/p5/meta.json +5 -0
- package/src/cli/templates/p5-webgl/fragment.fs +14 -0
- package/src/cli/templates/p5-webgl/index.js +67 -0
- package/src/cli/templates/p5-webgl/meta.json +5 -0
- package/src/cli/templates/three-fragment/fragment.fs +10 -0
- package/src/cli/templates/three-fragment/index.js +95 -0
- package/src/cli/templates/three-fragment/meta.json +5 -0
- package/src/cli/templates/three-orthographic/index.js +55 -0
- package/src/cli/templates/three-orthographic/meta.json +5 -0
- package/src/cli/templates/three-perspective/index.js +52 -0
- package/src/cli/templates/three-perspective/meta.json +5 -0
- package/src/cli/utils.js +70 -0
- package/src/cli/ws.js +87 -78
- package/src/client/app/App.svelte +3 -3
- package/src/client/app/client.js +55 -39
- package/src/client/app/components/IconCross.svelte +18 -18
- package/src/client/app/components/Init.svelte +40 -8
- package/src/client/app/components/KeyBinding.svelte +22 -22
- package/src/client/app/helpers.js +42 -0
- package/src/client/app/hooks.js +20 -0
- package/src/client/app/inputs/Input.js +9 -9
- package/src/client/app/inputs/Keyboard.js +13 -15
- package/src/client/app/inputs/MIDI.js +14 -15
- package/src/client/app/inputs/Mouse.js +1 -1
- package/src/client/app/inputs/Webcam.js +89 -88
- package/src/client/app/lib/canvas-recorder/CanvasRecorder.js +41 -21
- package/src/client/app/lib/canvas-recorder/FrameRecorder.js +7 -6
- package/src/client/app/lib/canvas-recorder/H264Recorder.js +45 -0
- package/src/client/app/lib/canvas-recorder/MP4Recorder.js +7 -9
- package/src/client/app/lib/canvas-recorder/WebMRecorder.js +3 -4
- package/src/client/app/lib/canvas-recorder/mp4.js +1649 -15
- package/src/client/app/lib/canvas-recorder/utils.js +33 -17
- package/src/client/app/lib/gl/Geometry.js +11 -8
- package/src/client/app/lib/gl/Program.js +38 -19
- package/src/client/app/lib/gl/Renderer.js +163 -156
- package/src/client/app/lib/gl/Texture.js +113 -85
- package/src/client/app/lib/gl/index.js +12 -12
- package/src/client/app/lib/gl/utils.js +1 -3
- package/src/client/app/lib/helpers/frameDebounce.js +30 -30
- package/src/client/app/lib/loader/index.js +10 -10
- package/src/client/app/lib/loader/loadImage.js +15 -15
- package/src/client/app/lib/loader/loadScript.js +1 -1
- package/src/client/app/lib/paper-sizes.js +75 -76
- package/src/client/app/lib/presets.js +25 -5
- package/src/client/app/lib/tempo/Analyser.js +18 -17
- package/src/client/app/lib/tempo/Range.js +15 -12
- package/src/client/app/lib/tempo/index.js +34 -27
- package/src/client/app/modules/AudioAnalyser/Range.svelte +69 -72
- package/src/client/app/modules/AudioAnalyser/Spectrum.svelte +20 -19
- package/src/client/app/modules/AudioAnalyser.svelte +52 -35
- package/src/client/app/modules/Console/ConsoleLine.svelte +193 -172
- package/src/client/app/modules/Console.svelte +76 -74
- package/src/client/app/modules/Exports.svelte +62 -43
- package/src/client/app/modules/MidiPanel.svelte +100 -101
- package/src/client/app/modules/Monitor.svelte +57 -57
- package/src/client/app/modules/Params.svelte +128 -103
- package/src/client/app/renderers/2DRenderer.js +3 -3
- package/src/client/app/renderers/FragmentRenderer.js +30 -23
- package/src/client/app/renderers/P5GLRenderer.js +144 -0
- package/src/client/app/renderers/P5Renderer.js +10 -7
- package/src/client/app/renderers/THREERenderer.js +136 -94
- package/src/client/app/stores/audioAnalysis.js +3 -4
- package/src/client/app/stores/console.js +9 -10
- package/src/client/app/stores/errors.js +1 -1
- package/src/client/app/stores/exports.js +36 -20
- package/src/client/app/stores/index.js +2 -2
- package/src/client/app/stores/layout.js +143 -138
- package/src/client/app/stores/multisampling.js +4 -4
- package/src/client/app/stores/props.js +76 -13
- package/src/client/app/stores/renderers.js +26 -15
- package/src/client/app/stores/rendering.js +108 -89
- package/src/client/app/stores/sketches.js +7 -9
- package/src/client/app/stores/time.js +18 -18
- package/src/client/app/stores/utils.js +95 -38
- package/src/client/app/transitions/fade.js +3 -3
- package/src/client/app/transitions/index.js +6 -7
- package/src/client/app/transitions/splitX.js +2 -2
- package/src/client/app/transitions/splitY.js +2 -2
- package/src/client/app/triggers/Keyboard.js +88 -79
- package/src/client/app/triggers/MIDI.js +110 -84
- package/src/client/app/triggers/Mouse.js +73 -65
- package/src/client/app/triggers/Trigger.js +59 -58
- package/src/client/app/triggers/index.js +7 -7
- package/src/client/app/triggers/shared.js +5 -5
- package/src/client/app/ui/Build.svelte +70 -71
- package/src/client/app/ui/ErrorOverlay.svelte +118 -104
- package/src/client/app/ui/Field.svelte +393 -258
- package/src/client/app/ui/FieldGroup.svelte +106 -94
- package/src/client/app/ui/FieldSection.svelte +127 -116
- package/src/client/app/ui/FieldSpace.svelte +29 -30
- package/src/client/app/ui/FieldTrigger.svelte +256 -244
- package/src/client/app/ui/FieldTriggers.svelte +46 -46
- package/src/client/app/ui/FloatingParams.svelte +29 -30
- package/src/client/app/ui/Layout.svelte +31 -32
- package/src/client/app/ui/LayoutColumn.svelte +4 -4
- package/src/client/app/ui/LayoutComponent.svelte +239 -225
- package/src/client/app/ui/LayoutResizer.svelte +195 -176
- package/src/client/app/ui/LayoutRoot.svelte +6 -6
- package/src/client/app/ui/LayoutRow.svelte +4 -4
- package/src/client/app/ui/LayoutToolbar.svelte +191 -194
- package/src/client/app/ui/Module.svelte +134 -135
- package/src/client/app/ui/ModuleHeaderAction.svelte +81 -78
- package/src/client/app/ui/ModuleHeaderButton.svelte +12 -12
- package/src/client/app/ui/ModuleHeaderSelect.svelte +47 -37
- package/src/client/app/ui/ModuleRenderer.svelte +26 -27
- package/src/client/app/ui/OutputRenderer.svelte +112 -105
- package/src/client/app/ui/ParamsMultisampling.svelte +96 -95
- package/src/client/app/ui/ParamsOutput.svelte +130 -113
- package/src/client/app/ui/Preview.svelte +7 -8
- package/src/client/app/ui/SelectChevrons.svelte +27 -15
- package/src/client/app/ui/SketchRenderer.svelte +780 -667
- package/src/client/app/ui/SketchSelect.svelte +50 -44
- package/src/client/app/ui/fields/ButtonInput.svelte +61 -48
- package/src/client/app/ui/fields/CheckboxInput.svelte +67 -61
- package/src/client/app/ui/fields/ColorInput.svelte +294 -238
- package/src/client/app/ui/fields/FieldInputRow.svelte +8 -8
- package/src/client/app/ui/fields/ImageInput.svelte +123 -121
- package/src/client/app/ui/fields/Input.svelte +100 -111
- package/src/client/app/ui/fields/IntervalInput.svelte +268 -0
- package/src/client/app/ui/fields/ListInput.svelte +96 -96
- package/src/client/app/ui/fields/NumberInput.svelte +120 -116
- package/src/client/app/ui/fields/ProgressInput.svelte +99 -73
- package/src/client/app/ui/fields/Select.svelte +137 -124
- package/src/client/app/ui/fields/TextInput.svelte +10 -11
- package/src/client/app/ui/fields/VectorInput.svelte +86 -82
- package/src/client/app/utils/canvas.utils.js +189 -208
- package/src/client/app/utils/color.utils.js +138 -101
- package/src/client/app/utils/fields.utils.js +131 -0
- package/src/client/app/utils/file.utils.js +209 -37
- package/src/client/app/utils/glsl.utils.js +2 -2
- package/src/client/app/utils/glslErrors.js +49 -31
- package/src/client/app/utils/index.js +32 -29
- package/src/client/app/utils/math.utils.js +14 -10
- package/src/client/index.html +16 -16
- package/src/client/main.js +4 -4
- package/src/client/public/css/global.css +26 -16
- package/src/cli/db.js +0 -17
- package/src/cli/index.js +0 -198
- package/src/cli/plugins/db.js +0 -12
- package/src/cli/plugins/hot-shader-reload.js +0 -86
- package/src/cli/plugins/screenshot.js +0 -46
- package/src/cli/server.js +0 -153
- package/src/cli/templates/2d.js +0 -15
- package/src/cli/templates/blank.js +0 -13
- package/src/cli/templates/fragment.js +0 -18
- package/src/cli/templates/index.js +0 -27
- package/src/cli/templates/p5.js +0 -13
- package/src/cli/templates/three-fragment.js +0 -53
- package/src/cli/templates/three-orthographic.js +0 -23
- package/src/cli/templates/three-perspective.js +0 -20
- package/src/client/app/lib/canvas-recorder/FFMPEGRecorder.js +0 -56
- package/src/client/app/utils/props.utils.js +0 -51
- 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/js/ffmpeg.min.js +0 -2
- package/src/client/public/js/ffmpeg.min.js.map +0 -1
- /package/src/cli/templates/{fragment.fs → fragment-gl/fragment.fs} +0 -0
|
@@ -1,33 +1,71 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @typedef {Object} File
|
|
3
|
+
* @property {string} filepath
|
|
4
|
+
* @property {string} exportDir
|
|
5
|
+
* @property {string} data
|
|
6
|
+
* @property {string} [encoding]
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Transform a Blob into a Data URL
|
|
11
|
+
* @param {Blob} blob
|
|
12
|
+
* @returns {Promise<string>}
|
|
13
|
+
*/
|
|
14
|
+
export async function createDataURLFromBlob(blob) {
|
|
15
|
+
return new Promise((resolve, reject) => {
|
|
16
|
+
const reader = new FileReader();
|
|
17
|
+
|
|
18
|
+
reader.onerror = (err) => {
|
|
19
|
+
reject(err);
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
reader.onload = (e) => {
|
|
23
|
+
resolve(e.target.result);
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
reader.readAsDataURL(blob);
|
|
27
|
+
});
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Transform a Data URL into a blob
|
|
32
|
+
* @param {string} dataURL
|
|
33
|
+
* @returns {Blob}
|
|
34
|
+
*/
|
|
1
35
|
export function createBlobFromDataURL(dataURL) {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
36
|
+
return new Promise((resolve, reject) => {
|
|
37
|
+
const splitIndex = dataURL.indexOf(',');
|
|
38
|
+
|
|
39
|
+
if (splitIndex === -1) {
|
|
40
|
+
reject(
|
|
41
|
+
new Error(
|
|
42
|
+
`createBlobFromDataURL: dataURL doesn't contain extension data.`,
|
|
43
|
+
),
|
|
44
|
+
);
|
|
45
|
+
return;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
const base64 = dataURL.slice(splitIndex + 1);
|
|
49
|
+
const byteString = window.atob(base64);
|
|
50
|
+
const type = dataURL.slice(0, splitIndex);
|
|
51
|
+
const mimeMatch = /data:([^;]+)/.exec(type);
|
|
52
|
+
const mime = (mimeMatch ? mimeMatch[1] : '') || undefined;
|
|
53
|
+
const ab = new ArrayBuffer(byteString.length);
|
|
54
|
+
const ia = new Uint8Array(ab);
|
|
55
|
+
for (var i = 0; i < byteString.length; i++) {
|
|
56
|
+
ia[i] = byteString.charCodeAt(i);
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
resolve(new window.Blob([ab], { type: mime }));
|
|
60
|
+
});
|
|
23
61
|
}
|
|
24
62
|
|
|
25
63
|
export function download(data, filename) {
|
|
26
64
|
let extension = getFileExtension(filename);
|
|
27
65
|
|
|
28
|
-
if (typeof data ===
|
|
29
|
-
|
|
30
|
-
|
|
66
|
+
if (typeof data === 'object' && ['json', 'txt'].includes(extension)) {
|
|
67
|
+
data = JSON.stringify(data, undefined, 4);
|
|
68
|
+
}
|
|
31
69
|
|
|
32
70
|
let type = getMimeType(extension);
|
|
33
71
|
let blob = new Blob([data], { type });
|
|
@@ -35,14 +73,20 @@ export function download(data, filename) {
|
|
|
35
73
|
downloadBlob(blob, { filename });
|
|
36
74
|
}
|
|
37
75
|
|
|
38
|
-
|
|
76
|
+
/**
|
|
77
|
+
* Download a blob from the browser
|
|
78
|
+
* @param {Blob} blob
|
|
79
|
+
* @param {object} [options]
|
|
80
|
+
* @param {string} [options.filename="untitled"]
|
|
81
|
+
*/
|
|
82
|
+
export function downloadBlob(blob, { filename = 'untitled' } = {}) {
|
|
39
83
|
let a = document.createElement('a');
|
|
40
84
|
a.style.visibility = 'hidden';
|
|
41
|
-
|
|
85
|
+
a.target = '_blank';
|
|
42
86
|
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
87
|
+
a.download = filename;
|
|
88
|
+
a.href = window.URL.createObjectURL(blob);
|
|
89
|
+
// a.dataset.downloadurl = [type, a.download, a.href].join(':');
|
|
46
90
|
|
|
47
91
|
a.onclick = () => {
|
|
48
92
|
a.onclick = () => {};
|
|
@@ -53,7 +97,26 @@ export function downloadBlob(blob, { filename = "untitled" } = {}) {
|
|
|
53
97
|
});
|
|
54
98
|
};
|
|
55
99
|
|
|
56
|
-
|
|
100
|
+
a.click();
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
/**
|
|
104
|
+
* Extract filename and extension from a string path
|
|
105
|
+
* @param {string} path
|
|
106
|
+
* @returns {string} filename
|
|
107
|
+
*/
|
|
108
|
+
export function getFilename(path) {
|
|
109
|
+
return path.split(/[\\/]/).pop();
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
/**
|
|
113
|
+
* Estimate file size in megabytes from a Data URL
|
|
114
|
+
* @param {string} data
|
|
115
|
+
* @returns {number}
|
|
116
|
+
*/
|
|
117
|
+
export function estimateFileSize(data) {
|
|
118
|
+
const base64Length = data.length - (data.indexOf(',') + 1);
|
|
119
|
+
return (base64Length * (3 / 4) - 2) / 1024 / 1024;
|
|
57
120
|
}
|
|
58
121
|
|
|
59
122
|
export function getFileExtension(path) {
|
|
@@ -65,13 +128,122 @@ export function getFileExtension(path) {
|
|
|
65
128
|
}
|
|
66
129
|
|
|
67
130
|
/**
|
|
68
|
-
*
|
|
69
|
-
* @param {string} extension
|
|
70
|
-
* @returns {string}
|
|
131
|
+
*
|
|
132
|
+
* @param {string} extension
|
|
133
|
+
* @returns {string}
|
|
71
134
|
*/
|
|
72
135
|
export function getMimeType(extension) {
|
|
73
|
-
if (extension ===
|
|
74
|
-
if (extension ===
|
|
75
|
-
if (extension ===
|
|
76
|
-
if (extension ===
|
|
136
|
+
if (extension === 'json') return 'application/json';
|
|
137
|
+
if (extension === 'txt') return 'text';
|
|
138
|
+
if (extension === 'png') return 'image/png';
|
|
139
|
+
if (extension === 'jpeg' || extension === 'jpg') return 'image/jpeg';
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
/**
|
|
143
|
+
*
|
|
144
|
+
* @param {File|File[]} files
|
|
145
|
+
*/
|
|
146
|
+
export async function saveInBrowser(files) {
|
|
147
|
+
/**
|
|
148
|
+
* @param {File} file
|
|
149
|
+
*/
|
|
150
|
+
async function saveFile({ filename, data, blob }) {
|
|
151
|
+
if (!blob) {
|
|
152
|
+
blob = await createBlobFromDataURL(data);
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
await downloadBlob(blob, { filename });
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
if (Array.isArray(files)) {
|
|
159
|
+
return Promise.all(files.map((file) => saveFile(file)));
|
|
160
|
+
} else {
|
|
161
|
+
await saveFile(files);
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
/**
|
|
166
|
+
* Save files to disk by sending them to Fragment save plugin. Fallback to saveInBrowser if fails
|
|
167
|
+
* @param {File[]} files
|
|
168
|
+
* @returns {Promise<string[]>}
|
|
169
|
+
*/
|
|
170
|
+
export async function saveFiles(files = [], out = []) {
|
|
171
|
+
if (__DEV__) {
|
|
172
|
+
files.forEach((file) => {
|
|
173
|
+
if (!file.size) {
|
|
174
|
+
file.size = estimateFileSize(file.data);
|
|
175
|
+
}
|
|
176
|
+
});
|
|
177
|
+
|
|
178
|
+
const limitInMb = 100;
|
|
179
|
+
const body = {
|
|
180
|
+
files: [],
|
|
181
|
+
};
|
|
182
|
+
|
|
183
|
+
let size = 0;
|
|
184
|
+
|
|
185
|
+
for (let i = 0; i < files.length; i++) {
|
|
186
|
+
const file = files[i];
|
|
187
|
+
if (size < limitInMb) {
|
|
188
|
+
body.files.push(file);
|
|
189
|
+
size += file.size;
|
|
190
|
+
} else {
|
|
191
|
+
break;
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
const response = await fetch('/save', {
|
|
196
|
+
method: 'POST',
|
|
197
|
+
body: JSON.stringify(body),
|
|
198
|
+
headers: {
|
|
199
|
+
Accept: 'application/json',
|
|
200
|
+
'Content-Type': 'application/json',
|
|
201
|
+
},
|
|
202
|
+
});
|
|
203
|
+
const { filepaths, error } = await response.json();
|
|
204
|
+
|
|
205
|
+
if (response.ok && filepaths?.length) {
|
|
206
|
+
out.push(...filepaths);
|
|
207
|
+
|
|
208
|
+
if (body.files.length < files.length) {
|
|
209
|
+
return saveFiles(files.slice(body.files.length), out);
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
if (out.length < 15) {
|
|
213
|
+
out.forEach((filepath) => {
|
|
214
|
+
console.log(`[fragment] Saved ${filepath}`);
|
|
215
|
+
});
|
|
216
|
+
} else {
|
|
217
|
+
console.log(`[fragment] Saved ${out.length} files.`, {
|
|
218
|
+
filepaths: out,
|
|
219
|
+
});
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
return out;
|
|
223
|
+
} else {
|
|
224
|
+
console.error(`[fragment] Error while saving files on disk.`);
|
|
225
|
+
await saveInBrowser(files);
|
|
226
|
+
}
|
|
227
|
+
} else {
|
|
228
|
+
await saveInBrowser(files);
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
/**
|
|
233
|
+
* Save a blob on disk
|
|
234
|
+
* @param {Blob} blob
|
|
235
|
+
* @param {object} options
|
|
236
|
+
* @returns {Promise<string[]>}
|
|
237
|
+
*/
|
|
238
|
+
export async function saveBlob(blob, { filename, exportDir }) {
|
|
239
|
+
const data = await createDataURLFromBlob(blob);
|
|
240
|
+
|
|
241
|
+
return saveFiles([
|
|
242
|
+
{
|
|
243
|
+
filename,
|
|
244
|
+
data,
|
|
245
|
+
exportDir,
|
|
246
|
+
encoding: 'base64',
|
|
247
|
+
},
|
|
248
|
+
]);
|
|
77
249
|
}
|
|
@@ -3,11 +3,11 @@ const regex = /<filepath:\/\/(.*)>/;
|
|
|
3
3
|
export function getShaderPath(shader) {
|
|
4
4
|
const match = shader.match(/<filepath:\/\/(.*)>/);
|
|
5
5
|
return match && match[1];
|
|
6
|
-
}
|
|
6
|
+
}
|
|
7
7
|
|
|
8
8
|
export function removeShaderPath(shader, filepath = getShaderPath(shader)) {
|
|
9
9
|
if (filepath) {
|
|
10
|
-
return shader.replace(`// <filepath://${filepath}>`,
|
|
10
|
+
return shader.replace(`// <filepath://${filepath}>`, '');
|
|
11
11
|
}
|
|
12
12
|
|
|
13
13
|
return shader;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { displayError } from
|
|
2
|
-
import { getShaderPath, removeShaderPath } from
|
|
1
|
+
import { displayError } from '../stores/errors';
|
|
2
|
+
import { getShaderPath, removeShaderPath } from './glsl.utils';
|
|
3
3
|
|
|
4
4
|
const methods = ['attachShader'];
|
|
5
5
|
|
|
@@ -13,38 +13,52 @@ for (let i = 0; i < methods.length; i++) {
|
|
|
13
13
|
|
|
14
14
|
function createUUID() {
|
|
15
15
|
function s4() {
|
|
16
|
-
return Math.floor((1 + Math.random()) * 0x10000)
|
|
16
|
+
return Math.floor((1 + Math.random()) * 0x10000)
|
|
17
|
+
.toString(16)
|
|
18
|
+
.substring(1);
|
|
17
19
|
}
|
|
18
20
|
|
|
19
|
-
return
|
|
20
|
-
|
|
21
|
+
return (
|
|
22
|
+
s4() +
|
|
23
|
+
s4() +
|
|
24
|
+
'-' +
|
|
25
|
+
s4() +
|
|
26
|
+
'-' +
|
|
27
|
+
s4() +
|
|
28
|
+
'-' +
|
|
29
|
+
s4() +
|
|
30
|
+
'-' +
|
|
31
|
+
s4() +
|
|
32
|
+
s4() +
|
|
33
|
+
s4()
|
|
34
|
+
);
|
|
35
|
+
}
|
|
21
36
|
|
|
22
37
|
function e(method, fn) {
|
|
23
|
-
contexts.forEach(context => {
|
|
38
|
+
contexts.forEach((context) => {
|
|
24
39
|
const f = context.prototype[method];
|
|
25
40
|
|
|
26
|
-
context.prototype[method] = function() {
|
|
27
|
-
var res = f.apply(
|
|
28
|
-
res = fn.apply(
|
|
41
|
+
context.prototype[method] = function () {
|
|
42
|
+
var res = f.apply(this, arguments);
|
|
43
|
+
res = fn.apply(this, [res, arguments]) || res;
|
|
29
44
|
return res;
|
|
30
|
-
}
|
|
31
|
-
})
|
|
45
|
+
};
|
|
46
|
+
});
|
|
32
47
|
}
|
|
33
48
|
|
|
34
49
|
const FRAGMENT_SHADER = 35632;
|
|
35
50
|
const VERTEX_SHADER = 35633;
|
|
36
51
|
|
|
37
52
|
class ShaderCompileError extends Error {
|
|
38
|
-
|
|
39
53
|
constructor({
|
|
40
54
|
source,
|
|
41
|
-
filename =
|
|
55
|
+
filename = '',
|
|
42
56
|
lineNumber,
|
|
43
|
-
message = `Cannot compile ${filename !==
|
|
57
|
+
message = `Cannot compile ${filename !== '' ? filename : 'shader'}`,
|
|
44
58
|
} = {}) {
|
|
45
59
|
super(message, filename, lineNumber);
|
|
46
60
|
|
|
47
|
-
this.name =
|
|
61
|
+
this.name = 'ShaderCompileError';
|
|
48
62
|
this.source = source;
|
|
49
63
|
this.lineNumber = lineNumber;
|
|
50
64
|
|
|
@@ -52,7 +66,7 @@ class ShaderCompileError extends Error {
|
|
|
52
66
|
}
|
|
53
67
|
}
|
|
54
68
|
|
|
55
|
-
e('createShader', function(res, args) {
|
|
69
|
+
e('createShader', function (res, args) {
|
|
56
70
|
if (!this.__uuid) {
|
|
57
71
|
this.__uuid = createUUID();
|
|
58
72
|
}
|
|
@@ -61,18 +75,18 @@ e('createShader', function(res, args) {
|
|
|
61
75
|
res.__type = args[0];
|
|
62
76
|
});
|
|
63
77
|
|
|
64
|
-
e('attachShader', function(res, args) {
|
|
78
|
+
e('attachShader', function (res, args) {
|
|
65
79
|
const program = args[0];
|
|
66
80
|
const shader = args[1];
|
|
67
81
|
|
|
68
82
|
if (shader.__type === FRAGMENT_SHADER) {
|
|
69
|
-
program.__fragmentShader = shader;
|
|
83
|
+
program.__fragmentShader = shader;
|
|
70
84
|
} else if (shader.__type === VERTEX_SHADER) {
|
|
71
85
|
program.__vertexShader = shader;
|
|
72
86
|
}
|
|
73
87
|
});
|
|
74
88
|
|
|
75
|
-
e('shaderSource', function(res, args) {
|
|
89
|
+
e('shaderSource', function (res, args) {
|
|
76
90
|
const shader = args[0];
|
|
77
91
|
const source = args[1];
|
|
78
92
|
|
|
@@ -81,25 +95,29 @@ e('shaderSource', function(res, args) {
|
|
|
81
95
|
const filepath = getShaderPath(source);
|
|
82
96
|
|
|
83
97
|
if (filepath) {
|
|
84
|
-
const filename = filepath.replace(`${__CWD__}/`,
|
|
98
|
+
const filename = filepath.replace(`${__CWD__}/`, '');
|
|
85
99
|
|
|
86
100
|
shader.__filepath = filepath;
|
|
87
101
|
shader.__filename = filename;
|
|
88
102
|
}
|
|
89
103
|
});
|
|
90
104
|
|
|
91
|
-
e('createProgram', function(res, args) {
|
|
105
|
+
e('createProgram', function (res, args) {
|
|
92
106
|
res.__uuid = createUUID();
|
|
93
107
|
});
|
|
94
108
|
|
|
95
|
-
e('compileShader', function(res, args) {
|
|
109
|
+
e('compileShader', function (res, args) {
|
|
96
110
|
const gl = this;
|
|
97
111
|
const shader = args[0];
|
|
98
112
|
const filename = shader.__filename;
|
|
99
113
|
|
|
100
114
|
if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) {
|
|
101
|
-
const { source, lineNumber, message } = getShaderError(
|
|
102
|
-
|
|
115
|
+
const { source, lineNumber, message } = getShaderError(
|
|
116
|
+
gl,
|
|
117
|
+
shader,
|
|
118
|
+
shader.__type,
|
|
119
|
+
);
|
|
120
|
+
|
|
103
121
|
const error = new ShaderCompileError({
|
|
104
122
|
source,
|
|
105
123
|
message,
|
|
@@ -118,7 +136,7 @@ function getShaderError(gl, shader, type) {
|
|
|
118
136
|
if (status && errors === '') return '';
|
|
119
137
|
|
|
120
138
|
const errorMatches = errors.match(/ERROR: 0:(\d+):([\s\S]*$)/);
|
|
121
|
-
|
|
139
|
+
|
|
122
140
|
if (errorMatches) {
|
|
123
141
|
const lineNumber = parseInt(errorMatches[1]);
|
|
124
142
|
const message = errorMatches[2];
|
|
@@ -126,7 +144,7 @@ function getShaderError(gl, shader, type) {
|
|
|
126
144
|
const source = handleSource(shaderSource, lineNumber);
|
|
127
145
|
|
|
128
146
|
return {
|
|
129
|
-
message,
|
|
147
|
+
message,
|
|
130
148
|
source: source,
|
|
131
149
|
lineNumber,
|
|
132
150
|
};
|
|
@@ -141,14 +159,14 @@ function handleSource(source, errorLine) {
|
|
|
141
159
|
const lines = (hasPath ? removeShaderPath(source) : source).split('\n');
|
|
142
160
|
const lines2 = [];
|
|
143
161
|
|
|
144
|
-
const from = Math.max(
|
|
145
|
-
const to = Math.min(
|
|
162
|
+
const from = Math.max(errorLine - 6, 0);
|
|
163
|
+
const to = Math.min(errorLine + 6, lines.length);
|
|
146
164
|
|
|
147
|
-
for (
|
|
165
|
+
for (let i = from; i < to; i++) {
|
|
148
166
|
const line = i + 1;
|
|
149
167
|
|
|
150
|
-
lines2.push(
|
|
168
|
+
lines2.push(`${line === errorLine ? '>' : ' '} ${line}: ${lines[i]}`);
|
|
151
169
|
}
|
|
152
170
|
|
|
153
|
-
return lines2.join(
|
|
171
|
+
return lines2.join('\n');
|
|
154
172
|
}
|
|
@@ -1,39 +1,42 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
3
|
-
* @param {Map} map
|
|
4
|
-
* @param {string} key
|
|
5
|
-
* @param {any} find
|
|
2
|
+
*
|
|
3
|
+
* @param {Map} map
|
|
4
|
+
* @param {string} key
|
|
5
|
+
* @param {any} find
|
|
6
6
|
*/
|
|
7
7
|
export const addToMapArray = (map, key, item) => {
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
}
|
|
8
|
+
if (map.has(key)) {
|
|
9
|
+
map.set(key, [...map.get(key), item]);
|
|
10
|
+
} else {
|
|
11
|
+
map.set(key, [item]);
|
|
12
|
+
}
|
|
13
|
+
};
|
|
14
14
|
|
|
15
15
|
/**
|
|
16
|
-
*
|
|
17
|
-
* @param {Map} map
|
|
18
|
-
* @param {string} key
|
|
19
|
-
* @param {function} findIndex
|
|
16
|
+
*
|
|
17
|
+
* @param {Map} map
|
|
18
|
+
* @param {string} key
|
|
19
|
+
* @param {function} findIndex
|
|
20
20
|
*/
|
|
21
21
|
export const removeFromMapArray = (map, key, findIndex) => {
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
22
|
+
if (map.has(key)) {
|
|
23
|
+
const items = map.get(key);
|
|
24
|
+
const index = items.findIndex(findIndex);
|
|
25
25
|
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
26
|
+
if (index >= 0) {
|
|
27
|
+
const newItems = [...items];
|
|
28
|
+
newItems.splice(index, 1);
|
|
29
29
|
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
30
|
+
if (newItems.length > 0) {
|
|
31
|
+
map.set(key, newItems);
|
|
32
|
+
} else {
|
|
33
|
+
map.delete(key);
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
} else {
|
|
37
|
+
console.error(
|
|
38
|
+
`removeFromMapArray: key ${key} doesn't exist in Map.`,
|
|
39
|
+
map,
|
|
40
|
+
);
|
|
41
|
+
}
|
|
39
42
|
};
|
|
@@ -1,23 +1,27 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Map a value from one range to another
|
|
3
|
-
* @param {Number} value
|
|
4
|
-
* @param {Number} min
|
|
5
|
-
* @param {Number} max
|
|
6
|
-
* @param {Number} nmin - The new minimum
|
|
7
|
-
* @param {Number} nmax - The new maximum
|
|
3
|
+
* @param {Number} value
|
|
4
|
+
* @param {Number} min
|
|
5
|
+
* @param {Number} max
|
|
6
|
+
* @param {Number} nmin - The new minimum
|
|
7
|
+
* @param {Number} nmax - The new maximum
|
|
8
8
|
* @returns {Number} result
|
|
9
9
|
*/
|
|
10
10
|
export function map(value, min, max, nmin, nmax) {
|
|
11
|
-
|
|
11
|
+
return ((value - min) / (max - min)) * (nmax - nmin) + nmin;
|
|
12
12
|
}
|
|
13
13
|
|
|
14
14
|
/**
|
|
15
15
|
* Clamp a number between min and max
|
|
16
|
-
* @param {Number} value
|
|
17
|
-
* @param {Number} min
|
|
18
|
-
* @param {Number} max
|
|
16
|
+
* @param {Number} value
|
|
17
|
+
* @param {Number} min
|
|
18
|
+
* @param {Number} max
|
|
19
19
|
* @returns {Number} result
|
|
20
20
|
*/
|
|
21
21
|
export function clamp(value, min, max) {
|
|
22
|
-
|
|
22
|
+
return Math.max(min, Math.min(value, max));
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export function roundToStep(value, step) {
|
|
26
|
+
return Math.round(value * (1 / step)) / (1 / step);
|
|
23
27
|
}
|
package/src/client/index.html
CHANGED
|
@@ -1,18 +1,18 @@
|
|
|
1
|
-
<!
|
|
1
|
+
<!doctype html>
|
|
2
2
|
<html lang="en">
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="UTF-8" />
|
|
5
|
+
<link rel="icon" href="/favicon.ico" />
|
|
6
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
7
|
+
<link rel="stylesheet" href="/css/global.css" />
|
|
8
|
+
<title>fragment</title>
|
|
9
|
+
</head>
|
|
10
|
+
<body>
|
|
11
|
+
<div class="loading">
|
|
12
|
+
<h1 class="loading__title">[fragment]</h1>
|
|
13
|
+
<span class="loading__step">▢ Loading dependencies...</span>
|
|
14
|
+
</div>
|
|
15
|
+
<div id="app"></div>
|
|
16
|
+
<script type="module" src="/main.js"></script>
|
|
17
|
+
</body>
|
|
18
18
|
</html>
|
package/src/client/main.js
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import
|
|
1
|
+
import './app/stores/console';
|
|
2
2
|
import App from './app/App.svelte';
|
|
3
3
|
|
|
4
4
|
const app = new App({
|
|
5
|
-
|
|
6
|
-
|
|
5
|
+
target: document.getElementById('app'),
|
|
6
|
+
props: {},
|
|
7
7
|
});
|
|
8
8
|
|
|
9
|
-
export default app
|
|
9
|
+
export default app;
|