q5 2.26.0 → 2.27.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/deno.json +1 -1
- package/package.json +1 -1
- package/q5.d.ts +227 -36
- package/q5.js +154 -113
- package/q5.min.js +1 -1
package/q5.js
CHANGED
|
@@ -160,7 +160,7 @@ function Q5(scope, parent, renderer) {
|
|
|
160
160
|
};
|
|
161
161
|
|
|
162
162
|
$.frameRate = (hz) => {
|
|
163
|
-
if (hz != $._targetFrameRate) {
|
|
163
|
+
if (hz && hz != $._targetFrameRate) {
|
|
164
164
|
$._targetFrameRate = hz;
|
|
165
165
|
$._targetFrameDuration = 1000 / hz;
|
|
166
166
|
|
|
@@ -256,18 +256,8 @@ function Q5(scope, parent, renderer) {
|
|
|
256
256
|
};
|
|
257
257
|
|
|
258
258
|
let t = globalScope || $;
|
|
259
|
-
$._isTouchAware = t.touchStarted || t.touchMoved || t.touchEnded;
|
|
260
259
|
|
|
261
|
-
|
|
262
|
-
$.preload = t.preload;
|
|
263
|
-
$.setup = t.setup;
|
|
264
|
-
$.draw = t.draw;
|
|
265
|
-
$.postProcess = t.postProcess;
|
|
266
|
-
}
|
|
267
|
-
$.preload ??= () => {};
|
|
268
|
-
$.setup ??= () => {};
|
|
269
|
-
$.draw ??= () => {};
|
|
270
|
-
$.postProcess ??= () => {};
|
|
260
|
+
$._isTouchAware = t.touchStarted || t.touchMoved || t.touchEnded;
|
|
271
261
|
|
|
272
262
|
let userFns = [
|
|
273
263
|
'setup',
|
|
@@ -277,6 +267,7 @@ function Q5(scope, parent, renderer) {
|
|
|
277
267
|
'mouseReleased',
|
|
278
268
|
'mouseDragged',
|
|
279
269
|
'mouseClicked',
|
|
270
|
+
'doubleClicked',
|
|
280
271
|
'mouseWheel',
|
|
281
272
|
'keyPressed',
|
|
282
273
|
'keyReleased',
|
|
@@ -286,12 +277,15 @@ function Q5(scope, parent, renderer) {
|
|
|
286
277
|
'touchEnded',
|
|
287
278
|
'windowResized'
|
|
288
279
|
];
|
|
289
|
-
|
|
290
|
-
|
|
280
|
+
// shim if undefined
|
|
281
|
+
for (let name of userFns) $[name] ??= () => {};
|
|
282
|
+
|
|
283
|
+
function wrapWithFES(fn) {
|
|
284
|
+
if (!t[fn]) $[fn] = () => {};
|
|
291
285
|
else if ($._isGlobal) {
|
|
292
|
-
$[
|
|
286
|
+
$[fn] = (event) => {
|
|
293
287
|
try {
|
|
294
|
-
return t[
|
|
288
|
+
return t[fn](event);
|
|
295
289
|
} catch (e) {
|
|
296
290
|
if ($._fes) $._fes(e);
|
|
297
291
|
throw e;
|
|
@@ -300,28 +294,24 @@ function Q5(scope, parent, renderer) {
|
|
|
300
294
|
}
|
|
301
295
|
}
|
|
302
296
|
|
|
303
|
-
async function
|
|
304
|
-
|
|
297
|
+
async function _start() {
|
|
298
|
+
wrapWithFES('preload');
|
|
299
|
+
$.preload();
|
|
305
300
|
await Promise.all($._preloadPromises);
|
|
306
301
|
if ($._g) await Promise.all($._g._preloadPromises);
|
|
302
|
+
|
|
303
|
+
for (let name of userFns) wrapWithFES(name);
|
|
304
|
+
|
|
305
|
+
$.draw = t.draw || (() => {});
|
|
306
|
+
|
|
307
307
|
millisStart = performance.now();
|
|
308
308
|
await $.setup();
|
|
309
309
|
$._setupDone = true;
|
|
310
|
-
if ($.frameCount) return;
|
|
311
310
|
if ($.ctx === null) $.createCanvas(200, 200);
|
|
311
|
+
if ($.frameCount) return;
|
|
312
312
|
raf($._draw);
|
|
313
313
|
}
|
|
314
314
|
|
|
315
|
-
function _start() {
|
|
316
|
-
try {
|
|
317
|
-
$.preload();
|
|
318
|
-
if (!$._startDone) _setup();
|
|
319
|
-
} catch (e) {
|
|
320
|
-
if ($._fes) $._fes(e);
|
|
321
|
-
throw e;
|
|
322
|
-
}
|
|
323
|
-
}
|
|
324
|
-
|
|
325
315
|
if (autoLoaded) _start();
|
|
326
316
|
else setTimeout(_start, 32);
|
|
327
317
|
}
|
|
@@ -430,21 +420,44 @@ Q5.modules.canvas = ($, q) => {
|
|
|
430
420
|
|
|
431
421
|
if ($._scope != 'image') {
|
|
432
422
|
if ($._scope == 'graphics') $._pixelDensity = this._pixelDensity;
|
|
433
|
-
else if (
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
423
|
+
else if (!Q5._server) {
|
|
424
|
+
// the canvas can become detached from the DOM
|
|
425
|
+
// if the innerHTML of one of its parents is edited
|
|
426
|
+
// check if canvas is still attached to the DOM
|
|
427
|
+
let el = c;
|
|
428
|
+
while (el && el.parentElement != document.body) {
|
|
429
|
+
el = el.parentElement;
|
|
430
|
+
}
|
|
431
|
+
if (!el) {
|
|
432
|
+
// reattach canvas to the DOM
|
|
433
|
+
document.getElementById(c.id)?.remove();
|
|
434
|
+
addCanvas();
|
|
435
|
+
}
|
|
436
|
+
|
|
437
|
+
if (window.IntersectionObserver) {
|
|
438
|
+
let wasObserved = false;
|
|
439
|
+
new IntersectionObserver((e) => {
|
|
440
|
+
let isIntersecting = e[0].isIntersecting;
|
|
441
|
+
|
|
442
|
+
if (!isIntersecting) {
|
|
443
|
+
// the canvas might still be onscreen, just behind other elements
|
|
444
|
+
let r = c.getBoundingClientRect();
|
|
445
|
+
c.visible = r.top < window.innerHeight && r.bottom > 0 && r.left < window.innerWidth && r.right > 0;
|
|
446
|
+
} else c.visible = true;
|
|
447
|
+
|
|
448
|
+
if (!wasObserved) {
|
|
449
|
+
$._wasLooping = $._loop;
|
|
450
|
+
wasObserved = true;
|
|
451
|
+
}
|
|
452
|
+
|
|
453
|
+
if (c.visible) {
|
|
454
|
+
if ($._wasLooping && !$._loop) $.loop();
|
|
455
|
+
} else {
|
|
456
|
+
$._wasLooping = $._loop;
|
|
457
|
+
$.noLoop();
|
|
458
|
+
}
|
|
459
|
+
}).observe(c);
|
|
460
|
+
}
|
|
448
461
|
}
|
|
449
462
|
}
|
|
450
463
|
|
|
@@ -609,7 +622,9 @@ Q5.modules.canvas = ($, q) => {
|
|
|
609
622
|
$.popStyles = () => {
|
|
610
623
|
let styles = $._styles.pop();
|
|
611
624
|
for (let s of $._styleNames) $[s] = styles[s];
|
|
612
|
-
|
|
625
|
+
|
|
626
|
+
if ($._webgpu) $.colorMode($._colorMode, $._colorFormat);
|
|
627
|
+
else q.Color = styles.Color;
|
|
613
628
|
};
|
|
614
629
|
|
|
615
630
|
if (window && $._scope != 'graphics') {
|
|
@@ -3091,7 +3106,12 @@ Q5.modules.input = ($, q) => {
|
|
|
3091
3106
|
|
|
3092
3107
|
$._updateMouse = (e) => {
|
|
3093
3108
|
if (e.changedTouches) return;
|
|
3094
|
-
|
|
3109
|
+
|
|
3110
|
+
if (document.pointerLockElement) {
|
|
3111
|
+
// In pointer lock mode, update position based on movement
|
|
3112
|
+
q.mouseX += e.movementX;
|
|
3113
|
+
q.mouseY += e.movementY;
|
|
3114
|
+
} else if (c) {
|
|
3095
3115
|
let rect = c.getBoundingClientRect();
|
|
3096
3116
|
let sx = c.scrollWidth / $.width || 1;
|
|
3097
3117
|
let sy = c.scrollHeight / $.height || 1;
|
|
@@ -3109,10 +3129,8 @@ Q5.modules.input = ($, q) => {
|
|
|
3109
3129
|
q.moveY = e.movementY;
|
|
3110
3130
|
};
|
|
3111
3131
|
|
|
3112
|
-
let pressedInCanvas = 0;
|
|
3113
|
-
|
|
3114
3132
|
$._onmousedown = (e) => {
|
|
3115
|
-
|
|
3133
|
+
if (!c?.visible) return;
|
|
3116
3134
|
$._startAudio();
|
|
3117
3135
|
$._updateMouse(e);
|
|
3118
3136
|
q.mouseIsPressed = true;
|
|
@@ -3127,19 +3145,30 @@ Q5.modules.input = ($, q) => {
|
|
|
3127
3145
|
};
|
|
3128
3146
|
|
|
3129
3147
|
$._onmouseup = (e) => {
|
|
3148
|
+
if (!c?.visible) return;
|
|
3130
3149
|
$._updateMouse(e);
|
|
3131
3150
|
q.mouseIsPressed = false;
|
|
3132
3151
|
$.mouseReleased(e);
|
|
3133
3152
|
};
|
|
3134
3153
|
|
|
3135
3154
|
$._onclick = (e) => {
|
|
3155
|
+
if (!c?.visible) return;
|
|
3136
3156
|
$._updateMouse(e);
|
|
3137
3157
|
q.mouseIsPressed = true;
|
|
3138
3158
|
$.mouseClicked(e);
|
|
3139
3159
|
q.mouseIsPressed = false;
|
|
3140
3160
|
};
|
|
3141
3161
|
|
|
3162
|
+
$._ondblclick = (e) => {
|
|
3163
|
+
if (!c?.visible) return;
|
|
3164
|
+
$._updateMouse(e);
|
|
3165
|
+
q.mouseIsPressed = true;
|
|
3166
|
+
$.doubleClicked(e);
|
|
3167
|
+
q.mouseIsPressed = false;
|
|
3168
|
+
};
|
|
3169
|
+
|
|
3142
3170
|
$._onwheel = (e) => {
|
|
3171
|
+
if (!c?.visible) return;
|
|
3143
3172
|
$._updateMouse(e);
|
|
3144
3173
|
e.delta = e.deltaY;
|
|
3145
3174
|
if ($.mouseWheel(e) == false || $._noScroll) e.preventDefault();
|
|
@@ -3160,10 +3189,10 @@ Q5.modules.input = ($, q) => {
|
|
|
3160
3189
|
$.noCursor = () => ($.canvas.style.cursor = 'none');
|
|
3161
3190
|
$.noScroll = () => ($._noScroll = true);
|
|
3162
3191
|
|
|
3163
|
-
|
|
3164
|
-
|
|
3165
|
-
|
|
3166
|
-
|
|
3192
|
+
$.requestPointerLock = (unadjustedMovement = false) => {
|
|
3193
|
+
return document.body?.requestPointerLock({ unadjustedMovement });
|
|
3194
|
+
};
|
|
3195
|
+
$.exitPointerLock = () => document.exitPointerLock();
|
|
3167
3196
|
|
|
3168
3197
|
$._onkeydown = (e) => {
|
|
3169
3198
|
if (e.repeat) return;
|
|
@@ -3204,6 +3233,7 @@ Q5.modules.input = ($, q) => {
|
|
|
3204
3233
|
}
|
|
3205
3234
|
|
|
3206
3235
|
$._ontouchstart = (e) => {
|
|
3236
|
+
if (!c?.visible) return;
|
|
3207
3237
|
$._startAudio();
|
|
3208
3238
|
q.touches = [...e.touches].map(getTouchInfo);
|
|
3209
3239
|
if (!$._isTouchAware) {
|
|
@@ -3217,6 +3247,7 @@ Q5.modules.input = ($, q) => {
|
|
|
3217
3247
|
};
|
|
3218
3248
|
|
|
3219
3249
|
$._ontouchmove = (e) => {
|
|
3250
|
+
if (!c?.visible) return;
|
|
3220
3251
|
q.touches = [...e.touches].map(getTouchInfo);
|
|
3221
3252
|
if (!$._isTouchAware) {
|
|
3222
3253
|
q.mouseX = $.touches[0].x;
|
|
@@ -3227,6 +3258,7 @@ Q5.modules.input = ($, q) => {
|
|
|
3227
3258
|
};
|
|
3228
3259
|
|
|
3229
3260
|
$._ontouchend = (e) => {
|
|
3261
|
+
if (!c?.visible) return;
|
|
3230
3262
|
q.touches = [...e.touches].map(getTouchInfo);
|
|
3231
3263
|
if (!$._isTouchAware && !$.touches.length) {
|
|
3232
3264
|
q.mouseIsPressed = false;
|
|
@@ -3235,11 +3267,18 @@ Q5.modules.input = ($, q) => {
|
|
|
3235
3267
|
if (!$.touchEnded(e)) e.preventDefault();
|
|
3236
3268
|
};
|
|
3237
3269
|
|
|
3238
|
-
if (
|
|
3239
|
-
let l =
|
|
3270
|
+
if (window) {
|
|
3271
|
+
let l = window.addEventListener;
|
|
3272
|
+
l('keydown', (e) => $._onkeydown(e), false);
|
|
3273
|
+
l('keyup', (e) => $._onkeyup(e), false);
|
|
3274
|
+
|
|
3240
3275
|
l('mousedown', (e) => $._onmousedown(e));
|
|
3241
|
-
l('
|
|
3276
|
+
l('mousemove', (e) => $._onmousemove(e), false);
|
|
3277
|
+
l('mouseup', (e) => $._onmouseup(e));
|
|
3242
3278
|
l('click', (e) => $._onclick(e));
|
|
3279
|
+
l('dblclick', (e) => $._ondblclick(e));
|
|
3280
|
+
|
|
3281
|
+
if (!c) l('wheel', (e) => $._onwheel(e));
|
|
3243
3282
|
|
|
3244
3283
|
l('touchstart', (e) => $._ontouchstart(e));
|
|
3245
3284
|
l('touchmove', (e) => $._ontouchmove(e));
|
|
@@ -3247,25 +3286,10 @@ Q5.modules.input = ($, q) => {
|
|
|
3247
3286
|
l('touchcancel', (e) => $._ontouchend(e));
|
|
3248
3287
|
}
|
|
3249
3288
|
|
|
3250
|
-
|
|
3251
|
-
|
|
3252
|
-
|
|
3253
|
-
|
|
3254
|
-
|
|
3255
|
-
if (!c) {
|
|
3256
|
-
l('mousedown', (e) => $._onmousedown(e));
|
|
3257
|
-
l('wheel', (e) => $._onwheel(e));
|
|
3258
|
-
l('click', (e) => $._onclick(e));
|
|
3259
|
-
}
|
|
3260
|
-
|
|
3261
|
-
l('mousemove', (e) => $._onmousemove(e), false);
|
|
3262
|
-
l('mouseup', (e) => {
|
|
3263
|
-
if (pressedInCanvas > 0) {
|
|
3264
|
-
pressedInCanvas--;
|
|
3265
|
-
$._onmouseup(e);
|
|
3266
|
-
}
|
|
3267
|
-
});
|
|
3268
|
-
}
|
|
3289
|
+
// making the window level event listener for wheel events
|
|
3290
|
+
// not passive would be necessary to be able to use `e.preventDefault`
|
|
3291
|
+
// but browsers warn that it's bad for performance
|
|
3292
|
+
if (c) c.addEventListener('wheel', (e) => $._onwheel(e));
|
|
3269
3293
|
};
|
|
3270
3294
|
Q5.modules.math = ($, q) => {
|
|
3271
3295
|
$.RADIANS = 0;
|
|
@@ -4134,6 +4158,10 @@ Q5.modules.sound = ($, q) => {
|
|
|
4134
4158
|
return Q5.aud.resume();
|
|
4135
4159
|
}
|
|
4136
4160
|
};
|
|
4161
|
+
|
|
4162
|
+
$.outputVolume = (level) => {
|
|
4163
|
+
if (Q5.soundOut) Q5.soundOut.gain.value = level;
|
|
4164
|
+
};
|
|
4137
4165
|
};
|
|
4138
4166
|
|
|
4139
4167
|
if (window.OfflineAudioContext) {
|
|
@@ -4183,6 +4211,7 @@ Q5.Sound = class {
|
|
|
4183
4211
|
source.onended = () => {
|
|
4184
4212
|
if (!this.paused) {
|
|
4185
4213
|
this.ended = true;
|
|
4214
|
+
if (this._onended) this._onended();
|
|
4186
4215
|
this.sources.delete(source);
|
|
4187
4216
|
}
|
|
4188
4217
|
};
|
|
@@ -4278,6 +4307,9 @@ Q5.Sound = class {
|
|
|
4278
4307
|
isLooping() {
|
|
4279
4308
|
return this._loop;
|
|
4280
4309
|
}
|
|
4310
|
+
onended(cb) {
|
|
4311
|
+
this._onended = cb;
|
|
4312
|
+
}
|
|
4281
4313
|
};
|
|
4282
4314
|
Q5.modules.util = ($, q) => {
|
|
4283
4315
|
$._loadFile = (url, cb, type) => {
|
|
@@ -4346,7 +4378,7 @@ Q5.modules.util = ($, q) => {
|
|
|
4346
4378
|
name = name || 'untitled';
|
|
4347
4379
|
ext = ext || 'png';
|
|
4348
4380
|
if (imgRegex.test(ext)) {
|
|
4349
|
-
if ($.canvas?.renderer == 'webgpu' && data.canvas
|
|
4381
|
+
if ($.canvas?.renderer == 'webgpu' && data.canvas?.renderer == 'c2d') {
|
|
4350
4382
|
data = await $._g._saveCanvas(data, ext);
|
|
4351
4383
|
} else {
|
|
4352
4384
|
data = await $._saveCanvas(data, ext);
|
|
@@ -4371,8 +4403,9 @@ Q5.modules.util = ($, q) => {
|
|
|
4371
4403
|
if (!a || (typeof a == 'string' && (!b || (!c && b.length < 5)))) {
|
|
4372
4404
|
c = b;
|
|
4373
4405
|
b = a;
|
|
4374
|
-
a =
|
|
4406
|
+
a = $;
|
|
4375
4407
|
}
|
|
4408
|
+
if (a == $.canvas) a = $;
|
|
4376
4409
|
if (c) saveFile(a, b, c);
|
|
4377
4410
|
else if (b) {
|
|
4378
4411
|
let lastDot = b.lastIndexOf('.');
|
|
@@ -4949,6 +4982,8 @@ fn fragMain(f: FragParams ) -> @location(0) vec4f {
|
|
|
4949
4982
|
createMainView();
|
|
4950
4983
|
};
|
|
4951
4984
|
|
|
4985
|
+
// since these values are checked so often in `addColor`,
|
|
4986
|
+
// they're stored in local variables for better performance
|
|
4952
4987
|
let usingRGB = true,
|
|
4953
4988
|
colorFormat = 1;
|
|
4954
4989
|
|
|
@@ -5473,7 +5508,7 @@ fn fragMain(f: FragParams ) -> @location(0) vec4f {
|
|
|
5473
5508
|
}
|
|
5474
5509
|
};
|
|
5475
5510
|
|
|
5476
|
-
$._finishRender =
|
|
5511
|
+
$._finishRender = () => {
|
|
5477
5512
|
pass.end();
|
|
5478
5513
|
|
|
5479
5514
|
pass = encoder.beginRenderPass({
|
|
@@ -5505,12 +5540,6 @@ fn fragMain(f: FragParams ) -> @location(0) vec4f {
|
|
|
5505
5540
|
Q5.device.queue.submit([encoder.finish()]);
|
|
5506
5541
|
$._pass = pass = encoder = null;
|
|
5507
5542
|
|
|
5508
|
-
// destroy buffers
|
|
5509
|
-
Q5.device.queue.onSubmittedWorkDone().then(() => {
|
|
5510
|
-
for (let b of $._buffers) b.destroy();
|
|
5511
|
-
$._buffers = [];
|
|
5512
|
-
});
|
|
5513
|
-
|
|
5514
5543
|
// clear the stacks for the next frame
|
|
5515
5544
|
drawStack.splice(0, drawStack.length);
|
|
5516
5545
|
colorIndex = 1;
|
|
@@ -5518,9 +5547,15 @@ fn fragMain(f: FragParams ) -> @location(0) vec4f {
|
|
|
5518
5547
|
matrices = [matrices[0]];
|
|
5519
5548
|
matricesIndexStack = [];
|
|
5520
5549
|
|
|
5521
|
-
$.
|
|
5550
|
+
$._texture = frameA;
|
|
5522
5551
|
|
|
5523
5552
|
for (let m of $._hooks.postRender) m();
|
|
5553
|
+
|
|
5554
|
+
// destroy buffers
|
|
5555
|
+
Q5.device.queue.onSubmittedWorkDone().then(() => {
|
|
5556
|
+
for (let b of $._buffers) b.destroy();
|
|
5557
|
+
$._buffers = [];
|
|
5558
|
+
});
|
|
5524
5559
|
};
|
|
5525
5560
|
};
|
|
5526
5561
|
|
|
@@ -6020,7 +6055,10 @@ fn fragMain(f: FragParams) -> @location(0) vec4f {
|
|
|
6020
6055
|
};
|
|
6021
6056
|
|
|
6022
6057
|
let curveSegments = 20;
|
|
6023
|
-
$.curveDetail = (
|
|
6058
|
+
$.curveDetail = (v) => (curveSegments = v);
|
|
6059
|
+
|
|
6060
|
+
let bezierSegments = 20;
|
|
6061
|
+
$.bezierDetail = (v) => (bezierSegments = v);
|
|
6024
6062
|
|
|
6025
6063
|
let shapeVertCount;
|
|
6026
6064
|
let sv = []; // shape vertices
|
|
@@ -6052,7 +6090,7 @@ fn fragMain(f: FragParams) -> @location(0) vec4f {
|
|
|
6052
6090
|
let startX = sv[prevIndex];
|
|
6053
6091
|
let startY = sv[prevIndex + 1];
|
|
6054
6092
|
|
|
6055
|
-
let step = 1 /
|
|
6093
|
+
let step = 1 / bezierSegments;
|
|
6056
6094
|
|
|
6057
6095
|
let vx, vy;
|
|
6058
6096
|
let quadratic = arguments.length == 4;
|
|
@@ -6100,6 +6138,9 @@ fn fragMain(f: FragParams) -> @location(0) vec4f {
|
|
|
6100
6138
|
}
|
|
6101
6139
|
}
|
|
6102
6140
|
|
|
6141
|
+
// Use curveSegments to determine step size
|
|
6142
|
+
let step = 1 / curveSegments;
|
|
6143
|
+
|
|
6103
6144
|
// calculate catmull-rom spline curve points
|
|
6104
6145
|
for (let i = 0; i < points.length - 3; i++) {
|
|
6105
6146
|
let p0 = points[i];
|
|
@@ -6107,7 +6148,7 @@ fn fragMain(f: FragParams) -> @location(0) vec4f {
|
|
|
6107
6148
|
let p2 = points[i + 2];
|
|
6108
6149
|
let p3 = points[i + 3];
|
|
6109
6150
|
|
|
6110
|
-
for (let t = 0; t <= 1; t +=
|
|
6151
|
+
for (let t = 0; t <= 1; t += step) {
|
|
6111
6152
|
let t2 = t * t;
|
|
6112
6153
|
let t3 = t2 * t;
|
|
6113
6154
|
|
|
@@ -6429,13 +6470,16 @@ fn fragMain(f: FragParams) -> @location(0) vec4f {
|
|
|
6429
6470
|
|
|
6430
6471
|
$._textureBindGroups = [];
|
|
6431
6472
|
|
|
6432
|
-
$._saveCanvas = async (
|
|
6433
|
-
let
|
|
6434
|
-
if (
|
|
6473
|
+
$._saveCanvas = async (g, ext) => {
|
|
6474
|
+
let makeFrame = g._drawStack?.length;
|
|
6475
|
+
if (makeFrame) {
|
|
6476
|
+
g._render();
|
|
6477
|
+
g._finishRender();
|
|
6478
|
+
}
|
|
6435
6479
|
|
|
6436
|
-
let texture =
|
|
6480
|
+
let texture = g._texture;
|
|
6437
6481
|
|
|
6438
|
-
if (
|
|
6482
|
+
if (makeFrame) g._beginRender();
|
|
6439
6483
|
|
|
6440
6484
|
let w = texture.width,
|
|
6441
6485
|
h = texture.height,
|
|
@@ -6446,8 +6490,6 @@ fn fragMain(f: FragParams) -> @location(0) vec4f {
|
|
|
6446
6490
|
usage: GPUBufferUsage.COPY_DST | GPUBufferUsage.MAP_READ
|
|
6447
6491
|
});
|
|
6448
6492
|
|
|
6449
|
-
$._buffers.push(buffer);
|
|
6450
|
-
|
|
6451
6493
|
let en = Q5.device.createCommandEncoder();
|
|
6452
6494
|
|
|
6453
6495
|
en.copyTextureToBuffer({ texture }, { buffer, bytesPerRow, rowsPerImage: h }, { width: w, height: h });
|
|
@@ -6482,6 +6524,8 @@ fn fragMain(f: FragParams) -> @location(0) vec4f {
|
|
|
6482
6524
|
let ctx = cnv.getContext('2d', { colorSpace });
|
|
6483
6525
|
ctx.putImageData(data, 0, 0);
|
|
6484
6526
|
|
|
6527
|
+
$._buffers.push(buffer);
|
|
6528
|
+
|
|
6485
6529
|
// Convert to blob then data URL
|
|
6486
6530
|
let blob = await cnv.convertToBlob({ type: 'image/' + ext });
|
|
6487
6531
|
return await new Promise((resolve) => {
|
|
@@ -6533,10 +6577,10 @@ fn fragMain(f: FragParams) -> @location(0) vec4f {
|
|
|
6533
6577
|
}
|
|
6534
6578
|
|
|
6535
6579
|
texture.index = tIdx + vidFrames;
|
|
6536
|
-
img.
|
|
6580
|
+
img._texture = texture;
|
|
6537
6581
|
|
|
6538
6582
|
$._textureBindGroups[texture.index] = Q5.device.createBindGroup({
|
|
6539
|
-
label: img.src || 'canvas',
|
|
6583
|
+
label: img.src || texture.label || 'canvas',
|
|
6540
6584
|
layout: textureLayout,
|
|
6541
6585
|
entries: [
|
|
6542
6586
|
{ binding: 0, resource: $._imageSampler },
|
|
@@ -6587,16 +6631,6 @@ fn fragMain(f: FragParams) -> @location(0) vec4f {
|
|
|
6587
6631
|
$._addTexture(g, g._frameA);
|
|
6588
6632
|
$._addTexture(g, g._frameB);
|
|
6589
6633
|
g._beginRender();
|
|
6590
|
-
|
|
6591
|
-
g.finishFrame = function () {
|
|
6592
|
-
this._render();
|
|
6593
|
-
this._finishRender();
|
|
6594
|
-
};
|
|
6595
|
-
g.beginFrame = function () {
|
|
6596
|
-
this.resetMatrix();
|
|
6597
|
-
this._beginRender();
|
|
6598
|
-
this.frameCount++;
|
|
6599
|
-
};
|
|
6600
6634
|
} else $._extendImage(g);
|
|
6601
6635
|
return g;
|
|
6602
6636
|
};
|
|
@@ -6618,7 +6652,7 @@ fn fragMain(f: FragParams) -> @location(0) vec4f {
|
|
|
6618
6652
|
|
|
6619
6653
|
$.image = (img, dx = 0, dy = 0, dw, dh, sx = 0, sy = 0, sw, sh) => {
|
|
6620
6654
|
let isVideo;
|
|
6621
|
-
if (img.
|
|
6655
|
+
if (img._texture == undefined) {
|
|
6622
6656
|
isVideo = img.tagName == 'VIDEO';
|
|
6623
6657
|
if (!isVideo || !img.width || !img.currentTime) return;
|
|
6624
6658
|
if (img.flipped) $.scale(-1, 1);
|
|
@@ -6630,14 +6664,17 @@ fn fragMain(f: FragParams) -> @location(0) vec4f {
|
|
|
6630
6664
|
w = cnv.width,
|
|
6631
6665
|
h = cnv.height,
|
|
6632
6666
|
pd = img._pixelDensity || 1,
|
|
6633
|
-
|
|
6667
|
+
makeFrame = img._graphics && img._drawStack?.length;
|
|
6634
6668
|
|
|
6635
|
-
if (
|
|
6669
|
+
if (makeFrame) {
|
|
6670
|
+
img._render();
|
|
6671
|
+
img._finishRender();
|
|
6672
|
+
}
|
|
6636
6673
|
|
|
6637
6674
|
if (img.modified) {
|
|
6638
6675
|
Q5.device.queue.copyExternalImageToTexture(
|
|
6639
6676
|
{ source: cnv },
|
|
6640
|
-
{ texture: img.
|
|
6677
|
+
{ texture: img._texture, colorSpace: $.canvas.colorSpace },
|
|
6641
6678
|
[w, h, 1]
|
|
6642
6679
|
);
|
|
6643
6680
|
img.frameCount++;
|
|
@@ -6667,9 +6704,13 @@ fn fragMain(f: FragParams) -> @location(0) vec4f {
|
|
|
6667
6704
|
addVert(r, b, u1, v1, ci, ti, ia);
|
|
6668
6705
|
|
|
6669
6706
|
if (!isVideo) {
|
|
6670
|
-
$._drawStack.push($._imagePL, img.
|
|
6707
|
+
$._drawStack.push($._imagePL, img._texture.index);
|
|
6671
6708
|
|
|
6672
|
-
if (
|
|
6709
|
+
if (makeFrame) {
|
|
6710
|
+
img.resetMatrix();
|
|
6711
|
+
img._beginRender();
|
|
6712
|
+
img.frameCount++;
|
|
6713
|
+
}
|
|
6673
6714
|
} else {
|
|
6674
6715
|
// render video
|
|
6675
6716
|
let externalTexture = Q5.device.importExternalTexture({ source: img });
|