/// /// /// interface KeyCode { evCode : string; representation : string; name : string; } module Controls.KeyHandler { let promiseStack : Array<(value?: KeyCode | PromiseLike) => void> = []; let promiseOriginalStack : Array> = []; export function rejectPromise (promise : (value?: KeyCode | PromiseLike) => void) { promiseStack.splice(promiseStack.indexOf(promise), 1); promiseOriginalStack.splice(promiseStack.indexOf(promise), 1); } export function createKeyCode (ev : KeyboardEvent) { let name = ev.key.toUpperCase(); let representation = name; let evCode = ev.code; if (ev.shiftKey) { name = "Shift + " + name; evCode = "Sh" + evCode; representation = "S" + representation; } if (ev.altKey) { name = "Alt + " + name; evCode = "Al" + evCode; representation = "A" + representation; } if (ev.ctrlKey) { name = "Control + " + name; evCode = "Ct" + evCode; representation = "C" + representation; } let keyCode : KeyCode = { evCode : evCode, name : name, representation : representation }; return keyCode; } window.addEventListener("mousedown", function (event) { let keyCode : KeyCode = { representation : "Click", evCode : "Click", name : "Click" }; let promise = promiseStack.shift(); if (promise != undefined) { promise(keyCode); promiseOriginalStack.shift(); return; } }); window.addEventListener("keydown", function (event) { //event.preventDefault(); This fucks up browser control. Let's just assume that this is always going to be the last thing to catch a key. let keyCode = createKeyCode(event); let promise = promiseStack.shift(); if (promise != undefined) { promise(keyCode); promiseOriginalStack.shift(); return; } if (keyCode.evCode == scrollKeyCode.getValue().evCode) { Elements.CurrentTurnHandler.scrollSpace(); return; } else if (keyCode.evCode == imageKeyCode.getValue().evCode) { if (SayImage.imageViewer.style.display == "block") { SayImage.imageViewer.style.display = "none"; } else { let images = Elements.CurrentTurnHandler.currentTurnTab.getElementsByClassName("contentImage"); if (images.length > 0) { ( images[images.length - 1]).click(); } } return; } let ele; Elements.getLinkElements().some((element : HTMLElement) => { let keyables = element.getElementsByClassName("keyable"); for (let i = 0; i < keyables.length; i++) { if (( keyables[i]).dataset['shortcutcode'] == keyCode.evCode) { ele = keyables[i]; return true; } } return false; }); if (ele != undefined) { ele.click(); } }); export function createKeyCodes (codes : Array, keys : Array, mods? : Array) { let arr = []; for (let mod = 0; mod < 4; mod++) { if (mod == 0 || mods[mod] == true) { for (let i = 0; i < codes.length; i++) { let name = keys[i]; let representation = keys[i]; let evCode = codes[i]; if (mod == 1) { name = "Shift + " + name; evCode = "Sh" + evCode; representation = "S" + representation; } if (mod == 2) { name = "Alt + " + name; evCode = "Al" + evCode; representation = "A" + representation; } if (mod == 3) { name = "Control + " + name; evCode = "Ct" + evCode; representation = "C" + representation; } let keyCode: KeyCode = { evCode: evCode, representation: representation, name : name }; arr.push(keyCode); } } } return arr; } export var scrollKeyCode = new StoredMemory("scrollKeyCode", { evCode : "Space", representation : "Space" }); export var imageKeyCode = new StoredMemory("imageKeyCode", { evCode : "KeyI", representation : "I" }); export var keyCodes1 = new StoredMemory( "keyCodesRoom", createKeyCodes( ["Digit1", "Digit2", "Digit3", "Digit4", "Digit5"], ["1", "2", "3", "4", "5"], [true, true, true, false]) ); export var keyCodes2 = new StoredMemory( "keyCodesActions", createKeyCodes( ["KeyQ", "KeyW", "KeyE", "KeyR", "KeyT"], ["Q", "W", "E", "R", "T"], [true, true, true, false]) ); export var keyCodes3 = new StoredMemory( "keyCodesGlobal", createKeyCodes( ["KeyF", "KeyV", "KeyG", "KeyB"], ["F", "V", "G", "B"], [true, true, true, false]) ); export var keyCodeNorth = new StoredMemory( "keyCodeNorth", { evCode : "KeyS", representation : "S" } ); export var keyCodeEast = new StoredMemory( "keyCodeEast", { evCode : "KeyC", representation : "C" } ); export var keyCodeSouth = new StoredMemory( "keyCodeSouth", { evCode : "KeyX", representation : "X" } ); export var keyCodeWest = new StoredMemory( "keyCodeWest", { evCode : "KeyZ", representation : "Z" } ); export var keyCodeUp = new StoredMemory( "keyCodeUp", { evCode : "KeyA", representation : "A" } ); export var keyCodeDown = new StoredMemory( "keyCodeDown", { evCode : "KeyD", representation : "D" } ); // TODO: Make this safer by creating it using Room.DIRECTIONS. var directionCodeByIndex = [keyCodeNorth, undefined, keyCodeEast, undefined, keyCodeSouth, undefined, keyCodeWest, undefined, keyCodeUp, keyCodeDown]; export function getDirectionCode (direction : Direction) { return getDirectionCodeByIndex(Room.DIRECTIONS.indexOf(direction)); } export function getDirectionCodeByIndex (index : number) { return directionCodeByIndex[index].getValue(); } export var keyRows = 3; export var available1 : Array = []; export var available2 : Array = []; export var available3 : Array = []; export function reset () { available1 = keyCodes1.getValue().slice(); available2 = keyCodes2.getValue().slice(); available3 = keyCodes3.getValue().slice(); } let showKeys = new StoredMemory("ShowKeys", !Elements.isMobile); export function applyCode (element : HTMLElement, code : KeyCode) { if (code == undefined) { delete(element.dataset['shortcut']); delete(element.dataset['shortcutcode']); element.classList.remove("keyable"); } else { element.dataset['shortcutcode'] = code.evCode; if (showKeys.getValue()) { element.dataset['shortcut'] = code.representation; } element.classList.add("keyable"); } } export function getFirstKeyCode () { let chosen = available1.length > 0 ? available1 : available2.length > 0 ? available2 : available3.length > 0 ? available3 : undefined; if (chosen != undefined) { return chosen.shift(); } return undefined; } export function getSecondKeyCode () { let chosen = available2.length > 0 ? available2 : available3.length > 0 ? available3 : undefined; if (chosen != undefined) { return chosen.splice(0, 1)[0]; } return undefined; } export function getThirdKeyCode () { let chosen = available3.length > 0 ? available3 : undefined; if (chosen != undefined) { return chosen.splice(0, 1)[0]; } return undefined; } /** * Returns a promise of a key press. * If after timeout seconds a key was not pressed, the promise fails. * @param {number} timeout */ export function getNextKey (timeout? : number) : Promise { let timeoutNumber; let promise = > (new Promise((resolve, reject) => { promiseStack.push(resolve); if (timeout != undefined) { timeoutNumber = setTimeout(() => { KeyHandler.rejectPromise(resolve); reject(); }, timeout * 1000); } })); promise.then(() => { clearTimeout(timeoutNumber); }); return promise; } export function stopGivingNextKey (originalPromise : Promise) { let index = promiseOriginalStack.indexOf(originalPromise); if (index != -1) { rejectPromise(promiseStack[index]); } } export function addKey (row : number, ev : KeyboardEvent) { let keyName = ev.key.toUpperCase(); if (["ALT", "CONTROL", "SHIFT", " ", "TAB"].includes(keyName)) { return; } if (keyName == "BACKSPACE") { clearKeys(row); return; } if (row >= 1 && row <= Controls.KeyHandler.keyRows) { let rowArray : StoredMemory> = Controls.KeyHandler["keyCodes" + row]; let keyArray = rowArray.getValue().splice(0); keyArray.push(... createKeyCodes( [ev.code], [keyName], [true, true, true, false]) ); let modNumber = (name : string) => { if (name.indexOf("Shift") != -1) { return 1; } else if (name.indexOf("Control") != -1) { return 2; } else if (name.indexOf("Alt") != -1) { return 3; } return 0; }; keyArray.sort((a, b) => { let ma = modNumber(a.name); let mb = modNumber(b.name); if (ma != mb) { return ma - mb; } return 0; }); rowArray.storeValue(keyArray); } } export function clearKeys (row : number) { if (row >= 1 && row <= Controls.KeyHandler.keyRows) { let rowArray: StoredMemory> = Controls.KeyHandler["keyCodes" + row]; rowArray.storeValue([]); } } }