@woosh/meep-engine 3.18.0 → 3.19.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/build/bundle-worker-image-decoder.js +1 -1
- package/editor/view/particles/effect/ParticleCurveEditorView.d.ts.map +1 -1
- package/editor/view/particles/effect/ParticleCurveEditorView.js +303 -120
- package/editor/view/particles/effect/ParticleGradientEditorView.d.ts.map +1 -1
- package/editor/view/particles/effect/ParticleGradientEditorView.js +108 -63
- package/editor/view/particles/effect/ParticleGraphEditorView.js +1 -1
- package/editor/view/particles/effect/ParticleNodeParametersView.d.ts.map +1 -1
- package/editor/view/particles/effect/ParticleNodeParametersView.js +3 -1
- package/editor/view/particles/effect/particle-editor.css +60 -30
- package/package.json +1 -2
- package/samples/engine/README.md +1 -1
- package/src/core/binary/compression/decompress_bytes.d.ts +13 -0
- package/src/core/binary/compression/decompress_bytes.d.ts.map +1 -0
- package/src/core/binary/compression/decompress_bytes.js +28 -0
- package/src/core/model/node-graph/visual/layout/layout_assign_coordinates.js +67 -22
- package/src/engine/asset/loaders/image/ImageDecoderWorker.js +12 -27
- package/src/engine/asset/loaders/image/prototypePNG.js +8 -7
- package/src/engine/ecs/storage/populateEngineSerializationRegistry.d.ts.map +1 -1
- package/src/engine/ecs/storage/populateEngineSerializationRegistry.js +4 -0
- package/src/engine/graphics/ecs/particles/ParticleEffect.d.ts +266 -0
- package/src/engine/graphics/ecs/particles/ParticleEffect.d.ts.map +1 -0
- package/src/engine/graphics/ecs/particles/ParticleEffect.js +455 -0
- package/src/engine/graphics/ecs/particles/ParticleEffectSerializationAdapter.d.ts +58 -0
- package/src/engine/graphics/ecs/particles/ParticleEffectSerializationAdapter.d.ts.map +1 -0
- package/src/engine/graphics/ecs/particles/ParticleEffectSerializationAdapter.js +219 -0
- package/src/engine/graphics3/GPUParticleEmitterSystem.d.ts +178 -25
- package/src/engine/graphics3/GPUParticleEmitterSystem.d.ts.map +1 -1
- package/src/engine/graphics3/GPUParticleEmitterSystem.js +809 -310
- package/src/format/image/png/PNGReader.d.ts +7 -6
- package/src/format/image/png/PNGReader.d.ts.map +1 -1
- package/src/format/image/png/PNGReader.js +13 -12
- package/src/format/image/png/chunk/png_chunk_decode_iTXt.d.ts +3 -2
- package/src/format/image/png/chunk/png_chunk_decode_iTXt.d.ts.map +1 -1
- package/src/format/image/png/chunk/png_chunk_decode_iTXt.js +5 -4
- package/src/format/image/png/chunk/png_chunk_decode_zTXt.d.ts +3 -2
- package/src/format/image/png/chunk/png_chunk_decode_zTXt.d.ts.map +1 -1
- package/src/format/image/png/chunk/png_chunk_decode_zTXt.js +5 -4
- package/src/format/image/png/png_inflate.d.ts +3 -3
- package/src/format/image/png/png_inflate.d.ts.map +1 -1
- package/src/format/image/png/png_inflate.js +29 -39
- package/src/format/texture/ktx2/ktx2_read.d.ts +4 -4
- package/src/format/texture/ktx2/ktx2_read.d.ts.map +1 -1
- package/src/format/texture/ktx2/ktx2_read.js +18 -21
- package/src/shade/playground/particle_ecs/README.md +203 -0
- package/src/shade/playground/particle_ecs/bonfire_editor.d.ts +39 -0
- package/src/shade/playground/particle_ecs/bonfire_editor.d.ts.map +1 -0
- package/src/shade/playground/particle_ecs/bonfire_editor.js +315 -0
- package/src/shade/playground/particle_ecs/bonfire_effects.d.ts +145 -0
- package/src/shade/playground/particle_ecs/bonfire_effects.d.ts.map +1 -0
- package/src/shade/playground/particle_ecs/bonfire_effects.js +202 -0
- package/src/shade/playground/particle_ecs/bonfire_sprites.d.ts +23 -0
- package/src/shade/playground/particle_ecs/bonfire_sprites.d.ts.map +1 -0
- package/src/shade/playground/particle_ecs/bonfire_sprites.js +315 -0
- package/src/shade/playground/particle_ecs/bonfire_world.d.ts +86 -0
- package/src/shade/playground/particle_ecs/bonfire_world.d.ts.map +1 -0
- package/src/shade/playground/particle_ecs/bonfire_world.js +303 -0
- package/src/shade/playground/particle_ecs/effects/embers.json +1634 -0
- package/src/shade/playground/particle_ecs/effects/flame.json +1882 -0
- package/src/shade/playground/particle_ecs/effects/smoke.json +1860 -0
- package/src/shade/playground/particle_ecs/effects/soot.json +1606 -0
- package/src/shade/playground/particle_ecs/index.html +330 -0
- package/src/shade/playground/particle_ecs/main.d.ts +2 -0
- package/src/shade/playground/particle_ecs/main.d.ts.map +1 -0
- package/src/shade/playground/particle_ecs/main.js +566 -0
- package/src/shade/playground/particle_ecs/moonlit_environment.d.ts +16 -0
- package/src/shade/playground/particle_ecs/moonlit_environment.d.ts.map +1 -0
- package/src/shade/playground/particle_ecs/moonlit_environment.js +144 -0
- package/src/shade/playground/particle_editor/README.md +5 -4
- package/src/shade/playground/profile_hotkey.d.ts +58 -0
- package/src/shade/playground/profile_hotkey.d.ts.map +1 -0
- package/src/shade/playground/profile_hotkey.js +325 -0
- package/src/shade/playground/ssr_variance/README.md +105 -0
- package/src/shade/playground/ssr_variance/capture.d.ts +16 -0
- package/src/shade/playground/ssr_variance/capture.d.ts.map +1 -0
- package/src/shade/playground/ssr_variance/capture.js +96 -0
- package/src/shade/playground/ssr_variance/index.html +22 -0
- package/src/shade/playground/ssr_variance/main.d.ts +2 -0
- package/src/shade/playground/ssr_variance/main.d.ts.map +1 -0
- package/src/shade/playground/ssr_variance/main.js +246 -0
- package/src/shade/playground/ssr_variance/reference.d.ts +18 -0
- package/src/shade/playground/ssr_variance/reference.d.ts.map +1 -0
- package/src/shade/playground/ssr_variance/reference.js +78 -0
- package/src/shade/playground/ssr_variance/scene.d.ts +11 -0
- package/src/shade/playground/ssr_variance/scene.d.ts.map +1 -0
- package/src/shade/playground/ssr_variance/scene.js +61 -0
- package/src/shade/playground/ssr_variance/statistics.d.ts +44 -0
- package/src/shade/playground/ssr_variance/statistics.d.ts.map +1 -0
- package/src/shade/playground/ssr_variance/statistics.js +51 -0
- package/src/shade/renderer/loader/gltf/tiny-gltf.d.ts.map +1 -1
- package/src/shade/renderer/loader/gltf/tiny-gltf.js +9 -3
- package/src/shade/renderer/loader/usd/usd_decode_image.d.ts +4 -4
- package/src/shade/renderer/loader/usd/usd_decode_image.d.ts.map +1 -1
- package/src/shade/renderer/loader/usd/usd_decode_image.js +4 -4
- package/src/shade/renderer/particles/DESIGN.md +748 -703
- package/src/shade/renderer/particles/runtime/ParticleEmitter.d.ts +11 -4
- package/src/shade/renderer/particles/runtime/ParticleEmitter.d.ts.map +1 -1
- package/src/shade/renderer/particles/runtime/ParticleEmitter.js +431 -424
- package/src/shade/renderer/postprocess/ssr/SSR.d.ts.map +1 -1
- package/src/shade/renderer/postprocess/ssr/SSR.js +2 -1
- package/src/shade/renderer/postprocess/ssr/reproject/chunk_ssr_reprojection.d.ts.map +1 -1
- package/src/shade/renderer/postprocess/ssr/reproject/chunk_ssr_reprojection.js +0 -6
- package/src/shade/renderer/postprocess/ssr/reproject/chunk_ssr_sample_history.d.ts.map +1 -1
- package/src/shade/renderer/postprocess/ssr/reproject/chunk_ssr_sample_history.js +19 -5
- package/src/shade/renderer/postprocess/ssr/reproject/chunk_ssr_temporal_accumulate.d.ts +4 -0
- package/src/shade/renderer/postprocess/ssr/reproject/chunk_ssr_temporal_accumulate.d.ts.map +1 -0
- package/src/shade/renderer/postprocess/ssr/reproject/chunk_ssr_temporal_accumulate.js +133 -0
- package/src/shade/renderer/postprocess/ssr/ssr_reproject_shader.d.ts +0 -8
- package/src/shade/renderer/postprocess/ssr/ssr_reproject_shader.d.ts.map +1 -1
- package/src/shade/renderer/postprocess/ssr/ssr_reproject_shader.js +16 -113
- package/src/shade/renderer/texture/source/texel_data_from_ktx2.d.ts +2 -2
- package/src/shade/renderer/texture/source/texel_data_from_ktx2.d.ts.map +1 -1
- package/src/shade/renderer/texture/source/texel_data_from_ktx2.js +3 -3
- package/src/shade/renderer/particles/shaders/chunk_particle_emitter_warmup.d.ts +0 -20
- package/src/shade/renderer/particles/shaders/chunk_particle_emitter_warmup.d.ts.map +0 -1
- package/src/shade/renderer/particles/shaders/chunk_particle_emitter_world_sphere.d.ts +0 -14
- package/src/shade/renderer/particles/shaders/chunk_particle_emitter_world_sphere.d.ts.map +0 -1
- package/src/shade/renderer/particles/shaders/shader_particle_reclaim.d.ts +0 -50
- package/src/shade/renderer/particles/shaders/shader_particle_reclaim.d.ts.map +0 -1
- package/src/shade/renderer/postprocess/ssr/reproject/shader_ffx_denoiser_reflections_reproject.d.ts +0 -17
- package/src/shade/renderer/postprocess/ssr/reproject/shader_ffx_denoiser_reflections_reproject.d.ts.map +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ParticleGradientEditorView.d.ts","sourceRoot":"","sources":["../../../../../editor/view/particles/effect/ParticleGradientEditorView.js"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"ParticleGradientEditorView.d.ts","sourceRoot":"","sources":["../../../../../editor/view/particles/effect/ParticleGradientEditorView.js"],"names":[],"mappings":"AAwDA;IAyCI;;;;;;OAMG;IACH;QALqC,IAAI;QACA,KAAK,mBAAnB,IAAI;QACF,KAAK,GAAvB,OAAO;OAgGjB;IAtFG,mBAAuC;IA0G3C;;;OAGG;IACH,gBAaC;IA8LD,eAsDC;;CACJ;iBA3dgB,8BAA8B"}
|
|
@@ -26,13 +26,19 @@ import View from "../../../../src/view/View.js";
|
|
|
26
26
|
*/
|
|
27
27
|
|
|
28
28
|
/** How wide the strip is drawn, in CSS pixels. @type {number} */
|
|
29
|
-
const WIDTH =
|
|
29
|
+
const WIDTH = 240;
|
|
30
30
|
|
|
31
31
|
/** How tall the colour strip is. @type {number} */
|
|
32
32
|
const STRIP_HEIGHT = 24;
|
|
33
33
|
|
|
34
34
|
/** How tall the lane of stop markers under it is. @type {number} */
|
|
35
|
-
const LANE_HEIGHT =
|
|
35
|
+
const LANE_HEIGHT = 18;
|
|
36
|
+
|
|
37
|
+
/** Keep the complete marker and its hit area inside the canvas, including at t = 0 and 1. */
|
|
38
|
+
const MARGIN = 10;
|
|
39
|
+
const STRIP_TOP = 4;
|
|
40
|
+
const STRIP_WIDTH = WIDTH - MARGIN * 2;
|
|
41
|
+
const HEIGHT = STRIP_TOP + STRIP_HEIGHT + LANE_HEIGHT;
|
|
36
42
|
|
|
37
43
|
/** How near a stop marker a press has to be to take hold of it rather than make a new one. */
|
|
38
44
|
const GRAB_RADIUS = 7;
|
|
@@ -65,8 +71,11 @@ export class ParticleGradientEditorView extends View {
|
|
|
65
71
|
/** @type {number} which stop the swatch and the fields below are about */
|
|
66
72
|
#selected = 0;
|
|
67
73
|
|
|
68
|
-
/** @type {
|
|
69
|
-
#
|
|
74
|
+
/** @type {number|null} the pointer that owns the current gesture */
|
|
75
|
+
#pointerId = null;
|
|
76
|
+
|
|
77
|
+
/** @type {boolean} ignore the synchronous echo of our own commit */
|
|
78
|
+
#writing = false;
|
|
70
79
|
|
|
71
80
|
/** @type {function(Array):void} */
|
|
72
81
|
#write;
|
|
@@ -107,8 +116,10 @@ export class ParticleGradientEditorView extends View {
|
|
|
107
116
|
const canvas = this.#canvas = document.createElement('canvas');
|
|
108
117
|
|
|
109
118
|
canvas.width = WIDTH;
|
|
110
|
-
canvas.height =
|
|
111
|
-
canvas.classList.add('strip');
|
|
119
|
+
canvas.height = HEIGHT;
|
|
120
|
+
canvas.classList.add('strip');
|
|
121
|
+
canvas.tabIndex = 0;
|
|
122
|
+
canvas.setAttribute('aria-label', 'Gradient stops. Drag to move; click to add; Escape to cancel.');
|
|
112
123
|
|
|
113
124
|
this.el.appendChild(canvas);
|
|
114
125
|
|
|
@@ -118,9 +129,9 @@ export class ParticleGradientEditorView extends View {
|
|
|
118
129
|
|
|
119
130
|
this.el.appendChild(fields);
|
|
120
131
|
|
|
121
|
-
this.#swatch = field(fields, 'color', 'swatch');
|
|
122
|
-
this.#alpha = field(fields, 'number', 'alpha');
|
|
123
|
-
this.#position = field(fields, 'number', 'position');
|
|
132
|
+
this.#swatch = field(fields, 'color', 'swatch', 'Color');
|
|
133
|
+
this.#alpha = field(fields, 'number', 'alpha', 'Alpha');
|
|
134
|
+
this.#position = field(fields, 'number', 'position', 'Position');
|
|
124
135
|
|
|
125
136
|
for (const input of [this.#alpha, this.#position]) {
|
|
126
137
|
input.setAttribute('min', '0');
|
|
@@ -128,7 +139,8 @@ export class ParticleGradientEditorView extends View {
|
|
|
128
139
|
input.setAttribute('step', 'any');
|
|
129
140
|
}
|
|
130
141
|
|
|
131
|
-
this.#alpha.hidden = !alpha;
|
|
142
|
+
this.#alpha.hidden = !alpha;
|
|
143
|
+
this.#alpha.parentElement.hidden = !alpha;
|
|
132
144
|
|
|
133
145
|
const remove = document.createElement('button');
|
|
134
146
|
|
|
@@ -146,7 +158,15 @@ export class ParticleGradientEditorView extends View {
|
|
|
146
158
|
canvas.addEventListener('pointerdown', event => this.#press(event));
|
|
147
159
|
canvas.addEventListener('pointermove', event => this.#move(event));
|
|
148
160
|
canvas.addEventListener('pointerup', event => this.#release(event));
|
|
149
|
-
canvas.addEventListener('pointercancel', event => this.#
|
|
161
|
+
canvas.addEventListener('pointercancel', event => this.#cancel(event));
|
|
162
|
+
canvas.addEventListener('lostpointercapture', event => this.#cancel(event));
|
|
163
|
+
canvas.addEventListener('keydown', event => {
|
|
164
|
+
if (event.key === 'Escape' && this.#pointerId !== null) {
|
|
165
|
+
event.stopPropagation();
|
|
166
|
+
this.refresh();
|
|
167
|
+
}
|
|
168
|
+
});
|
|
169
|
+
this.on.unlinked.add(() => this.refresh());
|
|
150
170
|
|
|
151
171
|
this.#swatch.addEventListener('change', () => this.#editSelected(stop => {
|
|
152
172
|
const rgb = hex_to_rgb(this.#swatch.value);
|
|
@@ -161,7 +181,7 @@ export class ParticleGradientEditorView extends View {
|
|
|
161
181
|
}));
|
|
162
182
|
|
|
163
183
|
this.#position.addEventListener('change', () => this.#editSelected(stop => {
|
|
164
|
-
stop.position = number_in(this.#position, stop.position);
|
|
184
|
+
stop.position = clamp01(number_in(this.#position, stop.position));
|
|
165
185
|
}));
|
|
166
186
|
|
|
167
187
|
remove.addEventListener('click', () => this.#removeSelected());
|
|
@@ -185,16 +205,24 @@ export class ParticleGradientEditorView extends View {
|
|
|
185
205
|
* next. It is also what makes each commit a distinct value, which is how the node knows anything
|
|
186
206
|
* changed at all.
|
|
187
207
|
*/
|
|
188
|
-
#commit() {
|
|
189
|
-
|
|
208
|
+
#commit() {
|
|
209
|
+
if (JSON.stringify(this.#stops) === JSON.stringify(this.#read())) return;
|
|
210
|
+
this.#writing = true;
|
|
211
|
+
try {
|
|
212
|
+
this.#write(structuredClone(this.#stops));
|
|
213
|
+
} finally {
|
|
214
|
+
this.#writing = false;
|
|
215
|
+
}
|
|
190
216
|
}
|
|
191
217
|
|
|
192
218
|
/**
|
|
193
219
|
* Re-read the parameter and redraw. Called when the value changed somewhere else — an undo, the
|
|
194
220
|
* code layer, a script.
|
|
195
221
|
*/
|
|
196
|
-
refresh() {
|
|
197
|
-
|
|
222
|
+
refresh() {
|
|
223
|
+
if (this.#writing) return;
|
|
224
|
+
this.#endDrag();
|
|
225
|
+
const value = this.#read();
|
|
198
226
|
|
|
199
227
|
this.#stops = Array.isArray(value)
|
|
200
228
|
? value.map(stop => ({ position: stop.position, color: (stop.color ?? []).slice() }))
|
|
@@ -228,7 +256,7 @@ export class ParticleGradientEditorView extends View {
|
|
|
228
256
|
#positionOf(event) {
|
|
229
257
|
const rect = this.#canvas.getBoundingClientRect();
|
|
230
258
|
|
|
231
|
-
return clamp01((event.clientX - rect.left) / rect.width);
|
|
259
|
+
return clamp01(((event.clientX - rect.left) / rect.width * WIDTH - MARGIN) / STRIP_WIDTH);
|
|
232
260
|
}
|
|
233
261
|
|
|
234
262
|
/**
|
|
@@ -238,18 +266,15 @@ export class ParticleGradientEditorView extends View {
|
|
|
238
266
|
#stopUnder(event) {
|
|
239
267
|
const rect = this.#canvas.getBoundingClientRect();
|
|
240
268
|
|
|
241
|
-
const x = event.clientX - rect.left;
|
|
242
|
-
|
|
243
|
-
// in CSS pixels, so the grab radius is the same however far the graph is zoomed out
|
|
244
|
-
const radius = GRAB_RADIUS * (rect.width / WIDTH);
|
|
269
|
+
const x = (event.clientX - rect.left) / rect.width * WIDTH;
|
|
245
270
|
|
|
246
271
|
let nearest = -1;
|
|
247
272
|
let distance = Infinity;
|
|
248
273
|
|
|
249
274
|
this.#stops.forEach((stop, index) => {
|
|
250
|
-
const away = Math.abs(stop.position *
|
|
275
|
+
const away = Math.abs(MARGIN + clamp01(stop.position) * STRIP_WIDTH - x);
|
|
251
276
|
|
|
252
|
-
if (away <=
|
|
277
|
+
if (away <= GRAB_RADIUS && (away < distance || (away === distance && index === this.#selected))) {
|
|
253
278
|
nearest = index;
|
|
254
279
|
distance = away;
|
|
255
280
|
}
|
|
@@ -261,8 +286,12 @@ export class ParticleGradientEditorView extends View {
|
|
|
261
286
|
/**
|
|
262
287
|
* @param {PointerEvent} event
|
|
263
288
|
*/
|
|
264
|
-
#press(event) {
|
|
265
|
-
|
|
289
|
+
#press(event) {
|
|
290
|
+
if (this.#pointerId !== null) return;
|
|
291
|
+
const rect = this.#canvas.getBoundingClientRect();
|
|
292
|
+
const y = (event.clientY - rect.top) / rect.height * HEIGHT;
|
|
293
|
+
if (y < STRIP_TOP || y > STRIP_TOP + STRIP_HEIGHT + LANE_HEIGHT) return;
|
|
294
|
+
const stop = this.#stopUnder(event);
|
|
266
295
|
|
|
267
296
|
if (event.button === 1) {
|
|
268
297
|
// the power-user path to the remove button beside the fields
|
|
@@ -291,12 +320,12 @@ export class ParticleGradientEditorView extends View {
|
|
|
291
320
|
color: particle_gradient_sample(this.#stops, position),
|
|
292
321
|
});
|
|
293
322
|
|
|
294
|
-
this.#selected = this.#stops.length - 1;
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
this.#
|
|
323
|
+
this.#selected = this.#stops.length - 1;
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
event.preventDefault();
|
|
327
|
+
this.#canvas.focus({ preventScroll: true });
|
|
328
|
+
this.#pointerId = event.pointerId ?? 0;
|
|
300
329
|
|
|
301
330
|
if (typeof this.#canvas.setPointerCapture === "function") {
|
|
302
331
|
this.#canvas.setPointerCapture(event.pointerId);
|
|
@@ -309,8 +338,8 @@ export class ParticleGradientEditorView extends View {
|
|
|
309
338
|
/**
|
|
310
339
|
* @param {PointerEvent} event
|
|
311
340
|
*/
|
|
312
|
-
#move(event) {
|
|
313
|
-
if (
|
|
341
|
+
#move(event) {
|
|
342
|
+
if (this.#pointerId !== (event.pointerId ?? 0)) {
|
|
314
343
|
return;
|
|
315
344
|
}
|
|
316
345
|
|
|
@@ -323,20 +352,29 @@ export class ParticleGradientEditorView extends View {
|
|
|
323
352
|
/**
|
|
324
353
|
* @param {PointerEvent} event
|
|
325
354
|
*/
|
|
326
|
-
#release(event) {
|
|
327
|
-
if (
|
|
355
|
+
#release(event) {
|
|
356
|
+
if (this.#pointerId !== (event.pointerId ?? 0)) {
|
|
328
357
|
return;
|
|
329
358
|
}
|
|
330
359
|
|
|
331
|
-
this.#
|
|
332
|
-
|
|
333
|
-
if (typeof this.#canvas.releasePointerCapture === "function" && this.#canvas.hasPointerCapture?.(event.pointerId)) {
|
|
334
|
-
this.#canvas.releasePointerCapture(event.pointerId);
|
|
335
|
-
}
|
|
360
|
+
this.#endDrag();
|
|
336
361
|
|
|
337
362
|
// one entry on the timeline for the whole drag; see the note at the top of this file
|
|
338
|
-
this.#commit();
|
|
339
|
-
}
|
|
363
|
+
this.#commit();
|
|
364
|
+
}
|
|
365
|
+
|
|
366
|
+
#endDrag() {
|
|
367
|
+
const pointerId = this.#pointerId;
|
|
368
|
+
this.#pointerId = null;
|
|
369
|
+
if (pointerId !== null && this.#canvas.hasPointerCapture?.(pointerId)) {
|
|
370
|
+
this.#canvas.releasePointerCapture(pointerId);
|
|
371
|
+
}
|
|
372
|
+
}
|
|
373
|
+
|
|
374
|
+
/** @param {PointerEvent} event */
|
|
375
|
+
#cancel(event) {
|
|
376
|
+
if (this.#pointerId === (event.pointerId ?? 0)) this.refresh();
|
|
377
|
+
}
|
|
340
378
|
|
|
341
379
|
/**
|
|
342
380
|
* @param {function(object):void} edit applied to the selected stop
|
|
@@ -381,7 +419,7 @@ export class ParticleGradientEditorView extends View {
|
|
|
381
419
|
|
|
382
420
|
this.#swatch.value = `#${rgb_to_hex(byte_of(colour[0]), byte_of(colour[1]), byte_of(colour[2]))}`;
|
|
383
421
|
this.#alpha.value = String(colour[3] ?? 1);
|
|
384
|
-
this.#position.value = String(stop === undefined ? 0 : stop.position);
|
|
422
|
+
this.#position.value = String(stop === undefined ? 0 : Number(stop.position.toFixed(6)));
|
|
385
423
|
}
|
|
386
424
|
|
|
387
425
|
render() {
|
|
@@ -398,33 +436,35 @@ export class ParticleGradientEditorView extends View {
|
|
|
398
436
|
// A checkerboard behind the strip, so that a stop's alpha is visible as transparency rather
|
|
399
437
|
// than as a colour that happens to look like the panel behind it.
|
|
400
438
|
if (this.#has_alpha) {
|
|
401
|
-
for (let x = 0; x <
|
|
439
|
+
for (let x = 0; x < STRIP_WIDTH; x += CHECKER) {
|
|
402
440
|
for (let y = 0; y < STRIP_HEIGHT; y += CHECKER) {
|
|
403
441
|
context.fillStyle = ((x + y) / CHECKER) % 2 === 0 ? '#4c4f54' : '#6a6e74';
|
|
404
|
-
context.fillRect(x, y, CHECKER, CHECKER);
|
|
442
|
+
context.fillRect(MARGIN + x, STRIP_TOP + y, Math.min(CHECKER, STRIP_WIDTH - x), CHECKER);
|
|
405
443
|
}
|
|
406
444
|
}
|
|
407
445
|
}
|
|
408
446
|
|
|
409
447
|
// The strip is drawn by sampling the same function the node compiles to, so what is on
|
|
410
448
|
// screen is what the effect will do — including a hard edge where two stops share a place.
|
|
411
|
-
for (let x = 0; x
|
|
412
|
-
const colour = particle_gradient_sample(this.#stops, x /
|
|
449
|
+
for (let x = 0; x <= STRIP_WIDTH; x++) {
|
|
450
|
+
const colour = particle_gradient_sample(this.#stops, x / STRIP_WIDTH);
|
|
413
451
|
|
|
414
452
|
const alpha = this.#has_alpha ? clamp01(colour[3] ?? 1) : 1;
|
|
415
453
|
|
|
416
454
|
context.fillStyle = `rgba(${byte_of(colour[0])}, ${byte_of(colour[1])}, ${byte_of(colour[2])}, ${alpha})`;
|
|
417
|
-
context.fillRect(x,
|
|
418
|
-
}
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
455
|
+
context.fillRect(MARGIN + x, STRIP_TOP, 1, STRIP_HEIGHT);
|
|
456
|
+
}
|
|
457
|
+
|
|
458
|
+
// Paint selection last so a coincident stop cannot hide its outline.
|
|
459
|
+
const ordered = this.#ordered().sort((a, b) => Number(a.index === this.#selected) - Number(b.index === this.#selected));
|
|
460
|
+
for (const { stop, index } of ordered) {
|
|
461
|
+
const x = MARGIN + clamp01(stop.position) * STRIP_WIDTH;
|
|
422
462
|
const selected = index === this.#selected;
|
|
423
463
|
|
|
424
464
|
context.beginPath();
|
|
425
|
-
context.moveTo(x, STRIP_HEIGHT +
|
|
426
|
-
context.lineTo(x - 5, STRIP_HEIGHT + LANE_HEIGHT -
|
|
427
|
-
context.lineTo(x + 5, STRIP_HEIGHT + LANE_HEIGHT -
|
|
465
|
+
context.moveTo(x, STRIP_TOP + STRIP_HEIGHT + 2);
|
|
466
|
+
context.lineTo(x - 5, STRIP_TOP + STRIP_HEIGHT + LANE_HEIGHT - 4);
|
|
467
|
+
context.lineTo(x + 5, STRIP_TOP + STRIP_HEIGHT + LANE_HEIGHT - 4);
|
|
428
468
|
context.closePath();
|
|
429
469
|
|
|
430
470
|
// the marker carries the stop's own colour, so the lane reads as the stops rather than
|
|
@@ -434,24 +474,29 @@ export class ParticleGradientEditorView extends View {
|
|
|
434
474
|
|
|
435
475
|
context.lineWidth = selected ? 2 : 1;
|
|
436
476
|
context.strokeStyle = selected ? '#ffd35c' : '#20242a';
|
|
437
|
-
context.stroke();
|
|
438
|
-
}
|
|
439
|
-
}
|
|
440
|
-
}
|
|
477
|
+
context.stroke();
|
|
478
|
+
}
|
|
479
|
+
}
|
|
480
|
+
}
|
|
441
481
|
|
|
442
482
|
/**
|
|
443
483
|
* @param {HTMLElement} parent
|
|
444
484
|
* @param {string} type
|
|
445
|
-
* @param {string} className
|
|
485
|
+
* @param {string} className
|
|
486
|
+
* @param {string} text
|
|
446
487
|
* @returns {HTMLInputElement}
|
|
447
488
|
*/
|
|
448
|
-
function field(parent, type, className) {
|
|
449
|
-
const
|
|
489
|
+
function field(parent, type, className, text) {
|
|
490
|
+
const label = document.createElement('label');
|
|
491
|
+
label.classList.add('ramp-field', `field-${className}`);
|
|
492
|
+
label.appendChild(document.createTextNode(text));
|
|
493
|
+
const input = document.createElement('input');
|
|
450
494
|
|
|
451
495
|
input.setAttribute('type', type);
|
|
452
496
|
input.classList.add(className);
|
|
453
497
|
|
|
454
|
-
|
|
498
|
+
label.appendChild(input);
|
|
499
|
+
parent.appendChild(label);
|
|
455
500
|
|
|
456
501
|
return input;
|
|
457
502
|
}
|
|
@@ -138,7 +138,7 @@ const PALETTE_CATEGORIES = [
|
|
|
138
138
|
{ name: "sources", types: ["const", "color", "builtin", "attribute", "random", "curve"] },
|
|
139
139
|
{ name: "output", types: ["setAttribute", "kill"] },
|
|
140
140
|
// The three that are authored data rather than wiring, and are edited as a picture: a gradient
|
|
141
|
-
// strip and a curve
|
|
141
|
+
// strip and a curve plot. Their own heading, because "a colour ramp" is a thing an
|
|
142
142
|
// author goes looking for by name and would not think to look for under `sources`.
|
|
143
143
|
{ name: "ramps", types: ["gradientRGBA", "gradientRGB", "curveLiteral"] },
|
|
144
144
|
{ name: "arithmetic", types: ["add", "sub", "mul", "div", "mad", "scale", "min", "max", "pow", "step", "mix", "clamp", "saturate", "smoothstep", "remap", "oneMinus"] },
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ParticleNodeParametersView.d.ts","sourceRoot":"","sources":["../../../../../editor/view/particles/effect/ParticleNodeParametersView.js"],"names":[],"mappings":"AAqCA;IAOI;;;;;;OAMG;IACH;QALyG,MAAM,EAApG,OAAO,qDAAqD,EAAE,sBAAsB;QAE9D,IAAI;QACG,MAAM,SAA1B,MAAM;OA6BzB;IAxBG,mBAAuC;IAIvC;;OAEG;IACH,mBAAgB;;
|
|
1
|
+
{"version":3,"file":"ParticleNodeParametersView.d.ts","sourceRoot":"","sources":["../../../../../editor/view/particles/effect/ParticleNodeParametersView.js"],"names":[],"mappings":"AAqCA;IAOI;;;;;;OAMG;IACH;QALyG,MAAM,EAApG,OAAO,qDAAqD,EAAE,sBAAsB;QAE9D,IAAI;QACG,MAAM,SAA1B,MAAM;OA6BzB;IAxBG,mBAAuC;IAIvC;;OAEG;IACH,mBAAgB;;CA4cvB;iBApgBgB,8BAA8B"}
|
|
@@ -87,7 +87,9 @@ export class ParticleNodeParametersView extends View {
|
|
|
87
87
|
#buildRow(effect, parameter, commit) {
|
|
88
88
|
const row = new EmptyView({ classList: ['parameter-row', `kind-${parameter.kind}`] });
|
|
89
89
|
|
|
90
|
-
|
|
90
|
+
if (parameter.kind !== PARTICLE_PARAMETER_KIND.GRADIENT && parameter.kind !== PARTICLE_PARAMETER_KIND.CURVE) {
|
|
91
|
+
row.addChild(new LabelView(parameter.name, { classList: ['name'] }));
|
|
92
|
+
}
|
|
91
93
|
|
|
92
94
|
if (typeof parameter.description === "string") {
|
|
93
95
|
row.el.setAttribute('title', parameter.description);
|
|
@@ -213,10 +213,9 @@
|
|
|
213
213
|
/*
|
|
214
214
|
The ramp controls — a gradient's strip and a curve's plot.
|
|
215
215
|
|
|
216
|
-
Both
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
around it grew would be the one thing on the node that could not be read.
|
|
216
|
+
Both controls use the width of the node. The canvases scale with the row rather than holding
|
|
217
|
+
their drawn size: the graph is zoomable, and a control that stayed 240 pixels while everything
|
|
218
|
+
around it grew would be the one thing on the node that could not be read.
|
|
220
219
|
*/
|
|
221
220
|
|
|
222
221
|
.ui-particle-node-parameters .parameter-row.kind-gradient,
|
|
@@ -226,11 +225,13 @@
|
|
|
226
225
|
gap: 3px;
|
|
227
226
|
}
|
|
228
227
|
|
|
229
|
-
.ui-particle-gradient,
|
|
230
|
-
.ui-particle-curve {
|
|
231
|
-
display: flex;
|
|
232
|
-
flex-direction: column;
|
|
233
|
-
gap:
|
|
228
|
+
.ui-particle-gradient,
|
|
229
|
+
.ui-particle-curve {
|
|
230
|
+
display: flex;
|
|
231
|
+
flex-direction: column;
|
|
232
|
+
gap: 5px;
|
|
233
|
+
width: 240px;
|
|
234
|
+
max-width: 100%;
|
|
234
235
|
}
|
|
235
236
|
|
|
236
237
|
.ui-particle-gradient > .strip,
|
|
@@ -238,7 +239,10 @@
|
|
|
238
239
|
display: block;
|
|
239
240
|
width: 100%;
|
|
240
241
|
height: auto;
|
|
241
|
-
|
|
242
|
+
/* An inset border keeps the canvas's drawing and pointer coordinate spaces identical. */
|
|
243
|
+
border: 0;
|
|
244
|
+
padding: 0;
|
|
245
|
+
box-shadow: inset 0 0 0 1px var(--meep-graph-node-border, #363c46);
|
|
242
246
|
border-radius: 3px;
|
|
243
247
|
background: var(--meep-graph-input-bg, #171b21);
|
|
244
248
|
/* the strip and the plot are both dragged in, and a drag that selects text is a drag that fights */
|
|
@@ -248,30 +252,56 @@
|
|
|
248
252
|
|
|
249
253
|
.ui-particle-gradient > .stop-fields,
|
|
250
254
|
.ui-particle-curve > .key-fields {
|
|
251
|
-
display:
|
|
252
|
-
gap:
|
|
253
|
-
align-items:
|
|
254
|
-
}
|
|
255
|
-
|
|
256
|
-
.ui-particle-gradient .
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
}
|
|
267
|
-
|
|
268
|
-
.
|
|
269
|
-
|
|
255
|
+
display: grid;
|
|
256
|
+
gap: 5px;
|
|
257
|
+
align-items: end;
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
.ui-particle-gradient > .stop-fields {
|
|
261
|
+
grid-template-columns: minmax(0, 0.8fr) minmax(0, 1fr) minmax(0, 1.4fr) auto;
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
.ui-particle-gradient > .stop-fields:has(.field-alpha[hidden]) {
|
|
265
|
+
grid-template-columns: minmax(0, 1fr) minmax(0, 1.4fr) auto;
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
.ui-particle-curve > .key-fields {
|
|
269
|
+
grid-template-columns: repeat(2, minmax(0, 1fr));
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
.ramp-field {
|
|
273
|
+
display: flex;
|
|
274
|
+
flex-direction: column;
|
|
275
|
+
gap: 2px;
|
|
276
|
+
min-width: 0;
|
|
277
|
+
color: var(--meep-fg-muted, #9da0a3);
|
|
278
|
+
font-size: 10px;
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
.ramp-field[hidden] {
|
|
282
|
+
display: none;
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
.ramp-field > input,
|
|
286
|
+
.ramp-field > select {
|
|
287
|
+
width: 100%;
|
|
288
|
+
min-width: 0;
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
.ui-particle-gradient .swatch {
|
|
292
|
+
height: 23px;
|
|
293
|
+
padding: 0;
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
.ui-particle-gradient > .strip:focus-visible,
|
|
297
|
+
.ui-particle-curve > .plot:focus-visible {
|
|
298
|
+
outline: 1px solid var(--meep-accent, #2d7dd2);
|
|
270
299
|
}
|
|
271
300
|
|
|
272
301
|
.ui-particle-gradient .remove,
|
|
273
302
|
.ui-particle-curve .remove {
|
|
274
|
-
flex: 0 0 auto;
|
|
303
|
+
flex: 0 0 auto;
|
|
304
|
+
justify-self: end;
|
|
275
305
|
width: 1.8em;
|
|
276
306
|
padding: 2px 0;
|
|
277
307
|
border: 1px solid var(--meep-graph-node-border, #363c46);
|
package/package.json
CHANGED
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
"description": "Advanced 3D game engine",
|
|
7
7
|
"type": "module",
|
|
8
8
|
"author": "Alexander Goldring",
|
|
9
|
-
"version": "3.
|
|
9
|
+
"version": "3.19.0",
|
|
10
10
|
"exports": {
|
|
11
11
|
"./build/*": "./build/*",
|
|
12
12
|
"./src/*": "./src/*",
|
|
@@ -48,7 +48,6 @@
|
|
|
48
48
|
],
|
|
49
49
|
"dependencies": {
|
|
50
50
|
"opentype.js": "1.3.3",
|
|
51
|
-
"pako": "2.0.3",
|
|
52
51
|
"robust-predicates": "3.0.2"
|
|
53
52
|
},
|
|
54
53
|
"peerDependencies": {
|
package/samples/engine/README.md
CHANGED
|
@@ -19,7 +19,7 @@ export default {
|
|
|
19
19
|
// CommonJS dependencies, so those have to be named. Without this, the first thing a new
|
|
20
20
|
// consumer sees is a SyntaxError about a package their application never referenced,
|
|
21
21
|
// a blank page, and no stack trace pointing anywhere near the engine.
|
|
22
|
-
include: ['dat.gui', '
|
|
22
|
+
include: ['dat.gui', 'opentype.js'],
|
|
23
23
|
},
|
|
24
24
|
};
|
|
25
25
|
```
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Decompress pieces of one stream using the platform's compression API.
|
|
3
|
+
*
|
|
4
|
+
* Feed the input through a pipe so that read failures also cancel the input and settle the
|
|
5
|
+
* writable side. Awaiting writes before draining the output can deadlock on backpressure.
|
|
6
|
+
* The input views must remain unchanged until the returned promise settles.
|
|
7
|
+
*
|
|
8
|
+
* @param {Uint8Array[]} chunks
|
|
9
|
+
* @param {"deflate"|"deflate-raw"|"gzip"} [format] `deflate` includes the zlib header and checksum
|
|
10
|
+
* @returns {Promise<Uint8Array>}
|
|
11
|
+
*/
|
|
12
|
+
export function decompress_bytes(chunks: Uint8Array[], format?: "deflate" | "deflate-raw" | "gzip"): Promise<Uint8Array>;
|
|
13
|
+
//# sourceMappingURL=decompress_bytes.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"decompress_bytes.d.ts","sourceRoot":"","sources":["../../../../../src/core/binary/compression/decompress_bytes.js"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AACH,yCAJW,UAAU,EAAE,WACZ,SAAS,GAAC,aAAa,GAAC,MAAM,GAC5B,QAAQ,UAAU,CAAC,CAkB/B"}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Decompress pieces of one stream using the platform's compression API.
|
|
3
|
+
*
|
|
4
|
+
* Feed the input through a pipe so that read failures also cancel the input and settle the
|
|
5
|
+
* writable side. Awaiting writes before draining the output can deadlock on backpressure.
|
|
6
|
+
* The input views must remain unchanged until the returned promise settles.
|
|
7
|
+
*
|
|
8
|
+
* @param {Uint8Array[]} chunks
|
|
9
|
+
* @param {"deflate"|"deflate-raw"|"gzip"} [format] `deflate` includes the zlib header and checksum
|
|
10
|
+
* @returns {Promise<Uint8Array>}
|
|
11
|
+
*/
|
|
12
|
+
export async function decompress_bytes(chunks, format = "deflate") {
|
|
13
|
+
let index = 0;
|
|
14
|
+
|
|
15
|
+
const input = new ReadableStream({
|
|
16
|
+
pull(controller) {
|
|
17
|
+
if (index === chunks.length) {
|
|
18
|
+
controller.close();
|
|
19
|
+
} else {
|
|
20
|
+
controller.enqueue(chunks[index++]);
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
const output = input.pipeThrough(new DecompressionStream(format));
|
|
26
|
+
|
|
27
|
+
return new Uint8Array(await new Response(output).arrayBuffer());
|
|
28
|
+
}
|