q5 2.9.21 → 2.9.22
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/package.json +1 -1
- package/q5.js +110 -17
- package/q5.min.js +1 -1
- package/src/q5-2d-canvas.js +8 -2
- package/src/q5-2d-drawing.js +20 -7
- package/src/q5-2d-image.js +1 -0
- package/src/q5-2d-text.js +7 -0
- package/src/q5-canvas.js +6 -5
- package/src/q5-color.js +5 -0
- package/src/q5-input.js +12 -0
- package/src/q5-math.js +10 -3
- package/src/q5-record.js +2 -0
- package/src/q5-vector.js +33 -0
- package/src/q5-webgpu-canvas.js +3 -0
- package/src/q5-webgpu-text.js +5 -0
package/src/q5-2d-text.js
CHANGED
|
@@ -36,6 +36,7 @@ Q5.renderers.q2d.text = ($, q) => {
|
|
|
36
36
|
fontMod = true;
|
|
37
37
|
styleHash = -1;
|
|
38
38
|
};
|
|
39
|
+
|
|
39
40
|
$.textSize = (x) => {
|
|
40
41
|
if (x == undefined || x == $._textSize) return $._textSize;
|
|
41
42
|
if ($._da) x *= $._da;
|
|
@@ -47,12 +48,14 @@ Q5.renderers.q2d.text = ($, q) => {
|
|
|
47
48
|
leadDiff = leading - x;
|
|
48
49
|
}
|
|
49
50
|
};
|
|
51
|
+
|
|
50
52
|
$.textStyle = (x) => {
|
|
51
53
|
if (!x || x == emphasis) return emphasis;
|
|
52
54
|
emphasis = x;
|
|
53
55
|
fontMod = true;
|
|
54
56
|
styleHash = -1;
|
|
55
57
|
};
|
|
58
|
+
|
|
56
59
|
$.textLeading = (x) => {
|
|
57
60
|
leadingSet = true;
|
|
58
61
|
if (x == undefined || x == leading) return leading;
|
|
@@ -61,6 +64,7 @@ Q5.renderers.q2d.text = ($, q) => {
|
|
|
61
64
|
leadDiff = x - $._textSize;
|
|
62
65
|
styleHash = -1;
|
|
63
66
|
};
|
|
67
|
+
|
|
64
68
|
$.textAlign = (horiz, vert) => {
|
|
65
69
|
$.ctx.textAlign = $._textAlign = horiz;
|
|
66
70
|
if (vert) {
|
|
@@ -90,6 +94,7 @@ Q5.renderers.q2d.text = ($, q) => {
|
|
|
90
94
|
if (enable !== undefined) useCache = enable;
|
|
91
95
|
return useCache;
|
|
92
96
|
};
|
|
97
|
+
|
|
93
98
|
$.createTextImage = (str, w, h) => {
|
|
94
99
|
genTextImage = true;
|
|
95
100
|
img = $.text(str, 0, 0, w, h);
|
|
@@ -98,6 +103,7 @@ Q5.renderers.q2d.text = ($, q) => {
|
|
|
98
103
|
};
|
|
99
104
|
|
|
100
105
|
let lines = [];
|
|
106
|
+
|
|
101
107
|
$.text = (str, x, y, w, h) => {
|
|
102
108
|
if (str === undefined || (!$._doFill && !$._doStroke)) return;
|
|
103
109
|
str = str.toString();
|
|
@@ -223,6 +229,7 @@ Q5.renderers.q2d.text = ($, q) => {
|
|
|
223
229
|
$.textImage(img, x, y);
|
|
224
230
|
}
|
|
225
231
|
};
|
|
232
|
+
|
|
226
233
|
$.textImage = (img, x, y) => {
|
|
227
234
|
if (typeof img == 'string') img = $.createTextImage(img);
|
|
228
235
|
|
package/src/q5-canvas.js
CHANGED
|
@@ -146,7 +146,7 @@ Q5.modules.canvas = ($, q) => {
|
|
|
146
146
|
return g;
|
|
147
147
|
};
|
|
148
148
|
|
|
149
|
-
|
|
149
|
+
async function saveFile(data, name, ext) {
|
|
150
150
|
name = name || 'untitled';
|
|
151
151
|
ext = ext || 'png';
|
|
152
152
|
if (ext == 'jpg' || ext == 'png' || ext == 'webp') {
|
|
@@ -174,18 +174,19 @@ Q5.modules.canvas = ($, q) => {
|
|
|
174
174
|
a.download = name + '.' + ext;
|
|
175
175
|
a.click();
|
|
176
176
|
URL.revokeObjectURL(a.href);
|
|
177
|
-
}
|
|
177
|
+
}
|
|
178
|
+
|
|
178
179
|
$.save = (a, b, c) => {
|
|
179
180
|
if (!a || (typeof a == 'string' && (!b || (!c && b.length < 5)))) {
|
|
180
181
|
c = b;
|
|
181
182
|
b = a;
|
|
182
183
|
a = $.canvas;
|
|
183
184
|
}
|
|
184
|
-
if (c) return
|
|
185
|
+
if (c) return saveFile(a, b, c);
|
|
185
186
|
if (b) {
|
|
186
187
|
b = b.split('.');
|
|
187
|
-
|
|
188
|
-
} else
|
|
188
|
+
saveFile(a, b[0], b.at(-1));
|
|
189
|
+
} else saveFile(a);
|
|
189
190
|
};
|
|
190
191
|
|
|
191
192
|
$._setCanvasSize = (w, h) => {
|
package/src/q5-color.js
CHANGED
|
@@ -146,6 +146,7 @@ Q5.Color = class {
|
|
|
146
146
|
this._q5Color = true;
|
|
147
147
|
}
|
|
148
148
|
};
|
|
149
|
+
|
|
149
150
|
Q5.ColorOKLCH = class extends Q5.Color {
|
|
150
151
|
constructor(l, c, h, a) {
|
|
151
152
|
super();
|
|
@@ -158,6 +159,7 @@ Q5.ColorOKLCH = class extends Q5.Color {
|
|
|
158
159
|
return `oklch(${this.l} ${this.c} ${this.h} / ${this.a})`;
|
|
159
160
|
}
|
|
160
161
|
};
|
|
162
|
+
|
|
161
163
|
Q5.ColorRGBA = class extends Q5.Color {
|
|
162
164
|
constructor(r, g, b, a) {
|
|
163
165
|
super();
|
|
@@ -173,11 +175,13 @@ Q5.ColorRGBA = class extends Q5.Color {
|
|
|
173
175
|
return `color(srgb ${this.r} ${this.g} ${this.b} / ${this.a})`;
|
|
174
176
|
}
|
|
175
177
|
};
|
|
178
|
+
|
|
176
179
|
Q5.ColorRGBA_P3 = class extends Q5.ColorRGBA {
|
|
177
180
|
toString() {
|
|
178
181
|
return `color(display-p3 ${this.r} ${this.g} ${this.b} / ${this.a})`;
|
|
179
182
|
}
|
|
180
183
|
};
|
|
184
|
+
|
|
181
185
|
// legacy 8-bit (0-255) integer color format
|
|
182
186
|
Q5.ColorRGBA_8 = class extends Q5.ColorRGBA {
|
|
183
187
|
constructor(r, g, b, a) {
|
|
@@ -202,6 +206,7 @@ Q5.ColorRGBA_8 = class extends Q5.ColorRGBA {
|
|
|
202
206
|
return `rgb(${this.r} ${this.g} ${this.b} / ${this.a / 255})`;
|
|
203
207
|
}
|
|
204
208
|
};
|
|
209
|
+
|
|
205
210
|
// p3 10-bit color in integer color format, for backwards compatibility
|
|
206
211
|
Q5.ColorRGBA_P3_8 = class extends Q5.ColorRGBA {
|
|
207
212
|
constructor(r, g, b, a) {
|
package/src/q5-input.js
CHANGED
|
@@ -59,6 +59,7 @@ Q5.modules.input = ($, q) => {
|
|
|
59
59
|
q.moveX = e.movementX;
|
|
60
60
|
q.moveY = e.movementY;
|
|
61
61
|
};
|
|
62
|
+
|
|
62
63
|
$._onmousedown = (e) => {
|
|
63
64
|
$._startAudio();
|
|
64
65
|
$._updateMouse(e);
|
|
@@ -66,22 +67,26 @@ Q5.modules.input = ($, q) => {
|
|
|
66
67
|
q.mouseButton = mouseBtns[e.button];
|
|
67
68
|
$.mousePressed(e);
|
|
68
69
|
};
|
|
70
|
+
|
|
69
71
|
$._onmousemove = (e) => {
|
|
70
72
|
$._updateMouse(e);
|
|
71
73
|
if ($.mouseIsPressed) $.mouseDragged(e);
|
|
72
74
|
else $.mouseMoved(e);
|
|
73
75
|
};
|
|
76
|
+
|
|
74
77
|
$._onmouseup = (e) => {
|
|
75
78
|
$._updateMouse(e);
|
|
76
79
|
q.mouseIsPressed = false;
|
|
77
80
|
$.mouseReleased(e);
|
|
78
81
|
};
|
|
82
|
+
|
|
79
83
|
$._onclick = (e) => {
|
|
80
84
|
$._updateMouse(e);
|
|
81
85
|
q.mouseIsPressed = true;
|
|
82
86
|
$.mouseClicked(e);
|
|
83
87
|
q.mouseIsPressed = false;
|
|
84
88
|
};
|
|
89
|
+
|
|
85
90
|
$._onwheel = (e) => {
|
|
86
91
|
$._updateMouse(e);
|
|
87
92
|
e.delta = e.deltaY;
|
|
@@ -99,9 +104,11 @@ Q5.modules.input = ($, q) => {
|
|
|
99
104
|
}
|
|
100
105
|
$.canvas.style.cursor = name + pfx;
|
|
101
106
|
};
|
|
107
|
+
|
|
102
108
|
$.noCursor = () => {
|
|
103
109
|
$.canvas.style.cursor = 'none';
|
|
104
110
|
};
|
|
111
|
+
|
|
105
112
|
if (window) {
|
|
106
113
|
$.requestPointerLock = document.body?.requestPointerLock;
|
|
107
114
|
$.exitPointerLock = document.exitPointerLock;
|
|
@@ -117,6 +124,7 @@ Q5.modules.input = ($, q) => {
|
|
|
117
124
|
$.keyPressed(e);
|
|
118
125
|
if (e.key.length == 1) $.keyTyped(e);
|
|
119
126
|
};
|
|
127
|
+
|
|
120
128
|
$._onkeyup = (e) => {
|
|
121
129
|
q.keyIsPressed = false;
|
|
122
130
|
q.key = e.key;
|
|
@@ -124,6 +132,7 @@ Q5.modules.input = ($, q) => {
|
|
|
124
132
|
keysHeld[$.keyCode] = keysHeld[$.key.toLowerCase()] = false;
|
|
125
133
|
$.keyReleased(e);
|
|
126
134
|
};
|
|
135
|
+
|
|
127
136
|
$.keyIsDown = (v) => !!keysHeld[typeof v == 'string' ? v.toLowerCase() : v];
|
|
128
137
|
|
|
129
138
|
function getTouchInfo(touch) {
|
|
@@ -136,6 +145,7 @@ Q5.modules.input = ($, q) => {
|
|
|
136
145
|
id: touch.identifier
|
|
137
146
|
};
|
|
138
147
|
}
|
|
148
|
+
|
|
139
149
|
$._ontouchstart = (e) => {
|
|
140
150
|
$._startAudio();
|
|
141
151
|
q.touches = [...e.touches].map(getTouchInfo);
|
|
@@ -148,6 +158,7 @@ Q5.modules.input = ($, q) => {
|
|
|
148
158
|
}
|
|
149
159
|
if (!$.touchStarted(e)) e.preventDefault();
|
|
150
160
|
};
|
|
161
|
+
|
|
151
162
|
$._ontouchmove = (e) => {
|
|
152
163
|
q.touches = [...e.touches].map(getTouchInfo);
|
|
153
164
|
if (!$._isTouchAware) {
|
|
@@ -157,6 +168,7 @@ Q5.modules.input = ($, q) => {
|
|
|
157
168
|
}
|
|
158
169
|
if (!$.touchMoved(e)) e.preventDefault();
|
|
159
170
|
};
|
|
171
|
+
|
|
160
172
|
$._ontouchend = (e) => {
|
|
161
173
|
q.touches = [...e.touches].map(getTouchInfo);
|
|
162
174
|
if (!$._isTouchAware && !$.touches.length) {
|
package/src/q5-math.js
CHANGED
|
@@ -42,13 +42,15 @@ Q5.modules.math = ($, q) => {
|
|
|
42
42
|
return Math.min(Math.max(val, ostop), ostart);
|
|
43
43
|
}
|
|
44
44
|
};
|
|
45
|
-
|
|
46
|
-
$.constrain = (x, lo, hi) => Math.min(Math.max(x, lo), hi);
|
|
45
|
+
|
|
47
46
|
$.dist = function () {
|
|
48
47
|
let a = arguments;
|
|
49
48
|
if (a.length == 4) return Math.hypot(a[0] - a[2], a[1] - a[3]);
|
|
50
49
|
else return Math.hypot(a[0] - a[3], a[1] - a[4], a[2] - a[5]);
|
|
51
50
|
};
|
|
51
|
+
|
|
52
|
+
$.lerp = (a, b, t) => a * (1 - t) + b * t;
|
|
53
|
+
$.constrain = (x, lo, hi) => Math.min(Math.max(x, lo), hi);
|
|
52
54
|
$.norm = (value, start, stop) => $.map(value, start, stop, 0, 1);
|
|
53
55
|
$.sq = (x) => x * x;
|
|
54
56
|
$.fract = (x) => x - Math.floor(x);
|
|
@@ -69,7 +71,6 @@ Q5.modules.math = ($, q) => {
|
|
|
69
71
|
let a = Math.atan(x);
|
|
70
72
|
return !angleMode ? a : a * RADTODEG;
|
|
71
73
|
};
|
|
72
|
-
|
|
73
74
|
$.atan2 = (y, x) => {
|
|
74
75
|
let a = Math.atan2(y, x);
|
|
75
76
|
return !angleMode ? a : a * RADTODEG;
|
|
@@ -93,6 +94,7 @@ Q5.modules.math = ($, q) => {
|
|
|
93
94
|
}
|
|
94
95
|
};
|
|
95
96
|
}
|
|
97
|
+
|
|
96
98
|
function shr3() {
|
|
97
99
|
let jsr, seed;
|
|
98
100
|
let m = 4294967295;
|
|
@@ -111,6 +113,7 @@ Q5.modules.math = ($, q) => {
|
|
|
111
113
|
}
|
|
112
114
|
};
|
|
113
115
|
}
|
|
116
|
+
|
|
114
117
|
let rng1 = shr3();
|
|
115
118
|
rng1.setSeed();
|
|
116
119
|
|
|
@@ -127,6 +130,7 @@ Q5.modules.math = ($, q) => {
|
|
|
127
130
|
return a[Math.trunc(a.length * rng1.rand())];
|
|
128
131
|
}
|
|
129
132
|
};
|
|
133
|
+
|
|
130
134
|
$.randomGenerator = (method) => {
|
|
131
135
|
if (method == $.LCG) rng1 = lcg();
|
|
132
136
|
else if (method == $.SHR3) rng1 = shr3();
|
|
@@ -282,13 +286,16 @@ Q5.modules.math = ($, q) => {
|
|
|
282
286
|
q.Noise = Q5[mode[0].toUpperCase() + mode.slice(1) + 'Noise'];
|
|
283
287
|
_noise = null;
|
|
284
288
|
};
|
|
289
|
+
|
|
285
290
|
$.noiseSeed = (seed) => {
|
|
286
291
|
_noise = new $.Noise(seed);
|
|
287
292
|
};
|
|
293
|
+
|
|
288
294
|
$.noise = (x = 0, y = 0, z = 0) => {
|
|
289
295
|
_noise ??= new $.Noise();
|
|
290
296
|
return _noise.noise(x, y, z);
|
|
291
297
|
};
|
|
298
|
+
|
|
292
299
|
$.noiseDetail = (lod, falloff) => {
|
|
293
300
|
_noise ??= new $.Noise();
|
|
294
301
|
if (lod > 0) _noise.octaves = lod;
|
package/src/q5-record.js
ADDED
package/src/q5-vector.js
CHANGED
|
@@ -11,15 +11,18 @@ Q5.Vector = class {
|
|
|
11
11
|
this._cn = null;
|
|
12
12
|
this._cnsq = null;
|
|
13
13
|
}
|
|
14
|
+
|
|
14
15
|
set(x, y, z) {
|
|
15
16
|
this.x = x?.x || x || 0;
|
|
16
17
|
this.y = x?.y || y || 0;
|
|
17
18
|
this.z = x?.z || z || 0;
|
|
18
19
|
return this;
|
|
19
20
|
}
|
|
21
|
+
|
|
20
22
|
copy() {
|
|
21
23
|
return new Q5.Vector(this.x, this.y, this.z);
|
|
22
24
|
}
|
|
25
|
+
|
|
23
26
|
_arg2v(x, y, z) {
|
|
24
27
|
if (x?.x !== undefined) return x;
|
|
25
28
|
if (y !== undefined) {
|
|
@@ -27,10 +30,12 @@ Q5.Vector = class {
|
|
|
27
30
|
}
|
|
28
31
|
return { x: x, y: x, z: x };
|
|
29
32
|
}
|
|
33
|
+
|
|
30
34
|
_calcNorm() {
|
|
31
35
|
this._cnsq = this.x * this.x + this.y * this.y + this.z * this.z;
|
|
32
36
|
this._cn = Math.sqrt(this._cnsq);
|
|
33
37
|
}
|
|
38
|
+
|
|
34
39
|
add() {
|
|
35
40
|
let u = this._arg2v(...arguments);
|
|
36
41
|
this.x += u.x;
|
|
@@ -38,6 +43,7 @@ Q5.Vector = class {
|
|
|
38
43
|
this.z += u.z;
|
|
39
44
|
return this;
|
|
40
45
|
}
|
|
46
|
+
|
|
41
47
|
rem() {
|
|
42
48
|
let u = this._arg2v(...arguments);
|
|
43
49
|
this.x %= u.x;
|
|
@@ -45,6 +51,7 @@ Q5.Vector = class {
|
|
|
45
51
|
this.z %= u.z;
|
|
46
52
|
return this;
|
|
47
53
|
}
|
|
54
|
+
|
|
48
55
|
sub() {
|
|
49
56
|
let u = this._arg2v(...arguments);
|
|
50
57
|
this.x -= u.x;
|
|
@@ -52,6 +59,7 @@ Q5.Vector = class {
|
|
|
52
59
|
this.z -= u.z;
|
|
53
60
|
return this;
|
|
54
61
|
}
|
|
62
|
+
|
|
55
63
|
mult() {
|
|
56
64
|
let u = this._arg2v(...arguments);
|
|
57
65
|
this.x *= u.x;
|
|
@@ -59,6 +67,7 @@ Q5.Vector = class {
|
|
|
59
67
|
this.z *= u.z;
|
|
60
68
|
return this;
|
|
61
69
|
}
|
|
70
|
+
|
|
62
71
|
div() {
|
|
63
72
|
let u = this._arg2v(...arguments);
|
|
64
73
|
if (u.x) this.x /= u.x;
|
|
@@ -69,18 +78,22 @@ Q5.Vector = class {
|
|
|
69
78
|
else this.z = 0;
|
|
70
79
|
return this;
|
|
71
80
|
}
|
|
81
|
+
|
|
72
82
|
mag() {
|
|
73
83
|
this._calcNorm();
|
|
74
84
|
return this._cn;
|
|
75
85
|
}
|
|
86
|
+
|
|
76
87
|
magSq() {
|
|
77
88
|
this._calcNorm();
|
|
78
89
|
return this._cnsq;
|
|
79
90
|
}
|
|
91
|
+
|
|
80
92
|
dot() {
|
|
81
93
|
let u = this._arg2v(...arguments);
|
|
82
94
|
return this.x * u.x + this.y * u.y + this.z * u.z;
|
|
83
95
|
}
|
|
96
|
+
|
|
84
97
|
dist() {
|
|
85
98
|
let u = this._arg2v(...arguments);
|
|
86
99
|
let x = this.x - u.x;
|
|
@@ -88,6 +101,7 @@ Q5.Vector = class {
|
|
|
88
101
|
let z = this.z - u.z;
|
|
89
102
|
return Math.sqrt(x * x + y * y + z * z);
|
|
90
103
|
}
|
|
104
|
+
|
|
91
105
|
cross() {
|
|
92
106
|
let u = this._arg2v(...arguments);
|
|
93
107
|
let x = this.y * u.z - this.z * u.y;
|
|
@@ -98,6 +112,7 @@ Q5.Vector = class {
|
|
|
98
112
|
this.z = z;
|
|
99
113
|
return this;
|
|
100
114
|
}
|
|
115
|
+
|
|
101
116
|
normalize() {
|
|
102
117
|
this._calcNorm();
|
|
103
118
|
let n = this._cn;
|
|
@@ -110,6 +125,7 @@ Q5.Vector = class {
|
|
|
110
125
|
this._cnsq = 1;
|
|
111
126
|
return this;
|
|
112
127
|
}
|
|
128
|
+
|
|
113
129
|
limit(m) {
|
|
114
130
|
this._calcNorm();
|
|
115
131
|
let n = this._cn;
|
|
@@ -123,6 +139,7 @@ Q5.Vector = class {
|
|
|
123
139
|
}
|
|
124
140
|
return this;
|
|
125
141
|
}
|
|
142
|
+
|
|
126
143
|
setMag(m) {
|
|
127
144
|
this._calcNorm();
|
|
128
145
|
let n = this._cn;
|
|
@@ -134,15 +151,18 @@ Q5.Vector = class {
|
|
|
134
151
|
this._cnsq = m * m;
|
|
135
152
|
return this;
|
|
136
153
|
}
|
|
154
|
+
|
|
137
155
|
heading() {
|
|
138
156
|
return this._$.atan2(this.y, this.x);
|
|
139
157
|
}
|
|
158
|
+
|
|
140
159
|
setHeading(ang) {
|
|
141
160
|
let mag = this.mag();
|
|
142
161
|
this.x = mag * this._$.cos(ang);
|
|
143
162
|
this.y = mag * this._$.sin(ang);
|
|
144
163
|
return this;
|
|
145
164
|
}
|
|
165
|
+
|
|
146
166
|
rotate(ang) {
|
|
147
167
|
let costh = this._$.cos(ang);
|
|
148
168
|
let sinth = this._$.sin(ang);
|
|
@@ -152,12 +172,14 @@ Q5.Vector = class {
|
|
|
152
172
|
this.y = vy;
|
|
153
173
|
return this;
|
|
154
174
|
}
|
|
175
|
+
|
|
155
176
|
angleBetween() {
|
|
156
177
|
let u = this._arg2v(...arguments);
|
|
157
178
|
let o = Q5.Vector.cross(this, u);
|
|
158
179
|
let ang = this._$.atan2(o.mag(), this.dot(u));
|
|
159
180
|
return ang * Math.sign(o.z || 1);
|
|
160
181
|
}
|
|
182
|
+
|
|
161
183
|
lerp() {
|
|
162
184
|
let args = [...arguments];
|
|
163
185
|
let amt = args.at(-1);
|
|
@@ -168,6 +190,7 @@ Q5.Vector = class {
|
|
|
168
190
|
this.z += (u.z - this.z) * amt;
|
|
169
191
|
return this;
|
|
170
192
|
}
|
|
193
|
+
|
|
171
194
|
slerp() {
|
|
172
195
|
let args = [...arguments];
|
|
173
196
|
let amt = args.at(-1);
|
|
@@ -206,17 +229,21 @@ Q5.Vector = class {
|
|
|
206
229
|
this.z = this.z * cosMultiplier + ey.z * sinMultiplier;
|
|
207
230
|
return this;
|
|
208
231
|
}
|
|
232
|
+
|
|
209
233
|
reflect(n) {
|
|
210
234
|
n.normalize();
|
|
211
235
|
return this.sub(n.mult(2 * this.dot(n)));
|
|
212
236
|
}
|
|
237
|
+
|
|
213
238
|
array() {
|
|
214
239
|
return [this.x, this.y, this.z];
|
|
215
240
|
}
|
|
241
|
+
|
|
216
242
|
equals(u, epsilon) {
|
|
217
243
|
epsilon ??= Number.EPSILON || 0;
|
|
218
244
|
return Math.abs(u.x - this.x) < epsilon && Math.abs(u.y - this.y) < epsilon && Math.abs(u.z - this.z) < epsilon;
|
|
219
245
|
}
|
|
246
|
+
|
|
220
247
|
fromAngle(th, l) {
|
|
221
248
|
if (l === undefined) l = 1;
|
|
222
249
|
this._cn = l;
|
|
@@ -226,6 +253,7 @@ Q5.Vector = class {
|
|
|
226
253
|
this.z = 0;
|
|
227
254
|
return this;
|
|
228
255
|
}
|
|
256
|
+
|
|
229
257
|
fromAngles(th, ph, l) {
|
|
230
258
|
if (l === undefined) l = 1;
|
|
231
259
|
this._cn = l;
|
|
@@ -239,18 +267,22 @@ Q5.Vector = class {
|
|
|
239
267
|
this.z = l * sinth * cosph;
|
|
240
268
|
return this;
|
|
241
269
|
}
|
|
270
|
+
|
|
242
271
|
random2D() {
|
|
243
272
|
this._cn = this._cnsq = 1;
|
|
244
273
|
return this.fromAngle(Math.random() * Math.PI * 2);
|
|
245
274
|
}
|
|
275
|
+
|
|
246
276
|
random3D() {
|
|
247
277
|
this._cn = this._cnsq = 1;
|
|
248
278
|
return this.fromAngles(Math.random() * Math.PI * 2, Math.random() * Math.PI * 2);
|
|
249
279
|
}
|
|
280
|
+
|
|
250
281
|
toString() {
|
|
251
282
|
return `[${this.x}, ${this.y}, ${this.z}]`;
|
|
252
283
|
}
|
|
253
284
|
};
|
|
285
|
+
|
|
254
286
|
Q5.Vector.add = (v, u) => v.copy().add(u);
|
|
255
287
|
Q5.Vector.cross = (v, u) => v.copy().cross(u);
|
|
256
288
|
Q5.Vector.dist = (v, u) => Math.hypot(v.x - u.x, v.y - u.y, v.z - u.z);
|
|
@@ -267,6 +299,7 @@ Q5.Vector.mult = (v, u) => v.copy().mult(u);
|
|
|
267
299
|
Q5.Vector.normalize = (v) => v.copy().normalize();
|
|
268
300
|
Q5.Vector.rem = (v, u) => v.copy().rem(u);
|
|
269
301
|
Q5.Vector.sub = (v, u) => v.copy().sub(u);
|
|
302
|
+
|
|
270
303
|
for (let k of ['fromAngle', 'fromAngles', 'random2D', 'random3D']) {
|
|
271
304
|
Q5.Vector[k] = (u, v, t) => new Q5.Vector()[k](u, v, t);
|
|
272
305
|
}
|
package/src/q5-webgpu-canvas.js
CHANGED
|
@@ -314,6 +314,7 @@ Q5.renderers.webgpu.canvas = ($, q) => {
|
|
|
314
314
|
if ($._matrixDirty) $._saveMatrix();
|
|
315
315
|
$._transformIndexStack.push($._transformIndex);
|
|
316
316
|
};
|
|
317
|
+
|
|
317
318
|
$.popMatrix = () => {
|
|
318
319
|
if (!$._transformIndexStack.length) {
|
|
319
320
|
return console.warn('Matrix index stack is empty!');
|
|
@@ -329,6 +330,7 @@ Q5.renderers.webgpu.canvas = ($, q) => {
|
|
|
329
330
|
$.pushMatrix();
|
|
330
331
|
$.pushStyles();
|
|
331
332
|
};
|
|
333
|
+
|
|
332
334
|
$.pop = () => {
|
|
333
335
|
$.popMatrix();
|
|
334
336
|
$.popStyles();
|
|
@@ -410,6 +412,7 @@ Q5.renderers.webgpu.canvas = ($, q) => {
|
|
|
410
412
|
}
|
|
411
413
|
|
|
412
414
|
$._blendMode = 'normal';
|
|
415
|
+
|
|
413
416
|
$.blendMode = (mode) => {
|
|
414
417
|
if (mode == $._blendMode) return;
|
|
415
418
|
if (mode == 'source-over') mode = 'normal';
|
package/src/q5-webgpu-text.js
CHANGED
|
@@ -114,6 +114,7 @@ fn fragmentMain(input : VertexOutput) -> @location(0) vec4f {
|
|
|
114
114
|
mipmapFilter: 'linear',
|
|
115
115
|
maxAnisotropy: 16
|
|
116
116
|
});
|
|
117
|
+
|
|
117
118
|
let fontBindGroupLayout = Q5.device.createBindGroupLayout({
|
|
118
119
|
label: 'MSDF font group layout',
|
|
119
120
|
entries: [
|
|
@@ -151,6 +152,7 @@ fn fragmentMain(input : VertexOutput) -> @location(0) vec4f {
|
|
|
151
152
|
primitive: { topology: 'triangle-strip', stripIndexFormat: 'uint32' },
|
|
152
153
|
multisample: { count: 4 }
|
|
153
154
|
};
|
|
155
|
+
|
|
154
156
|
$._pipelines[2] = Q5.device.createRenderPipeline($._pipelineConfigs[2]);
|
|
155
157
|
|
|
156
158
|
class MsdfFont {
|
|
@@ -299,6 +301,7 @@ fn fragmentMain(input : VertexOutput) -> @location(0) vec4f {
|
|
|
299
301
|
$.textFont = (fontName) => {
|
|
300
302
|
$._font = fonts[fontName];
|
|
301
303
|
};
|
|
304
|
+
|
|
302
305
|
$.textSize = (size) => {
|
|
303
306
|
$._textSize = size;
|
|
304
307
|
if (!leadingSet) {
|
|
@@ -306,12 +309,14 @@ fn fragmentMain(input : VertexOutput) -> @location(0) vec4f {
|
|
|
306
309
|
leadDiff = leading - size;
|
|
307
310
|
}
|
|
308
311
|
};
|
|
312
|
+
|
|
309
313
|
$.textLeading = (lineHeight) => {
|
|
310
314
|
$._font.lineHeight = leading = lineHeight;
|
|
311
315
|
leadDiff = leading - $._textSize;
|
|
312
316
|
leadPercent = leading / $._textSize;
|
|
313
317
|
leadingSet = true;
|
|
314
318
|
};
|
|
319
|
+
|
|
315
320
|
$.textAlign = (horiz, vert) => {
|
|
316
321
|
$._textAlign = horiz;
|
|
317
322
|
if (vert) $._textBaseline = vert;
|