From dd458c0a72a79e9d6c467cc3d8d2ebd4c581572d Mon Sep 17 00:00:00 2001 From: Vaivaswat Date: Fri, 17 Jan 2025 15:25:53 +0530 Subject: [PATCH 1/5] changed keyboard.js and added the updated objects in costants.js file --- src/core/constants.js | 72 ++++++++++++++++++++++++------------------ src/events/keyboard.js | 7 ++-- 2 files changed, 46 insertions(+), 33 deletions(-) diff --git a/src/core/constants.js b/src/core/constants.js index 0885ab3e48..36d1533c27 100644 --- a/src/core/constants.js +++ b/src/core/constants.js @@ -879,92 +879,104 @@ export const MITER = 'miter'; * @final */ export const AUTO = 'auto'; - +// INPUT /** - * @typedef {18} ALT + * @typedef {'AltLeft' | 'AltRight'} ALT * @property {ALT} ALT * @final */ -// INPUT -export const ALT = 18; +export const ALT = 'AltLeft'; + /** - * @typedef {8} BACKSPACE + * @typedef {'Backspace'} BACKSPACE * @property {BACKSPACE} BACKSPACE * @final */ -export const BACKSPACE = 8; +export const BACKSPACE = 'Backspace'; + /** - * @typedef {17} CONTROL + * @typedef {'ControlLeft' | 'ControlRight'} CONTROL * @property {CONTROL} CONTROL * @final */ -export const CONTROL = 17; +export const CONTROL = 'ControlLeft'; + /** - * @typedef {46} DELETE + * @typedef {'Delete'} DELETE * @property {DELETE} DELETE * @final */ -export const DELETE = 46; +export const DELETE = 'Delete'; + /** - * @typedef {40} DOWN_ARROW + * @typedef {'ArrowDown'} DOWN_ARROW * @property {DOWN_ARROW} DOWN_ARROW * @final */ -export const DOWN_ARROW = 40; +export const DOWN_ARROW = 'ArrowDown'; + /** - * @typedef {13} ENTER + * @typedef {'Enter'} ENTER * @property {ENTER} ENTER * @final */ -export const ENTER = 13; +export const ENTER = 'Enter'; + /** - * @typedef {27} ESCAPE + * @typedef {'Escape'} ESCAPE * @property {ESCAPE} ESCAPE * @final */ -export const ESCAPE = 27; +export const ESCAPE = 'Escape'; + /** - * @typedef {37} LEFT_ARROW + * @typedef {'ArrowLeft'} LEFT_ARROW * @property {LEFT_ARROW} LEFT_ARROW * @final */ -export const LEFT_ARROW = 37; +export const LEFT_ARROW = 'ArrowLeft'; + /** - * @typedef {18} OPTION + * @typedef {'AltLeft' | 'AltRight'} OPTION * @property {OPTION} OPTION * @final */ -export const OPTION = 18; +export const OPTION = 'AltLeft'; + /** - * @typedef {13} RETURN + * @typedef {'Enter'} RETURN * @property {RETURN} RETURN * @final */ -export const RETURN = 13; +export const RETURN = 'Enter'; + /** - * @typedef {39} RIGHT_ARROW + * @typedef {'ArrowRight'} RIGHT_ARROW * @property {RIGHT_ARROW} RIGHT_ARROW * @final */ -export const RIGHT_ARROW = 39; +export const RIGHT_ARROW = 'ArrowRight'; + /** - * @typedef {16} SHIFT + * @typedef {'ShiftLeft' | 'ShiftRight'} SHIFT * @property {SHIFT} SHIFT * @final */ -export const SHIFT = 16; +export const SHIFT = 'ShiftLeft'; + /** - * @typedef {9} TAB + * @typedef {'Tab'} TAB * @property {TAB} TAB * @final */ -export const TAB = 9; +export const TAB = 'Tab'; + /** - * @typedef {38} UP_ARROW + * @typedef {'ArrowUp'} UP_ARROW * @property {UP_ARROW} UP_ARROW * @final */ -export const UP_ARROW = 38; +export const UP_ARROW = 'ArrowUp'; // RENDERING /** diff --git a/src/events/keyboard.js b/src/events/keyboard.js index 5b0de949ed..761a583744 100644 --- a/src/events/keyboard.js +++ b/src/events/keyboard.js @@ -440,15 +440,16 @@ function keyboard(p5, fn){ * */ fn._onkeydown = function(e) { - if (this._downKeys[e.which]) { + if (this._downKeys[e.code]) { // prevent multiple firings return; } this.isKeyPressed = true; this.keyIsPressed = true; this.keyCode = e.which; - this._downKeys[e.which] = true; - this.key = e.key || String.fromCharCode(e.which) || e.which; + this._code = e.code; + this.key = e.key; + this._downKeys[e.code] = true; const context = this._isGlobal ? window : this; if (typeof context.keyPressed === 'function' && !e.charCode) { const executeDefault = context.keyPressed(e); From bcbed0f83e67a725b9ece1f2ce0ed18c1d8a140b Mon Sep 17 00:00:00 2001 From: Vaivaswat Date: Sat, 18 Jan 2025 00:25:35 +0530 Subject: [PATCH 2/5] fixed the repeat key issue in onkeyup --- src/events/keyboard.js | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/src/events/keyboard.js b/src/events/keyboard.js index 761a583744..8391a674b5 100644 --- a/src/events/keyboard.js +++ b/src/events/keyboard.js @@ -97,6 +97,8 @@ function keyboard(p5, fn){ */ fn.isKeyPressed = false; fn.keyIsPressed = false; // khan + fn._code = null; + fn.key = ''; /** * A `String` system variable that contains the value of the last key typed. @@ -440,14 +442,14 @@ function keyboard(p5, fn){ * */ fn._onkeydown = function(e) { + this._code = e.code; + // Check for repeat key events if (this._downKeys[e.code]) { - // prevent multiple firings return; } this.isKeyPressed = true; this.keyIsPressed = true; this.keyCode = e.which; - this._code = e.code; this.key = e.key; this._downKeys[e.code] = true; const context = this._isGlobal ? window : this; @@ -615,18 +617,19 @@ function keyboard(p5, fn){ * */ fn._onkeyup = function(e) { - this._downKeys[e.which] = false; + delete this._downKeys[e.code]; - if (!this._areDownKeys()) { + if (Object.keys(this._downKeys).length === 0) { this.isKeyPressed = false; this.keyIsPressed = false; + this.key = ''; + this._code = null; + } else { + // If other keys are still pressed, update code to the last pressed key + const lastPressedKey = Object.keys(this._downKeys).pop(); + this._code = lastPressedKey; } - this._lastKeyCodeTyped = null; - - this.key = e.key || String.fromCharCode(e.which) || e.which; - this.keyCode = e.which; - const context = this._isGlobal ? window : this; if (typeof context.keyReleased === 'function') { const executeDefault = context.keyReleased(e); From c42bb7e64a5c1cbdac47a3cb284cc2701f5c0785 Mon Sep 17 00:00:00 2001 From: Vaivaswat Date: Sat, 18 Jan 2025 23:46:40 +0530 Subject: [PATCH 3/5] updated keyIsDown() to work with characters as arguments --- src/events/keyboard.js | 29 +++++++++++++++++++++++++---- 1 file changed, 25 insertions(+), 4 deletions(-) diff --git a/src/events/keyboard.js b/src/events/keyboard.js index 8391a674b5..cfb2102f70 100644 --- a/src/events/keyboard.js +++ b/src/events/keyboard.js @@ -906,11 +906,32 @@ function keyboard(p5, fn){ * * */ - fn.keyIsDown = function(code) { - // p5._validateParameters('keyIsDown', arguments); - return this._downKeys[code] || false; + p5.prototype.keyIsDown = function(code) { + console.log('Current _downKeys:', this._downKeys); + console.log('Current key:', this.key); + + // For backward compatibility - if code is a number + if (typeof code === 'number') { + return this._downKeys[code] || false; + } + + // For string inputs (new functionality) + if (typeof code === 'string') { + // Handle single character inputs + if (code.length === 1) { + if (/[A-Za-z]/.test(code)) { + // For letters, we need to check the actual key value + return this.key === code; + } else if (/[0-9]/.test(code)) { + return this._downKeys[`Digit${code}`] || false; + } + } + // Handle direct code inputs (e.g., 'KeyA', 'ArrowLeft', etc.) + return this._downKeys[code] || false; + } + + return false; }; - /** * The _areDownKeys function returns a boolean true if any keys pressed * and a false if no keys are currently pressed. From 5709aac6ab427809b8f1359669fd8fecaac603ea Mon Sep 17 00:00:00 2001 From: Vaivaswat Date: Thu, 23 Jan 2025 21:58:36 +0530 Subject: [PATCH 4/5] fixed dillema of code/key and added isCode() --- src/core/main.js | 1 + src/events/keyboard.js | 57 +++++++++++++++++++----------------------- 2 files changed, 27 insertions(+), 31 deletions(-) diff --git a/src/core/main.js b/src/core/main.js index df5ef37367..125aedb835 100644 --- a/src/core/main.js +++ b/src/core/main.js @@ -418,6 +418,7 @@ class p5 { this._styles = []; this._downKeys = {}; //Holds the key codes of currently pressed keys + this._downKeyCodes = {}; } } diff --git a/src/events/keyboard.js b/src/events/keyboard.js index cfb2102f70..14698167ed 100644 --- a/src/events/keyboard.js +++ b/src/events/keyboard.js @@ -97,8 +97,7 @@ function keyboard(p5, fn){ */ fn.isKeyPressed = false; fn.keyIsPressed = false; // khan - fn._code = null; - fn.key = ''; + fn.code = null; /** * A `String` system variable that contains the value of the last key typed. @@ -442,8 +441,6 @@ function keyboard(p5, fn){ * */ fn._onkeydown = function(e) { - this._code = e.code; - // Check for repeat key events if (this._downKeys[e.code]) { return; } @@ -451,7 +448,9 @@ function keyboard(p5, fn){ this.keyIsPressed = true; this.keyCode = e.which; this.key = e.key; - this._downKeys[e.code] = true; + this.code = e.code; + this._downKeyCodes[e.code] = true; + this._downKeys[e.key] = true; const context = this._isGlobal ? window : this; if (typeof context.keyPressed === 'function' && !e.charCode) { const executeDefault = context.keyPressed(e); @@ -617,17 +616,18 @@ function keyboard(p5, fn){ * */ fn._onkeyup = function(e) { - delete this._downKeys[e.code]; + delete this._downKeyCodes[e.code]; + delete this._downKeys[e.key]; if (Object.keys(this._downKeys).length === 0) { this.isKeyPressed = false; this.keyIsPressed = false; this.key = ''; - this._code = null; + this.code = null; } else { // If other keys are still pressed, update code to the last pressed key const lastPressedKey = Object.keys(this._downKeys).pop(); - this._code = lastPressedKey; + this.code = lastPressedKey; } const context = this._isGlobal ? window : this; @@ -814,7 +814,7 @@ function keyboard(p5, fn){ * keycode.info. * * @method keyIsDown - * @param {Number} code key to check. + * @param {Number || String} code key to check. * @return {Boolean} whether the key is down or not. * * @example @@ -906,32 +906,27 @@ function keyboard(p5, fn){ * * */ - p5.prototype.keyIsDown = function(code) { - console.log('Current _downKeys:', this._downKeys); - console.log('Current key:', this.key); + function isCode(input) { + if (typeof input !== 'string') { + return false; + } - // For backward compatibility - if code is a number - if (typeof code === 'number') { - return this._downKeys[code] || false; + // If it's a single digit, it should be treated as a code (with "Digit" prefix) + if (input.length === 1 && /[0-9]/.test(input)) { + return true; } - // For string inputs (new functionality) - if (typeof code === 'string') { - // Handle single character inputs - if (code.length === 1) { - if (/[A-Za-z]/.test(code)) { - // For letters, we need to check the actual key value - return this.key === code; - } else if (/[0-9]/.test(code)) { - return this._downKeys[`Digit${code}`] || false; - } - } - // Handle direct code inputs (e.g., 'KeyA', 'ArrowLeft', etc.) - return this._downKeys[code] || false; + // If it's longer than 1 character, it's a code + return input.length > 1; + } + fn.keyIsDown = function(input) { + if (isCode(input)) { + const key = input.length === 1 ? `Digit${input}` : input; + return this._downKeyCodes[key] || this._downKeys[key]; + } else { + return this._downKeys[input] || this._downKeyCodes[input]; } - - return false; - }; + } /** * The _areDownKeys function returns a boolean true if any keys pressed * and a false if no keys are currently pressed. From 0ce4e891e32f1dc559a4dbbd84adf2b99da7fd41 Mon Sep 17 00:00:00 2001 From: Vaivaswat Date: Sun, 26 Jan 2025 10:51:00 +0530 Subject: [PATCH 5/5] added tests for isCode and small changes --- src/events/keyboard.js | 22 +++++++++----- test/unit/events/keyboard.js | 59 +++++++++++++++++++++++++++++++----- 2 files changed, 66 insertions(+), 15 deletions(-) diff --git a/src/events/keyboard.js b/src/events/keyboard.js index 14698167ed..b3396ae996 100644 --- a/src/events/keyboard.js +++ b/src/events/keyboard.js @@ -4,7 +4,17 @@ * @for p5 * @requires core */ +export function isCode(input) { + if (typeof input !== 'string') { + return false; + } + if (input.length === 1 && /[0-9]/.test(input)) { + return true; + } + + return input.length > 1; +} function keyboard(p5, fn){ /** * A `Boolean` system variable that's `true` if any key is currently pressed @@ -814,7 +824,7 @@ function keyboard(p5, fn){ * keycode.info. * * @method keyIsDown - * @param {Number || String} code key to check. + * @param {Number|String} code key to check. * @return {Boolean} whether the key is down or not. * * @example @@ -910,21 +920,17 @@ function keyboard(p5, fn){ if (typeof input !== 'string') { return false; } - - // If it's a single digit, it should be treated as a code (with "Digit" prefix) if (input.length === 1 && /[0-9]/.test(input)) { return true; } - - // If it's longer than 1 character, it's a code return input.length > 1; } + fn.keyIsDown = function(input) { if (isCode(input)) { - const key = input.length === 1 ? `Digit${input}` : input; - return this._downKeyCodes[key] || this._downKeys[key]; + return this._downKeyCodes[input] || this._downKeys[input] || false; } else { - return this._downKeys[input] || this._downKeyCodes[input]; + return this._downKeys[input] || this._downKeyCodes[input] || false; } } /** diff --git a/test/unit/events/keyboard.js b/test/unit/events/keyboard.js index 1ce199c66a..c1c80bd186 100644 --- a/test/unit/events/keyboard.js +++ b/test/unit/events/keyboard.js @@ -1,4 +1,5 @@ import p5 from '../../../src/app.js'; +import { isCode } from '../../../src/events/keyboard.js'; import { parallelSketches } from '../../js/p5_helpers'; suite('Keyboard Events', function() { @@ -180,18 +181,62 @@ suite('Keyboard Events', function() { }); }); + suite('isCode', function() { + test('returns false for non-string inputs', function() { + assert.isFalse(isCode(null)); + assert.isFalse(isCode(undefined)); + assert.isFalse(isCode(123)); + assert.isFalse(isCode({})); + assert.isFalse(isCode([])); + }); + + test('returns false for single non-digit characters', function() { + assert.isFalse(isCode('a')); + assert.isFalse(isCode('Z')); + assert.isFalse(isCode('!')); + assert.isFalse(isCode(' ')); + }); + + test('returns true for multi-character strings', function() { + assert.isTrue(isCode('Enter')); + assert.isTrue(isCode('ArrowUp')); + assert.isTrue(isCode('Shift')); + assert.isTrue(isCode('Control')); + assert.isTrue(isCode('ab')); + }); + + test('handles edge cases correctly', function() { + assert.isFalse(isCode('')); // empty string + assert.isTrue(isCode('11')); // multi-digit number + assert.isTrue(isCode('1a')); // digit + letter + }); + }); + suite('p5.prototype.keyIsDown', function() { test('keyIsDown should return a boolean', function() { - assert.isBoolean(myp5.keyIsDown(65)); + assert.isBoolean(myp5.keyIsDown('a')); + assert.isBoolean(myp5.keyIsDown('Enter')); }); test('keyIsDown should return true if key is down', function() { - window.dispatchEvent(new KeyboardEvent('keydown', { keyCode: 35 })); - assert.strictEqual(myp5.keyIsDown(35), true); - }); - - test.todo('keyIsDown should return false if key is not down', function() { - assert.strictEqual(myp5.keyIsDown(35), false); + // Test single character keys + window.dispatchEvent(new KeyboardEvent('keydown', { key: 'a' })); + assert.strictEqual(myp5.keyIsDown('a'), true); + + // Test digit keys + window.dispatchEvent(new KeyboardEvent('keydown', { key: '1', code: 'Digit1' })); + assert.strictEqual(myp5.keyIsDown('1'), true); + + // Test special keys + window.dispatchEvent(new KeyboardEvent('keydown', { key: 'Enter', code: 'Enter' })); + assert.strictEqual(myp5.keyIsDown('Enter'), true); + }); + + test('keyIsDown should return false if key is not down', function() { + // Ensure key is not down + window.dispatchEvent(new KeyboardEvent('keyup')); + assert.strictEqual(myp5.keyIsDown('z'), false); + }); }); });