diff --git a/Gruntfile.js b/Gruntfile.js index 4846362..b3b8ac7 100644 --- a/Gruntfile.js +++ b/Gruntfile.js @@ -13,6 +13,7 @@ '<%= dirs.src %>/Pixi.js', '<%= dirs.src %>/Point.js', '<%= dirs.src %>/Rectangle.js', + '<%= dirs.src %>/Polygon.js', '<%= dirs.src %>/DisplayObject.js', '<%= dirs.src %>/DisplayObjectContainer.js', '<%= dirs.src %>/Sprite.js', diff --git a/Gruntfile.js b/Gruntfile.js index 4846362..b3b8ac7 100644 --- a/Gruntfile.js +++ b/Gruntfile.js @@ -13,6 +13,7 @@ '<%= dirs.src %>/Pixi.js', '<%= dirs.src %>/Point.js', '<%= dirs.src %>/Rectangle.js', + '<%= dirs.src %>/Polygon.js', '<%= dirs.src %>/DisplayObject.js', '<%= dirs.src %>/DisplayObjectContainer.js', '<%= dirs.src %>/Sprite.js', diff --git a/src/pixi/InteractionManager.js b/src/pixi/InteractionManager.js index c6a8da2..bb88a5f 100644 --- a/src/pixi/InteractionManager.js +++ b/src/pixi/InteractionManager.js @@ -63,25 +63,27 @@ { var child = children[i]; - // push all interactive bits - if(child.interactive) - { - iParent.interactiveChildren = true; - //child.__iParent = iParent; - this.interactiveItems.push(child); - - if(child.children.length > 0) + if(child.visible) { + // push all interactive bits + if(child.interactive) { - this.collectInteractiveSprite(child, child); + iParent.interactiveChildren = true; + //child.__iParent = iParent; + this.interactiveItems.push(child); + + if(child.children.length > 0) + { + this.collectInteractiveSprite(child, child); + } } - } - else - { - child.__iParent = null; - - if(child.children.length > 0) + else { - this.collectInteractiveSprite(child, iParent); + child.__iParent = null; + + if(child.children.length > 0) + { + this.collectInteractiveSprite(child, iParent); + } } } } @@ -191,8 +193,6 @@ PIXI.InteractionManager.prototype.onMouseMove = function(event) { - event.preventDefault(); - // TODO optimize by not check EVERY TIME! maybe half as often? // var rect = this.target.view.getBoundingClientRect(); @@ -217,8 +217,6 @@ PIXI.InteractionManager.prototype.onMouseDown = function(event) { - event.preventDefault(); - // loop through inteaction tree... // hit test each item! -> // get interactive items under point?? @@ -255,7 +253,6 @@ PIXI.InteractionManager.prototype.onMouseUp = function(event) { - event.preventDefault(); var global = this.mouse.global; @@ -302,27 +299,66 @@ var global = interactionData.global; if(!item.visible)return false; - - if(item instanceof PIXI.Sprite) + + var isSprite = (item instanceof PIXI.Sprite), + worldTransform = item.worldTransform, + a00 = worldTransform[0], a01 = worldTransform[1], a02 = worldTransform[2], + a10 = worldTransform[3], a11 = worldTransform[4], a12 = worldTransform[5], + id = 1 / (a00 * a11 + a01 * -a10), + x = a11 * id * global.x + -a01 * id * global.y + (a12 * a01 - a02 * a11) * id, + y = a00 * id * global.y + -a10 * id * global.x + (-a12 * a00 + a02 * a10) * id; + + //a sprite or display object with a hit area defined + if(item.hitArea) { - var worldTransform = item.worldTransform; - - var a00 = worldTransform[0], a01 = worldTransform[1], a02 = worldTransform[2], - a10 = worldTransform[3], a11 = worldTransform[4], a12 = worldTransform[5], - id = 1 / (a00 * a11 + a01 * -a10); - - var x = a11 * id * global.x + -a01 * id * global.y + (a12 * a01 - a02 * a11) * id; - var y = a00 * id * global.y + -a10 * id * global.x + (-a12 * a00 + a02 * a10) * id; - - var width = item.texture.frame.width; - var height = item.texture.frame.height; - - var x1 = -width * item.anchor.x; + var hitArea = item.hitArea; + + //Polygon hit area + if(item.hitArea instanceof PIXI.Polygon) { + var inside = false; + + // use some raycasting to test hits + // https://github.com/substack/point-in-polygon/blob/master/index.js + for(var i = 0, j = item.hitArea.points.length - 1; i < item.hitArea.points.length; j = i++) { + var xi = item.hitArea.points[i].x, yi = item.hitArea.points[i].y, + xj = item.hitArea.points[j].x, yj = item.hitArea.points[j].y, + intersect = ((yi > y) != (yj > y)) && (x < (xj - xi) * (y - yi) / (yj - yi) + xi); + + if(intersect) inside = !inside; + } + + if(inside) { + if(isSprite) interactionData.target = item; + return true; + } + } + //Rectangle hit area + else { + var x1 = hitArea.x; + if(x > x1 && x < x1 + hitArea.width) + { + var y1 = hitArea.y; + + if(y > y1 && y < y1 + hitArea.height) + { + if(isSprite) interactionData.target = item; + return true; + } + } + } + } + // a sprite with no hitarea defined + else if(isSprite) + { + var width = item.texture.frame.width, + height = item.texture.frame.height, + x1 = -width * item.anchor.x, + y1; if(x > x1 && x < x1 + width) { - var y1 = -height * item.anchor.y; - + y1 = -height * item.anchor.y; + if(y > y1 && y < y1 + height) { // set the target property if a hit is true! @@ -331,30 +367,7 @@ } } } - else if(item.hitArea) - { - var worldTransform = item.worldTransform; - var hitArea = item.hitArea; - - var a00 = worldTransform[0], a01 = worldTransform[1], a02 = worldTransform[2], - a10 = worldTransform[3], a11 = worldTransform[4], a12 = worldTransform[5], - id = 1 / (a00 * a11 + a01 * -a10); - - var x = a11 * id * global.x + -a01 * id * global.y + (a12 * a01 - a02 * a11) * id; - var y = a00 * id * global.y + -a10 * id * global.x + (-a12 * a00 + a02 * a10) * id; - - var x1 = hitArea.x; - if(x > x1 && x < x1 + hitArea.width) - { - var y1 = hitArea.y; - - if(y > y1 && y < y1 + hitArea.height) - { - return true; - } - } - } - + var length = item.children.length; for (var i = 0; i < length; i++) @@ -363,7 +376,7 @@ var hit = this.hitTest(tempItem, interactionData); if(hit)return true; } - + return false; } @@ -371,8 +384,6 @@ PIXI.InteractionManager.prototype.onTouchMove = function(event) { - event.preventDefault(); - var rect = this.target.view.getBoundingClientRect(); var changedTouches = event.changedTouches; @@ -396,7 +407,6 @@ PIXI.InteractionManager.prototype.onTouchStart = function(event) { - event.preventDefault(); var rect = this.target.view.getBoundingClientRect(); var changedTouches = event.changedTouches; @@ -438,9 +448,6 @@ PIXI.InteractionManager.prototype.onTouchEnd = function(event) { - event.preventDefault(); - - var rect = this.target.view.getBoundingClientRect(); var changedTouches = event.changedTouches; diff --git a/Gruntfile.js b/Gruntfile.js index 4846362..b3b8ac7 100644 --- a/Gruntfile.js +++ b/Gruntfile.js @@ -13,6 +13,7 @@ '<%= dirs.src %>/Pixi.js', '<%= dirs.src %>/Point.js', '<%= dirs.src %>/Rectangle.js', + '<%= dirs.src %>/Polygon.js', '<%= dirs.src %>/DisplayObject.js', '<%= dirs.src %>/DisplayObjectContainer.js', '<%= dirs.src %>/Sprite.js', diff --git a/src/pixi/InteractionManager.js b/src/pixi/InteractionManager.js index c6a8da2..bb88a5f 100644 --- a/src/pixi/InteractionManager.js +++ b/src/pixi/InteractionManager.js @@ -63,25 +63,27 @@ { var child = children[i]; - // push all interactive bits - if(child.interactive) - { - iParent.interactiveChildren = true; - //child.__iParent = iParent; - this.interactiveItems.push(child); - - if(child.children.length > 0) + if(child.visible) { + // push all interactive bits + if(child.interactive) { - this.collectInteractiveSprite(child, child); + iParent.interactiveChildren = true; + //child.__iParent = iParent; + this.interactiveItems.push(child); + + if(child.children.length > 0) + { + this.collectInteractiveSprite(child, child); + } } - } - else - { - child.__iParent = null; - - if(child.children.length > 0) + else { - this.collectInteractiveSprite(child, iParent); + child.__iParent = null; + + if(child.children.length > 0) + { + this.collectInteractiveSprite(child, iParent); + } } } } @@ -191,8 +193,6 @@ PIXI.InteractionManager.prototype.onMouseMove = function(event) { - event.preventDefault(); - // TODO optimize by not check EVERY TIME! maybe half as often? // var rect = this.target.view.getBoundingClientRect(); @@ -217,8 +217,6 @@ PIXI.InteractionManager.prototype.onMouseDown = function(event) { - event.preventDefault(); - // loop through inteaction tree... // hit test each item! -> // get interactive items under point?? @@ -255,7 +253,6 @@ PIXI.InteractionManager.prototype.onMouseUp = function(event) { - event.preventDefault(); var global = this.mouse.global; @@ -302,27 +299,66 @@ var global = interactionData.global; if(!item.visible)return false; - - if(item instanceof PIXI.Sprite) + + var isSprite = (item instanceof PIXI.Sprite), + worldTransform = item.worldTransform, + a00 = worldTransform[0], a01 = worldTransform[1], a02 = worldTransform[2], + a10 = worldTransform[3], a11 = worldTransform[4], a12 = worldTransform[5], + id = 1 / (a00 * a11 + a01 * -a10), + x = a11 * id * global.x + -a01 * id * global.y + (a12 * a01 - a02 * a11) * id, + y = a00 * id * global.y + -a10 * id * global.x + (-a12 * a00 + a02 * a10) * id; + + //a sprite or display object with a hit area defined + if(item.hitArea) { - var worldTransform = item.worldTransform; - - var a00 = worldTransform[0], a01 = worldTransform[1], a02 = worldTransform[2], - a10 = worldTransform[3], a11 = worldTransform[4], a12 = worldTransform[5], - id = 1 / (a00 * a11 + a01 * -a10); - - var x = a11 * id * global.x + -a01 * id * global.y + (a12 * a01 - a02 * a11) * id; - var y = a00 * id * global.y + -a10 * id * global.x + (-a12 * a00 + a02 * a10) * id; - - var width = item.texture.frame.width; - var height = item.texture.frame.height; - - var x1 = -width * item.anchor.x; + var hitArea = item.hitArea; + + //Polygon hit area + if(item.hitArea instanceof PIXI.Polygon) { + var inside = false; + + // use some raycasting to test hits + // https://github.com/substack/point-in-polygon/blob/master/index.js + for(var i = 0, j = item.hitArea.points.length - 1; i < item.hitArea.points.length; j = i++) { + var xi = item.hitArea.points[i].x, yi = item.hitArea.points[i].y, + xj = item.hitArea.points[j].x, yj = item.hitArea.points[j].y, + intersect = ((yi > y) != (yj > y)) && (x < (xj - xi) * (y - yi) / (yj - yi) + xi); + + if(intersect) inside = !inside; + } + + if(inside) { + if(isSprite) interactionData.target = item; + return true; + } + } + //Rectangle hit area + else { + var x1 = hitArea.x; + if(x > x1 && x < x1 + hitArea.width) + { + var y1 = hitArea.y; + + if(y > y1 && y < y1 + hitArea.height) + { + if(isSprite) interactionData.target = item; + return true; + } + } + } + } + // a sprite with no hitarea defined + else if(isSprite) + { + var width = item.texture.frame.width, + height = item.texture.frame.height, + x1 = -width * item.anchor.x, + y1; if(x > x1 && x < x1 + width) { - var y1 = -height * item.anchor.y; - + y1 = -height * item.anchor.y; + if(y > y1 && y < y1 + height) { // set the target property if a hit is true! @@ -331,30 +367,7 @@ } } } - else if(item.hitArea) - { - var worldTransform = item.worldTransform; - var hitArea = item.hitArea; - - var a00 = worldTransform[0], a01 = worldTransform[1], a02 = worldTransform[2], - a10 = worldTransform[3], a11 = worldTransform[4], a12 = worldTransform[5], - id = 1 / (a00 * a11 + a01 * -a10); - - var x = a11 * id * global.x + -a01 * id * global.y + (a12 * a01 - a02 * a11) * id; - var y = a00 * id * global.y + -a10 * id * global.x + (-a12 * a00 + a02 * a10) * id; - - var x1 = hitArea.x; - if(x > x1 && x < x1 + hitArea.width) - { - var y1 = hitArea.y; - - if(y > y1 && y < y1 + hitArea.height) - { - return true; - } - } - } - + var length = item.children.length; for (var i = 0; i < length; i++) @@ -363,7 +376,7 @@ var hit = this.hitTest(tempItem, interactionData); if(hit)return true; } - + return false; } @@ -371,8 +384,6 @@ PIXI.InteractionManager.prototype.onTouchMove = function(event) { - event.preventDefault(); - var rect = this.target.view.getBoundingClientRect(); var changedTouches = event.changedTouches; @@ -396,7 +407,6 @@ PIXI.InteractionManager.prototype.onTouchStart = function(event) { - event.preventDefault(); var rect = this.target.view.getBoundingClientRect(); var changedTouches = event.changedTouches; @@ -438,9 +448,6 @@ PIXI.InteractionManager.prototype.onTouchEnd = function(event) { - event.preventDefault(); - - var rect = this.target.view.getBoundingClientRect(); var changedTouches = event.changedTouches; diff --git a/src/pixi/Polygon.js b/src/pixi/Polygon.js new file mode 100644 index 0000000..aca9aa7 --- /dev/null +++ b/src/pixi/Polygon.js @@ -0,0 +1,31 @@ +/** + * @author Adrien Brault + */ + +/** + * @class Polygon + * @constructor + * @param points {Array} + */ +PIXI.Polygon = function(points) +{ + this.points = points; +} + +/** + * @method clone + * @return a copy of the polygon + */ +PIXI.Polygon.clone = function() +{ + var points = []; + for (var i=0; i/Pixi.js', '<%= dirs.src %>/Point.js', '<%= dirs.src %>/Rectangle.js', + '<%= dirs.src %>/Polygon.js', '<%= dirs.src %>/DisplayObject.js', '<%= dirs.src %>/DisplayObjectContainer.js', '<%= dirs.src %>/Sprite.js', diff --git a/src/pixi/InteractionManager.js b/src/pixi/InteractionManager.js index c6a8da2..bb88a5f 100644 --- a/src/pixi/InteractionManager.js +++ b/src/pixi/InteractionManager.js @@ -63,25 +63,27 @@ { var child = children[i]; - // push all interactive bits - if(child.interactive) - { - iParent.interactiveChildren = true; - //child.__iParent = iParent; - this.interactiveItems.push(child); - - if(child.children.length > 0) + if(child.visible) { + // push all interactive bits + if(child.interactive) { - this.collectInteractiveSprite(child, child); + iParent.interactiveChildren = true; + //child.__iParent = iParent; + this.interactiveItems.push(child); + + if(child.children.length > 0) + { + this.collectInteractiveSprite(child, child); + } } - } - else - { - child.__iParent = null; - - if(child.children.length > 0) + else { - this.collectInteractiveSprite(child, iParent); + child.__iParent = null; + + if(child.children.length > 0) + { + this.collectInteractiveSprite(child, iParent); + } } } } @@ -191,8 +193,6 @@ PIXI.InteractionManager.prototype.onMouseMove = function(event) { - event.preventDefault(); - // TODO optimize by not check EVERY TIME! maybe half as often? // var rect = this.target.view.getBoundingClientRect(); @@ -217,8 +217,6 @@ PIXI.InteractionManager.prototype.onMouseDown = function(event) { - event.preventDefault(); - // loop through inteaction tree... // hit test each item! -> // get interactive items under point?? @@ -255,7 +253,6 @@ PIXI.InteractionManager.prototype.onMouseUp = function(event) { - event.preventDefault(); var global = this.mouse.global; @@ -302,27 +299,66 @@ var global = interactionData.global; if(!item.visible)return false; - - if(item instanceof PIXI.Sprite) + + var isSprite = (item instanceof PIXI.Sprite), + worldTransform = item.worldTransform, + a00 = worldTransform[0], a01 = worldTransform[1], a02 = worldTransform[2], + a10 = worldTransform[3], a11 = worldTransform[4], a12 = worldTransform[5], + id = 1 / (a00 * a11 + a01 * -a10), + x = a11 * id * global.x + -a01 * id * global.y + (a12 * a01 - a02 * a11) * id, + y = a00 * id * global.y + -a10 * id * global.x + (-a12 * a00 + a02 * a10) * id; + + //a sprite or display object with a hit area defined + if(item.hitArea) { - var worldTransform = item.worldTransform; - - var a00 = worldTransform[0], a01 = worldTransform[1], a02 = worldTransform[2], - a10 = worldTransform[3], a11 = worldTransform[4], a12 = worldTransform[5], - id = 1 / (a00 * a11 + a01 * -a10); - - var x = a11 * id * global.x + -a01 * id * global.y + (a12 * a01 - a02 * a11) * id; - var y = a00 * id * global.y + -a10 * id * global.x + (-a12 * a00 + a02 * a10) * id; - - var width = item.texture.frame.width; - var height = item.texture.frame.height; - - var x1 = -width * item.anchor.x; + var hitArea = item.hitArea; + + //Polygon hit area + if(item.hitArea instanceof PIXI.Polygon) { + var inside = false; + + // use some raycasting to test hits + // https://github.com/substack/point-in-polygon/blob/master/index.js + for(var i = 0, j = item.hitArea.points.length - 1; i < item.hitArea.points.length; j = i++) { + var xi = item.hitArea.points[i].x, yi = item.hitArea.points[i].y, + xj = item.hitArea.points[j].x, yj = item.hitArea.points[j].y, + intersect = ((yi > y) != (yj > y)) && (x < (xj - xi) * (y - yi) / (yj - yi) + xi); + + if(intersect) inside = !inside; + } + + if(inside) { + if(isSprite) interactionData.target = item; + return true; + } + } + //Rectangle hit area + else { + var x1 = hitArea.x; + if(x > x1 && x < x1 + hitArea.width) + { + var y1 = hitArea.y; + + if(y > y1 && y < y1 + hitArea.height) + { + if(isSprite) interactionData.target = item; + return true; + } + } + } + } + // a sprite with no hitarea defined + else if(isSprite) + { + var width = item.texture.frame.width, + height = item.texture.frame.height, + x1 = -width * item.anchor.x, + y1; if(x > x1 && x < x1 + width) { - var y1 = -height * item.anchor.y; - + y1 = -height * item.anchor.y; + if(y > y1 && y < y1 + height) { // set the target property if a hit is true! @@ -331,30 +367,7 @@ } } } - else if(item.hitArea) - { - var worldTransform = item.worldTransform; - var hitArea = item.hitArea; - - var a00 = worldTransform[0], a01 = worldTransform[1], a02 = worldTransform[2], - a10 = worldTransform[3], a11 = worldTransform[4], a12 = worldTransform[5], - id = 1 / (a00 * a11 + a01 * -a10); - - var x = a11 * id * global.x + -a01 * id * global.y + (a12 * a01 - a02 * a11) * id; - var y = a00 * id * global.y + -a10 * id * global.x + (-a12 * a00 + a02 * a10) * id; - - var x1 = hitArea.x; - if(x > x1 && x < x1 + hitArea.width) - { - var y1 = hitArea.y; - - if(y > y1 && y < y1 + hitArea.height) - { - return true; - } - } - } - + var length = item.children.length; for (var i = 0; i < length; i++) @@ -363,7 +376,7 @@ var hit = this.hitTest(tempItem, interactionData); if(hit)return true; } - + return false; } @@ -371,8 +384,6 @@ PIXI.InteractionManager.prototype.onTouchMove = function(event) { - event.preventDefault(); - var rect = this.target.view.getBoundingClientRect(); var changedTouches = event.changedTouches; @@ -396,7 +407,6 @@ PIXI.InteractionManager.prototype.onTouchStart = function(event) { - event.preventDefault(); var rect = this.target.view.getBoundingClientRect(); var changedTouches = event.changedTouches; @@ -438,9 +448,6 @@ PIXI.InteractionManager.prototype.onTouchEnd = function(event) { - event.preventDefault(); - - var rect = this.target.view.getBoundingClientRect(); var changedTouches = event.changedTouches; diff --git a/src/pixi/Polygon.js b/src/pixi/Polygon.js new file mode 100644 index 0000000..aca9aa7 --- /dev/null +++ b/src/pixi/Polygon.js @@ -0,0 +1,31 @@ +/** + * @author Adrien Brault + */ + +/** + * @class Polygon + * @constructor + * @param points {Array} + */ +PIXI.Polygon = function(points) +{ + this.points = points; +} + +/** + * @method clone + * @return a copy of the polygon + */ +PIXI.Polygon.clone = function() +{ + var points = []; + for (var i=0; i/Pixi.js', '<%= dirs.src %>/Point.js', '<%= dirs.src %>/Rectangle.js', + '<%= dirs.src %>/Polygon.js', '<%= dirs.src %>/DisplayObject.js', '<%= dirs.src %>/DisplayObjectContainer.js', '<%= dirs.src %>/Sprite.js', diff --git a/src/pixi/InteractionManager.js b/src/pixi/InteractionManager.js index c6a8da2..bb88a5f 100644 --- a/src/pixi/InteractionManager.js +++ b/src/pixi/InteractionManager.js @@ -63,25 +63,27 @@ { var child = children[i]; - // push all interactive bits - if(child.interactive) - { - iParent.interactiveChildren = true; - //child.__iParent = iParent; - this.interactiveItems.push(child); - - if(child.children.length > 0) + if(child.visible) { + // push all interactive bits + if(child.interactive) { - this.collectInteractiveSprite(child, child); + iParent.interactiveChildren = true; + //child.__iParent = iParent; + this.interactiveItems.push(child); + + if(child.children.length > 0) + { + this.collectInteractiveSprite(child, child); + } } - } - else - { - child.__iParent = null; - - if(child.children.length > 0) + else { - this.collectInteractiveSprite(child, iParent); + child.__iParent = null; + + if(child.children.length > 0) + { + this.collectInteractiveSprite(child, iParent); + } } } } @@ -191,8 +193,6 @@ PIXI.InteractionManager.prototype.onMouseMove = function(event) { - event.preventDefault(); - // TODO optimize by not check EVERY TIME! maybe half as often? // var rect = this.target.view.getBoundingClientRect(); @@ -217,8 +217,6 @@ PIXI.InteractionManager.prototype.onMouseDown = function(event) { - event.preventDefault(); - // loop through inteaction tree... // hit test each item! -> // get interactive items under point?? @@ -255,7 +253,6 @@ PIXI.InteractionManager.prototype.onMouseUp = function(event) { - event.preventDefault(); var global = this.mouse.global; @@ -302,27 +299,66 @@ var global = interactionData.global; if(!item.visible)return false; - - if(item instanceof PIXI.Sprite) + + var isSprite = (item instanceof PIXI.Sprite), + worldTransform = item.worldTransform, + a00 = worldTransform[0], a01 = worldTransform[1], a02 = worldTransform[2], + a10 = worldTransform[3], a11 = worldTransform[4], a12 = worldTransform[5], + id = 1 / (a00 * a11 + a01 * -a10), + x = a11 * id * global.x + -a01 * id * global.y + (a12 * a01 - a02 * a11) * id, + y = a00 * id * global.y + -a10 * id * global.x + (-a12 * a00 + a02 * a10) * id; + + //a sprite or display object with a hit area defined + if(item.hitArea) { - var worldTransform = item.worldTransform; - - var a00 = worldTransform[0], a01 = worldTransform[1], a02 = worldTransform[2], - a10 = worldTransform[3], a11 = worldTransform[4], a12 = worldTransform[5], - id = 1 / (a00 * a11 + a01 * -a10); - - var x = a11 * id * global.x + -a01 * id * global.y + (a12 * a01 - a02 * a11) * id; - var y = a00 * id * global.y + -a10 * id * global.x + (-a12 * a00 + a02 * a10) * id; - - var width = item.texture.frame.width; - var height = item.texture.frame.height; - - var x1 = -width * item.anchor.x; + var hitArea = item.hitArea; + + //Polygon hit area + if(item.hitArea instanceof PIXI.Polygon) { + var inside = false; + + // use some raycasting to test hits + // https://github.com/substack/point-in-polygon/blob/master/index.js + for(var i = 0, j = item.hitArea.points.length - 1; i < item.hitArea.points.length; j = i++) { + var xi = item.hitArea.points[i].x, yi = item.hitArea.points[i].y, + xj = item.hitArea.points[j].x, yj = item.hitArea.points[j].y, + intersect = ((yi > y) != (yj > y)) && (x < (xj - xi) * (y - yi) / (yj - yi) + xi); + + if(intersect) inside = !inside; + } + + if(inside) { + if(isSprite) interactionData.target = item; + return true; + } + } + //Rectangle hit area + else { + var x1 = hitArea.x; + if(x > x1 && x < x1 + hitArea.width) + { + var y1 = hitArea.y; + + if(y > y1 && y < y1 + hitArea.height) + { + if(isSprite) interactionData.target = item; + return true; + } + } + } + } + // a sprite with no hitarea defined + else if(isSprite) + { + var width = item.texture.frame.width, + height = item.texture.frame.height, + x1 = -width * item.anchor.x, + y1; if(x > x1 && x < x1 + width) { - var y1 = -height * item.anchor.y; - + y1 = -height * item.anchor.y; + if(y > y1 && y < y1 + height) { // set the target property if a hit is true! @@ -331,30 +367,7 @@ } } } - else if(item.hitArea) - { - var worldTransform = item.worldTransform; - var hitArea = item.hitArea; - - var a00 = worldTransform[0], a01 = worldTransform[1], a02 = worldTransform[2], - a10 = worldTransform[3], a11 = worldTransform[4], a12 = worldTransform[5], - id = 1 / (a00 * a11 + a01 * -a10); - - var x = a11 * id * global.x + -a01 * id * global.y + (a12 * a01 - a02 * a11) * id; - var y = a00 * id * global.y + -a10 * id * global.x + (-a12 * a00 + a02 * a10) * id; - - var x1 = hitArea.x; - if(x > x1 && x < x1 + hitArea.width) - { - var y1 = hitArea.y; - - if(y > y1 && y < y1 + hitArea.height) - { - return true; - } - } - } - + var length = item.children.length; for (var i = 0; i < length; i++) @@ -363,7 +376,7 @@ var hit = this.hitTest(tempItem, interactionData); if(hit)return true; } - + return false; } @@ -371,8 +384,6 @@ PIXI.InteractionManager.prototype.onTouchMove = function(event) { - event.preventDefault(); - var rect = this.target.view.getBoundingClientRect(); var changedTouches = event.changedTouches; @@ -396,7 +407,6 @@ PIXI.InteractionManager.prototype.onTouchStart = function(event) { - event.preventDefault(); var rect = this.target.view.getBoundingClientRect(); var changedTouches = event.changedTouches; @@ -438,9 +448,6 @@ PIXI.InteractionManager.prototype.onTouchEnd = function(event) { - event.preventDefault(); - - var rect = this.target.view.getBoundingClientRect(); var changedTouches = event.changedTouches; diff --git a/src/pixi/Polygon.js b/src/pixi/Polygon.js new file mode 100644 index 0000000..aca9aa7 --- /dev/null +++ b/src/pixi/Polygon.js @@ -0,0 +1,31 @@ +/** + * @author Adrien Brault + */ + +/** + * @class Polygon + * @constructor + * @param points {Array} + */ +PIXI.Polygon = function(points) +{ + this.points = points; +} + +/** + * @method clone + * @return a copy of the polygon + */ +PIXI.Polygon.clone = function() +{ + var points = []; + for (var i=0; i/Pixi.js', '<%= dirs.src %>/Point.js', '<%= dirs.src %>/Rectangle.js', + '<%= dirs.src %>/Polygon.js', '<%= dirs.src %>/DisplayObject.js', '<%= dirs.src %>/DisplayObjectContainer.js', '<%= dirs.src %>/Sprite.js', diff --git a/src/pixi/InteractionManager.js b/src/pixi/InteractionManager.js index c6a8da2..bb88a5f 100644 --- a/src/pixi/InteractionManager.js +++ b/src/pixi/InteractionManager.js @@ -63,25 +63,27 @@ { var child = children[i]; - // push all interactive bits - if(child.interactive) - { - iParent.interactiveChildren = true; - //child.__iParent = iParent; - this.interactiveItems.push(child); - - if(child.children.length > 0) + if(child.visible) { + // push all interactive bits + if(child.interactive) { - this.collectInteractiveSprite(child, child); + iParent.interactiveChildren = true; + //child.__iParent = iParent; + this.interactiveItems.push(child); + + if(child.children.length > 0) + { + this.collectInteractiveSprite(child, child); + } } - } - else - { - child.__iParent = null; - - if(child.children.length > 0) + else { - this.collectInteractiveSprite(child, iParent); + child.__iParent = null; + + if(child.children.length > 0) + { + this.collectInteractiveSprite(child, iParent); + } } } } @@ -191,8 +193,6 @@ PIXI.InteractionManager.prototype.onMouseMove = function(event) { - event.preventDefault(); - // TODO optimize by not check EVERY TIME! maybe half as often? // var rect = this.target.view.getBoundingClientRect(); @@ -217,8 +217,6 @@ PIXI.InteractionManager.prototype.onMouseDown = function(event) { - event.preventDefault(); - // loop through inteaction tree... // hit test each item! -> // get interactive items under point?? @@ -255,7 +253,6 @@ PIXI.InteractionManager.prototype.onMouseUp = function(event) { - event.preventDefault(); var global = this.mouse.global; @@ -302,27 +299,66 @@ var global = interactionData.global; if(!item.visible)return false; - - if(item instanceof PIXI.Sprite) + + var isSprite = (item instanceof PIXI.Sprite), + worldTransform = item.worldTransform, + a00 = worldTransform[0], a01 = worldTransform[1], a02 = worldTransform[2], + a10 = worldTransform[3], a11 = worldTransform[4], a12 = worldTransform[5], + id = 1 / (a00 * a11 + a01 * -a10), + x = a11 * id * global.x + -a01 * id * global.y + (a12 * a01 - a02 * a11) * id, + y = a00 * id * global.y + -a10 * id * global.x + (-a12 * a00 + a02 * a10) * id; + + //a sprite or display object with a hit area defined + if(item.hitArea) { - var worldTransform = item.worldTransform; - - var a00 = worldTransform[0], a01 = worldTransform[1], a02 = worldTransform[2], - a10 = worldTransform[3], a11 = worldTransform[4], a12 = worldTransform[5], - id = 1 / (a00 * a11 + a01 * -a10); - - var x = a11 * id * global.x + -a01 * id * global.y + (a12 * a01 - a02 * a11) * id; - var y = a00 * id * global.y + -a10 * id * global.x + (-a12 * a00 + a02 * a10) * id; - - var width = item.texture.frame.width; - var height = item.texture.frame.height; - - var x1 = -width * item.anchor.x; + var hitArea = item.hitArea; + + //Polygon hit area + if(item.hitArea instanceof PIXI.Polygon) { + var inside = false; + + // use some raycasting to test hits + // https://github.com/substack/point-in-polygon/blob/master/index.js + for(var i = 0, j = item.hitArea.points.length - 1; i < item.hitArea.points.length; j = i++) { + var xi = item.hitArea.points[i].x, yi = item.hitArea.points[i].y, + xj = item.hitArea.points[j].x, yj = item.hitArea.points[j].y, + intersect = ((yi > y) != (yj > y)) && (x < (xj - xi) * (y - yi) / (yj - yi) + xi); + + if(intersect) inside = !inside; + } + + if(inside) { + if(isSprite) interactionData.target = item; + return true; + } + } + //Rectangle hit area + else { + var x1 = hitArea.x; + if(x > x1 && x < x1 + hitArea.width) + { + var y1 = hitArea.y; + + if(y > y1 && y < y1 + hitArea.height) + { + if(isSprite) interactionData.target = item; + return true; + } + } + } + } + // a sprite with no hitarea defined + else if(isSprite) + { + var width = item.texture.frame.width, + height = item.texture.frame.height, + x1 = -width * item.anchor.x, + y1; if(x > x1 && x < x1 + width) { - var y1 = -height * item.anchor.y; - + y1 = -height * item.anchor.y; + if(y > y1 && y < y1 + height) { // set the target property if a hit is true! @@ -331,30 +367,7 @@ } } } - else if(item.hitArea) - { - var worldTransform = item.worldTransform; - var hitArea = item.hitArea; - - var a00 = worldTransform[0], a01 = worldTransform[1], a02 = worldTransform[2], - a10 = worldTransform[3], a11 = worldTransform[4], a12 = worldTransform[5], - id = 1 / (a00 * a11 + a01 * -a10); - - var x = a11 * id * global.x + -a01 * id * global.y + (a12 * a01 - a02 * a11) * id; - var y = a00 * id * global.y + -a10 * id * global.x + (-a12 * a00 + a02 * a10) * id; - - var x1 = hitArea.x; - if(x > x1 && x < x1 + hitArea.width) - { - var y1 = hitArea.y; - - if(y > y1 && y < y1 + hitArea.height) - { - return true; - } - } - } - + var length = item.children.length; for (var i = 0; i < length; i++) @@ -363,7 +376,7 @@ var hit = this.hitTest(tempItem, interactionData); if(hit)return true; } - + return false; } @@ -371,8 +384,6 @@ PIXI.InteractionManager.prototype.onTouchMove = function(event) { - event.preventDefault(); - var rect = this.target.view.getBoundingClientRect(); var changedTouches = event.changedTouches; @@ -396,7 +407,6 @@ PIXI.InteractionManager.prototype.onTouchStart = function(event) { - event.preventDefault(); var rect = this.target.view.getBoundingClientRect(); var changedTouches = event.changedTouches; @@ -438,9 +448,6 @@ PIXI.InteractionManager.prototype.onTouchEnd = function(event) { - event.preventDefault(); - - var rect = this.target.view.getBoundingClientRect(); var changedTouches = event.changedTouches; diff --git a/src/pixi/Polygon.js b/src/pixi/Polygon.js new file mode 100644 index 0000000..aca9aa7 --- /dev/null +++ b/src/pixi/Polygon.js @@ -0,0 +1,31 @@ +/** + * @author Adrien Brault + */ + +/** + * @class Polygon + * @constructor + * @param points {Array} + */ +PIXI.Polygon = function(points) +{ + this.points = points; +} + +/** + * @method clone + * @return a copy of the polygon + */ +PIXI.Polygon.clone = function() +{ + var points = []; + for (var i=0; i