pokerogue/src/ui/settings/settings-keyboard-ui-handler.ts

184 lines
7.0 KiB
TypeScript
Raw Normal View History

import BattleScene from "../../battle-scene";
2024-10-04 13:08:31 +08:00
import { Mode } from "../ui";
import cfg_keyboard_qwerty from "#app/configs/inputs/cfg_keyboard_qwerty";
import {
setSettingKeyboard,
SettingKeyboard,
settingKeyboardBlackList,
settingKeyboardDefaults,
settingKeyboardOptions
2024-06-03 19:57:47 -04:00
} from "#app/system/settings/settings-keyboard";
2024-10-04 13:08:31 +08:00
import { reverseValueToKeySetting, truncateString } from "#app/utils";
import AbstractControlSettingsUiHandler from "#app/ui/settings/abstract-control-settings-ui-handler";
2024-10-04 13:08:31 +08:00
import { InterfaceConfig } from "#app/inputs-controller";
import { addTextObject, TextStyle } from "#app/ui/text";
import { deleteBind } from "#app/configs/inputs/configHandler";
import { Device } from "#enums/devices";
import { NavigationManager } from "#app/ui/settings/navigationMenu";
import i18next from "i18next";
/**
* Class representing the settings UI handler for keyboards.
*
2024-06-03 19:57:47 -04:00
* @extends AbstractControlSettingsUiHandler
*/
2024-06-03 19:57:47 -04:00
export default class SettingsKeyboardUiHandler extends AbstractControlSettingsUiHandler {
/**
* Creates an instance of SettingsKeyboardUiHandler.
*
* @param scene - The BattleScene instance.
* @param mode - The UI mode, optional.
*/
constructor(scene: BattleScene, mode: Mode | null = null) {
super(scene, mode);
this.titleSelected = "Keyboard";
2024-06-03 19:57:47 -04:00
this.setting = SettingKeyboard;
this.settingDeviceDefaults = settingKeyboardDefaults;
this.settingDeviceOptions = settingKeyboardOptions;
2024-10-04 13:08:31 +08:00
this.configs = [ cfg_keyboard_qwerty ];
this.commonSettingsCount = 0;
this.textureOverride = "keyboard";
this.localStoragePropertyName = "settingsKeyboard";
this.settingBlacklisted = settingKeyboardBlackList;
2024-06-03 19:57:47 -04:00
this.device = Device.KEYBOARD;
[Refactor] use typescript `strict-null` (#3259) * TS: enable strict-null * fix battle-scene.ts * fix voucher.ts * adapt more files to strict-null * adapt more files to strict-null ( 2) * adapt ability.ts to strict-null * adapt `arena.ts` to strict-null * adapt TagAddedEvent constructor to strict-null * adapt phases.ts.to strict-null * adapt status-effect.ts to strict-null * adapt `account.ts` to strict-null * adapt `configHandler.ts` to strict-null * adapt `ability.ts` to strict-null * adapt `biomes.ts` to strict-null * adapt `challenge.ts` to strict-null * adapt `daily-run.ts` to strict-null * adapt `nature.ts` to strict-null * adapt `pokemon-forms.ts` to strict-null * adapt `tainer-names.ts` to strict-null * adapt `types.ts` to strict-null * adapt `weather.ts` to strict-null * adapt `egg-hatch-phase.ts` to strict-null * adapt `evolution-phase.ts` to strict-null * adapt `pokemon-sprite-sparkle-handler.ts` to strict-null * adapt `evolution-phase.ts` to strict-null * adapt `game-mode.ts` to strict-null * adapt `utils.ts` to strict-null * adapt `voucher-ui-handler.ts` to strict-null * adapt `src/ui/unavailable-modal-ui-handler.ts` to strict-null * adapt `src/ui/ui.ts` to strict-null * adapt `src/ui/ui-theme.ts` to strict-null * adapt `src/ui/title-ui-handler.ts` to strict-null * adapt `src/ui/time-of-day-widget.ts` to strict-null * adapt `src/ui/text.ts` to strict-null * adapt `src/ui/target-select-ui-handler.ts` to strict-null * adapt `src/ui/settings/settings-keyboard-ui-handler.ts` to strict-null * adapt more files to strict-null (3) * adapt more files to strict-null (4) * adapt more files (mostly tests) to strict-null (5) * adapt more files to strict-null (6) * adapt more files to strict-null (7) * Update `src/data/pokemon-evolutions.ts` for strict-null Partial update `src/data/pokemon-species.ts` for strict-null * adapt more files to strict-null (8) * adapt more files to strict-null (9) * Strict some more nulls (still a few errors remaining) * adapt rest of the files to strict-null (9) * fix tests (check for null instead of undefined) * repalce a lot of `??` with bangs And added TODO notice as usual * fix more tests * all tests pass now * fix broken game-loop after trainer battle add some console.warn for missing cases and falling back to default * remove guessed fallback from utils.rgbHexToRgba * add TODO for this.currentBattle = null * adjust getPokemonById() return to include `null` * fix compilation errors * add test for pokemon.trySetStatus * `chanceMultiplier` shouldn't be optional * allow `null` for currentPhase * adjust hasExpSprite logic for no keymatch found * reduce bang usage in account.updateUserInfo() * fix new strict-null issues after merge * fix `strict-null` issues in dropdown.ts and sand_spit.test.ts * fix egg-gacha * adapt gul_missile.test.ts to strict-null * fix move.ts strict-null * fix i18n.ts strict-null * fix strict-null issues * fix baton_pass test after accidentially breaking it * chore: fix compiler errors * revert accidential changes in baton_pass.test.ts --------- Co-authored-by: NightKev <34855794+DayKev@users.noreply.github.com>
2024-08-07 09:23:12 -07:00
const deleteEvent = scene.input.keyboard?.addKey(Phaser.Input.Keyboard.KeyCodes.DELETE);
const restoreDefaultEvent = scene.input.keyboard?.addKey(Phaser.Input.Keyboard.KeyCodes.HOME);
deleteEvent && deleteEvent.on("up", this.onDeleteDown, this);
restoreDefaultEvent && restoreDefaultEvent.on("up", this.onHomeDown, this);
}
2024-06-03 19:57:47 -04:00
setSetting = setSettingKeyboard;
/**
* Setup UI elements.
*/
setup() {
super.setup();
// If no gamepads are detected, set up a default UI prompt in the settings container.
this.layout["noKeyboard"] = new Map();
const optionsContainer = this.scene.add.container(0, 0);
optionsContainer.setVisible(false); // Initially hide the container as no gamepads are connected.
const label = addTextObject(this.scene, 8, 28, i18next.t("settings:keyboardPleasePress"), TextStyle.SETTINGS_LABEL);
label.setOrigin(0, 0);
optionsContainer.add(label);
this.settingsContainer.add(optionsContainer);
const iconDelete = this.scene.add.sprite(0, 0, "keyboard");
iconDelete.setOrigin(0, -0.1);
iconDelete.setPositionRelative(this.actionsBg, this.navigationContainer.width - 260, 4);
this.navigationIcons["BUTTON_DELETE"] = iconDelete;
const deleteText = addTextObject(this.scene, 0, 0, i18next.t("settings:delete"), TextStyle.SETTINGS_LABEL);
deleteText.setOrigin(0, 0.15);
2024-10-04 13:08:31 +08:00
deleteText.setPositionRelative(iconDelete, -deleteText.width / 6 - 2, 0);
this.settingsContainer.add(iconDelete);
this.settingsContainer.add(deleteText);
// Map the 'noKeyboard' layout options for easy access.
this.layout["noKeyboard"].optionsContainer = optionsContainer;
this.layout["noKeyboard"].label = label;
}
/**
* Handle the home key press event.
*/
onHomeDown(): void {
2024-10-04 13:08:31 +08:00
if (![ Mode.SETTINGS_KEYBOARD, Mode.SETTINGS_GAMEPAD ].includes(this.scene.ui.getMode())) {
return;
}
this.scene.gameData.resetMappingToFactory();
NavigationManager.getInstance().updateIcons();
}
/**
* Handle the delete key press event.
*/
onDeleteDown(): void {
if (this.scene.ui.getMode() !== Mode.SETTINGS_KEYBOARD) {
return;
}
const cursor = this.cursor + this.scrollCursor; // Calculate the absolute cursor position.
const selection = this.settingLabels[cursor].text;
const key = reverseValueToKeySetting(selection);
const settingName = SettingKeyboard[key];
const activeConfig = this.getActiveConfig();
const success = deleteBind(this.getActiveConfig(), settingName);
if (success) {
this.saveCustomKeyboardMappingToLocalStorage(activeConfig);
this.updateBindings();
NavigationManager.getInstance().updateIcons();
}
}
/**
* Set the layout for the active configuration.
*
* @param activeConfig - The active keyboard configuration.
* @returns `true` if the layout was successfully applied, otherwise `false`.
*/
setLayout(activeConfig: InterfaceConfig): boolean {
// Check if there is no active configuration (e.g., no gamepad connected).
if (!activeConfig) {
// Retrieve the layout for when no gamepads are connected.
const layout = this.layout["noKeyboard"];
// Make the options container visible to show message.
layout.optionsContainer.setVisible(true);
// Return false indicating the layout application was not successful due to lack of gamepad.
return false;
}
return super.setLayout(activeConfig);
}
/**
* Update the display of the chosen keyboard layout.
*/
updateChosenKeyboardDisplay(): void {
// Update any bindings that might have changed since the last update.
this.updateBindings();
// Iterate over the keys in the settingDevice enumeration.
2024-10-04 13:08:31 +08:00
for (const [ index, key ] of Object.keys(this.setting).entries()) {
2024-06-03 19:57:47 -04:00
const setting = this.setting[key]; // Get the actual setting value using the key.
// Check if the current setting corresponds to the layout setting.
2024-06-03 19:57:47 -04:00
if (setting === this.setting.Default_Layout) {
// Iterate over all layouts excluding the 'noGamepads' special case.
for (const _key of Object.keys(this.layout)) {
if (_key === "noKeyboard") {
continue;
} // Skip updating the no gamepad layout.
// Update the text of the first option label under the current setting to the name of the chosen gamepad,
// truncating the name to 30 characters if necessary.
this.layout[_key].optionValueLabels[index][0].setText(truncateString(this.scene.inputController.selectedDevice[Device.KEYBOARD], 22));
}
}
}
}
/**
* Save the custom keyboard mapping to local storage.
*
* @param config - The configuration to save.
*/
saveCustomKeyboardMappingToLocalStorage(config): void {
this.scene.gameData.saveMappingConfigs(this.scene.inputController?.selectedDevice[Device.KEYBOARD], config);
}
/**
* Save the setting to local storage.
*
* @param settingName - The name of the setting to save.
* @param cursor - The cursor position to save.
*/
saveSettingToLocalStorage(settingName, cursor): void {
2024-06-03 19:57:47 -04:00
if (this.setting[settingName] !== this.setting.Default_Layout) {
this.scene.gameData.saveControlSetting(this.device, this.localStoragePropertyName, settingName, this.settingDeviceDefaults, cursor);
}
}
}