diff --git a/src/inputs-controller.ts b/src/inputs-controller.ts index de4b80eb1..af2d1929c 100644 --- a/src/inputs-controller.ts +++ b/src/inputs-controller.ts @@ -66,8 +66,6 @@ export class InputsController { private gamepadSupport: boolean = true; - private gamepadSupport: boolean = true; - public customGamepadMapping = new Map(); public chosenGamepad: String; private disconnectedGamepads: Array = new Array(); diff --git a/src/system/settings-gamepad.ts b/src/system/settings-gamepad.ts index ce4fa77ea..b9bdc535c 100644 --- a/src/system/settings-gamepad.ts +++ b/src/system/settings-gamepad.ts @@ -24,9 +24,9 @@ export enum SettingGamepad { } export const settingGamepadOptions: SettingOptions = { - [SettingGamepad.Default_Controller]: [ 'Default', 'Change' ], - [SettingGamepad.Gamepad_Support]: [ 'Auto', 'Disabled' ], - [SettingGamepad.Swap_A_and_B]: [ 'Enabled', 'Disabled' ], + [SettingGamepad.Default_Controller]: ['Default', 'Change'], + [SettingGamepad.Gamepad_Support]: ['Auto', 'Disabled'], + [SettingGamepad.Swap_A_and_B]: ['Enabled', 'Disabled'], [SettingGamepad.Button_Action]: [`KEY ${Button.ACTION.toString()}`, 'Change'], [SettingGamepad.Button_Cancel]: [`KEY ${Button.CANCEL.toString()}`, 'Change'], // [SettingGamepad.Button_Menu]: [`KEY ${Button.MENU.toString()}`, 'Change'], @@ -59,7 +59,7 @@ export const settingGamepadDefaults: SettingDefaults = { // [SettingGamepad.Button_Slow_Down]: Button.SLOW_DOWN, }; -export const noOptionsCursors : Array = [ +export const noOptionsCursors: Array = [ SettingGamepad.Button_Action, SettingGamepad.Button_Cancel, ]; @@ -76,28 +76,25 @@ export function setSettingGamepad(scene: BattleScene, setting: SettingGamepad, v break; case SettingGamepad.Button_Action: case SettingGamepad.Button_Cancel: - // case SettingGamepad.Button_Menu: - // case SettingGamepad.Button_Stats: - // case SettingGamepad.Button_Cycle_Shiny: - // case SettingGamepad.Button_Cycle_Form: - // case SettingGamepad.Button_Cycle_Gender: - // case SettingGamepad.Button_Cycle_Ability: - // case SettingGamepad.Button_Cycle_Nature: - // case SettingGamepad.Button_Cycle_Variant: - // case SettingGamepad.Button_Speed_Up: - // case SettingGamepad.Button_Slow_Down: + // case SettingGamepad.Button_Menu: + // case SettingGamepad.Button_Stats: + // case SettingGamepad.Button_Cycle_Shiny: + // case SettingGamepad.Button_Cycle_Form: + // case SettingGamepad.Button_Cycle_Gender: + // case SettingGamepad.Button_Cycle_Ability: + // case SettingGamepad.Button_Cycle_Nature: + // case SettingGamepad.Button_Cycle_Variant: + // case SettingGamepad.Button_Speed_Up: + // case SettingGamepad.Button_Slow_Down: if (value) { if (scene.ui) { const cancelHandler = () => { scene.ui.revertMode(); - (scene.ui.getHandler() as SettingsGamepadUiHandler).setOptionCursor(Object.values(SettingGamepad).indexOf(setting), 0, true); return false; }; scene.ui.setOverlayMode(Mode.GAMEPAD_BINDING, { - options: [{ - label: 'Press a button on your gamepad', - handler: cancelHandler, - }] + target: setting, + cancelHandler: cancelHandler, }); } } @@ -117,7 +114,10 @@ export function setSettingGamepad(scene: BattleScene, setting: SettingGamepad, v return true; }; scene.ui.setOverlayMode(Mode.OPTION_SELECT, { - options: [...gp.map((g) => ({label: truncateString(g, 30), handler: () => changeGamepadHandler(g)})), { + options: [...gp.map((g) => ({ + label: truncateString(g, 30), + handler: () => changeGamepadHandler(g) + })), { label: 'Cancel', handler: cancelHandler, }] diff --git a/src/ui/gamepad-binding-ui-handler.ts b/src/ui/gamepad-binding-ui-handler.ts index e2dba78c7..f0f79c1cb 100644 --- a/src/ui/gamepad-binding-ui-handler.ts +++ b/src/ui/gamepad-binding-ui-handler.ts @@ -9,14 +9,22 @@ import Phaser from "phaser"; export default class GamepadBindingUiHandler extends UiHandler { protected optionSelectContainer: Phaser.GameObjects.Container; + protected actionsContainer: Phaser.GameObjects.Container; + protected titleBg: Phaser.GameObjects.NineSlice; + protected actionBg: Phaser.GameObjects.NineSlice; protected optionSelectBg: Phaser.GameObjects.NineSlice; private unlockText: Phaser.GameObjects.Text; private keyPressed: Phaser.GameObjects.Text; private alreadyAssignedText: Phaser.GameObjects.Text; + private actionLabel: Phaser.GameObjects.Text; + private cancelLabel: Phaser.GameObjects.Text; private listening: boolean = false; - private buttonPressed = ''; + private buttonPressed = null; private iconXbox: Phaser.GameObjects.Sprite; + private previousIconXbox: Phaser.GameObjects.Sprite; private iconDualshock: Phaser.GameObjects.Sprite; + private cancelFn; + private target; constructor(scene: BattleScene, mode: Mode = Mode.GAMEPAD_BINDING) { super(scene, mode); @@ -29,13 +37,20 @@ export default class GamepadBindingUiHandler extends UiHandler { setup() { const ui = this.getUi(); this.optionSelectContainer = this.scene.add.container(0, 0); + this.actionsContainer = this.scene.add.container(0, 0); this.optionSelectContainer.setVisible(false); + this.actionsContainer.setVisible(false); ui.add(this.optionSelectContainer); + ui.add(this.actionsContainer); - this.titleBg = addWindow(this.scene, (this.scene.game.canvas.width / 6) - this.getWindowWidth(), -(this.scene.game.canvas.height / 6) + 28 + 22, this.getWindowWidth(), 24); + 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); + this.unlockText = addTextObject(this.scene, 0, 0, 'Press a button...', TextStyle.WINDOW); this.unlockText.setOrigin(0, 0); this.unlockText.setPositionRelative(this.titleBg, 36, 4); @@ -46,29 +61,48 @@ export default class GamepadBindingUiHandler extends UiHandler { this.optionSelectContainer.add(this.optionSelectBg); this.iconXbox = this.scene.add.sprite(0, 0, 'xbox'); - this.iconXbox.setScale(0.2); - this.iconXbox.setPositionRelative(this.optionSelectBg, 0, 0); - this.iconXbox.setOrigin(0, 0); + this.iconXbox.setScale(0.15); + this.iconXbox.setPositionRelative(this.optionSelectBg, 78, 16); + this.iconXbox.setOrigin(0.5); this.iconXbox.setVisible(false); this.iconDualshock = this.scene.add.sprite(0, 0, 'dualshock'); - this.iconDualshock.setScale(0.2); - this.iconDualshock.setPositionRelative(this.optionSelectBg, this.optionSelectBg.width / 2, 0); - this.iconDualshock.setOrigin(0, 0); + this.iconDualshock.setScale(0.15); + this.iconDualshock.setPositionRelative(this.optionSelectBg, 78, 16); + this.iconDualshock.setOrigin(0.5); this.iconDualshock.setVisible(false); this.alreadyAssignedText = addTextObject(this.scene, 0, 0, 'already assigned to', TextStyle.WINDOW); - this.alreadyAssignedText.setOrigin(0, 0); - this.alreadyAssignedText.setPositionRelative(this.optionSelectBg, this.optionSelectBg.width / 2, 24); + this.alreadyAssignedText.setOrigin(0.5); + this.alreadyAssignedText.setPositionRelative(this.optionSelectBg, this.optionSelectBg.width / 2 - 2, this.optionSelectBg.height / 2 - 2); + this.alreadyAssignedText.setVisible(false); + + this.previousIconXbox = this.scene.add.sprite(0, 0, 'xbox'); + this.previousIconXbox.setScale(0.15); + this.previousIconXbox.setPositionRelative(this.optionSelectBg, 78, 48); + this.previousIconXbox.setOrigin(0.5); + this.previousIconXbox.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', TextStyle.SETTINGS_LABEL); + this.actionLabel.setOrigin(0, 0.5); + this.actionLabel.setPositionRelative(this.actionBg, this.actionBg.width - 45, this.actionBg.height / 2); this.optionSelectContainer.add(this.iconXbox); this.optionSelectContainer.add(this.iconDualshock); this.optionSelectContainer.add(this.alreadyAssignedText); + this.optionSelectContainer.add(this.previousIconXbox); + this.actionsContainer.add(this.actionLabel); + this.actionsContainer.add(this.cancelLabel); } gamepadButtonDown(pad: Phaser.Input.Gamepad.Gamepad, button: Phaser.Input.Gamepad.Button, value: number): void { - if (!this.listening || pad.id !== this.scene.inputController?.chosenGamepad) return; + const blacklist = [12, 13, 14, 15]; + if (!this.listening || pad.id !== this.scene.inputController?.chosenGamepad || blacklist.includes(button.index) || this.buttonPressed !== null) return; this.buttonPressed = button.index; const [type, buttonIcon] = this.scene.inputController.getButtonLabel(button); switch (type) { @@ -76,21 +110,30 @@ export default class GamepadBindingUiHandler extends UiHandler { this.iconXbox.setVisible(false); this.iconDualshock.setFrame(buttonIcon); this.iconDualshock.setVisible(true); + this.previousIconXbox.setVisible(true); + this.alreadyAssignedText.setVisible(true); break case 'xbox': default: this.iconDualshock.setVisible(false); this.iconXbox.setFrame(buttonIcon); this.iconXbox.setVisible(true); + this.previousIconXbox.setVisible(true); + this.alreadyAssignedText.setVisible(true); break } + this.setCursor(0); + this.actionsContainer.setVisible(true); } show(args: any[]): boolean { - console.log('args', args); super.show(args); + this.buttonPressed = null; + this.cancelFn = args[0].cancelHandler; + this.target = args[0].target; this.getUi().bringToTop(this.optionSelectContainer); + this.getUi().bringToTop(this.actionsContainer); this.optionSelectContainer.setVisible(true); setTimeout(() => this.listening = true, 150); @@ -106,12 +149,59 @@ export default class GamepadBindingUiHandler extends UiHandler { } processInput(button: Button): boolean { + if (this.buttonPressed === null) return; const ui = this.getUi(); - return true; + let success = false; + switch (button) { + case Button.LEFT: + case Button.RIGHT: + const cursor = this.cursor ? 0 : 1; + success = this.setCursor(cursor); + break + case Button.ACTION: + if (this.cursor === 0) { + success = true; + // Reverts UI to its previous state on cancel. + // this.scene.ui.revertMode(); + this.cancelFn(); + } + break; + } + + // Plays a select sound effect if an action was successfully processed. + if (success) + ui.playSelect(); + + return success; + } + + setCursor(cursor: number): boolean { + this.cursor = cursor; + 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; + } + this.actionLabel.setColor(this.getTextColor(TextStyle.WINDOW)); + 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; } clear() { super.clear(); + this.target = null; + this.cancelFn = null; + this.optionSelectContainer.setVisible(false); + this.actionsContainer.setVisible(false); + this.iconXbox.setVisible(false); + this.iconDualshock.setVisible(false); + this.previousIconXbox.setVisible(false); + this.alreadyAssignedText.setVisible(false); + this.iconXbox.setFrame(null); + this.iconDualshock.setFrame(null); } - } \ No newline at end of file