key displayed are correctly updated when swap or controller change + custom mapping is effective everywhere

pull/685/head
Greenlamp 2024-05-11 17:54:34 +02:00
parent 5ff09389db
commit e5e100990e
6 changed files with 78 additions and 26 deletions

View File

@ -1,5 +1,6 @@
import {GamepadConfig} from "../inputs-controller"; import {GamepadConfig} from "../inputs-controller";
import {SettingGamepad} from "#app/system/settings-gamepad"; import {SettingGamepad} from "#app/system/settings-gamepad";
import {Button} from "#app/enums/buttons";
export function getKeyForButtonIndex(config: GamepadConfig, index: number): String { export function getKeyForButtonIndex(config: GamepadConfig, index: number): String {
@ -21,6 +22,25 @@ export function getIconForCustomIndex(config: GamepadConfig, index: number): Str
return config.icons[key]; return config.icons[key];
} }
export function getKeyForRebindedAction(config: GamepadConfig, action: Button): String {
for (const key of Object.keys(config.default)) {
if (config.default[key] === action) return key;
}
return null;
}
export function getKeyForRebindedSettingName(config: GamepadConfig, settingName: SettingGamepad): String {
const oldKey = getKeyForSettingName(config, settingName)
const action = config.custom[oldKey];
return getKeyForRebindedAction(config, action);
}
export function getIconForRebindedKey(config: GamepadConfig, _key): String {
const action = config.custom[_key];
const key = getKeyForRebindedAction(config, action);
return config.icons[key];
}
export function getKeyForSettingName(config: GamepadConfig, settingName: SettingGamepad) { export function getKeyForSettingName(config: GamepadConfig, settingName: SettingGamepad) {
for (const key of Object.keys(config.setting)) { for (const key of Object.keys(config.setting)) {
const name = config.setting[key]; const name = config.setting[key];

View File

@ -58,12 +58,12 @@ const pad_xbox360 = {
RS: SettingGamepad.Button_Slow_Down, RS: SettingGamepad.Button_Slow_Down,
}, },
default: { default: {
RC_S: Button.ACTION, RC_S: Button.ACTION, //5
RC_E: Button.CANCEL, RC_E: Button.CANCEL,
RC_W: Button.CYCLE_NATURE, RC_W: Button.CYCLE_NATURE,
RC_N: Button.CYCLE_VARIANT, RC_N: Button.CYCLE_VARIANT, //14
START: Button.MENU, START: Button.MENU, //7
SELECT: Button.STATS, SELECT: Button.STATS, //8
LB: Button.CYCLE_FORM, LB: Button.CYCLE_FORM,
RB: Button.CYCLE_SHINY, RB: Button.CYCLE_SHINY,
LT: Button.CYCLE_GENDER, LT: Button.CYCLE_GENDER,

View File

@ -10,8 +10,8 @@ import SettingsGamepadUiHandler from "./ui/settings-gamepad-ui-handler";
import {SettingGamepad} from "./system/settings-gamepad"; import {SettingGamepad} from "./system/settings-gamepad";
import { import {
getButtonIndexForKey, getButtonIndexForKey,
getIconForCustomIndex, getIconForCustomIndex, getIconForRebindedKey,
getKeyForButtonIndex, getKeyForButtonIndex, getKeyForRebindedSettingName,
getKeyForSettingName getKeyForSettingName
} from "./configs/gamepad-utils"; } from "./configs/gamepad-utils";
@ -27,7 +27,7 @@ export interface SettingMapping {
[key: string]: string; [key: string]: string;
} }
export interface DefaultMapping { export interface MappingLayout {
[key: string]: Button; [key: string]: Button;
} }
@ -37,8 +37,8 @@ export interface GamepadConfig {
gamepadMapping: GamepadMapping; gamepadMapping: GamepadMapping;
icons: IconsMapping; icons: IconsMapping;
setting: SettingMapping; setting: SettingMapping;
default: DefaultMapping; default: MappingLayout;
custom: DefaultMapping; custom: MappingLayout;
} }
export interface ActionGamepadMapping { export interface ActionGamepadMapping {
@ -86,6 +86,8 @@ export class InputsController {
public chosenGamepad: String; public chosenGamepad: String;
private disconnectedGamepads: Array<String> = new Array(); private disconnectedGamepads: Array<String> = new Array();
private pauseUpdate: boolean = false;
/** /**
* Initializes a new instance of the game control system, setting up initial state and configurations. * Initializes a new instance of the game control system, setting up initial state and configurations.
* *
@ -218,7 +220,8 @@ export class InputsController {
// Prevents repeating button interactions when gamepad support is disabled. // Prevents repeating button interactions when gamepad support is disabled.
if ( if (
(!this.gamepadSupport && this.interactions[b].source === 'gamepad') || (!this.gamepadSupport && this.interactions[b].source === 'gamepad') ||
(this.interactions[b].sourceName && this.interactions[b].sourceName !== this.chosenGamepad) (this.interactions[b].sourceName && this.interactions[b].sourceName !== this.chosenGamepad) ||
this.pauseUpdate
) { ) {
// Deletes the last interaction for a button if gamepad is disabled. // Deletes the last interaction for a button if gamepad is disabled.
this.delLastProcessedMovementTime(b as Button); this.delLastProcessedMovementTime(b as Button);
@ -304,8 +307,8 @@ export class InputsController {
// for each gamepad, we set its mapping in this.configs // 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;
this.configs[gamepad] = config; this.configs[gamepad] = config;
this.configs[gamepad].custom = {...config.default};
} }
if (this.chosenGamepad === thisGamepad.id) this.initChosenGamepad(this.chosenGamepad) if (this.chosenGamepad === thisGamepad.id) this.initChosenGamepad(this.chosenGamepad)
} }
@ -583,6 +586,7 @@ export class InputsController {
* This method is typically called when needing to ensure that all inputs are neutralized. * This method is typically called when needing to ensure that all inputs are neutralized.
*/ */
deactivatePressedKey(): void { deactivatePressedKey(): void {
this.pauseUpdate = true;
this.releaseButtonLock(this.buttonLock); this.releaseButtonLock(this.buttonLock);
this.releaseButtonLock(this.buttonLock2); this.releaseButtonLock(this.buttonLock2);
for (const b of Utils.getEnumValues(Button)) { for (const b of Utils.getEnumValues(Button)) {
@ -593,6 +597,7 @@ export class InputsController {
this.interactions[b].sourceName = null; this.interactions[b].sourceName = null;
} }
} }
setTimeout(() => this.pauseUpdate = false, 500);
} }
/** /**
@ -643,12 +648,9 @@ export class InputsController {
else if (this.buttonLock2 === button) this.buttonLock2 = null; else if (this.buttonLock2 === button) this.buttonLock2 = null;
} }
setBind(setting: SettingGamepad, button: Button) {
console.log('button,', button);
}
getActiveConfig() :GamepadConfig { getActiveConfig() :GamepadConfig {
return this.configs[this.chosenGamepad] || pad_generic; if (this.configs[this.chosenGamepad]?.padID) return this.configs[this.chosenGamepad]
return pad_generic as GamepadConfig;
} }
getPressedButtonLabel(button: Phaser.Input.Gamepad.Button) { getPressedButtonLabel(button: Phaser.Input.Gamepad.Button) {
@ -657,17 +659,23 @@ export class InputsController {
getCurrentButtonLabel(target: SettingGamepad) { getCurrentButtonLabel(target: SettingGamepad) {
const key = getKeyForSettingName(this.configs[this.chosenGamepad], target); const key = getKeyForSettingName(this.configs[this.chosenGamepad], target);
const id = getButtonIndexForKey(this.configs[this.chosenGamepad], key); return getIconForRebindedKey(this.configs[this.chosenGamepad], key);
return getIconForCustomIndex(this.configs[this.chosenGamepad], id);
} }
swapBinding(target, newBinding) { swapBinding(target, newBinding) {
this.deactivatePressedKey(); this.pauseUpdate = true;
const keyTarget = getKeyForSettingName(this.configs[this.chosenGamepad], target); const keyTarget = getKeyForRebindedSettingName(this.configs[this.chosenGamepad], target)
const keyNewBinding = getKeyForButtonIndex(this.configs[this.chosenGamepad], newBinding); const keyNewBinding = getKeyForButtonIndex(this.configs[this.chosenGamepad], newBinding);
const previousActionForThisNewBinding = this.configs[this.chosenGamepad].custom[keyNewBinding]; const previousActionForThisNewBinding = this.configs[this.chosenGamepad].custom[keyNewBinding];
const ActionForThisNewBinding = this.configs[this.chosenGamepad].custom[keyTarget]; const ActionForThisNewBinding = this.configs[this.chosenGamepad].custom[keyTarget];
this.configs[this.chosenGamepad].custom[keyTarget] = previousActionForThisNewBinding; this.configs[this.chosenGamepad].custom[keyTarget] = previousActionForThisNewBinding;
this.configs[this.chosenGamepad].custom[keyNewBinding] = ActionForThisNewBinding; this.configs[this.chosenGamepad].custom[keyNewBinding] = ActionForThisNewBinding;
this.scene.gameData.saveCustomMapping(this.chosenGamepad, this.configs[this.chosenGamepad].custom);
setTimeout(() => this.pauseUpdate = false, 500);
}
loadConfig(gamepadName: String, customMappings: MappingLayout): void {
if (!this.configs[gamepadName]) this.configs[gamepadName] = {};
this.configs[gamepadName].custom = customMappings;
} }
} }

View File

@ -30,6 +30,7 @@ import { TrainerVariant } from "../field/trainer";
import { OutdatedPhase, ReloadSessionPhase } from "#app/phases"; import { OutdatedPhase, ReloadSessionPhase } from "#app/phases";
import { Variant, variantData } from "#app/data/variant"; import { Variant, variantData } from "#app/data/variant";
import {setSettingGamepad, SettingGamepad, settingGamepadDefaults} from "./settings-gamepad"; import {setSettingGamepad, SettingGamepad, settingGamepadDefaults} from "./settings-gamepad";
import {MappingLayout} from "#app/inputs-controller";
const saveKey = 'x0i2O7WRiANTqPmZ'; // Temporary; secure encryption is not yet necessary const saveKey = 'x0i2O7WRiANTqPmZ'; // Temporary; secure encryption is not yet necessary
@ -227,6 +228,7 @@ export class GameData {
this.scene = scene; this.scene = scene;
this.loadSettings(); this.loadSettings();
this.loadGamepadSettings(); this.loadGamepadSettings();
this.loadCustomMapping();
this.trainerId = Utils.randInt(65536); this.trainerId = Utils.randInt(65536);
this.secretId = Utils.randInt(65536); this.secretId = Utils.randInt(65536);
this.starterData = {}; this.starterData = {};
@ -482,6 +484,25 @@ export class GameData {
return true; return true;
} }
public saveCustomMapping(gamepadName: string, mapping: MappingLayout): boolean {
let customMappings: object = {};
if (localStorage.hasOwnProperty('customMapping'))
customMappings = JSON.parse(localStorage.getItem('customMapping'));
customMappings[gamepadName] = mapping;
localStorage.setItem('customMapping', JSON.stringify(customMappings));
return true;
}
public loadCustomMapping(): boolean {
console.log('loadCustomMapping');
if (!localStorage.hasOwnProperty('customMapping'))
return false;
const customMappings = JSON.parse(localStorage.getItem('customMapping'));
for (const key of Object.keys(customMappings))
this.scene.inputController.loadConfig(key, customMappings[key]);
}
public saveGamepadSetting(setting: SettingGamepad, valueIndex: integer): boolean { public saveGamepadSetting(setting: SettingGamepad, valueIndex: integer): boolean {
let settingsGamepad: object = {}; let settingsGamepad: object = {};
if (localStorage.hasOwnProperty('settingsGamepad')) if (localStorage.hasOwnProperty('settingsGamepad'))

View File

@ -121,6 +121,7 @@ export function setSettingGamepad(scene: BattleScene, setting: SettingGamepad, v
const cancelHandler = () => { const cancelHandler = () => {
scene.ui.revertMode(); scene.ui.revertMode();
(scene.ui.getHandler() as SettingsGamepadUiHandler).setOptionCursor(Object.values(SettingGamepad).indexOf(SettingGamepad.Default_Controller), 0, true); (scene.ui.getHandler() as SettingsGamepadUiHandler).setOptionCursor(Object.values(SettingGamepad).indexOf(SettingGamepad.Default_Controller), 0, true);
(scene.ui.getHandler() as SettingsGamepadUiHandler).updateBindings();
return false; return false;
}; };
const changeGamepadHandler = (gamepad: string) => { const changeGamepadHandler = (gamepad: string) => {

View File

@ -12,7 +12,7 @@ import {
settingGamepadOptions settingGamepadOptions
} from "../system/settings-gamepad"; } from "../system/settings-gamepad";
import {truncateString} from "../utils"; import {truncateString} from "../utils";
import {getKeyForSettingName} from "#app/configs/gamepad-utils"; import {getIconForRebindedKey, getKeyForSettingName} from "#app/configs/gamepad-utils";
export default class SettingsGamepadUiHandler extends UiHandler { export default class SettingsGamepadUiHandler extends UiHandler {
private settingsContainer: Phaser.GameObjects.Container; private settingsContainer: Phaser.GameObjects.Container;
@ -89,11 +89,9 @@ export default class SettingsGamepadUiHandler extends UiHandler {
continue; continue;
} }
const key = getKeyForSettingName(this.scene.inputController.getActiveConfig(), SettingGamepad[setting]); const key = getKeyForSettingName(this.scene.inputController.getActiveConfig(), SettingGamepad[setting]);
const frame = this.scene.inputController.getActiveConfig().icons[key];
const icon = this.scene.add.sprite(0, 0, 'xbox'); const icon = this.scene.add.sprite(0, 0, 'xbox');
icon.setScale(0.1); icon.setScale(0.1);
icon.setOrigin(0, 0); icon.setOrigin(0, 0);
icon.setFrame(frame);
this.inputsIcons[key] = icon; this.inputsIcons[key] = icon;
this.optionsContainer.add(icon); this.optionsContainer.add(icon);
valueLabels.push(icon); valueLabels.push(icon);
@ -140,13 +138,17 @@ export default class SettingsGamepadUiHandler extends UiHandler {
} }
updateBindings(): void { updateBindings(): void {
// for (const elm of noOptionsCursors) { const activeConfig = this.scene.inputController.getActiveConfig();
// console.log('elm:', elm); for (const elm of noOptionsCursors) {
// } const key = getKeyForSettingName(activeConfig, elm);
const icon = getIconForRebindedKey(activeConfig, key);
this.inputsIcons[key].setFrame(icon);
}
} }
show(args: any[]): boolean { show(args: any[]): boolean {
super.show(args); super.show(args);
this.updateBindings();
const settings: object = localStorage.hasOwnProperty('settingsGamepad') ? JSON.parse(localStorage.getItem('settingsGamepad')) : {}; const settings: object = localStorage.hasOwnProperty('settingsGamepad') ? JSON.parse(localStorage.getItem('settingsGamepad')) : {};
// in the menu, for each line, we set the cursor position for each option, either on the previously selected, or the default value. // in the menu, for each line, we set the cursor position for each option, either on the previously selected, or the default value.