2014-02-28 09:30:53 +00:00
/ * *
* @ author Mat Groves http : //matgroves.com/ @Doormat23
* /
( function ( ) {
var root = this ;
/ * *
* @ author Mat Groves http : //matgroves.com/ @Doormat23
* /
/ * *
2014-11-15 20:04:24 +00:00
* The [ pixi . js ] ( http : //www.pixijs.com/) module/namespace.
*
2014-02-28 09:30:53 +00:00
* @ module PIXI
* /
2014-11-15 20:04:24 +00:00
/ * *
* Namespace - class for [ pixi . js ] ( http : //www.pixijs.com/).
*
* Contains assorted static properties and enumerations .
*
* @ class PIXI
* @ static
* /
2014-02-28 09:30:53 +00:00
var PIXI = PIXI || { } ;
2014-11-15 20:04:24 +00:00
/ * *
* @ property { Number } WEBGL _RENDERER
* @ protected
* @ static
* /
2014-02-28 09:30:53 +00:00
PIXI . WEBGL _RENDERER = 0 ;
2014-11-15 20:04:24 +00:00
/ * *
* @ property { Number } CANVAS _RENDERER
* @ protected
* @ static
* /
2014-02-28 09:30:53 +00:00
PIXI . CANVAS _RENDERER = 1 ;
2014-11-15 20:04:24 +00:00
/ * *
* Version of pixi that is loaded .
* @ property { String } VERSION
* @ static
* /
2014-11-12 22:49:36 +00:00
PIXI . VERSION = "v2.1.0" ;
2014-07-10 19:18:20 +00:00
2014-11-15 20:04:24 +00:00
/ * *
* Various blend modes supported by pixi .
* @ property { Object } blendModes
* @ property { Number } blendModes . NORMAL
* @ property { Number } blendModes . ADD
* @ property { Number } blendModes . MULTIPLY
* @ property { Number } blendModes . SCREEN
* @ property { Number } blendModes . OVERLAY
* @ property { Number } blendModes . DARKEN
* @ property { Number } blendModes . LIGHTEN
* @ property { Number } blendModes . COLOR _DODGE
* @ property { Number } blendModes . COLOR _BURN
* @ property { Number } blendModes . HARD _LIGHT
* @ property { Number } blendModes . SOFT _LIGHT
* @ property { Number } blendModes . DIFFERENCE
* @ property { Number } blendModes . EXCLUSION
* @ property { Number } blendModes . HUE
* @ property { Number } blendModes . SATURATION
* @ property { Number } blendModes . COLOR
* @ property { Number } blendModes . LUMINOSITY
* @ static
* /
2014-02-28 09:30:53 +00:00
PIXI . blendModes = {
NORMAL : 0 ,
ADD : 1 ,
MULTIPLY : 2 ,
SCREEN : 3 ,
OVERLAY : 4 ,
DARKEN : 5 ,
LIGHTEN : 6 ,
COLOR _DODGE : 7 ,
COLOR _BURN : 8 ,
HARD _LIGHT : 9 ,
SOFT _LIGHT : 10 ,
DIFFERENCE : 11 ,
EXCLUSION : 12 ,
HUE : 13 ,
SATURATION : 14 ,
COLOR : 15 ,
LUMINOSITY : 16
} ;
2014-11-15 20:04:24 +00:00
/ * *
* The scale modes that are supported by pixi .
*
* The DEFAULT scale mode affects the default scaling mode of future operations .
* It can be re - assigned to either LINEAR or NEAREST , depending upon suitability .
*
* @ property { Object } scaleModes
* @ property { Number } scaleModes . DEFAULT = LINEAR
* @ property { Number } scaleModes . LINEAR Smooth scaling
* @ property { Number } scaleModes . NEAREST Pixelating scaling
* @ static
* /
2014-02-28 09:30:53 +00:00
PIXI . scaleModes = {
DEFAULT : 0 ,
LINEAR : 0 ,
NEAREST : 1
} ;
2014-07-01 14:04:03 +00:00
// used to create uids for various pixi objects..
PIXI . _UID = 0 ;
2014-07-11 17:03:43 +00:00
if ( typeof ( Float32Array ) != 'undefined' )
{
PIXI . Float32Array = Float32Array ;
PIXI . Uint16Array = Uint16Array ;
}
else
{
PIXI . Float32Array = Array ;
PIXI . Uint16Array = Array ;
}
2014-07-01 14:04:03 +00:00
2014-04-01 02:02:36 +00:00
// interaction frequency
2014-02-28 09:30:53 +00:00
PIXI . INTERACTION _FREQUENCY = 30 ;
PIXI . AUTO _PREVENT _DEFAULT = true ;
2014-11-15 20:04:24 +00:00
/ * *
* @ property { Number } PI _2
* @ static
* /
2014-10-22 20:42:03 +00:00
PIXI . PI _2 = Math . PI * 2 ;
2014-11-15 20:04:24 +00:00
/ * *
* @ property { Number } RAD _TO _DEG
* @ static
* /
2014-02-28 09:30:53 +00:00
PIXI . RAD _TO _DEG = 180 / Math . PI ;
2014-11-15 20:04:24 +00:00
/ * *
* @ property { Number } DEG _TO _RAD
* @ static
* /
2014-02-28 09:30:53 +00:00
PIXI . DEG _TO _RAD = Math . PI / 180 ;
2014-07-01 14:04:03 +00:00
2014-11-15 20:04:24 +00:00
/ * *
* @ property { String } RETINA _PREFIX
* @ protected
* @ static
* /
2014-10-22 20:42:03 +00:00
PIXI . RETINA _PREFIX = "@2x" ;
//PIXI.SCALE_PREFIX "@x%%";
2014-07-10 15:23:26 +00:00
2014-11-15 20:04:24 +00:00
/ * *
* If true the default pixi startup ( console ) banner message will be suppressed .
*
* @ property { Boolean } dontSayHello
* @ default false
* @ static
* /
2014-07-10 15:23:26 +00:00
PIXI . dontSayHello = false ;
2014-11-15 20:04:24 +00:00
/ * *
* The default render options if none are supplied to
* { { # crossLink "WebGLRenderer" } } { { / c r o s s L i n k } } o r { { # c r o s s L i n k " C a n v a s R e n d e r e r " } } { { / c r o s s L i n k } } .
*
* @ property { Object } defaultRenderOptions
* @ property { Object } defaultRenderOptions . view = null
* @ property { Boolean } defaultRenderOptions . transparent = false
* @ property { Boolean } defaultRenderOptions . antialias = false
* @ property { Boolean } defaultRenderOptions . preserveDrawingBuffer = false
* @ property { Number } defaultRenderOptions . resolution = 1
* @ property { Boolean } defaultRenderOptions . clearBeforeRender = true
* @ property { Boolean } defaultRenderOptions . autoResize = false
* @ static
* /
2014-10-22 20:42:03 +00:00
PIXI . defaultRenderOptions = {
2014-11-15 20:04:24 +00:00
view : null ,
transparent : false ,
2014-10-22 20:42:03 +00:00
antialias : false ,
preserveDrawingBuffer : false ,
resolution : 1 ,
2014-11-12 22:49:36 +00:00
clearBeforeRender : true ,
autoResize : false
2014-10-22 20:42:03 +00:00
}
2014-07-10 15:23:26 +00:00
PIXI . sayHello = function ( type )
2014-07-01 14:04:03 +00:00
{
2014-07-10 15:23:26 +00:00
if ( PIXI . dontSayHello ) return ;
2014-07-01 14:04:03 +00:00
if ( navigator . userAgent . toLowerCase ( ) . indexOf ( 'chrome' ) > - 1 )
{
var args = [
2014-07-18 10:52:48 +00:00
'%c %c %c Pixi.js ' + PIXI . VERSION + ' - ' + type + ' %c ' + ' %c ' + ' http://www.pixijs.com/ %c %c ♥%c♥%c♥ ' ,
2014-07-10 15:23:26 +00:00
'background: #ff66a5' ,
'background: #ff66a5' ,
'color: #ff66a5; background: #030307;' ,
'background: #ff66a5' ,
'background: #ffc3dc' ,
'background: #ff66a5' ,
2014-07-01 14:04:03 +00:00
'color: #ff2424; background: #fff' ,
'color: #ff2424; background: #fff' ,
'color: #ff2424; background: #fff'
] ;
console . log . apply ( console , args ) ;
}
else if ( window [ 'console' ] )
{
2014-07-18 10:52:48 +00:00
console . log ( 'Pixi.js ' + PIXI . VERSION + ' - http://www.pixijs.com/' ) ;
2014-07-01 14:04:03 +00:00
}
2014-07-10 15:23:26 +00:00
PIXI . dontSayHello = true ;
2014-07-01 14:04:03 +00:00
} ;
2014-10-22 22:53:32 +00:00
/ * *
* @ author Adrien Brault < adrien . brault @ gmail . com >
* /
/ * *
* @ class Polygon
* @ constructor
2014-11-15 20:04:24 +00:00
* @ param points * { Array ( Point ) | Array ( Number ) | Point ... | Number ... } This can be an array of Points that form the polygon ,
2014-10-22 22:53:32 +00:00
* a flat array of numbers that will be interpreted as [ x , y , x , y , ... ] , or the arguments passed can be
* all the points of the polygon e . g . ` new PIXI.Polygon(new PIXI.Point(), new PIXI.Point(), ...) ` , or the
* arguments passed can be flat x , y values e . g . ` new PIXI.Polygon(x,y, x,y, x,y, ...) ` where ` x ` and ` y ` are
* Numbers .
* /
PIXI . Polygon = function ( points )
{
//if points isn't an array, use arguments as the array
if ( ! ( points instanceof Array ) ) points = Array . prototype . slice . call ( arguments ) ;
//if this is a flat array of numbers, convert it to points
if ( points [ 0 ] instanceof PIXI . Point )
{
var p = [ ] ;
for ( var i = 0 , il = points . length ; i < il ; i ++ )
{
p . push ( points [ i ] . x , points [ i ] . y ) ;
}
points = p ;
}
this . closed = true ;
this . points = points ;
} ;
/ * *
* Creates a clone of this polygon
*
* @ method clone
* @ return { Polygon } a copy of the polygon
* /
PIXI . Polygon . prototype . clone = function ( )
{
var points = this . points . slice ( ) ;
return new PIXI . Polygon ( points ) ;
} ;
/ * *
* Checks whether the x and y coordinates passed to this function are contained within this polygon
*
* @ method contains
* @ param x { Number } The X coordinate of the point to test
* @ param y { Number } The Y coordinate of the point to test
* @ return { Boolean } Whether the x / y coordinates are within this polygon
* /
PIXI . Polygon . prototype . contains = function ( x , y )
{
var inside = false ;
// use some raycasting to test hits
// https://github.com/substack/point-in-polygon/blob/master/index.js
var length = this . points . length / 2 ;
for ( var i = 0 , j = length - 1 ; i < length ; j = i ++ )
{
var xi = this . points [ i * 2 ] , yi = this . points [ i * 2 + 1 ] ,
xj = this . points [ j * 2 ] , yj = this . points [ j * 2 + 1 ] ,
intersect = ( ( yi > y ) !== ( yj > y ) ) && ( x < ( xj - xi ) * ( y - yi ) / ( yj - yi ) + xi ) ;
if ( intersect ) inside = ! inside ;
}
return inside ;
} ;
// constructor
PIXI . Polygon . prototype . constructor = PIXI . Polygon ;
2014-02-28 09:30:53 +00:00
/ * *
* @ author Mat Groves http : //matgroves.com/ @Doormat23
* /
2014-07-01 14:04:03 +00:00
/ * *
* The Matrix class is now an object , which makes it a lot faster ,
* here is a representation of it :
* | a | b | tx |
2014-07-10 19:18:20 +00:00
* | c | d | ty |
2014-07-01 14:04:03 +00:00
* | 0 | 0 | 1 |
*
* @ class Matrix
* @ constructor
* /
2014-02-28 09:30:53 +00:00
PIXI . Matrix = function ( )
{
2014-10-22 20:42:03 +00:00
/ * *
* @ property a
* @ type Number
* @ default 1
* /
2014-02-28 09:30:53 +00:00
this . a = 1 ;
2014-10-22 20:42:03 +00:00
/ * *
* @ property b
* @ type Number
* @ default 0
* /
2014-02-28 09:30:53 +00:00
this . b = 0 ;
2014-10-22 20:42:03 +00:00
/ * *
* @ property c
* @ type Number
* @ default 0
* /
2014-02-28 09:30:53 +00:00
this . c = 0 ;
2014-10-22 20:42:03 +00:00
/ * *
* @ property d
* @ type Number
* @ default 1
* /
2014-02-28 09:30:53 +00:00
this . d = 1 ;
2014-10-22 20:42:03 +00:00
/ * *
* @ property tx
* @ type Number
* @ default 0
* /
2014-02-28 09:30:53 +00:00
this . tx = 0 ;
2014-10-22 20:42:03 +00:00
/ * *
* @ property ty
* @ type Number
* @ default 0
* /
2014-02-28 09:30:53 +00:00
this . ty = 0 ;
} ;
/ * *
2014-10-22 20:42:03 +00:00
* Creates a Matrix object based on the given array . The Element to Matrix mapping order is as follows :
*
* a = array [ 0 ]
* b = array [ 1 ]
* c = array [ 3 ]
* d = array [ 4 ]
* tx = array [ 2 ]
* ty = array [ 5 ]
2014-02-28 09:30:53 +00:00
*
* @ method fromArray
2014-10-22 20:42:03 +00:00
* @ param array { Array } The array that the matrix will be populated from .
2014-02-28 09:30:53 +00:00
* /
PIXI . Matrix . prototype . fromArray = function ( array )
{
this . a = array [ 0 ] ;
this . b = array [ 1 ] ;
this . c = array [ 3 ] ;
this . d = array [ 4 ] ;
this . tx = array [ 2 ] ;
this . ty = array [ 5 ] ;
} ;
/ * *
2014-10-22 20:42:03 +00:00
* Creates an array from the current Matrix object .
2014-02-28 09:30:53 +00:00
*
* @ method toArray
* @ param transpose { Boolean } Whether we need to transpose the matrix or not
2014-07-01 14:04:03 +00:00
* @ return { Array } the newly created array which contains the matrix
2014-02-28 09:30:53 +00:00
* /
PIXI . Matrix . prototype . toArray = function ( transpose )
{
2014-10-22 20:42:03 +00:00
if ( ! this . array ) this . array = new PIXI . Float32Array ( 9 ) ;
2014-02-28 09:30:53 +00:00
var array = this . array ;
if ( transpose )
{
2014-07-01 14:04:03 +00:00
array [ 0 ] = this . a ;
2014-10-22 20:42:03 +00:00
array [ 1 ] = this . b ;
2014-07-01 14:04:03 +00:00
array [ 2 ] = 0 ;
2014-10-22 20:42:03 +00:00
array [ 3 ] = this . c ;
2014-07-01 14:04:03 +00:00
array [ 4 ] = this . d ;
array [ 5 ] = 0 ;
array [ 6 ] = this . tx ;
array [ 7 ] = this . ty ;
array [ 8 ] = 1 ;
2014-02-28 09:30:53 +00:00
}
else
{
2014-07-01 14:04:03 +00:00
array [ 0 ] = this . a ;
2014-10-22 20:42:03 +00:00
array [ 1 ] = this . c ;
2014-07-01 14:04:03 +00:00
array [ 2 ] = this . tx ;
2014-10-22 20:42:03 +00:00
array [ 3 ] = this . b ;
2014-07-01 14:04:03 +00:00
array [ 4 ] = this . d ;
array [ 5 ] = this . ty ;
array [ 6 ] = 0 ;
array [ 7 ] = 0 ;
array [ 8 ] = 1 ;
2014-02-28 09:30:53 +00:00
}
2014-07-01 14:04:03 +00:00
return array ;
2014-02-28 09:30:53 +00:00
} ;
2014-08-29 17:13:33 +00:00
/ * *
2014-10-22 20:42:03 +00:00
* Get a new position with the current transformation applied .
2014-08-29 17:13:33 +00:00
* Can be used to go from a child ' s coordinate space to the world coordinate space . ( e . g . rendering )
*
* @ method apply
* @ param pos { Point } The origin
* @ param [ newPos ] { Point } The point that the new position is assigned to ( allowed to be same as input )
2014-10-22 20:42:03 +00:00
* @ return { Point } The new point , transformed through this matrix
2014-08-29 17:13:33 +00:00
* /
PIXI . Matrix . prototype . apply = function ( pos , newPos )
{
newPos = newPos || new PIXI . Point ( ) ;
2014-11-08 19:26:34 +00:00
newPos . x = this . a * pos . x + this . c * pos . y + this . tx ;
newPos . y = this . b * pos . x + this . d * pos . y + this . ty ;
2014-08-29 17:13:33 +00:00
return newPos ;
} ;
/ * *
2014-10-22 20:42:03 +00:00
* Get a new position with the inverse of the current transformation applied .
2014-08-29 17:13:33 +00:00
* Can be used to go from the world coordinate space to a child ' s coordinate space . ( e . g . input )
*
2014-10-22 20:42:03 +00:00
* @ method applyInverse
2014-08-29 17:13:33 +00:00
* @ param pos { Point } The origin
* @ param [ newPos ] { Point } The point that the new position is assigned to ( allowed to be same as input )
2014-10-22 20:42:03 +00:00
* @ return { Point } The new point , inverse - transformed through this matrix
2014-08-29 17:13:33 +00:00
* /
PIXI . Matrix . prototype . applyInverse = function ( pos , newPos )
{
newPos = newPos || new PIXI . Point ( ) ;
2014-10-22 20:42:03 +00:00
var id = 1 / ( this . a * this . d + this . c * - this . b ) ;
newPos . x = this . d * id * pos . x + - this . c * id * pos . y + ( this . ty * this . c - this . tx * this . d ) * id ;
newPos . y = this . a * id * pos . y + - this . b * id * pos . x + ( - this . ty * this . a + this . tx * this . b ) * id ;
2014-08-29 17:13:33 +00:00
return newPos ;
} ;
2014-10-22 20:42:03 +00:00
/ * *
* Translates the matrix on the x and y .
*
* @ method translate
* @ param { Number } x
* @ param { Number } y
* @ return { Matrix } This matrix . Good for chaining method calls .
* * /
PIXI . Matrix . prototype . translate = function ( x , y )
{
this . tx += x ;
this . ty += y ;
return this ;
} ;
/ * *
* Applies a scale transformation to the matrix .
*
* @ method scale
* @ param { Number } x The amount to scale horizontally
* @ param { Number } y The amount to scale vertically
* @ return { Matrix } This matrix . Good for chaining method calls .
* * /
PIXI . Matrix . prototype . scale = function ( x , y )
{
this . a *= x ;
this . d *= y ;
this . c *= x ;
this . b *= y ;
this . tx *= x ;
this . ty *= y ;
return this ;
} ;
/ * *
* Applies a rotation transformation to the matrix .
* @ method rotate
* @ param { Number } angle The angle in radians .
* @ return { Matrix } This matrix . Good for chaining method calls .
* * /
PIXI . Matrix . prototype . rotate = function ( angle )
{
var cos = Math . cos ( angle ) ;
var sin = Math . sin ( angle ) ;
var a1 = this . a ;
var c1 = this . c ;
var tx1 = this . tx ;
2014-07-01 14:04:03 +00:00
2014-10-22 20:42:03 +00:00
this . a = a1 * cos - this . b * sin ;
this . b = a1 * sin + this . b * cos ;
this . c = c1 * cos - this . d * sin ;
this . d = c1 * sin + this . d * cos ;
this . tx = tx1 * cos - this . ty * sin ;
this . ty = tx1 * sin + this . ty * cos ;
return this ;
2014-07-01 14:04:03 +00:00
} ;
/ * *
2014-10-22 20:42:03 +00:00
* Appends the given Matrix to this Matrix .
*
* @ method append
* @ param { Matrix } matrix
* @ return { Matrix } This matrix . Good for chaining method calls .
* /
PIXI . Matrix . prototype . append = function ( matrix )
{
var a1 = this . a ;
var b1 = this . b ;
var c1 = this . c ;
var d1 = this . d ;
this . a = matrix . a * a1 + matrix . b * c1 ;
this . b = matrix . a * b1 + matrix . b * d1 ;
this . c = matrix . c * a1 + matrix . d * c1 ;
this . d = matrix . c * b1 + matrix . d * d1 ;
this . tx = matrix . tx * a1 + matrix . ty * c1 + this . tx ;
this . ty = matrix . tx * b1 + matrix . ty * d1 + this . ty ;
return this ;
} ;
/ * *
* Resets this Matix to an identity ( default ) matrix .
*
* @ method identity
* @ return { Matrix } This matrix . Good for chaining method calls .
2014-07-01 14:04:03 +00:00
* /
2014-10-22 20:42:03 +00:00
PIXI . Matrix . prototype . identity = function ( )
{
this . a = 1 ;
this . b = 0 ;
this . c = 0 ;
this . d = 1 ;
this . tx = 0 ;
this . ty = 0 ;
return this ;
} ;
PIXI . identityMatrix = new PIXI . Matrix ( ) ;
2014-07-01 14:04:03 +00:00
2014-11-12 22:49:36 +00:00
/ * *
* @ author Mat Groves http : //matgroves.com/
* /
/ * *
* the Rectangle object is an area defined by its position , as indicated by its top - left corner point ( x , y ) and by its width and its height .
*
* @ class Rectangle
* @ constructor
* @ param x { Number } The X coordinate of the upper - left corner of the rectangle
* @ param y { Number } The Y coordinate of the upper - left corner of the rectangle
* @ param width { Number } The overall width of this rectangle
* @ param height { Number } The overall height of this rectangle
* /
PIXI . Rectangle = function ( x , y , width , height )
{
/ * *
* @ property x
* @ type Number
* @ default 0
* /
this . x = x || 0 ;
/ * *
* @ property y
* @ type Number
* @ default 0
* /
this . y = y || 0 ;
/ * *
* @ property width
* @ type Number
* @ default 0
* /
this . width = width || 0 ;
/ * *
* @ property height
* @ type Number
* @ default 0
* /
this . height = height || 0 ;
} ;
/ * *
* Creates a clone of this Rectangle
*
* @ method clone
* @ return { Rectangle } a copy of the rectangle
* /
PIXI . Rectangle . prototype . clone = function ( )
{
return new PIXI . Rectangle ( this . x , this . y , this . width , this . height ) ;
} ;
/ * *
* Checks whether the x and y coordinates given are contained within this Rectangle
*
* @ method contains
* @ param x { Number } The X coordinate of the point to test
* @ param y { Number } The Y coordinate of the point to test
* @ return { Boolean } Whether the x / y coordinates are within this Rectangle
* /
PIXI . Rectangle . prototype . contains = function ( x , y )
{
if ( this . width <= 0 || this . height <= 0 )
return false ;
var x1 = this . x ;
if ( x >= x1 && x <= x1 + this . width )
{
var y1 = this . y ;
if ( y >= y1 && y <= y1 + this . height )
{
return true ;
}
}
return false ;
} ;
// constructor
PIXI . Rectangle . prototype . constructor = PIXI . Rectangle ;
PIXI . EmptyRectangle = new PIXI . Rectangle ( 0 , 0 , 0 , 0 ) ;
/ * *
* @ author Mat Groves http : //matgroves.com/
* /
/ * *
2014-11-15 20:04:24 +00:00
* The Rounded Rectangle object is an area defined by its position and has nice rounded corners , as indicated by its top - left corner point ( x , y ) and by its width and its height .
2014-11-12 22:49:36 +00:00
*
2014-11-15 20:04:24 +00:00
* @ class RoundedRectangle
2014-11-12 22:49:36 +00:00
* @ constructor
* @ param x { Number } The X coordinate of the upper - left corner of the rounded rectangle
* @ param y { Number } The Y coordinate of the upper - left corner of the rounded rectangle
* @ param width { Number } The overall width of this rounded rectangle
* @ param height { Number } The overall height of this rounded rectangle
* @ param radius { Number } The overall radius of this corners of this rounded rectangle
* /
PIXI . RoundedRectangle = function ( x , y , width , height , radius )
{
/ * *
* @ property x
* @ type Number
* @ default 0
* /
this . x = x || 0 ;
/ * *
* @ property y
* @ type Number
* @ default 0
* /
this . y = y || 0 ;
/ * *
* @ property width
* @ type Number
* @ default 0
* /
this . width = width || 0 ;
/ * *
* @ property height
* @ type Number
* @ default 0
* /
this . height = height || 0 ;
/ * *
* @ property radius
* @ type Number
* @ default 20
* /
this . radius = radius || 20 ;
} ;
/ * *
* Creates a clone of this Rounded Rectangle
*
* @ method clone
2014-11-15 20:04:24 +00:00
* @ return { RoundedRectangle } a copy of the rounded rectangle
2014-11-12 22:49:36 +00:00
* /
PIXI . RoundedRectangle . prototype . clone = function ( )
{
return new PIXI . RoundedRectangle ( this . x , this . y , this . width , this . height , this . radius ) ;
} ;
/ * *
* Checks whether the x and y coordinates given are contained within this Rounded Rectangle
*
* @ method contains
* @ param x { Number } The X coordinate of the point to test
* @ param y { Number } The Y coordinate of the point to test
* @ return { Boolean } Whether the x / y coordinates are within this Rounded Rectangle
* /
PIXI . RoundedRectangle . prototype . contains = function ( x , y )
{
if ( this . width <= 0 || this . height <= 0 )
return false ;
var x1 = this . x ;
if ( x >= x1 && x <= x1 + this . width )
{
var y1 = this . y ;
if ( y >= y1 && y <= y1 + this . height )
{
return true ;
}
}
return false ;
} ;
// constructor
PIXI . RoundedRectangle . prototype . constructor = PIXI . RoundedRectangle ;
2014-02-28 09:30:53 +00:00
/ * *
* @ author Mat Groves http : //matgroves.com/ @Doormat23
* /
/ * *
2014-08-29 17:13:33 +00:00
* The base class for all objects that are rendered on the screen .
2014-04-29 14:39:53 +00:00
* This is an abstract class and should not be used on its own rather it should be extended .
2014-02-28 09:30:53 +00:00
*
* @ class DisplayObject
* @ constructor
* /
PIXI . DisplayObject = function ( )
{
/ * *
* The coordinate of the object relative to the local coordinates of the parent .
*
* @ property position
* @ type Point
* /
this . position = new PIXI . Point ( ) ;
/ * *
* The scale factor of the object .
*
* @ property scale
* @ type Point
* /
this . scale = new PIXI . Point ( 1 , 1 ) ; //{x:1, y:1};
2014-11-08 19:11:28 +00:00
/ * *
* The transform callback is an optional callback that if set will be called at the end of the updateTransform method and sent two parameters :
* This Display Objects worldTransform matrix and its parents transform matrix . Both are PIXI . Matrix object types .
* The matrix are passed by reference and can be modified directly without needing to return them .
* This ability allows you to check any of the matrix values and perform actions such as clamping scale or limiting rotation , regardless of the parent transforms .
*
* @ property transformCallback
* @ type Function
* /
this . transformCallback = null ;
/ * *
* The context under which the transformCallback is invoked .
*
* @ property transformCallbackContext
* @ type Object
* /
this . transformCallbackContext = null ;
2014-02-28 09:30:53 +00:00
/ * *
* The pivot point of the displayObject that it rotates around
*
* @ property pivot
* @ type Point
* /
this . pivot = new PIXI . Point ( 0 , 0 ) ;
/ * *
* The rotation of the object in radians .
*
* @ property rotation
* @ type Number
* /
this . rotation = 0 ;
/ * *
* The opacity of the object .
*
* @ property alpha
* @ type Number
* /
this . alpha = 1 ;
/ * *
* The visibility of the object .
*
* @ property visible
* @ type Boolean
* /
this . visible = true ;
/ * *
* This is the defined area that will pick up mouse / touch events . It is null by default .
* Setting it is a neat way of optimising the hitTest function that the interactionManager will use ( as it will not need to hit test all the children )
*
* @ property hitArea
* @ type Rectangle | Circle | Ellipse | Polygon
* /
this . hitArea = null ;
/ * *
* This is used to indicate if the displayObject should display a mouse hand cursor on rollover
*
* @ property buttonMode
* @ type Boolean
* /
this . buttonMode = false ;
/ * *
* Can this object be rendered
*
* @ property renderable
* @ type Boolean
* /
this . renderable = false ;
/ * *
* [ read - only ] The display object container that contains this display object .
*
* @ property parent
* @ type DisplayObjectContainer
* @ readOnly
* /
this . parent = null ;
/ * *
* [ read - only ] The stage the display object is connected to , or undefined if it is not connected to the stage .
*
* @ property stage
* @ type Stage
* @ readOnly
* /
this . stage = null ;
/ * *
* [ read - only ] The multiplied alpha of the displayObject
*
* @ property worldAlpha
* @ type Number
* @ readOnly
* /
this . worldAlpha = 1 ;
/ * *
* [ read - only ] Whether or not the object is interactive , do not toggle directly ! use the ` interactive ` property
*
* @ property _interactive
* @ type Boolean
* @ readOnly
* @ private
* /
this . _interactive = false ;
/ * *
* This is the cursor that will be used when the mouse is over this object . To enable this the element must have interaction = true and buttonMode = true
2014-08-29 17:13:33 +00:00
*
2014-02-28 09:30:53 +00:00
* @ property defaultCursor
* @ type String
*
* /
this . defaultCursor = 'pointer' ;
/ * *
* [ read - only ] Current transform of the object based on world ( parent ) factors
*
* @ property worldTransform
2014-10-22 20:42:03 +00:00
* @ type Matrix
2014-02-28 09:30:53 +00:00
* @ readOnly
* @ private
* /
this . worldTransform = new PIXI . Matrix ( ) ;
/ * *
2014-10-22 20:42:03 +00:00
* cached sin rotation and cos rotation
2014-02-28 09:30:53 +00:00
*
2014-10-22 20:42:03 +00:00
* @ property _sr
* @ type Number
2014-02-28 09:30:53 +00:00
* @ private
* /
2014-10-22 20:42:03 +00:00
this . _sr = 0 ;
2014-02-28 09:30:53 +00:00
/ * *
2014-10-22 20:42:03 +00:00
* cached sin rotation and cos rotation
2014-02-28 09:30:53 +00:00
*
2014-10-22 20:42:03 +00:00
* @ property _cr
* @ type Number
2014-02-28 09:30:53 +00:00
* @ private
* /
this . _cr = 1 ;
/ * *
2014-04-01 02:02:36 +00:00
* The area the filter is applied to like the hitArea this is used as more of an optimisation
* rather than figuring out the dimensions of the displayObject each frame you can set this rectangle
2014-02-28 09:30:53 +00:00
*
* @ property filterArea
* @ type Rectangle
* /
2014-04-01 02:02:36 +00:00
this . filterArea = null ; //new PIXI.Rectangle(0,0,1,1);
2014-02-28 09:30:53 +00:00
/ * *
* The original , cached bounds of the object
*
* @ property _bounds
* @ type Rectangle
* @ private
* /
this . _bounds = new PIXI . Rectangle ( 0 , 0 , 1 , 1 ) ;
2014-10-22 20:42:03 +00:00
2014-02-28 09:30:53 +00:00
/ * *
* The most up - to - date bounds of the object
*
* @ property _currentBounds
* @ type Rectangle
* @ private
* /
this . _currentBounds = null ;
2014-10-22 20:42:03 +00:00
2014-02-28 09:30:53 +00:00
/ * *
* The original , cached mask of the object
*
* @ property _currentBounds
* @ type Rectangle
* @ private
* /
this . _mask = null ;
2014-10-22 20:42:03 +00:00
/ * *
* Cached internal flag .
*
* @ property _cacheAsBitmap
* @ type Boolean
* @ private
* /
2014-02-28 09:30:53 +00:00
this . _cacheAsBitmap = false ;
2014-10-22 20:42:03 +00:00
/ * *
* Cached internal flag .
*
* @ property _cacheIsDirty
* @ type Boolean
* @ private
* /
2014-02-28 09:30:53 +00:00
this . _cacheIsDirty = false ;
/ *
* MOUSE Callbacks
* /
2014-08-29 17:13:33 +00:00
/ * *
* A callback that is used when the users mouse rolls over the displayObject
* @ method mouseover
* @ param interactionData { InteractionData }
* /
/ * *
* A callback that is used when the users mouse leaves the displayObject
* @ method mouseout
* @ param interactionData { InteractionData }
* /
2014-02-28 09:30:53 +00:00
2014-08-29 17:13:33 +00:00
//Left button
2014-02-28 09:30:53 +00:00
/ * *
2014-08-29 17:13:33 +00:00
* A callback that is used when the users clicks on the displayObject with their mouse ' s left button
2014-02-28 09:30:53 +00:00
* @ method click
* @ param interactionData { InteractionData }
* /
/ * *
2014-08-29 17:13:33 +00:00
* A callback that is used when the user clicks the mouse ' s left button down over the sprite
2014-02-28 09:30:53 +00:00
* @ method mousedown
* @ param interactionData { InteractionData }
* /
/ * *
2014-08-29 17:13:33 +00:00
* A callback that is used when the user releases the mouse ' s left button that was over the displayObject
* for this callback to be fired , the mouse ' s left button must have been pressed down over the displayObject
2014-02-28 09:30:53 +00:00
* @ method mouseup
* @ param interactionData { InteractionData }
* /
/ * *
2014-08-29 17:13:33 +00:00
* A callback that is used when the user releases the mouse ' s left button that was over the displayObject but is no longer over the displayObject
* for this callback to be fired , the mouse ' s left button must have been pressed down over the displayObject
2014-02-28 09:30:53 +00:00
* @ method mouseupoutside
* @ param interactionData { InteractionData }
* /
2014-08-29 17:13:33 +00:00
//Right button
2014-02-28 09:30:53 +00:00
/ * *
2014-08-29 17:13:33 +00:00
* A callback that is used when the users clicks on the displayObject with their mouse ' s right button
* @ method rightclick
2014-02-28 09:30:53 +00:00
* @ param interactionData { InteractionData }
* /
/ * *
2014-08-29 17:13:33 +00:00
* A callback that is used when the user clicks the mouse ' s right button down over the sprite
* @ method rightdown
2014-02-28 09:30:53 +00:00
* @ param interactionData { InteractionData }
* /
2014-08-29 17:13:33 +00:00
/ * *
* A callback that is used when the user releases the mouse ' s right button that was over the displayObject
* for this callback to be fired the mouse ' s right button must have been pressed down over the displayObject
* @ method rightup
* @ param interactionData { InteractionData }
* /
/ * *
* A callback that is used when the user releases the mouse ' s right button that was over the displayObject but is no longer over the displayObject
* for this callback to be fired , the mouse ' s right button must have been pressed down over the displayObject
* @ method rightupoutside
* @ param interactionData { InteractionData }
* /
2014-02-28 09:30:53 +00:00
/ *
* TOUCH Callbacks
* /
/ * *
* A callback that is used when the users taps on the sprite with their finger
* basically a touch version of click
* @ method tap
* @ param interactionData { InteractionData }
* /
/ * *
* A callback that is used when the user touches over the displayObject
* @ method touchstart
* @ param interactionData { InteractionData }
* /
/ * *
* A callback that is used when the user releases a touch over the displayObject
* @ method touchend
* @ param interactionData { InteractionData }
* /
/ * *
* A callback that is used when the user releases the touch that was over the displayObject
* for this callback to be fired , The touch must have started over the sprite
* @ method touchendoutside
* @ param interactionData { InteractionData }
* /
} ;
// constructor
PIXI . DisplayObject . prototype . constructor = PIXI . DisplayObject ;
/ * *
* Indicates if the sprite will have touch and mouse interactivity . It is false by default
*
* @ property interactive
* @ type Boolean
* @ default false
* /
Object . defineProperty ( PIXI . DisplayObject . prototype , 'interactive' , {
get : function ( ) {
return this . _interactive ;
} ,
set : function ( value ) {
this . _interactive = value ;
// TODO more to be done here..
// need to sort out a re-crawl!
if ( this . stage ) this . stage . dirty = true ;
}
} ) ;
/ * *
2014-10-22 20:42:03 +00:00
* [ read - only ] Indicates if the sprite is globally visible .
2014-02-28 09:30:53 +00:00
*
* @ property worldVisible
* @ type Boolean
* /
Object . defineProperty ( PIXI . DisplayObject . prototype , 'worldVisible' , {
get : function ( ) {
var item = this ;
do
{
if ( ! item . visible ) return false ;
item = item . parent ;
}
while ( item ) ;
return true ;
}
} ) ;
/ * *
* Sets a mask for the displayObject . A mask is an object that limits the visibility of an object to the shape of the mask applied to it .
* In PIXI a regular mask must be a PIXI . Graphics object . This allows for much faster masking in canvas as it utilises shape clipping .
* To remove a mask , set this property to null .
*
* @ property mask
* @ type Graphics
* /
Object . defineProperty ( PIXI . DisplayObject . prototype , 'mask' , {
get : function ( ) {
return this . _mask ;
} ,
set : function ( value ) {
if ( this . _mask ) this . _mask . isMask = false ;
this . _mask = value ;
if ( this . _mask ) this . _mask . isMask = true ;
}
} ) ;
/ * *
* Sets the filters for the displayObject .
* * IMPORTANT : This is a webGL only feature and will be ignored by the canvas renderer .
* To remove filters simply set this property to 'null'
* @ property filters
2014-11-15 20:04:24 +00:00
* @ type Array ( Filter )
2014-02-28 09:30:53 +00:00
* /
Object . defineProperty ( PIXI . DisplayObject . prototype , 'filters' , {
2014-10-22 20:42:03 +00:00
2014-02-28 09:30:53 +00:00
get : function ( ) {
return this . _filters ;
} ,
2014-10-22 20:42:03 +00:00
2014-02-28 09:30:53 +00:00
set : function ( value ) {
if ( value )
{
// now put all the passes in one place..
var passes = [ ] ;
for ( var i = 0 ; i < value . length ; i ++ )
{
var filterPasses = value [ i ] . passes ;
for ( var j = 0 ; j < filterPasses . length ; j ++ )
{
passes . push ( filterPasses [ j ] ) ;
}
}
// TODO change this as it is legacy
this . _filterBlock = { target : this , filterPasses : passes } ;
}
this . _filters = value ;
}
} ) ;
2014-04-01 02:02:36 +00:00
/ * *
2014-10-22 20:42:03 +00:00
* Set if this display object is cached as a bitmap .
* This basically takes a snap shot of the display object as it is at that moment . It can provide a performance benefit for complex static displayObjects .
* To remove simply set this property to 'null'
2014-04-01 02:02:36 +00:00
* @ property cacheAsBitmap
* @ type Boolean
* /
2014-02-28 09:30:53 +00:00
Object . defineProperty ( PIXI . DisplayObject . prototype , 'cacheAsBitmap' , {
2014-10-22 20:42:03 +00:00
2014-02-28 09:30:53 +00:00
get : function ( ) {
return this . _cacheAsBitmap ;
} ,
2014-10-22 20:42:03 +00:00
2014-02-28 09:30:53 +00:00
set : function ( value ) {
if ( this . _cacheAsBitmap === value ) return ;
if ( value )
{
this . _generateCachedSprite ( ) ;
}
else
{
this . _destroyCachedSprite ( ) ;
}
this . _cacheAsBitmap = value ;
}
} ) ;
/ *
* Updates the object transform for rendering
*
* @ method updateTransform
* @ private
* /
PIXI . DisplayObject . prototype . updateTransform = function ( )
{
2014-10-22 20:42:03 +00:00
// create some matrix refs for easy access
var pt = this . parent . worldTransform ;
var wt = this . worldTransform ;
2014-07-10 19:18:20 +00:00
2014-10-22 20:42:03 +00:00
// temporary matrix variables
var a , b , c , d , tx , ty ;
2014-02-28 09:30:53 +00:00
2014-10-22 20:42:03 +00:00
// so if rotation is between 0 then we can simplify the multiplication process..
if ( this . rotation % PIXI . PI _2 )
{
// check to see if the rotation is the same as the previous render. This means we only need to use sin and cos when rotation actually changes
if ( this . rotation !== this . rotationCache )
{
this . rotationCache = this . rotation ;
this . _sr = Math . sin ( this . rotation ) ;
this . _cr = Math . cos ( this . rotation ) ;
}
// get the matrix values of the displayobject based on its transform properties..
a = this . _cr * this . scale . x ;
b = this . _sr * this . scale . x ;
c = - this . _sr * this . scale . y ;
d = this . _cr * this . scale . y ;
tx = this . position . x ;
ty = this . position . y ;
// check for pivot.. not often used so geared towards that fact!
if ( this . pivot . x || this . pivot . y )
{
tx -= this . pivot . x * a + this . pivot . y * c ;
ty -= this . pivot . x * b + this . pivot . y * d ;
}
2014-02-28 09:30:53 +00:00
2014-10-22 20:42:03 +00:00
// concat the parent matrix with the objects transform.
wt . a = a * pt . a + b * pt . c ;
wt . b = a * pt . b + b * pt . d ;
wt . c = c * pt . a + d * pt . c ;
wt . d = c * pt . b + d * pt . d ;
wt . tx = tx * pt . a + ty * pt . c + pt . tx ;
wt . ty = tx * pt . b + ty * pt . d + pt . ty ;
}
else
{
// lets do the fast version as we know there is no rotation..
a = this . scale . x ;
d = this . scale . y ;
2014-02-28 09:30:53 +00:00
2014-11-15 20:04:24 +00:00
tx = this . position . x - this . pivot . x * a ;
ty = this . position . y - this . pivot . y * d ;
2014-11-12 22:49:36 +00:00
wt . a = a * pt . a ;
wt . b = a * pt . b ;
wt . c = d * pt . c ;
wt . d = d * pt . d ;
2014-10-22 20:42:03 +00:00
wt . tx = tx * pt . a + ty * pt . c + pt . tx ;
wt . ty = tx * pt . b + ty * pt . d + pt . ty ;
}
2014-02-28 09:30:53 +00:00
2014-10-22 20:42:03 +00:00
// multiply the alphas..
2014-02-28 09:30:53 +00:00
this . worldAlpha = this . alpha * this . parent . worldAlpha ;
2014-11-08 19:11:28 +00:00
// Custom callback?
if ( this . transformCallback )
{
this . transformCallback . call ( this . transformCallbackContext , wt , pt ) ;
}
2014-02-28 09:30:53 +00:00
} ;
2014-11-12 22:49:36 +00:00
// performance increase to avoid using call.. (10x faster)
PIXI . DisplayObject . prototype . displayObjectUpdateTransform = PIXI . DisplayObject . prototype . updateTransform ;
2014-02-28 09:30:53 +00:00
/ * *
* Retrieves the bounds of the displayObject as a rectangle object
*
* @ method getBounds
2014-10-22 20:42:03 +00:00
* @ param matrix { Matrix }
2014-02-28 09:30:53 +00:00
* @ return { Rectangle } the rectangular bounding area
* /
2014-10-22 20:42:03 +00:00
PIXI . DisplayObject . prototype . getBounds = function ( matrix )
2014-02-28 09:30:53 +00:00
{
matrix = matrix ; //just to get passed js hinting (and preserve inheritance)
return PIXI . EmptyRectangle ;
} ;
/ * *
* Retrieves the local bounds of the displayObject as a rectangle object
*
* @ method getLocalBounds
* @ return { Rectangle } the rectangular bounding area
* /
PIXI . DisplayObject . prototype . getLocalBounds = function ( )
{
return this . getBounds ( PIXI . identityMatrix ) ; ///PIXI.EmptyRectangle();
} ;
/ * *
* Sets the object ' s stage reference , the stage this object is connected to
*
* @ method setStageReference
* @ param stage { Stage } the stage that the object will have as its current stage reference
* /
PIXI . DisplayObject . prototype . setStageReference = function ( stage )
{
this . stage = stage ;
if ( this . _interactive ) this . stage . dirty = true ;
} ;
2014-10-22 20:42:03 +00:00
/ * *
* Useful function that returns a texture of the displayObject object that can then be used to create sprites
* This can be quite useful if your displayObject is static / complicated and needs to be reused multiple times .
*
* @ method generateTexture
* @ param resolution { Number } The resolution of the texture being generated
2014-11-15 20:04:24 +00:00
* @ param scaleMode { Number } See { { # crossLink "PIXI/scaleModes:property" } } PIXI . scaleModes { { / c r o s s L i n k } } f o r p o s s i b l e v a l u e s
2014-10-22 20:42:03 +00:00
* @ param renderer { CanvasRenderer | WebGLRenderer } The renderer used to generate the texture .
* @ return { Texture } a texture of the graphics object
* /
PIXI . DisplayObject . prototype . generateTexture = function ( resolution , scaleMode , renderer )
2014-02-28 09:30:53 +00:00
{
var bounds = this . getLocalBounds ( ) ;
2014-10-22 20:42:03 +00:00
var renderTexture = new PIXI . RenderTexture ( bounds . width | 0 , bounds . height | 0 , renderer , scaleMode , resolution ) ;
2014-10-23 11:34:33 +00:00
PIXI . DisplayObject . _tempMatrix . tx = - bounds . x ;
PIXI . DisplayObject . _tempMatrix . ty = - bounds . y ;
renderTexture . render ( this , PIXI . DisplayObject . _tempMatrix ) ;
2014-02-28 09:30:53 +00:00
return renderTexture ;
} ;
2014-10-22 20:42:03 +00:00
/ * *
* Generates and updates the cached sprite for this object .
*
* @ method updateCache
* /
2014-02-28 09:30:53 +00:00
PIXI . DisplayObject . prototype . updateCache = function ( )
{
this . _generateCachedSprite ( ) ;
} ;
2014-08-29 17:13:33 +00:00
/ * *
* Calculates the global position of the display object
*
* @ method toGlobal
* @ param position { Point } The world origin to calculate from
* @ return { Point } A point object representing the position of this object
* /
2014-10-22 20:42:03 +00:00
PIXI . DisplayObject . prototype . toGlobal = function ( position )
2014-08-29 17:13:33 +00:00
{
2014-11-15 20:04:24 +00:00
// don't need to u[date the lot
this . displayObjectUpdateTransform ( ) ;
2014-10-22 20:42:03 +00:00
return this . worldTransform . apply ( position ) ;
2014-08-29 17:13:33 +00:00
} ;
/ * *
* Calculates the local position of the display object relative to another point
*
2014-10-22 20:42:03 +00:00
* @ method toLocal
2014-08-29 17:13:33 +00:00
* @ param position { Point } The world origin to calculate from
* @ param [ from ] { DisplayObject } The DisplayObject to calculate the global position from
* @ return { Point } A point object representing the position of this object
* /
2014-10-22 20:42:03 +00:00
PIXI . DisplayObject . prototype . toLocal = function ( position , from )
2014-08-29 17:13:33 +00:00
{
2014-11-15 20:04:24 +00:00
//
2014-08-29 17:13:33 +00:00
if ( from )
{
2014-10-22 20:42:03 +00:00
position = from . toGlobal ( position ) ;
2014-08-29 17:13:33 +00:00
}
2014-10-22 20:42:03 +00:00
2014-11-15 20:04:24 +00:00
// don't need to u[date the lot
this . displayObjectUpdateTransform ( ) ;
2014-10-22 20:42:03 +00:00
return this . worldTransform . applyInverse ( position ) ;
2014-08-29 17:13:33 +00:00
} ;
2014-10-22 20:42:03 +00:00
/ * *
* Internal method .
*
* @ method _renderCachedSprite
* @ param renderSession { Object } The render session
* @ private
* /
2014-02-28 09:30:53 +00:00
PIXI . DisplayObject . prototype . _renderCachedSprite = function ( renderSession )
{
2014-07-01 14:04:03 +00:00
this . _cachedSprite . worldAlpha = this . worldAlpha ;
2014-08-29 17:13:33 +00:00
2014-02-28 09:30:53 +00:00
if ( renderSession . gl )
{
PIXI . Sprite . prototype . _renderWebGL . call ( this . _cachedSprite , renderSession ) ;
}
else
{
PIXI . Sprite . prototype . _renderCanvas . call ( this . _cachedSprite , renderSession ) ;
}
} ;
2014-10-22 20:42:03 +00:00
/ * *
* Internal method .
*
* @ method _generateCachedSprite
* @ private
* /
PIXI . DisplayObject . prototype . _generateCachedSprite = function ( )
2014-02-28 09:30:53 +00:00
{
this . _cacheAsBitmap = false ;
var bounds = this . getLocalBounds ( ) ;
2014-08-29 17:13:33 +00:00
2014-02-28 09:30:53 +00:00
if ( ! this . _cachedSprite )
{
var renderTexture = new PIXI . RenderTexture ( bounds . width | 0 , bounds . height | 0 ) ; //, renderSession.renderer);
2014-08-29 17:13:33 +00:00
2014-02-28 09:30:53 +00:00
this . _cachedSprite = new PIXI . Sprite ( renderTexture ) ;
this . _cachedSprite . worldTransform = this . worldTransform ;
}
else
{
this . _cachedSprite . texture . resize ( bounds . width | 0 , bounds . height | 0 ) ;
}
//REMOVE filter!
var tempFilters = this . _filters ;
this . _filters = null ;
this . _cachedSprite . filters = tempFilters ;
2014-10-22 20:42:03 +00:00
PIXI . DisplayObject . _tempMatrix . tx = - bounds . x ;
PIXI . DisplayObject . _tempMatrix . ty = - bounds . y ;
2014-11-15 20:04:24 +00:00
this . _cachedSprite . texture . render ( this , PIXI . DisplayObject . _tempMatrix , true ) ;
2014-04-29 14:39:53 +00:00
this . _cachedSprite . anchor . x = - ( bounds . x / bounds . width ) ;
this . _cachedSprite . anchor . y = - ( bounds . y / bounds . height ) ;
2014-02-28 09:30:53 +00:00
this . _filters = tempFilters ;
this . _cacheAsBitmap = true ;
} ;
/ * *
2014-10-22 20:42:03 +00:00
* Destroys the cached sprite .
2014-02-28 09:30:53 +00:00
*
2014-10-22 20:42:03 +00:00
* @ method _destroyCachedSprite
2014-02-28 09:30:53 +00:00
* @ private
* /
PIXI . DisplayObject . prototype . _destroyCachedSprite = function ( )
{
if ( ! this . _cachedSprite ) return ;
this . _cachedSprite . texture . destroy ( true ) ;
2014-10-22 20:42:03 +00:00
2014-02-28 09:30:53 +00:00
// TODO could be object pooled!
this . _cachedSprite = null ;
} ;
2014-10-22 20:42:03 +00:00
/ * *
* Renders the object using the WebGL renderer
*
* @ method _renderWebGL
* @ param renderSession { RenderSession }
* @ private
* /
2014-02-28 09:30:53 +00:00
PIXI . DisplayObject . prototype . _renderWebGL = function ( renderSession )
{
// OVERWRITE;
// this line is just here to pass jshinting :)
renderSession = renderSession ;
} ;
/ * *
* Renders the object using the Canvas renderer
*
* @ method _renderCanvas
2014-08-29 17:13:33 +00:00
* @ param renderSession { RenderSession }
2014-02-28 09:30:53 +00:00
* @ private
* /
PIXI . DisplayObject . prototype . _renderCanvas = function ( renderSession )
{
// OVERWRITE;
// this line is just here to pass jshinting :)
renderSession = renderSession ;
} ;
2014-10-22 20:42:03 +00:00
PIXI . DisplayObject . _tempMatrix = new PIXI . Matrix ( ) ;
2014-02-28 09:30:53 +00:00
/ * *
* The position of the displayObject on the x axis relative to the local coordinates of the parent .
*
* @ property x
* @ type Number
* /
Object . defineProperty ( PIXI . DisplayObject . prototype , 'x' , {
get : function ( ) {
return this . position . x ;
} ,
set : function ( value ) {
this . position . x = value ;
}
} ) ;
/ * *
* The position of the displayObject on the y axis relative to the local coordinates of the parent .
*
* @ property y
* @ type Number
* /
Object . defineProperty ( PIXI . DisplayObject . prototype , 'y' , {
get : function ( ) {
return this . position . y ;
} ,
set : function ( value ) {
this . position . y = value ;
}
} ) ;
/ * *
* @ author Mat Groves http : //matgroves.com/ @Doormat23
* /
/ * *
* A DisplayObjectContainer represents a collection of display objects .
* It is the base class of all display objects that act as a container for other objects .
*
* @ class DisplayObjectContainer
* @ extends DisplayObject
* @ constructor
* /
PIXI . DisplayObjectContainer = function ( )
{
PIXI . DisplayObject . call ( this ) ;
/ * *
* [ read - only ] The array of children of this container .
*
* @ property children
2014-11-15 20:04:24 +00:00
* @ type Array ( DisplayObject )
2014-02-28 09:30:53 +00:00
* @ readOnly
* /
this . children = [ ] ;
2014-11-12 22:49:36 +00:00
// fast access to update transform..
2014-02-28 09:30:53 +00:00
} ;
// constructor
PIXI . DisplayObjectContainer . prototype = Object . create ( PIXI . DisplayObject . prototype ) ;
PIXI . DisplayObjectContainer . prototype . constructor = PIXI . DisplayObjectContainer ;
2014-11-12 22:49:36 +00:00
2014-02-28 09:30:53 +00:00
/ * *
* The width of the displayObjectContainer , setting this will actually modify the scale to achieve the value set
*
* @ property width
* @ type Number
* /
Object . defineProperty ( PIXI . DisplayObjectContainer . prototype , 'width' , {
get : function ( ) {
return this . scale . x * this . getLocalBounds ( ) . width ;
} ,
set : function ( value ) {
2014-07-18 10:52:48 +00:00
var width = this . getLocalBounds ( ) . width ;
if ( width !== 0 )
{
2014-11-12 22:49:36 +00:00
this . scale . x = value / width ;
2014-07-18 10:52:48 +00:00
}
else
{
this . scale . x = 1 ;
}
2014-02-28 09:30:53 +00:00
this . _width = value ;
}
} ) ;
2014-07-01 14:04:03 +00:00
2014-02-28 09:30:53 +00:00
/ * *
* The height of the displayObjectContainer , setting this will actually modify the scale to achieve the value set
*
* @ property height
* @ type Number
* /
Object . defineProperty ( PIXI . DisplayObjectContainer . prototype , 'height' , {
get : function ( ) {
return this . scale . y * this . getLocalBounds ( ) . height ;
} ,
set : function ( value ) {
2014-07-18 10:52:48 +00:00
var height = this . getLocalBounds ( ) . height ;
if ( height !== 0 )
{
2014-11-12 22:49:36 +00:00
this . scale . y = value / height ;
2014-07-18 10:52:48 +00:00
}
else
{
this . scale . y = 1 ;
}
2014-02-28 09:30:53 +00:00
this . _height = value ;
}
} ) ;
2014-07-01 14:04:03 +00:00
2014-02-28 09:30:53 +00:00
/ * *
* Adds a child to the container .
*
* @ method addChild
* @ param child { DisplayObject } The DisplayObject to add to the container
2014-10-22 20:42:03 +00:00
* @ return { DisplayObject } The child that was added .
2014-02-28 09:30:53 +00:00
* /
PIXI . DisplayObjectContainer . prototype . addChild = function ( child )
{
2014-07-10 15:23:26 +00:00
return this . addChildAt ( child , this . children . length ) ;
2014-02-28 09:30:53 +00:00
} ;
/ * *
* Adds a child to the container at a specified index . If the index is out of bounds an error will be thrown
*
* @ method addChildAt
* @ param child { DisplayObject } The child to add
* @ param index { Number } The index to place the child in
2014-10-22 20:42:03 +00:00
* @ return { DisplayObject } The child that was added .
2014-02-28 09:30:53 +00:00
* /
PIXI . DisplayObjectContainer . prototype . addChildAt = function ( child , index )
{
if ( index >= 0 && index <= this . children . length )
{
if ( child . parent )
{
child . parent . removeChild ( child ) ;
}
child . parent = this ;
this . children . splice ( index , 0 , child ) ;
if ( this . stage ) child . setStageReference ( this . stage ) ;
2014-07-10 15:23:26 +00:00
return child ;
2014-02-28 09:30:53 +00:00
}
else
{
2014-10-22 20:42:03 +00:00
throw new Error ( child + 'addChildAt: The index ' + index + ' supplied is out of bounds ' + this . children . length ) ;
2014-02-28 09:30:53 +00:00
}
} ;
/ * *
2014-10-22 20:42:03 +00:00
* Swaps the position of 2 Display Objects within this container .
2014-02-28 09:30:53 +00:00
*
* @ method swapChildren
* @ param child { DisplayObject }
* @ param child2 { DisplayObject }
* /
PIXI . DisplayObjectContainer . prototype . swapChildren = function ( child , child2 )
{
if ( child === child2 ) {
return ;
}
2014-10-22 20:42:03 +00:00
var index1 = this . getChildIndex ( child ) ;
var index2 = this . getChildIndex ( child2 ) ;
2014-02-28 09:30:53 +00:00
if ( index1 < 0 || index2 < 0 ) {
throw new Error ( 'swapChildren: Both the supplied DisplayObjects must be a child of the caller.' ) ;
}
this . children [ index1 ] = child2 ;
this . children [ index2 ] = child ;
2014-10-22 20:42:03 +00:00
} ;
/ * *
* Returns the index position of a child DisplayObject instance
*
* @ method getChildIndex
* @ param child { DisplayObject } The DisplayObject instance to identify
* @ return { Number } The index position of the child display object to identify
* /
PIXI . DisplayObjectContainer . prototype . getChildIndex = function ( child )
{
var index = this . children . indexOf ( child ) ;
if ( index === - 1 )
{
throw new Error ( 'The supplied DisplayObject must be a child of the caller' ) ;
}
return index ;
} ;
/ * *
* Changes the position of an existing child in the display object container
*
* @ method setChildIndex
* @ param child { DisplayObject } The child DisplayObject instance for which you want to change the index number
* @ param index { Number } The resulting index number for the child display object
* /
PIXI . DisplayObjectContainer . prototype . setChildIndex = function ( child , index )
{
if ( index < 0 || index >= this . children . length )
{
throw new Error ( 'The supplied index is out of bounds' ) ;
}
var currentIndex = this . getChildIndex ( child ) ;
this . children . splice ( currentIndex , 1 ) ; //remove from old position
this . children . splice ( index , 0 , child ) ; //add at new position
2014-02-28 09:30:53 +00:00
} ;
/ * *
* Returns the child at the specified index
*
* @ method getChildAt
* @ param index { Number } The index to get the child from
2014-10-22 20:42:03 +00:00
* @ return { DisplayObject } The child at the given index , if any .
2014-02-28 09:30:53 +00:00
* /
PIXI . DisplayObjectContainer . prototype . getChildAt = function ( index )
{
2014-10-22 20:42:03 +00:00
if ( index < 0 || index >= this . children . length )
2014-02-28 09:30:53 +00:00
{
2014-10-22 20:42:03 +00:00
throw new Error ( 'getChildAt: Supplied index ' + index + ' does not exist in the child list, or the supplied DisplayObject must be a child of the caller' ) ;
2014-02-28 09:30:53 +00:00
}
2014-10-22 20:42:03 +00:00
return this . children [ index ] ;
2014-02-28 09:30:53 +00:00
} ;
/ * *
* Removes a child from the container .
*
* @ method removeChild
* @ param child { DisplayObject } The DisplayObject to remove
2014-10-22 20:42:03 +00:00
* @ return { DisplayObject } The child that was removed .
2014-02-28 09:30:53 +00:00
* /
PIXI . DisplayObjectContainer . prototype . removeChild = function ( child )
{
2014-10-22 20:42:03 +00:00
var index = this . children . indexOf ( child ) ;
if ( index === - 1 ) return ;
return this . removeChildAt ( index ) ;
2014-02-28 09:30:53 +00:00
} ;
2014-04-01 02:02:36 +00:00
/ * *
2014-10-22 20:42:03 +00:00
* Removes a child from the specified index position .
2014-04-01 02:02:36 +00:00
*
* @ method removeChildAt
* @ param index { Number } The index to get the child from
2014-10-22 20:42:03 +00:00
* @ return { DisplayObject } The child that was removed .
2014-04-01 02:02:36 +00:00
* /
PIXI . DisplayObjectContainer . prototype . removeChildAt = function ( index )
{
var child = this . getChildAt ( index ) ;
if ( this . stage )
child . removeStageReference ( ) ;
child . parent = undefined ;
this . children . splice ( index , 1 ) ;
return child ;
} ;
2014-02-28 09:30:53 +00:00
/ * *
2014-10-22 20:42:03 +00:00
* Removes all children from this container that are within the begin and end indexes .
2014-02-28 09:30:53 +00:00
*
2014-04-01 02:02:36 +00:00
* @ method removeChildren
2014-10-22 20:42:03 +00:00
* @ param beginIndex { Number } The beginning position . Default value is 0.
* @ param endIndex { Number } The ending position . Default value is size of the container .
2014-02-28 09:30:53 +00:00
* /
2014-04-01 02:02:36 +00:00
PIXI . DisplayObjectContainer . prototype . removeChildren = function ( beginIndex , endIndex )
2014-02-28 09:30:53 +00:00
{
2014-04-01 02:02:36 +00:00
var begin = beginIndex || 0 ;
var end = typeof endIndex === 'number' ? endIndex : this . children . length ;
var range = end - begin ;
2014-02-28 09:30:53 +00:00
2014-04-01 02:02:36 +00:00
if ( range > 0 && range <= end )
2014-02-28 09:30:53 +00:00
{
2014-04-01 02:02:36 +00:00
var removed = this . children . splice ( begin , range ) ;
for ( var i = 0 ; i < removed . length ; i ++ ) {
var child = removed [ i ] ;
if ( this . stage )
child . removeStageReference ( ) ;
child . parent = undefined ;
}
return removed ;
}
2014-08-29 17:13:33 +00:00
else if ( range === 0 && this . children . length === 0 )
{
return [ ] ;
}
2014-04-01 02:02:36 +00:00
else
{
2014-10-22 20:42:03 +00:00
throw new Error ( 'removeChildren: Range Error, numeric values are outside the acceptable range' ) ;
2014-02-28 09:30:53 +00:00
}
} ;
2014-04-01 02:02:36 +00:00
2014-02-28 09:30:53 +00:00
/ *
2014-10-22 20:42:03 +00:00
* Updates the transform on all children of this container for rendering
2014-02-28 09:30:53 +00:00
*
* @ method updateTransform
* @ private
* /
PIXI . DisplayObjectContainer . prototype . updateTransform = function ( )
{
if ( ! this . visible ) return ;
2014-11-12 22:49:36 +00:00
this . displayObjectUpdateTransform ( ) ;
//PIXI.DisplayObject.prototype.updateTransform.call( this );
2014-02-28 09:30:53 +00:00
if ( this . _cacheAsBitmap ) return ;
for ( var i = 0 , j = this . children . length ; i < j ; i ++ )
{
this . children [ i ] . updateTransform ( ) ;
}
} ;
2014-11-12 22:49:36 +00:00
// performance increase to avoid using call.. (10x faster)
PIXI . DisplayObjectContainer . prototype . displayObjectContainerUpdateTransform = PIXI . DisplayObjectContainer . prototype . updateTransform ;
2014-02-28 09:30:53 +00:00
/ * *
2014-10-22 20:42:03 +00:00
* Retrieves the bounds of the displayObjectContainer as a rectangle . The bounds calculation takes all visible children into consideration .
2014-02-28 09:30:53 +00:00
*
* @ method getBounds
2014-10-22 20:42:03 +00:00
* @ return { Rectangle } The rectangular bounding area
2014-02-28 09:30:53 +00:00
* /
2014-10-22 20:42:03 +00:00
PIXI . DisplayObjectContainer . prototype . getBounds = function ( )
2014-02-28 09:30:53 +00:00
{
if ( this . children . length === 0 ) return PIXI . EmptyRectangle ;
// TODO the bounds have already been calculated this render session so return what we have
var minX = Infinity ;
var minY = Infinity ;
var maxX = - Infinity ;
var maxY = - Infinity ;
var childBounds ;
var childMaxX ;
var childMaxY ;
var childVisible = false ;
for ( var i = 0 , j = this . children . length ; i < j ; i ++ )
{
var child = this . children [ i ] ;
2014-04-01 02:02:36 +00:00
2014-02-28 09:30:53 +00:00
if ( ! child . visible ) continue ;
childVisible = true ;
2014-10-22 20:42:03 +00:00
childBounds = this . children [ i ] . getBounds ( ) ;
2014-04-01 02:02:36 +00:00
2014-02-28 09:30:53 +00:00
minX = minX < childBounds . x ? minX : childBounds . x ;
minY = minY < childBounds . y ? minY : childBounds . y ;
childMaxX = childBounds . width + childBounds . x ;
childMaxY = childBounds . height + childBounds . y ;
maxX = maxX > childMaxX ? maxX : childMaxX ;
maxY = maxY > childMaxY ? maxY : childMaxY ;
}
if ( ! childVisible )
return PIXI . EmptyRectangle ;
var bounds = this . _bounds ;
bounds . x = minX ;
bounds . y = minY ;
bounds . width = maxX - minX ;
bounds . height = maxY - minY ;
// TODO: store a reference so that if this function gets called again in the render cycle we do not have to recalculate
//this._currentBounds = bounds;
2014-04-01 02:02:36 +00:00
2014-02-28 09:30:53 +00:00
return bounds ;
} ;
2014-10-22 20:42:03 +00:00
/ * *
* Retrieves the non - global local bounds of the displayObjectContainer as a rectangle . The calculation takes all visible children into consideration .
*
* @ method getLocalBounds
* @ return { Rectangle } The rectangular bounding area
* /
2014-02-28 09:30:53 +00:00
PIXI . DisplayObjectContainer . prototype . getLocalBounds = function ( )
{
var matrixCache = this . worldTransform ;
this . worldTransform = PIXI . identityMatrix ;
for ( var i = 0 , j = this . children . length ; i < j ; i ++ )
{
this . children [ i ] . updateTransform ( ) ;
}
var bounds = this . getBounds ( ) ;
this . worldTransform = matrixCache ;
return bounds ;
} ;
/ * *
2014-10-22 20:42:03 +00:00
* Sets the containers Stage reference . This is the Stage that this object , and all of its children , is connected to .
2014-02-28 09:30:53 +00:00
*
* @ method setStageReference
* @ param stage { Stage } the stage that the container will have as its current stage reference
* /
PIXI . DisplayObjectContainer . prototype . setStageReference = function ( stage )
{
this . stage = stage ;
if ( this . _interactive ) this . stage . dirty = true ;
for ( var i = 0 , j = this . children . length ; i < j ; i ++ )
{
var child = this . children [ i ] ;
child . setStageReference ( stage ) ;
}
} ;
/ * *
2014-10-22 20:42:03 +00:00
* Removes the current stage reference from the container and all of its children .
2014-02-28 09:30:53 +00:00
*
* @ method removeStageReference
* /
PIXI . DisplayObjectContainer . prototype . removeStageReference = function ( )
{
for ( var i = 0 , j = this . children . length ; i < j ; i ++ )
{
var child = this . children [ i ] ;
child . removeStageReference ( ) ;
}
if ( this . _interactive ) this . stage . dirty = true ;
2014-04-01 02:02:36 +00:00
2014-02-28 09:30:53 +00:00
this . stage = null ;
} ;
/ * *
* Renders the object using the WebGL renderer
*
* @ method _renderWebGL
2014-04-01 02:02:36 +00:00
* @ param renderSession { RenderSession }
2014-02-28 09:30:53 +00:00
* @ private
* /
PIXI . DisplayObjectContainer . prototype . _renderWebGL = function ( renderSession )
{
if ( ! this . visible || this . alpha <= 0 ) return ;
2014-04-01 02:02:36 +00:00
2014-02-28 09:30:53 +00:00
if ( this . _cacheAsBitmap )
{
this . _renderCachedSprite ( renderSession ) ;
return ;
}
2014-04-01 02:02:36 +00:00
2014-02-28 09:30:53 +00:00
var i , j ;
if ( this . _mask || this . _filters )
{
2014-07-01 14:04:03 +00:00
// push filter first as we need to ensure the stencil buffer is correct for any masking
if ( this . _filters )
{
renderSession . spriteBatch . flush ( ) ;
renderSession . filterManager . pushFilter ( this . _filterBlock ) ;
}
2014-02-28 09:30:53 +00:00
if ( this . _mask )
{
renderSession . spriteBatch . stop ( ) ;
renderSession . maskManager . pushMask ( this . mask , renderSession ) ;
renderSession . spriteBatch . start ( ) ;
}
// simple render children!
for ( i = 0 , j = this . children . length ; i < j ; i ++ )
{
this . children [ i ] . _renderWebGL ( renderSession ) ;
}
renderSession . spriteBatch . stop ( ) ;
2014-07-01 14:04:03 +00:00
if ( this . _mask ) renderSession . maskManager . popMask ( this . _mask , renderSession ) ;
2014-02-28 09:30:53 +00:00
if ( this . _filters ) renderSession . filterManager . popFilter ( ) ;
2014-04-01 02:02:36 +00:00
2014-02-28 09:30:53 +00:00
renderSession . spriteBatch . start ( ) ;
}
else
{
// simple render children!
for ( i = 0 , j = this . children . length ; i < j ; i ++ )
{
this . children [ i ] . _renderWebGL ( renderSession ) ;
}
}
} ;
/ * *
* Renders the object using the Canvas renderer
*
* @ method _renderCanvas
2014-04-01 02:02:36 +00:00
* @ param renderSession { RenderSession }
2014-02-28 09:30:53 +00:00
* @ private
* /
PIXI . DisplayObjectContainer . prototype . _renderCanvas = function ( renderSession )
{
if ( this . visible === false || this . alpha === 0 ) return ;
if ( this . _cacheAsBitmap )
{
this . _renderCachedSprite ( renderSession ) ;
return ;
}
if ( this . _mask )
{
2014-10-22 20:42:03 +00:00
renderSession . maskManager . pushMask ( this . _mask , renderSession ) ;
2014-02-28 09:30:53 +00:00
}
for ( var i = 0 , j = this . children . length ; i < j ; i ++ )
{
var child = this . children [ i ] ;
child . _renderCanvas ( renderSession ) ;
}
if ( this . _mask )
{
2014-10-22 20:42:03 +00:00
renderSession . maskManager . popMask ( renderSession ) ;
2014-02-28 09:30:53 +00:00
}
} ;
/ * *
* @ author Mat Groves http : //matgroves.com/ @Doormat23
* /
/ * *
* The Sprite object is the base for all textured objects that are rendered to the screen
*
* @ class Sprite
* @ extends DisplayObjectContainer
* @ constructor
* @ param texture { Texture } The texture for this sprite
2014-11-08 19:26:34 +00:00
*
* A sprite can be created directly from an image like this :
2014-07-01 14:04:03 +00:00
* var sprite = new PIXI . Sprite . fromImage ( 'assets/image.png' ) ;
2014-02-28 09:30:53 +00:00
* yourStage . addChild ( sprite ) ;
* then obviously don ' t forget to add it to the stage you have already created
* /
PIXI . Sprite = function ( texture )
{
PIXI . DisplayObjectContainer . call ( this ) ;
/ * *
* The anchor sets the origin point of the texture .
* The default is 0 , 0 this means the texture ' s origin is the top left
2014-10-22 20:42:03 +00:00
* Setting than anchor to 0.5 , 0.5 means the textures origin is centered
2014-02-28 09:30:53 +00:00
* Setting the anchor to 1 , 1 would mean the textures origin points will be the bottom right corner
*
* @ property anchor
* @ type Point
* /
this . anchor = new PIXI . Point ( ) ;
/ * *
* The texture that the sprite is using
*
* @ property texture
* @ type Texture
* /
this . texture = texture ;
/ * *
* The width of the sprite ( this is initially set by the texture )
*
* @ property _width
* @ type Number
* @ private
* /
this . _width = 0 ;
/ * *
* The height of the sprite ( this is initially set by the texture )
*
* @ property _height
* @ type Number
* @ private
* /
this . _height = 0 ;
/ * *
2014-10-22 20:42:03 +00:00
* The tint applied to the sprite . This is a hex value . A value of 0xFFFFFF will remove any tint effect .
2014-02-28 09:30:53 +00:00
*
* @ property tint
* @ type Number
* @ default 0xFFFFFF
* /
2014-10-22 20:42:03 +00:00
this . tint = 0xFFFFFF ;
2014-11-08 19:26:34 +00:00
2014-02-28 09:30:53 +00:00
/ * *
2014-10-22 20:42:03 +00:00
* The blend mode to be applied to the sprite . Set to PIXI . blendModes . NORMAL to remove any blend mode .
2014-02-28 09:30:53 +00:00
*
* @ property blendMode
* @ type Number
* @ default PIXI . blendModes . NORMAL ;
* /
this . blendMode = PIXI . blendModes . NORMAL ;
2014-10-22 20:42:03 +00:00
/ * *
* The shader that will be used to render the texture to the stage . Set to null to remove a current shader .
*
* @ property shader
2014-11-15 20:04:24 +00:00
* @ type AbstractFilter
2014-10-22 20:42:03 +00:00
* @ default null
* /
this . shader = null ;
2014-02-28 09:30:53 +00:00
if ( texture . baseTexture . hasLoaded )
{
this . onTextureUpdate ( ) ;
}
else
{
2014-11-08 19:26:34 +00:00
this . texture . on ( 'update' , this . onTextureUpdate . bind ( this ) ) ;
2014-02-28 09:30:53 +00:00
}
this . renderable = true ;
2014-10-22 20:42:03 +00:00
2014-02-28 09:30:53 +00:00
} ;
// constructor
PIXI . Sprite . prototype = Object . create ( PIXI . DisplayObjectContainer . prototype ) ;
PIXI . Sprite . prototype . constructor = PIXI . Sprite ;
/ * *
* The width of the sprite , setting this will actually modify the scale to achieve the value set
*
* @ property width
* @ type Number
* /
Object . defineProperty ( PIXI . Sprite . prototype , 'width' , {
get : function ( ) {
return this . scale . x * this . texture . frame . width ;
} ,
set : function ( value ) {
this . scale . x = value / this . texture . frame . width ;
this . _width = value ;
}
} ) ;
/ * *
* The height of the sprite , setting this will actually modify the scale to achieve the value set
*
* @ property height
* @ type Number
* /
Object . defineProperty ( PIXI . Sprite . prototype , 'height' , {
get : function ( ) {
return this . scale . y * this . texture . frame . height ;
} ,
set : function ( value ) {
this . scale . y = value / this . texture . frame . height ;
this . _height = value ;
}
} ) ;
/ * *
* Sets the texture of the sprite
*
* @ method setTexture
* @ param texture { Texture } The PIXI texture that is displayed by the sprite
* /
PIXI . Sprite . prototype . setTexture = function ( texture )
{
2014-07-16 00:58:24 +00:00
this . texture = texture ;
2014-02-28 09:30:53 +00:00
this . cachedTint = 0xFFFFFF ;
} ;
/ * *
* When the texture is updated , this event will fire to update the scale and frame
*
* @ method onTextureUpdate
* @ param event
* @ private
* /
PIXI . Sprite . prototype . onTextureUpdate = function ( )
{
// so if _width is 0 then width was not set..
if ( this . _width ) this . scale . x = this . _width / this . texture . frame . width ;
if ( this . _height ) this . scale . y = this . _height / this . texture . frame . height ;
2014-07-10 15:23:26 +00:00
//this.updateFrame = true;
2014-02-28 09:30:53 +00:00
} ;
/ * *
2014-10-22 20:42:03 +00:00
* Returns the bounds of the Sprite as a rectangle . The bounds calculation takes the worldTransform into account .
2014-02-28 09:30:53 +00:00
*
* @ method getBounds
* @ param matrix { Matrix } the transformation matrix of the sprite
* @ return { Rectangle } the framing rectangle
* /
PIXI . Sprite . prototype . getBounds = function ( matrix )
{
var width = this . texture . frame . width ;
var height = this . texture . frame . height ;
var w0 = width * ( 1 - this . anchor . x ) ;
var w1 = width * - this . anchor . x ;
var h0 = height * ( 1 - this . anchor . y ) ;
var h1 = height * - this . anchor . y ;
var worldTransform = matrix || this . worldTransform ;
var a = worldTransform . a ;
2014-11-11 14:31:31 +00:00
var b = worldTransform . b ;
var c = worldTransform . c ;
2014-02-28 09:30:53 +00:00
var d = worldTransform . d ;
var tx = worldTransform . tx ;
var ty = worldTransform . ty ;
var maxX = - Infinity ;
var maxY = - Infinity ;
var minX = Infinity ;
var minY = Infinity ;
2014-11-17 13:08:53 +00:00
if ( b === 0 && c === 0 )
{
// scale may be negative!
if ( a < 0 ) a *= - 1 ;
if ( d < 0 ) d *= - 1 ;
// this means there is no rotation going on right? RIGHT?
// if thats the case then we can avoid checking the bound values! yay
minX = a * w1 + tx ;
maxX = a * w0 + tx ;
minY = d * h1 + ty ;
maxY = d * h0 + ty ;
}
else
{
var x1 = a * w1 + c * h1 + tx ;
var y1 = d * h1 + b * w1 + ty ;
var x2 = a * w0 + c * h1 + tx ;
var y2 = d * h1 + b * w0 + ty ;
var x3 = a * w0 + c * h0 + tx ;
var y3 = d * h0 + b * w0 + ty ;
var x4 = a * w1 + c * h0 + tx ;
var y4 = d * h0 + b * w1 + ty ;
maxX = - Infinity ;
maxY = - Infinity ;
minX = Infinity ;
minY = Infinity ;
minX = x1 < minX ? x1 : minX ;
minX = x2 < minX ? x2 : minX ;
minX = x3 < minX ? x3 : minX ;
minX = x4 < minX ? x4 : minX ;
minY = y1 < minY ? y1 : minY ;
minY = y2 < minY ? y2 : minY ;
minY = y3 < minY ? y3 : minY ;
minY = y4 < minY ? y4 : minY ;
maxX = x1 > maxX ? x1 : maxX ;
maxX = x2 > maxX ? x2 : maxX ;
maxX = x3 > maxX ? x3 : maxX ;
maxX = x4 > maxX ? x4 : maxX ;
maxY = y1 > maxY ? y1 : maxY ;
maxY = y2 > maxY ? y2 : maxY ;
maxY = y3 > maxY ? y3 : maxY ;
maxY = y4 > maxY ? y4 : maxY ;
}
2014-02-28 09:30:53 +00:00
var bounds = this . _bounds ;
bounds . x = minX ;
bounds . width = maxX - minX ;
bounds . y = minY ;
bounds . height = maxY - minY ;
// store a reference so that if this function gets called again in the render cycle we do not have to recalculate
this . _currentBounds = bounds ;
return bounds ;
} ;
/ * *
* Renders the object using the WebGL renderer
*
* @ method _renderWebGL
2014-11-08 19:26:34 +00:00
* @ param renderSession { RenderSession }
2014-02-28 09:30:53 +00:00
* @ private
* /
PIXI . Sprite . prototype . _renderWebGL = function ( renderSession )
{
// if the sprite is not visible or the alpha is 0 then no need to render this element
if ( ! this . visible || this . alpha <= 0 ) return ;
2014-11-08 19:26:34 +00:00
2014-02-28 09:30:53 +00:00
var i , j ;
// do a quick check to see if this element has a mask or a filter.
if ( this . _mask || this . _filters )
{
var spriteBatch = renderSession . spriteBatch ;
2014-07-01 14:04:03 +00:00
// push filter first as we need to ensure the stencil buffer is correct for any masking
if ( this . _filters )
{
spriteBatch . flush ( ) ;
renderSession . filterManager . pushFilter ( this . _filterBlock ) ;
}
2014-02-28 09:30:53 +00:00
if ( this . _mask )
{
spriteBatch . stop ( ) ;
renderSession . maskManager . pushMask ( this . mask , renderSession ) ;
spriteBatch . start ( ) ;
}
// add this sprite to the batch
spriteBatch . render ( this ) ;
// now loop through the children and make sure they get rendered
for ( i = 0 , j = this . children . length ; i < j ; i ++ )
{
this . children [ i ] . _renderWebGL ( renderSession ) ;
}
// time to stop the sprite batch as either a mask element or a filter draw will happen next
spriteBatch . stop ( ) ;
2014-07-01 14:04:03 +00:00
if ( this . _mask ) renderSession . maskManager . popMask ( this . _mask , renderSession ) ;
2014-02-28 09:30:53 +00:00
if ( this . _filters ) renderSession . filterManager . popFilter ( ) ;
2014-11-08 19:26:34 +00:00
2014-02-28 09:30:53 +00:00
spriteBatch . start ( ) ;
}
else
{
renderSession . spriteBatch . render ( this ) ;
// simple render children!
for ( i = 0 , j = this . children . length ; i < j ; i ++ )
{
this . children [ i ] . _renderWebGL ( renderSession ) ;
}
2014-11-08 19:26:34 +00:00
2014-02-28 09:30:53 +00:00
}
} ;
/ * *
* Renders the object using the Canvas renderer
*
* @ method _renderCanvas
2014-11-08 19:26:34 +00:00
* @ param renderSession { RenderSession }
2014-02-28 09:30:53 +00:00
* @ private
* /
PIXI . Sprite . prototype . _renderCanvas = function ( renderSession )
{
2014-07-10 15:23:26 +00:00
// If the sprite is not visible or the alpha is 0 then no need to render this element
2014-08-29 17:13:33 +00:00
if ( this . visible === false || this . alpha === 0 || this . texture . crop . width <= 0 || this . texture . crop . height <= 0 ) return ;
2014-11-08 19:26:34 +00:00
2014-07-10 15:23:26 +00:00
if ( this . blendMode !== renderSession . currentBlendMode )
2014-02-28 09:30:53 +00:00
{
renderSession . currentBlendMode = this . blendMode ;
2014-07-10 15:23:26 +00:00
renderSession . context . globalCompositeOperation = PIXI . blendModesCanvas [ renderSession . currentBlendMode ] ;
2014-02-28 09:30:53 +00:00
}
2014-07-10 15:23:26 +00:00
if ( this . _mask )
2014-02-28 09:30:53 +00:00
{
2014-10-22 20:42:03 +00:00
renderSession . maskManager . pushMask ( this . _mask , renderSession ) ;
2014-02-28 09:30:53 +00:00
}
2014-07-10 15:23:26 +00:00
// Ignore null sources
if ( this . texture . valid )
2014-02-28 09:30:53 +00:00
{
2014-10-22 20:42:03 +00:00
var resolution = this . texture . baseTexture . resolution / renderSession . resolution ;
2014-07-10 15:23:26 +00:00
renderSession . context . globalAlpha = this . worldAlpha ;
2014-02-28 09:30:53 +00:00
2014-07-10 15:23:26 +00:00
// Allow for pixel rounding
2014-02-28 09:30:53 +00:00
if ( renderSession . roundPixels )
{
2014-07-10 15:23:26 +00:00
renderSession . context . setTransform (
this . worldTransform . a ,
this . worldTransform . b ,
2014-10-22 20:42:03 +00:00
this . worldTransform . c ,
2014-07-10 15:23:26 +00:00
this . worldTransform . d ,
2014-10-22 20:42:03 +00:00
( this . worldTransform . tx * renderSession . resolution ) | 0 ,
( this . worldTransform . ty * renderSession . resolution ) | 0 ) ;
2014-02-28 09:30:53 +00:00
}
else
{
2014-07-10 15:23:26 +00:00
renderSession . context . setTransform (
this . worldTransform . a ,
this . worldTransform . b ,
2014-10-22 20:42:03 +00:00
this . worldTransform . c ,
2014-07-10 15:23:26 +00:00
this . worldTransform . d ,
2014-10-22 20:42:03 +00:00
this . worldTransform . tx * renderSession . resolution ,
this . worldTransform . ty * renderSession . resolution ) ;
2014-02-28 09:30:53 +00:00
}
2014-07-10 15:23:26 +00:00
// If smoothingEnabled is supported and we need to change the smoothing property for this texture
if ( renderSession . smoothProperty && renderSession . scaleMode !== this . texture . baseTexture . scaleMode )
{
2014-02-28 09:30:53 +00:00
renderSession . scaleMode = this . texture . baseTexture . scaleMode ;
2014-07-10 15:23:26 +00:00
renderSession . context [ renderSession . smoothProperty ] = ( renderSession . scaleMode === PIXI . scaleModes . LINEAR ) ;
2014-02-28 09:30:53 +00:00
}
2014-07-10 15:23:26 +00:00
// If the texture is trimmed we offset by the trim x/y, otherwise we use the frame dimensions
var dx = ( this . texture . trim ) ? this . texture . trim . x - this . anchor . x * this . texture . trim . width : this . anchor . x * - this . texture . frame . width ;
var dy = ( this . texture . trim ) ? this . texture . trim . y - this . anchor . y * this . texture . trim . height : this . anchor . y * - this . texture . frame . height ;
if ( this . tint !== 0xFFFFFF )
2014-02-28 09:30:53 +00:00
{
2014-07-10 15:23:26 +00:00
if ( this . cachedTint !== this . tint )
2014-02-28 09:30:53 +00:00
{
this . cachedTint = this . tint ;
2014-11-08 19:26:34 +00:00
2014-07-10 15:23:26 +00:00
// TODO clean up caching - how to clean up the caches?
2014-02-28 09:30:53 +00:00
this . tintedTexture = PIXI . CanvasTinter . getTintedTexture ( this , this . tint ) ;
}
2014-07-10 15:23:26 +00:00
renderSession . context . drawImage (
this . tintedTexture ,
0 ,
0 ,
this . texture . crop . width ,
this . texture . crop . height ,
2014-10-22 20:42:03 +00:00
dx / resolution ,
dy / resolution ,
this . texture . crop . width / resolution ,
this . texture . crop . height / resolution ) ;
2014-02-28 09:30:53 +00:00
}
else
{
2014-07-10 15:23:26 +00:00
renderSession . context . drawImage (
this . texture . baseTexture . source ,
this . texture . crop . x ,
this . texture . crop . y ,
this . texture . crop . width ,
this . texture . crop . height ,
2014-10-22 20:42:03 +00:00
dx / resolution ,
dy / resolution ,
this . texture . crop . width / resolution ,
this . texture . crop . height / resolution ) ;
2014-02-28 09:30:53 +00:00
}
}
// OVERWRITE
2014-07-10 15:23:26 +00:00
for ( var i = 0 , j = this . children . length ; i < j ; i ++ )
2014-02-28 09:30:53 +00:00
{
2014-07-10 15:23:26 +00:00
this . children [ i ] . _renderCanvas ( renderSession ) ;
2014-02-28 09:30:53 +00:00
}
2014-07-10 15:23:26 +00:00
if ( this . _mask )
2014-02-28 09:30:53 +00:00
{
2014-10-22 20:42:03 +00:00
renderSession . maskManager . popMask ( renderSession ) ;
2014-02-28 09:30:53 +00:00
}
} ;
// some helper functions..
/ * *
*
* Helper function that creates a sprite that will contain a texture from the TextureCache based on the frameId
* The frame ids are created when a Texture packer file has been loaded
*
* @ method fromFrame
* @ static
* @ param frameId { String } The frame Id of the texture in the cache
* @ return { Sprite } A new Sprite using a texture from the texture cache matching the frameId
* /
PIXI . Sprite . fromFrame = function ( frameId )
{
var texture = PIXI . TextureCache [ frameId ] ;
if ( ! texture ) throw new Error ( 'The frameId "' + frameId + '" does not exist in the texture cache' + this ) ;
return new PIXI . Sprite ( texture ) ;
} ;
/ * *
*
* Helper function that creates a sprite that will contain a texture based on an image url
* If the image is not in the texture cache it will be loaded
*
* @ method fromImage
* @ static
* @ param imageId { String } The image url of the texture
* @ return { Sprite } A new Sprite using a texture from the texture cache matching the image id
* /
PIXI . Sprite . fromImage = function ( imageId , crossorigin , scaleMode )
{
var texture = PIXI . Texture . fromImage ( imageId , crossorigin , scaleMode ) ;
return new PIXI . Sprite ( texture ) ;
} ;
/ * *
* @ author Mat Groves http : //matgroves.com/
* /
/ * *
2014-04-01 02:02:36 +00:00
* The SpriteBatch class is a really fast version of the DisplayObjectContainer
2014-02-28 09:30:53 +00:00
* built solely for speed , so use when you need a lot of sprites or particles .
2014-04-01 02:02:36 +00:00
* And it ' s extremely easy to use :
2014-02-28 09:30:53 +00:00
var container = new PIXI . SpriteBatch ( ) ;
2014-04-01 02:02:36 +00:00
2014-02-28 09:30:53 +00:00
stage . addChild ( container ) ;
2014-04-01 02:02:36 +00:00
2014-02-28 09:30:53 +00:00
for ( var i = 0 ; i < 100 ; i ++ )
{
var sprite = new PIXI . Sprite . fromImage ( "myImage.png" ) ;
container . addChild ( sprite ) ;
}
* And here you have a hundred sprites that will be renderer at the speed of light
*
* @ class SpriteBatch
* @ constructor
* @ param texture { Texture }
* /
2014-10-22 20:42:03 +00:00
//TODO RENAME to PARTICLE CONTAINER?
2014-02-28 09:30:53 +00:00
PIXI . SpriteBatch = function ( texture )
{
PIXI . DisplayObjectContainer . call ( this ) ;
this . textureThing = texture ;
this . ready = false ;
} ;
PIXI . SpriteBatch . prototype = Object . create ( PIXI . DisplayObjectContainer . prototype ) ;
2014-10-22 20:42:03 +00:00
PIXI . SpriteBatch . prototype . constructor = PIXI . SpriteBatch ;
2014-02-28 09:30:53 +00:00
/ *
* Initialises the spriteBatch
*
* @ method initWebGL
* @ param gl { WebGLContext } the current WebGL drawing context
* /
PIXI . SpriteBatch . prototype . initWebGL = function ( gl )
{
// TODO only one needed for the whole engine really?
this . fastSpriteBatch = new PIXI . WebGLFastSpriteBatch ( gl ) ;
this . ready = true ;
} ;
/ *
* Updates the object transform for rendering
*
* @ method updateTransform
* @ private
* /
PIXI . SpriteBatch . prototype . updateTransform = function ( )
{
2014-10-22 20:42:03 +00:00
// TODO don't need to!
2014-02-28 09:30:53 +00:00
PIXI . DisplayObject . prototype . updateTransform . call ( this ) ;
2014-10-22 20:42:03 +00:00
// PIXI.DisplayObjectContainer.prototype.updateTransform.call( this );
2014-02-28 09:30:53 +00:00
} ;
/ * *
* Renders the object using the WebGL renderer
*
* @ method _renderWebGL
2014-04-01 02:02:36 +00:00
* @ param renderSession { RenderSession }
2014-02-28 09:30:53 +00:00
* @ private
* /
PIXI . SpriteBatch . prototype . _renderWebGL = function ( renderSession )
{
if ( ! this . visible || this . alpha <= 0 || ! this . children . length ) return ;
if ( ! this . ready ) this . initWebGL ( renderSession . gl ) ;
2014-04-01 02:02:36 +00:00
2014-02-28 09:30:53 +00:00
renderSession . spriteBatch . stop ( ) ;
2014-04-01 02:02:36 +00:00
2014-07-01 14:04:03 +00:00
renderSession . shaderManager . setShader ( renderSession . shaderManager . fastShader ) ;
2014-04-01 02:02:36 +00:00
2014-02-28 09:30:53 +00:00
this . fastSpriteBatch . begin ( this , renderSession ) ;
this . fastSpriteBatch . render ( this ) ;
renderSession . spriteBatch . start ( ) ;
2014-04-01 02:02:36 +00:00
2014-02-28 09:30:53 +00:00
} ;
/ * *
* Renders the object using the Canvas renderer
*
* @ method _renderCanvas
2014-04-01 02:02:36 +00:00
* @ param renderSession { RenderSession }
2014-02-28 09:30:53 +00:00
* @ private
* /
PIXI . SpriteBatch . prototype . _renderCanvas = function ( renderSession )
{
2014-10-22 20:42:03 +00:00
if ( ! this . visible || this . alpha <= 0 || ! this . children . length ) return ;
2014-02-28 09:30:53 +00:00
var context = renderSession . context ;
context . globalAlpha = this . worldAlpha ;
PIXI . DisplayObject . prototype . updateTransform . call ( this ) ;
var transform = this . worldTransform ;
// alow for trimming
2014-04-01 02:02:36 +00:00
2014-02-28 09:30:53 +00:00
var isRotated = true ;
for ( var i = 0 ; i < this . children . length ; i ++ ) {
2014-04-01 02:02:36 +00:00
2014-02-28 09:30:53 +00:00
var child = this . children [ i ] ;
2014-02-28 18:55:07 +00:00
if ( ! child . visible ) continue ;
2014-02-28 09:30:53 +00:00
var texture = child . texture ;
var frame = texture . frame ;
context . globalAlpha = this . worldAlpha * child . alpha ;
if ( child . rotation % ( Math . PI * 2 ) === 0 )
{
if ( isRotated )
{
2014-10-22 20:42:03 +00:00
context . setTransform ( transform . a , transform . b , transform . c , transform . d , transform . tx , transform . ty ) ;
2014-02-28 09:30:53 +00:00
isRotated = false ;
}
// this is the fastest way to optimise! - if rotation is 0 then we can avoid any kind of setTransform call
context . drawImage ( texture . baseTexture . source ,
frame . x ,
frame . y ,
frame . width ,
frame . height ,
( ( child . anchor . x ) * ( - frame . width * child . scale . x ) + child . position . x + 0.5 ) | 0 ,
( ( child . anchor . y ) * ( - frame . height * child . scale . y ) + child . position . y + 0.5 ) | 0 ,
frame . width * child . scale . x ,
frame . height * child . scale . y ) ;
}
else
{
if ( ! isRotated ) isRotated = true ;
2014-04-01 02:02:36 +00:00
2014-02-28 09:30:53 +00:00
PIXI . DisplayObject . prototype . updateTransform . call ( child ) ;
2014-04-01 02:02:36 +00:00
2014-02-28 09:30:53 +00:00
var childTransform = child . worldTransform ;
// allow for trimming
2014-04-01 02:02:36 +00:00
2014-02-28 09:30:53 +00:00
if ( renderSession . roundPixels )
{
2014-10-22 20:42:03 +00:00
context . setTransform ( childTransform . a , childTransform . b , childTransform . c , childTransform . d , childTransform . tx | 0 , childTransform . ty | 0 ) ;
2014-02-28 09:30:53 +00:00
}
else
{
2014-10-22 20:42:03 +00:00
context . setTransform ( childTransform . a , childTransform . b , childTransform . c , childTransform . d , childTransform . tx , childTransform . ty ) ;
2014-02-28 09:30:53 +00:00
}
context . drawImage ( texture . baseTexture . source ,
frame . x ,
frame . y ,
frame . width ,
frame . height ,
( ( child . anchor . x ) * ( - frame . width ) + 0.5 ) | 0 ,
( ( child . anchor . y ) * ( - frame . height ) + 0.5 ) | 0 ,
frame . width ,
frame . height ) ;
2014-04-01 02:02:36 +00:00
2014-02-28 09:30:53 +00:00
}
// context.restore();
}
// context.restore();
} ;
2014-04-26 02:48:06 +00:00
/ * *
* @ author Mat Groves http : //matgroves.com/ @Doormat23
* /
/ * *
2014-10-22 20:42:03 +00:00
* A target and pass info object for filters .
*
* @ class FilterBlock
2014-04-26 02:48:06 +00:00
* @ constructor
* /
2014-10-22 20:42:03 +00:00
PIXI . FilterBlock = function ( )
2014-04-26 02:48:06 +00:00
{
/ * *
2014-10-22 20:42:03 +00:00
* The visible state of this FilterBlock .
*
* @ property visible
* @ type Boolean
* /
this . visible = true ;
2014-04-26 02:48:06 +00:00
/ * *
2014-10-22 20:42:03 +00:00
* The renderable state of this FilterBlock .
*
* @ property renderable
* @ type Boolean
* /
2014-02-28 09:30:53 +00:00
this . renderable = true ;
} ;
2014-10-22 20:42:03 +00:00
PIXI . FilterBlock . prototype . constructor = PIXI . FilterBlock ;
2014-02-28 09:30:53 +00:00
/ * *
* @ author Mat Groves http : //matgroves.com/ @Doormat23
2014-10-22 20:42:03 +00:00
* Modified by Tom Slezakowski http : //www.tomslezakowski.com @TomSlezakowski (24/03/2014) - Added dropShadowColor.
2014-02-28 09:30:53 +00:00
* /
/ * *
2014-10-22 20:42:03 +00:00
* A Text Object will create a line or multiple lines of text . To split a line you can use '\n' in your text string ,
* or add a wordWrap property set to true and and wordWrapWidth property with a value in the style object .
2014-02-28 09:30:53 +00:00
*
* @ class Text
* @ extends Sprite
* @ constructor
* @ param text { String } The copy that you would like the text to display
* @ param [ style ] { Object } The style parameters
* @ param [ style . font ] { String } default 'bold 20px Arial' The style and size of the font
* @ param [ style . fill = 'black' ] { String | Number } A canvas fillstyle that will be used on the text e . g 'red' , '#00FF00'
* @ param [ style . align = 'left' ] { String } Alignment for multiline text ( 'left' , 'center' or 'right' ) , does not affect single line text
* @ param [ style . stroke ] { String | Number } A canvas fillstyle that will be used on the text stroke e . g 'blue' , '#FCFF00'
* @ param [ style . strokeThickness = 0 ] { Number } A number that represents the thickness of the stroke . Default is 0 ( no stroke )
* @ param [ style . wordWrap = false ] { Boolean } Indicates if word wrap should be used
* @ param [ style . wordWrapWidth = 100 ] { Number } The width at which text will wrap , it needs wordWrap to be set to true
2014-04-01 02:02:36 +00:00
* @ param [ style . dropShadow = false ] { Boolean } Set a drop shadow for the text
* @ param [ style . dropShadowColor = '#000000' ] { String } A fill style to be used on the dropshadow e . g 'red' , '#00FF00'
* @ param [ style . dropShadowAngle = Math . PI / 4 ] { Number } Set a angle of the drop shadow
* @ param [ style . dropShadowDistance = 5 ] { Number } Set a distance of the drop shadow
2014-02-28 09:30:53 +00:00
* /
PIXI . Text = function ( text , style )
{
/ * *
* The canvas element that everything is drawn to
*
* @ property canvas
* @ type HTMLCanvasElement
* /
this . canvas = document . createElement ( 'canvas' ) ;
/ * *
* The canvas 2 d context that everything is drawn with
* @ property context
2014-10-22 20:42:03 +00:00
* @ type HTMLCanvasElement
2014-02-28 09:30:53 +00:00
* /
this . context = this . canvas . getContext ( '2d' ) ;
2014-10-22 20:42:03 +00:00
/ * *
* The resolution of the canvas .
* @ property resolution
* @ type Number
* /
this . resolution = 1 ;
2014-02-28 09:30:53 +00:00
PIXI . Sprite . call ( this , PIXI . Texture . fromCanvas ( this . canvas ) ) ;
this . setText ( text ) ;
this . setStyle ( style ) ;
2014-10-22 20:42:03 +00:00
2014-02-28 09:30:53 +00:00
} ;
// constructor
PIXI . Text . prototype = Object . create ( PIXI . Sprite . prototype ) ;
PIXI . Text . prototype . constructor = PIXI . Text ;
2014-07-16 00:58:24 +00:00
/ * *
2014-10-22 20:42:03 +00:00
* The width of the Text , setting this will actually modify the scale to achieve the value set
2014-07-16 00:58:24 +00:00
*
* @ property width
* @ type Number
* /
Object . defineProperty ( PIXI . Text . prototype , 'width' , {
get : function ( ) {
if ( this . dirty )
{
this . updateText ( ) ;
this . dirty = false ;
}
return this . scale . x * this . texture . frame . width ;
} ,
set : function ( value ) {
this . scale . x = value / this . texture . frame . width ;
this . _width = value ;
}
} ) ;
/ * *
* The height of the Text , setting this will actually modify the scale to achieve the value set
*
* @ property height
* @ type Number
* /
Object . defineProperty ( PIXI . Text . prototype , 'height' , {
get : function ( ) {
if ( this . dirty )
{
this . updateText ( ) ;
this . dirty = false ;
}
return this . scale . y * this . texture . frame . height ;
} ,
set : function ( value ) {
this . scale . y = value / this . texture . frame . height ;
this . _height = value ;
}
} ) ;
2014-02-28 09:30:53 +00:00
/ * *
* Set the style of the text
*
* @ method setStyle
* @ param [ style ] { Object } The style parameters
* @ param [ style . font = 'bold 20pt Arial' ] { String } The style and size of the font
* @ param [ style . fill = 'black' ] { Object } A canvas fillstyle that will be used on the text eg 'red' , '#00FF00'
* @ param [ style . align = 'left' ] { String } Alignment for multiline text ( 'left' , 'center' or 'right' ) , does not affect single line text
* @ param [ style . stroke = 'black' ] { String } A canvas fillstyle that will be used on the text stroke eg 'blue' , '#FCFF00'
* @ param [ style . strokeThickness = 0 ] { Number } A number that represents the thickness of the stroke . Default is 0 ( no stroke )
* @ param [ style . wordWrap = false ] { Boolean } Indicates if word wrap should be used
* @ param [ style . wordWrapWidth = 100 ] { Number } The width at which text will wrap
2014-04-01 02:02:36 +00:00
* @ param [ style . dropShadow = false ] { Boolean } Set a drop shadow for the text
* @ param [ style . dropShadowColor = '#000000' ] { String } A fill style to be used on the dropshadow e . g 'red' , '#00FF00'
* @ param [ style . dropShadowAngle = Math . PI / 4 ] { Number } Set a angle of the drop shadow
* @ param [ style . dropShadowDistance = 5 ] { Number } Set a distance of the drop shadow
2014-02-28 09:30:53 +00:00
* /
PIXI . Text . prototype . setStyle = function ( style )
{
style = style || { } ;
style . font = style . font || 'bold 20pt Arial' ;
style . fill = style . fill || 'black' ;
style . align = style . align || 'left' ;
style . stroke = style . stroke || 'black' ; //provide a default, see: https://github.com/GoodBoyDigital/pixi.js/issues/136
style . strokeThickness = style . strokeThickness || 0 ;
style . wordWrap = style . wordWrap || false ;
style . wordWrapWidth = style . wordWrapWidth || 100 ;
2014-04-01 02:02:36 +00:00
style . dropShadow = style . dropShadow || false ;
style . dropShadowAngle = style . dropShadowAngle || Math . PI / 6 ;
style . dropShadowDistance = style . dropShadowDistance || 4 ;
style . dropShadowColor = style . dropShadowColor || 'black' ;
2014-02-28 09:30:53 +00:00
this . style = style ;
this . dirty = true ;
} ;
/ * *
2014-10-22 20:42:03 +00:00
* Set the copy for the text object . To split a line you can use '\n' .
2014-02-28 09:30:53 +00:00
*
* @ method setText
2014-10-22 20:42:03 +00:00
* @ param text { String } The copy that you would like the text to display
2014-02-28 09:30:53 +00:00
* /
PIXI . Text . prototype . setText = function ( text )
{
this . text = text . toString ( ) || ' ' ;
this . dirty = true ;
} ;
/ * *
* Renders text and updates it when needed
*
* @ method updateText
* @ private
* /
PIXI . Text . prototype . updateText = function ( )
{
2014-10-22 20:42:03 +00:00
this . texture . baseTexture . resolution = this . resolution ;
2014-02-28 09:30:53 +00:00
this . context . font = this . style . font ;
var outputText = this . text ;
// word wrap
// preserve original text
if ( this . style . wordWrap ) outputText = this . wordWrap ( this . text ) ;
//split text into lines
var lines = outputText . split ( /(?:\r\n|\r|\n)/ ) ;
//calculate text width
var lineWidths = [ ] ;
var maxLineWidth = 0 ;
2014-10-22 20:42:03 +00:00
var fontProperties = this . determineFontProperties ( this . style . font ) ;
2014-02-28 09:30:53 +00:00
for ( var i = 0 ; i < lines . length ; i ++ )
{
var lineWidth = this . context . measureText ( lines [ i ] ) . width ;
lineWidths [ i ] = lineWidth ;
maxLineWidth = Math . max ( maxLineWidth , lineWidth ) ;
}
2014-04-01 02:02:36 +00:00
var width = maxLineWidth + this . style . strokeThickness ;
if ( this . style . dropShadow ) width += this . style . dropShadowDistance ;
2014-10-22 20:42:03 +00:00
this . canvas . width = ( width + this . context . lineWidth ) * this . resolution ;
2014-04-01 02:02:36 +00:00
2014-10-22 20:42:03 +00:00
//calculate text height
var lineHeight = fontProperties . fontSize + this . style . strokeThickness ;
2014-04-01 02:02:36 +00:00
var height = lineHeight * lines . length ;
if ( this . style . dropShadow ) height += this . style . dropShadowDistance ;
2014-02-28 09:30:53 +00:00
2014-10-22 20:42:03 +00:00
this . canvas . height = height * this . resolution ;
this . context . scale ( this . resolution , this . resolution ) ;
2014-03-28 01:42:49 +00:00
2014-04-01 02:02:36 +00:00
if ( navigator . isCocoonJS ) this . context . clearRect ( 0 , 0 , this . canvas . width , this . canvas . height ) ;
2014-02-28 09:30:53 +00:00
this . context . font = this . style . font ;
this . context . strokeStyle = this . style . stroke ;
this . context . lineWidth = this . style . strokeThickness ;
2014-10-22 20:42:03 +00:00
this . context . textBaseline = 'alphabetic' ;
2014-11-08 19:26:34 +00:00
//this.context.lineJoin = 'round';
2014-02-28 09:30:53 +00:00
2014-04-01 02:02:36 +00:00
var linePositionX ;
var linePositionY ;
if ( this . style . dropShadow )
{
this . context . fillStyle = this . style . dropShadowColor ;
var xShadowOffset = Math . sin ( this . style . dropShadowAngle ) * this . style . dropShadowDistance ;
var yShadowOffset = Math . cos ( this . style . dropShadowAngle ) * this . style . dropShadowDistance ;
for ( i = 0 ; i < lines . length ; i ++ )
{
linePositionX = this . style . strokeThickness / 2 ;
2014-10-22 20:42:03 +00:00
linePositionY = ( this . style . strokeThickness / 2 + i * lineHeight ) + fontProperties . ascent ;
2014-04-01 02:02:36 +00:00
if ( this . style . align === 'right' )
{
linePositionX += maxLineWidth - lineWidths [ i ] ;
}
else if ( this . style . align === 'center' )
{
linePositionX += ( maxLineWidth - lineWidths [ i ] ) / 2 ;
}
if ( this . style . fill )
{
this . context . fillText ( lines [ i ] , linePositionX + xShadowOffset , linePositionY + yShadowOffset ) ;
}
// if(dropShadow)
}
}
//set canvas text styles
this . context . fillStyle = this . style . fill ;
2014-02-28 09:30:53 +00:00
//draw lines line by line
for ( i = 0 ; i < lines . length ; i ++ )
{
2014-04-01 02:02:36 +00:00
linePositionX = this . style . strokeThickness / 2 ;
2014-10-22 20:42:03 +00:00
linePositionY = ( this . style . strokeThickness / 2 + i * lineHeight ) + fontProperties . ascent ;
2014-02-28 09:30:53 +00:00
if ( this . style . align === 'right' )
{
2014-04-01 02:02:36 +00:00
linePositionX += maxLineWidth - lineWidths [ i ] ;
2014-02-28 09:30:53 +00:00
}
else if ( this . style . align === 'center' )
{
2014-04-01 02:02:36 +00:00
linePositionX += ( maxLineWidth - lineWidths [ i ] ) / 2 ;
2014-02-28 09:30:53 +00:00
}
if ( this . style . stroke && this . style . strokeThickness )
{
2014-04-01 02:02:36 +00:00
this . context . strokeText ( lines [ i ] , linePositionX , linePositionY ) ;
2014-02-28 09:30:53 +00:00
}
if ( this . style . fill )
{
2014-04-01 02:02:36 +00:00
this . context . fillText ( lines [ i ] , linePositionX , linePositionY ) ;
2014-02-28 09:30:53 +00:00
}
2014-04-01 02:02:36 +00:00
// if(dropShadow)
2014-02-28 09:30:53 +00:00
}
this . updateTexture ( ) ;
} ;
/ * *
* Updates texture size based on canvas size
*
* @ method updateTexture
* @ private
* /
PIXI . Text . prototype . updateTexture = function ( )
{
this . texture . baseTexture . width = this . canvas . width ;
this . texture . baseTexture . height = this . canvas . height ;
2014-07-10 15:23:26 +00:00
this . texture . crop . width = this . texture . frame . width = this . canvas . width ;
this . texture . crop . height = this . texture . frame . height = this . canvas . height ;
2014-02-28 09:30:53 +00:00
this . _width = this . canvas . width ;
this . _height = this . canvas . height ;
2014-10-22 20:42:03 +00:00
// update the dirty base textures
this . texture . baseTexture . dirty ( ) ;
2014-02-28 09:30:53 +00:00
} ;
/ * *
* Renders the object using the WebGL renderer
*
* @ method _renderWebGL
2014-04-01 02:02:36 +00:00
* @ param renderSession { RenderSession }
2014-02-28 09:30:53 +00:00
* @ private
* /
PIXI . Text . prototype . _renderWebGL = function ( renderSession )
{
2014-10-22 20:42:03 +00:00
if ( this . dirty )
2014-02-28 09:30:53 +00:00
{
2014-10-22 20:42:03 +00:00
this . resolution = renderSession . resolution ;
this . updateText ( ) ;
this . dirty = false ;
2014-02-28 09:30:53 +00:00
}
PIXI . Sprite . prototype . _renderWebGL . call ( this , renderSession ) ;
} ;
/ * *
2014-10-22 20:42:03 +00:00
* Renders the object using the Canvas renderer
*
* @ method _renderCanvas
* @ param renderSession { RenderSession }
* @ private
* /
PIXI . Text . prototype . _renderCanvas = function ( renderSession )
2014-02-28 09:30:53 +00:00
{
if ( this . dirty )
{
2014-10-22 20:42:03 +00:00
this . resolution = renderSession . resolution ;
2014-02-28 09:30:53 +00:00
this . updateText ( ) ;
this . dirty = false ;
}
2014-10-22 20:42:03 +00:00
PIXI . Sprite . prototype . _renderCanvas . call ( this , renderSession ) ;
2014-02-28 09:30:53 +00:00
} ;
2014-10-22 20:42:03 +00:00
/ * *
* Calculates the ascent , descent and fontSize of a given fontStyle
*
* @ method determineFontProperties
* @ param fontStyle { Object }
* @ private
* /
PIXI . Text . prototype . determineFontProperties = function ( fontStyle )
2014-02-28 09:30:53 +00:00
{
2014-10-22 20:42:03 +00:00
var properties = PIXI . Text . fontPropertiesCache [ fontStyle ] ;
2014-02-28 09:30:53 +00:00
2014-10-22 20:42:03 +00:00
if ( ! properties )
2014-02-28 09:30:53 +00:00
{
2014-10-22 20:42:03 +00:00
properties = { } ;
var canvas = PIXI . Text . fontPropertiesCanvas ;
var context = PIXI . Text . fontPropertiesContext ;
context . font = fontStyle ;
var width = Math . ceil ( context . measureText ( '|Mq' ) . width ) ;
var baseline = Math . ceil ( context . measureText ( 'M' ) . width ) ;
var height = 2 * baseline ;
baseline = baseline * 1.4 | 0 ;
canvas . width = width ;
canvas . height = height ;
context . fillStyle = '#f00' ;
context . fillRect ( 0 , 0 , width , height ) ;
context . font = fontStyle ;
context . textBaseline = 'alphabetic' ;
context . fillStyle = '#000' ;
context . fillText ( '|Mq' , 0 , baseline ) ;
var imagedata = context . getImageData ( 0 , 0 , width , height ) . data ;
var pixels = imagedata . length ;
var line = width * 4 ;
var i , j ;
var idx = 0 ;
var stop = false ;
// ascent. scan from top to bottom until we find a non red pixel
for ( i = 0 ; i < baseline ; i ++ )
{
for ( j = 0 ; j < line ; j += 4 )
{
if ( imagedata [ idx + j ] !== 255 )
{
stop = true ;
break ;
}
}
if ( ! stop )
{
idx += line ;
}
else
{
break ;
}
}
properties . ascent = baseline - i ;
idx = pixels - line ;
stop = false ;
2014-02-28 09:30:53 +00:00
2014-10-22 20:42:03 +00:00
// descent. scan from bottom to top until we find a non red pixel
for ( i = height ; i > baseline ; i -- )
{
for ( j = 0 ; j < line ; j += 4 )
{
if ( imagedata [ idx + j ] !== 255 )
{
stop = true ;
break ;
}
}
if ( ! stop )
{
idx -= line ;
}
else
{
break ;
}
}
2014-02-28 09:30:53 +00:00
2014-10-22 20:42:03 +00:00
properties . descent = i - baseline ;
properties . fontSize = properties . ascent + properties . descent ;
PIXI . Text . fontPropertiesCache [ fontStyle ] = properties ;
2014-02-28 09:30:53 +00:00
}
2014-10-22 20:42:03 +00:00
return properties ;
2014-02-28 09:30:53 +00:00
} ;
/ * *
* Applies newlines to a string to have it optimally fit into the horizontal
* bounds set by the Text object ' s wordWrapWidth property .
*
* @ method wordWrap
* @ param text { String }
* @ private
* /
PIXI . Text . prototype . wordWrap = function ( text )
{
// Greedy wrapping algorithm that will wrap words as the line grows longer
// than its horizontal bounds.
var result = '' ;
var lines = text . split ( '\n' ) ;
for ( var i = 0 ; i < lines . length ; i ++ )
{
var spaceLeft = this . style . wordWrapWidth ;
var words = lines [ i ] . split ( ' ' ) ;
for ( var j = 0 ; j < words . length ; j ++ )
{
var wordWidth = this . context . measureText ( words [ j ] ) . width ;
var wordWidthWithSpace = wordWidth + this . context . measureText ( ' ' ) . width ;
2014-04-29 14:39:53 +00:00
if ( j === 0 || wordWidthWithSpace > spaceLeft )
2014-02-28 09:30:53 +00:00
{
// Skip printing the newline if it's the first word of the line that is
// greater than the word wrap width.
if ( j > 0 )
{
result += '\n' ;
}
2014-04-29 14:39:53 +00:00
result += words [ j ] ;
2014-02-28 09:30:53 +00:00
spaceLeft = this . style . wordWrapWidth - wordWidth ;
}
else
{
spaceLeft -= wordWidthWithSpace ;
2014-04-29 14:39:53 +00:00
result += ' ' + words [ j ] ;
2014-02-28 09:30:53 +00:00
}
}
if ( i < lines . length - 1 )
{
result += '\n' ;
}
}
return result ;
} ;
2014-11-12 22:49:36 +00:00
/ * *
* Returns the bounds of the Text as a rectangle . The bounds calculation takes the worldTransform into account .
*
* @ method getBounds
* @ param matrix { Matrix } the transformation matrix of the Text
* @ return { Rectangle } the framing rectangle
* /
PIXI . Text . prototype . getBounds = function ( matrix )
{
if ( this . dirty )
{
this . updateText ( ) ;
this . dirty = false ;
}
return PIXI . Sprite . prototype . getBounds . call ( this , matrix ) ;
} ;
2014-02-28 09:30:53 +00:00
/ * *
2014-10-22 20:42:03 +00:00
* Destroys this text object .
2014-02-28 09:30:53 +00:00
*
* @ method destroy
2014-07-01 14:04:03 +00:00
* @ param destroyBaseTexture { Boolean } whether to destroy the base texture as well
2014-02-28 09:30:53 +00:00
* /
2014-07-01 14:04:03 +00:00
PIXI . Text . prototype . destroy = function ( destroyBaseTexture )
2014-02-28 09:30:53 +00:00
{
2014-07-01 14:04:03 +00:00
// make sure to reset the the context and canvas.. dont want this hanging around in memory!
this . context = null ;
this . canvas = null ;
2014-02-28 09:30:53 +00:00
2014-07-01 14:04:03 +00:00
this . texture . destroy ( destroyBaseTexture === undefined ? true : destroyBaseTexture ) ;
2014-02-28 09:30:53 +00:00
} ;
2014-10-22 20:42:03 +00:00
PIXI . Text . fontPropertiesCache = { } ;
PIXI . Text . fontPropertiesCanvas = document . createElement ( 'canvas' ) ;
PIXI . Text . fontPropertiesContext = PIXI . Text . fontPropertiesCanvas . getContext ( '2d' ) ;
2014-02-28 09:30:53 +00:00
/ * *
* @ author Mat Groves http : //matgroves.com/ @Doormat23
* /
/ * *
2014-10-22 20:42:03 +00:00
* A BitmapText object will create a line or multiple lines of text using bitmap font . To split a line you can use '\n' , '\r' or '\r\n' in your string .
2014-02-28 09:30:53 +00:00
* You can generate the fnt files using
* http : //www.angelcode.com/products/bmfont/ for windows or
* http : //www.bmglyph.com/ for mac.
*
* @ class BitmapText
* @ extends DisplayObjectContainer
* @ constructor
* @ param text { String } The copy that you would like the text to display
* @ param style { Object } The style parameters
* @ param style . font { String } The size ( optional ) and bitmap font id ( required ) eq 'Arial' or '20px Arial' ( must have loaded previously )
* @ param [ style . align = 'left' ] { String } Alignment for multiline text ( 'left' , 'center' or 'right' ) , does not affect single line text
* /
PIXI . BitmapText = function ( text , style )
{
PIXI . DisplayObjectContainer . call ( this ) ;
2014-10-22 20:42:03 +00:00
/ * *
* [ read - only ] The width of the overall text , different from fontSize ,
* which is defined in the style object
*
* @ property textWidth
* @ type Number
* @ readOnly
* /
this . textWidth = 0 ;
/ * *
* [ read - only ] The height of the overall text , different from fontSize ,
* which is defined in the style object
*
* @ property textHeight
* @ type Number
* @ readOnly
* /
this . textHeight = 0 ;
/ * *
* @ property _pool
* @ type Array
* @ private
* /
2014-02-28 09:30:53 +00:00
this . _pool = [ ] ;
this . setText ( text ) ;
this . setStyle ( style ) ;
this . updateText ( ) ;
2014-10-22 20:42:03 +00:00
/ * *
* The dirty state of this object .
* @ property dirty
* @ type Boolean
* /
2014-02-28 09:30:53 +00:00
this . dirty = false ;
} ;
// constructor
PIXI . BitmapText . prototype = Object . create ( PIXI . DisplayObjectContainer . prototype ) ;
PIXI . BitmapText . prototype . constructor = PIXI . BitmapText ;
/ * *
2014-10-22 20:42:03 +00:00
* Set the text string to be rendered .
2014-02-28 09:30:53 +00:00
*
* @ method setText
2014-10-22 20:42:03 +00:00
* @ param text { String } The text that you would like displayed
2014-02-28 09:30:53 +00:00
* /
PIXI . BitmapText . prototype . setText = function ( text )
{
this . text = text || ' ' ;
this . dirty = true ;
} ;
/ * *
* Set the style of the text
* style . font { String } The size ( optional ) and bitmap font id ( required ) eq 'Arial' or '20px Arial' ( must have loaded previously )
2014-10-22 20:42:03 +00:00
* [ style . align = 'left' ] { String } Alignment for multiline text ( 'left' , 'center' or 'right' ) , does not affect single lines of text
2014-02-28 09:30:53 +00:00
*
* @ method setStyle
* @ param style { Object } The style parameters , contained as properties of an object
* /
PIXI . BitmapText . prototype . setStyle = function ( style )
{
style = style || { } ;
style . align = style . align || 'left' ;
this . style = style ;
var font = style . font . split ( ' ' ) ;
this . fontName = font [ font . length - 1 ] ;
this . fontSize = font . length >= 2 ? parseInt ( font [ font . length - 2 ] , 10 ) : PIXI . BitmapText . fonts [ this . fontName ] . size ;
this . dirty = true ;
this . tint = style . tint ;
} ;
/ * *
* Renders text and updates it when needed
*
* @ method updateText
* @ private
* /
PIXI . BitmapText . prototype . updateText = function ( )
{
var data = PIXI . BitmapText . fonts [ this . fontName ] ;
var pos = new PIXI . Point ( ) ;
var prevCharCode = null ;
var chars = [ ] ;
var maxLineWidth = 0 ;
var lineWidths = [ ] ;
var line = 0 ;
var scale = this . fontSize / data . size ;
for ( var i = 0 ; i < this . text . length ; i ++ )
{
var charCode = this . text . charCodeAt ( i ) ;
2014-10-22 20:42:03 +00:00
2014-02-28 09:30:53 +00:00
if ( /(?:\r\n|\r|\n)/ . test ( this . text . charAt ( i ) ) )
{
lineWidths . push ( pos . x ) ;
maxLineWidth = Math . max ( maxLineWidth , pos . x ) ;
line ++ ;
pos . x = 0 ;
pos . y += data . lineHeight ;
prevCharCode = null ;
continue ;
}
var charData = data . chars [ charCode ] ;
2014-10-22 20:42:03 +00:00
2014-02-28 09:30:53 +00:00
if ( ! charData ) continue ;
2014-10-22 20:42:03 +00:00
if ( prevCharCode && charData . kerning [ prevCharCode ] )
2014-02-28 09:30:53 +00:00
{
pos . x += charData . kerning [ prevCharCode ] ;
}
2014-10-22 20:42:03 +00:00
2014-02-28 09:30:53 +00:00
chars . push ( { texture : charData . texture , line : line , charCode : charCode , position : new PIXI . Point ( pos . x + charData . xOffset , pos . y + charData . yOffset ) } ) ;
pos . x += charData . xAdvance ;
prevCharCode = charCode ;
}
lineWidths . push ( pos . x ) ;
maxLineWidth = Math . max ( maxLineWidth , pos . x ) ;
var lineAlignOffsets = [ ] ;
2014-10-22 20:42:03 +00:00
2014-02-28 09:30:53 +00:00
for ( i = 0 ; i <= line ; i ++ )
{
var alignOffset = 0 ;
if ( this . style . align === 'right' )
{
alignOffset = maxLineWidth - lineWidths [ i ] ;
}
else if ( this . style . align === 'center' )
{
alignOffset = ( maxLineWidth - lineWidths [ i ] ) / 2 ;
}
lineAlignOffsets . push ( alignOffset ) ;
}
var lenChildren = this . children . length ;
var lenChars = chars . length ;
var tint = this . tint || 0xFFFFFF ;
2014-10-22 20:42:03 +00:00
2014-02-28 09:30:53 +00:00
for ( i = 0 ; i < lenChars ; i ++ )
{
var c = i < lenChildren ? this . children [ i ] : this . _pool . pop ( ) ; // get old child if have. if not - take from pool.
if ( c ) c . setTexture ( chars [ i ] . texture ) ; // check if got one before.
else c = new PIXI . Sprite ( chars [ i ] . texture ) ; // if no create new one.
c . position . x = ( chars [ i ] . position . x + lineAlignOffsets [ chars [ i ] . line ] ) * scale ;
c . position . y = chars [ i ] . position . y * scale ;
c . scale . x = c . scale . y = scale ;
c . tint = tint ;
if ( ! c . parent ) this . addChild ( c ) ;
}
// remove unnecessary children.
// and put their into the pool.
while ( this . children . length > lenChars )
{
var child = this . getChildAt ( this . children . length - 1 ) ;
this . _pool . push ( child ) ;
this . removeChild ( child ) ;
}
this . textWidth = maxLineWidth * scale ;
this . textHeight = ( pos . y + data . lineHeight ) * scale ;
} ;
/ * *
* Updates the transform of this object
*
* @ method updateTransform
* @ private
* /
PIXI . BitmapText . prototype . updateTransform = function ( )
{
if ( this . dirty )
{
this . updateText ( ) ;
this . dirty = false ;
}
PIXI . DisplayObjectContainer . prototype . updateTransform . call ( this ) ;
} ;
PIXI . BitmapText . fonts = { } ;
/ * *
* @ author Mat Groves http : //matgroves.com/ @Doormat23
* /
/ * *
* A Stage represents the root of the display tree . Everything connected to the stage is rendered
*
* @ class Stage
* @ extends DisplayObjectContainer
* @ constructor
* @ param backgroundColor { Number } the background color of the stage , you have to pass this in is in hex format
* like : 0xFFFFFF for white
2014-04-01 02:02:36 +00:00
*
* Creating a stage is a mandatory process when you use Pixi , which is as simple as this :
2014-02-28 09:30:53 +00:00
* var stage = new PIXI . Stage ( 0xFFFFFF ) ;
* where the parameter given is the background colour of the stage , in hex
* you will use this stage instance to add your sprites to it and therefore to the renderer
2014-04-01 02:02:36 +00:00
* Here is how to add a sprite to the stage :
2014-02-28 09:30:53 +00:00
* stage . addChild ( sprite ) ;
* /
PIXI . Stage = function ( backgroundColor )
{
PIXI . DisplayObjectContainer . call ( this ) ;
/ * *
* [ read - only ] Current transform of the object based on world ( parent ) factors
*
* @ property worldTransform
2014-10-22 20:42:03 +00:00
* @ type Matrix
2014-02-28 09:30:53 +00:00
* @ readOnly
* @ private
* /
this . worldTransform = new PIXI . Matrix ( ) ;
/ * *
* Whether or not the stage is interactive
*
* @ property interactive
* @ type Boolean
* /
this . interactive = true ;
/ * *
* The interaction manage for this stage , manages all interactive activity on the stage
*
2014-07-10 15:23:26 +00:00
* @ property interactionManager
2014-02-28 09:30:53 +00:00
* @ type InteractionManager
* /
this . interactionManager = new PIXI . InteractionManager ( this ) ;
/ * *
* Whether the stage is dirty and needs to have interactions updated
*
* @ property dirty
* @ type Boolean
* @ private
* /
this . dirty = true ;
//the stage is its own stage
this . stage = this ;
//optimize hit detection a bit
2014-10-22 20:42:03 +00:00
this . stage . hitArea = new PIXI . Rectangle ( 0 , 0 , 100000 , 100000 ) ;
2014-02-28 09:30:53 +00:00
this . setBackgroundColor ( backgroundColor ) ;
} ;
// constructor
PIXI . Stage . prototype = Object . create ( PIXI . DisplayObjectContainer . prototype ) ;
PIXI . Stage . prototype . constructor = PIXI . Stage ;
/ * *
* Sets another DOM element which can receive mouse / touch interactions instead of the default Canvas element .
* This is useful for when you have other DOM elements on top of the Canvas element .
*
* @ method setInteractionDelegate
* @ param domElement { DOMElement } This new domElement which will receive mouse / touch events
* /
PIXI . Stage . prototype . setInteractionDelegate = function ( domElement )
{
this . interactionManager . setTargetDomElement ( domElement ) ;
} ;
/ *
* Updates the object transform for rendering
*
* @ method updateTransform
* @ private
* /
PIXI . Stage . prototype . updateTransform = function ( )
{
this . worldAlpha = 1 ;
for ( var i = 0 , j = this . children . length ; i < j ; i ++ )
{
this . children [ i ] . updateTransform ( ) ;
}
if ( this . dirty )
{
this . dirty = false ;
// update interactive!
this . interactionManager . dirty = true ;
}
if ( this . interactive ) this . interactionManager . update ( ) ;
} ;
/ * *
* Sets the background color for the stage
*
* @ method setBackgroundColor
* @ param backgroundColor { Number } the color of the background , easiest way to pass this in is in hex format
* like : 0xFFFFFF for white
* /
PIXI . Stage . prototype . setBackgroundColor = function ( backgroundColor )
{
this . backgroundColor = backgroundColor || 0x000000 ;
this . backgroundColorSplit = PIXI . hex2rgb ( this . backgroundColor ) ;
var hex = this . backgroundColor . toString ( 16 ) ;
hex = '000000' . substr ( 0 , 6 - hex . length ) + hex ;
this . backgroundColorString = '#' + hex ;
} ;
/ * *
2014-10-22 20:42:03 +00:00
* This will return the point containing global coordinates of the mouse .
2014-02-28 09:30:53 +00:00
*
* @ method getMousePosition
2014-10-22 20:42:03 +00:00
* @ return { Point } A point containing the coordinates of the global InteractionData position .
2014-02-28 09:30:53 +00:00
* /
PIXI . Stage . prototype . getMousePosition = function ( )
{
return this . interactionManager . mouse . global ;
} ;
/ * *
* @ author Mat Groves http : //matgroves.com/ @Doormat23
* /
2014-04-01 02:02:36 +00:00
2014-02-28 09:30:53 +00:00
// http://paulirish.com/2011/requestanimationframe-for-smart-animating/
// http://my.opera.com/emoller/blog/2011/12/20/requestanimationframe-for-smart-er-animating
// requestAnimationFrame polyfill by Erik Möller. fixes from Paul Irish and Tino Zijdel
// MIT license
/ * *
* A polyfill for requestAnimationFrame
2014-04-01 02:02:36 +00:00
* You can actually use both requestAnimationFrame and requestAnimFrame ,
2014-02-28 09:30:53 +00:00
* you will still benefit from the polyfill
*
* @ method requestAnimationFrame
* /
2014-10-22 20:42:03 +00:00
2014-02-28 09:30:53 +00:00
/ * *
* A polyfill for cancelAnimationFrame
*
* @ method cancelAnimationFrame
* /
2014-08-29 17:13:33 +00:00
( function ( window ) {
var lastTime = 0 ;
var vendors = [ 'ms' , 'moz' , 'webkit' , 'o' ] ;
for ( var x = 0 ; x < vendors . length && ! window . requestAnimationFrame ; ++ x ) {
window . requestAnimationFrame = window [ vendors [ x ] + 'RequestAnimationFrame' ] ;
window . cancelAnimationFrame = window [ vendors [ x ] + 'CancelAnimationFrame' ] ||
window [ vendors [ x ] + 'CancelRequestAnimationFrame' ] ;
}
if ( ! window . requestAnimationFrame ) {
window . requestAnimationFrame = function ( callback ) {
var currTime = new Date ( ) . getTime ( ) ;
var timeToCall = Math . max ( 0 , 16 - ( currTime - lastTime ) ) ;
var id = window . setTimeout ( function ( ) { callback ( currTime + timeToCall ) ; } ,
timeToCall ) ;
lastTime = currTime + timeToCall ;
return id ;
} ;
}
2014-02-28 09:30:53 +00:00
2014-08-29 17:13:33 +00:00
if ( ! window . cancelAnimationFrame ) {
window . cancelAnimationFrame = function ( id ) {
clearTimeout ( id ) ;
} ;
}
2014-02-28 09:30:53 +00:00
2014-08-29 17:13:33 +00:00
window . requestAnimFrame = window . requestAnimationFrame ;
} ) ( this ) ;
2014-02-28 09:30:53 +00:00
/ * *
* Converts a hex color number to an [ R , G , B ] array
*
* @ method hex2rgb
* @ param hex { Number }
* /
PIXI . hex2rgb = function ( hex ) {
return [ ( hex >> 16 & 0xFF ) / 255 , ( hex >> 8 & 0xFF ) / 255 , ( hex & 0xFF ) / 255 ] ;
} ;
/ * *
* Converts a color as an [ R , G , B ] array to a hex number
*
* @ method rgb2hex
* @ param rgb { Array }
* /
PIXI . rgb2hex = function ( rgb ) {
return ( ( rgb [ 0 ] * 255 << 16 ) + ( rgb [ 1 ] * 255 << 8 ) + rgb [ 2 ] * 255 ) ;
} ;
/ * *
* A polyfill for Function . prototype . bind
*
* @ method bind
* /
if ( typeof Function . prototype . bind !== 'function' ) {
Function . prototype . bind = ( function ( ) {
return function ( thisArg ) {
2014-08-29 17:13:33 +00:00
var target = this , i = arguments . length - 1 , boundArgs = [ ] ;
if ( i > 0 )
{
boundArgs . length = i ;
while ( i -- ) boundArgs [ i ] = arguments [ i + 1 ] ;
}
2014-02-28 09:30:53 +00:00
if ( typeof target !== 'function' ) throw new TypeError ( ) ;
function bound ( ) {
2014-08-29 17:13:33 +00:00
var i = arguments . length , args = new Array ( i ) ;
while ( i -- ) args [ i ] = arguments [ i ] ;
args = boundArgs . concat ( args ) ;
2014-10-22 20:42:03 +00:00
return target . apply ( this instanceof bound ? this : thisArg , args ) ;
2014-02-28 09:30:53 +00:00
}
bound . prototype = ( function F ( proto ) {
if ( proto ) F . prototype = proto ;
if ( ! ( this instanceof F ) ) return new F ( ) ;
} ) ( target . prototype ) ;
return bound ;
} ;
} ) ( ) ;
}
/ * *
* A wrapper for ajax requests to be handled cross browser
*
* @ class AjaxRequest
* @ constructor
* /
PIXI . AjaxRequest = function ( )
{
var activexmodes = [ 'Msxml2.XMLHTTP.6.0' , 'Msxml2.XMLHTTP.3.0' , 'Microsoft.XMLHTTP' ] ; //activeX versions to check for in IE
if ( window . ActiveXObject )
{ //Test for support for ActiveXObject in IE first (as XMLHttpRequest in IE7 is broken)
for ( var i = 0 ; i < activexmodes . length ; i ++ )
{
try {
return new window . ActiveXObject ( activexmodes [ i ] ) ;
}
catch ( e ) {
//suppress error
}
}
}
else if ( window . XMLHttpRequest ) // if Mozilla, Safari etc
{
return new window . XMLHttpRequest ( ) ;
}
else
{
return false ;
}
} ;
/ *
PIXI . packColorRGBA = function ( r , g , b , a ) //r, g, b, a)
{
// console.log(r, b, c, d)
return ( Math . floor ( ( r ) * 63 ) << 18 ) | ( Math . floor ( ( g ) * 63 ) << 12 ) | ( Math . floor ( ( b ) * 63 ) << 6 ) ; // | (Math.floor((a)*63))
// i = i | (Math.floor((a)*63));
// return i;
// var r = (i / 262144.0 ) / 64;
// var g = (i / 4096.0)%64 / 64;
// var b = (i / 64.0)%64 / 64;
// var a = (i)%64 / 64;
2014-04-01 02:02:36 +00:00
2014-02-28 09:30:53 +00:00
// console.log(r, g, b, a);
// return i;
} ;
* /
/ *
PIXI . packColorRGB = function ( r , g , b ) //r, g, b, a)
{
return ( Math . floor ( ( r ) * 255 ) << 16 ) | ( Math . floor ( ( g ) * 255 ) << 8 ) | ( Math . floor ( ( b ) * 255 ) ) ;
} ;
PIXI . unpackColorRGB = function ( r , g , b ) //r, g, b, a)
{
return ( Math . floor ( ( r ) * 255 ) << 16 ) | ( Math . floor ( ( g ) * 255 ) << 8 ) | ( Math . floor ( ( b ) * 255 ) ) ;
} ;
* /
/ * *
* Checks whether the Canvas BlendModes are supported by the current browser
*
* @ method canUseNewCanvasBlendModes
* @ return { Boolean } whether they are supported
* /
PIXI . canUseNewCanvasBlendModes = function ( )
{
2014-08-29 17:13:33 +00:00
if ( typeof document === 'undefined' ) return false ;
2014-02-28 09:30:53 +00:00
var canvas = document . createElement ( 'canvas' ) ;
canvas . width = 1 ;
canvas . height = 1 ;
var context = canvas . getContext ( '2d' ) ;
context . fillStyle = '#000' ;
context . fillRect ( 0 , 0 , 1 , 1 ) ;
context . globalCompositeOperation = 'multiply' ;
context . fillStyle = '#fff' ;
context . fillRect ( 0 , 0 , 1 , 1 ) ;
return context . getImageData ( 0 , 0 , 1 , 1 ) . data [ 0 ] === 0 ;
} ;
/ * *
* Given a number , this function returns the closest number that is a power of two
* this function is taken from Starling Framework as its pretty neat ; )
*
* @ method getNextPowerOfTwo
* @ param number { Number }
* @ return { Number } the closest number that is a power of two
* /
PIXI . getNextPowerOfTwo = function ( number )
{
if ( number > 0 && ( number & ( number - 1 ) ) === 0 ) // see: http://goo.gl/D9kPj
return number ;
else
{
var result = 1 ;
while ( result < number ) result <<= 1 ;
return result ;
}
} ;
/ * *
* @ author Mat Groves http : //matgroves.com/ @Doormat23
2014-10-22 20:42:03 +00:00
* @ author Chad Engler https : //github.com/englercj @Rolnaaba
2014-02-28 09:30:53 +00:00
* /
2014-10-22 20:42:03 +00:00
2014-02-28 09:30:53 +00:00
/ * *
2014-10-22 20:42:03 +00:00
* Originally based on https : //github.com/mrdoob/eventtarget.js/ from mr Doob.
* Currently takes inspiration from the nodejs EventEmitter , EventEmitter3 , and smokesignals
2014-02-28 09:30:53 +00:00
* /
/ * *
2014-10-22 20:42:03 +00:00
* Mixins event emitter functionality to a class
2014-02-28 09:30:53 +00:00
*
* @ class EventTarget
* @ example
2014-10-22 20:42:03 +00:00
* function MyEmitter ( ) { }
*
* PIXI . EventTarget . mixin ( MyEmitter . prototype ) ;
2014-02-28 09:30:53 +00:00
*
* var em = new MyEmitter ( ) ;
2014-10-22 20:42:03 +00:00
* em . emit ( 'eventName' , 'some data' , 'some more data' , { } , null , ... ) ;
2014-02-28 09:30:53 +00:00
* /
2014-10-22 20:42:03 +00:00
PIXI . EventTarget = {
2014-02-28 09:30:53 +00:00
/ * *
2014-10-22 20:42:03 +00:00
* Backward compat from when this used to be a function
2014-02-28 09:30:53 +00:00
* /
2014-10-22 20:42:03 +00:00
call : function callCompat ( obj ) {
if ( obj ) {
obj = obj . prototype || obj ;
PIXI . EventTarget . mixin ( obj ) ;
}
} ,
2014-02-28 09:30:53 +00:00
/ * *
2014-10-22 20:42:03 +00:00
* Mixes in the properties of the EventTarget prototype onto another object
2014-02-28 09:30:53 +00:00
*
2014-10-22 20:42:03 +00:00
* @ method mixin
* @ param object { Object } The obj to mix into
2014-02-28 09:30:53 +00:00
* /
2014-10-22 20:42:03 +00:00
mixin : function mixin ( obj ) {
/ * *
* Return a list of assigned event listeners .
*
* @ method listeners
* @ param eventName { String } The events that should be listed .
2014-11-15 20:04:24 +00:00
* @ return { Array } An array of listener functions
2014-10-22 20:42:03 +00:00
* /
obj . listeners = function listeners ( eventName ) {
this . _listeners = this . _listeners || { } ;
2014-02-28 09:30:53 +00:00
2014-10-22 20:42:03 +00:00
return this . _listeners [ eventName ] ? this . _listeners [ eventName ] . slice ( ) : [ ] ;
} ;
2014-02-28 09:30:53 +00:00
2014-10-22 20:42:03 +00:00
/ * *
* Emit an event to all registered event listeners .
*
* @ method emit
* @ alias dispatchEvent
* @ param eventName { String } The name of the event .
2014-11-15 20:04:24 +00:00
* @ return { Boolean } Indication if we ' ve emitted an event .
2014-10-22 20:42:03 +00:00
* /
obj . emit = obj . dispatchEvent = function emit ( eventName , data ) {
this . _listeners = this . _listeners || { } ;
2014-02-28 09:30:53 +00:00
2014-10-22 20:42:03 +00:00
//backwards compat with old method ".emit({ type: 'something' })"
if ( typeof eventName === 'object' ) {
data = eventName ;
eventName = eventName . type ;
}
2014-02-28 09:30:53 +00:00
2014-10-22 20:42:03 +00:00
//ensure we are using a real pixi event
if ( ! data || data . _ _isEventObject !== true ) {
data = new PIXI . Event ( this , eventName , data ) ;
}
2014-02-28 09:30:53 +00:00
2014-10-22 20:42:03 +00:00
//iterate the listeners
if ( this . _listeners && this . _listeners [ eventName ] ) {
2014-11-08 19:26:34 +00:00
var listeners = this . _listeners [ eventName ] . slice ( 0 ) ,
2014-10-22 20:42:03 +00:00
length = listeners . length ,
fn = listeners [ 0 ] ,
i ;
2014-02-28 09:30:53 +00:00
2014-10-22 20:42:03 +00:00
for ( i = 0 ; i < length ; fn = listeners [ ++ i ] ) {
//call the event listener
fn . call ( this , data ) ;
2014-02-28 09:30:53 +00:00
2014-10-22 20:42:03 +00:00
//if "stopImmediatePropagation" is called, stop calling sibling events
if ( data . stoppedImmediate ) {
return this ;
}
}
2014-02-28 09:30:53 +00:00
2014-10-22 20:42:03 +00:00
//if "stopPropagation" is called then don't bubble the event
if ( data . stopped ) {
return this ;
}
}
2014-02-28 09:30:53 +00:00
2014-10-22 20:42:03 +00:00
//bubble this event up the scene graph
if ( this . parent && this . parent . emit ) {
this . parent . emit . call ( this . parent , eventName , data ) ;
}
2014-02-28 09:30:53 +00:00
2014-10-22 20:42:03 +00:00
return this ;
} ;
2014-02-28 09:30:53 +00:00
2014-10-22 20:42:03 +00:00
/ * *
* Register a new EventListener for the given event .
*
* @ method on
* @ alias addEventListener
* @ param eventName { String } Name of the event .
* @ param callback { Functon } fn Callback function .
* /
obj . on = obj . addEventListener = function on ( eventName , fn ) {
this . _listeners = this . _listeners || { } ;
2014-02-28 09:30:53 +00:00
2014-10-22 20:42:03 +00:00
( this . _listeners [ eventName ] = this . _listeners [ eventName ] || [ ] )
. push ( fn ) ;
2014-07-01 14:04:03 +00:00
2014-10-22 20:42:03 +00:00
return this ;
} ;
2014-07-01 14:04:03 +00:00
2014-10-22 20:42:03 +00:00
/ * *
* Add an EventListener that ' s only called once .
*
* @ method once
* @ param eventName { String } Name of the event .
* @ param callback { Function } Callback function .
* /
obj . once = function once ( eventName , fn ) {
this . _listeners = this . _listeners || { } ;
2014-02-28 09:30:53 +00:00
2014-10-22 20:42:03 +00:00
var self = this ;
function onceHandlerWrapper ( ) {
fn . apply ( self . off ( eventName , onceHandlerWrapper ) , arguments ) ;
}
onceHandlerWrapper . _originalHandler = fn ;
2014-02-28 09:30:53 +00:00
2014-10-22 20:42:03 +00:00
return this . on ( eventName , onceHandlerWrapper ) ;
} ;
2014-02-28 09:30:53 +00:00
2014-10-22 20:42:03 +00:00
/ * *
* Remove event listeners .
*
* @ method off
* @ alias removeEventListener
* @ param eventName { String } The event we want to remove .
* @ param callback { Function } The listener that we need to find .
* /
obj . off = obj . removeEventListener = function off ( eventName , fn ) {
this . _listeners = this . _listeners || { } ;
2014-02-28 09:30:53 +00:00
2014-10-22 20:42:03 +00:00
if ( ! this . _listeners [ eventName ] )
return this ;
2014-02-28 09:30:53 +00:00
2014-10-22 20:42:03 +00:00
var list = this . _listeners [ eventName ] ,
i = fn ? list . length : 0 ;
2014-07-10 15:23:26 +00:00
2014-10-22 20:42:03 +00:00
while ( i -- > 0 ) {
if ( list [ i ] === fn || list [ i ] . _originalHandler === fn ) {
list . splice ( i , 1 ) ;
}
}
2014-02-28 09:30:53 +00:00
2014-10-22 20:42:03 +00:00
if ( list . length === 0 ) {
delete this . _listeners [ eventName ] ;
}
2014-02-28 09:30:53 +00:00
2014-10-22 20:42:03 +00:00
return this ;
} ;
2014-02-28 09:30:53 +00:00
2014-10-22 20:42:03 +00:00
/ * *
* Remove all listeners or only the listeners for the specified event .
*
* @ method removeAllListeners
* @ param eventName { String } The event you want to remove all listeners for .
* /
obj . removeAllListeners = function removeAllListeners ( eventName ) {
this . _listeners = this . _listeners || { } ;
2014-02-28 09:30:53 +00:00
2014-10-22 20:42:03 +00:00
if ( ! this . _listeners [ eventName ] )
return this ;
delete this . _listeners [ eventName ] ;
return this ;
} ;
}
} ;
/ * *
* Creates an homogenous object for tracking events so users can know what to expect .
*
* @ class Event
* @ extends Object
* @ constructor
* @ param target { Object } The target object that the event is called on
* @ param name { String } The string name of the event that was triggered
* @ param data { Object } Arbitrary event data to pass along
* /
PIXI . Event = function ( target , name , data ) {
//for duck typing in the ".on()" function
this . _ _isEventObject = true ;
2014-02-28 09:30:53 +00:00
/ * *
2014-10-22 20:42:03 +00:00
* Tracks the state of bubbling propagation . Do not
* set this directly , instead use ` event.stopPropagation() `
2014-02-28 09:30:53 +00:00
*
2014-10-22 20:42:03 +00:00
* @ property stopped
* @ type Boolean
* @ private
* @ readOnly
2014-02-28 09:30:53 +00:00
* /
2014-10-22 20:42:03 +00:00
this . stopped = false ;
2014-02-28 09:30:53 +00:00
2014-10-22 20:42:03 +00:00
/ * *
* Tracks the state of sibling listener propagation . Do not
* set this directly , instead use ` event.stopImmediatePropagation() `
*
* @ property stoppedImmediate
* @ type Boolean
* @ private
* @ readOnly
* /
this . stoppedImmediate = false ;
2014-02-28 09:30:53 +00:00
2014-10-22 20:42:03 +00:00
/ * *
* The original target the event triggered on .
*
* @ property target
* @ type Object
* @ readOnly
* /
this . target = target ;
2014-02-28 09:30:53 +00:00
2014-10-22 20:42:03 +00:00
/ * *
* The string name of the event that this represents .
*
* @ property type
* @ type String
* @ readOnly
* /
this . type = name ;
/ * *
* The data that was passed in with this event .
*
* @ property data
* @ type Object
* @ readOnly
* /
this . data = data ;
//backwards compat with older version of events
this . content = data ;
/ * *
* The timestamp when the event occurred .
*
* @ property timeStamp
* @ type Number
* @ readOnly
* /
this . timeStamp = Date . now ( ) ;
} ;
/ * *
* Stops the propagation of events up the scene graph ( prevents bubbling ) .
*
* @ method stopPropagation
* /
PIXI . Event . prototype . stopPropagation = function stopPropagation ( ) {
this . stopped = true ;
} ;
/ * *
* Stops the propagation of events to sibling listeners ( no longer calls any listeners ) .
*
* @ method stopImmediatePropagation
* /
PIXI . Event . prototype . stopImmediatePropagation = function stopImmediatePropagation ( ) {
this . stoppedImmediate = true ;
} ;
/ *
PolyK library
url : http : //polyk.ivank.net
Released under MIT licence .
Copyright ( c ) 2012 Ivan Kuckir
Permission is hereby granted , free of charge , to any person
obtaining a copy of this software and associated documentation
files ( the "Software" ) , to deal in the Software without
restriction , including without limitation the rights to use ,
copy , modify , merge , publish , distribute , sublicense , and / or sell
copies of the Software , and to permit persons to whom the
Software is furnished to do so , subject to the following
conditions :
2014-02-28 09:30:53 +00:00
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software .
THE SOFTWARE IS PROVIDED "AS IS" , WITHOUT WARRANTY OF ANY KIND ,
EXPRESS OR IMPLIED , INCLUDING BUT NOT LIMITED TO THE WARRANTIES
OF MERCHANTABILITY , FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT . IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
HOLDERS BE LIABLE FOR ANY CLAIM , DAMAGES OR OTHER LIABILITY ,
WHETHER IN AN ACTION OF CONTRACT , TORT OR OTHERWISE , ARISING
FROM , OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
OTHER DEALINGS IN THE SOFTWARE .
This is an amazing lib !
2014-10-22 20:42:03 +00:00
Slightly modified by Mat Groves ( matgroves . com ) ;
2014-02-28 09:30:53 +00:00
* /
/ * *
* Based on the Polyk library http : //polyk.ivank.net released under MIT licence.
* This is an amazing lib !
2014-10-22 20:42:03 +00:00
* Slightly modified by Mat Groves ( matgroves . com ) ;
2014-02-28 09:30:53 +00:00
* @ class PolyK
* /
PIXI . PolyK = { } ;
/ * *
2014-10-22 20:42:03 +00:00
* Triangulates shapes for webGL graphic fills .
2014-02-28 09:30:53 +00:00
*
* @ method Triangulate
* /
PIXI . PolyK . Triangulate = function ( p )
{
var sign = true ;
var n = p . length >> 1 ;
if ( n < 3 ) return [ ] ;
var tgs = [ ] ;
var avl = [ ] ;
for ( var i = 0 ; i < n ; i ++ ) avl . push ( i ) ;
i = 0 ;
var al = n ;
while ( al > 3 )
{
var i0 = avl [ ( i + 0 ) % al ] ;
var i1 = avl [ ( i + 1 ) % al ] ;
var i2 = avl [ ( i + 2 ) % al ] ;
var ax = p [ 2 * i0 ] , ay = p [ 2 * i0 + 1 ] ;
var bx = p [ 2 * i1 ] , by = p [ 2 * i1 + 1 ] ;
var cx = p [ 2 * i2 ] , cy = p [ 2 * i2 + 1 ] ;
var earFound = false ;
if ( PIXI . PolyK . _convex ( ax , ay , bx , by , cx , cy , sign ) )
{
earFound = true ;
for ( var j = 0 ; j < al ; j ++ )
{
var vi = avl [ j ] ;
if ( vi === i0 || vi === i1 || vi === i2 ) continue ;
if ( PIXI . PolyK . _PointInTriangle ( p [ 2 * vi ] , p [ 2 * vi + 1 ] , ax , ay , bx , by , cx , cy ) ) {
earFound = false ;
break ;
}
}
}
if ( earFound )
{
tgs . push ( i0 , i1 , i2 ) ;
avl . splice ( ( i + 1 ) % al , 1 ) ;
al -- ;
i = 0 ;
}
else if ( i ++ > 3 * al )
{
// need to flip flip reverse it!
// reset!
if ( sign )
{
tgs = [ ] ;
avl = [ ] ;
for ( i = 0 ; i < n ; i ++ ) avl . push ( i ) ;
i = 0 ;
al = n ;
sign = false ;
}
else
{
2014-11-12 22:49:36 +00:00
// window.console.log("PIXI Warning: shape too complex to fill");
return null ;
2014-02-28 09:30:53 +00:00
}
}
}
tgs . push ( avl [ 0 ] , avl [ 1 ] , avl [ 2 ] ) ;
return tgs ;
} ;
/ * *
* Checks whether a point is within a triangle
*
* @ method _PointInTriangle
* @ param px { Number } x coordinate of the point to test
* @ param py { Number } y coordinate of the point to test
* @ param ax { Number } x coordinate of the a point of the triangle
* @ param ay { Number } y coordinate of the a point of the triangle
* @ param bx { Number } x coordinate of the b point of the triangle
* @ param by { Number } y coordinate of the b point of the triangle
* @ param cx { Number } x coordinate of the c point of the triangle
* @ param cy { Number } y coordinate of the c point of the triangle
* @ private
2014-10-22 20:42:03 +00:00
* @ return { Boolean }
2014-02-28 09:30:53 +00:00
* /
PIXI . PolyK . _PointInTriangle = function ( px , py , ax , ay , bx , by , cx , cy )
{
var v0x = cx - ax ;
var v0y = cy - ay ;
var v1x = bx - ax ;
var v1y = by - ay ;
var v2x = px - ax ;
var v2y = py - ay ;
var dot00 = v0x * v0x + v0y * v0y ;
var dot01 = v0x * v1x + v0y * v1y ;
var dot02 = v0x * v2x + v0y * v2y ;
var dot11 = v1x * v1x + v1y * v1y ;
var dot12 = v1x * v2x + v1y * v2y ;
var invDenom = 1 / ( dot00 * dot11 - dot01 * dot01 ) ;
var u = ( dot11 * dot02 - dot01 * dot12 ) * invDenom ;
var v = ( dot00 * dot12 - dot01 * dot02 ) * invDenom ;
// Check if point is in triangle
return ( u >= 0 ) && ( v >= 0 ) && ( u + v < 1 ) ;
} ;
/ * *
* Checks whether a shape is convex
*
* @ method _convex
* @ private
2014-10-22 20:42:03 +00:00
* @ return { Boolean }
2014-02-28 09:30:53 +00:00
* /
PIXI . PolyK . _convex = function ( ax , ay , bx , by , cx , cy , sign )
{
return ( ( ay - by ) * ( cx - bx ) + ( bx - ax ) * ( cy - by ) >= 0 ) === sign ;
} ;
/ * *
* @ author Mat Groves http : //matgroves.com/ @Doormat23
* /
2014-10-22 20:42:03 +00:00
/ * *
* @ method initDefaultShaders
* @ static
* @ private
* /
2014-02-28 09:30:53 +00:00
PIXI . initDefaultShaders = function ( )
{
} ;
2014-10-22 20:42:03 +00:00
/ * *
* @ method CompileVertexShader
* @ static
* @ param gl { WebGLContext } the current WebGL drawing context
* @ param shaderSrc { Array }
* @ return { Any }
* /
2014-02-28 09:30:53 +00:00
PIXI . CompileVertexShader = function ( gl , shaderSrc )
{
return PIXI . _CompileShader ( gl , shaderSrc , gl . VERTEX _SHADER ) ;
} ;
2014-10-22 20:42:03 +00:00
/ * *
* @ method CompileFragmentShader
* @ static
* @ param gl { WebGLContext } the current WebGL drawing context
* @ param shaderSrc { Array }
* @ return { Any }
* /
2014-02-28 09:30:53 +00:00
PIXI . CompileFragmentShader = function ( gl , shaderSrc )
{
return PIXI . _CompileShader ( gl , shaderSrc , gl . FRAGMENT _SHADER ) ;
} ;
2014-10-22 20:42:03 +00:00
/ * *
* @ method _CompileShader
* @ static
* @ private
* @ param gl { WebGLContext } the current WebGL drawing context
* @ param shaderSrc { Array }
* @ param shaderType { Number }
* @ return { Any }
* /
2014-02-28 09:30:53 +00:00
PIXI . _CompileShader = function ( gl , shaderSrc , shaderType )
{
var src = shaderSrc . join ( "\n" ) ;
var shader = gl . createShader ( shaderType ) ;
gl . shaderSource ( shader , src ) ;
gl . compileShader ( shader ) ;
2014-10-22 20:42:03 +00:00
if ( ! gl . getShaderParameter ( shader , gl . COMPILE _STATUS ) )
{
2014-02-28 09:30:53 +00:00
window . console . log ( gl . getShaderInfoLog ( shader ) ) ;
return null ;
}
return shader ;
} ;
2014-10-22 20:42:03 +00:00
/ * *
* @ method compileProgram
* @ static
* @ param gl { WebGLContext } the current WebGL drawing context
* @ param vertexSrc { Array }
* @ param fragmentSrc { Array }
* @ return { Any }
* /
2014-02-28 09:30:53 +00:00
PIXI . compileProgram = function ( gl , vertexSrc , fragmentSrc )
{
var fragmentShader = PIXI . CompileFragmentShader ( gl , fragmentSrc ) ;
var vertexShader = PIXI . CompileVertexShader ( gl , vertexSrc ) ;
var shaderProgram = gl . createProgram ( ) ;
gl . attachShader ( shaderProgram , vertexShader ) ;
gl . attachShader ( shaderProgram , fragmentShader ) ;
gl . linkProgram ( shaderProgram ) ;
2014-10-22 20:42:03 +00:00
if ( ! gl . getProgramParameter ( shaderProgram , gl . LINK _STATUS ) )
{
2014-02-28 09:30:53 +00:00
window . console . log ( "Could not initialise shaders" ) ;
}
return shaderProgram ;
} ;
/ * *
* @ author Mat Groves http : //matgroves.com/ @Doormat23
* @ author Richard Davey http : //www.photonstorm.com @photonstorm
* /
/ * *
* @ class PixiShader
* @ constructor
2014-10-22 20:42:03 +00:00
* @ param gl { WebGLContext } the current WebGL drawing context
2014-02-28 09:30:53 +00:00
* /
PIXI . PixiShader = function ( gl )
{
2014-10-22 20:42:03 +00:00
/ * *
* @ property _UID
* @ type Number
* @ private
* /
2014-07-01 14:04:03 +00:00
this . _UID = PIXI . _UID ++ ;
2014-11-12 22:49:36 +00:00
2014-02-28 09:30:53 +00:00
/ * *
* @ property gl
* @ type WebGLContext
* /
this . gl = gl ;
/ * *
2014-10-22 20:42:03 +00:00
* The WebGL program .
* @ property program
2014-11-15 20:04:24 +00:00
* @ type Any
2014-10-22 20:42:03 +00:00
* /
2014-02-28 09:30:53 +00:00
this . program = null ;
/ * *
2014-10-22 20:42:03 +00:00
* The fragment shader .
* @ property fragmentSrc
* @ type Array
* /
2014-02-28 09:30:53 +00:00
this . fragmentSrc = [
'precision lowp float;' ,
'varying vec2 vTextureCoord;' ,
'varying vec4 vColor;' ,
'uniform sampler2D uSampler;' ,
'void main(void) {' ,
' gl_FragColor = texture2D(uSampler, vTextureCoord) * vColor ;' ,
'}'
] ;
/ * *
2014-10-22 20:42:03 +00:00
* A local texture counter for multi - texture shaders .
* @ property textureCount
* @ type Number
* /
2014-02-28 09:30:53 +00:00
this . textureCount = 0 ;
2014-10-22 20:42:03 +00:00
/ * *
* A local flag
* @ property firstRun
* @ type Boolean
* @ private
* /
this . firstRun = true ;
/ * *
* A dirty flag
* @ property dirty
* @ type Boolean
* /
this . dirty = true ;
/ * *
* Uniform attributes cache .
* @ property attributes
* @ type Array
* @ private
* /
2014-02-28 09:30:53 +00:00
this . attributes = [ ] ;
this . init ( ) ;
} ;
2014-10-22 20:42:03 +00:00
PIXI . PixiShader . prototype . constructor = PIXI . PixiShader ;
2014-02-28 09:30:53 +00:00
/ * *
2014-10-22 20:42:03 +00:00
* Initialises the shader .
2014-11-12 22:49:36 +00:00
*
2014-02-28 09:30:53 +00:00
* @ method init
* /
PIXI . PixiShader . prototype . init = function ( )
{
var gl = this . gl ;
var program = PIXI . compileProgram ( gl , this . vertexSrc || PIXI . PixiShader . defaultVertexSrc , this . fragmentSrc ) ;
2014-11-12 22:49:36 +00:00
2014-02-28 09:30:53 +00:00
gl . useProgram ( program ) ;
// get and store the uniforms for the shader
this . uSampler = gl . getUniformLocation ( program , 'uSampler' ) ;
this . projectionVector = gl . getUniformLocation ( program , 'projectionVector' ) ;
this . offsetVector = gl . getUniformLocation ( program , 'offsetVector' ) ;
this . dimensions = gl . getUniformLocation ( program , 'dimensions' ) ;
// get and store the attributes
this . aVertexPosition = gl . getAttribLocation ( program , 'aVertexPosition' ) ;
this . aTextureCoord = gl . getAttribLocation ( program , 'aTextureCoord' ) ;
this . colorAttribute = gl . getAttribLocation ( program , 'aColor' ) ;
// Begin worst hack eva //
// WHY??? ONLY on my chrome pixel the line above returns -1 when using filters?
// maybe its something to do with the current state of the gl context.
2014-10-22 20:42:03 +00:00
// I'm convinced this is a bug in the chrome browser as there is NO reason why this should be returning -1 especially as it only manifests on my chrome pixel
2014-02-28 09:30:53 +00:00
// If theres any webGL people that know why could happen please help :)
if ( this . colorAttribute === - 1 )
{
this . colorAttribute = 2 ;
}
this . attributes = [ this . aVertexPosition , this . aTextureCoord , this . colorAttribute ] ;
// End worst hack eva //
// add those custom shaders!
for ( var key in this . uniforms )
{
// get the uniform locations..
this . uniforms [ key ] . uniformLocation = gl . getUniformLocation ( program , key ) ;
}
this . initUniforms ( ) ;
this . program = program ;
} ;
/ * *
* Initialises the shader uniform values .
2014-11-12 22:49:36 +00:00
*
2014-02-28 09:30:53 +00:00
* Uniforms are specified in the GLSL _ES Specification : http : //www.khronos.org/registry/webgl/specs/latest/1.0/
* http : //www.khronos.org/registry/gles/specs/2.0/GLSL_ES_Specification_1.0.17.pdf
*
* @ method initUniforms
* /
PIXI . PixiShader . prototype . initUniforms = function ( )
{
this . textureCount = 1 ;
var gl = this . gl ;
var uniform ;
for ( var key in this . uniforms )
{
uniform = this . uniforms [ key ] ;
var type = uniform . type ;
if ( type === 'sampler2D' )
{
uniform . _init = false ;
if ( uniform . value !== null )
{
this . initSampler2D ( uniform ) ;
}
}
else if ( type === 'mat2' || type === 'mat3' || type === 'mat4' )
{
// These require special handling
uniform . glMatrix = true ;
uniform . glValueLength = 1 ;
if ( type === 'mat2' )
{
uniform . glFunc = gl . uniformMatrix2fv ;
}
else if ( type === 'mat3' )
{
uniform . glFunc = gl . uniformMatrix3fv ;
}
else if ( type === 'mat4' )
{
uniform . glFunc = gl . uniformMatrix4fv ;
}
}
else
{
// GL function reference
uniform . glFunc = gl [ 'uniform' + type ] ;
if ( type === '2f' || type === '2i' )
{
uniform . glValueLength = 2 ;
}
else if ( type === '3f' || type === '3i' )
{
uniform . glValueLength = 3 ;
}
else if ( type === '4f' || type === '4i' )
{
uniform . glValueLength = 4 ;
}
else
{
uniform . glValueLength = 1 ;
}
}
}
} ;
/ * *
* Initialises a Sampler2D uniform ( which may only be available later on after initUniforms once the texture has loaded )
*
* @ method initSampler2D
* /
PIXI . PixiShader . prototype . initSampler2D = function ( uniform )
{
if ( ! uniform . value || ! uniform . value . baseTexture || ! uniform . value . baseTexture . hasLoaded )
{
return ;
}
var gl = this . gl ;
gl . activeTexture ( gl [ 'TEXTURE' + this . textureCount ] ) ;
gl . bindTexture ( gl . TEXTURE _2D , uniform . value . baseTexture . _glTextures [ gl . id ] ) ;
// Extended texture data
if ( uniform . textureData )
{
var data = uniform . textureData ;
// GLTexture = mag linear, min linear_mipmap_linear, wrap repeat + gl.generateMipmap(gl.TEXTURE_2D);
// GLTextureLinear = mag/min linear, wrap clamp
// GLTextureNearestRepeat = mag/min NEAREST, wrap repeat
// GLTextureNearest = mag/min nearest, wrap clamp
// AudioTexture = whatever + luminance + width 512, height 2, border 0
// KeyTexture = whatever + luminance + width 256, height 2, border 0
// magFilter can be: gl.LINEAR, gl.LINEAR_MIPMAP_LINEAR or gl.NEAREST
// wrapS/T can be: gl.CLAMP_TO_EDGE or gl.REPEAT
var magFilter = ( data . magFilter ) ? data . magFilter : gl . LINEAR ;
var minFilter = ( data . minFilter ) ? data . minFilter : gl . LINEAR ;
var wrapS = ( data . wrapS ) ? data . wrapS : gl . CLAMP _TO _EDGE ;
var wrapT = ( data . wrapT ) ? data . wrapT : gl . CLAMP _TO _EDGE ;
var format = ( data . luminance ) ? gl . LUMINANCE : gl . RGBA ;
if ( data . repeat )
{
wrapS = gl . REPEAT ;
wrapT = gl . REPEAT ;
}
gl . pixelStorei ( gl . UNPACK _FLIP _Y _WEBGL , ! ! data . flipY ) ;
if ( data . width )
{
var width = ( data . width ) ? data . width : 512 ;
var height = ( data . height ) ? data . height : 2 ;
var border = ( data . border ) ? data . border : 0 ;
// void texImage2D(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, ArrayBufferView? pixels);
gl . texImage2D ( gl . TEXTURE _2D , 0 , format , width , height , border , format , gl . UNSIGNED _BYTE , null ) ;
}
else
{
// void texImage2D(GLenum target, GLint level, GLenum internalformat, GLenum format, GLenum type, ImageData? pixels);
gl . texImage2D ( gl . TEXTURE _2D , 0 , format , gl . RGBA , gl . UNSIGNED _BYTE , uniform . value . baseTexture . source ) ;
}
gl . texParameteri ( gl . TEXTURE _2D , gl . TEXTURE _MAG _FILTER , magFilter ) ;
gl . texParameteri ( gl . TEXTURE _2D , gl . TEXTURE _MIN _FILTER , minFilter ) ;
gl . texParameteri ( gl . TEXTURE _2D , gl . TEXTURE _WRAP _S , wrapS ) ;
gl . texParameteri ( gl . TEXTURE _2D , gl . TEXTURE _WRAP _T , wrapT ) ;
}
gl . uniform1i ( uniform . uniformLocation , this . textureCount ) ;
uniform . _init = true ;
this . textureCount ++ ;
} ;
/ * *
* Updates the shader uniform values .
*
* @ method syncUniforms
* /
PIXI . PixiShader . prototype . syncUniforms = function ( )
{
this . textureCount = 1 ;
var uniform ;
var gl = this . gl ;
// This would probably be faster in an array and it would guarantee key order
for ( var key in this . uniforms )
{
uniform = this . uniforms [ key ] ;
if ( uniform . glValueLength === 1 )
{
if ( uniform . glMatrix === true )
{
uniform . glFunc . call ( gl , uniform . uniformLocation , uniform . transpose , uniform . value ) ;
}
else
{
uniform . glFunc . call ( gl , uniform . uniformLocation , uniform . value ) ;
}
}
else if ( uniform . glValueLength === 2 )
{
uniform . glFunc . call ( gl , uniform . uniformLocation , uniform . value . x , uniform . value . y ) ;
}
else if ( uniform . glValueLength === 3 )
{
uniform . glFunc . call ( gl , uniform . uniformLocation , uniform . value . x , uniform . value . y , uniform . value . z ) ;
}
else if ( uniform . glValueLength === 4 )
{
uniform . glFunc . call ( gl , uniform . uniformLocation , uniform . value . x , uniform . value . y , uniform . value . z , uniform . value . w ) ;
}
else if ( uniform . type === 'sampler2D' )
{
if ( uniform . _init )
{
gl . activeTexture ( gl [ 'TEXTURE' + this . textureCount ] ) ;
2014-10-22 20:42:03 +00:00
if ( uniform . value . baseTexture . _dirty [ gl . id ] )
{
2014-11-12 22:49:36 +00:00
PIXI . instances [ gl . id ] . updateTexture ( uniform . value . baseTexture ) ;
2014-10-22 20:42:03 +00:00
}
else
{
// bind the current texture
gl . bindTexture ( gl . TEXTURE _2D , uniform . value . baseTexture . _glTextures [ gl . id ] ) ;
}
// gl.bindTexture(gl.TEXTURE_2D, uniform.value.baseTexture._glTextures[gl.id] || PIXI.createWebGLTexture( uniform.value.baseTexture, gl));
2014-02-28 09:30:53 +00:00
gl . uniform1i ( uniform . uniformLocation , this . textureCount ) ;
this . textureCount ++ ;
}
else
{
this . initSampler2D ( uniform ) ;
}
}
}
} ;
/ * *
2014-10-22 20:42:03 +00:00
* Destroys the shader .
2014-11-12 22:49:36 +00:00
*
2014-02-28 09:30:53 +00:00
* @ method destroy
* /
PIXI . PixiShader . prototype . destroy = function ( )
{
this . gl . deleteProgram ( this . program ) ;
this . uniforms = null ;
this . gl = null ;
this . attributes = null ;
} ;
/ * *
2014-10-22 20:42:03 +00:00
* The Default Vertex shader source .
2014-11-12 22:49:36 +00:00
*
2014-02-28 09:30:53 +00:00
* @ property defaultVertexSrc
* @ type String
* /
PIXI . PixiShader . defaultVertexSrc = [
'attribute vec2 aVertexPosition;' ,
'attribute vec2 aTextureCoord;' ,
2014-11-15 20:04:24 +00:00
'attribute vec2 aColor;' ,
2014-02-28 09:30:53 +00:00
'uniform vec2 projectionVector;' ,
'uniform vec2 offsetVector;' ,
'varying vec2 vTextureCoord;' ,
'varying vec4 vColor;' ,
'const vec2 center = vec2(-1.0, 1.0);' ,
'void main(void) {' ,
' gl_Position = vec4( ((aVertexPosition + offsetVector) / projectionVector) + center , 0.0, 1.0);' ,
' vTextureCoord = aTextureCoord;' ,
' vec3 color = mod(vec3(aColor.y/65536.0, aColor.y/256.0, aColor.y), 256.0) / 256.0;' ,
' vColor = vec4(color * aColor.x, aColor.x);' ,
'}'
] ;
/ * *
* @ author Mat Groves http : //matgroves.com/ @Doormat23
* /
/ * *
* @ class PixiFastShader
* @ constructor
* @ param gl { WebGLContext } the current WebGL drawing context
* /
PIXI . PixiFastShader = function ( gl )
{
2014-10-22 20:42:03 +00:00
/ * *
* @ property _UID
* @ type Number
* @ private
* /
2014-07-01 14:04:03 +00:00
this . _UID = PIXI . _UID ++ ;
2014-02-28 09:30:53 +00:00
/ * *
* @ property gl
* @ type WebGLContext
* /
this . gl = gl ;
/ * *
2014-10-22 20:42:03 +00:00
* The WebGL program .
* @ property program
2014-11-15 20:04:24 +00:00
* @ type Any
2014-02-28 09:30:53 +00:00
* /
this . program = null ;
/ * *
2014-10-22 20:42:03 +00:00
* The fragment shader .
* @ property fragmentSrc
* @ type Array
2014-02-28 09:30:53 +00:00
* /
this . fragmentSrc = [
'precision lowp float;' ,
'varying vec2 vTextureCoord;' ,
'varying float vColor;' ,
'uniform sampler2D uSampler;' ,
'void main(void) {' ,
' gl_FragColor = texture2D(uSampler, vTextureCoord) * vColor ;' ,
'}'
] ;
/ * *
2014-10-22 20:42:03 +00:00
* The vertex shader .
* @ property vertexSrc
* @ type Array
* /
2014-02-28 09:30:53 +00:00
this . vertexSrc = [
'attribute vec2 aVertexPosition;' ,
'attribute vec2 aPositionCoord;' ,
'attribute vec2 aScale;' ,
'attribute float aRotation;' ,
'attribute vec2 aTextureCoord;' ,
'attribute float aColor;' ,
'uniform vec2 projectionVector;' ,
'uniform vec2 offsetVector;' ,
'uniform mat3 uMatrix;' ,
'varying vec2 vTextureCoord;' ,
'varying float vColor;' ,
'const vec2 center = vec2(-1.0, 1.0);' ,
'void main(void) {' ,
' vec2 v;' ,
' vec2 sv = aVertexPosition * aScale;' ,
' v.x = (sv.x) * cos(aRotation) - (sv.y) * sin(aRotation);' ,
' v.y = (sv.x) * sin(aRotation) + (sv.y) * cos(aRotation);' ,
' v = ( uMatrix * vec3(v + aPositionCoord , 1.0) ).xy ;' ,
' gl_Position = vec4( ( v / projectionVector) + center , 0.0, 1.0);' ,
' vTextureCoord = aTextureCoord;' ,
// ' vec3 color = mod(vec3(aColor.y/65536.0, aColor.y/256.0, aColor.y), 256.0) / 256.0;',
' vColor = aColor;' ,
'}'
] ;
/ * *
2014-10-22 20:42:03 +00:00
* A local texture counter for multi - texture shaders .
* @ property textureCount
* @ type Number
* /
2014-02-28 09:30:53 +00:00
this . textureCount = 0 ;
2014-04-01 02:02:36 +00:00
2014-02-28 09:30:53 +00:00
this . init ( ) ;
} ;
2014-10-22 20:42:03 +00:00
PIXI . PixiFastShader . prototype . constructor = PIXI . PixiFastShader ;
2014-02-28 09:30:53 +00:00
/ * *
2014-10-22 20:42:03 +00:00
* Initialises the shader .
*
2014-02-28 09:30:53 +00:00
* @ method init
* /
PIXI . PixiFastShader . prototype . init = function ( )
{
var gl = this . gl ;
var program = PIXI . compileProgram ( gl , this . vertexSrc , this . fragmentSrc ) ;
2014-04-01 02:02:36 +00:00
2014-02-28 09:30:53 +00:00
gl . useProgram ( program ) ;
// get and store the uniforms for the shader
this . uSampler = gl . getUniformLocation ( program , 'uSampler' ) ;
this . projectionVector = gl . getUniformLocation ( program , 'projectionVector' ) ;
this . offsetVector = gl . getUniformLocation ( program , 'offsetVector' ) ;
this . dimensions = gl . getUniformLocation ( program , 'dimensions' ) ;
this . uMatrix = gl . getUniformLocation ( program , 'uMatrix' ) ;
// get and store the attributes
this . aVertexPosition = gl . getAttribLocation ( program , 'aVertexPosition' ) ;
this . aPositionCoord = gl . getAttribLocation ( program , 'aPositionCoord' ) ;
this . aScale = gl . getAttribLocation ( program , 'aScale' ) ;
this . aRotation = gl . getAttribLocation ( program , 'aRotation' ) ;
this . aTextureCoord = gl . getAttribLocation ( program , 'aTextureCoord' ) ;
this . colorAttribute = gl . getAttribLocation ( program , 'aColor' ) ;
2014-04-01 02:02:36 +00:00
2014-02-28 09:30:53 +00:00
// Begin worst hack eva //
// WHY??? ONLY on my chrome pixel the line above returns -1 when using filters?
// maybe its somthing to do with the current state of the gl context.
// Im convinced this is a bug in the chrome browser as there is NO reason why this should be returning -1 especially as it only manifests on my chrome pixel
// If theres any webGL people that know why could happen please help :)
if ( this . colorAttribute === - 1 )
{
this . colorAttribute = 2 ;
}
this . attributes = [ this . aVertexPosition , this . aPositionCoord , this . aScale , this . aRotation , this . aTextureCoord , this . colorAttribute ] ;
2014-04-01 02:02:36 +00:00
2014-02-28 09:30:53 +00:00
// End worst hack eva //
this . program = program ;
} ;
/ * *
2014-10-22 20:42:03 +00:00
* Destroys the shader .
*
2014-02-28 09:30:53 +00:00
* @ method destroy
* /
PIXI . PixiFastShader . prototype . destroy = function ( )
{
this . gl . deleteProgram ( this . program ) ;
this . uniforms = null ;
this . gl = null ;
this . attributes = null ;
} ;
/ * *
* @ author Mat Groves http : //matgroves.com/ @Doormat23
* /
2014-10-22 20:42:03 +00:00
/ * *
* @ class StripShader
* @ constructor
* @ param gl { WebGLContext } the current WebGL drawing context
* /
2014-07-01 14:04:03 +00:00
PIXI . StripShader = function ( gl )
2014-02-28 09:30:53 +00:00
{
2014-10-22 20:42:03 +00:00
/ * *
* @ property _UID
* @ type Number
* @ private
* /
2014-07-01 14:04:03 +00:00
this . _UID = PIXI . _UID ++ ;
2014-10-22 20:42:03 +00:00
/ * *
* @ property gl
* @ type WebGLContext
* /
2014-07-01 14:04:03 +00:00
this . gl = gl ;
2014-02-28 09:30:53 +00:00
/ * *
2014-10-22 20:42:03 +00:00
* The WebGL program .
* @ property program
2014-11-15 20:04:24 +00:00
* @ type Any
2014-10-22 20:42:03 +00:00
* /
2014-02-28 09:30:53 +00:00
this . program = null ;
/ * *
2014-10-22 20:42:03 +00:00
* The fragment shader .
* @ property fragmentSrc
* @ type Array
2014-02-28 09:30:53 +00:00
* /
this . fragmentSrc = [
'precision mediump float;' ,
'varying vec2 vTextureCoord;' ,
2014-07-01 14:04:03 +00:00
// 'varying float vColor;',
2014-02-28 09:30:53 +00:00
'uniform float alpha;' ,
'uniform sampler2D uSampler;' ,
'void main(void) {' ,
2014-11-08 19:26:34 +00:00
' gl_FragColor = texture2D(uSampler, vec2(vTextureCoord.x, vTextureCoord.y)) * alpha;' ,
2014-07-01 14:04:03 +00:00
// ' gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);',//gl_FragColor * alpha;',
2014-02-28 09:30:53 +00:00
'}'
] ;
2014-10-22 20:42:03 +00:00
/ * *
* The vertex shader .
* @ property vertexSrc
* @ type Array
* /
2014-07-01 14:04:03 +00:00
this . vertexSrc = [
2014-02-28 09:30:53 +00:00
'attribute vec2 aVertexPosition;' ,
'attribute vec2 aTextureCoord;' ,
'uniform mat3 translationMatrix;' ,
'uniform vec2 projectionVector;' ,
'uniform vec2 offsetVector;' ,
2014-07-01 14:04:03 +00:00
// 'uniform float alpha;',
// 'uniform vec3 tint;',
'varying vec2 vTextureCoord;' ,
// 'varying vec4 vColor;',
2014-02-28 09:30:53 +00:00
'void main(void) {' ,
2014-07-01 14:04:03 +00:00
' vec3 v = translationMatrix * vec3(aVertexPosition , 1.0);' ,
2014-02-28 09:30:53 +00:00
' v -= offsetVector.xyx;' ,
2014-07-01 14:04:03 +00:00
' gl_Position = vec4( v.x / projectionVector.x -1.0, v.y / -projectionVector.y + 1.0 , 0.0, 1.0);' ,
2014-02-28 09:30:53 +00:00
' vTextureCoord = aTextureCoord;' ,
2014-07-01 14:04:03 +00:00
// ' vColor = aColor * vec4(tint * alpha, alpha);',
2014-02-28 09:30:53 +00:00
'}'
] ;
2014-07-01 14:04:03 +00:00
this . init ( ) ;
2014-02-28 09:30:53 +00:00
} ;
2014-10-22 20:42:03 +00:00
PIXI . StripShader . prototype . constructor = PIXI . StripShader ;
2014-02-28 09:30:53 +00:00
/ * *
2014-10-22 20:42:03 +00:00
* Initialises the shader .
*
2014-02-28 09:30:53 +00:00
* @ method init
* /
PIXI . StripShader . prototype . init = function ( )
{
2014-07-01 14:04:03 +00:00
var gl = this . gl ;
2014-02-28 09:30:53 +00:00
var program = PIXI . compileProgram ( gl , this . vertexSrc , this . fragmentSrc ) ;
gl . useProgram ( program ) ;
// get and store the uniforms for the shader
this . uSampler = gl . getUniformLocation ( program , 'uSampler' ) ;
this . projectionVector = gl . getUniformLocation ( program , 'projectionVector' ) ;
this . offsetVector = gl . getUniformLocation ( program , 'offsetVector' ) ;
this . colorAttribute = gl . getAttribLocation ( program , 'aColor' ) ;
//this.dimensions = gl.getUniformLocation(this.program, 'dimensions');
// get and store the attributes
this . aVertexPosition = gl . getAttribLocation ( program , 'aVertexPosition' ) ;
this . aTextureCoord = gl . getAttribLocation ( program , 'aTextureCoord' ) ;
2014-07-01 14:04:03 +00:00
this . attributes = [ this . aVertexPosition , this . aTextureCoord ] ;
2014-02-28 09:30:53 +00:00
this . translationMatrix = gl . getUniformLocation ( program , 'translationMatrix' ) ;
this . alpha = gl . getUniformLocation ( program , 'alpha' ) ;
this . program = program ;
} ;
2014-08-29 17:13:33 +00:00
/ * *
2014-10-22 20:42:03 +00:00
* Destroys the shader .
*
2014-08-29 17:13:33 +00:00
* @ method destroy
* /
PIXI . StripShader . prototype . destroy = function ( )
{
this . gl . deleteProgram ( this . program ) ;
this . uniforms = null ;
this . gl = null ;
this . attribute = null ;
} ;
2014-02-28 09:30:53 +00:00
/ * *
* @ author Mat Groves http : //matgroves.com/ @Doormat23
* /
/ * *
* @ class PrimitiveShader
* @ constructor
* @ param gl { WebGLContext } the current WebGL drawing context
* /
PIXI . PrimitiveShader = function ( gl )
{
2014-10-22 20:42:03 +00:00
/ * *
* @ property _UID
* @ type Number
* @ private
* /
2014-07-01 14:04:03 +00:00
this . _UID = PIXI . _UID ++ ;
2014-02-28 09:30:53 +00:00
/ * *
* @ property gl
* @ type WebGLContext
* /
this . gl = gl ;
/ * *
2014-10-22 20:42:03 +00:00
* The WebGL program .
* @ property program
2014-11-15 20:04:24 +00:00
* @ type Any
2014-10-22 20:42:03 +00:00
* /
2014-02-28 09:30:53 +00:00
this . program = null ;
/ * *
2014-10-22 20:42:03 +00:00
* The fragment shader .
2014-02-28 09:30:53 +00:00
* @ property fragmentSrc
* @ type Array
* /
this . fragmentSrc = [
'precision mediump float;' ,
'varying vec4 vColor;' ,
'void main(void) {' ,
' gl_FragColor = vColor;' ,
'}'
] ;
/ * *
2014-10-22 20:42:03 +00:00
* The vertex shader .
2014-02-28 09:30:53 +00:00
* @ property vertexSrc
* @ type Array
* /
this . vertexSrc = [
'attribute vec2 aVertexPosition;' ,
'attribute vec4 aColor;' ,
'uniform mat3 translationMatrix;' ,
'uniform vec2 projectionVector;' ,
'uniform vec2 offsetVector;' ,
'uniform float alpha;' ,
'uniform vec3 tint;' ,
'varying vec4 vColor;' ,
'void main(void) {' ,
' vec3 v = translationMatrix * vec3(aVertexPosition , 1.0);' ,
' v -= offsetVector.xyx;' ,
' gl_Position = vec4( v.x / projectionVector.x -1.0, v.y / -projectionVector.y + 1.0 , 0.0, 1.0);' ,
' vColor = aColor * vec4(tint * alpha, alpha);' ,
'}'
] ;
this . init ( ) ;
} ;
2014-10-22 20:42:03 +00:00
PIXI . PrimitiveShader . prototype . constructor = PIXI . PrimitiveShader ;
2014-02-28 09:30:53 +00:00
/ * *
2014-10-22 20:42:03 +00:00
* Initialises the shader .
*
2014-02-28 09:30:53 +00:00
* @ method init
* /
PIXI . PrimitiveShader . prototype . init = function ( )
{
var gl = this . gl ;
var program = PIXI . compileProgram ( gl , this . vertexSrc , this . fragmentSrc ) ;
gl . useProgram ( program ) ;
// get and store the uniforms for the shader
this . projectionVector = gl . getUniformLocation ( program , 'projectionVector' ) ;
this . offsetVector = gl . getUniformLocation ( program , 'offsetVector' ) ;
this . tintColor = gl . getUniformLocation ( program , 'tint' ) ;
// get and store the attributes
this . aVertexPosition = gl . getAttribLocation ( program , 'aVertexPosition' ) ;
this . colorAttribute = gl . getAttribLocation ( program , 'aColor' ) ;
this . attributes = [ this . aVertexPosition , this . colorAttribute ] ;
this . translationMatrix = gl . getUniformLocation ( program , 'translationMatrix' ) ;
this . alpha = gl . getUniformLocation ( program , 'alpha' ) ;
this . program = program ;
} ;
/ * *
2014-10-22 20:42:03 +00:00
* Destroys the shader .
*
2014-02-28 09:30:53 +00:00
* @ method destroy
* /
PIXI . PrimitiveShader . prototype . destroy = function ( )
{
this . gl . deleteProgram ( this . program ) ;
this . uniforms = null ;
this . gl = null ;
2014-08-29 17:13:33 +00:00
this . attributes = null ;
2014-02-28 09:30:53 +00:00
} ;
2014-07-01 14:04:03 +00:00
/ * *
* @ author Mat Groves http : //matgroves.com/ @Doormat23
* /
/ * *
* @ class ComplexPrimitiveShader
* @ constructor
* @ param gl { WebGLContext } the current WebGL drawing context
* /
PIXI . ComplexPrimitiveShader = function ( gl )
{
2014-10-22 20:42:03 +00:00
/ * *
* @ property _UID
* @ type Number
* @ private
* /
2014-07-01 14:04:03 +00:00
this . _UID = PIXI . _UID ++ ;
2014-10-22 20:42:03 +00:00
2014-07-01 14:04:03 +00:00
/ * *
* @ property gl
* @ type WebGLContext
* /
this . gl = gl ;
/ * *
2014-10-22 20:42:03 +00:00
* The WebGL program .
* @ property program
2014-11-15 20:04:24 +00:00
* @ type Any
2014-10-22 20:42:03 +00:00
* /
2014-07-01 14:04:03 +00:00
this . program = null ;
/ * *
2014-10-22 20:42:03 +00:00
* The fragment shader .
2014-07-01 14:04:03 +00:00
* @ property fragmentSrc
* @ type Array
* /
this . fragmentSrc = [
2014-10-22 20:42:03 +00:00
'precision mediump float;' ,
2014-07-01 14:04:03 +00:00
'varying vec4 vColor;' ,
'void main(void) {' ,
' gl_FragColor = vColor;' ,
'}'
] ;
/ * *
2014-10-22 20:42:03 +00:00
* The vertex shader .
2014-07-01 14:04:03 +00:00
* @ property vertexSrc
* @ type Array
* /
this . vertexSrc = [
'attribute vec2 aVertexPosition;' ,
//'attribute vec4 aColor;',
'uniform mat3 translationMatrix;' ,
'uniform vec2 projectionVector;' ,
'uniform vec2 offsetVector;' ,
'uniform vec3 tint;' ,
'uniform float alpha;' ,
'uniform vec3 color;' ,
'varying vec4 vColor;' ,
'void main(void) {' ,
' vec3 v = translationMatrix * vec3(aVertexPosition , 1.0);' ,
' v -= offsetVector.xyx;' ,
' gl_Position = vec4( v.x / projectionVector.x -1.0, v.y / -projectionVector.y + 1.0 , 0.0, 1.0);' ,
' vColor = vec4(color * alpha * tint, alpha);' , //" * vec4(tint * alpha, alpha);',
'}'
] ;
this . init ( ) ;
} ;
2014-10-22 20:42:03 +00:00
PIXI . ComplexPrimitiveShader . prototype . constructor = PIXI . ComplexPrimitiveShader ;
2014-07-01 14:04:03 +00:00
/ * *
2014-10-22 20:42:03 +00:00
* Initialises the shader .
*
2014-07-01 14:04:03 +00:00
* @ method init
* /
PIXI . ComplexPrimitiveShader . prototype . init = function ( )
{
var gl = this . gl ;
var program = PIXI . compileProgram ( gl , this . vertexSrc , this . fragmentSrc ) ;
gl . useProgram ( program ) ;
// get and store the uniforms for the shader
this . projectionVector = gl . getUniformLocation ( program , 'projectionVector' ) ;
this . offsetVector = gl . getUniformLocation ( program , 'offsetVector' ) ;
this . tintColor = gl . getUniformLocation ( program , 'tint' ) ;
this . color = gl . getUniformLocation ( program , 'color' ) ;
// get and store the attributes
this . aVertexPosition = gl . getAttribLocation ( program , 'aVertexPosition' ) ;
// this.colorAttribute = gl.getAttribLocation(program, 'aColor');
this . attributes = [ this . aVertexPosition , this . colorAttribute ] ;
this . translationMatrix = gl . getUniformLocation ( program , 'translationMatrix' ) ;
this . alpha = gl . getUniformLocation ( program , 'alpha' ) ;
this . program = program ;
} ;
/ * *
2014-10-22 20:42:03 +00:00
* Destroys the shader .
*
2014-07-01 14:04:03 +00:00
* @ method destroy
* /
PIXI . ComplexPrimitiveShader . prototype . destroy = function ( )
{
this . gl . deleteProgram ( this . program ) ;
this . uniforms = null ;
this . gl = null ;
this . attribute = null ;
} ;
2014-02-28 09:30:53 +00:00
/ * *
* @ author Mat Groves http : //matgroves.com/ @Doormat23
* /
/ * *
* A set of functions used by the webGL renderer to draw the primitive graphics data
*
* @ class WebGLGraphics
* @ private
* @ static
* /
PIXI . WebGLGraphics = function ( )
{
} ;
/ * *
* Renders the graphics object
*
* @ static
* @ private
* @ method renderGraphics
* @ param graphics { Graphics }
* @ param renderSession { Object }
* /
PIXI . WebGLGraphics . renderGraphics = function ( graphics , renderSession ) //projection, offset)
{
var gl = renderSession . gl ;
var projection = renderSession . projection ,
offset = renderSession . offset ,
2014-07-01 14:04:03 +00:00
shader = renderSession . shaderManager . primitiveShader ,
webGLData ;
2014-02-28 09:30:53 +00:00
if ( graphics . dirty )
{
PIXI . WebGLGraphics . updateGraphics ( graphics , gl ) ;
}
2014-07-01 14:04:03 +00:00
var webGL = graphics . _webGL [ gl . id ] ;
2014-02-28 09:30:53 +00:00
// This could be speeded up for sure!
2014-07-01 14:04:03 +00:00
for ( var i = 0 ; i < webGL . data . length ; i ++ )
{
if ( webGL . data [ i ] . mode === 1 )
{
webGLData = webGL . data [ i ] ;
2014-02-28 09:30:53 +00:00
2014-07-01 14:04:03 +00:00
renderSession . stencilManager . pushStencil ( graphics , webGLData , renderSession ) ;
2014-02-28 09:30:53 +00:00
2014-07-01 14:04:03 +00:00
// render quad..
gl . drawElements ( gl . TRIANGLE _FAN , 4 , gl . UNSIGNED _SHORT , ( webGLData . indices . length - 4 ) * 2 ) ;
renderSession . stencilManager . popStencil ( graphics , webGLData , renderSession ) ;
}
else
{
2014-07-10 15:23:26 +00:00
webGLData = webGL . data [ i ] ;
2014-07-01 14:04:03 +00:00
renderSession . shaderManager . setShader ( shader ) ; //activatePrimitiveShader();
shader = renderSession . shaderManager . primitiveShader ;
gl . uniformMatrix3fv ( shader . translationMatrix , false , graphics . worldTransform . toArray ( true ) ) ;
2014-02-28 09:30:53 +00:00
2014-07-01 14:04:03 +00:00
gl . uniform2f ( shader . projectionVector , projection . x , - projection . y ) ;
gl . uniform2f ( shader . offsetVector , - offset . x , - offset . y ) ;
2014-02-28 09:30:53 +00:00
2014-07-01 14:04:03 +00:00
gl . uniform3fv ( shader . tintColor , PIXI . hex2rgb ( graphics . tint ) ) ;
2014-02-28 09:30:53 +00:00
2014-07-01 14:04:03 +00:00
gl . uniform1f ( shader . alpha , graphics . worldAlpha ) ;
gl . bindBuffer ( gl . ARRAY _BUFFER , webGLData . buffer ) ;
2014-02-28 09:30:53 +00:00
2014-07-01 14:04:03 +00:00
gl . vertexAttribPointer ( shader . aVertexPosition , 2 , gl . FLOAT , false , 4 * 6 , 0 ) ;
gl . vertexAttribPointer ( shader . colorAttribute , 4 , gl . FLOAT , false , 4 * 6 , 2 * 4 ) ;
2014-02-28 09:30:53 +00:00
2014-07-01 14:04:03 +00:00
// set the index buffer!
gl . bindBuffer ( gl . ELEMENT _ARRAY _BUFFER , webGLData . indexBuffer ) ;
gl . drawElements ( gl . TRIANGLE _STRIP , webGLData . indices . length , gl . UNSIGNED _SHORT , 0 ) ;
}
}
2014-02-28 09:30:53 +00:00
} ;
/ * *
* Updates the graphics object
*
* @ static
* @ private
* @ method updateGraphics
* @ param graphicsData { Graphics } The graphics object to update
* @ param gl { WebGLContext } the current WebGL drawing context
* /
PIXI . WebGLGraphics . updateGraphics = function ( graphics , gl )
{
2014-07-01 14:04:03 +00:00
// get the contexts graphics object
2014-02-28 09:30:53 +00:00
var webGL = graphics . _webGL [ gl . id ] ;
2014-07-01 14:04:03 +00:00
// if the graphics object does not exist in the webGL context time to create it!
if ( ! webGL ) webGL = graphics . _webGL [ gl . id ] = { lastIndex : 0 , data : [ ] , gl : gl } ;
// flag the graphics as not dirty as we are about to update it...
graphics . dirty = false ;
var i ;
// if the user cleared the graphics object we will need to clear every object
if ( graphics . clearDirty )
{
graphics . clearDirty = false ;
// lop through and return all the webGLDatas to the object pool so than can be reused later on
for ( i = 0 ; i < webGL . data . length ; i ++ )
{
var graphicsData = webGL . data [ i ] ;
graphicsData . reset ( ) ;
PIXI . WebGLGraphics . graphicsDataPool . push ( graphicsData ) ;
}
// clear the array and reset the index..
webGL . data = [ ] ;
webGL . lastIndex = 0 ;
}
var webGLData ;
2014-04-01 02:02:36 +00:00
2014-07-01 14:04:03 +00:00
// loop through the graphics datas and construct each one..
// if the object is a complex fill then the new stencil buffer technique will be used
// other wise graphics objects will be pushed into a batch..
for ( i = webGL . lastIndex ; i < graphics . graphicsData . length ; i ++ )
2014-02-28 09:30:53 +00:00
{
var data = graphics . graphicsData [ i ] ;
if ( data . type === PIXI . Graphics . POLY )
{
2014-10-22 20:42:03 +00:00
// need to add the points the the graphics object..
data . points = data . shape . points . slice ( ) ;
if ( data . shape . closed )
{
// close the poly if the valu is true!
if ( data . points [ 0 ] !== data . points [ data . points . length - 2 ] && data . points [ 1 ] !== data . points [ data . points . length - 1 ] )
{
data . points . push ( data . points [ 0 ] , data . points [ 1 ] ) ;
}
}
2014-07-01 14:04:03 +00:00
// MAKE SURE WE HAVE THE CORRECT TYPE..
2014-02-28 09:30:53 +00:00
if ( data . fill )
{
2014-10-22 20:42:03 +00:00
if ( data . points . length >= 6 )
2014-07-01 14:04:03 +00:00
{
2014-11-12 22:49:36 +00:00
if ( data . points . length < 6 * 2 )
2014-07-01 14:04:03 +00:00
{
2014-11-12 22:49:36 +00:00
webGLData = PIXI . WebGLGraphics . switchMode ( webGL , 0 ) ;
var canDrawUsingSimple = PIXI . WebGLGraphics . buildPoly ( data , webGLData ) ;
// console.log(canDrawUsingSimple);
if ( ! canDrawUsingSimple )
{
// console.log("<>>>")
webGLData = PIXI . WebGLGraphics . switchMode ( webGL , 1 ) ;
PIXI . WebGLGraphics . buildComplexPoly ( data , webGLData ) ;
}
2014-07-01 14:04:03 +00:00
}
else
{
2014-11-12 22:49:36 +00:00
webGLData = PIXI . WebGLGraphics . switchMode ( webGL , 1 ) ;
PIXI . WebGLGraphics . buildComplexPoly ( data , webGLData ) ;
2014-07-01 14:04:03 +00:00
}
}
2014-02-28 09:30:53 +00:00
}
if ( data . lineWidth > 0 )
{
2014-07-01 14:04:03 +00:00
webGLData = PIXI . WebGLGraphics . switchMode ( webGL , 0 ) ;
PIXI . WebGLGraphics . buildLine ( data , webGLData ) ;
2014-02-28 09:30:53 +00:00
}
}
2014-07-01 14:04:03 +00:00
else
2014-02-28 09:30:53 +00:00
{
2014-07-01 14:04:03 +00:00
webGLData = PIXI . WebGLGraphics . switchMode ( webGL , 0 ) ;
if ( data . type === PIXI . Graphics . RECT )
{
PIXI . WebGLGraphics . buildRectangle ( data , webGLData ) ;
}
else if ( data . type === PIXI . Graphics . CIRC || data . type === PIXI . Graphics . ELIP )
{
PIXI . WebGLGraphics . buildCircle ( data , webGLData ) ;
}
else if ( data . type === PIXI . Graphics . RREC )
{
2014-07-18 10:52:48 +00:00
PIXI . WebGLGraphics . buildRoundedRectangle ( data , webGLData ) ;
2014-07-01 14:04:03 +00:00
}
2014-02-28 09:30:53 +00:00
}
2014-07-01 14:04:03 +00:00
webGL . lastIndex ++ ;
2014-02-28 09:30:53 +00:00
}
2014-07-01 14:04:03 +00:00
// upload all the dirty data...
for ( i = 0 ; i < webGL . data . length ; i ++ )
{
webGLData = webGL . data [ i ] ;
if ( webGLData . dirty ) webGLData . upload ( ) ;
}
} ;
2014-02-28 09:30:53 +00:00
2014-10-22 20:42:03 +00:00
/ * *
* @ static
* @ private
* @ method switchMode
* @ param webGL { WebGLContext }
* @ param type { Number }
* /
2014-07-01 14:04:03 +00:00
PIXI . WebGLGraphics . switchMode = function ( webGL , type )
{
var webGLData ;
if ( ! webGL . data . length )
{
webGLData = PIXI . WebGLGraphics . graphicsDataPool . pop ( ) || new PIXI . WebGLGraphicsData ( webGL . gl ) ;
webGLData . mode = type ;
webGL . data . push ( webGLData ) ;
}
else
{
webGLData = webGL . data [ webGL . data . length - 1 ] ;
2014-02-28 09:30:53 +00:00
2014-07-01 14:04:03 +00:00
if ( webGLData . mode !== type || type === 1 )
{
webGLData = PIXI . WebGLGraphics . graphicsDataPool . pop ( ) || new PIXI . WebGLGraphicsData ( webGL . gl ) ;
webGLData . mode = type ;
webGL . data . push ( webGLData ) ;
}
}
2014-02-28 09:30:53 +00:00
2014-07-01 14:04:03 +00:00
webGLData . dirty = true ;
2014-02-28 09:30:53 +00:00
2014-07-01 14:04:03 +00:00
return webGLData ;
2014-02-28 09:30:53 +00:00
} ;
/ * *
* Builds a rectangle to draw
*
* @ static
* @ private
* @ method buildRectangle
* @ param graphicsData { Graphics } The graphics object containing all the necessary properties
* @ param webGLData { Object }
* /
PIXI . WebGLGraphics . buildRectangle = function ( graphicsData , webGLData )
{
// --- //
// need to convert points to a nice regular data
//
2014-10-22 20:42:03 +00:00
var rectData = graphicsData . shape ;
var x = rectData . x ;
var y = rectData . y ;
var width = rectData . width ;
var height = rectData . height ;
2014-02-28 09:30:53 +00:00
if ( graphicsData . fill )
{
var color = PIXI . hex2rgb ( graphicsData . fillColor ) ;
var alpha = graphicsData . fillAlpha ;
var r = color [ 0 ] * alpha ;
var g = color [ 1 ] * alpha ;
var b = color [ 2 ] * alpha ;
var verts = webGLData . points ;
var indices = webGLData . indices ;
var vertPos = verts . length / 6 ;
// start
verts . push ( x , y ) ;
verts . push ( r , g , b , alpha ) ;
verts . push ( x + width , y ) ;
verts . push ( r , g , b , alpha ) ;
verts . push ( x , y + height ) ;
verts . push ( r , g , b , alpha ) ;
verts . push ( x + width , y + height ) ;
verts . push ( r , g , b , alpha ) ;
// insert 2 dead triangles..
indices . push ( vertPos , vertPos , vertPos + 1 , vertPos + 2 , vertPos + 3 , vertPos + 3 ) ;
}
if ( graphicsData . lineWidth )
{
var tempPoints = graphicsData . points ;
graphicsData . points = [ x , y ,
x + width , y ,
x + width , y + height ,
x , y + height ,
x , y ] ;
PIXI . WebGLGraphics . buildLine ( graphicsData , webGLData ) ;
graphicsData . points = tempPoints ;
}
} ;
2014-07-01 14:04:03 +00:00
/ * *
* Builds a rounded rectangle to draw
*
* @ static
* @ private
* @ method buildRoundedRectangle
* @ param graphicsData { Graphics } The graphics object containing all the necessary properties
* @ param webGLData { Object }
* /
PIXI . WebGLGraphics . buildRoundedRectangle = function ( graphicsData , webGLData )
{
2014-11-12 22:49:36 +00:00
var rrectData = graphicsData . shape ;
var x = rrectData . x ;
var y = rrectData . y ;
var width = rrectData . width ;
var height = rrectData . height ;
var radius = rrectData . radius ;
2014-07-01 14:04:03 +00:00
var recPoints = [ ] ;
recPoints . push ( x , y + radius ) ;
2014-07-18 10:52:48 +00:00
recPoints = recPoints . concat ( PIXI . WebGLGraphics . quadraticBezierCurve ( x , y + height - radius , x , y + height , x + radius , y + height ) ) ;
recPoints = recPoints . concat ( PIXI . WebGLGraphics . quadraticBezierCurve ( x + width - radius , y + height , x + width , y + height , x + width , y + height - radius ) ) ;
recPoints = recPoints . concat ( PIXI . WebGLGraphics . quadraticBezierCurve ( x + width , y + radius , x + width , y , x + width - radius , y ) ) ;
recPoints = recPoints . concat ( PIXI . WebGLGraphics . quadraticBezierCurve ( x + radius , y , x , y , x , y + radius ) ) ;
2014-07-01 14:04:03 +00:00
if ( graphicsData . fill ) {
var color = PIXI . hex2rgb ( graphicsData . fillColor ) ;
var alpha = graphicsData . fillAlpha ;
var r = color [ 0 ] * alpha ;
var g = color [ 1 ] * alpha ;
var b = color [ 2 ] * alpha ;
var verts = webGLData . points ;
var indices = webGLData . indices ;
var vecPos = verts . length / 6 ;
var triangles = PIXI . PolyK . Triangulate ( recPoints ) ;
var i = 0 ;
for ( i = 0 ; i < triangles . length ; i += 3 )
{
indices . push ( triangles [ i ] + vecPos ) ;
indices . push ( triangles [ i ] + vecPos ) ;
indices . push ( triangles [ i + 1 ] + vecPos ) ;
indices . push ( triangles [ i + 2 ] + vecPos ) ;
indices . push ( triangles [ i + 2 ] + vecPos ) ;
}
for ( i = 0 ; i < recPoints . length ; i ++ )
{
verts . push ( recPoints [ i ] , recPoints [ ++ i ] , r , g , b , alpha ) ;
}
}
if ( graphicsData . lineWidth ) {
var tempPoints = graphicsData . points ;
graphicsData . points = recPoints ;
PIXI . WebGLGraphics . buildLine ( graphicsData , webGLData ) ;
graphicsData . points = tempPoints ;
}
} ;
2014-07-18 10:52:48 +00:00
/ * *
2014-10-22 20:42:03 +00:00
* Calculate the points for a quadratic bezier curve . ( helper function . . )
* Based on : https : //stackoverflow.com/questions/785097/how-do-i-implement-a-bezier-curve-in-c
2014-07-18 10:52:48 +00:00
*
2014-10-22 20:42:03 +00:00
* @ static
* @ private
* @ method quadraticBezierCurve
* @ param fromX { Number } Origin point x
* @ param fromY { Number } Origin point x
* @ param cpX { Number } Control point x
* @ param cpY { Number } Control point y
* @ param toX { Number } Destination point x
* @ param toY { Number } Destination point y
2014-11-15 20:04:24 +00:00
* @ return { Array ( Number ) }
2014-07-18 10:52:48 +00:00
* /
PIXI . WebGLGraphics . quadraticBezierCurve = function ( fromX , fromY , cpX , cpY , toX , toY ) {
2014-10-22 20:42:03 +00:00
2014-07-18 10:52:48 +00:00
var xa ,
ya ,
xb ,
yb ,
x ,
y ,
n = 20 ,
points = [ ] ;
function getPt ( n1 , n2 , perc ) {
var diff = n2 - n1 ;
return n1 + ( diff * perc ) ;
}
var j = 0 ;
for ( var i = 0 ; i <= n ; i ++ )
{
j = i / n ;
// The Green Line
xa = getPt ( fromX , cpX , j ) ;
ya = getPt ( fromY , cpY , j ) ;
xb = getPt ( cpX , toX , j ) ;
yb = getPt ( cpY , toY , j ) ;
// The Black Dot
x = getPt ( xa , xb , j ) ;
y = getPt ( ya , yb , j ) ;
points . push ( x , y ) ;
}
return points ;
} ;
2014-07-01 14:04:03 +00:00
2014-02-28 09:30:53 +00:00
/ * *
* Builds a circle to draw
*
* @ static
* @ private
* @ method buildCircle
* @ param graphicsData { Graphics } The graphics object to draw
* @ param webGLData { Object }
* /
PIXI . WebGLGraphics . buildCircle = function ( graphicsData , webGLData )
{
// need to convert points to a nice regular data
2014-10-22 20:42:03 +00:00
var circleData = graphicsData . shape ;
var x = circleData . x ;
var y = circleData . y ;
var width ;
var height ;
// TODO - bit hacky??
if ( graphicsData . type === PIXI . Graphics . CIRC )
{
width = circleData . radius ;
height = circleData . radius ;
}
else
{
width = circleData . width ;
height = circleData . height ;
}
2014-02-28 09:30:53 +00:00
var totalSegs = 40 ;
var seg = ( Math . PI * 2 ) / totalSegs ;
var i = 0 ;
if ( graphicsData . fill )
{
var color = PIXI . hex2rgb ( graphicsData . fillColor ) ;
var alpha = graphicsData . fillAlpha ;
var r = color [ 0 ] * alpha ;
var g = color [ 1 ] * alpha ;
var b = color [ 2 ] * alpha ;
var verts = webGLData . points ;
var indices = webGLData . indices ;
var vecPos = verts . length / 6 ;
indices . push ( vecPos ) ;
for ( i = 0 ; i < totalSegs + 1 ; i ++ )
{
verts . push ( x , y , r , g , b , alpha ) ;
verts . push ( x + Math . sin ( seg * i ) * width ,
y + Math . cos ( seg * i ) * height ,
r , g , b , alpha ) ;
indices . push ( vecPos ++ , vecPos ++ ) ;
}
indices . push ( vecPos - 1 ) ;
}
if ( graphicsData . lineWidth )
{
var tempPoints = graphicsData . points ;
graphicsData . points = [ ] ;
for ( i = 0 ; i < totalSegs + 1 ; i ++ )
{
graphicsData . points . push ( x + Math . sin ( seg * i ) * width ,
y + Math . cos ( seg * i ) * height ) ;
}
PIXI . WebGLGraphics . buildLine ( graphicsData , webGLData ) ;
graphicsData . points = tempPoints ;
}
} ;
/ * *
* Builds a line to draw
*
* @ static
* @ private
* @ method buildLine
* @ param graphicsData { Graphics } The graphics object containing all the necessary properties
* @ param webGLData { Object }
* /
PIXI . WebGLGraphics . buildLine = function ( graphicsData , webGLData )
{
// TODO OPTIMISE!
var i = 0 ;
var points = graphicsData . points ;
if ( points . length === 0 ) return ;
// if the line width is an odd number add 0.5 to align to a whole pixel
if ( graphicsData . lineWidth % 2 )
{
for ( i = 0 ; i < points . length ; i ++ ) {
points [ i ] += 0.5 ;
}
}
// get first and last point.. figure out the middle!
var firstPoint = new PIXI . Point ( points [ 0 ] , points [ 1 ] ) ;
var lastPoint = new PIXI . Point ( points [ points . length - 2 ] , points [ points . length - 1 ] ) ;
// if the first point is the last point - gonna have issues :)
if ( firstPoint . x === lastPoint . x && firstPoint . y === lastPoint . y )
{
2014-07-01 14:04:03 +00:00
// need to clone as we are going to slightly modify the shape..
points = points . slice ( ) ;
2014-02-28 09:30:53 +00:00
points . pop ( ) ;
points . pop ( ) ;
lastPoint = new PIXI . Point ( points [ points . length - 2 ] , points [ points . length - 1 ] ) ;
var midPointX = lastPoint . x + ( firstPoint . x - lastPoint . x ) * 0.5 ;
var midPointY = lastPoint . y + ( firstPoint . y - lastPoint . y ) * 0.5 ;
points . unshift ( midPointX , midPointY ) ;
points . push ( midPointX , midPointY ) ;
}
var verts = webGLData . points ;
var indices = webGLData . indices ;
var length = points . length / 2 ;
var indexCount = points . length ;
var indexStart = verts . length / 6 ;
// DRAW the Line
var width = graphicsData . lineWidth / 2 ;
// sort color
var color = PIXI . hex2rgb ( graphicsData . lineColor ) ;
var alpha = graphicsData . lineAlpha ;
var r = color [ 0 ] * alpha ;
var g = color [ 1 ] * alpha ;
var b = color [ 2 ] * alpha ;
var px , py , p1x , p1y , p2x , p2y , p3x , p3y ;
var perpx , perpy , perp2x , perp2y , perp3x , perp3y ;
var a1 , b1 , c1 , a2 , b2 , c2 ;
var denom , pdist , dist ;
p1x = points [ 0 ] ;
p1y = points [ 1 ] ;
p2x = points [ 2 ] ;
p2y = points [ 3 ] ;
perpx = - ( p1y - p2y ) ;
perpy = p1x - p2x ;
dist = Math . sqrt ( perpx * perpx + perpy * perpy ) ;
perpx /= dist ;
perpy /= dist ;
perpx *= width ;
perpy *= width ;
// start
verts . push ( p1x - perpx , p1y - perpy ,
r , g , b , alpha ) ;
verts . push ( p1x + perpx , p1y + perpy ,
r , g , b , alpha ) ;
for ( i = 1 ; i < length - 1 ; i ++ )
{
p1x = points [ ( i - 1 ) * 2 ] ;
p1y = points [ ( i - 1 ) * 2 + 1 ] ;
p2x = points [ ( i ) * 2 ] ;
p2y = points [ ( i ) * 2 + 1 ] ;
p3x = points [ ( i + 1 ) * 2 ] ;
p3y = points [ ( i + 1 ) * 2 + 1 ] ;
perpx = - ( p1y - p2y ) ;
perpy = p1x - p2x ;
dist = Math . sqrt ( perpx * perpx + perpy * perpy ) ;
perpx /= dist ;
perpy /= dist ;
perpx *= width ;
perpy *= width ;
perp2x = - ( p2y - p3y ) ;
perp2y = p2x - p3x ;
dist = Math . sqrt ( perp2x * perp2x + perp2y * perp2y ) ;
perp2x /= dist ;
perp2y /= dist ;
perp2x *= width ;
perp2y *= width ;
a1 = ( - perpy + p1y ) - ( - perpy + p2y ) ;
b1 = ( - perpx + p2x ) - ( - perpx + p1x ) ;
c1 = ( - perpx + p1x ) * ( - perpy + p2y ) - ( - perpx + p2x ) * ( - perpy + p1y ) ;
a2 = ( - perp2y + p3y ) - ( - perp2y + p2y ) ;
b2 = ( - perp2x + p2x ) - ( - perp2x + p3x ) ;
c2 = ( - perp2x + p3x ) * ( - perp2y + p2y ) - ( - perp2x + p2x ) * ( - perp2y + p3y ) ;
denom = a1 * b2 - a2 * b1 ;
if ( Math . abs ( denom ) < 0.1 )
{
denom += 10.1 ;
verts . push ( p2x - perpx , p2y - perpy ,
r , g , b , alpha ) ;
verts . push ( p2x + perpx , p2y + perpy ,
r , g , b , alpha ) ;
continue ;
}
px = ( b1 * c2 - b2 * c1 ) / denom ;
py = ( a2 * c1 - a1 * c2 ) / denom ;
pdist = ( px - p2x ) * ( px - p2x ) + ( py - p2y ) + ( py - p2y ) ;
if ( pdist > 140 * 140 )
{
perp3x = perpx - perp2x ;
perp3y = perpy - perp2y ;
dist = Math . sqrt ( perp3x * perp3x + perp3y * perp3y ) ;
perp3x /= dist ;
perp3y /= dist ;
perp3x *= width ;
perp3y *= width ;
verts . push ( p2x - perp3x , p2y - perp3y ) ;
verts . push ( r , g , b , alpha ) ;
verts . push ( p2x + perp3x , p2y + perp3y ) ;
verts . push ( r , g , b , alpha ) ;
verts . push ( p2x - perp3x , p2y - perp3y ) ;
verts . push ( r , g , b , alpha ) ;
indexCount ++ ;
}
else
{
verts . push ( px , py ) ;
verts . push ( r , g , b , alpha ) ;
verts . push ( p2x - ( px - p2x ) , p2y - ( py - p2y ) ) ;
verts . push ( r , g , b , alpha ) ;
}
}
p1x = points [ ( length - 2 ) * 2 ] ;
p1y = points [ ( length - 2 ) * 2 + 1 ] ;
p2x = points [ ( length - 1 ) * 2 ] ;
p2y = points [ ( length - 1 ) * 2 + 1 ] ;
perpx = - ( p1y - p2y ) ;
perpy = p1x - p2x ;
dist = Math . sqrt ( perpx * perpx + perpy * perpy ) ;
perpx /= dist ;
perpy /= dist ;
perpx *= width ;
perpy *= width ;
verts . push ( p2x - perpx , p2y - perpy ) ;
verts . push ( r , g , b , alpha ) ;
verts . push ( p2x + perpx , p2y + perpy ) ;
verts . push ( r , g , b , alpha ) ;
indices . push ( indexStart ) ;
for ( i = 0 ; i < indexCount ; i ++ )
{
indices . push ( indexStart ++ ) ;
}
indices . push ( indexStart - 1 ) ;
} ;
/ * *
2014-07-01 14:04:03 +00:00
* Builds a complex polygon to draw
2014-02-28 09:30:53 +00:00
*
* @ static
* @ private
2014-10-22 20:42:03 +00:00
* @ method buildComplexPoly
2014-02-28 09:30:53 +00:00
* @ param graphicsData { Graphics } The graphics object containing all the necessary properties
* @ param webGLData { Object }
* /
2014-07-01 14:04:03 +00:00
PIXI . WebGLGraphics . buildComplexPoly = function ( graphicsData , webGLData )
{
//TODO - no need to copy this as it gets turned into a FLoat32Array anyways..
var points = graphicsData . points . slice ( ) ;
if ( points . length < 6 ) return ;
// get first and last point.. figure out the middle!
var indices = webGLData . indices ;
webGLData . points = points ;
webGLData . alpha = graphicsData . fillAlpha ;
webGLData . color = PIXI . hex2rgb ( graphicsData . fillColor ) ;
/ *
calclate the bounds . .
* /
var minX = Infinity ;
var maxX = - Infinity ;
var minY = Infinity ;
var maxY = - Infinity ;
var x , y ;
// get size..
for ( var i = 0 ; i < points . length ; i += 2 )
{
x = points [ i ] ;
y = points [ i + 1 ] ;
minX = x < minX ? x : minX ;
maxX = x > maxX ? x : maxX ;
minY = y < minY ? y : minY ;
maxY = y > maxY ? y : maxY ;
}
// add a quad to the end cos there is no point making another buffer!
points . push ( minX , minY ,
maxX , minY ,
maxX , maxY ,
minX , maxY ) ;
// push a quad onto the end..
//TODO - this aint needed!
var length = points . length / 2 ;
for ( i = 0 ; i < length ; i ++ )
{
indices . push ( i ) ;
}
} ;
2014-10-22 20:42:03 +00:00
/ * *
* Builds a polygon to draw
*
* @ static
* @ private
* @ method buildPoly
* @ param graphicsData { Graphics } The graphics object containing all the necessary properties
* @ param webGLData { Object }
* /
2014-02-28 09:30:53 +00:00
PIXI . WebGLGraphics . buildPoly = function ( graphicsData , webGLData )
{
var points = graphicsData . points ;
2014-10-22 20:42:03 +00:00
if ( points . length < 6 ) return ;
2014-02-28 09:30:53 +00:00
// get first and last point.. figure out the middle!
var verts = webGLData . points ;
var indices = webGLData . indices ;
var length = points . length / 2 ;
// sort color
var color = PIXI . hex2rgb ( graphicsData . fillColor ) ;
var alpha = graphicsData . fillAlpha ;
var r = color [ 0 ] * alpha ;
var g = color [ 1 ] * alpha ;
var b = color [ 2 ] * alpha ;
var triangles = PIXI . PolyK . Triangulate ( points ) ;
2014-11-12 22:49:36 +00:00
if ( ! triangles ) return false ;
2014-02-28 09:30:53 +00:00
var vertPos = verts . length / 6 ;
var i = 0 ;
for ( i = 0 ; i < triangles . length ; i += 3 )
{
indices . push ( triangles [ i ] + vertPos ) ;
indices . push ( triangles [ i ] + vertPos ) ;
indices . push ( triangles [ i + 1 ] + vertPos ) ;
indices . push ( triangles [ i + 2 ] + vertPos ) ;
indices . push ( triangles [ i + 2 ] + vertPos ) ;
}
for ( i = 0 ; i < length ; i ++ )
{
verts . push ( points [ i * 2 ] , points [ i * 2 + 1 ] ,
r , g , b , alpha ) ;
}
2014-07-01 14:04:03 +00:00
2014-11-12 22:49:36 +00:00
return true ;
2014-07-01 14:04:03 +00:00
} ;
PIXI . WebGLGraphics . graphicsDataPool = [ ] ;
2014-10-22 20:42:03 +00:00
/ * *
* @ class WebGLGraphicsData
* @ private
* @ static
* /
2014-07-01 14:04:03 +00:00
PIXI . WebGLGraphicsData = function ( gl )
{
this . gl = gl ;
//TODO does this need to be split before uploding??
this . color = [ 0 , 0 , 0 ] ; // color split!
this . points = [ ] ;
this . indices = [ ] ;
this . lastIndex = 0 ;
this . buffer = gl . createBuffer ( ) ;
this . indexBuffer = gl . createBuffer ( ) ;
this . mode = 1 ;
this . alpha = 1 ;
this . dirty = true ;
} ;
2014-10-22 20:42:03 +00:00
/ * *
* @ method reset
* /
2014-07-01 14:04:03 +00:00
PIXI . WebGLGraphicsData . prototype . reset = function ( )
{
this . points = [ ] ;
this . indices = [ ] ;
this . lastIndex = 0 ;
} ;
2014-10-22 20:42:03 +00:00
/ * *
* @ method upload
* /
2014-07-01 14:04:03 +00:00
PIXI . WebGLGraphicsData . prototype . upload = function ( )
{
var gl = this . gl ;
// this.lastIndex = graphics.graphicsData.length;
2014-11-08 19:26:34 +00:00
this . glPoints = new PIXI . Float32Array ( this . points ) ;
2014-07-01 14:04:03 +00:00
gl . bindBuffer ( gl . ARRAY _BUFFER , this . buffer ) ;
gl . bufferData ( gl . ARRAY _BUFFER , this . glPoints , gl . STATIC _DRAW ) ;
2014-11-08 19:26:34 +00:00
this . glIndicies = new PIXI . Uint16Array ( this . indices ) ;
2014-07-01 14:04:03 +00:00
gl . bindBuffer ( gl . ELEMENT _ARRAY _BUFFER , this . indexBuffer ) ;
gl . bufferData ( gl . ELEMENT _ARRAY _BUFFER , this . glIndicies , gl . STATIC _DRAW ) ;
this . dirty = false ;
2014-02-28 09:30:53 +00:00
} ;
/ * *
* @ author Mat Groves http : //matgroves.com/ @Doormat23
* /
PIXI . glContexts = [ ] ; // this is where we store the webGL contexts for easy access.
2014-11-12 22:49:36 +00:00
PIXI . instances = [ ] ;
2014-02-28 09:30:53 +00:00
/ * *
2014-10-22 20:42:03 +00:00
* The WebGLRenderer draws the stage and all its content onto a webGL enabled canvas . This renderer
* should be used for browsers that support webGL . This Render works by automatically managing webGLBatchs .
* So no need for Sprite Batches or Sprite Clouds .
* Don ' t forget to add the view to your DOM or you will not see anything : )
2014-02-28 09:30:53 +00:00
*
* @ class WebGLRenderer
* @ constructor
2014-10-22 20:42:03 +00:00
* @ param [ width = 0 ] { Number } the width of the canvas view
* @ param [ height = 0 ] { Number } the height of the canvas view
* @ param [ options ] { Object } The optional renderer parameters
* @ param [ options . view ] { HTMLCanvasElement } the canvas to use as a view , optional
* @ param [ options . transparent = false ] { Boolean } If the render view is transparent , default false
2014-11-11 01:10:47 +00:00
* @ param [ options . autoResize = false ] { Boolean } If the render view is automatically resized , default false
2014-10-22 20:42:03 +00:00
* @ param [ options . antialias = false ] { Boolean } sets antialias ( only applicable in chrome at the moment )
* @ param [ options . preserveDrawingBuffer = false ] { Boolean } enables drawing buffer preservation , enable this if you need to call toDataUrl on the webgl context
* @ param [ options . resolution = 1 ] { Number } the resolution of the renderer retina would be 2
2014-02-28 09:30:53 +00:00
* /
2014-10-22 20:42:03 +00:00
PIXI . WebGLRenderer = function ( width , height , options )
2014-02-28 09:30:53 +00:00
{
2014-10-22 20:42:03 +00:00
if ( options )
{
for ( var i in PIXI . defaultRenderOptions )
{
if ( typeof options [ i ] === 'undefined' ) options [ i ] = PIXI . defaultRenderOptions [ i ] ;
}
}
else
{
options = PIXI . defaultRenderOptions ;
}
2014-07-10 15:23:26 +00:00
if ( ! PIXI . defaultRenderer )
{
PIXI . sayHello ( 'webGL' ) ;
PIXI . defaultRenderer = this ;
}
2014-02-28 09:30:53 +00:00
2014-10-22 20:42:03 +00:00
/ * *
* @ property type
* @ type Number
* /
2014-02-28 09:30:53 +00:00
this . type = PIXI . WEBGL _RENDERER ;
/ * *
2014-10-22 20:42:03 +00:00
* The resolution of the renderer
*
* @ property resolution
* @ type Number
* @ default 1
* /
this . resolution = options . resolution ;
// do a catch.. only 1 webGL renderer..
/ * *
* Whether the render view is transparent
2014-02-28 09:30:53 +00:00
*
* @ property transparent
* @ type Boolean
* /
2014-10-22 20:42:03 +00:00
this . transparent = options . transparent ;
2014-02-28 09:30:53 +00:00
2014-11-11 01:10:47 +00:00
/ * *
* Whether the render view should be resized automatically
*
* @ property autoResize
* @ type Boolean
* /
2014-11-11 14:31:31 +00:00
this . autoResize = options . autoResize || false ;
2014-11-11 01:10:47 +00:00
2014-07-10 15:23:26 +00:00
/ * *
* The value of the preserveDrawingBuffer flag affects whether or not the contents of the stencil buffer is retained after rendering .
*
* @ property preserveDrawingBuffer
* @ type Boolean
* /
2014-10-22 20:42:03 +00:00
this . preserveDrawingBuffer = options . preserveDrawingBuffer ;
2014-11-12 22:49:36 +00:00
2014-10-22 20:42:03 +00:00
/ * *
* This sets if the WebGLRenderer will clear the context texture or not before the new render pass . If true :
* If the Stage is NOT transparent , Pixi will clear to alpha ( 0 , 0 , 0 , 0 ) .
* If the Stage is transparent , Pixi will clear to the target Stage ' s background color .
* Disable this by setting this to false . For example : if your game has a canvas filling background image , you often don ' t need this set .
*
* @ property clearBeforeRender
* @ type Boolean
* @ default
* /
this . clearBeforeRender = options . clearBeforeRender ;
2014-11-12 22:49:36 +00:00
2014-02-28 09:30:53 +00:00
/ * *
* The width of the canvas view
*
* @ property width
* @ type Number
* @ default 800
* /
this . width = width || 800 ;
/ * *
* The height of the canvas view
*
* @ property height
* @ type Number
* @ default 600
* /
this . height = height || 600 ;
/ * *
* The canvas element that everything is drawn to
*
* @ property view
* @ type HTMLCanvasElement
* /
2014-10-22 20:42:03 +00:00
this . view = options . view || document . createElement ( 'canvas' ) ;
2014-02-28 09:30:53 +00:00
// deal with losing context..
2014-08-29 17:13:33 +00:00
2014-10-22 20:42:03 +00:00
/ * *
* @ property contextLostBound
* @ type Function
* /
this . contextLostBound = this . handleContextLost . bind ( this ) ;
/ * *
* @ property contextRestoredBound
* @ type Function
* /
this . contextRestoredBound = this . handleContextRestored . bind ( this ) ;
this . view . addEventListener ( 'webglcontextlost' , this . contextLostBound , false ) ;
this . view . addEventListener ( 'webglcontextrestored' , this . contextRestoredBound , false ) ;
2014-02-28 09:30:53 +00:00
2014-10-22 20:42:03 +00:00
/ * *
* @ property _contextOptions
* @ type Object
* @ private
* /
this . _contextOptions = {
2014-02-28 09:30:53 +00:00
alpha : this . transparent ,
2014-10-22 20:42:03 +00:00
antialias : options . antialias , // SPEED UP??
premultipliedAlpha : this . transparent && this . transparent !== 'notMultiplied' ,
2014-07-10 15:23:26 +00:00
stencil : true ,
2014-10-22 20:42:03 +00:00
preserveDrawingBuffer : options . preserveDrawingBuffer
2014-02-28 09:30:53 +00:00
} ;
2014-10-22 20:42:03 +00:00
/ * *
* @ property projection
* @ type Point
* /
this . projection = new PIXI . Point ( ) ;
2014-02-28 09:30:53 +00:00
2014-10-22 20:42:03 +00:00
/ * *
* @ property offset
* @ type Point
* /
this . offset = new PIXI . Point ( 0 , 0 ) ;
2014-02-28 09:30:53 +00:00
2014-10-22 20:42:03 +00:00
// time to create the render managers! each one focuses on managing a state in webGL
2014-02-28 09:30:53 +00:00
2014-10-22 20:42:03 +00:00
/ * *
* Deals with managing the shader programs and their attribs
* @ property shaderManager
* @ type WebGLShaderManager
* /
this . shaderManager = new PIXI . WebGLShaderManager ( ) ;
2014-02-28 09:30:53 +00:00
2014-10-22 20:42:03 +00:00
/ * *
* Manages the rendering of sprites
* @ property spriteBatch
* @ type WebGLSpriteBatch
* /
this . spriteBatch = new PIXI . WebGLSpriteBatch ( ) ;
2014-02-28 09:30:53 +00:00
2014-10-22 20:42:03 +00:00
/ * *
* Manages the masks using the stencil buffer
* @ property maskManager
* @ type WebGLMaskManager
* /
this . maskManager = new PIXI . WebGLMaskManager ( ) ;
2014-02-28 09:30:53 +00:00
2014-10-22 20:42:03 +00:00
/ * *
* Manages the filters
* @ property filterManager
* @ type WebGLFilterManager
* /
this . filterManager = new PIXI . WebGLFilterManager ( ) ;
2014-02-28 09:30:53 +00:00
2014-10-22 20:42:03 +00:00
/ * *
* Manages the stencil buffer
* @ property stencilManager
* @ type WebGLStencilManager
* /
this . stencilManager = new PIXI . WebGLStencilManager ( ) ;
2014-02-28 09:30:53 +00:00
2014-10-22 20:42:03 +00:00
/ * *
* Manages the blendModes
* @ property blendModeManager
* @ type WebGLBlendModeManager
* /
this . blendModeManager = new PIXI . WebGLBlendModeManager ( ) ;
2014-02-28 09:30:53 +00:00
2014-10-22 20:42:03 +00:00
/ * *
* TODO remove
* @ property renderSession
* @ type Object
* /
2014-02-28 09:30:53 +00:00
this . renderSession = { } ;
this . renderSession . gl = this . gl ;
this . renderSession . drawCount = 0 ;
this . renderSession . shaderManager = this . shaderManager ;
this . renderSession . maskManager = this . maskManager ;
this . renderSession . filterManager = this . filterManager ;
2014-07-10 15:23:26 +00:00
this . renderSession . blendModeManager = this . blendModeManager ;
2014-02-28 09:30:53 +00:00
this . renderSession . spriteBatch = this . spriteBatch ;
2014-07-01 14:04:03 +00:00
this . renderSession . stencilManager = this . stencilManager ;
2014-02-28 09:30:53 +00:00
this . renderSession . renderer = this ;
2014-10-22 20:42:03 +00:00
this . renderSession . resolution = this . resolution ;
2014-02-28 09:30:53 +00:00
2014-10-22 20:42:03 +00:00
// time init the context..
this . initContext ( ) ;
2014-02-28 09:30:53 +00:00
2014-10-22 20:42:03 +00:00
// map some webGL blend modes..
this . mapBlendModes ( ) ;
2014-02-28 09:30:53 +00:00
} ;
// constructor
PIXI . WebGLRenderer . prototype . constructor = PIXI . WebGLRenderer ;
2014-10-22 20:42:03 +00:00
/ * *
* @ method initContext
* /
PIXI . WebGLRenderer . prototype . initContext = function ( )
{
var gl = this . view . getContext ( 'webgl' , this . _contextOptions ) || this . view . getContext ( 'experimental-webgl' , this . _contextOptions ) ;
this . gl = gl ;
if ( ! gl ) {
// fail, not able to get a context
throw new Error ( 'This browser does not support webGL. Try using the canvas renderer' ) ;
}
this . glContextId = gl . id = PIXI . WebGLRenderer . glContextId ++ ;
PIXI . glContexts [ this . glContextId ] = gl ;
2014-11-12 22:49:36 +00:00
PIXI . instances [ this . glContextId ] = this ;
2014-10-22 20:42:03 +00:00
// set up the default pixi settings..
gl . disable ( gl . DEPTH _TEST ) ;
gl . disable ( gl . CULL _FACE ) ;
gl . enable ( gl . BLEND ) ;
// need to set the context for all the managers...
this . shaderManager . setContext ( gl ) ;
this . spriteBatch . setContext ( gl ) ;
this . maskManager . setContext ( gl ) ;
this . filterManager . setContext ( gl ) ;
this . blendModeManager . setContext ( gl ) ;
this . stencilManager . setContext ( gl ) ;
this . renderSession . gl = this . gl ;
// now resize and we are good to go!
this . resize ( this . width , this . height ) ;
} ;
2014-02-28 09:30:53 +00:00
/ * *
* Renders the stage to its webGL view
*
* @ method render
* @ param stage { Stage } the Stage element to be rendered
* /
PIXI . WebGLRenderer . prototype . render = function ( stage )
{
2014-10-22 20:42:03 +00:00
// no point rendering if our context has been blown up!
2014-02-28 09:30:53 +00:00
if ( this . contextLost ) return ;
// if rendering a new stage clear the batches..
if ( this . _ _stage !== stage )
{
if ( stage . interactive ) stage . interactionManager . removeEvents ( ) ;
// TODO make this work
// dont think this is needed any more?
this . _ _stage = stage ;
}
// update the scene graph
stage . updateTransform ( ) ;
2014-10-22 20:42:03 +00:00
var gl = this . gl ;
2014-11-12 22:49:36 +00:00
2014-02-28 09:30:53 +00:00
// interaction
if ( stage . _interactive )
{
//need to add some events!
if ( ! stage . _interactiveEventsAdded )
{
stage . _interactiveEventsAdded = true ;
stage . interactionManager . setTarget ( this ) ;
}
}
2014-10-22 20:42:03 +00:00
else
{
if ( stage . _interactiveEventsAdded )
{
stage . _interactiveEventsAdded = false ;
stage . interactionManager . setTarget ( this ) ;
}
}
2014-02-28 09:30:53 +00:00
// -- Does this need to be set every frame? -- //
gl . viewport ( 0 , 0 , this . width , this . height ) ;
// make sure we are bound to the main frame buffer
gl . bindFramebuffer ( gl . FRAMEBUFFER , null ) ;
2014-10-22 20:42:03 +00:00
if ( this . clearBeforeRender )
2014-02-28 09:30:53 +00:00
{
2014-10-22 20:42:03 +00:00
if ( this . transparent )
{
gl . clearColor ( 0 , 0 , 0 , 0 ) ;
2014-02-28 09:30:53 +00:00
}
2014-10-22 20:42:03 +00:00
else
2014-02-28 09:30:53 +00:00
{
2014-10-22 20:42:03 +00:00
gl . clearColor ( stage . backgroundColorSplit [ 0 ] , stage . backgroundColorSplit [ 1 ] , stage . backgroundColorSplit [ 2 ] , 1 ) ;
2014-02-28 09:30:53 +00:00
}
2014-11-12 22:49:36 +00:00
2014-10-22 20:42:03 +00:00
gl . clear ( gl . COLOR _BUFFER _BIT ) ;
2014-02-28 09:30:53 +00:00
}
2014-11-12 22:49:36 +00:00
2014-10-22 20:42:03 +00:00
this . renderDisplayObject ( stage , this . projection ) ;
} ;
2014-02-28 09:30:53 +00:00
2014-10-22 20:42:03 +00:00
/ * *
* Renders a Display Object .
*
* @ method renderDisplayObject
2014-02-28 09:30:53 +00:00
* @ param displayObject { DisplayObject } The DisplayObject to render
* @ param projection { Point } The projection
2014-08-29 17:13:33 +00:00
* @ param buffer { Array } a standard WebGL buffer
2014-02-28 09:30:53 +00:00
* /
PIXI . WebGLRenderer . prototype . renderDisplayObject = function ( displayObject , projection , buffer )
{
2014-07-10 15:23:26 +00:00
this . renderSession . blendModeManager . setBlendMode ( PIXI . blendModes . NORMAL ) ;
2014-11-12 22:49:36 +00:00
2014-02-28 09:30:53 +00:00
// reset the render session data..
this . renderSession . drawCount = 0 ;
2014-10-22 20:42:03 +00:00
// set the default projection
2014-02-28 09:30:53 +00:00
this . renderSession . projection = projection ;
2014-10-22 20:42:03 +00:00
//set the default offset
2014-02-28 09:30:53 +00:00
this . renderSession . offset = this . offset ;
// start the sprite batch
this . spriteBatch . begin ( this . renderSession ) ;
// start the filter manager
this . filterManager . begin ( this . renderSession , buffer ) ;
// render the scene!
displayObject . _renderWebGL ( this . renderSession ) ;
// finish the sprite batch
this . spriteBatch . end ( ) ;
} ;
/ * *
2014-10-22 20:42:03 +00:00
* Resizes the webGL view to the specified width and height .
2014-02-28 09:30:53 +00:00
*
* @ method resize
* @ param width { Number } the new width of the webGL view
* @ param height { Number } the new height of the webGL view
* /
PIXI . WebGLRenderer . prototype . resize = function ( width , height )
{
2014-10-22 20:42:03 +00:00
this . width = width * this . resolution ;
this . height = height * this . resolution ;
2014-02-28 09:30:53 +00:00
2014-10-22 20:42:03 +00:00
this . view . width = this . width ;
this . view . height = this . height ;
2014-02-28 09:30:53 +00:00
2014-11-11 01:10:47 +00:00
if ( this . autoResize ) {
this . view . style . width = this . width / this . resolution + 'px' ;
this . view . style . height = this . height / this . resolution + 'px' ;
}
2014-02-28 09:30:53 +00:00
this . gl . viewport ( 0 , 0 , this . width , this . height ) ;
2014-10-22 20:42:03 +00:00
this . projection . x = this . width / 2 / this . resolution ;
this . projection . y = - this . height / 2 / this . resolution ;
2014-02-28 09:30:53 +00:00
} ;
/ * *
2014-10-22 20:42:03 +00:00
* Updates and Creates a WebGL texture for the renderers context .
2014-02-28 09:30:53 +00:00
*
2014-10-22 20:42:03 +00:00
* @ method updateTexture
* @ param texture { Texture } the texture to update
2014-02-28 09:30:53 +00:00
* /
2014-10-22 20:42:03 +00:00
PIXI . WebGLRenderer . prototype . updateTexture = function ( texture )
2014-02-28 09:30:53 +00:00
{
2014-10-22 20:42:03 +00:00
if ( ! texture . hasLoaded ) return ;
2014-02-28 09:30:53 +00:00
2014-10-22 20:42:03 +00:00
var gl = this . gl ;
2014-02-28 09:30:53 +00:00
2014-10-22 20:42:03 +00:00
if ( ! texture . _glTextures [ gl . id ] ) texture . _glTextures [ gl . id ] = gl . createTexture ( ) ;
2014-02-28 09:30:53 +00:00
2014-10-22 20:42:03 +00:00
gl . bindTexture ( gl . TEXTURE _2D , texture . _glTextures [ gl . id ] ) ;
2014-02-28 09:30:53 +00:00
2014-10-22 20:42:03 +00:00
gl . pixelStorei ( gl . UNPACK _PREMULTIPLY _ALPHA _WEBGL , texture . premultipliedAlpha ) ;
gl . texImage2D ( gl . TEXTURE _2D , 0 , gl . RGBA , gl . RGBA , gl . UNSIGNED _BYTE , texture . source ) ;
2014-11-12 22:49:36 +00:00
2014-10-22 20:42:03 +00:00
gl . texParameteri ( gl . TEXTURE _2D , gl . TEXTURE _MAG _FILTER , texture . scaleMode === PIXI . scaleModes . LINEAR ? gl . LINEAR : gl . NEAREST ) ;
gl . texParameteri ( gl . TEXTURE _2D , gl . TEXTURE _MIN _FILTER , texture . scaleMode === PIXI . scaleModes . LINEAR ? gl . LINEAR : gl . NEAREST ) ;
2014-07-01 14:04:03 +00:00
2014-10-22 20:42:03 +00:00
// reguler...
if ( ! texture . _powerOf2 )
{
gl . texParameteri ( gl . TEXTURE _2D , gl . TEXTURE _WRAP _S , gl . CLAMP _TO _EDGE ) ;
gl . texParameteri ( gl . TEXTURE _2D , gl . TEXTURE _WRAP _T , gl . CLAMP _TO _EDGE ) ;
2014-02-28 09:30:53 +00:00
}
2014-10-22 20:42:03 +00:00
else
2014-02-28 09:30:53 +00:00
{
2014-10-22 20:42:03 +00:00
gl . texParameteri ( gl . TEXTURE _2D , gl . TEXTURE _WRAP _S , gl . REPEAT ) ;
gl . texParameteri ( gl . TEXTURE _2D , gl . TEXTURE _WRAP _T , gl . REPEAT ) ;
2014-02-28 09:30:53 +00:00
}
2014-08-29 17:13:33 +00:00
2014-10-22 20:42:03 +00:00
texture . _dirty [ gl . id ] = false ;
return texture . _glTextures [ gl . id ] ;
2014-02-28 09:30:53 +00:00
} ;
/ * *
* Handles a lost webgl context
*
* @ method handleContextLost
* @ param event { Event }
* @ private
* /
PIXI . WebGLRenderer . prototype . handleContextLost = function ( event )
{
event . preventDefault ( ) ;
this . contextLost = true ;
} ;
/ * *
* Handles a restored webgl context
*
* @ method handleContextRestored
* @ param event { Event }
* @ private
* /
PIXI . WebGLRenderer . prototype . handleContextRestored = function ( )
{
2014-10-22 20:42:03 +00:00
this . initContext ( ) ;
2014-02-28 09:30:53 +00:00
2014-10-22 20:42:03 +00:00
// empty all the ol gl textures as they are useless now
2014-02-28 09:30:53 +00:00
for ( var key in PIXI . TextureCache )
{
var texture = PIXI . TextureCache [ key ] . baseTexture ;
texture . _glTextures = [ ] ;
}
2014-11-12 22:49:36 +00:00
2014-02-28 09:30:53 +00:00
this . contextLost = false ;
} ;
/ * *
* Removes everything from the renderer ( event listeners , spritebatch , etc ... )
*
* @ method destroy
* /
PIXI . WebGLRenderer . prototype . destroy = function ( )
{
// remove listeners
2014-11-08 19:26:34 +00:00
this . view . removeEventListener ( 'webglcontextlost' , this . contextLostBound ) ;
this . view . removeEventListener ( 'webglcontextrestored' , this . contextRestoredBound ) ;
2014-02-28 09:30:53 +00:00
PIXI . glContexts [ this . glContextId ] = null ;
this . projection = null ;
this . offset = null ;
// time to create the render managers! each one focuses on managine a state in webGL
this . shaderManager . destroy ( ) ;
this . spriteBatch . destroy ( ) ;
this . maskManager . destroy ( ) ;
this . filterManager . destroy ( ) ;
this . shaderManager = null ;
this . spriteBatch = null ;
this . maskManager = null ;
this . filterManager = null ;
2014-08-29 17:13:33 +00:00
2014-02-28 09:30:53 +00:00
this . gl = null ;
this . renderSession = null ;
} ;
2014-10-22 20:42:03 +00:00
/ * *
* Maps Pixi blend modes to WebGL blend modes .
*
* @ method mapBlendModes
* /
PIXI . WebGLRenderer . prototype . mapBlendModes = function ( )
{
var gl = this . gl ;
if ( ! PIXI . blendModesWebGL )
{
PIXI . blendModesWebGL = [ ] ;
PIXI . blendModesWebGL [ PIXI . blendModes . NORMAL ] = [ gl . ONE , gl . ONE _MINUS _SRC _ALPHA ] ;
PIXI . blendModesWebGL [ PIXI . blendModes . ADD ] = [ gl . SRC _ALPHA , gl . DST _ALPHA ] ;
PIXI . blendModesWebGL [ PIXI . blendModes . MULTIPLY ] = [ gl . DST _COLOR , gl . ONE _MINUS _SRC _ALPHA ] ;
PIXI . blendModesWebGL [ PIXI . blendModes . SCREEN ] = [ gl . SRC _ALPHA , gl . ONE ] ;
PIXI . blendModesWebGL [ PIXI . blendModes . OVERLAY ] = [ gl . ONE , gl . ONE _MINUS _SRC _ALPHA ] ;
PIXI . blendModesWebGL [ PIXI . blendModes . DARKEN ] = [ gl . ONE , gl . ONE _MINUS _SRC _ALPHA ] ;
PIXI . blendModesWebGL [ PIXI . blendModes . LIGHTEN ] = [ gl . ONE , gl . ONE _MINUS _SRC _ALPHA ] ;
PIXI . blendModesWebGL [ PIXI . blendModes . COLOR _DODGE ] = [ gl . ONE , gl . ONE _MINUS _SRC _ALPHA ] ;
PIXI . blendModesWebGL [ PIXI . blendModes . COLOR _BURN ] = [ gl . ONE , gl . ONE _MINUS _SRC _ALPHA ] ;
PIXI . blendModesWebGL [ PIXI . blendModes . HARD _LIGHT ] = [ gl . ONE , gl . ONE _MINUS _SRC _ALPHA ] ;
PIXI . blendModesWebGL [ PIXI . blendModes . SOFT _LIGHT ] = [ gl . ONE , gl . ONE _MINUS _SRC _ALPHA ] ;
PIXI . blendModesWebGL [ PIXI . blendModes . DIFFERENCE ] = [ gl . ONE , gl . ONE _MINUS _SRC _ALPHA ] ;
PIXI . blendModesWebGL [ PIXI . blendModes . EXCLUSION ] = [ gl . ONE , gl . ONE _MINUS _SRC _ALPHA ] ;
PIXI . blendModesWebGL [ PIXI . blendModes . HUE ] = [ gl . ONE , gl . ONE _MINUS _SRC _ALPHA ] ;
PIXI . blendModesWebGL [ PIXI . blendModes . SATURATION ] = [ gl . ONE , gl . ONE _MINUS _SRC _ALPHA ] ;
PIXI . blendModesWebGL [ PIXI . blendModes . COLOR ] = [ gl . ONE , gl . ONE _MINUS _SRC _ALPHA ] ;
PIXI . blendModesWebGL [ PIXI . blendModes . LUMINOSITY ] = [ gl . ONE , gl . ONE _MINUS _SRC _ALPHA ] ;
}
} ;
2014-02-28 09:30:53 +00:00
PIXI . WebGLRenderer . glContextId = 0 ;
2014-07-10 15:23:26 +00:00
/ * *
* @ author Mat Groves http : //matgroves.com/ @Doormat23
* /
/ * *
2014-10-22 20:42:03 +00:00
* @ class WebGLBlendModeManager
2014-07-10 15:23:26 +00:00
* @ constructor
* @ param gl { WebGLContext } the current WebGL drawing context
* /
2014-10-22 20:42:03 +00:00
PIXI . WebGLBlendModeManager = function ( )
2014-07-10 15:23:26 +00:00
{
2014-10-22 20:42:03 +00:00
/ * *
* @ property currentBlendMode
* @ type Number
* /
2014-07-10 15:23:26 +00:00
this . currentBlendMode = 99999 ;
} ;
2014-10-22 20:42:03 +00:00
PIXI . WebGLBlendModeManager . prototype . constructor = PIXI . WebGLBlendModeManager ;
/ * *
* Sets the WebGL Context .
*
* @ method setContext
* @ param gl { WebGLContext } the current WebGL drawing context
* /
PIXI . WebGLBlendModeManager . prototype . setContext = function ( gl )
{
this . gl = gl ;
} ;
2014-07-10 15:23:26 +00:00
/ * *
2014-10-22 20:42:03 +00:00
* Sets - up the given blendMode from WebGL ' s point of view .
*
2014-07-10 15:23:26 +00:00
* @ method setBlendMode
* @ param blendMode { Number } the blendMode , should be a Pixi const , such as PIXI . BlendModes . ADD
* /
PIXI . WebGLBlendModeManager . prototype . setBlendMode = function ( blendMode )
{
if ( this . currentBlendMode === blendMode ) return false ;
2014-10-22 20:42:03 +00:00
2014-07-10 15:23:26 +00:00
this . currentBlendMode = blendMode ;
var blendModeWebGL = PIXI . blendModesWebGL [ this . currentBlendMode ] ;
this . gl . blendFunc ( blendModeWebGL [ 0 ] , blendModeWebGL [ 1 ] ) ;
return true ;
} ;
2014-10-22 20:42:03 +00:00
/ * *
* Destroys this object .
*
* @ method destroy
* /
2014-07-10 15:23:26 +00:00
PIXI . WebGLBlendModeManager . prototype . destroy = function ( )
{
this . gl = null ;
} ;
2014-10-22 20:42:03 +00:00
2014-02-28 09:30:53 +00:00
/ * *
* @ author Mat Groves http : //matgroves.com/ @Doormat23
* /
/ * *
* @ class WebGLMaskManager
* @ constructor
* @ private
* /
2014-10-22 20:42:03 +00:00
PIXI . WebGLMaskManager = function ( )
2014-02-28 09:30:53 +00:00
{
} ;
2014-10-22 20:42:03 +00:00
PIXI . WebGLMaskManager . prototype . constructor = PIXI . WebGLMaskManager ;
2014-02-28 09:30:53 +00:00
/ * *
2014-10-22 20:42:03 +00:00
* Sets the drawing context to the one given in parameter .
*
2014-04-01 02:02:36 +00:00
* @ method setContext
2014-02-28 09:30:53 +00:00
* @ param gl { WebGLContext } the current WebGL drawing context
* /
PIXI . WebGLMaskManager . prototype . setContext = function ( gl )
{
this . gl = gl ;
} ;
/ * *
2014-10-22 20:42:03 +00:00
* Applies the Mask and adds it to the current filter stack .
*
2014-02-28 09:30:53 +00:00
* @ method pushMask
* @ param maskData { Array }
2014-10-22 20:42:03 +00:00
* @ param renderSession { Object }
2014-02-28 09:30:53 +00:00
* /
PIXI . WebGLMaskManager . prototype . pushMask = function ( maskData , renderSession )
{
2014-07-01 14:04:03 +00:00
var gl = renderSession . gl ;
2014-02-28 09:30:53 +00:00
2014-07-01 14:04:03 +00:00
if ( maskData . dirty )
2014-02-28 09:30:53 +00:00
{
2014-07-01 14:04:03 +00:00
PIXI . WebGLGraphics . updateGraphics ( maskData , gl ) ;
2014-02-28 09:30:53 +00:00
}
2014-07-01 14:04:03 +00:00
if ( ! maskData . _webGL [ gl . id ] . data . length ) return ;
2014-02-28 09:30:53 +00:00
2014-07-01 14:04:03 +00:00
renderSession . stencilManager . pushStencil ( maskData , maskData . _webGL [ gl . id ] . data [ 0 ] , renderSession ) ;
2014-02-28 09:30:53 +00:00
} ;
/ * *
2014-10-22 20:42:03 +00:00
* Removes the last filter from the filter stack and doesn ' t return it .
*
2014-02-28 09:30:53 +00:00
* @ method popMask
2014-10-22 20:42:03 +00:00
* @ param maskData { Array }
* @ param renderSession { Object } an object containing all the useful parameters
2014-02-28 09:30:53 +00:00
* /
2014-07-01 14:04:03 +00:00
PIXI . WebGLMaskManager . prototype . popMask = function ( maskData , renderSession )
2014-02-28 09:30:53 +00:00
{
var gl = this . gl ;
2014-07-01 14:04:03 +00:00
renderSession . stencilManager . popStencil ( maskData , maskData . _webGL [ gl . id ] . data [ 0 ] , renderSession ) ;
2014-02-28 09:30:53 +00:00
} ;
/ * *
2014-10-22 20:42:03 +00:00
* Destroys the mask stack .
*
2014-02-28 09:30:53 +00:00
* @ method destroy
* /
PIXI . WebGLMaskManager . prototype . destroy = function ( )
{
this . gl = null ;
} ;
2014-08-29 17:13:33 +00:00
2014-02-28 09:30:53 +00:00
/ * *
* @ author Mat Groves http : //matgroves.com/ @Doormat23
* /
/ * *
2014-07-01 14:04:03 +00:00
* @ class WebGLStencilManager
2014-02-28 09:30:53 +00:00
* @ constructor
* @ private
* /
2014-10-22 20:42:03 +00:00
PIXI . WebGLStencilManager = function ( )
2014-02-28 09:30:53 +00:00
{
2014-07-01 14:04:03 +00:00
this . stencilStack = [ ] ;
this . reverse = true ;
this . count = 0 ;
} ;
2014-02-28 09:30:53 +00:00
/ * *
2014-10-22 20:42:03 +00:00
* Sets the drawing context to the one given in parameter .
*
2014-04-01 02:02:36 +00:00
* @ method setContext
2014-02-28 09:30:53 +00:00
* @ param gl { WebGLContext } the current WebGL drawing context
* /
2014-07-01 14:04:03 +00:00
PIXI . WebGLStencilManager . prototype . setContext = function ( gl )
2014-02-28 09:30:53 +00:00
{
this . gl = gl ;
} ;
/ * *
2014-10-22 20:42:03 +00:00
* Applies the Mask and adds it to the current filter stack .
*
2014-07-01 14:04:03 +00:00
* @ method pushMask
2014-10-22 20:42:03 +00:00
* @ param graphics { Graphics }
* @ param webGLData { Array }
* @ param renderSession { Object }
2014-02-28 09:30:53 +00:00
* /
2014-07-01 14:04:03 +00:00
PIXI . WebGLStencilManager . prototype . pushStencil = function ( graphics , webGLData , renderSession )
2014-02-28 09:30:53 +00:00
{
2014-07-01 14:04:03 +00:00
var gl = this . gl ;
this . bindGraphics ( graphics , webGLData , renderSession ) ;
2014-02-28 09:30:53 +00:00
2014-07-01 14:04:03 +00:00
if ( this . stencilStack . length === 0 )
2014-02-28 09:30:53 +00:00
{
2014-07-01 14:04:03 +00:00
gl . enable ( gl . STENCIL _TEST ) ;
gl . clear ( gl . STENCIL _BUFFER _BIT ) ;
this . reverse = true ;
this . count = 0 ;
2014-02-28 09:30:53 +00:00
}
2014-07-01 14:04:03 +00:00
this . stencilStack . push ( webGLData ) ;
2014-02-28 09:30:53 +00:00
2014-07-01 14:04:03 +00:00
var level = this . count ;
2014-02-28 09:30:53 +00:00
2014-07-01 14:04:03 +00:00
gl . colorMask ( false , false , false , false ) ;
gl . stencilFunc ( gl . ALWAYS , 0 , 0xFF ) ;
gl . stencilOp ( gl . KEEP , gl . KEEP , gl . INVERT ) ;
// draw the triangle strip!
if ( webGLData . mode === 1 )
2014-02-28 09:30:53 +00:00
{
2014-07-01 14:04:03 +00:00
gl . drawElements ( gl . TRIANGLE _FAN , webGLData . indices . length - 4 , gl . UNSIGNED _SHORT , 0 ) ;
if ( this . reverse )
2014-02-28 09:30:53 +00:00
{
2014-07-01 14:04:03 +00:00
gl . stencilFunc ( gl . EQUAL , 0xFF - level , 0xFF ) ;
gl . stencilOp ( gl . KEEP , gl . KEEP , gl . DECR ) ;
}
else
{
gl . stencilFunc ( gl . EQUAL , level , 0xFF ) ;
gl . stencilOp ( gl . KEEP , gl . KEEP , gl . INCR ) ;
2014-02-28 09:30:53 +00:00
}
2014-07-01 14:04:03 +00:00
// draw a quad to increment..
gl . drawElements ( gl . TRIANGLE _FAN , 4 , gl . UNSIGNED _SHORT , ( webGLData . indices . length - 4 ) * 2 ) ;
if ( this . reverse )
{
gl . stencilFunc ( gl . EQUAL , 0xFF - ( level + 1 ) , 0xFF ) ;
}
else
{
gl . stencilFunc ( gl . EQUAL , level + 1 , 0xFF ) ;
}
this . reverse = ! this . reverse ;
}
else
{
if ( ! this . reverse )
{
gl . stencilFunc ( gl . EQUAL , 0xFF - level , 0xFF ) ;
gl . stencilOp ( gl . KEEP , gl . KEEP , gl . DECR ) ;
}
else
{
gl . stencilFunc ( gl . EQUAL , level , 0xFF ) ;
gl . stencilOp ( gl . KEEP , gl . KEEP , gl . INCR ) ;
}
gl . drawElements ( gl . TRIANGLE _STRIP , webGLData . indices . length , gl . UNSIGNED _SHORT , 0 ) ;
if ( ! this . reverse )
{
gl . stencilFunc ( gl . EQUAL , 0xFF - ( level + 1 ) , 0xFF ) ;
}
else
{
gl . stencilFunc ( gl . EQUAL , level + 1 , 0xFF ) ;
}
}
gl . colorMask ( true , true , true , true ) ;
gl . stencilOp ( gl . KEEP , gl . KEEP , gl . KEEP ) ;
this . count ++ ;
} ;
2014-10-22 20:42:03 +00:00
/ * *
* TODO this does not belong here !
*
* @ method bindGraphics
* @ param graphics { Graphics }
* @ param webGLData { Array }
* @ param renderSession { Object }
* /
2014-07-01 14:04:03 +00:00
PIXI . WebGLStencilManager . prototype . bindGraphics = function ( graphics , webGLData , renderSession )
2014-02-28 09:30:53 +00:00
{
2014-07-01 14:04:03 +00:00
//if(this._currentGraphics === graphics)return;
this . _currentGraphics = graphics ;
2014-02-28 09:30:53 +00:00
2014-07-01 14:04:03 +00:00
var gl = this . gl ;
2014-02-28 09:30:53 +00:00
2014-07-01 14:04:03 +00:00
// bind the graphics object..
var projection = renderSession . projection ,
offset = renderSession . offset ,
shader ; // = renderSession.shaderManager.primitiveShader;
if ( webGLData . mode === 1 )
{
2014-08-29 17:13:33 +00:00
shader = renderSession . shaderManager . complexPrimitiveShader ;
2014-07-01 14:04:03 +00:00
renderSession . shaderManager . setShader ( shader ) ;
gl . uniformMatrix3fv ( shader . translationMatrix , false , graphics . worldTransform . toArray ( true ) ) ;
gl . uniform2f ( shader . projectionVector , projection . x , - projection . y ) ;
gl . uniform2f ( shader . offsetVector , - offset . x , - offset . y ) ;
gl . uniform3fv ( shader . tintColor , PIXI . hex2rgb ( graphics . tint ) ) ;
gl . uniform3fv ( shader . color , webGLData . color ) ;
gl . uniform1f ( shader . alpha , graphics . worldAlpha * webGLData . alpha ) ;
gl . bindBuffer ( gl . ARRAY _BUFFER , webGLData . buffer ) ;
gl . vertexAttribPointer ( shader . aVertexPosition , 2 , gl . FLOAT , false , 4 * 2 , 0 ) ;
// now do the rest..
// set the index buffer!
gl . bindBuffer ( gl . ELEMENT _ARRAY _BUFFER , webGLData . indexBuffer ) ;
}
else
{
//renderSession.shaderManager.activatePrimitiveShader();
shader = renderSession . shaderManager . primitiveShader ;
renderSession . shaderManager . setShader ( shader ) ;
gl . uniformMatrix3fv ( shader . translationMatrix , false , graphics . worldTransform . toArray ( true ) ) ;
gl . uniform2f ( shader . projectionVector , projection . x , - projection . y ) ;
gl . uniform2f ( shader . offsetVector , - offset . x , - offset . y ) ;
gl . uniform3fv ( shader . tintColor , PIXI . hex2rgb ( graphics . tint ) ) ;
gl . uniform1f ( shader . alpha , graphics . worldAlpha ) ;
gl . bindBuffer ( gl . ARRAY _BUFFER , webGLData . buffer ) ;
gl . vertexAttribPointer ( shader . aVertexPosition , 2 , gl . FLOAT , false , 4 * 6 , 0 ) ;
gl . vertexAttribPointer ( shader . colorAttribute , 4 , gl . FLOAT , false , 4 * 6 , 2 * 4 ) ;
// set the index buffer!
gl . bindBuffer ( gl . ELEMENT _ARRAY _BUFFER , webGLData . indexBuffer ) ;
}
} ;
2014-10-22 20:42:03 +00:00
/ * *
* @ method popStencil
* @ param graphics { Graphics }
* @ param webGLData { Array }
* @ param renderSession { Object }
* /
2014-07-01 14:04:03 +00:00
PIXI . WebGLStencilManager . prototype . popStencil = function ( graphics , webGLData , renderSession )
{
var gl = this . gl ;
this . stencilStack . pop ( ) ;
this . count -- ;
if ( this . stencilStack . length === 0 )
{
// the stack is empty!
gl . disable ( gl . STENCIL _TEST ) ;
}
else
{
var level = this . count ;
this . bindGraphics ( graphics , webGLData , renderSession ) ;
gl . colorMask ( false , false , false , false ) ;
if ( webGLData . mode === 1 )
{
this . reverse = ! this . reverse ;
if ( this . reverse )
{
gl . stencilFunc ( gl . EQUAL , 0xFF - ( level + 1 ) , 0xFF ) ;
gl . stencilOp ( gl . KEEP , gl . KEEP , gl . INCR ) ;
}
else
{
gl . stencilFunc ( gl . EQUAL , level + 1 , 0xFF ) ;
gl . stencilOp ( gl . KEEP , gl . KEEP , gl . DECR ) ;
}
// draw a quad to increment..
gl . drawElements ( gl . TRIANGLE _FAN , 4 , gl . UNSIGNED _SHORT , ( webGLData . indices . length - 4 ) * 2 ) ;
gl . stencilFunc ( gl . ALWAYS , 0 , 0xFF ) ;
gl . stencilOp ( gl . KEEP , gl . KEEP , gl . INVERT ) ;
// draw the triangle strip!
gl . drawElements ( gl . TRIANGLE _FAN , webGLData . indices . length - 4 , gl . UNSIGNED _SHORT , 0 ) ;
if ( ! this . reverse )
{
gl . stencilFunc ( gl . EQUAL , 0xFF - ( level ) , 0xFF ) ;
}
else
{
gl . stencilFunc ( gl . EQUAL , level , 0xFF ) ;
}
}
else
{
// console.log("<<>>")
if ( ! this . reverse )
{
gl . stencilFunc ( gl . EQUAL , 0xFF - ( level + 1 ) , 0xFF ) ;
gl . stencilOp ( gl . KEEP , gl . KEEP , gl . INCR ) ;
}
else
{
gl . stencilFunc ( gl . EQUAL , level + 1 , 0xFF ) ;
gl . stencilOp ( gl . KEEP , gl . KEEP , gl . DECR ) ;
}
gl . drawElements ( gl . TRIANGLE _STRIP , webGLData . indices . length , gl . UNSIGNED _SHORT , 0 ) ;
if ( ! this . reverse )
{
gl . stencilFunc ( gl . EQUAL , 0xFF - ( level ) , 0xFF ) ;
}
else
{
gl . stencilFunc ( gl . EQUAL , level , 0xFF ) ;
}
}
gl . colorMask ( true , true , true , true ) ;
gl . stencilOp ( gl . KEEP , gl . KEEP , gl . KEEP ) ;
}
2014-02-28 09:30:53 +00:00
} ;
/ * *
2014-10-22 20:42:03 +00:00
* Destroys the mask stack .
*
2014-07-01 14:04:03 +00:00
* @ method destroy
2014-02-28 09:30:53 +00:00
* /
2014-07-01 14:04:03 +00:00
PIXI . WebGLStencilManager . prototype . destroy = function ( )
2014-02-28 09:30:53 +00:00
{
2014-08-29 17:13:33 +00:00
this . stencilStack = null ;
2014-07-01 14:04:03 +00:00
this . gl = null ;
} ;
2014-08-29 17:13:33 +00:00
2014-07-01 14:04:03 +00:00
/ * *
* @ author Mat Groves http : //matgroves.com/ @Doormat23
* /
/ * *
* @ class WebGLShaderManager
* @ constructor
* @ private
* /
2014-10-22 20:42:03 +00:00
PIXI . WebGLShaderManager = function ( )
2014-07-01 14:04:03 +00:00
{
2014-10-22 20:42:03 +00:00
/ * *
* @ property maxAttibs
* @ type Number
* /
2014-07-01 14:04:03 +00:00
this . maxAttibs = 10 ;
2014-10-22 20:42:03 +00:00
/ * *
* @ property attribState
* @ type Array
* /
2014-07-01 14:04:03 +00:00
this . attribState = [ ] ;
2014-10-22 20:42:03 +00:00
/ * *
* @ property tempAttribState
* @ type Array
* /
2014-07-01 14:04:03 +00:00
this . tempAttribState = [ ] ;
2014-10-22 20:42:03 +00:00
for ( var i = 0 ; i < this . maxAttibs ; i ++ )
{
2014-07-01 14:04:03 +00:00
this . attribState [ i ] = false ;
}
2014-10-22 20:42:03 +00:00
/ * *
* @ property stack
* @ type Array
* /
this . stack = [ ] ;
2014-07-01 14:04:03 +00:00
} ;
2014-02-28 09:30:53 +00:00
2014-10-22 20:42:03 +00:00
PIXI . WebGLShaderManager . prototype . constructor = PIXI . WebGLShaderManager ;
2014-02-28 09:30:53 +00:00
2014-07-01 14:04:03 +00:00
/ * *
2014-10-22 20:42:03 +00:00
* Initialises the context and the properties .
*
2014-07-01 14:04:03 +00:00
* @ method setContext
* @ param gl { WebGLContext } the current WebGL drawing context
* /
PIXI . WebGLShaderManager . prototype . setContext = function ( gl )
{
this . gl = gl ;
2014-04-01 02:02:36 +00:00
2014-10-22 20:42:03 +00:00
// the next one is used for rendering primitives
2014-07-01 14:04:03 +00:00
this . primitiveShader = new PIXI . PrimitiveShader ( gl ) ;
// the next one is used for rendering triangle strips
2014-08-29 17:13:33 +00:00
this . complexPrimitiveShader = new PIXI . ComplexPrimitiveShader ( gl ) ;
2014-07-01 14:04:03 +00:00
// this shader is used for the default sprite rendering
this . defaultShader = new PIXI . PixiShader ( gl ) ;
// this shader is used for the fast sprite rendering
this . fastShader = new PIXI . PixiFastShader ( gl ) ;
// the next one is used for rendering triangle strips
this . stripShader = new PIXI . StripShader ( gl ) ;
this . setShader ( this . defaultShader ) ;
2014-02-28 09:30:53 +00:00
} ;
/ * *
2014-10-22 20:42:03 +00:00
* Takes the attributes given in parameters .
*
2014-07-01 14:04:03 +00:00
* @ method setAttribs
* @ param attribs { Array } attribs
2014-02-28 09:30:53 +00:00
* /
2014-07-01 14:04:03 +00:00
PIXI . WebGLShaderManager . prototype . setAttribs = function ( attribs )
2014-02-28 09:30:53 +00:00
{
2014-07-01 14:04:03 +00:00
// reset temp state
var i ;
for ( i = 0 ; i < this . tempAttribState . length ; i ++ )
{
this . tempAttribState [ i ] = false ;
}
// set the new attribs
for ( i = 0 ; i < attribs . length ; i ++ )
{
var attribId = attribs [ i ] ;
this . tempAttribState [ attribId ] = true ;
}
2014-02-28 09:30:53 +00:00
var gl = this . gl ;
2014-07-01 14:04:03 +00:00
for ( i = 0 ; i < this . attribState . length ; i ++ )
{
if ( this . attribState [ i ] !== this . tempAttribState [ i ] )
{
this . attribState [ i ] = this . tempAttribState [ i ] ;
if ( this . tempAttribState [ i ] )
{
gl . enableVertexAttribArray ( i ) ;
}
else
{
gl . disableVertexAttribArray ( i ) ;
}
}
}
} ;
2014-10-22 20:42:03 +00:00
/ * *
* Sets the current shader .
*
* @ method setShader
* @ param shader { Any }
* /
2014-07-01 14:04:03 +00:00
PIXI . WebGLShaderManager . prototype . setShader = function ( shader )
{
2014-07-10 15:23:26 +00:00
if ( this . _currentId === shader . _UID ) return false ;
2014-07-01 14:04:03 +00:00
this . _currentId = shader . _UID ;
this . currentShader = shader ;
2014-02-28 09:30:53 +00:00
2014-07-01 14:04:03 +00:00
this . gl . useProgram ( shader . program ) ;
this . setAttribs ( shader . attributes ) ;
2014-07-10 15:23:26 +00:00
return true ;
2014-02-28 09:30:53 +00:00
} ;
/ * *
2014-10-22 20:42:03 +00:00
* Destroys this object .
*
2014-02-28 09:30:53 +00:00
* @ method destroy
* /
PIXI . WebGLShaderManager . prototype . destroy = function ( )
{
this . attribState = null ;
this . tempAttribState = null ;
this . primitiveShader . destroy ( ) ;
2014-08-29 17:13:33 +00:00
this . complexPrimitiveShader . destroy ( ) ;
2014-02-28 09:30:53 +00:00
this . defaultShader . destroy ( ) ;
this . fastShader . destroy ( ) ;
2014-07-01 14:04:03 +00:00
this . stripShader . destroy ( ) ;
2014-02-28 09:30:53 +00:00
this . gl = null ;
} ;
/ * *
* @ author Mat Groves
2014-04-01 02:02:36 +00:00
*
2014-02-28 09:30:53 +00:00
* Big thanks to the very clever Matt DesLauriers < mattdesl > https : //github.com/mattdesl/
* for creating the original pixi version !
*
* Heavily inspired by LibGDX ' s WebGLSpriteBatch :
* https : //github.com/libgdx/libgdx/blob/master/gdx/src/com/badlogic/gdx/graphics/g2d/WebGLSpriteBatch.java
* /
/ * *
*
* @ class WebGLSpriteBatch
* @ private
* @ constructor
* /
2014-10-22 20:42:03 +00:00
PIXI . WebGLSpriteBatch = function ( )
2014-02-28 09:30:53 +00:00
{
/ * *
* @ property vertSize
* @ type Number
* /
this . vertSize = 6 ;
/ * *
* The number of images in the SpriteBatch before it flushes
* @ property size
* @ type Number
* /
2014-03-04 01:29:04 +00:00
this . size = 2000 ; //Math.pow(2, 16) / this.vertSize;
2014-02-28 09:30:53 +00:00
//the total number of floats in our batch
var numVerts = this . size * 4 * this . vertSize ;
//the total number of indices in our batch
var numIndices = this . size * 6 ;
/ * *
* Holds the vertices
*
* @ property vertices
* @ type Float32Array
* /
2014-11-08 19:26:34 +00:00
this . vertices = new PIXI . Float32Array ( numVerts ) ;
2014-02-28 09:30:53 +00:00
/ * *
* Holds the indices
*
* @ property indices
* @ type Uint16Array
* /
2014-11-08 19:26:34 +00:00
this . indices = new PIXI . Uint16Array ( numIndices ) ;
2014-04-01 02:02:36 +00:00
2014-10-22 20:42:03 +00:00
/ * *
* @ property lastIndexCount
* @ type Number
* /
2014-02-28 09:30:53 +00:00
this . lastIndexCount = 0 ;
for ( var i = 0 , j = 0 ; i < numIndices ; i += 6 , j += 4 )
{
this . indices [ i + 0 ] = j + 0 ;
this . indices [ i + 1 ] = j + 1 ;
this . indices [ i + 2 ] = j + 2 ;
this . indices [ i + 3 ] = j + 0 ;
this . indices [ i + 4 ] = j + 2 ;
this . indices [ i + 5 ] = j + 3 ;
}
2014-10-22 20:42:03 +00:00
/ * *
* @ property drawing
* @ type Boolean
* /
2014-02-28 09:30:53 +00:00
this . drawing = false ;
2014-10-22 20:42:03 +00:00
/ * *
* @ property currentBatchSize
* @ type Number
* /
2014-02-28 09:30:53 +00:00
this . currentBatchSize = 0 ;
2014-10-22 20:42:03 +00:00
/ * *
* @ property currentBaseTexture
* @ type BaseTexture
* /
2014-02-28 09:30:53 +00:00
this . currentBaseTexture = null ;
2014-07-10 15:23:26 +00:00
2014-10-22 20:42:03 +00:00
/ * *
* @ property dirty
* @ type Boolean
* /
2014-07-10 15:23:26 +00:00
this . dirty = true ;
2014-07-16 00:58:24 +00:00
2014-10-22 20:42:03 +00:00
/ * *
* @ property textures
* @ type Array
* /
2014-07-16 00:58:24 +00:00
this . textures = [ ] ;
2014-10-22 20:42:03 +00:00
/ * *
* @ property blendModes
* @ type Array
* /
2014-07-16 00:58:24 +00:00
this . blendModes = [ ] ;
2014-10-22 20:42:03 +00:00
/ * *
* @ property shaders
* @ type Array
* /
this . shaders = [ ] ;
/ * *
* @ property sprites
* @ type Array
* /
this . sprites = [ ] ;
/ * *
* @ property defaultShader
* @ type AbstractFilter
* /
this . defaultShader = new PIXI . AbstractFilter ( [
'precision lowp float;' ,
'varying vec2 vTextureCoord;' ,
'varying vec4 vColor;' ,
'uniform sampler2D uSampler;' ,
'void main(void) {' ,
' gl_FragColor = texture2D(uSampler, vTextureCoord) * vColor ;' ,
'}'
] ) ;
2014-02-28 09:30:53 +00:00
} ;
/ * *
* @ method setContext
* @ param gl { WebGLContext } the current WebGL drawing context
* /
PIXI . WebGLSpriteBatch . prototype . setContext = function ( gl )
{
this . gl = gl ;
// create a couple of buffers
this . vertexBuffer = gl . createBuffer ( ) ;
this . indexBuffer = gl . createBuffer ( ) ;
// 65535 is max index, so 65535 / 6 = 10922.
//upload the index data
gl . bindBuffer ( gl . ELEMENT _ARRAY _BUFFER , this . indexBuffer ) ;
gl . bufferData ( gl . ELEMENT _ARRAY _BUFFER , this . indices , gl . STATIC _DRAW ) ;
gl . bindBuffer ( gl . ARRAY _BUFFER , this . vertexBuffer ) ;
gl . bufferData ( gl . ARRAY _BUFFER , this . vertices , gl . DYNAMIC _DRAW ) ;
this . currentBlendMode = 99999 ;
2014-10-22 20:42:03 +00:00
var shader = new PIXI . PixiShader ( gl ) ;
shader . fragmentSrc = this . defaultShader . fragmentSrc ;
shader . uniforms = { } ;
shader . init ( ) ;
this . defaultShader . shaders [ gl . id ] = shader ;
2014-02-28 09:30:53 +00:00
} ;
/ * *
* @ method begin
2014-10-22 20:42:03 +00:00
* @ param renderSession { Object } The RenderSession object
2014-02-28 09:30:53 +00:00
* /
PIXI . WebGLSpriteBatch . prototype . begin = function ( renderSession )
{
this . renderSession = renderSession ;
this . shader = this . renderSession . shaderManager . defaultShader ;
this . start ( ) ;
} ;
/ * *
* @ method end
* /
PIXI . WebGLSpriteBatch . prototype . end = function ( )
{
this . flush ( ) ;
} ;
/ * *
* @ method render
* @ param sprite { Sprite } the sprite to render when using this spritebatch
* /
PIXI . WebGLSpriteBatch . prototype . render = function ( sprite )
{
var texture = sprite . texture ;
2014-07-16 00:58:24 +00:00
//TODO set blend modes..
2014-02-28 09:30:53 +00:00
// check texture..
2014-07-16 00:58:24 +00:00
if ( this . currentBatchSize >= this . size )
2014-02-28 09:30:53 +00:00
{
this . flush ( ) ;
this . currentBaseTexture = texture . baseTexture ;
}
// get the uvs for the texture
2014-07-10 15:23:26 +00:00
var uvs = texture . _uvs ;
2014-02-28 09:30:53 +00:00
// if the uvs have not updated then no point rendering just yet!
if ( ! uvs ) return ;
// get the sprites current alpha
var alpha = sprite . worldAlpha ;
var tint = sprite . tint ;
var verticies = this . vertices ;
// TODO trim??
var aX = sprite . anchor . x ;
var aY = sprite . anchor . y ;
var w0 , w1 , h0 , h1 ;
2014-04-01 02:02:36 +00:00
2014-07-10 15:23:26 +00:00
if ( texture . trim )
2014-02-28 09:30:53 +00:00
{
// if the sprite is trimmed then we need to add the extra space before transforming the sprite coords..
2014-07-10 15:23:26 +00:00
var trim = texture . trim ;
2014-02-28 09:30:53 +00:00
w1 = trim . x - aX * trim . width ;
2014-07-10 15:23:26 +00:00
w0 = w1 + texture . crop . width ;
2014-02-28 09:30:53 +00:00
h1 = trim . y - aY * trim . height ;
2014-07-10 15:23:26 +00:00
h0 = h1 + texture . crop . height ;
2014-02-28 09:30:53 +00:00
}
else
{
w0 = ( texture . frame . width ) * ( 1 - aX ) ;
w1 = ( texture . frame . width ) * - aX ;
h0 = texture . frame . height * ( 1 - aY ) ;
h1 = texture . frame . height * - aY ;
}
var index = this . currentBatchSize * 4 * this . vertSize ;
2014-10-22 20:42:03 +00:00
var resolution = texture . baseTexture . resolution ;
2014-02-28 09:30:53 +00:00
2014-07-16 00:58:24 +00:00
var worldTransform = sprite . worldTransform ;
2014-02-28 09:30:53 +00:00
2014-10-22 20:42:03 +00:00
var a = worldTransform . a / resolution ;
var b = worldTransform . b / resolution ;
var c = worldTransform . c / resolution ;
var d = worldTransform . d / resolution ;
var tx = worldTransform . tx ;
var ty = worldTransform . ty ;
2014-02-28 09:30:53 +00:00
// xy
verticies [ index ++ ] = a * w1 + c * h1 + tx ;
verticies [ index ++ ] = d * h1 + b * w1 + ty ;
// uv
verticies [ index ++ ] = uvs . x0 ;
verticies [ index ++ ] = uvs . y0 ;
// color
verticies [ index ++ ] = alpha ;
verticies [ index ++ ] = tint ;
// xy
verticies [ index ++ ] = a * w0 + c * h1 + tx ;
verticies [ index ++ ] = d * h1 + b * w0 + ty ;
// uv
verticies [ index ++ ] = uvs . x1 ;
verticies [ index ++ ] = uvs . y1 ;
// color
verticies [ index ++ ] = alpha ;
verticies [ index ++ ] = tint ;
// xy
verticies [ index ++ ] = a * w0 + c * h0 + tx ;
verticies [ index ++ ] = d * h0 + b * w0 + ty ;
// uv
verticies [ index ++ ] = uvs . x2 ;
verticies [ index ++ ] = uvs . y2 ;
// color
verticies [ index ++ ] = alpha ;
verticies [ index ++ ] = tint ;
// xy
verticies [ index ++ ] = a * w1 + c * h0 + tx ;
verticies [ index ++ ] = d * h0 + b * w1 + ty ;
// uv
verticies [ index ++ ] = uvs . x3 ;
verticies [ index ++ ] = uvs . y3 ;
// color
verticies [ index ++ ] = alpha ;
verticies [ index ++ ] = tint ;
2014-04-01 02:02:36 +00:00
2014-02-28 09:30:53 +00:00
// increment the batchsize
2014-10-22 20:42:03 +00:00
this . sprites [ this . currentBatchSize ++ ] = sprite ;
2014-02-28 09:30:53 +00:00
} ;
/ * *
2014-10-22 20:42:03 +00:00
* Renders a TilingSprite using the spriteBatch .
2014-04-01 02:02:36 +00:00
*
2014-10-22 20:42:03 +00:00
* @ method renderTilingSprite
2014-02-28 09:30:53 +00:00
* @ param sprite { TilingSprite } the tilingSprite to render
* /
PIXI . WebGLSpriteBatch . prototype . renderTilingSprite = function ( tilingSprite )
{
var texture = tilingSprite . tilingTexture ;
2014-07-10 15:23:26 +00:00
// check texture..
2014-07-16 00:58:24 +00:00
if ( this . currentBatchSize >= this . size )
2014-02-28 09:30:53 +00:00
{
2014-07-16 00:58:24 +00:00
//return;
2014-02-28 09:30:53 +00:00
this . flush ( ) ;
this . currentBaseTexture = texture . baseTexture ;
}
// set the textures uvs temporarily
// TODO create a separate texture so that we can tile part of a texture
if ( ! tilingSprite . _uvs ) tilingSprite . _uvs = new PIXI . TextureUvs ( ) ;
var uvs = tilingSprite . _uvs ;
tilingSprite . tilePosition . x %= texture . baseTexture . width * tilingSprite . tileScaleOffset . x ;
tilingSprite . tilePosition . y %= texture . baseTexture . height * tilingSprite . tileScaleOffset . y ;
var offsetX = tilingSprite . tilePosition . x / ( texture . baseTexture . width * tilingSprite . tileScaleOffset . x ) ;
var offsetY = tilingSprite . tilePosition . y / ( texture . baseTexture . height * tilingSprite . tileScaleOffset . y ) ;
var scaleX = ( tilingSprite . width / texture . baseTexture . width ) / ( tilingSprite . tileScale . x * tilingSprite . tileScaleOffset . x ) ;
var scaleY = ( tilingSprite . height / texture . baseTexture . height ) / ( tilingSprite . tileScale . y * tilingSprite . tileScaleOffset . y ) ;
uvs . x0 = 0 - offsetX ;
uvs . y0 = 0 - offsetY ;
uvs . x1 = ( 1 * scaleX ) - offsetX ;
uvs . y1 = 0 - offsetY ;
uvs . x2 = ( 1 * scaleX ) - offsetX ;
uvs . y2 = ( 1 * scaleY ) - offsetY ;
uvs . x3 = 0 - offsetX ;
uvs . y3 = ( 1 * scaleY ) - offsetY ;
// get the tilingSprites current alpha
var alpha = tilingSprite . worldAlpha ;
var tint = tilingSprite . tint ;
var verticies = this . vertices ;
var width = tilingSprite . width ;
var height = tilingSprite . height ;
// TODO trim??
2014-07-16 00:58:24 +00:00
var aX = tilingSprite . anchor . x ;
var aY = tilingSprite . anchor . y ;
2014-02-28 09:30:53 +00:00
var w0 = width * ( 1 - aX ) ;
var w1 = width * - aX ;
var h0 = height * ( 1 - aY ) ;
var h1 = height * - aY ;
var index = this . currentBatchSize * 4 * this . vertSize ;
2014-10-22 20:42:03 +00:00
var resolution = texture . baseTexture . resolution ;
2014-02-28 09:30:53 +00:00
var worldTransform = tilingSprite . worldTransform ;
2014-10-22 20:42:03 +00:00
var a = worldTransform . a / resolution ; //[0];
var b = worldTransform . b / resolution ; //[3];
var c = worldTransform . c / resolution ; //[1];
var d = worldTransform . d / resolution ; //[4];
2014-02-28 09:30:53 +00:00
var tx = worldTransform . tx ; //[2];
var ty = worldTransform . ty ; ///[5];
// xy
verticies [ index ++ ] = a * w1 + c * h1 + tx ;
verticies [ index ++ ] = d * h1 + b * w1 + ty ;
// uv
verticies [ index ++ ] = uvs . x0 ;
verticies [ index ++ ] = uvs . y0 ;
// color
verticies [ index ++ ] = alpha ;
verticies [ index ++ ] = tint ;
// xy
2014-07-16 00:58:24 +00:00
verticies [ index ++ ] = ( a * w0 + c * h1 + tx ) ;
2014-02-28 09:30:53 +00:00
verticies [ index ++ ] = d * h1 + b * w0 + ty ;
// uv
verticies [ index ++ ] = uvs . x1 ;
verticies [ index ++ ] = uvs . y1 ;
// color
verticies [ index ++ ] = alpha ;
verticies [ index ++ ] = tint ;
2014-04-01 02:02:36 +00:00
2014-02-28 09:30:53 +00:00
// xy
verticies [ index ++ ] = a * w0 + c * h0 + tx ;
verticies [ index ++ ] = d * h0 + b * w0 + ty ;
// uv
verticies [ index ++ ] = uvs . x2 ;
verticies [ index ++ ] = uvs . y2 ;
// color
verticies [ index ++ ] = alpha ;
verticies [ index ++ ] = tint ;
// xy
verticies [ index ++ ] = a * w1 + c * h0 + tx ;
verticies [ index ++ ] = d * h0 + b * w1 + ty ;
// uv
verticies [ index ++ ] = uvs . x3 ;
verticies [ index ++ ] = uvs . y3 ;
// color
verticies [ index ++ ] = alpha ;
verticies [ index ++ ] = tint ;
2014-10-22 20:42:03 +00:00
// increment the batchsize
this . sprites [ this . currentBatchSize ++ ] = tilingSprite ;
2014-02-28 09:30:53 +00:00
} ;
/ * *
2014-10-22 20:42:03 +00:00
* Renders the content and empties the current batch .
2014-02-28 09:30:53 +00:00
*
* @ method flush
* /
PIXI . WebGLSpriteBatch . prototype . flush = function ( )
{
// If the batch is length 0 then return as there is nothing to draw
if ( this . currentBatchSize === 0 ) return ;
var gl = this . gl ;
2014-10-22 20:42:03 +00:00
var shader ;
2014-07-01 14:04:03 +00:00
2014-07-10 15:23:26 +00:00
if ( this . dirty )
{
this . dirty = false ;
// bind the main texture
gl . activeTexture ( gl . TEXTURE0 ) ;
// bind the buffers
gl . bindBuffer ( gl . ARRAY _BUFFER , this . vertexBuffer ) ;
gl . bindBuffer ( gl . ELEMENT _ARRAY _BUFFER , this . indexBuffer ) ;
2014-10-22 20:42:03 +00:00
shader = this . defaultShader . shaders [ gl . id ] ;
2014-07-10 15:23:26 +00:00
2014-10-22 20:42:03 +00:00
// this is the same for each shader?
2014-07-10 15:23:26 +00:00
var stride = this . vertSize * 4 ;
2014-10-22 20:42:03 +00:00
gl . vertexAttribPointer ( shader . aVertexPosition , 2 , gl . FLOAT , false , stride , 0 ) ;
gl . vertexAttribPointer ( shader . aTextureCoord , 2 , gl . FLOAT , false , stride , 2 * 4 ) ;
gl . vertexAttribPointer ( shader . colorAttribute , 2 , gl . FLOAT , false , stride , 4 * 4 ) ;
2014-07-10 15:23:26 +00:00
}
2014-07-01 14:04:03 +00:00
// upload the verts to the buffer
2014-02-28 09:30:53 +00:00
if ( this . currentBatchSize > ( this . size * 0.5 ) )
{
gl . bufferSubData ( gl . ARRAY _BUFFER , 0 , this . vertices ) ;
}
else
{
var view = this . vertices . subarray ( 0 , this . currentBatchSize * 4 * this . vertSize ) ;
gl . bufferSubData ( gl . ARRAY _BUFFER , 0 , view ) ;
}
2014-10-22 20:42:03 +00:00
var nextTexture , nextBlendMode , nextShader ;
2014-07-16 00:58:24 +00:00
var batchSize = 0 ;
var start = 0 ;
var currentBaseTexture = null ;
var currentBlendMode = this . renderSession . blendModeManager . currentBlendMode ;
2014-10-22 20:42:03 +00:00
var currentShader = null ;
var blendSwap = false ;
var shaderSwap = false ;
var sprite ;
2014-07-16 00:58:24 +00:00
for ( var i = 0 , j = this . currentBatchSize ; i < j ; i ++ ) {
2014-10-22 20:42:03 +00:00
sprite = this . sprites [ i ] ;
nextTexture = sprite . texture . baseTexture ;
nextBlendMode = sprite . blendMode ;
nextShader = sprite . shader || this . defaultShader ;
2014-07-16 00:58:24 +00:00
2014-10-22 20:42:03 +00:00
blendSwap = currentBlendMode !== nextBlendMode ;
shaderSwap = currentShader !== nextShader ; // should I use _UIDS???
if ( currentBaseTexture !== nextTexture || blendSwap || shaderSwap )
2014-07-16 00:58:24 +00:00
{
this . renderBatch ( currentBaseTexture , batchSize , start ) ;
start = i ;
batchSize = 0 ;
currentBaseTexture = nextTexture ;
2014-10-22 20:42:03 +00:00
if ( blendSwap )
{
currentBlendMode = nextBlendMode ;
this . renderSession . blendModeManager . setBlendMode ( currentBlendMode ) ;
}
if ( shaderSwap )
{
currentShader = nextShader ;
shader = currentShader . shaders [ gl . id ] ;
if ( ! shader )
{
shader = new PIXI . PixiShader ( gl ) ;
shader . fragmentSrc = currentShader . fragmentSrc ;
shader . uniforms = currentShader . uniforms ;
shader . init ( ) ;
currentShader . shaders [ gl . id ] = shader ;
}
// set shader function???
this . renderSession . shaderManager . setShader ( shader ) ;
if ( shader . dirty ) shader . syncUniforms ( ) ;
// both thease only need to be set if they are changing..
// set the projection
var projection = this . renderSession . projection ;
gl . uniform2f ( shader . projectionVector , projection . x , projection . y ) ;
// TODO - this is temprorary!
var offsetVector = this . renderSession . offset ;
gl . uniform2f ( shader . offsetVector , offsetVector . x , offsetVector . y ) ;
// set the pointers
}
2014-07-16 00:58:24 +00:00
}
batchSize ++ ;
}
this . renderBatch ( currentBaseTexture , batchSize , start ) ;
2014-02-28 09:30:53 +00:00
// then reset the batch!
this . currentBatchSize = 0 ;
2014-07-16 00:58:24 +00:00
} ;
2014-02-28 09:30:53 +00:00
2014-10-22 20:42:03 +00:00
/ * *
* @ method renderBatch
* @ param texture { Texture }
* @ param size { Number }
* @ param startIndex { Number }
* /
2014-07-16 00:58:24 +00:00
PIXI . WebGLSpriteBatch . prototype . renderBatch = function ( texture , size , startIndex )
{
if ( size === 0 ) return ;
var gl = this . gl ;
// check if a texture is dirty..
if ( texture . _dirty [ gl . id ] )
{
2014-10-22 20:42:03 +00:00
this . renderSession . renderer . updateTexture ( texture ) ;
2014-07-16 00:58:24 +00:00
}
2014-10-22 20:42:03 +00:00
else
{
// bind the current texture
gl . bindTexture ( gl . TEXTURE _2D , texture . _glTextures [ gl . id ] ) ;
}
// now draw those suckas!
2014-07-16 00:58:24 +00:00
gl . drawElements ( gl . TRIANGLES , size * 6 , gl . UNSIGNED _SHORT , startIndex * 6 * 2 ) ;
2014-02-28 09:30:53 +00:00
// increment the draw count
this . renderSession . drawCount ++ ;
} ;
/ * *
* @ method stop
* /
PIXI . WebGLSpriteBatch . prototype . stop = function ( )
{
this . flush ( ) ;
2014-10-22 20:42:03 +00:00
this . dirty = true ;
2014-02-28 09:30:53 +00:00
} ;
/ * *
* @ method start
* /
PIXI . WebGLSpriteBatch . prototype . start = function ( )
{
2014-07-10 15:23:26 +00:00
this . dirty = true ;
2014-02-28 09:30:53 +00:00
} ;
/ * *
2014-10-22 20:42:03 +00:00
* Destroys the SpriteBatch .
*
2014-02-28 09:30:53 +00:00
* @ method destroy
* /
PIXI . WebGLSpriteBatch . prototype . destroy = function ( )
{
this . vertices = null ;
this . indices = null ;
2014-04-01 02:02:36 +00:00
2014-02-28 09:30:53 +00:00
this . gl . deleteBuffer ( this . vertexBuffer ) ;
this . gl . deleteBuffer ( this . indexBuffer ) ;
2014-04-01 02:02:36 +00:00
2014-02-28 09:30:53 +00:00
this . currentBaseTexture = null ;
2014-04-01 02:02:36 +00:00
2014-02-28 09:30:53 +00:00
this . gl = null ;
} ;
/ * *
* @ author Mat Groves
2014-04-01 02:02:36 +00:00
*
2014-02-28 09:30:53 +00:00
* Big thanks to the very clever Matt DesLauriers < mattdesl > https : //github.com/mattdesl/
* for creating the original pixi version !
*
* Heavily inspired by LibGDX ' s WebGLSpriteBatch :
* https : //github.com/libgdx/libgdx/blob/master/gdx/src/com/badlogic/gdx/graphics/g2d/WebGLSpriteBatch.java
* /
2014-10-22 20:42:03 +00:00
/ * *
* @ class WebGLFastSpriteBatch
* @ constructor
* /
2014-10-23 11:34:33 +00:00
PIXI . WebGLFastSpriteBatch = function ( gl )
2014-02-28 09:30:53 +00:00
{
2014-10-22 20:42:03 +00:00
/ * *
* @ property vertSize
* @ type Number
* /
2014-02-28 09:30:53 +00:00
this . vertSize = 10 ;
2014-10-22 20:42:03 +00:00
/ * *
* @ property maxSize
* @ type Number
* /
2014-02-28 09:30:53 +00:00
this . maxSize = 6000 ; //Math.pow(2, 16) / this.vertSize;
2014-10-22 20:42:03 +00:00
/ * *
* @ property size
* @ type Number
* /
2014-02-28 09:30:53 +00:00
this . size = this . maxSize ;
//the total number of floats in our batch
var numVerts = this . size * 4 * this . vertSize ;
2014-10-22 20:42:03 +00:00
2014-02-28 09:30:53 +00:00
//the total number of indices in our batch
var numIndices = this . maxSize * 6 ;
2014-10-22 20:42:03 +00:00
/ * *
* Vertex data
* @ property vertices
* @ type Float32Array
* /
2014-11-08 19:26:34 +00:00
this . vertices = new PIXI . Float32Array ( numVerts ) ;
2014-10-22 20:42:03 +00:00
/ * *
* Index data
* @ property indices
* @ type Uint16Array
* /
2014-11-08 19:26:34 +00:00
this . indices = new PIXI . Uint16Array ( numIndices ) ;
2014-04-01 02:02:36 +00:00
2014-10-22 20:42:03 +00:00
/ * *
* @ property vertexBuffer
* @ type Object
* /
2014-02-28 09:30:53 +00:00
this . vertexBuffer = null ;
2014-10-22 20:42:03 +00:00
/ * *
* @ property indexBuffer
* @ type Object
* /
2014-02-28 09:30:53 +00:00
this . indexBuffer = null ;
2014-10-22 20:42:03 +00:00
/ * *
* @ property lastIndexCount
* @ type Number
* /
2014-02-28 09:30:53 +00:00
this . lastIndexCount = 0 ;
for ( var i = 0 , j = 0 ; i < numIndices ; i += 6 , j += 4 )
{
this . indices [ i + 0 ] = j + 0 ;
this . indices [ i + 1 ] = j + 1 ;
this . indices [ i + 2 ] = j + 2 ;
this . indices [ i + 3 ] = j + 0 ;
this . indices [ i + 4 ] = j + 2 ;
this . indices [ i + 5 ] = j + 3 ;
}
2014-10-22 20:42:03 +00:00
/ * *
* @ property drawing
* @ type Boolean
* /
2014-02-28 09:30:53 +00:00
this . drawing = false ;
2014-10-22 20:42:03 +00:00
/ * *
* @ property currentBatchSize
* @ type Number
* /
2014-02-28 09:30:53 +00:00
this . currentBatchSize = 0 ;
2014-10-22 20:42:03 +00:00
/ * *
* @ property currentBaseTexture
* @ type BaseTexture
* /
2014-02-28 09:30:53 +00:00
this . currentBaseTexture = null ;
2014-04-01 02:02:36 +00:00
2014-10-22 20:42:03 +00:00
/ * *
* @ property currentBlendMode
* @ type Number
* /
2014-02-28 09:30:53 +00:00
this . currentBlendMode = 0 ;
2014-10-22 20:42:03 +00:00
/ * *
* @ property renderSession
* @ type Object
* /
2014-02-28 09:30:53 +00:00
this . renderSession = null ;
2014-04-01 02:02:36 +00:00
2014-10-22 20:42:03 +00:00
/ * *
* @ property shader
* @ type Object
* /
2014-02-28 09:30:53 +00:00
this . shader = null ;
2014-10-22 20:42:03 +00:00
/ * *
* @ property matrix
* @ type Matrix
* /
2014-02-28 09:30:53 +00:00
this . matrix = null ;
2014-10-23 11:34:33 +00:00
this . setContext ( gl ) ;
2014-02-28 09:30:53 +00:00
} ;
2014-10-22 20:42:03 +00:00
PIXI . WebGLFastSpriteBatch . prototype . constructor = PIXI . WebGLFastSpriteBatch ;
/ * *
* Sets the WebGL Context .
*
* @ method setContext
* @ param gl { WebGLContext } the current WebGL drawing context
* /
2014-02-28 09:30:53 +00:00
PIXI . WebGLFastSpriteBatch . prototype . setContext = function ( gl )
{
this . gl = gl ;
// create a couple of buffers
this . vertexBuffer = gl . createBuffer ( ) ;
this . indexBuffer = gl . createBuffer ( ) ;
// 65535 is max index, so 65535 / 6 = 10922.
//upload the index data
gl . bindBuffer ( gl . ELEMENT _ARRAY _BUFFER , this . indexBuffer ) ;
gl . bufferData ( gl . ELEMENT _ARRAY _BUFFER , this . indices , gl . STATIC _DRAW ) ;
gl . bindBuffer ( gl . ARRAY _BUFFER , this . vertexBuffer ) ;
gl . bufferData ( gl . ARRAY _BUFFER , this . vertices , gl . DYNAMIC _DRAW ) ;
} ;
2014-10-22 20:42:03 +00:00
/ * *
* @ method begin
* @ param spriteBatch { WebGLSpriteBatch }
* @ param renderSession { Object }
* /
2014-02-28 09:30:53 +00:00
PIXI . WebGLFastSpriteBatch . prototype . begin = function ( spriteBatch , renderSession )
{
this . renderSession = renderSession ;
this . shader = this . renderSession . shaderManager . fastShader ;
this . matrix = spriteBatch . worldTransform . toArray ( true ) ;
this . start ( ) ;
} ;
2014-10-22 20:42:03 +00:00
/ * *
* @ method end
* /
2014-02-28 09:30:53 +00:00
PIXI . WebGLFastSpriteBatch . prototype . end = function ( )
{
this . flush ( ) ;
} ;
2014-10-22 20:42:03 +00:00
/ * *
* @ method render
* @ param spriteBatch { WebGLSpriteBatch }
* /
2014-02-28 09:30:53 +00:00
PIXI . WebGLFastSpriteBatch . prototype . render = function ( spriteBatch )
{
var children = spriteBatch . children ;
var sprite = children [ 0 ] ;
// if the uvs have not updated then no point rendering just yet!
2014-04-01 02:02:36 +00:00
2014-02-28 09:30:53 +00:00
// check texture.
if ( ! sprite . texture . _uvs ) return ;
2014-04-01 02:02:36 +00:00
2014-02-28 09:30:53 +00:00
this . currentBaseTexture = sprite . texture . baseTexture ;
2014-07-10 15:23:26 +00:00
2014-02-28 09:30:53 +00:00
// check blend mode
2014-07-10 15:23:26 +00:00
if ( sprite . blendMode !== this . renderSession . blendModeManager . currentBlendMode )
2014-02-28 09:30:53 +00:00
{
2014-07-10 15:23:26 +00:00
this . flush ( ) ;
this . renderSession . blendModeManager . setBlendMode ( sprite . blendMode ) ;
2014-02-28 09:30:53 +00:00
}
2014-04-01 02:02:36 +00:00
2014-02-28 09:30:53 +00:00
for ( var i = 0 , j = children . length ; i < j ; i ++ )
{
this . renderSprite ( children [ i ] ) ;
}
this . flush ( ) ;
} ;
2014-10-22 20:42:03 +00:00
/ * *
* @ method renderSprite
* @ param sprite { Sprite }
* /
2014-02-28 09:30:53 +00:00
PIXI . WebGLFastSpriteBatch . prototype . renderSprite = function ( sprite )
{
//sprite = children[i];
2014-02-28 18:55:07 +00:00
if ( ! sprite . visible ) return ;
2014-04-01 02:02:36 +00:00
2014-02-28 09:30:53 +00:00
// TODO trim??
if ( sprite . texture . baseTexture !== this . currentBaseTexture )
{
this . flush ( ) ;
this . currentBaseTexture = sprite . texture . baseTexture ;
2014-04-01 02:02:36 +00:00
2014-02-28 09:30:53 +00:00
if ( ! sprite . texture . _uvs ) return ;
}
var uvs , verticies = this . vertices , width , height , w0 , w1 , h0 , h1 , index ;
uvs = sprite . texture . _uvs ;
width = sprite . texture . frame . width ;
height = sprite . texture . frame . height ;
if ( sprite . texture . trim )
{
// if the sprite is trimmed then we need to add the extra space before transforming the sprite coords..
var trim = sprite . texture . trim ;
w1 = trim . x - sprite . anchor . x * trim . width ;
2014-07-10 15:23:26 +00:00
w0 = w1 + sprite . texture . crop . width ;
2014-02-28 09:30:53 +00:00
h1 = trim . y - sprite . anchor . y * trim . height ;
2014-07-10 15:23:26 +00:00
h0 = h1 + sprite . texture . crop . height ;
2014-02-28 09:30:53 +00:00
}
else
{
w0 = ( sprite . texture . frame . width ) * ( 1 - sprite . anchor . x ) ;
w1 = ( sprite . texture . frame . width ) * - sprite . anchor . x ;
h0 = sprite . texture . frame . height * ( 1 - sprite . anchor . y ) ;
h1 = sprite . texture . frame . height * - sprite . anchor . y ;
}
index = this . currentBatchSize * 4 * this . vertSize ;
// xy
verticies [ index ++ ] = w1 ;
verticies [ index ++ ] = h1 ;
verticies [ index ++ ] = sprite . position . x ;
verticies [ index ++ ] = sprite . position . y ;
//scale
verticies [ index ++ ] = sprite . scale . x ;
verticies [ index ++ ] = sprite . scale . y ;
//rotation
verticies [ index ++ ] = sprite . rotation ;
// uv
verticies [ index ++ ] = uvs . x0 ;
verticies [ index ++ ] = uvs . y1 ;
// color
verticies [ index ++ ] = sprite . alpha ;
2014-04-01 02:02:36 +00:00
2014-02-28 09:30:53 +00:00
// xy
verticies [ index ++ ] = w0 ;
verticies [ index ++ ] = h1 ;
verticies [ index ++ ] = sprite . position . x ;
verticies [ index ++ ] = sprite . position . y ;
//scale
verticies [ index ++ ] = sprite . scale . x ;
verticies [ index ++ ] = sprite . scale . y ;
//rotation
verticies [ index ++ ] = sprite . rotation ;
// uv
verticies [ index ++ ] = uvs . x1 ;
verticies [ index ++ ] = uvs . y1 ;
// color
verticies [ index ++ ] = sprite . alpha ;
2014-04-01 02:02:36 +00:00
2014-02-28 09:30:53 +00:00
// xy
verticies [ index ++ ] = w0 ;
verticies [ index ++ ] = h0 ;
verticies [ index ++ ] = sprite . position . x ;
verticies [ index ++ ] = sprite . position . y ;
//scale
verticies [ index ++ ] = sprite . scale . x ;
verticies [ index ++ ] = sprite . scale . y ;
//rotation
verticies [ index ++ ] = sprite . rotation ;
// uv
verticies [ index ++ ] = uvs . x2 ;
verticies [ index ++ ] = uvs . y2 ;
// color
verticies [ index ++ ] = sprite . alpha ;
2014-04-01 02:02:36 +00:00
2014-02-28 09:30:53 +00:00
// xy
verticies [ index ++ ] = w1 ;
verticies [ index ++ ] = h0 ;
verticies [ index ++ ] = sprite . position . x ;
verticies [ index ++ ] = sprite . position . y ;
//scale
verticies [ index ++ ] = sprite . scale . x ;
verticies [ index ++ ] = sprite . scale . y ;
//rotation
verticies [ index ++ ] = sprite . rotation ;
// uv
verticies [ index ++ ] = uvs . x3 ;
verticies [ index ++ ] = uvs . y3 ;
// color
verticies [ index ++ ] = sprite . alpha ;
// increment the batchs
this . currentBatchSize ++ ;
if ( this . currentBatchSize >= this . size )
{
this . flush ( ) ;
}
} ;
2014-10-22 20:42:03 +00:00
/ * *
* @ method flush
* /
2014-02-28 09:30:53 +00:00
PIXI . WebGLFastSpriteBatch . prototype . flush = function ( )
{
// If the batch is length 0 then return as there is nothing to draw
if ( this . currentBatchSize === 0 ) return ;
var gl = this . gl ;
2014-04-01 02:02:36 +00:00
2014-02-28 09:30:53 +00:00
// bind the current texture
2014-10-23 11:34:33 +00:00
if ( ! this . currentBaseTexture . _glTextures [ gl . id ] ) this . renderSession . renderer . updateTexture ( this . currentBaseTexture , gl ) ;
2014-02-28 09:30:53 +00:00
2014-07-16 00:58:24 +00:00
gl . bindTexture ( gl . TEXTURE _2D , this . currentBaseTexture . _glTextures [ gl . id ] ) ;
2014-02-28 09:30:53 +00:00
// upload the verts to the buffer
2014-04-01 02:02:36 +00:00
2014-02-28 09:30:53 +00:00
if ( this . currentBatchSize > ( this . size * 0.5 ) )
{
gl . bufferSubData ( gl . ARRAY _BUFFER , 0 , this . vertices ) ;
}
else
{
var view = this . vertices . subarray ( 0 , this . currentBatchSize * 4 * this . vertSize ) ;
gl . bufferSubData ( gl . ARRAY _BUFFER , 0 , view ) ;
}
2014-04-01 02:02:36 +00:00
2014-02-28 09:30:53 +00:00
// now draw those suckas!
gl . drawElements ( gl . TRIANGLES , this . currentBatchSize * 6 , gl . UNSIGNED _SHORT , 0 ) ;
2014-04-01 02:02:36 +00:00
2014-02-28 09:30:53 +00:00
// then reset the batch!
this . currentBatchSize = 0 ;
// increment the draw count
this . renderSession . drawCount ++ ;
} ;
2014-10-22 20:42:03 +00:00
/ * *
* @ method stop
* /
2014-02-28 09:30:53 +00:00
PIXI . WebGLFastSpriteBatch . prototype . stop = function ( )
{
this . flush ( ) ;
} ;
2014-10-22 20:42:03 +00:00
/ * *
* @ method start
* /
2014-02-28 09:30:53 +00:00
PIXI . WebGLFastSpriteBatch . prototype . start = function ( )
{
var gl = this . gl ;
// bind the main texture
gl . activeTexture ( gl . TEXTURE0 ) ;
// bind the buffers
gl . bindBuffer ( gl . ARRAY _BUFFER , this . vertexBuffer ) ;
gl . bindBuffer ( gl . ELEMENT _ARRAY _BUFFER , this . indexBuffer ) ;
// set the projection
var projection = this . renderSession . projection ;
gl . uniform2f ( this . shader . projectionVector , projection . x , projection . y ) ;
// set the matrix
gl . uniformMatrix3fv ( this . shader . uMatrix , false , this . matrix ) ;
// set the pointers
var stride = this . vertSize * 4 ;
gl . vertexAttribPointer ( this . shader . aVertexPosition , 2 , gl . FLOAT , false , stride , 0 ) ;
gl . vertexAttribPointer ( this . shader . aPositionCoord , 2 , gl . FLOAT , false , stride , 2 * 4 ) ;
gl . vertexAttribPointer ( this . shader . aScale , 2 , gl . FLOAT , false , stride , 4 * 4 ) ;
gl . vertexAttribPointer ( this . shader . aRotation , 1 , gl . FLOAT , false , stride , 6 * 4 ) ;
gl . vertexAttribPointer ( this . shader . aTextureCoord , 2 , gl . FLOAT , false , stride , 7 * 4 ) ;
gl . vertexAttribPointer ( this . shader . colorAttribute , 1 , gl . FLOAT , false , stride , 9 * 4 ) ;
2014-04-01 02:02:36 +00:00
2014-02-28 09:30:53 +00:00
} ;
/ * *
* @ author Mat Groves http : //matgroves.com/ @Doormat23
* /
/ * *
* @ class WebGLFilterManager
* @ constructor
* /
2014-10-22 20:42:03 +00:00
PIXI . WebGLFilterManager = function ( )
2014-02-28 09:30:53 +00:00
{
2014-10-22 20:42:03 +00:00
/ * *
* @ property filterStack
* @ type Array
* /
2014-02-28 09:30:53 +00:00
this . filterStack = [ ] ;
2014-04-01 02:02:36 +00:00
2014-10-22 20:42:03 +00:00
/ * *
* @ property offsetX
* @ type Number
* /
2014-02-28 09:30:53 +00:00
this . offsetX = 0 ;
2014-10-22 20:42:03 +00:00
/ * *
* @ property offsetY
* @ type Number
* /
this . offsetY = 0 ;
2014-02-28 09:30:53 +00:00
} ;
2014-10-22 20:42:03 +00:00
PIXI . WebGLFilterManager . prototype . constructor = PIXI . WebGLFilterManager ;
2014-02-28 09:30:53 +00:00
/ * *
2014-10-22 20:42:03 +00:00
* Initialises the context and the properties .
*
2014-04-01 02:02:36 +00:00
* @ method setContext
2014-02-28 09:30:53 +00:00
* @ param gl { WebGLContext } the current WebGL drawing context
* /
PIXI . WebGLFilterManager . prototype . setContext = function ( gl )
{
this . gl = gl ;
this . texturePool = [ ] ;
this . initShaderBuffers ( ) ;
} ;
/ * *
* @ method begin
2014-04-01 02:02:36 +00:00
* @ param renderSession { RenderSession }
* @ param buffer { ArrayBuffer }
2014-02-28 09:30:53 +00:00
* /
PIXI . WebGLFilterManager . prototype . begin = function ( renderSession , buffer )
{
this . renderSession = renderSession ;
this . defaultShader = renderSession . shaderManager . defaultShader ;
var projection = this . renderSession . projection ;
this . width = projection . x * 2 ;
this . height = - projection . y * 2 ;
this . buffer = buffer ;
} ;
/ * *
2014-10-22 20:42:03 +00:00
* Applies the filter and adds it to the current filter stack .
*
2014-02-28 09:30:53 +00:00
* @ method pushFilter
* @ param filterBlock { Object } the filter that will be pushed to the current filter stack
* /
PIXI . WebGLFilterManager . prototype . pushFilter = function ( filterBlock )
{
var gl = this . gl ;
var projection = this . renderSession . projection ;
var offset = this . renderSession . offset ;
2014-04-01 02:02:36 +00:00
filterBlock . _filterArea = filterBlock . target . filterArea || filterBlock . target . getBounds ( ) ;
2014-02-28 09:30:53 +00:00
// filter program
// OPTIMISATION - the first filter is free if its a simple color change?
this . filterStack . push ( filterBlock ) ;
var filter = filterBlock . filterPasses [ 0 ] ;
2014-04-01 02:02:36 +00:00
this . offsetX += filterBlock . _filterArea . x ;
this . offsetY += filterBlock . _filterArea . y ;
2014-02-28 09:30:53 +00:00
var texture = this . texturePool . pop ( ) ;
if ( ! texture )
{
texture = new PIXI . FilterTexture ( this . gl , this . width , this . height ) ;
}
else
{
texture . resize ( this . width , this . height ) ;
}
gl . bindTexture ( gl . TEXTURE _2D , texture . texture ) ;
2014-04-01 02:02:36 +00:00
var filterArea = filterBlock . _filterArea ; // filterBlock.target.getBounds();///filterBlock.target.filterArea;
2014-02-28 09:30:53 +00:00
2014-04-29 14:39:53 +00:00
var padding = filter . padding ;
filterArea . x -= padding ;
filterArea . y -= padding ;
filterArea . width += padding * 2 ;
filterArea . height += padding * 2 ;
2014-02-28 09:30:53 +00:00
// cap filter to screen size..
if ( filterArea . x < 0 ) filterArea . x = 0 ;
if ( filterArea . width > this . width ) filterArea . width = this . width ;
if ( filterArea . y < 0 ) filterArea . y = 0 ;
if ( filterArea . height > this . height ) filterArea . height = this . height ;
//gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, filterArea.width, filterArea.height, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);
gl . bindFramebuffer ( gl . FRAMEBUFFER , texture . frameBuffer ) ;
// set view port
gl . viewport ( 0 , 0 , filterArea . width , filterArea . height ) ;
projection . x = filterArea . width / 2 ;
projection . y = - filterArea . height / 2 ;
offset . x = - filterArea . x ;
offset . y = - filterArea . y ;
// update projection
2014-07-10 19:18:20 +00:00
// now restore the regular shader..
2014-10-22 20:42:03 +00:00
// this.renderSession.shaderManager.setShader(this.defaultShader);
//gl.uniform2f(this.defaultShader.projectionVector, filterArea.width/2, -filterArea.height/2);
//gl.uniform2f(this.defaultShader.offsetVector, -filterArea.x, -filterArea.y);
2014-02-28 09:30:53 +00:00
gl . colorMask ( true , true , true , true ) ;
gl . clearColor ( 0 , 0 , 0 , 0 ) ;
gl . clear ( gl . COLOR _BUFFER _BIT ) ;
filterBlock . _glFilterTexture = texture ;
} ;
/ * *
2014-10-22 20:42:03 +00:00
* Removes the last filter from the filter stack and doesn ' t return it .
*
2014-02-28 09:30:53 +00:00
* @ method popFilter
* /
PIXI . WebGLFilterManager . prototype . popFilter = function ( )
{
var gl = this . gl ;
var filterBlock = this . filterStack . pop ( ) ;
2014-04-01 02:02:36 +00:00
var filterArea = filterBlock . _filterArea ;
2014-02-28 09:30:53 +00:00
var texture = filterBlock . _glFilterTexture ;
var projection = this . renderSession . projection ;
var offset = this . renderSession . offset ;
if ( filterBlock . filterPasses . length > 1 )
{
gl . viewport ( 0 , 0 , filterArea . width , filterArea . height ) ;
gl . bindBuffer ( gl . ARRAY _BUFFER , this . vertexBuffer ) ;
this . vertexArray [ 0 ] = 0 ;
this . vertexArray [ 1 ] = filterArea . height ;
this . vertexArray [ 2 ] = filterArea . width ;
this . vertexArray [ 3 ] = filterArea . height ;
this . vertexArray [ 4 ] = 0 ;
this . vertexArray [ 5 ] = 0 ;
this . vertexArray [ 6 ] = filterArea . width ;
this . vertexArray [ 7 ] = 0 ;
gl . bufferSubData ( gl . ARRAY _BUFFER , 0 , this . vertexArray ) ;
gl . bindBuffer ( gl . ARRAY _BUFFER , this . uvBuffer ) ;
// now set the uvs..
this . uvArray [ 2 ] = filterArea . width / this . width ;
this . uvArray [ 5 ] = filterArea . height / this . height ;
this . uvArray [ 6 ] = filterArea . width / this . width ;
this . uvArray [ 7 ] = filterArea . height / this . height ;
gl . bufferSubData ( gl . ARRAY _BUFFER , 0 , this . uvArray ) ;
var inputTexture = texture ;
var outputTexture = this . texturePool . pop ( ) ;
if ( ! outputTexture ) outputTexture = new PIXI . FilterTexture ( this . gl , this . width , this . height ) ;
outputTexture . resize ( this . width , this . height ) ;
// need to clear this FBO as it may have some left over elements from a previous filter.
gl . bindFramebuffer ( gl . FRAMEBUFFER , outputTexture . frameBuffer ) ;
gl . clear ( gl . COLOR _BUFFER _BIT ) ;
gl . disable ( gl . BLEND ) ;
for ( var i = 0 ; i < filterBlock . filterPasses . length - 1 ; i ++ )
{
var filterPass = filterBlock . filterPasses [ i ] ;
gl . bindFramebuffer ( gl . FRAMEBUFFER , outputTexture . frameBuffer ) ;
// set texture
gl . activeTexture ( gl . TEXTURE0 ) ;
gl . bindTexture ( gl . TEXTURE _2D , inputTexture . texture ) ;
// draw texture..
//filterPass.applyFilterPass(filterArea.width, filterArea.height);
this . applyFilterPass ( filterPass , filterArea , filterArea . width , filterArea . height ) ;
// swap the textures..
var temp = inputTexture ;
inputTexture = outputTexture ;
outputTexture = temp ;
}
gl . enable ( gl . BLEND ) ;
texture = inputTexture ;
this . texturePool . push ( outputTexture ) ;
}
var filter = filterBlock . filterPasses [ filterBlock . filterPasses . length - 1 ] ;
this . offsetX -= filterArea . x ;
this . offsetY -= filterArea . y ;
var sizeX = this . width ;
var sizeY = this . height ;
var offsetX = 0 ;
var offsetY = 0 ;
var buffer = this . buffer ;
// time to render the filters texture to the previous scene
if ( this . filterStack . length === 0 )
{
gl . colorMask ( true , true , true , true ) ; //this.transparent);
}
else
{
var currentFilter = this . filterStack [ this . filterStack . length - 1 ] ;
2014-04-01 02:02:36 +00:00
filterArea = currentFilter . _filterArea ;
2014-02-28 09:30:53 +00:00
sizeX = filterArea . width ;
sizeY = filterArea . height ;
offsetX = filterArea . x ;
offsetY = filterArea . y ;
buffer = currentFilter . _glFilterTexture . frameBuffer ;
}
2014-10-22 20:42:03 +00:00
// TODO need to remove these global elements..
2014-02-28 09:30:53 +00:00
projection . x = sizeX / 2 ;
projection . y = - sizeY / 2 ;
offset . x = offsetX ;
offset . y = offsetY ;
2014-04-01 02:02:36 +00:00
filterArea = filterBlock . _filterArea ;
2014-02-28 09:30:53 +00:00
var x = filterArea . x - offsetX ;
var y = filterArea . y - offsetY ;
// update the buffers..
// make sure to flip the y!
gl . bindBuffer ( gl . ARRAY _BUFFER , this . vertexBuffer ) ;
this . vertexArray [ 0 ] = x ;
this . vertexArray [ 1 ] = y + filterArea . height ;
this . vertexArray [ 2 ] = x + filterArea . width ;
this . vertexArray [ 3 ] = y + filterArea . height ;
this . vertexArray [ 4 ] = x ;
this . vertexArray [ 5 ] = y ;
this . vertexArray [ 6 ] = x + filterArea . width ;
this . vertexArray [ 7 ] = y ;
gl . bufferSubData ( gl . ARRAY _BUFFER , 0 , this . vertexArray ) ;
gl . bindBuffer ( gl . ARRAY _BUFFER , this . uvBuffer ) ;
this . uvArray [ 2 ] = filterArea . width / this . width ;
this . uvArray [ 5 ] = filterArea . height / this . height ;
this . uvArray [ 6 ] = filterArea . width / this . width ;
this . uvArray [ 7 ] = filterArea . height / this . height ;
gl . bufferSubData ( gl . ARRAY _BUFFER , 0 , this . uvArray ) ;
gl . viewport ( 0 , 0 , sizeX , sizeY ) ;
// bind the buffer
gl . bindFramebuffer ( gl . FRAMEBUFFER , buffer ) ;
2014-04-01 02:02:36 +00:00
// set the blend mode!
2014-02-28 09:30:53 +00:00
//gl.blendFunc(gl.ONE, gl.ONE_MINUS_SRC_ALPHA)
// set texture
gl . activeTexture ( gl . TEXTURE0 ) ;
gl . bindTexture ( gl . TEXTURE _2D , texture . texture ) ;
// apply!
this . applyFilterPass ( filter , filterArea , sizeX , sizeY ) ;
2014-10-22 20:42:03 +00:00
// now restore the regular shader.. should happen automatically now..
// this.renderSession.shaderManager.setShader(this.defaultShader);
// gl.uniform2f(this.defaultShader.projectionVector, sizeX/2, -sizeY/2);
// gl.uniform2f(this.defaultShader.offsetVector, -offsetX, -offsetY);
2014-02-28 09:30:53 +00:00
// return the texture to the pool
this . texturePool . push ( texture ) ;
filterBlock . _glFilterTexture = null ;
} ;
/ * *
2014-10-22 20:42:03 +00:00
* Applies the filter to the specified area .
*
2014-02-28 09:30:53 +00:00
* @ method applyFilterPass
* @ param filter { AbstractFilter } the filter that needs to be applied
2014-10-22 20:42:03 +00:00
* @ param filterArea { Texture } TODO - might need an update
2014-02-28 09:30:53 +00:00
* @ param width { Number } the horizontal range of the filter
* @ param height { Number } the vertical range of the filter
* /
PIXI . WebGLFilterManager . prototype . applyFilterPass = function ( filter , filterArea , width , height )
{
// use program
var gl = this . gl ;
var shader = filter . shaders [ gl . id ] ;
if ( ! shader )
{
shader = new PIXI . PixiShader ( gl ) ;
shader . fragmentSrc = filter . fragmentSrc ;
shader . uniforms = filter . uniforms ;
shader . init ( ) ;
filter . shaders [ gl . id ] = shader ;
}
// set the shader
2014-07-01 14:04:03 +00:00
this . renderSession . shaderManager . setShader ( shader ) ;
// gl.useProgram(shader.program);
2014-02-28 09:30:53 +00:00
gl . uniform2f ( shader . projectionVector , width / 2 , - height / 2 ) ;
gl . uniform2f ( shader . offsetVector , 0 , 0 ) ;
if ( filter . uniforms . dimensions )
{
filter . uniforms . dimensions . value [ 0 ] = this . width ; //width;
filter . uniforms . dimensions . value [ 1 ] = this . height ; //height;
filter . uniforms . dimensions . value [ 2 ] = this . vertexArray [ 0 ] ;
filter . uniforms . dimensions . value [ 3 ] = this . vertexArray [ 5 ] ; //filterArea.height;
}
shader . syncUniforms ( ) ;
gl . bindBuffer ( gl . ARRAY _BUFFER , this . vertexBuffer ) ;
gl . vertexAttribPointer ( shader . aVertexPosition , 2 , gl . FLOAT , false , 0 , 0 ) ;
gl . bindBuffer ( gl . ARRAY _BUFFER , this . uvBuffer ) ;
gl . vertexAttribPointer ( shader . aTextureCoord , 2 , gl . FLOAT , false , 0 , 0 ) ;
gl . bindBuffer ( gl . ARRAY _BUFFER , this . colorBuffer ) ;
gl . vertexAttribPointer ( shader . colorAttribute , 2 , gl . FLOAT , false , 0 , 0 ) ;
gl . bindBuffer ( gl . ELEMENT _ARRAY _BUFFER , this . indexBuffer ) ;
// draw the filter...
gl . drawElements ( gl . TRIANGLES , 6 , gl . UNSIGNED _SHORT , 0 ) ;
this . renderSession . drawCount ++ ;
} ;
/ * *
2014-10-22 20:42:03 +00:00
* Initialises the shader buffers .
*
2014-02-28 09:30:53 +00:00
* @ method initShaderBuffers
* /
PIXI . WebGLFilterManager . prototype . initShaderBuffers = function ( )
{
var gl = this . gl ;
// create some buffers
this . vertexBuffer = gl . createBuffer ( ) ;
this . uvBuffer = gl . createBuffer ( ) ;
this . colorBuffer = gl . createBuffer ( ) ;
this . indexBuffer = gl . createBuffer ( ) ;
// bind and upload the vertexs..
// keep a reference to the vertexFloatData..
2014-11-08 19:26:34 +00:00
this . vertexArray = new PIXI . Float32Array ( [ 0.0 , 0.0 ,
2014-02-28 09:30:53 +00:00
1.0 , 0.0 ,
0.0 , 1.0 ,
1.0 , 1.0 ] ) ;
gl . bindBuffer ( gl . ARRAY _BUFFER , this . vertexBuffer ) ;
2014-10-22 20:42:03 +00:00
gl . bufferData ( gl . ARRAY _BUFFER , this . vertexArray , gl . STATIC _DRAW ) ;
2014-02-28 09:30:53 +00:00
// bind and upload the uv buffer
2014-11-08 19:26:34 +00:00
this . uvArray = new PIXI . Float32Array ( [ 0.0 , 0.0 ,
2014-02-28 09:30:53 +00:00
1.0 , 0.0 ,
0.0 , 1.0 ,
1.0 , 1.0 ] ) ;
gl . bindBuffer ( gl . ARRAY _BUFFER , this . uvBuffer ) ;
2014-10-22 20:42:03 +00:00
gl . bufferData ( gl . ARRAY _BUFFER , this . uvArray , gl . STATIC _DRAW ) ;
2014-02-28 09:30:53 +00:00
2014-11-08 19:26:34 +00:00
this . colorArray = new PIXI . Float32Array ( [ 1.0 , 0xFFFFFF ,
2014-02-28 09:30:53 +00:00
1.0 , 0xFFFFFF ,
1.0 , 0xFFFFFF ,
1.0 , 0xFFFFFF ] ) ;
gl . bindBuffer ( gl . ARRAY _BUFFER , this . colorBuffer ) ;
2014-10-22 20:42:03 +00:00
gl . bufferData ( gl . ARRAY _BUFFER , this . colorArray , gl . STATIC _DRAW ) ;
2014-02-28 09:30:53 +00:00
// bind and upload the index
gl . bindBuffer ( gl . ELEMENT _ARRAY _BUFFER , this . indexBuffer ) ;
2014-10-22 20:42:03 +00:00
gl . bufferData ( gl . ELEMENT _ARRAY _BUFFER , new Uint16Array ( [ 0 , 1 , 2 , 1 , 3 , 2 ] ) , gl . STATIC _DRAW ) ;
2014-02-28 09:30:53 +00:00
} ;
/ * *
2014-10-22 20:42:03 +00:00
* Destroys the filter and removes it from the filter stack .
*
2014-02-28 09:30:53 +00:00
* @ method destroy
* /
PIXI . WebGLFilterManager . prototype . destroy = function ( )
{
var gl = this . gl ;
this . filterStack = null ;
2014-04-01 02:02:36 +00:00
2014-02-28 09:30:53 +00:00
this . offsetX = 0 ;
this . offsetY = 0 ;
// destroy textures
for ( var i = 0 ; i < this . texturePool . length ; i ++ ) {
2014-07-10 15:23:26 +00:00
this . texturePool [ i ] . destroy ( ) ;
2014-02-28 09:30:53 +00:00
}
2014-04-01 02:02:36 +00:00
2014-02-28 09:30:53 +00:00
this . texturePool = null ;
//destroy buffers..
gl . deleteBuffer ( this . vertexBuffer ) ;
gl . deleteBuffer ( this . uvBuffer ) ;
gl . deleteBuffer ( this . colorBuffer ) ;
gl . deleteBuffer ( this . indexBuffer ) ;
} ;
/ * *
* @ author Mat Groves http : //matgroves.com/ @Doormat23
* /
/ * *
* @ class FilterTexture
* @ constructor
* @ param gl { WebGLContext } the current WebGL drawing context
* @ param width { Number } the horizontal range of the filter
* @ param height { Number } the vertical range of the filter
2014-11-15 20:04:24 +00:00
* @ param scaleMode { Number } See { { # crossLink "PIXI/scaleModes:property" } } PIXI . scaleModes { { / c r o s s L i n k } } f o r p o s s i b l e v a l u e s
2014-02-28 09:30:53 +00:00
* /
2014-04-29 14:39:53 +00:00
PIXI . FilterTexture = function ( gl , width , height , scaleMode )
2014-02-28 09:30:53 +00:00
{
/ * *
* @ property gl
* @ type WebGLContext
* /
this . gl = gl ;
// next time to create a frame buffer and texture
2014-10-22 20:42:03 +00:00
/ * *
* @ property frameBuffer
* @ type Any
* /
2014-02-28 09:30:53 +00:00
this . frameBuffer = gl . createFramebuffer ( ) ;
2014-10-22 20:42:03 +00:00
/ * *
* @ property texture
* @ type Any
* /
2014-02-28 09:30:53 +00:00
this . texture = gl . createTexture ( ) ;
2014-10-22 20:42:03 +00:00
/ * *
* @ property scaleMode
* @ type Number
* /
2014-04-29 14:39:53 +00:00
scaleMode = scaleMode || PIXI . scaleModes . DEFAULT ;
2014-02-28 09:30:53 +00:00
gl . bindTexture ( gl . TEXTURE _2D , this . texture ) ;
2014-04-29 14:39:53 +00:00
gl . texParameteri ( gl . TEXTURE _2D , gl . TEXTURE _MAG _FILTER , scaleMode === PIXI . scaleModes . LINEAR ? gl . LINEAR : gl . NEAREST ) ;
gl . texParameteri ( gl . TEXTURE _2D , gl . TEXTURE _MIN _FILTER , scaleMode === PIXI . scaleModes . LINEAR ? gl . LINEAR : gl . NEAREST ) ;
2014-02-28 09:30:53 +00:00
gl . texParameteri ( gl . TEXTURE _2D , gl . TEXTURE _WRAP _S , gl . CLAMP _TO _EDGE ) ;
gl . texParameteri ( gl . TEXTURE _2D , gl . TEXTURE _WRAP _T , gl . CLAMP _TO _EDGE ) ;
2014-08-29 17:13:33 +00:00
gl . bindFramebuffer ( gl . FRAMEBUFFER , this . frameBuffer ) ;
2014-02-28 09:30:53 +00:00
gl . bindFramebuffer ( gl . FRAMEBUFFER , this . frameBuffer ) ;
gl . framebufferTexture2D ( gl . FRAMEBUFFER , gl . COLOR _ATTACHMENT0 , gl . TEXTURE _2D , this . texture , 0 ) ;
2014-04-29 14:39:53 +00:00
// required for masking a mask??
this . renderBuffer = gl . createRenderbuffer ( ) ;
gl . bindRenderbuffer ( gl . RENDERBUFFER , this . renderBuffer ) ;
gl . framebufferRenderbuffer ( gl . FRAMEBUFFER , gl . DEPTH _STENCIL _ATTACHMENT , gl . RENDERBUFFER , this . renderBuffer ) ;
2014-02-28 09:30:53 +00:00
this . resize ( width , height ) ;
} ;
2014-10-22 20:42:03 +00:00
PIXI . FilterTexture . prototype . constructor = PIXI . FilterTexture ;
2014-02-28 09:30:53 +00:00
/ * *
2014-10-22 20:42:03 +00:00
* Clears the filter texture .
*
2014-02-28 09:30:53 +00:00
* @ method clear
* /
PIXI . FilterTexture . prototype . clear = function ( )
{
var gl = this . gl ;
2014-04-01 02:02:36 +00:00
2014-02-28 09:30:53 +00:00
gl . clearColor ( 0 , 0 , 0 , 0 ) ;
gl . clear ( gl . COLOR _BUFFER _BIT ) ;
} ;
/ * *
* Resizes the texture to the specified width and height
*
* @ method resize
* @ param width { Number } the new width of the texture
* @ param height { Number } the new height of the texture
* /
PIXI . FilterTexture . prototype . resize = function ( width , height )
{
if ( this . width === width && this . height === height ) return ;
this . width = width ;
this . height = height ;
var gl = this . gl ;
gl . bindTexture ( gl . TEXTURE _2D , this . texture ) ;
2014-10-22 20:42:03 +00:00
gl . texImage2D ( gl . TEXTURE _2D , 0 , gl . RGBA , width , height , 0 , gl . RGBA , gl . UNSIGNED _BYTE , null ) ;
2014-04-29 14:39:53 +00:00
// update the stencil buffer width and height
gl . bindRenderbuffer ( gl . RENDERBUFFER , this . renderBuffer ) ;
2014-10-22 20:42:03 +00:00
gl . renderbufferStorage ( gl . RENDERBUFFER , gl . DEPTH _STENCIL , width , height ) ;
2014-02-28 09:30:53 +00:00
} ;
/ * *
2014-10-22 20:42:03 +00:00
* Destroys the filter texture .
*
2014-02-28 09:30:53 +00:00
* @ method destroy
* /
PIXI . FilterTexture . prototype . destroy = function ( )
{
var gl = this . gl ;
gl . deleteFramebuffer ( this . frameBuffer ) ;
gl . deleteTexture ( this . texture ) ;
this . frameBuffer = null ;
this . texture = null ;
} ;
/ * *
2014-10-22 20:42:03 +00:00
* @ author Mat Groves http : //matgroves.com/ @Doormat23
* /
/ * *
* Creates a Canvas element of the given size .
*
* @ class CanvasBuffer
* @ constructor
* @ param width { Number } the width for the newly created canvas
* @ param height { Number } the height for the newly created canvas
* /
PIXI . CanvasBuffer = function ( width , height )
{
/ * *
* The width of the Canvas in pixels .
*
* @ property width
* @ type Number
* /
this . width = width ;
/ * *
* The height of the Canvas in pixels .
*
* @ property height
* @ type Number
* /
this . height = height ;
/ * *
* The Canvas object that belongs to this CanvasBuffer .
*
* @ property canvas
* @ type HTMLCanvasElement
* /
this . canvas = document . createElement ( "canvas" ) ;
/ * *
* A CanvasRenderingContext2D object representing a two - dimensional rendering context .
*
* @ property context
* @ type CanvasRenderingContext2D
* /
this . context = this . canvas . getContext ( "2d" ) ;
this . canvas . width = width ;
this . canvas . height = height ;
} ;
PIXI . CanvasBuffer . prototype . constructor = PIXI . CanvasBuffer ;
/ * *
* Clears the canvas that was created by the CanvasBuffer class .
*
* @ method clear
* @ private
* /
PIXI . CanvasBuffer . prototype . clear = function ( )
{
2014-11-11 01:10:47 +00:00
this . context . setTransform ( 1 , 0 , 0 , 1 , 0 , 0 ) ;
2014-10-22 20:42:03 +00:00
this . context . clearRect ( 0 , 0 , this . width , this . height ) ;
} ;
/ * *
* Resizes the canvas to the specified width and height .
*
* @ method resize
* @ param width { Number } the new width of the canvas
* @ param height { Number } the new height of the canvas
* /
PIXI . CanvasBuffer . prototype . resize = function ( width , height )
{
this . width = this . canvas . width = width ;
this . height = this . canvas . height = height ;
} ;
/ * *
* @ author Mat Groves http : //matgroves.com/ @Doormat23
2014-02-28 09:30:53 +00:00
* /
2014-10-22 20:42:03 +00:00
2014-02-28 09:30:53 +00:00
/ * *
2014-10-22 20:42:03 +00:00
* A set of functions used to handle masking .
2014-02-28 09:30:53 +00:00
*
* @ class CanvasMaskManager
2014-10-22 20:42:03 +00:00
* @ constructor
2014-02-28 09:30:53 +00:00
* /
PIXI . CanvasMaskManager = function ( )
{
} ;
2014-10-22 20:42:03 +00:00
PIXI . CanvasMaskManager . prototype . constructor = PIXI . CanvasMaskManager ;
2014-02-28 09:30:53 +00:00
/ * *
2014-10-22 20:42:03 +00:00
* This method adds it to the current stack of masks .
2014-02-28 09:30:53 +00:00
*
* @ method pushMask
2014-10-22 20:42:03 +00:00
* @ param maskData { Object } the maskData that will be pushed
* @ param renderSession { Object } The renderSession whose context will be used for this mask manager .
2014-02-28 09:30:53 +00:00
* /
2014-10-22 20:42:03 +00:00
PIXI . CanvasMaskManager . prototype . pushMask = function ( maskData , renderSession )
2014-02-28 09:30:53 +00:00
{
2014-10-22 20:42:03 +00:00
var context = renderSession . context ;
2014-02-28 09:30:53 +00:00
context . save ( ) ;
2014-04-01 02:02:36 +00:00
2014-02-28 09:30:53 +00:00
var cacheAlpha = maskData . alpha ;
var transform = maskData . worldTransform ;
2014-10-22 20:42:03 +00:00
var resolution = renderSession . resolution ;
context . setTransform ( transform . a * resolution ,
transform . b * resolution ,
transform . c * resolution ,
transform . d * resolution ,
transform . tx * resolution ,
transform . ty * resolution ) ;
2014-02-28 09:30:53 +00:00
PIXI . CanvasGraphics . renderGraphicsMask ( maskData , context ) ;
context . clip ( ) ;
maskData . worldAlpha = cacheAlpha ;
} ;
/ * *
2014-10-22 20:42:03 +00:00
* Restores the current drawing context to the state it was before the mask was applied .
2014-02-28 09:30:53 +00:00
*
* @ method popMask
2014-10-22 20:42:03 +00:00
* @ param renderSession { Object } The renderSession whose context will be used for this mask manager .
2014-02-28 09:30:53 +00:00
* /
2014-10-22 20:42:03 +00:00
PIXI . CanvasMaskManager . prototype . popMask = function ( renderSession )
2014-02-28 09:30:53 +00:00
{
2014-10-22 20:42:03 +00:00
renderSession . context . restore ( ) ;
2014-02-28 09:30:53 +00:00
} ;
/ * *
2014-10-22 20:42:03 +00:00
* @ author Mat Groves http : //matgroves.com/ @Doormat23
2014-02-28 09:30:53 +00:00
* /
/ * *
2014-11-15 20:04:24 +00:00
* Utility methods for Sprite / Texture tinting .
*
2014-02-28 09:30:53 +00:00
* @ class CanvasTinter
* @ static
* /
PIXI . CanvasTinter = function ( )
{
} ;
/ * *
2014-10-22 20:42:03 +00:00
* Basically this method just needs a sprite and a color and tints the sprite with the given color .
2014-04-01 02:02:36 +00:00
*
* @ method getTintedTexture
2014-11-15 20:04:24 +00:00
* @ static
2014-02-28 09:30:53 +00:00
* @ param sprite { Sprite } the sprite to tint
* @ param color { Number } the color to use to tint the sprite with
2014-10-22 20:42:03 +00:00
* @ return { HTMLCanvasElement } The tinted canvas
2014-02-28 09:30:53 +00:00
* /
PIXI . CanvasTinter . getTintedTexture = function ( sprite , color )
{
var texture = sprite . texture ;
color = PIXI . CanvasTinter . roundColor ( color ) ;
var stringColor = "#" + ( "00000" + ( color | 0 ) . toString ( 16 ) ) . substr ( - 6 ) ;
2014-04-01 02:02:36 +00:00
2014-02-28 09:30:53 +00:00
texture . tintCache = texture . tintCache || { } ;
if ( texture . tintCache [ stringColor ] ) return texture . tintCache [ stringColor ] ;
// clone texture..
var canvas = PIXI . CanvasTinter . canvas || document . createElement ( "canvas" ) ;
2014-04-01 02:02:36 +00:00
2014-02-28 09:30:53 +00:00
//PIXI.CanvasTinter.tintWithPerPixel(texture, stringColor, canvas);
PIXI . CanvasTinter . tintMethod ( texture , color , canvas ) ;
if ( PIXI . CanvasTinter . convertTintToImage )
{
// is this better?
var tintImage = new Image ( ) ;
tintImage . src = canvas . toDataURL ( ) ;
texture . tintCache [ stringColor ] = tintImage ;
}
else
{
texture . tintCache [ stringColor ] = canvas ;
// if we are not converting the texture to an image then we need to lose the reference to the canvas
PIXI . CanvasTinter . canvas = null ;
}
return canvas ;
} ;
/ * *
2014-10-22 20:42:03 +00:00
* Tint a texture using the "multiply" operation .
*
2014-02-28 09:30:53 +00:00
* @ method tintWithMultiply
2014-11-15 20:04:24 +00:00
* @ static
2014-10-22 20:42:03 +00:00
* @ param texture { Texture } the texture to tint
2014-02-28 09:30:53 +00:00
* @ param color { Number } the color to use to tint the sprite with
* @ param canvas { HTMLCanvasElement } the current canvas
* /
PIXI . CanvasTinter . tintWithMultiply = function ( texture , color , canvas )
{
var context = canvas . getContext ( "2d" ) ;
2014-10-22 20:42:03 +00:00
var crop = texture . crop ;
2014-02-28 09:30:53 +00:00
2014-10-22 20:42:03 +00:00
canvas . width = crop . width ;
canvas . height = crop . height ;
2014-02-28 09:30:53 +00:00
context . fillStyle = "#" + ( "00000" + ( color | 0 ) . toString ( 16 ) ) . substr ( - 6 ) ;
2014-04-01 02:02:36 +00:00
2014-10-22 20:42:03 +00:00
context . fillRect ( 0 , 0 , crop . width , crop . height ) ;
2014-04-01 02:02:36 +00:00
2014-02-28 09:30:53 +00:00
context . globalCompositeOperation = "multiply" ;
context . drawImage ( texture . baseTexture . source ,
2014-10-22 20:42:03 +00:00
crop . x ,
crop . y ,
crop . width ,
crop . height ,
2014-02-28 09:30:53 +00:00
0 ,
0 ,
2014-10-22 20:42:03 +00:00
crop . width ,
crop . height ) ;
2014-02-28 09:30:53 +00:00
context . globalCompositeOperation = "destination-atop" ;
2014-10-22 20:42:03 +00:00
2014-02-28 09:30:53 +00:00
context . drawImage ( texture . baseTexture . source ,
2014-10-22 20:42:03 +00:00
crop . x ,
crop . y ,
crop . width ,
crop . height ,
2014-02-28 09:30:53 +00:00
0 ,
0 ,
2014-10-22 20:42:03 +00:00
crop . width ,
crop . height ) ;
2014-02-28 09:30:53 +00:00
} ;
/ * *
2014-10-22 20:42:03 +00:00
* Tint a texture using the "overlay" operation .
*
2014-02-28 09:30:53 +00:00
* @ method tintWithOverlay
2014-11-15 20:04:24 +00:00
* @ static
2014-10-22 20:42:03 +00:00
* @ param texture { Texture } the texture to tint
2014-02-28 09:30:53 +00:00
* @ param color { Number } the color to use to tint the sprite with
* @ param canvas { HTMLCanvasElement } the current canvas
* /
PIXI . CanvasTinter . tintWithOverlay = function ( texture , color , canvas )
{
var context = canvas . getContext ( "2d" ) ;
2014-10-22 20:42:03 +00:00
var crop = texture . crop ;
2014-02-28 09:30:53 +00:00
2014-10-22 20:42:03 +00:00
canvas . width = crop . width ;
canvas . height = crop . height ;
2014-04-01 02:02:36 +00:00
2014-02-28 09:30:53 +00:00
context . globalCompositeOperation = "copy" ;
context . fillStyle = "#" + ( "00000" + ( color | 0 ) . toString ( 16 ) ) . substr ( - 6 ) ;
2014-10-22 20:42:03 +00:00
context . fillRect ( 0 , 0 , crop . width , crop . height ) ;
2014-02-28 09:30:53 +00:00
context . globalCompositeOperation = "destination-atop" ;
context . drawImage ( texture . baseTexture . source ,
2014-10-22 20:42:03 +00:00
crop . x ,
crop . y ,
crop . width ,
crop . height ,
2014-02-28 09:30:53 +00:00
0 ,
0 ,
2014-10-22 20:42:03 +00:00
crop . width ,
crop . height ) ;
2014-04-01 02:02:36 +00:00
2014-02-28 09:30:53 +00:00
//context.globalCompositeOperation = "copy";
} ;
/ * *
2014-10-22 20:42:03 +00:00
* Tint a texture pixel per pixel .
*
2014-02-28 09:30:53 +00:00
* @ method tintPerPixel
2014-11-15 20:04:24 +00:00
* @ static
2014-10-22 20:42:03 +00:00
* @ param texture { Texture } the texture to tint
2014-02-28 09:30:53 +00:00
* @ param color { Number } the color to use to tint the sprite with
* @ param canvas { HTMLCanvasElement } the current canvas
* /
PIXI . CanvasTinter . tintWithPerPixel = function ( texture , color , canvas )
{
var context = canvas . getContext ( "2d" ) ;
2014-10-22 20:42:03 +00:00
var crop = texture . crop ;
2014-02-28 09:30:53 +00:00
2014-10-22 20:42:03 +00:00
canvas . width = crop . width ;
canvas . height = crop . height ;
2014-04-01 02:02:36 +00:00
2014-02-28 09:30:53 +00:00
context . globalCompositeOperation = "copy" ;
context . drawImage ( texture . baseTexture . source ,
2014-10-22 20:42:03 +00:00
crop . x ,
crop . y ,
crop . width ,
crop . height ,
2014-02-28 09:30:53 +00:00
0 ,
0 ,
2014-10-22 20:42:03 +00:00
crop . width ,
crop . height ) ;
2014-02-28 09:30:53 +00:00
var rgbValues = PIXI . hex2rgb ( color ) ;
var r = rgbValues [ 0 ] , g = rgbValues [ 1 ] , b = rgbValues [ 2 ] ;
2014-10-22 20:42:03 +00:00
var pixelData = context . getImageData ( 0 , 0 , crop . width , crop . height ) ;
2014-02-28 09:30:53 +00:00
var pixels = pixelData . data ;
for ( var i = 0 ; i < pixels . length ; i += 4 )
{
pixels [ i + 0 ] *= r ;
pixels [ i + 1 ] *= g ;
pixels [ i + 2 ] *= b ;
}
context . putImageData ( pixelData , 0 , 0 ) ;
} ;
/ * *
2014-10-22 20:42:03 +00:00
* Rounds the specified color according to the PIXI . CanvasTinter . cacheStepsPerColorChannel .
*
2014-02-28 09:30:53 +00:00
* @ method roundColor
2014-11-15 20:04:24 +00:00
* @ static
2014-02-28 09:30:53 +00:00
* @ param color { number } the color to round , should be a hex color
* /
PIXI . CanvasTinter . roundColor = function ( color )
{
var step = PIXI . CanvasTinter . cacheStepsPerColorChannel ;
var rgbValues = PIXI . hex2rgb ( color ) ;
rgbValues [ 0 ] = Math . min ( 255 , ( rgbValues [ 0 ] / step ) * step ) ;
rgbValues [ 1 ] = Math . min ( 255 , ( rgbValues [ 1 ] / step ) * step ) ;
rgbValues [ 2 ] = Math . min ( 255 , ( rgbValues [ 2 ] / step ) * step ) ;
return PIXI . rgb2hex ( rgbValues ) ;
} ;
/ * *
2014-10-22 20:42:03 +00:00
* Number of steps which will be used as a cap when rounding colors .
2014-02-28 09:30:53 +00:00
*
2014-11-15 20:04:24 +00:00
* @ property cacheStepsPerColorChannel
2014-02-28 09:30:53 +00:00
* @ type Number
2014-11-15 20:04:24 +00:00
* @ static
2014-02-28 09:30:53 +00:00
* /
PIXI . CanvasTinter . cacheStepsPerColorChannel = 8 ;
2014-10-22 20:42:03 +00:00
2014-02-28 09:30:53 +00:00
/ * *
2014-10-22 20:42:03 +00:00
* Tint cache boolean flag .
2014-02-28 09:30:53 +00:00
*
* @ property convertTintToImage
* @ type Boolean
2014-11-15 20:04:24 +00:00
* @ static
2014-02-28 09:30:53 +00:00
* /
PIXI . CanvasTinter . convertTintToImage = false ;
/ * *
2014-10-22 20:42:03 +00:00
* Whether or not the Canvas BlendModes are supported , consequently the ability to tint using the multiply method .
2014-02-28 09:30:53 +00:00
*
* @ property canUseMultiply
* @ type Boolean
2014-11-15 20:04:24 +00:00
* @ static
2014-02-28 09:30:53 +00:00
* /
PIXI . CanvasTinter . canUseMultiply = PIXI . canUseNewCanvasBlendModes ( ) ;
2014-10-22 20:42:03 +00:00
/ * *
* The tinting method that will be used .
*
* @ method tintMethod
2014-11-15 20:04:24 +00:00
* @ static
2014-10-22 20:42:03 +00:00
* /
2014-02-28 09:30:53 +00:00
PIXI . CanvasTinter . tintMethod = PIXI . CanvasTinter . canUseMultiply ? PIXI . CanvasTinter . tintWithMultiply : PIXI . CanvasTinter . tintWithPerPixel ;
/ * *
* @ author Mat Groves http : //matgroves.com/ @Doormat23
* /
/ * *
2014-10-22 20:42:03 +00:00
* The CanvasRenderer draws the Stage and all its content onto a 2 d canvas . This renderer should be used for browsers that do not support webGL .
* Don ' t forget to add the CanvasRenderer . view to your DOM or you will not see anything : )
2014-02-28 09:30:53 +00:00
*
* @ class CanvasRenderer
* @ constructor
2014-10-22 20:42:03 +00:00
* @ param [ width = 800 ] { Number } the width of the canvas view
* @ param [ height = 600 ] { Number } the height of the canvas view
* @ param [ options ] { Object } The optional renderer parameters
* @ param [ options . view ] { HTMLCanvasElement } the canvas to use as a view , optional
* @ param [ options . transparent = false ] { Boolean } If the render view is transparent , default false
2014-11-11 01:10:47 +00:00
* @ param [ options . autoResize = false ] { Boolean } If the render view is automatically resized , default false
2014-10-22 20:42:03 +00:00
* @ param [ options . resolution = 1 ] { Number } the resolution of the renderer retina would be 2
* @ param [ options . clearBeforeRender = true ] { Boolean } This sets if the CanvasRenderer will clear the canvas or not before the new render pass .
2014-02-28 09:30:53 +00:00
* /
2014-10-22 20:42:03 +00:00
PIXI . CanvasRenderer = function ( width , height , options )
2014-02-28 09:30:53 +00:00
{
2014-10-22 20:42:03 +00:00
if ( options )
{
for ( var i in PIXI . defaultRenderOptions )
{
if ( typeof options [ i ] === "undefined" ) options [ i ] = PIXI . defaultRenderOptions [ i ] ;
}
}
else
{
options = PIXI . defaultRenderOptions ;
}
2014-07-10 15:23:26 +00:00
if ( ! PIXI . defaultRenderer )
{
PIXI . sayHello ( "Canvas" ) ;
PIXI . defaultRenderer = this ;
}
2014-02-28 09:30:53 +00:00
2014-10-22 20:42:03 +00:00
/ * *
* The renderer type .
*
* @ property type
* @ type Number
* /
2014-02-28 09:30:53 +00:00
this . type = PIXI . CANVAS _RENDERER ;
2014-10-22 20:42:03 +00:00
/ * *
* The resolution of the canvas .
*
* @ property resolution
* @ type Number
* /
this . resolution = options . resolution ;
2014-02-28 09:30:53 +00:00
/ * *
* This sets if the CanvasRenderer will clear the canvas or not before the new render pass .
* If the Stage is NOT transparent Pixi will use a canvas sized fillRect operation every frame to set the canvas background color .
* If the Stage is transparent Pixi will use clearRect to clear the canvas every frame .
* Disable this by setting this to false . For example if your game has a canvas filling background image you often don ' t need this set .
*
* @ property clearBeforeRender
* @ type Boolean
* @ default
* /
2014-10-22 20:42:03 +00:00
this . clearBeforeRender = options . clearBeforeRender ;
2014-02-28 09:30:53 +00:00
/ * *
* Whether the render view is transparent
*
* @ property transparent
* @ type Boolean
* /
2014-10-22 20:42:03 +00:00
this . transparent = options . transparent ;
2014-11-11 01:10:47 +00:00
/ * *
* Whether the render view should be resized automatically
*
* @ property autoResize
* @ type Boolean
* /
2014-11-11 14:31:31 +00:00
this . autoResize = options . autoResize || false ;
2014-11-11 01:10:47 +00:00
2014-02-28 09:30:53 +00:00
/ * *
* The width of the canvas view
*
* @ property width
* @ type Number
* @ default 800
* /
this . width = width || 800 ;
/ * *
* The height of the canvas view
*
* @ property height
* @ type Number
* @ default 600
* /
this . height = height || 600 ;
2014-10-22 20:42:03 +00:00
this . width *= this . resolution ;
this . height *= this . resolution ;
2014-02-28 09:30:53 +00:00
/ * *
2014-10-22 20:42:03 +00:00
* The canvas element that everything is drawn to .
2014-02-28 09:30:53 +00:00
*
* @ property view
* @ type HTMLCanvasElement
* /
2014-10-22 20:42:03 +00:00
this . view = options . view || document . createElement ( "canvas" ) ;
2014-02-28 09:30:53 +00:00
/ * *
* The canvas 2 d context that everything is drawn with
* @ property context
2014-10-22 20:42:03 +00:00
* @ type CanvasRenderingContext2D
2014-02-28 09:30:53 +00:00
* /
this . context = this . view . getContext ( "2d" , { alpha : this . transparent } ) ;
2014-10-22 20:42:03 +00:00
/ * *
* Boolean flag controlling canvas refresh .
*
* @ property refresh
* @ type Boolean
* /
2014-02-28 09:30:53 +00:00
this . refresh = true ;
2014-10-22 20:42:03 +00:00
this . view . width = this . width * this . resolution ;
this . view . height = this . height * this . resolution ;
/ * *
* Internal var .
*
* @ property count
* @ type Number
* /
2014-02-28 09:30:53 +00:00
this . count = 0 ;
/ * *
* Instance of a PIXI . CanvasMaskManager , handles masking when using the canvas renderer
* @ property CanvasMaskManager
* @ type CanvasMaskManager
* /
this . maskManager = new PIXI . CanvasMaskManager ( ) ;
/ * *
* The render session is just a bunch of parameter used for rendering
* @ property renderSession
* @ type Object
* /
this . renderSession = {
context : this . context ,
maskManager : this . maskManager ,
scaleMode : null ,
2014-07-10 15:23:26 +00:00
smoothProperty : null ,
/ * *
* If true Pixi will Math . floor ( ) x / y values when rendering , stopping pixel interpolation .
* Handy for crisp pixel art and speed on legacy devices .
*
* /
roundPixels : false
2014-02-28 09:30:53 +00:00
} ;
2014-10-22 20:42:03 +00:00
this . mapBlendModes ( ) ;
this . resize ( width , height ) ;
2014-02-28 09:30:53 +00:00
if ( "imageSmoothingEnabled" in this . context )
this . renderSession . smoothProperty = "imageSmoothingEnabled" ;
else if ( "webkitImageSmoothingEnabled" in this . context )
this . renderSession . smoothProperty = "webkitImageSmoothingEnabled" ;
else if ( "mozImageSmoothingEnabled" in this . context )
this . renderSession . smoothProperty = "mozImageSmoothingEnabled" ;
else if ( "oImageSmoothingEnabled" in this . context )
this . renderSession . smoothProperty = "oImageSmoothingEnabled" ;
2014-10-22 20:42:03 +00:00
else if ( "msImageSmoothingEnabled" in this . context )
this . renderSession . smoothProperty = "msImageSmoothingEnabled" ;
2014-02-28 09:30:53 +00:00
} ;
// constructor
PIXI . CanvasRenderer . prototype . constructor = PIXI . CanvasRenderer ;
/ * *
2014-10-22 20:42:03 +00:00
* Renders the Stage to this canvas view
2014-02-28 09:30:53 +00:00
*
* @ method render
* @ param stage { Stage } the Stage element to be rendered
* /
PIXI . CanvasRenderer . prototype . render = function ( stage )
{
stage . updateTransform ( ) ;
this . context . setTransform ( 1 , 0 , 0 , 1 , 0 , 0 ) ;
2014-10-22 20:42:03 +00:00
2014-02-28 09:30:53 +00:00
this . context . globalAlpha = 1 ;
2014-10-22 20:42:03 +00:00
this . renderSession . currentBlendMode = PIXI . blendModes . NORMAL ;
this . context . globalCompositeOperation = PIXI . blendModesCanvas [ PIXI . blendModes . NORMAL ] ;
2014-07-01 14:04:03 +00:00
if ( navigator . isCocoonJS && this . view . screencanvas ) {
this . context . fillStyle = "black" ;
this . context . clear ( ) ;
}
2014-10-22 20:42:03 +00:00
if ( this . clearBeforeRender )
2014-02-28 09:30:53 +00:00
{
2014-10-22 20:42:03 +00:00
if ( this . transparent )
{
this . context . clearRect ( 0 , 0 , this . width , this . height ) ;
}
else
{
this . context . fillStyle = stage . backgroundColorString ;
this . context . fillRect ( 0 , 0 , this . width , this . height ) ;
}
2014-02-28 09:30:53 +00:00
}
2014-10-22 20:42:03 +00:00
2014-02-28 09:30:53 +00:00
this . renderDisplayObject ( stage ) ;
// run interaction!
if ( stage . interactive )
{
//need to add some events!
if ( ! stage . _interactiveEventsAdded )
{
stage . _interactiveEventsAdded = true ;
stage . interactionManager . setTarget ( this ) ;
}
}
} ;
2014-10-23 11:34:33 +00:00
/ * *
* Removes everything from the renderer and optionally removes the Canvas DOM element .
*
* @ method destroy
* @ param [ removeView = true ] { boolean } Removes the Canvas element from the DOM .
* /
PIXI . CanvasRenderer . prototype . destroy = function ( removeView )
{
if ( typeof removeView === "undefined" ) { removeView = true ; }
if ( removeView && this . view . parent )
{
this . view . parent . removeChild ( this . view ) ;
}
this . view = null ;
this . context = null ;
this . maskManager = null ;
this . renderSession = null ;
} ;
2014-02-28 09:30:53 +00:00
/ * *
* Resizes the canvas view to the specified width and height
*
* @ method resize
* @ param width { Number } the new width of the canvas view
* @ param height { Number } the new height of the canvas view
* /
PIXI . CanvasRenderer . prototype . resize = function ( width , height )
{
2014-10-22 20:42:03 +00:00
this . width = width * this . resolution ;
this . height = height * this . resolution ;
this . view . width = this . width ;
this . view . height = this . height ;
2014-02-28 09:30:53 +00:00
2014-11-11 01:10:47 +00:00
if ( this . autoResize ) {
this . view . style . width = this . width / this . resolution + "px" ;
this . view . style . height = this . height / this . resolution + "px" ;
}
2014-02-28 09:30:53 +00:00
} ;
/ * *
* Renders a display object
*
* @ method renderDisplayObject
* @ param displayObject { DisplayObject } The displayObject to render
2014-10-22 20:42:03 +00:00
* @ param context { CanvasRenderingContext2D } the context 2 d method of the canvas
2014-02-28 09:30:53 +00:00
* @ private
* /
PIXI . CanvasRenderer . prototype . renderDisplayObject = function ( displayObject , context )
{
this . renderSession . context = context || this . context ;
2014-10-22 20:42:03 +00:00
this . renderSession . resolution = this . resolution ;
2014-02-28 09:30:53 +00:00
displayObject . _renderCanvas ( this . renderSession ) ;
} ;
/ * *
2014-10-22 20:42:03 +00:00
* Maps Pixi blend modes to canvas blend modes .
2014-02-28 09:30:53 +00:00
*
2014-10-22 20:42:03 +00:00
* @ method mapBlendModes
2014-02-28 09:30:53 +00:00
* @ private
* /
2014-10-22 20:42:03 +00:00
PIXI . CanvasRenderer . prototype . mapBlendModes = function ( )
2014-02-28 09:30:53 +00:00
{
2014-10-22 20:42:03 +00:00
if ( ! PIXI . blendModesCanvas )
2014-02-28 09:30:53 +00:00
{
2014-10-22 20:42:03 +00:00
PIXI . blendModesCanvas = [ ] ;
2014-02-28 09:30:53 +00:00
2014-10-22 20:42:03 +00:00
if ( PIXI . canUseNewCanvasBlendModes ( ) )
{
PIXI . blendModesCanvas [ PIXI . blendModes . NORMAL ] = "source-over" ;
PIXI . blendModesCanvas [ PIXI . blendModes . ADD ] = "lighter" ; //IS THIS OK???
PIXI . blendModesCanvas [ PIXI . blendModes . MULTIPLY ] = "multiply" ;
PIXI . blendModesCanvas [ PIXI . blendModes . SCREEN ] = "screen" ;
PIXI . blendModesCanvas [ PIXI . blendModes . OVERLAY ] = "overlay" ;
PIXI . blendModesCanvas [ PIXI . blendModes . DARKEN ] = "darken" ;
PIXI . blendModesCanvas [ PIXI . blendModes . LIGHTEN ] = "lighten" ;
PIXI . blendModesCanvas [ PIXI . blendModes . COLOR _DODGE ] = "color-dodge" ;
PIXI . blendModesCanvas [ PIXI . blendModes . COLOR _BURN ] = "color-burn" ;
PIXI . blendModesCanvas [ PIXI . blendModes . HARD _LIGHT ] = "hard-light" ;
PIXI . blendModesCanvas [ PIXI . blendModes . SOFT _LIGHT ] = "soft-light" ;
PIXI . blendModesCanvas [ PIXI . blendModes . DIFFERENCE ] = "difference" ;
PIXI . blendModesCanvas [ PIXI . blendModes . EXCLUSION ] = "exclusion" ;
PIXI . blendModesCanvas [ PIXI . blendModes . HUE ] = "hue" ;
PIXI . blendModesCanvas [ PIXI . blendModes . SATURATION ] = "saturation" ;
PIXI . blendModesCanvas [ PIXI . blendModes . COLOR ] = "color" ;
PIXI . blendModesCanvas [ PIXI . blendModes . LUMINOSITY ] = "luminosity" ;
}
else
{
// this means that the browser does not support the cool new blend modes in canvas "cough" ie "cough"
PIXI . blendModesCanvas [ PIXI . blendModes . NORMAL ] = "source-over" ;
PIXI . blendModesCanvas [ PIXI . blendModes . ADD ] = "lighter" ; //IS THIS OK???
PIXI . blendModesCanvas [ PIXI . blendModes . MULTIPLY ] = "source-over" ;
PIXI . blendModesCanvas [ PIXI . blendModes . SCREEN ] = "source-over" ;
PIXI . blendModesCanvas [ PIXI . blendModes . OVERLAY ] = "source-over" ;
PIXI . blendModesCanvas [ PIXI . blendModes . DARKEN ] = "source-over" ;
PIXI . blendModesCanvas [ PIXI . blendModes . LIGHTEN ] = "source-over" ;
PIXI . blendModesCanvas [ PIXI . blendModes . COLOR _DODGE ] = "source-over" ;
PIXI . blendModesCanvas [ PIXI . blendModes . COLOR _BURN ] = "source-over" ;
PIXI . blendModesCanvas [ PIXI . blendModes . HARD _LIGHT ] = "source-over" ;
PIXI . blendModesCanvas [ PIXI . blendModes . SOFT _LIGHT ] = "source-over" ;
PIXI . blendModesCanvas [ PIXI . blendModes . DIFFERENCE ] = "source-over" ;
PIXI . blendModesCanvas [ PIXI . blendModes . EXCLUSION ] = "source-over" ;
PIXI . blendModesCanvas [ PIXI . blendModes . HUE ] = "source-over" ;
PIXI . blendModesCanvas [ PIXI . blendModes . SATURATION ] = "source-over" ;
PIXI . blendModesCanvas [ PIXI . blendModes . COLOR ] = "source-over" ;
PIXI . blendModesCanvas [ PIXI . blendModes . LUMINOSITY ] = "source-over" ;
}
2014-02-28 09:30:53 +00:00
}
} ;
/ * *
2014-10-22 20:42:03 +00:00
* @ author Mat Groves http : //matgroves.com/ @Doormat23
2014-02-28 09:30:53 +00:00
* /
/ * *
2014-10-22 20:42:03 +00:00
* A set of functions used by the canvas renderer to draw the primitive graphics data .
2014-02-28 09:30:53 +00:00
*
2014-10-22 20:42:03 +00:00
* @ class CanvasGraphics
2014-02-28 09:30:53 +00:00
* @ static
* /
2014-10-22 20:42:03 +00:00
PIXI . CanvasGraphics = function ( )
2014-02-28 09:30:53 +00:00
{
} ;
2014-10-22 20:42:03 +00:00
/ *
* Renders a PIXI . Graphics object to a canvas .
2014-02-28 09:30:53 +00:00
*
2014-10-22 20:42:03 +00:00
* @ method renderGraphics
* @ static
* @ param graphics { Graphics } the actual graphics object to render
* @ param context { CanvasRenderingContext2D } the 2 d drawing method of the canvas
2014-02-28 09:30:53 +00:00
* /
2014-10-22 20:42:03 +00:00
PIXI . CanvasGraphics . renderGraphics = function ( graphics , context )
2014-02-28 09:30:53 +00:00
{
2014-10-22 20:42:03 +00:00
var worldAlpha = graphics . worldAlpha ;
2014-11-15 20:04:24 +00:00
if ( graphics . dirty )
{
this . updateGraphicsTint ( graphics ) ;
graphics . dirty = false ;
}
2014-02-28 09:30:53 +00:00
for ( var i = 0 ; i < graphics . graphicsData . length ; i ++ )
{
var data = graphics . graphicsData [ i ] ;
2014-10-22 20:42:03 +00:00
var shape = data . shape ;
2014-02-28 09:30:53 +00:00
2014-11-15 20:04:24 +00:00
var fillColor = data . _fillTint ;
var lineColor = data . _lineTint ;
2014-02-28 09:30:53 +00:00
context . lineWidth = data . lineWidth ;
if ( data . type === PIXI . Graphics . POLY )
{
context . beginPath ( ) ;
2014-10-22 20:42:03 +00:00
var points = shape . points ;
2014-02-28 09:30:53 +00:00
context . moveTo ( points [ 0 ] , points [ 1 ] ) ;
for ( var j = 1 ; j < points . length / 2 ; j ++ )
{
context . lineTo ( points [ j * 2 ] , points [ j * 2 + 1 ] ) ;
}
2014-10-22 20:42:03 +00:00
if ( shape . closed )
{
context . lineTo ( points [ 0 ] , points [ 1 ] ) ;
}
2014-02-28 09:30:53 +00:00
// if the first and last point are the same close the path - much neater :)
if ( points [ 0 ] === points [ points . length - 2 ] && points [ 1 ] === points [ points . length - 1 ] )
{
context . closePath ( ) ;
}
if ( data . fill )
{
context . globalAlpha = data . fillAlpha * worldAlpha ;
2014-11-15 20:04:24 +00:00
context . fillStyle = '#' + ( '00000' + ( fillColor | 0 ) . toString ( 16 ) ) . substr ( - 6 ) ;
2014-02-28 09:30:53 +00:00
context . fill ( ) ;
}
if ( data . lineWidth )
{
context . globalAlpha = data . lineAlpha * worldAlpha ;
2014-11-15 20:04:24 +00:00
context . strokeStyle = '#' + ( '00000' + ( lineColor | 0 ) . toString ( 16 ) ) . substr ( - 6 ) ;
2014-02-28 09:30:53 +00:00
context . stroke ( ) ;
}
}
else if ( data . type === PIXI . Graphics . RECT )
{
if ( data . fillColor || data . fillColor === 0 )
{
context . globalAlpha = data . fillAlpha * worldAlpha ;
2014-11-15 20:04:24 +00:00
context . fillStyle = '#' + ( '00000' + ( fillColor | 0 ) . toString ( 16 ) ) . substr ( - 6 ) ;
context . colorRect ( shape . x , shape . y , shape . width , shape . height ) ;
2014-07-01 14:04:03 +00:00
}
if ( data . lineWidth )
{
context . globalAlpha = data . lineAlpha * worldAlpha ;
2014-11-15 20:04:24 +00:00
context . strokeStyle = '#' + ( '00000' + ( lineColor | 0 ) . toString ( 16 ) ) . substr ( - 6 ) ;
2014-10-22 20:42:03 +00:00
context . strokeRect ( shape . x , shape . y , shape . width , shape . height ) ;
2014-02-28 09:30:53 +00:00
}
}
else if ( data . type === PIXI . Graphics . CIRC )
2014-10-22 20:42:03 +00:00
{
// TODO - need to be Undefined!
context . beginPath ( ) ;
context . arc ( shape . x , shape . y , shape . radius , 0 , 2 * Math . PI ) ;
context . closePath ( ) ;
2014-07-01 14:04:03 +00:00
2014-10-22 20:42:03 +00:00
if ( data . fill )
{
context . globalAlpha = data . fillAlpha * worldAlpha ;
2014-11-15 20:04:24 +00:00
context . fillStyle = '#' + ( '00000' + ( fillColor | 0 ) . toString ( 16 ) ) . substr ( - 6 ) ;
2014-10-22 20:42:03 +00:00
context . fill ( ) ;
}
if ( data . lineWidth )
{
context . globalAlpha = data . lineAlpha * worldAlpha ;
2014-11-15 20:04:24 +00:00
context . strokeStyle = '#' + ( '00000' + ( lineColor | 0 ) . toString ( 16 ) ) . substr ( - 6 ) ;
2014-10-22 20:42:03 +00:00
context . stroke ( ) ;
}
}
else if ( data . type === PIXI . Graphics . ELIP )
{
// ellipse code taken from: http://stackoverflow.com/questions/2172798/how-to-draw-an-oval-in-html5-canvas
2014-07-01 14:04:03 +00:00
2014-10-22 20:42:03 +00:00
var w = shape . width * 2 ;
var h = shape . height * 2 ;
2014-07-01 14:04:03 +00:00
2014-10-22 20:42:03 +00:00
var x = shape . x - w / 2 ;
var y = shape . y - h / 2 ;
2014-07-01 14:04:03 +00:00
2014-10-22 20:42:03 +00:00
context . beginPath ( ) ;
2014-07-01 14:04:03 +00:00
2014-10-22 20:42:03 +00:00
var kappa = 0.5522848 ,
ox = ( w / 2 ) * kappa , // control point offset horizontal
oy = ( h / 2 ) * kappa , // control point offset vertical
xe = x + w , // x-end
ye = y + h , // y-end
xm = x + w / 2 , // x-middle
ym = y + h / 2 ; // y-middle
2014-07-01 14:04:03 +00:00
2014-10-22 20:42:03 +00:00
context . moveTo ( x , ym ) ;
context . bezierCurveTo ( x , ym - oy , xm - ox , y , xm , y ) ;
context . bezierCurveTo ( xm + ox , y , xe , ym - oy , xe , ym ) ;
context . bezierCurveTo ( xe , ym + oy , xm + ox , ye , xm , ye ) ;
context . bezierCurveTo ( xm - ox , ye , x , ym + oy , x , ym ) ;
2014-07-01 14:04:03 +00:00
2014-10-22 20:42:03 +00:00
context . closePath ( ) ;
2014-07-01 14:04:03 +00:00
2014-10-22 20:42:03 +00:00
if ( data . fill )
{
context . globalAlpha = data . fillAlpha * worldAlpha ;
2014-11-15 20:04:24 +00:00
context . fillStyle = '#' + ( '00000' + ( fillColor | 0 ) . toString ( 16 ) ) . substr ( - 6 ) ;
2014-10-22 20:42:03 +00:00
context . fill ( ) ;
}
if ( data . lineWidth )
{
context . globalAlpha = data . lineAlpha * worldAlpha ;
2014-11-15 20:04:24 +00:00
context . strokeStyle = '#' + ( '00000' + ( lineColor | 0 ) . toString ( 16 ) ) . substr ( - 6 ) ;
2014-10-22 20:42:03 +00:00
context . stroke ( ) ;
}
}
else if ( data . type === PIXI . Graphics . RREC )
{
2014-11-12 22:49:36 +00:00
var rx = shape . x ;
var ry = shape . y ;
var width = shape . width ;
var height = shape . height ;
var radius = shape . radius ;
2014-07-01 14:04:03 +00:00
2014-10-22 20:42:03 +00:00
var maxRadius = Math . min ( width , height ) / 2 | 0 ;
radius = radius > maxRadius ? maxRadius : radius ;
2014-07-01 14:04:03 +00:00
2014-10-22 20:42:03 +00:00
context . beginPath ( ) ;
context . moveTo ( rx , ry + radius ) ;
context . lineTo ( rx , ry + height - radius ) ;
context . quadraticCurveTo ( rx , ry + height , rx + radius , ry + height ) ;
context . lineTo ( rx + width - radius , ry + height ) ;
context . quadraticCurveTo ( rx + width , ry + height , rx + width , ry + height - radius ) ;
context . lineTo ( rx + width , ry + radius ) ;
context . quadraticCurveTo ( rx + width , ry , rx + width - radius , ry ) ;
context . lineTo ( rx + radius , ry ) ;
context . quadraticCurveTo ( rx , ry , rx , ry + radius ) ;
context . closePath ( ) ;
2014-07-01 14:04:03 +00:00
2014-10-22 20:42:03 +00:00
if ( data . fillColor || data . fillColor === 0 )
{
context . globalAlpha = data . fillAlpha * worldAlpha ;
2014-11-15 20:04:24 +00:00
context . fillStyle = '#' + ( '00000' + ( fillColor | 0 ) . toString ( 16 ) ) . substr ( - 6 ) ;
2014-10-22 20:42:03 +00:00
context . fill ( ) ;
2014-07-01 14:04:03 +00:00
2014-10-22 20:42:03 +00:00
}
if ( data . lineWidth )
{
context . globalAlpha = data . lineAlpha * worldAlpha ;
2014-11-15 20:04:24 +00:00
context . strokeStyle = '#' + ( '00000' + ( lineColor | 0 ) . toString ( 16 ) ) . substr ( - 6 ) ;
2014-10-22 20:42:03 +00:00
context . stroke ( ) ;
}
}
}
2014-07-01 14:04:03 +00:00
} ;
2014-10-22 20:42:03 +00:00
/ *
* Renders a graphics mask
2014-07-01 14:04:03 +00:00
*
2014-10-22 20:42:03 +00:00
* @ static
* @ private
* @ method renderGraphicsMask
* @ param graphics { Graphics } the graphics which will be used as a mask
* @ param context { CanvasRenderingContext2D } the context 2 d method of the canvas
2014-07-01 14:04:03 +00:00
* /
2014-10-22 20:42:03 +00:00
PIXI . CanvasGraphics . renderGraphicsMask = function ( graphics , context )
2014-07-01 14:04:03 +00:00
{
2014-10-22 20:42:03 +00:00
var len = graphics . graphicsData . length ;
2014-07-01 14:04:03 +00:00
2014-10-22 20:42:03 +00:00
if ( len === 0 ) return ;
2014-07-01 14:04:03 +00:00
2014-10-22 20:42:03 +00:00
if ( len > 1 )
{
len = 1 ;
window . console . log ( 'Pixi.js warning: masks in canvas can only mask using the first path in the graphics object' ) ;
}
2014-07-01 14:04:03 +00:00
2014-10-22 20:42:03 +00:00
for ( var i = 0 ; i < 1 ; i ++ )
{
var data = graphics . graphicsData [ i ] ;
var shape = data . shape ;
2014-07-01 14:04:03 +00:00
2014-10-22 20:42:03 +00:00
if ( data . type === PIXI . Graphics . POLY )
2014-07-01 14:04:03 +00:00
{
2014-10-22 20:42:03 +00:00
context . beginPath ( ) ;
var points = shape . points ;
context . moveTo ( points [ 0 ] , points [ 1 ] ) ;
for ( var j = 1 ; j < points . length / 2 ; j ++ )
{
context . lineTo ( points [ j * 2 ] , points [ j * 2 + 1 ] ) ;
}
2014-07-01 14:04:03 +00:00
2014-10-22 20:42:03 +00:00
// if the first and last point are the same close the path - much neater :)
if ( points [ 0 ] === points [ points . length - 2 ] && points [ 1 ] === points [ points . length - 1 ] )
{
context . closePath ( ) ;
}
2014-07-01 14:04:03 +00:00
}
2014-10-22 20:42:03 +00:00
else if ( data . type === PIXI . Graphics . RECT )
2014-07-01 14:04:03 +00:00
{
2014-10-22 20:42:03 +00:00
context . beginPath ( ) ;
context . rect ( shape . x , shape . y , shape . width , shape . height ) ;
context . closePath ( ) ;
2014-07-01 14:04:03 +00:00
}
2014-10-22 20:42:03 +00:00
else if ( data . type === PIXI . Graphics . CIRC )
2014-07-01 14:04:03 +00:00
{
2014-10-22 20:42:03 +00:00
// TODO - need to be Undefined!
context . beginPath ( ) ;
context . arc ( shape . x , shape . y , shape . radius , 0 , 2 * Math . PI ) ;
context . closePath ( ) ;
2014-07-01 14:04:03 +00:00
}
2014-10-22 20:42:03 +00:00
else if ( data . type === PIXI . Graphics . ELIP )
{
2014-07-01 14:04:03 +00:00
2014-10-22 20:42:03 +00:00
// ellipse code taken from: http://stackoverflow.com/questions/2172798/how-to-draw-an-oval-in-html5-canvas
2014-07-01 14:04:03 +00:00
2014-10-22 20:42:03 +00:00
var w = shape . width * 2 ;
var h = shape . height * 2 ;
2014-07-01 14:04:03 +00:00
2014-10-22 20:42:03 +00:00
var x = shape . x - w / 2 ;
var y = shape . y - h / 2 ;
2014-07-01 14:04:03 +00:00
2014-10-22 20:42:03 +00:00
context . beginPath ( ) ;
2014-07-01 14:04:03 +00:00
2014-10-22 20:42:03 +00:00
var kappa = 0.5522848 ,
ox = ( w / 2 ) * kappa , // control point offset horizontal
oy = ( h / 2 ) * kappa , // control point offset vertical
xe = x + w , // x-end
ye = y + h , // y-end
xm = x + w / 2 , // x-middle
ym = y + h / 2 ; // y-middle
2014-07-01 14:04:03 +00:00
2014-10-22 20:42:03 +00:00
context . moveTo ( x , ym ) ;
context . bezierCurveTo ( x , ym - oy , xm - ox , y , xm , y ) ;
context . bezierCurveTo ( xm + ox , y , xe , ym - oy , xe , ym ) ;
context . bezierCurveTo ( xe , ym + oy , xm + ox , ye , xm , ye ) ;
context . bezierCurveTo ( xm - ox , ye , x , ym + oy , x , ym ) ;
context . closePath ( ) ;
}
else if ( data . type === PIXI . Graphics . RREC )
{
var pts = shape . points ;
var rx = pts [ 0 ] ;
var ry = pts [ 1 ] ;
var width = pts [ 2 ] ;
var height = pts [ 3 ] ;
var radius = pts [ 4 ] ;
2014-07-01 14:04:03 +00:00
2014-10-22 20:42:03 +00:00
var maxRadius = Math . min ( width , height ) / 2 | 0 ;
radius = radius > maxRadius ? maxRadius : radius ;
2014-07-01 14:04:03 +00:00
2014-10-22 20:42:03 +00:00
context . beginPath ( ) ;
context . moveTo ( rx , ry + radius ) ;
context . lineTo ( rx , ry + height - radius ) ;
context . quadraticCurveTo ( rx , ry + height , rx + radius , ry + height ) ;
context . lineTo ( rx + width - radius , ry + height ) ;
context . quadraticCurveTo ( rx + width , ry + height , rx + width , ry + height - radius ) ;
context . lineTo ( rx + width , ry + radius ) ;
context . quadraticCurveTo ( rx + width , ry , rx + width - radius , ry ) ;
context . lineTo ( rx + radius , ry ) ;
context . quadraticCurveTo ( rx , ry , rx , ry + radius ) ;
context . closePath ( ) ;
}
}
2014-07-01 14:04:03 +00:00
} ;
2014-11-15 20:04:24 +00:00
PIXI . CanvasGraphics . updateGraphicsTint = function ( graphics )
{
if ( graphics . tint === 0xFFFFFF ) return ;
var tintR = ( graphics . tint >> 16 & 0xFF ) / 255 ;
var tintG = ( graphics . tint >> 8 & 0xFF ) / 255 ;
var tintB = ( graphics . tint & 0xFF ) / 255 ;
for ( var i = 0 ; i < graphics . graphicsData . length ; i ++ )
{
var data = graphics . graphicsData [ i ] ;
var fillColor = data . fillColor | 0 ;
var lineColor = data . lineColor | 0 ;
/ *
var colorR = ( fillColor >> 16 & 0xFF ) / 255 ;
var colorG = ( fillColor >> 8 & 0xFF ) / 255 ;
var colorB = ( fillColor & 0xFF ) / 255 ;
colorR *= tintR ;
colorG *= tintG ;
colorB *= tintB ;
fillColor = ( ( colorR * 255 << 16 ) + ( colorG * 255 << 8 ) + colorB * 255 ) ;
colorR = ( lineColor >> 16 & 0xFF ) / 255 ;
colorG = ( lineColor >> 8 & 0xFF ) / 255 ;
colorB = ( lineColor & 0xFF ) / 255 ;
colorR *= tintR ;
colorG *= tintG ;
colorB *= tintB ;
lineColor = ( ( colorR * 255 << 16 ) + ( colorG * 255 << 8 ) + colorB * 255 ) ;
* /
// super inline cos im an optimization NAZI :)
data . _fillTint = ( ( ( fillColor >> 16 & 0xFF ) / 255 * tintR * 255 << 16 ) + ( ( fillColor >> 8 & 0xFF ) / 255 * tintG * 255 << 8 ) + ( fillColor & 0xFF ) / 255 * tintB * 255 ) ;
data . _lineTint = ( ( ( lineColor >> 16 & 0xFF ) / 255 * tintR * 255 << 16 ) + ( ( lineColor >> 8 & 0xFF ) / 255 * tintG * 255 << 8 ) + ( lineColor & 0xFF ) / 255 * tintB * 255 ) ;
}
} ;
2014-07-01 14:04:03 +00:00
/ * *
* @ author Mat Groves http : //matgroves.com/
* /
/ * *
*
* @ class Strip
* @ extends DisplayObjectContainer
* @ constructor
* @ param texture { Texture } The texture to use
* @ param width { Number } the width
* @ param height { Number } the height
*
* /
PIXI . Strip = function ( texture )
{
PIXI . DisplayObjectContainer . call ( this ) ;
2014-08-29 17:13:33 +00:00
/ * *
* The texture of the strip
*
* @ property texture
* @ type Texture
* /
2014-07-01 14:04:03 +00:00
this . texture = texture ;
// set up the main bits..
this . uvs = new PIXI . Float32Array ( [ 0 , 1 ,
2014-10-22 20:42:03 +00:00
1 , 1 ,
1 , 0 ,
0 , 1 ] ) ;
2014-07-01 14:04:03 +00:00
this . verticies = new PIXI . Float32Array ( [ 0 , 0 ,
2014-10-22 20:42:03 +00:00
100 , 0 ,
100 , 100 ,
0 , 100 ] ) ;
2014-07-01 14:04:03 +00:00
this . colors = new PIXI . Float32Array ( [ 1 , 1 , 1 , 1 ] ) ;
this . indices = new PIXI . Uint16Array ( [ 0 , 1 , 2 , 3 ] ) ;
2014-08-29 17:13:33 +00:00
/ * *
* Whether the strip is dirty or not
*
* @ property dirty
* @ type Boolean
* /
2014-07-01 14:04:03 +00:00
this . dirty = true ;
2014-08-29 17:13:33 +00:00
2014-11-12 22:49:36 +00:00
/ * *
* The blend mode to be applied to the sprite . Set to PIXI . blendModes . NORMAL to remove any blend mode .
*
* @ property blendMode
* @ type Number
* @ default PIXI . blendModes . NORMAL ;
* /
this . blendMode = PIXI . blendModes . NORMAL ;
2014-08-29 17:13:33 +00:00
/ * *
* if you need a padding , not yet implemented
*
* @ property padding
* @ type Number
* /
this . padding = 0 ;
// NYI, TODO padding ?
2014-07-01 14:04:03 +00:00
} ;
// constructor
PIXI . Strip . prototype = Object . create ( PIXI . DisplayObjectContainer . prototype ) ;
PIXI . Strip . prototype . constructor = PIXI . Strip ;
PIXI . Strip . prototype . _renderWebGL = function ( renderSession )
{
// if the sprite is not visible or the alpha is 0 then no need to render this element
if ( ! this . visible || this . alpha <= 0 ) return ;
// render triangle strip..
renderSession . spriteBatch . stop ( ) ;
// init! init!
if ( ! this . _vertexBuffer ) this . _initWebGL ( renderSession ) ;
renderSession . shaderManager . setShader ( renderSession . shaderManager . stripShader ) ;
this . _renderStrip ( renderSession ) ;
///renderSession.shaderManager.activateDefaultShader();
renderSession . spriteBatch . start ( ) ;
//TODO check culling
} ;
PIXI . Strip . prototype . _initWebGL = function ( renderSession )
{
// build the strip!
var gl = renderSession . gl ;
this . _vertexBuffer = gl . createBuffer ( ) ;
this . _indexBuffer = gl . createBuffer ( ) ;
this . _uvBuffer = gl . createBuffer ( ) ;
this . _colorBuffer = gl . createBuffer ( ) ;
gl . bindBuffer ( gl . ARRAY _BUFFER , this . _vertexBuffer ) ;
gl . bufferData ( gl . ARRAY _BUFFER , this . verticies , gl . DYNAMIC _DRAW ) ;
gl . bindBuffer ( gl . ARRAY _BUFFER , this . _uvBuffer ) ;
gl . bufferData ( gl . ARRAY _BUFFER , this . uvs , gl . STATIC _DRAW ) ;
gl . bindBuffer ( gl . ARRAY _BUFFER , this . _colorBuffer ) ;
gl . bufferData ( gl . ARRAY _BUFFER , this . colors , gl . STATIC _DRAW ) ;
gl . bindBuffer ( gl . ELEMENT _ARRAY _BUFFER , this . _indexBuffer ) ;
gl . bufferData ( gl . ELEMENT _ARRAY _BUFFER , this . indices , gl . STATIC _DRAW ) ;
} ;
PIXI . Strip . prototype . _renderStrip = function ( renderSession )
{
var gl = renderSession . gl ;
var projection = renderSession . projection ,
offset = renderSession . offset ,
shader = renderSession . shaderManager . stripShader ;
// gl.uniformMatrix4fv(shaderProgram.mvMatrixUniform, false, mat4Real);
2014-11-12 22:49:36 +00:00
renderSession . blendModeManager . setBlendMode ( this . blendMode ) ;
2014-07-01 14:04:03 +00:00
// set uniforms
gl . uniformMatrix3fv ( shader . translationMatrix , false , this . worldTransform . toArray ( true ) ) ;
gl . uniform2f ( shader . projectionVector , projection . x , - projection . y ) ;
gl . uniform2f ( shader . offsetVector , - offset . x , - offset . y ) ;
2014-10-22 20:42:03 +00:00
gl . uniform1f ( shader . alpha , this . worldAlpha ) ;
2014-07-01 14:04:03 +00:00
if ( ! this . dirty )
{
gl . bindBuffer ( gl . ARRAY _BUFFER , this . _vertexBuffer ) ;
gl . bufferSubData ( gl . ARRAY _BUFFER , 0 , this . verticies ) ;
gl . vertexAttribPointer ( shader . aVertexPosition , 2 , gl . FLOAT , false , 0 , 0 ) ;
// update the uvs
gl . bindBuffer ( gl . ARRAY _BUFFER , this . _uvBuffer ) ;
gl . vertexAttribPointer ( shader . aTextureCoord , 2 , gl . FLOAT , false , 0 , 0 ) ;
gl . activeTexture ( gl . TEXTURE0 ) ;
2014-10-22 20:42:03 +00:00
// check if a texture is dirty..
if ( this . texture . baseTexture . _dirty [ gl . id ] )
{
renderSession . renderer . updateTexture ( this . texture . baseTexture ) ;
}
else
{
// bind the current texture
gl . bindTexture ( gl . TEXTURE _2D , this . texture . baseTexture . _glTextures [ gl . id ] ) ;
}
2014-07-01 14:04:03 +00:00
// dont need to upload!
gl . bindBuffer ( gl . ELEMENT _ARRAY _BUFFER , this . _indexBuffer ) ;
}
else
{
this . dirty = false ;
gl . bindBuffer ( gl . ARRAY _BUFFER , this . _vertexBuffer ) ;
gl . bufferData ( gl . ARRAY _BUFFER , this . verticies , gl . STATIC _DRAW ) ;
gl . vertexAttribPointer ( shader . aVertexPosition , 2 , gl . FLOAT , false , 0 , 0 ) ;
// update the uvs
gl . bindBuffer ( gl . ARRAY _BUFFER , this . _uvBuffer ) ;
gl . bufferData ( gl . ARRAY _BUFFER , this . uvs , gl . STATIC _DRAW ) ;
gl . vertexAttribPointer ( shader . aTextureCoord , 2 , gl . FLOAT , false , 0 , 0 ) ;
gl . activeTexture ( gl . TEXTURE0 ) ;
2014-10-22 20:42:03 +00:00
// check if a texture is dirty..
if ( this . texture . baseTexture . _dirty [ gl . id ] )
{
renderSession . renderer . updateTexture ( this . texture . baseTexture ) ;
}
else
{
gl . bindTexture ( gl . TEXTURE _2D , this . texture . baseTexture . _glTextures [ gl . id ] ) ;
}
2014-07-01 14:04:03 +00:00
// dont need to upload!
gl . bindBuffer ( gl . ELEMENT _ARRAY _BUFFER , this . _indexBuffer ) ;
gl . bufferData ( gl . ELEMENT _ARRAY _BUFFER , this . indices , gl . STATIC _DRAW ) ;
}
//console.log(gl.TRIANGLE_STRIP)
//
//
gl . drawElements ( gl . TRIANGLE _STRIP , this . indices . length , gl . UNSIGNED _SHORT , 0 ) ;
} ;
2014-10-22 20:42:03 +00:00
2014-07-01 14:04:03 +00:00
PIXI . Strip . prototype . _renderCanvas = function ( renderSession )
{
var context = renderSession . context ;
var transform = this . worldTransform ;
if ( renderSession . roundPixels )
{
2014-10-22 20:42:03 +00:00
context . setTransform ( transform . a , transform . b , transform . c , transform . d , transform . tx | 0 , transform . ty | 0 ) ;
2014-07-01 14:04:03 +00:00
}
else
{
2014-10-22 20:42:03 +00:00
context . setTransform ( transform . a , transform . b , transform . c , transform . d , transform . tx , transform . ty ) ;
2014-07-01 14:04:03 +00:00
}
var strip = this ;
// draw triangles!!
var verticies = strip . verticies ;
var uvs = strip . uvs ;
var length = verticies . length / 2 ;
this . count ++ ;
for ( var i = 0 ; i < length - 2 ; i ++ )
{
// draw some triangles!
var index = i * 2 ;
var x0 = verticies [ index ] , x1 = verticies [ index + 2 ] , x2 = verticies [ index + 4 ] ;
var y0 = verticies [ index + 1 ] , y1 = verticies [ index + 3 ] , y2 = verticies [ index + 5 ] ;
2014-10-22 20:42:03 +00:00
if ( this . padding > 0 )
2014-07-01 14:04:03 +00:00
{
var centerX = ( x0 + x1 + x2 ) / 3 ;
var centerY = ( y0 + y1 + y2 ) / 3 ;
var normX = x0 - centerX ;
var normY = y0 - centerY ;
var dist = Math . sqrt ( normX * normX + normY * normY ) ;
x0 = centerX + ( normX / dist ) * ( dist + 3 ) ;
y0 = centerY + ( normY / dist ) * ( dist + 3 ) ;
//
normX = x1 - centerX ;
normY = y1 - centerY ;
dist = Math . sqrt ( normX * normX + normY * normY ) ;
x1 = centerX + ( normX / dist ) * ( dist + 3 ) ;
y1 = centerY + ( normY / dist ) * ( dist + 3 ) ;
normX = x2 - centerX ;
normY = y2 - centerY ;
dist = Math . sqrt ( normX * normX + normY * normY ) ;
x2 = centerX + ( normX / dist ) * ( dist + 3 ) ;
y2 = centerY + ( normY / dist ) * ( dist + 3 ) ;
}
var u0 = uvs [ index ] * strip . texture . width , u1 = uvs [ index + 2 ] * strip . texture . width , u2 = uvs [ index + 4 ] * strip . texture . width ;
var v0 = uvs [ index + 1 ] * strip . texture . height , v1 = uvs [ index + 3 ] * strip . texture . height , v2 = uvs [ index + 5 ] * strip . texture . height ;
context . save ( ) ;
context . beginPath ( ) ;
context . moveTo ( x0 , y0 ) ;
context . lineTo ( x1 , y1 ) ;
context . lineTo ( x2 , y2 ) ;
context . closePath ( ) ;
context . clip ( ) ;
// Compute matrix transform
var delta = u0 * v1 + v0 * u2 + u1 * v2 - v1 * u2 - v0 * u1 - u0 * v2 ;
var deltaA = x0 * v1 + v0 * x2 + x1 * v2 - v1 * x2 - v0 * x1 - x0 * v2 ;
var deltaB = u0 * x1 + x0 * u2 + u1 * x2 - x1 * u2 - x0 * u1 - u0 * x2 ;
var deltaC = u0 * v1 * x2 + v0 * x1 * u2 + x0 * u1 * v2 - x0 * v1 * u2 - v0 * u1 * x2 - u0 * x1 * v2 ;
var deltaD = y0 * v1 + v0 * y2 + y1 * v2 - v1 * y2 - v0 * y1 - y0 * v2 ;
var deltaE = u0 * y1 + y0 * u2 + u1 * y2 - y1 * u2 - y0 * u1 - u0 * y2 ;
var deltaF = u0 * v1 * y2 + v0 * y1 * u2 + y0 * u1 * v2 - y0 * v1 * u2 - v0 * u1 * y2 - u0 * y1 * v2 ;
context . transform ( deltaA / delta , deltaD / delta ,
deltaB / delta , deltaE / delta ,
deltaC / delta , deltaF / delta ) ;
2014-10-22 20:42:03 +00:00
context . drawImage ( strip . texture . baseTexture . source , 0 , 0 ) ;
context . restore ( ) ;
}
} ;
/ * *
* Renders a flat strip
*
* @ method renderStripFlat
* @ param strip { Strip } The Strip to render
* @ private
* /
PIXI . Strip . prototype . renderStripFlat = function ( strip )
{
var context = this . context ;
var verticies = strip . verticies ;
var length = verticies . length / 2 ;
this . count ++ ;
context . beginPath ( ) ;
for ( var i = 1 ; i < length - 2 ; i ++ )
{
// draw some triangles!
var index = i * 2 ;
var x0 = verticies [ index ] , x1 = verticies [ index + 2 ] , x2 = verticies [ index + 4 ] ;
var y0 = verticies [ index + 1 ] , y1 = verticies [ index + 3 ] , y2 = verticies [ index + 5 ] ;
context . moveTo ( x0 , y0 ) ;
context . lineTo ( x1 , y1 ) ;
context . lineTo ( x2 , y2 ) ;
2014-07-01 14:04:03 +00:00
}
2014-10-22 20:42:03 +00:00
context . fillStyle = "#FF0000" ;
context . fill ( ) ;
context . closePath ( ) ;
} ;
2014-07-01 14:04:03 +00:00
/ *
PIXI . Strip . prototype . setTexture = function ( texture )
{
//TODO SET THE TEXTURES
//TODO VISIBILITY
// stop current texture
this . texture = texture ;
this . width = texture . frame . width ;
this . height = texture . frame . height ;
this . updateFrame = true ;
2014-02-28 09:30:53 +00:00
} ;
* /
2014-07-01 14:04:03 +00:00
/ * *
* When the texture is updated , this event will fire to update the scale and frame
*
* @ method onTextureUpdate
* @ param event
* @ private
* /
2014-02-28 09:30:53 +00:00
2014-07-01 14:04:03 +00:00
PIXI . Strip . prototype . onTextureUpdate = function ( )
{
this . updateFrame = true ;
2014-02-28 09:30:53 +00:00
} ;
2014-10-22 20:42:03 +00:00
/ * *
* @ author Mat Groves http : //matgroves.com/ @Doormat23
* @ copyright Mat Groves , Rovanion Luckey
2014-07-01 14:04:03 +00:00
* /
2014-02-28 09:30:53 +00:00
/ * *
2014-10-22 20:42:03 +00:00
*
2014-07-01 14:04:03 +00:00
* @ class Rope
* @ constructor
2014-08-29 17:13:33 +00:00
* @ extends Strip
2014-10-22 20:42:03 +00:00
* @ param { Texture } texture - The texture to use on the rope .
* @ param { Array } points - An array of { PIXI . Point } .
*
2014-02-28 09:30:53 +00:00
* /
2014-07-01 14:04:03 +00:00
PIXI . Rope = function ( texture , points )
2014-02-28 09:30:53 +00:00
{
2014-07-01 14:04:03 +00:00
PIXI . Strip . call ( this , texture ) ;
this . points = points ;
2014-02-28 09:30:53 +00:00
2014-07-01 14:04:03 +00:00
this . verticies = new PIXI . Float32Array ( points . length * 4 ) ;
this . uvs = new PIXI . Float32Array ( points . length * 4 ) ;
this . colors = new PIXI . Float32Array ( points . length * 2 ) ;
this . indices = new PIXI . Uint16Array ( points . length * 2 ) ;
2014-10-22 20:42:03 +00:00
2014-02-28 09:30:53 +00:00
2014-07-01 14:04:03 +00:00
this . refresh ( ) ;
} ;
2014-02-28 09:30:53 +00:00
2014-07-01 14:04:03 +00:00
// constructor
PIXI . Rope . prototype = Object . create ( PIXI . Strip . prototype ) ;
PIXI . Rope . prototype . constructor = PIXI . Rope ;
2014-02-28 09:30:53 +00:00
2014-07-01 14:04:03 +00:00
/ *
2014-10-22 20:42:03 +00:00
* Refreshes
2014-07-01 14:04:03 +00:00
*
* @ method refresh
* /
PIXI . Rope . prototype . refresh = function ( )
{
var points = this . points ;
if ( points . length < 1 ) return ;
2014-02-28 09:30:53 +00:00
2014-07-01 14:04:03 +00:00
var uvs = this . uvs ;
2014-02-28 09:30:53 +00:00
2014-07-01 14:04:03 +00:00
var lastPoint = points [ 0 ] ;
var indices = this . indices ;
var colors = this . colors ;
2014-02-28 09:30:53 +00:00
2014-07-01 14:04:03 +00:00
this . count -= 0.2 ;
2014-02-28 09:30:53 +00:00
2014-07-01 14:04:03 +00:00
uvs [ 0 ] = 0 ;
uvs [ 1 ] = 0 ;
uvs [ 2 ] = 0 ;
uvs [ 3 ] = 1 ;
2014-02-28 09:30:53 +00:00
2014-07-01 14:04:03 +00:00
colors [ 0 ] = 1 ;
colors [ 1 ] = 1 ;
2014-02-28 09:30:53 +00:00
2014-07-01 14:04:03 +00:00
indices [ 0 ] = 0 ;
indices [ 1 ] = 1 ;
2014-02-28 09:30:53 +00:00
2014-07-01 14:04:03 +00:00
var total = points . length ,
point , index , amount ;
2014-02-28 09:30:53 +00:00
2014-07-01 14:04:03 +00:00
for ( var i = 1 ; i < total ; i ++ )
{
point = points [ i ] ;
index = i * 4 ;
// time to do some smart drawing!
amount = i / ( total - 1 ) ;
2014-02-28 09:30:53 +00:00
2014-07-01 14:04:03 +00:00
if ( i % 2 )
{
uvs [ index ] = amount ;
uvs [ index + 1 ] = 0 ;
2014-02-28 09:30:53 +00:00
2014-07-01 14:04:03 +00:00
uvs [ index + 2 ] = amount ;
uvs [ index + 3 ] = 1 ;
}
else
{
uvs [ index ] = amount ;
uvs [ index + 1 ] = 0 ;
2014-02-28 09:30:53 +00:00
2014-07-01 14:04:03 +00:00
uvs [ index + 2 ] = amount ;
uvs [ index + 3 ] = 1 ;
}
2014-02-28 09:30:53 +00:00
2014-07-01 14:04:03 +00:00
index = i * 2 ;
colors [ index ] = 1 ;
colors [ index + 1 ] = 1 ;
2014-02-28 09:30:53 +00:00
2014-07-01 14:04:03 +00:00
index = i * 2 ;
indices [ index ] = index ;
indices [ index + 1 ] = index + 1 ;
lastPoint = point ;
}
2014-02-28 09:30:53 +00:00
} ;
2014-07-01 14:04:03 +00:00
/ *
* Updates the object transform for rendering
2014-02-28 09:30:53 +00:00
*
2014-07-01 14:04:03 +00:00
* @ method updateTransform
* @ private
2014-02-28 09:30:53 +00:00
* /
2014-07-01 14:04:03 +00:00
PIXI . Rope . prototype . updateTransform = function ( )
2014-02-28 09:30:53 +00:00
{
2014-07-01 14:04:03 +00:00
var points = this . points ;
if ( points . length < 1 ) return ;
2014-02-28 09:30:53 +00:00
2014-07-01 14:04:03 +00:00
var lastPoint = points [ 0 ] ;
var nextPoint ;
var perp = { x : 0 , y : 0 } ;
2014-02-28 09:30:53 +00:00
2014-07-01 14:04:03 +00:00
this . count -= 0.2 ;
2014-02-28 09:30:53 +00:00
2014-07-01 14:04:03 +00:00
var verticies = this . verticies ;
var total = points . length ,
point , index , ratio , perpLength , num ;
2014-02-28 09:30:53 +00:00
2014-07-01 14:04:03 +00:00
for ( var i = 0 ; i < total ; i ++ )
{
point = points [ i ] ;
index = i * 4 ;
2014-02-28 09:30:53 +00:00
2014-07-01 14:04:03 +00:00
if ( i < points . length - 1 )
2014-02-28 09:30:53 +00:00
{
2014-07-01 14:04:03 +00:00
nextPoint = points [ i + 1 ] ;
2014-02-28 09:30:53 +00:00
}
else
{
2014-07-01 14:04:03 +00:00
nextPoint = point ;
2014-02-28 09:30:53 +00:00
}
2014-07-01 14:04:03 +00:00
perp . y = - ( nextPoint . x - lastPoint . x ) ;
perp . x = nextPoint . y - lastPoint . y ;
2014-02-28 09:30:53 +00:00
2014-07-01 14:04:03 +00:00
ratio = ( 1 - ( i / ( total - 1 ) ) ) * 10 ;
2014-02-28 09:30:53 +00:00
2014-07-01 14:04:03 +00:00
if ( ratio > 1 ) ratio = 1 ;
2014-02-28 09:30:53 +00:00
2014-07-01 14:04:03 +00:00
perpLength = Math . sqrt ( perp . x * perp . x + perp . y * perp . y ) ;
num = this . texture . height / 2 ; //(20 + Math.abs(Math.sin((i + this.count) * 0.3) * 50) )* ratio;
perp . x /= perpLength ;
perp . y /= perpLength ;
2014-02-28 09:30:53 +00:00
2014-07-01 14:04:03 +00:00
perp . x *= num ;
perp . y *= num ;
2014-02-28 09:30:53 +00:00
2014-07-01 14:04:03 +00:00
verticies [ index ] = point . x + perp . x ;
verticies [ index + 1 ] = point . y + perp . y ;
verticies [ index + 2 ] = point . x - perp . x ;
verticies [ index + 3 ] = point . y - perp . y ;
2014-02-28 09:30:53 +00:00
2014-07-01 14:04:03 +00:00
lastPoint = point ;
}
2014-04-01 02:02:36 +00:00
2014-07-01 14:04:03 +00:00
PIXI . DisplayObjectContainer . prototype . updateTransform . call ( this ) ;
2014-02-28 09:30:53 +00:00
} ;
2014-07-01 14:04:03 +00:00
/ *
2014-10-22 20:42:03 +00:00
* Sets the texture that the Rope will use
2014-07-01 14:04:03 +00:00
*
* @ method setTexture
* @ param texture { Texture } the texture that will be used
* /
PIXI . Rope . prototype . setTexture = function ( texture )
2014-02-28 09:30:53 +00:00
{
2014-07-01 14:04:03 +00:00
// stop current texture
this . texture = texture ;
2014-07-10 15:23:26 +00:00
//this.updateFrame = true;
2014-02-28 09:30:53 +00:00
} ;
/ * *
* @ author Mat Groves http : //matgroves.com/
* /
/ * *
* A tiling sprite is a fast way of rendering a tiling image
*
* @ class TilingSprite
2014-02-28 18:55:07 +00:00
* @ extends Sprite
2014-02-28 09:30:53 +00:00
* @ constructor
* @ param texture { Texture } the texture of the tiling sprite
* @ param width { Number } the width of the tiling sprite
* @ param height { Number } the height of the tiling sprite
* /
PIXI . TilingSprite = function ( texture , width , height )
{
PIXI . Sprite . call ( this , texture ) ;
/ * *
* The with of the tiling sprite
*
* @ property width
* @ type Number
* /
2014-07-16 00:58:24 +00:00
this . _width = width || 100 ;
2014-02-28 18:55:07 +00:00
2014-02-28 09:30:53 +00:00
/ * *
* The height of the tiling sprite
*
* @ property height
* @ type Number
* /
2014-07-16 00:58:24 +00:00
this . _height = height || 100 ;
2014-02-28 09:30:53 +00:00
/ * *
* The scaling of the image that is being tiled
*
* @ property tileScale
* @ type Point
* /
this . tileScale = new PIXI . Point ( 1 , 1 ) ;
/ * *
* A point that represents the scale of the texture object
*
* @ property tileScaleOffset
* @ type Point
* /
this . tileScaleOffset = new PIXI . Point ( 1 , 1 ) ;
2014-04-01 02:02:36 +00:00
2014-02-28 09:30:53 +00:00
/ * *
* The offset position of the image that is being tiled
*
* @ property tilePosition
* @ type Point
* /
this . tilePosition = new PIXI . Point ( 0 , 0 ) ;
/ * *
* Whether this sprite is renderable or not
*
* @ property renderable
* @ type Boolean
* @ default true
* /
this . renderable = true ;
/ * *
* The tint applied to the sprite . This is a hex value
*
* @ property tint
* @ type Number
* @ default 0xFFFFFF
* /
this . tint = 0xFFFFFF ;
2014-04-01 02:02:36 +00:00
2014-02-28 09:30:53 +00:00
/ * *
* The blend mode to be applied to the sprite
*
* @ property blendMode
* @ type Number
* @ default PIXI . blendModes . NORMAL ;
* /
this . blendMode = PIXI . blendModes . NORMAL ;
2014-07-16 00:58:24 +00:00
2014-02-28 09:30:53 +00:00
} ;
// constructor
PIXI . TilingSprite . prototype = Object . create ( PIXI . Sprite . prototype ) ;
PIXI . TilingSprite . prototype . constructor = PIXI . TilingSprite ;
/ * *
* The width of the sprite , setting this will actually modify the scale to achieve the value set
*
* @ property width
* @ type Number
* /
Object . defineProperty ( PIXI . TilingSprite . prototype , 'width' , {
get : function ( ) {
return this . _width ;
} ,
set : function ( value ) {
2014-04-01 02:02:36 +00:00
2014-02-28 09:30:53 +00:00
this . _width = value ;
}
} ) ;
/ * *
* The height of the TilingSprite , setting this will actually modify the scale to achieve the value set
*
* @ property height
* @ type Number
* /
Object . defineProperty ( PIXI . TilingSprite . prototype , 'height' , {
get : function ( ) {
return this . _height ;
} ,
set : function ( value ) {
this . _height = value ;
}
} ) ;
PIXI . TilingSprite . prototype . setTexture = function ( texture )
{
2014-07-10 15:23:26 +00:00
if ( this . texture === texture ) return ;
2014-02-28 09:30:53 +00:00
this . texture = texture ;
this . refreshTexture = true ;
this . cachedTint = 0xFFFFFF ;
} ;
/ * *
* Renders the object using the WebGL renderer
*
* @ method _renderWebGL
2014-04-01 02:02:36 +00:00
* @ param renderSession { RenderSession }
2014-02-28 09:30:53 +00:00
* @ private
* /
PIXI . TilingSprite . prototype . _renderWebGL = function ( renderSession )
{
2014-07-10 15:23:26 +00:00
if ( this . visible === false || this . alpha === 0 ) return ;
2014-02-28 09:30:53 +00:00
var i , j ;
2014-07-16 00:58:24 +00:00
if ( this . _mask )
2014-02-28 09:30:53 +00:00
{
2014-02-28 18:55:07 +00:00
renderSession . spriteBatch . stop ( ) ;
renderSession . maskManager . pushMask ( this . mask , renderSession ) ;
renderSession . spriteBatch . start ( ) ;
}
2014-02-28 09:30:53 +00:00
2014-07-16 00:58:24 +00:00
if ( this . _filters )
2014-02-28 18:55:07 +00:00
{
renderSession . spriteBatch . flush ( ) ;
renderSession . filterManager . pushFilter ( this . _filterBlock ) ;
}
2014-02-28 09:30:53 +00:00
2014-07-16 00:58:24 +00:00
2014-07-10 15:23:26 +00:00
if ( ! this . tilingTexture || this . refreshTexture )
2014-02-28 18:55:07 +00:00
{
this . generateTilingTexture ( true ) ;
2014-07-10 15:23:26 +00:00
if ( this . tilingTexture && this . tilingTexture . needsUpdate )
2014-02-28 09:30:53 +00:00
{
2014-02-28 18:55:07 +00:00
//TODO - tweaking
PIXI . updateWebGLTexture ( this . tilingTexture . baseTexture , renderSession . gl ) ;
this . tilingTexture . needsUpdate = false ;
// this.tilingTexture._uvs = null;
2014-02-28 09:30:53 +00:00
}
}
2014-07-10 15:23:26 +00:00
else
{
renderSession . spriteBatch . renderTilingSprite ( this ) ;
}
2014-02-28 18:55:07 +00:00
// simple render children!
2014-07-10 15:23:26 +00:00
for ( i = 0 , j = this . children . length ; i < j ; i ++ )
2014-02-28 09:30:53 +00:00
{
2014-02-28 18:55:07 +00:00
this . children [ i ] . _renderWebGL ( renderSession ) ;
2014-02-28 09:30:53 +00:00
}
2014-02-28 18:55:07 +00:00
renderSession . spriteBatch . stop ( ) ;
2014-07-16 00:58:24 +00:00
if ( this . _filters ) renderSession . filterManager . popFilter ( ) ;
2014-08-29 17:13:33 +00:00
if ( this . _mask ) renderSession . maskManager . popMask ( this . _mask , renderSession ) ;
2014-04-01 02:02:36 +00:00
2014-02-28 18:55:07 +00:00
renderSession . spriteBatch . start ( ) ;
2014-02-28 09:30:53 +00:00
} ;
/ * *
* Renders the object using the Canvas renderer
*
* @ method _renderCanvas
2014-04-01 02:02:36 +00:00
* @ param renderSession { RenderSession }
2014-02-28 09:30:53 +00:00
* @ private
* /
PIXI . TilingSprite . prototype . _renderCanvas = function ( renderSession )
{
2014-07-10 15:23:26 +00:00
if ( this . visible === false || this . alpha === 0 ) return ;
2014-04-01 02:02:36 +00:00
2014-02-28 09:30:53 +00:00
var context = renderSession . context ;
2014-07-10 15:23:26 +00:00
if ( this . _mask )
2014-02-28 09:30:53 +00:00
{
renderSession . maskManager . pushMask ( this . _mask , context ) ;
}
context . globalAlpha = this . worldAlpha ;
2014-04-01 02:02:36 +00:00
2014-02-28 09:30:53 +00:00
var transform = this . worldTransform ;
2014-07-01 14:04:03 +00:00
var i , j ;
2014-10-22 20:42:03 +00:00
var resolution = renderSession . resolution ;
context . setTransform ( transform . a * resolution ,
transform . c * resolution ,
transform . b * resolution ,
transform . d * resolution ,
transform . tx * resolution ,
transform . ty * resolution ) ;
2014-02-28 09:30:53 +00:00
2014-07-10 15:23:26 +00:00
if ( ! this . _ _tilePattern || this . refreshTexture )
2014-02-28 09:30:53 +00:00
{
this . generateTilingTexture ( false ) ;
2014-04-01 02:02:36 +00:00
2014-07-10 15:23:26 +00:00
if ( this . tilingTexture )
2014-02-28 09:30:53 +00:00
{
this . _ _tilePattern = context . createPattern ( this . tilingTexture . baseTexture . source , 'repeat' ) ;
}
2014-04-01 02:02:36 +00:00
else
{
return ;
}
2014-02-28 09:30:53 +00:00
}
// check blend mode
2014-07-10 15:23:26 +00:00
if ( this . blendMode !== renderSession . currentBlendMode )
2014-02-28 09:30:53 +00:00
{
renderSession . currentBlendMode = this . blendMode ;
context . globalCompositeOperation = PIXI . blendModesCanvas [ renderSession . currentBlendMode ] ;
}
var tilePosition = this . tilePosition ;
var tileScale = this . tileScale ;
tilePosition . x %= this . tilingTexture . baseTexture . width ;
tilePosition . y %= this . tilingTexture . baseTexture . height ;
2014-10-22 20:42:03 +00:00
// offset - make sure to account for the anchor point..
2014-02-28 09:30:53 +00:00
context . scale ( tileScale . x , tileScale . y ) ;
2014-10-22 20:42:03 +00:00
context . translate ( tilePosition . x + ( this . anchor . x * - this . _width ) , tilePosition . y + ( this . anchor . y * - this . _height ) ) ;
2014-02-28 09:30:53 +00:00
context . fillStyle = this . _ _tilePattern ;
2014-04-01 02:02:36 +00:00
2014-10-22 20:42:03 +00:00
context . fillRect ( - tilePosition . x ,
- tilePosition . y ,
2014-07-10 19:18:20 +00:00
this . _width / tileScale . x ,
2014-07-10 15:23:26 +00:00
this . _height / tileScale . y ) ;
2014-02-28 09:30:53 +00:00
2014-07-10 15:23:26 +00:00
context . scale ( 1 / tileScale . x , 1 / tileScale . y ) ;
2014-10-22 20:42:03 +00:00
context . translate ( - tilePosition . x + ( this . anchor . x * this . _width ) , - tilePosition . y + ( this . anchor . y * this . _height ) ) ;
2014-02-28 09:30:53 +00:00
2014-07-10 15:23:26 +00:00
if ( this . _mask )
2014-02-28 09:30:53 +00:00
{
renderSession . maskManager . popMask ( renderSession . context ) ;
}
2014-07-01 14:04:03 +00:00
2014-07-10 15:23:26 +00:00
for ( i = 0 , j = this . children . length ; i < j ; i ++ )
2014-07-01 14:04:03 +00:00
{
this . children [ i ] . _renderCanvas ( renderSession ) ;
}
2014-02-28 09:30:53 +00:00
} ;
/ * *
* Returns the framing rectangle of the sprite as a PIXI . Rectangle object
*
* @ method getBounds
* @ return { Rectangle } the framing rectangle
* /
PIXI . TilingSprite . prototype . getBounds = function ( )
{
var width = this . _width ;
var height = this . _height ;
var w0 = width * ( 1 - this . anchor . x ) ;
var w1 = width * - this . anchor . x ;
var h0 = height * ( 1 - this . anchor . y ) ;
var h1 = height * - this . anchor . y ;
var worldTransform = this . worldTransform ;
var a = worldTransform . a ;
2014-11-11 14:31:31 +00:00
var b = worldTransform . b ;
var c = worldTransform . c ;
2014-02-28 09:30:53 +00:00
var d = worldTransform . d ;
var tx = worldTransform . tx ;
var ty = worldTransform . ty ;
2014-04-01 02:02:36 +00:00
2014-02-28 09:30:53 +00:00
var x1 = a * w1 + c * h1 + tx ;
var y1 = d * h1 + b * w1 + ty ;
var x2 = a * w0 + c * h1 + tx ;
var y2 = d * h1 + b * w0 + ty ;
var x3 = a * w0 + c * h0 + tx ;
var y3 = d * h0 + b * w0 + ty ;
var x4 = a * w1 + c * h0 + tx ;
var y4 = d * h0 + b * w1 + ty ;
var maxX = - Infinity ;
var maxY = - Infinity ;
var minX = Infinity ;
var minY = Infinity ;
minX = x1 < minX ? x1 : minX ;
minX = x2 < minX ? x2 : minX ;
minX = x3 < minX ? x3 : minX ;
minX = x4 < minX ? x4 : minX ;
minY = y1 < minY ? y1 : minY ;
minY = y2 < minY ? y2 : minY ;
minY = y3 < minY ? y3 : minY ;
minY = y4 < minY ? y4 : minY ;
maxX = x1 > maxX ? x1 : maxX ;
maxX = x2 > maxX ? x2 : maxX ;
maxX = x3 > maxX ? x3 : maxX ;
maxX = x4 > maxX ? x4 : maxX ;
maxY = y1 > maxY ? y1 : maxY ;
maxY = y2 > maxY ? y2 : maxY ;
maxY = y3 > maxY ? y3 : maxY ;
maxY = y4 > maxY ? y4 : maxY ;
var bounds = this . _bounds ;
bounds . x = minX ;
bounds . width = maxX - minX ;
bounds . y = minY ;
bounds . height = maxY - minY ;
// store a reference so that if this function gets called again in the render cycle we do not have to recalculate
this . _currentBounds = bounds ;
return bounds ;
} ;
2014-07-16 00:58:24 +00:00
/ * *
* When the texture is updated , this event will fire to update the scale and frame
*
* @ method onTextureUpdate
* @ param event
* @ private
* /
PIXI . TilingSprite . prototype . onTextureUpdate = function ( )
{
// overriding the sprite version of this!
} ;
2014-02-28 09:30:53 +00:00
/ * *
2014-04-01 02:02:36 +00:00
*
2014-02-28 09:30:53 +00:00
* @ method generateTilingTexture
2014-04-01 02:02:36 +00:00
*
2014-02-28 09:30:53 +00:00
* @ param forcePowerOfTwo { Boolean } Whether we want to force the texture to be a power of two
* /
PIXI . TilingSprite . prototype . generateTilingTexture = function ( forcePowerOfTwo )
{
2014-07-10 15:23:26 +00:00
if ( ! this . texture . baseTexture . hasLoaded ) return ;
2014-02-28 09:30:53 +00:00
2014-10-22 20:42:03 +00:00
var texture = this . originalTexture || this . texture ;
2014-02-28 09:30:53 +00:00
var frame = texture . frame ;
var targetWidth , targetHeight ;
2014-07-10 15:23:26 +00:00
// Check that the frame is the same size as the base texture.
var isFrame = frame . width !== texture . baseTexture . width || frame . height !== texture . baseTexture . height ;
2014-02-28 09:30:53 +00:00
var newTextureRequired = false ;
2014-07-10 15:23:26 +00:00
if ( ! forcePowerOfTwo )
2014-02-28 09:30:53 +00:00
{
2014-07-10 15:23:26 +00:00
if ( isFrame )
2014-02-28 09:30:53 +00:00
{
2014-02-28 18:55:07 +00:00
targetWidth = frame . width ;
targetHeight = frame . height ;
2014-04-01 02:02:36 +00:00
2014-02-28 09:30:53 +00:00
newTextureRequired = true ;
}
}
else
{
targetWidth = PIXI . getNextPowerOfTwo ( frame . width ) ;
targetHeight = PIXI . getNextPowerOfTwo ( frame . height ) ;
2014-07-01 14:04:03 +00:00
2014-07-10 15:23:26 +00:00
if ( frame . width !== targetWidth || frame . height !== targetHeight ) newTextureRequired = true ;
2014-02-28 09:30:53 +00:00
}
2014-07-10 15:23:26 +00:00
if ( newTextureRequired )
2014-02-28 09:30:53 +00:00
{
var canvasBuffer ;
2014-07-10 15:23:26 +00:00
if ( this . tilingTexture && this . tilingTexture . isTiling )
2014-02-28 09:30:53 +00:00
{
canvasBuffer = this . tilingTexture . canvasBuffer ;
canvasBuffer . resize ( targetWidth , targetHeight ) ;
this . tilingTexture . baseTexture . width = targetWidth ;
this . tilingTexture . baseTexture . height = targetHeight ;
this . tilingTexture . needsUpdate = true ;
}
else
{
canvasBuffer = new PIXI . CanvasBuffer ( targetWidth , targetHeight ) ;
this . tilingTexture = PIXI . Texture . fromCanvas ( canvasBuffer . canvas ) ;
this . tilingTexture . canvasBuffer = canvasBuffer ;
this . tilingTexture . isTiling = true ;
}
2014-07-10 15:23:26 +00:00
2014-02-28 09:30:53 +00:00
canvasBuffer . context . drawImage ( texture . baseTexture . source ,
2014-07-10 15:23:26 +00:00
texture . crop . x ,
texture . crop . y ,
texture . crop . width ,
texture . crop . height ,
0 ,
0 ,
targetWidth ,
targetHeight ) ;
2014-02-28 09:30:53 +00:00
this . tileScaleOffset . x = frame . width / targetWidth ;
this . tileScaleOffset . y = frame . height / targetHeight ;
}
else
{
2014-07-10 15:23:26 +00:00
// TODO - switching?
if ( this . tilingTexture && this . tilingTexture . isTiling )
2014-02-28 09:30:53 +00:00
{
// destroy the tiling texture!
// TODO could store this somewhere?
this . tilingTexture . destroy ( true ) ;
}
this . tileScaleOffset . x = 1 ;
this . tileScaleOffset . y = 1 ;
this . tilingTexture = texture ;
}
2014-07-10 15:23:26 +00:00
2014-02-28 09:30:53 +00:00
this . refreshTexture = false ;
2014-10-22 20:42:03 +00:00
this . originalTexture = this . texture ;
this . texture = this . tilingTexture ;
2014-02-28 09:30:53 +00:00
this . tilingTexture . baseTexture . _powerOf2 = true ;
} ;
2014-08-29 17:13:33 +00:00
2014-02-28 09:30:53 +00:00
/ * *
* @ author Mat Groves http : //matgroves.com/ @Doormat23
* /
PIXI . BaseTextureCache = { } ;
PIXI . BaseTextureCacheIdGenerator = 0 ;
/ * *
2014-10-22 20:42:03 +00:00
* A texture stores the information that represents an image . All textures have a base texture .
2014-02-28 09:30:53 +00:00
*
* @ class BaseTexture
* @ uses EventTarget
* @ constructor
* @ param source { String } the source object ( image or canvas )
2014-11-15 20:04:24 +00:00
* @ param scaleMode { Number } See { { # crossLink "PIXI/scaleModes:property" } } PIXI . scaleModes { { / c r o s s L i n k } } f o r p o s s i b l e v a l u e s
2014-02-28 09:30:53 +00:00
* /
PIXI . BaseTexture = function ( source , scaleMode )
{
2014-10-22 20:42:03 +00:00
/ * *
* The Resolution of the texture .
*
* @ property resolution
* @ type Number
* /
this . resolution = 1 ;
2014-02-28 09:30:53 +00:00
/ * *
* [ read - only ] The width of the base texture set when the image has loaded
*
* @ property width
* @ type Number
* @ readOnly
* /
this . width = 100 ;
/ * *
* [ read - only ] The height of the base texture set when the image has loaded
*
* @ property height
* @ type Number
* @ readOnly
* /
this . height = 100 ;
/ * *
* The scale mode to apply when scaling this texture
2014-10-22 20:42:03 +00:00
*
2014-02-28 09:30:53 +00:00
* @ property scaleMode
2014-11-15 20:04:24 +00:00
* @ type { Number }
2014-02-28 09:30:53 +00:00
* @ default PIXI . scaleModes . LINEAR
* /
this . scaleMode = scaleMode || PIXI . scaleModes . DEFAULT ;
/ * *
2014-10-22 20:42:03 +00:00
* [ read - only ] Set to true once the base texture has loaded
2014-02-28 09:30:53 +00:00
*
* @ property hasLoaded
* @ type Boolean
* @ readOnly
* /
this . hasLoaded = false ;
/ * *
2014-10-22 20:42:03 +00:00
* The image source that is used to create the texture .
2014-02-28 09:30:53 +00:00
*
* @ property source
* @ type Image
* /
this . source = source ;
2014-10-22 20:42:03 +00:00
this . _UID = PIXI . _UID ++ ;
2014-02-28 09:30:53 +00:00
2014-07-01 14:04:03 +00:00
/ * *
2014-10-22 20:42:03 +00:00
* Controls if RGB channels should be pre - multiplied by Alpha ( WebGL only )
2014-07-01 14:04:03 +00:00
*
2014-10-22 20:42:03 +00:00
* @ property premultipliedAlpha
2014-07-01 14:04:03 +00:00
* @ type Boolean
2014-10-22 20:42:03 +00:00
* @ default true
* /
2014-07-01 14:04:03 +00:00
this . premultipliedAlpha = true ;
2014-02-28 09:30:53 +00:00
// used for webGL
2014-10-22 20:42:03 +00:00
/ * *
* @ property _glTextures
* @ type Array
* @ private
* /
2014-02-28 09:30:53 +00:00
this . _glTextures = [ ] ;
2014-08-29 17:13:33 +00:00
2014-10-22 20:42:03 +00:00
// used for webGL texture updating...
// TODO - this needs to be addressed
/ * *
* @ property _dirty
* @ type Array
* @ private
* /
this . _dirty = [ true , true , true , true ] ;
2014-08-29 17:13:33 +00:00
2014-02-28 09:30:53 +00:00
if ( ! source ) return ;
2014-04-29 14:39:53 +00:00
if ( ( this . source . complete || this . source . getContext ) && this . source . width && this . source . height )
2014-02-28 09:30:53 +00:00
{
this . hasLoaded = true ;
2014-10-22 20:42:03 +00:00
this . width = this . source . naturalWidth || this . source . width ;
this . height = this . source . naturalHeight || this . source . height ;
this . dirty ( ) ;
2014-02-28 09:30:53 +00:00
}
else
{
var scope = this ;
2014-10-22 20:42:03 +00:00
2014-02-28 09:30:53 +00:00
this . source . onload = function ( ) {
scope . hasLoaded = true ;
2014-10-22 20:42:03 +00:00
scope . width = scope . source . naturalWidth || scope . source . width ;
scope . height = scope . source . naturalHeight || scope . source . height ;
2014-02-28 09:30:53 +00:00
2014-10-22 20:42:03 +00:00
scope . dirty ( ) ;
2014-07-01 14:04:03 +00:00
2014-02-28 09:30:53 +00:00
// add it to somewhere...
scope . dispatchEvent ( { type : 'loaded' , content : scope } ) ;
} ;
2014-10-22 20:42:03 +00:00
2014-07-01 14:04:03 +00:00
this . source . onerror = function ( ) {
scope . dispatchEvent ( { type : 'error' , content : scope } ) ;
} ;
2014-02-28 09:30:53 +00:00
}
2014-10-22 20:42:03 +00:00
/ * *
* @ property imageUrl
* @ type String
* /
2014-02-28 09:30:53 +00:00
this . imageUrl = null ;
2014-08-29 17:13:33 +00:00
2014-10-22 20:42:03 +00:00
/ * *
* @ property _powerOf2
* @ type Boolean
* @ private
* /
this . _powerOf2 = false ;
2014-02-28 09:30:53 +00:00
} ;
PIXI . BaseTexture . prototype . constructor = PIXI . BaseTexture ;
2014-10-22 20:42:03 +00:00
PIXI . EventTarget . mixin ( PIXI . BaseTexture . prototype ) ;
2014-02-28 09:30:53 +00:00
/ * *
* Destroys this base texture
*
* @ method destroy
* /
PIXI . BaseTexture . prototype . destroy = function ( )
{
if ( this . imageUrl )
{
delete PIXI . BaseTextureCache [ this . imageUrl ] ;
2014-07-01 14:04:03 +00:00
delete PIXI . TextureCache [ this . imageUrl ] ;
2014-02-28 09:30:53 +00:00
this . imageUrl = null ;
2014-11-11 01:10:47 +00:00
if ( ! navigator . isCocoonJS ) this . source . src = '' ;
2014-02-28 09:30:53 +00:00
}
2014-07-01 14:04:03 +00:00
else if ( this . source && this . source . _pixiId )
{
delete PIXI . BaseTextureCache [ this . source . _pixiId ] ;
}
2014-02-28 09:30:53 +00:00
this . source = null ;
2014-10-22 20:42:03 +00:00
2014-11-08 19:26:34 +00:00
this . unloadFromGPU ( ) ;
2014-02-28 09:30:53 +00:00
} ;
/ * *
* Changes the source image of the texture
*
* @ method updateSourceImage
* @ param newSrc { String } the path of the image
* /
PIXI . BaseTexture . prototype . updateSourceImage = function ( newSrc )
{
this . hasLoaded = false ;
this . source . src = null ;
this . source . src = newSrc ;
} ;
/ * *
2014-10-22 20:42:03 +00:00
* Sets all glTextures to be dirty .
*
* @ method dirty
* /
PIXI . BaseTexture . prototype . dirty = function ( )
{
for ( var i = 0 ; i < this . _glTextures . length ; i ++ )
{
this . _dirty [ i ] = true ;
}
} ;
2014-11-08 19:26:34 +00:00
/ * *
* Removes the base texture from the GPU , useful for managing resources on the GPU .
* Atexture is still 100 % usable and will simply be reuploaded if there is a sprite on screen that is using it .
*
* @ method unloadFromGPU
* /
PIXI . BaseTexture . prototype . unloadFromGPU = function ( )
{
this . dirty ( ) ;
// delete the webGL textures if any.
for ( var i = this . _glTextures . length - 1 ; i >= 0 ; i -- )
{
var glTexture = this . _glTextures [ i ] ;
var gl = PIXI . glContexts [ i ] ;
if ( gl && glTexture )
{
gl . deleteTexture ( glTexture ) ;
}
}
this . _glTextures . length = 0 ;
this . dirty ( ) ;
} ;
2014-10-22 20:42:03 +00:00
/ * *
* Helper function that creates a base texture from the given image url .
* If the image is not in the base texture cache it will be created and loaded .
2014-02-28 09:30:53 +00:00
*
* @ static
* @ method fromImage
* @ param imageUrl { String } The image url of the texture
2014-08-29 17:13:33 +00:00
* @ param crossorigin { Boolean }
2014-11-15 20:04:24 +00:00
* @ param scaleMode { Number } See { { # crossLink "PIXI/scaleModes:property" } } PIXI . scaleModes { { / c r o s s L i n k } } f o r p o s s i b l e v a l u e s
2014-02-28 09:30:53 +00:00
* @ return BaseTexture
* /
PIXI . BaseTexture . fromImage = function ( imageUrl , crossorigin , scaleMode )
{
var baseTexture = PIXI . BaseTextureCache [ imageUrl ] ;
2014-08-29 17:13:33 +00:00
2014-04-29 14:39:53 +00:00
if ( crossorigin === undefined && imageUrl . indexOf ( 'data:' ) === - 1 ) crossorigin = true ;
2014-02-28 09:30:53 +00:00
if ( ! baseTexture )
{
// new Image() breaks tex loading in some versions of Chrome.
// See https://code.google.com/p/chromium/issues/detail?id=238071
var image = new Image ( ) ; //document.createElement('img');
if ( crossorigin )
{
image . crossOrigin = '' ;
}
2014-10-22 20:42:03 +00:00
2014-02-28 09:30:53 +00:00
image . src = imageUrl ;
baseTexture = new PIXI . BaseTexture ( image , scaleMode ) ;
baseTexture . imageUrl = imageUrl ;
PIXI . BaseTextureCache [ imageUrl ] = baseTexture ;
2014-10-22 20:42:03 +00:00
// if there is an @2x at the end of the url we are going to assume its a highres image
if ( imageUrl . indexOf ( PIXI . RETINA _PREFIX + '.' ) !== - 1 )
{
baseTexture . resolution = 2 ;
}
2014-02-28 09:30:53 +00:00
}
return baseTexture ;
} ;
2014-07-10 19:18:20 +00:00
/ * *
2014-10-22 20:42:03 +00:00
* Helper function that creates a base texture from the given canvas element .
2014-07-10 19:18:20 +00:00
*
* @ static
* @ method fromCanvas
* @ param canvas { Canvas } The canvas element source of the texture
2014-11-15 20:04:24 +00:00
* @ param scaleMode { Number } See { { # crossLink "PIXI/scaleModes:property" } } PIXI . scaleModes { { / c r o s s L i n k } } f o r p o s s i b l e v a l u e s
2014-07-10 19:18:20 +00:00
* @ return BaseTexture
* /
2014-02-28 09:30:53 +00:00
PIXI . BaseTexture . fromCanvas = function ( canvas , scaleMode )
{
if ( ! canvas . _pixiId )
{
canvas . _pixiId = 'canvas_' + PIXI . TextureCacheIdGenerator ++ ;
}
var baseTexture = PIXI . BaseTextureCache [ canvas . _pixiId ] ;
if ( ! baseTexture )
{
baseTexture = new PIXI . BaseTexture ( canvas , scaleMode ) ;
PIXI . BaseTextureCache [ canvas . _pixiId ] = baseTexture ;
}
return baseTexture ;
} ;
/ * *
* @ author Mat Groves http : //matgroves.com/ @Doormat23
* /
PIXI . TextureCache = { } ;
PIXI . FrameCache = { } ;
PIXI . TextureCacheIdGenerator = 0 ;
/ * *
* A texture stores the information that represents an image or part of an image . It cannot be added
2014-10-22 20:42:03 +00:00
* to the display list directly . Instead use it as the texture for a PIXI . Sprite . If no frame is provided then the whole image is used .
2014-02-28 09:30:53 +00:00
*
* @ class Texture
* @ uses EventTarget
* @ constructor
* @ param baseTexture { BaseTexture } The base texture source to create the texture from
* @ param frame { Rectangle } The rectangle frame of the texture to show
2014-10-22 20:42:03 +00:00
* @ param [ crop ] { Rectangle } The area of original texture
* @ param [ trim ] { Rectangle } Trimmed texture rectangle
2014-02-28 09:30:53 +00:00
* /
2014-10-22 20:42:03 +00:00
PIXI . Texture = function ( baseTexture , frame , crop , trim )
2014-02-28 09:30:53 +00:00
{
2014-07-10 15:23:26 +00:00
/ * *
* Does this Texture have any frame data assigned to it ?
*
* @ property noFrame
* @ type Boolean
* /
this . noFrame = false ;
if ( ! frame )
2014-02-28 09:30:53 +00:00
{
this . noFrame = true ;
frame = new PIXI . Rectangle ( 0 , 0 , 1 , 1 ) ;
}
2014-07-10 15:23:26 +00:00
if ( baseTexture instanceof PIXI . Texture )
{
2014-02-28 09:30:53 +00:00
baseTexture = baseTexture . baseTexture ;
2014-07-10 15:23:26 +00:00
}
2014-02-28 09:30:53 +00:00
/ * *
2014-07-10 15:23:26 +00:00
* The base texture that this texture uses .
2014-02-28 09:30:53 +00:00
*
* @ property baseTexture
* @ type BaseTexture
* /
this . baseTexture = baseTexture ;
/ * *
* The frame specifies the region of the base texture that this texture uses
*
* @ property frame
* @ type Rectangle
* /
this . frame = frame ;
/ * *
2014-10-22 20:42:03 +00:00
* The texture trim data .
2014-02-28 09:30:53 +00:00
*
* @ property trim
* @ type Rectangle
* /
2014-10-22 20:42:03 +00:00
this . trim = trim ;
2014-08-29 17:13:33 +00:00
2014-07-01 14:04:03 +00:00
/ * *
2014-10-22 20:42:03 +00:00
* This will let the renderer know if the texture is valid . If it ' s not then it cannot be rendered .
2014-07-01 14:04:03 +00:00
*
* @ property valid
* @ type Boolean
* /
this . valid = false ;
2014-10-22 20:42:03 +00:00
/ * *
* This will let a renderer know that a texture has been updated ( used mainly for webGL uv updates )
*
* @ property requiresUpdate
* @ type Boolean
* /
this . requiresUpdate = false ;
2014-07-10 15:23:26 +00:00
/ * *
* The WebGL UV data cache .
*
* @ property _uvs
* @ type Object
2014-10-22 20:42:03 +00:00
* @ private
2014-07-10 15:23:26 +00:00
* /
2014-02-28 09:30:53 +00:00
this . _uvs = null ;
2014-08-29 17:13:33 +00:00
2014-07-10 15:23:26 +00:00
/ * *
* The width of the Texture in pixels .
*
* @ property width
* @ type Number
* /
this . width = 0 ;
/ * *
* The height of the Texture in pixels .
*
* @ property height
* @ type Number
* /
this . height = 0 ;
/ * *
* This is the area of the BaseTexture image to actually copy to the Canvas / WebGL when rendering ,
* irrespective of the actual frame size or placement ( which can be influenced by trimmed texture atlases )
*
* @ property crop
* @ type Rectangle
* /
2014-10-22 20:42:03 +00:00
this . crop = crop || new PIXI . Rectangle ( 0 , 0 , 1 , 1 ) ;
2014-07-10 15:23:26 +00:00
if ( baseTexture . hasLoaded )
2014-02-28 09:30:53 +00:00
{
2014-07-10 15:23:26 +00:00
if ( this . noFrame ) frame = new PIXI . Rectangle ( 0 , 0 , baseTexture . width , baseTexture . height ) ;
2014-02-28 09:30:53 +00:00
this . setFrame ( frame ) ;
}
else
{
2014-08-29 17:13:33 +00:00
baseTexture . addEventListener ( 'loaded' , this . onBaseTextureLoaded . bind ( this ) ) ;
2014-02-28 09:30:53 +00:00
}
} ;
PIXI . Texture . prototype . constructor = PIXI . Texture ;
2014-10-22 20:42:03 +00:00
PIXI . EventTarget . mixin ( PIXI . Texture . prototype ) ;
2014-02-28 09:30:53 +00:00
/ * *
* Called when the base texture is loaded
*
* @ method onBaseTextureLoaded
* @ private
* /
PIXI . Texture . prototype . onBaseTextureLoaded = function ( )
{
var baseTexture = this . baseTexture ;
2014-07-10 15:23:26 +00:00
baseTexture . removeEventListener ( 'loaded' , this . onLoaded ) ;
2014-02-28 09:30:53 +00:00
2014-07-10 15:23:26 +00:00
if ( this . noFrame ) this . frame = new PIXI . Rectangle ( 0 , 0 , baseTexture . width , baseTexture . height ) ;
2014-08-29 17:13:33 +00:00
2014-02-28 09:30:53 +00:00
this . setFrame ( this . frame ) ;
2014-08-29 17:13:33 +00:00
this . dispatchEvent ( { type : 'update' , content : this } ) ;
2014-02-28 09:30:53 +00:00
} ;
/ * *
* Destroys this texture
*
* @ method destroy
* @ param destroyBase { Boolean } Whether to destroy the base texture as well
* /
PIXI . Texture . prototype . destroy = function ( destroyBase )
{
2014-07-10 15:23:26 +00:00
if ( destroyBase ) this . baseTexture . destroy ( ) ;
2014-07-01 14:04:03 +00:00
this . valid = false ;
2014-02-28 09:30:53 +00:00
} ;
/ * *
2014-07-10 15:23:26 +00:00
* Specifies the region of the baseTexture that this texture will use .
2014-02-28 09:30:53 +00:00
*
* @ method setFrame
* @ param frame { Rectangle } The frame of the texture to set it to
* /
PIXI . Texture . prototype . setFrame = function ( frame )
{
2014-07-10 15:23:26 +00:00
this . noFrame = false ;
2014-02-28 09:30:53 +00:00
this . frame = frame ;
this . width = frame . width ;
this . height = frame . height ;
2014-07-10 15:23:26 +00:00
this . crop . x = frame . x ;
this . crop . y = frame . y ;
this . crop . width = frame . width ;
this . crop . height = frame . height ;
if ( ! this . trim && ( frame . x + frame . width > this . baseTexture . width || frame . y + frame . height > this . baseTexture . height ) )
2014-02-28 09:30:53 +00:00
{
throw new Error ( 'Texture Error: frame does not fit inside the base Texture dimensions ' + this ) ;
}
2014-07-01 14:04:03 +00:00
this . valid = frame && frame . width && frame . height && this . baseTexture . source && this . baseTexture . hasLoaded ;
2014-02-28 09:30:53 +00:00
2014-07-10 15:23:26 +00:00
if ( this . trim )
{
this . width = this . trim . width ;
this . height = this . trim . height ;
this . frame . width = this . trim . width ;
this . frame . height = this . trim . height ;
}
2014-10-22 20:42:03 +00:00
if ( this . valid ) this . _updateUvs ( ) ;
2014-02-28 09:30:53 +00:00
2014-07-10 15:23:26 +00:00
} ;
2014-07-01 14:04:03 +00:00
2014-07-10 15:23:26 +00:00
/ * *
* Updates the internal WebGL UV cache .
*
2014-10-22 20:42:03 +00:00
* @ method _updateUvs
2014-07-10 15:23:26 +00:00
* @ private
* /
2014-10-22 20:42:03 +00:00
PIXI . Texture . prototype . _updateUvs = function ( )
2014-02-28 09:30:53 +00:00
{
if ( ! this . _uvs ) this . _uvs = new PIXI . TextureUvs ( ) ;
2014-07-10 15:23:26 +00:00
var frame = this . crop ;
2014-02-28 09:30:53 +00:00
var tw = this . baseTexture . width ;
var th = this . baseTexture . height ;
2014-10-22 20:42:03 +00:00
2014-02-28 09:30:53 +00:00
this . _uvs . x0 = frame . x / tw ;
this . _uvs . y0 = frame . y / th ;
this . _uvs . x1 = ( frame . x + frame . width ) / tw ;
this . _uvs . y1 = frame . y / th ;
this . _uvs . x2 = ( frame . x + frame . width ) / tw ;
this . _uvs . y2 = ( frame . y + frame . height ) / th ;
this . _uvs . x3 = frame . x / tw ;
this . _uvs . y3 = ( frame . y + frame . height ) / th ;
} ;
/ * *
2014-10-22 20:42:03 +00:00
* Helper function that creates a Texture object from the given image url .
* If the image is not in the texture cache it will be created and loaded .
2014-02-28 09:30:53 +00:00
*
* @ static
* @ method fromImage
* @ param imageUrl { String } The image url of the texture
* @ param crossorigin { Boolean } Whether requests should be treated as crossorigin
2014-11-15 20:04:24 +00:00
* @ param scaleMode { Number } See { { # crossLink "PIXI/scaleModes:property" } } PIXI . scaleModes { { / c r o s s L i n k } } f o r p o s s i b l e v a l u e s
2014-02-28 09:30:53 +00:00
* @ return Texture
* /
PIXI . Texture . fromImage = function ( imageUrl , crossorigin , scaleMode )
{
var texture = PIXI . TextureCache [ imageUrl ] ;
if ( ! texture )
{
texture = new PIXI . Texture ( PIXI . BaseTexture . fromImage ( imageUrl , crossorigin , scaleMode ) ) ;
PIXI . TextureCache [ imageUrl ] = texture ;
}
return texture ;
} ;
/ * *
2014-10-22 20:42:03 +00:00
* Helper function that returns a Texture objected based on the given frame id .
* If the frame id is not in the texture cache an error will be thrown .
2014-02-28 09:30:53 +00:00
*
* @ static
* @ method fromFrame
* @ param frameId { String } The frame id of the texture
* @ return Texture
* /
PIXI . Texture . fromFrame = function ( frameId )
{
var texture = PIXI . TextureCache [ frameId ] ;
if ( ! texture ) throw new Error ( 'The frameId "' + frameId + '" does not exist in the texture cache ' ) ;
return texture ;
} ;
/ * *
2014-10-22 20:42:03 +00:00
* Helper function that creates a new a Texture based on the given canvas element .
2014-02-28 09:30:53 +00:00
*
* @ static
* @ method fromCanvas
* @ param canvas { Canvas } The canvas element source of the texture
2014-11-15 20:04:24 +00:00
* @ param scaleMode { Number } See { { # crossLink "PIXI/scaleModes:property" } } PIXI . scaleModes { { / c r o s s L i n k } } f o r p o s s i b l e v a l u e s
2014-02-28 09:30:53 +00:00
* @ return Texture
* /
PIXI . Texture . fromCanvas = function ( canvas , scaleMode )
{
var baseTexture = PIXI . BaseTexture . fromCanvas ( canvas , scaleMode ) ;
return new PIXI . Texture ( baseTexture ) ;
} ;
/ * *
2014-10-22 20:42:03 +00:00
* Adds a texture to the global PIXI . TextureCache . This cache is shared across the whole PIXI object .
2014-02-28 09:30:53 +00:00
*
* @ static
* @ method addTextureToCache
2014-10-22 20:42:03 +00:00
* @ param texture { Texture } The Texture to add to the cache .
* @ param id { String } The id that the texture will be stored against .
2014-02-28 09:30:53 +00:00
* /
PIXI . Texture . addTextureToCache = function ( texture , id )
{
PIXI . TextureCache [ id ] = texture ;
} ;
/ * *
2014-10-22 20:42:03 +00:00
* Remove a texture from the global PIXI . TextureCache .
2014-02-28 09:30:53 +00:00
*
* @ static
* @ method removeTextureFromCache
2014-10-22 20:42:03 +00:00
* @ param id { String } The id of the texture to be removed
* @ return { Texture } The texture that was removed
2014-02-28 09:30:53 +00:00
* /
PIXI . Texture . removeTextureFromCache = function ( id )
{
var texture = PIXI . TextureCache [ id ] ;
delete PIXI . TextureCache [ id ] ;
delete PIXI . BaseTextureCache [ id ] ;
return texture ;
} ;
PIXI . TextureUvs = function ( )
{
this . x0 = 0 ;
this . y0 = 0 ;
this . x1 = 0 ;
this . y1 = 0 ;
this . x2 = 0 ;
this . y2 = 0 ;
this . x3 = 0 ;
2014-07-10 15:23:26 +00:00
this . y3 = 0 ;
2014-02-28 09:30:53 +00:00
} ;
2014-11-12 22:49:36 +00:00
PIXI . Texture . emptyTexture = new PIXI . Texture ( new PIXI . BaseTexture ( ) ) ;
2014-02-28 09:30:53 +00:00
/ * *
* @ author Mat Groves http : //matgroves.com/ @Doormat23
* /
/ * *
2014-10-22 20:42:03 +00:00
* A RenderTexture is a special texture that allows any Pixi display object to be rendered to it .
*
* _ _Hint _ _ : All DisplayObjects ( i . e . Sprites ) that render to a RenderTexture should be preloaded otherwise black rectangles will be drawn instead .
*
* A RenderTexture takes a snapshot of any Display Object given to its render method . The position and rotation of the given Display Objects is ignored . For example :
*
* var renderTexture = new PIXI . RenderTexture ( 800 , 600 ) ;
* var sprite = PIXI . Sprite . fromImage ( "spinObj_01.png" ) ;
* sprite . position . x = 800 / 2 ;
* sprite . position . y = 600 / 2 ;
* sprite . anchor . x = 0.5 ;
* sprite . anchor . y = 0.5 ;
* renderTexture . render ( sprite ) ;
*
* The Sprite in this case will be rendered to a position of 0 , 0. To render this sprite at its actual position a DisplayObjectContainer should be used :
*
* var doc = new PIXI . DisplayObjectContainer ( ) ;
* doc . addChild ( sprite ) ;
* renderTexture . render ( doc ) ; // Renders to center of renderTexture
*
2014-02-28 09:30:53 +00:00
* @ class RenderTexture
* @ extends Texture
* @ constructor
* @ param width { Number } The width of the render texture
* @ param height { Number } The height of the render texture
2014-10-22 20:42:03 +00:00
* @ param renderer { CanvasRenderer | WebGLRenderer } The renderer used for this RenderTexture
2014-11-15 20:04:24 +00:00
* @ param scaleMode { Number } See { { # crossLink "PIXI/scaleModes:property" } } PIXI . scaleModes { { / c r o s s L i n k } } f o r p o s s i b l e v a l u e s
2014-10-22 20:42:03 +00:00
* @ param resolution { Number } The resolution of the texture being generated
2014-02-28 09:30:53 +00:00
* /
2014-10-22 20:42:03 +00:00
PIXI . RenderTexture = function ( width , height , renderer , scaleMode , resolution )
2014-02-28 09:30:53 +00:00
{
/ * *
* The with of the render texture
*
* @ property width
* @ type Number
* /
this . width = width || 100 ;
2014-10-22 20:42:03 +00:00
2014-02-28 09:30:53 +00:00
/ * *
* The height of the render texture
*
* @ property height
* @ type Number
* /
this . height = height || 100 ;
2014-10-22 20:42:03 +00:00
/ * *
* The Resolution of the texture .
*
* @ property resolution
* @ type Number
* /
this . resolution = resolution || 1 ;
2014-02-28 09:30:53 +00:00
/ * *
* The framing rectangle of the render texture
*
* @ property frame
* @ type Rectangle
* /
2014-10-22 20:42:03 +00:00
this . frame = new PIXI . Rectangle ( 0 , 0 , this . width * this . resolution , this . height * this . resolution ) ;
2014-02-28 09:30:53 +00:00
2014-07-10 15:23:26 +00:00
/ * *
* This is the area of the BaseTexture image to actually copy to the Canvas / WebGL when rendering ,
* irrespective of the actual frame size or placement ( which can be influenced by trimmed texture atlases )
*
* @ property crop
* @ type Rectangle
* /
2014-10-22 20:42:03 +00:00
this . crop = new PIXI . Rectangle ( 0 , 0 , this . width * this . resolution , this . height * this . resolution ) ;
2014-02-28 09:30:53 +00:00
/ * *
* The base texture object that this texture uses
*
* @ property baseTexture
* @ type BaseTexture
* /
this . baseTexture = new PIXI . BaseTexture ( ) ;
2014-10-22 20:42:03 +00:00
this . baseTexture . width = this . width * this . resolution ;
this . baseTexture . height = this . height * this . resolution ;
2014-02-28 09:30:53 +00:00
this . baseTexture . _glTextures = [ ] ;
2014-10-22 20:42:03 +00:00
this . baseTexture . resolution = this . resolution ;
2014-02-28 09:30:53 +00:00
2014-04-29 14:39:53 +00:00
this . baseTexture . scaleMode = scaleMode || PIXI . scaleModes . DEFAULT ;
2014-02-28 09:30:53 +00:00
this . baseTexture . hasLoaded = true ;
2014-10-22 20:42:03 +00:00
PIXI . Texture . call ( this ,
this . baseTexture ,
new PIXI . Rectangle ( 0 , 0 , this . width , this . height )
) ;
/ * *
* The renderer this RenderTexture uses . A RenderTexture can only belong to one renderer at the moment if its webGL .
*
* @ property renderer
* @ type CanvasRenderer | WebGLRenderer
* /
2014-02-28 09:30:53 +00:00
this . renderer = renderer || PIXI . defaultRenderer ;
if ( this . renderer . type === PIXI . WEBGL _RENDERER )
{
var gl = this . renderer . gl ;
2014-10-22 20:42:03 +00:00
this . baseTexture . _dirty [ gl . id ] = false ;
2014-02-28 09:30:53 +00:00
2014-10-22 20:42:03 +00:00
this . textureBuffer = new PIXI . FilterTexture ( gl , this . width * this . resolution , this . height * this . resolution , this . baseTexture . scaleMode ) ;
2014-02-28 09:30:53 +00:00
this . baseTexture . _glTextures [ gl . id ] = this . textureBuffer . texture ;
this . render = this . renderWebGL ;
2014-10-22 20:42:03 +00:00
this . projection = new PIXI . Point ( this . width * 0.5 , - this . height * 0.5 ) ;
2014-02-28 09:30:53 +00:00
}
else
{
this . render = this . renderCanvas ;
2014-10-22 20:42:03 +00:00
this . textureBuffer = new PIXI . CanvasBuffer ( this . width * this . resolution , this . height * this . resolution ) ;
2014-02-28 09:30:53 +00:00
this . baseTexture . source = this . textureBuffer . canvas ;
}
2014-10-22 20:42:03 +00:00
/ * *
* @ property valid
* @ type Boolean
* /
2014-07-11 17:03:43 +00:00
this . valid = true ;
2014-02-28 09:30:53 +00:00
2014-10-22 20:42:03 +00:00
this . _updateUvs ( ) ;
2014-02-28 09:30:53 +00:00
} ;
PIXI . RenderTexture . prototype = Object . create ( PIXI . Texture . prototype ) ;
PIXI . RenderTexture . prototype . constructor = PIXI . RenderTexture ;
2014-05-20 09:02:23 +00:00
/ * *
2014-10-22 20:42:03 +00:00
* Resizes the RenderTexture .
2014-05-20 09:02:23 +00:00
*
* @ method resize
* @ param width { Number } The width to resize to .
* @ param height { Number } The height to resize to .
* @ param updateBase { Boolean } Should the baseTexture . width and height values be resized as well ?
* /
PIXI . RenderTexture . prototype . resize = function ( width , height , updateBase )
2014-02-28 09:30:53 +00:00
{
2014-10-22 20:42:03 +00:00
if ( width === this . width && height === this . height ) return ;
2014-05-20 09:02:23 +00:00
2014-08-29 17:13:33 +00:00
this . valid = ( width > 0 && height > 0 ) ;
2014-07-11 17:03:43 +00:00
this . width = this . frame . width = this . crop . width = width ;
this . height = this . frame . height = this . crop . height = height ;
2014-02-28 09:30:53 +00:00
2014-05-20 09:02:23 +00:00
if ( updateBase )
{
this . baseTexture . width = this . width ;
this . baseTexture . height = this . height ;
}
if ( this . renderer . type === PIXI . WEBGL _RENDERER )
2014-02-28 09:30:53 +00:00
{
this . projection . x = this . width / 2 ;
this . projection . y = - this . height / 2 ;
}
2014-10-22 20:42:03 +00:00
2014-08-29 17:13:33 +00:00
if ( ! this . valid ) return ;
2014-10-22 20:42:03 +00:00
this . textureBuffer . resize ( this . width * this . resolution , this . height * this . resolution ) ;
2014-05-20 09:02:23 +00:00
} ;
/ * *
* Clears the RenderTexture .
*
* @ method clear
* /
PIXI . RenderTexture . prototype . clear = function ( )
{
2014-08-29 17:13:33 +00:00
if ( ! this . valid ) return ;
2014-05-20 09:02:23 +00:00
if ( this . renderer . type === PIXI . WEBGL _RENDERER )
2014-02-28 09:30:53 +00:00
{
2014-05-20 09:02:23 +00:00
this . renderer . gl . bindFramebuffer ( this . renderer . gl . FRAMEBUFFER , this . textureBuffer . frameBuffer ) ;
2014-02-28 09:30:53 +00:00
}
2014-10-22 20:42:03 +00:00
2014-05-20 09:02:23 +00:00
this . textureBuffer . clear ( ) ;
2014-02-28 09:30:53 +00:00
} ;
/ * *
* This function will draw the display object to the texture .
*
* @ method renderWebGL
* @ param displayObject { DisplayObject } The display object to render this texture on
2014-10-22 20:42:03 +00:00
* @ param [ matrix ] { Matrix } Optional matrix to apply to the display object before rendering .
* @ param [ clear ] { Boolean } If true the texture will be cleared before the displayObject is drawn
2014-02-28 09:30:53 +00:00
* @ private
* /
2014-10-22 20:42:03 +00:00
PIXI . RenderTexture . prototype . renderWebGL = function ( displayObject , matrix , clear )
2014-02-28 09:30:53 +00:00
{
2014-08-29 17:13:33 +00:00
if ( ! this . valid ) return ;
2014-02-28 09:30:53 +00:00
//TOOD replace position with matrix..
2014-10-22 20:42:03 +00:00
//Lets create a nice matrix to apply to our display object. Frame buffers come in upside down so we need to flip the matrix
var wt = displayObject . worldTransform ;
wt . identity ( ) ;
wt . translate ( 0 , this . projection . y * 2 ) ;
if ( matrix ) wt . append ( matrix ) ;
wt . scale ( 1 , - 1 ) ;
2014-02-28 09:30:53 +00:00
2014-10-22 20:42:03 +00:00
// setWorld Alpha to ensure that the object is renderer at full opacity
displayObject . worldAlpha = 1 ;
2014-07-10 15:23:26 +00:00
2014-10-22 20:42:03 +00:00
// Time to update all the children of the displayObject with the new matrix..
2014-02-28 09:30:53 +00:00
var children = displayObject . children ;
for ( var i = 0 , j = children . length ; i < j ; i ++ )
{
children [ i ] . updateTransform ( ) ;
}
2014-10-22 20:42:03 +00:00
// time for the webGL fun stuff!
var gl = this . renderer . gl ;
gl . viewport ( 0 , 0 , this . width * this . resolution , this . height * this . resolution ) ;
gl . bindFramebuffer ( gl . FRAMEBUFFER , this . textureBuffer . frameBuffer ) ;
2014-02-28 09:30:53 +00:00
2014-10-22 20:42:03 +00:00
if ( clear ) this . textureBuffer . clear ( ) ;
2014-02-28 09:30:53 +00:00
2014-07-10 15:23:26 +00:00
this . renderer . spriteBatch . dirty = true ;
2014-02-28 09:30:53 +00:00
2014-10-22 20:42:03 +00:00
this . renderer . renderDisplayObject ( displayObject , this . projection , this . textureBuffer . frameBuffer ) ;
2014-07-10 15:23:26 +00:00
this . renderer . spriteBatch . dirty = true ;
2014-02-28 09:30:53 +00:00
} ;
/ * *
* This function will draw the display object to the texture .
*
* @ method renderCanvas
* @ param displayObject { DisplayObject } The display object to render this texture on
2014-10-22 20:42:03 +00:00
* @ param [ matrix ] { Matrix } Optional matrix to apply to the display object before rendering .
* @ param [ clear ] { Boolean } If true the texture will be cleared before the displayObject is drawn
2014-02-28 09:30:53 +00:00
* @ private
* /
2014-10-22 20:42:03 +00:00
PIXI . RenderTexture . prototype . renderCanvas = function ( displayObject , matrix , clear )
2014-02-28 09:30:53 +00:00
{
2014-08-29 17:13:33 +00:00
if ( ! this . valid ) return ;
2014-10-22 20:42:03 +00:00
var wt = displayObject . worldTransform ;
wt . identity ( ) ;
if ( matrix ) wt . append ( matrix ) ;
2014-11-08 19:26:34 +00:00
// setWorld Alpha to ensure that the object is renderer at full opacity
displayObject . worldAlpha = 1 ;
2014-02-28 09:30:53 +00:00
2014-10-22 20:42:03 +00:00
// Time to update all the children of the displayObject with the new matrix..
var children = displayObject . children ;
2014-02-28 09:30:53 +00:00
for ( var i = 0 , j = children . length ; i < j ; i ++ )
{
children [ i ] . updateTransform ( ) ;
}
if ( clear ) this . textureBuffer . clear ( ) ;
var context = this . textureBuffer . context ;
2014-10-22 20:42:03 +00:00
var realResolution = this . renderer . resolution ;
2014-02-28 09:30:53 +00:00
2014-10-22 20:42:03 +00:00
this . renderer . resolution = this . resolution ;
this . renderer . renderDisplayObject ( displayObject , context ) ;
2014-02-28 09:30:53 +00:00
2014-10-22 20:42:03 +00:00
this . renderer . resolution = realResolution ;
2014-02-28 09:30:53 +00:00
} ;
2014-08-29 17:13:33 +00:00
/ * *
* Will return a HTML Image of the texture
*
* @ method getImage
2014-10-22 20:42:03 +00:00
* @ return { Image }
2014-08-29 17:13:33 +00:00
* /
PIXI . RenderTexture . prototype . getImage = function ( )
{
var image = new Image ( ) ;
image . src = this . getBase64 ( ) ;
return image ;
} ;
/ * *
2014-10-22 20:42:03 +00:00
* Will return a a base64 encoded string of this texture . It works by calling RenderTexture . getCanvas and then running toDataURL on that .
2014-08-29 17:13:33 +00:00
*
2014-10-22 20:42:03 +00:00
* @ method getBase64
* @ return { String } A base64 encoded string of the texture .
2014-08-29 17:13:33 +00:00
* /
PIXI . RenderTexture . prototype . getBase64 = function ( )
{
return this . getCanvas ( ) . toDataURL ( ) ;
} ;
2014-10-22 20:42:03 +00:00
/ * *
* Creates a Canvas element , renders this RenderTexture to it and then returns it .
*
* @ method getCanvas
* @ return { HTMLCanvasElement } A Canvas element with the texture rendered on .
* /
2014-08-29 17:13:33 +00:00
PIXI . RenderTexture . prototype . getCanvas = function ( )
{
if ( this . renderer . type === PIXI . WEBGL _RENDERER )
{
var gl = this . renderer . gl ;
var width = this . textureBuffer . width ;
var height = this . textureBuffer . height ;
var webGLPixels = new Uint8Array ( 4 * width * height ) ;
gl . bindFramebuffer ( gl . FRAMEBUFFER , this . textureBuffer . frameBuffer ) ;
gl . readPixels ( 0 , 0 , width , height , gl . RGBA , gl . UNSIGNED _BYTE , webGLPixels ) ;
gl . bindFramebuffer ( gl . FRAMEBUFFER , null ) ;
var tempCanvas = new PIXI . CanvasBuffer ( width , height ) ;
var canvasData = tempCanvas . context . getImageData ( 0 , 0 , width , height ) ;
2014-11-11 01:10:47 +00:00
canvasData . data . set ( webGLPixels ) ;
2014-08-29 17:13:33 +00:00
tempCanvas . context . putImageData ( canvasData , 0 , 0 ) ;
2014-10-22 20:42:03 +00:00
2014-08-29 17:13:33 +00:00
return tempCanvas . canvas ;
}
else
{
return this . textureBuffer . canvas ;
}
} ;
2014-02-28 09:30:53 +00:00
PIXI . RenderTexture . tempMatrix = new PIXI . Matrix ( ) ;
2014-10-22 20:42:03 +00:00
/ * *
* @ author Mat Groves http : //matgroves.com/ @Doormat23
* /
/ * *
* This is the base class for creating a PIXI filter . Currently only webGL supports filters .
* If you want to make a custom filter this should be your base class .
* @ class AbstractFilter
* @ constructor
* @ param fragmentSrc { Array } The fragment source in an array of strings .
* @ param uniforms { Object } An object containing the uniforms for this filter .
* /
PIXI . AbstractFilter = function ( fragmentSrc , uniforms )
{
/ * *
* An array of passes - some filters contain a few steps this array simply stores the steps in a liniear fashion .
* For example the blur filter has two passes blurX and blurY .
* @ property passes
2014-11-15 20:04:24 +00:00
* @ type Array ( Filter )
2014-10-22 20:42:03 +00:00
* @ private
* /
this . passes = [ this ] ;
/ * *
* @ property shaders
2014-11-15 20:04:24 +00:00
* @ type Array ( Shader )
2014-10-22 20:42:03 +00:00
* @ private
* /
this . shaders = [ ] ;
/ * *
* @ property dirty
* @ type Boolean
* /
this . dirty = true ;
/ * *
* @ property padding
* @ type Number
* /
this . padding = 0 ;
/ * *
* @ property uniforms
* @ type object
* @ private
* /
this . uniforms = uniforms || { } ;
/ * *
* @ property fragmentSrc
* @ type Array
* @ private
* /
this . fragmentSrc = fragmentSrc || [ ] ;
} ;
PIXI . AbstractFilter . prototype . constructor = PIXI . AbstractFilter ;
/ * *
* Syncs the uniforms between the class object and the shaders .
*
* @ method syncUniforms
* /
PIXI . AbstractFilter . prototype . syncUniforms = function ( )
{
for ( var i = 0 , j = this . shaders . length ; i < j ; i ++ )
{
this . shaders [ i ] . dirty = true ;
}
} ;
2014-02-28 09:30:53 +00:00
2014-10-22 20:42:03 +00:00
/ *
PIXI . AbstractFilter . prototype . apply = function ( frameBuffer )
{
// TODO :)
} ;
* /
2014-02-28 09:30:53 +00:00
/ * *
* @ author Mat Groves http : //matgroves.com/ @Doormat23
* /
if ( typeof exports !== 'undefined' ) {
if ( typeof module !== 'undefined' && module . exports ) {
exports = module . exports = PIXI ;
}
exports . PIXI = PIXI ;
} else if ( typeof define !== 'undefined' && define . amd ) {
2014-07-11 10:52:14 +00:00
define ( 'PIXI' , ( function ( ) { return root . PIXI = PIXI ; } ) ( ) ) ;
2014-02-28 09:30:53 +00:00
} else {
root . PIXI = PIXI ;
}
2014-04-01 02:02:36 +00:00
} ) . call ( this ) ;