q5play 4.2.3 → 4.3.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.
Files changed (4) hide show
  1. package/package.json +1 -1
  2. package/q5play.d.ts +12 -0
  3. package/q5play.js +129 -333
  4. package/q5play.pyi +12 -0
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "q5play",
3
- "version": "4.2.3",
3
+ "version": "4.3.0",
4
4
  "author": "quinton-ashley",
5
5
  "license": "SEE LICENSE IN LICENSE.md",
6
6
  "description": "A beginner friendly, web-based game engine that uses q5.js WebGPU for graphics and Box2D v3 WASM for physics.",
package/q5play.d.ts CHANGED
@@ -60,6 +60,18 @@ declare global {
60
60
  hasMouse: boolean;
61
61
  standardizeKeyboard: boolean;
62
62
 
63
+ /**
64
+ * Set to true to disable q5play's console logs, warnings, and error messages.
65
+ * Severe errors will still be thrown.
66
+ */
67
+ silent: boolean;
68
+
69
+ /**
70
+ * Set to true to disable q5play's console logs.
71
+ * Warnings and errors will still be shown, and severe errors will still be thrown.
72
+ */
73
+ quiet: boolean;
74
+
63
75
  /**
64
76
  * Displays the version of q5play being used,
65
77
  * the number of sprites being drawn
package/q5play.js CHANGED
@@ -12,15 +12,15 @@
12
12
  * |__/ |__/ \______/
13
13
  *
14
14
  * @package q5play
15
- * @version 4.2
15
+ * @version 4.3
16
16
  * @author quinton-ashley
17
17
  * @website https://q5play.org
18
18
  */
19
19
 
20
- let q5play_version = '4.2';
20
+ let q5play_version = '4.3';
21
21
 
22
22
  if (typeof globalThis.Q5 == 'undefined' && typeof globalThis.p5 == 'undefined') {
23
- console.error('q5play requires q5.js to be loaded first. Visit https://q5js.org to learn more.');
23
+ throw new Error('q5play requires q5.js to be loaded first. Visit https://q5js.org to learn more.');
24
24
  }
25
25
 
26
26
  let box2dPromise,
@@ -28,8 +28,9 @@ let box2dPromise,
28
28
 
29
29
  // called when a new instance of Q5 is created
30
30
  async function q5playPreSetup(q) {
31
- const $ = this,
32
- log = console.log;
31
+ const $ = this;
32
+
33
+ using_p5 = !$._q5;
33
34
 
34
35
  if (!box2dPromise) {
35
36
  box2dPromise = (async () => {
@@ -246,6 +247,8 @@ async function q5playPreSetup(q) {
246
247
  this.emojiScale = 1;
247
248
  this.os = {};
248
249
  this.context = 'web';
250
+ this.silent = false;
251
+ this.quiet = false;
249
252
 
250
253
  this.update = () => q5playUpdate.call($, q);
251
254
  this.draw = () => q5playPostDraw.call($, q);
@@ -365,23 +368,27 @@ async function q5playPreSetup(q) {
365
368
  $.q5play = new $.Q5Play();
366
369
  delete $.Q5Play;
367
370
 
368
- using_p5 = !$._q5;
369
- if (using_p5 && p5.VERSION[0] != 2) {
370
- throw new Error(`q5play requires q5.js or p5.js v2. Detected version: ${p5.VERSION}. Please upgrade.`);
371
- }
371
+ const log = (...args) => {
372
+ if (!$.q5play.quiet && !$.q5play.silent) console.log(...args);
373
+ };
374
+ const warn = (...args) => {
375
+ if (!$.q5play.silent) console.warn(...args);
376
+ };
377
+ const error = (...args) => {
378
+ if (!$.q5play.silent) console.error(...args);
379
+ };
372
380
 
373
381
  const DEGREES = $.DEGREES,
374
382
  DEGTORAD = Math.PI / 180,
375
383
  RADTODEG = 180 / Math.PI;
376
384
 
377
- // in q5play the default angle mode is degrees
385
+ // in q5play defaults
378
386
  $.angleMode(DEGREES);
379
-
380
- // in q5play the default color mode is float RGB
381
- if (!using_p5) $.colorMode($.RGB, 1);
382
-
383
- // in q5play the default image mode is center
384
- if (!using_p5) $.imageMode($.CENTER);
387
+ if (!using_p5) {
388
+ // set later in p5 compatibility mode
389
+ $.colorMode($.RGB, 1);
390
+ $.imageMode($.CENTER);
391
+ }
385
392
 
386
393
  const ZERO_VEC = new b2Vec2(0, 0),
387
394
  ZERO_ROT = b2MakeRot(0),
@@ -785,7 +792,7 @@ async function q5playPreSetup(q) {
785
792
  }
786
793
  if (args.length >= 2) {
787
794
  if (typeof spriteSheet == 'string') {
788
- spriteSheet = $.load(spriteSheet);
795
+ spriteSheet = $.loadImage(spriteSheet);
789
796
  }
790
797
  this.anis.spriteSheet = spriteSheet;
791
798
  }
@@ -813,7 +820,7 @@ async function q5playPreSetup(q) {
813
820
  ani = v._anis?.[name];
814
821
  }
815
822
  if (ani) ani = ani.clone();
816
- else return console.error('Ani not found: ' + name);
823
+ else return error('Ani not found: ' + name);
817
824
  }
818
825
  // reset to frame 0 of that animation
819
826
  if (this.resetAniOnChange) ani._frame = 0;
@@ -1092,30 +1099,6 @@ async function q5playPreSetup(q) {
1092
1099
  }
1093
1100
  });
1094
1101
 
1095
- if (using_p5) {
1096
- this._vel.direction = function () {
1097
- if (!this._directionCached) {
1098
- const x = this.x,
1099
- y = this.y;
1100
- if (x || y) this._direction = $.atan2(this.y, this.x);
1101
- else this._direction = 0;
1102
- this._directionCached = this._useCache;
1103
- }
1104
- return this._direction;
1105
- };
1106
-
1107
- this._vel.setDirection = function (ang) {
1108
- let mag = this.mag();
1109
- if (mag) {
1110
- this.x = mag * $.cos(ang);
1111
- this.y = mag * $.sin(ang);
1112
- }
1113
- this._direction = ang;
1114
- this._directionCached = this._useCache;
1115
- return this;
1116
- };
1117
- }
1118
-
1119
1102
  this._heading = 'right';
1120
1103
 
1121
1104
  if (group._layer) this.layer = group._layer;
@@ -1370,7 +1353,7 @@ async function q5playPreSetup(q) {
1370
1353
 
1371
1354
  addCollider(offsetX, offsetY, w, h) {
1372
1355
  if (this._deleted) {
1373
- console.error("Can't add colliders to a sprite that was deleted.");
1356
+ error("Can't add colliders to a sprite that was deleted.");
1374
1357
  return;
1375
1358
  }
1376
1359
 
@@ -1386,7 +1369,7 @@ async function q5playPreSetup(q) {
1386
1369
 
1387
1370
  addSensor(offsetX, offsetY, w, h) {
1388
1371
  if (this._deleted) {
1389
- console.error("Can't add sensors to a sprite that was deleted.");
1372
+ error("Can't add sensors to a sprite that was deleted.");
1390
1373
  return;
1391
1374
  }
1392
1375
 
@@ -1409,7 +1392,7 @@ async function q5playPreSetup(q) {
1409
1392
  _add(isSensor, a0, a1, a2, a3, a4) {
1410
1393
  if (this._shapes.length >= $.Sprite.maxColliders) {
1411
1394
  if (!this._warnedMaxColliders) {
1412
- console.warn(
1395
+ warn(
1413
1396
  `Sprite has ${this._shapes.length} colliders and sensors, which is greater than Sprite.maxColliders. Increasing the limit may cause performance issues.`
1414
1397
  );
1415
1398
  this._warnedMaxColliders = true;
@@ -2324,7 +2307,7 @@ async function q5playPreSetup(q) {
2324
2307
  set surfaceSpeed(val) {
2325
2308
  if (this.watch) this.mod[21] = true;
2326
2309
  if (this._hasCapsuleChain) {
2327
- return console.error('Can not set surfaceSpeed of a capsule chain.');
2310
+ return error('Can not set surfaceSpeed of a capsule chain.');
2328
2311
  }
2329
2312
  if (this._hasChain) this._chain.surfaceSpeed = val;
2330
2313
  for (let collider of this.colliders) {
@@ -2951,7 +2934,7 @@ async function q5playPreSetup(q) {
2951
2934
 
2952
2935
  attractTo(x, y, force) {
2953
2936
  if (this._phys != 0) {
2954
- console.error('attractTo can only be used on sprites with dynamic physics bodies');
2937
+ error('attractTo can only be used on sprites with dynamic physics bodies');
2955
2938
  return;
2956
2939
  }
2957
2940
  if (typeof x != 'number') {
@@ -2975,7 +2958,7 @@ async function q5playPreSetup(q) {
2975
2958
 
2976
2959
  repelFrom(x, y, force) {
2977
2960
  if (this._phys != 0) {
2978
- console.error('repelFrom can only be used on sprites with dynamic colliders');
2961
+ error('repelFrom can only be used on sprites with dynamic colliders');
2979
2962
  return;
2980
2963
  }
2981
2964
  if (typeof x != 'number') {
@@ -3830,7 +3813,7 @@ async function q5playPreSetup(q) {
3830
3813
  if (args[i] instanceof Q5.Image) this.push(args[i]);
3831
3814
  else if (using_p5) {
3832
3815
  throw new Error(
3833
- 'p5.js v2 does not support preloading or lazy loading images. You need to use `await load(url)`.'
3816
+ 'p5.js v2 does not support preloading or lazy loading images. You need to use `await loadImage(url)`.'
3834
3817
  );
3835
3818
  } else this.push($.loadImage(args[i]));
3836
3819
  }
@@ -4372,7 +4355,7 @@ async function q5playPreSetup(q) {
4372
4355
  }
4373
4356
  }
4374
4357
  if (!this.idNum) {
4375
- console.warn('ERROR: Surpassed the limit of 999 groups in memory. Delete groups to recycle group ids.');
4358
+ warn('ERROR: Surpassed the limit of 999 groups in memory. Delete groups to recycle group ids.');
4376
4359
  // if there are no empty slots, try to prevent a crash by
4377
4360
  // finding the first slot that has a group with no sprites in it
4378
4361
  for (let i = 1; i < $.q5play.groups.length; i++) {
@@ -5158,7 +5141,7 @@ async function q5playPreSetup(q) {
5158
5141
 
5159
5142
  splice(start, removalCount, ...sprites) {
5160
5143
  if (this.deleted) {
5161
- console.warn(
5144
+ warn(
5162
5145
  'Edited group' +
5163
5146
  this._uid +
5164
5147
  " that was deleted. Use `group.deleteAll()` to remove all of a group's sprites without deleting the group itself. Restoring the group to q5play's memory."
@@ -5170,11 +5153,11 @@ async function q5playPreSetup(q) {
5170
5153
  // filter out non-sprites and log a warning
5171
5154
  sprites = sprites.filter((s) => {
5172
5155
  if (!(s instanceof $.Sprite)) {
5173
- console.warn('Only sprites can be added to a group, skipping:', s);
5156
+ warn('Only sprites can be added to a group, skipping:', s);
5174
5157
  return false;
5175
5158
  }
5176
5159
  if (s.deleted) {
5177
- console.warn("Can't add a deleted sprite to a group, skipping:", s);
5160
+ warn("Can't add a deleted sprite to a group, skipping:", s);
5178
5161
  return false;
5179
5162
  }
5180
5163
  return true;
@@ -5629,7 +5612,7 @@ async function q5playPreSetup(q) {
5629
5612
  }
5630
5613
  set timeScale(val) {
5631
5614
  if (val < 0 || val > 2) {
5632
- return console.error('world.timeScale must be between 0 and 2');
5615
+ return error('world.timeScale must be between 0 and 2');
5633
5616
  }
5634
5617
  if (this._timeScale == val) return;
5635
5618
  this._timeScale = val;
@@ -6029,7 +6012,7 @@ async function q5playPreSetup(q) {
6029
6012
  }
6030
6013
  speed ??= 1;
6031
6014
  if (speed <= 0) {
6032
- console.warn('camera.moveTo: speed should be a positive number');
6015
+ warn('camera.moveTo: speed should be a positive number');
6033
6016
  return Promise.resolve(false);
6034
6017
  }
6035
6018
  let a = y - this.y;
@@ -7032,7 +7015,7 @@ async function q5playPreSetup(q) {
7032
7015
 
7033
7016
  // same code as img.trim() in q5.js
7034
7017
  let ctx = g.drawingContext;
7035
- let pd = g._pixelDensity || 1;
7018
+ let pd = g._pixelDensity || g._renderer?._pixelDensity || 1;
7036
7019
  let w = g.canvas.width;
7037
7020
  let h = g.canvas.height;
7038
7021
  let data = ctx.getImageData(0, 0, w, h).data;
@@ -7141,7 +7124,7 @@ async function q5playPreSetup(q) {
7141
7124
  }
7142
7125
  } else $.image(img, dx, dy, dw, dh);
7143
7126
  } else {
7144
- console.warn(
7127
+ warn(
7145
7128
  'q5play: "' +
7146
7129
  ani.name +
7147
7130
  '"' +
@@ -7244,60 +7227,19 @@ async function q5playPreSetup(q) {
7244
7227
  }
7245
7228
  }
7246
7229
 
7247
- // let userDisabledP5Errors = p5.disableFriendlyErrors;
7248
- // p5.disableFriendlyErrors = true;
7249
-
7250
7230
  let didCreateCanvas = false;
7251
7231
 
7252
- const _createCanvas = $.createCanvas;
7253
-
7254
- $.Canvas = $.createCanvas = function (w, h) {
7255
- let args = [...arguments];
7256
-
7257
- if (using_p5 && !didCreateCanvas && w == 100 && h == 100) return _createCanvas.call($, ...args);
7258
-
7259
- // prevent p5 v1 overriding the user's canvas with a new default canvas
7260
- if (didCreateCanvas && w == 100 && h == 100) return;
7261
-
7262
- if (typeof args[0] == 'string') {
7263
- if (args[0].includes(':')) {
7264
- let ratio = args[0].split(':'),
7265
- rW = Number(ratio[0]),
7266
- rH = Number(ratio[1]),
7267
- w = window.innerWidth,
7268
- h = window.innerWidth * (rH / rW);
7269
- if (h > window.innerHeight) {
7270
- w = window.innerHeight * (rW / rH);
7271
- h = window.innerHeight;
7272
- }
7273
- args[0] = Math.round(w);
7274
- args.splice(1, 0, Math.round(h));
7275
- } else {
7276
- args = [0, 0, ...args];
7277
- }
7278
- }
7279
- if (!args[0]) {
7280
- args[0] = window.innerWidth;
7281
- args[1] = window.innerHeight;
7282
- }
7283
- args[1] ??= args[0];
7284
- args[0] = Math.floor(args[0] / 2) * 2;
7285
- args[1] = Math.floor(args[1] / 2) * 2;
7286
- let rend = _createCanvas.call($, ...args);
7232
+ const q5playCanvas = (rend, args) => {
7287
7233
  $.ctx = $.drawingContext;
7288
7234
  let c = rend.canvas || rend;
7235
+
7289
7236
  if (using_p5) {
7290
- window.canvas = c;
7291
- if (rend.GPU) {
7292
- c.renderer = 'webgpu';
7293
- $._webgpu = true;
7294
- } else if (rend.GL) {
7295
- c.renderer = 'webgl';
7296
- $._webgl = true;
7297
- } else {
7298
- $._webgpu = $._webgpuFallback = true;
7299
- }
7237
+ if (rend.device) $._webgpu = true;
7238
+ else if (rend.GL) $._webgl = true;
7239
+ else if ($._specifiedRenderer) $._c2d = true;
7240
+ else $._webgpu = $._webgpuFallback = true;
7300
7241
  }
7242
+
7301
7243
  c.tabIndex = 0;
7302
7244
  c.w = args[0];
7303
7245
  c.h = args[1];
@@ -7347,7 +7289,6 @@ async function q5playPreSetup(q) {
7347
7289
  rs.y = -c.hh + 20;
7348
7290
  }
7349
7291
  }
7350
- // p5.disableFriendlyErrors = userDisabledP5Errors;
7351
7292
 
7352
7293
  let pointer = window.PointerEvent ? 'pointer' : 'mouse';
7353
7294
  c.addEventListener(pointer + 'down', onpointerdown);
@@ -7357,9 +7298,57 @@ async function q5playPreSetup(q) {
7357
7298
  }
7358
7299
 
7359
7300
  didCreateCanvas = true;
7301
+
7302
+ if (using_p5) p5._q5playCompat($);
7303
+
7360
7304
  return rend;
7361
7305
  };
7362
7306
 
7307
+ const _createCanvas = $.createCanvas;
7308
+
7309
+ $.Canvas = $.createCanvas = function (w, h) {
7310
+ let args = [...arguments];
7311
+
7312
+ if (using_p5 && !didCreateCanvas && w == 100 && h == 100) return _createCanvas.call($, ...args);
7313
+
7314
+ // prevent p5 v1 overriding the user's canvas with a new default canvas
7315
+ if (didCreateCanvas && w == 100 && h == 100) return;
7316
+
7317
+ if (typeof args[0] == 'string') {
7318
+ if (args[0].includes(':')) {
7319
+ let ratio = args[0].split(':'),
7320
+ rW = Number(ratio[0]),
7321
+ rH = Number(ratio[1]),
7322
+ w = window.innerWidth,
7323
+ h = window.innerWidth * (rH / rW);
7324
+ if (h > window.innerHeight) {
7325
+ w = window.innerHeight * (rW / rH);
7326
+ h = window.innerHeight;
7327
+ }
7328
+ args[0] = Math.round(w);
7329
+ args.splice(1, 0, Math.round(h));
7330
+ } else {
7331
+ args = [0, 0, ...args];
7332
+ }
7333
+ }
7334
+ if (!args[0]) {
7335
+ args[0] = window.innerWidth;
7336
+ args[1] = window.innerHeight;
7337
+ }
7338
+ args[1] ??= args[0];
7339
+ args[0] = Math.floor(args[0] / 2) * 2;
7340
+ args[1] = Math.floor(args[1] / 2) * 2;
7341
+
7342
+ let rend = _createCanvas.call($, ...args);
7343
+
7344
+ if (rend instanceof Promise) {
7345
+ return rend.then((r) => {
7346
+ return q5playCanvas(r, args);
7347
+ });
7348
+ }
7349
+ return q5playCanvas(rend, args);
7350
+ };
7351
+
7363
7352
  $.canvas = $.canvas; // for brython
7364
7353
 
7365
7354
  const _resizeCanvas = $.resizeCanvas;
@@ -7446,6 +7435,8 @@ async function q5playPreSetup(q) {
7446
7435
  constructor(func, errorNum, e) {
7447
7436
  super();
7448
7437
 
7438
+ if ($.q5play.silent) return;
7439
+
7449
7440
  if (typeof func != 'string') {
7450
7441
  e = errorNum;
7451
7442
  errorNum = func;
@@ -7620,15 +7611,14 @@ async function q5playPreSetup(q) {
7620
7611
  mx = $.mouseX,
7621
7612
  my = $.mouseY;
7622
7613
 
7623
- if (using_p5) {
7624
- if ($._webgpuFallback) {
7625
- mx -= $.halfWidth;
7626
- my -= $.halfHeight;
7627
- }
7614
+ if (using_p5 && ($._webgpuFallback || $._webgl)) {
7615
+ mx -= $.halfWidth;
7616
+ my -= $.halfHeight;
7628
7617
  }
7629
7618
 
7630
- m.x = mx / cam.zoom + cam.x;
7631
- m.y = my / cam.zoom + cam.y;
7619
+ // divide by camera zoom and add camera translation
7620
+ m.x = mx / cam.zoom + cam.__pos.x;
7621
+ m.y = my / cam.zoom + cam.__pos.y;
7632
7622
 
7633
7623
  if (m.scroll < 0) m.scroll = 0;
7634
7624
  if (m.scrollDelta.x == 0 && m.scrollDelta.y == 0) {
@@ -8433,7 +8423,7 @@ async function q5playPreSetup(q) {
8433
8423
  */
8434
8424
  _update() {
8435
8425
  for (let c of this) {
8436
- if (c.connected) c._update();
8426
+ if (c?.connected) c._update();
8437
8427
  }
8438
8428
  }
8439
8429
  };
@@ -8556,24 +8546,14 @@ async function q5playPreSetup(q) {
8556
8546
  debugYellow = $._q5 ? $.color(colorMax, colorMax, 0, colorMax * 0.9) : '#ff0e',
8557
8547
  debugYellowFill = $._q5 ? $.color(colorMax, colorMax, 0, colorMax * 0.1) : '#ff02';
8558
8548
 
8559
- if (using_p5) {
8560
- $._getFillIdx = () => $._renderer.states.fillColor;
8561
- $._setFillIdx = (v) => ($._renderer.states.fillColor = v);
8562
- $._getStrokeIdx = () => $._renderer.states.strokeColor;
8563
- $._setStrokeIdx = (v) => ($._renderer.states.strokeColor = v);
8564
- $._getStrokeWeight = () => [$._renderer.states.strokeWeight];
8565
- $._setStrokeWeight = (v) => $.strokeWeight(...v);
8566
- $._getImageMode = () => $._renderer.states.imageMode;
8567
- $._doFill = () => {};
8568
- $._doStroke = () => {};
8569
- } else if ($.canvas.c2d) {
8570
- // polyfill for q5 WebGPU high efficiency functions
8549
+ // polyfills for q5 WebGPU high efficiency style changing functions
8550
+ if ($._c2d || $._webgpuFallback) {
8571
8551
  $._getFillIdx = () => $._fill;
8572
8552
  $._setFillIdx = (v) => ($._fill = v);
8573
8553
  $._getStrokeIdx = () => $._stroke;
8574
8554
  $._setStrokeIdx = (v) => ($._stroke = v);
8575
8555
  $._getStrokeWeight = () => [$._strokeWeight];
8576
- $._setStrokeWeight = (v) => $.strokeWeight(...v);
8556
+ $._setStrokeWeight = (v) => ($.ctx.lineWidth = $._strokeWeight = v[0]);
8577
8557
  }
8578
8558
 
8579
8559
  $._q5playDraw = () => {
@@ -8589,8 +8569,12 @@ async function q5playPreSetup(q) {
8589
8569
 
8590
8570
  let swData = $._getStrokeWeight();
8591
8571
  let ogSW = [...swData];
8592
- for (let i = 0; i < swData.length; i++) {
8593
- swData[i] /= meterSize;
8572
+ // if using q5 or p5's P2D mode
8573
+ // (in p5's WebGL and WebGPU modes, stroke weight doesn't scale)
8574
+ if ($._q5 || $._c2d || $._webgpuFallback) {
8575
+ for (let i = 0; i < swData.length; i++) {
8576
+ swData[i] /= meterSize;
8577
+ }
8594
8578
  }
8595
8579
  $._setStrokeWeight(swData);
8596
8580
 
@@ -8751,8 +8735,11 @@ async function q5playPreSetup(q) {
8751
8735
  if (ta) $.textAlign(ta.horizontal, ta.vertical);
8752
8736
  };
8753
8737
 
8738
+ // p5 won't run the draw loop unless a draw function is defined
8739
+ if (using_p5) window.draw ??= () => {};
8740
+
8754
8741
  // prettier-ignore
8755
- let q5playGlobals = ['q5play','Box2D','DYN','DYNAMIC','STA','STATIC','KIN','KINEMATIC','Sprite','Group','allSprites','Ani','Anis','Visual','Visuals','Joint','GlueJoint','DistanceJoint','WheelJoint','HingeJoint','SliderJoint','GrabberJoint','world','camera','kb','keyboard','mouse','contro','contros','controllers','pointer','pointers','spriteArt','EmojiImage','getFPS','animation','parseTextureAtlas','delay'];
8742
+ let q5playGlobals = ['q5play','Box2D','Canvas','createCanvas','DYN','DYNAMIC','STA','STATIC','KIN','KINEMATIC','Sprite','Group','allSprites','Ani','Anis','Visual','Visuals','Joint','GlueJoint','DistanceJoint','WheelJoint','HingeJoint','SliderJoint','GrabberJoint','world','camera','kb','keyboard','mouse','contro','contros','controllers','pointer','pointers','spriteArt','EmojiImage','getFPS','animation','parseTextureAtlas','delay'];
8756
8743
 
8757
8744
  // manually propagate q5play stuff to the global window object
8758
8745
  if ($._isGlobal) {
@@ -8775,24 +8762,6 @@ function q5playPostSetup() {
8775
8762
 
8776
8763
  if ($._isGlobal && window.update) $.update = window.update;
8777
8764
 
8778
- if (using_p5) {
8779
- // p5 won't run the draw loop without a draw function defined
8780
- window.draw ??= () => {};
8781
-
8782
- $.loge = $.log;
8783
- $.log = console.log;
8784
- $.camera = $._camera;
8785
-
8786
- if ($._isGlobal) {
8787
- $.camera3D = window.camera;
8788
- for (let prop of ['log', 'loge', 'camera', 'camera3D']) {
8789
- Object.defineProperty(window, prop, {
8790
- value: $[prop]
8791
- });
8792
- }
8793
- }
8794
- }
8795
-
8796
8765
  $.update ??= $.clear;
8797
8766
 
8798
8767
  $._setupDone = true;
@@ -8802,11 +8771,6 @@ function q5playPostSetup() {
8802
8771
  function q5playUpdate() {
8803
8772
  const $ = this;
8804
8773
 
8805
- if (using_p5) {
8806
- $.q5play._preDrawFrameTime = performance.now();
8807
- $.resetMatrix();
8808
- }
8809
-
8810
8774
  $.q5play.spritesDrawn = 0;
8811
8775
 
8812
8776
  $.contros._update();
@@ -8949,10 +8913,6 @@ function q5playPostDraw() {
8949
8913
  else if ($.kb[k] > 0) $.kb[k]++;
8950
8914
  }
8951
8915
 
8952
- if (using_p5) {
8953
- $.q5play._postDrawFrameTime = performance.now();
8954
- $.q5play._fps = Math.round(1000 / ($.q5play._postDrawFrameTime - $.q5play._preDrawFrameTime)) || 1;
8955
- }
8956
8916
  $.q5play._inPostDraw = false;
8957
8917
  }
8958
8918
 
@@ -9158,180 +9118,16 @@ pressure -> es:presión
9158
9118
  };
9159
9119
  q5playClassLangs.Group += q5playClassLangs.Sprite;
9160
9120
 
9161
- if (typeof globalThis.Q5 == 'undefined') {
9162
- let upgrade = ' Consider upgrading to q5: https://q5js.org';
9163
- console.warn('p5.js v2 is not fully compatible with q5play.' + upgrade);
9164
-
9165
- p5.addHook = (hook, fn) => {
9166
- p5.registerAddon((p5, proto, lifecycles) => {
9167
- lifecycles[hook] = fn;
9168
- });
9169
- };
9170
-
9171
- // p5.js v2 compatibility layer
9172
- globalThis.Canvas = (...args) => {
9173
- return new Promise((resolve) => {
9174
- window.setup = async function () {
9175
- const $ = p5.instance;
9176
-
9177
- $.Canvas(...args);
9178
-
9179
- // q5play defaults
9180
- $.angleMode($.DEGREES);
9181
- $.colorMode($.RGB, 1);
9182
- $.imageMode($.CENTER);
9183
-
9184
- $.halfWidth = width / 2;
9185
- $.halfHeight = height / 2;
9186
- $.jit = (v) => $.random(-v, v);
9187
-
9188
- $._loaders = [];
9189
- $._colorFormat = 1;
9190
-
9191
- const imgRegex = /(jpe?g|png|gif|webp|avif|svg)/i,
9192
- fontRegex = /(ttf|otf|woff2?|eot|json)/i,
9193
- fontCategoryRegex = /(serif|sans-serif|monospace|cursive|fantasy)/i,
9194
- audioRegex = /(wav|flac|mp3|ogg|m4a|aac|aiff|weba)/i;
9195
-
9196
- $.load = function (...urls) {
9197
- if (Array.isArray(urls[0])) urls = urls[0];
9198
-
9199
- let promises = [];
9200
-
9201
- for (let url of urls) {
9202
- let ext = url.split('.').pop().toLowerCase();
9203
-
9204
- let obj;
9205
- if (ext == 'json') {
9206
- if (url.includes('-msdf.')) {
9207
- throw new Error('p5.js v2 can not load MSDF fonts.' + upgrade);
9208
- }
9209
- obj = $.loadJSON(url);
9210
- } else if (ext == 'csv') {
9211
- obj = $.loadCSV(url);
9212
- } else if (imgRegex.test(ext)) {
9213
- obj = $.loadImage(url);
9214
- } else if (fontRegex.test(ext) || fontCategoryRegex.test(url)) {
9215
- obj = $.loadFont(url);
9216
- } else if (audioRegex.test(ext)) {
9217
- obj = $.loadSound(url);
9218
- } else if (ext == 'xml') {
9219
- obj = $.loadXML(url);
9220
- } else {
9221
- obj = $.loadText(url);
9222
- }
9223
- promises.push(obj);
9224
- }
9225
-
9226
- if (urls.length == 1) return promises[0];
9227
- return Promise.all(promises);
9228
- };
9229
-
9230
- if ($._webgpuFallback) {
9231
- $.opacity = function (v) {
9232
- $.ctx.globalAlpha = v;
9233
- };
9234
- }
9235
-
9236
- $.pushMatrix = $.push;
9237
- $.popMatrix = $.pop;
9238
-
9239
- $.loadAll = function () {
9240
- console.error('p5.js v2 does not have loadAll().' + upgrade);
9241
- };
9242
-
9243
- $.displayMode = () => {
9244
- console.error('p5.js v2 does not have displayMode().' + upgrade);
9245
- };
9246
-
9247
- $.MAXED = 'maxed';
9248
- $.SMOOTH = 'smooth';
9249
- $.PIXELATED = 'pixelated';
9250
-
9251
- if ($._isGlobal) {
9252
- let props = [
9253
- 'halfWidth',
9254
- 'halfHeight',
9255
- 'jit',
9256
- 'load',
9257
- 'opacity',
9258
- 'pushMatrix',
9259
- 'popMatrix',
9260
- 'loadAll',
9261
- 'displayMode',
9262
- 'MAXED',
9263
- 'PIXELATED'
9264
- ];
9265
- for (let p of props) {
9266
- window[p] = $[p];
9267
- }
9268
- }
9269
-
9270
- if ($._webgpuFallback) {
9271
- const _resetMatrix = $.resetMatrix;
9272
- $.resetMatrix = () => {
9273
- _resetMatrix.call($);
9274
- // sets origin to the center of the canvas
9275
- $.translate($.halfWidth, $.halfHeight);
9276
- };
9277
- }
9278
-
9279
- Object.defineProperty(p5, 'lang', {
9280
- set() {
9281
- console.error('p5.js v2 does not support changing language.' + upgrade);
9282
- },
9283
- get() {
9284
- return 'en';
9285
- },
9286
- configurable: true
9287
- });
9288
-
9289
- const entryPoints = [
9290
- 'setup',
9291
- 'update',
9292
- 'draw',
9293
- 'deviceMoved',
9294
- 'deviceTurned',
9295
- 'deviceShaken',
9296
- 'doubleClicked',
9297
- 'mousePressed',
9298
- 'mouseReleased',
9299
- 'mouseMoved',
9300
- 'mouseDragged',
9301
- 'mouseClicked',
9302
- 'mouseWheel',
9303
- 'touchStarted',
9304
- 'touchMoved',
9305
- 'touchEnded',
9306
- 'keyPressed',
9307
- 'keyReleased',
9308
- 'keyTyped',
9309
- 'windowResized'
9310
- ];
9311
-
9312
- for (let ep of entryPoints) {
9313
- Object.defineProperty(p5, ep, {
9314
- set(fn) {
9315
- $[ep] = fn;
9316
- if ($._isGlobal) window[ep] = fn;
9317
- },
9318
- get() {
9319
- return $[ep];
9320
- },
9321
- configurable: true
9322
- });
9323
- }
9324
-
9325
- resolve();
9326
- };
9327
- });
9328
- };
9329
-
9330
- globalThis.Q5 = globalThis.q5 = p5;
9331
- }
9121
+ globalThis.Canvas ??= () => {
9122
+ p5._friendlyError(`Visit https://github.com/q5play/p5-compat to learn how to use q5play with p5.js`);
9123
+ throw new Error();
9124
+ };
9332
9125
 
9333
- Q5.addHook('presetup', q5playPreSetup);
9334
- Q5.addHook('postsetup', q5playPostSetup);
9335
- Q5.addHook('predraw', q5playUpdate);
9336
- Q5.addHook('postdraw', q5playPostDraw);
9337
- Q5.addHook('remove', q5playRemove);
9126
+ (p5 || Q5).registerAddon((_, __, l) => {
9127
+ // add lifecycle hooks for q5play
9128
+ l.presetup = q5playPreSetup;
9129
+ l.postsetup = q5playPostSetup;
9130
+ l.predraw = q5playUpdate;
9131
+ l.postdraw = q5playPostDraw;
9132
+ l.remove = q5playRemove;
9133
+ });
package/q5play.pyi CHANGED
@@ -60,6 +60,18 @@ class Q5Play:
60
60
 
61
61
  standardizeKeyboard: bool
62
62
 
63
+ silent: bool
64
+ """
65
+ Set to true to disable q5play's console logs, warnings, and error messages.
66
+ Severe errors will still be thrown.
67
+ """
68
+
69
+ quiet: bool
70
+ """
71
+ Set to true to disable q5play's console logs.
72
+ Warnings and errors will still be shown, and severe errors will still be thrown.
73
+ """
74
+
63
75
  renderStats: bool
64
76
  """
65
77
  Displays the version of q5play being used,