From feba8ac641c212fb4ab5451be24ededbd1cab6a4 Mon Sep 17 00:00:00 2001 From: Greenlamp Date: Thu, 2 May 2024 19:47:07 +0200 Subject: [PATCH] first version of a too complex inputHandler based on phaser3-merged-input --- src/battle-scene.ts | 195 +----- src/inputHandler.ts | 744 +++++++++++++++++++++ src/main.ts | 5 + src/ui/abstact-option-select-ui-handler.ts | 3 +- src/ui/achvs-ui-handler.ts | 3 +- src/ui/awaitable-ui-handler.ts | 3 +- src/ui/ball-ui-handler.ts | 3 +- src/ui/battle-message-ui-handler.ts | 3 +- src/ui/command-ui-handler.ts | 3 +- src/ui/confirm-ui-handler.ts | 3 +- src/ui/egg-gacha-ui-handler.ts | 3 +- src/ui/egg-hatch-scene-handler.ts | 3 +- src/ui/egg-list-ui-handler.ts | 3 +- src/ui/evolution-scene-handler.ts | 3 +- src/ui/fight-ui-handler.ts | 3 +- src/ui/form-modal-ui-handler.ts | 3 +- src/ui/game-stats-ui-handler.ts | 3 +- src/ui/menu-ui-handler.ts | 3 +- src/ui/modal-ui-handler.ts | 3 +- src/ui/modifier-select-ui-handler.ts | 3 +- src/ui/party-ui-handler.ts | 3 +- src/ui/save-slot-select-ui-handler.ts | 3 +- src/ui/settings-ui-handler.ts | 3 +- src/ui/starter-select-ui-handler.ts | 3 +- src/ui/summary-ui-handler.ts | 3 +- src/ui/target-select-ui-handler.ts | 3 +- src/ui/ui-handler.ts | 3 +- src/ui/ui.ts | 3 +- src/ui/vouchers-ui-handler.ts | 3 +- 29 files changed, 815 insertions(+), 207 deletions(-) create mode 100644 src/inputHandler.ts diff --git a/src/battle-scene.ts b/src/battle-scene.ts index 26976604a36..e04d31ade31 100644 --- a/src/battle-scene.ts +++ b/src/battle-scene.ts @@ -1,4 +1,4 @@ -import Phaser, { Time } from 'phaser'; +import Phaser from 'phaser'; import UI, { Mode } from './ui/ui'; import { NextEncounterPhase, NewBiomeEncounterPhase, SelectBiomePhase, MessagePhase, TurnInitPhase, ReturnPhase, LevelCapPhase, ShowTrainerPhase, LoginPhase, MovePhase, TitlePhase, SwitchPhase } from './phases'; import Pokemon, { PlayerPokemon, EnemyPokemon } from './field/pokemon'; @@ -54,17 +54,13 @@ import CharSprite from './ui/char-sprite'; import DamageNumberHandler from './field/damage-number-handler'; import PokemonInfoContainer from './ui/pokemon-info-container'; import { biomeDepths } from './data/biomes'; -import { initTouchControls } from './touch-controls'; import { UiTheme } from './enums/ui-theme'; import { SceneBase } from './scene-base'; import CandyBar from './ui/candy-bar'; import { Variant, variantData } from './data/variant'; import { Localizable } from './plugins/i18n'; import { STARTING_WAVE_OVERRIDE, OPP_SPECIES_OVERRIDE, SEED_OVERRIDE, STARTING_BIOME_OVERRIDE } from './overrides'; -import pad_generic from "./configs/pad_generic"; -import pad_unlicensedSNES from "./configs/pad_unlicensedSNES"; -import pad_xbox360 from "./configs/pad_xbox360"; -import pad_dualshock from "./configs/pad_dualshock"; + export const bypassLogin = import.meta.env.VITE_BYPASS_LOGIN === "1"; @@ -79,26 +75,6 @@ interface StarterColors { [key: string]: [string, string] } -export enum Button { - UP, - DOWN, - LEFT, - RIGHT, - SUBMIT, - ACTION, - CANCEL, - MENU, - STATS, - CYCLE_SHINY, - CYCLE_FORM, - CYCLE_GENDER, - CYCLE_ABILITY, - CYCLE_NATURE, - CYCLE_VARIANT, - SPEED_UP, - SLOW_DOWN -} - export interface PokeballCounts { [pb: string]: integer; } @@ -107,6 +83,7 @@ export type AnySound = Phaser.Sound.WebAudioSound | Phaser.Sound.HTML5AudioSound export default class BattleScene extends SceneBase { public rexUI: UIPlugin; + public inputHandler: InputHandler; public sessionPlayTime: integer = null; public masterVolume: number = 0.5; @@ -193,13 +170,10 @@ export default class BattleScene extends SceneBase { private bgmCache: Set = new Set(); private playTimeTimer: Phaser.Time.TimerEvent; - private buttonKeys: Phaser.Input.Keyboard.Key[][]; - private isButtonPressing: boolean; private lastProcessedButtonPressTimes: Map = new Map(); // movementButtonLock ensures only a single movement key is firing repeated inputs // (i.e. by holding down a button) at a time private movementButtonLock: Button; - private mappedPad; public rngCounter: integer = 0; public rngSeedOverride: string = ''; @@ -243,7 +217,7 @@ export default class BattleScene extends SceneBase { return ret; }; } - + populateAnims(); await this.initVariantData(); @@ -253,13 +227,10 @@ export default class BattleScene extends SceneBase { initGameSpeed.apply(this); this.gameData = new GameData(this); + this.checkInputs(); addUiThemeOverrides(this); - this.setupControls(); - this.checkInputGamepad(); - this.checkInputKeyboard(); - this.load.setBaseURL(); this.spritePipeline = new SpritePipeline(this.game); @@ -275,6 +246,15 @@ export default class BattleScene extends SceneBase { this.ui?.update(); } + checkInputs() { + this.inputHandler.events.on('gamepad_directiondown', (event) => { + console.log('event:', event); + }); + this.inputHandler.events.on('gamepad_buttondown', (event) => { + console.log('event:', event); + }); + } + launchBattle() { this.arenaBg = this.add.sprite(0, 0, 'plains_bg'); this.arenaBgTransition = this.add.sprite(0, 0, 'plains_bg'); @@ -590,42 +570,6 @@ export default class BattleScene extends SceneBase { return true; } - setupControls() { - const keyCodes = Phaser.Input.Keyboard.KeyCodes; - const keyConfig = { - [Button.UP]: [keyCodes.UP, keyCodes.W], - [Button.DOWN]: [keyCodes.DOWN, keyCodes.S], - [Button.LEFT]: [keyCodes.LEFT, keyCodes.A], - [Button.RIGHT]: [keyCodes.RIGHT, keyCodes.D], - [Button.SUBMIT]: [keyCodes.ENTER], - [Button.ACTION]: [keyCodes.SPACE, keyCodes.ENTER, keyCodes.Z], - [Button.CANCEL]: [keyCodes.BACKSPACE, keyCodes.X], - [Button.MENU]: [keyCodes.ESC, keyCodes.M], - [Button.STATS]: [keyCodes.SHIFT, keyCodes.C], - [Button.CYCLE_SHINY]: [keyCodes.R], - [Button.CYCLE_FORM]: [keyCodes.F], - [Button.CYCLE_GENDER]: [keyCodes.G], - [Button.CYCLE_ABILITY]: [keyCodes.E], - [Button.CYCLE_NATURE]: [keyCodes.N], - [Button.CYCLE_VARIANT]: [keyCodes.V], - [Button.SPEED_UP]: [keyCodes.PLUS], - [Button.SLOW_DOWN]: [keyCodes.MINUS] - }; - const mobileKeyConfig = {}; - this.buttonKeys = []; - for (let b of Utils.getEnumValues(Button)) { - const keys: Phaser.Input.Keyboard.Key[] = []; - if (keyConfig.hasOwnProperty(b)) { - for (let k of keyConfig[b]) - keys.push(this.input.keyboard.addKey(k, false)); - mobileKeyConfig[Button[b]] = keys[0]; - } - this.buttonKeys[b] = keys; - } - - initTouchControls(mobileKeyConfig); - } - getParty(): PlayerPokemon[] { return this.party; } @@ -1327,23 +1271,6 @@ export default class BattleScene extends SceneBase { return biomes[Utils.randSeedInt(biomes.length)]; } - mapGamepad(id) { - id = id.toLowerCase(); - let padConfig = pad_generic; - - if (id.includes('081f') && id.includes('e401')) { - padConfig = pad_unlicensedSNES; - } - else if (id.includes('xbox') && id.includes('360')) { - padConfig = pad_xbox360; - } - else if (id.includes('054c')) { - padConfig = pad_dualshock; - } - - return padConfig; - } - button_up() { const inputSuccess = this.ui.processInput(Button.UP); const vibrationLength = 5; @@ -1526,100 +1453,6 @@ export default class BattleScene extends SceneBase { } } - checkInputKeyboard() { - this.buttonKeys.forEach((row, index) => { - for (const key of row) { - key.on('down', () => { - if (!this.isButtonPressing) { - this.isButtonPressing = true; - this.key_down(index); - } - }); - key.on('up', () => { - if (this.isButtonPressing) { - this.isButtonPressing = false; - this.key_up(index); - } - }); - } - }) - } - checkInputGamepad() { - this.input.gamepad.once('connected', function (pad) { - const gamepadID = pad.id.toLowerCase(); - this.scene.mappedPad = this.scene.mapGamepad(gamepadID); - }); - - this.input.gamepad.on('down', function (gamepad, button) { - if (!this.scene.mappedPad) return; - let inputSuccess; - let vibrationLength; - switch(button.index) { - case this.scene.mappedPad.gamepadMapping.LC_N: - [inputSuccess, vibrationLength] = this.scene.button_up(); - break; - case this.scene.mappedPad.gamepadMapping.LC_S: - [inputSuccess, vibrationLength] = this.scene.button_down(); - break; - case this.scene.mappedPad.gamepadMapping.LC_W: - [inputSuccess, vibrationLength] = this.scene.button_left(); - break - case this.scene.mappedPad.gamepadMapping.LC_E: - [inputSuccess, vibrationLength] = this.scene.button_right(); - break - case this.scene.mappedPad.gamepadMapping.TOUCH: - inputSuccess = this.scene.button_touch(); - break - case this.scene.mappedPad.gamepadMapping.RC_S: - inputSuccess = this.scene.button_action(); - break; - case this.scene.mappedPad.gamepadMapping.RC_E: - inputSuccess = this.scene.button_cancel(); - break - case this.scene.mappedPad.gamepadMapping.SELECT: - this.scene.button_stats(true); - break - case this.scene.mappedPad.gamepadMapping.START: - inputSuccess = this.scene.button_menu(); - break - case this.scene.mappedPad.gamepadMapping.RB: - inputSuccess = this.scene.button_cycle_option(Button.CYCLE_SHINY); - break - case this.scene.mappedPad.gamepadMapping.LB: - inputSuccess = this.scene.button_cycle_option(Button.CYCLE_FORM); - break - case this.scene.mappedPad.gamepadMapping.LT: - inputSuccess = this.scene.button_cycle_option(Button.CYCLE_GENDER); - break - case this.scene.mappedPad.gamepadMapping.RT: - inputSuccess = this.scene.button_cycle_option(Button.CYCLE_ABILITY); - break; - case this.scene.mappedPad.gamepadMapping.RC_W: - inputSuccess = this.scene.button_cycle_option(Button.CYCLE_NATURE); - break - case this.scene.mappedPad.gamepadMapping.RC_N: - inputSuccess = this.scene.button_cycle_option(Button.CYCLE_VARIANT); - break - case this.scene.mappedPad.gamepadMapping.LS: - this.scene.button_speed_up(); - break - case this.scene.mappedPad.gamepadMapping.RS: - this.scene.button_speed_down(); - break - } - if (inputSuccess && this.scene.enableVibration && typeof navigator.vibrate !== 'undefined') - navigator.vibrate(vibrationLength); - }); - - this.input.gamepad.on('up', function (gamepad, button) { - switch(button.index) { - case this.scene.mappedPad.gamepadMapping.SELECT: - this.scene.button_stats(false); - break - } - }); - } - setLastProcessedMovementTime(button: Button) { this.lastProcessedButtonPressTimes.set(button, this.time.now); diff --git a/src/inputHandler.ts b/src/inputHandler.ts new file mode 100644 index 00000000000..e1ac4518345 --- /dev/null +++ b/src/inputHandler.ts @@ -0,0 +1,744 @@ +import Phaser from "phaser"; +import * as Utils from "./utils"; +import {initTouchControls} from './touch-controls'; +import pad_generic from "#app/configs/pad_generic"; +import pad_unlicensedSNES from "#app/configs/pad_unlicensedSNES"; +import pad_xbox360 from "#app/configs/pad_xbox360"; +import pad_dualshock from "#app/configs/pad_dualshock"; + + +export enum Button { + UP, + DOWN, + LEFT, + RIGHT, + SUBMIT, + ACTION, + CANCEL, + MENU, + STATS, + CYCLE_SHINY, + CYCLE_FORM, + CYCLE_GENDER, + CYCLE_ABILITY, + CYCLE_NATURE, + CYCLE_VARIANT, + SPEED_UP, + SLOW_DOWN +} + +export class InputHandler extends Phaser.Plugins.ScenePlugin { + game: Phaser.Game; + + constructor(scene: Phaser.Scene, pluginManager: Phaser.Plugins.PluginManager, pluginKey: string) { + super(scene, pluginManager, pluginKey); + this.game = pluginManager.game; + this.scene = scene; + // Keys object to store Phaser key objects. We'll check these during update + this.keys = {}; + this.players = []; + this.gamepads = []; + + this.dpadMappings = { + 'UP': 12, + 'DOWN': 13, + 'LEFT': 14, + 'RIGHT': 15 + }; + } + + boot() { + this.eventEmitter = this.systems.events; + this.events = new Phaser.Events.EventEmitter(); + + this.game.events.on(Phaser.Core.Events.PRE_STEP, this.preupdate, this); + // Handle the game losing focus + this.game.events.on(Phaser.Core.Events.BLUR, () => { + this.loseFocus() + }); + if (typeof this.systems.input.gamepad !== 'undefined') { + this.systems.input.gamepad.on('connected', function (thisGamepad) { + this.refreshGamepads(); + this.setupGamepad(thisGamepad); + }, this); + } + + // Check to see if the gamepad has already been setup by the browser + this.systems.input.gamepad.refreshPads(); + if (this.systems.input.gamepad.total) { + this.refreshGamepads(); + for (const thisGamepad of this.gamepads) { + this.systems.input.gamepad.emit('connected', thisGamepad); + } + } + + this.systems.input.gamepad.on('down', this.gamepadButtonDown, this); + this.systems.input.gamepad.on('up', this.gamepadButtonUp, this); + + // Keyboard + // this.systems.input.keyboard.on('keydown', this.keyboardKeyDown, this); + // this.systems.input.keyboard.on('keyup', this.keyboardKeyUp, this); + console.log('==[input handler initialized'); + } + + setupGamepad(thisGamepad) { + console.log('gamepad on'); + this.eventEmitter.emit('inputHandler', { + device: 'gamepad', + id: thisGamepad.id, + action: 'Connected' + }); + this.events.emit('gamepad_connected', thisGamepad); + + if (typeof this.players[thisGamepad.index] === 'undefined') { + this.addPlayer(); + } + + let gamepadID = thisGamepad.id.toLowerCase(); + let mappedPad = this.mapGamepad(gamepadID); + this.players[thisGamepad.index].gamepadMapping = mappedPad.gamepadMapping; + this.players[thisGamepad.index].interaction_mapped.gamepadType = mappedPad.padType; + for (let thisButton in this.players[thisGamepad.index].gamepadMapping) { + this.players[thisGamepad.index].buttons_mapped[thisButton] = 0; + } + } + refreshGamepads() { + // Sometimes, gamepads are undefined. For some reason. + this.gamepads = this.systems.input.gamepad.gamepads.filter(function (el) { + return el != null; + }); + + for (const [index, thisGamepad] of this.gamepads.entries()) { + thisGamepad.index = index; // Overwrite the gamepad index, in case we had undefined gamepads earlier + + /** + * Some cheap gamepads use the first axis as a dpad, in which case we won't have the dpad buttons 12-15 + */ + thisGamepad.fakedpad = thisGamepad.buttons.length < 15; + } + } + + preupdate() { + // this.setupControls(); + // this.checkInputGamepad(); + // this.checkInputKeyboard(); + } + + /** + * Function to run when the game loses focus + * We want to fake releasing the buttons here, so that they're not stuck down without an off event when focus returns to the game + */ + loseFocus() { + // Loop through defined keys and reset them + for (let thisKey in this.keys) { + this.keys[thisKey].reset(); + } + } + + /** + * Add a new player object to the players array + * @param {number} index Player index - if a player object at this index already exists, it will be returned instead of creating a new player object + * @param {number} numberOfButtons The number of buttons to assign to the player object. Defaults to 16. Fewer than 16 is not recommended, as gamepad DPads typically map to buttons 12-15 + */ + addPlayer(index= 0, numberOfButtons=16) { + if (typeof this.players[index] !== 'undefined') { + return this.players[index]; + } else { + // Set up player object + let newPlayer = this.setupControls(numberOfButtons); + + // Add helper functions to the player object + this.addPlayerHelperFunctions(newPlayer); + + // Push new player to players array + this.players.push(newPlayer); + + this.players[this.players.length - 1].index = this.players.length - 1; + return this.players[this.players.length - 1]; + } + } + + /** + * Add helper functions to the player object + * @param {*} player + */ + addPlayerHelperFunctions(player) { + /** + * Pass a button name, or an array of button names to check if any were pressed in this update step. + * This will only fire once per button press. If you need to check for a button being held down, use isDown instead. + * Returns the name of the matched button(s), in case you need it. + */ + player.interaction.isPressed = (button) => { + button = (typeof button === 'string') ? Array(button) : button; + let matchedButtons = button.filter(x => player.interaction.pressed.includes(x)) + return matchedButtons.length ? matchedButtons : false; + } + + /** + * Pass a button name, or an array of button names to check if any are currently pressed in this update step. + * This differs from the isPressed function in that it will return true if the button is currently pressed, even if it was pressed in a previous update step. + * Returns the name of the matched button(s), in case you need it. + */ + player.interaction.isDown = (button) => { + button = (typeof button === 'string') ? Array(button) : button; + let matchedButtons = button.filter(x => player.buttons[x]) + let matchedDirections = button.filter(x => player.direction[x]) + let matchedAll = [...matchedButtons, ...matchedDirections]; + + return matchedAll.length ? matchedAll : false; + } + + /** + * Pass a button name, or an array of button names to check if any are currently pressed in this update step. + * Similar to Phaser's keyboard plugin, the checkDown function can accept a 'duration' parameter, and will only register a press once every X milliseconds. + * Returns the name of the matched button(s) + * + * @param {string|array} button Array of buttons to check + * @param {number} duration The duration which must have elapsed before this button is considered as being down. + * @param {boolean} includeFirst - When true, the initial press of the button will be included in the results. Defaults to false. + */ + player.interaction.checkDown = (button, duration, includeFirst) => { + if (includeFirst === undefined) { includeFirst = false; } + if (duration === undefined) { duration = 0; } + + let matchedButtons = []; + let downButtons = player.interaction.isDown(button) + console.log('downButtons:', downButtons); + if (downButtons.length) { + + for (let thisButton of downButtons) { + if (typeof player.timers[thisButton]._tick === 'undefined') { + player.timers[thisButton]._tick = 0; + if (includeFirst) { + matchedButtons.push(thisButton); + } + } + + let t = Phaser.Math.Snap.Floor(this.scene.sys.time.now - player.timers[thisButton].pressed, duration); + if (t > player.timers[thisButton]._tick) { + this.game.events.once(Phaser.Core.Events.POST_STEP, ()=>{ + player.timers[thisButton]._tick = t; + }); + matchedButtons.push(thisButton); + } + } + } + + return matchedButtons.length ? matchedButtons : false; + } + + /** + * Mapped version of the checkDown version - resolves mapped button names and calls the checkDown function + */ + player.interaction_mapped.checkDown = (button, duration, includeFirst) => { + if (includeFirst === undefined) { includeFirst = false; } + let unmappedButtons = []; + + // Resolve the unmapped button names to a new array + for (let thisButton of button) { + let unmappedButton = this.getUnmappedButton(player, thisButton); + + if (unmappedButton) { + unmappedButtons.push(unmappedButton) + } + } + + let downButtons = player.interaction.checkDown(unmappedButtons, duration, includeFirst); + return downButtons.length ? downButtons.map(x => this.getMappedButton(player, x)) : false; + } + + + /** + * The previous functions are specific to the interaction and interaction_mapped definition of buttons. + * In general you would pick a definition scheme and query that object (interaction or interaction_mapped), just for ease though, we'll add some functions that accept either type of convention + */ + + /** + * Pass a button name, or an array of button names to check if any were pressed in this update step. + * This will only fire once per button press. If you need to check for a button being held down, use isDown instead. + * Returns the name of the matched button(s), in case you need it. + */ + player.isPressed = (button) => { + let interaction = player.interaction.isPressed(button) || []; + let interaction_mapped = player.interaction_mapped.isPressed(button) || []; + let matchedButtons = [...interaction, ...interaction_mapped]; + return matchedButtons.length ? matchedButtons : false + } + + /** + * Pass a button name, or an array of button names to check if any are currently pressed in this update step. + * This differs from the isPressed function in that it will return true if the button is currently pressed, even if it was pressed in a previous update step. + * Returns the name of the button(s), in case you need it. + */ + player.isDown = (button) => { + let interaction = player.interaction.isDown(button) || []; + let interaction_mapped = player.interaction_mapped.isDown(button) || []; + let matchedButtons = [...interaction, ...interaction_mapped]; + return matchedButtons.length ? matchedButtons : false + } + + /** + * Pass a button name, or an array of button names to check if any were released in this update step. + * Returns the name of the matched button(s), in case you need it. + */ + player.isReleased = (button) => { + let interaction = player.interaction.isReleased(button) || []; + let interaction_mapped = player.interaction_mapped.isReleased(button) || []; + let matchedButtons = [...interaction, ...interaction_mapped]; + return matchedButtons.length ? matchedButtons : false + } + + + /** + * Pass a button name, or an array of button names to check if any are currently pressed in this update step. + * Similar to Phaser's keyboard plugin, the checkDown function can accept a 'duration' parameter, and will only register a press once every X milliseconds. + * Returns the name of the matched button(s) + * + * @param {string|array} button Array of buttons to check + * @param {number} - The duration which must have elapsed before this button is considered as being down. + */ + player.checkDown = (button, duration, includeFirst) => { + if (includeFirst === undefined) { includeFirst = false; } + let interaction = player.interaction.checkDown(button, duration, includeFirst) || []; + let interaction_mapped = player.interaction_mapped.checkDown(button, duration, includeFirst) || []; + let matchedButtons = [...interaction, ...interaction_mapped]; + return matchedButtons.length ? matchedButtons : false + } + + + player.setDevice = (device) => { + if (player.interaction.device != device) { + this.eventEmitter.emit('inputHandler', { device: device, player: player.index, action: 'Device Changed' }); + this.events.emit('device_changed', { player: player.index, device: device }); + } + player.interaction.device = device; + + return this; + } + + return this; + } + + + + /** + * Returns a struct to hold input control information + * Set up a struct for each player in the game + * Direction and Buttons contain the input from the devices + * The keys struct contains arrays of keyboard characters that will trigger the action + */ + setupControls(numberOfButtons = 16) { + let controls = this.getBaseControls(); + + // Add buttons + for (let i = 0; i <= numberOfButtons; i++) { + controls.buttons['B' + i] = 0; + controls.keys['B' + i] = []; + } + + // Add timers + for (let i = 0; i <= numberOfButtons; i++) { + controls.timers['B' + i] = { + 'pressed': 0, + 'released': 0, + 'duration': 0 + }; + } + for (let thisDirection of ['UP', 'DOWN', 'LEFT', 'RIGHT', 'ALT_UP', 'ALT_DOWN', 'ALT_LEFT', 'ALT_RIGHT']) { + controls.timers[thisDirection] = { + 'pressed': 0, + 'released': 0, + 'duration': 0 + }; + } + + + controls.setPosition = function(x,y) { + this.position.x = x; + this.position.y = y; + } + + return controls; + } + + getBaseControls() { + return { + 'direction': { + 'UP': 0, + 'DOWN': 0, + 'LEFT': 0, + 'RIGHT': 0, + }, + 'direction_secondary': { + 'UP': 0, + 'DOWN': 0, + 'LEFT': 0, + 'RIGHT': 0, + }, + 'buttons': { + + }, + 'keys': { + + }, + 'timers': { + + }, + 'position': {x:0,y:0}, + 'interaction': { + 'buffer': [], + 'pressed': [], + 'released': [], + 'last': '', + 'lastPressed': '', + 'lastReleased': '', + 'device': '', + }, + 'interaction_mapped': { + 'pressed': [], + 'released': [], + 'last': '', + 'lastPressed': '', + 'lastReleased': '', + 'gamepadType': '', + }, + 'buttons_mapped': { + + } + } + } + + + // Gamepad functions + + /** + * When a gamepad button is pressed down, this function will emit a inputHandler event in the global registry. + * The event contains a reference to the player assigned to the gamepad, and passes a mapped action and value + * @param {number} index Button index + * @param {number} value Button value + * @param {Phaser.Input.Gamepad.Button} button Phaser Button object + */ + gamepadButtonDown(pad, button, value) { + this.players[pad.index].setDevice('gamepad'); + this.players[pad.index].buttons.TIMESTAMP = this.scene.sys.time.now; + this.eventEmitter.emit('inputHandler', { + device: 'gamepad', + value: value, + player: pad.index, + action: 'B' + button.index, + state: 'DOWN' + }); + this.events.emit('gamepad_buttondown', { + player: pad.index, + button: `B${button.index}` + }); + + // Buttons + if (![12, 13, 14, 15].includes(button.index)) { + let playerAction = 'B' + button.index; + + // Update the last button state + this.players[pad.index].interaction.pressed.push(playerAction); + this.players[pad.index].interaction.last = playerAction; + this.players[pad.index].interaction.lastPressed = playerAction; + this.players[pad.index].interaction.buffer.push(playerAction); + + // Update timers + this.players[pad.index].timers[playerAction].pressed = this.scene.sys.time.now; + this.players[pad.index].timers[playerAction].released = 0; + this.players[pad.index].timers[playerAction].duration = 0; + + // Update mapped button object + let mappedButton = this.getMappedButton(this.players[pad.index], button.index); + if (typeof mappedButton !== "undefined") { + this.players[pad.index].interaction_mapped.pressed.push(mappedButton); + this.players[pad.index].interaction_mapped.last = mappedButton; + this.players[pad.index].interaction_mapped.lastPressed = mappedButton; + } + } + // DPad + else { + let dpadMapping = this.dpadMappings; + let direction = Object.keys(dpadMapping).find(key => dpadMapping[key] == button.index); + this.eventEmitter.emit('inputHandler', { + device: 'gamepad', + value: 1, + player: pad.index, + action: direction, + state: 'DOWN' + }); + this.events.emit('gamepad_directiondown', { player: pad.index, button: direction }); + + this.players[pad.index].interaction.pressed.push(direction); + this.players[pad.index].interaction.last = direction; + this.players[pad.index].interaction.lastPressed = direction; + this.players[pad.index].interaction.buffer.push(direction); + this.players[pad.index].direction.TIMESTAMP = this.scene.sys.time.now; + + // Update timers + this.players[pad.index].timers[direction].pressed = this.scene.sys.time.now; + this.players[pad.index].timers[direction].released = 0; + this.players[pad.index].timers[direction].duration = 0; + + + // Update mapped button object + let mappedButton = this.getMappedButton(this.players[pad.index], button.index); + if (typeof mappedButton !== "undefined") { + this.players[pad.index].interaction_mapped.pressed.push(mappedButton); + this.players[pad.index].interaction_mapped.last = mappedButton; + this.players[pad.index].interaction_mapped.lastPressed = mappedButton; + } + } + + } + + + /** + * Given a player and a button ID, return the mapped button name, e.g. 0 = 'RC_S' (Right cluster, South - X on an xbox gamepad) + * @param {*} player + * @param {*} buttonID + */ + getMappedButton(player, buttonID) { + buttonID = buttonID.toString().replace(/\D/g, ''); + return Object.keys(player.gamepadMapping).find(key => player.gamepadMapping[key] == buttonID); + } + + /** + * When a gamepad button is released, this function will emit a inputHandler event in the global registry. + * The event contains a reference to the player assigned to the gamepad, and passes a mapped action and value + * @param {number} index Button index + * @param {number} value Button value + * @param {Phaser.Input.Gamepad.Button} button Phaser Button object + */ + gamepadButtonUp(pad, button, value) { + this.players[pad.index].setDevice('gamepad'); + this.players[pad.index].buttons.TIMESTAMP = this.scene.sys.time.now; + + this.eventEmitter.emit('inputHandler', { + device: 'gamepad', + value: value, + player: pad.index, + action: 'B' + button.index, + state: 'UP' + }); + this.events.emit('gamepad_buttonup', { + player: pad.index, + button: `B${button.index}` + }); + + // Buttons + if (![12, 13, 14, 15].includes(button.index)) { + let playerAction = 'B' + button.index; + + // Update the last button state + this.players[pad.index].interaction.released.push(playerAction); + this.players[pad.index].interaction.lastReleased = playerAction; + + // Update timers + this.players[pad.index].timers[playerAction].released = this.scene.sys.time.now; + this.players[pad.index].timers[playerAction].duration = this.players[pad.index].timers[playerAction].released - this.players[pad.index].timers[playerAction].pressed; + delete this.players[pad.index].timers[playerAction]._tick; + + // Update mapped button object + let mappedButton = this.getMappedButton(this.players[pad.index], button.index); + if (typeof mappedButton !== "undefined") { + this.players[pad.index].interaction_mapped.released = mappedButton; + this.players[pad.index].interaction_mapped.lastReleased = mappedButton; + } + } + // DPad + else { + let dpadMapping = this.dpadMappings; + let direction = Object.keys(dpadMapping).find(key => dpadMapping[key] == button.index); + this.eventEmitter.emit('inputHandler', { + device: 'gamepad', + value: 1, + player: pad.index, + action: direction, + state: 'UP' + }); + this.events.emit('gamepad_directionup', { + player: pad.index, + button: direction + }); + + this.players[pad.index].interaction.released.push(direction); + this.players[pad.index].interaction.lastReleased = direction; + + // Update timers + this.players[pad.index].timers[direction].released = this.scene.sys.time.now; + this.players[pad.index].timers[direction].duration = this.players[pad.index].timers[direction].released - this.players[pad.index].timers[direction].pressed; + delete this.players[pad.index].timers[direction]._tick; + + // Update mapped button object + let mappedButton = this.getMappedButton(this.players[pad.index], button.index); + if (typeof mappedButton !== "undefined") { + this.players[pad.index].interaction_mapped.released = mappedButton; + this.players[pad.index].interaction_mapped.lastReleased = mappedButton; + } + } + } + + // setupControls() { + // const keyCodes = Phaser.Input.Keyboard.KeyCodes; + // const keyConfig = { + // [Button.UP]: [keyCodes.UP, keyCodes.W], + // [Button.DOWN]: [keyCodes.DOWN, keyCodes.S], + // [Button.LEFT]: [keyCodes.LEFT, keyCodes.A], + // [Button.RIGHT]: [keyCodes.RIGHT, keyCodes.D], + // [Button.SUBMIT]: [keyCodes.ENTER], + // [Button.ACTION]: [keyCodes.SPACE, keyCodes.ENTER, keyCodes.Z], + // [Button.CANCEL]: [keyCodes.BACKSPACE, keyCodes.X], + // [Button.MENU]: [keyCodes.ESC, keyCodes.M], + // [Button.STATS]: [keyCodes.SHIFT, keyCodes.C], + // [Button.CYCLE_SHINY]: [keyCodes.R], + // [Button.CYCLE_FORM]: [keyCodes.F], + // [Button.CYCLE_GENDER]: [keyCodes.G], + // [Button.CYCLE_ABILITY]: [keyCodes.E], + // [Button.CYCLE_NATURE]: [keyCodes.N], + // [Button.CYCLE_VARIANT]: [keyCodes.V], + // [Button.SPEED_UP]: [keyCodes.PLUS], + // [Button.SLOW_DOWN]: [keyCodes.MINUS] + // }; + // const mobileKeyConfig = {}; + // this.buttonKeys = []; + // for (let b of Utils.getEnumValues(Button)) { + // const keys: Phaser.Input.Keyboard.Key[] = []; + // if (keyConfig.hasOwnProperty(b)) { + // for (let k of keyConfig[b]) + // keys.push(this.input.keyboard.addKey(k, false)); + // mobileKeyConfig[Button[b]] = keys[0]; + // } + // this.buttonKeys[b] = keys; + // } + // + // initTouchControls(mobileKeyConfig); + // } + + checkInputKeyboard() { + // this.buttonKeys.forEach((row, index) => { + // for (const key of row) { + // key.on('down', () => { + // if (!this.isButtonPressing) { + // this.isButtonPressing = true; + // this.key_down(index); + // } + // }); + // key.on('up', () => { + // if (this.isButtonPressing) { + // this.isButtonPressing = false; + // this.key_up(index); + // } + // }); + // } + // }) + } + + mapGamepad(id) { + id = id.toLowerCase(); + let padConfig = pad_generic; + + if (id.includes('081f') && id.includes('e401')) { + padConfig = pad_unlicensedSNES; + } + else if (id.includes('xbox') && id.includes('360')) { + padConfig = pad_xbox360; + } + else if (id.includes('054c')) { + padConfig = pad_dualshock; + } + + console.log('padConfig:', padConfig); + + return padConfig; + } + + checkInputGamepad() { + // this.input.gamepad.once('connected', function (pad) { + // const gamepadID = pad.id.toLowerCase(); + // this.scene.mappedPad = this.scene.mapGamepad(gamepadID); + // }); + + // this.input.gamepad.on('down', function (gamepad, button) { + // if (!this.scene.mappedPad) return; + // let inputSuccess; + // let vibrationLength; + // switch(button.index) { + // case this.scene.mappedPad.gamepadMapping.LC_N: + // [inputSuccess, vibrationLength] = this.scene.button_up(); + // break; + // case this.scene.mappedPad.gamepadMapping.LC_S: + // [inputSuccess, vibrationLength] = this.scene.button_down(); + // break; + // case this.scene.mappedPad.gamepadMapping.LC_W: + // [inputSuccess, vibrationLength] = this.scene.button_left(); + // break + // case this.scene.mappedPad.gamepadMapping.LC_E: + // [inputSuccess, vibrationLength] = this.scene.button_right(); + // break + // case this.scene.mappedPad.gamepadMapping.TOUCH: + // inputSuccess = this.scene.button_touch(); + // break + // case this.scene.mappedPad.gamepadMapping.RC_S: + // inputSuccess = this.scene.button_action(); + // break; + // case this.scene.mappedPad.gamepadMapping.RC_E: + // inputSuccess = this.scene.button_cancel(); + // break + // case this.scene.mappedPad.gamepadMapping.SELECT: + // this.scene.button_stats(true); + // break + // case this.scene.mappedPad.gamepadMapping.START: + // inputSuccess = this.scene.button_menu(); + // break + // case this.scene.mappedPad.gamepadMapping.RB: + // inputSuccess = this.scene.button_cycle_option(Button.CYCLE_SHINY); + // break + // case this.scene.mappedPad.gamepadMapping.LB: + // inputSuccess = this.scene.button_cycle_option(Button.CYCLE_FORM); + // break + // case this.scene.mappedPad.gamepadMapping.LT: + // inputSuccess = this.scene.button_cycle_option(Button.CYCLE_GENDER); + // break + // case this.scene.mappedPad.gamepadMapping.RT: + // inputSuccess = this.scene.button_cycle_option(Button.CYCLE_ABILITY); + // break; + // case this.scene.mappedPad.gamepadMapping.RC_W: + // inputSuccess = this.scene.button_cycle_option(Button.CYCLE_NATURE); + // break + // case this.scene.mappedPad.gamepadMapping.RC_N: + // inputSuccess = this.scene.button_cycle_option(Button.CYCLE_VARIANT); + // break + // case this.scene.mappedPad.gamepadMapping.LS: + // this.scene.button_speed_up(); + // break + // case this.scene.mappedPad.gamepadMapping.RS: + // this.scene.button_speed_down(); + // break + // } + // if (inputSuccess && this.scene.enableVibration && typeof navigator.vibrate !== 'undefined') + // navigator.vibrate(vibrationLength); + // }); + // + // this.input.gamepad.on('up', function (gamepad, button) { + // switch(button.index) { + // case this.scene.mappedPad.gamepadMapping.SELECT: + // this.scene.button_stats(false); + // break + // } + // }); + } + + /** + * Get player object + * @param {number} index Player index + */ + getPlayer(index) { + return typeof this.players[index] !== 'undefined' ? this.players[index] : '' + } + + destroy() { + this.shutdown(); + this.scene = undefined; + } +} \ No newline at end of file diff --git a/src/main.ts b/src/main.ts index 6a00693fc71..78991f84be7 100644 --- a/src/main.ts +++ b/src/main.ts @@ -8,6 +8,7 @@ import InputTextPlugin from 'phaser3-rex-plugins/plugins/inputtext-plugin.js'; import BBCodeText from 'phaser3-rex-plugins/plugins/bbcodetext'; import TransitionImagePackPlugin from 'phaser3-rex-plugins/templates/transitionimagepack/transitionimagepack-plugin.js'; import { LoadingScene } from './loading-scene'; +import {InputHandler} from "./inputHandler"; const config: Phaser.Types.Core.GameConfig = { type: Phaser.WEBGL, @@ -35,6 +36,10 @@ const config: Phaser.Types.Core.GameConfig = { key: 'rexUI', plugin: UIPlugin, mapping: 'rexUI' + }, { + key: 'inputHandler', + plugin: InputHandler, + mapping: 'inputHandler' }] }, input: { diff --git a/src/ui/abstact-option-select-ui-handler.ts b/src/ui/abstact-option-select-ui-handler.ts index 2f2c4face89..adb979fb5eb 100644 --- a/src/ui/abstact-option-select-ui-handler.ts +++ b/src/ui/abstact-option-select-ui-handler.ts @@ -1,10 +1,11 @@ -import BattleScene, { Button } from "../battle-scene"; +import BattleScene from "../battle-scene"; import { TextStyle, addTextObject } from "./text"; import { Mode } from "./ui"; import UiHandler from "./ui-handler"; import { addWindow } from "./ui-theme"; import * as Utils from "../utils"; import { argbFromRgba } from "@material/material-color-utilities"; +import {Button} from "#app/inputHandler"; export interface OptionSelectConfig { xOffset?: number; diff --git a/src/ui/achvs-ui-handler.ts b/src/ui/achvs-ui-handler.ts index cadda64e032..28998229504 100644 --- a/src/ui/achvs-ui-handler.ts +++ b/src/ui/achvs-ui-handler.ts @@ -1,9 +1,10 @@ -import BattleScene, { Button } from "../battle-scene"; +import BattleScene from "../battle-scene"; import { Achv, achvs } from "../system/achv"; import MessageUiHandler from "./message-ui-handler"; import { TextStyle, addTextObject } from "./text"; import { Mode } from "./ui"; import { addWindow } from "./ui-theme"; +import {Button} from "#app/inputHandler"; export default class AchvsUiHandler extends MessageUiHandler { private achvsContainer: Phaser.GameObjects.Container; diff --git a/src/ui/awaitable-ui-handler.ts b/src/ui/awaitable-ui-handler.ts index e8cc979e423..522a3246dc2 100644 --- a/src/ui/awaitable-ui-handler.ts +++ b/src/ui/awaitable-ui-handler.ts @@ -1,6 +1,7 @@ -import BattleScene, { Button } from "../battle-scene"; +import BattleScene from "../battle-scene"; import { Mode } from "./ui"; import UiHandler from "./ui-handler"; +import {Button} from "#app/inputHandler"; export default abstract class AwaitableUiHandler extends UiHandler { protected awaitingActionInput: boolean; diff --git a/src/ui/ball-ui-handler.ts b/src/ui/ball-ui-handler.ts index f2ebdc342a4..293be7f54d2 100644 --- a/src/ui/ball-ui-handler.ts +++ b/src/ui/ball-ui-handler.ts @@ -1,11 +1,12 @@ import { CommandPhase } from "../phases"; -import BattleScene, { Button } from "../battle-scene"; +import BattleScene from "../battle-scene"; import { getPokeballName } from "../data/pokeball"; import { addTextObject, TextStyle } from "./text"; import { Command } from "./command-ui-handler"; import { Mode } from "./ui"; import UiHandler from "./ui-handler"; import { addWindow } from "./ui-theme"; +import {Button} from "#app/inputHandler"; export default class BallUiHandler extends UiHandler { private pokeballSelectContainer: Phaser.GameObjects.Container; diff --git a/src/ui/battle-message-ui-handler.ts b/src/ui/battle-message-ui-handler.ts index 5e2cb56518f..12618542a0f 100644 --- a/src/ui/battle-message-ui-handler.ts +++ b/src/ui/battle-message-ui-handler.ts @@ -1,4 +1,4 @@ -import BattleScene, { Button } from "../battle-scene"; +import BattleScene from "../battle-scene"; import { addBBCodeTextObject, addTextObject, getTextColor, TextStyle } from "./text"; import { Mode } from "./ui"; import * as Utils from "../utils"; @@ -6,6 +6,7 @@ import MessageUiHandler from "./message-ui-handler"; import { getStatName, Stat } from "../data/pokemon-stat"; import { addWindow } from "./ui-theme"; import BBCodeText from "phaser3-rex-plugins/plugins/bbcodetext"; +import {Button} from "#app/inputHandler"; export default class BattleMessageUiHandler extends MessageUiHandler { private levelUpStatsContainer: Phaser.GameObjects.Container; diff --git a/src/ui/command-ui-handler.ts b/src/ui/command-ui-handler.ts index b8223694b4c..9b69698df12 100644 --- a/src/ui/command-ui-handler.ts +++ b/src/ui/command-ui-handler.ts @@ -1,10 +1,11 @@ import { CommandPhase } from "../phases"; -import BattleScene, { Button } from "../battle-scene"; +import BattleScene from "../battle-scene"; import { addTextObject, TextStyle } from "./text"; import PartyUiHandler, { PartyUiMode } from "./party-ui-handler"; import { Mode } from "./ui"; import UiHandler from "./ui-handler"; import i18next from '../plugins/i18n'; +import {Button} from "#app/inputHandler"; export enum Command { FIGHT = 0, diff --git a/src/ui/confirm-ui-handler.ts b/src/ui/confirm-ui-handler.ts index d9e7726d826..ae75716e160 100644 --- a/src/ui/confirm-ui-handler.ts +++ b/src/ui/confirm-ui-handler.ts @@ -1,6 +1,7 @@ -import BattleScene, { Button } from "../battle-scene"; +import BattleScene from "../battle-scene"; import AbstractOptionSelectUiHandler, { OptionSelectConfig } from "./abstact-option-select-ui-handler"; import { Mode } from "./ui"; +import {Button} from "#app/inputHandler"; export default class ConfirmUiHandler extends AbstractOptionSelectUiHandler { private switchCheck: boolean; diff --git a/src/ui/egg-gacha-ui-handler.ts b/src/ui/egg-gacha-ui-handler.ts index f0e32dbc2e9..2260d5f3faa 100644 --- a/src/ui/egg-gacha-ui-handler.ts +++ b/src/ui/egg-gacha-ui-handler.ts @@ -1,4 +1,4 @@ -import BattleScene, { Button } from "../battle-scene"; +import BattleScene from "../battle-scene"; import { Mode } from "./ui"; import { TextStyle, addTextObject, getEggTierTextTint } from "./text"; import MessageUiHandler from "./message-ui-handler"; @@ -9,6 +9,7 @@ import { getPokemonSpecies } from "../data/pokemon-species"; import { addWindow } from "./ui-theme"; import { Tutorial, handleTutorial } from "../tutorial"; import { EggTier } from "../data/enums/egg-type"; +import {Button} from "#app/inputHandler"; const defaultText = 'Select a machine.'; diff --git a/src/ui/egg-hatch-scene-handler.ts b/src/ui/egg-hatch-scene-handler.ts index f841bafc268..2a426f46edd 100644 --- a/src/ui/egg-hatch-scene-handler.ts +++ b/src/ui/egg-hatch-scene-handler.ts @@ -1,7 +1,8 @@ -import BattleScene, { Button } from "../battle-scene"; +import BattleScene from "../battle-scene"; import { EggHatchPhase } from "../egg-hatch-phase"; import { Mode } from "./ui"; import UiHandler from "./ui-handler"; +import {Button} from "#app/inputHandler"; export default class EggHatchSceneHandler extends UiHandler { public eggHatchContainer: Phaser.GameObjects.Container; diff --git a/src/ui/egg-list-ui-handler.ts b/src/ui/egg-list-ui-handler.ts index 7537b8deeb0..bc948fb657d 100644 --- a/src/ui/egg-list-ui-handler.ts +++ b/src/ui/egg-list-ui-handler.ts @@ -1,4 +1,4 @@ -import BattleScene, { Button } from "../battle-scene"; +import BattleScene from "../battle-scene"; import { Mode } from "./ui"; import PokemonIconAnimHandler, { PokemonIconAnimMode } from "./pokemon-icon-anim-handler"; import { TextStyle, addTextObject } from "./text"; @@ -6,6 +6,7 @@ import MessageUiHandler from "./message-ui-handler"; import { EGG_SEED, Egg, GachaType, getEggGachaTypeDescriptor, getEggHatchWavesMessage, getEggDescriptor } from "../data/egg"; import * as Utils from "../utils"; import { addWindow } from "./ui-theme"; +import {Button} from "#app/inputHandler"; export default class EggListUiHandler extends MessageUiHandler { private eggListContainer: Phaser.GameObjects.Container; diff --git a/src/ui/evolution-scene-handler.ts b/src/ui/evolution-scene-handler.ts index 7e0ef063ea0..6abd2e5be34 100644 --- a/src/ui/evolution-scene-handler.ts +++ b/src/ui/evolution-scene-handler.ts @@ -1,7 +1,8 @@ -import BattleScene, { Button } from "../battle-scene"; +import BattleScene from "../battle-scene"; import MessageUiHandler from "./message-ui-handler"; import { TextStyle, addTextObject } from "./text"; import { Mode } from "./ui"; +import {Button} from "#app/inputHandler"; export default class EvolutionSceneHandler extends MessageUiHandler { public evolutionContainer: Phaser.GameObjects.Container; diff --git a/src/ui/fight-ui-handler.ts b/src/ui/fight-ui-handler.ts index 1a7a8bef597..e85c984f8e2 100644 --- a/src/ui/fight-ui-handler.ts +++ b/src/ui/fight-ui-handler.ts @@ -1,4 +1,4 @@ -import BattleScene, { Button } from "../battle-scene"; +import BattleScene from "../battle-scene"; import { addTextObject, TextStyle } from "./text"; import { Type } from "../data/type"; import { Command } from "./command-ui-handler"; @@ -8,6 +8,7 @@ import * as Utils from "../utils"; import { CommandPhase } from "../phases"; import { MoveCategory } from "#app/data/move.js"; import i18next from '../plugins/i18n'; +import {Button} from "#app/inputHandler"; export default class FightUiHandler extends UiHandler { private movesContainer: Phaser.GameObjects.Container; diff --git a/src/ui/form-modal-ui-handler.ts b/src/ui/form-modal-ui-handler.ts index ec5f4147c58..5244db6fb4d 100644 --- a/src/ui/form-modal-ui-handler.ts +++ b/src/ui/form-modal-ui-handler.ts @@ -1,4 +1,4 @@ -import BattleScene, { Button } from "../battle-scene"; +import BattleScene from "../battle-scene"; import { ModalConfig, ModalUiHandler } from "./modal-ui-handler"; import { Mode } from "./ui"; import { TextStyle, addTextInputObject, addTextObject } from "./text"; @@ -6,6 +6,7 @@ import { WindowVariant, addWindow } from "./ui-theme"; import InputText from "phaser3-rex-plugins/plugins/inputtext"; import * as Utils from "../utils"; import i18next from '../plugins/i18n'; +import {Button} from "#app/inputHandler"; export interface FormModalConfig extends ModalConfig { errorMessage?: string; diff --git a/src/ui/game-stats-ui-handler.ts b/src/ui/game-stats-ui-handler.ts index 00e358ff8e4..6658442dadb 100644 --- a/src/ui/game-stats-ui-handler.ts +++ b/src/ui/game-stats-ui-handler.ts @@ -1,4 +1,4 @@ -import BattleScene, { Button } from "../battle-scene"; +import BattleScene from "../battle-scene"; import { TextStyle, addTextObject, getTextColor } from "./text"; import { Mode } from "./ui"; import UiHandler from "./ui-handler"; @@ -6,6 +6,7 @@ import { addWindow } from "./ui-theme"; import * as Utils from "../utils"; import { DexAttr, GameData } from "../system/game-data"; import { speciesStarters } from "../data/pokemon-species"; +import {Button} from "#app/inputHandler"; interface DisplayStat { label?: string; diff --git a/src/ui/menu-ui-handler.ts b/src/ui/menu-ui-handler.ts index 03d93699e75..c44f489a2df 100644 --- a/src/ui/menu-ui-handler.ts +++ b/src/ui/menu-ui-handler.ts @@ -1,4 +1,4 @@ -import BattleScene, { Button, bypassLogin } from "../battle-scene"; +import BattleScene, { bypassLogin } from "../battle-scene"; import { TextStyle, addTextObject } from "./text"; import { Mode } from "./ui"; import * as Utils from "../utils"; @@ -9,6 +9,7 @@ import { OptionSelectConfig, OptionSelectItem } from "./abstact-option-select-ui import { Tutorial, handleTutorial } from "../tutorial"; import { updateUserInfo } from "../account"; import i18next from '../plugins/i18n'; +import {Button} from "#app/inputHandler"; export enum MenuOptions { GAME_SETTINGS, diff --git a/src/ui/modal-ui-handler.ts b/src/ui/modal-ui-handler.ts index f193a3db54f..807a0120348 100644 --- a/src/ui/modal-ui-handler.ts +++ b/src/ui/modal-ui-handler.ts @@ -1,8 +1,9 @@ -import BattleScene, { Button } from "../battle-scene"; +import BattleScene from "../battle-scene"; import { TextStyle, addTextObject } from "./text"; import { Mode } from "./ui"; import UiHandler from "./ui-handler"; import { WindowVariant, addWindow } from "./ui-theme"; +import {Button} from "#app/inputHandler"; export interface ModalConfig { buttonActions: Function[]; diff --git a/src/ui/modifier-select-ui-handler.ts b/src/ui/modifier-select-ui-handler.ts index e5252e02a8f..2fc27368fc0 100644 --- a/src/ui/modifier-select-ui-handler.ts +++ b/src/ui/modifier-select-ui-handler.ts @@ -1,4 +1,4 @@ -import BattleScene, { Button } from "../battle-scene"; +import BattleScene from "../battle-scene"; import { getPlayerShopModifierTypeOptionsForWave, ModifierTypeOption } from "../modifier/modifier-type"; import { getPokeballAtlasKey, PokeballType } from "../data/pokeball"; import { addTextObject, getModifierTierTextTint, getTextColor, TextStyle } from "./text"; @@ -6,6 +6,7 @@ import AwaitableUiHandler from "./awaitable-ui-handler"; import { Mode } from "./ui"; import { LockModifierTiersModifier, PokemonHeldItemModifier } from "../modifier/modifier"; import { handleTutorial, Tutorial } from "../tutorial"; +import {Button} from "#app/inputHandler"; export const SHOP_OPTIONS_ROW_LIMIT = 6; diff --git a/src/ui/party-ui-handler.ts b/src/ui/party-ui-handler.ts index 35014fa7027..722ec2488cb 100644 --- a/src/ui/party-ui-handler.ts +++ b/src/ui/party-ui-handler.ts @@ -1,5 +1,5 @@ import { CommandPhase } from "../phases"; -import BattleScene, { Button } from "../battle-scene"; +import BattleScene from "../battle-scene"; import { PlayerPokemon, PokemonMove } from "../field/pokemon"; import { addTextObject, TextStyle } from "./text"; import { Command } from "./command-ui-handler"; @@ -16,6 +16,7 @@ import { pokemonEvolutions } from "../data/pokemon-evolutions"; import { addWindow } from "./ui-theme"; import { SpeciesFormChangeItemTrigger } from "../data/pokemon-forms"; import { getVariantTint } from "#app/data/variant"; +import {Button} from "#app/inputHandler"; const defaultMessage = 'Choose a Pokémon.'; diff --git a/src/ui/save-slot-select-ui-handler.ts b/src/ui/save-slot-select-ui-handler.ts index 181b0643cb9..1d023a02a93 100644 --- a/src/ui/save-slot-select-ui-handler.ts +++ b/src/ui/save-slot-select-ui-handler.ts @@ -1,4 +1,4 @@ -import BattleScene, { Button } from "../battle-scene"; +import BattleScene from "../battle-scene"; import { gameModes } from "../game-mode"; import { SessionSaveData } from "../system/game-data"; import { TextStyle, addTextObject } from "./text"; @@ -8,6 +8,7 @@ import * as Utils from "../utils"; import PokemonData from "../system/pokemon-data"; import { PokemonHeldItemModifier } from "../modifier/modifier"; import MessageUiHandler from "./message-ui-handler"; +import {Button} from "#app/inputHandler"; const sessionSlotCount = 5; diff --git a/src/ui/settings-ui-handler.ts b/src/ui/settings-ui-handler.ts index 8f43b377d21..9d772edeff7 100644 --- a/src/ui/settings-ui-handler.ts +++ b/src/ui/settings-ui-handler.ts @@ -1,10 +1,11 @@ -import BattleScene, { Button } from "../battle-scene"; +import BattleScene from "../battle-scene"; 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 "#app/inputHandler"; export default class SettingsUiHandler extends UiHandler { private settingsContainer: Phaser.GameObjects.Container; diff --git a/src/ui/starter-select-ui-handler.ts b/src/ui/starter-select-ui-handler.ts index f1e058b12cf..bb60d4eb98c 100644 --- a/src/ui/starter-select-ui-handler.ts +++ b/src/ui/starter-select-ui-handler.ts @@ -1,4 +1,4 @@ -import BattleScene, { Button, starterColors } from "../battle-scene"; +import BattleScene, { starterColors } from "../battle-scene"; import PokemonSpecies, { allSpecies, getPokemonSpecies, getPokemonSpeciesForm, speciesStarters, starterPassiveAbilities } from "../data/pokemon-species"; import { Species } from "../data/enums/species"; import { TextStyle, addBBCodeTextObject, addTextObject } from "./text"; @@ -27,6 +27,7 @@ import { argbFromRgba } from "@material/material-color-utilities"; import { OptionSelectItem } from "./abstact-option-select-ui-handler"; import { pokemonPrevolutions } from "#app/data/pokemon-evolutions"; import { Variant, getVariantTint } from "#app/data/variant"; +import {Button} from "#app/inputHandler"; export type StarterSelectCallback = (starters: Starter[]) => void; diff --git a/src/ui/summary-ui-handler.ts b/src/ui/summary-ui-handler.ts index cf5eb3639fd..6a5429debd6 100644 --- a/src/ui/summary-ui-handler.ts +++ b/src/ui/summary-ui-handler.ts @@ -1,4 +1,4 @@ -import BattleScene, { Button } from "../battle-scene"; +import BattleScene from "../battle-scene"; import { Mode } from "./ui"; import UiHandler from "./ui-handler"; import * as Utils from "../utils"; @@ -17,6 +17,7 @@ import { Nature, getNatureStatMultiplier } from "../data/nature"; import { loggedInUser } from "../account"; import { PlayerGender } from "../system/game-data"; import { Variant, getVariantTint } from "#app/data/variant"; +import {Button} from "#app/inputHandler"; enum Page { PROFILE, diff --git a/src/ui/target-select-ui-handler.ts b/src/ui/target-select-ui-handler.ts index f8a7c9d28a3..0fb586bd818 100644 --- a/src/ui/target-select-ui-handler.ts +++ b/src/ui/target-select-ui-handler.ts @@ -1,10 +1,11 @@ import { BattlerIndex } from "../battle"; -import BattleScene, { Button } from "../battle-scene"; +import BattleScene from "../battle-scene"; import { Moves } from "../data/enums/moves"; import { Mode } from "./ui"; import UiHandler from "./ui-handler"; import * as Utils from "../utils"; import { getMoveTargets } from "../data/move"; +import {Button} from "#app/inputHandler"; export type TargetSelectCallback = (cursor: integer) => void; diff --git a/src/ui/ui-handler.ts b/src/ui/ui-handler.ts index e3c94b76467..516b98ac9de 100644 --- a/src/ui/ui-handler.ts +++ b/src/ui/ui-handler.ts @@ -1,6 +1,7 @@ -import BattleScene, { Button } from "../battle-scene"; +import BattleScene from "../battle-scene"; import { TextStyle, getTextColor } from "./text"; import UI, { Mode } from "./ui"; +import {Button} from "#app/inputHandler"; export default abstract class UiHandler { protected scene: BattleScene; diff --git a/src/ui/ui.ts b/src/ui/ui.ts index 6e20b2cb8b8..496e6a2ad15 100644 --- a/src/ui/ui.ts +++ b/src/ui/ui.ts @@ -1,4 +1,4 @@ -import { Button, default as BattleScene } from '../battle-scene'; +import { default as BattleScene } from '../battle-scene'; import UiHandler from './ui-handler'; import BattleMessageUiHandler from './battle-message-ui-handler'; import CommandUiHandler from './command-ui-handler'; @@ -35,6 +35,7 @@ import SavingIconHandler from './saving-icon-handler'; import UnavailableModalUiHandler from './unavailable-modal-ui-handler'; import OutdatedModalUiHandler from './outdated-modal-ui-handler'; import SessionReloadModalUiHandler from './session-reload-modal-ui-handler'; +import {Button} from "#app/inputHandler"; export enum Mode { MESSAGE, diff --git a/src/ui/vouchers-ui-handler.ts b/src/ui/vouchers-ui-handler.ts index 3f41cf9ae74..f3b4b8c315b 100644 --- a/src/ui/vouchers-ui-handler.ts +++ b/src/ui/vouchers-ui-handler.ts @@ -1,9 +1,10 @@ -import BattleScene, { Button } from "../battle-scene"; +import BattleScene from "../battle-scene"; import { Voucher, getVoucherTypeIcon, getVoucherTypeName, vouchers } from "../system/voucher"; import MessageUiHandler from "./message-ui-handler"; import { TextStyle, addTextObject } from "./text"; import { Mode } from "./ui"; import { addWindow } from "./ui-theme"; +import {Button} from "#app/inputHandler"; const itemRows = 4; const itemCols = 17;