diff --git a/src/js/game/key_action_mapper.js b/src/js/game/key_action_mapper.js index 77cfd53c..7e1fb9e8 100644 --- a/src/js/game/key_action_mapper.js +++ b/src/js/game/key_action_mapper.js @@ -15,69 +15,69 @@ function key(str) { export const KEYMAPPINGS = { general: { - confirm: { keyCode: 13 }, // enter - back: { keyCode: 27, builtin: true }, // escape + confirm: { keyCodes: [13] }, // enter + back: { keyCodes: [27], builtin: true }, // escape }, ingame: { - menuOpenShop: { keyCode: key("F") }, - menuOpenStats: { keyCode: key("G") }, + menuOpenShop: { keyCodes: [key("F")] }, + menuOpenStats: { keyCodes: [key("G")] }, - toggleHud: { keyCode: 113 }, // F2 - exportScreenshot: { keyCode: 114 }, // F3 - toggleFPSInfo: { keyCode: 115 }, // F4 + toggleHud: { keyCodes: [113] }, // F2 + exportScreenshot: { keyCodes: [114] }, // F3 + toggleFPSInfo: { keyCodes: [115] }, // F4 }, navigation: { - mapMoveUp: { keyCode: key("W") }, - mapMoveRight: { keyCode: key("D") }, - mapMoveDown: { keyCode: key("S") }, - mapMoveLeft: { keyCode: key("A") }, - mapMoveFaster: { keyCode: 16 }, //shift + mapMoveUp: { keyCodes: [key("W")] }, + mapMoveRight: { keyCodes: [key("D")] }, + mapMoveDown: { keyCodes: [key("S")] }, + mapMoveLeft: { keyCodes: [key("A")] }, + mapMoveFaster: { keyCodes: [16] }, //shift - centerMap: { keyCode: 32 }, // SPACE - mapZoomIn: { keyCode: 187, repeated: true }, // "+" - mapZoomOut: { keyCode: 189, repeated: true }, // "-" + centerMap: { keyCodes: [32] }, // SPACE + mapZoomIn: { keyCodes: [187], repeated: true }, // "+" + mapZoomOut: { keyCodes: [189], repeated: true }, // "-" - createMarker: { keyCode: key("M") }, + createMarker: { keyCodes: [key("M")] }, }, buildings: { - belt: { keyCode: key("1") }, - splitter: { keyCode: key("2") }, - underground_belt: { keyCode: key("3") }, - miner: { keyCode: key("4") }, - cutter: { keyCode: key("5") }, - rotater: { keyCode: key("6") }, - stacker: { keyCode: key("7") }, - mixer: { keyCode: key("8") }, - painter: { keyCode: key("9") }, - trash: { keyCode: key("0") }, + belt: { keyCodes: [key("1")] }, + splitter: { keyCodes: [key("2")] }, + underground_belt: { keyCodes: [key("3")] }, + miner: { keyCodes: [key("4")] }, + cutter: { keyCodes: [key("5")] }, + rotater: { keyCodes: [key("6")] }, + stacker: { keyCodes: [key("7")] }, + mixer: { keyCodes: [key("8")] }, + painter: { keyCodes: [key("9")] }, + trash: { keyCodes: [key("0")] }, }, placement: { - abortBuildingPlacement: { keyCode: key("Q") }, - rotateWhilePlacing: { keyCode: key("R") }, - rotateInverseModifier: { keyCode: 16 }, // SHIFT - cycleBuildingVariants: { keyCode: key("T") }, - cycleBuildings: { keyCode: 9 }, // TAB - switchDirectionLockSide: { keyCode: key("R") }, + abortBuildingPlacement: { keyCodes: [key("Q")] }, + rotateWhilePlacing: { keyCodes: [key("R")] }, + rotateInverseModifier: { keyCodes: [16] }, // SHIFT + cycleBuildingVariants: { keyCodes: [key("T")] }, + cycleBuildings: { keyCodes: [9] }, // TAB + switchDirectionLockSide: { keyCodes: [key("R")] }, }, massSelect: { - massSelectStart: { keyCode: 17 }, // CTRL - massSelectSelectMultiple: { keyCode: 16 }, // SHIFT - massSelectCopy: { keyCode: key("C") }, - massSelectCut: { keyCode: key("X") }, - confirmMassDelete: { keyCode: 46 }, // DEL - pasteLastBlueprint: { keyCode: key("V") }, + massSelectStart: { keyCodes: [17] }, // CTRL + massSelectSelectMultiple: { keyCodes: [16] }, // SHIFT + massSelectCopy: { keyCodes: [key("C")] }, + massSelectCut: { keyCodes: [key("X")] }, + confirmMassDelete: { keyCodes: [46] }, // DEL + pasteLastBlueprint: { keyCodes: [key("V")] }, }, placementModifiers: { - lockBeltDirection: { keyCode: 16 }, // SHIFT - placementDisableAutoOrientation: { keyCode: 17 }, // CTRL - placeMultiple: { keyCode: 16 }, // SHIFT - placeInverse: { keyCode: 18 }, // ALT + lockBeltDirection: { keyCodes: [16] }, // SHIFT + placementDisableAutoOrientation: { keyCodes: [17] }, // CTRL + placeMultiple: { keyCodes: [16] }, // SHIFT + placeInverse: { keyCodes: [18] }, // ALT }, }; @@ -244,15 +244,11 @@ export class Keybinding { * @param {KeyActionMapper} keyMapper * @param {Application} app * @param {object} param0 - * @param {number} [param0.keyCode] - * @param {number[]} [param0.keyCodes] + * @param {number[]} param0.keyCodes * @param {boolean=} param0.builtin * @param {boolean=} param0.repeated */ - constructor(keyMapper, app, { keyCode = 0, keyCodes = [], builtin = false, repeated = false }) { - if (keyCode && keyCode != keyCodes[0]) { - keyCodes.unshift(keyCode); - } + constructor(keyMapper, app, { keyCodes, builtin = false, repeated = false }) { for (let keyCode of keyCodes) { assert(Number.isInteger(keyCode), "Invalid key code: " + keyCode); } @@ -344,12 +340,18 @@ export class KeyActionMapper { for (const key in KEYMAPPINGS[category]) { let payload = Object.assign({}, KEYMAPPINGS[category][key]); if (overrides[key]) { - payload.keyCode = overrides[key]; + payload.keyCodes[0] = overrides[key]; } - payload.keyCodes = payload.keyCodes || []; let index = 1; - while (overrides[`${key}_${index + 1}`]) { - payload.keyCodes.push(overrides[`${key}_${index + 1}`]); + while (overrides[`${key}_${index}`]) { + if (!+overrides[`${key}_${index}`]) { + break; + } + if (payload.keyCodes.length < index) { + payload.keyCodes.push(overrides[`${key}_${index}`]); + } else { + payload.keyCodes[index] = overrides[`${key}_${index}`]; + } index++; } @@ -418,10 +420,7 @@ export class KeyActionMapper { for (const key in this.keybindings) { /** @type {Keybinding} */ const binding = this.keybindings[key]; - if ( - binding.keyCodes.includes(keyCode) && - (initial || binding.repeated) - ) { + if (binding.keyCodes.includes(keyCode) && (initial || binding.repeated)) { /** @type {Signal} */ const signal = this.keybindings[key].signal; if (signal.dispatch() === STOP_PROPAGATION) { diff --git a/src/js/profile/application_settings.js b/src/js/profile/application_settings.js index 5b69c7ae..354f9f23 100644 --- a/src/js/profile/application_settings.js +++ b/src/js/profile/application_settings.js @@ -373,7 +373,11 @@ export class ApplicationSettings extends ReadWriteProxy { * @param {string} id */ resetKeybindingOverride(id) { - delete this.getAllSettings().keybindingOverrides[id]; + let overrides = this.getAllSettings().keybindingOverrides; + delete overrides[id]; + for (let index = 1; overrides[id + "_" + index]; index++) { + delete overrides[id + "_" + index]; + } return this.writeAsync(); } /** diff --git a/src/js/states/keybindings.js b/src/js/states/keybindings.js index ba468715..c1882320 100644 --- a/src/js/states/keybindings.js +++ b/src/js/states/keybindings.js @@ -29,6 +29,24 @@ export class KeybindingsState extends TextualGameState { `; } + addEditField(elem, keybindingId, index = 0, builtin) { + if (index) { + keybindingId += "_" + index; + } + const mappingDiv = document.createElement("span"); + mappingDiv.classList.add("mapping", "mapping_" + index); + + const editBtn = document.createElement("button"); + editBtn.classList.add("styledButton", "editKeybinding", "editKeybinding_" + index); + + if (builtin) { + editBtn.classList.add("disabled"); + } else { + this.trackClicks(editBtn, () => this.editKeybinding(keybindingId)); + } + elem.querySelector(".resetKeybinding").before(mappingDiv, editBtn); + } + onEnter() { const keybindingsElem = this.htmlElement.querySelector(".keybindings"); @@ -57,43 +75,19 @@ export class KeybindingsState extends TextualGameState { title.innerText = T.keybindings.mappings[keybindingId] || `unset(${keybindingId})`; elem.appendChild(title); - const mappingDiv = document.createElement("span"); - mappingDiv.classList.add("mapping"); - elem.appendChild(mappingDiv); - - const editBtn = document.createElement("button"); - editBtn.classList.add("styledButton", "editKeybinding"); - - const mappingDiv2 = document.createElement("span"); - mappingDiv2.classList.add("mapping"); - mappingDiv2.classList.add("mapping_2"); - - const editBtn2 = document.createElement("button"); - editBtn2.classList.add("styledButton", "editKeybinding"); - editBtn2.classList.add("styledButton", "editKeybinding_2"); - const resetBtn = document.createElement("button"); resetBtn.classList.add("styledButton", "resetKeybinding"); - const resetBtn2 = document.createElement("button"); - resetBtn2.classList.add("styledButton", "resetKeybinding"); - resetBtn2.classList.add("styledButton", "resetKeybinding_2"); - if (mapped.builtin) { - editBtn.classList.add("disabled"); resetBtn.classList.add("disabled"); - editBtn2.classList.add("disabled"); - resetBtn2.classList.add("disabled"); } else { - this.trackClicks(editBtn, () => this.editKeybinding(keybindingId)); this.trackClicks(resetBtn, () => this.resetKeybinding(keybindingId)); - this.trackClicks(editBtn2, () => this.editKeybinding(keybindingId + "_2")); - this.trackClicks(resetBtn2, () => this.resetKeybinding(keybindingId + "_2")); } - elem.appendChild(editBtn); elem.appendChild(resetBtn); - elem.appendChild(mappingDiv2); - elem.appendChild(editBtn2); - elem.appendChild(resetBtn2); + + mapped.keyCodes = mapped.keyCodes.filter(Boolean); + for (let i = 0; i < mapped.keyCodes.length; i++) { + this.addEditField(elem, keybindingId, i, mapped.builtin); + } } } this.updateKeybindings(); @@ -158,28 +152,21 @@ export class KeybindingsState extends TextualGameState { const container = this.htmlElement.querySelector("[data-keybinding='" + keybindingId + "']"); assert(container, "Container for keybinding not found: " + keybindingId); - let keyCode = mapped.keyCode; - if (overrides[keybindingId]) { - keyCode = overrides[keybindingId]; + let allRaw = true; + for (let i = 0; i < mapped.keyCodes.length; i++) { + let raw = mapped.keyCodes[i]; + let kid = keybindingId + (!i ? "" : "_" + i); + let over = overrides[kid]; + let mappingDiv = container.querySelector(".mapping_" + i); + mappingDiv.innerHTML = getStringForKeyCode(over || raw); + mappingDiv.classList.toggle("changed", over != raw); + if (over && over != raw) { + allRaw = false; + } } - let keyCode2 = mapped.keyCode2; - if (overrides[keybindingId + "_2"]) { - keyCode2 = overrides[keybindingId + "_2"]; - } - - const mappingDiv = container.querySelector(".mapping"); - mappingDiv.innerHTML = getStringForKeyCode(keyCode); - mappingDiv.classList.toggle("changed", !!overrides[keybindingId]); - - const mappingDiv2 = container.querySelector(".mapping_2"); - mappingDiv2.innerHTML = getStringForKeyCode(keyCode2); - mappingDiv2.classList.toggle("changed", !!overrides[keybindingId + "_2"]); const resetBtn = container.querySelector("button.resetKeybinding"); - resetBtn.classList.toggle("disabled", mapped.builtin || !overrides[keybindingId]); - - const resetBtn2 = container.querySelector("button.resetKeybinding_2"); - resetBtn2.classList.toggle("disabled", mapped.builtin || !overrides[keybindingId + "_2"]); + resetBtn.classList.toggle("disabled", allRaw); } } }