Skip to content

Commit

Permalink
[crosscode] add a mod for binding mouse buttons to actions
Browse files Browse the repository at this point in the history
  • Loading branch information
dmitmel committed Feb 12, 2021
1 parent 32cfe4f commit bddaea1
Showing 1 changed file with 154 additions and 0 deletions.
154 changes: 154 additions & 0 deletions crosscode/btw-i-use-arch-mod/prestart.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,157 @@ sc.OPTIONS_DEFINITION['keys-btw-i-use-arch.open-map-menu'] = {
hasDivider: true,
header: 'btw-i-use-arch',
};

ig.KEY.MOUSE_LEFT = ig.KEY.MOUSE1;
ig.KEY.MOUSE_RIGHT = ig.KEY.MOUSE2;
ig.KEY.MOUSE_MIDDLE = -6;
ig.KEY.MOUSE_BACK = -7;
ig.KEY.MOUSE_FORWARD = -8;

// As for the copied implementations of ig.Input#keydown and ig.Input#keyup:
// there is probably a way to avoid copying, most notably by abusing the logic
// of the keyCode check. See, in both methods it is basically the same, just
// with differing event names, but the logic is as follows: if the event is a
// keyboard event, get the `keyCode` property, otherwise check if
// `event.button` is 2, then assume the key is `ig.KEY.MOUSE2`, otherwise
// `ig.KEY.MOUSE1`. This means that I could replace the value of the `MOUSE1`
// constant to the keyCode determined with my custom logic, and so the fallback
// path will read my value, but ultimately I didn't do that because I figured
// there might be other parts of these functions which can use some
// refactoring.
ig.Input.inject({
keydown(event) {
if (
ig.system.crashed ||
this.isInIframeAndUnfocused() ||
(this.ignoreKeyboard && event.type !== 'mousedown')
) {
return;
}

if (ig.system.hasFocusLost()) {
if (event.type === 'mousedown') {
ig.system.regainFocus();
}
return;
}

if (event.type === 'mousedown') {
this.mouseGuiActive = true;
}
this.currentDevice = ig.INPUT_DEVICES.KEYBOARD_AND_MOUSE;

if (event.target.type === 'text') {
return;
}

let keyCode = this.getKeyCodeFromEvent(event);

if (
// It's quite interesting that the game kinda supports touch events, but
// they are never actually used in practice.
event.type === 'touchstart' ||
event.type === 'mousedown'
) {
this.mousemove(event);
}

let action = this.bindings[keyCode];
if (action != null) {
this.actions[action] = true;
// Not sure what are locks supposed to do. Oh wait, I figured it out:
// this is so that if a button is detected to be pressed in a frame, but
// if an un-press event is caught during the processing of the frame, the
// button... Hmmm, still not sure. Entirety of the game logic blocks the
// main thread, so it's impossible to catch two events during processing
// of the frame.
if (!this.locks[action]) {
this.presses[action] = true;
this.locks[action] = true;
}
event.stopPropagation();
event.preventDefault();
}
},

keyup(event) {
if (
ig.system.crashed ||
this.isInIframeAndUnfocused() ||
(this.ignoreKeyboard && event.type !== 'mouseup') ||
event.target.type === 'text' ||
(ig.system.hasFocusLost() && event.type === 'mouseup')
) {
return;
}

this.currentDevice = ig.INPUT_DEVICES.KEYBOARD_AND_MOUSE;

let keyCode = this.getKeyCodeFromEvent(event);

let action = this.bindings[keyCode];
if (action != null) {
this.keyups[action] = true;
this.delayedKeyup.push(action);
event.stopPropagation();
event.preventDefault();
}
},

getKeyCodeFromEvent(event) {
switch (event.type) {
case 'keyup':
case 'keydown':
return event.keyCode;

case 'mouseup':
case 'mousedown':
switch (event.button) {
case 0:
return ig.KEY.MOUSE_LEFT;
case 1:
return ig.KEY.MOUSE_MIDDLE;
case 2:
return ig.KEY.MOUSE_RIGHT;
case 3:
return ig.KEY.MOUSE_BACK;
case 4:
return ig.KEY.MOUSE_FORWARD;
}
}

// idk, fall back to the left mouse button. That's kind of what the default
// implementation does though.
return ig.KEY.MOUSE_LEFT;
},
});

// Finally, some nice injection places.
sc.KeyBinderGui.inject({
show(...args) {
this.parent(...args);
window.addEventListener('mousedown', this.bindedKeyCheck, false);
},

hide(...args) {
this.parent(...args);
window.removeEventListener('mousedown', this.bindedKeyCheck);
},

onKeyCheck(event) {
event.preventDefault();

let keyCode = ig.input.getKeyCodeFromEvent(event);
if (ig.interact.isBlocked() || this._isBlackedListed(keyCode)) return;

// This call was added by me. Just in case. Because the `stopPropagation`
// call in `ig.Input` saved me from re-binds of left/right mouse buttons to
// whatever else other than interactions with menus.
event.stopPropagation();

if (this.finishCallback != null) {
this.finishCallback(keyCode, this.isAlternative, false);
}
this.hide();
},
});

0 comments on commit bddaea1

Please sign in to comment.