From 251192bdc2f73190cb80530fc3a5bd681a016358 Mon Sep 17 00:00:00 2001 From: Siarhei Siniak Date: Sun, 3 Apr 2022 16:36:40 +0300 Subject: [PATCH] [~] Refactor --- d2/gamepad/game-pad.js | 258 ++++++++++++++++++++++++++++++++++++ d2/gamepad/miniroyale-io.js | 14 ++ d2/gamepad/mouse.js | 89 +++++++++++++ d2/gamepad/script.js | 195 +++++++++++++++++++++++++++ 4 files changed, 556 insertions(+) create mode 100644 d2/gamepad/game-pad.js create mode 100644 d2/gamepad/miniroyale-io.js create mode 100644 d2/gamepad/mouse.js create mode 100644 d2/gamepad/script.js diff --git a/d2/gamepad/game-pad.js b/d2/gamepad/game-pad.js new file mode 100644 index 0000000..4c0aa16 --- /dev/null +++ b/d2/gamepad/game-pad.js @@ -0,0 +1,258 @@ +(() => { + const KEYS = { + "KEY_0":48,"KEY_1":49,"KEY_2":50,"KEY_3":51,"KEY_4":52,"KEY_5":53,"KEY_6":54,"KEY_7":55,"KEY_8":56,"KEY_9":57,"KEY_A":65,"KEY_ADD":107,"KEY_ALT":18,"KEY_B":66,"KEY_BACKSPACE":8,"KEY_BACK_SLASH":220,"KEY_C":67,"KEY_CAPS_LOCK":20,"KEY_CLOSE_BRACKET":221,"KEY_COMMA":188,"KEY_CONTEXT_MENU":93,"KEY_CONTROL":17,"KEY_D":68,"KEY_DECIMAL":110,"KEY_DELETE":46,"KEY_DIVIDE":111,"KEY_DOWN":40,"KEY_E":69,"KEY_END":35,"KEY_ENTER":13,"KEY_EQUAL":61,"KEY_ESCAPE":27,"KEY_F":70,"KEY_F1":112,"KEY_F10":121,"KEY_F11":122,"KEY_F12":123,"KEY_F2":113,"KEY_F3":114,"KEY_F4":115,"KEY_F5":116,"KEY_F6":117,"KEY_F7":118,"KEY_F8":119,"KEY_F9":120,"KEY_G":71,"KEY_H":72,"KEY_HOME":36,"KEY_I":73,"KEY_INSERT":45,"KEY_J":74,"KEY_K":75,"KEY_L":76,"KEY_LEFT":37,"KEY_M":77,"KEY_META":224,"KEY_MULTIPLY":106,"KEY_N":78,"KEY_NUMPAD_0":96,"KEY_NUMPAD_1":97,"KEY_NUMPAD_2":98,"KEY_NUMPAD_3":99,"KEY_NUMPAD_4":100,"KEY_NUMPAD_5":101,"KEY_NUMPAD_6":102,"KEY_NUMPAD_7":103,"KEY_NUMPAD_8":104,"KEY_NUMPAD_9":105,"KEY_O":79,"KEY_OPEN_BRACKET":219,"KEY_P":80,"KEY_PAGE_DOWN":34,"KEY_PAGE_UP":33,"KEY_PAUSE":19,"KEY_PERIOD":190,"KEY_PRINT_SCREEN":44,"KEY_Q":81,"KEY_R":82,"KEY_RETURN":13,"KEY_RIGHT":39,"KEY_S":83,"KEY_SEMICOLON":59,"KEY_SEPARATOR":108,"KEY_SHIFT":16,"KEY_SLASH":191,"KEY_SPACE":32,"KEY_SUBTRACT":109,"KEY_T":84,"KEY_TAB":9,"KEY_U":85,"KEY_UP":38,"KEY_V":86,"KEY_W":87,"KEY_WINDOWS":91,"KEY_X":88,"KEY_Y":89,"KEY_Z":90 + }; + const MAPS = { + DEFAULT: { + buttons: [ + // Face buttons + 'PAD_FACE_1', + 'PAD_FACE_2', + 'PAD_FACE_3', + 'PAD_FACE_4', + + // Shoulder buttons + 'PAD_L_SHOULDER_1', + 'PAD_R_SHOULDER_1', + 'PAD_L_SHOULDER_2', + 'PAD_R_SHOULDER_2', + + // Other buttons + 'PAD_SELECT', + 'PAD_START', + 'PAD_L_STICK_BUTTON', + 'PAD_R_STICK_BUTTON', + + // D Pad + 'PAD_UP', + 'PAD_DOWN', + 'PAD_LEFT', + 'PAD_RIGHT', + + // Vendor specific button + 'PAD_VENDOR' + ], + + axes: [ + // Analogue Sticks + 'PAD_L_STICK_X', + 'PAD_L_STICK_Y', + 'PAD_R_STICK_X', + 'PAD_R_STICK_Y' + ] + }, + + PS3: { + buttons: [ + // X, O, TRI, SQ + 'PAD_FACE_1', + 'PAD_FACE_2', + 'PAD_FACE_4', + 'PAD_FACE_3', + + // Shoulder buttons + 'PAD_L_SHOULDER_1', + 'PAD_R_SHOULDER_1', + 'PAD_L_SHOULDER_2', + 'PAD_R_SHOULDER_2', + + // Other buttons + 'PAD_SELECT', + 'PAD_START', + 'PAD_L_STICK_BUTTON', + 'PAD_R_STICK_BUTTON', + + // D Pad + 'PAD_UP', + 'PAD_DOWN', + 'PAD_LEFT', + 'PAD_RIGHT', + + 'PAD_VENDOR' + ], + + axes: [ + // Analogue Sticks + 'PAD_L_STICK_X', + 'PAD_L_STICK_Y', + 'PAD_R_STICK_X', + 'PAD_R_STICK_Y' + ] + } + }; + + const PRODUCT_CODES = { + 'Product: 0268': 'PS3' + }; + + /** + * Input handler for accessing GamePad input. + */ + class GamePads { + /** + * Create a new GamePads instance. + */ + constructor() { + this.gamepadsSupported = !!navigator.getGamepads || !!navigator.webkitGetGamepads; + + this.current = []; + this.previous = []; + + this.deadZone = 0.25; + } + + /** + * Update the current and previous state of the gamepads. This must be called every frame for + * `wasPressed` to work. + */ + update() { + // move current buttons status into previous array + for (let i = 0, l = this.current.length; i < l; i++) { + const buttons = this.current[i].pad.buttons; + const buttonsLen = buttons.length; + for (let j = 0; j < buttonsLen; j++) { + if (this.previous[i] === undefined) { + this.previous[i] = []; + } + this.previous[i][j] = buttons[j].pressed; + } + } + + // update current + this.poll(this.current); + } + + /** + * Poll for the latest data from the gamepad API. + * + * @param {object[]} [pads] - An optional array used to receive the gamepads mapping. This + * array will be returned by this function. + * @returns {object[]} An array of gamepads and mappings for the model of gamepad that is + * attached. + * @example + * var gamepads = new pc.GamePads(); + * var pads = gamepads.poll(); + */ + poll(pads = []) { + if (pads.length > 0) { + pads.length = 0; + } + + if (this.gamepadsSupported) { + const padDevices = navigator.getGamepads ? navigator.getGamepads() : navigator.webkitGetGamepads(); + for (let i = 0, len = padDevices.length; i < len; i++) { + if (padDevices[i]) { + pads.push({ + map: this.getMap(padDevices[i]), + pad: padDevices[i] + }); + } + } + } + return pads; + } + + getMap(pad) { + for (const code in PRODUCT_CODES) { + if (pad.id.indexOf(code) >= 0) { + return MAPS[PRODUCT_CODES[code]]; + } + } + + return MAPS.DEFAULT; + } + + /** + * Returns true if the button on the pad requested is pressed. + * + * @param {number} index - The index of the pad to check, use constants {@link PAD_1}, + * {@link PAD_2}, etc. + * @param {number} button - The button to test, use constants {@link PAD_FACE_1}, etc. + * @returns {boolean} True if the button is pressed. + */ + isPressed(index, button) { + if (!this.current[index]) { + return false; + } + + const key = this.current[index].map.buttons[button]; + return this.current[index].pad.buttons[pc[key]].pressed; + } + + /** + * Returns true if the button was pressed since the last frame. + * + * @param {number} index - The index of the pad to check, use constants {@link PAD_1}, + * {@link PAD_2}, etc. + * @param {number} button - The button to test, use constants {@link PAD_FACE_1}, etc. + * @returns {boolean} True if the button was pressed since the last frame. + */ + wasPressed(index, button) { + if (!this.current[index]) { + return false; + } + + const key = this.current[index].map.buttons[button]; + const i = pc[key]; + + // Previous pad buttons may not have been populated yet + // If this is the first time frame a pad has been detected + return this.current[index].pad.buttons[i].pressed && !(this.previous[index] && this.previous[index][i]); + } + + /** + * Returns true if the button was released since the last frame. + * + * @param {number} index - The index of the pad to check, use constants {@link PAD_1}, + * {@link PAD_2}, etc. + * @param {number} button - The button to test, use constants {@link PAD_FACE_1}, etc. + * @returns {boolean} True if the button was released since the last frame. + */ + wasReleased(index, button) { + if (!this.current[index]) { + return false; + } + + const key = this.current[index].map.buttons[button]; + const i = pc[key]; + + // Previous pad buttons may not have been populated yet + // If this is the first time frame a pad has been detected + return !this.current[index].pad.buttons[i].pressed && (this.previous[index] && this.previous[index][i]); + } + + /** + * Get the value of one of the analogue axes of the pad. + * + * @param {number} index - The index of the pad to check, use constants {@link PAD_1}, + * {@link PAD_2}, etc. + * @param {number} axes - The axes to get the value of, use constants {@link PAD_L_STICK_X}, + * etc. + * @returns {number} The value of the axis between -1 and 1. + */ + getAxis(index, axes) { + if (!this.current[index]) { + return 0; + } + + const key = this.current[index].map.axes[axes]; + let value = this.current[index].pad.axes[pc[key]]; + + if (Math.abs(value) < this.deadZone) { + value = 0; + } + return value; + } + } + + if (window['context'] == undefined) + { + window.context = {}; + } + window.context.game_pad = { + GamePads: GamePads, + MAPS: MAPS, + KEYS: KEYS, + }; +})(); +//export { GamePads }; diff --git a/d2/gamepad/miniroyale-io.js b/d2/gamepad/miniroyale-io.js new file mode 100644 index 0000000..4be9b8b --- /dev/null +++ b/d2/gamepad/miniroyale-io.js @@ -0,0 +1,14 @@ +(() => { + window.context.runtime = {}; + + window.context.drag_mouse(100, 0, [pc.MOUSEBUTTON_LEFT], $$('canvas')[0]) + window.context.runtime.m1_ctx = window.context.c1.m1( + window, + { + "PAD_FACE_1": window.context.game_pad.KEYS.KEY_W, + "PAD_FACE_2": window.context.game_pad.KEYS.KEY_D, + "PAD_FACE_3": window.context.game_pad.KEYS.KEY_S, + "PAD_FACE_4": window.context.game_pad.KEYS.KEY_A, + }, + ); +})(); diff --git a/d2/gamepad/mouse.js b/d2/gamepad/mouse.js new file mode 100644 index 0000000..64b3aab --- /dev/null +++ b/d2/gamepad/mouse.js @@ -0,0 +1,89 @@ +if (window.context == undefined) +{ + window.context = {}; +} + +window.context.drag_mouse = (dx, dy, buttons, element) => { + let sx = null; + let sy = null; + + if (element == undefined) + { + element = document.body; + } + if (buttons == undefined) + { + buttons = [] + } + + { + let t1 = element.getBoundingClientRect(); + sx = t1.left + t1.width / 2; + sy = t1.top + t1.height / 2; + } + //console.log([sx, sy]); + + t2 = (btn, mvx, mvy, clx, cly, t) => { + return new MouseEvent( + t, + { + type: t, + button: btn, + target: element, + movementX: mvx, + movementY: mvy, + clientX: clx, + clientY: cly, + shiftKey: false, // you don't need to include values + ctrlKey: false, // if you aren't going to use them. + metaKey: false // these are here for example's sake. + } + ); + } + + t3 = [ + t2(-1, 0, 0, sx, sy, "mousemove"), + t2(pc.MOUSEBUTTON_LEFT, 0, 0, sx, sy, "mousedown"), + t2(-1, 0, 0, sx, sy, "mousemove"), + t2(-1, dx, dy, sx + dx, sy + dy, "mousemove"), + t2(-1, 0, 0, sx + dx, sy + dy, "mousemove"), + t2(-1, 0, 0, sx + dx, sy + dy, "mousemove"), + t2(pc.MOUSEBUTTON_LEFT, 0, 0, sx + dx, sy + dy, "mouseup"), + ]; + if (true) + { + window.dispatchEvent(t3[0]); + } + if (true) + { + for (let button in buttons) + { + let event = t2( + button, 0, 0, sx, sy, "mousedown" + ); + window.dispatchEvent(event); + } + } + t3.slice(3, 4).forEach( + (o) => window.dispatchEvent(o) + ); + //t3.slice(4, 5).forEach( + // (o) => window.dispatchEvent(o) + //); + //t3.slice(5, 6).forEach( + // (o) => window.dispatchEvent(o) + //); + + if (false) + { + for (let button in buttons) + { + let event = t2( + button, 0, 0, sx + dx, sy + dy, "mouseup", + ); + window.dispatchEvent(event); + } + } + + window.dispatchEvent(t3[6]); +} diff --git a/d2/gamepad/script.js b/d2/gamepad/script.js new file mode 100644 index 0000000..67279ae --- /dev/null +++ b/d2/gamepad/script.js @@ -0,0 +1,195 @@ +(() => { + window.context.c1 = { + m1: (target, key_map, timeout, freq, mouse_amplifier) => { + if (mouse_amplifier == undefined) + { + mouse_amplifier = 100; + } + + if (freq == undefined) + { + freq = 50; + } + if (timeout == undefined) + { + timeout = 40; + } + + let ctx = { + timer_id: null, + game_pad: null + }; + ctx.game_pad = new window.context.game_pad.GamePads(); + if (target == undefined) + { + throw "NOT_IMPLEMENTED_ERROR"; + } + if (key_map == undefined) + { + throw "NOT_IMPLEMENTED_ERROR"; + } + if (timeout == undefined) + { + throw "NOT_IMPLEMENTED_ERROR"; + } + let t6 = null; + let t7 = null; + ctx.timer_id = setInterval( + () => { + ctx.game_pad.update(); + if ( + ctx.game_pad.current.length < 1 && + ctx.game_pad.previous.length < 1 + ) + { + return; + } + + let o3 = {}; + let o4 = {} + let t4 = ctx.game_pad.previous[0]; + let t5 = ctx.game_pad.current[0]; + + if (t4 == undefined || t5 == undefined) + { + return; + } + t6 = t7; + t7 = {}; + + t5.pad.buttons.forEach( + (o, i) => { + o4[i] = t5.map.buttons[i]; + o4[o4[i]] = i; + + o3[ + t5.map.buttons[i] + ] = o.value; + t7[o4[i]] = o.value; + } + ); + for (k in o3) + { + if (key_map[k] != undefined) + { + let event_type = null; + + if ( + o3[k] == 1 && (t6 == null || t6[k] == 0) + ) + { + event_type = "keydown"; + } + else if ( + o3[k] == 0 && ( + t6 != null && t6[k] == 1 + ) + ) + { + event_type = "keyup"; + } + + if (event_type != null) + { + console.log([target, key_map[k], event_type]); + window.context.c1.m2( + target, + key_map[k], + event_type, + ); + } + } + } + { + let dx = t5.pad.axes[1]; + let dy = t5.pad.axes[2]; + + if (Math.abs(dx) > 0.05 || Math.abs(dy) > 0.05) + { + window.context.drag_mouse( + dx * mouse_amplifier, + dy * mouse_amplifier, + ); + } + } + if (o3.PAD_SELECT == 1) + { + clearInterval(ctx.timer_id); + console.log( + ` + d2.gamepad.script window.context.c1.m1 + clearInterval ${ctx.timer_id} + ` + ); + } + }, + freq, + ); + return ctx; + }, + m4: (key_code) => { + let t1 = null; + for (let k in window.context.game_pad.KEYS) + { + if (window.context.game_pad.KEYS[k] == key_code) + { + t1 = k; + } + } + if (t1 == null) + { + throw `NOT_IMPLEMENTED_ERROR`; + } + return { + code: key_code, + lable: t1, + }; + }, + m3: (target, key_code, timeout) => { + window.context.c1.m2(target, key_code, `keydown`); + + if (!(timeout > 0 && timeout < 2000)) + { + throw `NOT_IMPLEMENTED_ERROR`; + } + + return setTimeout( + () => { + window.context.c1.m2(target, key_code, `keyup`); + }, + timeout, + ); + }, + m5: (a, b) => { + return b.findIndex((o) => o == a); + }, + m2: (target, key_code, key_event_name) => { + let t1 = window.context.c1.m4(key_code); + + if ( + window.context.c1.m5( + key_event_name, + [`keydown`, `keyup`] + ) == -1 + ) + { + throw `NOT_IMPLEMENTED_ERROR`; + } + + target.dispatchEvent( + new KeyboardEvent( + key_event_name, + { + key: t1.label, + keyCode: t1.code, // example values. + code: t1.code, // put everything you need in this object. + which: t1.code, + shiftKey: false, // you don't need to include values + ctrlKey: false, // if you aren't going to use them. + metaKey: false // these are here for example's sake. + } + ) + ); + }, + }; +})();