Skip to content

Commit

Permalink
1.9.6
Browse files Browse the repository at this point in the history
  • Loading branch information
quinton-ashley committed Jan 29, 2024
1 parent 549812a commit 9ca7865
Show file tree
Hide file tree
Showing 4 changed files with 69 additions and 78 deletions.
12 changes: 6 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -181,9 +181,9 @@ Thanks in large part to @LingDong-'s design, q5 is well organized, concise, and

Features added by @quinton-ashley:

- `opacity`: set the opacity multiplier for anything subsequently drawn to the canvas. Range between 0 and 1.
- `textCache(true)`: Text image caching is enabled by default. Rotated text is only rendered once, and then cached as an image. This can result in ridiculously high 90x performance boosts for text-heavy sketches. Users don't need to change their code, the `text` function can be used as normal, q5 takes care of everything behind the scenes.
- `loadSound()`: Basic sound support in q5.js, returns a Web Audio object with `setVolume()` and `setLoop()` functions added. Not as powerful as p5.sound, but it's good enough in many cases.
- `opacity(globalAlpha)`: set the opacity multiplier for anything subsequently drawn to the canvas in a range between 0 (transparent) and 1 (opaque).
- `textCache(enabled)`: Text image caching is enabled by default. Rotated text is only rendered once, and then cached as an image. This can result in ridiculously high 90x performance boosts for text-heavy sketches. Users don't need to change their code, the `text` function can be used as normal, q5 takes care of everything behind the scenes.
- `loadSound(file)`: Basic sound support in q5.js, returns a Web Audio object with `setVolume()` and `setLoop()` functions added. Not as powerful as p5.sound, but it's good enough in many cases.
- `ctx`: an alias for `drawingContext`

Features added by @LingDong-:
Expand Down Expand Up @@ -220,9 +220,9 @@ The following benchmarks are generated with Google Chrome 120, on a MacBook Air

Less time (milliseconds) is better.

| Task | p5.js | q5.js |
| -------------------------------------------------- | ----- | ----- |
| Generate 100,000 random colors with `color(r,g,b)` | 168ms | 12ms |
| Task | p5.js | q5.js |
| ------------------------------------------------- | ----- | ----- |
| Generate 10,000 random colors with `color(r,g,b)` | 33ms | 3ms |

