first iteration of KeyboardBindingUiHandler

pull/685/head
Greenlamp 2024-05-12 21:22:32 +02:00
parent c963970adf
commit c6d3f93b3f
4 changed files with 197 additions and 54 deletions

View File

@ -5,6 +5,7 @@ const cfg_keyboard_azerty = {
padID: 'keyboard', padID: 'keyboard',
padType: 'azerty', padType: 'azerty',
gamepadMapping: { gamepadMapping: {
NEED TO ADD KEYCODE FROM EVENT HERE
KEY_A: 0, KEY_A: 0,
KEY_B: 0, KEY_B: 0,
KEY_C: 0, KEY_C: 0,

View File

@ -10,6 +10,12 @@ export function getKeyFromInputIndex(config: GamepadConfig, index: number): Stri
} }
return null; return null;
} }
export function getKeyFromKeyboardKey(config: GamepadConfig, key): String | null {
for (const _key of Object.keys(config.gamepadMapping)) {
if (config.gamepadMapping[_key] === key) return _key;
}
return null;
}
// Given a setting name, return the key assigned to it from the config file // Given a setting name, return the key assigned to it from the config file
export function getKeyForSettingName(config: GamepadConfig, settingName: string): String | null { export function getKeyForSettingName(config: GamepadConfig, settingName: string): String | null {
@ -41,6 +47,11 @@ export function getCurrenlyAssignedIconFromInputIndex(config: GamepadConfig, ind
return config.icons[key]; return config.icons[key];
} }
export function getCurrenlyAssignedIconFromKeyboardKey(config: GamepadConfig, key): String {
const _key = getKeyFromKeyboardKey(config, key);
return config.icons[_key];
}
// 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): string { export function getCurrentlyAssignedIconToSettingName(config: GamepadConfig, settingName: string): string {
const key = getCurrentlyAssignedToSettingName(config, settingName); const key = getCurrentlyAssignedToSettingName(config, settingName);

View File

@ -10,7 +10,7 @@ import SettingsGamepadUiHandler from "./ui/settings/settings-gamepad-ui-handler"
import {SettingGamepad} from "./system/settings-gamepad"; import {SettingGamepad} from "./system/settings-gamepad";
import { import {
getCurrenlyAssignedIconFromInputIndex, getCurrentlyAssignedIconToSettingName, getCurrenlyAssignedIconFromInputIndex, getCurrentlyAssignedIconToSettingName,
getKeyFromInputIndex, getCurrentlyAssignedToSettingName getKeyFromInputIndex, getCurrentlyAssignedToSettingName, getCurrenlyAssignedIconFromKeyboardKey
} from "./configs/gamepad-utils"; } from "./configs/gamepad-utils";
import SettingsKeyboardUiHandler from "#app/ui/settings/settings-keyboard-ui-handler"; import SettingsKeyboardUiHandler from "#app/ui/settings/settings-keyboard-ui-handler";
import cfg_keyboard_azerty from "#app/configs/cfg_keyboard_azerty"; import cfg_keyboard_azerty from "#app/configs/cfg_keyboard_azerty";
@ -724,6 +724,10 @@ export class InputsController {
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)];
} }
getPressedKeyLabel(key): string {
return getCurrenlyAssignedIconFromKeyboardKey(this.configs[this.chosenKeyboard], key);
}
/** /**
* Retrieves the currently assigned icon for a specific setting on the chosen gamepad. * Retrieves the currently assigned icon for a specific setting on the chosen gamepad.
* *
@ -734,6 +738,10 @@ export class InputsController {
return getCurrentlyAssignedIconToSettingName(this.configs[this.chosenGamepad], target); return getCurrentlyAssignedIconToSettingName(this.configs[this.chosenGamepad], target);
} }
getKeyboardCurrentlyAssignedIconToDisplay(target: SettingGamepad): string {
return getCurrentlyAssignedIconToSettingName(this.configs[this.chosenKeyboard], target);
}
/** /**
* Swaps the binding of two controls on the chosen gamepad configuration. * Swaps the binding of two controls on the chosen gamepad configuration.
* It temporarily pauses updates, swaps the key bindings, saves the new configuration, * It temporarily pauses updates, swaps the key bindings, saves the new configuration,
@ -754,6 +762,10 @@ export class InputsController {
setTimeout(() => this.pauseUpdate = false, 500); setTimeout(() => this.pauseUpdate = false, 500);
} }
swapKeyboardBinding(settingName, pressedButton): void {
}
/** /**
* Injects a custom mapping configuration into the gamepad configuration for a specific gamepad. * 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. * If the gamepad does not have an existing configuration, it initializes one first.

View File

@ -2,88 +2,207 @@ import UiHandler from "../ui-handler";
import BattleScene from "../../battle-scene"; import BattleScene from "../../battle-scene";
import {Mode} from "../ui"; import {Mode} from "../ui";
import {Button} from "../../enums/buttons"; import {Button} from "../../enums/buttons";
import Phaser from "phaser";
import {addWindow} from "#app/ui/ui-theme";
import {addTextObject, TextStyle} from "#app/ui/text";
import {SettingKeyboard} from "#app/system/settings-keyboard";
export default class KeyboardBindingUiHandler extends UiHandler { export default class KeyboardBindingUiHandler extends UiHandler {
// Containers for different segments of the UI.
protected optionSelectContainer: Phaser.GameObjects.Container;
protected actionsContainer: Phaser.GameObjects.Container;
// Background elements for titles and action areas.
protected titleBg: Phaser.GameObjects.NineSlice;
protected actionBg: Phaser.GameObjects.NineSlice;
protected optionSelectBg: Phaser.GameObjects.NineSlice;
// Text elements for displaying instructions and actions.
private unlockText: Phaser.GameObjects.Text;
private swapText: Phaser.GameObjects.Text;
private actionLabel: Phaser.GameObjects.Text;
private cancelLabel: Phaser.GameObjects.Text;
private listening: boolean = false;
private buttonPressed: number | null = null;
// Icons for displaying current and new button assignments.
private newButtonIcon: Phaser.GameObjects.Sprite;
private targetButtonIcon: Phaser.GameObjects.Sprite;
// Function to call on cancel or completion of binding.
private cancelFn: (boolean?) => boolean;
// The specific setting being modified.
private target: SettingKeyboard;
constructor(scene: BattleScene, mode?: Mode) { constructor(scene: BattleScene, mode?: Mode) {
super(scene, mode); super(scene, mode);
// Listen to gamepad button down events to initiate binding.
scene.input.keyboard.on('keydown', this.onKeyDown, this);
} }
setup() { setup() {
const ui = this.getUi(); const ui = this.getUi();
this.optionSelectContainer = this.scene.add.container(0, 0);
this.actionsContainer = this.scene.add.container(0, 0);
// Initially, containers are not visible.
this.optionSelectContainer.setVisible(false);
this.actionsContainer.setVisible(false);
// Add containers to the UI.
ui.add(this.optionSelectContainer);
ui.add(this.actionsContainer);
// Setup backgrounds and text objects for UI.
this.titleBg = addWindow(this.scene, (this.scene.game.canvas.width / 6) - this.getWindowWidth(), -(this.scene.game.canvas.height / 6) + 28 + 21, this.getWindowWidth(), 24);
this.titleBg.setOrigin(0.5);
this.optionSelectContainer.add(this.titleBg);
this.actionBg = addWindow(this.scene, (this.scene.game.canvas.width / 6) - this.getWindowWidth(), -(this.scene.game.canvas.height / 6) + this.getWindowHeight() + 28 + 21 + 21, this.getWindowWidth(), 24);
this.actionBg.setOrigin(0.5);
this.actionsContainer.add(this.actionBg);
// Text prompts and instructions for the user.
this.unlockText = addTextObject(this.scene, 0, 0, 'Press a button...', TextStyle.WINDOW);
this.unlockText.setOrigin(0, 0);
this.unlockText.setPositionRelative(this.titleBg, 36, 4);
this.optionSelectContainer.add(this.unlockText);
this.optionSelectBg = addWindow(this.scene, (this.scene.game.canvas.width / 6) - this.getWindowWidth(), -(this.scene.game.canvas.height / 6) + this.getWindowHeight() + 28, this.getWindowWidth(), this.getWindowHeight());
this.optionSelectBg.setOrigin(0.5);
this.optionSelectContainer.add(this.optionSelectBg);
// New button icon setup.
this.newButtonIcon = this.scene.add.sprite(0, 0, 'keyboard');
this.newButtonIcon.setScale(0.15);
this.newButtonIcon.setPositionRelative(this.optionSelectBg, 78, 16);
this.newButtonIcon.setOrigin(0.5);
this.newButtonIcon.setVisible(false);
this.swapText = addTextObject(this.scene, 0, 0, 'will swap with', TextStyle.WINDOW);
this.swapText.setOrigin(0.5);
this.swapText.setPositionRelative(this.optionSelectBg, this.optionSelectBg.width / 2 - 2, this.optionSelectBg.height / 2 - 2);
this.swapText.setVisible(false);
this.targetButtonIcon = this.scene.add.sprite(0, 0, 'keyboard');
this.targetButtonIcon.setScale(0.15);
this.targetButtonIcon.setPositionRelative(this.optionSelectBg, 78, 48);
this.targetButtonIcon.setOrigin(0.5);
this.targetButtonIcon.setVisible(false);
this.cancelLabel = addTextObject(this.scene, 0, 0, 'Cancel', TextStyle.SETTINGS_LABEL);
this.cancelLabel.setOrigin(0, 0.5);
this.cancelLabel.setPositionRelative(this.actionBg, 10, this.actionBg.height / 2);
this.actionLabel = addTextObject(this.scene, 0, 0, 'Confirm Swap', TextStyle.SETTINGS_LABEL);
this.actionLabel.setOrigin(0, 0.5);
this.actionLabel.setPositionRelative(this.actionBg, this.actionBg.width - 75, this.actionBg.height / 2);
// Add swap and cancel labels to the containers.
this.optionSelectContainer.add(this.newButtonIcon);
this.optionSelectContainer.add(this.swapText);
this.optionSelectContainer.add(this.targetButtonIcon);
this.actionsContainer.add(this.actionLabel);
this.actionsContainer.add(this.cancelLabel);
} }
updateBindings(): void { onKeyDown(event): void {
const key = event.keyCode;
// // Check conditions before processing the button press.
if (!this.listening || this.buttonPressed !== null) return;
this.buttonPressed = key;
const buttonIcon = this.scene.inputController.getPressedKeyLabel(key);
const assignedButtonIcon = this.scene.inputController.getKeyboardCurrentlyAssignedIconToDisplay(this.target);
this.newButtonIcon.setFrame(buttonIcon);
this.targetButtonIcon.setFrame(assignedButtonIcon);
this.newButtonIcon.setVisible(true);
this.targetButtonIcon.setVisible(true);
this.swapText.setVisible(true);
this.setCursor(0);
this.actionsContainer.setVisible(true);
} }
show(args: any[]): boolean { show(args: any[]): boolean {
super.show(args); super.show(args);
this.buttonPressed = null;
this.cancelFn = args[0].cancelHandler;
this.target = args[0].target;
// Move the settings container to the end of the UI stack to ensure it is displayed on top. // Bring the option and action containers to the front of the UI.
// this.getUi().moveTo(this.settingsContainer, this.getUi().length - 1); this.getUi().bringToTop(this.optionSelectContainer);
this.getUi().bringToTop(this.actionsContainer);
// Hide any tooltips that might be visible before showing the settings container. this.optionSelectContainer.setVisible(true);
this.getUi().hideTooltip(); setTimeout(() => this.listening = true, 150);
// Return true to indicate the UI was successfully shown.
return true; return true;
} }
getWindowWidth(): number {
return 160;
}
getWindowHeight(): number {
return 64;
}
processInput(button: Button): boolean { processInput(button: Button): boolean {
if (this.buttonPressed === null) return;
const ui = this.getUi(); const ui = this.getUi();
return false; let success = false;
switch (button) {
case Button.LEFT:
case Button.RIGHT:
// Toggle between action and cancel options.
const cursor = this.cursor ? 0 : 1;
success = this.setCursor(cursor);
break
case Button.ACTION:
// Process actions based on current cursor position.
if (this.cursor === 0) {
this.cancelFn();
} else {
success = true;
this.scene.inputController.swapKeyboardBinding(this.target, this.buttonPressed);
this.cancelFn(success);
}
break;
}
// Plays a select sound effect if an action was successfully processed.
if (success)
ui.playSelect();
else
ui.playError();
return success;
} }
setCursor(cursor: integer): boolean { setCursor(cursor: integer): boolean {
const ret = super.setCursor(cursor); this.cursor = cursor;
return ret; if (cursor === 1) {
this.actionLabel.setColor(this.getTextColor(TextStyle.SETTINGS_SELECTED));
this.actionLabel.setShadowColor(this.getTextColor(TextStyle.SETTINGS_SELECTED, true));
this.cancelLabel.setColor(this.getTextColor(TextStyle.WINDOW));
this.cancelLabel.setShadowColor(this.getTextColor(TextStyle.WINDOW, true));
return true;
} }
this.actionLabel.setColor(this.getTextColor(TextStyle.WINDOW));
setOptionCursor(settingIndex: integer, cursor: integer, save?: boolean): boolean { this.actionLabel.setShadowColor(this.getTextColor(TextStyle.WINDOW, true));
this.cancelLabel.setColor(this.getTextColor(TextStyle.SETTINGS_SELECTED));
this.cancelLabel.setShadowColor(this.getTextColor(TextStyle.SETTINGS_SELECTED, true));
return true; return true;
} }
setScrollCursor(scrollCursor: integer): boolean { clear() {
return true;
}
// updateSettingsScroll(): void {
// // Return immediately if the options container is not initialized.
// if (!this.optionsContainer) return;
//
// // Set the vertical position of the options container based on the current scroll cursor, multiplying by the item height.
// this.optionsContainer.setY(-16 * this.scrollCursor);
//
// // Iterate over all setting labels to update their visibility.
// for (let s = 0; s < this.settingLabels.length; s++) {
// // Determine if the current setting should be visible based on the scroll position.
// const visible = s >= this.scrollCursor && s < this.scrollCursor + 9;
//
// // Set the visibility of the setting label and its corresponding options.
// this.settingLabels[s].setVisible(visible);
// for (let option of this.optionValueLabels[s])
// option.setVisible(visible);
// }
// }
clear(): void {
super.clear(); super.clear();
this.target = null;
// Hide the settings container to remove it from the view. this.cancelFn = null;
// this.settingsContainer.setVisible(false); this.optionSelectContainer.setVisible(false);
this.actionsContainer.setVisible(false);
// Remove the cursor from the UI. this.newButtonIcon.setVisible(false);
this.eraseCursor(); this.targetButtonIcon.setVisible(false);
} this.swapText.setVisible(false);
eraseCursor(): void {
// Check if a cursor object exists.
// if (this.cursorObj)
// this.cursorObj.destroy(); // Destroy the cursor object to clean up resources.
//
// // Set the cursor object reference to null to fully dereference it.
// this.cursorObj = null;
} }
} }