I have done some more experimentation on input in general and am definitely missing something!
When looking a game Objects stack on one another the input behaves like the following from my testing (I just used the pointerdown event for testing, I was using a couple tilemaps and a graphics object for testing)…
Events placed on the scene (scene.input.on) get called even if setTopOnly is true and GameObjects with input are on top. If the GameObject stopPropagation the scene event is not called. Scene event is last in the list to get input event, so GameObjects first then the Scene.
It seems like the order in which setInteractive is enabled on a GameObjects is the order in which events are delivered to the objects. The first object to setInteractive is on top to receive and event even if other GameObjects are displayed visually on top of them. SetDepth on a GameObject doesn’t change the input order.
I am sure I am doing something wrong here. It would see that input order would reflect the display order?
Appreciate any input. Test code below…
import * as Phaser from "phaser";
import images from '../assets/images/*.png'
import V2 = Phaser.Math.Vector2
export class PopUp extends Phaser.GameObjects.Container {
public zone:Phaser.GameObjects.Zone
constructor(public scene:Phaser.Scene, private point:V2, private items:string[], private callback:(context:any, selected:string)=>void, private context:any) {
super(scene, point.x, point.y)
this.zone = new Phaser.GameObjects.Zone(scene, scene.cameras.main.x, scene.cameras.main.y, scene.cameras.main.width, scene.cameras.main.height)
this.zone.setInteractive().setDepth(1)
this.zone.on('pointerup', ()=>{
console.log('pointerup - close')
})
let y = 0
for (let item of items) {
let menuItem = scene.add.text(0, y, item, {}).setInteractive().setScrollFactor(0)
this.add(menuItem)
menuItem.on('pointerdown', ()=>{
console.log('pointerdown - '+item)
})
y += 20
}
scene.add.existing(this)
}
}
export class Menu extends Phaser.Scene {
constructor() {
super({
key: 'examples'
})
}
preload() {
this.load.spritesheet('tilesheet', images.tiles, { frameWidth: 32, frameHeight: 32 })
}
create() {
let graphics = new Phaser.GameObjects.Graphics(this)
graphics.fillStyle(0xFFFF00, 1.0);
graphics.fillRect(50, 50, 400, 200);
this.add.existing(graphics)
let tilemap2 = {data: [[926,926,926,926,926,]]} // [ [], [], ... ]
let map2 = this.make.tilemap(tilemap2);
let tiles2 = map2.addTilesetImage('tiles', 'tilesheet');
let board2 = map2.createLayer('layer', 'tiles')!
board2.setName('2')
board2.setPosition(66,66)
let tilemap = {data: [[950,950,950,950,950,]]} // [ [], [], ... ]
let map = this.make.tilemap(tilemap);
let tiles = map.addTilesetImage('tiles', 'tilesheet');
let board = map.createLayer('layer', 'tiles')!
board.setPosition(50,50)
this.input.enableDebug(board)
board2.on('pointerdown', this.pointerDown1Board2, board2)
board.on('pointerdown', this.pointerDown1Board, board)
graphics.on('pointerdown', this.pointerDown1Graphics, graphics)
board2.setInteractive()
board.setInteractive()
graphics.setInteractive({ useHandCursor: true,
hitArea: new Phaser.Geom.Rectangle(50, 50, 400, 200),
hitAreaCallback: Phaser.Geom.Rectangle.Contains, //Required if Hit Area Provided
})
this.input.on('pointerdown', this.pointerDown1Scene, this)
this.input.setTopOnly(false)
}
public pointerDown1Scene(pointer:Phaser.Input.Pointer, x:number, y:number, e:Phaser.Types.Input.EventData) {
console.log('Scene - pointerDown',this)
}
public pointerDown1Graphics(pointer:Phaser.Input.Pointer, x:number, y:number, e:Phaser.Types.Input.EventData) {
console.log('Graphics - pointerDown',this)
}
public pointerDown1Board(pointer:Phaser.Input.Pointer, x:number, y:number, e:Phaser.Types.Input.EventData) {
console.log('Board - pointerDown',this)
}
public pointerDown1Board2(pointer:Phaser.Input.Pointer, x:number, y:number, e:Phaser.Types.Input.EventData) {
console.log('Board2 - pointerDown',this)
//e.stopPropagation()
}