## Older Benchmarks

Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"author": "quinton-ashley",
"name": "q5",
"version": "1.9.5",
"version": "1.9.6",
"description": "An implementation of the p5.js 2D API that's smaller and faster",
"main": "q5.js",
"scripts": {
Expand Down
131 changes: 61 additions & 70 deletions q5.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
* @type {Q5}
*/
function Q5(scope, parent) {
let $ = this;
let preloadCnt = 0;
if (!scope) {
scope = 'global';
Expand All @@ -19,11 +20,10 @@ function Q5(scope, parent) {
if (!(window.setup || window.draw)) return;
else scope = 'global';
}
if (scope == 'global') Q5._hasGlobal = true;
if (scope == 'global') Q5._hasGlobal = $._isGlobal = true;

// CANVAS

let $ = this;
if (scope == 'image' || scope == 'graphics') {
$.canvas = new OffscreenCanvas(100, 100);
} else {
Expand All @@ -34,7 +34,6 @@ function Q5(scope, parent) {

$.canvas.width = $.width = 100;
$.canvas.height = $.height = 100;
$._windowResizedFn = () => {};

if (scope != 'graphics' && scope != 'image') {
$._setupDone = false;
Expand Down Expand Up @@ -677,14 +676,23 @@ function Q5(scope, parent) {
return c;
}

$.resizeCanvas = (w, h) => {
function _resizeCanvas(w, h) {
$.width = w;
$.height = h;
let c = cloneCtx();
$.canvas.width = w * $._pixelDensity;
$.canvas.height = h * $._pixelDensity;
$.canvas.width = Math.ceil(w * $._pixelDensity);
$.canvas.height = Math.ceil(h * $._pixelDensity);
if (!$.canvas.fullscreen && $.canvas.style) {
$.canvas.style.width = w + 'px';
$.canvas.style.height = h + 'px';
}
for (let prop in c) $.ctx[prop] = c[prop];
if (scope != 'image') $.pixelDensity($._pixelDensity);
ctx.scale($._pixelDensity, $._pixelDensity);
}

$.resizeCanvas = (w, h) => {
if (w == $.width && h == $.height) return;
_resizeCanvas(w, h);
};

$.createGraphics = function (w, h) {
Expand All @@ -697,19 +705,11 @@ function Q5(scope, parent) {
};

$.displayDensity = () => window.devicePixelRatio;
$.pixelDensity = (n) => {
if (n === undefined) return $._pixelDensity;
$._pixelDensity = n;

let c = cloneCtx();
$.canvas.width = Math.ceil($.width * n);
$.canvas.height = Math.ceil($.height * n);
$.canvas.style.width = $.width + 'px';
$.canvas.style.height = $.height + 'px';
for (let prop in c) $.ctx[prop] = c[prop];

ctx.scale($._pixelDensity, $._pixelDensity);
return $._pixelDensity;
$.pixelDensity = (v) => {
if (!v || v == $._pixelDensity) return $._pixelDensity;
$._pixelDensity = v;
_resizeCanvas($.width, $.height);
return v;
};

// MATH
Expand Down Expand Up @@ -1943,14 +1943,14 @@ function Q5(scope, parent) {
$._frameRate = 1000 / $.deltaTime;
$.frameCount++;
if ($._shouldResize) {
$._windowResizedFn();
$.windowResized();
$._shouldResize = false;
}
for (let m of Q5.prototype._methods.pre) m.call($);
clearBuff();
firstVertex = true;
ctx.save();
$._drawFn();
$.draw();
for (let m of Q5.prototype._methods.post) m.call($);
ctx.restore();
$.resetMatrix();
Expand Down Expand Up @@ -1999,22 +1999,22 @@ function Q5(scope, parent) {
$._updateMouse(e);
$.mouseIsPressed = true;
$.mouseButton = [$.LEFT, $.CENTER, $.RIGHT][e.button];
$._mousePressedFn(e);
$.mousePressed(e);
};
$._onmousemove = (e) => {
$._updateMouse(e);
if ($.mouseIsPressed) $._mouseDraggedFn(e);
else $._mouseMovedFn(e);
if ($.mouseIsPressed) $.mouseDragged(e);
else $.mouseMoved(e);
};
$._onmouseup = (e) => {
$._updateMouse(e);
$.mouseIsPressed = false;
$._mouseReleasedFn(e);
$.mouseReleased(e);
};
$._onclick = (e) => {
$._updateMouse(e);
$.mouseIsPressed = true;
$._mouseClickedFn(e);
$.mouseClicked(e);
$.mouseIsPressed = false;
};
$.cursor = (name, x, y) => {
Expand All @@ -2038,17 +2038,17 @@ function Q5(scope, parent) {
$.key = e.key;
$.keyCode = e.keyCode;
keysHeld[$.keyCode] = true;
$._keyPressedFn(e);
$.keyPressed(e);
if (e.key.length == 1) {
$._keyTypedFn(e);
$.keyTyped(e);
}
};
$._onkeyup = (e) => {
$.keyIsPressed = false;
$.key = e.key;
$.keyCode = e.keyCode;
keysHeld[$.keyCode] = false;
$._keyReleasedFn(e);
$.keyReleased(e);
};

$.canvas.onmousedown = (e) => $._onmousedown(e);
Expand All @@ -2066,36 +2066,33 @@ function Q5(scope, parent) {
id: touch.identifier
};
}
function isTouchUnaware() {
return $._touchStartedFn.isPlaceHolder && $._touchMovedFn.isPlaceHolder && $._touchEndedFn.isPlaceHolder;
}
$._ontouchstart = (e) => {
$.touches = [...e.touches].map(getTouchInfo);
if (isTouchUnaware()) {
if (!$._isTouchAware) {
$.mouseX = $.touches[0].x;
$.mouseY = $.touches[0].y;
$.mouseIsPressed = true;
$.mouseButton = $.LEFT;
if (!$._mousePressedFn(e)) e.preventDefault();
if (!$.mousePressed(e)) e.preventDefault();
}
if (!$._touchStartedFn(e)) e.preventDefault();
if (!$.touchStarted(e)) e.preventDefault();
};
$._ontouchmove = (e) => {
$.touches = [...e.touches].map(getTouchInfo);
if (isTouchUnaware()) {
if (!$._isTouchAware) {
$.mouseX = $.touches[0].x;
$.mouseY = $.touches[0].y;
if (!$._mouseDraggedFn(e)) e.preventDefault();
if (!$.mouseDragged(e)) e.preventDefault();
}
if (!$._touchMovedFn(e)) e.preventDefault();
if (!$.touchMoved(e)) e.preventDefault();
};
$._ontouchend = (e) => {
$.touches = [...e.touches].map(getTouchInfo);
if (isTouchUnaware() && !$.touches.length) {
if (!$._isTouchAware && !$.touches.length) {
$.mouseIsPressed = false;
if (!$._mouseReleasedFn(e)) e.preventDefault();
if (!$.mouseReleased(e)) e.preventDefault();
}
if (!$._touchEndedFn(e)) e.preventDefault();
if (!$.touchEnded(e)) e.preventDefault();
};
$.canvas.ontouchstart = (e) => $._ontouchstart(e);
$.canvas.ontouchmove = (e) => $._ontouchmove(e);
Expand Down Expand Up @@ -2250,8 +2247,10 @@ function Q5(scope, parent) {

if (typeof scope == 'function') scope($);

if (scope == 'graphics' || scope == 'image') return;

function _init() {
let o = scope == 'global' ? window : $;
let t = scope == 'global' ? window : $;
let eventNames = [
'setup',
'draw',
Expand All @@ -2270,38 +2269,30 @@ function Q5(scope, parent) {
'windowResized'
];
for (let k of eventNames) {
let intern = '_' + k + 'Fn';
$[intern] = () => {};
$[intern].isPlaceHolder = true;
if (o[k]) {
$[intern] = o[k];
} else {
Object.defineProperty($, k, {
set: (fun) => {
$[intern] = fun;
}
});
}
if (!t[k]) $[k] = () => {};
else if ($._isGlobal) $[k] = t[k];
}

if (scope != 'graphics' || scope != 'image') {
$._preloadFn();
millisStart = performance.now();
function _start() {
if (preloadCnt > 0) return requestAnimationFrame(_start);
$._setupFn();
if (!ctx) $.createCanvas(100, 100);
$._setupDone = true;
ctx.restore();
$.resetMatrix();
requestAnimationFrame(_draw);
}
_start();
}
$._isTouchAware = $.touchStarted || $.touchMoved || $.mouseReleased;

addEventListener('mousemove', (e) => $._onmousemove(e), false);
addEventListener('keydown', (e) => $._onkeydown(e), false);
addEventListener('keyup', (e) => $._onkeyup(e), false);

$.preload();
millisStart = performance.now();
function _start() {
if (preloadCnt > 0) return requestAnimationFrame(_start);
$.setup();
if (!ctx) $.createCanvas(100, 100);
$._setupDone = true;
ctx.restore();
$.resetMatrix();
requestAnimationFrame(_draw);
}
_start();
}

if (scope == 'global') _init();
else requestAnimationFrame(_init);
}
Expand Down Expand Up @@ -2627,8 +2618,8 @@ for (let k of ['fromAngle', 'fromAngles', 'random2D', 'random3D']) {
class _Q5Image extends Q5 {
constructor(w, h) {
super('image');
this.createCanvas(w, h);
delete this.createCanvas;
this._createCanvas(w, h);
this._loop = false;
}
get w() {
Expand Down
2 changes: 1 addition & 1 deletion q5.min.js

Large diffs are not rendered by default.

0 comments on commit 9ca7865

Please sign in to comment.