q5 4.6.6 → 4.7.1
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 +4 -2
- package/package.json +2 -3
- package/py.typed +0 -0
- package/q5.js +53 -43
- package/q5.pyi +4435 -0
- package/q5.min.js +0 -10
- package/q5.min.js.map +0 -1
package/deno.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@q5/q5",
|
|
3
|
-
"version": "4.
|
|
3
|
+
"version": "4.7.0",
|
|
4
4
|
"license": "LGPL-3.0-only",
|
|
5
5
|
"description": "Beginner friendly graphics powered by WebGPU, optimized for interactive art!",
|
|
6
6
|
"author": "quinton-ashley",
|
|
@@ -32,7 +32,9 @@
|
|
|
32
32
|
"CODE_OF_CONDUCT.md",
|
|
33
33
|
"deno.lock",
|
|
34
34
|
"Icon?",
|
|
35
|
-
"package.json"
|
|
35
|
+
"package.json",
|
|
36
|
+
"q5.min.js",
|
|
37
|
+
"q5.min.js.map"
|
|
36
38
|
]
|
|
37
39
|
}
|
|
38
40
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "q5",
|
|
3
|
-
"version": "4.
|
|
3
|
+
"version": "4.7.1",
|
|
4
4
|
"description": "Beginner friendly graphics powered by WebGPU, optimized for interactive art!",
|
|
5
5
|
"author": "quinton-ashley",
|
|
6
6
|
"license": "LGPL-3.0-only",
|
|
@@ -18,7 +18,6 @@
|
|
|
18
18
|
"node": "./q5-server.js",
|
|
19
19
|
"default": "./q5.js"
|
|
20
20
|
},
|
|
21
|
-
"./q5.min.js": "./q5.min.js",
|
|
22
21
|
"./q5.js": "./q5.js",
|
|
23
22
|
"./q5-server.js": {
|
|
24
23
|
"browser": null,
|
|
@@ -43,7 +42,7 @@
|
|
|
43
42
|
"scripts": {
|
|
44
43
|
"bundle": "cat src/q5-core.js src/q5-canvas.js src/q5-c2d-canvas.js src/q5-c2d-shapes.js src/q5-c2d-image.js src/q5-c2d-soft-filters.js src/q5-c2d-text.js src/q5-color.js src/q5-display.js src/q5-dom.js src/q5-fes.js src/q5-input.js src/q5-math.js src/q5-record.js src/q5-sound.js src/q5-util.js src/q5-vector.js src/q5-webgpu.js src/q5-lang.js src/q5-python.js > q5.js",
|
|
45
44
|
"min": "terser q5.js --compress ecma=2026 --mangle --output q5.min.js --source-map url=q5.min.js.map",
|
|
46
|
-
"dist": "bun bundle
|
|
45
|
+
"dist": "bun bundle",
|
|
47
46
|
"tests": "jest test",
|
|
48
47
|
"bld": "node lang/build.js",
|
|
49
48
|
"types": "node lang/types.js",
|
package/py.typed
ADDED
|
File without changes
|
package/q5.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* q5.js
|
|
3
|
-
* @version 4.
|
|
3
|
+
* @version 4.7
|
|
4
4
|
* @author quinton-ashley
|
|
5
5
|
* @contributors evanalulu, Tezumie, keturn, ormaq, bertubi, RedWilly, Dukemz, LingDong-
|
|
6
6
|
* @license LGPL-3.0
|
|
@@ -226,8 +226,6 @@ function Q5(scope, parent, renderer) {
|
|
|
226
226
|
r[m]($, q);
|
|
227
227
|
}
|
|
228
228
|
|
|
229
|
-
// INIT
|
|
230
|
-
|
|
231
229
|
for (let k in Q5) {
|
|
232
230
|
if (k[1] != '_' && k[1] == k[1].toUpperCase()) {
|
|
233
231
|
$[k] = Q5[k];
|
|
@@ -496,18 +494,19 @@ if (typeof window == 'object') {
|
|
|
496
494
|
window.addEventListener('pagehide', cleanup);
|
|
497
495
|
} else global.window = 0;
|
|
498
496
|
|
|
499
|
-
Q5.version = Q5.VERSION = '4.
|
|
497
|
+
Q5.version = Q5.VERSION = '4.7';
|
|
500
498
|
|
|
501
499
|
if (typeof document == 'object') {
|
|
502
|
-
|
|
503
|
-
if (
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
}
|
|
500
|
+
function init() {
|
|
501
|
+
if (Q5._hasGlobal) return;
|
|
502
|
+
if (Q5.update || Q5.draw) {
|
|
503
|
+
Q5.WebGPU();
|
|
504
|
+
} else {
|
|
505
|
+
new Q5('auto');
|
|
509
506
|
}
|
|
510
|
-
}
|
|
507
|
+
}
|
|
508
|
+
if (document.readyState === 'loading') document.addEventListener('DOMContentLoaded', init);
|
|
509
|
+
else setTimeout(init, 0); // defer until the rest of q5.js is run
|
|
511
510
|
}
|
|
512
511
|
Q5.modules.canvas = ($, q) => {
|
|
513
512
|
$._Canvas =
|
|
@@ -6660,7 +6659,7 @@ fn fragMain(f: FragParams) -> @location(0) vec4f {
|
|
|
6660
6659
|
if (shapeVertCount === 0) throw new Error('Shape needs a vertex()');
|
|
6661
6660
|
|
|
6662
6661
|
// Get the last vertex as the starting point (P₀)
|
|
6663
|
-
let prevIndex = (shapeVertCount - 1) *
|
|
6662
|
+
let prevIndex = (shapeVertCount - 1) * 3;
|
|
6664
6663
|
let startX = sv[prevIndex];
|
|
6665
6664
|
let startY = sv[prevIndex + 1];
|
|
6666
6665
|
|
|
@@ -6673,7 +6672,7 @@ fn fragMain(f: FragParams) -> @location(0) vec4f {
|
|
|
6673
6672
|
y = cy2;
|
|
6674
6673
|
}
|
|
6675
6674
|
|
|
6676
|
-
let end = 1 + step;
|
|
6675
|
+
let end = 1 + step * 0.5;
|
|
6677
6676
|
for (let t = step; t <= end; t += step) {
|
|
6678
6677
|
// Start from 0.1 to avoid duplicating the start point
|
|
6679
6678
|
let t2 = t * t;
|
|
@@ -6802,15 +6801,6 @@ fn fragMain(f: FragParams) -> @location(0) vec4f {
|
|
|
6802
6801
|
}
|
|
6803
6802
|
}
|
|
6804
6803
|
} else {
|
|
6805
|
-
let cx = 0,
|
|
6806
|
-
cy = 0;
|
|
6807
|
-
for (let i = 0; i < shapeVertCount - 1; i++) {
|
|
6808
|
-
cx += sv[i * 3];
|
|
6809
|
-
cy += sv[i * 3 + 1];
|
|
6810
|
-
}
|
|
6811
|
-
cx /= Math.max(1, shapeVertCount - 1);
|
|
6812
|
-
cy /= Math.max(1, shapeVertCount - 1);
|
|
6813
|
-
|
|
6814
6804
|
let signedArea = 0,
|
|
6815
6805
|
sign = 1;
|
|
6816
6806
|
for (let i = 0; i < shapeVertCount - 1; i++) {
|
|
@@ -9621,42 +9611,60 @@ Q5.addHook('predraw', (q) => {
|
|
|
9621
9611
|
}
|
|
9622
9612
|
});
|
|
9623
9613
|
const runPython = async function () {
|
|
9624
|
-
let scripts = [...document.getElementsByTagName('script')]
|
|
9625
|
-
|
|
9614
|
+
let scripts = [...document.getElementsByTagName('script')].filter(
|
|
9615
|
+
(s) => s.type == 'q5-python' || s.type == 'text/q5-python'
|
|
9616
|
+
);
|
|
9626
9617
|
if (!scripts.length) return;
|
|
9627
9618
|
|
|
9628
9619
|
if (!window.brython) {
|
|
9629
|
-
const
|
|
9630
|
-
new Promise((
|
|
9631
|
-
const
|
|
9632
|
-
|
|
9633
|
-
|
|
9634
|
-
|
|
9635
|
-
document.head.appendChild(
|
|
9620
|
+
const load = (src) =>
|
|
9621
|
+
new Promise((res, rej) => {
|
|
9622
|
+
const s = document.createElement('script');
|
|
9623
|
+
s.src = src;
|
|
9624
|
+
s.onload = res;
|
|
9625
|
+
s.onerror = rej;
|
|
9626
|
+
document.head.appendChild(s);
|
|
9636
9627
|
});
|
|
9637
9628
|
|
|
9638
|
-
await
|
|
9639
|
-
await
|
|
9629
|
+
await load('https://cdn.jsdelivr.net/npm/brython@3.14.0/brython.min.js');
|
|
9630
|
+
await load('https://cdn.jsdelivr.net/npm/brython@3.14.0/brython_stdlib.min.js');
|
|
9640
9631
|
}
|
|
9641
9632
|
|
|
9642
9633
|
let code = '';
|
|
9643
9634
|
for (const script of scripts) {
|
|
9644
|
-
|
|
9635
|
+
if (script.src?.endsWith?.('.ipynb')) {
|
|
9636
|
+
const nb = await (await fetch(script.src)).json();
|
|
9637
|
+
for (const cell of nb.cells) {
|
|
9638
|
+
if (cell.cell_type !== 'code') continue;
|
|
9639
|
+
const m = cell.metadata,
|
|
9640
|
+
cellLang = m?.language_info?.name ?? m?.kernelspec?.language ?? m?.kernelspec?.name ?? m?.language;
|
|
9641
|
+
if (cellLang && !String(cellLang).toLowerCase().includes('python')) continue;
|
|
9642
|
+
const src = Array.isArray(cell.source)
|
|
9643
|
+
? cell.source.join('')
|
|
9644
|
+
: typeof cell.source === 'string'
|
|
9645
|
+
? cell.source
|
|
9646
|
+
: '';
|
|
9647
|
+
code += src + '\n';
|
|
9648
|
+
}
|
|
9649
|
+
} else {
|
|
9650
|
+
code += script.src ? await (await fetch(script.src)).text() : script.innerText;
|
|
9651
|
+
}
|
|
9645
9652
|
}
|
|
9646
9653
|
|
|
9654
|
+
// strip `from q5 import *` — it's only used for type hints (q5.pyi)
|
|
9655
|
+
code = code.startsWith('from q5') ? code.slice(code.indexOf('\n') + 1) : code;
|
|
9656
|
+
|
|
9647
9657
|
const useWebGPU = !code.slice(0, code.indexOf('\n')).includes('C2D'),
|
|
9648
9658
|
q = useWebGPU ? await Q5.WebGPU() : new Q5();
|
|
9659
|
+
await q.ready;
|
|
9649
9660
|
|
|
9650
|
-
|
|
9651
|
-
|
|
9652
|
-
// so to make Brython happy with `await Canvas()` we need to make it async
|
|
9653
|
-
const Canvas = q.Canvas;
|
|
9654
|
-
q.Canvas = async (...a) => Canvas(...a);
|
|
9661
|
+
let pyReady;
|
|
9662
|
+
q._loaders.push(new Promise((res) => (pyReady = res)));
|
|
9655
9663
|
|
|
9656
9664
|
// add a tab before each line of code to nest it inside the __run function
|
|
9657
9665
|
// but not within triple-quoted strings
|
|
9658
9666
|
code = code
|
|
9659
|
-
.split(/(
|
|
9667
|
+
.split(/("""[\s\S]*?"""|\'\'\'[\s\S]*?\'\'\')/g)
|
|
9660
9668
|
.map((part, i) => (i % 2 === 0 ? part.replaceAll('\n', '\n\t') : part))
|
|
9661
9669
|
.join('');
|
|
9662
9670
|
|
|
@@ -9753,8 +9761,8 @@ async def _run_py(q, code):
|
|
|
9753
9761
|
pass
|
|
9754
9762
|
|
|
9755
9763
|
_orig_Canvas = ns['Canvas']
|
|
9756
|
-
|
|
9757
|
-
result =
|
|
9764
|
+
def _canvas_wrapper(*args):
|
|
9765
|
+
result = _orig_Canvas(*args)
|
|
9758
9766
|
_sync_state(q, ns)
|
|
9759
9767
|
return result
|
|
9760
9768
|
ns['Canvas'] = ns['createCanvas'] = _canvas_wrapper
|
|
@@ -9776,6 +9784,8 @@ window._runPy = _run_py
|
|
|
9776
9784
|
|
|
9777
9785
|
console.log = log;
|
|
9778
9786
|
|
|
9787
|
+
pyReady();
|
|
9788
|
+
|
|
9779
9789
|
await window._runPy(q, code);
|
|
9780
9790
|
};
|
|
9781
9791
|
|