update comment in inputs-controller.ts

pull/685/head
Greenlamp 2024-05-12 13:40:16 +02:00
parent 32a9b7170c
commit ba42f072e1
3 changed files with 99 additions and 69 deletions

View File

@ -42,7 +42,7 @@ export function getCurrenlyAssignedIconFromInputIndex(config: GamepadConfig, ind
} }
// Given a setting name, return the icon currently assigned to this setting name // Given a setting name, return the icon currently assigned to this setting name
export function getCurrentlyAssignedIconToSettingName(config: GamepadConfig, settingName: string) { export function getCurrentlyAssignedIconToSettingName(config: GamepadConfig, settingName: string): string {
const key = getCurrentlyAssignedToSettingName(config, settingName); const key = getCurrentlyAssignedToSettingName(config, settingName);
return config.icons[key]; return config.icons[key];
} }

View File

@ -6,7 +6,7 @@ import {Button} from "../enums/buttons";
*/ */
const pad_unlicensedSNES = { const pad_unlicensedSNES = {
padID: '081f-e401', padID: '081f-e401',
padType: 'snes', padType: 'xbox',
gamepadMapping : { gamepadMapping : {
RC_S: 2, RC_S: 2,
RC_E: 1, RC_E: 1,

View File

@ -188,6 +188,12 @@ export class InputsController {
} }
} }
/**
* Sets the currently chosen gamepad and initializes related settings.
* This method first deactivates any active key presses and then initializes the gamepad settings.
*
* @param gamepad - The identifier of the gamepad to set as chosen.
*/
setChosenGamepad(gamepad: String): void { setChosenGamepad(gamepad: String): void {
this.deactivatePressedKey(); this.deactivatePressedKey();
this.initChosenGamepad(gamepad) this.initChosenGamepad(gamepad)
@ -196,15 +202,13 @@ export class InputsController {
/** /**
* Updates the interaction handling by processing input states. * Updates the interaction handling by processing input states.
* This method gives priority to certain buttons by reversing the order in which they are checked. * This method gives priority to certain buttons by reversing the order in which they are checked.
* This method loops through all button values, checks for valid and timely interactions, and conditionally processes
* or ignores them based on the current state of gamepad support and other criteria.
* *
* @remarks * It handles special conditions such as the absence of gamepad support or mismatches between the source of the input and
* The method iterates over all possible buttons, checking for specific conditions such as: * the currently chosen gamepad. It also respects the paused state of updates to prevent unwanted input processing.
* - If the button is registered in the `interactions` dictionary.
* - If the button has been held down long enough.
* - If the button is currently pressed.
* *
* Special handling is applied if gamepad support is disabled but a gamepad source is still triggering inputs, * If an interaction is valid and should be processed, it emits an 'input_down' event with details of the interaction.
* preventing potential infinite loops by removing the last processed movement time for the button.
*/ */
update(): void { update(): void {
for (const b of Utils.getEnumValues(Button).reverse()) { for (const b of Utils.getEnumValues(Button).reverse()) {
@ -233,34 +237,39 @@ export class InputsController {
} }
} }
/**
* Retrieves the identifiers of all connected gamepads, excluding any that are currently marked as disconnected.
* @returns Array<String> An array of strings representing the IDs of the connected gamepads.
*/
getGamepadsName(): Array<String> { getGamepadsName(): Array<String> {
return this.gamepads.filter(g => !this.disconnectedGamepads.includes(g.id)).map(g => g.id); return this.gamepads.filter(g => !this.disconnectedGamepads.includes(g.id)).map(g => g.id);
} }
/**
* Initializes the chosen gamepad by setting its identifier in the local storage and updating the UI to reflect the chosen gamepad.
* If a gamepad name is provided, it uses that as the chosen gamepad; otherwise, it defaults to the currently chosen gamepad.
* @param gamepadName Optional parameter to specify the name of the gamepad to initialize as chosen.
*/
initChosenGamepad(gamepadName?: String): void { initChosenGamepad(gamepadName?: String): void {
// if we have a gamepad name in parameter, we set the chosen gamepad with this value
let name = gamepadName; let name = gamepadName;
if (gamepadName) if (gamepadName)
this.chosenGamepad = gamepadName; this.chosenGamepad = gamepadName;
else else
name = this.chosenGamepad; // otherwise we use the chosen gamepad's name name = this.chosenGamepad;
localStorage.setItem('chosenGamepad', name); localStorage.setItem('chosenGamepad', name);
// we update the ui with the chosen gamepad
const handler = this.scene.ui?.handlers[Mode.SETTINGS_GAMEPAD] as SettingsGamepadUiHandler; const handler = this.scene.ui?.handlers[Mode.SETTINGS_GAMEPAD] as SettingsGamepadUiHandler;
handler && handler.updateChosenGamepadDisplay() handler && handler.updateChosenGamepadDisplay()
} }
clearChosenGamepad() { /**
this.chosenGamepad = null; * Handles the disconnection of a gamepad by adding its identifier to a list of disconnected gamepads.
if (localStorage.hasOwnProperty('chosenGamepad')) * This is necessary because Phaser retains memory of previously connected gamepads, and without tracking
localStorage.removeItem('chosenGamepad'); * disconnections, it would be impossible to determine the connection status of gamepads. This method ensures
} * that disconnected gamepads are recognized and can be appropriately hidden in the gamepad selection menu.
*
* @param thisGamepad The gamepad that has been disconnected.
*/
onDisconnect(thisGamepad: Phaser.Input.Gamepad.Gamepad): void { onDisconnect(thisGamepad: Phaser.Input.Gamepad.Gamepad): void {
// We need to add the disconnected gamepad into a local array
// Because Phaser keep in memory the previously connected gamepad
// If we don't do that, we have no way to determine if the gamepad is connected or not.
// We want to know that because we want to hide it in the selection menu of gamepad to use
this.disconnectedGamepads.push(thisGamepad.id); this.disconnectedGamepads.push(thisGamepad.id);
/** commented for now this code because i don't know anymore if it's good to do that /** commented for now this code because i don't know anymore if it's good to do that
* for example i'm playing with a wireless gamepad that shutdown after 5 min * for example i'm playing with a wireless gamepad that shutdown after 5 min
@ -280,27 +289,28 @@ export class InputsController {
// } // }
} }
/**
* Updates the tracking of disconnected gamepads when a gamepad is reconnected.
* It removes the reconnected gamepad's identifier from the `disconnectedGamepads` array,
* effectively updating its status to connected.
*
* @param thisGamepad The gamepad that has been reconnected.
*/
onReconnect(thisGamepad: Phaser.Input.Gamepad.Gamepad): void { onReconnect(thisGamepad: Phaser.Input.Gamepad.Gamepad): void {
// We check if a gamepad reconnect by looking in the disconnectedGamepads array if is there
// If he is there, we remove it.
this.disconnectedGamepads = this.disconnectedGamepads.filter(g => g !== thisGamepad.id); this.disconnectedGamepads = this.disconnectedGamepads.filter(g => g !== thisGamepad.id);
} }
/** /**
* Configures a gamepad for use based on its device ID. * Initializes or updates configurations for connected gamepads.
* It retrieves the names of all connected gamepads, sets up their configurations according to stored or default settings,
* and ensures these configurations are saved. If the connected gamepad is the currently chosen one,
* it reinitializes the chosen gamepad settings.
* *
* @param thisGamepad - The gamepad to set up. * @param thisGamepad The gamepad that is being set up.
*
* @remarks
* This method initializes a gamepad by mapping its ID to a predefined configuration.
* It updates the player's gamepad mapping based on the identified configuration, ensuring
* that the gamepad controls are correctly mapped to in-game actions.
*/ */
setupGamepad(thisGamepad: Phaser.Input.Gamepad.Gamepad): void { setupGamepad(thisGamepad: Phaser.Input.Gamepad.Gamepad): void {
// we fetch all the gamepads name
const allGamepads = this.getGamepadsName(); const allGamepads = this.getGamepadsName();
for (const gamepad of allGamepads) { for (const gamepad of allGamepads) {
// for each gamepad, we set its mapping in this.configs
const gamepadID = gamepad.toLowerCase(); const gamepadID = gamepad.toLowerCase();
const config = this.getConfig(gamepadID); const config = this.getConfig(gamepadID);
config.custom = this.configs[gamepad]?.custom || {...config.default}; config.custom = this.configs[gamepad]?.custom || {...config.default};
@ -330,21 +340,17 @@ export class InputsController {
} }
/** /**
* Handles the 'down' event for gamepad buttons, emitting appropriate events and updating the interaction state. * Handles button press events on a gamepad. This method sets the gamepad as chosen on the first input if no gamepad is currently chosen.
* It checks if gamepad support is enabled and if the event comes from the chosen gamepad. If so, it maps the button press to a specific
* action using a custom configuration, emits an event for the button press, and records the time of the action.
* *
* @param pad - The gamepad on which the button press occurred. * @param pad The gamepad on which the button was pressed.
* @param button - The button that was pressed. * @param button The specific button that was pressed.
* @param value - The value associated with the button press, typically indicating pressure or degree of activation. * @param value The intensity or value of the button press, if applicable.
*
* @remarks
* This method is triggered when a gamepad button is pressed. If gamepad support is enabled, it:
* - Retrieves the current gamepad action mapping.
* - Checks if the pressed button is mapped to a game action.
* - If mapped, emits an 'input_down' event with the controller type and button action, and updates the interaction of this button.
*/ */
gamepadButtonDown(pad: Phaser.Input.Gamepad.Gamepad, button: Phaser.Input.Gamepad.Button, value: number): void { gamepadButtonDown(pad: Phaser.Input.Gamepad.Gamepad, button: Phaser.Input.Gamepad.Button, value: number): void {
if (!pad) return; if (!pad) return;
if (!this.chosenGamepad) // at the very first input, if we have not yet a chosen gamepad, we set it if (!this.chosenGamepad)
this.setChosenGamepad(pad.id); this.setChosenGamepad(pad.id);
if (!this.gamepadSupport || pad.id.toLowerCase() !== this.chosenGamepad.toLowerCase()) return; if (!this.gamepadSupport || pad.id.toLowerCase() !== this.chosenGamepad.toLowerCase()) return;
const key = getKeyFromInputIndex(this.configs[pad.id], button.index); const key = getKeyFromInputIndex(this.configs[pad.id], button.index);
@ -360,17 +366,13 @@ export class InputsController {
} }
/** /**
* Handles the 'up' event for gamepad buttons, emitting appropriate events and clearing the interaction state. * Responds to a button release event on a gamepad by checking if the gamepad is supported and currently chosen.
* If conditions are met, it identifies the configured action for the button, emits an event signaling the button release,
* and clears the record of the button.
* *
* @param pad - The gamepad on which the button release occurred. * @param pad The gamepad from which the button was released.
* @param button - The button that was released. * @param button The specific button that was released.
* @param value - The value associated with the button release, typically indicating pressure or degree of deactivation. * @param value The intensity or value of the button release, if applicable.
*
* @remarks
* This method is triggered when a gamepad button is released. If gamepad support is enabled, it:
* - Retrieves the current gamepad action mapping.
* - Checks if the released button is mapped to a game action.
* - If mapped, emits an 'input_up' event with the controller type and button action, and clears the interaction for this button.
*/ */
gamepadButtonUp(pad: Phaser.Input.Gamepad.Gamepad, button: Phaser.Input.Gamepad.Button, value: number): void { gamepadButtonUp(pad: Phaser.Input.Gamepad.Gamepad, button: Phaser.Input.Gamepad.Button, value: number): void {
if (!pad) return; if (!pad) return;
@ -481,17 +483,12 @@ export class InputsController {
} }
/** /**
* Maps a gamepad ID to a specific gamepad configuration based on the ID's characteristics. * Retrieves the configuration object for a gamepad based on its identifier. The method identifies specific gamepad models
* based on substrings in the identifier and returns predefined configurations for recognized models.
* If no specific configuration matches, it defaults to a generic gamepad configuration.
* *
* @param id - The gamepad ID string, typically representing a unique identifier for a gamepad model or make. * @param id The identifier string of the gamepad.
* @returns A `GamepadConfig` object corresponding to the identified gamepad model. * @returns GamepadConfig The configuration object corresponding to the identified gamepad type.
*
* @remarks
* This function analyzes the provided gamepad ID and matches it to a predefined configuration based on known identifiers:
* - If the ID includes both '081f' and 'e401', it is identified as an unlicensed SNES gamepad.
* - If the ID contains 'xbox' and '360', it is identified as an Xbox 360 gamepad.
* - If the ID contains '054c', it is identified as a DualShock gamepad.
* If no specific identifiers are recognized, a generic gamepad configuration is returned.
*/ */
getConfig(id: string): GamepadConfig { getConfig(id: string): GamepadConfig {
id = id.toLowerCase(); id = id.toLowerCase();
@ -504,7 +501,7 @@ export class InputsController {
return pad_dualshock; return pad_dualshock;
} }
// return pad_dualshock; return pad_unlicensedSNES;
return pad_generic; return pad_generic;
} }
@ -648,20 +645,46 @@ export class InputsController {
else if (this.buttonLock2 === button) this.buttonLock2 = null; else if (this.buttonLock2 === button) this.buttonLock2 = null;
} }
getActiveConfig(): GamepadConfig { /**
* Retrieves the active configuration for the currently chosen gamepad.
* It checks if a specific gamepad ID is stored under the chosen gamepad's configurations and returns it.
*
* @returns GamepadConfig The configuration object for the active gamepad, or null if not set.
*/
getActiveConfig(): GamepadConfig | null {
if (this.configs[this.chosenGamepad]?.padID) return this.configs[this.chosenGamepad] if (this.configs[this.chosenGamepad]?.padID) return this.configs[this.chosenGamepad]
return null; return null;
} }
getPressedButtonLabel(button: Phaser.Input.Gamepad.Button) { /**
* Determines icon for a button pressed on the currently chosen gamepad based on its configuration.
*
* @param button The button for which to retrieve the label and icon.
* @returns Array Tuple containing the pad type and the currently assigned icon for the button index.
*/
getPressedButtonLabel(button: Phaser.Input.Gamepad.Button): [string, string] {
return [this.configs[this.chosenGamepad].padType, getCurrenlyAssignedIconFromInputIndex(this.configs[this.chosenGamepad], button.index)]; return [this.configs[this.chosenGamepad].padType, getCurrenlyAssignedIconFromInputIndex(this.configs[this.chosenGamepad], button.index)];
} }
getCurrentlyAssignedIconToDisplay(target: SettingGamepad) { /**
* Retrieves the currently assigned icon for a specific setting on the chosen gamepad.
*
* @param target The gamepad setting for which to retrieve the assigned icon.
* @returns string The icon assigned to the specified setting.
*/
getCurrentlyAssignedIconToDisplay(target: SettingGamepad): string {
return getCurrentlyAssignedIconToSettingName(this.configs[this.chosenGamepad], target); return getCurrentlyAssignedIconToSettingName(this.configs[this.chosenGamepad], target);
} }
swapBinding(settingName, pressedButton) { /**
* Swaps the binding of two controls on the chosen gamepad configuration.
* It temporarily pauses updates, swaps the key bindings, saves the new configuration,
* and then resumes updates after a short delay.
*
* @param settingName The name of the setting for which to swap the binding.
* @param pressedButton The button index whose binding is to be swapped.
*/
swapBinding(settingName, pressedButton): void {
this.pauseUpdate = true; this.pauseUpdate = true;
const keyTarget = getCurrentlyAssignedToSettingName(this.configs[this.chosenGamepad], settingName) const keyTarget = getCurrentlyAssignedToSettingName(this.configs[this.chosenGamepad], settingName)
const keyNewBinding = getKeyFromInputIndex(this.configs[this.chosenGamepad], pressedButton); const keyNewBinding = getKeyFromInputIndex(this.configs[this.chosenGamepad], pressedButton);
@ -673,6 +696,13 @@ export class InputsController {
setTimeout(() => this.pauseUpdate = false, 500); setTimeout(() => this.pauseUpdate = false, 500);
} }
/**
* Injects a custom mapping configuration into the gamepad configuration for a specific gamepad.
* If the gamepad does not have an existing configuration, it initializes one first.
*
* @param gamepadName The identifier of the gamepad to configure.
* @param customMappings The custom mapping configuration to apply to the gamepad.
*/
injectConfig(gamepadName: String, customMappings: MappingLayout): void { injectConfig(gamepadName: String, customMappings: MappingLayout): void {
if (!this.configs[gamepadName]) this.configs[gamepadName] = {}; if (!this.configs[gamepadName]) this.configs[gamepadName] = {};
this.configs[gamepadName].custom = customMappings; this.configs[gamepadName].custom = customMappings;