mirror of
https://github.com/redphx/better-xcloud.git
synced 2025-06-06 23:57:19 +02:00
Reduce Virtual Controller's input latency
This commit is contained in:
parent
8d7fbf2804
commit
153873e034
137
dist/better-xcloud.lite.user.js
vendored
137
dist/better-xcloud.lite.user.js
vendored
@ -1,7 +1,7 @@
|
|||||||
// ==UserScript==
|
// ==UserScript==
|
||||||
// @name Better xCloud (Lite)
|
// @name Better xCloud (Lite)
|
||||||
// @namespace https://github.com/redphx
|
// @namespace https://github.com/redphx
|
||||||
// @version 6.2.0
|
// @version 6.2.1-beta
|
||||||
// @description Improve Xbox Cloud Gaming (xCloud) experience
|
// @description Improve Xbox Cloud Gaming (xCloud) experience
|
||||||
// @author redphx
|
// @author redphx
|
||||||
// @license MIT
|
// @license MIT
|
||||||
@ -105,7 +105,7 @@ class UserAgent {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
var SCRIPT_VERSION = "6.2.0", SCRIPT_VARIANT = "lite", AppInterface = window.AppInterface;
|
var SCRIPT_VERSION = "6.2.1-beta", SCRIPT_VARIANT = "lite", AppInterface = window.AppInterface;
|
||||||
UserAgent.init();
|
UserAgent.init();
|
||||||
var userAgent = window.navigator.userAgent.toLowerCase(), isTv = userAgent.includes("smart-tv") || userAgent.includes("smarttv") || /\baft.*\b/.test(userAgent), isVr = window.navigator.userAgent.includes("VR") && window.navigator.userAgent.includes("OculusBrowser"), browserHasTouchSupport = "ontouchstart" in window || navigator.maxTouchPoints > 0, userAgentHasTouchSupport = !isTv && !isVr && browserHasTouchSupport, STATES = {
|
var userAgent = window.navigator.userAgent.toLowerCase(), isTv = userAgent.includes("smart-tv") || userAgent.includes("smarttv") || /\baft.*\b/.test(userAgent), isVr = window.navigator.userAgent.includes("VR") && window.navigator.userAgent.includes("OculusBrowser"), browserHasTouchSupport = "ontouchstart" in window || navigator.maxTouchPoints > 0, userAgentHasTouchSupport = !isTv && !isVr && browserHasTouchSupport, STATES = {
|
||||||
supportedRegion: !0,
|
supportedRegion: !0,
|
||||||
@ -2792,17 +2792,37 @@ function hasGamepad() {
|
|||||||
if (gamepad?.connected) return !0;
|
if (gamepad?.connected) return !0;
|
||||||
return !1;
|
return !1;
|
||||||
}
|
}
|
||||||
class StreamSettings {
|
function generateVirtualControllerMapping(index, override = {}) {
|
||||||
static settings = {
|
return Object.assign({}, {
|
||||||
settings: {},
|
GamepadIndex: index,
|
||||||
xCloudPollingMode: "all",
|
A: 0,
|
||||||
deviceVibrationIntensity: 0,
|
B: 0,
|
||||||
controllerPollingRate: 4,
|
X: 0,
|
||||||
controllers: {},
|
Y: 0,
|
||||||
mkbPreset: null,
|
LeftShoulder: 0,
|
||||||
keyboardShortcuts: {}
|
RightShoulder: 0,
|
||||||
};
|
LeftTrigger: 0,
|
||||||
static CONTROLLER_CUSTOMIZATION_MAPPING = {
|
RightTrigger: 0,
|
||||||
|
View: 0,
|
||||||
|
Menu: 0,
|
||||||
|
LeftThumb: 0,
|
||||||
|
RightThumb: 0,
|
||||||
|
DPadUp: 0,
|
||||||
|
DPadDown: 0,
|
||||||
|
DPadLeft: 0,
|
||||||
|
DPadRight: 0,
|
||||||
|
Nexus: 0,
|
||||||
|
LeftThumbXAxis: 0,
|
||||||
|
LeftThumbYAxis: 0,
|
||||||
|
RightThumbXAxis: 0,
|
||||||
|
RightThumbYAxis: 0,
|
||||||
|
PhysicalPhysicality: 0,
|
||||||
|
VirtualPhysicality: 0,
|
||||||
|
Dirty: !1,
|
||||||
|
Virtual: !1
|
||||||
|
}, override);
|
||||||
|
}
|
||||||
|
var XCLOUD_GAMEPAD_KEY_MAPPING = {
|
||||||
0: "A",
|
0: "A",
|
||||||
1: "B",
|
1: "B",
|
||||||
2: "X",
|
2: "X",
|
||||||
@ -2821,7 +2841,29 @@ class StreamSettings {
|
|||||||
204: "RightStickAxes",
|
204: "RightStickAxes",
|
||||||
8: "View",
|
8: "View",
|
||||||
9: "Menu",
|
9: "Menu",
|
||||||
17: "Share"
|
16: "Nexus",
|
||||||
|
17: "Share",
|
||||||
|
102: "LeftThumbXAxis",
|
||||||
|
103: "LeftThumbXAxis",
|
||||||
|
100: "LeftThumbYAxis",
|
||||||
|
101: "LeftThumbYAxis",
|
||||||
|
202: "RightThumbXAxis",
|
||||||
|
203: "RightThumbXAxis",
|
||||||
|
200: "RightThumbYAxis",
|
||||||
|
201: "RightThumbYAxis"
|
||||||
|
};
|
||||||
|
function toXcloudGamepadKey(gamepadKey) {
|
||||||
|
return XCLOUD_GAMEPAD_KEY_MAPPING[gamepadKey];
|
||||||
|
}
|
||||||
|
class StreamSettings {
|
||||||
|
static settings = {
|
||||||
|
settings: {},
|
||||||
|
xCloudPollingMode: "all",
|
||||||
|
deviceVibrationIntensity: 0,
|
||||||
|
controllerPollingRate: 4,
|
||||||
|
controllers: {},
|
||||||
|
mkbPreset: null,
|
||||||
|
keyboardShortcuts: {}
|
||||||
};
|
};
|
||||||
static getPref(key) {
|
static getPref(key) {
|
||||||
return getPref(key);
|
return getPref(key);
|
||||||
@ -2853,10 +2895,10 @@ class StreamSettings {
|
|||||||
vibrationIntensity: 1
|
vibrationIntensity: 1
|
||||||
}, gamepadKey;
|
}, gamepadKey;
|
||||||
for (gamepadKey in customization.mapping) {
|
for (gamepadKey in customization.mapping) {
|
||||||
let gamepadStr = StreamSettings.CONTROLLER_CUSTOMIZATION_MAPPING[gamepadKey];
|
let gamepadStr = toXcloudGamepadKey(gamepadKey);
|
||||||
if (!gamepadStr) continue;
|
if (!gamepadStr) continue;
|
||||||
let mappedKey = customization.mapping[gamepadKey];
|
let mappedKey = customization.mapping[gamepadKey];
|
||||||
if (typeof mappedKey === "number") converted.mapping[gamepadStr] = StreamSettings.CONTROLLER_CUSTOMIZATION_MAPPING[mappedKey];
|
if (typeof mappedKey === "number") converted.mapping[gamepadStr] = toXcloudGamepadKey(mappedKey);
|
||||||
else converted.mapping[gamepadStr] = !1;
|
else converted.mapping[gamepadStr] = !1;
|
||||||
}
|
}
|
||||||
return StreamSettings.preCalculateControllerRange(converted.ranges, "LeftTrigger", customization.settings.leftTriggerRange), StreamSettings.preCalculateControllerRange(converted.ranges, "RightTrigger", customization.settings.rightTriggerRange), StreamSettings.preCalculateControllerRange(converted.ranges, "LeftThumb", customization.settings.leftStickDeadzone), StreamSettings.preCalculateControllerRange(converted.ranges, "RightThumb", customization.settings.rightStickDeadzone), converted.vibrationIntensity = customization.settings.vibrationIntensity / 100, converted;
|
return StreamSettings.preCalculateControllerRange(converted.ranges, "LeftTrigger", customization.settings.leftTriggerRange), StreamSettings.preCalculateControllerRange(converted.ranges, "RightTrigger", customization.settings.rightTriggerRange), StreamSettings.preCalculateControllerRange(converted.ranges, "LeftThumb", customization.settings.leftStickDeadzone), StreamSettings.preCalculateControllerRange(converted.ranges, "RightThumb", customization.settings.rightStickDeadzone), converted.vibrationIntensity = customization.settings.vibrationIntensity / 100, converted;
|
||||||
@ -2982,7 +3024,7 @@ class NativeMkbHandler extends MkbHandler {
|
|||||||
mouseButtonsPressed = 0;
|
mouseButtonsPressed = 0;
|
||||||
mouseVerticalMultiply = 0;
|
mouseVerticalMultiply = 0;
|
||||||
mouseHorizontalMultiply = 0;
|
mouseHorizontalMultiply = 0;
|
||||||
inputSink;
|
inputChannel;
|
||||||
popup;
|
popup;
|
||||||
constructor() {
|
constructor() {
|
||||||
super();
|
super();
|
||||||
@ -3024,7 +3066,7 @@ class NativeMkbHandler extends MkbHandler {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
init() {
|
init() {
|
||||||
this.pointerClient = PointerClient.getInstance(), this.inputSink = window.BX_EXPOSED.inputSink, this.updateInputConfigurationAsync(!1);
|
this.pointerClient = PointerClient.getInstance(), this.inputChannel = window.BX_EXPOSED.inputChannel, this.updateInputConfigurationAsync(!1);
|
||||||
try {
|
try {
|
||||||
this.pointerClient.start(STATES.pointerServerPort, this);
|
this.pointerClient.start(STATES.pointerServerPort, this);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
@ -3109,7 +3151,7 @@ class NativeMkbHandler extends MkbHandler {
|
|||||||
return this.enabled;
|
return this.enabled;
|
||||||
}
|
}
|
||||||
sendMouseInput(data) {
|
sendMouseInput(data) {
|
||||||
data.Type = 0, this.inputSink?.onMouseInput(data);
|
data.Type = 0, this.inputChannel?.queueMouseInput(data);
|
||||||
}
|
}
|
||||||
resetMouseInput() {
|
resetMouseInput() {
|
||||||
this.mouseButtonsPressed = 0, this.sendMouseInput({
|
this.mouseButtonsPressed = 0, this.sendMouseInput({
|
||||||
@ -3202,6 +3244,7 @@ class EmulatedMkbHandler extends MkbHandler {
|
|||||||
vibrationActuator: null
|
vibrationActuator: null
|
||||||
};
|
};
|
||||||
nativeGetGamepads;
|
nativeGetGamepads;
|
||||||
|
xCloudGamepad = generateVirtualControllerMapping(0);
|
||||||
initialized = !1;
|
initialized = !1;
|
||||||
enabled = !1;
|
enabled = !1;
|
||||||
mouseDataProvider;
|
mouseDataProvider;
|
||||||
@ -3216,14 +3259,14 @@ class EmulatedMkbHandler extends MkbHandler {
|
|||||||
RIGHT_STICK_Y = [];
|
RIGHT_STICK_Y = [];
|
||||||
popup;
|
popup;
|
||||||
STICK_MAP = {
|
STICK_MAP = {
|
||||||
102: [this.LEFT_STICK_X, 0, -1],
|
102: [this.LEFT_STICK_X, -1],
|
||||||
103: [this.LEFT_STICK_X, 0, 1],
|
103: [this.LEFT_STICK_X, 1],
|
||||||
100: [this.LEFT_STICK_Y, 1, -1],
|
100: [this.LEFT_STICK_Y, 1],
|
||||||
101: [this.LEFT_STICK_Y, 1, 1],
|
101: [this.LEFT_STICK_Y, -1],
|
||||||
202: [this.RIGHT_STICK_X, 2, -1],
|
202: [this.RIGHT_STICK_X, -1],
|
||||||
203: [this.RIGHT_STICK_X, 2, 1],
|
203: [this.RIGHT_STICK_X, 1],
|
||||||
200: [this.RIGHT_STICK_Y, 3, -1],
|
200: [this.RIGHT_STICK_Y, 1],
|
||||||
201: [this.RIGHT_STICK_Y, 3, 1]
|
201: [this.RIGHT_STICK_Y, -1]
|
||||||
};
|
};
|
||||||
constructor() {
|
constructor() {
|
||||||
super();
|
super();
|
||||||
@ -3236,31 +3279,32 @@ class EmulatedMkbHandler extends MkbHandler {
|
|||||||
};
|
};
|
||||||
getVirtualGamepad = () => this.VIRTUAL_GAMEPAD;
|
getVirtualGamepad = () => this.VIRTUAL_GAMEPAD;
|
||||||
updateStick(stick, x, y) {
|
updateStick(stick, x, y) {
|
||||||
let virtualGamepad = this.getVirtualGamepad();
|
let gamepad = this.xCloudGamepad;
|
||||||
virtualGamepad.axes[stick * 2] = x, virtualGamepad.axes[stick * 2 + 1] = y, virtualGamepad.timestamp = performance.now();
|
if (stick === 0) gamepad.LeftThumbXAxis = x, gamepad.LeftThumbYAxis = -y;
|
||||||
|
else gamepad.RightThumbXAxis = x, gamepad.RightThumbYAxis = -y;
|
||||||
|
window.BX_EXPOSED.inputChannel?.sendGamepadInput(performance.now(), [this.xCloudGamepad]);
|
||||||
}
|
}
|
||||||
vectorLength = (x, y) => Math.sqrt(x ** 2 + y ** 2);
|
vectorLength = (x, y) => Math.sqrt(x ** 2 + y ** 2);
|
||||||
resetGamepad() {
|
resetXcloudGamepads() {
|
||||||
let gamepad = this.getVirtualGamepad();
|
let index = getPref("mkb.p1.slot") - 1;
|
||||||
gamepad.axes = [0, 0, 0, 0];
|
this.xCloudGamepad = generateVirtualControllerMapping(0, {
|
||||||
for (let button of gamepad.buttons)
|
GamepadIndex: getPref("localCoOp.enabled") ? index : 0,
|
||||||
button.pressed = !1, button.value = 0;
|
Dirty: !0
|
||||||
gamepad.timestamp = performance.now();
|
}), this.VIRTUAL_GAMEPAD.index = index;
|
||||||
}
|
}
|
||||||
pressButton(buttonIndex, pressed) {
|
pressButton(buttonIndex, pressed) {
|
||||||
let virtualGamepad = this.getVirtualGamepad();
|
let xCloudKey = toXcloudGamepadKey(buttonIndex);
|
||||||
if (buttonIndex >= 100) {
|
if (buttonIndex >= 100) {
|
||||||
let [valueArr, axisIndex] = this.STICK_MAP[buttonIndex];
|
let [valueArr] = this.STICK_MAP[buttonIndex];
|
||||||
valueArr = valueArr, axisIndex = axisIndex;
|
|
||||||
for (let i = valueArr.length - 1;i >= 0; i--)
|
for (let i = valueArr.length - 1;i >= 0; i--)
|
||||||
if (valueArr[i] === buttonIndex) valueArr.splice(i, 1);
|
if (valueArr[i] === buttonIndex) valueArr.splice(i, 1);
|
||||||
pressed && valueArr.push(buttonIndex);
|
pressed && valueArr.push(buttonIndex);
|
||||||
let value;
|
let value;
|
||||||
if (valueArr.length) value = this.STICK_MAP[valueArr[valueArr.length - 1]][2];
|
if (valueArr.length) value = this.STICK_MAP[valueArr[valueArr.length - 1]][1];
|
||||||
else value = 0;
|
else value = 0;
|
||||||
virtualGamepad.axes[axisIndex] = value;
|
this.xCloudGamepad[xCloudKey] = value;
|
||||||
} else virtualGamepad.buttons[buttonIndex].pressed = pressed, virtualGamepad.buttons[buttonIndex].value = pressed ? 1 : 0;
|
} else this.xCloudGamepad[xCloudKey] = pressed ? 1 : 0;
|
||||||
virtualGamepad.timestamp = performance.now();
|
window.BX_EXPOSED.inputChannel?.sendGamepadInput(performance.now(), [this.xCloudGamepad]);
|
||||||
}
|
}
|
||||||
onKeyboardEvent = (e) => {
|
onKeyboardEvent = (e) => {
|
||||||
let isKeyDown = e.type === "keydown";
|
let isKeyDown = e.type === "keydown";
|
||||||
@ -3336,7 +3380,7 @@ class EmulatedMkbHandler extends MkbHandler {
|
|||||||
else document.pointerLockElement && document.exitPointerLock();
|
else document.pointerLockElement && document.exitPointerLock();
|
||||||
}
|
}
|
||||||
refreshPresetData() {
|
refreshPresetData() {
|
||||||
this.PRESET = window.BX_STREAM_SETTINGS.mkbPreset, this.resetGamepad();
|
this.PRESET = window.BX_STREAM_SETTINGS.mkbPreset, this.resetXcloudGamepads();
|
||||||
}
|
}
|
||||||
waitForMouseData(showPopup) {
|
waitForMouseData(showPopup) {
|
||||||
this.popup.toggleVisibility(showPopup);
|
this.popup.toggleVisibility(showPopup);
|
||||||
@ -3395,12 +3439,9 @@ class EmulatedMkbHandler extends MkbHandler {
|
|||||||
else document.removeEventListener("pointerlockchange", this.onPointerLockChange), document.removeEventListener("pointerlockerror", this.onPointerLockError);
|
else document.removeEventListener("pointerlockchange", this.onPointerLockChange), document.removeEventListener("pointerlockerror", this.onPointerLockError);
|
||||||
window.removeEventListener(BxEvent.XCLOUD_POLLING_MODE_CHANGED, this.onPollingModeChanged), BxEventBus.Script.off("dialog.shown", this.onDialogShown), this.mouseDataProvider?.destroy(), window.removeEventListener(BxEvent.XCLOUD_POLLING_MODE_CHANGED, this.onPollingModeChanged);
|
window.removeEventListener(BxEvent.XCLOUD_POLLING_MODE_CHANGED, this.onPollingModeChanged), BxEventBus.Script.off("dialog.shown", this.onDialogShown), this.mouseDataProvider?.destroy(), window.removeEventListener(BxEvent.XCLOUD_POLLING_MODE_CHANGED, this.onPollingModeChanged);
|
||||||
}
|
}
|
||||||
updateGamepadSlots() {
|
|
||||||
this.VIRTUAL_GAMEPAD.index = getPref("mkb.p1.slot") - 1;
|
|
||||||
}
|
|
||||||
start() {
|
start() {
|
||||||
if (!this.enabled) this.enabled = !0, Toast.show(t("virtual-controller"), t("enabled"), { instant: !0 });
|
if (!this.enabled) this.enabled = !0, Toast.show(t("virtual-controller"), t("enabled"), { instant: !0 });
|
||||||
this.isPolling = !0, this.escKeyDownTime = -1, this.resetGamepad(), this.updateGamepadSlots(), window.navigator.getGamepads = this.patchedGetGamepads, this.waitForMouseData(!1), this.mouseDataProvider?.start();
|
this.isPolling = !0, this.escKeyDownTime = -1, window.BX_EXPOSED.toggleLocalCoOp(getPref("localCoOp.enabled")), this.resetXcloudGamepads(), window.navigator.getGamepads = this.patchedGetGamepads, this.waitForMouseData(!1), this.mouseDataProvider?.start();
|
||||||
let virtualGamepad = this.getVirtualGamepad();
|
let virtualGamepad = this.getVirtualGamepad();
|
||||||
virtualGamepad.connected = !0, virtualGamepad.timestamp = performance.now(), BxEvent.dispatch(window, "gamepadconnected", {
|
virtualGamepad.connected = !0, virtualGamepad.timestamp = performance.now(), BxEvent.dispatch(window, "gamepadconnected", {
|
||||||
gamepad: virtualGamepad
|
gamepad: virtualGamepad
|
||||||
@ -3409,7 +3450,7 @@ class EmulatedMkbHandler extends MkbHandler {
|
|||||||
stop() {
|
stop() {
|
||||||
this.enabled = !1, this.isPolling = !1, this.escKeyDownTime = -1;
|
this.enabled = !1, this.isPolling = !1, this.escKeyDownTime = -1;
|
||||||
let virtualGamepad = this.getVirtualGamepad();
|
let virtualGamepad = this.getVirtualGamepad();
|
||||||
if (virtualGamepad.connected) this.resetGamepad(), virtualGamepad.connected = !1, virtualGamepad.timestamp = performance.now(), BxEvent.dispatch(window, "gamepaddisconnected", {
|
if (virtualGamepad.connected) this.resetXcloudGamepads(), virtualGamepad.connected = !1, virtualGamepad.timestamp = performance.now(), BxEvent.dispatch(window, "gamepaddisconnected", {
|
||||||
gamepad: virtualGamepad
|
gamepad: virtualGamepad
|
||||||
}), window.navigator.getGamepads = this.nativeGetGamepads;
|
}), window.navigator.getGamepads = this.nativeGetGamepads;
|
||||||
this.waitForMouseData(!0), this.mouseDataProvider?.stop();
|
this.waitForMouseData(!0), this.mouseDataProvider?.stop();
|
||||||
|
133
dist/better-xcloud.user.js
vendored
133
dist/better-xcloud.user.js
vendored
@ -1,7 +1,7 @@
|
|||||||
// ==UserScript==
|
// ==UserScript==
|
||||||
// @name Better xCloud
|
// @name Better xCloud
|
||||||
// @namespace https://github.com/redphx
|
// @namespace https://github.com/redphx
|
||||||
// @version 6.2.0
|
// @version 6.2.1-beta
|
||||||
// @description Improve Xbox Cloud Gaming (xCloud) experience
|
// @description Improve Xbox Cloud Gaming (xCloud) experience
|
||||||
// @author redphx
|
// @author redphx
|
||||||
// @license MIT
|
// @license MIT
|
||||||
@ -107,7 +107,7 @@ class UserAgent {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
var SCRIPT_VERSION = "6.2.0", SCRIPT_VARIANT = "full", AppInterface = window.AppInterface;
|
var SCRIPT_VERSION = "6.2.1-beta", SCRIPT_VARIANT = "full", AppInterface = window.AppInterface;
|
||||||
UserAgent.init();
|
UserAgent.init();
|
||||||
var userAgent = window.navigator.userAgent.toLowerCase(), isTv = userAgent.includes("smart-tv") || userAgent.includes("smarttv") || /\baft.*\b/.test(userAgent), isVr = window.navigator.userAgent.includes("VR") && window.navigator.userAgent.includes("OculusBrowser"), browserHasTouchSupport = "ontouchstart" in window || navigator.maxTouchPoints > 0, userAgentHasTouchSupport = !isTv && !isVr && browserHasTouchSupport, STATES = {
|
var userAgent = window.navigator.userAgent.toLowerCase(), isTv = userAgent.includes("smart-tv") || userAgent.includes("smarttv") || /\baft.*\b/.test(userAgent), isVr = window.navigator.userAgent.includes("VR") && window.navigator.userAgent.includes("OculusBrowser"), browserHasTouchSupport = "ontouchstart" in window || navigator.maxTouchPoints > 0, userAgentHasTouchSupport = !isTv && !isVr && browserHasTouchSupport, STATES = {
|
||||||
supportedRegion: !0,
|
supportedRegion: !0,
|
||||||
@ -2908,9 +2908,9 @@ function hasGamepad() {
|
|||||||
if (gamepad?.connected) return !0;
|
if (gamepad?.connected) return !0;
|
||||||
return !1;
|
return !1;
|
||||||
}
|
}
|
||||||
function generateVirtualControllerMapping(override = {}) {
|
function generateVirtualControllerMapping(index, override = {}) {
|
||||||
return Object.assign({}, {
|
return Object.assign({}, {
|
||||||
GamepadIndex: 0,
|
GamepadIndex: index,
|
||||||
A: 0,
|
A: 0,
|
||||||
B: 0,
|
B: 0,
|
||||||
X: 0,
|
X: 0,
|
||||||
@ -2941,17 +2941,7 @@ function generateVirtualControllerMapping(override = {}) {
|
|||||||
function getGamepadPrompt(gamepadKey) {
|
function getGamepadPrompt(gamepadKey) {
|
||||||
return GamepadKeyName[gamepadKey][1];
|
return GamepadKeyName[gamepadKey][1];
|
||||||
}
|
}
|
||||||
class StreamSettings {
|
var XCLOUD_GAMEPAD_KEY_MAPPING = {
|
||||||
static settings = {
|
|
||||||
settings: {},
|
|
||||||
xCloudPollingMode: "all",
|
|
||||||
deviceVibrationIntensity: 0,
|
|
||||||
controllerPollingRate: 4,
|
|
||||||
controllers: {},
|
|
||||||
mkbPreset: null,
|
|
||||||
keyboardShortcuts: {}
|
|
||||||
};
|
|
||||||
static CONTROLLER_CUSTOMIZATION_MAPPING = {
|
|
||||||
0: "A",
|
0: "A",
|
||||||
1: "B",
|
1: "B",
|
||||||
2: "X",
|
2: "X",
|
||||||
@ -2970,7 +2960,29 @@ class StreamSettings {
|
|||||||
204: "RightStickAxes",
|
204: "RightStickAxes",
|
||||||
8: "View",
|
8: "View",
|
||||||
9: "Menu",
|
9: "Menu",
|
||||||
17: "Share"
|
16: "Nexus",
|
||||||
|
17: "Share",
|
||||||
|
102: "LeftThumbXAxis",
|
||||||
|
103: "LeftThumbXAxis",
|
||||||
|
100: "LeftThumbYAxis",
|
||||||
|
101: "LeftThumbYAxis",
|
||||||
|
202: "RightThumbXAxis",
|
||||||
|
203: "RightThumbXAxis",
|
||||||
|
200: "RightThumbYAxis",
|
||||||
|
201: "RightThumbYAxis"
|
||||||
|
};
|
||||||
|
function toXcloudGamepadKey(gamepadKey) {
|
||||||
|
return XCLOUD_GAMEPAD_KEY_MAPPING[gamepadKey];
|
||||||
|
}
|
||||||
|
class StreamSettings {
|
||||||
|
static settings = {
|
||||||
|
settings: {},
|
||||||
|
xCloudPollingMode: "all",
|
||||||
|
deviceVibrationIntensity: 0,
|
||||||
|
controllerPollingRate: 4,
|
||||||
|
controllers: {},
|
||||||
|
mkbPreset: null,
|
||||||
|
keyboardShortcuts: {}
|
||||||
};
|
};
|
||||||
static getPref(key) {
|
static getPref(key) {
|
||||||
return getPref(key);
|
return getPref(key);
|
||||||
@ -3002,10 +3014,10 @@ class StreamSettings {
|
|||||||
vibrationIntensity: 1
|
vibrationIntensity: 1
|
||||||
}, gamepadKey;
|
}, gamepadKey;
|
||||||
for (gamepadKey in customization.mapping) {
|
for (gamepadKey in customization.mapping) {
|
||||||
let gamepadStr = StreamSettings.CONTROLLER_CUSTOMIZATION_MAPPING[gamepadKey];
|
let gamepadStr = toXcloudGamepadKey(gamepadKey);
|
||||||
if (!gamepadStr) continue;
|
if (!gamepadStr) continue;
|
||||||
let mappedKey = customization.mapping[gamepadKey];
|
let mappedKey = customization.mapping[gamepadKey];
|
||||||
if (typeof mappedKey === "number") converted.mapping[gamepadStr] = StreamSettings.CONTROLLER_CUSTOMIZATION_MAPPING[mappedKey];
|
if (typeof mappedKey === "number") converted.mapping[gamepadStr] = toXcloudGamepadKey(mappedKey);
|
||||||
else converted.mapping[gamepadStr] = !1;
|
else converted.mapping[gamepadStr] = !1;
|
||||||
}
|
}
|
||||||
return StreamSettings.preCalculateControllerRange(converted.ranges, "LeftTrigger", customization.settings.leftTriggerRange), StreamSettings.preCalculateControllerRange(converted.ranges, "RightTrigger", customization.settings.rightTriggerRange), StreamSettings.preCalculateControllerRange(converted.ranges, "LeftThumb", customization.settings.leftStickDeadzone), StreamSettings.preCalculateControllerRange(converted.ranges, "RightThumb", customization.settings.rightStickDeadzone), converted.vibrationIntensity = customization.settings.vibrationIntensity / 100, converted;
|
return StreamSettings.preCalculateControllerRange(converted.ranges, "LeftTrigger", customization.settings.leftTriggerRange), StreamSettings.preCalculateControllerRange(converted.ranges, "RightTrigger", customization.settings.rightTriggerRange), StreamSettings.preCalculateControllerRange(converted.ranges, "LeftThumb", customization.settings.leftStickDeadzone), StreamSettings.preCalculateControllerRange(converted.ranges, "RightThumb", customization.settings.rightStickDeadzone), converted.vibrationIntensity = customization.settings.vibrationIntensity / 100, converted;
|
||||||
@ -3131,7 +3143,7 @@ class NativeMkbHandler extends MkbHandler {
|
|||||||
mouseButtonsPressed = 0;
|
mouseButtonsPressed = 0;
|
||||||
mouseVerticalMultiply = 0;
|
mouseVerticalMultiply = 0;
|
||||||
mouseHorizontalMultiply = 0;
|
mouseHorizontalMultiply = 0;
|
||||||
inputSink;
|
inputChannel;
|
||||||
popup;
|
popup;
|
||||||
constructor() {
|
constructor() {
|
||||||
super();
|
super();
|
||||||
@ -3173,7 +3185,7 @@ class NativeMkbHandler extends MkbHandler {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
init() {
|
init() {
|
||||||
this.pointerClient = PointerClient.getInstance(), this.inputSink = window.BX_EXPOSED.inputSink, this.updateInputConfigurationAsync(!1);
|
this.pointerClient = PointerClient.getInstance(), this.inputChannel = window.BX_EXPOSED.inputChannel, this.updateInputConfigurationAsync(!1);
|
||||||
try {
|
try {
|
||||||
this.pointerClient.start(STATES.pointerServerPort, this);
|
this.pointerClient.start(STATES.pointerServerPort, this);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
@ -3258,7 +3270,7 @@ class NativeMkbHandler extends MkbHandler {
|
|||||||
return this.enabled;
|
return this.enabled;
|
||||||
}
|
}
|
||||||
sendMouseInput(data) {
|
sendMouseInput(data) {
|
||||||
data.Type = 0, this.inputSink?.onMouseInput(data);
|
data.Type = 0, this.inputChannel?.queueMouseInput(data);
|
||||||
}
|
}
|
||||||
resetMouseInput() {
|
resetMouseInput() {
|
||||||
this.mouseButtonsPressed = 0, this.sendMouseInput({
|
this.mouseButtonsPressed = 0, this.sendMouseInput({
|
||||||
@ -3351,6 +3363,7 @@ class EmulatedMkbHandler extends MkbHandler {
|
|||||||
vibrationActuator: null
|
vibrationActuator: null
|
||||||
};
|
};
|
||||||
nativeGetGamepads;
|
nativeGetGamepads;
|
||||||
|
xCloudGamepad = generateVirtualControllerMapping(0);
|
||||||
initialized = !1;
|
initialized = !1;
|
||||||
enabled = !1;
|
enabled = !1;
|
||||||
mouseDataProvider;
|
mouseDataProvider;
|
||||||
@ -3365,14 +3378,14 @@ class EmulatedMkbHandler extends MkbHandler {
|
|||||||
RIGHT_STICK_Y = [];
|
RIGHT_STICK_Y = [];
|
||||||
popup;
|
popup;
|
||||||
STICK_MAP = {
|
STICK_MAP = {
|
||||||
102: [this.LEFT_STICK_X, 0, -1],
|
102: [this.LEFT_STICK_X, -1],
|
||||||
103: [this.LEFT_STICK_X, 0, 1],
|
103: [this.LEFT_STICK_X, 1],
|
||||||
100: [this.LEFT_STICK_Y, 1, -1],
|
100: [this.LEFT_STICK_Y, 1],
|
||||||
101: [this.LEFT_STICK_Y, 1, 1],
|
101: [this.LEFT_STICK_Y, -1],
|
||||||
202: [this.RIGHT_STICK_X, 2, -1],
|
202: [this.RIGHT_STICK_X, -1],
|
||||||
203: [this.RIGHT_STICK_X, 2, 1],
|
203: [this.RIGHT_STICK_X, 1],
|
||||||
200: [this.RIGHT_STICK_Y, 3, -1],
|
200: [this.RIGHT_STICK_Y, 1],
|
||||||
201: [this.RIGHT_STICK_Y, 3, 1]
|
201: [this.RIGHT_STICK_Y, -1]
|
||||||
};
|
};
|
||||||
constructor() {
|
constructor() {
|
||||||
super();
|
super();
|
||||||
@ -3385,31 +3398,32 @@ class EmulatedMkbHandler extends MkbHandler {
|
|||||||
};
|
};
|
||||||
getVirtualGamepad = () => this.VIRTUAL_GAMEPAD;
|
getVirtualGamepad = () => this.VIRTUAL_GAMEPAD;
|
||||||
updateStick(stick, x, y) {
|
updateStick(stick, x, y) {
|
||||||
let virtualGamepad = this.getVirtualGamepad();
|
let gamepad = this.xCloudGamepad;
|
||||||
virtualGamepad.axes[stick * 2] = x, virtualGamepad.axes[stick * 2 + 1] = y, virtualGamepad.timestamp = performance.now();
|
if (stick === 0) gamepad.LeftThumbXAxis = x, gamepad.LeftThumbYAxis = -y;
|
||||||
|
else gamepad.RightThumbXAxis = x, gamepad.RightThumbYAxis = -y;
|
||||||
|
window.BX_EXPOSED.inputChannel?.sendGamepadInput(performance.now(), [this.xCloudGamepad]);
|
||||||
}
|
}
|
||||||
vectorLength = (x, y) => Math.sqrt(x ** 2 + y ** 2);
|
vectorLength = (x, y) => Math.sqrt(x ** 2 + y ** 2);
|
||||||
resetGamepad() {
|
resetXcloudGamepads() {
|
||||||
let gamepad = this.getVirtualGamepad();
|
let index = getPref("mkb.p1.slot") - 1;
|
||||||
gamepad.axes = [0, 0, 0, 0];
|
this.xCloudGamepad = generateVirtualControllerMapping(0, {
|
||||||
for (let button of gamepad.buttons)
|
GamepadIndex: getPref("localCoOp.enabled") ? index : 0,
|
||||||
button.pressed = !1, button.value = 0;
|
Dirty: !0
|
||||||
gamepad.timestamp = performance.now();
|
}), this.VIRTUAL_GAMEPAD.index = index;
|
||||||
}
|
}
|
||||||
pressButton(buttonIndex, pressed) {
|
pressButton(buttonIndex, pressed) {
|
||||||
let virtualGamepad = this.getVirtualGamepad();
|
let xCloudKey = toXcloudGamepadKey(buttonIndex);
|
||||||
if (buttonIndex >= 100) {
|
if (buttonIndex >= 100) {
|
||||||
let [valueArr, axisIndex] = this.STICK_MAP[buttonIndex];
|
let [valueArr] = this.STICK_MAP[buttonIndex];
|
||||||
valueArr = valueArr, axisIndex = axisIndex;
|
|
||||||
for (let i = valueArr.length - 1;i >= 0; i--)
|
for (let i = valueArr.length - 1;i >= 0; i--)
|
||||||
if (valueArr[i] === buttonIndex) valueArr.splice(i, 1);
|
if (valueArr[i] === buttonIndex) valueArr.splice(i, 1);
|
||||||
pressed && valueArr.push(buttonIndex);
|
pressed && valueArr.push(buttonIndex);
|
||||||
let value;
|
let value;
|
||||||
if (valueArr.length) value = this.STICK_MAP[valueArr[valueArr.length - 1]][2];
|
if (valueArr.length) value = this.STICK_MAP[valueArr[valueArr.length - 1]][1];
|
||||||
else value = 0;
|
else value = 0;
|
||||||
virtualGamepad.axes[axisIndex] = value;
|
this.xCloudGamepad[xCloudKey] = value;
|
||||||
} else virtualGamepad.buttons[buttonIndex].pressed = pressed, virtualGamepad.buttons[buttonIndex].value = pressed ? 1 : 0;
|
} else this.xCloudGamepad[xCloudKey] = pressed ? 1 : 0;
|
||||||
virtualGamepad.timestamp = performance.now();
|
window.BX_EXPOSED.inputChannel?.sendGamepadInput(performance.now(), [this.xCloudGamepad]);
|
||||||
}
|
}
|
||||||
onKeyboardEvent = (e) => {
|
onKeyboardEvent = (e) => {
|
||||||
let isKeyDown = e.type === "keydown";
|
let isKeyDown = e.type === "keydown";
|
||||||
@ -3485,7 +3499,7 @@ class EmulatedMkbHandler extends MkbHandler {
|
|||||||
else document.pointerLockElement && document.exitPointerLock();
|
else document.pointerLockElement && document.exitPointerLock();
|
||||||
}
|
}
|
||||||
refreshPresetData() {
|
refreshPresetData() {
|
||||||
this.PRESET = window.BX_STREAM_SETTINGS.mkbPreset, this.resetGamepad();
|
this.PRESET = window.BX_STREAM_SETTINGS.mkbPreset, this.resetXcloudGamepads();
|
||||||
}
|
}
|
||||||
waitForMouseData(showPopup) {
|
waitForMouseData(showPopup) {
|
||||||
this.popup.toggleVisibility(showPopup);
|
this.popup.toggleVisibility(showPopup);
|
||||||
@ -3544,12 +3558,9 @@ class EmulatedMkbHandler extends MkbHandler {
|
|||||||
else document.removeEventListener("pointerlockchange", this.onPointerLockChange), document.removeEventListener("pointerlockerror", this.onPointerLockError);
|
else document.removeEventListener("pointerlockchange", this.onPointerLockChange), document.removeEventListener("pointerlockerror", this.onPointerLockError);
|
||||||
window.removeEventListener(BxEvent.XCLOUD_POLLING_MODE_CHANGED, this.onPollingModeChanged), BxEventBus.Script.off("dialog.shown", this.onDialogShown), this.mouseDataProvider?.destroy(), window.removeEventListener(BxEvent.XCLOUD_POLLING_MODE_CHANGED, this.onPollingModeChanged);
|
window.removeEventListener(BxEvent.XCLOUD_POLLING_MODE_CHANGED, this.onPollingModeChanged), BxEventBus.Script.off("dialog.shown", this.onDialogShown), this.mouseDataProvider?.destroy(), window.removeEventListener(BxEvent.XCLOUD_POLLING_MODE_CHANGED, this.onPollingModeChanged);
|
||||||
}
|
}
|
||||||
updateGamepadSlots() {
|
|
||||||
this.VIRTUAL_GAMEPAD.index = getPref("mkb.p1.slot") - 1;
|
|
||||||
}
|
|
||||||
start() {
|
start() {
|
||||||
if (!this.enabled) this.enabled = !0, Toast.show(t("virtual-controller"), t("enabled"), { instant: !0 });
|
if (!this.enabled) this.enabled = !0, Toast.show(t("virtual-controller"), t("enabled"), { instant: !0 });
|
||||||
this.isPolling = !0, this.escKeyDownTime = -1, this.resetGamepad(), this.updateGamepadSlots(), window.navigator.getGamepads = this.patchedGetGamepads, this.waitForMouseData(!1), this.mouseDataProvider?.start();
|
this.isPolling = !0, this.escKeyDownTime = -1, window.BX_EXPOSED.toggleLocalCoOp(getPref("localCoOp.enabled")), this.resetXcloudGamepads(), window.navigator.getGamepads = this.patchedGetGamepads, this.waitForMouseData(!1), this.mouseDataProvider?.start();
|
||||||
let virtualGamepad = this.getVirtualGamepad();
|
let virtualGamepad = this.getVirtualGamepad();
|
||||||
virtualGamepad.connected = !0, virtualGamepad.timestamp = performance.now(), BxEvent.dispatch(window, "gamepadconnected", {
|
virtualGamepad.connected = !0, virtualGamepad.timestamp = performance.now(), BxEvent.dispatch(window, "gamepadconnected", {
|
||||||
gamepad: virtualGamepad
|
gamepad: virtualGamepad
|
||||||
@ -3558,7 +3569,7 @@ class EmulatedMkbHandler extends MkbHandler {
|
|||||||
stop() {
|
stop() {
|
||||||
this.enabled = !1, this.isPolling = !1, this.escKeyDownTime = -1;
|
this.enabled = !1, this.isPolling = !1, this.escKeyDownTime = -1;
|
||||||
let virtualGamepad = this.getVirtualGamepad();
|
let virtualGamepad = this.getVirtualGamepad();
|
||||||
if (virtualGamepad.connected) this.resetGamepad(), virtualGamepad.connected = !1, virtualGamepad.timestamp = performance.now(), BxEvent.dispatch(window, "gamepaddisconnected", {
|
if (virtualGamepad.connected) this.resetXcloudGamepads(), virtualGamepad.connected = !1, virtualGamepad.timestamp = performance.now(), BxEvent.dispatch(window, "gamepaddisconnected", {
|
||||||
gamepad: virtualGamepad
|
gamepad: virtualGamepad
|
||||||
}), window.navigator.getGamepads = this.nativeGetGamepads;
|
}), window.navigator.getGamepads = this.nativeGetGamepads;
|
||||||
this.waitForMouseData(!0), this.mouseDataProvider?.stop();
|
this.waitForMouseData(!0), this.mouseDataProvider?.stop();
|
||||||
@ -4690,11 +4701,11 @@ true` + text;
|
|||||||
if (!str.includes(text)) return !1;
|
if (!str.includes(text)) return !1;
|
||||||
return str = str.replace(text, text + "return true;"), str;
|
return str = str.replace(text, text + "return true;"), str;
|
||||||
},
|
},
|
||||||
exposeInputSink(str) {
|
exposeInputChannel(str) {
|
||||||
let text = "this.controlChannel=null,this.inputChannel=null";
|
let index = str.indexOf("this.flushData=");
|
||||||
if (!str.includes(text)) return !1;
|
if (index < 0) return !1;
|
||||||
let newCode = "window.BX_EXPOSED.inputSink = this;";
|
let newCode = "window.BX_EXPOSED.inputChannel = this,";
|
||||||
return str = str.replace(text, newCode + text), str;
|
return str = PatcherUtils.insertAt(str, index, newCode), str;
|
||||||
},
|
},
|
||||||
disableNativeRequestPointerLock(str) {
|
disableNativeRequestPointerLock(str) {
|
||||||
let text = "async requestPointerLock(){";
|
let text = "async requestPointerLock(){";
|
||||||
@ -4892,7 +4903,6 @@ ${subsVar} = subs;
|
|||||||
}, PATCH_ORDERS = PatcherUtils.filterPatches([
|
}, PATCH_ORDERS = PatcherUtils.filterPatches([
|
||||||
...AppInterface && getPref("nativeMkb.mode") === "on" ? [
|
...AppInterface && getPref("nativeMkb.mode") === "on" ? [
|
||||||
"enableNativeMkb",
|
"enableNativeMkb",
|
||||||
"exposeInputSink",
|
|
||||||
"disableAbsoluteMouse"
|
"disableAbsoluteMouse"
|
||||||
] : [],
|
] : [],
|
||||||
"exposeReactCreateComponent",
|
"exposeReactCreateComponent",
|
||||||
@ -4952,6 +4962,7 @@ ${subsVar} = subs;
|
|||||||
STATES.browser.capabilities.touch && hideSections.includes("touch") && "ignorePlayWithTouchSection",
|
STATES.browser.capabilities.touch && hideSections.includes("touch") && "ignorePlayWithTouchSection",
|
||||||
hideSections.some((value) => ["native-mkb", "most-popular"].includes(value)) && "ignoreSiglSections"
|
hideSections.some((value) => ["native-mkb", "most-popular"].includes(value)) && "ignoreSiglSections"
|
||||||
]), STREAM_PAGE_PATCH_ORDERS = PatcherUtils.filterPatches([
|
]), STREAM_PAGE_PATCH_ORDERS = PatcherUtils.filterPatches([
|
||||||
|
"exposeInputChannel",
|
||||||
"patchXcloudTitleInfo",
|
"patchXcloudTitleInfo",
|
||||||
"disableGamepadDisconnectedScreen",
|
"disableGamepadDisconnectedScreen",
|
||||||
"patchStreamHud",
|
"patchStreamHud",
|
||||||
@ -5024,11 +5035,15 @@ class Patcher {
|
|||||||
if (!tmpStr) continue;
|
if (!tmpStr) continue;
|
||||||
modified = !0, patchedFuncStr = tmpStr, BxLogger.info(LOG_TAG2, `✅ ${patchName}`), appliedPatches.push(patchName), patchesToCheck.splice(patchIndex, 1), patchIndex--, PATCH_ORDERS = PATCH_ORDERS.filter((item2) => item2 != patchName), BxLogger.info(LOG_TAG2, "Remaining patches", PATCH_ORDERS);
|
modified = !0, patchedFuncStr = tmpStr, BxLogger.info(LOG_TAG2, `✅ ${patchName}`), appliedPatches.push(patchName), patchesToCheck.splice(patchIndex, 1), patchIndex--, PATCH_ORDERS = PATCH_ORDERS.filter((item2) => item2 != patchName), BxLogger.info(LOG_TAG2, "Remaining patches", PATCH_ORDERS);
|
||||||
}
|
}
|
||||||
if (modified) try {
|
if (modified) {
|
||||||
|
BX_FLAGS.Debug && console.time(LOG_TAG2);
|
||||||
|
try {
|
||||||
chunkData[chunkId] = eval(patchedFuncStr);
|
chunkData[chunkId] = eval(patchedFuncStr);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
if (e instanceof Error) BxLogger.error(LOG_TAG2, "Error", appliedPatches, e.message, patchedFuncStr);
|
if (e instanceof Error) BxLogger.error(LOG_TAG2, "Error", appliedPatches, e.message, patchedFuncStr);
|
||||||
}
|
}
|
||||||
|
BX_FLAGS.Debug && console.timeEnd(LOG_TAG2);
|
||||||
|
}
|
||||||
if (appliedPatches.length) patchesMap[chunkId] = appliedPatches;
|
if (appliedPatches.length) patchesMap[chunkId] = appliedPatches;
|
||||||
}
|
}
|
||||||
if (Object.keys(patchesMap).length) patcherCache.saveToCache(patchesMap);
|
if (Object.keys(patchesMap).length) patcherCache.saveToCache(patchesMap);
|
||||||
@ -6341,7 +6356,7 @@ class MkbExtraSettings extends HTMLElement {
|
|||||||
})
|
})
|
||||||
})), { multiLines: !0 }),
|
})), { multiLines: !0 }),
|
||||||
createSettingRow(t("virtual-controller-slot"), SettingElement.fromPref("mkb.p1.slot", STORAGE.Global, () => {
|
createSettingRow(t("virtual-controller-slot"), SettingElement.fromPref("mkb.p1.slot", STORAGE.Global, () => {
|
||||||
EmulatedMkbHandler.getInstance()?.updateGamepadSlots();
|
EmulatedMkbHandler.getInstance()?.resetXcloudGamepads();
|
||||||
}))
|
}))
|
||||||
] : [], createSettingRow(t("in-game-keyboard-shortcuts"), CE("div", {
|
] : [], createSettingRow(t("in-game-keyboard-shortcuts"), CE("div", {
|
||||||
class: "bx-preset-row",
|
class: "bx-preset-row",
|
||||||
@ -7385,7 +7400,7 @@ class VirtualControllerShortcut {
|
|||||||
static pressXboxButton() {
|
static pressXboxButton() {
|
||||||
let streamSession = window.BX_EXPOSED.streamSession;
|
let streamSession = window.BX_EXPOSED.streamSession;
|
||||||
if (!streamSession) return;
|
if (!streamSession) return;
|
||||||
let released = generateVirtualControllerMapping(), pressed = generateVirtualControllerMapping({
|
let released = generateVirtualControllerMapping(0), pressed = generateVirtualControllerMapping(0, {
|
||||||
Nexus: 1,
|
Nexus: 1,
|
||||||
VirtualPhysicality: 1024
|
VirtualPhysicality: 1024
|
||||||
});
|
});
|
||||||
|
@ -19,6 +19,7 @@ import type { MkbConvertedPresetData } from "@/types/presets";
|
|||||||
import { StreamSettings } from "@/utils/stream-settings";
|
import { StreamSettings } from "@/utils/stream-settings";
|
||||||
import { ShortcutAction } from "@/enums/shortcut-actions";
|
import { ShortcutAction } from "@/enums/shortcut-actions";
|
||||||
import { BxEventBus } from "@/utils/bx-event-bus";
|
import { BxEventBus } from "@/utils/bx-event-bus";
|
||||||
|
import { generateVirtualControllerMapping, toXcloudGamepadKey } from "@/utils/gamepad";
|
||||||
|
|
||||||
const PointerToMouseButton = {
|
const PointerToMouseButton = {
|
||||||
1: 0,
|
1: 0,
|
||||||
@ -152,6 +153,8 @@ export class EmulatedMkbHandler extends MkbHandler {
|
|||||||
};
|
};
|
||||||
private nativeGetGamepads: Navigator['getGamepads'];
|
private nativeGetGamepads: Navigator['getGamepads'];
|
||||||
|
|
||||||
|
private xCloudGamepad: XcloudGamepad = generateVirtualControllerMapping(0);
|
||||||
|
|
||||||
private initialized = false;
|
private initialized = false;
|
||||||
private enabled = false;
|
private enabled = false;
|
||||||
private mouseDataProvider: MouseDataProvider | undefined;
|
private mouseDataProvider: MouseDataProvider | undefined;
|
||||||
@ -171,16 +174,16 @@ export class EmulatedMkbHandler extends MkbHandler {
|
|||||||
|
|
||||||
private popup: MkbPopup;
|
private popup: MkbPopup;
|
||||||
|
|
||||||
private STICK_MAP: { [key in GamepadKey]?: [GamepadKey[], number, number] } = {
|
private STICK_MAP: { [key in GamepadKey]?: [GamepadKey[], number] } = {
|
||||||
[GamepadKey.LS_LEFT]: [this.LEFT_STICK_X, 0, -1],
|
[GamepadKey.LS_LEFT]: [this.LEFT_STICK_X, -1],
|
||||||
[GamepadKey.LS_RIGHT]: [this.LEFT_STICK_X, 0, 1],
|
[GamepadKey.LS_RIGHT]: [this.LEFT_STICK_X, 1],
|
||||||
[GamepadKey.LS_UP]: [this.LEFT_STICK_Y, 1, -1],
|
[GamepadKey.LS_UP]: [this.LEFT_STICK_Y, 1],
|
||||||
[GamepadKey.LS_DOWN]: [this.LEFT_STICK_Y, 1, 1],
|
[GamepadKey.LS_DOWN]: [this.LEFT_STICK_Y, -1],
|
||||||
|
|
||||||
[GamepadKey.RS_LEFT]: [this.RIGHT_STICK_X, 2, -1],
|
[GamepadKey.RS_LEFT]: [this.RIGHT_STICK_X, -1],
|
||||||
[GamepadKey.RS_RIGHT]: [this.RIGHT_STICK_X, 2, 1],
|
[GamepadKey.RS_RIGHT]: [this.RIGHT_STICK_X, 1],
|
||||||
[GamepadKey.RS_UP]: [this.RIGHT_STICK_Y, 3, -1],
|
[GamepadKey.RS_UP]: [this.RIGHT_STICK_Y, 1],
|
||||||
[GamepadKey.RS_DOWN]: [this.RIGHT_STICK_Y, 3, 1],
|
[GamepadKey.RS_DOWN]: [this.RIGHT_STICK_Y, -1],
|
||||||
};
|
};
|
||||||
|
|
||||||
private constructor() {
|
private constructor() {
|
||||||
@ -205,11 +208,16 @@ export class EmulatedMkbHandler extends MkbHandler {
|
|||||||
private getVirtualGamepad = () => this.VIRTUAL_GAMEPAD;
|
private getVirtualGamepad = () => this.VIRTUAL_GAMEPAD;
|
||||||
|
|
||||||
private updateStick(stick: GamepadStick, x: number, y: number) {
|
private updateStick(stick: GamepadStick, x: number, y: number) {
|
||||||
const virtualGamepad = this.getVirtualGamepad();
|
const gamepad = this.xCloudGamepad;
|
||||||
virtualGamepad.axes[stick * 2] = x;
|
if (stick === GamepadStick.LEFT) {
|
||||||
virtualGamepad.axes[stick * 2 + 1] = y;
|
gamepad.LeftThumbXAxis = x;
|
||||||
|
gamepad.LeftThumbYAxis = -y;
|
||||||
|
} else {
|
||||||
|
gamepad.RightThumbXAxis = x;
|
||||||
|
gamepad.RightThumbYAxis = -y;
|
||||||
|
}
|
||||||
|
|
||||||
virtualGamepad.timestamp = performance.now();
|
window.BX_EXPOSED.inputChannel?.sendGamepadInput(performance.now(), [this.xCloudGamepad]);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -224,29 +232,20 @@ export class EmulatedMkbHandler extends MkbHandler {
|
|||||||
|
|
||||||
private vectorLength = (x: number, y: number): number => Math.sqrt(x ** 2 + y ** 2);
|
private vectorLength = (x: number, y: number): number => Math.sqrt(x ** 2 + y ** 2);
|
||||||
|
|
||||||
private resetGamepad() {
|
resetXcloudGamepads() {
|
||||||
const gamepad = this.getVirtualGamepad();
|
const index = getPref(PrefKey.MKB_P1_SLOT) - 1;
|
||||||
|
|
||||||
// Reset axes
|
this.xCloudGamepad = generateVirtualControllerMapping(0, {
|
||||||
gamepad.axes = [0, 0, 0, 0];
|
GamepadIndex: getPref(PrefKey.LOCAL_CO_OP_ENABLED) ? index : 0,
|
||||||
|
Dirty: true,
|
||||||
// Reset buttons
|
});
|
||||||
for (const button of gamepad.buttons) {
|
this.VIRTUAL_GAMEPAD.index = index;
|
||||||
button.pressed = false;
|
|
||||||
button.value = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
gamepad.timestamp = performance.now();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private pressButton(buttonIndex: GamepadKey, pressed: boolean) {
|
private pressButton(buttonIndex: GamepadKey, pressed: boolean) {
|
||||||
const virtualGamepad = this.getVirtualGamepad();
|
const xCloudKey = toXcloudGamepadKey(buttonIndex)!;
|
||||||
|
|
||||||
if (buttonIndex >= 100) {
|
if (buttonIndex >= 100) {
|
||||||
let [valueArr, axisIndex] = this.STICK_MAP[buttonIndex]!;
|
let [valueArr]: [GamepadKey[], number] = this.STICK_MAP[buttonIndex]!;
|
||||||
valueArr = valueArr as number[];
|
|
||||||
axisIndex = axisIndex as number;
|
|
||||||
|
|
||||||
// Remove old index of the array
|
// Remove old index of the array
|
||||||
for (let i = valueArr.length - 1; i >= 0; i--) {
|
for (let i = valueArr.length - 1; i >= 0; i--) {
|
||||||
if (valueArr[i] === buttonIndex) {
|
if (valueArr[i] === buttonIndex) {
|
||||||
@ -259,18 +258,19 @@ export class EmulatedMkbHandler extends MkbHandler {
|
|||||||
let value;
|
let value;
|
||||||
if (valueArr.length) {
|
if (valueArr.length) {
|
||||||
// Get value of the last key of the axis
|
// Get value of the last key of the axis
|
||||||
value = this.STICK_MAP[valueArr[valueArr.length - 1]]![2] as number;
|
value = this.STICK_MAP[valueArr[valueArr.length - 1]]![1] as number;
|
||||||
} else {
|
} else {
|
||||||
value = 0;
|
value = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
virtualGamepad.axes[axisIndex] = value;
|
// @ts-ignore
|
||||||
|
this.xCloudGamepad[xCloudKey] = value;
|
||||||
} else {
|
} else {
|
||||||
virtualGamepad.buttons[buttonIndex].pressed = pressed;
|
// @ts-ignore
|
||||||
virtualGamepad.buttons[buttonIndex].value = pressed ? 1 : 0;
|
this.xCloudGamepad[xCloudKey] = pressed ? 1 : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
virtualGamepad.timestamp = performance.now();
|
window.BX_EXPOSED.inputChannel?.sendGamepadInput(performance.now(), [this.xCloudGamepad]);
|
||||||
}
|
}
|
||||||
|
|
||||||
private onKeyboardEvent = (e: KeyboardEvent) => {
|
private onKeyboardEvent = (e: KeyboardEvent) => {
|
||||||
@ -453,7 +453,7 @@ export class EmulatedMkbHandler extends MkbHandler {
|
|||||||
|
|
||||||
refreshPresetData() {
|
refreshPresetData() {
|
||||||
this.PRESET = window.BX_STREAM_SETTINGS.mkbPreset;
|
this.PRESET = window.BX_STREAM_SETTINGS.mkbPreset;
|
||||||
this.resetGamepad();
|
this.resetXcloudGamepads();
|
||||||
}
|
}
|
||||||
|
|
||||||
waitForMouseData(showPopup: boolean) {
|
waitForMouseData(showPopup: boolean) {
|
||||||
@ -581,11 +581,6 @@ export class EmulatedMkbHandler extends MkbHandler {
|
|||||||
window.removeEventListener(BxEvent.XCLOUD_POLLING_MODE_CHANGED, this.onPollingModeChanged);
|
window.removeEventListener(BxEvent.XCLOUD_POLLING_MODE_CHANGED, this.onPollingModeChanged);
|
||||||
}
|
}
|
||||||
|
|
||||||
updateGamepadSlots() {
|
|
||||||
// Set gamepad slot
|
|
||||||
this.VIRTUAL_GAMEPAD.index = getPref(PrefKey.MKB_P1_SLOT) - 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
start() {
|
start() {
|
||||||
if (!this.enabled) {
|
if (!this.enabled) {
|
||||||
this.enabled = true;
|
this.enabled = true;
|
||||||
@ -595,8 +590,8 @@ export class EmulatedMkbHandler extends MkbHandler {
|
|||||||
this.isPolling = true;
|
this.isPolling = true;
|
||||||
this.escKeyDownTime = -1;
|
this.escKeyDownTime = -1;
|
||||||
|
|
||||||
this.resetGamepad();
|
window.BX_EXPOSED.toggleLocalCoOp(getPref(PrefKey.LOCAL_CO_OP_ENABLED));
|
||||||
this.updateGamepadSlots();
|
this.resetXcloudGamepads();
|
||||||
window.navigator.getGamepads = this.patchedGetGamepads;
|
window.navigator.getGamepads = this.patchedGetGamepads;
|
||||||
|
|
||||||
this.waitForMouseData(false);
|
this.waitForMouseData(false);
|
||||||
@ -625,7 +620,7 @@ export class EmulatedMkbHandler extends MkbHandler {
|
|||||||
const virtualGamepad = this.getVirtualGamepad();
|
const virtualGamepad = this.getVirtualGamepad();
|
||||||
if (virtualGamepad.connected) {
|
if (virtualGamepad.connected) {
|
||||||
// Dispatch "gamepaddisconnected" event
|
// Dispatch "gamepaddisconnected" event
|
||||||
this.resetGamepad();
|
this.resetXcloudGamepads();
|
||||||
|
|
||||||
virtualGamepad.connected = false;
|
virtualGamepad.connected = false;
|
||||||
virtualGamepad.timestamp = performance.now();
|
virtualGamepad.timestamp = performance.now();
|
||||||
|
@ -13,19 +13,7 @@ import { StreamSettings } from "@/utils/stream-settings";
|
|||||||
import { ShortcutAction } from "@/enums/shortcut-actions";
|
import { ShortcutAction } from "@/enums/shortcut-actions";
|
||||||
import { NativeMkbMode } from "@/enums/pref-values";
|
import { NativeMkbMode } from "@/enums/pref-values";
|
||||||
import { BxEventBus } from "@/utils/bx-event-bus";
|
import { BxEventBus } from "@/utils/bx-event-bus";
|
||||||
|
import type { NativeMouseData, XcloudInputChannel } from "@/utils/gamepad";
|
||||||
type NativeMouseData = {
|
|
||||||
X: number,
|
|
||||||
Y: number,
|
|
||||||
Buttons: number,
|
|
||||||
WheelX: number,
|
|
||||||
WheelY: number,
|
|
||||||
Type?: 0, // 0: Relative, 1: Absolute
|
|
||||||
}
|
|
||||||
|
|
||||||
type XcloudInputSink = {
|
|
||||||
onMouseInput: (data: NativeMouseData) => void;
|
|
||||||
}
|
|
||||||
|
|
||||||
export class NativeMkbHandler extends MkbHandler {
|
export class NativeMkbHandler extends MkbHandler {
|
||||||
private static instance: NativeMkbHandler | null | undefined;
|
private static instance: NativeMkbHandler | null | undefined;
|
||||||
@ -54,7 +42,7 @@ export class NativeMkbHandler extends MkbHandler {
|
|||||||
private mouseVerticalMultiply = 0;
|
private mouseVerticalMultiply = 0;
|
||||||
private mouseHorizontalMultiply = 0;
|
private mouseHorizontalMultiply = 0;
|
||||||
|
|
||||||
private inputSink: XcloudInputSink | undefined;
|
private inputChannel: XcloudInputChannel | undefined;
|
||||||
|
|
||||||
private popup!: MkbPopup;
|
private popup!: MkbPopup;
|
||||||
|
|
||||||
@ -114,7 +102,7 @@ export class NativeMkbHandler extends MkbHandler {
|
|||||||
|
|
||||||
init() {
|
init() {
|
||||||
this.pointerClient = PointerClient.getInstance();
|
this.pointerClient = PointerClient.getInstance();
|
||||||
this.inputSink = window.BX_EXPOSED.inputSink;
|
this.inputChannel = window.BX_EXPOSED.inputChannel;
|
||||||
|
|
||||||
// Stop keyboard input at startup
|
// Stop keyboard input at startup
|
||||||
this.updateInputConfigurationAsync(false);
|
this.updateInputConfigurationAsync(false);
|
||||||
@ -274,7 +262,7 @@ export class NativeMkbHandler extends MkbHandler {
|
|||||||
|
|
||||||
private sendMouseInput(data: NativeMouseData) {
|
private sendMouseInput(data: NativeMouseData) {
|
||||||
data.Type = 0; // Relative
|
data.Type = 0; // Relative
|
||||||
this.inputSink?.onMouseInput(data);
|
this.inputChannel?.queueMouseInput(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
private resetMouseInput() {
|
private resetMouseInput() {
|
||||||
|
@ -643,15 +643,14 @@ true` + text;
|
|||||||
return str;
|
return str;
|
||||||
},
|
},
|
||||||
|
|
||||||
exposeInputSink(str: string) {
|
exposeInputChannel(str: string) {
|
||||||
let text = 'this.controlChannel=null,this.inputChannel=null';
|
let index = str.indexOf('this.flushData=');
|
||||||
if (!str.includes(text)) {
|
if (index < 0) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
const newCode = 'window.BX_EXPOSED.inputSink = this;';
|
const newCode = 'window.BX_EXPOSED.inputChannel = this,';
|
||||||
|
str = PatcherUtils.insertAt(str, index, newCode);
|
||||||
str = str.replace(text, newCode + text);
|
|
||||||
return str;
|
return str;
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -1120,7 +1119,6 @@ ${subsVar} = subs;
|
|||||||
let PATCH_ORDERS = PatcherUtils.filterPatches([
|
let PATCH_ORDERS = PatcherUtils.filterPatches([
|
||||||
...(AppInterface && getPref(PrefKey.NATIVE_MKB_MODE) === NativeMkbMode.ON ? [
|
...(AppInterface && getPref(PrefKey.NATIVE_MKB_MODE) === NativeMkbMode.ON ? [
|
||||||
'enableNativeMkb',
|
'enableNativeMkb',
|
||||||
'exposeInputSink',
|
|
||||||
'disableAbsoluteMouse',
|
'disableAbsoluteMouse',
|
||||||
] : []),
|
] : []),
|
||||||
|
|
||||||
@ -1208,6 +1206,8 @@ let HOME_PAGE_PATCH_ORDERS = PatcherUtils.filterPatches([
|
|||||||
// TODO: check this
|
// TODO: check this
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
let STREAM_PAGE_PATCH_ORDERS = PatcherUtils.filterPatches([
|
let STREAM_PAGE_PATCH_ORDERS = PatcherUtils.filterPatches([
|
||||||
|
'exposeInputChannel',
|
||||||
|
|
||||||
'patchXcloudTitleInfo',
|
'patchXcloudTitleInfo',
|
||||||
'disableGamepadDisconnectedScreen',
|
'disableGamepadDisconnectedScreen',
|
||||||
'patchStreamHud',
|
'patchStreamHud',
|
||||||
@ -1377,6 +1377,7 @@ export class Patcher {
|
|||||||
|
|
||||||
// Apply patched functions
|
// Apply patched functions
|
||||||
if (modified) {
|
if (modified) {
|
||||||
|
BX_FLAGS.Debug && console.time(LOG_TAG);
|
||||||
try {
|
try {
|
||||||
chunkData[chunkId] = eval(patchedFuncStr);
|
chunkData[chunkId] = eval(patchedFuncStr);
|
||||||
} catch (e: unknown) {
|
} catch (e: unknown) {
|
||||||
@ -1384,6 +1385,7 @@ export class Patcher {
|
|||||||
BxLogger.error(LOG_TAG, 'Error', appliedPatches, e.message, patchedFuncStr);
|
BxLogger.error(LOG_TAG, 'Error', appliedPatches, e.message, patchedFuncStr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
BX_FLAGS.Debug && console.timeEnd(LOG_TAG);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Save to cache
|
// Save to cache
|
||||||
|
@ -7,8 +7,8 @@ export class VirtualControllerShortcut {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const released = generateVirtualControllerMapping();
|
const released = generateVirtualControllerMapping(0);
|
||||||
const pressed = generateVirtualControllerMapping({
|
const pressed = generateVirtualControllerMapping(0, {
|
||||||
Nexus: 1,
|
Nexus: 1,
|
||||||
VirtualPhysicality: 1024, // Home
|
VirtualPhysicality: 1024, // Home
|
||||||
});
|
});
|
||||||
|
@ -69,7 +69,7 @@ export class MkbExtraSettings extends HTMLElement {
|
|||||||
createSettingRow(
|
createSettingRow(
|
||||||
t('virtual-controller-slot'),
|
t('virtual-controller-slot'),
|
||||||
SettingElement.fromPref(PrefKey.MKB_P1_SLOT, STORAGE.Global, () => {
|
SettingElement.fromPref(PrefKey.MKB_P1_SLOT, STORAGE.Global, () => {
|
||||||
EmulatedMkbHandler.getInstance()?.updateGamepadSlots();
|
EmulatedMkbHandler.getInstance()?.resetXcloudGamepads();
|
||||||
}),
|
}),
|
||||||
),
|
),
|
||||||
] : []),
|
] : []),
|
||||||
|
3
src/types/global.d.ts
vendored
3
src/types/global.d.ts
vendored
@ -5,6 +5,7 @@ import type { StreamSettings, type StreamSettingsData } from "@/utils/stream-set
|
|||||||
import type { BxEvent } from "@/utils/bx-event";
|
import type { BxEvent } from "@/utils/bx-event";
|
||||||
import type { BxEventBus } from "@/utils/bx-event-bus";
|
import type { BxEventBus } from "@/utils/bx-event-bus";
|
||||||
import type { BxLogger } from "@/utils/bx-logger";
|
import type { BxLogger } from "@/utils/bx-logger";
|
||||||
|
import type { XcloudInputChannel } from "@/utils/gamepad";
|
||||||
|
|
||||||
export {};
|
export {};
|
||||||
|
|
||||||
@ -20,7 +21,7 @@ declare global {
|
|||||||
closeAll: () => void;
|
closeAll: () => void;
|
||||||
};
|
};
|
||||||
showStreamMenu: () => void;
|
showStreamMenu: () => void;
|
||||||
inputSink: any;
|
inputChannel: XcloudInputChannel | undefined;
|
||||||
streamSession: any;
|
streamSession: any;
|
||||||
touchLayoutManager: any;
|
touchLayoutManager: any;
|
||||||
}>;
|
}>;
|
||||||
|
@ -4,7 +4,21 @@ import { Toast } from "@utils/toast";
|
|||||||
import { BxLogger } from "@utils/bx-logger";
|
import { BxLogger } from "@utils/bx-logger";
|
||||||
import { PrefKey } from "@/enums/pref-keys";
|
import { PrefKey } from "@/enums/pref-keys";
|
||||||
import { getPref } from "./settings-storages/global-settings-storage";
|
import { getPref } from "./settings-storages/global-settings-storage";
|
||||||
import { GamepadKeyName, type GamepadKey } from "@/enums/gamepad";
|
import { GamepadKey, GamepadKeyName } from "@/enums/gamepad";
|
||||||
|
|
||||||
|
export type NativeMouseData = {
|
||||||
|
X: number,
|
||||||
|
Y: number,
|
||||||
|
Buttons: number,
|
||||||
|
WheelX: number,
|
||||||
|
WheelY: number,
|
||||||
|
Type?: 0, // 0: Relative, 1: Absolute
|
||||||
|
}
|
||||||
|
|
||||||
|
export type XcloudInputChannel = {
|
||||||
|
sendGamepadInput: (timestamp: number, gamepads: XcloudGamepad[]) => void;
|
||||||
|
queueMouseInput: (data: NativeMouseData) => void;
|
||||||
|
}
|
||||||
|
|
||||||
// Show a toast when connecting/disconecting controller
|
// Show a toast when connecting/disconecting controller
|
||||||
export function showGamepadToast(gamepad: Gamepad) {
|
export function showGamepadToast(gamepad: Gamepad) {
|
||||||
@ -59,9 +73,9 @@ export function hasGamepad() {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function generateVirtualControllerMapping(override: {}={}) {
|
export function generateVirtualControllerMapping(index: number, override: Partial<XcloudGamepad>={}) {
|
||||||
const mapping = {
|
const mapping = {
|
||||||
GamepadIndex: 0,
|
GamepadIndex: index,
|
||||||
A: 0,
|
A: 0,
|
||||||
B: 0,
|
B: 0,
|
||||||
X: 0,
|
X: 0,
|
||||||
@ -95,3 +109,44 @@ export function generateVirtualControllerMapping(override: {}={}) {
|
|||||||
export function getGamepadPrompt(gamepadKey: GamepadKey): string {
|
export function getGamepadPrompt(gamepadKey: GamepadKey): string {
|
||||||
return GamepadKeyName[gamepadKey][1];
|
return GamepadKeyName[gamepadKey][1];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const XCLOUD_GAMEPAD_KEY_MAPPING: { [key in GamepadKey]?: keyof XcloudGamepad } = {
|
||||||
|
[GamepadKey.A]: 'A',
|
||||||
|
[GamepadKey.B]: 'B',
|
||||||
|
[GamepadKey.X]: 'X',
|
||||||
|
[GamepadKey.Y]: 'Y',
|
||||||
|
|
||||||
|
[GamepadKey.UP]: 'DPadUp',
|
||||||
|
[GamepadKey.RIGHT]: 'DPadRight',
|
||||||
|
[GamepadKey.DOWN]: 'DPadDown',
|
||||||
|
[GamepadKey.LEFT]: 'DPadLeft',
|
||||||
|
|
||||||
|
[GamepadKey.LB]: 'LeftShoulder',
|
||||||
|
[GamepadKey.RB]: 'RightShoulder',
|
||||||
|
[GamepadKey.LT]: 'LeftTrigger',
|
||||||
|
[GamepadKey.RT]: 'RightTrigger',
|
||||||
|
|
||||||
|
[GamepadKey.L3]: 'LeftThumb',
|
||||||
|
[GamepadKey.R3]: 'RightThumb',
|
||||||
|
[GamepadKey.LS]: 'LeftStickAxes',
|
||||||
|
[GamepadKey.RS]: 'RightStickAxes',
|
||||||
|
|
||||||
|
[GamepadKey.SELECT]: 'View',
|
||||||
|
[GamepadKey.START]: 'Menu',
|
||||||
|
[GamepadKey.HOME]: 'Nexus',
|
||||||
|
[GamepadKey.SHARE]: 'Share',
|
||||||
|
|
||||||
|
[GamepadKey.LS_LEFT]: 'LeftThumbXAxis',
|
||||||
|
[GamepadKey.LS_RIGHT]: 'LeftThumbXAxis',
|
||||||
|
[GamepadKey.LS_UP]: 'LeftThumbYAxis',
|
||||||
|
[GamepadKey.LS_DOWN]: 'LeftThumbYAxis',
|
||||||
|
|
||||||
|
[GamepadKey.RS_LEFT]: 'RightThumbXAxis',
|
||||||
|
[GamepadKey.RS_RIGHT]: 'RightThumbXAxis',
|
||||||
|
[GamepadKey.RS_UP]: 'RightThumbYAxis',
|
||||||
|
[GamepadKey.RS_DOWN]: 'RightThumbYAxis',
|
||||||
|
};
|
||||||
|
|
||||||
|
export function toXcloudGamepadKey(gamepadKey: GamepadKey) {
|
||||||
|
return XCLOUD_GAMEPAD_KEY_MAPPING[gamepadKey];
|
||||||
|
}
|
||||||
|
@ -6,7 +6,7 @@ import type { ControllerCustomizationConvertedPresetData, ControllerCustomizatio
|
|||||||
import { STATES } from "./global";
|
import { STATES } from "./global";
|
||||||
import { DeviceVibrationMode } from "@/enums/pref-values";
|
import { DeviceVibrationMode } from "@/enums/pref-values";
|
||||||
import { VIRTUAL_GAMEPAD_ID } from "@/modules/mkb/mkb-handler";
|
import { VIRTUAL_GAMEPAD_ID } from "@/modules/mkb/mkb-handler";
|
||||||
import { hasGamepad } from "./gamepad";
|
import { hasGamepad, toXcloudGamepadKey } from "./gamepad";
|
||||||
import { MkbMappingPresetsTable } from "./local-db/mkb-mapping-presets-table";
|
import { MkbMappingPresetsTable } from "./local-db/mkb-mapping-presets-table";
|
||||||
import { GamepadKey } from "@/enums/gamepad";
|
import { GamepadKey } from "@/enums/gamepad";
|
||||||
import { MkbPresetKey, MouseConstant } from "@/enums/mkb";
|
import { MkbPresetKey, MouseConstant } from "@/enums/mkb";
|
||||||
@ -51,32 +51,6 @@ export class StreamSettings {
|
|||||||
keyboardShortcuts: {},
|
keyboardShortcuts: {},
|
||||||
};
|
};
|
||||||
|
|
||||||
private static CONTROLLER_CUSTOMIZATION_MAPPING: { [key in GamepadKey]?: keyof XcloudGamepad } = {
|
|
||||||
[GamepadKey.A]: 'A',
|
|
||||||
[GamepadKey.B]: 'B',
|
|
||||||
[GamepadKey.X]: 'X',
|
|
||||||
[GamepadKey.Y]: 'Y',
|
|
||||||
|
|
||||||
[GamepadKey.UP]: 'DPadUp',
|
|
||||||
[GamepadKey.RIGHT]: 'DPadRight',
|
|
||||||
[GamepadKey.DOWN]: 'DPadDown',
|
|
||||||
[GamepadKey.LEFT]: 'DPadLeft',
|
|
||||||
|
|
||||||
[GamepadKey.LB]: 'LeftShoulder',
|
|
||||||
[GamepadKey.RB]: 'RightShoulder',
|
|
||||||
[GamepadKey.LT]: 'LeftTrigger',
|
|
||||||
[GamepadKey.RT]: 'RightTrigger',
|
|
||||||
|
|
||||||
[GamepadKey.L3]: 'LeftThumb',
|
|
||||||
[GamepadKey.R3]: 'RightThumb',
|
|
||||||
[GamepadKey.LS]: 'LeftStickAxes',
|
|
||||||
[GamepadKey.RS]: 'RightStickAxes',
|
|
||||||
|
|
||||||
[GamepadKey.SELECT]: 'View',
|
|
||||||
[GamepadKey.START]: 'Menu',
|
|
||||||
[GamepadKey.SHARE]: 'Share',
|
|
||||||
};
|
|
||||||
|
|
||||||
static getPref<T extends keyof PrefTypeMap>(key: T) {
|
static getPref<T extends keyof PrefTypeMap>(key: T) {
|
||||||
return getPref<T>(key);
|
return getPref<T>(key);
|
||||||
}
|
}
|
||||||
@ -146,14 +120,14 @@ export class StreamSettings {
|
|||||||
// Swap GamepadKey.A with "A"
|
// Swap GamepadKey.A with "A"
|
||||||
let gamepadKey: unknown;
|
let gamepadKey: unknown;
|
||||||
for (gamepadKey in customization.mapping) {
|
for (gamepadKey in customization.mapping) {
|
||||||
const gamepadStr = StreamSettings.CONTROLLER_CUSTOMIZATION_MAPPING[gamepadKey as GamepadKey];
|
const gamepadStr = toXcloudGamepadKey(gamepadKey as GamepadKey);
|
||||||
if (!gamepadStr) {
|
if (!gamepadStr) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
const mappedKey = customization.mapping[gamepadKey as GamepadKey];
|
const mappedKey = customization.mapping[gamepadKey as GamepadKey];
|
||||||
if (typeof mappedKey === 'number') {
|
if (typeof mappedKey === 'number') {
|
||||||
converted.mapping[gamepadStr] = StreamSettings.CONTROLLER_CUSTOMIZATION_MAPPING[mappedKey as GamepadKey];
|
converted.mapping[gamepadStr] = toXcloudGamepadKey(mappedKey as GamepadKey);
|
||||||
} else {
|
} else {
|
||||||
converted.mapping[gamepadStr] = false;
|
converted.mapping[gamepadStr] = false;
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user