remove localStorage for gamepads connected + fix lost focus effect on controller change + disconnect/reconnect handling

pull/685/head
Greenlamp 2024-05-09 17:02:07 +02:00
parent b58a444f80
commit d34d48f1b5
4 changed files with 92 additions and 37 deletions

View File

@ -6,6 +6,8 @@ import pad_unlicensedSNES from "./configs/pad_unlicensedSNES";
import pad_xbox360 from "./configs/pad_xbox360";
import pad_dualshock from "./configs/pad_dualshock";
import {Button} from "./enums/buttons";
import {Mode} from "./ui/ui";
import SettingsGamepadUiHandler from "./ui/settings-gamepad-ui-handler";
export interface GamepadMapping {
[key: string]: number;
@ -34,17 +36,19 @@ export class InputsController {
private buttonLock2: Button;
private interactions: Map<Button, Map<string, boolean>> = new Map();
private time: Time;
private player: Map<String, GamepadMapping> = new Map();
private player;
private gamepadSupport: boolean = true;
public customGamepadMapping = new Map();
public chosenGamepad: String;
private disconnectedGamepads: Array<String> = new Array();
constructor(scene: Phaser.Scene) {
this.scene = scene;
this.time = this.scene.time;
this.buttonKeys = [];
this.player = {};
for (const b of Utils.getEnumValues(Button)) {
this.interactions[b] = {
@ -74,6 +78,10 @@ export class InputsController {
this.scene.input.gamepad.on('connected', function (thisGamepad) {
this.refreshGamepads();
this.setupGamepad(thisGamepad);
this.onReconnect(thisGamepad);
}, this);
this.scene.input.gamepad.on('disconnected', function (thisGamepad) {
this.onDisconnect(thisGamepad);
}, this);
// Check to see if the gamepad has already been setup by the browser
@ -108,7 +116,7 @@ export class InputsController {
setChosenGamepad(gamepad: String): void {
this.deactivatePressedKey();
this.chosenGamepad = gamepad;
this.initChosenGamepad(gamepad)
}
update(): void {
@ -136,17 +144,52 @@ export class InputsController {
}
getGamepadsName(): Array<String> {
return this.gamepads.map(g => g.id);
return this.gamepads.filter(g => !this.disconnectedGamepads.includes(g.id)).map(g => g.id);
}
initChosenGamepad(gamepadName?: String): void {
let name = gamepadName;
if (gamepadName)
this.chosenGamepad = gamepadName;
else
name = this.chosenGamepad;
localStorage.setItem('chosenGamepad', name);
const handler = this.scene.ui?.handlers[Mode.SETTINGS_GAMEPAD] as SettingsGamepadUiHandler;
handler && handler.updateChosenGamepadDisplay()
}
clearChosenGamepad() {
this.chosenGamepad = null;
if (localStorage.hasOwnProperty('chosenGamepad'))
localStorage.removeItem('chosenGamepad');
}
onDisconnect(thisGamepad: Phaser.Input.Gamepad.Gamepad): void {
this.disconnectedGamepads.push(thisGamepad.id);
const gamepadsLeft = this.gamepads.filter(g => !this.disconnectedGamepads.includes(g.id)).map(g => g);
const chosenIsConnected = gamepadsLeft.some(g => g.id === this.chosenGamepad);
if (!chosenIsConnected && gamepadsLeft?.length) {
this.clearChosenGamepad();
this.setChosenGamepad(gamepadsLeft[0].id);
return;
}
}
onReconnect(thisGamepad: Phaser.Input.Gamepad.Gamepad): void {
if (this.disconnectedGamepads.some(g => g === thisGamepad.id)) {
this.disconnectedGamepads = this.disconnectedGamepads.filter(g => g !== thisGamepad.id);
}
}
setupGamepad(thisGamepad: Phaser.Input.Gamepad.Gamepad): void {
let gamepadID = this.chosenGamepad?.toLowerCase() || thisGamepad.id.toLowerCase();
const mappedPad = this.mapGamepad(gamepadID);
this.player['mapping'] = mappedPad.gamepadMapping;
if (!this.chosenGamepad) {
this.chosenGamepad = thisGamepad.id;
localStorage.setItem('chosenGamepad', this.chosenGamepad);
const allGamepads = this.getGamepadsName();
for (const gamepad of allGamepads) {
const gamepadID = gamepad.toLowerCase();
const mappedPad = this.mapGamepad(gamepadID);
if (!this.player[gamepad]) this.player[gamepad] = {};
this.player[gamepad]['mapping'] = mappedPad.gamepadMapping;
}
if (this.chosenGamepad === thisGamepad.id) this.initChosenGamepad(this.chosenGamepad)
}
refreshGamepads(): void {
@ -162,29 +205,31 @@ export class InputsController {
getActionGamepadMapping(): ActionGamepadMapping {
const gamepadMapping = {};
if (!this.player?.mapping) return gamepadMapping;
gamepadMapping[this.player.mapping.LC_N] = Button.UP;
gamepadMapping[this.player.mapping.LC_S] = Button.DOWN;
gamepadMapping[this.player.mapping.LC_W] = Button.LEFT;
gamepadMapping[this.player.mapping.LC_E] = Button.RIGHT;
gamepadMapping[this.player.mapping.TOUCH] = Button.SUBMIT;
gamepadMapping[this.player.mapping.RC_S] = this.scene.abSwapped ? Button.CANCEL : Button.ACTION;
gamepadMapping[this.player.mapping.RC_E] = this.scene.abSwapped ? Button.ACTION : Button.CANCEL;
gamepadMapping[this.player.mapping.SELECT] = Button.STATS;
gamepadMapping[this.player.mapping.START] = Button.MENU;
gamepadMapping[this.player.mapping.RB] = Button.RB;
gamepadMapping[this.player.mapping.LB] = Button.LB;
gamepadMapping[this.player.mapping.LT] = Button.CYCLE_GENDER;
gamepadMapping[this.player.mapping.RT] = Button.CYCLE_ABILITY;
gamepadMapping[this.player.mapping.RC_W] = Button.CYCLE_NATURE;
gamepadMapping[this.player.mapping.RC_N] = Button.CYCLE_VARIANT;
gamepadMapping[this.player.mapping.LS] = Button.SPEED_UP;
gamepadMapping[this.player.mapping.RS] = Button.SLOW_DOWN;
if (!this.player[this.chosenGamepad] || !this.player[this.chosenGamepad]?.mapping || !this.chosenGamepad) return gamepadMapping;
gamepadMapping[this.player[this.chosenGamepad].mapping.LC_N] = Button.UP;
gamepadMapping[this.player[this.chosenGamepad].mapping.LC_S] = Button.DOWN;
gamepadMapping[this.player[this.chosenGamepad].mapping.LC_W] = Button.LEFT;
gamepadMapping[this.player[this.chosenGamepad].mapping.LC_E] = Button.RIGHT;
gamepadMapping[this.player[this.chosenGamepad].mapping.TOUCH] = Button.SUBMIT;
gamepadMapping[this.player[this.chosenGamepad].mapping.RC_S] = this.scene.abSwapped ? Button.CANCEL : Button.ACTION;
gamepadMapping[this.player[this.chosenGamepad].mapping.RC_E] = this.scene.abSwapped ? Button.ACTION : Button.CANCEL;
gamepadMapping[this.player[this.chosenGamepad].mapping.SELECT] = Button.STATS;
gamepadMapping[this.player[this.chosenGamepad].mapping.START] = Button.MENU;
gamepadMapping[this.player[this.chosenGamepad].mapping.RB] = Button.RB;
gamepadMapping[this.player[this.chosenGamepad].mapping.LB] = Button.LB;
gamepadMapping[this.player[this.chosenGamepad].mapping.LT] = Button.CYCLE_GENDER;
gamepadMapping[this.player[this.chosenGamepad].mapping.RT] = Button.CYCLE_ABILITY;
gamepadMapping[this.player[this.chosenGamepad].mapping.RC_W] = Button.CYCLE_NATURE;
gamepadMapping[this.player[this.chosenGamepad].mapping.RC_N] = Button.CYCLE_VARIANT;
gamepadMapping[this.player[this.chosenGamepad].mapping.LS] = Button.SPEED_UP;
gamepadMapping[this.player[this.chosenGamepad].mapping.RS] = Button.SLOW_DOWN;
return gamepadMapping;
}
gamepadButtonDown(pad: Phaser.Input.Gamepad.Gamepad, button: Phaser.Input.Gamepad.Button, value: number): void {
if (!this.chosenGamepad)
this.setChosenGamepad(pad.id);
if (!this.gamepadSupport || pad.id.toLowerCase() !== this.chosenGamepad.toLowerCase()) return;
const actionMapping = this.getActionGamepadMapping();
const buttonDown = actionMapping.hasOwnProperty(button.index) && actionMapping[button.index];
@ -198,7 +243,7 @@ export class InputsController {
}
gamepadButtonUp(pad: Phaser.Input.Gamepad.Gamepad, button: Phaser.Input.Gamepad.Button, value: number): void {
if (!this.gamepadSupport || pad.id.toLowerCase() !== this.chosenGamepad.toLowerCase()) return;
if (!this.gamepadSupport || pad.id !== this.chosenGamepad) return;
const actionMapping = this.getActionGamepadMapping();
const buttonUp = actionMapping.hasOwnProperty(button.index) && actionMapping[button.index];
if (buttonUp !== undefined) {

View File

@ -2,6 +2,7 @@ import BattleScene from "../battle-scene";
import {SettingDefaults, SettingOptions} from "#app/system/settings";
import SettingsGamepadUiHandler from "#app/ui/settings-gamepad-ui-handler";
import {Mode} from "#app/ui/ui";
import {truncateString} from "../utils";
export enum SettingGamepad {
Default_Controller = "DEFAULT_CONTROLLER",
@ -57,13 +58,6 @@ export const settingGamepadDefaults: SettingDefaults = {
// [SettingGamepad.Button_Slow_Down]: Button.SLOW_DOWN,
};
function truncateString(str: String, maxLength: number = 10) {
if (str.length > maxLength) {
return str.slice(0, maxLength - 3) + "..."; // Subtract 3 to accommodate the ellipsis
}
return str;
}
export function setSettingGamepad(scene: BattleScene, setting: SettingGamepad, value: integer): boolean {
switch (setting) {
case SettingGamepad.Gamepad_Support:
@ -97,7 +91,6 @@ export function setSettingGamepad(scene: BattleScene, setting: SettingGamepad, v
};
const changeGamepadHandler = (gamepad: string) => {
scene.inputController.setChosenGamepad(gamepad);
localStorage.setItem('chosenGamepad', gamepad);
cancelHandler();
return true;
};

View File

@ -10,6 +10,7 @@ import {
settingGamepadDefaults,
settingGamepadOptions
} from "../system/settings-gamepad";
import {truncateString} from "../utils";
export default class SettingsGamepadUiHandler extends UiHandler {
private settingsContainer: Phaser.GameObjects.Container;
@ -193,6 +194,15 @@ export default class SettingsGamepadUiHandler extends UiHandler {
return ret;
}
updateChosenGamepadDisplay(): void {
for (const [index, key] of Object.keys(SettingGamepad).entries()) {
const setting = SettingGamepad[key]
if (setting === SettingGamepad.Default_Controller) {
this.optionValueLabels[index][0].setText(truncateString(this.scene.inputController.chosenGamepad, 30));
}
}
}
setOptionCursor(settingIndex: integer, cursor: integer, save?: boolean): boolean {
const setting = SettingGamepad[Object.keys(SettingGamepad)[settingIndex]];

View File

@ -356,4 +356,11 @@ export function rgbHexToRgba(hex: string) {
export function rgbaToInt(rgba: integer[]): integer {
return (rgba[0] << 24) + (rgba[1] << 16) + (rgba[2] << 8) + rgba[3];
}
}
export function truncateString(str: String, maxLength: number = 10) {
if (str.length > maxLength) {
return str.slice(0, maxLength - 3) + "..."; // Subtract 3 to accommodate the ellipsis
}
return str;
}