mirror of
https://github.com/pagefaultgames/pokerogue.git
synced 2025-07-15 12:52:20 +02:00
added navigation icon in the setting menu
This commit is contained in:
parent
72e75ffca8
commit
8491f0b1ad
@ -2,8 +2,8 @@ import {Button} from "#app/enums/buttons";
|
||||
import {SettingKeyboard} from "#app/system/settings-keyboard";
|
||||
|
||||
const cfg_keyboard_azerty = {
|
||||
padID: 'keyboard',
|
||||
padType: 'default',
|
||||
padID: 'default',
|
||||
padType: 'keyboard',
|
||||
deviceMapping: {
|
||||
KEY_A: Phaser.Input.Keyboard.KeyCodes.A,
|
||||
KEY_B: Phaser.Input.Keyboard.KeyCodes.B,
|
||||
|
@ -1,3 +1,5 @@
|
||||
import {Device} from "#app/enums/devices";
|
||||
|
||||
/**
|
||||
* Retrieves the key associated with the specified keycode from the mapping.
|
||||
*
|
||||
@ -118,6 +120,13 @@ export function getIconWithSettingName(config, settingName) {
|
||||
return getIconWithKey(config, key);
|
||||
}
|
||||
|
||||
export function getIconForLatestInput(configs, source, devices, settingName) {
|
||||
let config;
|
||||
if (source === 'gamepad') config = configs[devices[Device.GAMEPAD]];
|
||||
else config = configs[devices[Device.KEYBOARD]];
|
||||
return getIconWithSettingName(config, settingName);
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the setting name associated with the specified button.
|
||||
*
|
||||
|
@ -11,7 +11,7 @@ import SettingsGamepadUiHandler from "./ui/settings/settings-gamepad-ui-handler"
|
||||
import SettingsKeyboardUiHandler from "./ui/settings/settings-keyboard-ui-handler";
|
||||
import cfg_keyboard_azerty from "./configs/cfg_keyboard_azerty";
|
||||
import {Device} from "#app/enums/devices";
|
||||
import {getButtonWithKeycode, regenerateIdentifiers, swap} from "#app/configs/configHandler";
|
||||
import {getButtonWithKeycode, getIconForLatestInput, regenerateIdentifiers, swap} from "#app/configs/configHandler";
|
||||
|
||||
export interface DeviceMapping {
|
||||
[key: string]: number;
|
||||
@ -321,6 +321,7 @@ export class InputsController {
|
||||
* @param thisGamepad The gamepad that is being set up.
|
||||
*/
|
||||
setupGamepad(thisGamepad: Phaser.Input.Gamepad.Gamepad): void {
|
||||
this.lastSource = 'gamepad';
|
||||
const allGamepads = this.getGamepadsName();
|
||||
for (const gamepad of allGamepads) {
|
||||
const gamepadID = gamepad.toLowerCase();
|
||||
@ -381,12 +382,12 @@ export class InputsController {
|
||||
* @param event The keyboard event.
|
||||
*/
|
||||
keyboardKeyDown(event): void {
|
||||
this.lastSource = 'keyboard';
|
||||
const keyDown = event.keyCode;
|
||||
this.ensureKeyboardIsInit();
|
||||
if (this.keys.includes(keyDown)) return;
|
||||
this.keys.push(keyDown);
|
||||
const buttonDown = getButtonWithKeycode(this.getActiveConfig(Device.KEYBOARD), keyDown);
|
||||
this.lastSource = 'keyboard';
|
||||
if (buttonDown !== undefined) {
|
||||
this.events.emit('input_down', {
|
||||
controller_type: 'keyboard',
|
||||
@ -402,6 +403,7 @@ export class InputsController {
|
||||
* @param event The keyboard event.
|
||||
*/
|
||||
keyboardKeyUp(event): void {
|
||||
this.lastSource = 'keyboard';
|
||||
const keyDown = event.keyCode;
|
||||
this.keys = this.keys.filter(k => k !== keyDown);
|
||||
this.ensureKeyboardIsInit()
|
||||
@ -428,11 +430,11 @@ export class InputsController {
|
||||
if (!this.configs[this.selectedDevice[Device.KEYBOARD]]?.padID)
|
||||
this.setupKeyboard();
|
||||
if (!pad) return;
|
||||
this.lastSource = 'gamepad';
|
||||
if (!this.selectedDevice[Device.GAMEPAD])
|
||||
this.setChosenGamepad(pad.id);
|
||||
if (!this.gamepadSupport || pad.id.toLowerCase() !== this.selectedDevice[Device.GAMEPAD].toLowerCase()) return;
|
||||
const buttonDown = getButtonWithKeycode(this.getActiveConfig(Device.GAMEPAD), button.index);
|
||||
this.lastSource = 'gamepad';
|
||||
if (buttonDown !== undefined) {
|
||||
this.events.emit('input_down', {
|
||||
controller_type: 'gamepad',
|
||||
@ -453,6 +455,7 @@ export class InputsController {
|
||||
*/
|
||||
gamepadButtonUp(pad: Phaser.Input.Gamepad.Gamepad, button: Phaser.Input.Gamepad.Button, value: number): void {
|
||||
if (!pad) return;
|
||||
this.lastSource = 'gamepad';
|
||||
if (!this.gamepadSupport || pad.id.toLowerCase() !== this.selectedDevice[Device.GAMEPAD]) return;
|
||||
const buttonUp = getButtonWithKeycode(this.getActiveConfig(Device.GAMEPAD), button.index);
|
||||
if (buttonUp !== undefined) {
|
||||
@ -650,6 +653,28 @@ export class InputsController {
|
||||
return null;
|
||||
}
|
||||
|
||||
getIconForLatestInputRecorded(settingName) {
|
||||
if (this.lastSource === 'keyboard') this.ensureKeyboardIsInit();
|
||||
return getIconForLatestInput(this.configs, this.lastSource, this.selectedDevice, settingName);
|
||||
}
|
||||
|
||||
getLastSourceDevice(): Device {
|
||||
if (this.lastSource === 'gamepad') return Device.GAMEPAD;
|
||||
else return Device.KEYBOARD;
|
||||
}
|
||||
|
||||
getLastSourceConfig() {
|
||||
const sourceDevice = this.getLastSourceDevice();
|
||||
if (sourceDevice === Device.KEYBOARD)
|
||||
this.ensureKeyboardIsInit();
|
||||
return this.getActiveConfig(sourceDevice);
|
||||
}
|
||||
|
||||
getLastSourceType() {
|
||||
const config = this.getLastSourceConfig();
|
||||
return config?.padType;
|
||||
}
|
||||
|
||||
/**
|
||||
* Injects a custom mapping configuration into the configuration for a specific gamepad.
|
||||
* If the device does not have an existing configuration, it initializes one first.
|
||||
|
@ -39,8 +39,8 @@ export enum SettingInterface {
|
||||
}
|
||||
|
||||
const cfg_keyboard_azerty = {
|
||||
padID: 'keyboard',
|
||||
padType: 'default',
|
||||
padID: 'default',
|
||||
padType: 'keyboard',
|
||||
deviceMapping: {
|
||||
KEY_A: Phaser.Input.Keyboard.KeyCodes.A,
|
||||
KEY_B: Phaser.Input.Keyboard.KeyCodes.B,
|
||||
|
@ -1,4 +1,7 @@
|
||||
import {getSettingNameWithKeycode} from "#app/configs/configHandler";
|
||||
import {
|
||||
getIconForLatestInput,
|
||||
getSettingNameWithKeycode
|
||||
} from "#app/configs/configHandler";
|
||||
import {expect} from "vitest";
|
||||
import {SettingInterface} from "#app/test/cfg_keyboard.example";
|
||||
|
||||
@ -7,11 +10,18 @@ export class InGameManip {
|
||||
private keycode;
|
||||
private settingName;
|
||||
private icon;
|
||||
constructor(config) {
|
||||
private configs;
|
||||
private latestSource;
|
||||
private selectedDevice;
|
||||
|
||||
constructor(configs, config, selectedDevice) {
|
||||
this.config = config;
|
||||
this.configs = configs;
|
||||
this.selectedDevice = selectedDevice;
|
||||
this.keycode = null;
|
||||
this.settingName = null;
|
||||
this.icon = null;
|
||||
this.latestSource = null;
|
||||
}
|
||||
|
||||
whenWePressOnKeyboard(keycode) {
|
||||
@ -25,6 +35,24 @@ export class InGameManip {
|
||||
return this;
|
||||
}
|
||||
|
||||
forTheWantedBind(settingName) {
|
||||
if (!settingName.includes("Button_")) settingName = "Button_" + settingName;
|
||||
this.settingName = SettingInterface[settingName];
|
||||
return this;
|
||||
}
|
||||
|
||||
weShouldSeeTheIcon(icon) {
|
||||
if (!icon.includes("KEY_")) icon = "KEY_" + icon;
|
||||
this.icon = this.config.icons[icon];
|
||||
expect(getIconForLatestInput(this.configs, this.latestSource, this.selectedDevice, this.settingName)).toEqual(this.icon);
|
||||
return this;
|
||||
}
|
||||
|
||||
forTheSource(source) {
|
||||
this.latestSource = source;
|
||||
return this;
|
||||
}
|
||||
|
||||
normalizeSettingNameString(input) {
|
||||
// Convert the input string to lower case
|
||||
const lowerCasedInput = input.toLowerCase();
|
||||
|
@ -42,6 +42,7 @@ export class MenuManip {
|
||||
}
|
||||
|
||||
whenCursorIsOnSetting(settingName) {
|
||||
if (!settingName.includes("Button_")) settingName = "Button_" + settingName;
|
||||
this.settingName = SettingInterface[settingName];
|
||||
const buttonName = this.convertNameToButtonString(settingName);
|
||||
expect(this.config.settings[this.settingName]).toEqual(Button[buttonName]);
|
||||
|
@ -14,17 +14,26 @@ import {
|
||||
} from "#app/configs/configHandler";
|
||||
import {MenuManip} from "#app/test/helpers/menuManip";
|
||||
import {InGameManip} from "#app/test/helpers/inGameManip";
|
||||
import {Device} from "#app/enums/devices";
|
||||
import {InterfaceConfig} from "#app/inputs-controller";
|
||||
|
||||
|
||||
describe('Test Rebinding', () => {
|
||||
let config;
|
||||
let inGame;
|
||||
let inTheSettingMenu;
|
||||
const configs: Map<string, InterfaceConfig> = new Map();
|
||||
const selectedDevice = {
|
||||
[Device.GAMEPAD]: null,
|
||||
[Device.KEYBOARD]: 'default',
|
||||
}
|
||||
|
||||
beforeEach(() => {
|
||||
config = deepCopy(cfg_keyboard_azerty);
|
||||
config.custom = {...config.default}
|
||||
regenerateIdentifiers(config);
|
||||
inGame = new InGameManip(config);
|
||||
configs.default = config;
|
||||
inGame = new InGameManip(configs, config, selectedDevice);
|
||||
inTheSettingMenu = new MenuManip(config);
|
||||
});
|
||||
|
||||
@ -308,4 +317,10 @@ describe('Test Rebinding', () => {
|
||||
const buttonDown = config.settings[settingName];
|
||||
expect(buttonDown).toEqual(Button.DOWN);
|
||||
});
|
||||
it("retrieve the correct icon for a given source", () => {
|
||||
inTheSettingMenu.whenCursorIsOnSetting("Cycle_Shiny").iconDisplayedIs("KEY_R");
|
||||
inTheSettingMenu.whenCursorIsOnSetting("Cycle_Form").iconDisplayedIs("KEY_F");
|
||||
inGame.forTheSource("keyboard").forTheWantedBind("Cycle_Shiny").weShouldSeeTheIcon("R")
|
||||
inGame.forTheSource("keyboard").forTheWantedBind("Cycle_Form").weShouldSeeTheIcon("F")
|
||||
});
|
||||
});
|
||||
|
@ -62,13 +62,13 @@ function simulateKeyboardEvent(eventType, key, events) {
|
||||
switch (eventType) {
|
||||
case 'keydown':
|
||||
events.emit('input_down', {
|
||||
controller_type: 'touch',
|
||||
controller_type: 'keyboard',
|
||||
button: button,
|
||||
});
|
||||
break;
|
||||
case 'keyup':
|
||||
events.emit('input_up', {
|
||||
controller_type: 'touch',
|
||||
controller_type: 'keyboard',
|
||||
button: button,
|
||||
});
|
||||
break;
|
||||
|
@ -41,6 +41,7 @@ export default abstract class AbstractSettingsUiUiHandler extends UiHandler {
|
||||
protected layout: Map<string, LayoutConfig> = new Map<string, LayoutConfig>();
|
||||
// Will contain the input icons from the selected layout
|
||||
protected inputsIcons: InputsIcons;
|
||||
protected navigationIcons: InputsIcons;
|
||||
// list all the setting keys used in the selected layout (because dualshock has more buttons than xbox)
|
||||
protected keys: Array<String>;
|
||||
|
||||
@ -85,17 +86,31 @@ export default abstract class AbstractSettingsUiUiHandler extends UiHandler {
|
||||
const headerBg = addWindow(this.scene, 0, 0, (this.scene.game.canvas.width / 6) - 2, 24);
|
||||
headerBg.setOrigin(0, 0);
|
||||
|
||||
this.navigationIcons = {};
|
||||
|
||||
const iconPreviousTab = this.scene.add.sprite(0, 0, 'keyboard');
|
||||
iconPreviousTab.setScale(.1);
|
||||
iconPreviousTab.setOrigin(0, -0.1);
|
||||
iconPreviousTab.setPositionRelative(headerBg, 8, 4);
|
||||
this.navigationIcons['BUTTON_CYCLE_FORM'] = iconPreviousTab;
|
||||
|
||||
const iconNextTab = this.scene.add.sprite(0, 0, 'keyboard');
|
||||
iconNextTab.setScale(.1);
|
||||
iconNextTab.setOrigin(0, -0.1);
|
||||
iconNextTab.setPositionRelative(headerBg, headerBg.width - 20, 4);
|
||||
this.navigationIcons['BUTTON_CYCLE_SHINY'] = iconNextTab;
|
||||
|
||||
const headerText = addTextObject(this.scene, 0, 0, 'General', TextStyle.SETTINGS_LABEL);
|
||||
headerText.setOrigin(0, 0);
|
||||
headerText.setPositionRelative(headerBg, 8, 4);
|
||||
headerText.setPositionRelative(headerBg, 8 + iconPreviousTab.width/6 - 4, 4);
|
||||
|
||||
const gamepadText = addTextObject(this.scene, 0, 0, 'Gamepad', this.titleSelected === 'Gamepad' ? TextStyle.SETTINGS_SELECTED : TextStyle.SETTINGS_LABEL);
|
||||
gamepadText.setOrigin(0, 0);
|
||||
gamepadText.setPositionRelative(headerBg, 50, 4);
|
||||
gamepadText.setPositionRelative(headerBg, 50 + iconPreviousTab.width/6 - 4, 4);
|
||||
|
||||
const keyboardText = addTextObject(this.scene, 0, 0, 'Keyboard', this.titleSelected === 'Keyboard' ? TextStyle.SETTINGS_SELECTED : TextStyle.SETTINGS_LABEL);
|
||||
keyboardText.setOrigin(0, 0);
|
||||
keyboardText.setPositionRelative(headerBg, 97, 4);
|
||||
keyboardText.setPositionRelative(headerBg, 97 + iconPreviousTab.width/6 - 4, 4);
|
||||
|
||||
this.optionsBg = addWindow(this.scene, 0, headerBg.height, (this.scene.game.canvas.width / 6) - 2, (this.scene.game.canvas.height / 6) - headerBg.height - 2);
|
||||
this.optionsBg.setOrigin(0, 0);
|
||||
@ -105,6 +120,8 @@ export default abstract class AbstractSettingsUiUiHandler extends UiHandler {
|
||||
this.settingsContainer.add(gamepadText);
|
||||
this.settingsContainer.add(keyboardText);
|
||||
this.settingsContainer.add(this.optionsBg);
|
||||
this.settingsContainer.add(iconNextTab)
|
||||
this.settingsContainer.add(iconPreviousTab)
|
||||
|
||||
/// Initialize a new configuration "screen" for each type of gamepad.
|
||||
for (const config of this.configs) {
|
||||
@ -235,6 +252,19 @@ export default abstract class AbstractSettingsUiUiHandler extends UiHandler {
|
||||
Object.keys(this.layout).forEach((key) => this.layout[key].optionsContainer.setVisible(false));
|
||||
// Fetch the active gamepad configuration from the input controller.
|
||||
const activeConfig = this.getActiveConfig();
|
||||
|
||||
for (const settingName of Object.keys(this.navigationIcons)) {
|
||||
const icon = this.scene.inputController?.getIconForLatestInputRecorded(settingName);
|
||||
if (icon) {
|
||||
const type = this.scene.inputController?.getLastSourceType();
|
||||
this.navigationIcons[settingName].setTexture(type);
|
||||
this.navigationIcons[settingName].setFrame(icon);
|
||||
this.navigationIcons[settingName].alpha = 1;
|
||||
} else {
|
||||
this.navigationIcons[settingName].alpha = 0;
|
||||
}
|
||||
}
|
||||
|
||||
// Set the UI layout for the active configuration. If unsuccessful, exit the function early.
|
||||
if (!this.setLayout(activeConfig)) return;
|
||||
|
||||
@ -258,7 +288,6 @@ export default abstract class AbstractSettingsUiUiHandler extends UiHandler {
|
||||
this.inputsIcons[elm].setFrame(icon);
|
||||
this.inputsIcons[elm].alpha = 1;
|
||||
} else {
|
||||
if (!this.inputsIcons[elm]) debugger;
|
||||
this.inputsIcons[elm].alpha = 0;
|
||||
}
|
||||
}
|
||||
|
@ -1,11 +1,12 @@
|
||||
import BattleScene from "../../battle-scene";
|
||||
import { Setting, reloadSettings, settingDefaults, settingOptions } from "../../system/settings";
|
||||
import {Setting, reloadSettings, settingDefaults, settingOptions} from "../../system/settings";
|
||||
import { hasTouchscreen, isMobile } from "../../touch-controls";
|
||||
import { TextStyle, addTextObject } from "../text";
|
||||
import { Mode } from "../ui";
|
||||
import UiHandler from "../ui-handler";
|
||||
import { addWindow } from "../ui-theme";
|
||||
import {Button} from "../../enums/buttons";
|
||||
import {InputsIcons} from "#app/ui/settings/abstract-settings-ui-handler";
|
||||
|
||||
export default class SettingsUiHandler extends UiHandler {
|
||||
private settingsContainer: Phaser.GameObjects.Container;
|
||||
@ -20,6 +21,8 @@ export default class SettingsUiHandler extends UiHandler {
|
||||
private settingLabels: Phaser.GameObjects.Text[];
|
||||
private optionValueLabels: Phaser.GameObjects.Text[][];
|
||||
|
||||
protected navigationIcons: InputsIcons;
|
||||
|
||||
private cursorObj: Phaser.GameObjects.NineSlice;
|
||||
|
||||
private reloadRequired: boolean;
|
||||
@ -39,20 +42,34 @@ export default class SettingsUiHandler extends UiHandler {
|
||||
|
||||
this.settingsContainer.setInteractive(new Phaser.Geom.Rectangle(0, 0, this.scene.game.canvas.width / 6, this.scene.game.canvas.height / 6), Phaser.Geom.Rectangle.Contains);
|
||||
|
||||
this.navigationIcons = {};
|
||||
|
||||
const headerBg = addWindow(this.scene, 0, 0, (this.scene.game.canvas.width / 6) - 2, 24);
|
||||
headerBg.setOrigin(0, 0);
|
||||
|
||||
const iconPreviousTab = this.scene.add.sprite(0, 0, 'keyboard');
|
||||
iconPreviousTab.setScale(.1);
|
||||
iconPreviousTab.setOrigin(0, -0.1);
|
||||
iconPreviousTab.setPositionRelative(headerBg, 8, 4);
|
||||
this.navigationIcons['BUTTON_CYCLE_FORM'] = iconPreviousTab;
|
||||
|
||||
const iconNextTab = this.scene.add.sprite(0, 0, 'keyboard');
|
||||
iconNextTab.setScale(.1);
|
||||
iconNextTab.setOrigin(0, -0.1);
|
||||
iconNextTab.setPositionRelative(headerBg, headerBg.width - 20, 4);
|
||||
this.navigationIcons['BUTTON_CYCLE_SHINY'] = iconNextTab;
|
||||
|
||||
const headerText = addTextObject(this.scene, 0, 0, 'General', TextStyle.SETTINGS_SELECTED);
|
||||
headerText.setOrigin(0, 0);
|
||||
headerText.setPositionRelative(headerBg, 8, 4);
|
||||
headerText.setPositionRelative(headerBg, 8 + iconPreviousTab.width/6 - 4, 4);
|
||||
|
||||
const gamepadText = addTextObject(this.scene, 0, 0, 'Gamepad', TextStyle.SETTINGS_LABEL);
|
||||
gamepadText.setOrigin(0, 0);
|
||||
gamepadText.setPositionRelative(headerBg, 50, 4);
|
||||
gamepadText.setPositionRelative(headerBg, 50 + iconPreviousTab.width/6 - 4, 4);
|
||||
|
||||
const keyboardText = addTextObject(this.scene, 0, 0, 'Keyboard', TextStyle.SETTINGS_LABEL);
|
||||
keyboardText.setOrigin(0, 0);
|
||||
keyboardText.setPositionRelative(headerBg, 97, 4);
|
||||
keyboardText.setPositionRelative(headerBg, 97 + iconPreviousTab.width/6 - 4, 4);
|
||||
|
||||
this.optionsBg = addWindow(this.scene, 0, headerBg.height, (this.scene.game.canvas.width / 6) - 2, (this.scene.game.canvas.height / 6) - headerBg.height - 2);
|
||||
this.optionsBg.setOrigin(0, 0);
|
||||
@ -104,6 +121,8 @@ export default class SettingsUiHandler extends UiHandler {
|
||||
this.settingsContainer.add(keyboardText);
|
||||
this.settingsContainer.add(this.optionsBg);
|
||||
this.settingsContainer.add(this.optionsContainer);
|
||||
this.settingsContainer.add(iconNextTab)
|
||||
this.settingsContainer.add(iconPreviousTab)
|
||||
|
||||
ui.add(this.settingsContainer);
|
||||
|
||||
@ -113,9 +132,23 @@ export default class SettingsUiHandler extends UiHandler {
|
||||
this.settingsContainer.setVisible(false);
|
||||
}
|
||||
|
||||
updateBindings(): void {
|
||||
for (const settingName of Object.keys(this.navigationIcons)) {
|
||||
const icon = this.scene.inputController?.getIconForLatestInputRecorded(settingName);
|
||||
if (icon) {
|
||||
const type = this.scene.inputController?.getLastSourceType();
|
||||
this.navigationIcons[settingName].setTexture(type);
|
||||
this.navigationIcons[settingName].setFrame(icon);
|
||||
this.navigationIcons[settingName].alpha = 1;
|
||||
} else
|
||||
this.navigationIcons[settingName].alpha = 0;
|
||||
}
|
||||
}
|
||||
|
||||
show(args: any[]): boolean {
|
||||
super.show(args);
|
||||
|
||||
this.updateBindings();
|
||||
|
||||
const settings: object = localStorage.hasOwnProperty('settings') ? JSON.parse(localStorage.getItem('settings')) : {};
|
||||
|
||||
Object.keys(settingDefaults).forEach((setting, s) => this.setOptionCursor(s, settings.hasOwnProperty(setting) ? settings[setting] : settingDefaults[setting]));
|
||||
|
Loading…
Reference in New Issue
Block a user