diff --git a/src/core/graphics/canvas/CanvasGraphicsRenderer.js b/src/core/graphics/canvas/CanvasGraphicsRenderer.js index 2d53be3..fe62c2b 100644 --- a/src/core/graphics/canvas/CanvasGraphicsRenderer.js +++ b/src/core/graphics/canvas/CanvasGraphicsRenderer.js @@ -10,7 +10,7 @@ * now share 4 bytes on the vertex buffer * * Heavily inspired by LibGDX's CanvasGraphicsRenderer: - * https://github.com/libgdx/libgdx/blob/master/gdx/src/com/badlogic/gdx/graphics/g2d/CanvasGraphicsRenderer.java + * https://github.com/libgdx/libgdx/blob/1.0.0/gdx/src/com/badlogic/gdx/graphics/glutils/ShapeRenderer.java */ /** diff --git a/src/core/graphics/canvas/CanvasGraphicsRenderer.js b/src/core/graphics/canvas/CanvasGraphicsRenderer.js index 2d53be3..fe62c2b 100644 --- a/src/core/graphics/canvas/CanvasGraphicsRenderer.js +++ b/src/core/graphics/canvas/CanvasGraphicsRenderer.js @@ -10,7 +10,7 @@ * now share 4 bytes on the vertex buffer * * Heavily inspired by LibGDX's CanvasGraphicsRenderer: - * https://github.com/libgdx/libgdx/blob/master/gdx/src/com/badlogic/gdx/graphics/g2d/CanvasGraphicsRenderer.java + * https://github.com/libgdx/libgdx/blob/1.0.0/gdx/src/com/badlogic/gdx/graphics/glutils/ShapeRenderer.java */ /** diff --git a/src/core/math/shapes/Rectangle.js b/src/core/math/shapes/Rectangle.js index 3e4f18f..29b312a 100644 --- a/src/core/math/shapes/Rectangle.js +++ b/src/core/math/shapes/Rectangle.js @@ -222,19 +222,14 @@ /** * Enlarges this rectangle to include the passed rectangle. * - * @param {PIXI.Rectangle} rect - The rectangle to include. + * @param {PIXI.Rectangle} rectangle - The rectangle to include. */ - enlarge(rect) + enlarge(rectangle) { - if (rect === Rectangle.EMPTY) - { - return; - } - - const x1 = Math.min(this.x, rect.x); - const x2 = Math.max(this.x + this.width, rect.x + rect.width); - const y1 = Math.min(this.y, rect.y); - const y2 = Math.max(this.y + this.height, rect.y + rect.height); + const x1 = Math.min(this.x, rectangle.x); + const x2 = Math.max(this.x + this.width, rectangle.x + rectangle.width); + const y1 = Math.min(this.y, rectangle.y); + const y2 = Math.max(this.y + this.height, rectangle.y + rectangle.height); this.x = x1; this.width = x2 - x1; diff --git a/src/core/graphics/canvas/CanvasGraphicsRenderer.js b/src/core/graphics/canvas/CanvasGraphicsRenderer.js index 2d53be3..fe62c2b 100644 --- a/src/core/graphics/canvas/CanvasGraphicsRenderer.js +++ b/src/core/graphics/canvas/CanvasGraphicsRenderer.js @@ -10,7 +10,7 @@ * now share 4 bytes on the vertex buffer * * Heavily inspired by LibGDX's CanvasGraphicsRenderer: - * https://github.com/libgdx/libgdx/blob/master/gdx/src/com/badlogic/gdx/graphics/g2d/CanvasGraphicsRenderer.java + * https://github.com/libgdx/libgdx/blob/1.0.0/gdx/src/com/badlogic/gdx/graphics/glutils/ShapeRenderer.java */ /** diff --git a/src/core/math/shapes/Rectangle.js b/src/core/math/shapes/Rectangle.js index 3e4f18f..29b312a 100644 --- a/src/core/math/shapes/Rectangle.js +++ b/src/core/math/shapes/Rectangle.js @@ -222,19 +222,14 @@ /** * Enlarges this rectangle to include the passed rectangle. * - * @param {PIXI.Rectangle} rect - The rectangle to include. + * @param {PIXI.Rectangle} rectangle - The rectangle to include. */ - enlarge(rect) + enlarge(rectangle) { - if (rect === Rectangle.EMPTY) - { - return; - } - - const x1 = Math.min(this.x, rect.x); - const x2 = Math.max(this.x + this.width, rect.x + rect.width); - const y1 = Math.min(this.y, rect.y); - const y2 = Math.max(this.y + this.height, rect.y + rect.height); + const x1 = Math.min(this.x, rectangle.x); + const x2 = Math.max(this.x + this.width, rectangle.x + rectangle.width); + const y1 = Math.min(this.y, rectangle.y); + const y2 = Math.max(this.y + this.height, rectangle.y + rectangle.height); this.x = x1; this.width = x2 - x1; diff --git a/src/extras/AnimatedSprite.js b/src/extras/AnimatedSprite.js index 660fed7..13b804f 100644 --- a/src/extras/AnimatedSprite.js +++ b/src/extras/AnimatedSprite.js @@ -32,8 +32,9 @@ /** * @param {PIXI.Texture[]|FrameObject[]} textures - an array of {@link PIXI.Texture} or frame * objects that make up the animation + * @param {boolean} [autoUpdate=true] - Whether use PIXI.ticker.shared to auto update animation time. */ - constructor(textures) + constructor(textures, autoUpdate) { super(textures[0] instanceof core.Texture ? textures[0] : textures[0].texture); @@ -50,6 +51,14 @@ this.textures = textures; /** + * `true` uses PIXI.ticker.shared to auto update animation time. + * @type {boolean} + * @default true + * @private + */ + this._autoUpdate = autoUpdate !== false; + + /** * The speed that the AnimatedSprite will play at. Higher is faster, lower is slower * * @member {number} @@ -108,7 +117,10 @@ } this.playing = false; - core.ticker.shared.remove(this.update, this); + if (this._autoUpdate) + { + core.ticker.shared.remove(this.update, this); + } } /** @@ -123,7 +135,10 @@ } this.playing = true; - core.ticker.shared.add(this.update, this); + if (this._autoUpdate) + { + core.ticker.shared.add(this.update, this); + } } /** diff --git a/src/core/graphics/canvas/CanvasGraphicsRenderer.js b/src/core/graphics/canvas/CanvasGraphicsRenderer.js index 2d53be3..fe62c2b 100644 --- a/src/core/graphics/canvas/CanvasGraphicsRenderer.js +++ b/src/core/graphics/canvas/CanvasGraphicsRenderer.js @@ -10,7 +10,7 @@ * now share 4 bytes on the vertex buffer * * Heavily inspired by LibGDX's CanvasGraphicsRenderer: - * https://github.com/libgdx/libgdx/blob/master/gdx/src/com/badlogic/gdx/graphics/g2d/CanvasGraphicsRenderer.java + * https://github.com/libgdx/libgdx/blob/1.0.0/gdx/src/com/badlogic/gdx/graphics/glutils/ShapeRenderer.java */ /** diff --git a/src/core/math/shapes/Rectangle.js b/src/core/math/shapes/Rectangle.js index 3e4f18f..29b312a 100644 --- a/src/core/math/shapes/Rectangle.js +++ b/src/core/math/shapes/Rectangle.js @@ -222,19 +222,14 @@ /** * Enlarges this rectangle to include the passed rectangle. * - * @param {PIXI.Rectangle} rect - The rectangle to include. + * @param {PIXI.Rectangle} rectangle - The rectangle to include. */ - enlarge(rect) + enlarge(rectangle) { - if (rect === Rectangle.EMPTY) - { - return; - } - - const x1 = Math.min(this.x, rect.x); - const x2 = Math.max(this.x + this.width, rect.x + rect.width); - const y1 = Math.min(this.y, rect.y); - const y2 = Math.max(this.y + this.height, rect.y + rect.height); + const x1 = Math.min(this.x, rectangle.x); + const x2 = Math.max(this.x + this.width, rectangle.x + rectangle.width); + const y1 = Math.min(this.y, rectangle.y); + const y2 = Math.max(this.y + this.height, rectangle.y + rectangle.height); this.x = x1; this.width = x2 - x1; diff --git a/src/extras/AnimatedSprite.js b/src/extras/AnimatedSprite.js index 660fed7..13b804f 100644 --- a/src/extras/AnimatedSprite.js +++ b/src/extras/AnimatedSprite.js @@ -32,8 +32,9 @@ /** * @param {PIXI.Texture[]|FrameObject[]} textures - an array of {@link PIXI.Texture} or frame * objects that make up the animation + * @param {boolean} [autoUpdate=true] - Whether use PIXI.ticker.shared to auto update animation time. */ - constructor(textures) + constructor(textures, autoUpdate) { super(textures[0] instanceof core.Texture ? textures[0] : textures[0].texture); @@ -50,6 +51,14 @@ this.textures = textures; /** + * `true` uses PIXI.ticker.shared to auto update animation time. + * @type {boolean} + * @default true + * @private + */ + this._autoUpdate = autoUpdate !== false; + + /** * The speed that the AnimatedSprite will play at. Higher is faster, lower is slower * * @member {number} @@ -108,7 +117,10 @@ } this.playing = false; - core.ticker.shared.remove(this.update, this); + if (this._autoUpdate) + { + core.ticker.shared.remove(this.update, this); + } } /** @@ -123,7 +135,10 @@ } this.playing = true; - core.ticker.shared.add(this.update, this); + if (this._autoUpdate) + { + core.ticker.shared.add(this.update, this); + } } /** diff --git a/test/core/Rectangle.js b/test/core/Rectangle.js index 71f4355..40ca3b0 100644 --- a/test/core/Rectangle.js +++ b/test/core/Rectangle.js @@ -67,25 +67,6 @@ expect(rect2.contains(21, 21)).to.be.false; }); - it('should make rectangle grow', function () - { - const rect = new PIXI.Rectangle(10, 10, 10, 10); - - rect.pad(1, 1); - - expect(rect.left).to.equal(9); - expect(rect.top).to.equal(9); - expect(rect.right).to.equal(21); - expect(rect.bottom).to.equal(21); - - rect.pad(10, 10); - - expect(rect.left).to.equal(-1); - expect(rect.top).to.equal(-1); - expect(rect.right).to.equal(31); - expect(rect.bottom).to.equal(31); - }); - it('should enlarge rectangle', function () { const rect1 = new PIXI.Rectangle(10, 10, 10, 10); @@ -97,5 +78,91 @@ expect(rect1.top).to.equal(10); expect(rect1.right).to.equal(25); expect(rect1.bottom).to.equal(25); + + const rect3 = new PIXI.Rectangle(0, 0, 0, 0); + const rect4 = new PIXI.Rectangle(10, 10, 10, 10); + + rect4.enlarge(rect3); + + expect(rect4.left).to.equal(0); + expect(rect4.top).to.equal(0); + expect(rect4.right).to.equal(20); + expect(rect4.bottom).to.equal(20); + }); + + it('should pad a rectangle', function () + { + // Pad with X & Y + const rect = new PIXI.Rectangle(10, 10, 10, 10); + + rect.pad(10, 10); + + expect(rect.left).to.equal(0); + expect(rect.top).to.equal(0); + expect(rect.right).to.equal(30); + expect(rect.bottom).to.equal(30); + + // Pad with X + const rect1 = new PIXI.Rectangle(10, 10, 10, 10); + + rect1.pad(10); + + expect(rect1.left).to.equal(0); + expect(rect1.top).to.equal(0); + expect(rect1.right).to.equal(30); + expect(rect1.bottom).to.equal(30); + + // Pad with nothing + const rect2 = new PIXI.Rectangle(10, 10, 10, 10); + + rect2.pad(); + + expect(rect2.left).to.equal(10); + expect(rect2.top).to.equal(10); + expect(rect2.right).to.equal(20); + expect(rect2.bottom).to.equal(20); + + // Pad with Y + const rect3 = new PIXI.Rectangle(10, 10, 10, 10); + + rect3.pad(null, 10); + + expect(rect3.left).to.equal(10); + expect(rect3.top).to.equal(0); + expect(rect3.right).to.equal(20); + expect(rect3.bottom).to.equal(30); + }); + + it('should fit a rectangle', function () + { + const rect1 = new PIXI.Rectangle(0, 0, -10, -10); + const rect2 = new PIXI.Rectangle(-10, -10, 5, 5); + + rect2.fit(rect1); + + expect(rect2.left).to.equal(0); + expect(rect2.top).to.equal(0); + expect(rect2.right).to.equal(0); + expect(rect2.bottom).to.equal(0); + + const rect3 = new PIXI.Rectangle(0, 0, 20, 20); + const rect4 = new PIXI.Rectangle(10, 0, 20, 20); + + rect3.fit(rect4); + + expect(rect3.left).to.equal(10); + expect(rect3.top).to.equal(0); + expect(rect3.right).to.equal(30); + expect(rect3.bottom).to.equal(20); + }); + + it('should generate an empty rectangle', function () + { + const rect = PIXI.Rectangle.EMPTY; + + expect(rect.left).to.equal(0); + expect(rect.top).to.equal(0); + expect(rect.right).to.equal(0); + expect(rect.bottom).to.equal(0); }); }); diff --git a/src/core/graphics/canvas/CanvasGraphicsRenderer.js b/src/core/graphics/canvas/CanvasGraphicsRenderer.js index 2d53be3..fe62c2b 100644 --- a/src/core/graphics/canvas/CanvasGraphicsRenderer.js +++ b/src/core/graphics/canvas/CanvasGraphicsRenderer.js @@ -10,7 +10,7 @@ * now share 4 bytes on the vertex buffer * * Heavily inspired by LibGDX's CanvasGraphicsRenderer: - * https://github.com/libgdx/libgdx/blob/master/gdx/src/com/badlogic/gdx/graphics/g2d/CanvasGraphicsRenderer.java + * https://github.com/libgdx/libgdx/blob/1.0.0/gdx/src/com/badlogic/gdx/graphics/glutils/ShapeRenderer.java */ /** diff --git a/src/core/math/shapes/Rectangle.js b/src/core/math/shapes/Rectangle.js index 3e4f18f..29b312a 100644 --- a/src/core/math/shapes/Rectangle.js +++ b/src/core/math/shapes/Rectangle.js @@ -222,19 +222,14 @@ /** * Enlarges this rectangle to include the passed rectangle. * - * @param {PIXI.Rectangle} rect - The rectangle to include. + * @param {PIXI.Rectangle} rectangle - The rectangle to include. */ - enlarge(rect) + enlarge(rectangle) { - if (rect === Rectangle.EMPTY) - { - return; - } - - const x1 = Math.min(this.x, rect.x); - const x2 = Math.max(this.x + this.width, rect.x + rect.width); - const y1 = Math.min(this.y, rect.y); - const y2 = Math.max(this.y + this.height, rect.y + rect.height); + const x1 = Math.min(this.x, rectangle.x); + const x2 = Math.max(this.x + this.width, rectangle.x + rectangle.width); + const y1 = Math.min(this.y, rectangle.y); + const y2 = Math.max(this.y + this.height, rectangle.y + rectangle.height); this.x = x1; this.width = x2 - x1; diff --git a/src/extras/AnimatedSprite.js b/src/extras/AnimatedSprite.js index 660fed7..13b804f 100644 --- a/src/extras/AnimatedSprite.js +++ b/src/extras/AnimatedSprite.js @@ -32,8 +32,9 @@ /** * @param {PIXI.Texture[]|FrameObject[]} textures - an array of {@link PIXI.Texture} or frame * objects that make up the animation + * @param {boolean} [autoUpdate=true] - Whether use PIXI.ticker.shared to auto update animation time. */ - constructor(textures) + constructor(textures, autoUpdate) { super(textures[0] instanceof core.Texture ? textures[0] : textures[0].texture); @@ -50,6 +51,14 @@ this.textures = textures; /** + * `true` uses PIXI.ticker.shared to auto update animation time. + * @type {boolean} + * @default true + * @private + */ + this._autoUpdate = autoUpdate !== false; + + /** * The speed that the AnimatedSprite will play at. Higher is faster, lower is slower * * @member {number} @@ -108,7 +117,10 @@ } this.playing = false; - core.ticker.shared.remove(this.update, this); + if (this._autoUpdate) + { + core.ticker.shared.remove(this.update, this); + } } /** @@ -123,7 +135,10 @@ } this.playing = true; - core.ticker.shared.add(this.update, this); + if (this._autoUpdate) + { + core.ticker.shared.add(this.update, this); + } } /** diff --git a/test/core/Rectangle.js b/test/core/Rectangle.js index 71f4355..40ca3b0 100644 --- a/test/core/Rectangle.js +++ b/test/core/Rectangle.js @@ -67,25 +67,6 @@ expect(rect2.contains(21, 21)).to.be.false; }); - it('should make rectangle grow', function () - { - const rect = new PIXI.Rectangle(10, 10, 10, 10); - - rect.pad(1, 1); - - expect(rect.left).to.equal(9); - expect(rect.top).to.equal(9); - expect(rect.right).to.equal(21); - expect(rect.bottom).to.equal(21); - - rect.pad(10, 10); - - expect(rect.left).to.equal(-1); - expect(rect.top).to.equal(-1); - expect(rect.right).to.equal(31); - expect(rect.bottom).to.equal(31); - }); - it('should enlarge rectangle', function () { const rect1 = new PIXI.Rectangle(10, 10, 10, 10); @@ -97,5 +78,91 @@ expect(rect1.top).to.equal(10); expect(rect1.right).to.equal(25); expect(rect1.bottom).to.equal(25); + + const rect3 = new PIXI.Rectangle(0, 0, 0, 0); + const rect4 = new PIXI.Rectangle(10, 10, 10, 10); + + rect4.enlarge(rect3); + + expect(rect4.left).to.equal(0); + expect(rect4.top).to.equal(0); + expect(rect4.right).to.equal(20); + expect(rect4.bottom).to.equal(20); + }); + + it('should pad a rectangle', function () + { + // Pad with X & Y + const rect = new PIXI.Rectangle(10, 10, 10, 10); + + rect.pad(10, 10); + + expect(rect.left).to.equal(0); + expect(rect.top).to.equal(0); + expect(rect.right).to.equal(30); + expect(rect.bottom).to.equal(30); + + // Pad with X + const rect1 = new PIXI.Rectangle(10, 10, 10, 10); + + rect1.pad(10); + + expect(rect1.left).to.equal(0); + expect(rect1.top).to.equal(0); + expect(rect1.right).to.equal(30); + expect(rect1.bottom).to.equal(30); + + // Pad with nothing + const rect2 = new PIXI.Rectangle(10, 10, 10, 10); + + rect2.pad(); + + expect(rect2.left).to.equal(10); + expect(rect2.top).to.equal(10); + expect(rect2.right).to.equal(20); + expect(rect2.bottom).to.equal(20); + + // Pad with Y + const rect3 = new PIXI.Rectangle(10, 10, 10, 10); + + rect3.pad(null, 10); + + expect(rect3.left).to.equal(10); + expect(rect3.top).to.equal(0); + expect(rect3.right).to.equal(20); + expect(rect3.bottom).to.equal(30); + }); + + it('should fit a rectangle', function () + { + const rect1 = new PIXI.Rectangle(0, 0, -10, -10); + const rect2 = new PIXI.Rectangle(-10, -10, 5, 5); + + rect2.fit(rect1); + + expect(rect2.left).to.equal(0); + expect(rect2.top).to.equal(0); + expect(rect2.right).to.equal(0); + expect(rect2.bottom).to.equal(0); + + const rect3 = new PIXI.Rectangle(0, 0, 20, 20); + const rect4 = new PIXI.Rectangle(10, 0, 20, 20); + + rect3.fit(rect4); + + expect(rect3.left).to.equal(10); + expect(rect3.top).to.equal(0); + expect(rect3.right).to.equal(30); + expect(rect3.bottom).to.equal(20); + }); + + it('should generate an empty rectangle', function () + { + const rect = PIXI.Rectangle.EMPTY; + + expect(rect.left).to.equal(0); + expect(rect.top).to.equal(0); + expect(rect.right).to.equal(0); + expect(rect.bottom).to.equal(0); }); }); diff --git a/test/interaction/InteractionManager.js b/test/interaction/InteractionManager.js index 47d6819..2cf6d9d 100644 --- a/test/interaction/InteractionManager.js +++ b/test/interaction/InteractionManager.js @@ -81,4 +81,384 @@ expect(clickSpy).to.not.have.been.called; }); }); + + describe('overlapping children', function () + { + function getScene(callbackEventName) + { + const behindChild = new PIXI.Graphics(); + const frontChild = new PIXI.Graphics(); + const parent = new PIXI.Container(); + const behindChildCallback = sinon.spy(); + const frontChildCallback = sinon.spy(); + const parentCallback = sinon.spy(); + + behindChild.beginFill(0xFF); + behindChild.drawRect(0, 0, 50, 50); + behindChild.on(callbackEventName, behindChildCallback); + + frontChild.beginFill(0x00FF); + frontChild.drawRect(0, 0, 50, 50); + frontChild.on(callbackEventName, frontChildCallback); + + parent.addChild(behindChild, frontChild); + parent.on(callbackEventName, parentCallback); + + return { + behindChild, + frontChild, + parent, + behindChildCallback, + frontChildCallback, + parentCallback, + }; + } + + describe('when parent is non-interactive', function () + { + describe('when both children are interactive', function () + { + it('should callback front child when clicking front child', function () + { + const stage = new PIXI.Container(); + const pointer = new MockPointer(stage); + const scene = getScene('click'); + + scene.behindChild.interactive = true; + scene.behindChild.x = 25; + scene.frontChild.interactive = true; + + stage.addChild(scene.parent); + pointer.click(10, 10); + + expect(scene.behindChildCallback).to.not.have.been.called; + expect(scene.frontChildCallback).to.have.been.calledOnce; + expect(scene.parentCallback).to.not.have.been.called; + }); + + it('should callback front child when clicking overlap', function () + { + const stage = new PIXI.Container(); + const pointer = new MockPointer(stage); + const scene = getScene('click'); + + scene.behindChild.interactive = true; + scene.behindChild.x = 25; + scene.frontChild.interactive = true; + + stage.addChild(scene.parent); + pointer.click(40, 10); + + expect(scene.behindChildCallback).to.not.have.been.called; + expect(scene.frontChildCallback).to.have.been.calledOnce; + expect(scene.parentCallback).to.not.have.been.called; + }); + + it('should callback behind child when clicking behind child', function () + { + const stage = new PIXI.Container(); + const pointer = new MockPointer(stage); + const scene = getScene('click'); + + scene.behindChild.interactive = true; + scene.behindChild.x = 25; + scene.frontChild.interactive = true; + + stage.addChild(scene.parent); + pointer.click(60, 10); + + expect(scene.frontChildCallback).to.not.have.been.called; + expect(scene.behindChildCallback).to.have.been.calledOnce; + expect(scene.parentCallback).to.not.have.been.called; + }); + }); + + describe('when front child is non-interactive', function () + { + it('should not callback when clicking front child', function () + { + const stage = new PIXI.Container(); + const pointer = new MockPointer(stage); + const scene = getScene('click'); + + scene.behindChild.interactive = true; + scene.behindChild.x = 25; + + stage.addChild(scene.parent); + pointer.click(10, 10); + + expect(scene.behindChildCallback).to.not.have.been.called; + expect(scene.frontChildCallback).to.not.have.been.called; + expect(scene.parentCallback).to.not.have.been.called; + }); + + it('should callback behind child when clicking overlap', function () + { + const stage = new PIXI.Container(); + const pointer = new MockPointer(stage); + const scene = getScene('click'); + + scene.behindChild.interactive = true; + scene.behindChild.x = 25; + + stage.addChild(scene.parent); + pointer.click(40, 10); + + expect(scene.behindChildCallback).to.have.been.calledOnce; + expect(scene.frontChildCallback).to.not.have.been.called; + expect(scene.parentCallback).to.not.have.been.called; + }); + + it('should callback behind child when clicking behind child', function () + { + const stage = new PIXI.Container(); + const pointer = new MockPointer(stage); + const scene = getScene('click'); + + scene.behindChild.interactive = true; + scene.behindChild.x = 25; + + stage.addChild(scene.parent); + pointer.click(60, 10); + + expect(scene.frontChildCallback).to.not.have.been.called; + expect(scene.behindChildCallback).to.have.been.calledOnce; + expect(scene.parentCallback).to.not.have.been.called; + }); + }); + + describe('when behind child is non-interactive', function () + { + it('should callback front child when clicking front child', function () + { + const stage = new PIXI.Container(); + const pointer = new MockPointer(stage); + const scene = getScene('click'); + + scene.behindChild.x = 25; + scene.frontChild.interactive = true; + + stage.addChild(scene.parent); + pointer.click(10, 10); + + expect(scene.behindChildCallback).to.not.have.been.called; + expect(scene.frontChildCallback).to.have.been.calledOnce; + expect(scene.parentCallback).to.not.have.been.called; + }); + + it('should callback front child when clicking overlap', function () + { + const stage = new PIXI.Container(); + const pointer = new MockPointer(stage); + const scene = getScene('click'); + + scene.behindChild.x = 25; + scene.frontChild.interactive = true; + + stage.addChild(scene.parent); + pointer.click(40, 10); + + expect(scene.behindChildCallback).to.not.have.been.called; + expect(scene.frontChildCallback).to.have.been.calledOnce; + expect(scene.parentCallback).to.not.have.been.called; + }); + + it('should not callback when clicking behind child', function () + { + const stage = new PIXI.Container(); + const pointer = new MockPointer(stage); + const scene = getScene('click'); + + scene.behindChild.x = 25; + scene.frontChild.interactive = true; + + stage.addChild(scene.parent); + pointer.click(60, 10); + + expect(scene.frontChildCallback).to.not.have.been.called; + expect(scene.behindChildCallback).to.not.have.been.called; + expect(scene.parentCallback).to.not.have.been.called; + }); + }); + }); + + describe('when parent is interactive', function () + { + describe('when both children are interactive', function () + { + it('should callback parent and front child when clicking front child', function () + { + const stage = new PIXI.Container(); + const pointer = new MockPointer(stage); + const scene = getScene('click'); + + scene.behindChild.interactive = true; + scene.behindChild.x = 25; + scene.frontChild.interactive = true; + scene.parent.interactive = true; + + stage.addChild(scene.parent); + pointer.click(10, 10); + + expect(scene.behindChildCallback).to.not.have.been.called; + expect(scene.frontChildCallback).to.have.been.calledOnce; + expect(scene.parentCallback).to.have.been.calledOnce; + }); + + it('should callback parent and front child when clicking overlap', function () + { + const stage = new PIXI.Container(); + const pointer = new MockPointer(stage); + const scene = getScene('click'); + + scene.behindChild.interactive = true; + scene.behindChild.x = 25; + scene.frontChild.interactive = true; + scene.parent.interactive = true; + + stage.addChild(scene.parent); + pointer.click(40, 10); + + expect(scene.behindChildCallback).to.not.have.been.called; + expect(scene.frontChildCallback).to.have.been.calledOnce; + expect(scene.parentCallback).to.have.been.calledOnce; + }); + + it('should callback parent and behind child when clicking behind child', function () + { + const stage = new PIXI.Container(); + const pointer = new MockPointer(stage); + const scene = getScene('click'); + + scene.behindChild.interactive = true; + scene.behindChild.x = 25; + scene.frontChild.interactive = true; + scene.parent.interactive = true; + + stage.addChild(scene.parent); + pointer.click(60, 10); + + expect(scene.frontChildCallback).to.not.have.been.called; + expect(scene.behindChildCallback).to.have.been.calledOnce; + expect(scene.parentCallback).to.have.been.calledOnce; + }); + }); + + describe('when front child is non-interactive', function () + { + it('should callback parent when clicking front child', function () + { + const stage = new PIXI.Container(); + const pointer = new MockPointer(stage); + const scene = getScene('click'); + + scene.behindChild.interactive = true; + scene.behindChild.x = 25; + scene.parent.interactive = true; + + stage.addChild(scene.parent); + pointer.click(10, 10); + + expect(scene.behindChildCallback).to.not.have.been.called; + expect(scene.frontChildCallback).to.not.have.been.called; + expect(scene.parentCallback).to.have.been.calledOnce; + }); + + /* TODO: Fix #3596 + it('should callback parent and behind child when clicking overlap', function () + { + const stage = new PIXI.Container(); + const pointer = new MockPointer(stage); + const scene = getScene('click'); + + scene.behindChild.interactive = true; + scene.behindChild.x = 25; + scene.parent.interactive = true; + + stage.addChild(scene.parent); + pointer.click(40, 10); + + expect(scene.behindChildCallback).to.have.been.calledOnce; + expect(scene.frontChildCallback).to.not.have.been.called; + expect(scene.parentCallback).to.have.been.calledOnce; + }); + */ + + it('should callback parent and behind child when clicking behind child', function () + { + const stage = new PIXI.Container(); + const pointer = new MockPointer(stage); + const scene = getScene('click'); + + scene.behindChild.interactive = true; + scene.behindChild.x = 25; + scene.parent.interactive = true; + + stage.addChild(scene.parent); + pointer.click(60, 10); + + expect(scene.frontChildCallback).to.not.have.been.called; + expect(scene.behindChildCallback).to.have.been.calledOnce; + expect(scene.parentCallback).to.have.been.calledOnce; + }); + }); + + describe('when behind child is non-interactive', function () + { + it('should callback parent and front child when clicking front child', function () + { + const stage = new PIXI.Container(); + const pointer = new MockPointer(stage); + const scene = getScene('click'); + + scene.behindChild.x = 25; + scene.frontChild.interactive = true; + scene.parent.interactive = true; + + stage.addChild(scene.parent); + pointer.click(10, 10); + + expect(scene.behindChildCallback).to.not.have.been.called; + expect(scene.frontChildCallback).to.have.been.calledOnce; + expect(scene.parentCallback).to.have.been.calledOnce; + }); + + it('should callback parent and front child when clicking overlap', function () + { + const stage = new PIXI.Container(); + const pointer = new MockPointer(stage); + const scene = getScene('click'); + + scene.behindChild.x = 25; + scene.frontChild.interactive = true; + scene.parent.interactive = true; + + stage.addChild(scene.parent); + pointer.click(40, 10); + + expect(scene.behindChildCallback).to.not.have.been.called; + expect(scene.frontChildCallback).to.have.been.calledOnce; + expect(scene.parentCallback).to.have.been.calledOnce; + }); + + it('should callback parent when clicking behind child', function () + { + const stage = new PIXI.Container(); + const pointer = new MockPointer(stage); + const scene = getScene('click'); + + scene.behindChild.x = 25; + scene.frontChild.interactive = true; + scene.parent.interactive = true; + + stage.addChild(scene.parent); + pointer.click(60, 10); + + expect(scene.frontChildCallback).to.not.have.been.called; + expect(scene.behindChildCallback).to.not.have.been.called; + expect(scene.parentCallback).to.have.been.calledOnce; + }); + }); + }); + }); });